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