• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
2 /*
3  * Copyright © 2000 SuSE, Inc.
4  * Copyright © 2007 Red Hat, Inc.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of SuSE not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  SuSE makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Author:  Keith Packard, SuSE, Inc.
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 #include "pixman-private.h"
30 
31 #include <stdlib.h>
32 
33 pixman_implementation_t *global_implementation;
34 
35 #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
36 static void __attribute__((constructor))
pixman_constructor(void)37 pixman_constructor (void)
38 {
39     global_implementation = _pixman_choose_implementation ();
40 }
41 #endif
42 
43 typedef struct operator_info_t operator_info_t;
44 
45 struct operator_info_t
46 {
47     uint8_t	opaque_info[4];
48 };
49 
50 #define PACK(neither, src, dest, both)			\
51     {{	    (uint8_t)PIXMAN_OP_ ## neither,		\
52 	    (uint8_t)PIXMAN_OP_ ## src,			\
53 	    (uint8_t)PIXMAN_OP_ ## dest,		\
54 	    (uint8_t)PIXMAN_OP_ ## both		}}
55 
56 static const operator_info_t operator_table[] =
57 {
58     /*    Neither Opaque         Src Opaque             Dst Opaque             Both Opaque */
59     PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
60     PACK (SRC,                   SRC,                   SRC,                   SRC),
61     PACK (DST,                   DST,                   DST,                   DST),
62     PACK (OVER,                  SRC,                   OVER,                  SRC),
63     PACK (OVER_REVERSE,          OVER_REVERSE,          DST,                   DST),
64     PACK (IN,                    IN,                    SRC,                   SRC),
65     PACK (IN_REVERSE,            DST,                   IN_REVERSE,            DST),
66     PACK (OUT,                   OUT,                   CLEAR,                 CLEAR),
67     PACK (OUT_REVERSE,           CLEAR,                 OUT_REVERSE,           CLEAR),
68     PACK (ATOP,                  IN,                    OVER,                  SRC),
69     PACK (ATOP_REVERSE,          OVER_REVERSE,          IN_REVERSE,            DST),
70     PACK (XOR,                   OUT,                   OUT_REVERSE,           CLEAR),
71     PACK (ADD,                   ADD,                   ADD,                   ADD),
72     PACK (SATURATE,              OVER_REVERSE,          DST,                   DST),
73 
74     {{ 0 /* 0x0e */ }},
75     {{ 0 /* 0x0f */ }},
76 
77     PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
78     PACK (SRC,                   SRC,                   SRC,                   SRC),
79     PACK (DST,                   DST,                   DST,                   DST),
80     PACK (DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER),
81     PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
82     PACK (DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN),
83     PACK (DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE),
84     PACK (DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT),
85     PACK (DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE),
86     PACK (DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP),
87     PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
88     PACK (DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR),
89 
90     {{ 0 /* 0x1c */ }},
91     {{ 0 /* 0x1d */ }},
92     {{ 0 /* 0x1e */ }},
93     {{ 0 /* 0x1f */ }},
94 
95     PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
96     PACK (SRC,                   SRC,                   SRC,                   SRC),
97     PACK (DST,                   DST,                   DST,                   DST),
98     PACK (CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER),
99     PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
100     PACK (CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN),
101     PACK (CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE),
102     PACK (CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT),
103     PACK (CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE),
104     PACK (CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP),
105     PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
106     PACK (CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR),
107 
108     {{ 0 /* 0x2c */ }},
109     {{ 0 /* 0x2d */ }},
110     {{ 0 /* 0x2e */ }},
111     {{ 0 /* 0x2f */ }},
112 
113     PACK (MULTIPLY,              MULTIPLY,              MULTIPLY,              MULTIPLY),
114     PACK (SCREEN,                SCREEN,                SCREEN,                SCREEN),
115     PACK (OVERLAY,               OVERLAY,               OVERLAY,               OVERLAY),
116     PACK (DARKEN,                DARKEN,                DARKEN,                DARKEN),
117     PACK (LIGHTEN,               LIGHTEN,               LIGHTEN,               LIGHTEN),
118     PACK (COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE),
119     PACK (COLOR_BURN,            COLOR_BURN,            COLOR_BURN,            COLOR_BURN),
120     PACK (HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT),
121     PACK (SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT),
122     PACK (DIFFERENCE,            DIFFERENCE,            DIFFERENCE,            DIFFERENCE),
123     PACK (EXCLUSION,             EXCLUSION,             EXCLUSION,             EXCLUSION),
124     PACK (HSL_HUE,               HSL_HUE,               HSL_HUE,               HSL_HUE),
125     PACK (HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION),
126     PACK (HSL_COLOR,             HSL_COLOR,             HSL_COLOR,             HSL_COLOR),
127     PACK (HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY),
128 };
129 
130 /*
131  * Optimize the current operator based on opacity of source or destination
132  * The output operator should be mathematically equivalent to the source.
133  */
134 static pixman_op_t
optimize_operator(pixman_op_t op,uint32_t src_flags,uint32_t mask_flags,uint32_t dst_flags)135 optimize_operator (pixman_op_t     op,
136 		   uint32_t        src_flags,
137 		   uint32_t        mask_flags,
138 		   uint32_t        dst_flags)
139 {
140     pixman_bool_t is_source_opaque, is_dest_opaque;
141 
142 #define OPAQUE_SHIFT 13
143 
144     COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
145 
146     is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
147     is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
148 
149     is_dest_opaque >>= OPAQUE_SHIFT - 1;
150     is_source_opaque >>= OPAQUE_SHIFT;
151 
152     return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
153 }
154 
155 /*
156  * Computing composite region
157  */
158 static inline pixman_bool_t
clip_general_image(pixman_region32_t * region,pixman_region32_t * clip,int dx,int dy)159 clip_general_image (pixman_region32_t * region,
160                     pixman_region32_t * clip,
161                     int                 dx,
162                     int                 dy)
163 {
164     if (pixman_region32_n_rects (region) == 1 &&
165         pixman_region32_n_rects (clip) == 1)
166     {
167 	pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
168 	pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
169 	int v;
170 
171 	if (rbox->x1 < (v = cbox->x1 + dx))
172 	    rbox->x1 = v;
173 	if (rbox->x2 > (v = cbox->x2 + dx))
174 	    rbox->x2 = v;
175 	if (rbox->y1 < (v = cbox->y1 + dy))
176 	    rbox->y1 = v;
177 	if (rbox->y2 > (v = cbox->y2 + dy))
178 	    rbox->y2 = v;
179 	if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
180 	{
181 	    pixman_region32_init (region);
182 	    return FALSE;
183 	}
184     }
185     else if (!pixman_region32_not_empty (clip))
186     {
187 	return FALSE;
188     }
189     else
190     {
191 	if (dx || dy)
192 	    pixman_region32_translate (region, -dx, -dy);
193 
194 	if (!pixman_region32_intersect (region, region, clip))
195 	    return FALSE;
196 
197 	if (dx || dy)
198 	    pixman_region32_translate (region, dx, dy);
199     }
200 
201     return pixman_region32_not_empty (region);
202 }
203 
204 static inline pixman_bool_t
clip_source_image(pixman_region32_t * region,pixman_image_t * image,int dx,int dy)205 clip_source_image (pixman_region32_t * region,
206                    pixman_image_t *    image,
207                    int                 dx,
208                    int                 dy)
209 {
210     /* Source clips are ignored, unless they are explicitly turned on
211      * and the clip in question was set by an X client. (Because if
212      * the clip was not set by a client, then it is a hierarchy
213      * clip and those should always be ignored for sources).
214      */
215     if (!image->common.clip_sources || !image->common.client_clip)
216 	return TRUE;
217 
218     return clip_general_image (region,
219                                &image->common.clip_region,
220                                dx, dy);
221 }
222 
223 /*
224  * returns FALSE if the final region is empty.  Indistinguishable from
225  * an allocation failure, but rendering ignores those anyways.
226  */
227 pixman_bool_t
_pixman_compute_composite_region32(pixman_region32_t * region,pixman_image_t * src_image,pixman_image_t * mask_image,pixman_image_t * dest_image,int32_t src_x,int32_t src_y,int32_t mask_x,int32_t mask_y,int32_t dest_x,int32_t dest_y,int32_t width,int32_t height)228 _pixman_compute_composite_region32 (pixman_region32_t * region,
229 				    pixman_image_t *    src_image,
230 				    pixman_image_t *    mask_image,
231 				    pixman_image_t *    dest_image,
232 				    int32_t             src_x,
233 				    int32_t             src_y,
234 				    int32_t             mask_x,
235 				    int32_t             mask_y,
236 				    int32_t             dest_x,
237 				    int32_t             dest_y,
238 				    int32_t             width,
239 				    int32_t             height)
240 {
241     region->extents.x1 = dest_x;
242     region->extents.x2 = dest_x + width;
243     region->extents.y1 = dest_y;
244     region->extents.y2 = dest_y + height;
245 
246     region->extents.x1 = MAX (region->extents.x1, 0);
247     region->extents.y1 = MAX (region->extents.y1, 0);
248     region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
249     region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
250 
251     region->data = 0;
252 
253     /* Check for empty operation */
254     if (region->extents.x1 >= region->extents.x2 ||
255         region->extents.y1 >= region->extents.y2)
256     {
257 	region->extents.x1 = 0;
258 	region->extents.x2 = 0;
259 	region->extents.y1 = 0;
260 	region->extents.y2 = 0;
261 	return FALSE;
262     }
263 
264     if (dest_image->common.have_clip_region)
265     {
266 	if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
267 	    return FALSE;
268     }
269 
270     if (dest_image->common.alpha_map)
271     {
272 	if (!pixman_region32_intersect_rect (region, region,
273 					     dest_image->common.alpha_origin_x,
274 					     dest_image->common.alpha_origin_y,
275 					     dest_image->common.alpha_map->width,
276 					     dest_image->common.alpha_map->height))
277 	{
278 	    return FALSE;
279 	}
280 	if (!pixman_region32_not_empty (region))
281 	    return FALSE;
282 	if (dest_image->common.alpha_map->common.have_clip_region)
283 	{
284 	    if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
285 				     -dest_image->common.alpha_origin_x,
286 				     -dest_image->common.alpha_origin_y))
287 	    {
288 		return FALSE;
289 	    }
290 	}
291     }
292 
293     /* clip against src */
294     if (src_image->common.have_clip_region)
295     {
296 	if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
297 	    return FALSE;
298     }
299     if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
300     {
301 	if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
302 	                        dest_x - (src_x - src_image->common.alpha_origin_x),
303 	                        dest_y - (src_y - src_image->common.alpha_origin_y)))
304 	{
305 	    return FALSE;
306 	}
307     }
308     /* clip against mask */
309     if (mask_image && mask_image->common.have_clip_region)
310     {
311 	if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
312 	    return FALSE;
313 
314 	if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
315 	{
316 	    if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
317 	                            dest_x - (mask_x - mask_image->common.alpha_origin_x),
318 	                            dest_y - (mask_y - mask_image->common.alpha_origin_y)))
319 	    {
320 		return FALSE;
321 	    }
322 	}
323     }
324 
325     return TRUE;
326 }
327 
328 typedef struct box_48_16 box_48_16_t;
329 
330 struct box_48_16
331 {
332     pixman_fixed_48_16_t        x1;
333     pixman_fixed_48_16_t        y1;
334     pixman_fixed_48_16_t        x2;
335     pixman_fixed_48_16_t        y2;
336 };
337 
338 static pixman_bool_t
compute_transformed_extents(pixman_transform_t * transform,const pixman_box32_t * extents,box_48_16_t * transformed)339 compute_transformed_extents (pixman_transform_t   *transform,
340 			     const pixman_box32_t *extents,
341 			     box_48_16_t          *transformed)
342 {
343     pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
344     pixman_fixed_t x1, y1, x2, y2;
345     int i;
346 
347     x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
348     y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
349     x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
350     y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
351 
352     if (!transform)
353     {
354 	transformed->x1 = x1;
355 	transformed->y1 = y1;
356 	transformed->x2 = x2;
357 	transformed->y2 = y2;
358 
359 	return TRUE;
360     }
361 
362     tx1 = ty1 = INT64_MAX;
363     tx2 = ty2 = INT64_MIN;
364 
365     for (i = 0; i < 4; ++i)
366     {
367 	pixman_fixed_48_16_t tx, ty;
368 	pixman_vector_t v;
369 
370 	v.vector[0] = (i & 0x01)? x1 : x2;
371 	v.vector[1] = (i & 0x02)? y1 : y2;
372 	v.vector[2] = pixman_fixed_1;
373 
374 	if (!pixman_transform_point (transform, &v))
375 	    return FALSE;
376 
377 	tx = (pixman_fixed_48_16_t)v.vector[0];
378 	ty = (pixman_fixed_48_16_t)v.vector[1];
379 
380 	if (tx < tx1)
381 	    tx1 = tx;
382 	if (ty < ty1)
383 	    ty1 = ty;
384 	if (tx > tx2)
385 	    tx2 = tx;
386 	if (ty > ty2)
387 	    ty2 = ty;
388     }
389 
390     transformed->x1 = tx1;
391     transformed->y1 = ty1;
392     transformed->x2 = tx2;
393     transformed->y2 = ty2;
394 
395     return TRUE;
396 }
397 
398 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
399 #define ABS(f)      (((f) < 0)?  (-(f)) : (f))
400 #define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
401 
402 static pixman_bool_t
analyze_extent(pixman_image_t * image,const pixman_box32_t * extents,uint32_t * flags)403 analyze_extent (pixman_image_t       *image,
404 		const pixman_box32_t *extents,
405 		uint32_t             *flags)
406 {
407     pixman_transform_t *transform;
408     pixman_fixed_t x_off, y_off;
409     pixman_fixed_t width, height;
410     pixman_fixed_t *params;
411     box_48_16_t transformed;
412     pixman_box32_t exp_extents;
413 
414     if (!image)
415 	return TRUE;
416 
417     /* Some compositing functions walk one step
418      * outside the destination rectangle, so we
419      * check here that the expanded-by-one source
420      * extents in destination space fits in 16 bits
421      */
422     if (!IS_16BIT (extents->x1 - 1)		||
423 	!IS_16BIT (extents->y1 - 1)		||
424 	!IS_16BIT (extents->x2 + 1)		||
425 	!IS_16BIT (extents->y2 + 1))
426     {
427 	return FALSE;
428     }
429 
430     transform = image->common.transform;
431     if (image->common.type == BITS)
432     {
433 	/* During repeat mode calculations we might convert the
434 	 * width/height of an image to fixed 16.16, so we need
435 	 * them to be smaller than 16 bits.
436 	 */
437 	if (image->bits.width >= 0x7fff	|| image->bits.height >= 0x7fff)
438 	    return FALSE;
439 
440 	if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
441 	    extents->x1 >= 0 &&
442 	    extents->y1 >= 0 &&
443 	    extents->x2 <= image->bits.width &&
444 	    extents->y2 <= image->bits.height)
445 	{
446 	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
447 	    return TRUE;
448 	}
449 
450 	switch (image->common.filter)
451 	{
452 	case PIXMAN_FILTER_CONVOLUTION:
453 	    params = image->common.filter_params;
454 	    x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
455 	    y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
456 	    width = params[0];
457 	    height = params[1];
458 	    break;
459 
460 	case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
461 	    params = image->common.filter_params;
462 	    x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
463 	    y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
464 	    width = params[0];
465 	    height = params[1];
466 	    break;
467 
468 	case PIXMAN_FILTER_GOOD:
469 	case PIXMAN_FILTER_BEST:
470 	case PIXMAN_FILTER_BILINEAR:
471 	    x_off = - pixman_fixed_1 / 2;
472 	    y_off = - pixman_fixed_1 / 2;
473 	    width = pixman_fixed_1;
474 	    height = pixman_fixed_1;
475 	    break;
476 
477 	case PIXMAN_FILTER_FAST:
478 	case PIXMAN_FILTER_NEAREST:
479 	    x_off = - pixman_fixed_e;
480 	    y_off = - pixman_fixed_e;
481 	    width = 0;
482 	    height = 0;
483 	    break;
484 
485 	default:
486 	    return FALSE;
487 	}
488     }
489     else
490     {
491 	x_off = 0;
492 	y_off = 0;
493 	width = 0;
494 	height = 0;
495     }
496 
497     if (!compute_transformed_extents (transform, extents, &transformed))
498 	return FALSE;
499 
500     if (image->common.type == BITS)
501     {
502 	if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_e) >= 0                &&
503 	    pixman_fixed_to_int (transformed.y1 - pixman_fixed_e) >= 0                &&
504 	    pixman_fixed_to_int (transformed.x2 - pixman_fixed_e) < image->bits.width &&
505 	    pixman_fixed_to_int (transformed.y2 - pixman_fixed_e) < image->bits.height)
506 	{
507 	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
508 	}
509 
510 	if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0		  &&
511 	    pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0		  &&
512 	    pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
513 	    pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
514 	{
515 	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
516 	}
517     }
518 
519     /* Check we don't overflow when the destination extents are expanded by one.
520      * This ensures that compositing functions can simply walk the source space
521      * using 16.16 variables without worrying about overflow.
522      */
523     exp_extents = *extents;
524     exp_extents.x1 -= 1;
525     exp_extents.y1 -= 1;
526     exp_extents.x2 += 1;
527     exp_extents.y2 += 1;
528 
529     if (!compute_transformed_extents (transform, &exp_extents, &transformed))
530 	return FALSE;
531 
532     if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e)	||
533 	!IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e)	||
534 	!IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width)	||
535 	!IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
536     {
537 	return FALSE;
538     }
539 
540     return TRUE;
541 }
542 
543 /*
544  * Work around GCC bug causing crashes in Mozilla with SSE2
545  *
546  * When using -msse, gcc generates movdqa instructions assuming that
547  * the stack is 16 byte aligned. Unfortunately some applications, such
548  * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
549  * causes the movdqa instructions to fail.
550  *
551  * The __force_align_arg_pointer__ makes gcc generate a prologue that
552  * realigns the stack pointer to 16 bytes.
553  *
554  * On x86-64 this is not necessary because the standard ABI already
555  * calls for a 16 byte aligned stack.
556  *
557  * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
558  */
559 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
560 __attribute__((__force_align_arg_pointer__))
561 #endif
562 PIXMAN_EXPORT void
pixman_image_composite32(pixman_op_t op,pixman_image_t * src,pixman_image_t * mask,pixman_image_t * dest,int32_t src_x,int32_t src_y,int32_t mask_x,int32_t mask_y,int32_t dest_x,int32_t dest_y,int32_t width,int32_t height)563 pixman_image_composite32 (pixman_op_t      op,
564                           pixman_image_t * src,
565                           pixman_image_t * mask,
566                           pixman_image_t * dest,
567                           int32_t          src_x,
568                           int32_t          src_y,
569                           int32_t          mask_x,
570                           int32_t          mask_y,
571                           int32_t          dest_x,
572                           int32_t          dest_y,
573                           int32_t          width,
574                           int32_t          height)
575 {
576     pixman_format_code_t src_format, mask_format, dest_format;
577     pixman_region32_t region;
578     pixman_box32_t extents;
579     pixman_implementation_t *imp;
580     pixman_composite_func_t func;
581     pixman_composite_info_t info;
582     const pixman_box32_t *pbox;
583     int n;
584 
585     _pixman_image_validate (src);
586     if (mask)
587 	_pixman_image_validate (mask);
588     _pixman_image_validate (dest);
589 
590     src_format = src->common.extended_format_code;
591     info.src_flags = src->common.flags;
592 
593     if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE))
594     {
595 	mask_format = mask->common.extended_format_code;
596 	info.mask_flags = mask->common.flags;
597     }
598     else
599     {
600 	mask_format = PIXMAN_null;
601 	info.mask_flags = FAST_PATH_IS_OPAQUE | FAST_PATH_NO_ALPHA_MAP;
602     }
603 
604     dest_format = dest->common.extended_format_code;
605     info.dest_flags = dest->common.flags;
606 
607     /* Check for pixbufs */
608     if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
609 	(src->type == BITS && src->bits.bits == mask->bits.bits)	   &&
610 	(src->common.repeat == mask->common.repeat)			   &&
611 	(info.src_flags & info.mask_flags & FAST_PATH_ID_TRANSFORM)	   &&
612 	(src_x == mask_x && src_y == mask_y))
613     {
614 	if (src_format == PIXMAN_x8b8g8r8)
615 	    src_format = mask_format = PIXMAN_pixbuf;
616 	else if (src_format == PIXMAN_x8r8g8b8)
617 	    src_format = mask_format = PIXMAN_rpixbuf;
618     }
619 
620     pixman_region32_init (&region);
621 
622     if (!_pixman_compute_composite_region32 (
623 	    &region, src, mask, dest,
624 	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
625     {
626 	goto out;
627     }
628 
629     extents = *pixman_region32_extents (&region);
630 
631     extents.x1 -= dest_x - src_x;
632     extents.y1 -= dest_y - src_y;
633     extents.x2 -= dest_x - src_x;
634     extents.y2 -= dest_y - src_y;
635 
636     if (!analyze_extent (src, &extents, &info.src_flags))
637 	goto out;
638 
639     extents.x1 -= src_x - mask_x;
640     extents.y1 -= src_y - mask_y;
641     extents.x2 -= src_x - mask_x;
642     extents.y2 -= src_y - mask_y;
643 
644     if (!analyze_extent (mask, &extents, &info.mask_flags))
645 	goto out;
646 
647     /* If the clip is within the source samples, and the samples are
648      * opaque, then the source is effectively opaque.
649      */
650 #define NEAREST_OPAQUE	(FAST_PATH_SAMPLES_OPAQUE |			\
651 			 FAST_PATH_NEAREST_FILTER |			\
652 			 FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
653 #define BILINEAR_OPAQUE	(FAST_PATH_SAMPLES_OPAQUE |			\
654 			 FAST_PATH_BILINEAR_FILTER |			\
655 			 FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
656 
657     if ((info.src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
658 	(info.src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
659     {
660 	info.src_flags |= FAST_PATH_IS_OPAQUE;
661     }
662 
663     if ((info.mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
664 	(info.mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
665     {
666 	info.mask_flags |= FAST_PATH_IS_OPAQUE;
667     }
668 
669     /*
670      * Check if we can replace our operator by a simpler one
671      * if the src or dest are opaque. The output operator should be
672      * mathematically equivalent to the source.
673      */
674     info.op = optimize_operator (op, info.src_flags, info.mask_flags, info.dest_flags);
675 
676     _pixman_implementation_lookup_composite (
677 	get_implementation (), info.op,
678 	src_format, info.src_flags,
679 	mask_format, info.mask_flags,
680 	dest_format, info.dest_flags,
681 	&imp, &func);
682 
683     info.src_image = src;
684     info.mask_image = mask;
685     info.dest_image = dest;
686 
687     pbox = pixman_region32_rectangles (&region, &n);
688 
689     while (n--)
690     {
691 	info.src_x = pbox->x1 + src_x - dest_x;
692 	info.src_y = pbox->y1 + src_y - dest_y;
693 	info.mask_x = pbox->x1 + mask_x - dest_x;
694 	info.mask_y = pbox->y1 + mask_y - dest_y;
695 	info.dest_x = pbox->x1;
696 	info.dest_y = pbox->y1;
697 	info.width = pbox->x2 - pbox->x1;
698 	info.height = pbox->y2 - pbox->y1;
699 
700 	func (imp, &info);
701 
702 	pbox++;
703     }
704 
705 out:
706     pixman_region32_fini (&region);
707 }
708 
709 PIXMAN_EXPORT void
pixman_image_composite(pixman_op_t op,pixman_image_t * src,pixman_image_t * mask,pixman_image_t * dest,int16_t src_x,int16_t src_y,int16_t mask_x,int16_t mask_y,int16_t dest_x,int16_t dest_y,uint16_t width,uint16_t height)710 pixman_image_composite (pixman_op_t      op,
711                         pixman_image_t * src,
712                         pixman_image_t * mask,
713                         pixman_image_t * dest,
714                         int16_t          src_x,
715                         int16_t          src_y,
716                         int16_t          mask_x,
717                         int16_t          mask_y,
718                         int16_t          dest_x,
719                         int16_t          dest_y,
720                         uint16_t         width,
721                         uint16_t         height)
722 {
723     pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
724                               mask_x, mask_y, dest_x, dest_y, width, height);
725 }
726 
727 PIXMAN_EXPORT pixman_bool_t
pixman_blt(uint32_t * src_bits,uint32_t * dst_bits,int src_stride,int dst_stride,int src_bpp,int dst_bpp,int src_x,int src_y,int dest_x,int dest_y,int width,int height)728 pixman_blt (uint32_t *src_bits,
729             uint32_t *dst_bits,
730             int       src_stride,
731             int       dst_stride,
732             int       src_bpp,
733             int       dst_bpp,
734             int       src_x,
735             int       src_y,
736             int       dest_x,
737             int       dest_y,
738             int       width,
739             int       height)
740 {
741     return _pixman_implementation_blt (get_implementation(),
742 				       src_bits, dst_bits, src_stride, dst_stride,
743                                        src_bpp, dst_bpp,
744                                        src_x, src_y,
745                                        dest_x, dest_y,
746                                        width, height);
747 }
748 
749 PIXMAN_EXPORT pixman_bool_t
pixman_fill(uint32_t * bits,int stride,int bpp,int x,int y,int width,int height,uint32_t filler)750 pixman_fill (uint32_t *bits,
751              int       stride,
752              int       bpp,
753              int       x,
754              int       y,
755              int       width,
756              int       height,
757              uint32_t  filler)
758 {
759     return _pixman_implementation_fill (
760 	get_implementation(), bits, stride, bpp, x, y, width, height, filler);
761 }
762 
763 static uint32_t
color_to_uint32(const pixman_color_t * color)764 color_to_uint32 (const pixman_color_t *color)
765 {
766     return
767         (color->alpha >> 8 << 24) |
768         (color->red >> 8 << 16) |
769         (color->green & 0xff00) |
770         (color->blue >> 8);
771 }
772 
773 static pixman_bool_t
color_to_pixel(const pixman_color_t * color,uint32_t * pixel,pixman_format_code_t format)774 color_to_pixel (const pixman_color_t *color,
775                 uint32_t *            pixel,
776                 pixman_format_code_t  format)
777 {
778     uint32_t c = color_to_uint32 (color);
779 
780     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA_FLOAT)
781     {
782 	return FALSE;
783     }
784 
785     if (!(format == PIXMAN_a8r8g8b8     ||
786           format == PIXMAN_x8r8g8b8     ||
787           format == PIXMAN_a8b8g8r8     ||
788           format == PIXMAN_x8b8g8r8     ||
789           format == PIXMAN_b8g8r8a8     ||
790           format == PIXMAN_b8g8r8x8     ||
791           format == PIXMAN_r8g8b8a8     ||
792           format == PIXMAN_r8g8b8x8     ||
793           format == PIXMAN_r5g6b5       ||
794           format == PIXMAN_b5g6r5       ||
795           format == PIXMAN_a8           ||
796           format == PIXMAN_a1))
797     {
798 	return FALSE;
799     }
800 
801     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
802     {
803 	c = ((c & 0xff000000) >>  0) |
804 	    ((c & 0x00ff0000) >> 16) |
805 	    ((c & 0x0000ff00) >>  0) |
806 	    ((c & 0x000000ff) << 16);
807     }
808     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
809     {
810 	c = ((c & 0xff000000) >> 24) |
811 	    ((c & 0x00ff0000) >>  8) |
812 	    ((c & 0x0000ff00) <<  8) |
813 	    ((c & 0x000000ff) << 24);
814     }
815     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
816 	c = ((c & 0xff000000) >> 24) | (c << 8);
817 
818     if (format == PIXMAN_a1)
819 	c = c >> 31;
820     else if (format == PIXMAN_a8)
821 	c = c >> 24;
822     else if (format == PIXMAN_r5g6b5 ||
823              format == PIXMAN_b5g6r5)
824 	c = convert_8888_to_0565 (c);
825 
826 #if 0
827     printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
828     printf ("pixel: %x\n", c);
829 #endif
830 
831     *pixel = c;
832     return TRUE;
833 }
834 
835 PIXMAN_EXPORT pixman_bool_t
pixman_image_fill_rectangles(pixman_op_t op,pixman_image_t * dest,const pixman_color_t * color,int n_rects,const pixman_rectangle16_t * rects)836 pixman_image_fill_rectangles (pixman_op_t                 op,
837                               pixman_image_t *            dest,
838 			      const pixman_color_t *      color,
839                               int                         n_rects,
840                               const pixman_rectangle16_t *rects)
841 {
842     pixman_box32_t stack_boxes[6];
843     pixman_box32_t *boxes;
844     pixman_bool_t result;
845     int i;
846 
847     if (n_rects > 6)
848     {
849         boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
850         if (boxes == NULL)
851             return FALSE;
852     }
853     else
854     {
855         boxes = stack_boxes;
856     }
857 
858     for (i = 0; i < n_rects; ++i)
859     {
860         boxes[i].x1 = rects[i].x;
861         boxes[i].y1 = rects[i].y;
862         boxes[i].x2 = boxes[i].x1 + rects[i].width;
863         boxes[i].y2 = boxes[i].y1 + rects[i].height;
864     }
865 
866     result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
867 
868     if (boxes != stack_boxes)
869         free (boxes);
870 
871     return result;
872 }
873 
874 PIXMAN_EXPORT pixman_bool_t
pixman_image_fill_boxes(pixman_op_t op,pixman_image_t * dest,const pixman_color_t * color,int n_boxes,const pixman_box32_t * boxes)875 pixman_image_fill_boxes (pixman_op_t           op,
876                          pixman_image_t *      dest,
877                          const pixman_color_t *color,
878                          int                   n_boxes,
879                          const pixman_box32_t *boxes)
880 {
881     pixman_image_t *solid;
882     pixman_color_t c;
883     int i;
884 
885     _pixman_image_validate (dest);
886 
887     if (color->alpha == 0xffff)
888     {
889         if (op == PIXMAN_OP_OVER)
890             op = PIXMAN_OP_SRC;
891     }
892 
893     if (op == PIXMAN_OP_CLEAR)
894     {
895         c.red = 0;
896         c.green = 0;
897         c.blue = 0;
898         c.alpha = 0;
899 
900         color = &c;
901 
902         op = PIXMAN_OP_SRC;
903     }
904 
905     if (op == PIXMAN_OP_SRC)
906     {
907         uint32_t pixel;
908 
909         if (color_to_pixel (color, &pixel, dest->bits.format))
910         {
911             pixman_region32_t fill_region;
912             int n_rects, j;
913             pixman_box32_t *rects;
914 
915             if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
916                 return FALSE;
917 
918             if (dest->common.have_clip_region)
919             {
920                 if (!pixman_region32_intersect (&fill_region,
921                                                 &fill_region,
922                                                 &dest->common.clip_region))
923                     return FALSE;
924             }
925 
926             rects = pixman_region32_rectangles (&fill_region, &n_rects);
927             for (j = 0; j < n_rects; ++j)
928             {
929                 const pixman_box32_t *rect = &(rects[j]);
930                 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
931                              rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
932                              pixel);
933             }
934 
935             pixman_region32_fini (&fill_region);
936             return TRUE;
937         }
938     }
939 
940     solid = pixman_image_create_solid_fill (color);
941     if (!solid)
942         return FALSE;
943 
944     for (i = 0; i < n_boxes; ++i)
945     {
946         const pixman_box32_t *box = &(boxes[i]);
947 
948         pixman_image_composite32 (op, solid, NULL, dest,
949                                   0, 0, 0, 0,
950                                   box->x1, box->y1,
951                                   box->x2 - box->x1, box->y2 - box->y1);
952     }
953 
954     pixman_image_unref (solid);
955 
956     return TRUE;
957 }
958 
959 /**
960  * pixman_version:
961  *
962  * Returns the version of the pixman library encoded in a single
963  * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
964  * later versions compare greater than earlier versions.
965  *
966  * A run-time comparison to check that pixman's version is greater than
967  * or equal to version X.Y.Z could be performed as follows:
968  *
969  * <informalexample><programlisting>
970  * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
971  * </programlisting></informalexample>
972  *
973  * See also pixman_version_string() as well as the compile-time
974  * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
975  *
976  * Return value: the encoded version.
977  **/
978 PIXMAN_EXPORT int
pixman_version(void)979 pixman_version (void)
980 {
981     return PIXMAN_VERSION;
982 }
983 
984 /**
985  * pixman_version_string:
986  *
987  * Returns the version of the pixman library as a human-readable string
988  * of the form "X.Y.Z".
989  *
990  * See also pixman_version() as well as the compile-time equivalents
991  * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
992  *
993  * Return value: a string containing the version.
994  **/
995 PIXMAN_EXPORT const char*
pixman_version_string(void)996 pixman_version_string (void)
997 {
998     return PIXMAN_VERSION_STRING;
999 }
1000 
1001 /**
1002  * pixman_format_supported_source:
1003  * @format: A pixman_format_code_t format
1004  *
1005  * Return value: whether the provided format code is a supported
1006  * format for a pixman surface used as a source in
1007  * rendering.
1008  *
1009  * Currently, all pixman_format_code_t values are supported.
1010  **/
1011 PIXMAN_EXPORT pixman_bool_t
pixman_format_supported_source(pixman_format_code_t format)1012 pixman_format_supported_source (pixman_format_code_t format)
1013 {
1014     switch (format)
1015     {
1016     /* 32 bpp formats */
1017     case PIXMAN_a2b10g10r10:
1018     case PIXMAN_x2b10g10r10:
1019     case PIXMAN_a2r10g10b10:
1020     case PIXMAN_x2r10g10b10:
1021     case PIXMAN_a8r8g8b8:
1022     case PIXMAN_a8r8g8b8_sRGB:
1023     case PIXMAN_x8r8g8b8:
1024     case PIXMAN_a8b8g8r8:
1025     case PIXMAN_x8b8g8r8:
1026     case PIXMAN_b8g8r8a8:
1027     case PIXMAN_b8g8r8x8:
1028     case PIXMAN_r8g8b8a8:
1029     case PIXMAN_r8g8b8x8:
1030     case PIXMAN_r8g8b8:
1031     case PIXMAN_b8g8r8:
1032     case PIXMAN_r5g6b5:
1033     case PIXMAN_b5g6r5:
1034     case PIXMAN_x14r6g6b6:
1035     /* 16 bpp formats */
1036     case PIXMAN_a1r5g5b5:
1037     case PIXMAN_x1r5g5b5:
1038     case PIXMAN_a1b5g5r5:
1039     case PIXMAN_x1b5g5r5:
1040     case PIXMAN_a4r4g4b4:
1041     case PIXMAN_x4r4g4b4:
1042     case PIXMAN_a4b4g4r4:
1043     case PIXMAN_x4b4g4r4:
1044     /* 8bpp formats */
1045     case PIXMAN_a8:
1046     case PIXMAN_r3g3b2:
1047     case PIXMAN_b2g3r3:
1048     case PIXMAN_a2r2g2b2:
1049     case PIXMAN_a2b2g2r2:
1050     case PIXMAN_c8:
1051     case PIXMAN_g8:
1052     case PIXMAN_x4a4:
1053     /* Collides with PIXMAN_c8
1054        case PIXMAN_x4c4:
1055      */
1056     /* Collides with PIXMAN_g8
1057        case PIXMAN_x4g4:
1058      */
1059     /* 4bpp formats */
1060     case PIXMAN_a4:
1061     case PIXMAN_r1g2b1:
1062     case PIXMAN_b1g2r1:
1063     case PIXMAN_a1r1g1b1:
1064     case PIXMAN_a1b1g1r1:
1065     case PIXMAN_c4:
1066     case PIXMAN_g4:
1067     /* 1bpp formats */
1068     case PIXMAN_a1:
1069     case PIXMAN_g1:
1070     /* YUV formats */
1071     case PIXMAN_yuy2:
1072     case PIXMAN_yv12:
1073 	return TRUE;
1074 
1075     default:
1076 	return FALSE;
1077     }
1078 }
1079 
1080 /**
1081  * pixman_format_supported_destination:
1082  * @format: A pixman_format_code_t format
1083  *
1084  * Return value: whether the provided format code is a supported
1085  * format for a pixman surface used as a destination in
1086  * rendering.
1087  *
1088  * Currently, all pixman_format_code_t values are supported
1089  * except for the YUV formats.
1090  **/
1091 PIXMAN_EXPORT pixman_bool_t
pixman_format_supported_destination(pixman_format_code_t format)1092 pixman_format_supported_destination (pixman_format_code_t format)
1093 {
1094     /* YUV formats cannot be written to at the moment */
1095     if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1096 	return FALSE;
1097 
1098     return pixman_format_supported_source (format);
1099 }
1100 
1101 PIXMAN_EXPORT pixman_bool_t
pixman_compute_composite_region(pixman_region16_t * region,pixman_image_t * src_image,pixman_image_t * mask_image,pixman_image_t * dest_image,int16_t src_x,int16_t src_y,int16_t mask_x,int16_t mask_y,int16_t dest_x,int16_t dest_y,uint16_t width,uint16_t height)1102 pixman_compute_composite_region (pixman_region16_t * region,
1103                                  pixman_image_t *    src_image,
1104                                  pixman_image_t *    mask_image,
1105                                  pixman_image_t *    dest_image,
1106                                  int16_t             src_x,
1107                                  int16_t             src_y,
1108                                  int16_t             mask_x,
1109                                  int16_t             mask_y,
1110                                  int16_t             dest_x,
1111                                  int16_t             dest_y,
1112                                  uint16_t            width,
1113                                  uint16_t            height)
1114 {
1115     pixman_region32_t r32;
1116     pixman_bool_t retval;
1117 
1118     pixman_region32_init (&r32);
1119 
1120     retval = _pixman_compute_composite_region32 (
1121 	&r32, src_image, mask_image, dest_image,
1122 	src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1123 	width, height);
1124 
1125     if (retval)
1126     {
1127 	if (!pixman_region16_copy_from_region32 (region, &r32))
1128 	    retval = FALSE;
1129     }
1130 
1131     pixman_region32_fini (&r32);
1132     return retval;
1133 }
1134