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