Move sse2 and mmx blt implementations to their respective files
[profile/ivi/pixman.git] / pixman / pixman-utils.c
1 /*
2  * Copyright © 2000 SuSE, Inc.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of SuSE not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  SuSE makes no representations about the
11  * suitability of this software for any purpose.  It is provided "as is"
12  * without express or implied warranty.
13  *
14  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
16  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
18  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
19  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  * Author:  Keith Packard, SuSE, Inc.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdlib.h>
29
30 #include "pixman-private.h"
31 #include "pixman-mmx.h"
32 #include "pixman-sse2.h"
33
34 static void
35 pixman_fill8 (uint32_t  *bits,
36               int       stride,
37               int       x,
38               int       y,
39               int       width,
40               int       height,
41               uint32_t  xor)
42 {
43     int byte_stride = stride * (int) sizeof (uint32_t);
44     uint8_t *dst = (uint8_t *) bits;
45     uint8_t v = xor & 0xff;
46     int i;
47
48     dst = dst + y * byte_stride + x;
49
50     while (height--)
51     {
52         for (i = 0; i < width; ++i)
53             dst[i] = v;
54
55         dst += byte_stride;
56     }
57 }
58
59 static void
60 pixman_fill16 (uint32_t *bits,
61                int       stride,
62                int       x,
63                int       y,
64                int       width,
65                int       height,
66                uint32_t  xor)
67 {
68     int short_stride = (stride * (int) sizeof (uint32_t)) / (int) sizeof (uint16_t);
69     uint16_t *dst = (uint16_t *)bits;
70     uint16_t v = xor & 0xffff;
71     int i;
72
73     dst = dst + y * short_stride + x;
74
75     while (height--)
76     {
77         for (i = 0; i < width; ++i)
78             dst[i] = v;
79
80         dst += short_stride;
81     }
82 }
83
84 static void
85 pixman_fill32 (uint32_t *bits,
86                int       stride,
87                int       x,
88                int       y,
89                int       width,
90                int       height,
91                uint32_t  xor)
92 {
93     int i;
94
95     bits = bits + y * stride + x;
96
97     while (height--)
98     {
99         for (i = 0; i < width; ++i)
100             bits[i] = xor;
101
102         bits += stride;
103     }
104 }
105
106 #if defined(USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
107 __attribute__((__force_align_arg_pointer__))
108 #endif
109 PIXMAN_EXPORT pixman_bool_t
110 pixman_fill (uint32_t *bits,
111              int stride,
112              int bpp,
113              int x,
114              int y,
115              int width,
116              int height,
117              uint32_t xor)
118 {
119 #if 0
120     printf ("filling: %d %d %d %d (stride: %d, bpp: %d)   pixel: %x\n",
121             x, y, width, height, stride, bpp, xor);
122 #endif
123
124 #ifdef USE_SSE2
125     if (pixman_have_sse2() && pixmanFillsse2 (bits, stride, bpp, x, y, width, height, xor))
126         return TRUE;
127 #endif
128
129 #ifdef USE_MMX
130     if (pixman_have_mmx() && pixman_fill_mmx (bits, stride, bpp, x, y, width, height, xor))
131         return TRUE;
132 #endif
133     
134     switch (bpp)
135     {
136     case 8:
137         pixman_fill8 (bits, stride, x, y, width, height, xor);
138         break;
139         
140     case 16:
141         pixman_fill16 (bits, stride, x, y, width, height, xor);
142         break;
143         
144     case 32:
145         pixman_fill32 (bits, stride, x, y, width, height, xor);
146         break;
147         
148     default:
149         return FALSE;
150         break;
151     }
152
153     return TRUE;
154 }
155
156
157 /*
158  * Compute the smallest value no less than y which is on a
159  * grid row
160  */
161
162 PIXMAN_EXPORT pixman_fixed_t
163 pixman_sample_ceil_y (pixman_fixed_t y, int n)
164 {
165     pixman_fixed_t   f = pixman_fixed_frac(y);
166     pixman_fixed_t   i = pixman_fixed_floor(y);
167
168     f = ((f + Y_FRAC_FIRST(n)) / STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
169     if (f > Y_FRAC_LAST(n))
170     {
171         if (pixman_fixed_to_int(i) == 0x7fff)
172         {
173             f = 0xffff; /* saturate */
174         } else {
175             f = Y_FRAC_FIRST(n);
176             i += pixman_fixed_1;
177         }
178     }
179     return (i | f);
180 }
181
182 #define _div(a,b)    ((a) >= 0 ? (a) / (b) : -((-(a) + (b) - 1) / (b)))
183
184 /*
185  * Compute the largest value no greater than y which is on a
186  * grid row
187  */
188 PIXMAN_EXPORT pixman_fixed_t
189 pixman_sample_floor_y (pixman_fixed_t y, int n)
190 {
191     pixman_fixed_t   f = pixman_fixed_frac(y);
192     pixman_fixed_t   i = pixman_fixed_floor (y);
193
194     f = _div(f - Y_FRAC_FIRST(n), STEP_Y_SMALL(n)) * STEP_Y_SMALL(n) + Y_FRAC_FIRST(n);
195     if (f < Y_FRAC_FIRST(n))
196     {
197         if (pixman_fixed_to_int(i) == 0x8000)
198         {
199             f = 0; /* saturate */
200         } else {
201             f = Y_FRAC_LAST(n);
202             i -= pixman_fixed_1;
203         }
204     }
205     return (i | f);
206 }
207
208 /*
209  * Step an edge by any amount (including negative values)
210  */
211 PIXMAN_EXPORT void
212 pixman_edge_step (pixman_edge_t *e, int n)
213 {
214     pixman_fixed_48_16_t        ne;
215
216     e->x += n * e->stepx;
217
218     ne = e->e + n * (pixman_fixed_48_16_t) e->dx;
219
220     if (n >= 0)
221     {
222         if (ne > 0)
223         {
224             int nx = (ne + e->dy - 1) / e->dy;
225             e->e = ne - nx * (pixman_fixed_48_16_t) e->dy;
226             e->x += nx * e->signdx;
227         }
228     }
229     else
230     {
231         if (ne <= -e->dy)
232         {
233             int nx = (-ne) / e->dy;
234             e->e = ne + nx * (pixman_fixed_48_16_t) e->dy;
235             e->x -= nx * e->signdx;
236         }
237     }
238 }
239
240 /*
241  * A private routine to initialize the multi-step
242  * elements of an edge structure
243  */
244 static void
245 _pixman_edge_multi_init (pixman_edge_t *e, int n, pixman_fixed_t *stepx_p, pixman_fixed_t *dx_p)
246 {
247     pixman_fixed_t      stepx;
248     pixman_fixed_48_16_t        ne;
249
250     ne = n * (pixman_fixed_48_16_t) e->dx;
251     stepx = n * e->stepx;
252     if (ne > 0)
253     {
254         int nx = ne / e->dy;
255         ne -= nx * e->dy;
256         stepx += nx * e->signdx;
257     }
258     *dx_p = ne;
259     *stepx_p = stepx;
260 }
261
262 /*
263  * Initialize one edge structure given the line endpoints and a
264  * starting y value
265  */
266 PIXMAN_EXPORT void
267 pixman_edge_init (pixman_edge_t *e,
268                   int           n,
269                   pixman_fixed_t                y_start,
270                   pixman_fixed_t                x_top,
271                   pixman_fixed_t                y_top,
272                   pixman_fixed_t                x_bot,
273                   pixman_fixed_t                y_bot)
274 {
275     pixman_fixed_t      dx, dy;
276
277     e->x = x_top;
278     e->e = 0;
279     dx = x_bot - x_top;
280     dy = y_bot - y_top;
281     e->dy = dy;
282     e->dx = 0;
283     if (dy)
284     {
285         if (dx >= 0)
286         {
287             e->signdx = 1;
288             e->stepx = dx / dy;
289             e->dx = dx % dy;
290             e->e = -dy;
291         }
292         else
293         {
294             e->signdx = -1;
295             e->stepx = -(-dx / dy);
296             e->dx = -dx % dy;
297             e->e = 0;
298         }
299
300         _pixman_edge_multi_init (e, STEP_Y_SMALL(n), &e->stepx_small, &e->dx_small);
301         _pixman_edge_multi_init (e, STEP_Y_BIG(n), &e->stepx_big, &e->dx_big);
302     }
303     pixman_edge_step (e, y_start - y_top);
304 }
305
306 /*
307  * Initialize one edge structure given a line, starting y value
308  * and a pixel offset for the line
309  */
310 PIXMAN_EXPORT void
311 pixman_line_fixed_edge_init (pixman_edge_t *e,
312                              int            n,
313                              pixman_fixed_t         y,
314                              const pixman_line_fixed_t *line,
315                              int            x_off,
316                              int            y_off)
317 {
318     pixman_fixed_t      x_off_fixed = pixman_int_to_fixed(x_off);
319     pixman_fixed_t      y_off_fixed = pixman_int_to_fixed(y_off);
320     const pixman_point_fixed_t *top, *bot;
321
322     if (line->p1.y <= line->p2.y)
323     {
324         top = &line->p1;
325         bot = &line->p2;
326     }
327     else
328     {
329         top = &line->p2;
330         bot = &line->p1;
331     }
332     pixman_edge_init (e, n, y,
333                     top->x + x_off_fixed,
334                     top->y + y_off_fixed,
335                     bot->x + x_off_fixed,
336                     bot->y + y_off_fixed);
337 }
338
339 pixman_bool_t
340 pixman_multiply_overflows_int (unsigned int a,
341                                unsigned int b)
342 {
343     return a >= INT32_MAX / b;
344 }
345
346 pixman_bool_t
347 pixman_addition_overflows_int (unsigned int a,
348                                unsigned int b)
349 {
350     return a > INT32_MAX - b;
351 }
352
353 void *
354 pixman_malloc_ab(unsigned int a,
355                  unsigned int b)
356 {
357     if (a >= INT32_MAX / b)
358         return NULL;
359
360     return malloc (a * b);
361 }
362
363 void *
364 pixman_malloc_abc (unsigned int a,
365                    unsigned int b,
366                    unsigned int c)
367 {
368     if (a >= INT32_MAX / b)
369         return NULL;
370     else if (a * b >= INT32_MAX / c)
371         return NULL;
372     else
373         return malloc (a * b * c);
374 }
375
376
377 /**
378  * pixman_version:
379  *
380  * Returns the version of the pixman library encoded in a single
381  * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
382  * later versions compare greater than earlier versions.
383  *
384  * A run-time comparison to check that pixman's version is greater than
385  * or equal to version X.Y.Z could be performed as follows:
386  *
387  * <informalexample><programlisting>
388  * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
389  * </programlisting></informalexample>
390  *
391  * See also pixman_version_string() as well as the compile-time
392  * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
393  *
394  * Return value: the encoded version.
395  **/
396 PIXMAN_EXPORT int
397 pixman_version (void)
398 {
399     return PIXMAN_VERSION;
400 }
401
402 /**
403  * pixman_version_string:
404  *
405  * Returns the version of the pixman library as a human-readable string
406  * of the form "X.Y.Z".
407  *
408  * See also pixman_version() as well as the compile-time equivalents
409  * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
410  *
411  * Return value: a string containing the version.
412  **/
413 PIXMAN_EXPORT const char*
414 pixman_version_string (void)
415 {
416     return PIXMAN_VERSION_STRING;
417 }
418
419 /**
420  * pixman_format_supported_destination:
421  * @format: A pixman_format_code_t format
422  * 
423  * Return value: whether the provided format code is a supported
424  * format for a pixman surface used as a destination in
425  * rendering.
426  *
427  * Currently, all pixman_format_code_t values are supported
428  * except for the YUV formats.
429  **/
430 PIXMAN_EXPORT pixman_bool_t
431 pixman_format_supported_destination (pixman_format_code_t format)
432 {
433     switch (format) {
434     /* 32 bpp formats */
435     case PIXMAN_a2b10g10r10:
436     case PIXMAN_x2b10g10r10:
437     case PIXMAN_a8r8g8b8:
438     case PIXMAN_x8r8g8b8:
439     case PIXMAN_a8b8g8r8:
440     case PIXMAN_x8b8g8r8:
441     case PIXMAN_b8g8r8a8:
442     case PIXMAN_b8g8r8x8:
443     case PIXMAN_r8g8b8:
444     case PIXMAN_b8g8r8:
445     case PIXMAN_r5g6b5:
446     case PIXMAN_b5g6r5:
447     /* 16 bpp formats */
448     case PIXMAN_a1r5g5b5:
449     case PIXMAN_x1r5g5b5:
450     case PIXMAN_a1b5g5r5:
451     case PIXMAN_x1b5g5r5:
452     case PIXMAN_a4r4g4b4:
453     case PIXMAN_x4r4g4b4:
454     case PIXMAN_a4b4g4r4:
455     case PIXMAN_x4b4g4r4:
456     /* 8bpp formats */
457     case PIXMAN_a8:
458     case PIXMAN_r3g3b2:
459     case PIXMAN_b2g3r3:
460     case PIXMAN_a2r2g2b2:
461     case PIXMAN_a2b2g2r2:
462     case PIXMAN_c8:
463     case PIXMAN_g8:
464     case PIXMAN_x4a4:
465     /* Collides with PIXMAN_c8
466     case PIXMAN_x4c4:
467     */
468     /* Collides with PIXMAN_g8
469     case PIXMAN_x4g4:
470     */
471     /* 4bpp formats */
472     case PIXMAN_a4:
473     case PIXMAN_r1g2b1:
474     case PIXMAN_b1g2r1:
475     case PIXMAN_a1r1g1b1:
476     case PIXMAN_a1b1g1r1:
477     case PIXMAN_c4:
478     case PIXMAN_g4:
479     /* 1bpp formats */
480     case PIXMAN_a1:
481     case PIXMAN_g1:
482         return TRUE;
483         
484     /* YUV formats */
485     case PIXMAN_yuy2:
486     case PIXMAN_yv12:
487     default:
488         return FALSE;
489     }
490 }
491
492 /**
493  * pixman_format_supported_source:
494  * @format: A pixman_format_code_t format
495  * 
496  * Return value: whether the provided format code is a supported
497  * format for a pixman surface used as a source in
498  * rendering.
499  *
500  * Currently, all pixman_format_code_t values are supported.
501  **/
502 PIXMAN_EXPORT pixman_bool_t
503 pixman_format_supported_source (pixman_format_code_t format)
504 {
505     switch (format) {
506     /* 32 bpp formats */
507     case PIXMAN_a2b10g10r10:
508     case PIXMAN_x2b10g10r10:
509     case PIXMAN_a8r8g8b8:
510     case PIXMAN_x8r8g8b8:
511     case PIXMAN_a8b8g8r8:
512     case PIXMAN_x8b8g8r8:
513     case PIXMAN_b8g8r8a8:
514     case PIXMAN_b8g8r8x8:
515     case PIXMAN_r8g8b8:
516     case PIXMAN_b8g8r8:
517     case PIXMAN_r5g6b5:
518     case PIXMAN_b5g6r5:
519     /* 16 bpp formats */
520     case PIXMAN_a1r5g5b5:
521     case PIXMAN_x1r5g5b5:
522     case PIXMAN_a1b5g5r5:
523     case PIXMAN_x1b5g5r5:
524     case PIXMAN_a4r4g4b4:
525     case PIXMAN_x4r4g4b4:
526     case PIXMAN_a4b4g4r4:
527     case PIXMAN_x4b4g4r4:
528     /* 8bpp formats */
529     case PIXMAN_a8:
530     case PIXMAN_r3g3b2:
531     case PIXMAN_b2g3r3:
532     case PIXMAN_a2r2g2b2:
533     case PIXMAN_a2b2g2r2:
534     case PIXMAN_c8:
535     case PIXMAN_g8:
536     case PIXMAN_x4a4:
537     /* Collides with PIXMAN_c8
538     case PIXMAN_x4c4:
539     */
540     /* Collides with PIXMAN_g8
541     case PIXMAN_x4g4:
542     */
543     /* 4bpp formats */
544     case PIXMAN_a4:
545     case PIXMAN_r1g2b1:
546     case PIXMAN_b1g2r1:
547     case PIXMAN_a1r1g1b1:
548     case PIXMAN_a1b1g1r1:
549     case PIXMAN_c4:
550     case PIXMAN_g4:
551     /* 1bpp formats */
552     case PIXMAN_a1:
553     case PIXMAN_g1:
554     /* YUV formats */
555     case PIXMAN_yuy2:
556     case PIXMAN_yv12:
557         return TRUE;
558
559     default:
560         return FALSE;
561     }
562 }
563
564 void
565 _pixman_walk_composite_region (pixman_implementation_t *imp,
566                               pixman_op_t op,
567                               pixman_image_t * pSrc,
568                               pixman_image_t * pMask,
569                               pixman_image_t * pDst,
570                               int16_t xSrc,
571                               int16_t ySrc,
572                               int16_t xMask,
573                               int16_t yMask,
574                               int16_t xDst,
575                               int16_t yDst,
576                               uint16_t width,
577                               uint16_t height,
578                               pixman_bool_t srcRepeat,
579                               pixman_bool_t maskRepeat,
580                               pixman_composite_func_t compositeRect)
581 {
582     int             n;
583     const pixman_box32_t *pbox;
584     int             w, h, w_this, h_this;
585     int             x_msk, y_msk, x_src, y_src, x_dst, y_dst;
586     pixman_region32_t reg;
587     pixman_region32_t *region;
588
589     pixman_region32_init (&reg);
590     if (!pixman_compute_composite_region32 (&reg, pSrc, pMask, pDst,
591                                             xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
592     {
593         return;
594     }
595
596     region = &reg;
597
598     pbox = pixman_region32_rectangles (region, &n);
599     while (n--)
600     {
601         h = pbox->y2 - pbox->y1;
602         y_src = pbox->y1 - yDst + ySrc;
603         y_msk = pbox->y1 - yDst + yMask;
604         y_dst = pbox->y1;
605         while (h)
606         {
607             h_this = h;
608             w = pbox->x2 - pbox->x1;
609             x_src = pbox->x1 - xDst + xSrc;
610             x_msk = pbox->x1 - xDst + xMask;
611             x_dst = pbox->x1;
612             if (maskRepeat)
613             {
614                 y_msk = MOD (y_msk, pMask->bits.height);
615                 if (h_this > pMask->bits.height - y_msk)
616                     h_this = pMask->bits.height - y_msk;
617             }
618             if (srcRepeat)
619             {
620                 y_src = MOD (y_src, pSrc->bits.height);
621                 if (h_this > pSrc->bits.height - y_src)
622                     h_this = pSrc->bits.height - y_src;
623             }
624             while (w)
625             {
626                 w_this = w;
627                 if (maskRepeat)
628                 {
629                     x_msk = MOD (x_msk, pMask->bits.width);
630                     if (w_this > pMask->bits.width - x_msk)
631                         w_this = pMask->bits.width - x_msk;
632                 }
633                 if (srcRepeat)
634                 {
635                     x_src = MOD (x_src, pSrc->bits.width);
636                     if (w_this > pSrc->bits.width - x_src)
637                         w_this = pSrc->bits.width - x_src;
638                 }
639                 (*compositeRect) (imp,
640                                   op, pSrc, pMask, pDst,
641                                   x_src, y_src, x_msk, y_msk, x_dst, y_dst,
642                                   w_this, h_this);
643                 w -= w_this;
644                 x_src += w_this;
645                 x_msk += w_this;
646                 x_dst += w_this;
647             }
648             h -= h_this;
649             y_src += h_this;
650             y_msk += h_this;
651             y_dst += h_this;
652         }
653         pbox++;
654     }
655     pixman_region32_fini (&reg);
656 }
657
658 static pixman_bool_t
659 mask_is_solid (pixman_image_t *mask)
660 {
661     if (mask->type == SOLID)
662         return TRUE;
663
664     if (mask->type == BITS &&
665         mask->common.repeat == PIXMAN_REPEAT_NORMAL &&
666         mask->bits.width == 1 &&
667         mask->bits.height == 1)
668     {
669         return TRUE;
670     }
671
672     return FALSE;
673 }
674
675 static const FastPathInfo *
676 get_fast_path (const FastPathInfo *fast_paths,
677                pixman_op_t         op,
678                pixman_image_t     *pSrc,
679                pixman_image_t     *pMask,
680                pixman_image_t     *pDst,
681                pixman_bool_t       is_pixbuf)
682 {
683     const FastPathInfo *info;
684
685     for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++)
686     {
687         pixman_bool_t valid_src         = FALSE;
688         pixman_bool_t valid_mask        = FALSE;
689
690         if (info->op != op)
691             continue;
692
693         if ((info->src_format == PIXMAN_solid && pixman_image_can_get_solid (pSrc))             ||
694             (pSrc->type == BITS && info->src_format == pSrc->bits.format))
695         {
696             valid_src = TRUE;
697         }
698
699         if (!valid_src)
700             continue;
701
702         if ((info->mask_format == PIXMAN_null && !pMask)                        ||
703             (pMask && pMask->type == BITS && info->mask_format == pMask->bits.format))
704         {
705             valid_mask = TRUE;
706
707             if (info->flags & NEED_SOLID_MASK)
708             {
709                 if (!pMask || !mask_is_solid (pMask))
710                     valid_mask = FALSE;
711             }
712
713             if (info->flags & NEED_COMPONENT_ALPHA)
714             {
715                 if (!pMask || !pMask->common.component_alpha)
716                     valid_mask = FALSE;
717             }
718         }
719
720         if (!valid_mask)
721             continue;
722         
723         if (info->dest_format != pDst->bits.format)
724             continue;
725
726         if ((info->flags & NEED_PIXBUF) && !is_pixbuf)
727             continue;
728
729         return info;
730     }
731
732     return NULL;
733 }
734
735 pixman_bool_t
736 _pixman_run_fast_path (const FastPathInfo *paths,
737                        pixman_implementation_t *imp,
738                        pixman_op_t op,
739                        pixman_image_t *src,
740                        pixman_image_t *mask,
741                        pixman_image_t *dest,
742                        int32_t src_x,
743                        int32_t src_y,
744                        int32_t mask_x,
745                        int32_t mask_y,
746                        int32_t dest_x,
747                        int32_t dest_y,
748                        int32_t width,
749                        int32_t height)
750 {
751     pixman_composite_func_t func = NULL;
752     pixman_bool_t src_repeat = src->common.repeat == PIXMAN_REPEAT_NORMAL;
753     pixman_bool_t mask_repeat = mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL;
754     
755     if ((src->type == BITS || pixman_image_can_get_solid (src)) &&
756         (!mask || mask->type == BITS)
757         && !src->common.transform && !(mask && mask->common.transform)
758         && !(mask && mask->common.alpha_map) && !src->common.alpha_map && !dest->common.alpha_map
759         && (src->common.filter != PIXMAN_FILTER_CONVOLUTION)
760         && (src->common.repeat != PIXMAN_REPEAT_PAD)
761         && (src->common.repeat != PIXMAN_REPEAT_REFLECT)
762         && (!mask || (mask->common.filter != PIXMAN_FILTER_CONVOLUTION &&
763                       mask->common.repeat != PIXMAN_REPEAT_PAD &&
764                       mask->common.repeat != PIXMAN_REPEAT_REFLECT))
765         && !src->common.read_func && !src->common.write_func
766         && !(mask && mask->common.read_func)
767         && !(mask && mask->common.write_func)
768         && !dest->common.read_func
769         && !dest->common.write_func)
770     {
771         const FastPathInfo *info;       
772         pixman_bool_t pixbuf;
773
774         pixbuf =
775             src && src->type == BITS            &&
776             mask && mask->type == BITS          &&
777             src->bits.bits == mask->bits.bits   &&
778             src_x == mask_x                     &&
779             src_y == mask_y                     &&
780             !mask->common.component_alpha       &&
781             !mask_repeat;
782         
783         info = get_fast_path (paths, op, src, mask, dest, pixbuf);
784
785         if (info)
786         {
787             func = info->func;
788                 
789             if (info->src_format == PIXMAN_solid)
790                 src_repeat = FALSE;
791
792             if (info->mask_format == PIXMAN_solid || info->flags & NEED_SOLID_MASK)
793                 mask_repeat = FALSE;
794
795             if ((src_repeat                     &&
796                  src->bits.width == 1           &&
797                  src->bits.height == 1) ||
798                 (mask_repeat                    &&
799                  mask->bits.width == 1          &&
800                  mask->bits.height == 1))
801             {
802                 /* If src or mask are repeating 1x1 images and src_repeat or
803                  * mask_repeat are still TRUE, it means the fast path we
804                  * selected does not actually handle repeating images.
805                  *
806                  * So rather than call the "fast path" with a zillion
807                  * 1x1 requests, we just fall back to the general code (which
808                  * does do something sensible with 1x1 repeating images).
809                  */
810                 func = NULL;
811             }
812         }
813     }
814
815     if (func)
816     {
817         _pixman_walk_composite_region (imp, op,
818                                        src, mask, dest,
819                                        src_x, src_y, mask_x, mask_y,
820                                        dest_x, dest_y,
821                                        width, height,
822                                        src_repeat, mask_repeat,
823                                        func);
824         return TRUE;
825     }
826     
827     return FALSE;
828 }