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