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 (®ion);
621
622 if (!_pixman_compute_composite_region32 (
623 ®ion, 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 (®ion);
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 (®ion, &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 (®ion);
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