Fix for potential unaligned memory accesses
[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 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 #include <stdlib.h>
32 #include <string.h>
33 #include <math.h>
34 #include <limits.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include "pixman-private.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     uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
60     uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
61     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
62     fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL;
63     pixman_combine_32_func_t compose;
64     store_scanline_t store;
65     source_image_class_t src_class, mask_class;
66     pixman_bool_t component_alpha;
67     uint32_t *bits;
68     int32_t stride;
69     int narrow, Bpp;
70     int i;
71
72     narrow =
73         (src->common.flags & FAST_PATH_NARROW_FORMAT)           &&
74         (!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) &&
75         (dest->common.flags & FAST_PATH_NARROW_FORMAT);
76     Bpp = narrow ? 4 : 8;
77
78     if (width * Bpp > SCANLINE_BUFFER_LENGTH)
79     {
80         scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
81
82         if (!scanline_buffer)
83             return;
84     }
85
86     src_buffer = scanline_buffer;
87     mask_buffer = src_buffer + width * Bpp;
88     dest_buffer = mask_buffer + width * Bpp;
89
90     src_class = _pixman_image_classify (src,
91                                         src_x, src_y,
92                                         width, height);
93
94     mask_class = SOURCE_IMAGE_CLASS_UNKNOWN;
95
96     if (mask)
97     {
98         mask_class = _pixman_image_classify (mask,
99                                              src_x, src_y,
100                                              width, height);
101     }
102
103     if (op == PIXMAN_OP_CLEAR)
104         fetch_src = NULL;
105     else if (narrow)
106         fetch_src = _pixman_image_get_scanline_32;
107     else
108         fetch_src = _pixman_image_get_scanline_64;
109
110     if (!mask || op == PIXMAN_OP_CLEAR)
111         fetch_mask = NULL;
112     else if (narrow)
113         fetch_mask = _pixman_image_get_scanline_32;
114     else
115         fetch_mask = _pixman_image_get_scanline_64;
116
117     if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
118         fetch_dest = NULL;
119     else if (narrow)
120         fetch_dest = _pixman_image_get_scanline_32;
121     else
122         fetch_dest = _pixman_image_get_scanline_64;
123
124     if (narrow)
125         store = _pixman_image_store_scanline_32;
126     else
127         store = _pixman_image_store_scanline_64;
128
129     /* Skip the store step and composite directly into the
130      * destination if the output format of the compose func matches
131      * the destination format.
132      *
133      * If the destination format is a8r8g8b8 then we can always do
134      * this. If it is x8r8g8b8, then we can only do it if the
135      * operator doesn't make use of destination alpha.
136      */
137     if ((dest->bits.format == PIXMAN_a8r8g8b8)  ||
138         (dest->bits.format == PIXMAN_x8r8g8b8   &&
139          (op == PIXMAN_OP_OVER          ||
140           op == PIXMAN_OP_ADD           ||
141           op == PIXMAN_OP_SRC           ||
142           op == PIXMAN_OP_CLEAR         ||
143           op == PIXMAN_OP_IN_REVERSE    ||
144           op == PIXMAN_OP_OUT_REVERSE   ||
145           op == PIXMAN_OP_DST)))
146     {
147         if (narrow &&
148             !dest->common.alpha_map &&
149             !dest->bits.write_func)
150         {
151             store = NULL;
152         }
153     }
154
155     if (!store)
156     {
157         bits = dest->bits.bits;
158         stride = dest->bits.rowstride;
159     }
160     else
161     {
162         bits = NULL;
163         stride = 0;
164     }
165
166     component_alpha =
167         fetch_src                       &&
168         fetch_mask                      &&
169         mask                            &&
170         mask->common.type == BITS       &&
171         mask->common.component_alpha    &&
172         PIXMAN_FORMAT_RGB (mask->bits.format);
173
174     if (narrow)
175     {
176         if (component_alpha)
177             compose = _pixman_implementation_combine_32_ca;
178         else
179             compose = _pixman_implementation_combine_32;
180     }
181     else
182     {
183         if (component_alpha)
184             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
185         else
186             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
187     }
188
189     if (!compose)
190         return;
191
192     if (!fetch_mask)
193         mask_buffer = NULL;
194
195     for (i = 0; i < height; ++i)
196     {
197         /* fill first half of scanline with source */
198         if (fetch_src)
199         {
200             if (fetch_mask)
201             {
202                 /* fetch mask before source so that fetching of
203                    source can be optimized */
204                 fetch_mask (mask, mask_x, mask_y + i,
205                             width, (void *)mask_buffer, 0);
206
207                 if (mask_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
208                     fetch_mask = NULL;
209             }
210
211             if (src_class == SOURCE_IMAGE_CLASS_HORIZONTAL)
212             {
213                 fetch_src (src, src_x, src_y + i,
214                            width, (void *)src_buffer, 0);
215                 fetch_src = NULL;
216             }
217             else
218             {
219                 fetch_src (src, src_x, src_y + i,
220                            width, (void *)src_buffer, (void *)mask_buffer);
221             }
222         }
223         else if (fetch_mask)
224         {
225             fetch_mask (mask, mask_x, mask_y + i,
226                         width, (void *)mask_buffer, 0);
227         }
228
229         if (store)
230         {
231             /* fill dest into second half of scanline */
232             if (fetch_dest)
233             {
234                 fetch_dest (dest, dest_x, dest_y + i,
235                             width, (void *)dest_buffer, 0);
236             }
237
238             /* blend */
239             compose (imp->toplevel, op,
240                      (void *)dest_buffer,
241                      (void *)src_buffer,
242                      (void *)mask_buffer,
243                      width);
244
245             /* write back */
246             store (&(dest->bits), dest_x, dest_y + i, width,
247                    (void *)dest_buffer);
248         }
249         else
250         {
251             /* blend */
252             compose (imp->toplevel, op,
253                      bits + (dest_y + i) * stride + dest_x,
254                      (void *)src_buffer, (void *)mask_buffer, width);
255         }
256     }
257
258     if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
259         free (scanline_buffer);
260 }
261
262 static const pixman_fast_path_t general_fast_path[] =
263 {
264     { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect },
265     { PIXMAN_OP_NONE }
266 };
267
268 static pixman_bool_t
269 general_blt (pixman_implementation_t *imp,
270              uint32_t *               src_bits,
271              uint32_t *               dst_bits,
272              int                      src_stride,
273              int                      dst_stride,
274              int                      src_bpp,
275              int                      dst_bpp,
276              int                      src_x,
277              int                      src_y,
278              int                      dst_x,
279              int                      dst_y,
280              int                      width,
281              int                      height)
282 {
283     /* We can't blit unless we have sse2 or mmx */
284
285     return FALSE;
286 }
287
288 static pixman_bool_t
289 general_fill (pixman_implementation_t *imp,
290               uint32_t *               bits,
291               int                      stride,
292               int                      bpp,
293               int                      x,
294               int                      y,
295               int                      width,
296               int                      height,
297               uint32_t xor)
298 {
299     return FALSE;
300 }
301
302 pixman_implementation_t *
303 _pixman_implementation_create_general (void)
304 {
305     pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
306
307     _pixman_setup_combiner_functions_32 (imp);
308     _pixman_setup_combiner_functions_64 (imp);
309
310     imp->blt = general_blt;
311     imp->fill = general_fill;
312
313     return imp;
314 }
315