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