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