49c1d4c559b09c98daccfcf22b8516ca68eea074
[profile/ivi/pixman.git] / pixman / pixman-fast-path.c
1 /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
2 /*
3  * Copyright © 2000 SuSE, Inc.
4  * Copyright © 2007 Red Hat, Inc.
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 SuSE not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  SuSE 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  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Author:  Keith Packard, SuSE, Inc.
24  */
25
26 #include <config.h>
27 #include <string.h>
28 #include "pixman-private.h"
29 #include "pixman-combine32.h"
30
31 static force_inline uint32_t
32 fbOver (uint32_t src, uint32_t dest)
33 {
34     // dest = (dest * (255 - alpha)) / 255 + src
35     uint32_t a = ~src >> 24; // 255 - alpha == 255 + (~alpha + 1) == ~alpha
36     FbByteMulAdd(dest, a, src);
37
38     return dest;
39 }
40
41 static uint32_t
42 fbOver24 (uint32_t x, uint32_t y)
43 {
44     uint16_t  a = ~x >> 24;
45     uint16_t  t;
46     uint32_t  m,n,o;
47
48     m = FbOverU(x,y,0,a,t);
49     n = FbOverU(x,y,8,a,t);
50     o = FbOverU(x,y,16,a,t);
51     return m|n|o;
52 }
53
54 static uint32_t
55 fbIn (uint32_t x, uint8_t y)
56 {
57     uint16_t  a = y;
58     uint16_t  t;
59     uint32_t  m,n,o,p;
60
61     m = FbInU(x,0,a,t);
62     n = FbInU(x,8,a,t);
63     o = FbInU(x,16,a,t);
64     p = FbInU(x,24,a,t);
65     return m|n|o|p;
66 }
67
68 /*
69  * Naming convention:
70  *
71  *  opSRCxMASKxDST
72  */
73
74 static void
75 fbCompositeOver_x888x8x8888 (pixman_implementation_t *imp,
76                              pixman_op_t      op,
77                              pixman_image_t * pSrc,
78                              pixman_image_t * pMask,
79                              pixman_image_t * pDst,
80                              int32_t      xSrc,
81                              int32_t      ySrc,
82                              int32_t      xMask,
83                              int32_t      yMask,
84                              int32_t      xDst,
85                              int32_t      yDst,
86                              int32_t     width,
87                              int32_t     height)
88 {
89     uint32_t    *src, *srcLine;
90     uint32_t    *dst, *dstLine;
91     uint8_t     *mask, *maskLine;
92     int          srcStride, maskStride, dstStride;
93     uint8_t m;
94     uint32_t s, d;
95     uint16_t w;
96
97     fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1);
98     fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1);
99     fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1);
100
101     while (height--)
102     {
103         src = srcLine;
104         srcLine += srcStride;
105         dst = dstLine;
106         dstLine += dstStride;
107         mask = maskLine;
108         maskLine += maskStride;
109
110         w = width;
111         while (w--)
112         {
113             m = *mask++;
114             if (m)
115             {
116                 s = *src | 0xff000000;
117
118                 if (m == 0xff)
119                     *dst = s;
120                 else
121                 {
122                     d = fbIn (s, m);
123                     *dst = fbOver (d, *dst);
124                 }
125             }
126             src++;
127             dst++;
128         }
129     }
130 }
131
132 static void
133 fbCompositeSolidMaskIn_nx8x8 (pixman_implementation_t *imp,
134                               pixman_op_t      op,
135                               pixman_image_t    *iSrc,
136                               pixman_image_t    *iMask,
137                               pixman_image_t    *iDst,
138                               int32_t      xSrc,
139                               int32_t      ySrc,
140                               int32_t      xMask,
141                               int32_t      yMask,
142                               int32_t      xDst,
143                               int32_t      yDst,
144                               int32_t     width,
145                               int32_t     height)
146 {
147     uint32_t    src, srca;
148     uint8_t     *dstLine, *dst;
149     uint8_t     *maskLine, *mask, m;
150     int dstStride, maskStride;
151     uint16_t    w;
152     uint16_t    t;
153
154     src = _pixman_image_get_solid(iSrc, iDst->bits.format);
155
156     srca = src >> 24;
157
158     fbComposeGetStart (iDst, xDst, yDst, uint8_t, dstStride, dstLine, 1);
159     fbComposeGetStart (iMask, xMask, yMask, uint8_t, maskStride, maskLine, 1);
160
161     if (srca == 0xff) {
162         while (height--)
163         {
164             dst = dstLine;
165             dstLine += dstStride;
166             mask = maskLine;
167             maskLine += maskStride;
168             w = width;
169
170             while (w--)
171             {
172                 m = *mask++;
173                 if (m == 0)
174                 {
175                     *dst = 0;
176                 }
177                 else if (m != 0xff)
178                 {
179                     *dst = FbIntMult(m, *dst, t);
180                 }
181                 dst++;
182             }
183         }
184     }
185     else
186     {
187         while (height--)
188         {
189             dst = dstLine;
190             dstLine += dstStride;
191             mask = maskLine;
192             maskLine += maskStride;
193             w = width;
194
195             while (w--)
196             {
197                 m = *mask++;
198                 m = FbIntMult(m, srca, t);
199                 if (m == 0)
200                 {
201                     *dst = 0;
202                 }
203                 else if (m != 0xff)
204                 {
205                     *dst = FbIntMult(m, *dst, t);
206                 }
207                 dst++;
208             }
209         }
210     }
211 }
212
213
214 static void
215 fbCompositeSrcIn_8x8 (pixman_implementation_t *imp,
216                       pixman_op_t      op,
217                       pixman_image_t  *iSrc,
218                       pixman_image_t  *iMask,
219                       pixman_image_t  *iDst,
220                       int32_t          xSrc,
221                       int32_t          ySrc,
222                       int32_t          xMask,
223                       int32_t          yMask,
224                       int32_t          xDst,
225                       int32_t          yDst,
226                       int32_t         width,
227                       int32_t         height)
228 {
229     uint8_t     *dstLine, *dst;
230     uint8_t     *srcLine, *src;
231     int dstStride, srcStride;
232     uint16_t    w;
233     uint8_t     s;
234     uint16_t    t;
235
236     fbComposeGetStart (iSrc, xSrc, ySrc, uint8_t, srcStride, srcLine, 1);
237     fbComposeGetStart (iDst, xDst, yDst, uint8_t, dstStride, dstLine, 1);
238
239     while (height--)
240     {
241         dst = dstLine;
242         dstLine += dstStride;
243         src = srcLine;
244         srcLine += srcStride;
245         w = width;
246
247         while (w--)
248         {
249             s = *src++;
250             if (s == 0)
251             {
252                 *dst = 0;
253             }
254             else if (s != 0xff)
255             {
256                 *dst = FbIntMult(s, *dst, t);
257             }
258             dst++;
259         }
260     }
261 }
262
263 static void
264 fbCompositeSolidMask_nx8x8888 (pixman_implementation_t *imp,
265                                pixman_op_t      op,
266                                pixman_image_t * pSrc,
267                                pixman_image_t * pMask,
268                                pixman_image_t * pDst,
269                                int32_t      xSrc,
270                                int32_t      ySrc,
271                                int32_t      xMask,
272                                int32_t      yMask,
273                                int32_t      xDst,
274                                int32_t      yDst,
275                                int32_t     width,
276                                int32_t     height)
277 {
278     uint32_t     src, srca;
279     uint32_t    *dstLine, *dst, d;
280     uint8_t     *maskLine, *mask, m;
281     int          dstStride, maskStride;
282     uint16_t     w;
283
284     src = _pixman_image_get_solid(pSrc, pDst->bits.format);
285
286     srca = src >> 24;
287     if (src == 0)
288         return;
289
290     fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1);
291     fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1);
292
293     while (height--)
294     {
295         dst = dstLine;
296         dstLine += dstStride;
297         mask = maskLine;
298         maskLine += maskStride;
299         w = width;
300
301         while (w--)
302         {
303             m = *mask++;
304             if (m == 0xff)
305             {
306                 if (srca == 0xff)
307                     *dst = src;
308                 else
309                     *dst = fbOver (src, *dst);
310             }
311             else if (m)
312             {
313                 d = fbIn (src, m);
314                 *dst = fbOver (d, *dst);
315             }
316             dst++;
317         }
318     }
319 }
320
321 static void
322 fbCompositeSolidMask_nx8888x8888C (pixman_implementation_t *imp,
323                                    pixman_op_t op,
324                                    pixman_image_t * pSrc,
325                                    pixman_image_t * pMask,
326                                    pixman_image_t * pDst,
327                                    int32_t      xSrc,
328                                    int32_t      ySrc,
329                                    int32_t      xMask,
330                                    int32_t      yMask,
331                                    int32_t      xDst,
332                                    int32_t      yDst,
333                                    int32_t     width,
334                                    int32_t     height)
335 {
336     uint32_t    src, srca;
337     uint32_t    *dstLine, *dst, d;
338     uint32_t    *maskLine, *mask, ma;
339     int dstStride, maskStride;
340     uint16_t    w;
341     uint32_t    m, n, o, p;
342
343     src = _pixman_image_get_solid(pSrc, pDst->bits.format);
344
345     srca = src >> 24;
346     if (src == 0)
347         return;
348
349     fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1);
350     fbComposeGetStart (pMask, xMask, yMask, uint32_t, maskStride, maskLine, 1);
351
352     while (height--)
353     {
354         dst = dstLine;
355         dstLine += dstStride;
356         mask = maskLine;
357         maskLine += maskStride;
358         w = width;
359
360         while (w--)
361         {
362             ma = *mask++;
363             if (ma == 0xffffffff)
364             {
365                 if (srca == 0xff)
366                     *dst = src;
367                 else
368                     *dst = fbOver (src, *dst);
369             }
370             else if (ma)
371             {
372                 d = *dst;
373 #define FbInOverC(src,srca,msk,dst,i,result) { \
374     uint16_t  __a = FbGet8(msk,i); \
375     uint32_t  __t, __ta; \
376     uint32_t  __i; \
377     __t = FbIntMult (FbGet8(src,i), __a,__i); \
378     __ta = (uint8_t) ~FbIntMult (srca, __a,__i); \
379     __t = __t + FbIntMult(FbGet8(dst,i),__ta,__i); \
380     __t = (uint32_t) (uint8_t) (__t | (-(__t >> 8))); \
381     result = __t << (i); \
382 }
383                 FbInOverC (src, srca, ma, d, 0, m);
384                 FbInOverC (src, srca, ma, d, 8, n);
385                 FbInOverC (src, srca, ma, d, 16, o);
386                 FbInOverC (src, srca, ma, d, 24, p);
387                 *dst = m|n|o|p;
388             }
389             dst++;
390         }
391     }
392 }
393
394 static void
395 fbCompositeSolidMask_nx8x0888 (pixman_implementation_t *imp,
396                                pixman_op_t op,
397                                pixman_image_t * pSrc,
398                                pixman_image_t * pMask,
399                                pixman_image_t * pDst,
400                                int32_t      xSrc,
401                                int32_t      ySrc,
402                                int32_t      xMask,
403                                int32_t      yMask,
404                                int32_t      xDst,
405                                int32_t      yDst,
406                                int32_t     width,
407                                int32_t     height)
408 {
409     uint32_t    src, srca;
410     uint8_t     *dstLine, *dst;
411     uint32_t    d;
412     uint8_t     *maskLine, *mask, m;
413     int dstStride, maskStride;
414     uint16_t    w;
415
416     src = _pixman_image_get_solid(pSrc, pDst->bits.format);
417
418     srca = src >> 24;
419     if (src == 0)
420         return;
421
422     fbComposeGetStart (pDst, xDst, yDst, uint8_t, dstStride, dstLine, 3);
423     fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1);
424
425     while (height--)
426     {
427         dst = dstLine;
428         dstLine += dstStride;
429         mask = maskLine;
430         maskLine += maskStride;
431         w = width;
432
433         while (w--)
434         {
435             m = *mask++;
436             if (m == 0xff)
437             {
438                 if (srca == 0xff)
439                     d = src;
440                 else
441                 {
442                     d = Fetch24(pDst, dst);
443                     d = fbOver24 (src, d);
444                 }
445                 Store24(pDst, dst,d);
446             }
447             else if (m)
448             {
449                 d = fbOver24 (fbIn(src,m), Fetch24(pDst, dst));
450                 Store24(pDst, dst, d);
451             }
452             dst += 3;
453         }
454     }
455 }
456
457 static void
458 fbCompositeSolidMask_nx8x0565 (pixman_implementation_t *imp,
459                                pixman_op_t op,
460                                   pixman_image_t * pSrc,
461                                   pixman_image_t * pMask,
462                                   pixman_image_t * pDst,
463                                   int32_t      xSrc,
464                                   int32_t      ySrc,
465                                   int32_t      xMask,
466                                   int32_t      yMask,
467                                   int32_t      xDst,
468                                   int32_t      yDst,
469                                   int32_t     width,
470                                   int32_t     height)
471 {
472     uint32_t    src, srca;
473     uint16_t    *dstLine, *dst;
474     uint32_t    d;
475     uint8_t     *maskLine, *mask, m;
476     int dstStride, maskStride;
477     uint16_t    w;
478
479     src = _pixman_image_get_solid(pSrc, pDst->bits.format);
480
481     srca = src >> 24;
482     if (src == 0)
483         return;
484
485     fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1);
486     fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1);
487
488     while (height--)
489     {
490         dst = dstLine;
491         dstLine += dstStride;
492         mask = maskLine;
493         maskLine += maskStride;
494         w = width;
495
496         while (w--)
497         {
498             m = *mask++;
499             if (m == 0xff)
500             {
501                 if (srca == 0xff)
502                     d = src;
503                 else
504                 {
505                     d = *dst;
506                     d = fbOver24 (src, cvt0565to0888(d));
507                 }
508                 *dst = cvt8888to0565(d);
509             }
510             else if (m)
511             {
512                 d = *dst;
513                 d = fbOver24 (fbIn(src,m), cvt0565to0888(d));
514                 *dst = cvt8888to0565(d);
515             }
516             dst++;
517         }
518     }
519 }
520
521 static void
522 fbCompositeSolidMask_nx8888x0565C (pixman_implementation_t *imp,
523                                    pixman_op_t op,
524                                    pixman_image_t * pSrc,
525                                    pixman_image_t * pMask,
526                                    pixman_image_t * pDst,
527                                    int32_t      xSrc,
528                                    int32_t      ySrc,
529                                    int32_t      xMask,
530                                    int32_t      yMask,
531                                    int32_t      xDst,
532                                    int32_t      yDst,
533                                    int32_t     width,
534                                    int32_t     height)
535 {
536     uint32_t    src, srca;
537     uint16_t    src16;
538     uint16_t    *dstLine, *dst;
539     uint32_t    d;
540     uint32_t    *maskLine, *mask, ma;
541     int dstStride, maskStride;
542     uint16_t    w;
543     uint32_t    m, n, o;
544
545     src = _pixman_image_get_solid(pSrc, pDst->bits.format);
546
547     srca = src >> 24;
548     if (src == 0)
549         return;
550
551     src16 = cvt8888to0565(src);
552
553     fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1);
554     fbComposeGetStart (pMask, xMask, yMask, uint32_t, maskStride, maskLine, 1);
555
556     while (height--)
557     {
558         dst = dstLine;
559         dstLine += dstStride;
560         mask = maskLine;
561         maskLine += maskStride;
562         w = width;
563
564         while (w--)
565         {
566             ma = *mask++;
567             if (ma == 0xffffffff)
568             {
569                 if (srca == 0xff)
570                 {
571                     *dst = src16;
572                 }
573                 else
574                 {
575                     d = *dst;
576                     d = fbOver24 (src, cvt0565to0888(d));
577                     *dst = cvt8888to0565(d);
578                 }
579             }
580             else if (ma)
581             {
582                 d = *dst;
583                 d = cvt0565to0888(d);
584                 FbInOverC (src, srca, ma, d, 0, m);
585                 FbInOverC (src, srca, ma, d, 8, n);
586                 FbInOverC (src, srca, ma, d, 16, o);
587                 d = m|n|o;
588                 *dst = cvt8888to0565(d);
589             }
590             dst++;
591         }
592     }
593 }
594
595 static void
596 fbCompositeSrc_8888x8888 (pixman_implementation_t *imp,
597                           pixman_op_t op,
598                          pixman_image_t * pSrc,
599                          pixman_image_t * pMask,
600                          pixman_image_t * pDst,
601                          int32_t      xSrc,
602                          int32_t      ySrc,
603                          int32_t      xMask,
604                          int32_t      yMask,
605                          int32_t      xDst,
606                          int32_t      yDst,
607                          int32_t     width,
608                          int32_t     height)
609 {
610     uint32_t    *dstLine, *dst;
611     uint32_t    *srcLine, *src, s;
612     int dstStride, srcStride;
613     uint8_t     a;
614     uint16_t    w;
615
616     fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1);
617     fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1);
618
619     while (height--)
620     {
621         dst = dstLine;
622         dstLine += dstStride;
623         src = srcLine;
624         srcLine += srcStride;
625         w = width;
626
627         while (w--)
628         {
629             s = *src++;
630             a = s >> 24;
631             if (a == 0xff)
632                 *dst = s;
633             else if (s)
634                 *dst = fbOver (s, *dst);
635             dst++;
636         }
637     }
638 }
639
640 static void
641 fbCompositeSrc_8888x0888 (pixman_implementation_t *imp,
642                           pixman_op_t op,
643                          pixman_image_t * pSrc,
644                          pixman_image_t * pMask,
645                          pixman_image_t * pDst,
646                          int32_t      xSrc,
647                          int32_t      ySrc,
648                          int32_t      xMask,
649                          int32_t      yMask,
650                          int32_t      xDst,
651                          int32_t      yDst,
652                          int32_t     width,
653                          int32_t     height)
654 {
655     uint8_t     *dstLine, *dst;
656     uint32_t    d;
657     uint32_t    *srcLine, *src, s;
658     uint8_t     a;
659     int dstStride, srcStride;
660     uint16_t    w;
661
662     fbComposeGetStart (pDst, xDst, yDst, uint8_t, dstStride, dstLine, 3);
663     fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1);
664
665     while (height--)
666     {
667         dst = dstLine;
668         dstLine += dstStride;
669         src = srcLine;
670         srcLine += srcStride;
671         w = width;
672
673         while (w--)
674         {
675             s = *src++;
676             a = s >> 24;
677             if (a)
678             {
679                 if (a == 0xff)
680                     d = s;
681                 else
682                     d = fbOver24 (s, Fetch24(pDst, dst));
683                 Store24(pDst, dst, d);
684             }
685             dst += 3;
686         }
687     }
688 }
689
690 static void
691 fbCompositeSrc_8888x0565 (pixman_implementation_t *imp,
692                           pixman_op_t op,
693                          pixman_image_t * pSrc,
694                          pixman_image_t * pMask,
695                          pixman_image_t * pDst,
696                          int32_t      xSrc,
697                          int32_t      ySrc,
698                          int32_t      xMask,
699                          int32_t      yMask,
700                          int32_t      xDst,
701                          int32_t      yDst,
702                          int32_t     width,
703                          int32_t     height)
704 {
705     uint16_t    *dstLine, *dst;
706     uint32_t    d;
707     uint32_t    *srcLine, *src, s;
708     uint8_t     a;
709     int dstStride, srcStride;
710     uint16_t    w;
711
712     fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1);
713     fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1);
714
715     while (height--)
716     {
717         dst = dstLine;
718         dstLine += dstStride;
719         src = srcLine;
720         srcLine += srcStride;
721         w = width;
722
723         while (w--)
724         {
725             s = *src++;
726             a = s >> 24;
727             if (s)
728             {
729                 if (a == 0xff)
730                     d = s;
731                 else
732                 {
733                     d = *dst;
734                     d = fbOver24 (s, cvt0565to0888(d));
735                 }
736                 *dst = cvt8888to0565(d);
737             }
738             dst++;
739         }
740     }
741 }
742
743 static void
744 fbCompositeSrc_x888x0565 (pixman_implementation_t *imp,
745                           pixman_op_t op,
746                           pixman_image_t * pSrc,
747                           pixman_image_t * pMask,
748                           pixman_image_t * pDst,
749                           int32_t      xSrc,
750                           int32_t      ySrc,
751                           int32_t      xMask,
752                           int32_t      yMask,
753                           int32_t      xDst,
754                           int32_t      yDst,
755                           int32_t     width,
756                           int32_t     height)
757 {
758     uint16_t    *dstLine, *dst;
759     uint32_t    *srcLine, *src, s;
760     int dstStride, srcStride;
761     uint16_t    w;
762
763     fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1);
764     fbComposeGetStart (pDst, xDst, yDst, uint16_t, dstStride, dstLine, 1);
765
766     while (height--)
767     {
768         dst = dstLine;
769         dstLine += dstStride;
770         src = srcLine;
771         srcLine += srcStride;
772         w = width;
773
774         while (w--)
775         {
776             s = *src++;
777             *dst = cvt8888to0565(s);
778             dst++;
779         }
780     }
781 }
782
783 static void
784 fbCompositeSrcAdd_8000x8000 (pixman_implementation_t *imp,
785                              pixman_op_t        op,
786                              pixman_image_t * pSrc,
787                              pixman_image_t * pMask,
788                              pixman_image_t * pDst,
789                              int32_t      xSrc,
790                              int32_t      ySrc,
791                              int32_t      xMask,
792                              int32_t      yMask,
793                              int32_t      xDst,
794                              int32_t      yDst,
795                              int32_t     width,
796                              int32_t     height)
797 {
798     uint8_t     *dstLine, *dst;
799     uint8_t     *srcLine, *src;
800     int dstStride, srcStride;
801     uint16_t    w;
802     uint8_t     s, d;
803     uint16_t    t;
804
805     fbComposeGetStart (pSrc, xSrc, ySrc, uint8_t, srcStride, srcLine, 1);
806     fbComposeGetStart (pDst, xDst, yDst, uint8_t, dstStride, dstLine, 1);
807
808     while (height--)
809     {
810         dst = dstLine;
811         dstLine += dstStride;
812         src = srcLine;
813         srcLine += srcStride;
814         w = width;
815
816         while (w--)
817         {
818             s = *src++;
819             if (s)
820             {
821                 if (s != 0xff)
822                 {
823                     d = *dst;
824                     t = d + s;
825                     s = t | (0 - (t >> 8));
826                 }
827                 *dst = s;
828             }
829             dst++;
830         }
831     }
832 }
833
834 static void
835 fbCompositeSrcAdd_8888x8888 (pixman_implementation_t *imp,
836                              pixman_op_t        op,
837                              pixman_image_t * pSrc,
838                              pixman_image_t * pMask,
839                              pixman_image_t * pDst,
840                              int32_t      xSrc,
841                              int32_t      ySrc,
842                              int32_t      xMask,
843                              int32_t      yMask,
844                              int32_t      xDst,
845                              int32_t      yDst,
846                              int32_t     width,
847                              int32_t     height)
848 {
849     uint32_t    *dstLine, *dst;
850     uint32_t    *srcLine, *src;
851     int dstStride, srcStride;
852     uint16_t    w;
853     uint32_t    s, d;
854     uint16_t    t;
855     uint32_t    m,n,o,p;
856
857     fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, srcLine, 1);
858     fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dstLine, 1);
859
860     while (height--)
861     {
862         dst = dstLine;
863         dstLine += dstStride;
864         src = srcLine;
865         srcLine += srcStride;
866         w = width;
867
868         while (w--)
869         {
870             s = *src++;
871             if (s)
872             {
873                 if (s != 0xffffffff)
874                 {
875                     d = *dst;
876                     if (d)
877                     {
878                         m = FbAdd(s,d,0,t);
879                         n = FbAdd(s,d,8,t);
880                         o = FbAdd(s,d,16,t);
881                         p = FbAdd(s,d,24,t);
882                         s = m|n|o|p;
883                     }
884                 }
885                 *dst = s;
886             }
887             dst++;
888         }
889     }
890 }
891
892 static void
893 fbCompositeSrcAdd_8888x8x8 (pixman_implementation_t *imp,
894                             pixman_op_t op,
895                             pixman_image_t * pSrc,
896                             pixman_image_t * pMask,
897                             pixman_image_t * pDst,
898                             int32_t      xSrc,
899                             int32_t      ySrc,
900                             int32_t      xMask,
901                             int32_t      yMask,
902                             int32_t      xDst,
903                             int32_t      yDst,
904                             int32_t     width,
905                             int32_t     height)
906 {
907     uint8_t     *dstLine, *dst;
908     uint8_t     *maskLine, *mask;
909     int dstStride, maskStride;
910     uint16_t    w;
911     uint32_t    src;
912     uint8_t     sa;
913
914     fbComposeGetStart (pDst, xDst, yDst, uint8_t, dstStride, dstLine, 1);
915     fbComposeGetStart (pMask, xMask, yMask, uint8_t, maskStride, maskLine, 1);
916     src = _pixman_image_get_solid (pSrc, pDst->bits.format);
917     sa = (src >> 24);
918
919     while (height--)
920     {
921         dst = dstLine;
922         dstLine += dstStride;
923         mask = maskLine;
924         maskLine += maskStride;
925         w = width;
926
927         while (w--)
928         {
929             uint16_t    tmp;
930             uint16_t    a;
931             uint32_t    m, d;
932             uint32_t    r;
933
934             a = *mask++;
935             d = *dst;
936
937             m = FbInU (sa, 0, a, tmp);
938             r = FbAdd (m, d, 0, tmp);
939
940             *dst++ = r;
941         }
942     }
943 }
944
945 /*
946  * Simple bitblt
947  */
948
949 static void
950 fbCompositeSolidFill (pixman_implementation_t *imp,
951                       pixman_op_t op,
952                       pixman_image_t * pSrc,
953                       pixman_image_t * pMask,
954                       pixman_image_t * pDst,
955                       int32_t      xSrc,
956                       int32_t      ySrc,
957                       int32_t      xMask,
958                       int32_t      yMask,
959                       int32_t      xDst,
960                       int32_t      yDst,
961                       int32_t     width,
962                       int32_t     height)
963 {
964     uint32_t    src;
965
966     src = _pixman_image_get_solid(pSrc, pDst->bits.format);
967
968     if (pDst->bits.format == PIXMAN_a8)
969         src = src >> 24;
970     else if (pDst->bits.format == PIXMAN_r5g6b5 ||
971              pDst->bits.format == PIXMAN_b5g6r5)
972         src = cvt8888to0565 (src);
973
974     pixman_fill (pDst->bits.bits, pDst->bits.rowstride,
975                  PIXMAN_FORMAT_BPP (pDst->bits.format),
976                  xDst, yDst,
977                  width, height,
978                  src);
979 }
980
981 static void
982 fbCompositeSrc_8888xx888 (pixman_implementation_t *imp,
983                           pixman_op_t op,
984                           pixman_image_t * pSrc,
985                           pixman_image_t * pMask,
986                           pixman_image_t * pDst,
987                           int32_t      xSrc,
988                           int32_t      ySrc,
989                           int32_t      xMask,
990                           int32_t      yMask,
991                           int32_t      xDst,
992                           int32_t      yDst,
993                           int32_t     width,
994                           int32_t     height)
995 {
996     uint32_t    *dst;
997     uint32_t    *src;
998     int          dstStride, srcStride;
999     uint32_t     n_bytes = width * sizeof (uint32_t);
1000
1001     fbComposeGetStart (pSrc, xSrc, ySrc, uint32_t, srcStride, src, 1);
1002     fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dst, 1);
1003
1004     while (height--)
1005     {
1006         memcpy (dst, src, n_bytes);
1007
1008         dst += dstStride;
1009         src += srcStride;
1010     }
1011 }
1012
1013 static const pixman_fast_path_t c_fast_paths[] =
1014 {
1015     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8,       PIXMAN_r5g6b5,   fbCompositeSolidMask_nx8x0565, 0 },
1016     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8,       PIXMAN_b5g6r5,   fbCompositeSolidMask_nx8x0565, 0 },
1017     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8,       PIXMAN_r8g8b8,   fbCompositeSolidMask_nx8x0888, 0 },
1018     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8,       PIXMAN_b8g8r8,   fbCompositeSolidMask_nx8x0888, 0 },
1019     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8,       PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8x8888, 0 },
1020     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8,       PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8x8888, 0 },
1021     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8,       PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8x8888, 0 },
1022     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8,       PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8x8888, 0 },
1023     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8r8g8b8, PIXMAN_a8r8g8b8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA },
1024     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8r8g8b8, PIXMAN_x8r8g8b8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA },
1025     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8r8g8b8, PIXMAN_r5g6b5,   fbCompositeSolidMask_nx8888x0565C, NEED_COMPONENT_ALPHA },
1026     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8b8g8r8, PIXMAN_a8b8g8r8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA },
1027     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8b8g8r8, PIXMAN_x8b8g8r8, fbCompositeSolidMask_nx8888x8888C, NEED_COMPONENT_ALPHA },
1028     { PIXMAN_OP_OVER, PIXMAN_solid,    PIXMAN_a8b8g8r8, PIXMAN_b5g6r5,   fbCompositeSolidMask_nx8888x0565C, NEED_COMPONENT_ALPHA },
1029     { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8,       PIXMAN_x8r8g8b8, fbCompositeOver_x888x8x8888,       0 },
1030     { PIXMAN_OP_OVER, PIXMAN_x8r8g8b8, PIXMAN_a8,       PIXMAN_a8r8g8b8, fbCompositeOver_x888x8x8888,       0 },
1031     { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8,       PIXMAN_x8b8g8r8, fbCompositeOver_x888x8x8888,       0 },
1032     { PIXMAN_OP_OVER, PIXMAN_x8b8g8r8, PIXMAN_a8,       PIXMAN_a8b8g8r8, fbCompositeOver_x888x8x8888,       0 },
1033     { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null,     PIXMAN_a8r8g8b8, fbCompositeSrc_8888x8888,         0 },
1034     { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null,     PIXMAN_x8r8g8b8, fbCompositeSrc_8888x8888,         0 },
1035     { PIXMAN_OP_OVER, PIXMAN_a8r8g8b8, PIXMAN_null,     PIXMAN_r5g6b5,   fbCompositeSrc_8888x0565,         0 },
1036     { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null,     PIXMAN_a8b8g8r8, fbCompositeSrc_8888x8888,         0 },
1037     { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null,     PIXMAN_x8b8g8r8, fbCompositeSrc_8888x8888,         0 },
1038     { PIXMAN_OP_OVER, PIXMAN_a8b8g8r8, PIXMAN_null,     PIXMAN_b5g6r5,   fbCompositeSrc_8888x0565,         0 },
1039     { PIXMAN_OP_ADD, PIXMAN_a8r8g8b8,  PIXMAN_null,     PIXMAN_a8r8g8b8, fbCompositeSrcAdd_8888x8888,   0 },
1040     { PIXMAN_OP_ADD, PIXMAN_a8b8g8r8,  PIXMAN_null,     PIXMAN_a8b8g8r8, fbCompositeSrcAdd_8888x8888,   0 },
1041     { PIXMAN_OP_ADD, PIXMAN_a8,        PIXMAN_null,     PIXMAN_a8,       fbCompositeSrcAdd_8000x8000,   0 },
1042     { PIXMAN_OP_ADD, PIXMAN_solid,     PIXMAN_a8,       PIXMAN_a8,       fbCompositeSrcAdd_8888x8x8,    0 },
1043     { PIXMAN_OP_SRC, PIXMAN_solid,     PIXMAN_null,     PIXMAN_a8r8g8b8, fbCompositeSolidFill, 0 },
1044     { PIXMAN_OP_SRC, PIXMAN_solid,     PIXMAN_null,     PIXMAN_x8r8g8b8, fbCompositeSolidFill, 0 },
1045     { PIXMAN_OP_SRC, PIXMAN_solid,     PIXMAN_null,     PIXMAN_a8b8g8r8, fbCompositeSolidFill, 0 },
1046     { PIXMAN_OP_SRC, PIXMAN_solid,     PIXMAN_null,     PIXMAN_x8b8g8r8, fbCompositeSolidFill, 0 },
1047     { PIXMAN_OP_SRC, PIXMAN_solid,     PIXMAN_null,     PIXMAN_a8,       fbCompositeSolidFill, 0 },
1048     { PIXMAN_OP_SRC, PIXMAN_solid,     PIXMAN_null,     PIXMAN_r5g6b5,   fbCompositeSolidFill, 0 },
1049     { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8,  PIXMAN_null,     PIXMAN_x8r8g8b8, fbCompositeSrc_8888xx888, 0 },
1050     { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8,  PIXMAN_null,     PIXMAN_x8r8g8b8, fbCompositeSrc_8888xx888, 0 },
1051     { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8,  PIXMAN_null,     PIXMAN_x8b8g8r8, fbCompositeSrc_8888xx888, 0 },
1052     { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8,  PIXMAN_null,     PIXMAN_x8b8g8r8, fbCompositeSrc_8888xx888, 0 },
1053     { PIXMAN_OP_SRC, PIXMAN_a8r8g8b8,  PIXMAN_null,     PIXMAN_r5g6b5,   fbCompositeSrc_x888x0565, 0 },
1054     { PIXMAN_OP_SRC, PIXMAN_x8r8g8b8,  PIXMAN_null,     PIXMAN_r5g6b5,   fbCompositeSrc_x888x0565, 0 },
1055     { PIXMAN_OP_SRC, PIXMAN_a8b8g8r8,  PIXMAN_null,     PIXMAN_b5g6r5,   fbCompositeSrc_x888x0565, 0 },
1056     { PIXMAN_OP_SRC, PIXMAN_x8b8g8r8,  PIXMAN_null,     PIXMAN_b5g6r5,   fbCompositeSrc_x888x0565, 0 },
1057     { PIXMAN_OP_IN,  PIXMAN_a8,        PIXMAN_null,     PIXMAN_a8,       fbCompositeSrcIn_8x8,   0 },
1058     { PIXMAN_OP_IN,  PIXMAN_solid,     PIXMAN_a8,       PIXMAN_a8,       fbCompositeSolidMaskIn_nx8x8, 0 },
1059     { PIXMAN_OP_NONE },
1060 };
1061
1062 static void
1063 fbCompositeSrcScaleNearest (pixman_implementation_t *imp,
1064                             pixman_op_t     op,
1065                             pixman_image_t *pSrc,
1066                             pixman_image_t *pMask,
1067                             pixman_image_t *pDst,
1068                             int32_t         xSrc,
1069                             int32_t         ySrc,
1070                             int32_t         xMask,
1071                             int32_t         yMask,
1072                             int32_t         xDst,
1073                             int32_t         yDst,
1074                             int32_t        width,
1075                             int32_t        height)
1076 {
1077     uint32_t       *dst;
1078     uint32_t       *src;
1079     int             dstStride, srcStride;
1080     int             i, j;
1081     pixman_vector_t v;
1082     
1083     fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dst, 1);
1084     /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be
1085      * transformed from destination space to source space */
1086     fbComposeGetStart (pSrc, 0, 0, uint32_t, srcStride, src, 1);
1087     
1088     /* reference point is the center of the pixel */
1089     v.vector[0] = pixman_int_to_fixed(xSrc) + pixman_fixed_1 / 2;
1090     v.vector[1] = pixman_int_to_fixed(ySrc) + pixman_fixed_1 / 2;
1091     v.vector[2] = pixman_fixed_1;
1092     
1093     if (!pixman_transform_point_3d (pSrc->common.transform, &v))
1094         return;
1095     
1096     /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */
1097     v.vector[0] -= pixman_fixed_e;
1098     v.vector[1] -= pixman_fixed_e;
1099     
1100     for (j = 0; j < height; j++) {
1101         pixman_fixed_t vx = v.vector[0];
1102         pixman_fixed_t vy = v.vector[1];
1103         for (i = 0; i < width; ++i) {
1104             pixman_bool_t inside_bounds;
1105             uint32_t result;
1106             int x, y;
1107             x = vx >> 16;
1108             y = vy >> 16;
1109             
1110             /* apply the repeat function */
1111             switch (pSrc->common.repeat) {
1112             case PIXMAN_REPEAT_NORMAL:
1113                 x = MOD (x, pSrc->bits.width);
1114                 y = MOD (y, pSrc->bits.height);
1115                 inside_bounds = TRUE;
1116                 break;
1117                 
1118             case PIXMAN_REPEAT_PAD:
1119                 x = CLIP (x, 0, pSrc->bits.width-1);
1120                 y = CLIP (y, 0, pSrc->bits.height-1);
1121                 inside_bounds = TRUE;
1122                 break;
1123                 
1124             case PIXMAN_REPEAT_REFLECT:
1125                 x = MOD (x, pSrc->bits.width * 2);
1126                 if (x >= pSrc->bits.width)
1127                     x = pSrc->bits.width * 2 - x - 1;
1128                 y = MOD (y, pSrc->bits.height * 2);
1129                 if (y >= pSrc->bits.height)
1130                     y = pSrc->bits.height * 2 - y - 1;
1131                 inside_bounds = TRUE;
1132                 break;
1133                 
1134             case PIXMAN_REPEAT_NONE:
1135             default:
1136                 inside_bounds = (x >= 0 && x < pSrc->bits.width && y >= 0 && y < pSrc->bits.height);
1137                 break;
1138             }
1139             
1140             if (inside_bounds) {
1141                 //XXX: we should move this multiplication out of the loop
1142                 result = *(src + y * srcStride + x);
1143             } else {
1144                 result = 0;
1145             }
1146             *(dst + i) = result;
1147             
1148             /* adjust the x location by a unit vector in the x direction:
1149              * this is equivalent to transforming x+1 of the destination point to source space */
1150             vx += pSrc->common.transform->matrix[0][0];
1151         }
1152         /* adjust the y location by a unit vector in the y direction
1153          * this is equivalent to transforming y+1 of the destination point to source space */
1154         v.vector[1] += pSrc->common.transform->matrix[1][1];
1155         dst += dstStride;
1156     }
1157 }
1158
1159 static void
1160 fast_path_composite (pixman_implementation_t *imp,
1161                      pixman_op_t     op,
1162                      pixman_image_t *src,
1163                      pixman_image_t *mask,
1164                      pixman_image_t *dest,
1165                      int32_t         src_x,
1166                      int32_t         src_y,
1167                      int32_t         mask_x,
1168                      int32_t         mask_y,
1169                      int32_t         dest_x,
1170                      int32_t         dest_y,
1171                      int32_t        width,
1172                      int32_t        height)
1173 {
1174     if (src->type == BITS
1175         && src->common.transform
1176         && !mask
1177         && op == PIXMAN_OP_SRC
1178         && !src->common.alpha_map && !dest->common.alpha_map
1179         && (src->common.filter == PIXMAN_FILTER_NEAREST)
1180         && PIXMAN_FORMAT_BPP(dest->bits.format) == 32
1181         && src->bits.format == dest->bits.format
1182         && !src->common.read_func && !src->common.write_func
1183         && !dest->common.read_func && !dest->common.write_func)
1184     {
1185         /* ensure that the transform matrix only has a scale */
1186         if (src->common.transform->matrix[0][1] == 0 &&
1187             src->common.transform->matrix[1][0] == 0 &&
1188             src->common.transform->matrix[2][0] == 0 &&
1189             src->common.transform->matrix[2][1] == 0 &&
1190             src->common.transform->matrix[2][2] == pixman_fixed_1)
1191         {
1192             _pixman_walk_composite_region (imp, op,
1193                                            src, mask, dest,
1194                                            src_x, src_y,
1195                                            mask_x, mask_y,
1196                                            dest_x, dest_y,
1197                                            width, height,
1198                                            fbCompositeSrcScaleNearest);
1199             return;
1200         }
1201     }
1202
1203     if (_pixman_run_fast_path (c_fast_paths, imp,
1204                                op, src, mask, dest,
1205                                src_x, src_y,
1206                                mask_x, mask_y,
1207                                dest_x, dest_y,
1208                                width, height))
1209     {
1210         return;
1211     }
1212
1213     _pixman_implementation_composite (imp->delegate, op,
1214                                       src, mask, dest,
1215                                       src_x, src_y,
1216                                       mask_x, mask_y,
1217                                       dest_x, dest_y,
1218                                       width, height);
1219 }
1220
1221 static void
1222 pixman_fill8 (uint32_t  *bits,
1223               int       stride,
1224               int       x,
1225               int       y,
1226               int       width,
1227               int       height,
1228               uint32_t  xor)
1229 {
1230     int byte_stride = stride * (int) sizeof (uint32_t);
1231     uint8_t *dst = (uint8_t *) bits;
1232     uint8_t v = xor & 0xff;
1233     int i;
1234
1235     dst = dst + y * byte_stride + x;
1236
1237     while (height--)
1238     {
1239         for (i = 0; i < width; ++i)
1240             dst[i] = v;
1241
1242         dst += byte_stride;
1243     }
1244 }
1245
1246 static void
1247 pixman_fill16 (uint32_t *bits,
1248                int       stride,
1249                int       x,
1250                int       y,
1251                int       width,
1252                int       height,
1253                uint32_t  xor)
1254 {
1255     int short_stride = (stride * (int) sizeof (uint32_t)) / (int) sizeof (uint16_t);
1256     uint16_t *dst = (uint16_t *)bits;
1257     uint16_t v = xor & 0xffff;
1258     int i;
1259
1260     dst = dst + y * short_stride + x;
1261
1262     while (height--)
1263     {
1264         for (i = 0; i < width; ++i)
1265             dst[i] = v;
1266
1267         dst += short_stride;
1268     }
1269 }
1270
1271 static void
1272 pixman_fill32 (uint32_t *bits,
1273                int       stride,
1274                int       x,
1275                int       y,
1276                int       width,
1277                int       height,
1278                uint32_t  xor)
1279 {
1280     int i;
1281
1282     bits = bits + y * stride + x;
1283
1284     while (height--)
1285     {
1286         for (i = 0; i < width; ++i)
1287             bits[i] = xor;
1288
1289         bits += stride;
1290     }
1291 }
1292
1293 static pixman_bool_t
1294 fast_path_fill (pixman_implementation_t *imp,
1295                 uint32_t *bits,
1296                 int stride,
1297                 int bpp,
1298                 int x,
1299                 int y,
1300                 int width,
1301                 int height,
1302                 uint32_t xor)
1303 {
1304     switch (bpp)
1305     {
1306     case 8:
1307         pixman_fill8 (bits, stride, x, y, width, height, xor);
1308         break;
1309         
1310     case 16:
1311         pixman_fill16 (bits, stride, x, y, width, height, xor);
1312         break;
1313         
1314     case 32:
1315         pixman_fill32 (bits, stride, x, y, width, height, xor);
1316         break;
1317         
1318     default:
1319         return _pixman_implementation_fill (
1320             imp->delegate, bits, stride, bpp, x, y, width, height, xor);
1321         break;
1322     }
1323     
1324     return TRUE;
1325 }
1326
1327 pixman_implementation_t *
1328 _pixman_implementation_create_fast_path (void)
1329 {
1330     pixman_implementation_t *general = _pixman_implementation_create_general ();
1331     pixman_implementation_t *imp = _pixman_implementation_create (general);
1332
1333     imp->composite = fast_path_composite;
1334     imp->fill = fast_path_fill;
1335     
1336     return imp;
1337 }