Add direct-write optimization back
[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, dest_flags;
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     if (op == PIXMAN_OP_CLEAR           ||
171         op == PIXMAN_OP_SRC             ||
172         op == PIXMAN_OP_DST             ||
173         op == PIXMAN_OP_OVER            ||
174         op == PIXMAN_OP_IN_REVERSE      ||
175         op == PIXMAN_OP_OUT_REVERSE     ||
176         op == PIXMAN_OP_ADD)
177     {
178         dest_flags = narrow | ITER_LOCALIZED_ALPHA;
179     }
180     else
181     {
182         dest_flags = narrow;
183     }
184
185     _pixman_implementation_dest_iter_init (imp->toplevel, &dest_iter, dest,
186                                            dest_x, dest_y, width, height,
187                                            dest_buffer, dest_flags);
188
189     component_alpha =
190         mask                            &&
191         mask->common.type == BITS       &&
192         mask->common.component_alpha    &&
193         PIXMAN_FORMAT_RGB (mask->bits.format);
194
195     if (narrow)
196     {
197         if (component_alpha)
198             compose = _pixman_implementation_combine_32_ca;
199         else
200             compose = _pixman_implementation_combine_32;
201     }
202     else
203     {
204         if (component_alpha)
205             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
206         else
207             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
208     }
209
210     if (!compose)
211         return;
212
213     for (i = 0; i < height; ++i)
214     {
215         uint32_t *s, *m, *d;
216
217         m = mask_iter.get_scanline (&mask_iter, NULL);
218         s = src_iter.get_scanline (&src_iter, m);
219         d = dest_iter.get_scanline (&dest_iter, NULL);
220
221         compose (imp->toplevel, op, d, s, m, width);
222
223         dest_iter.write_back (&dest_iter);
224     }
225
226     if (scanline_buffer != (uint8_t *) stack_scanline_buffer)
227         free (scanline_buffer);
228 }
229
230 static const pixman_fast_path_t general_fast_path[] =
231 {
232     { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect },
233     { PIXMAN_OP_NONE }
234 };
235
236 static pixman_bool_t
237 general_blt (pixman_implementation_t *imp,
238              uint32_t *               src_bits,
239              uint32_t *               dst_bits,
240              int                      src_stride,
241              int                      dst_stride,
242              int                      src_bpp,
243              int                      dst_bpp,
244              int                      src_x,
245              int                      src_y,
246              int                      dst_x,
247              int                      dst_y,
248              int                      width,
249              int                      height)
250 {
251     /* We can't blit unless we have sse2 or mmx */
252
253     return FALSE;
254 }
255
256 static pixman_bool_t
257 general_fill (pixman_implementation_t *imp,
258               uint32_t *               bits,
259               int                      stride,
260               int                      bpp,
261               int                      x,
262               int                      y,
263               int                      width,
264               int                      height,
265               uint32_t xor)
266 {
267     return FALSE;
268 }
269
270 pixman_implementation_t *
271 _pixman_implementation_create_general (void)
272 {
273     pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path);
274
275     _pixman_setup_combiner_functions_32 (imp);
276     _pixman_setup_combiner_functions_64 (imp);
277
278     imp->blt = general_blt;
279     imp->fill = general_fill;
280     imp->src_iter_init = general_src_iter_init;
281     imp->dest_iter_init = general_dest_iter_init;
282
283     return imp;
284 }
285