summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;