summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/sna/sna.h2
-rw-r--r--src/sna/sna_accel.c41
-rw-r--r--src/sna/sna_display.c23
3 files changed, 56 insertions, 10 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 3d4792ca..00b12e9f 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -377,6 +377,8 @@ extern void sna_mode_update(struct sna *sna);
extern void sna_mode_reset(struct sna *sna);
extern void sna_mode_wakeup(struct sna *sna);
extern void sna_mode_redisplay(struct sna *sna);
+extern void sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
+ RegionPtr region);
extern void sna_mode_close(struct sna *sna);
extern void sna_mode_fini(struct sna *sna);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 50b46725..1f1a5a6f 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -3131,10 +3131,24 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
assert_pixmap_contains_box(pixmap, box);
assert(priv->gpu_damage == NULL || priv->gpu_bo);
- if (priv->move_to_gpu &&
- !priv->move_to_gpu(sna, priv, flags | MOVE_READ | (priv->cpu_damage ? MOVE_WRITE : 0))) {
- DBG(("%s: move-to-gpu override failed\n", __FUNCTION__));
- return NULL;
+ if ((flags & MOVE_READ) == 0)
+ sna_damage_subtract_box(&priv->cpu_damage, box);
+
+ if (priv->move_to_gpu) {
+ unsigned int hint;
+
+ hint = flags | MOVE_READ | (priv->cpu_damage ? MOVE_WRITE : 0);
+ if ((flags & MOVE_READ) == 0) {
+ RegionRec region;
+
+ region.extents = *box;
+ region.data = NULL;
+ sna_pixmap_discard_shadow_damage(priv, &region);
+ }
+ if (!priv->move_to_gpu(sna, priv, hint)) {
+ DBG(("%s: move-to-gpu override failed\n", __FUNCTION__));
+ return NULL;
+ }
}
if (priv->cow && (flags & MOVE_WRITE || priv->cpu_damage)) {
@@ -3177,9 +3191,6 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
priv->gpu_bo = NULL;
}
- if ((flags & MOVE_READ) == 0)
- sna_damage_subtract_box(&priv->cpu_damage, box);
-
sna_damage_reduce(&priv->cpu_damage);
assert_pixmap_damage(pixmap);
@@ -3652,14 +3663,26 @@ use_gpu_bo:
if (priv->move_to_gpu) {
unsigned hint = MOVE_READ | MOVE_WRITE;
+ sna = to_sna_from_pixmap(pixmap);
+
if (flags & IGNORE_CPU) {
region.extents = *box;
region.data = NULL;
- if (region_subsumes_drawable(&region, &pixmap->drawable))
+ if (region_subsumes_pixmap(&region, pixmap)) {
+ DBG(("%s: discarding move-to-gpu READ for subsumed pixmap\n", __FUNCTION__));
hint = MOVE_WRITE;
+ } else {
+ if (get_drawable_deltas(drawable, pixmap, &dx, &dy)) {
+ region.extents.x1 += dx;
+ region.extents.x2 += dx;
+ region.extents.y1 += dy;
+ region.extents.y2 += dy;
+ }
+ sna_pixmap_discard_shadow_damage(priv, &region);
+ }
}
- if (!priv->move_to_gpu(to_sna_from_pixmap(pixmap), priv, hint)) {
+ if (!priv->move_to_gpu(sna, priv, hint)) {
DBG(("%s: move-to-gpu override failed\n", __FUNCTION__));
goto use_cpu_bo;
}
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index b1f88a66..cb0d063f 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -855,7 +855,7 @@ static bool wait_for_shadow(struct sna *sna, struct sna_pixmap *priv, unsigned f
sna->mode.shadow_damage = damage;
- if (flags & MOVE_READ) {
+ if (flags & MOVE_READ && RegionNotEmpty(&wait->region)) {
DBG(("%s: copying existing GPU damage: %ldx(%d, %d), (%d, %d)\n",
__FUNCTION__, (long)REGION_NUM_RECTS(&wait->region),
wait->region.extents.x1, wait->region.extents.y1,
@@ -887,6 +887,27 @@ done:
return ret;
}
+void sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
+ RegionPtr region)
+{
+ struct wait_for_shadow *wait = priv->move_to_gpu_data;
+
+ if (priv->move_to_gpu != wait_for_shadow)
+ return;
+
+ DBG(("%s: discarding region %dx[(%d, %d), (%d, %d)] from damage %dx[(%d, %d], (%d, %d)]\n",
+ __FUNCTION__,
+ RegionNumRects(region),
+ region->extents.x1, region->extents.y1,
+ region->extents.x2, region->extents.y2,
+ RegionNumRects(&wait->region),
+ wait->region.extents.x1, wait->region.extents.y1,
+ wait->region.extents.x2, wait->region.extents.y2));
+
+ assert(wait);
+ RegionSubtract(&wait->region, &wait->region, region);
+}
+
static bool sna_mode_enable_shadow(struct sna *sna)
{
ScreenPtr screen = sna->scrn->pScreen;