summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-12-19 12:25:30 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2014-12-19 20:08:44 +0000
commit9b3b591476cc52cc285a8a1f02462db37d5e10c2 (patch)
tree5d358197e1138f98cf8a8c8ae186c8bc04735fa7
parent391b50c81decd208c47c109217b2c882c064ac69 (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.h2
-rw-r--r--src/sna/sna_display.c48
-rw-r--r--src/sna/sna_dri2.c6
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, &region);
+ }
}
}
@@ -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;