diff options
-rw-r--r-- | src/sna/sna.h | 2 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 41 | ||||
-rw-r--r-- | src/sna/sna_display.c | 23 |
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, ®ion); + } + 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(®ion, &pixmap->drawable)) + if (region_subsumes_pixmap(®ion, 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, ®ion); + } } - 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; |