diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-12-19 12:25:30 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-12-19 20:08:44 +0000 |
commit | 9b3b591476cc52cc285a8a1f02462db37d5e10c2 (patch) | |
tree | 5d358197e1138f98cf8a8c8ae186c8bc04735fa7 | |
parent | 391b50c81decd208c47c109217b2c882c064ac69 (diff) |
sna/dri2: Preserve the shadow CRTCs when copying to other areas
In the Composite setup, if we are doing a DRI2 copy onto the front
buffer, we are fully cognizant that the copy will not go onto the
unredirected Windows of another Client. So we can preserve the shadow
CRTC mapping for those Clients, and prevent ping-ponging between CRTC
modes.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-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; |