Simplify clipping rule
[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     return_if_fail (src != NULL);
58     return_if_fail (dest != NULL);
59     
60     uint8_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH * 3];
61     const pixman_format_code_t srcFormat = src->type == BITS ? src->bits.format : 0;
62     const pixman_format_code_t maskFormat = mask && mask->type == BITS ? mask->bits.format : 0;
63     const pixman_format_code_t destFormat = dest->type == BITS ? dest->bits.format : 0;
64     const int srcWide = PIXMAN_FORMAT_16BPC(srcFormat);
65     const int maskWide = mask && PIXMAN_FORMAT_16BPC(maskFormat);
66     const int destWide = PIXMAN_FORMAT_16BPC(destFormat);
67     const int wide = srcWide || maskWide || destWide;
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     scanFetchProc fetchSrc = NULL, fetchMask = NULL, fetchDest = NULL;
72     pixman_combine_32_func_t compose;
73     scanStoreProc store;
74     source_pict_class_t srcClass, maskClass;
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     srcClass = _pixman_image_classify (src,
93                                        src_x, src_y,
94                                        width, height);
95     
96     maskClass = SOURCE_IMAGE_CLASS_UNKNOWN;
97     if (mask)
98     {
99         maskClass = _pixman_image_classify (mask,
100                                             src_x, src_y,
101                                             width, height);
102     }
103     
104     if (op == PIXMAN_OP_CLEAR)
105         fetchSrc = NULL;
106     else if (wide)
107         fetchSrc = _pixman_image_get_scanline_64;
108     else
109         fetchSrc = _pixman_image_get_scanline_32;
110     
111     if (!mask || op == PIXMAN_OP_CLEAR)
112         fetchMask = NULL;
113     else if (wide)
114         fetchMask = _pixman_image_get_scanline_64;
115     else
116         fetchMask = _pixman_image_get_scanline_32;
117     
118     if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC)
119         fetchDest = NULL;
120     else if (wide)
121         fetchDest = _pixman_image_get_scanline_64;
122     else
123         fetchDest = _pixman_image_get_scanline_32;
124
125     if (wide)
126         store = _pixman_image_store_scanline_64;
127     else
128         store = _pixman_image_store_scanline_32;
129
130     /* Skip the store step and composite directly into the
131      * destination if the output format of the compose func matches
132      * the destination format.
133      */
134     if (!wide &&
135         !dest->common.alpha_map &&
136         !dest->common.write_func && 
137         (op == PIXMAN_OP_ADD || op == PIXMAN_OP_OVER) &&
138         (dest->bits.format == PIXMAN_a8r8g8b8 ||
139          dest->bits.format == PIXMAN_x8r8g8b8))
140     {
141         store = NULL;
142     }
143     
144     if (!store)
145     {
146         bits = dest->bits.bits;
147         stride = dest->bits.rowstride;
148     }
149     else
150     {
151         bits = NULL;
152         stride = 0;
153     }
154     
155     component_alpha =
156         fetchSrc                        &&
157         fetchMask                       &&
158         mask                            &&
159         mask->common.type == BITS       &&
160         mask->common.component_alpha    &&
161         PIXMAN_FORMAT_RGB (mask->bits.format);
162     
163     if (wide)
164     {
165         if (component_alpha)
166             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca;
167         else
168             compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64;
169     }
170     else
171     {
172         if (component_alpha)
173             compose = _pixman_implementation_combine_32_ca;
174         else
175             compose = _pixman_implementation_combine_32;
176     }
177     
178     if (!compose)
179         return;
180     
181     if (!fetchMask)
182         mask_buffer = NULL;
183     
184     for (i = 0; i < height; ++i)
185     {
186         /* fill first half of scanline with source */
187         if (fetchSrc)
188         {
189             if (fetchMask)
190             {
191                 /* fetch mask before source so that fetching of
192                    source can be optimized */
193                 fetchMask (mask, mask_x, mask_y + i,
194                            width, (void *)mask_buffer, 0, 0);
195                 
196                 if (maskClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
197                     fetchMask = NULL;
198             }
199             
200             if (srcClass == SOURCE_IMAGE_CLASS_HORIZONTAL)
201             {
202                 fetchSrc (src, src_x, src_y + i,
203                           width, (void *)src_buffer, 0, 0);
204                 fetchSrc = NULL;
205             }
206             else
207             {
208                 fetchSrc (src, src_x, src_y + i,
209                           width, (void *)src_buffer, (void *)mask_buffer,
210                           0xffffffff);
211             }
212         }
213         else if (fetchMask)
214         {
215             fetchMask (mask, mask_x, mask_y + i,
216                        width, (void *)mask_buffer, 0, 0);
217         }
218         
219         if (store)
220         {
221             /* fill dest into second half of scanline */
222             if (fetchDest)
223                 fetchDest (dest, dest_x, dest_y + i,
224                            width, (void *)dest_buffer, 0, 0);
225             
226             /* blend */
227             compose (imp->toplevel, op, (void *)dest_buffer, (void *)src_buffer, (void *)mask_buffer, width);
228             
229             /* write back */
230             store (&(dest->bits), dest_x, dest_y + i, width,
231                    (void *)dest_buffer);
232         }
233         else
234         {
235             /* blend */
236             compose (imp->toplevel, op, bits + (dest_y + i) * stride +
237                      dest_x,
238                      (void *)src_buffer, (void *)mask_buffer, width);
239         }
240     }
241     
242     if (scanline_buffer != stack_scanline_buffer)
243         free (scanline_buffer);
244 }
245
246 static void
247 general_composite (pixman_implementation_t *    imp,
248                    pixman_op_t                  op,
249                    pixman_image_t *             src,
250                    pixman_image_t *             mask,
251                    pixman_image_t *             dest,
252                    int32_t                      src_x,
253                    int32_t                      src_y,
254                    int32_t                      mask_x,
255                    int32_t                      mask_y,
256                    int32_t                      dest_x,
257                    int32_t                      dest_y,
258                    int32_t                      width,
259                    int32_t                      height)
260 {
261     _pixman_walk_composite_region (imp, op, src, mask, dest, src_x, src_y,
262                                    mask_x, mask_y, dest_x, dest_y, width, height,
263                                    general_composite_rect);
264 }
265
266 static pixman_bool_t
267 general_blt (pixman_implementation_t *imp,
268              uint32_t *src_bits,
269              uint32_t *dst_bits,
270              int src_stride,
271              int dst_stride,
272              int src_bpp,
273              int dst_bpp,
274              int src_x, int src_y,
275              int dst_x, int dst_y,
276              int width, int height)
277 {
278     /* We can't blit unless we have sse2 or mmx */
279     
280     return FALSE;
281 }
282
283 static pixman_bool_t
284 general_fill (pixman_implementation_t *imp,
285               uint32_t *bits,
286               int stride,
287               int bpp,
288               int x,
289               int y,
290               int width,
291               int height,
292               uint32_t xor)
293 {
294     return FALSE;
295 }
296
297 pixman_implementation_t *
298 _pixman_implementation_create_general (void)
299 {
300     pixman_implementation_t *imp = _pixman_implementation_create (NULL);
301
302     _pixman_setup_combiner_functions_32 (imp);
303     _pixman_setup_combiner_functions_64 (imp);
304     
305     imp->composite = general_composite;
306     imp->blt = general_blt;
307     imp->fill = general_fill;
308     
309     return imp;
310 }