Skip fetching pixels when possible
[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 static void
43 general_src_iter_init (pixman_implementation_t *imp,
44                        pixman_iter_t *iter,
45                        pixman_image_t *image,
46                        int x, int y, int width, int height,
47                        uint8_t *buffer, iter_flags_t flags)
48 {
49     iter->image = image;
50     iter->x = x;
51     iter->y = y;
52     iter->width = width;
53     iter->buffer = (uint32_t *)buffer;
54
55     if (image->type == SOLID)
56     {
57         _pixman_solid_fill_iter_init (
58             image, iter, x, y, width, height, buffer, flags);
59     }
60     else if (image->type == LINEAR)
61     {
62         _pixman_linear_gradient_iter_init (
63             image, iter, x, y, width, height, buffer, flags);
64     }
65     else if (image->type == RADIAL)
66     {
67         _pixman_radial_gradient_iter_init (
68             image, iter, x, y, width, height, buffer, flags);
69     }
70     else if (image->type == CONICAL)
71     {
72         _pixman_conical_gradient_iter_init (
73             image, iter, x, y, width, height, buffer, flags);
74     }
75     else if (image->type == BITS)
76     {
77         _pixman_bits_image_src_iter_init (
78             image, iter, x, y, width, height, buffer, flags);
79     }
80     else
81     {
82         _pixman_log_error (FUNC, "Pixman bug: unknown image type\n");
83     }
84 }
85
86 static void
87 general_dest_iter_init (pixman_implementation_t *imp,
88                         pixman_iter_t *iter,
89                         pixman_image_t *image,
90                         int x, int y, int width, int height,
91                         uint8_t *buffer, iter_flags_t flags)
92 {
93     iter->image = image;
94     iter->x = x;
95     iter->y = y;
96     iter->width = width;
97     iter->buffer = (uint32_t *)buffer;
98
99     if (image->type == BITS)
100     {
101         _pixman_bits_image_dest_iter_init (
102             image, iter, x, y, width, height, buffer, flags);
103     }
104     else
105     {
106         _pixman_log_error (FUNC, "Trying to write to a non-writable image");
107     }
108 }
109
110 typedef struct op_info_t op_info_t;
111 struct op_info_t
112 {
113     uint8_t src, dst;
114 };
115
116 #define ITER_IGNORE_BOTH                                                \
117     (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA)
118
119 static const op_info_t op_flags[PIXMAN_N_OPERATORS] =
120 {
121     /* Src                   Dst                   */
122     { ITER_IGNORE_BOTH,      ITER_IGNORE_BOTH      }, /* CLEAR */
123     { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_BOTH      }, /* SRC */
124     { ITER_IGNORE_BOTH,      ITER_LOCALIZED_ALPHA  }, /* DST */
125     { 0,                     ITER_LOCALIZED_ALPHA  }, /* OVER */
126     { ITER_LOCALIZED_ALPHA,  0                     }, /* OVER_REVERSE */
127     { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_RGB       }, /* IN */
128     { ITER_IGNORE_RGB,       ITER_LOCALIZED_ALPHA  }, /* IN_REVERSE */
129     { ITER_LOCALIZED_ALPHA,  ITER_IGNORE_RGB       }, /* OUT */
130     { ITER_IGNORE_RGB,       ITER_LOCALIZED_ALPHA  }, /* OUT_REVERSE */
131     { 0,                     0                     }, /* ATOP */
132     { 0,                     0                     }, /* ATOP_REVERSE */
133     { 0,                     0                     }, /* XOR */
134     { ITER_LOCALIZED_ALPHA,  ITER_LOCALIZED_ALPHA  }, /* ADD */
135     { 0,                     0                     }, /* SATURATE */
136 };
137
138 #define SCANLINE_BUFFER_LENGTH 8192
139
140 static void
141 general_composite_rect  (pixman_implementation_t *imp,
142                          pixman_op_t              op,
143                          pixman_image_t *         src,
144                          pixman_image_t *         mask,
145                          pixman_image_t *         dest,
146                          int32_t                  src_x,
147                          int32_t                  src_y,
148                          int32_t                  mask_x,
149                          int32_t                  mask_y,
150                          int32_t                  dest_x,
151                          int32_t                  dest_y,
152                          int32_t                  width,
153                          int32_t                  height)
154 {
155     uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
156     uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
157     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
158     pixman_iter_t src_iter, mask_iter, dest_iter;
159     pixman_combine_32_func_t compose;
160     pixman_bool_t component_alpha;
161     iter_flags_t narrow, src_flags;
162     int Bpp;
163     int i;
164
165     if ((src->common.flags & FAST_PATH_NARROW_FORMAT)           &&
166         (!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) &&
167         (dest->common.flags & FAST_PATH_NARROW_FORMAT))
168     {
169         narrow = ITER_NARROW;
170         Bpp = 4;
171     }
172     else
173     {
174         narrow = 0;
175         Bpp = 8;
176     }
177
178     if (width * Bpp > SCANLINE_BUFFER_LENGTH)
179     {
180         scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
181
182         if (!scanline_buffer)
183             return;
184     }
185
186     src_buffer = scanline_buffer;
187     mask_buffer = src_buffer + width * Bpp;
188     dest_buffer = mask_buffer + width * Bpp;
189
190     /* src iter */
191     src_flags = narrow | op_flags[op].src;
192
193     _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src,
194                                           src_x, src_y, width, height,
195                                           src_buffer, src_flags);
196
197     /* mask iter */
198     if ((src_flags & (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB)) ==
199         (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB))
200     {
201         /* If it doesn't matter what the source is, then it doesn't matter
202          * what the mask is
203          */
204         mask = NULL;
205     }
206
207     component_alpha =
208         mask                            &&
209         mask->common.type == BITS       &&
210         mask->common.component_alpha    &&
211         PIXMAN_FORMAT_RGB (mask->bits.format);
212
213     _pixman_implementation_src_iter_init (
214         imp->toplevel, &mask_iter, mask, mask_x, mask_y, width, height,
215         mask_buffer, narrow | (component_alpha? 0 : ITER_IGNORE_RGB));
216
217     /* dest iter */
218     _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest,
219                                            dest_x, dest_y, width, height,
220                                            dest_buffer,
221                                            narrow | op_flags[op].dst);
222
223     if (narrow)
224     {
225         if (component_alpha)
226             compose = _pixman_implementation_combine_32_ca;
227         else
228             compose = _pixman_implementation_combine_32;
229     }
230     else
231     {
232         if (component_alpha)
233             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
234         else
235             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
236     }
237
238     if (!compose)
239         return;
240
241     for (i = 0; i < height; ++i)
242     {
243         uint32_t *s, *m, *d;
244
245         m = mask_iter.get_scanline (&mask_iter, NULL);
246         s = src_iter.get_scanline (&src_iter, m);
247         d = dest_iter.get_scanline (&dest_iter, NULL);
248
249         compose (imp->toplevel, op, d, s, m, width);
250
251         dest_iter.write_back (&dest_iter);
252     }
253
254     if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
255         free (scanline_buffer);
256 }
257
258 static const pixman_fast_path_t general_fast_path[] =
259 {
260     { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect },
261     { PIXMAN_OP_NONE }
262 };
263
264 static pixman_bool_t
265 general_blt (pixman_implementation_t *imp,
266              uint32_t *               src_bits,
267              uint32_t *               dst_bits,
268              int                      src_stride,
269              int                      dst_stride,
270              int                      src_bpp,
271              int                      dst_bpp,
272              int                      src_x,
273              int                      src_y,
274              int                      dst_x,
275              int                      dst_y,
276              int                      width,
277              int                      height)
278 {
279     /* We can't blit unless we have sse2 or mmx */
280
281     return FALSE;
282 }
283
284 static pixman_bool_t
285 general_fill (pixman_implementation_t *imp,
286               uint32_t *               bits,
287               int                      stride,
288               int                      bpp,
289               int                      x,
290               int                      y,
291               int                      width,
292               int                      height,
293               uint32_t xor)
294 {
295     return FALSE;
296 }
297
298 pixman_implementation_t *
299 _pixman_implementation_create_general (void)
300 {
301     pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
302
303     _pixman_setup_combiner_functions_32 (imp);
304     _pixman_setup_combiner_functions_64 (imp);
305
306     imp->blt = general_blt;
307     imp->fill = general_fill;
308     imp->src_iter_init = general_src_iter_init;
309     imp->dest_iter_init = general_dest_iter_init;
310
311     return imp;
312 }
313