$NetBSD: patch-bc,v 1.2 2012/05/12 17:38:32 wiz Exp $ --- pixman/pixman.c.orig 2012-01-27 15:45:27.000000000 +0000 +++ pixman/pixman.c @@ -162,6 +162,57 @@ optimize_operator (pixman_op_t op, return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque]; } +static void +apply_workaround (pixman_image_t *image, + int32_t * x, + int32_t * y, + uint32_t ** save_bits, + int * save_dx, + int * save_dy) +{ + if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND)) + { + /* Some X servers generate images that point to the + * wrong place in memory, but then set the clip region + * to point to the right place. Because of an old bug + * in pixman, this would actually work. + * + * Here we try and undo the damage + */ + int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8; + pixman_box32_t *extents; + uint8_t *t; + int dx, dy; + + extents = pixman_region32_extents (&(image->common.clip_region)); + dx = extents->x1; + dy = extents->y1; + + *save_bits = image->bits.bits; + + *x -= dx; + *y -= dy; + pixman_region32_translate (&(image->common.clip_region), -dx, -dy); + + t = (uint8_t *)image->bits.bits; + t += dy * image->bits.rowstride * 4 + dx * bpp; + image->bits.bits = (uint32_t *)t; + + *save_dx = dx; + *save_dy = dy; + } +} + +static void +unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy) +{ + if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND)) + { + image->bits.bits = bits; + pixman_region32_translate (&image->common.clip_region, dx, dy); + } +} + /* * Computing composite region */ @@ -586,6 +637,13 @@ pixman_image_composite32 (pixman_op_t uint32_t src_flags, mask_flags, dest_flags; pixman_region32_t region; pixman_box32_t extents; + uint32_t *src_bits; + int src_dx, src_dy; + uint32_t *mask_bits; + int mask_dx, mask_dy; + uint32_t *dest_bits; + int dest_dx, dest_dy; + pixman_bool_t need_workaround; pixman_implementation_t *imp; pixman_composite_func_t func; @@ -623,6 +681,16 @@ pixman_image_composite32 (pixman_op_t src_format = mask_format = PIXMAN_rpixbuf; } + /* Check for workaround */ + need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND; + + if (need_workaround) + { + apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy); + apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy); + apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy); + } + pixman_region32_init (®ion); if (!pixman_compute_composite_region32 ( @@ -716,6 +784,13 @@ pixman_image_composite32 (pixman_op_t } out: + if (need_workaround) + { + unapply_workaround (src, src_bits, src_dx, src_dy); + unapply_workaround (mask, mask_bits, mask_dx, mask_dy); + unapply_workaround (dest, dest_bits, dest_dx, dest_dy); + } + pixman_region32_fini (®ion); }