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
329 {
330 pixman_fixed_48_16_t x1;
331 pixman_fixed_48_16_t y1;
332 pixman_fixed_48_16_t x2;
333 pixman_fixed_48_16_t y2;
334 } box_48_16_t;
335
336 static pixman_bool_t
compute_transformed_extents(pixman_transform_t * transform,const pixman_box32_t * extents,box_48_16_t * transformed)337 compute_transformed_extents (pixman_transform_t *transform,
338 const pixman_box32_t *extents,
339 box_48_16_t *transformed)
340 {
341 pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
342 pixman_fixed_t x1, y1, x2, y2;
343 int i;
344
345 x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
346 y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
347 x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
348 y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
349
350 if (!transform)
351 {
352 transformed->x1 = x1;
353 transformed->y1 = y1;
354 transformed->x2 = x2;
355 transformed->y2 = y2;
356
357 return TRUE;
358 }
359
360 tx1 = ty1 = INT64_MAX;
361 tx2 = ty2 = INT64_MIN;
362
363 for (i = 0; i < 4; ++i)
364 {
365 pixman_fixed_48_16_t tx, ty;
366 pixman_vector_t v;
367
368 v.vector[0] = (i & 0x01)? x1 : x2;
369 v.vector[1] = (i & 0x02)? y1 : y2;
370 v.vector[2] = pixman_fixed_1;
371
372 if (!pixman_transform_point (transform, &v))
373 return FALSE;
374
375 tx = (pixman_fixed_48_16_t)v.vector[0];
376 ty = (pixman_fixed_48_16_t)v.vector[1];
377
378 if (tx < tx1)
379 tx1 = tx;
380 if (ty < ty1)
381 ty1 = ty;
382 if (tx > tx2)
383 tx2 = tx;
384 if (ty > ty2)
385 ty2 = ty;
386 }
387
388 transformed->x1 = tx1;
389 transformed->y1 = ty1;
390 transformed->x2 = tx2;
391 transformed->y2 = ty2;
392
393 return TRUE;
394 }
395
396 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
397 #define ABS(f) (((f) < 0)? (-(f)) : (f))
398 #define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
399
400 static pixman_bool_t
analyze_extent(pixman_image_t * image,const pixman_box32_t * extents,uint32_t * flags)401 analyze_extent (pixman_image_t *image,
402 const pixman_box32_t *extents,
403 uint32_t *flags)
404 {
405 pixman_transform_t *transform;
406 pixman_fixed_t x_off, y_off;
407 pixman_fixed_t width, height;
408 pixman_fixed_t *params;
409 box_48_16_t transformed;
410 pixman_box32_t exp_extents;
411
412 if (!image)
413 return TRUE;
414
415 /* Some compositing functions walk one step
416 * outside the destination rectangle, so we
417 * check here that the expanded-by-one source
418 * extents in destination space fits in 16 bits
419 */
420 if (!IS_16BIT (extents->x1 - 1) ||
421 !IS_16BIT (extents->y1 - 1) ||
422 !IS_16BIT (extents->x2 + 1) ||
423 !IS_16BIT (extents->y2 + 1))
424 {
425 return FALSE;
426 }
427
428 transform = image->common.transform;
429 if (image->common.type == BITS)
430 {
431 /* During repeat mode calculations we might convert the
432 * width/height of an image to fixed 16.16, so we need
433 * them to be smaller than 16 bits.
434 */
435 if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
436 return FALSE;
437
438 if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
439 extents->x1 >= 0 &&
440 extents->y1 >= 0 &&
441 extents->x2 <= image->bits.width &&
442 extents->y2 <= image->bits.height)
443 {
444 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
445 return TRUE;
446 }
447
448 switch (image->common.filter)
449 {
450 case PIXMAN_FILTER_CONVOLUTION:
451 params = image->common.filter_params;
452 x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
453 y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
454 width = params[0];
455 height = params[1];
456 break;
457
458 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
459 params = image->common.filter_params;
460 x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
461 y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
462 width = params[0];
463 height = params[1];
464 break;
465
466 case PIXMAN_FILTER_GOOD:
467 case PIXMAN_FILTER_BEST:
468 case PIXMAN_FILTER_BILINEAR:
469 x_off = - pixman_fixed_1 / 2;
470 y_off = - pixman_fixed_1 / 2;
471 width = pixman_fixed_1;
472 height = pixman_fixed_1;
473 break;
474
475 case PIXMAN_FILTER_FAST:
476 case PIXMAN_FILTER_NEAREST:
477 x_off = - pixman_fixed_e;
478 y_off = - pixman_fixed_e;
479 width = 0;
480 height = 0;
481 break;
482
483 default:
484 return FALSE;
485 }
486 }
487 else
488 {
489 x_off = 0;
490 y_off = 0;
491 width = 0;
492 height = 0;
493 }
494
495 if (!compute_transformed_extents (transform, extents, &transformed))
496 return FALSE;
497
498 /* Expand the source area by a tiny bit so account of different rounding that
499 * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
500 * 0.5 so this won't cause the area computed to be overly pessimistic.
501 */
502 transformed.x1 -= 8 * pixman_fixed_e;
503 transformed.y1 -= 8 * pixman_fixed_e;
504 transformed.x2 += 8 * pixman_fixed_e;
505 transformed.y2 += 8 * pixman_fixed_e;
506
507 if (image->common.type == BITS)
508 {
509 if (pixman_fixed_to_int (transformed.x1) >= 0 &&
510 pixman_fixed_to_int (transformed.y1) >= 0 &&
511 pixman_fixed_to_int (transformed.x2) < image->bits.width &&
512 pixman_fixed_to_int (transformed.y2) < image->bits.height)
513 {
514 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
515 }
516
517 if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0 &&
518 pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0 &&
519 pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
520 pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
521 {
522 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
523 }
524 }
525
526 /* Check we don't overflow when the destination extents are expanded by one.
527 * This ensures that compositing functions can simply walk the source space
528 * using 16.16 variables without worrying about overflow.
529 */
530 exp_extents = *extents;
531 exp_extents.x1 -= 1;
532 exp_extents.y1 -= 1;
533 exp_extents.x2 += 1;
534 exp_extents.y2 += 1;
535
536 if (!compute_transformed_extents (transform, &exp_extents, &transformed))
537 return FALSE;
538
539 if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e) ||
540 !IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e) ||
541 !IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width) ||
542 !IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
543 {
544 return FALSE;
545 }
546
547 return TRUE;
548 }
549
550 /*
551 * Work around GCC bug causing crashes in Mozilla with SSE2
552 *
553 * When using -msse, gcc generates movdqa instructions assuming that
554 * the stack is 16 byte aligned. Unfortunately some applications, such
555 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
556 * causes the movdqa instructions to fail.
557 *
558 * The __force_align_arg_pointer__ makes gcc generate a prologue that
559 * realigns the stack pointer to 16 bytes.
560 *
561 * On x86-64 this is not necessary because the standard ABI already
562 * calls for a 16 byte aligned stack.
563 *
564 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
565 */
566 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
567 __attribute__((__force_align_arg_pointer__))
568 #endif
569 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)570 pixman_image_composite32 (pixman_op_t op,
571 pixman_image_t * src,
572 pixman_image_t * mask,
573 pixman_image_t * dest,
574 int32_t src_x,
575 int32_t src_y,
576 int32_t mask_x,
577 int32_t mask_y,
578 int32_t dest_x,
579 int32_t dest_y,
580 int32_t width,
581 int32_t height)
582 {
583 pixman_format_code_t src_format, mask_format, dest_format;
584 pixman_region32_t region;
585 pixman_box32_t extents;
586 pixman_implementation_t *imp;
587 pixman_composite_func_t func;
588 pixman_composite_info_t info;
589 const pixman_box32_t *pbox;
590 int n;
591
592 _pixman_image_validate (src);
593 if (mask)
594 _pixman_image_validate (mask);
595 _pixman_image_validate (dest);
596
597 src_format = src->common.extended_format_code;
598 info.src_flags = src->common.flags;
599
600 if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE))
601 {
602 mask_format = mask->common.extended_format_code;
603 info.mask_flags = mask->common.flags;
604 }
605 else
606 {
607 mask_format = PIXMAN_null;
608 info.mask_flags = FAST_PATH_IS_OPAQUE;
609 }
610
611 dest_format = dest->common.extended_format_code;
612 info.dest_flags = dest->common.flags;
613
614 /* Check for pixbufs */
615 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
616 (src->type == BITS && src->bits.bits == mask->bits.bits) &&
617 (src->common.repeat == mask->common.repeat) &&
618 (info.src_flags & info.mask_flags & FAST_PATH_ID_TRANSFORM) &&
619 (src_x == mask_x && src_y == mask_y))
620 {
621 if (src_format == PIXMAN_x8b8g8r8)
622 src_format = mask_format = PIXMAN_pixbuf;
623 else if (src_format == PIXMAN_x8r8g8b8)
624 src_format = mask_format = PIXMAN_rpixbuf;
625 }
626
627 pixman_region32_init (®ion);
628
629 if (!_pixman_compute_composite_region32 (
630 ®ion, src, mask, dest,
631 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
632 {
633 goto out;
634 }
635
636 extents = *pixman_region32_extents (®ion);
637
638 extents.x1 -= dest_x - src_x;
639 extents.y1 -= dest_y - src_y;
640 extents.x2 -= dest_x - src_x;
641 extents.y2 -= dest_y - src_y;
642
643 if (!analyze_extent (src, &extents, &info.src_flags))
644 goto out;
645
646 extents.x1 -= src_x - mask_x;
647 extents.y1 -= src_y - mask_y;
648 extents.x2 -= src_x - mask_x;
649 extents.y2 -= src_y - mask_y;
650
651 if (!analyze_extent (mask, &extents, &info.mask_flags))
652 goto out;
653
654 /* If the clip is within the source samples, and the samples are
655 * opaque, then the source is effectively opaque.
656 */
657 #define NEAREST_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
658 FAST_PATH_NEAREST_FILTER | \
659 FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
660 #define BILINEAR_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
661 FAST_PATH_BILINEAR_FILTER | \
662 FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
663
664 if ((info.src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
665 (info.src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
666 {
667 info.src_flags |= FAST_PATH_IS_OPAQUE;
668 }
669
670 if ((info.mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
671 (info.mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
672 {
673 info.mask_flags |= FAST_PATH_IS_OPAQUE;
674 }
675
676 /*
677 * Check if we can replace our operator by a simpler one
678 * if the src or dest are opaque. The output operator should be
679 * mathematically equivalent to the source.
680 */
681 info.op = optimize_operator (op, info.src_flags, info.mask_flags, info.dest_flags);
682
683 _pixman_implementation_lookup_composite (
684 get_implementation (), info.op,
685 src_format, info.src_flags,
686 mask_format, info.mask_flags,
687 dest_format, info.dest_flags,
688 &imp, &func);
689
690 info.src_image = src;
691 info.mask_image = mask;
692 info.dest_image = dest;
693
694 pbox = pixman_region32_rectangles (®ion, &n);
695
696 while (n--)
697 {
698 info.src_x = pbox->x1 + src_x - dest_x;
699 info.src_y = pbox->y1 + src_y - dest_y;
700 info.mask_x = pbox->x1 + mask_x - dest_x;
701 info.mask_y = pbox->y1 + mask_y - dest_y;
702 info.dest_x = pbox->x1;
703 info.dest_y = pbox->y1;
704 info.width = pbox->x2 - pbox->x1;
705 info.height = pbox->y2 - pbox->y1;
706
707 func (imp, &info);
708
709 pbox++;
710 }
711
712 out:
713 pixman_region32_fini (®ion);
714 }
715
716 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)717 pixman_image_composite (pixman_op_t op,
718 pixman_image_t * src,
719 pixman_image_t * mask,
720 pixman_image_t * dest,
721 int16_t src_x,
722 int16_t src_y,
723 int16_t mask_x,
724 int16_t mask_y,
725 int16_t dest_x,
726 int16_t dest_y,
727 uint16_t width,
728 uint16_t height)
729 {
730 pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
731 mask_x, mask_y, dest_x, dest_y, width, height);
732 }
733
734 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)735 pixman_blt (uint32_t *src_bits,
736 uint32_t *dst_bits,
737 int src_stride,
738 int dst_stride,
739 int src_bpp,
740 int dst_bpp,
741 int src_x,
742 int src_y,
743 int dest_x,
744 int dest_y,
745 int width,
746 int height)
747 {
748 return _pixman_implementation_blt (get_implementation(),
749 src_bits, dst_bits, src_stride, dst_stride,
750 src_bpp, dst_bpp,
751 src_x, src_y,
752 dest_x, dest_y,
753 width, height);
754 }
755
756 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)757 pixman_fill (uint32_t *bits,
758 int stride,
759 int bpp,
760 int x,
761 int y,
762 int width,
763 int height,
764 uint32_t filler)
765 {
766 return _pixman_implementation_fill (
767 get_implementation(), bits, stride, bpp, x, y, width, height, filler);
768 }
769
770 static uint32_t
color_to_uint32(const pixman_color_t * color)771 color_to_uint32 (const pixman_color_t *color)
772 {
773 return
774 (color->alpha >> 8 << 24) |
775 (color->red >> 8 << 16) |
776 (color->green & 0xff00) |
777 (color->blue >> 8);
778 }
779
780 static pixman_bool_t
color_to_pixel(const pixman_color_t * color,uint32_t * pixel,pixman_format_code_t format)781 color_to_pixel (const pixman_color_t *color,
782 uint32_t * pixel,
783 pixman_format_code_t format)
784 {
785 uint32_t c = color_to_uint32 (color);
786
787 if (!(format == PIXMAN_a8r8g8b8 ||
788 format == PIXMAN_x8r8g8b8 ||
789 format == PIXMAN_a8b8g8r8 ||
790 format == PIXMAN_x8b8g8r8 ||
791 format == PIXMAN_b8g8r8a8 ||
792 format == PIXMAN_b8g8r8x8 ||
793 format == PIXMAN_r8g8b8a8 ||
794 format == PIXMAN_r8g8b8x8 ||
795 format == PIXMAN_r5g6b5 ||
796 format == PIXMAN_b5g6r5 ||
797 format == PIXMAN_a8 ||
798 format == PIXMAN_a1))
799 {
800 return FALSE;
801 }
802
803 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
804 {
805 c = ((c & 0xff000000) >> 0) |
806 ((c & 0x00ff0000) >> 16) |
807 ((c & 0x0000ff00) >> 0) |
808 ((c & 0x000000ff) << 16);
809 }
810 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
811 {
812 c = ((c & 0xff000000) >> 24) |
813 ((c & 0x00ff0000) >> 8) |
814 ((c & 0x0000ff00) << 8) |
815 ((c & 0x000000ff) << 24);
816 }
817 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
818 c = ((c & 0xff000000) >> 24) | (c << 8);
819
820 if (format == PIXMAN_a1)
821 c = c >> 31;
822 else if (format == PIXMAN_a8)
823 c = c >> 24;
824 else if (format == PIXMAN_r5g6b5 ||
825 format == PIXMAN_b5g6r5)
826 c = convert_8888_to_0565 (c);
827
828 #if 0
829 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
830 printf ("pixel: %x\n", c);
831 #endif
832
833 *pixel = c;
834 return TRUE;
835 }
836
837 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)838 pixman_image_fill_rectangles (pixman_op_t op,
839 pixman_image_t * dest,
840 const pixman_color_t * color,
841 int n_rects,
842 const pixman_rectangle16_t *rects)
843 {
844 pixman_box32_t stack_boxes[6];
845 pixman_box32_t *boxes;
846 pixman_bool_t result;
847 int i;
848
849 if (n_rects > 6)
850 {
851 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
852 if (boxes == NULL)
853 return FALSE;
854 }
855 else
856 {
857 boxes = stack_boxes;
858 }
859
860 for (i = 0; i < n_rects; ++i)
861 {
862 boxes[i].x1 = rects[i].x;
863 boxes[i].y1 = rects[i].y;
864 boxes[i].x2 = boxes[i].x1 + rects[i].width;
865 boxes[i].y2 = boxes[i].y1 + rects[i].height;
866 }
867
868 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
869
870 if (boxes != stack_boxes)
871 free (boxes);
872
873 return result;
874 }
875
876 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)877 pixman_image_fill_boxes (pixman_op_t op,
878 pixman_image_t * dest,
879 const pixman_color_t *color,
880 int n_boxes,
881 const pixman_box32_t *boxes)
882 {
883 pixman_image_t *solid;
884 pixman_color_t c;
885 int i;
886
887 _pixman_image_validate (dest);
888
889 if (color->alpha == 0xffff)
890 {
891 if (op == PIXMAN_OP_OVER)
892 op = PIXMAN_OP_SRC;
893 }
894
895 if (op == PIXMAN_OP_CLEAR)
896 {
897 c.red = 0;
898 c.green = 0;
899 c.blue = 0;
900 c.alpha = 0;
901
902 color = &c;
903
904 op = PIXMAN_OP_SRC;
905 }
906
907 if (op == PIXMAN_OP_SRC)
908 {
909 uint32_t pixel;
910
911 if (color_to_pixel (color, &pixel, dest->bits.format))
912 {
913 pixman_region32_t fill_region;
914 int n_rects, j;
915 pixman_box32_t *rects;
916
917 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
918 return FALSE;
919
920 if (dest->common.have_clip_region)
921 {
922 if (!pixman_region32_intersect (&fill_region,
923 &fill_region,
924 &dest->common.clip_region))
925 return FALSE;
926 }
927
928 rects = pixman_region32_rectangles (&fill_region, &n_rects);
929 for (j = 0; j < n_rects; ++j)
930 {
931 const pixman_box32_t *rect = &(rects[j]);
932 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
933 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
934 pixel);
935 }
936
937 pixman_region32_fini (&fill_region);
938 return TRUE;
939 }
940 }
941
942 solid = pixman_image_create_solid_fill (color);
943 if (!solid)
944 return FALSE;
945
946 for (i = 0; i < n_boxes; ++i)
947 {
948 const pixman_box32_t *box = &(boxes[i]);
949
950 pixman_image_composite32 (op, solid, NULL, dest,
951 0, 0, 0, 0,
952 box->x1, box->y1,
953 box->x2 - box->x1, box->y2 - box->y1);
954 }
955
956 pixman_image_unref (solid);
957
958 return TRUE;
959 }
960
961 /**
962 * pixman_version:
963 *
964 * Returns the version of the pixman library encoded in a single
965 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
966 * later versions compare greater than earlier versions.
967 *
968 * A run-time comparison to check that pixman's version is greater than
969 * or equal to version X.Y.Z could be performed as follows:
970 *
971 * <informalexample><programlisting>
972 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
973 * </programlisting></informalexample>
974 *
975 * See also pixman_version_string() as well as the compile-time
976 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
977 *
978 * Return value: the encoded version.
979 **/
980 PIXMAN_EXPORT int
pixman_version(void)981 pixman_version (void)
982 {
983 return PIXMAN_VERSION;
984 }
985
986 /**
987 * pixman_version_string:
988 *
989 * Returns the version of the pixman library as a human-readable string
990 * of the form "X.Y.Z".
991 *
992 * See also pixman_version() as well as the compile-time equivalents
993 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
994 *
995 * Return value: a string containing the version.
996 **/
997 PIXMAN_EXPORT const char*
pixman_version_string(void)998 pixman_version_string (void)
999 {
1000 return PIXMAN_VERSION_STRING;
1001 }
1002
1003 /**
1004 * pixman_format_supported_source:
1005 * @format: A pixman_format_code_t format
1006 *
1007 * Return value: whether the provided format code is a supported
1008 * format for a pixman surface used as a source in
1009 * rendering.
1010 *
1011 * Currently, all pixman_format_code_t values are supported.
1012 **/
1013 PIXMAN_EXPORT pixman_bool_t
pixman_format_supported_source(pixman_format_code_t format)1014 pixman_format_supported_source (pixman_format_code_t format)
1015 {
1016 switch (format)
1017 {
1018 /* 32 bpp formats */
1019 case PIXMAN_a2b10g10r10:
1020 case PIXMAN_x2b10g10r10:
1021 case PIXMAN_a2r10g10b10:
1022 case PIXMAN_x2r10g10b10:
1023 case PIXMAN_a8r8g8b8:
1024 case PIXMAN_a8r8g8b8_sRGB:
1025 case PIXMAN_x8r8g8b8:
1026 case PIXMAN_a8b8g8r8:
1027 case PIXMAN_x8b8g8r8:
1028 case PIXMAN_b8g8r8a8:
1029 case PIXMAN_b8g8r8x8:
1030 case PIXMAN_r8g8b8a8:
1031 case PIXMAN_r8g8b8x8:
1032 case PIXMAN_r8g8b8:
1033 case PIXMAN_b8g8r8:
1034 case PIXMAN_r5g6b5:
1035 case PIXMAN_b5g6r5:
1036 case PIXMAN_x14r6g6b6:
1037 /* 16 bpp formats */
1038 case PIXMAN_a1r5g5b5:
1039 case PIXMAN_x1r5g5b5:
1040 case PIXMAN_a1b5g5r5:
1041 case PIXMAN_x1b5g5r5:
1042 case PIXMAN_a4r4g4b4:
1043 case PIXMAN_x4r4g4b4:
1044 case PIXMAN_a4b4g4r4:
1045 case PIXMAN_x4b4g4r4:
1046 /* 8bpp formats */
1047 case PIXMAN_a8:
1048 case PIXMAN_r3g3b2:
1049 case PIXMAN_b2g3r3:
1050 case PIXMAN_a2r2g2b2:
1051 case PIXMAN_a2b2g2r2:
1052 case PIXMAN_c8:
1053 case PIXMAN_g8:
1054 case PIXMAN_x4a4:
1055 /* Collides with PIXMAN_c8
1056 case PIXMAN_x4c4:
1057 */
1058 /* Collides with PIXMAN_g8
1059 case PIXMAN_x4g4:
1060 */
1061 /* 4bpp formats */
1062 case PIXMAN_a4:
1063 case PIXMAN_r1g2b1:
1064 case PIXMAN_b1g2r1:
1065 case PIXMAN_a1r1g1b1:
1066 case PIXMAN_a1b1g1r1:
1067 case PIXMAN_c4:
1068 case PIXMAN_g4:
1069 /* 1bpp formats */
1070 case PIXMAN_a1:
1071 case PIXMAN_g1:
1072 /* YUV formats */
1073 case PIXMAN_yuy2:
1074 case PIXMAN_yv12:
1075 return TRUE;
1076
1077 default:
1078 return FALSE;
1079 }
1080 }
1081
1082 /**
1083 * pixman_format_supported_destination:
1084 * @format: A pixman_format_code_t format
1085 *
1086 * Return value: whether the provided format code is a supported
1087 * format for a pixman surface used as a destination in
1088 * rendering.
1089 *
1090 * Currently, all pixman_format_code_t values are supported
1091 * except for the YUV formats.
1092 **/
1093 PIXMAN_EXPORT pixman_bool_t
pixman_format_supported_destination(pixman_format_code_t format)1094 pixman_format_supported_destination (pixman_format_code_t format)
1095 {
1096 /* YUV formats cannot be written to at the moment */
1097 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1098 return FALSE;
1099
1100 return pixman_format_supported_source (format);
1101 }
1102
1103 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)1104 pixman_compute_composite_region (pixman_region16_t * region,
1105 pixman_image_t * src_image,
1106 pixman_image_t * mask_image,
1107 pixman_image_t * dest_image,
1108 int16_t src_x,
1109 int16_t src_y,
1110 int16_t mask_x,
1111 int16_t mask_y,
1112 int16_t dest_x,
1113 int16_t dest_y,
1114 uint16_t width,
1115 uint16_t height)
1116 {
1117 pixman_region32_t r32;
1118 pixman_bool_t retval;
1119
1120 pixman_region32_init (&r32);
1121
1122 retval = _pixman_compute_composite_region32 (
1123 &r32, src_image, mask_image, dest_image,
1124 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1125 width, height);
1126
1127 if (retval)
1128 {
1129 if (!pixman_region16_copy_from_region32 (region, &r32))
1130 retval = FALSE;
1131 }
1132
1133 pixman_region32_fini (&r32);
1134 return retval;
1135 }
1136