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 static pixman_implementation_t *imp;
34
35 typedef struct operator_info_t operator_info_t;
36
37 struct operator_info_t
38 {
39 uint8_t opaque_info[4];
40 };
41
42 #define PACK(neither, src, dest, both) \
43 {{ (uint8_t)PIXMAN_OP_ ## neither, \
44 (uint8_t)PIXMAN_OP_ ## src, \
45 (uint8_t)PIXMAN_OP_ ## dest, \
46 (uint8_t)PIXMAN_OP_ ## both }}
47
48 static const operator_info_t operator_table[] =
49 {
50 /* Neither Opaque Src Opaque Dst Opaque Both Opaque */
51 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
52 PACK (SRC, SRC, SRC, SRC),
53 PACK (DST, DST, DST, DST),
54 PACK (OVER, SRC, OVER, SRC),
55 PACK (OVER_REVERSE, OVER_REVERSE, DST, DST),
56 PACK (IN, IN, SRC, SRC),
57 PACK (IN_REVERSE, DST, IN_REVERSE, DST),
58 PACK (OUT, OUT, CLEAR, CLEAR),
59 PACK (OUT_REVERSE, CLEAR, OUT_REVERSE, CLEAR),
60 PACK (ATOP, IN, OVER, SRC),
61 PACK (ATOP_REVERSE, OVER_REVERSE, IN_REVERSE, DST),
62 PACK (XOR, OUT, OUT_REVERSE, CLEAR),
63 PACK (ADD, ADD, ADD, ADD),
64 PACK (SATURATE, OVER_REVERSE, DST, DST),
65
66 {{ 0 /* 0x0e */ }},
67 {{ 0 /* 0x0f */ }},
68
69 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
70 PACK (SRC, SRC, SRC, SRC),
71 PACK (DST, DST, DST, DST),
72 PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER),
73 PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
74 PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN),
75 PACK (DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE),
76 PACK (DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT),
77 PACK (DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE),
78 PACK (DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP),
79 PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
80 PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR),
81
82 {{ 0 /* 0x1c */ }},
83 {{ 0 /* 0x1d */ }},
84 {{ 0 /* 0x1e */ }},
85 {{ 0 /* 0x1f */ }},
86
87 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
88 PACK (SRC, SRC, SRC, SRC),
89 PACK (DST, DST, DST, DST),
90 PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER),
91 PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
92 PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN),
93 PACK (CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE),
94 PACK (CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT),
95 PACK (CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE),
96 PACK (CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP),
97 PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
98 PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR),
99
100 {{ 0 /* 0x2c */ }},
101 {{ 0 /* 0x2d */ }},
102 {{ 0 /* 0x2e */ }},
103 {{ 0 /* 0x2f */ }},
104
105 PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY),
106 PACK (SCREEN, SCREEN, SCREEN, SCREEN),
107 PACK (OVERLAY, OVERLAY, OVERLAY, OVERLAY),
108 PACK (DARKEN, DARKEN, DARKEN, DARKEN),
109 PACK (LIGHTEN, LIGHTEN, LIGHTEN, LIGHTEN),
110 PACK (COLOR_DODGE, COLOR_DODGE, COLOR_DODGE, COLOR_DODGE),
111 PACK (COLOR_BURN, COLOR_BURN, COLOR_BURN, COLOR_BURN),
112 PACK (HARD_LIGHT, HARD_LIGHT, HARD_LIGHT, HARD_LIGHT),
113 PACK (SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT),
114 PACK (DIFFERENCE, DIFFERENCE, DIFFERENCE, DIFFERENCE),
115 PACK (EXCLUSION, EXCLUSION, EXCLUSION, EXCLUSION),
116 PACK (HSL_HUE, HSL_HUE, HSL_HUE, HSL_HUE),
117 PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION),
118 PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR),
119 PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY),
120 };
121
122 /*
123 * Optimize the current operator based on opacity of source or destination
124 * The output operator should be mathematically equivalent to the source.
125 */
126 static pixman_op_t
optimize_operator(pixman_op_t op,uint32_t src_flags,uint32_t mask_flags,uint32_t dst_flags)127 optimize_operator (pixman_op_t op,
128 uint32_t src_flags,
129 uint32_t mask_flags,
130 uint32_t dst_flags)
131 {
132 pixman_bool_t is_source_opaque, is_dest_opaque;
133 int opaqueness;
134
135 is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0;
136 is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0;
137
138 opaqueness = ((is_dest_opaque << 1) | is_source_opaque);
139
140 return operator_table[op].opaque_info[opaqueness];
141 }
142
143 static void
apply_workaround(pixman_image_t * image,int32_t * x,int32_t * y,uint32_t ** save_bits,int * save_dx,int * save_dy)144 apply_workaround (pixman_image_t *image,
145 int32_t * x,
146 int32_t * y,
147 uint32_t ** save_bits,
148 int * save_dx,
149 int * save_dy)
150 {
151 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
152 {
153 /* Some X servers generate images that point to the
154 * wrong place in memory, but then set the clip region
155 * to point to the right place. Because of an old bug
156 * in pixman, this would actually work.
157 *
158 * Here we try and undo the damage
159 */
160 int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
161 pixman_box32_t *extents;
162 uint8_t *t;
163 int dx, dy;
164
165 extents = pixman_region32_extents (&(image->common.clip_region));
166 dx = extents->x1;
167 dy = extents->y1;
168
169 *save_bits = image->bits.bits;
170
171 *x -= dx;
172 *y -= dy;
173 pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
174
175 t = (uint8_t *)image->bits.bits;
176 t += dy * image->bits.rowstride * 4 + dx * bpp;
177 image->bits.bits = (uint32_t *)t;
178
179 *save_dx = dx;
180 *save_dy = dy;
181 }
182 }
183
184 static void
unapply_workaround(pixman_image_t * image,uint32_t * bits,int dx,int dy)185 unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
186 {
187 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
188 {
189 image->bits.bits = bits;
190 pixman_region32_translate (&image->common.clip_region, dx, dy);
191 }
192 }
193
194 /*
195 * Computing composite region
196 */
197 static inline pixman_bool_t
clip_general_image(pixman_region32_t * region,pixman_region32_t * clip,int dx,int dy)198 clip_general_image (pixman_region32_t * region,
199 pixman_region32_t * clip,
200 int dx,
201 int dy)
202 {
203 if (pixman_region32_n_rects (region) == 1 &&
204 pixman_region32_n_rects (clip) == 1)
205 {
206 pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL);
207 pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL);
208 int v;
209
210 if (rbox->x1 < (v = cbox->x1 + dx))
211 rbox->x1 = v;
212 if (rbox->x2 > (v = cbox->x2 + dx))
213 rbox->x2 = v;
214 if (rbox->y1 < (v = cbox->y1 + dy))
215 rbox->y1 = v;
216 if (rbox->y2 > (v = cbox->y2 + dy))
217 rbox->y2 = v;
218 if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
219 {
220 pixman_region32_init (region);
221 return FALSE;
222 }
223 }
224 else if (!pixman_region32_not_empty (clip))
225 {
226 return FALSE;
227 }
228 else
229 {
230 if (dx || dy)
231 pixman_region32_translate (region, -dx, -dy);
232
233 if (!pixman_region32_intersect (region, region, clip))
234 return FALSE;
235
236 if (dx || dy)
237 pixman_region32_translate (region, dx, dy);
238 }
239
240 return pixman_region32_not_empty (region);
241 }
242
243 static inline pixman_bool_t
clip_source_image(pixman_region32_t * region,pixman_image_t * image,int dx,int dy)244 clip_source_image (pixman_region32_t * region,
245 pixman_image_t * image,
246 int dx,
247 int dy)
248 {
249 /* Source clips are ignored, unless they are explicitly turned on
250 * and the clip in question was set by an X client. (Because if
251 * the clip was not set by a client, then it is a hierarchy
252 * clip and those should always be ignored for sources).
253 */
254 if (!image->common.clip_sources || !image->common.client_clip)
255 return TRUE;
256
257 return clip_general_image (region,
258 &image->common.clip_region,
259 dx, dy);
260 }
261
262 /*
263 * returns FALSE if the final region is empty. Indistinguishable from
264 * an allocation failure, but rendering ignores those anyways.
265 */
266 static pixman_bool_t
pixman_compute_composite_region32(pixman_region32_t * region,pixman_image_t * src_image,pixman_image_t * mask_image,pixman_image_t * dst_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)267 pixman_compute_composite_region32 (pixman_region32_t * region,
268 pixman_image_t * src_image,
269 pixman_image_t * mask_image,
270 pixman_image_t * dst_image,
271 int32_t src_x,
272 int32_t src_y,
273 int32_t mask_x,
274 int32_t mask_y,
275 int32_t dest_x,
276 int32_t dest_y,
277 int32_t width,
278 int32_t height)
279 {
280 region->extents.x1 = dest_x;
281 region->extents.x2 = dest_x + width;
282 region->extents.y1 = dest_y;
283 region->extents.y2 = dest_y + height;
284
285 region->extents.x1 = MAX (region->extents.x1, 0);
286 region->extents.y1 = MAX (region->extents.y1, 0);
287 region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
288 region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
289
290 region->data = 0;
291
292 /* Check for empty operation */
293 if (region->extents.x1 >= region->extents.x2 ||
294 region->extents.y1 >= region->extents.y2)
295 {
296 pixman_region32_init (region);
297 return FALSE;
298 }
299
300 if (dst_image->common.have_clip_region)
301 {
302 if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
303 {
304 pixman_region32_fini (region);
305 return FALSE;
306 }
307 }
308
309 if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
310 {
311 if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
312 -dst_image->common.alpha_origin_x,
313 -dst_image->common.alpha_origin_y))
314 {
315 pixman_region32_fini (region);
316 return FALSE;
317 }
318 }
319
320 /* clip against src */
321 if (src_image->common.have_clip_region)
322 {
323 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
324 {
325 pixman_region32_fini (region);
326 return FALSE;
327 }
328 }
329 if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
330 {
331 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
332 dest_x - (src_x - src_image->common.alpha_origin_x),
333 dest_y - (src_y - src_image->common.alpha_origin_y)))
334 {
335 pixman_region32_fini (region);
336 return FALSE;
337 }
338 }
339 /* clip against mask */
340 if (mask_image && mask_image->common.have_clip_region)
341 {
342 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
343 {
344 pixman_region32_fini (region);
345 return FALSE;
346 }
347 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
348 {
349 if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
350 dest_x - (mask_x - mask_image->common.alpha_origin_x),
351 dest_y - (mask_y - mask_image->common.alpha_origin_y)))
352 {
353 pixman_region32_fini (region);
354 return FALSE;
355 }
356 }
357 }
358
359 return TRUE;
360 }
361
362 static void
walk_region_internal(pixman_implementation_t * imp,pixman_op_t op,pixman_image_t * src_image,pixman_image_t * mask_image,pixman_image_t * dst_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,pixman_bool_t src_repeat,pixman_bool_t mask_repeat,pixman_region32_t * region,pixman_composite_func_t composite_rect)363 walk_region_internal (pixman_implementation_t *imp,
364 pixman_op_t op,
365 pixman_image_t * src_image,
366 pixman_image_t * mask_image,
367 pixman_image_t * dst_image,
368 int32_t src_x,
369 int32_t src_y,
370 int32_t mask_x,
371 int32_t mask_y,
372 int32_t dest_x,
373 int32_t dest_y,
374 int32_t width,
375 int32_t height,
376 pixman_bool_t src_repeat,
377 pixman_bool_t mask_repeat,
378 pixman_region32_t * region,
379 pixman_composite_func_t composite_rect)
380 {
381 int w, h, w_this, h_this;
382 int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
383 int src_dy = src_y - dest_y;
384 int src_dx = src_x - dest_x;
385 int mask_dy = mask_y - dest_y;
386 int mask_dx = mask_x - dest_x;
387 const pixman_box32_t *pbox;
388 int n;
389
390 pbox = pixman_region32_rectangles (region, &n);
391
392 /* Fast path for non-repeating sources */
393 if (!src_repeat && !mask_repeat)
394 {
395 while (n--)
396 {
397 (*composite_rect) (imp, op,
398 src_image, mask_image, dst_image,
399 pbox->x1 + src_dx,
400 pbox->y1 + src_dy,
401 pbox->x1 + mask_dx,
402 pbox->y1 + mask_dy,
403 pbox->x1,
404 pbox->y1,
405 pbox->x2 - pbox->x1,
406 pbox->y2 - pbox->y1);
407
408 pbox++;
409 }
410
411 return;
412 }
413
414 while (n--)
415 {
416 h = pbox->y2 - pbox->y1;
417 y_src = pbox->y1 + src_dy;
418 y_msk = pbox->y1 + mask_dy;
419 y_dst = pbox->y1;
420
421 while (h)
422 {
423 h_this = h;
424 w = pbox->x2 - pbox->x1;
425 x_src = pbox->x1 + src_dx;
426 x_msk = pbox->x1 + mask_dx;
427 x_dst = pbox->x1;
428
429 if (mask_repeat)
430 {
431 y_msk = MOD (y_msk, mask_image->bits.height);
432 if (h_this > mask_image->bits.height - y_msk)
433 h_this = mask_image->bits.height - y_msk;
434 }
435
436 if (src_repeat)
437 {
438 y_src = MOD (y_src, src_image->bits.height);
439 if (h_this > src_image->bits.height - y_src)
440 h_this = src_image->bits.height - y_src;
441 }
442
443 while (w)
444 {
445 w_this = w;
446
447 if (mask_repeat)
448 {
449 x_msk = MOD (x_msk, mask_image->bits.width);
450 if (w_this > mask_image->bits.width - x_msk)
451 w_this = mask_image->bits.width - x_msk;
452 }
453
454 if (src_repeat)
455 {
456 x_src = MOD (x_src, src_image->bits.width);
457 if (w_this > src_image->bits.width - x_src)
458 w_this = src_image->bits.width - x_src;
459 }
460
461 (*composite_rect) (imp, op,
462 src_image, mask_image, dst_image,
463 x_src, y_src, x_msk, y_msk, x_dst, y_dst,
464 w_this, h_this);
465 w -= w_this;
466
467 x_src += w_this;
468 x_msk += w_this;
469 x_dst += w_this;
470 }
471
472 h -= h_this;
473 y_src += h_this;
474 y_msk += h_this;
475 y_dst += h_this;
476 }
477
478 pbox++;
479 }
480 }
481
482 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
483
484 static force_inline uint32_t
compute_src_extents_flags(pixman_image_t * image,pixman_box32_t * extents,int x,int y)485 compute_src_extents_flags (pixman_image_t *image,
486 pixman_box32_t *extents,
487 int x,
488 int y)
489 {
490 pixman_box16_t extents16;
491 uint32_t flags;
492
493 flags = FAST_PATH_COVERS_CLIP;
494
495 if (image->common.type != BITS)
496 return flags;
497
498 if (image->common.repeat == PIXMAN_REPEAT_NONE &&
499 (x > extents->x1 || y > extents->y1 ||
500 x + image->bits.width < extents->x2 ||
501 y + image->bits.height < extents->y2))
502 {
503 flags &= ~FAST_PATH_COVERS_CLIP;
504 }
505
506 if (IS_16BIT (extents->x1 - x) &&
507 IS_16BIT (extents->y1 - y) &&
508 IS_16BIT (extents->x2 - x) &&
509 IS_16BIT (extents->y2 - y))
510 {
511 extents16.x1 = extents->x1 - x;
512 extents16.y1 = extents->y1 - y;
513 extents16.x2 = extents->x2 - x;
514 extents16.y2 = extents->y2 - y;
515
516 if (!image->common.transform ||
517 pixman_transform_bounds (image->common.transform, &extents16))
518 {
519 if (extents16.x1 >= 0 && extents16.y1 >= 0 &&
520 extents16.x2 <= image->bits.width &&
521 extents16.y2 <= image->bits.height)
522 {
523 flags |= FAST_PATH_SAMPLES_COVER_CLIP;
524 }
525 }
526 }
527
528 if (IS_16BIT (extents->x1 - x - 1) &&
529 IS_16BIT (extents->y1 - y - 1) &&
530 IS_16BIT (extents->x2 - x + 1) &&
531 IS_16BIT (extents->y2 - y + 1))
532 {
533 extents16.x1 = extents->x1 - x - 1;
534 extents16.y1 = extents->y1 - y - 1;
535 extents16.x2 = extents->x2 - x + 1;
536 extents16.y2 = extents->y2 - y + 1;
537
538 if (/* src space expanded by one in dest space fits in 16 bit */
539 (!image->common.transform ||
540 pixman_transform_bounds (image->common.transform, &extents16)) &&
541 /* And src image size can be used as 16.16 fixed point */
542 image->bits.width < 0x7fff &&
543 image->bits.height < 0x7fff)
544 {
545 /* Then we're "16bit safe" */
546 flags |= FAST_PATH_16BIT_SAFE;
547 }
548 }
549
550 return flags;
551 }
552
553 #define N_CACHED_FAST_PATHS 8
554
555 typedef struct
556 {
557 pixman_fast_path_t cache [N_CACHED_FAST_PATHS];
558 } cache_t;
559
560 PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
561
562 static void
do_composite(pixman_implementation_t * imp,pixman_op_t op,pixman_image_t * src,pixman_image_t * mask,pixman_image_t * dest,int src_x,int src_y,int mask_x,int mask_y,int dest_x,int dest_y,int width,int height)563 do_composite (pixman_implementation_t *imp,
564 pixman_op_t op,
565 pixman_image_t *src,
566 pixman_image_t *mask,
567 pixman_image_t *dest,
568 int src_x,
569 int src_y,
570 int mask_x,
571 int mask_y,
572 int dest_x,
573 int dest_y,
574 int width,
575 int height)
576 {
577 pixman_format_code_t src_format, mask_format, dest_format;
578 uint32_t src_flags, mask_flags, dest_flags;
579 pixman_region32_t region;
580 pixman_box32_t *extents;
581 uint32_t *src_bits;
582 int src_dx, src_dy;
583 uint32_t *mask_bits;
584 int mask_dx, mask_dy;
585 uint32_t *dest_bits;
586 int dest_dx, dest_dy;
587 pixman_bool_t need_workaround;
588 const pixman_fast_path_t *info;
589 cache_t *cache;
590 int i;
591
592 src_format = src->common.extended_format_code;
593 src_flags = src->common.flags;
594
595 if (mask)
596 {
597 mask_format = mask->common.extended_format_code;
598 mask_flags = mask->common.flags;
599 }
600 else
601 {
602 mask_format = PIXMAN_null;
603 mask_flags = FAST_PATH_IS_OPAQUE;
604 }
605
606 dest_format = dest->common.extended_format_code;
607 dest_flags = dest->common.flags;
608
609 /* Check for pixbufs */
610 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
611 (src->type == BITS && src->bits.bits == mask->bits.bits) &&
612 (src->common.repeat == mask->common.repeat) &&
613 (src_x == mask_x && src_y == mask_y))
614 {
615 if (src_format == PIXMAN_x8b8g8r8)
616 src_format = mask_format = PIXMAN_pixbuf;
617 else if (src_format == PIXMAN_x8r8g8b8)
618 src_format = mask_format = PIXMAN_rpixbuf;
619 }
620
621 /* Check for workaround */
622 need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
623
624 if (need_workaround)
625 {
626 apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
627 apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
628 apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
629 }
630
631 pixman_region32_init (®ion);
632
633 if (!pixman_compute_composite_region32 (
634 ®ion, src, mask, dest,
635 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
636 {
637 goto out;
638 }
639
640 extents = pixman_region32_extents (®ion);
641
642 src_flags |= compute_src_extents_flags (src, extents, dest_x - src_x, dest_y - src_y);
643
644 if (mask)
645 mask_flags |= compute_src_extents_flags (mask, extents, dest_x - mask_x, dest_y - mask_y);
646
647 /*
648 * Check if we can replace our operator by a simpler one
649 * if the src or dest are opaque. The output operator should be
650 * mathematically equivalent to the source.
651 */
652 op = optimize_operator (op, src_flags, mask_flags, dest_flags);
653 if (op == PIXMAN_OP_DST)
654 goto out;
655
656 /* Check cache for fast paths */
657 cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
658
659 for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
660 {
661 info = &(cache->cache[i]);
662
663 /* Note that we check for equality here, not whether
664 * the cached fast path matches. This is to prevent
665 * us from selecting an overly general fast path
666 * when a more specific one would work.
667 */
668 if (info->op == op &&
669 info->src_format == src_format &&
670 info->mask_format == mask_format &&
671 info->dest_format == dest_format &&
672 info->src_flags == src_flags &&
673 info->mask_flags == mask_flags &&
674 info->dest_flags == dest_flags &&
675 info->func)
676 {
677 goto found;
678 }
679 }
680
681 while (imp)
682 {
683 info = imp->fast_paths;
684
685 while (info->op != PIXMAN_OP_NONE)
686 {
687 if ((info->op == op || info->op == PIXMAN_OP_any) &&
688 /* Formats */
689 ((info->src_format == src_format) ||
690 (info->src_format == PIXMAN_any)) &&
691 ((info->mask_format == mask_format) ||
692 (info->mask_format == PIXMAN_any)) &&
693 ((info->dest_format == dest_format) ||
694 (info->dest_format == PIXMAN_any)) &&
695 /* Flags */
696 (info->src_flags & src_flags) == info->src_flags &&
697 (info->mask_flags & mask_flags) == info->mask_flags &&
698 (info->dest_flags & dest_flags) == info->dest_flags)
699 {
700 /* Set i to the last spot in the cache so that the
701 * move-to-front code below will work
702 */
703 i = N_CACHED_FAST_PATHS - 1;
704
705 goto found;
706 }
707
708 ++info;
709 }
710
711 imp = imp->delegate;
712 }
713
714 /* We didn't find a compositing routine. This should not happen, but if
715 * it somehow does, just exit rather than crash.
716 */
717 goto out;
718
719 found:
720 walk_region_internal (imp, op,
721 src, mask, dest,
722 src_x, src_y, mask_x, mask_y,
723 dest_x, dest_y,
724 width, height,
725 (src_flags & FAST_PATH_SIMPLE_REPEAT),
726 (mask_flags & FAST_PATH_SIMPLE_REPEAT),
727 ®ion, info->func);
728
729 if (i)
730 {
731 /* Make a copy of info->func, because info->func may change when
732 * we update the cache.
733 */
734 pixman_composite_func_t func = info->func;
735
736 while (i--)
737 cache->cache[i + 1] = cache->cache[i];
738
739 cache->cache[0].op = op;
740 cache->cache[0].src_format = src_format;
741 cache->cache[0].src_flags = src_flags;
742 cache->cache[0].mask_format = mask_format;
743 cache->cache[0].mask_flags = mask_flags;
744 cache->cache[0].dest_format = dest_format;
745 cache->cache[0].dest_flags = dest_flags;
746 cache->cache[0].func = func;
747 }
748
749 out:
750 if (need_workaround)
751 {
752 unapply_workaround (src, src_bits, src_dx, src_dy);
753 unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
754 unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
755 }
756
757 pixman_region32_fini (®ion);
758 }
759
760 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)761 pixman_image_composite (pixman_op_t op,
762 pixman_image_t * src,
763 pixman_image_t * mask,
764 pixman_image_t * dest,
765 int16_t src_x,
766 int16_t src_y,
767 int16_t mask_x,
768 int16_t mask_y,
769 int16_t dest_x,
770 int16_t dest_y,
771 uint16_t width,
772 uint16_t height)
773 {
774 pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
775 mask_x, mask_y, dest_x, dest_y, width, height);
776 }
777
778 /*
779 * Work around GCC bug causing crashes in Mozilla with SSE2
780 *
781 * When using -msse, gcc generates movdqa instructions assuming that
782 * the stack is 16 byte aligned. Unfortunately some applications, such
783 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
784 * causes the movdqa instructions to fail.
785 *
786 * The __force_align_arg_pointer__ makes gcc generate a prologue that
787 * realigns the stack pointer to 16 bytes.
788 *
789 * On x86-64 this is not necessary because the standard ABI already
790 * calls for a 16 byte aligned stack.
791 *
792 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
793 */
794 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
795 __attribute__((__force_align_arg_pointer__))
796 #endif
797 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)798 pixman_image_composite32 (pixman_op_t op,
799 pixman_image_t * src,
800 pixman_image_t * mask,
801 pixman_image_t * dest,
802 int32_t src_x,
803 int32_t src_y,
804 int32_t mask_x,
805 int32_t mask_y,
806 int32_t dest_x,
807 int32_t dest_y,
808 int32_t width,
809 int32_t height)
810 {
811 _pixman_image_validate (src);
812 if (mask)
813 _pixman_image_validate (mask);
814 _pixman_image_validate (dest);
815
816 if (!imp)
817 imp = _pixman_choose_implementation ();
818
819 do_composite (imp, op,
820 src, mask, dest,
821 src_x, src_y,
822 mask_x, mask_y,
823 dest_x, dest_y,
824 width, height);
825 }
826
827 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 dst_x,int dst_y,int width,int height)828 pixman_blt (uint32_t *src_bits,
829 uint32_t *dst_bits,
830 int src_stride,
831 int dst_stride,
832 int src_bpp,
833 int dst_bpp,
834 int src_x,
835 int src_y,
836 int dst_x,
837 int dst_y,
838 int width,
839 int height)
840 {
841 if (!imp)
842 imp = _pixman_choose_implementation ();
843
844 return _pixman_implementation_blt (imp, src_bits, dst_bits, src_stride, dst_stride,
845 src_bpp, dst_bpp,
846 src_x, src_y,
847 dst_x, dst_y,
848 width, height);
849 }
850
851 PIXMAN_EXPORT pixman_bool_t
pixman_fill(uint32_t * bits,int stride,int bpp,int x,int y,int width,int height,uint32_t xor)852 pixman_fill (uint32_t *bits,
853 int stride,
854 int bpp,
855 int x,
856 int y,
857 int width,
858 int height,
859 uint32_t xor)
860 {
861 if (!imp)
862 imp = _pixman_choose_implementation ();
863
864 return _pixman_implementation_fill (imp, bits, stride, bpp, x, y, width, height, xor);
865 }
866
867 static uint32_t
color_to_uint32(const pixman_color_t * color)868 color_to_uint32 (const pixman_color_t *color)
869 {
870 return
871 (color->alpha >> 8 << 24) |
872 (color->red >> 8 << 16) |
873 (color->green & 0xff00) |
874 (color->blue >> 8);
875 }
876
877 static pixman_bool_t
color_to_pixel(pixman_color_t * color,uint32_t * pixel,pixman_format_code_t format)878 color_to_pixel (pixman_color_t * color,
879 uint32_t * pixel,
880 pixman_format_code_t format)
881 {
882 uint32_t c = color_to_uint32 (color);
883
884 if (!(format == PIXMAN_a8r8g8b8 ||
885 format == PIXMAN_x8r8g8b8 ||
886 format == PIXMAN_a8b8g8r8 ||
887 format == PIXMAN_x8b8g8r8 ||
888 format == PIXMAN_b8g8r8a8 ||
889 format == PIXMAN_b8g8r8x8 ||
890 format == PIXMAN_r5g6b5 ||
891 format == PIXMAN_b5g6r5 ||
892 format == PIXMAN_a8))
893 {
894 return FALSE;
895 }
896
897 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
898 {
899 c = ((c & 0xff000000) >> 0) |
900 ((c & 0x00ff0000) >> 16) |
901 ((c & 0x0000ff00) >> 0) |
902 ((c & 0x000000ff) << 16);
903 }
904 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
905 {
906 c = ((c & 0xff000000) >> 24) |
907 ((c & 0x00ff0000) >> 8) |
908 ((c & 0x0000ff00) << 8) |
909 ((c & 0x000000ff) << 24);
910 }
911
912 if (format == PIXMAN_a8)
913 c = c >> 24;
914 else if (format == PIXMAN_r5g6b5 ||
915 format == PIXMAN_b5g6r5)
916 c = CONVERT_8888_TO_0565 (c);
917
918 #if 0
919 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
920 printf ("pixel: %x\n", c);
921 #endif
922
923 *pixel = c;
924 return TRUE;
925 }
926
927 PIXMAN_EXPORT pixman_bool_t
pixman_image_fill_rectangles(pixman_op_t op,pixman_image_t * dest,pixman_color_t * color,int n_rects,const pixman_rectangle16_t * rects)928 pixman_image_fill_rectangles (pixman_op_t op,
929 pixman_image_t * dest,
930 pixman_color_t * color,
931 int n_rects,
932 const pixman_rectangle16_t *rects)
933 {
934 pixman_box32_t stack_boxes[6];
935 pixman_box32_t *boxes;
936 pixman_bool_t result;
937 int i;
938
939 if (n_rects > 6)
940 {
941 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
942 if (boxes == NULL)
943 return FALSE;
944 }
945 else
946 {
947 boxes = stack_boxes;
948 }
949
950 for (i = 0; i < n_rects; ++i)
951 {
952 boxes[i].x1 = rects[i].x;
953 boxes[i].y1 = rects[i].y;
954 boxes[i].x2 = boxes[i].x1 + rects[i].width;
955 boxes[i].y2 = boxes[i].y1 + rects[i].height;
956 }
957
958 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
959
960 if (boxes != stack_boxes)
961 free (boxes);
962
963 return result;
964 }
965
966 PIXMAN_EXPORT pixman_bool_t
pixman_image_fill_boxes(pixman_op_t op,pixman_image_t * dest,pixman_color_t * color,int n_boxes,const pixman_box32_t * boxes)967 pixman_image_fill_boxes (pixman_op_t op,
968 pixman_image_t * dest,
969 pixman_color_t * color,
970 int n_boxes,
971 const pixman_box32_t *boxes)
972 {
973 pixman_image_t *solid;
974 pixman_color_t c;
975 int i;
976
977 _pixman_image_validate (dest);
978
979 if (color->alpha == 0xffff)
980 {
981 if (op == PIXMAN_OP_OVER)
982 op = PIXMAN_OP_SRC;
983 }
984
985 if (op == PIXMAN_OP_CLEAR)
986 {
987 c.red = 0;
988 c.green = 0;
989 c.blue = 0;
990 c.alpha = 0;
991
992 color = &c;
993
994 op = PIXMAN_OP_SRC;
995 }
996
997 if (op == PIXMAN_OP_SRC)
998 {
999 uint32_t pixel;
1000
1001 if (color_to_pixel (color, &pixel, dest->bits.format))
1002 {
1003 pixman_region32_t fill_region;
1004 int n_rects, j;
1005 pixman_box32_t *rects;
1006
1007 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
1008 return FALSE;
1009
1010 if (dest->common.have_clip_region)
1011 {
1012 if (!pixman_region32_intersect (&fill_region,
1013 &fill_region,
1014 &dest->common.clip_region))
1015 return FALSE;
1016 }
1017
1018 rects = pixman_region32_rectangles (&fill_region, &n_rects);
1019 for (j = 0; j < n_rects; ++j)
1020 {
1021 const pixman_box32_t *rect = &(rects[j]);
1022 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
1023 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
1024 pixel);
1025 }
1026
1027 pixman_region32_fini (&fill_region);
1028 return TRUE;
1029 }
1030 }
1031
1032 solid = pixman_image_create_solid_fill (color);
1033 if (!solid)
1034 return FALSE;
1035
1036 for (i = 0; i < n_boxes; ++i)
1037 {
1038 const pixman_box32_t *box = &(boxes[i]);
1039
1040 pixman_image_composite32 (op, solid, NULL, dest,
1041 0, 0, 0, 0,
1042 box->x1, box->y1,
1043 box->x2 - box->x1, box->y2 - box->y1);
1044 }
1045
1046 pixman_image_unref (solid);
1047
1048 return TRUE;
1049 }
1050
1051 /**
1052 * pixman_version:
1053 *
1054 * Returns the version of the pixman library encoded in a single
1055 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
1056 * later versions compare greater than earlier versions.
1057 *
1058 * A run-time comparison to check that pixman's version is greater than
1059 * or equal to version X.Y.Z could be performed as follows:
1060 *
1061 * <informalexample><programlisting>
1062 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1063 * </programlisting></informalexample>
1064 *
1065 * See also pixman_version_string() as well as the compile-time
1066 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1067 *
1068 * Return value: the encoded version.
1069 **/
1070 PIXMAN_EXPORT int
pixman_version(void)1071 pixman_version (void)
1072 {
1073 return PIXMAN_VERSION;
1074 }
1075
1076 /**
1077 * pixman_version_string:
1078 *
1079 * Returns the version of the pixman library as a human-readable string
1080 * of the form "X.Y.Z".
1081 *
1082 * See also pixman_version() as well as the compile-time equivalents
1083 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1084 *
1085 * Return value: a string containing the version.
1086 **/
1087 PIXMAN_EXPORT const char*
pixman_version_string(void)1088 pixman_version_string (void)
1089 {
1090 return PIXMAN_VERSION_STRING;
1091 }
1092
1093 /**
1094 * pixman_format_supported_source:
1095 * @format: A pixman_format_code_t format
1096 *
1097 * Return value: whether the provided format code is a supported
1098 * format for a pixman surface used as a source in
1099 * rendering.
1100 *
1101 * Currently, all pixman_format_code_t values are supported.
1102 **/
1103 PIXMAN_EXPORT pixman_bool_t
pixman_format_supported_source(pixman_format_code_t format)1104 pixman_format_supported_source (pixman_format_code_t format)
1105 {
1106 switch (format)
1107 {
1108 /* 32 bpp formats */
1109 case PIXMAN_a2b10g10r10:
1110 case PIXMAN_x2b10g10r10:
1111 case PIXMAN_a2r10g10b10:
1112 case PIXMAN_x2r10g10b10:
1113 case PIXMAN_a8r8g8b8:
1114 case PIXMAN_x8r8g8b8:
1115 case PIXMAN_a8b8g8r8:
1116 case PIXMAN_x8b8g8r8:
1117 case PIXMAN_b8g8r8a8:
1118 case PIXMAN_b8g8r8x8:
1119 case PIXMAN_r8g8b8:
1120 case PIXMAN_b8g8r8:
1121 case PIXMAN_r5g6b5:
1122 case PIXMAN_b5g6r5:
1123 /* 16 bpp formats */
1124 case PIXMAN_a1r5g5b5:
1125 case PIXMAN_x1r5g5b5:
1126 case PIXMAN_a1b5g5r5:
1127 case PIXMAN_x1b5g5r5:
1128 case PIXMAN_a4r4g4b4:
1129 case PIXMAN_x4r4g4b4:
1130 case PIXMAN_a4b4g4r4:
1131 case PIXMAN_x4b4g4r4:
1132 /* 8bpp formats */
1133 case PIXMAN_a8:
1134 case PIXMAN_r3g3b2:
1135 case PIXMAN_b2g3r3:
1136 case PIXMAN_a2r2g2b2:
1137 case PIXMAN_a2b2g2r2:
1138 case PIXMAN_c8:
1139 case PIXMAN_g8:
1140 case PIXMAN_x4a4:
1141 /* Collides with PIXMAN_c8
1142 case PIXMAN_x4c4:
1143 */
1144 /* Collides with PIXMAN_g8
1145 case PIXMAN_x4g4:
1146 */
1147 /* 4bpp formats */
1148 case PIXMAN_a4:
1149 case PIXMAN_r1g2b1:
1150 case PIXMAN_b1g2r1:
1151 case PIXMAN_a1r1g1b1:
1152 case PIXMAN_a1b1g1r1:
1153 case PIXMAN_c4:
1154 case PIXMAN_g4:
1155 /* 1bpp formats */
1156 case PIXMAN_a1:
1157 case PIXMAN_g1:
1158 /* YUV formats */
1159 case PIXMAN_yuy2:
1160 case PIXMAN_yv12:
1161 return TRUE;
1162
1163 default:
1164 return FALSE;
1165 }
1166 }
1167
1168 /**
1169 * pixman_format_supported_destination:
1170 * @format: A pixman_format_code_t format
1171 *
1172 * Return value: whether the provided format code is a supported
1173 * format for a pixman surface used as a destination in
1174 * rendering.
1175 *
1176 * Currently, all pixman_format_code_t values are supported
1177 * except for the YUV formats.
1178 **/
1179 PIXMAN_EXPORT pixman_bool_t
pixman_format_supported_destination(pixman_format_code_t format)1180 pixman_format_supported_destination (pixman_format_code_t format)
1181 {
1182 /* YUV formats cannot be written to at the moment */
1183 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1184 return FALSE;
1185
1186 return pixman_format_supported_source (format);
1187 }
1188
1189 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 * dst_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)1190 pixman_compute_composite_region (pixman_region16_t * region,
1191 pixman_image_t * src_image,
1192 pixman_image_t * mask_image,
1193 pixman_image_t * dst_image,
1194 int16_t src_x,
1195 int16_t src_y,
1196 int16_t mask_x,
1197 int16_t mask_y,
1198 int16_t dest_x,
1199 int16_t dest_y,
1200 uint16_t width,
1201 uint16_t height)
1202 {
1203 pixman_region32_t r32;
1204 pixman_bool_t retval;
1205
1206 pixman_region32_init (&r32);
1207
1208 retval = pixman_compute_composite_region32 (
1209 &r32, src_image, mask_image, dst_image,
1210 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1211 width, height);
1212
1213 if (retval)
1214 {
1215 if (!pixman_region16_copy_from_region32 (region, &r32))
1216 retval = FALSE;
1217 }
1218
1219 pixman_region32_fini (&r32);
1220 return retval;
1221 }
1222