diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-24 18:22:12 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-01-24 18:54:07 +0000 |
commit | 3d1bba033bc29fdf498dc082f3542c520a5ed39a (patch) | |
tree | e0ab0a419fd145f76e47657679961a8a1cefefc8 | |
parent | ff4b8a03a40f7eb1d71b96aebb5daa1d8df83d2a (diff) |
sna/gen3: Apply damage to video pixmap
Reported-by: Paul Neumann <paul104x@yahoo.de>
References: https://bugs.freedesktop.org/show_bug.cgi?id=44504
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/gen3_render.c | 21 | ||||
-rw-r--r-- | src/sna/sna_damage.c | 82 | ||||
-rw-r--r-- | src/sna/sna_damage.h | 12 |
3 files changed, 113 insertions, 2 deletions
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c index 4b61f65d..acccf0ae 100644 --- a/src/sna/gen3_render.c +++ b/src/sna/gen3_render.c @@ -3610,6 +3610,7 @@ gen3_render_video(struct sna *sna, short drw_w, short drw_h, PixmapPtr pixmap) { + struct sna_pixmap *priv = sna_pixmap(pixmap); BoxPtr pbox = REGION_RECTS(dstRegion); int nbox = REGION_NUM_RECTS(dstRegion); int dxo = dstRegion->extents.x1; @@ -3623,7 +3624,7 @@ gen3_render_video(struct sna *sna, DBG(("%s: %dx%d -> %dx%d\n", __FUNCTION__, src_w, src_h, drw_w, drw_h)); - dst_bo = sna_pixmap_get_bo(pixmap); + dst_bo = priv->gpu_bo; if (dst_bo == NULL) return FALSE; @@ -3721,7 +3722,7 @@ gen3_render_video(struct sna *sna, #endif sna_blt_copy_boxes(sna, GXcopy, dst_bo, -dxo, -dyo, - sna_pixmap_get_bo(pixmap), pix_xoff, pix_yoff, + priv->gpu_bo, pix_xoff, pix_yoff, pixmap->drawable.bitsPerPixel, REGION_RECTS(dstRegion), REGION_NUM_RECTS(dstRegion)); @@ -3729,6 +3730,22 @@ gen3_render_video(struct sna *sna, kgem_bo_destroy(&sna->kgem, dst_bo); } + if (!DAMAGE_IS_ALL(priv->gpu_damage)) { + if ((pix_xoff | pix_yoff) == 0) { + sna_damage_add(&priv->gpu_damage, dstRegion); + sna_damage_subtract(&priv->cpu_damage, dstRegion); + } else { + sna_damage_add_boxes(&priv->gpu_damage, + REGION_RECTS(dstRegion), + REGION_NUM_RECTS(dstRegion), + pix_xoff, pix_yoff); + sna_damage_subtract_boxes(&priv->cpu_damage, + REGION_RECTS(dstRegion), + REGION_NUM_RECTS(dstRegion), + pix_xoff, pix_yoff); + } + } + return TRUE; } diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c index 490e7a94..d15ec60a 100644 --- a/src/sna/sna_damage.c +++ b/src/sna/sna_damage.c @@ -1148,6 +1148,88 @@ fastcall struct sna_damage *_sna_damage_subtract_box(struct sna_damage *damage, } #endif +static struct sna_damage *__sna_damage_subtract_boxes(struct sna_damage *damage, + const BoxRec *box, int n, + int dx, int dy) +{ + BoxRec extents; + int i; + + if (damage == NULL) + return NULL; + + assert(n); + + extents = box[0]; + for (i = 1; i < n; i++) { + if (extents.x1 > box[i].x1) + extents.x1 = box[i].x1; + if (extents.x2 < box[i].x2) + extents.x2 = box[i].x2; + if (extents.y1 > box[i].y1) + extents.y1 = box[i].y1; + if (extents.y2 < box[i].y2) + extents.y2 = box[i].y2; + } + + assert(extents.y2 > extents.y1 && extents.x2 > extents.x1); + + extents.x1 += dx; + extents.x2 += dx; + extents.y1 += dy; + extents.y2 += dy; + + if (!sna_damage_maybe_contains_box(damage, &extents)) + return damage; + + if (n == 1) + return __sna_damage_subtract_box(damage, &extents); + + if (damage->mode != DAMAGE_SUBTRACT) { + if (damage->dirty) + __sna_damage_reduce(damage); + + if (!pixman_region_not_empty(&damage->region)) { + __sna_damage_destroy(damage); + return NULL; + } + + damage->mode = DAMAGE_SUBTRACT; + } + + return _sna_damage_create_elt_from_boxes(damage, box, n, dx, dy); +} + +#if DEBUG_DAMAGE +fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage, + const BoxRec *box, int n, + int dx, int dy) +{ + char damage_buf[1000]; + char region_buf[120]; + + ErrorF("%s(%s - [(%d,%d), (%d,%d)...x%d])...\n", __FUNCTION__, + _debug_describe_damage(damage_buf, sizeof(damage_buf), damage), + box->x1 + dx, box->y1 + dy, + box->x2 + dx, box->y2 + dy, + n); + + damage = __sna_damage_subtract_boxes(damage, box, n, dx, dy); + + ErrorF(" = %s\n", + _debug_describe_damage(damage_buf, sizeof(damage_buf), damage)); + + return damage; +} +#else +fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage, + const BoxRec *box, int n, + int dx, int dy) +{ + return __sna_damage_subtract_boxes(damage, box, n, dx, dy); +} +#endif + static int __sna_damage_contains_box(struct sna_damage *damage, const BoxRec *box) { diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h index dc0962f2..228aba02 100644 --- a/src/sna/sna_damage.h +++ b/src/sna/sna_damage.h @@ -153,6 +153,18 @@ static inline void sna_damage_subtract_box(struct sna_damage **damage, assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL); } +fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage, + const BoxRec *box, int n, + int dx, int dy); +static inline void sna_damage_subtract_boxes(struct sna_damage **damage, + const BoxRec *box, int n, + int dx, int dy) +{ + *damage = _sna_damage_subtract_boxes(DAMAGE_PTR(*damage), + box, n, dx, dy); + assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL); +} + Bool _sna_damage_intersect(struct sna_damage *damage, RegionPtr region, RegionPtr result); |