diff options
-rw-r--r-- | src/sna/sna.h | 2 | ||||
-rw-r--r-- | src/sna/sna_display.c | 48 | ||||
-rw-r--r-- | src/sna/sna_dri2.c | 6 |
3 files changed, 47 insertions, 9 deletions
diff --git a/src/sna/sna.h b/src/sna/sna.h index 3116f116..18425e30 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -428,6 +428,8 @@ extern void sna_mode_reset(struct sna *sna); extern int sna_mode_wakeup(struct sna *sna); extern void sna_mode_redisplay(struct sna *sna); extern void sna_shadow_set_crtc(struct sna *sna, xf86CrtcPtr crtc, struct kgem_bo *bo); +extern void sna_shadow_steal_crtcs(struct sna *sna, struct list *list); +extern void sna_shadow_unsteal_crtcs(struct sna *sna, struct list *list); extern void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc); extern bool sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv, const RegionRec *region); diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index c31c68f2..e9fecef7 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -1114,14 +1114,13 @@ static bool wait_for_shadow(struct sna *sna, if ((flags & MOVE_WRITE) == 0) { if ((flags & __MOVE_SCANOUT) == 0) { - while (!list_is_empty(&sna->mode.shadow_crtc)) { - struct sna_crtc *crtc = - list_first_entry(&sna->mode.shadow_crtc, - struct sna_crtc, - shadow_link); + struct sna_crtc *crtc; + + list_for_each_entry(crtc, &sna->mode.shadow_crtc, shadow_link) { if (overlap(&sna->mode.shadow_region.extents, &crtc->base->bounds)) { DrawableRec draw; + RegionRec region; draw.width = crtc->base->mode.HDisplay; draw.height = crtc->base->mode.VDisplay; @@ -1141,11 +1140,11 @@ static bool wait_for_shadow(struct sna *sna, &pixmap->drawable, priv->gpu_bo, 0, 0, &crtc->base->bounds, 1, 0); - } - kgem_bo_destroy(&sna->kgem, crtc->client_bo); - crtc->client_bo = NULL; - list_del(&crtc->shadow_link); + region.extents = crtc->base->bounds; + region.data = NULL; + RegionSubtract(&sna->mode.shadow_region, &sna->mode.shadow_region, ®ion); + } } } @@ -6915,6 +6914,37 @@ void sna_shadow_set_crtc(struct sna *sna, priv->move_to_gpu_data = sna; } +void sna_shadow_steal_crtcs(struct sna *sna, struct list *list) +{ + list_init(list); + while (!list_is_empty(&sna->mode.shadow_crtc)) { + RegionRec sub, *damage; + struct sna_crtc *crtc = + list_first_entry(&sna->mode.shadow_crtc, + struct sna_crtc, + shadow_link); + + damage = DamageRegion(sna->mode.shadow_damage); + sub.extents = crtc->base->bounds; + sub.data = NULL; + RegionSubtract(damage, damage, &sub); + + list_move(&crtc->shadow_link, list); + } +} + +void sna_shadow_unsteal_crtcs(struct sna *sna, struct list *list) +{ + while (!list_is_empty(list)) { + struct sna_crtc *crtc = + list_first_entry(list, + struct sna_crtc, + shadow_link); + assert(crtc->client_bo); + sna_shadow_set_crtc(sna, crtc->base, crtc->client_bo); + } +} + void sna_shadow_unset_crtc(struct sna *sna, xf86CrtcPtr crtc) { diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index 75e85a3c..430c99ec 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -1006,6 +1006,10 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region, assert(dst_bo->refcnt); if (is_front(dst->attachment)) { struct sna_pixmap *priv; + struct list shadow; + + /* Preserve the CRTC shadow overrides */ + sna_shadow_steal_crtcs(sna, &shadow); flags = MOVE_WRITE | __MOVE_FORCE; if (clip.data) @@ -1020,6 +1024,8 @@ __sna_dri2_copy_region(struct sna *sna, DrawablePtr draw, RegionPtr region, DBG(("%s: updated FrontLeft dst_bo from handle=%d to handle=%d\n", __FUNCTION__, dst_priv->bo->handle, dst_bo->handle)); assert(dst_bo->refcnt); + + sna_shadow_unsteal_crtcs(sna, &shadow); } else { RegionRec target; |