Delete pixman-sse2.h and pixman-mmx.h
[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-arm-simd.h"
40 #include "pixman-combine32.h"
41 #include "pixman-private.h"
42
43
44 static void
45 general_combine_32 (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.combineU[op];
50
51     f (dest, src, mask, width);
52 }
53
54 static void
55 general_combine_32_ca (pixman_implementation_t *imp, pixman_op_t op,
56                        uint32_t *dest, const uint32_t *src, const uint32_t *mask,
57                        int width)
58 {
59     CombineFunc32 f = pixman_composeFunctions.combineC[op];
60
61     f (dest, src, mask, width);
62 }
63
64 static void
65 general_combine_64 (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.combineU[op];
70
71     f (dest, src, mask, width);
72 }
73
74 static void
75 general_combine_64_ca (pixman_implementation_t *imp, pixman_op_t op,
76                        uint64_t *dest, const uint64_t *src, const uint64_t *mask,
77                        int width)
78 {
79     CombineFunc64 f = pixman_composeFunctions64.combineC[op];
80
81     f (dest, src, mask, width);
82 }
83
84 static void
85 pixman_composite_rect_general_internal (pixman_implementation_t *imp,
86                                         const FbComposeData *data,
87                                         void *src_buffer, void *mask_buffer, 
88                                         void *dest_buffer, const int wide)
89 {
90     int i;
91     scanStoreProc store;
92     scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
93     uint32_t *bits;
94     int32_t stride;
95     source_pict_class_t srcClass, maskClass;
96     pixman_bool_t component_alpha;
97
98     srcClass = _pixman_image_classify (data->src,
99                                        data->xSrc, data->ySrc,
100                                        data->width, data->height);
101
102     maskClass = SOURCE_IMAGE_CLASS_UNKNOWN;
103     if (data->mask)
104     {
105         maskClass = _pixman_image_classify (data->mask,
106                                             data->xSrc, data->ySrc,
107                                             data->width, data->height);
108     }
109     
110     if (data->op == PIXMAN_OP_CLEAR)
111         fetchSrc = NULL;
112     else if (wide)
113         fetchSrc = _pixman_image_get_scanline_64;
114     else
115         fetchSrc = _pixman_image_get_scanline_32;
116
117     if (!data->mask || data->op == PIXMAN_OP_CLEAR)
118         fetchMask = NULL;
119     else if (wide)
120         fetchMask = _pixman_image_get_scanline_64;
121     else
122         fetchMask = _pixman_image_get_scanline_32;
123
124     if (data->op == PIXMAN_OP_CLEAR || data->op == PIXMAN_OP_SRC)
125         fetchDest = NULL;
126     else if (wide)
127         fetchDest = _pixman_image_get_scanline_64;
128     else
129         fetchDest = _pixman_image_get_scanline_32;
130
131     if (wide)
132         store = _pixman_image_store_scanline_64;
133     else
134         store = _pixman_image_store_scanline_32;
135
136     // Skip the store step and composite directly into the
137     // destination if the output format of the compose func matches
138     // the destination format.
139     if (!wide &&
140         !data->dest->common.alpha_map &&
141         !data->dest->common.write_func && 
142         (data->op == PIXMAN_OP_ADD || data->op == PIXMAN_OP_OVER) &&
143         (data->dest->bits.format == PIXMAN_a8r8g8b8 ||
144          data->dest->bits.format == PIXMAN_x8r8g8b8))
145     {
146         store = NULL;
147     }
148
149     if (!store)
150     {
151         bits = data->dest->bits.bits;
152         stride = data->dest->bits.rowstride;
153     }
154     else
155     {
156         bits = NULL;
157         stride = 0;
158     }
159
160     component_alpha =
161         fetchSrc                   &&
162         fetchMask                  &&
163         data->mask                 &&
164         data->mask->common.type == BITS &&
165         data->mask->common.component_alpha &&
166         PIXMAN_FORMAT_RGB (data->mask->bits.format);
167
168     {
169         pixman_combine_32_func_t compose;
170
171         if (wide)
172         {
173             if (component_alpha)
174                 compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
175             else
176                 compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
177         }
178         else
179         {
180             if (component_alpha)
181                 compose = _pixman_implementation_combine_32_ca;
182             else
183                 compose = _pixman_implementation_combine_32;
184         }
185
186         if (!compose)
187             return;
188
189         if (!fetchMask)
190             mask_buffer = NULL;
191         
192         for (i = 0; i < data->height; ++i)
193         {
194             /* fill first half of scanline with source */
195             if (fetchSrc)
196             {
197                 if (fetchMask)
198                 {
199                     /* fetch mask before source so that fetching of
200                        source can be optimized */
201                     fetchMask (data->mask, data->xMask, data->yMask + i,
202                                data->width, mask_buffer, 0, 0);
203
204                     if (maskClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
205                         fetchMask = NULL;
206                 }
207
208                 if (srcClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
209                 {
210                     fetchSrc (data->src, data->xSrc, data->ySrc + i,
211                               data->width, src_buffer, 0, 0);
212                     fetchSrc = NULL;
213                 }
214                 else
215                 {
216                     fetchSrc (data->src, data->xSrc, data->ySrc + i,
217                               data->width, src_buffer, mask_buffer,
218                               0xffffffff);
219                 }
220             }
221             else if (fetchMask)
222             {
223                 fetchMask (data->mask, data->xMask, data->yMask + i,
224                            data->width, mask_buffer, 0, 0);
225             }
226
227             if (store)
228             {
229                 /* fill dest into second half of scanline */
230                 if (fetchDest)
231                     fetchDest (data->dest, data->xDest, data->yDest + i,
232                                data->width, dest_buffer, 0, 0);
233
234                 /* blend */
235                 compose (imp, data->op, dest_buffer, src_buffer, mask_buffer, data->width);
236
237                 /* write back */
238                 store (&(data->dest->bits), data->xDest, data->yDest + i, data->width,
239                        dest_buffer);
240             }
241             else
242             {
243                 /* blend */
244                 compose (imp, data->op, bits + (data->yDest + i) * stride +
245                          data->xDest,
246                          src_buffer, mask_buffer, data->width);
247             }
248         }
249     }
250 }
251
252 #define SCANLINE_BUFFER_LENGTH 8192
253
254 static void
255 general_composite_rect (pixman_implementation_t *imp,
256                         const FbComposeData *data)
257 {
258     uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3];
259     const pixman_format_code_t srcFormat =
260         data->src->type == BITS ? data->src->bits.format : 0;
261     const pixman_format_code_t maskFormat =
262         data->mask && data->mask->type == BITS ? data->mask->bits.format : 0;
263     const pixman_format_code_t destFormat = data->dest->type == BITS ? data->dest->bits.format : 0;
264     const int srcWide = PIXMAN_FORMAT_16BPC(srcFormat);
265     const int maskWide = data->mask && PIXMAN_FORMAT_16BPC(maskFormat);
266     const int destWide = PIXMAN_FORMAT_16BPC(destFormat);
267     const int wide = srcWide || maskWide || destWide;
268     const int Bpp = wide ? 8 : 4;
269     uint8_t *scanline_buffer = stack_scanline_buffer;
270     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
271     
272     if (data->width * Bpp > SCANLINE_BUFFER_LENGTH)
273     {
274         scanline_buffer = pixman_malloc_abc (data->width, 3, Bpp);
275
276         if (!scanline_buffer)
277             return;
278     }
279
280     src_buffer = scanline_buffer;
281     mask_buffer = src_buffer + data->width * Bpp;
282     dest_buffer = mask_buffer + data->width * Bpp;
283
284     pixman_composite_rect_general_internal (imp, data, src_buffer,
285                                             mask_buffer, dest_buffer,
286                                             wide);
287
288     if (scanline_buffer != stack_scanline_buffer)
289         free (scanline_buffer);
290 }
291
292 static void
293 pixman_image_composite_rect  (pixman_implementation_t *imp,
294                               pixman_op_t                   op,
295                               pixman_image_t               *src,
296                               pixman_image_t               *mask,
297                               pixman_image_t               *dest,
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     FbComposeData compose_data;
308
309     return_if_fail (src != NULL);
310     return_if_fail (dest != NULL);
311
312     compose_data.op = op;
313     compose_data.src = src;
314     compose_data.mask = mask;
315     compose_data.dest = dest;
316     compose_data.xSrc = src_x;
317     compose_data.ySrc = src_y;
318     compose_data.xMask = mask_x;
319     compose_data.yMask = mask_y;
320     compose_data.xDest = dest_x;
321     compose_data.yDest = dest_y;
322     compose_data.width = width;
323     compose_data.height = height;
324
325     general_composite_rect (imp, &compose_data);
326 }
327
328 static void
329 general_composite (pixman_implementation_t *    imp,
330                    pixman_op_t                  op,
331                    pixman_image_t *             src,
332                    pixman_image_t *             mask,
333                    pixman_image_t *             dest,
334                    int32_t                      src_x,
335                    int32_t                      src_y,
336                    int32_t                      mask_x,
337                    int32_t                      mask_y,
338                    int32_t                      dest_x,
339                    int32_t                      dest_y,
340                    int32_t                      width,
341                    int32_t                      height)
342 {
343     pixman_bool_t srcRepeat = src->type == BITS && src->common.repeat == PIXMAN_REPEAT_NORMAL;
344     pixman_bool_t maskRepeat = FALSE;
345     pixman_bool_t srcTransform = src->common.transform != NULL;
346     pixman_bool_t maskTransform = FALSE;
347
348 #ifdef USE_VMX
349     fbComposeSetupVMX();
350 #endif
351
352     if (srcRepeat && srcTransform &&
353         src->bits.width == 1 &&
354         src->bits.height == 1)
355     {
356         srcTransform = FALSE;
357     }
358
359     if (mask && mask->type == BITS)
360     {
361         maskRepeat = mask->common.repeat == PIXMAN_REPEAT_NORMAL;
362
363         maskTransform = mask->common.transform != 0;
364         if (mask->common.filter == PIXMAN_FILTER_CONVOLUTION)
365             maskTransform = TRUE;
366
367         if (maskRepeat && maskTransform &&
368             mask->bits.width == 1 &&
369             mask->bits.height == 1)
370         {
371             maskTransform = FALSE;
372         }
373     }
374     
375 #ifdef USE_VMX
376     if (_pixman_run_fast_path (vmx_fast_paths, imp,
377                                op, src, mask, dest,
378                                src_x, src_y,
379                                mask_x, mask_y,
380                                dest_x, dest_y,
381                                width, height))
382         return;
383 #endif
384
385 #ifdef USE_ARM_NEON
386     if (pixman_have_arm_neon() && _pixman_run_fast_path (arm_neon_fast_paths, imp,
387                                                          op, src, mask, dest,
388                                                          src_x, src_y,
389                                                          mask_x, mask_y,
390                                                          dest_x, dest_y,
391                                                          width, height))
392         return;
393 #endif
394
395 #ifdef USE_ARM_SIMD
396     if (pixman_have_arm_simd() && _pixman_run_fast_path (arm_simd_fast_paths, imp,
397                                                          op, src, mask, dest,
398                                                          src_x, src_y,
399                                                          mask_x, mask_y,
400                                                          dest_x, dest_y,
401                                                          width, height))
402         return;
403 #endif
404
405     /* CompositeGeneral optimizes 1x1 repeating images itself */
406     if (src->type == BITS &&
407         src->bits.width == 1 && src->bits.height == 1)
408     {
409         srcRepeat = FALSE;
410     }
411     
412     if (mask && mask->type == BITS &&
413         mask->bits.width == 1 && mask->bits.height == 1)
414     {
415         maskRepeat = FALSE;
416     }
417     
418     /* if we are transforming, repeats are handled in fbFetchTransformed */
419     if (srcTransform)
420         srcRepeat = FALSE;
421     
422     if (maskTransform)
423         maskRepeat = FALSE;
424
425     _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
426                                    mask_x, mask_y, dest_x, dest_y, width, height,
427                                    srcRepeat, maskRepeat, pixman_image_composite_rect);
428 }
429
430 static pixman_bool_t
431 general_blt (pixman_implementation_t *imp,
432              uint32_t *src_bits,
433              uint32_t *dst_bits,
434              int src_stride,
435              int dst_stride,
436              int src_bpp,
437              int dst_bpp,
438              int src_x, int src_y,
439              int dst_x, int dst_y,
440              int width, int height)
441 {
442     /* We can't blit unless we have sse2 or mmx */
443     
444     return FALSE;
445 }
446
447 static pixman_bool_t
448 general_fill (pixman_implementation_t *imp,
449               uint32_t *bits,
450               int stride,
451               int bpp,
452               int x,
453               int y,
454               int width,
455               int height,
456               uint32_t xor)
457 {
458     return FALSE;
459 }
460
461 pixman_implementation_t *
462 _pixman_implementation_create_general (pixman_implementation_t *toplevel)
463 {
464     pixman_implementation_t *imp = _pixman_implementation_create (toplevel, NULL);
465     int i;
466
467     for (i = 0; i < PIXMAN_OP_LAST; ++i)
468     {
469         imp->combine_32[i] = general_combine_32;
470         imp->combine_32_ca[i] = general_combine_32_ca;
471         imp->combine_64[i] = general_combine_64;
472         imp->combine_64_ca[i] = general_combine_64_ca;
473     }
474     imp->composite = general_composite;
475     imp->blt = general_blt;
476     imp->fill = general_fill;
477     
478     return imp;
479 }