Change prototypes for compositing functions to use 32 bit integers
[profile/ivi/pixman.git] / pixman / pixman-general.c
1 /*
2  * Copyright © 2009 Red Hat, Inc.
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 Red Hat not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  Red Hat makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23  * SOFTWARE.
24  */
25 #include <config.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <math.h>
29 #include <assert.h>
30 #include <limits.h>
31 #include "pixman-private.h"
32
33
34 static void
35 general_combine_32 (pixman_implementation_t *imp, pixman_op_t op,
36                     uint32_t *dest, const uint32_t *src, const uint32_t *mask,
37                     int width)
38 {
39     CombineFunc32 f = pixman_composeFunctions.combineU[op];
40
41     f (dest, src, mask, width);
42 }
43
44 static void
45 general_combine_32_ca (pixman_implementation_t *imp, pixman_op_t op,
46                        uint32_t *dest, const uint32_t *src, const uint32_t *mask,
47                        int width)
48 {
49     CombineFunc32 f = pixman_composeFunctions.combineC[op];
50
51     f (dest, src, mask, width);
52 }
53
54 static void
55 general_combine_64 (pixman_implementation_t *imp, pixman_op_t op,
56                     uint64_t *dest, const uint64_t *src, const uint64_t *mask,
57                     int width)
58 {
59     CombineFunc64 f = pixman_composeFunctions64.combineU[op];
60
61     f (dest, src, mask, width);
62 }
63
64 static void
65 general_combine_64_ca (pixman_implementation_t *imp, pixman_op_t op,
66                        uint64_t *dest, const uint64_t *src, const uint64_t *mask,
67                        int width)
68 {
69     CombineFunc64 f = pixman_composeFunctions64.combineC[op];
70
71     f (dest, src, mask, width);
72 }
73
74 /*
75  *
76  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
77  *             2005 Lars Knoll & Zack Rusin, Trolltech
78  *             2008 Aaron Plattner, NVIDIA Corporation
79  *
80  * Permission to use, copy, modify, distribute, and sell this software and its
81  * documentation for any purpose is hereby granted without fee, provided that
82  * the above copyright notice appear in all copies and that both that
83  * copyright notice and this permission notice appear in supporting
84  * documentation, and that the name of Keith Packard not be used in
85  * advertising or publicity pertaining to distribution of the software without
86  * specific, written prior permission.  Keith Packard makes no
87  * representations about the suitability of this software for any purpose.  It
88  * is provided "as is" without express or implied warranty.
89  *
90  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
91  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
92  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
93  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
94  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
95  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
96  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
97  * SOFTWARE.
98  */
99
100 #ifdef HAVE_CONFIG_H
101 #include <config.h>
102 #endif
103
104 static void
105 pixman_composite_rect_general_internal (const FbComposeData *data,
106                                         void *src_buffer, void *mask_buffer, 
107                                         void *dest_buffer, const int wide)
108 {
109     int i;
110     scanStoreProc store;
111     scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
112     uint32_t *bits;
113     int32_t stride;
114     source_pict_class_t srcClass, maskClass;
115     pixman_bool_t component_alpha;
116
117     srcClass = _pixman_image_classify (data->src,
118                                        data->xSrc, data->ySrc,
119                                        data->width, data->height);
120
121     maskClass = SOURCE_IMAGE_CLASS_UNKNOWN;
122     if (data->mask)
123     {
124         maskClass = _pixman_image_classify (data->mask,
125                                             data->xSrc, data->ySrc,
126                                             data->width, data->height);
127     }
128     
129     if (data->op == PIXMAN_OP_CLEAR)
130         fetchSrc = NULL;
131     else if (wide)
132         fetchSrc = _pixman_image_get_scanline_64;
133     else
134         fetchSrc = _pixman_image_get_scanline_32;
135
136     if (!data->mask || data->op == PIXMAN_OP_CLEAR)
137         fetchMask = NULL;
138     else if (wide)
139         fetchMask = _pixman_image_get_scanline_64;
140     else
141         fetchMask = _pixman_image_get_scanline_32;
142
143     if (data->op == PIXMAN_OP_CLEAR || data->op == PIXMAN_OP_SRC)
144         fetchDest = NULL;
145     else if (wide)
146         fetchDest = _pixman_image_get_scanline_64;
147     else
148         fetchDest = _pixman_image_get_scanline_32;
149
150     if (wide)
151         store = _pixman_image_store_scanline_64;
152     else
153         store = _pixman_image_store_scanline_32;
154
155     // Skip the store step and composite directly into the
156     // destination if the output format of the compose func matches
157     // the destination format.
158     if (!wide &&
159         !data->dest->common.alpha_map &&
160         !data->dest->common.write_func && 
161         (data->op == PIXMAN_OP_ADD || data->op == PIXMAN_OP_OVER) &&
162         (data->dest->bits.format == PIXMAN_a8r8g8b8 ||
163          data->dest->bits.format == PIXMAN_x8r8g8b8))
164     {
165         store = NULL;
166     }
167
168     if (!store)
169     {
170         bits = data->dest->bits.bits;
171         stride = data->dest->bits.rowstride;
172     }
173     else
174     {
175         bits = NULL;
176         stride = 0;
177     }
178
179     component_alpha =
180         fetchSrc                   &&
181         fetchMask                  &&
182         data->mask                 &&
183         data->mask->common.type == BITS &&
184         data->mask->common.component_alpha &&
185         PIXMAN_FORMAT_RGB (data->mask->bits.format);
186
187     {
188         CombineFunc32 compose;
189
190         if (wide)
191         {
192             if (component_alpha)
193                 compose = (CombineFunc32)pixman_composeFunctions64.combineC[data->op];
194             else
195                 compose = (CombineFunc32)pixman_composeFunctions64.combineU[data->op];
196         }
197         else
198         {
199             if (component_alpha)
200                 compose = pixman_composeFunctions.combineC[data->op];
201             else
202                 compose = pixman_composeFunctions.combineU[data->op];
203         }
204
205         if (!compose)
206             return;
207
208         if (!fetchMask)
209             mask_buffer = NULL;
210         
211         for (i = 0; i < data->height; ++i)
212         {
213             /* fill first half of scanline with source */
214             if (fetchSrc)
215             {
216                 if (fetchMask)
217                 {
218                     /* fetch mask before source so that fetching of
219                        source can be optimized */
220                     fetchMask (data->mask, data->xMask, data->yMask + i,
221                                data->width, mask_buffer, 0, 0);
222
223                     if (maskClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
224                         fetchMask = NULL;
225                 }
226
227                 if (srcClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
228                 {
229                     fetchSrc (data->src, data->xSrc, data->ySrc + i,
230                               data->width, src_buffer, 0, 0);
231                     fetchSrc = NULL;
232                 }
233                 else
234                 {
235                     fetchSrc (data->src, data->xSrc, data->ySrc + i,
236                               data->width, src_buffer, mask_buffer,
237                               0xffffffff);
238                 }
239             }
240             else if (fetchMask)
241             {
242                 fetchMask (data->mask, data->xMask, data->yMask + i,
243                            data->width, mask_buffer, 0, 0);
244             }
245
246             if (store)
247             {
248                 /* fill dest into second half of scanline */
249                 if (fetchDest)
250                     fetchDest (data->dest, data->xDest, data->yDest + i,
251                                data->width, dest_buffer, 0, 0);
252
253                 /* blend */
254                 compose (dest_buffer, src_buffer, mask_buffer, data->width);
255
256                 /* write back */
257                 store (&(data->dest->bits), data->xDest, data->yDest + i, data->width,
258                        dest_buffer);
259             }
260             else
261             {
262                 /* blend */
263                 compose (bits + (data->yDest + i) * stride +
264                          data->xDest,
265                          src_buffer, mask_buffer, data->width);
266             }
267         }
268     }
269 }
270
271 #define SCANLINE_BUFFER_LENGTH 8192
272
273 static void
274 general_composite_rect (const FbComposeData *data)
275 {
276     uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3];
277     const pixman_format_code_t srcFormat =
278         data->src->type == BITS ? data->src->bits.format : 0;
279     const pixman_format_code_t maskFormat =
280         data->mask && data->mask->type == BITS ? data->mask->bits.format : 0;
281     const pixman_format_code_t destFormat = data->dest->type == BITS ? data->dest->bits.format : 0;
282     const int srcWide = PIXMAN_FORMAT_16BPC(srcFormat);
283     const int maskWide = data->mask && PIXMAN_FORMAT_16BPC(maskFormat);
284     const int destWide = PIXMAN_FORMAT_16BPC(destFormat);
285     const int wide = srcWide || maskWide || destWide;
286     const int Bpp = wide ? 8 : 4;
287     uint8_t *scanline_buffer = stack_scanline_buffer;
288     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
289     
290     if (data->width * Bpp > SCANLINE_BUFFER_LENGTH)
291     {
292         scanline_buffer = pixman_malloc_abc (data->width, 3, Bpp);
293
294         if (!scanline_buffer)
295             return;
296     }
297
298     src_buffer = scanline_buffer;
299     mask_buffer = src_buffer + data->width * Bpp;
300     dest_buffer = mask_buffer + data->width * Bpp;
301
302     pixman_composite_rect_general_internal (data, src_buffer,
303                                             mask_buffer, dest_buffer,
304                                             wide);
305
306     if (scanline_buffer != stack_scanline_buffer)
307         free (scanline_buffer);
308 }
309
310 #include <stdio.h>
311 #include <stdlib.h>
312 #include <string.h>
313 #include "pixman-private.h"
314 #include "pixman-mmx.h"
315 #include "pixman-vmx.h"
316 #include "pixman-sse2.h"
317 #include "pixman-arm-simd.h"
318 #include "pixman-combine32.h"
319
320 static void
321 fbCompositeSrcScaleNearest (pixman_implementation_t *imp,
322                             pixman_op_t     op,
323                             pixman_image_t *pSrc,
324                             pixman_image_t *pMask,
325                             pixman_image_t *pDst,
326                             int32_t         xSrc,
327                             int32_t         ySrc,
328                             int32_t         xMask,
329                             int32_t         yMask,
330                             int32_t         xDst,
331                             int32_t         yDst,
332                             int32_t        width,
333                             int32_t        height)
334 {
335     uint32_t       *dst;
336     uint32_t       *src;
337     int             dstStride, srcStride;
338     int             i, j;
339     pixman_vector_t v;
340
341     fbComposeGetStart (pDst, xDst, yDst, uint32_t, dstStride, dst, 1);
342     /* pass in 0 instead of xSrc and ySrc because xSrc and ySrc need to be
343      * transformed from destination space to source space */
344     fbComposeGetStart (pSrc, 0, 0, uint32_t, srcStride, src, 1);
345
346     /* reference point is the center of the pixel */
347     v.vector[0] = pixman_int_to_fixed(xSrc) + pixman_fixed_1 / 2;
348     v.vector[1] = pixman_int_to_fixed(ySrc) + pixman_fixed_1 / 2;
349     v.vector[2] = pixman_fixed_1;
350
351     if (!pixman_transform_point_3d (pSrc->common.transform, &v))
352         return;
353
354     /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */
355     v.vector[0] -= pixman_fixed_e;
356     v.vector[1] -= pixman_fixed_e;
357
358     for (j = 0; j < height; j++) {
359         pixman_fixed_t vx = v.vector[0];
360         pixman_fixed_t vy = v.vector[1];
361         for (i = 0; i < width; ++i) {
362             pixman_bool_t inside_bounds;
363             uint32_t result;
364             int x, y;
365             x = vx >> 16;
366             y = vy >> 16;
367
368             /* apply the repeat function */
369             switch (pSrc->common.repeat) {
370                 case PIXMAN_REPEAT_NORMAL:
371                     x = MOD (x, pSrc->bits.width);
372                     y = MOD (y, pSrc->bits.height);
373                     inside_bounds = TRUE;
374                     break;
375
376                 case PIXMAN_REPEAT_PAD:
377                     x = CLIP (x, 0, pSrc->bits.width-1);
378                     y = CLIP (y, 0, pSrc->bits.height-1);
379                     inside_bounds = TRUE;
380                     break;
381
382                 case PIXMAN_REPEAT_REFLECT:
383                     x = MOD (x, pSrc->bits.width * 2);
384                     if (x >= pSrc->bits.width)
385                             x = pSrc->bits.width * 2 - x - 1;
386                     y = MOD (y, pSrc->bits.height * 2);
387                     if (y >= pSrc->bits.height)
388                             y = pSrc->bits.height * 2 - y - 1;
389                     inside_bounds = TRUE;
390                     break;
391
392                 case PIXMAN_REPEAT_NONE:
393                 default:
394                     inside_bounds = (x >= 0 && x < pSrc->bits.width && y >= 0 && y < pSrc->bits.height);
395                     break;
396             }
397
398             if (inside_bounds) {
399                 //XXX: we should move this multiplication out of the loop
400                 result = READ(pSrc, src + y * srcStride + x);
401             } else {
402                 result = 0;
403             }
404             WRITE(pDst, dst + i, result);
405
406             /* adjust the x location by a unit vector in the x direction:
407              * this is equivalent to transforming x+1 of the destination point to source space */
408             vx += pSrc->common.transform->matrix[0][0];
409         }
410         /* adjust the y location by a unit vector in the y direction
411          * this is equivalent to transforming y+1 of the destination point to source space */
412         v.vector[1] += pSrc->common.transform->matrix[1][1];
413         dst += dstStride;
414     }
415 }
416
417 static void
418 pixman_walk_composite_region (pixman_implementation_t *imp,
419                               pixman_op_t op,
420                               pixman_image_t * pSrc,
421                               pixman_image_t * pMask,
422                               pixman_image_t * pDst,
423                               int16_t xSrc,
424                               int16_t ySrc,
425                               int16_t xMask,
426                               int16_t yMask,
427                               int16_t xDst,
428                               int16_t yDst,
429                               uint16_t width,
430                               uint16_t height,
431                               pixman_bool_t srcRepeat,
432                               pixman_bool_t maskRepeat,
433                               pixman_composite_func_t compositeRect)
434 {
435     int             n;
436     const pixman_box32_t *pbox;
437     int             w, h, w_this, h_this;
438     int             x_msk, y_msk, x_src, y_src, x_dst, y_dst;
439     pixman_region32_t reg;
440     pixman_region32_t *region;
441
442     pixman_region32_init (&reg);
443     if (!pixman_compute_composite_region32 (&reg, pSrc, pMask, pDst,
444                                             xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
445     {
446         return;
447     }
448
449     region = &reg;
450
451     pbox = pixman_region32_rectangles (region, &n);
452     while (n--)
453     {
454         h = pbox->y2 - pbox->y1;
455         y_src = pbox->y1 - yDst + ySrc;
456         y_msk = pbox->y1 - yDst + yMask;
457         y_dst = pbox->y1;
458         while (h)
459         {
460             h_this = h;
461             w = pbox->x2 - pbox->x1;
462             x_src = pbox->x1 - xDst + xSrc;
463             x_msk = pbox->x1 - xDst + xMask;
464             x_dst = pbox->x1;
465             if (maskRepeat)
466             {
467                 y_msk = MOD (y_msk, pMask->bits.height);
468                 if (h_this > pMask->bits.height - y_msk)
469                     h_this = pMask->bits.height - y_msk;
470             }
471             if (srcRepeat)
472             {
473                 y_src = MOD (y_src, pSrc->bits.height);
474                 if (h_this > pSrc->bits.height - y_src)
475                     h_this = pSrc->bits.height - y_src;
476             }
477             while (w)
478             {
479                 w_this = w;
480                 if (maskRepeat)
481                 {
482                     x_msk = MOD (x_msk, pMask->bits.width);
483                     if (w_this > pMask->bits.width - x_msk)
484                         w_this = pMask->bits.width - x_msk;
485                 }
486                 if (srcRepeat)
487                 {
488                     x_src = MOD (x_src, pSrc->bits.width);
489                     if (w_this > pSrc->bits.width - x_src)
490                         w_this = pSrc->bits.width - x_src;
491                 }
492                 (*compositeRect) (imp,
493                                   op, pSrc, pMask, pDst,
494                                   x_src, y_src, x_msk, y_msk, x_dst, y_dst,
495                                   w_this, h_this);
496                 w -= w_this;
497                 x_src += w_this;
498                 x_msk += w_this;
499                 x_dst += w_this;
500             }
501             h -= h_this;
502             y_src += h_this;
503             y_msk += h_this;
504             y_dst += h_this;
505         }
506         pbox++;
507     }
508     pixman_region32_fini (&reg);
509 }
510
511 static void
512 pixman_image_composite_rect  (pixman_implementation_t *imp,
513                               pixman_op_t                   op,
514                               pixman_image_t               *src,
515                               pixman_image_t               *mask,
516                               pixman_image_t               *dest,
517                               int32_t                       src_x,
518                               int32_t                       src_y,
519                               int32_t                       mask_x,
520                               int32_t                       mask_y,
521                               int32_t                       dest_x,
522                               int32_t                       dest_y,
523                               int32_t                      width,
524                               int32_t                      height)
525 {
526     FbComposeData compose_data;
527
528     return_if_fail (src != NULL);
529     return_if_fail (dest != NULL);
530
531     compose_data.op = op;
532     compose_data.src = src;
533     compose_data.mask = mask;
534     compose_data.dest = dest;
535     compose_data.xSrc = src_x;
536     compose_data.ySrc = src_y;
537     compose_data.xMask = mask_x;
538     compose_data.yMask = mask_y;
539     compose_data.xDest = dest_x;
540     compose_data.yDest = dest_y;
541     compose_data.width = width;
542     compose_data.height = height;
543
544     general_composite_rect (&compose_data);
545 }
546
547 static pixman_bool_t
548 mask_is_solid (pixman_image_t *mask)
549 {
550     if (mask->type == SOLID)
551         return TRUE;
552
553     if (mask->type == BITS &&
554         mask->common.repeat == PIXMAN_REPEAT_NORMAL &&
555         mask->bits.width == 1 &&
556         mask->bits.height == 1)
557     {
558         return TRUE;
559     }
560
561     return FALSE;
562 }
563
564 static const FastPathInfo *
565 get_fast_path (const FastPathInfo *fast_paths,
566                pixman_op_t         op,
567                pixman_image_t     *pSrc,
568                pixman_image_t     *pMask,
569                pixman_image_t     *pDst,
570                pixman_bool_t       is_pixbuf)
571 {
572     const FastPathInfo *info;
573
574     for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++)
575     {
576         pixman_bool_t valid_src         = FALSE;
577         pixman_bool_t valid_mask        = FALSE;
578
579         if (info->op != op)
580             continue;
581
582         if ((info->src_format == PIXMAN_solid && pixman_image_can_get_solid (pSrc))             ||
583             (pSrc->type == BITS && info->src_format == pSrc->bits.format))
584         {
585             valid_src = TRUE;
586         }
587
588         if (!valid_src)
589             continue;
590
591         if ((info->mask_format == PIXMAN_null && !pMask)                        ||
592             (pMask && pMask->type == BITS && info->mask_format == pMask->bits.format))
593         {
594             valid_mask = TRUE;
595
596             if (info->flags & NEED_SOLID_MASK)
597             {
598                 if (!pMask || !mask_is_solid (pMask))
599                     valid_mask = FALSE;
600             }
601
602             if (info->flags & NEED_COMPONENT_ALPHA)
603             {
604                 if (!pMask || !pMask->common.component_alpha)
605                     valid_mask = FALSE;
606             }
607         }
608
609         if (!valid_mask)
610             continue;
611         
612         if (info->dest_format != pDst->bits.format)
613             continue;
614
615         if ((info->flags & NEED_PIXBUF) && !is_pixbuf)
616             continue;
617
618         return info;
619     }
620
621     return NULL;
622 }
623
624 #if defined(USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
625
626 /*
627  * Work around GCC bug causing crashes in Mozilla with SSE2
628  * 
629  * When using SSE2 intrinsics, gcc assumes that the stack is 16 byte
630  * aligned. Unfortunately some code, such as Mozilla and Mono contain
631  * code that aligns the stack to 4 bytes.
632  *
633  * The __force_align_arg_pointer__ makes gcc generate a prologue that
634  * realigns the stack pointer to 16 bytes.
635  *
636  * On x86-64 this is not necessary because the standard ABI already
637  * calls for a 16 byte aligned stack.
638  *
639  * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
640  */
641
642 __attribute__((__force_align_arg_pointer__))
643 #endif
644 static void
645 general_composite (pixman_implementation_t *    imp,
646                    pixman_op_t                  op,
647                    pixman_image_t *             src,
648                    pixman_image_t *             mask,
649                    pixman_image_t *             dest,
650                    int32_t                      src_x,
651                    int32_t                      src_y,
652                    int32_t                      mask_x,
653                    int32_t                      mask_y,
654                    int32_t                      dest_x,
655                    int32_t                      dest_y,
656                    int32_t                      width,
657                    int32_t                      height)
658 {
659     pixman_bool_t srcRepeat = src->type == BITS && src->common.repeat == PIXMAN_REPEAT_NORMAL;
660     pixman_bool_t maskRepeat = FALSE;
661     pixman_bool_t srcTransform = src->common.transform != NULL;
662     pixman_bool_t maskTransform = FALSE;
663     pixman_bool_t srcAlphaMap = src->common.alpha_map != NULL;
664     pixman_bool_t maskAlphaMap = FALSE;
665     pixman_bool_t dstAlphaMap = dest->common.alpha_map != NULL;
666     pixman_composite_func_t func = NULL;
667
668 #ifdef USE_MMX
669     fbComposeSetupMMX();
670 #endif
671
672 #ifdef USE_VMX
673     fbComposeSetupVMX();
674 #endif
675
676 #ifdef USE_SSE2
677     fbComposeSetupSSE2();
678 #endif
679
680     if (srcRepeat && srcTransform &&
681         src->bits.width == 1 &&
682         src->bits.height == 1)
683     {
684         srcTransform = FALSE;
685     }
686
687     if (mask && mask->type == BITS)
688     {
689         maskRepeat = mask->common.repeat == PIXMAN_REPEAT_NORMAL;
690
691         maskTransform = mask->common.transform != 0;
692         if (mask->common.filter == PIXMAN_FILTER_CONVOLUTION)
693             maskTransform = TRUE;
694
695         maskAlphaMap = mask->common.alpha_map != 0;
696
697         if (maskRepeat && maskTransform &&
698             mask->bits.width == 1 &&
699             mask->bits.height == 1)
700         {
701             maskTransform = FALSE;
702         }
703     }
704
705     if (src->type == BITS
706         && srcTransform
707         && !mask
708         && op == PIXMAN_OP_SRC
709         && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
710         && (src->common.filter == PIXMAN_FILTER_NEAREST)
711         && PIXMAN_FORMAT_BPP(dest->bits.format) == 32
712         && src->bits.format == dest->bits.format
713         && src->common.src_clip == &(src->common.full_region)
714         && !src->common.read_func && !src->common.write_func
715         && !dest->common.read_func && !dest->common.write_func)
716     {
717         /* ensure that the transform matrix only has a scale */
718         if (src->common.transform->matrix[0][1] == 0 &&
719             src->common.transform->matrix[1][0] == 0 &&
720             src->common.transform->matrix[2][0] == 0 &&
721             src->common.transform->matrix[2][1] == 0 &&
722             src->common.transform->matrix[2][2] == pixman_fixed_1) {
723             func = fbCompositeSrcScaleNearest;
724             /* Like the general path, fbCompositeSrcScaleNearest handles all the repeat types itself */
725             srcRepeat = FALSE;
726         }
727     } else if ((src->type == BITS || pixman_image_can_get_solid (src)) && (!mask || mask->type == BITS)
728         && !srcTransform && !maskTransform
729         && !maskAlphaMap && !srcAlphaMap && !dstAlphaMap
730         && (src->common.filter != PIXMAN_FILTER_CONVOLUTION)
731         && (src->common.repeat != PIXMAN_REPEAT_PAD)
732         && (src->common.repeat != PIXMAN_REPEAT_REFLECT)
733         && (!mask || (mask->common.filter != PIXMAN_FILTER_CONVOLUTION &&
734                 mask->common.repeat != PIXMAN_REPEAT_PAD && mask->common.repeat != PIXMAN_REPEAT_REFLECT))
735         && !src->common.read_func && !src->common.write_func
736         && !(mask && mask->common.read_func) && !(mask && mask->common.write_func)
737         && !dest->common.read_func && !dest->common.write_func)
738     {
739         const FastPathInfo *info;
740         pixman_bool_t pixbuf;
741
742         pixbuf =
743             src && src->type == BITS            &&
744             mask && mask->type == BITS  &&
745             src->bits.bits == mask->bits.bits &&
746             src_x == mask_x                     &&
747             src_y == mask_y                     &&
748             !mask->common.component_alpha       &&
749             !maskRepeat;
750         info = NULL;
751         
752 #ifdef USE_SSE2
753         if (pixman_have_sse2 ())
754             info = get_fast_path (sse2_fast_paths, op, src, mask, dest, pixbuf);
755 #endif
756
757 #ifdef USE_MMX
758         if (!info && pixman_have_mmx())
759             info = get_fast_path (mmx_fast_paths, op, src, mask, dest, pixbuf);
760 #endif
761
762 #ifdef USE_VMX
763
764         if (!info && pixman_have_vmx())
765             info = get_fast_path (vmx_fast_paths, op, src, mask, dest, pixbuf);
766 #endif
767
768 #ifdef USE_ARM_NEON
769         if (!info && pixman_have_arm_neon())
770             info = get_fast_path (arm_neon_fast_paths, op, src, mask, dest, pixbuf);
771 #endif
772
773 #ifdef USE_ARM_SIMD
774         if (!info && pixman_have_arm_simd())
775             info = get_fast_path (arm_simd_fast_paths, op, src, mask, dest, pixbuf);
776 #endif
777
778         if (!info)
779             info = get_fast_path (c_fast_paths, op, src, mask, dest, pixbuf);
780
781         if (info)
782         {
783             func = info->func;
784
785             if (info->src_format == PIXMAN_solid)
786                 srcRepeat = FALSE;
787
788             if (info->mask_format == PIXMAN_solid       ||
789                 info->flags & NEED_SOLID_MASK)
790             {
791                 maskRepeat = FALSE;
792             }
793         }
794     }
795     
796     if ((srcRepeat                      &&
797          src->bits.width == 1           &&
798          src->bits.height == 1) ||
799         (maskRepeat                     &&
800          mask->bits.width == 1          &&
801          mask->bits.height == 1))
802     {
803         /* If src or mask are repeating 1x1 images and srcRepeat or
804          * maskRepeat are still TRUE, it means the fast path we
805          * selected does not actually handle repeating images.
806          *
807          * So rather than call the "fast path" with a zillion
808          * 1x1 requests, we just use the general code (which does
809          * do something sensible with 1x1 repeating images).
810          */
811         func = NULL;
812     }
813
814     if (!func)
815     {
816         func = pixman_image_composite_rect;
817
818         /* CompositeGeneral optimizes 1x1 repeating images itself */
819         if (src->type == BITS &&
820             src->bits.width == 1 && src->bits.height == 1)
821         {
822             srcRepeat = FALSE;
823         }
824
825         if (mask && mask->type == BITS &&
826             mask->bits.width == 1 && mask->bits.height == 1)
827         {
828             maskRepeat = FALSE;
829         }
830
831         /* if we are transforming, repeats are handled in fbFetchTransformed */
832         if (srcTransform)
833             srcRepeat = FALSE;
834
835         if (maskTransform)
836             maskRepeat = FALSE;
837     }
838
839     pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
840                                   mask_x, mask_y, dest_x, dest_y, width, height,
841                                   srcRepeat, maskRepeat, func);
842 }
843
844 pixman_implementation_t *
845 _pixman_implementation_create_general (pixman_implementation_t *toplevel)
846 {
847     pixman_implementation_t *imp = _pixman_implementation_create (toplevel, NULL);
848     int i;
849
850     imp->composite = general_composite;
851     
852     for (i = 0; i < PIXMAN_OP_LAST; ++i)
853     {
854         imp->combine_32[i] = general_combine_32;
855         imp->combine_32_ca[i] = general_combine_32_ca;
856         imp->combine_64[i] = general_combine_64;
857         imp->combine_64_ca[i] = general_combine_64_ca;
858     }
859
860     return imp;
861 }