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