mmx: fix formats in commented code
[profile/ivi/pixman.git] / pixman / pixman-mmx.c
1 /*
2  * Copyright © 2004, 2005 Red Hat, Inc.
3  * Copyright © 2004 Nicholas Miell
4  * Copyright © 2005 Trolltech AS
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of Red Hat not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  Red Hat makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23  * SOFTWARE.
24  *
25  * Author:  Søren Sandmann (sandmann@redhat.com)
26  * Minor Improvements: Nicholas Miell (nmiell@gmail.com)
27  * MMX code paths for fbcompose.c by Lars Knoll (lars@trolltech.com)
28  *
29  * Based on work by Owen Taylor
30  */
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #ifdef USE_MMX
37
38 #include <mmintrin.h>
39 #include "pixman-private.h"
40 #include "pixman-combine32.h"
41
42 #define no_vERBOSE
43
44 #ifdef VERBOSE
45 #define CHECKPOINT() error_f ("at %s %d\n", __FUNCTION__, __LINE__)
46 #else
47 #define CHECKPOINT()
48 #endif
49
50 /* Notes about writing mmx code
51  *
52  * give memory operands as the second operand. If you give it as the
53  * first, gcc will first load it into a register, then use that
54  * register
55  *
56  *   ie. use
57  *
58  *         _mm_mullo_pi16 (x, mmx_constant);
59  *
60  *   not
61  *
62  *         _mm_mullo_pi16 (mmx_constant, x);
63  *
64  * Also try to minimize dependencies. i.e. when you need a value, try
65  * to calculate it from a value that was calculated as early as
66  * possible.
67  */
68
69 /* --------------- MMX primitives ------------------------------------- */
70
71 #ifdef __GNUC__
72 typedef uint64_t mmxdatafield;
73 #else
74 typedef __m64 mmxdatafield;
75 /* If __m64 is defined as a struct or union, define M64_MEMBER to be the
76    name of the member used to access the data */
77 # ifdef _MSC_VER
78 #  define M64_MEMBER m64_u64
79 # elif defined(__SUNPRO_C)
80 #  define M64_MEMBER l_
81 # endif
82 #endif
83
84 typedef struct
85 {
86     mmxdatafield mmx_4x00ff;
87     mmxdatafield mmx_4x0080;
88     mmxdatafield mmx_565_rgb;
89     mmxdatafield mmx_565_unpack_multiplier;
90     mmxdatafield mmx_565_r;
91     mmxdatafield mmx_565_g;
92     mmxdatafield mmx_565_b;
93     mmxdatafield mmx_mask_0;
94     mmxdatafield mmx_mask_1;
95     mmxdatafield mmx_mask_2;
96     mmxdatafield mmx_mask_3;
97     mmxdatafield mmx_full_alpha;
98     mmxdatafield mmx_ffff0000ffff0000;
99     mmxdatafield mmx_0000ffff00000000;
100     mmxdatafield mmx_000000000000ffff;
101 } mmx_data_t;
102
103 #if defined(_MSC_VER)
104 # define MMXDATA_INIT(field, val) { val ## UI64 }
105 #elif defined(M64_MEMBER)       /* __m64 is a struct, not an integral type */
106 # define MMXDATA_INIT(field, val) field =   { val ## ULL }
107 #else                           /* __m64 is an integral type */
108 # define MMXDATA_INIT(field, val) field =   val ## ULL
109 #endif
110
111 static const mmx_data_t c =
112 {
113     MMXDATA_INIT (.mmx_4x00ff,                   0x00ff00ff00ff00ff),
114     MMXDATA_INIT (.mmx_4x0080,                   0x0080008000800080),
115     MMXDATA_INIT (.mmx_565_rgb,                  0x000001f0003f001f),
116     MMXDATA_INIT (.mmx_565_unpack_multiplier,    0x0000008404100840),
117     MMXDATA_INIT (.mmx_565_r,                    0x000000f800000000),
118     MMXDATA_INIT (.mmx_565_g,                    0x0000000000fc0000),
119     MMXDATA_INIT (.mmx_565_b,                    0x00000000000000f8),
120     MMXDATA_INIT (.mmx_mask_0,                   0xffffffffffff0000),
121     MMXDATA_INIT (.mmx_mask_1,                   0xffffffff0000ffff),
122     MMXDATA_INIT (.mmx_mask_2,                   0xffff0000ffffffff),
123     MMXDATA_INIT (.mmx_mask_3,                   0x0000ffffffffffff),
124     MMXDATA_INIT (.mmx_full_alpha,               0x00ff000000000000),
125     MMXDATA_INIT (.mmx_ffff0000ffff0000,         0xffff0000ffff0000),
126     MMXDATA_INIT (.mmx_0000ffff00000000,         0x0000ffff00000000),
127     MMXDATA_INIT (.mmx_000000000000ffff,         0x000000000000ffff),
128 };
129
130 #ifdef __GNUC__
131 #    ifdef __ICC
132 #        define MC(x) to_m64 (c.mmx_ ## x)
133 #    else
134 #        define MC(x) ((__m64)c.mmx_ ## x)
135 #    endif
136 #else
137 #    define MC(x) c.mmx_ ## x
138 #endif
139
140 static force_inline __m64
141 to_m64 (uint64_t x)
142 {
143 #ifdef __ICC
144     return _mm_cvtsi64_m64 (x);
145 #elif defined M64_MEMBER        /* __m64 is a struct, not an integral type */
146     __m64 res;
147
148     res.M64_MEMBER = x;
149     return res;
150 #else                           /* __m64 is an integral type */
151     return (__m64)x;
152 #endif
153 }
154
155 static force_inline uint64_t
156 to_uint64 (__m64 x)
157 {
158 #ifdef __ICC
159     return _mm_cvtm64_si64 (x);
160 #elif defined M64_MEMBER        /* __m64 is a struct, not an integral type */
161     uint64_t res = x.M64_MEMBER;
162     return res;
163 #else                           /* __m64 is an integral type */
164     return (uint64_t)x;
165 #endif
166 }
167
168 static force_inline __m64
169 shift (__m64 v,
170        int   s)
171 {
172     if (s > 0)
173         return _mm_slli_si64 (v, s);
174     else if (s < 0)
175         return _mm_srli_si64 (v, -s);
176     else
177         return v;
178 }
179
180 static force_inline __m64
181 negate (__m64 mask)
182 {
183     return _mm_xor_si64 (mask, MC (4x00ff));
184 }
185
186 static force_inline __m64
187 pix_multiply (__m64 a, __m64 b)
188 {
189     __m64 res;
190
191     res = _mm_mullo_pi16 (a, b);
192     res = _mm_adds_pu16 (res, MC (4x0080));
193     res = _mm_adds_pu16 (res, _mm_srli_pi16 (res, 8));
194     res = _mm_srli_pi16 (res, 8);
195
196     return res;
197 }
198
199 static force_inline __m64
200 pix_add (__m64 a, __m64 b)
201 {
202     return _mm_adds_pu8 (a, b);
203 }
204
205 static force_inline __m64
206 expand_alpha (__m64 pixel)
207 {
208     __m64 t1, t2;
209
210     t1 = shift (pixel, -48);
211     t2 = shift (t1, 16);
212     t1 = _mm_or_si64 (t1, t2);
213     t2 = shift (t1, 32);
214     t1 = _mm_or_si64 (t1, t2);
215
216     return t1;
217 }
218
219 static force_inline __m64
220 expand_alpha_rev (__m64 pixel)
221 {
222     __m64 t1, t2;
223
224     /* move alpha to low 16 bits and zero the rest */
225     t1 = shift (pixel,  48);
226     t1 = shift (t1, -48);
227
228     t2 = shift (t1, 16);
229     t1 = _mm_or_si64 (t1, t2);
230     t2 = shift (t1, 32);
231     t1 = _mm_or_si64 (t1, t2);
232
233     return t1;
234 }
235
236 static force_inline __m64
237 invert_colors (__m64 pixel)
238 {
239     __m64 x, y, z;
240
241     x = y = z = pixel;
242
243     x = _mm_and_si64 (x, MC (ffff0000ffff0000));
244     y = _mm_and_si64 (y, MC (000000000000ffff));
245     z = _mm_and_si64 (z, MC (0000ffff00000000));
246
247     y = shift (y, 32);
248     z = shift (z, -32);
249
250     x = _mm_or_si64 (x, y);
251     x = _mm_or_si64 (x, z);
252
253     return x;
254 }
255
256 static force_inline __m64
257 over (__m64 src,
258       __m64 srca,
259       __m64 dest)
260 {
261     return _mm_adds_pu8 (src, pix_multiply (dest, negate (srca)));
262 }
263
264 static force_inline __m64
265 over_rev_non_pre (__m64 src, __m64 dest)
266 {
267     __m64 srca = expand_alpha (src);
268     __m64 srcfaaa = _mm_or_si64 (srca, MC (full_alpha));
269
270     return over (pix_multiply (invert_colors (src), srcfaaa), srca, dest);
271 }
272
273 static force_inline __m64
274 in (__m64 src, __m64 mask)
275 {
276     return pix_multiply (src, mask);
277 }
278
279 static force_inline __m64
280 in_over_full_src_alpha (__m64 src, __m64 mask, __m64 dest)
281 {
282     src = _mm_or_si64 (src, MC (full_alpha));
283
284     return over (in (src, mask), mask, dest);
285 }
286
287 #ifndef _MSC_VER
288 static force_inline __m64
289 in_over (__m64 src, __m64 srca, __m64 mask, __m64 dest)
290 {
291     return over (in (src, mask), pix_multiply (srca, mask), dest);
292 }
293
294 #else
295
296 #define in_over(src, srca, mask, dest)                                  \
297     over (in (src, mask), pix_multiply (srca, mask), dest)
298
299 #endif
300
301 static force_inline __m64
302 load8888 (uint32_t v)
303 {
304     return _mm_unpacklo_pi8 (_mm_cvtsi32_si64 (v), _mm_setzero_si64 ());
305 }
306
307 static force_inline __m64
308 pack8888 (__m64 lo, __m64 hi)
309 {
310     return _mm_packs_pu16 (lo, hi);
311 }
312
313 static force_inline uint32_t
314 store8888 (__m64 v)
315 {
316     return _mm_cvtsi64_si32 (pack8888 (v, _mm_setzero_si64 ()));
317 }
318
319 /* Expand 16 bits positioned at @pos (0-3) of a mmx register into
320  *
321  *    00RR00GG00BB
322  *
323  * --- Expanding 565 in the low word ---
324  *
325  * m = (m << (32 - 3)) | (m << (16 - 5)) | m;
326  * m = m & (01f0003f001f);
327  * m = m * (008404100840);
328  * m = m >> 8;
329  *
330  * Note the trick here - the top word is shifted by another nibble to
331  * avoid it bumping into the middle word
332  */
333 static force_inline __m64
334 expand565 (__m64 pixel, int pos)
335 {
336     __m64 p = pixel;
337     __m64 t1, t2;
338
339     /* move pixel to low 16 bit and zero the rest */
340     p = shift (shift (p, (3 - pos) * 16), -48);
341
342     t1 = shift (p, 36 - 11);
343     t2 = shift (p, 16 - 5);
344
345     p = _mm_or_si64 (t1, p);
346     p = _mm_or_si64 (t2, p);
347     p = _mm_and_si64 (p, MC (565_rgb));
348
349     pixel = _mm_mullo_pi16 (p, MC (565_unpack_multiplier));
350     return _mm_srli_pi16 (pixel, 8);
351 }
352
353 static force_inline __m64
354 expand8888 (__m64 in, int pos)
355 {
356     if (pos == 0)
357         return _mm_unpacklo_pi8 (in, _mm_setzero_si64 ());
358     else
359         return _mm_unpackhi_pi8 (in, _mm_setzero_si64 ());
360 }
361
362 static force_inline __m64
363 expandx888 (__m64 in, int pos)
364 {
365     return _mm_or_si64 (expand8888 (in, pos), MC (full_alpha));
366 }
367
368 static force_inline __m64
369 pack_565 (__m64 pixel, __m64 target, int pos)
370 {
371     __m64 p = pixel;
372     __m64 t = target;
373     __m64 r, g, b;
374
375     r = _mm_and_si64 (p, MC (565_r));
376     g = _mm_and_si64 (p, MC (565_g));
377     b = _mm_and_si64 (p, MC (565_b));
378
379     r = shift (r, -(32 - 8) + pos * 16);
380     g = shift (g, -(16 - 3) + pos * 16);
381     b = shift (b, -(0  + 3) + pos * 16);
382
383     if (pos == 0)
384         t = _mm_and_si64 (t, MC (mask_0));
385     else if (pos == 1)
386         t = _mm_and_si64 (t, MC (mask_1));
387     else if (pos == 2)
388         t = _mm_and_si64 (t, MC (mask_2));
389     else if (pos == 3)
390         t = _mm_and_si64 (t, MC (mask_3));
391
392     p = _mm_or_si64 (r, t);
393     p = _mm_or_si64 (g, p);
394
395     return _mm_or_si64 (b, p);
396 }
397
398 #ifndef _MSC_VER
399
400 static force_inline __m64
401 pix_add_mul (__m64 x, __m64 a, __m64 y, __m64 b)
402 {
403     x = pix_multiply (x, a);
404     y = pix_multiply (y, b);
405
406     return pix_add (x, y);
407 }
408
409 #else
410
411 #define pix_add_mul(x, a, y, b)  \
412     ( x = pix_multiply (x, a),   \
413       y = pix_multiply (y, a),   \
414       pix_add (x, y) )
415
416 #endif
417
418 /* --------------- MMX code patch for fbcompose.c --------------------- */
419
420 static force_inline uint32_t
421 combine (const uint32_t *src, const uint32_t *mask)
422 {
423     uint32_t ssrc = *src;
424
425     if (mask)
426     {
427         __m64 m = load8888 (*mask);
428         __m64 s = load8888 (ssrc);
429
430         m = expand_alpha (m);
431         s = pix_multiply (s, m);
432
433         ssrc = store8888 (s);
434     }
435
436     return ssrc;
437 }
438
439 static void
440 mmx_combine_over_u (pixman_implementation_t *imp,
441                     pixman_op_t              op,
442                     uint32_t *               dest,
443                     const uint32_t *         src,
444                     const uint32_t *         mask,
445                     int                      width)
446 {
447     const uint32_t *end = dest + width;
448
449     while (dest < end)
450     {
451         uint32_t ssrc = combine (src, mask);
452         uint32_t a = ssrc >> 24;
453
454         if (a == 0xff)
455         {
456             *dest = ssrc;
457         }
458         else if (ssrc)
459         {
460             __m64 s, sa;
461             s = load8888 (ssrc);
462             sa = expand_alpha (s);
463             *dest = store8888 (over (s, sa, load8888 (*dest)));
464         }
465
466         ++dest;
467         ++src;
468         if (mask)
469             ++mask;
470     }
471     _mm_empty ();
472 }
473
474 static void
475 mmx_combine_over_reverse_u (pixman_implementation_t *imp,
476                             pixman_op_t              op,
477                             uint32_t *               dest,
478                             const uint32_t *         src,
479                             const uint32_t *         mask,
480                             int                      width)
481 {
482     const uint32_t *end = dest + width;
483
484     while (dest < end)
485     {
486         __m64 d, da;
487         uint32_t s = combine (src, mask);
488
489         d = load8888 (*dest);
490         da = expand_alpha (d);
491         *dest = store8888 (over (d, da, load8888 (s)));
492
493         ++dest;
494         ++src;
495         if (mask)
496             mask++;
497     }
498     _mm_empty ();
499 }
500
501 static void
502 mmx_combine_in_u (pixman_implementation_t *imp,
503                   pixman_op_t              op,
504                   uint32_t *               dest,
505                   const uint32_t *         src,
506                   const uint32_t *         mask,
507                   int                      width)
508 {
509     const uint32_t *end = dest + width;
510
511     while (dest < end)
512     {
513         __m64 x, a;
514
515         x = load8888 (combine (src, mask));
516         a = load8888 (*dest);
517         a = expand_alpha (a);
518         x = pix_multiply (x, a);
519
520         *dest = store8888 (x);
521
522         ++dest;
523         ++src;
524         if (mask)
525             mask++;
526     }
527     _mm_empty ();
528 }
529
530 static void
531 mmx_combine_in_reverse_u (pixman_implementation_t *imp,
532                           pixman_op_t              op,
533                           uint32_t *               dest,
534                           const uint32_t *         src,
535                           const uint32_t *         mask,
536                           int                      width)
537 {
538     const uint32_t *end = dest + width;
539
540     while (dest < end)
541     {
542         __m64 x, a;
543
544         x = load8888 (*dest);
545         a = load8888 (combine (src, mask));
546         a = expand_alpha (a);
547         x = pix_multiply (x, a);
548         *dest = store8888 (x);
549
550         ++dest;
551         ++src;
552         if (mask)
553             mask++;
554     }
555     _mm_empty ();
556 }
557
558 static void
559 mmx_combine_out_u (pixman_implementation_t *imp,
560                    pixman_op_t              op,
561                    uint32_t *               dest,
562                    const uint32_t *         src,
563                    const uint32_t *         mask,
564                    int                      width)
565 {
566     const uint32_t *end = dest + width;
567
568     while (dest < end)
569     {
570         __m64 x, a;
571
572         x = load8888 (combine (src, mask));
573         a = load8888 (*dest);
574         a = expand_alpha (a);
575         a = negate (a);
576         x = pix_multiply (x, a);
577         *dest = store8888 (x);
578
579         ++dest;
580         ++src;
581         if (mask)
582             mask++;
583     }
584     _mm_empty ();
585 }
586
587 static void
588 mmx_combine_out_reverse_u (pixman_implementation_t *imp,
589                            pixman_op_t              op,
590                            uint32_t *               dest,
591                            const uint32_t *         src,
592                            const uint32_t *         mask,
593                            int                      width)
594 {
595     const uint32_t *end = dest + width;
596
597     while (dest < end)
598     {
599         __m64 x, a;
600
601         x = load8888 (*dest);
602         a = load8888 (combine (src, mask));
603         a = expand_alpha (a);
604         a = negate (a);
605         x = pix_multiply (x, a);
606
607         *dest = store8888 (x);
608
609         ++dest;
610         ++src;
611         if (mask)
612             mask++;
613     }
614     _mm_empty ();
615 }
616
617 static void
618 mmx_combine_atop_u (pixman_implementation_t *imp,
619                     pixman_op_t              op,
620                     uint32_t *               dest,
621                     const uint32_t *         src,
622                     const uint32_t *         mask,
623                     int                      width)
624 {
625     const uint32_t *end = dest + width;
626
627     while (dest < end)
628     {
629         __m64 s, da, d, sia;
630
631         s = load8888 (combine (src, mask));
632         d = load8888 (*dest);
633         sia = expand_alpha (s);
634         sia = negate (sia);
635         da = expand_alpha (d);
636         s = pix_add_mul (s, da, d, sia);
637         *dest = store8888 (s);
638
639         ++dest;
640         ++src;
641         if (mask)
642             mask++;
643     }
644     _mm_empty ();
645 }
646
647 static void
648 mmx_combine_atop_reverse_u (pixman_implementation_t *imp,
649                             pixman_op_t              op,
650                             uint32_t *               dest,
651                             const uint32_t *         src,
652                             const uint32_t *         mask,
653                             int                      width)
654 {
655     const uint32_t *end;
656
657     end = dest + width;
658
659     while (dest < end)
660     {
661         __m64 s, dia, d, sa;
662
663         s = load8888 (combine (src, mask));
664         d = load8888 (*dest);
665         sa = expand_alpha (s);
666         dia = expand_alpha (d);
667         dia = negate (dia);
668         s = pix_add_mul (s, dia, d, sa);
669         *dest = store8888 (s);
670
671         ++dest;
672         ++src;
673         if (mask)
674             mask++;
675     }
676     _mm_empty ();
677 }
678
679 static void
680 mmx_combine_xor_u (pixman_implementation_t *imp,
681                    pixman_op_t              op,
682                    uint32_t *               dest,
683                    const uint32_t *         src,
684                    const uint32_t *         mask,
685                    int                      width)
686 {
687     const uint32_t *end = dest + width;
688
689     while (dest < end)
690     {
691         __m64 s, dia, d, sia;
692
693         s = load8888 (combine (src, mask));
694         d = load8888 (*dest);
695         sia = expand_alpha (s);
696         dia = expand_alpha (d);
697         sia = negate (sia);
698         dia = negate (dia);
699         s = pix_add_mul (s, dia, d, sia);
700         *dest = store8888 (s);
701
702         ++dest;
703         ++src;
704         if (mask)
705             mask++;
706     }
707     _mm_empty ();
708 }
709
710 static void
711 mmx_combine_add_u (pixman_implementation_t *imp,
712                    pixman_op_t              op,
713                    uint32_t *               dest,
714                    const uint32_t *         src,
715                    const uint32_t *         mask,
716                    int                      width)
717 {
718     const uint32_t *end = dest + width;
719
720     while (dest < end)
721     {
722         __m64 s, d;
723
724         s = load8888 (combine (src, mask));
725         d = load8888 (*dest);
726         s = pix_add (s, d);
727         *dest = store8888 (s);
728
729         ++dest;
730         ++src;
731         if (mask)
732             mask++;
733     }
734     _mm_empty ();
735 }
736
737 static void
738 mmx_combine_saturate_u (pixman_implementation_t *imp,
739                         pixman_op_t              op,
740                         uint32_t *               dest,
741                         const uint32_t *         src,
742                         const uint32_t *         mask,
743                         int                      width)
744 {
745     const uint32_t *end = dest + width;
746
747     while (dest < end)
748     {
749         uint32_t s = combine (src, mask);
750         uint32_t d = *dest;
751         __m64 ms = load8888 (s);
752         __m64 md = load8888 (d);
753         uint32_t sa = s >> 24;
754         uint32_t da = ~d >> 24;
755
756         if (sa > da)
757         {
758             __m64 msa = load8888 (DIV_UN8 (da, sa) << 24);
759             msa = expand_alpha (msa);
760             ms = pix_multiply (ms, msa);
761         }
762
763         md = pix_add (md, ms);
764         *dest = store8888 (md);
765
766         ++src;
767         ++dest;
768         if (mask)
769             mask++;
770     }
771     _mm_empty ();
772 }
773
774 static void
775 mmx_combine_src_ca (pixman_implementation_t *imp,
776                     pixman_op_t              op,
777                     uint32_t *               dest,
778                     const uint32_t *         src,
779                     const uint32_t *         mask,
780                     int                      width)
781 {
782     const uint32_t *end = src + width;
783
784     while (src < end)
785     {
786         __m64 a = load8888 (*mask);
787         __m64 s = load8888 (*src);
788
789         s = pix_multiply (s, a);
790         *dest = store8888 (s);
791
792         ++src;
793         ++mask;
794         ++dest;
795     }
796     _mm_empty ();
797 }
798
799 static void
800 mmx_combine_over_ca (pixman_implementation_t *imp,
801                      pixman_op_t              op,
802                      uint32_t *               dest,
803                      const uint32_t *         src,
804                      const uint32_t *         mask,
805                      int                      width)
806 {
807     const uint32_t *end = src + width;
808
809     while (src < end)
810     {
811         __m64 a = load8888 (*mask);
812         __m64 s = load8888 (*src);
813         __m64 d = load8888 (*dest);
814         __m64 sa = expand_alpha (s);
815
816         *dest = store8888 (in_over (s, sa, a, d));
817
818         ++src;
819         ++dest;
820         ++mask;
821     }
822     _mm_empty ();
823 }
824
825 static void
826 mmx_combine_over_reverse_ca (pixman_implementation_t *imp,
827                              pixman_op_t              op,
828                              uint32_t *               dest,
829                              const uint32_t *         src,
830                              const uint32_t *         mask,
831                              int                      width)
832 {
833     const uint32_t *end = src + width;
834
835     while (src < end)
836     {
837         __m64 a = load8888 (*mask);
838         __m64 s = load8888 (*src);
839         __m64 d = load8888 (*dest);
840         __m64 da = expand_alpha (d);
841
842         *dest = store8888 (over (d, da, in (s, a)));
843
844         ++src;
845         ++dest;
846         ++mask;
847     }
848     _mm_empty ();
849 }
850
851 static void
852 mmx_combine_in_ca (pixman_implementation_t *imp,
853                    pixman_op_t              op,
854                    uint32_t *               dest,
855                    const uint32_t *         src,
856                    const uint32_t *         mask,
857                    int                      width)
858 {
859     const uint32_t *end = src + width;
860
861     while (src < end)
862     {
863         __m64 a = load8888 (*mask);
864         __m64 s = load8888 (*src);
865         __m64 d = load8888 (*dest);
866         __m64 da = expand_alpha (d);
867
868         s = pix_multiply (s, a);
869         s = pix_multiply (s, da);
870         *dest = store8888 (s);
871
872         ++src;
873         ++dest;
874         ++mask;
875     }
876     _mm_empty ();
877 }
878
879 static void
880 mmx_combine_in_reverse_ca (pixman_implementation_t *imp,
881                            pixman_op_t              op,
882                            uint32_t *               dest,
883                            const uint32_t *         src,
884                            const uint32_t *         mask,
885                            int                      width)
886 {
887     const uint32_t *end = src + width;
888
889     while (src < end)
890     {
891         __m64 a = load8888 (*mask);
892         __m64 s = load8888 (*src);
893         __m64 d = load8888 (*dest);
894         __m64 sa = expand_alpha (s);
895
896         a = pix_multiply (a, sa);
897         d = pix_multiply (d, a);
898         *dest = store8888 (d);
899
900         ++src;
901         ++dest;
902         ++mask;
903     }
904     _mm_empty ();
905 }
906
907 static void
908 mmx_combine_out_ca (pixman_implementation_t *imp,
909                     pixman_op_t              op,
910                     uint32_t *               dest,
911                     const uint32_t *         src,
912                     const uint32_t *         mask,
913                     int                      width)
914 {
915     const uint32_t *end = src + width;
916
917     while (src < end)
918     {
919         __m64 a = load8888 (*mask);
920         __m64 s = load8888 (*src);
921         __m64 d = load8888 (*dest);
922         __m64 da = expand_alpha (d);
923
924         da = negate (da);
925         s = pix_multiply (s, a);
926         s = pix_multiply (s, da);
927         *dest = store8888 (s);
928
929         ++src;
930         ++dest;
931         ++mask;
932     }
933     _mm_empty ();
934 }
935
936 static void
937 mmx_combine_out_reverse_ca (pixman_implementation_t *imp,
938                             pixman_op_t              op,
939                             uint32_t *               dest,
940                             const uint32_t *         src,
941                             const uint32_t *         mask,
942                             int                      width)
943 {
944     const uint32_t *end = src + width;
945
946     while (src < end)
947     {
948         __m64 a = load8888 (*mask);
949         __m64 s = load8888 (*src);
950         __m64 d = load8888 (*dest);
951         __m64 sa = expand_alpha (s);
952
953         a = pix_multiply (a, sa);
954         a = negate (a);
955         d = pix_multiply (d, a);
956         *dest = store8888 (d);
957
958         ++src;
959         ++dest;
960         ++mask;
961     }
962     _mm_empty ();
963 }
964
965 static void
966 mmx_combine_atop_ca (pixman_implementation_t *imp,
967                      pixman_op_t              op,
968                      uint32_t *               dest,
969                      const uint32_t *         src,
970                      const uint32_t *         mask,
971                      int                      width)
972 {
973     const uint32_t *end = src + width;
974
975     while (src < end)
976     {
977         __m64 a = load8888 (*mask);
978         __m64 s = load8888 (*src);
979         __m64 d = load8888 (*dest);
980         __m64 da = expand_alpha (d);
981         __m64 sa = expand_alpha (s);
982
983         s = pix_multiply (s, a);
984         a = pix_multiply (a, sa);
985         a = negate (a);
986         d = pix_add_mul (d, a, s, da);
987         *dest = store8888 (d);
988
989         ++src;
990         ++dest;
991         ++mask;
992     }
993     _mm_empty ();
994 }
995
996 static void
997 mmx_combine_atop_reverse_ca (pixman_implementation_t *imp,
998                              pixman_op_t              op,
999                              uint32_t *               dest,
1000                              const uint32_t *         src,
1001                              const uint32_t *         mask,
1002                              int                      width)
1003 {
1004     const uint32_t *end = src + width;
1005
1006     while (src < end)
1007     {
1008         __m64 a = load8888 (*mask);
1009         __m64 s = load8888 (*src);
1010         __m64 d = load8888 (*dest);
1011         __m64 da = expand_alpha (d);
1012         __m64 sa = expand_alpha (s);
1013
1014         s = pix_multiply (s, a);
1015         a = pix_multiply (a, sa);
1016         da = negate (da);
1017         d = pix_add_mul (d, a, s, da);
1018         *dest = store8888 (d);
1019
1020         ++src;
1021         ++dest;
1022         ++mask;
1023     }
1024     _mm_empty ();
1025 }
1026
1027 static void
1028 mmx_combine_xor_ca (pixman_implementation_t *imp,
1029                     pixman_op_t              op,
1030                     uint32_t *               dest,
1031                     const uint32_t *         src,
1032                     const uint32_t *         mask,
1033                     int                      width)
1034 {
1035     const uint32_t *end = src + width;
1036
1037     while (src < end)
1038     {
1039         __m64 a = load8888 (*mask);
1040         __m64 s = load8888 (*src);
1041         __m64 d = load8888 (*dest);
1042         __m64 da = expand_alpha (d);
1043         __m64 sa = expand_alpha (s);
1044
1045         s = pix_multiply (s, a);
1046         a = pix_multiply (a, sa);
1047         da = negate (da);
1048         a = negate (a);
1049         d = pix_add_mul (d, a, s, da);
1050         *dest = store8888 (d);
1051
1052         ++src;
1053         ++dest;
1054         ++mask;
1055     }
1056     _mm_empty ();
1057 }
1058
1059 static void
1060 mmx_combine_add_ca (pixman_implementation_t *imp,
1061                     pixman_op_t              op,
1062                     uint32_t *               dest,
1063                     const uint32_t *         src,
1064                     const uint32_t *         mask,
1065                     int                      width)
1066 {
1067     const uint32_t *end = src + width;
1068
1069     while (src < end)
1070     {
1071         __m64 a = load8888 (*mask);
1072         __m64 s = load8888 (*src);
1073         __m64 d = load8888 (*dest);
1074
1075         s = pix_multiply (s, a);
1076         d = pix_add (s, d);
1077         *dest = store8888 (d);
1078
1079         ++src;
1080         ++dest;
1081         ++mask;
1082     }
1083     _mm_empty ();
1084 }
1085
1086 /* ------------- MMX code paths called from fbpict.c -------------------- */
1087
1088 static void
1089 mmx_composite_over_n_8888 (pixman_implementation_t *imp,
1090                            pixman_composite_info_t *info)
1091 {
1092     PIXMAN_COMPOSITE_ARGS (info);
1093     uint32_t src;
1094     uint32_t    *dst_line, *dst;
1095     int32_t w;
1096     int dst_stride;
1097     __m64 vsrc, vsrca;
1098
1099     CHECKPOINT ();
1100
1101     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1102
1103     if (src == 0)
1104         return;
1105
1106     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1107
1108     vsrc = load8888 (src);
1109     vsrca = expand_alpha (vsrc);
1110
1111     while (height--)
1112     {
1113         dst = dst_line;
1114         dst_line += dst_stride;
1115         w = width;
1116
1117         CHECKPOINT ();
1118
1119         while (w && (unsigned long)dst & 7)
1120         {
1121             *dst = store8888 (over (vsrc, vsrca, load8888 (*dst)));
1122
1123             w--;
1124             dst++;
1125         }
1126
1127         while (w >= 2)
1128         {
1129             __m64 vdest;
1130             __m64 dest0, dest1;
1131
1132             vdest = *(__m64 *)dst;
1133
1134             dest0 = over (vsrc, vsrca, expand8888 (vdest, 0));
1135             dest1 = over (vsrc, vsrca, expand8888 (vdest, 1));
1136
1137             *(__m64 *)dst = pack8888 (dest0, dest1);
1138
1139             dst += 2;
1140             w -= 2;
1141         }
1142
1143         CHECKPOINT ();
1144
1145         while (w)
1146         {
1147             *dst = store8888 (over (vsrc, vsrca, load8888 (*dst)));
1148
1149             w--;
1150             dst++;
1151         }
1152     }
1153
1154     _mm_empty ();
1155 }
1156
1157 static void
1158 mmx_composite_over_n_0565 (pixman_implementation_t *imp,
1159                            pixman_composite_info_t *info)
1160 {
1161     PIXMAN_COMPOSITE_ARGS (info);
1162     uint32_t src;
1163     uint16_t    *dst_line, *dst;
1164     int32_t w;
1165     int dst_stride;
1166     __m64 vsrc, vsrca;
1167
1168     CHECKPOINT ();
1169
1170     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1171
1172     if (src == 0)
1173         return;
1174
1175     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1176
1177     vsrc = load8888 (src);
1178     vsrca = expand_alpha (vsrc);
1179
1180     while (height--)
1181     {
1182         dst = dst_line;
1183         dst_line += dst_stride;
1184         w = width;
1185
1186         CHECKPOINT ();
1187
1188         while (w && (unsigned long)dst & 7)
1189         {
1190             uint64_t d = *dst;
1191             __m64 vdest = expand565 (to_m64 (d), 0);
1192
1193             vdest = pack_565 (over (vsrc, vsrca, vdest), vdest, 0);
1194             *dst = to_uint64 (vdest);
1195
1196             w--;
1197             dst++;
1198         }
1199
1200         while (w >= 4)
1201         {
1202             __m64 vdest;
1203
1204             vdest = *(__m64 *)dst;
1205
1206             vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 0)), vdest, 0);
1207             vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 1)), vdest, 1);
1208             vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 2)), vdest, 2);
1209             vdest = pack_565 (over (vsrc, vsrca, expand565 (vdest, 3)), vdest, 3);
1210
1211             *(__m64 *)dst = vdest;
1212
1213             dst += 4;
1214             w -= 4;
1215         }
1216
1217         CHECKPOINT ();
1218
1219         while (w)
1220         {
1221             uint64_t d = *dst;
1222             __m64 vdest = expand565 (to_m64 (d), 0);
1223
1224             vdest = pack_565 (over (vsrc, vsrca, vdest), vdest, 0);
1225             *dst = to_uint64 (vdest);
1226
1227             w--;
1228             dst++;
1229         }
1230     }
1231
1232     _mm_empty ();
1233 }
1234
1235 static void
1236 mmx_composite_over_n_8888_8888_ca (pixman_implementation_t *imp,
1237                                    pixman_composite_info_t *info)
1238 {
1239     PIXMAN_COMPOSITE_ARGS (info);
1240     uint32_t src;
1241     uint32_t    *dst_line;
1242     uint32_t    *mask_line;
1243     int dst_stride, mask_stride;
1244     __m64 vsrc, vsrca;
1245
1246     CHECKPOINT ();
1247
1248     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1249
1250     if (src == 0)
1251         return;
1252
1253     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1254     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
1255
1256     vsrc = load8888 (src);
1257     vsrca = expand_alpha (vsrc);
1258
1259     while (height--)
1260     {
1261         int twidth = width;
1262         uint32_t *p = (uint32_t *)mask_line;
1263         uint32_t *q = (uint32_t *)dst_line;
1264
1265         while (twidth && (unsigned long)q & 7)
1266         {
1267             uint32_t m = *(uint32_t *)p;
1268
1269             if (m)
1270             {
1271                 __m64 vdest = load8888 (*q);
1272                 vdest = in_over (vsrc, vsrca, load8888 (m), vdest);
1273                 *q = store8888 (vdest);
1274             }
1275
1276             twidth--;
1277             p++;
1278             q++;
1279         }
1280
1281         while (twidth >= 2)
1282         {
1283             uint32_t m0, m1;
1284             m0 = *p;
1285             m1 = *(p + 1);
1286
1287             if (m0 | m1)
1288             {
1289                 __m64 dest0, dest1;
1290                 __m64 vdest = *(__m64 *)q;
1291
1292                 dest0 = in_over (vsrc, vsrca, load8888 (m0),
1293                                  expand8888 (vdest, 0));
1294                 dest1 = in_over (vsrc, vsrca, load8888 (m1),
1295                                  expand8888 (vdest, 1));
1296
1297                 *(__m64 *)q = pack8888 (dest0, dest1);
1298             }
1299
1300             p += 2;
1301             q += 2;
1302             twidth -= 2;
1303         }
1304
1305         while (twidth)
1306         {
1307             uint32_t m = *(uint32_t *)p;
1308
1309             if (m)
1310             {
1311                 __m64 vdest = load8888 (*q);
1312                 vdest = in_over (vsrc, vsrca, load8888 (m), vdest);
1313                 *q = store8888 (vdest);
1314             }
1315
1316             twidth--;
1317             p++;
1318             q++;
1319         }
1320
1321         dst_line += dst_stride;
1322         mask_line += mask_stride;
1323     }
1324
1325     _mm_empty ();
1326 }
1327
1328 static void
1329 mmx_composite_over_8888_n_8888 (pixman_implementation_t *imp,
1330                                 pixman_composite_info_t *info)
1331 {
1332     PIXMAN_COMPOSITE_ARGS (info);
1333     uint32_t    *dst_line, *dst;
1334     uint32_t    *src_line, *src;
1335     uint32_t mask;
1336     __m64 vmask;
1337     int dst_stride, src_stride;
1338     int32_t w;
1339
1340     CHECKPOINT ();
1341
1342     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1343     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1344
1345     mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format);
1346     mask &= 0xff000000;
1347     mask = mask | mask >> 8 | mask >> 16 | mask >> 24;
1348     vmask = load8888 (mask);
1349
1350     while (height--)
1351     {
1352         dst = dst_line;
1353         dst_line += dst_stride;
1354         src = src_line;
1355         src_line += src_stride;
1356         w = width;
1357
1358         while (w && (unsigned long)dst & 7)
1359         {
1360             __m64 s = load8888 (*src);
1361             __m64 d = load8888 (*dst);
1362
1363             *dst = store8888 (in_over (s, expand_alpha (s), vmask, d));
1364
1365             w--;
1366             dst++;
1367             src++;
1368         }
1369
1370         while (w >= 2)
1371         {
1372             __m64 vs = *(__m64 *)src;
1373             __m64 vd = *(__m64 *)dst;
1374             __m64 vsrc0 = expand8888 (vs, 0);
1375             __m64 vsrc1 = expand8888 (vs, 1);
1376
1377             *(__m64 *)dst = pack8888 (
1378                 in_over (vsrc0, expand_alpha (vsrc0), vmask, expand8888 (vd, 0)),
1379                 in_over (vsrc1, expand_alpha (vsrc1), vmask, expand8888 (vd, 1)));
1380
1381             w -= 2;
1382             dst += 2;
1383             src += 2;
1384         }
1385
1386         while (w)
1387         {
1388             __m64 s = load8888 (*src);
1389             __m64 d = load8888 (*dst);
1390
1391             *dst = store8888 (in_over (s, expand_alpha (s), vmask, d));
1392
1393             w--;
1394             dst++;
1395             src++;
1396         }
1397     }
1398
1399     _mm_empty ();
1400 }
1401
1402 static void
1403 mmx_composite_over_x888_n_8888 (pixman_implementation_t *imp,
1404                                 pixman_composite_info_t *info)
1405 {
1406     PIXMAN_COMPOSITE_ARGS (info);
1407     uint32_t *dst_line, *dst;
1408     uint32_t *src_line, *src;
1409     uint32_t mask;
1410     __m64 vmask;
1411     int dst_stride, src_stride;
1412     int32_t w;
1413     __m64 srca;
1414
1415     CHECKPOINT ();
1416
1417     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1418     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1419     mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format);
1420
1421     mask &= 0xff000000;
1422     mask = mask | mask >> 8 | mask >> 16 | mask >> 24;
1423     vmask = load8888 (mask);
1424     srca = MC (4x00ff);
1425
1426     while (height--)
1427     {
1428         dst = dst_line;
1429         dst_line += dst_stride;
1430         src = src_line;
1431         src_line += src_stride;
1432         w = width;
1433
1434         while (w && (unsigned long)dst & 7)
1435         {
1436             __m64 s = load8888 (*src | 0xff000000);
1437             __m64 d = load8888 (*dst);
1438
1439             *dst = store8888 (in_over (s, srca, vmask, d));
1440
1441             w--;
1442             dst++;
1443             src++;
1444         }
1445
1446         while (w >= 16)
1447         {
1448             __m64 vd0 = *(__m64 *)(dst + 0);
1449             __m64 vd1 = *(__m64 *)(dst + 2);
1450             __m64 vd2 = *(__m64 *)(dst + 4);
1451             __m64 vd3 = *(__m64 *)(dst + 6);
1452             __m64 vd4 = *(__m64 *)(dst + 8);
1453             __m64 vd5 = *(__m64 *)(dst + 10);
1454             __m64 vd6 = *(__m64 *)(dst + 12);
1455             __m64 vd7 = *(__m64 *)(dst + 14);
1456
1457             __m64 vs0 = *(__m64 *)(src + 0);
1458             __m64 vs1 = *(__m64 *)(src + 2);
1459             __m64 vs2 = *(__m64 *)(src + 4);
1460             __m64 vs3 = *(__m64 *)(src + 6);
1461             __m64 vs4 = *(__m64 *)(src + 8);
1462             __m64 vs5 = *(__m64 *)(src + 10);
1463             __m64 vs6 = *(__m64 *)(src + 12);
1464             __m64 vs7 = *(__m64 *)(src + 14);
1465
1466             vd0 = pack8888 (
1467                 in_over (expandx888 (vs0, 0), srca, vmask, expand8888 (vd0, 0)),
1468                 in_over (expandx888 (vs0, 1), srca, vmask, expand8888 (vd0, 1)));
1469
1470             vd1 = pack8888 (
1471                 in_over (expandx888 (vs1, 0), srca, vmask, expand8888 (vd1, 0)),
1472                 in_over (expandx888 (vs1, 1), srca, vmask, expand8888 (vd1, 1)));
1473
1474             vd2 = pack8888 (
1475                 in_over (expandx888 (vs2, 0), srca, vmask, expand8888 (vd2, 0)),
1476                 in_over (expandx888 (vs2, 1), srca, vmask, expand8888 (vd2, 1)));
1477
1478             vd3 = pack8888 (
1479                 in_over (expandx888 (vs3, 0), srca, vmask, expand8888 (vd3, 0)),
1480                 in_over (expandx888 (vs3, 1), srca, vmask, expand8888 (vd3, 1)));
1481
1482             vd4 = pack8888 (
1483                 in_over (expandx888 (vs4, 0), srca, vmask, expand8888 (vd4, 0)),
1484                 in_over (expandx888 (vs4, 1), srca, vmask, expand8888 (vd4, 1)));
1485
1486             vd5 = pack8888 (
1487                 in_over (expandx888 (vs5, 0), srca, vmask, expand8888 (vd5, 0)),
1488                 in_over (expandx888 (vs5, 1), srca, vmask, expand8888 (vd5, 1)));
1489
1490             vd6 = pack8888 (
1491                 in_over (expandx888 (vs6, 0), srca, vmask, expand8888 (vd6, 0)),
1492                 in_over (expandx888 (vs6, 1), srca, vmask, expand8888 (vd6, 1)));
1493
1494             vd7 = pack8888 (
1495                 in_over (expandx888 (vs7, 0), srca, vmask, expand8888 (vd7, 0)),
1496                 in_over (expandx888 (vs7, 1), srca, vmask, expand8888 (vd7, 1)));
1497
1498             *(__m64 *)(dst + 0) = vd0;
1499             *(__m64 *)(dst + 2) = vd1;
1500             *(__m64 *)(dst + 4) = vd2;
1501             *(__m64 *)(dst + 6) = vd3;
1502             *(__m64 *)(dst + 8) = vd4;
1503             *(__m64 *)(dst + 10) = vd5;
1504             *(__m64 *)(dst + 12) = vd6;
1505             *(__m64 *)(dst + 14) = vd7;
1506
1507             w -= 16;
1508             dst += 16;
1509             src += 16;
1510         }
1511
1512         while (w)
1513         {
1514             __m64 s = load8888 (*src | 0xff000000);
1515             __m64 d = load8888 (*dst);
1516
1517             *dst = store8888 (in_over (s, srca, vmask, d));
1518
1519             w--;
1520             dst++;
1521             src++;
1522         }
1523     }
1524
1525     _mm_empty ();
1526 }
1527
1528 static void
1529 mmx_composite_over_8888_8888 (pixman_implementation_t *imp,
1530                               pixman_composite_info_t *info)
1531 {
1532     PIXMAN_COMPOSITE_ARGS (info);
1533     uint32_t *dst_line, *dst;
1534     uint32_t *src_line, *src;
1535     uint32_t s;
1536     int dst_stride, src_stride;
1537     uint8_t a;
1538     int32_t w;
1539
1540     CHECKPOINT ();
1541
1542     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1543     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1544
1545     while (height--)
1546     {
1547         dst = dst_line;
1548         dst_line += dst_stride;
1549         src = src_line;
1550         src_line += src_stride;
1551         w = width;
1552
1553         while (w--)
1554         {
1555             s = *src++;
1556             a = s >> 24;
1557
1558             if (a == 0xff)
1559             {
1560                 *dst = s;
1561             }
1562             else if (s)
1563             {
1564                 __m64 ms, sa;
1565                 ms = load8888 (s);
1566                 sa = expand_alpha (ms);
1567                 *dst = store8888 (over (ms, sa, load8888 (*dst)));
1568             }
1569
1570             dst++;
1571         }
1572     }
1573     _mm_empty ();
1574 }
1575
1576 static void
1577 mmx_composite_over_8888_0565 (pixman_implementation_t *imp,
1578                               pixman_composite_info_t *info)
1579 {
1580     PIXMAN_COMPOSITE_ARGS (info);
1581     uint16_t    *dst_line, *dst;
1582     uint32_t    *src_line, *src;
1583     int dst_stride, src_stride;
1584     int32_t w;
1585
1586     CHECKPOINT ();
1587
1588     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
1589     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
1590
1591 #if 0
1592     /* FIXME */
1593     assert (src_image->drawable == mask_image->drawable);
1594 #endif
1595
1596     while (height--)
1597     {
1598         dst = dst_line;
1599         dst_line += dst_stride;
1600         src = src_line;
1601         src_line += src_stride;
1602         w = width;
1603
1604         CHECKPOINT ();
1605
1606         while (w && (unsigned long)dst & 7)
1607         {
1608             __m64 vsrc = load8888 (*src);
1609             uint64_t d = *dst;
1610             __m64 vdest = expand565 (to_m64 (d), 0);
1611
1612             vdest = pack_565 (
1613                 over (vsrc, expand_alpha (vsrc), vdest), vdest, 0);
1614
1615             *dst = to_uint64 (vdest);
1616
1617             w--;
1618             dst++;
1619             src++;
1620         }
1621
1622         CHECKPOINT ();
1623
1624         while (w >= 4)
1625         {
1626             __m64 vsrc0, vsrc1, vsrc2, vsrc3;
1627             __m64 vdest;
1628
1629             vsrc0 = load8888 (*(src + 0));
1630             vsrc1 = load8888 (*(src + 1));
1631             vsrc2 = load8888 (*(src + 2));
1632             vsrc3 = load8888 (*(src + 3));
1633
1634             vdest = *(__m64 *)dst;
1635
1636             vdest = pack_565 (over (vsrc0, expand_alpha (vsrc0), expand565 (vdest, 0)), vdest, 0);
1637             vdest = pack_565 (over (vsrc1, expand_alpha (vsrc1), expand565 (vdest, 1)), vdest, 1);
1638             vdest = pack_565 (over (vsrc2, expand_alpha (vsrc2), expand565 (vdest, 2)), vdest, 2);
1639             vdest = pack_565 (over (vsrc3, expand_alpha (vsrc3), expand565 (vdest, 3)), vdest, 3);
1640
1641             *(__m64 *)dst = vdest;
1642
1643             w -= 4;
1644             dst += 4;
1645             src += 4;
1646         }
1647
1648         CHECKPOINT ();
1649
1650         while (w)
1651         {
1652             __m64 vsrc = load8888 (*src);
1653             uint64_t d = *dst;
1654             __m64 vdest = expand565 (to_m64 (d), 0);
1655
1656             vdest = pack_565 (over (vsrc, expand_alpha (vsrc), vdest), vdest, 0);
1657
1658             *dst = to_uint64 (vdest);
1659
1660             w--;
1661             dst++;
1662             src++;
1663         }
1664     }
1665
1666     _mm_empty ();
1667 }
1668
1669 static void
1670 mmx_composite_over_n_8_8888 (pixman_implementation_t *imp,
1671                              pixman_composite_info_t *info)
1672 {
1673     PIXMAN_COMPOSITE_ARGS (info);
1674     uint32_t src, srca;
1675     uint32_t *dst_line, *dst;
1676     uint8_t *mask_line, *mask;
1677     int dst_stride, mask_stride;
1678     int32_t w;
1679     __m64 vsrc, vsrca;
1680     uint64_t srcsrc;
1681
1682     CHECKPOINT ();
1683
1684     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1685
1686     srca = src >> 24;
1687     if (src == 0)
1688         return;
1689
1690     srcsrc = (uint64_t)src << 32 | src;
1691
1692     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1693     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
1694
1695     vsrc = load8888 (src);
1696     vsrca = expand_alpha (vsrc);
1697
1698     while (height--)
1699     {
1700         dst = dst_line;
1701         dst_line += dst_stride;
1702         mask = mask_line;
1703         mask_line += mask_stride;
1704         w = width;
1705
1706         CHECKPOINT ();
1707
1708         while (w && (unsigned long)dst & 7)
1709         {
1710             uint64_t m = *mask;
1711
1712             if (m)
1713             {
1714                 __m64 vdest = in_over (vsrc, vsrca,
1715                                        expand_alpha_rev (to_m64 (m)),
1716                                        load8888 (*dst));
1717
1718                 *dst = store8888 (vdest);
1719             }
1720
1721             w--;
1722             mask++;
1723             dst++;
1724         }
1725
1726         CHECKPOINT ();
1727
1728         while (w >= 2)
1729         {
1730             uint64_t m0, m1;
1731
1732             m0 = *mask;
1733             m1 = *(mask + 1);
1734
1735             if (srca == 0xff && (m0 & m1) == 0xff)
1736             {
1737                 *(uint64_t *)dst = srcsrc;
1738             }
1739             else if (m0 | m1)
1740             {
1741                 __m64 vdest;
1742                 __m64 dest0, dest1;
1743
1744                 vdest = *(__m64 *)dst;
1745
1746                 dest0 = in_over (vsrc, vsrca, expand_alpha_rev (to_m64 (m0)),
1747                                  expand8888 (vdest, 0));
1748                 dest1 = in_over (vsrc, vsrca, expand_alpha_rev (to_m64 (m1)),
1749                                  expand8888 (vdest, 1));
1750
1751                 *(__m64 *)dst = pack8888 (dest0, dest1);
1752             }
1753
1754             mask += 2;
1755             dst += 2;
1756             w -= 2;
1757         }
1758
1759         CHECKPOINT ();
1760
1761         while (w)
1762         {
1763             uint64_t m = *mask;
1764
1765             if (m)
1766             {
1767                 __m64 vdest = load8888 (*dst);
1768
1769                 vdest = in_over (
1770                     vsrc, vsrca, expand_alpha_rev (to_m64 (m)), vdest);
1771                 *dst = store8888 (vdest);
1772             }
1773
1774             w--;
1775             mask++;
1776             dst++;
1777         }
1778     }
1779
1780     _mm_empty ();
1781 }
1782
1783 pixman_bool_t
1784 pixman_fill_mmx (uint32_t *bits,
1785                  int       stride,
1786                  int       bpp,
1787                  int       x,
1788                  int       y,
1789                  int       width,
1790                  int       height,
1791                  uint32_t xor)
1792 {
1793     uint64_t fill;
1794     __m64 vfill;
1795     uint32_t byte_width;
1796     uint8_t     *byte_line;
1797
1798 #ifdef __GNUC__
1799     __m64 v1, v2, v3, v4, v5, v6, v7;
1800 #endif
1801
1802     if (bpp != 16 && bpp != 32 && bpp != 8)
1803         return FALSE;
1804
1805     if (bpp == 8)
1806     {
1807         stride = stride * (int) sizeof (uint32_t) / 1;
1808         byte_line = (uint8_t *)(((uint8_t *)bits) + stride * y + x);
1809         byte_width = width;
1810         stride *= 1;
1811         xor = (xor & 0xff) * 0x01010101;
1812     }
1813     else if (bpp == 16)
1814     {
1815         stride = stride * (int) sizeof (uint32_t) / 2;
1816         byte_line = (uint8_t *)(((uint16_t *)bits) + stride * y + x);
1817         byte_width = 2 * width;
1818         stride *= 2;
1819         xor = (xor & 0xffff) * 0x00010001;
1820     }
1821     else
1822     {
1823         stride = stride * (int) sizeof (uint32_t) / 4;
1824         byte_line = (uint8_t *)(((uint32_t *)bits) + stride * y + x);
1825         byte_width = 4 * width;
1826         stride *= 4;
1827     }
1828
1829     fill = ((uint64_t)xor << 32) | xor;
1830     vfill = to_m64 (fill);
1831
1832 #ifdef __GNUC__
1833     __asm__ (
1834         "movq           %7,     %0\n"
1835         "movq           %7,     %1\n"
1836         "movq           %7,     %2\n"
1837         "movq           %7,     %3\n"
1838         "movq           %7,     %4\n"
1839         "movq           %7,     %5\n"
1840         "movq           %7,     %6\n"
1841         : "=&y" (v1), "=&y" (v2), "=&y" (v3),
1842           "=&y" (v4), "=&y" (v5), "=&y" (v6), "=y" (v7)
1843         : "y" (vfill));
1844 #endif
1845
1846     while (height--)
1847     {
1848         int w;
1849         uint8_t *d = byte_line;
1850
1851         byte_line += stride;
1852         w = byte_width;
1853
1854         while (w >= 1 && ((unsigned long)d & 1))
1855         {
1856             *(uint8_t *)d = (xor & 0xff);
1857             w--;
1858             d++;
1859         }
1860
1861         while (w >= 2 && ((unsigned long)d & 3))
1862         {
1863             *(uint16_t *)d = xor;
1864             w -= 2;
1865             d += 2;
1866         }
1867
1868         while (w >= 4 && ((unsigned long)d & 7))
1869         {
1870             *(uint32_t *)d = xor;
1871
1872             w -= 4;
1873             d += 4;
1874         }
1875
1876         while (w >= 64)
1877         {
1878 #ifdef __GNUC__
1879             __asm__ (
1880                 "movq   %1,       (%0)\n"
1881                 "movq   %2,      8(%0)\n"
1882                 "movq   %3,     16(%0)\n"
1883                 "movq   %4,     24(%0)\n"
1884                 "movq   %5,     32(%0)\n"
1885                 "movq   %6,     40(%0)\n"
1886                 "movq   %7,     48(%0)\n"
1887                 "movq   %8,     56(%0)\n"
1888                 :
1889                 : "r" (d),
1890                   "y" (vfill), "y" (v1), "y" (v2), "y" (v3),
1891                   "y" (v4), "y" (v5), "y" (v6), "y" (v7)
1892                 : "memory");
1893 #else
1894             *(__m64*) (d +  0) = vfill;
1895             *(__m64*) (d +  8) = vfill;
1896             *(__m64*) (d + 16) = vfill;
1897             *(__m64*) (d + 24) = vfill;
1898             *(__m64*) (d + 32) = vfill;
1899             *(__m64*) (d + 40) = vfill;
1900             *(__m64*) (d + 48) = vfill;
1901             *(__m64*) (d + 56) = vfill;
1902 #endif
1903             w -= 64;
1904             d += 64;
1905         }
1906
1907         while (w >= 4)
1908         {
1909             *(uint32_t *)d = xor;
1910
1911             w -= 4;
1912             d += 4;
1913         }
1914         while (w >= 2)
1915         {
1916             *(uint16_t *)d = xor;
1917             w -= 2;
1918             d += 2;
1919         }
1920         while (w >= 1)
1921         {
1922             *(uint8_t *)d = (xor & 0xff);
1923             w--;
1924             d++;
1925         }
1926
1927     }
1928
1929     _mm_empty ();
1930     return TRUE;
1931 }
1932
1933 static void
1934 mmx_composite_src_n_8_8888 (pixman_implementation_t *imp,
1935                             pixman_composite_info_t *info)
1936 {
1937     PIXMAN_COMPOSITE_ARGS (info);
1938     uint32_t src, srca;
1939     uint32_t    *dst_line, *dst;
1940     uint8_t     *mask_line, *mask;
1941     int dst_stride, mask_stride;
1942     int32_t w;
1943     __m64 vsrc;
1944     uint64_t srcsrc;
1945
1946     CHECKPOINT ();
1947
1948     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
1949
1950     srca = src >> 24;
1951     if (src == 0)
1952     {
1953         pixman_fill_mmx (dest_image->bits.bits, dest_image->bits.rowstride,
1954                          PIXMAN_FORMAT_BPP (dest_image->bits.format),
1955                          dest_x, dest_y, width, height, 0);
1956         return;
1957     }
1958
1959     srcsrc = (uint64_t)src << 32 | src;
1960
1961     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
1962     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
1963
1964     vsrc = load8888 (src);
1965
1966     while (height--)
1967     {
1968         dst = dst_line;
1969         dst_line += dst_stride;
1970         mask = mask_line;
1971         mask_line += mask_stride;
1972         w = width;
1973
1974         CHECKPOINT ();
1975
1976         while (w && (unsigned long)dst & 7)
1977         {
1978             uint64_t m = *mask;
1979
1980             if (m)
1981             {
1982                 __m64 vdest = in (vsrc, expand_alpha_rev (to_m64 (m)));
1983
1984                 *dst = store8888 (vdest);
1985             }
1986             else
1987             {
1988                 *dst = 0;
1989             }
1990
1991             w--;
1992             mask++;
1993             dst++;
1994         }
1995
1996         CHECKPOINT ();
1997
1998         while (w >= 2)
1999         {
2000             uint64_t m0, m1;
2001             m0 = *mask;
2002             m1 = *(mask + 1);
2003
2004             if (srca == 0xff && (m0 & m1) == 0xff)
2005             {
2006                 *(uint64_t *)dst = srcsrc;
2007             }
2008             else if (m0 | m1)
2009             {
2010                 __m64 dest0, dest1;
2011
2012                 dest0 = in (vsrc, expand_alpha_rev (to_m64 (m0)));
2013                 dest1 = in (vsrc, expand_alpha_rev (to_m64 (m1)));
2014
2015                 *(__m64 *)dst = pack8888 (dest0, dest1);
2016             }
2017             else
2018             {
2019                 *(uint64_t *)dst = 0;
2020             }
2021
2022             mask += 2;
2023             dst += 2;
2024             w -= 2;
2025         }
2026
2027         CHECKPOINT ();
2028
2029         while (w)
2030         {
2031             uint64_t m = *mask;
2032
2033             if (m)
2034             {
2035                 __m64 vdest = load8888 (*dst);
2036
2037                 vdest = in (vsrc, expand_alpha_rev (to_m64 (m)));
2038                 *dst = store8888 (vdest);
2039             }
2040             else
2041             {
2042                 *dst = 0;
2043             }
2044
2045             w--;
2046             mask++;
2047             dst++;
2048         }
2049     }
2050
2051     _mm_empty ();
2052 }
2053
2054 static void
2055 mmx_composite_over_n_8_0565 (pixman_implementation_t *imp,
2056                              pixman_composite_info_t *info)
2057 {
2058     PIXMAN_COMPOSITE_ARGS (info);
2059     uint32_t src, srca;
2060     uint16_t *dst_line, *dst;
2061     uint8_t *mask_line, *mask;
2062     int dst_stride, mask_stride;
2063     int32_t w;
2064     __m64 vsrc, vsrca, tmp;
2065     uint64_t srcsrcsrcsrc, src16;
2066
2067     CHECKPOINT ();
2068
2069     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2070
2071     srca = src >> 24;
2072     if (src == 0)
2073         return;
2074
2075     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2076     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2077
2078     vsrc = load8888 (src);
2079     vsrca = expand_alpha (vsrc);
2080
2081     tmp = pack_565 (vsrc, _mm_setzero_si64 (), 0);
2082     src16 = to_uint64 (tmp);
2083
2084     srcsrcsrcsrc =
2085         (uint64_t)src16 << 48 | (uint64_t)src16 << 32 |
2086         (uint64_t)src16 << 16 | (uint64_t)src16;
2087
2088     while (height--)
2089     {
2090         dst = dst_line;
2091         dst_line += dst_stride;
2092         mask = mask_line;
2093         mask_line += mask_stride;
2094         w = width;
2095
2096         CHECKPOINT ();
2097
2098         while (w && (unsigned long)dst & 7)
2099         {
2100             uint64_t m = *mask;
2101
2102             if (m)
2103             {
2104                 uint64_t d = *dst;
2105                 __m64 vd = to_m64 (d);
2106                 __m64 vdest = in_over (
2107                     vsrc, vsrca, expand_alpha_rev (to_m64 (m)), expand565 (vd, 0));
2108
2109                 vd = pack_565 (vdest, _mm_setzero_si64 (), 0);
2110                 *dst = to_uint64 (vd);
2111             }
2112
2113             w--;
2114             mask++;
2115             dst++;
2116         }
2117
2118         CHECKPOINT ();
2119
2120         while (w >= 4)
2121         {
2122             uint64_t m0, m1, m2, m3;
2123             m0 = *mask;
2124             m1 = *(mask + 1);
2125             m2 = *(mask + 2);
2126             m3 = *(mask + 3);
2127
2128             if (srca == 0xff && (m0 & m1 & m2 & m3) == 0xff)
2129             {
2130                 *(uint64_t *)dst = srcsrcsrcsrc;
2131             }
2132             else if (m0 | m1 | m2 | m3)
2133             {
2134                 __m64 vdest;
2135                 __m64 vm0, vm1, vm2, vm3;
2136
2137                 vdest = *(__m64 *)dst;
2138
2139                 vm0 = to_m64 (m0);
2140                 vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm0),
2141                                            expand565 (vdest, 0)), vdest, 0);
2142                 vm1 = to_m64 (m1);
2143                 vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm1),
2144                                            expand565 (vdest, 1)), vdest, 1);
2145                 vm2 = to_m64 (m2);
2146                 vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm2),
2147                                            expand565 (vdest, 2)), vdest, 2);
2148                 vm3 = to_m64 (m3);
2149                 vdest = pack_565 (in_over (vsrc, vsrca, expand_alpha_rev (vm3),
2150                                            expand565 (vdest, 3)), vdest, 3);
2151
2152                 *(__m64 *)dst = vdest;
2153             }
2154
2155             w -= 4;
2156             mask += 4;
2157             dst += 4;
2158         }
2159
2160         CHECKPOINT ();
2161
2162         while (w)
2163         {
2164             uint64_t m = *mask;
2165
2166             if (m)
2167             {
2168                 uint64_t d = *dst;
2169                 __m64 vd = to_m64 (d);
2170                 __m64 vdest = in_over (vsrc, vsrca, expand_alpha_rev (to_m64 (m)),
2171                                        expand565 (vd, 0));
2172                 vd = pack_565 (vdest, _mm_setzero_si64 (), 0);
2173                 *dst = to_uint64 (vd);
2174             }
2175
2176             w--;
2177             mask++;
2178             dst++;
2179         }
2180     }
2181
2182     _mm_empty ();
2183 }
2184
2185 static void
2186 mmx_composite_over_pixbuf_0565 (pixman_implementation_t *imp,
2187                                 pixman_composite_info_t *info)
2188 {
2189     PIXMAN_COMPOSITE_ARGS (info);
2190     uint16_t    *dst_line, *dst;
2191     uint32_t    *src_line, *src;
2192     int dst_stride, src_stride;
2193     int32_t w;
2194
2195     CHECKPOINT ();
2196
2197     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2198     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2199
2200 #if 0
2201     /* FIXME */
2202     assert (src_image->drawable == mask_image->drawable);
2203 #endif
2204
2205     while (height--)
2206     {
2207         dst = dst_line;
2208         dst_line += dst_stride;
2209         src = src_line;
2210         src_line += src_stride;
2211         w = width;
2212
2213         CHECKPOINT ();
2214
2215         while (w && (unsigned long)dst & 7)
2216         {
2217             __m64 vsrc = load8888 (*src);
2218             uint64_t d = *dst;
2219             __m64 vdest = expand565 (to_m64 (d), 0);
2220
2221             vdest = pack_565 (over_rev_non_pre (vsrc, vdest), vdest, 0);
2222
2223             *dst = to_uint64 (vdest);
2224
2225             w--;
2226             dst++;
2227             src++;
2228         }
2229
2230         CHECKPOINT ();
2231
2232         while (w >= 4)
2233         {
2234             uint32_t s0, s1, s2, s3;
2235             unsigned char a0, a1, a2, a3;
2236
2237             s0 = *src;
2238             s1 = *(src + 1);
2239             s2 = *(src + 2);
2240             s3 = *(src + 3);
2241
2242             a0 = (s0 >> 24);
2243             a1 = (s1 >> 24);
2244             a2 = (s2 >> 24);
2245             a3 = (s3 >> 24);
2246
2247             if ((a0 & a1 & a2 & a3) == 0xFF)
2248             {
2249                 __m64 vdest;
2250                 vdest = pack_565 (invert_colors (load8888 (s0)), _mm_setzero_si64 (), 0);
2251                 vdest = pack_565 (invert_colors (load8888 (s1)), vdest, 1);
2252                 vdest = pack_565 (invert_colors (load8888 (s2)), vdest, 2);
2253                 vdest = pack_565 (invert_colors (load8888 (s3)), vdest, 3);
2254
2255                 *(__m64 *)dst = vdest;
2256             }
2257             else if (s0 | s1 | s2 | s3)
2258             {
2259                 __m64 vdest = *(__m64 *)dst;
2260
2261                 vdest = pack_565 (over_rev_non_pre (load8888 (s0), expand565 (vdest, 0)), vdest, 0);
2262                 vdest = pack_565 (over_rev_non_pre (load8888 (s1), expand565 (vdest, 1)), vdest, 1);
2263                 vdest = pack_565 (over_rev_non_pre (load8888 (s2), expand565 (vdest, 2)), vdest, 2);
2264                 vdest = pack_565 (over_rev_non_pre (load8888 (s3), expand565 (vdest, 3)), vdest, 3);
2265
2266                 *(__m64 *)dst = vdest;
2267             }
2268
2269             w -= 4;
2270             dst += 4;
2271             src += 4;
2272         }
2273
2274         CHECKPOINT ();
2275
2276         while (w)
2277         {
2278             __m64 vsrc = load8888 (*src);
2279             uint64_t d = *dst;
2280             __m64 vdest = expand565 (to_m64 (d), 0);
2281
2282             vdest = pack_565 (over_rev_non_pre (vsrc, vdest), vdest, 0);
2283
2284             *dst = to_uint64 (vdest);
2285
2286             w--;
2287             dst++;
2288             src++;
2289         }
2290     }
2291
2292     _mm_empty ();
2293 }
2294
2295 static void
2296 mmx_composite_over_pixbuf_8888 (pixman_implementation_t *imp,
2297                                 pixman_composite_info_t *info)
2298 {
2299     PIXMAN_COMPOSITE_ARGS (info);
2300     uint32_t    *dst_line, *dst;
2301     uint32_t    *src_line, *src;
2302     int dst_stride, src_stride;
2303     int32_t w;
2304
2305     CHECKPOINT ();
2306
2307     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
2308     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2309
2310 #if 0
2311     /* FIXME */
2312     assert (src_image->drawable == mask_image->drawable);
2313 #endif
2314
2315     while (height--)
2316     {
2317         dst = dst_line;
2318         dst_line += dst_stride;
2319         src = src_line;
2320         src_line += src_stride;
2321         w = width;
2322
2323         while (w && (unsigned long)dst & 7)
2324         {
2325             __m64 s = load8888 (*src);
2326             __m64 d = load8888 (*dst);
2327
2328             *dst = store8888 (over_rev_non_pre (s, d));
2329
2330             w--;
2331             dst++;
2332             src++;
2333         }
2334
2335         while (w >= 2)
2336         {
2337             uint64_t s0, s1;
2338             unsigned char a0, a1;
2339             __m64 d0, d1;
2340
2341             s0 = *src;
2342             s1 = *(src + 1);
2343
2344             a0 = (s0 >> 24);
2345             a1 = (s1 >> 24);
2346
2347             if ((a0 & a1) == 0xFF)
2348             {
2349                 d0 = invert_colors (load8888 (s0));
2350                 d1 = invert_colors (load8888 (s1));
2351
2352                 *(__m64 *)dst = pack8888 (d0, d1);
2353             }
2354             else if (s0 | s1)
2355             {
2356                 __m64 vdest = *(__m64 *)dst;
2357
2358                 d0 = over_rev_non_pre (load8888 (s0), expand8888 (vdest, 0));
2359                 d1 = over_rev_non_pre (load8888 (s1), expand8888 (vdest, 1));
2360
2361                 *(__m64 *)dst = pack8888 (d0, d1);
2362             }
2363
2364             w -= 2;
2365             dst += 2;
2366             src += 2;
2367         }
2368
2369         while (w)
2370         {
2371             __m64 s = load8888 (*src);
2372             __m64 d = load8888 (*dst);
2373
2374             *dst = store8888 (over_rev_non_pre (s, d));
2375
2376             w--;
2377             dst++;
2378             src++;
2379         }
2380     }
2381
2382     _mm_empty ();
2383 }
2384
2385 static void
2386 mmx_composite_over_n_8888_0565_ca (pixman_implementation_t *imp,
2387                                    pixman_composite_info_t *info)
2388 {
2389     PIXMAN_COMPOSITE_ARGS (info);
2390     uint32_t src;
2391     uint16_t    *dst_line;
2392     uint32_t    *mask_line;
2393     int dst_stride, mask_stride;
2394     __m64 vsrc, vsrca;
2395
2396     CHECKPOINT ();
2397
2398     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2399
2400     if (src == 0)
2401         return;
2402
2403     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint16_t, dst_stride, dst_line, 1);
2404     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint32_t, mask_stride, mask_line, 1);
2405
2406     vsrc = load8888 (src);
2407     vsrca = expand_alpha (vsrc);
2408
2409     while (height--)
2410     {
2411         int twidth = width;
2412         uint32_t *p = (uint32_t *)mask_line;
2413         uint16_t *q = (uint16_t *)dst_line;
2414
2415         while (twidth && ((unsigned long)q & 7))
2416         {
2417             uint32_t m = *(uint32_t *)p;
2418
2419             if (m)
2420             {
2421                 uint64_t d = *q;
2422                 __m64 vdest = expand565 (to_m64 (d), 0);
2423                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (m), vdest), vdest, 0);
2424                 *q = to_uint64 (vdest);
2425             }
2426
2427             twidth--;
2428             p++;
2429             q++;
2430         }
2431
2432         while (twidth >= 4)
2433         {
2434             uint32_t m0, m1, m2, m3;
2435
2436             m0 = *p;
2437             m1 = *(p + 1);
2438             m2 = *(p + 2);
2439             m3 = *(p + 3);
2440
2441             if ((m0 | m1 | m2 | m3))
2442             {
2443                 __m64 vdest = *(__m64 *)q;
2444
2445                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (m0), expand565 (vdest, 0)), vdest, 0);
2446                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (m1), expand565 (vdest, 1)), vdest, 1);
2447                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (m2), expand565 (vdest, 2)), vdest, 2);
2448                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (m3), expand565 (vdest, 3)), vdest, 3);
2449
2450                 *(__m64 *)q = vdest;
2451             }
2452             twidth -= 4;
2453             p += 4;
2454             q += 4;
2455         }
2456
2457         while (twidth)
2458         {
2459             uint32_t m;
2460
2461             m = *(uint32_t *)p;
2462             if (m)
2463             {
2464                 uint64_t d = *q;
2465                 __m64 vdest = expand565 (to_m64 (d), 0);
2466                 vdest = pack_565 (in_over (vsrc, vsrca, load8888 (m), vdest), vdest, 0);
2467                 *q = to_uint64 (vdest);
2468             }
2469
2470             twidth--;
2471             p++;
2472             q++;
2473         }
2474
2475         mask_line += mask_stride;
2476         dst_line += dst_stride;
2477     }
2478
2479     _mm_empty ();
2480 }
2481
2482 static void
2483 mmx_composite_in_n_8_8 (pixman_implementation_t *imp,
2484                         pixman_composite_info_t *info)
2485 {
2486     PIXMAN_COMPOSITE_ARGS (info);
2487     uint8_t *dst_line, *dst;
2488     uint8_t *mask_line, *mask;
2489     int dst_stride, mask_stride;
2490     int32_t w;
2491     uint32_t src;
2492     uint8_t sa;
2493     __m64 vsrc, vsrca;
2494
2495     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2496     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2497
2498     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2499
2500     sa = src >> 24;
2501
2502     vsrc = load8888 (src);
2503     vsrca = expand_alpha (vsrc);
2504
2505     while (height--)
2506     {
2507         dst = dst_line;
2508         dst_line += dst_stride;
2509         mask = mask_line;
2510         mask_line += mask_stride;
2511         w = width;
2512
2513         if ((((unsigned long)dest_image & 3) == 0) &&
2514             (((unsigned long)src_image & 3) == 0))
2515         {
2516             while (w >= 4)
2517             {
2518                 __m64 vmask;
2519                 __m64 vdest;
2520
2521                 vmask = load8888 (*(uint32_t *)mask);
2522                 vdest = load8888 (*(uint32_t *)dst);
2523
2524                 *(uint32_t *)dst = store8888 (in (in (vsrca, vmask), vdest));
2525
2526                 dst += 4;
2527                 mask += 4;
2528                 w -= 4;
2529             }
2530         }
2531
2532         while (w--)
2533         {
2534             uint16_t tmp;
2535             uint8_t a;
2536             uint32_t m, d;
2537
2538             a = *mask++;
2539             d = *dst;
2540
2541             m = MUL_UN8 (sa, a, tmp);
2542             d = MUL_UN8 (m, d, tmp);
2543
2544             *dst++ = d;
2545         }
2546     }
2547
2548     _mm_empty ();
2549 }
2550
2551 static void
2552 mmx_composite_in_8_8 (pixman_implementation_t *imp,
2553                       pixman_composite_info_t *info)
2554 {
2555     PIXMAN_COMPOSITE_ARGS (info);
2556     uint8_t     *dst_line, *dst;
2557     uint8_t     *src_line, *src;
2558     int src_stride, dst_stride;
2559     int32_t w;
2560
2561     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2562     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
2563
2564     while (height--)
2565     {
2566         dst = dst_line;
2567         dst_line += dst_stride;
2568         src = src_line;
2569         src_line += src_stride;
2570         w = width;
2571
2572         if ((((unsigned long)dest_image & 3) == 0) &&
2573             (((unsigned long)src_image & 3) == 0))
2574         {
2575             while (w >= 4)
2576             {
2577                 uint32_t *s = (uint32_t *)src;
2578                 uint32_t *d = (uint32_t *)dst;
2579
2580                 *d = store8888 (in (load8888 (*s), load8888 (*d)));
2581
2582                 w -= 4;
2583                 dst += 4;
2584                 src += 4;
2585             }
2586         }
2587
2588         while (w--)
2589         {
2590             uint8_t s, d;
2591             uint16_t tmp;
2592
2593             s = *src;
2594             d = *dst;
2595
2596             *dst = MUL_UN8 (s, d, tmp);
2597
2598             src++;
2599             dst++;
2600         }
2601     }
2602
2603     _mm_empty ();
2604 }
2605
2606 static void
2607 mmx_composite_add_n_8_8 (pixman_implementation_t *imp,
2608                          pixman_composite_info_t *info)
2609 {
2610     PIXMAN_COMPOSITE_ARGS (info);
2611     uint8_t     *dst_line, *dst;
2612     uint8_t     *mask_line, *mask;
2613     int dst_stride, mask_stride;
2614     int32_t w;
2615     uint32_t src;
2616     uint8_t sa;
2617     __m64 vsrc, vsrca;
2618
2619     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2620     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2621
2622     src = _pixman_image_get_solid (imp, src_image, dest_image->bits.format);
2623
2624     sa = src >> 24;
2625
2626     if (src == 0)
2627         return;
2628
2629     vsrc = load8888 (src);
2630     vsrca = expand_alpha (vsrc);
2631
2632     while (height--)
2633     {
2634         dst = dst_line;
2635         dst_line += dst_stride;
2636         mask = mask_line;
2637         mask_line += mask_stride;
2638         w = width;
2639
2640         if ((((unsigned long)mask_image & 3) == 0) &&
2641             (((unsigned long)dest_image  & 3) == 0))
2642         {
2643             while (w >= 4)
2644             {
2645                 __m64 vmask = load8888 (*(uint32_t *)mask);
2646                 __m64 vdest = load8888 (*(uint32_t *)dst);
2647
2648                 *(uint32_t *)dst = store8888 (_mm_adds_pu8 (in (vsrca, vmask), vdest));
2649
2650                 w -= 4;
2651                 dst += 4;
2652                 mask += 4;
2653             }
2654         }
2655
2656         while (w--)
2657         {
2658             uint16_t tmp;
2659             uint16_t a;
2660             uint32_t m, d;
2661             uint32_t r;
2662
2663             a = *mask++;
2664             d = *dst;
2665
2666             m = MUL_UN8 (sa, a, tmp);
2667             r = ADD_UN8 (m, d, tmp);
2668
2669             *dst++ = r;
2670         }
2671     }
2672
2673     _mm_empty ();
2674 }
2675
2676 static void
2677 mmx_composite_add_8_8 (pixman_implementation_t *imp,
2678                        pixman_composite_info_t *info)
2679 {
2680     PIXMAN_COMPOSITE_ARGS (info);
2681     uint8_t *dst_line, *dst;
2682     uint8_t *src_line, *src;
2683     int dst_stride, src_stride;
2684     int32_t w;
2685     uint8_t s, d;
2686     uint16_t t;
2687
2688     CHECKPOINT ();
2689
2690     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint8_t, src_stride, src_line, 1);
2691     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint8_t, dst_stride, dst_line, 1);
2692
2693     while (height--)
2694     {
2695         dst = dst_line;
2696         dst_line += dst_stride;
2697         src = src_line;
2698         src_line += src_stride;
2699         w = width;
2700
2701         while (w && (unsigned long)dst & 7)
2702         {
2703             s = *src;
2704             d = *dst;
2705             t = d + s;
2706             s = t | (0 - (t >> 8));
2707             *dst = s;
2708
2709             dst++;
2710             src++;
2711             w--;
2712         }
2713
2714         while (w >= 8)
2715         {
2716             *(__m64*)dst = _mm_adds_pu8 (*(__m64*)src, *(__m64*)dst);
2717             dst += 8;
2718             src += 8;
2719             w -= 8;
2720         }
2721
2722         while (w)
2723         {
2724             s = *src;
2725             d = *dst;
2726             t = d + s;
2727             s = t | (0 - (t >> 8));
2728             *dst = s;
2729
2730             dst++;
2731             src++;
2732             w--;
2733         }
2734     }
2735
2736     _mm_empty ();
2737 }
2738
2739 static void
2740 mmx_composite_add_8888_8888 (pixman_implementation_t *imp,
2741                              pixman_composite_info_t *info)
2742 {
2743     PIXMAN_COMPOSITE_ARGS (info);
2744     __m64 dst64;
2745     uint32_t    *dst_line, *dst;
2746     uint32_t    *src_line, *src;
2747     int dst_stride, src_stride;
2748     int32_t w;
2749
2750     CHECKPOINT ();
2751
2752     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2753     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
2754
2755     while (height--)
2756     {
2757         dst = dst_line;
2758         dst_line += dst_stride;
2759         src = src_line;
2760         src_line += src_stride;
2761         w = width;
2762
2763         while (w && (unsigned long)dst & 7)
2764         {
2765             *dst = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (*src),
2766                                                    _mm_cvtsi32_si64 (*dst)));
2767             dst++;
2768             src++;
2769             w--;
2770         }
2771
2772         while (w >= 2)
2773         {
2774             dst64 = _mm_adds_pu8 (*(__m64*)src, *(__m64*)dst);
2775             *(uint64_t*)dst = to_uint64 (dst64);
2776             dst += 2;
2777             src += 2;
2778             w -= 2;
2779         }
2780
2781         if (w)
2782         {
2783             *dst = _mm_cvtsi64_si32 (_mm_adds_pu8 (_mm_cvtsi32_si64 (*src),
2784                                                    _mm_cvtsi32_si64 (*dst)));
2785
2786         }
2787     }
2788
2789     _mm_empty ();
2790 }
2791
2792 static pixman_bool_t
2793 pixman_blt_mmx (uint32_t *src_bits,
2794                 uint32_t *dst_bits,
2795                 int       src_stride,
2796                 int       dst_stride,
2797                 int       src_bpp,
2798                 int       dst_bpp,
2799                 int       src_x,
2800                 int       src_y,
2801                 int       dest_x,
2802                 int       dest_y,
2803                 int       width,
2804                 int       height)
2805 {
2806     uint8_t *   src_bytes;
2807     uint8_t *   dst_bytes;
2808     int byte_width;
2809
2810     if (src_bpp != dst_bpp)
2811         return FALSE;
2812
2813     if (src_bpp == 16)
2814     {
2815         src_stride = src_stride * (int) sizeof (uint32_t) / 2;
2816         dst_stride = dst_stride * (int) sizeof (uint32_t) / 2;
2817         src_bytes = (uint8_t *)(((uint16_t *)src_bits) + src_stride * (src_y) + (src_x));
2818         dst_bytes = (uint8_t *)(((uint16_t *)dst_bits) + dst_stride * (dest_y) + (dest_x));
2819         byte_width = 2 * width;
2820         src_stride *= 2;
2821         dst_stride *= 2;
2822     }
2823     else if (src_bpp == 32)
2824     {
2825         src_stride = src_stride * (int) sizeof (uint32_t) / 4;
2826         dst_stride = dst_stride * (int) sizeof (uint32_t) / 4;
2827         src_bytes = (uint8_t *)(((uint32_t *)src_bits) + src_stride * (src_y) + (src_x));
2828         dst_bytes = (uint8_t *)(((uint32_t *)dst_bits) + dst_stride * (dest_y) + (dest_x));
2829         byte_width = 4 * width;
2830         src_stride *= 4;
2831         dst_stride *= 4;
2832     }
2833     else
2834     {
2835         return FALSE;
2836     }
2837
2838     while (height--)
2839     {
2840         int w;
2841         uint8_t *s = src_bytes;
2842         uint8_t *d = dst_bytes;
2843         src_bytes += src_stride;
2844         dst_bytes += dst_stride;
2845         w = byte_width;
2846
2847         while (w >= 2 && ((unsigned long)d & 3))
2848         {
2849             *(uint16_t *)d = *(uint16_t *)s;
2850             w -= 2;
2851             s += 2;
2852             d += 2;
2853         }
2854
2855         while (w >= 4 && ((unsigned long)d & 7))
2856         {
2857             *(uint32_t *)d = *(uint32_t *)s;
2858
2859             w -= 4;
2860             s += 4;
2861             d += 4;
2862         }
2863
2864         while (w >= 64)
2865         {
2866 #if defined (__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
2867             __asm__ (
2868                 "movq     (%1),   %%mm0\n"
2869                 "movq    8(%1),   %%mm1\n"
2870                 "movq   16(%1),   %%mm2\n"
2871                 "movq   24(%1),   %%mm3\n"
2872                 "movq   32(%1),   %%mm4\n"
2873                 "movq   40(%1),   %%mm5\n"
2874                 "movq   48(%1),   %%mm6\n"
2875                 "movq   56(%1),   %%mm7\n"
2876
2877                 "movq   %%mm0,    (%0)\n"
2878                 "movq   %%mm1,   8(%0)\n"
2879                 "movq   %%mm2,  16(%0)\n"
2880                 "movq   %%mm3,  24(%0)\n"
2881                 "movq   %%mm4,  32(%0)\n"
2882                 "movq   %%mm5,  40(%0)\n"
2883                 "movq   %%mm6,  48(%0)\n"
2884                 "movq   %%mm7,  56(%0)\n"
2885                 :
2886                 : "r" (d), "r" (s)
2887                 : "memory",
2888                   "%mm0", "%mm1", "%mm2", "%mm3",
2889                   "%mm4", "%mm5", "%mm6", "%mm7");
2890 #else
2891             __m64 v0 = *(__m64 *)(s + 0);
2892             __m64 v1 = *(__m64 *)(s + 8);
2893             __m64 v2 = *(__m64 *)(s + 16);
2894             __m64 v3 = *(__m64 *)(s + 24);
2895             __m64 v4 = *(__m64 *)(s + 32);
2896             __m64 v5 = *(__m64 *)(s + 40);
2897             __m64 v6 = *(__m64 *)(s + 48);
2898             __m64 v7 = *(__m64 *)(s + 56);
2899             *(__m64 *)(d + 0)  = v0;
2900             *(__m64 *)(d + 8)  = v1;
2901             *(__m64 *)(d + 16) = v2;
2902             *(__m64 *)(d + 24) = v3;
2903             *(__m64 *)(d + 32) = v4;
2904             *(__m64 *)(d + 40) = v5;
2905             *(__m64 *)(d + 48) = v6;
2906             *(__m64 *)(d + 56) = v7;
2907 #endif
2908
2909             w -= 64;
2910             s += 64;
2911             d += 64;
2912         }
2913         while (w >= 4)
2914         {
2915             *(uint32_t *)d = *(uint32_t *)s;
2916
2917             w -= 4;
2918             s += 4;
2919             d += 4;
2920         }
2921         if (w >= 2)
2922         {
2923             *(uint16_t *)d = *(uint16_t *)s;
2924             w -= 2;
2925             s += 2;
2926             d += 2;
2927         }
2928     }
2929
2930     _mm_empty ();
2931
2932     return TRUE;
2933 }
2934
2935 static void
2936 mmx_composite_copy_area (pixman_implementation_t *imp,
2937                          pixman_composite_info_t *info)
2938 {
2939     PIXMAN_COMPOSITE_ARGS (info);
2940
2941     pixman_blt_mmx (src_image->bits.bits,
2942                     dest_image->bits.bits,
2943                     src_image->bits.rowstride,
2944                     dest_image->bits.rowstride,
2945                     PIXMAN_FORMAT_BPP (src_image->bits.format),
2946                     PIXMAN_FORMAT_BPP (dest_image->bits.format),
2947                     src_x, src_y, dest_x, dest_y, width, height);
2948 }
2949
2950 #if 0
2951 static void
2952 mmx_composite_over_x888_8_8888 (pixman_implementation_t *imp,
2953                                 pixman_composite_info_t *info)
2954 {
2955     PIXMAN_COMPOSITE_ARGS (info);
2956     uint32_t  *src, *src_line;
2957     uint32_t  *dst, *dst_line;
2958     uint8_t  *mask, *mask_line;
2959     int src_stride, mask_stride, dst_stride;
2960     int32_t w;
2961
2962     PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, uint32_t, dst_stride, dst_line, 1);
2963     PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, uint8_t, mask_stride, mask_line, 1);
2964     PIXMAN_IMAGE_GET_LINE (src_image, src_x, src_y, uint32_t, src_stride, src_line, 1);
2965
2966     while (height--)
2967     {
2968         src = src_line;
2969         src_line += src_stride;
2970         dst = dst_line;
2971         dst_line += dst_stride;
2972         mask = mask_line;
2973         mask_line += mask_stride;
2974
2975         w = width;
2976
2977         while (w--)
2978         {
2979             uint64_t m = *mask;
2980
2981             if (m)
2982             {
2983                 __m64 s = load8888 (*src | 0xff000000);
2984
2985                 if (m == 0xff)
2986                 {
2987                     *dst = store8888 (s);
2988                 }
2989                 else
2990                 {
2991                     __m64 sa = expand_alpha (s);
2992                     __m64 vm = expand_alpha_rev (to_m64 (m));
2993                     __m64 vdest = in_over (s, sa, vm, load8888 (*dst));
2994
2995                     *dst = store8888 (vdest);
2996                 }
2997             }
2998
2999             mask++;
3000             dst++;
3001             src++;
3002         }
3003     }
3004
3005     _mm_empty ();
3006 }
3007 #endif
3008
3009 static const pixman_fast_path_t mmx_fast_paths[] =
3010 {
3011     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       r5g6b5,   mmx_composite_over_n_8_0565       ),
3012     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       b5g6r5,   mmx_composite_over_n_8_0565       ),
3013     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       a8r8g8b8, mmx_composite_over_n_8_8888       ),
3014     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       x8r8g8b8, mmx_composite_over_n_8_8888       ),
3015     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       a8b8g8r8, mmx_composite_over_n_8_8888       ),
3016     PIXMAN_STD_FAST_PATH    (OVER, solid,    a8,       x8b8g8r8, mmx_composite_over_n_8_8888       ),
3017     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8r8g8b8, a8r8g8b8, mmx_composite_over_n_8888_8888_ca ),
3018     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8r8g8b8, x8r8g8b8, mmx_composite_over_n_8888_8888_ca ),
3019     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8r8g8b8, r5g6b5,   mmx_composite_over_n_8888_0565_ca ),
3020     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8b8g8r8, a8b8g8r8, mmx_composite_over_n_8888_8888_ca ),
3021     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8b8g8r8, x8b8g8r8, mmx_composite_over_n_8888_8888_ca ),
3022     PIXMAN_STD_FAST_PATH_CA (OVER, solid,    a8b8g8r8, b5g6r5,   mmx_composite_over_n_8888_0565_ca ),
3023     PIXMAN_STD_FAST_PATH    (OVER, pixbuf,   pixbuf,   a8r8g8b8, mmx_composite_over_pixbuf_8888    ),
3024     PIXMAN_STD_FAST_PATH    (OVER, pixbuf,   pixbuf,   x8r8g8b8, mmx_composite_over_pixbuf_8888    ),
3025     PIXMAN_STD_FAST_PATH    (OVER, pixbuf,   pixbuf,   r5g6b5,   mmx_composite_over_pixbuf_0565    ),
3026     PIXMAN_STD_FAST_PATH    (OVER, rpixbuf,  rpixbuf,  a8b8g8r8, mmx_composite_over_pixbuf_8888    ),
3027     PIXMAN_STD_FAST_PATH    (OVER, rpixbuf,  rpixbuf,  x8b8g8r8, mmx_composite_over_pixbuf_8888    ),
3028     PIXMAN_STD_FAST_PATH    (OVER, rpixbuf,  rpixbuf,  b5g6r5,   mmx_composite_over_pixbuf_0565    ),
3029     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, solid,    a8r8g8b8, mmx_composite_over_x888_n_8888    ),
3030     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, solid,    x8r8g8b8, mmx_composite_over_x888_n_8888    ),
3031     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, solid,    a8b8g8r8, mmx_composite_over_x888_n_8888    ),
3032     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, solid,    x8b8g8r8, mmx_composite_over_x888_n_8888    ),
3033     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, solid,    a8r8g8b8, mmx_composite_over_8888_n_8888    ),
3034     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, solid,    x8r8g8b8, mmx_composite_over_8888_n_8888    ),
3035     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, solid,    a8b8g8r8, mmx_composite_over_8888_n_8888    ),
3036     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, solid,    x8b8g8r8, mmx_composite_over_8888_n_8888    ),
3037 #if 0
3038     /* FIXME: This code is commented out since it's apparently
3039      * not actually faster than the generic code.
3040      */
3041     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, a8,       x8r8g8b8, mmx_composite_over_x888_8_8888    ),
3042     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, a8,       a8r8g8b8, mmx_composite_over_x888_8_8888    ),
3043     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, a8,       x8b8g8r8, mmx_composite_over_x888_8_8888    ),
3044     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, a8,       a8b8g8r8, mmx_composite_over_x888_8_8888    ),
3045 #endif
3046     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     a8r8g8b8, mmx_composite_over_n_8888         ),
3047     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     x8r8g8b8, mmx_composite_over_n_8888         ),
3048     PIXMAN_STD_FAST_PATH    (OVER, solid,    null,     r5g6b5,   mmx_composite_over_n_0565         ),
3049     PIXMAN_STD_FAST_PATH    (OVER, x8r8g8b8, null,     x8r8g8b8, mmx_composite_copy_area           ),
3050     PIXMAN_STD_FAST_PATH    (OVER, x8b8g8r8, null,     x8b8g8r8, mmx_composite_copy_area           ),
3051
3052     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, null,     a8r8g8b8, mmx_composite_over_8888_8888      ),
3053     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, null,     x8r8g8b8, mmx_composite_over_8888_8888      ),
3054     PIXMAN_STD_FAST_PATH    (OVER, a8r8g8b8, null,     r5g6b5,   mmx_composite_over_8888_0565      ),
3055     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, null,     a8b8g8r8, mmx_composite_over_8888_8888      ),
3056     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, null,     x8b8g8r8, mmx_composite_over_8888_8888      ),
3057     PIXMAN_STD_FAST_PATH    (OVER, a8b8g8r8, null,     b5g6r5,   mmx_composite_over_8888_0565      ),
3058
3059     PIXMAN_STD_FAST_PATH    (ADD,  a8r8g8b8, null,     a8r8g8b8, mmx_composite_add_8888_8888       ),
3060     PIXMAN_STD_FAST_PATH    (ADD,  a8b8g8r8, null,     a8b8g8r8, mmx_composite_add_8888_8888       ),
3061     PIXMAN_STD_FAST_PATH    (ADD,  a8,       null,     a8,       mmx_composite_add_8_8             ),
3062     PIXMAN_STD_FAST_PATH    (ADD,  solid,    a8,       a8,       mmx_composite_add_n_8_8           ),
3063
3064     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       a8r8g8b8, mmx_composite_src_n_8_8888        ),
3065     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       x8r8g8b8, mmx_composite_src_n_8_8888        ),
3066     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       a8b8g8r8, mmx_composite_src_n_8_8888        ),
3067     PIXMAN_STD_FAST_PATH    (SRC,  solid,    a8,       x8b8g8r8, mmx_composite_src_n_8_8888        ),
3068     PIXMAN_STD_FAST_PATH    (SRC,  a8r8g8b8, null,     a8r8g8b8, mmx_composite_copy_area           ),
3069     PIXMAN_STD_FAST_PATH    (SRC,  a8b8g8r8, null,     a8b8g8r8, mmx_composite_copy_area           ),
3070     PIXMAN_STD_FAST_PATH    (SRC,  a8r8g8b8, null,     x8r8g8b8, mmx_composite_copy_area           ),
3071     PIXMAN_STD_FAST_PATH    (SRC,  a8b8g8r8, null,     x8b8g8r8, mmx_composite_copy_area           ),
3072     PIXMAN_STD_FAST_PATH    (SRC,  x8r8g8b8, null,     x8r8g8b8, mmx_composite_copy_area           ),
3073     PIXMAN_STD_FAST_PATH    (SRC,  x8b8g8r8, null,     x8b8g8r8, mmx_composite_copy_area           ),
3074     PIXMAN_STD_FAST_PATH    (SRC,  r5g6b5,   null,     r5g6b5,   mmx_composite_copy_area           ),
3075     PIXMAN_STD_FAST_PATH    (SRC,  b5g6r5,   null,     b5g6r5,   mmx_composite_copy_area           ),
3076
3077     PIXMAN_STD_FAST_PATH    (IN,   a8,       null,     a8,       mmx_composite_in_8_8              ),
3078     PIXMAN_STD_FAST_PATH    (IN,   solid,    a8,       a8,       mmx_composite_in_n_8_8            ),
3079
3080     { PIXMAN_OP_NONE },
3081 };
3082
3083 static pixman_bool_t
3084 mmx_blt (pixman_implementation_t *imp,
3085          uint32_t *               src_bits,
3086          uint32_t *               dst_bits,
3087          int                      src_stride,
3088          int                      dst_stride,
3089          int                      src_bpp,
3090          int                      dst_bpp,
3091          int                      src_x,
3092          int                      src_y,
3093          int                      dest_x,
3094          int                      dest_y,
3095          int                      width,
3096          int                      height)
3097 {
3098     if (!pixman_blt_mmx (
3099             src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
3100             src_x, src_y, dest_x, dest_y, width, height))
3101
3102     {
3103         return _pixman_implementation_blt (
3104             imp->delegate,
3105             src_bits, dst_bits, src_stride, dst_stride, src_bpp, dst_bpp,
3106             src_x, src_y, dest_x, dest_y, width, height);
3107     }
3108
3109     return TRUE;
3110 }
3111
3112 static pixman_bool_t
3113 mmx_fill (pixman_implementation_t *imp,
3114           uint32_t *               bits,
3115           int                      stride,
3116           int                      bpp,
3117           int                      x,
3118           int                      y,
3119           int                      width,
3120           int                      height,
3121           uint32_t xor)
3122 {
3123     if (!pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor))
3124     {
3125         return _pixman_implementation_fill (
3126             imp->delegate, bits, stride, bpp, x, y, width, height, xor);
3127     }
3128
3129     return TRUE;
3130 }
3131
3132 pixman_implementation_t *
3133 _pixman_implementation_create_mmx (pixman_implementation_t *fallback)
3134 {
3135     pixman_implementation_t *imp = _pixman_implementation_create (fallback, mmx_fast_paths);
3136
3137     imp->combine_32[PIXMAN_OP_OVER] = mmx_combine_over_u;
3138     imp->combine_32[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_u;
3139     imp->combine_32[PIXMAN_OP_IN] = mmx_combine_in_u;
3140     imp->combine_32[PIXMAN_OP_IN_REVERSE] = mmx_combine_in_reverse_u;
3141     imp->combine_32[PIXMAN_OP_OUT] = mmx_combine_out_u;
3142     imp->combine_32[PIXMAN_OP_OUT_REVERSE] = mmx_combine_out_reverse_u;
3143     imp->combine_32[PIXMAN_OP_ATOP] = mmx_combine_atop_u;
3144     imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = mmx_combine_atop_reverse_u;
3145     imp->combine_32[PIXMAN_OP_XOR] = mmx_combine_xor_u;
3146     imp->combine_32[PIXMAN_OP_ADD] = mmx_combine_add_u;
3147     imp->combine_32[PIXMAN_OP_SATURATE] = mmx_combine_saturate_u;
3148
3149     imp->combine_32_ca[PIXMAN_OP_SRC] = mmx_combine_src_ca;
3150     imp->combine_32_ca[PIXMAN_OP_OVER] = mmx_combine_over_ca;
3151     imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = mmx_combine_over_reverse_ca;
3152     imp->combine_32_ca[PIXMAN_OP_IN] = mmx_combine_in_ca;
3153     imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = mmx_combine_in_reverse_ca;
3154     imp->combine_32_ca[PIXMAN_OP_OUT] = mmx_combine_out_ca;
3155     imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = mmx_combine_out_reverse_ca;
3156     imp->combine_32_ca[PIXMAN_OP_ATOP] = mmx_combine_atop_ca;
3157     imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = mmx_combine_atop_reverse_ca;
3158     imp->combine_32_ca[PIXMAN_OP_XOR] = mmx_combine_xor_ca;
3159     imp->combine_32_ca[PIXMAN_OP_ADD] = mmx_combine_add_ca;
3160
3161     imp->blt = mmx_blt;
3162     imp->fill = mmx_fill;
3163
3164     return imp;
3165 }
3166
3167 #endif /* USE_MMX */