Fixup the arm-simd and arm-neon implementations.
[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  * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
6  *             2005 Lars Knoll & Zack Rusin, Trolltech
7  *             2008 Aaron Plattner, NVIDIA Corporation
8  *
9  * Permission to use, copy, modify, distribute, and sell this software and its
10  * documentation for any purpose is hereby granted without fee, provided that
11  * the above copyright notice appear in all copies and that both that
12  * copyright notice and this permission notice appear in supporting
13  * documentation, and that the name of Red Hat not be used in advertising or
14  * publicity pertaining to distribution of the software without specific,
15  * written prior permission.  Red Hat makes no representations about the
16  * suitability of this software for any purpose.  It is provided "as is"
17  * without express or implied warranty.
18  *
19  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
20  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
24  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
25  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26  * SOFTWARE.
27  */
28 #include <config.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <math.h>
32 #include <assert.h>
33 #include <limits.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include "pixman-private.h"
38 #include "pixman-vmx.h"
39 #include "pixman-combine32.h"
40 #include "pixman-private.h"
41
42 #define SCANLINE_BUFFER_LENGTH 8192
43
44 static void
45 general_composite_rect  (pixman_implementation_t *imp,
46                          pixman_op_t              op,
47                          pixman_image_t          *src,
48                          pixman_image_t          *mask,
49                          pixman_image_t          *dest,
50                          int32_t                  src_x,
51                          int32_t                  src_y,
52                          int32_t                  mask_x,
53                          int32_t                  mask_y,
54                          int32_t                  dest_x,
55                          int32_t                  dest_y,
56                          int32_t                  width,
57                          int32_t                  height)
58 {
59     return_if_fail (src != NULL);
60     return_if_fail (dest != NULL);
61     
62     uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3];
63     const pixman_format_code_t srcFormat = src->type == BITS ? src->bits.format : 0;
64     const pixman_format_code_t maskFormat = mask && mask->type == BITS ? mask->bits.format : 0;
65     const pixman_format_code_t destFormat = dest->type == BITS ? dest->bits.format : 0;
66     const int srcWide = PIXMAN_FORMAT_16BPC(srcFormat);
67     const int maskWide = mask && PIXMAN_FORMAT_16BPC(maskFormat);
68     const int destWide = PIXMAN_FORMAT_16BPC(destFormat);
69     const int wide = srcWide || maskWide || destWide;
70     const int Bpp = wide ? 8 : 4;
71     uint8_t *scanline_buffer = stack_scanline_buffer;
72     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
73     scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
74     pixman_combine_32_func_t compose;
75     scanStoreProc store;
76     source_pict_class_t srcClass, maskClass;
77     pixman_bool_t component_alpha;
78     uint32_t *bits;
79     int32_t stride;
80     int i;
81     
82     if (width * Bpp > SCANLINE_BUFFER_LENGTH)
83     {
84         scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
85         
86         if (!scanline_buffer)
87             return;
88     }
89     
90     src_buffer = scanline_buffer;
91     mask_buffer = src_buffer + width * Bpp;
92     dest_buffer = mask_buffer + width * Bpp;
93     
94     srcClass = _pixman_image_classify (src,
95                                        src_x, src_y,
96                                        width, height);
97     
98     maskClass = SOURCE_IMAGE_CLASS_UNKNOWN;
99     if (mask)
100     {
101         maskClass = _pixman_image_classify (mask,
102                                             src_x, src_y,
103                                             width, height);
104     }
105     
106     if (op == PIXMAN_OP_CLEAR)
107         fetchSrc = NULL;
108     else if (wide)
109         fetchSrc = _pixman_image_get_scanline_64;
110     else
111         fetchSrc = _pixman_image_get_scanline_32;
112     
113     if (!mask || op == PIXMAN_OP_CLEAR)
114         fetchMask = NULL;
115     else if (wide)
116         fetchMask = _pixman_image_get_scanline_64;
117     else
118         fetchMask = _pixman_image_get_scanline_32;
119     
120     if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
121         fetchDest = NULL;
122     else if (wide)
123         fetchDest = _pixman_image_get_scanline_64;
124     else
125         fetchDest = _pixman_image_get_scanline_32;
126
127     if (wide)
128         store = _pixman_image_store_scanline_64;
129     else
130         store = _pixman_image_store_scanline_32;
131
132     /* Skip the store step and composite directly into the
133      * destination if the output format of the compose func matches
134      * the destination format.
135      */
136     if (!wide &&
137         !dest->common.alpha_map &&
138         !dest->common.write_func && 
139         (op == PIXMAN_OP_ADD || op == PIXMAN_OP_OVER) &&
140         (dest->bits.format == PIXMAN_a8r8g8b8 ||
141          dest->bits.format == PIXMAN_x8r8g8b8))
142     {
143         store = NULL;
144     }
145     
146     if (!store)
147     {
148         bits = dest->bits.bits;
149         stride = dest->bits.rowstride;
150     }
151     else
152     {
153         bits = NULL;
154         stride = 0;
155     }
156     
157     component_alpha =
158         fetchSrc                        &&
159         fetchMask                       &&
160         mask                            &&
161         mask->common.type == BITS       &&
162         mask->common.component_alpha    &&
163         PIXMAN_FORMAT_RGB (mask->bits.format);
164     
165     if (wide)
166     {
167         if (component_alpha)
168             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
169         else
170             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
171     }
172     else
173     {
174         if (component_alpha)
175             compose = _pixman_implementation_combine_32_ca;
176         else
177             compose = _pixman_implementation_combine_32;
178     }
179     
180     if (!compose)
181         return;
182     
183     if (!fetchMask)
184         mask_buffer = NULL;
185     
186     for (i = 0; i < height; ++i)
187     {
188         /* fill first half of scanline with source */
189         if (fetchSrc)
190         {
191             if (fetchMask)
192             {
193                 /* fetch mask before source so that fetching of
194                    source can be optimized */
195                 fetchMask (mask, mask_x, mask_y + i,
196                            width, (void *)mask_buffer, 0, 0);
197                 
198                 if (maskClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
199                     fetchMask = NULL;
200             }
201             
202             if (srcClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
203             {
204                 fetchSrc (src, src_x, src_y + i,
205                           width, (void *)src_buffer, 0, 0);
206                 fetchSrc = NULL;
207             }
208             else
209             {
210                 fetchSrc (src, src_x, src_y + i,
211                           width, (void *)src_buffer, (void *)mask_buffer,
212                           0xffffffff);
213             }
214         }
215         else if (fetchMask)
216         {
217             fetchMask (mask, mask_x, mask_y + i,
218                        width, (void *)mask_buffer, 0, 0);
219         }
220         
221         if (store)
222         {
223             /* fill dest into second half of scanline */
224             if (fetchDest)
225                 fetchDest (dest, dest_x, dest_y + i,
226                            width, (void *)dest_buffer, 0, 0);
227             
228             /* blend */
229             compose (imp->toplevel, op, (void *)dest_buffer, (void *)src_buffer, (void *)mask_buffer, width);
230             
231             /* write back */
232             store (&(dest->bits), dest_x, dest_y + i, width,
233                    (void *)dest_buffer);
234         }
235         else
236         {
237             /* blend */
238             compose (imp->toplevel, op, bits + (dest_y + i) * stride +
239                      dest_x,
240                      (void *)src_buffer, (void *)mask_buffer, width);
241         }
242     }
243     
244     if (scanline_buffer != stack_scanline_buffer)
245         free (scanline_buffer);
246 }
247
248 static void
249 general_composite (pixman_implementation_t *    imp,
250                    pixman_op_t                  op,
251                    pixman_image_t *             src,
252                    pixman_image_t *             mask,
253                    pixman_image_t *             dest,
254                    int32_t                      src_x,
255                    int32_t                      src_y,
256                    int32_t                      mask_x,
257                    int32_t                      mask_y,
258                    int32_t                      dest_x,
259                    int32_t                      dest_y,
260                    int32_t                      width,
261                    int32_t                      height)
262 {
263     pixman_bool_t srcRepeat = src->type == BITS && src->common.repeat == PIXMAN_REPEAT_NORMAL;
264     pixman_bool_t maskRepeat = FALSE;
265     pixman_bool_t srcTransform = src->common.transform != NULL;
266     pixman_bool_t maskTransform = FALSE;
267     
268 #ifdef USE_VMX
269     fbComposeSetupVMX();
270 #endif
271     
272     if (srcRepeat && srcTransform &&
273         src->bits.width == 1 &&
274         src->bits.height == 1)
275     {
276         srcTransform = FALSE;
277     }
278     
279     if (mask && mask->type == BITS)
280     {
281         maskRepeat = mask->common.repeat == PIXMAN_REPEAT_NORMAL;
282         
283         maskTransform = mask->common.transform != 0;
284         if (mask->common.filter == PIXMAN_FILTER_CONVOLUTION)
285             maskTransform = TRUE;
286         
287         if (maskRepeat && maskTransform &&
288             mask->bits.width == 1 &&
289             mask->bits.height == 1)
290         {
291             maskTransform = FALSE;
292         }
293     }
294     
295 #ifdef USE_VMX
296     if (_pixman_run_fast_path (vmx_fast_paths, imp,
297                                op, src, mask, dest,
298                                src_x, src_y,
299                                mask_x, mask_y,
300                                dest_x, dest_y,
301                                width, height))
302         return;
303 #endif
304     
305     /* CompositeGeneral optimizes 1x1 repeating images itself */
306     if (src->type == BITS &&
307         src->bits.width == 1 && src->bits.height == 1)
308     {
309         srcRepeat = FALSE;
310     }
311     
312     if (mask && mask->type == BITS &&
313         mask->bits.width == 1 && mask->bits.height == 1)
314     {
315         maskRepeat = FALSE;
316     }
317     
318     /* if we are transforming, repeats are handled in fbFetchTransformed */
319     if (srcTransform)
320         srcRepeat = FALSE;
321     
322     if (maskTransform)
323         maskRepeat = FALSE;
324     
325     _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
326                                    mask_x, mask_y, dest_x, dest_y, width, height,
327                                    srcRepeat, maskRepeat, general_composite_rect);
328 }
329
330 static pixman_bool_t
331 general_blt (pixman_implementation_t *imp,
332              uint32_t *src_bits,
333              uint32_t *dst_bits,
334              int src_stride,
335              int dst_stride,
336              int src_bpp,
337              int dst_bpp,
338              int src_x, int src_y,
339              int dst_x, int dst_y,
340              int width, int height)
341 {
342     /* We can't blit unless we have sse2 or mmx */
343     
344     return FALSE;
345 }
346
347 static pixman_bool_t
348 general_fill (pixman_implementation_t *imp,
349               uint32_t *bits,
350               int stride,
351               int bpp,
352               int x,
353               int y,
354               int width,
355               int height,
356               uint32_t xor)
357 {
358     return FALSE;
359 }
360
361 pixman_implementation_t *
362 _pixman_implementation_create_general (pixman_implementation_t *toplevel)
363 {
364     pixman_implementation_t *imp = _pixman_implementation_create (toplevel, NULL);
365
366     _pixman_setup_combiner_functions_32 (imp);
367     _pixman_setup_combiner_functions_64 (imp);
368     
369     imp->composite = general_composite;
370     imp->blt = general_blt;
371     imp->fill = general_fill;
372     
373     return imp;
374 }