{
if (image->common.clip_sources &&
image->common.repeat == PIXMAN_REPEAT_NONE &&
+ image->common.have_clip_region &&
out_of_bounds_workaround)
{
const pixman_box32_t *boxes;
int dx,
int dy)
{
- /* The workaround lets certain fast paths run even when they
- * would normally be rejected because of out-of-bounds access.
- * We need to clip against the source geometry in that case
+ /* Source clips are ignored, unless they are explicitly turned on
+ * and the clip in question was set by an X client. (Because if
+ * the clip was not set by a client, then it is a hierarchy
+ * clip and those should always be ignored for sources).
*/
- if (!picture->common.need_workaround)
- {
- /* Source clips are ignored, unless they are explicitly turned on
- * and the clip in question was set by an X client. (Because if
- * the clip was not set by a client, then it is a hierarchy
- * clip and those should always be ignored for sources).
- */
- if (!picture->common.clip_sources || !picture->common.client_clip)
- return TRUE;
- }
+ if (!picture->common.clip_sources || !picture->common.client_clip)
+ return TRUE;
return clip_general_image (region,
&picture->common.clip_region,
region->extents.x1 = MAX (region->extents.x1, 0);
region->extents.y1 = MAX (region->extents.y1, 0);
-
- /* Some X servers rely on an old bug, where pixman would just believe the
- * set clip_region and not clip against the destination geometry. So,
- * since only X servers set "source clip", we don't clip against
- * destination geometry when that is set and when the workaround has
- * not been explicitly disabled by
- *
- * pixman_disable_out_of_bounds_workaround();
- *
- */
- if (!(dst_image->common.need_workaround))
- {
- region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
- region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
- }
+ region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
+ region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
region->data = 0;
if (sources_cover (
src, mask, extents,
- src_x, src_y, mask_x, mask_y, dest_x, dest_y) ||
- src->common.need_workaround)
+ src_x, src_y, mask_x, mask_y, dest_x, dest_y))
{
walk_region_internal (imp, op,
src, mask, dest,
{ PIXMAN_OP_NONE }
};
+static pixman_implementation_t *imp;
+
/*
* Check if the current operator could be optimized
*/
}
-static pixman_implementation_t *imp;
+static void
+apply_workaround (pixman_image_t *image,
+ int16_t * x,
+ int16_t * y,
+ uint32_t ** save_bits,
+ int * save_dx,
+ int * save_dy)
+{
+ /* 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)
+{
+ image->bits.bits = bits;
+ pixman_region32_translate (&image->common.clip_region, dx, dy);
+}
PIXMAN_EXPORT void
pixman_image_composite (pixman_op_t op,
uint16_t width,
uint16_t height)
{
+ 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;
+
/*
* Check if we can replace our operator by a simpler one
* if the src or dest are opaque. The output operator should be
if (!imp)
imp = _pixman_choose_implementation ();
+ if (src->common.need_workaround)
+ apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
+ if (mask && mask->common.need_workaround)
+ apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
+ if (dest->common.need_workaround)
+ apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
+
_pixman_implementation_composite (imp, op,
src, mask, dest,
src_x, src_y,
mask_x, mask_y,
dest_x, dest_y,
width, height);
+
+ if (src->common.need_workaround)
+ unapply_workaround (src, src_bits, src_dx, src_dy);
+ if (mask && mask->common.need_workaround)
+ unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
+ if (dest->common.need_workaround)
+ unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
}
PIXMAN_EXPORT pixman_bool_t
dx = get_rand (500);
dy = get_rand (500);
- /* Now simulate the bogus X server translations */
- bits -= (dy * stride + dx) * bpp;
+ if (!src)
+ {
+ /* Now simulate the bogus X server translations */
+ bits -= (dy * stride + dx) * bpp;
+ }
image = pixman_image_create_bits (
format, width, height, (uint32_t *)bits, stride * bpp);
- /* And add the bogus clip region */
- pixman_region32_init_rect (®ion, dx, dy, dx + width, dy + height);
+ if (!src)
+ {
+ /* And add the bogus clip region */
+ pixman_region32_init_rect (®ion, dx, dy, dx + width, dy + height);
- pixman_image_set_clip_region32 (image, ®ion);
+ pixman_image_set_clip_region32 (image, ®ion);
+ }
pixman_image_set_source_clipping (image, TRUE);
pixman_image_set_repeat (image, PIXMAN_REPEAT_PAD);
}
- *rx = dx;
- *ry = dy;
+ if (!src)
+ {
+ *rx = dx;
+ *ry = dy;
+ }
+ else
+ {
+ *rx = *ry = 0;
+ }
return image;
}
uint8_t *pixel =
bits + (i + dest_y) * stride + (j + dest_x) * bpp;
- assert (*(uint16_t *)pixel == 0x788f);
+ if (*(uint16_t *)pixel != 0x788f)
+ {
+ printf ("bad pixel %x\n", *(uint16_t *)pixel);
+ assert (*(uint16_t *)pixel == 0x788f);
+ }
}
}