Virtualize iterator initialization
[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 #define SCANLINE_BUFFER_LENGTH 8192
111
112 static void
113 general_composite_rect  (pixman_implementation_t *imp,
114                          pixman_op_t              op,
115                          pixman_image_t *         src,
116                          pixman_image_t *         mask,
117                          pixman_image_t *         dest,
118                          int32_t                  src_x,
119                          int32_t                  src_y,
120                          int32_t                  mask_x,
121                          int32_t                  mask_y,
122                          int32_t                  dest_x,
123                          int32_t                  dest_y,
124                          int32_t                  width,
125                          int32_t                  height)
126 {
127     uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8];
128     uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer;
129     uint8_t *src_buffer, *mask_buffer, *dest_buffer;
130     pixman_iter_t src_iter, mask_iter, dest_iter;
131     pixman_combine_32_func_t compose;
132     pixman_bool_t component_alpha;
133     iter_flags_t narrow;
134     int Bpp;
135     int i;
136
137     if ((src->common.flags & FAST_PATH_NARROW_FORMAT)           &&
138         (!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) &&
139         (dest->common.flags & FAST_PATH_NARROW_FORMAT))
140     {
141         narrow = ITER_NARROW;
142         Bpp = 4;
143     }
144     else
145     {
146         narrow = 0;
147         Bpp = 8;
148     }
149
150     if (width * Bpp > SCANLINE_BUFFER_LENGTH)
151     {
152         scanline_buffer = pixman_malloc_abc (width, 3, Bpp);
153
154         if (!scanline_buffer)
155             return;
156     }
157
158     src_buffer = scanline_buffer;
159     mask_buffer = src_buffer + width * Bpp;
160     dest_buffer = mask_buffer + width * Bpp;
161
162     _pixman_implementation_src_iter_init (imp->toplevel, &src_iter, src,
163                                           src_x, src_y, width, height,
164                                           src_buffer, narrow);
165
166     _pixman_implementation_src_iter_init (imp->toplevel, &mask_iter, mask,
167                                           mask_x, mask_y, width, height,
168                                           mask_buffer, narrow);
169
170     _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest,
171                                            dest_x, dest_y, width, height,
172                                            dest_buffer, narrow);
173
174     component_alpha =
175         mask                            &&
176         mask->common.type == BITS       &&
177         mask->common.component_alpha    &&
178         PIXMAN_FORMAT_RGB (mask->bits.format);
179
180     if (narrow)
181     {
182         if (component_alpha)
183             compose = _pixman_implementation_combine_32_ca;
184         else
185             compose = _pixman_implementation_combine_32;
186     }
187     else
188     {
189         if (component_alpha)
190             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
191         else
192             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
193     }
194
195     if (!compose)
196         return;
197
198     for (i = 0; i < height; ++i)
199     {
200         uint32_t *s, *m, *d;
201
202         m = mask_iter.get_scanline (&mask_iter, NULL);
203         s = src_iter.get_scanline (&src_iter, m);
204         d = dest_iter.get_scanline (&dest_iter, NULL);
205
206         compose (imp->toplevel, op, d, s, m, width);
207
208         dest_iter.write_back (&dest_iter);
209     }
210
211     if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
212         free (scanline_buffer);
213 }
214
215 static const pixman_fast_path_t general_fast_path[] =
216 {
217     { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect },
218     { PIXMAN_OP_NONE }
219 };
220
221 static pixman_bool_t
222 general_blt (pixman_implementation_t *imp,
223              uint32_t *               src_bits,
224              uint32_t *               dst_bits,
225              int                      src_stride,
226              int                      dst_stride,
227              int                      src_bpp,
228              int                      dst_bpp,
229              int                      src_x,
230              int                      src_y,
231              int                      dst_x,
232              int                      dst_y,
233              int                      width,
234              int                      height)
235 {
236     /* We can't blit unless we have sse2 or mmx */
237
238     return FALSE;
239 }
240
241 static pixman_bool_t
242 general_fill (pixman_implementation_t *imp,
243               uint32_t *               bits,
244               int                      stride,
245               int                      bpp,
246               int                      x,
247               int                      y,
248               int                      width,
249               int                      height,
250               uint32_t xor)
251 {
252     return FALSE;
253 }
254
255 pixman_implementation_t *
256 _pixman_implementation_create_general (void)
257 {
258     pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
259
260     _pixman_setup_combiner_functions_32 (imp);
261     _pixman_setup_combiner_functions_64 (imp);
262
263     imp->blt = general_blt;
264     imp->fill = general_fill;
265     imp->src_iter_init = general_src_iter_init;
266     imp->dest_iter_init = general_dest_iter_init;
267
268     return imp;
269 }
270