diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-08-12 10:33:41 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-08-12 10:33:41 +0100 |
commit | e8dfc5b3f4ffeec93e52a5319b5a3118edf0e94e (patch) | |
tree | 97c0a2be30cd61aa25ef051d48038d8bf58c5820 /src/sna | |
parent | 8d48a43ed956ff21d779aff1a11a0f7bf6b65bcb (diff) |
sna: Fix destination offset along memcpy composite fallback fastback
The application of dst_x|y was incorrect, and so the drawing could end
up in the wrong location for a window.
References: https://bugs.freedesktop.org/show_bug.cgi?id=66990
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/sna')
-rw-r--r-- | src/sna/sna_composite.c | 144 |
1 files changed, 74 insertions, 70 deletions
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c index 58dd3567..000e27ef 100644 --- a/src/sna/sna_composite.c +++ b/src/sna/sna_composite.c @@ -504,79 +504,83 @@ sna_composite_fb(CARD8 op, return; } - if (mask && mask->pDrawable) { - DBG(("%s: fallback -- move mask to cpu\n", __FUNCTION__)); - if (!sna_drawable_move_to_cpu(mask->pDrawable, - MOVE_READ)) - return; - - if (mask->alphaMap && - !sna_drawable_move_to_cpu(mask->alphaMap->pDrawable, - MOVE_READ)) - return; - } - validate_source(src); - if (mask) - validate_source(mask); - if (mask == NULL && - src->pDrawable && - dst->pDrawable->bitsPerPixel >= 8 && - src->filter != PictFilterConvolution && - (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(src->format))) && - (dst->format == src->format || dst->format == alphaless(src->format)) && - sna_transform_is_integer_translation(src->transform, &tx, &ty)) { - PixmapPtr dst_pixmap = get_drawable_pixmap(dst->pDrawable); - PixmapPtr src_pixmap = get_drawable_pixmap(src->pDrawable); - int16_t sx = src_x + tx - (dst->pDrawable->x - dst_x); - int16_t sy = src_y + ty - (dst->pDrawable->y - dst_y); - if (region->extents.x1 + sx >= 0 && - region->extents.y1 + sy >= 0 && - region->extents.x2 + sx <= src->pDrawable->width && - region->extents.y2 + sy <= src->pDrawable->height) { - BoxPtr box = RegionRects(region); - int nbox = RegionNumRects(region); - - sx += src->pDrawable->x; - sy += src->pDrawable->y; - if (get_drawable_deltas(src->pDrawable, src_pixmap, &tx, &ty)) - sx += tx, sy += ty; - - assert(region->extents.x1 + sx >= 0); - assert(region->extents.x2 + sx <= src_pixmap->drawable.width); - assert(region->extents.y1 + sy >= 0); - assert(region->extents.y2 + sy <= src_pixmap->drawable.height); - - if (get_drawable_deltas(dst->pDrawable, dst_pixmap, &tx, &ty)) - dst_x += tx, dst_y += ty; - - assert(nbox); - do { - assert(box->x1 + sx >= 0); - assert(box->x2 + sx <= src_pixmap->drawable.width); - assert(box->y1 + sy >= 0); - assert(box->y2 + sy <= src_pixmap->drawable.height); - - assert(box->x1 + dst_x >= 0); - assert(box->x2 + dst_x <= dst_pixmap->drawable.width); - assert(box->y1 + dst_y >= 0); - assert(box->y2 + dst_y <= dst_pixmap->drawable.height); - - assert(box->x2 > box->x1 && box->y2 > box->y1); - - memcpy_blt(src_pixmap->devPrivate.ptr, - dst_pixmap->devPrivate.ptr, - dst_pixmap->drawable.bitsPerPixel, - src_pixmap->devKind, - dst_pixmap->devKind, - box->x1 + sx, box->y1 + sy, - box->x1 + dst_x, box->y1 + dst_y, - box->x2 - box->x1, box->y2 - box->y1); - box++; - } while (--nbox); + if (mask) { + if (mask->pDrawable) { + DBG(("%s: fallback -- move mask to cpu\n", __FUNCTION__)); + if (!sna_drawable_move_to_cpu(mask->pDrawable, + MOVE_READ)) + return; + + if (mask->alphaMap && + !sna_drawable_move_to_cpu(mask->alphaMap->pDrawable, + MOVE_READ)) + return; + } - return; + validate_source(mask); + } else { + if (src->pDrawable && + dst->pDrawable->bitsPerPixel >= 8 && + src->filter != PictFilterConvolution && + (op == PictOpSrc || (op == PictOpOver && !PICT_FORMAT_A(src->format))) && + (dst->format == src->format || dst->format == alphaless(src->format)) && + sna_transform_is_integer_translation(src->transform, &tx, &ty)) { + PixmapPtr dst_pixmap = get_drawable_pixmap(dst->pDrawable); + PixmapPtr src_pixmap = get_drawable_pixmap(src->pDrawable); + int16_t sx = src_x + tx - (dst->pDrawable->x + dst_x); + int16_t sy = src_y + ty - (dst->pDrawable->y + dst_y); + + assert(src->pDrawable->bitsPerPixel == dst->pDrawable->bitsPerPixel); + assert(src_pixmap->drawable.bitsPerPixel == dst_pixmap->drawable.bitsPerPixel); + + if (region->extents.x1 + sx >= 0 && + region->extents.y1 + sy >= 0 && + region->extents.x2 + sx <= src->pDrawable->width && + region->extents.y2 + sy <= src->pDrawable->height) { + BoxPtr box = RegionRects(region); + int nbox = RegionNumRects(region); + + sx += src->pDrawable->x; + sy += src->pDrawable->y; + if (get_drawable_deltas(src->pDrawable, src_pixmap, &tx, &ty)) + sx += tx, sy += ty; + + assert(region->extents.x1 + sx >= 0); + assert(region->extents.x2 + sx <= src_pixmap->drawable.width); + assert(region->extents.y1 + sy >= 0); + assert(region->extents.y2 + sy <= src_pixmap->drawable.height); + + get_drawable_deltas(dst->pDrawable, dst_pixmap, &tx, &ty); + + assert(nbox); + do { + assert(box->x1 + sx >= 0); + assert(box->x2 + sx <= src_pixmap->drawable.width); + assert(box->y1 + sy >= 0); + assert(box->y2 + sy <= src_pixmap->drawable.height); + + assert(box->x1 + dst_x >= 0); + assert(box->x2 + dst_x <= dst_pixmap->drawable.width); + assert(box->y1 + dst_y >= 0); + assert(box->y2 + dst_y <= dst_pixmap->drawable.height); + + assert(box->x2 > box->x1 && box->y2 > box->y1); + + memcpy_blt(src_pixmap->devPrivate.ptr, + dst_pixmap->devPrivate.ptr, + dst_pixmap->drawable.bitsPerPixel, + src_pixmap->devKind, + dst_pixmap->devKind, + box->x1 + sx, box->y1 + sy, + box->x1 + tx, box->y1 + ty, + box->x2 - box->x1, box->y2 - box->y1); + box++; + } while (--nbox); + + return; + } } } |