summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-01-24 18:22:12 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-01-24 18:54:07 +0000
commit3d1bba033bc29fdf498dc082f3542c520a5ed39a (patch)
treee0ab0a419fd145f76e47657679961a8a1cefefc8
parentff4b8a03a40f7eb1d71b96aebb5daa1d8df83d2a (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.c21
-rw-r--r--src/sna/sna_damage.c82
-rw-r--r--src/sna/sna_damage.h12
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);