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>
This commit is contained in:
Chris Wilson 2014-12-19 12:25:30 +00:00
parent 391b50c81d
commit 9b3b591476
3 changed files with 47 additions and 9 deletions

View File

@ -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);

View File

@ -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)
{

View File

@ -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;