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