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