sna: Fix TearFree for non-compositors

The tearfree code forgot to update the shadow bo, so after the first
flip it would be rendering to the scanout anyway and flip to itself
periodically.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2014-06-07 08:30:38 +01:00
parent c65fab0740
commit dcb64b5509
2 changed files with 59 additions and 73 deletions

View File

@ -290,6 +290,7 @@ struct sna {
bool dirty;
int max_crtc_width, max_crtc_height;
RegionRec shadow_region;
unsigned num_real_crtc;
unsigned num_real_output;

View File

@ -1007,24 +1007,19 @@ sna_crtc_apply(xf86CrtcPtr crtc)
return true;
}
struct wait_for_shadow {
RegionRec region;
struct kgem_bo *bo;
};
static bool wait_for_shadow(struct sna *sna, struct sna_pixmap *priv, unsigned flags)
{
struct wait_for_shadow *wait = priv->move_to_gpu_data;
struct kgem_bo *bo = wait->bo;
PixmapPtr pixmap = priv->pixmap;
DamagePtr damage;
struct kgem_bo *bo, *tmp;
bool ret = true;
DBG(("%s: flags=%x, flips=%d, handle=%d, wait=%d, old=%d\n",
DBG(("%s: flags=%x, flips=%d, handle=%d, shadow=%d\n",
__FUNCTION__, flags, sna->mode.flip_active,
priv->gpu_bo->handle, wait->bo->handle, sna->mode.shadow->handle));
priv->gpu_bo->handle, sna->mode.shadow->handle));
assert(wait->bo != priv->gpu_bo);
assert(priv->move_to_gpu_data == sna);
assert(sna->mode.shadow != priv->gpu_bo);
if (flags == 0 || pixmap != sna->front || !sna->mode.shadow_damage)
goto done;
@ -1040,6 +1035,7 @@ static bool wait_for_shadow(struct sna *sna, struct sna_pixmap *priv, unsigned f
while (sna->mode.flip_active && sna_mode_has_pending_events(sna))
sna_mode_wakeup(sna);
bo = sna->mode.shadow;
if (sna->mode.flip_active) {
bo = kgem_create_2d(&sna->kgem,
pixmap->drawable.width,
@ -1051,18 +1047,18 @@ static bool wait_for_shadow(struct sna *sna, struct sna_pixmap *priv, unsigned f
DBG(("%s: replacing still-attached GPU bo\n",
__FUNCTION__));
RegionUninit(&wait->region);
wait->region.extents.x1 = 0;
wait->region.extents.y1 = 0;
wait->region.extents.x2 = pixmap->drawable.width;
wait->region.extents.y2 = pixmap->drawable.height;
wait->region.data = NULL;
RegionUninit(&sna->mode.shadow_region);
sna->mode.shadow_region.extents.x1 = 0;
sna->mode.shadow_region.extents.y1 = 0;
sna->mode.shadow_region.extents.x2 = pixmap->drawable.width;
sna->mode.shadow_region.extents.y2 = pixmap->drawable.height;
sna->mode.shadow_region.data = NULL;
} else {
while (sna->mode.flip_active &&
sna_mode_wait_for_event(sna))
sna_mode_wakeup(sna);
bo = wait->bo;
bo = sna->mode.shadow;
}
}
@ -1077,28 +1073,30 @@ static bool wait_for_shadow(struct sna *sna, struct sna_pixmap *priv, unsigned f
DBG(("%s: replacing exported GPU bo\n",
__FUNCTION__));
RegionUninit(&wait->region);
wait->region.extents.x1 = 0;
wait->region.extents.y1 = 0;
wait->region.extents.x2 = pixmap->drawable.width;
wait->region.extents.y2 = pixmap->drawable.height;
wait->region.data = NULL;
RegionUninit(&sna->mode.shadow_region);
sna->mode.shadow_region.extents.x1 = 0;
sna->mode.shadow_region.extents.y1 = 0;
sna->mode.shadow_region.extents.x2 = pixmap->drawable.width;
sna->mode.shadow_region.extents.y2 = pixmap->drawable.height;
sna->mode.shadow_region.data = NULL;
} else
bo = wait->bo;
bo = sna->mode.shadow;
}
sna->mode.shadow_damage = damage;
if (flags & MOVE_READ && RegionNotEmpty(&wait->region)) {
if (flags & MOVE_READ && RegionNotEmpty(&sna->mode.shadow_region)) {
DBG(("%s: copying existing GPU damage: %ldx(%d, %d), (%d, %d)\n",
__FUNCTION__, (long)REGION_NUM_RECTS(&wait->region),
wait->region.extents.x1, wait->region.extents.y1,
wait->region.extents.x2, wait->region.extents.y2));
__FUNCTION__, (long)REGION_NUM_RECTS(&sna->mode.shadow_region),
sna->mode.shadow_region.extents.x1,
sna->mode.shadow_region.extents.y1,
sna->mode.shadow_region.extents.x2,
sna->mode.shadow_region.extents.y2));
ret = sna->render.copy_boxes(sna, GXcopy,
pixmap, priv->gpu_bo, 0, 0,
pixmap, bo, 0, 0,
REGION_RECTS(&wait->region),
REGION_NUM_RECTS(&wait->region),
REGION_RECTS(&sna->mode.shadow_region),
REGION_NUM_RECTS(&sna->mode.shadow_region),
0);
}
@ -1108,15 +1106,16 @@ static bool wait_for_shadow(struct sna *sna, struct sna_pixmap *priv, unsigned f
sna_pixmap_unmap(pixmap, priv);
DBG(("%s: setting front pixmap to handle=%d\n", __FUNCTION__, bo->handle));
kgem_bo_destroy(&sna->kgem, priv->gpu_bo);
priv->gpu_bo = bo == wait->bo ? kgem_bo_reference(bo) : bo;
tmp = priv->gpu_bo;
priv->gpu_bo = bo;
if (bo != sna->mode.shadow)
kgem_bo_destroy(&sna->kgem, sna->mode.shadow);
sna->mode.shadow = tmp;
sna_dri2_pixmap_update_bo(sna, pixmap, bo);
done:
kgem_bo_destroy(&sna->kgem, wait->bo);
RegionUninit(&wait->region);
free(wait);
RegionUninit(&sna->mode.shadow_region);
priv->move_to_gpu_data = NULL;
priv->move_to_gpu = NULL;
@ -1127,25 +1126,27 @@ done:
void sna_pixmap_discard_shadow_damage(struct sna_pixmap *priv,
RegionPtr region)
{
struct wait_for_shadow *wait = priv->move_to_gpu_data;
struct sna *sna;
if (priv->move_to_gpu != wait_for_shadow)
return;
sna = priv->move_to_gpu_data;
DBG(("%s: discarding region %dx[(%d, %d), (%d, %d)] from damage %dx[(%d, %d], (%d, %d)]\n",
__FUNCTION__,
RegionNumRects(region),
region->extents.x1, region->extents.y1,
region->extents.x2, region->extents.y2,
RegionNumRects(&wait->region),
wait->region.extents.x1, wait->region.extents.y1,
wait->region.extents.x2, wait->region.extents.y2));
RegionNumRects(&sna->mode.shadow_region),
sna->mode.shadow_region.extents.x1, sna->mode.shadow_region.extents.y1,
sna->mode.shadow_region.extents.x2, sna->mode.shadow_region.extents.y2));
assert(wait);
if (region)
RegionSubtract(&wait->region, &wait->region, region);
RegionSubtract(&sna->mode.shadow_region,
&sna->mode.shadow_region,
region);
else
RegionEmpty(&wait->region);
RegionEmpty(&sna->mode.shadow_region);
}
static bool sna_mode_enable_shadow(struct sna *sna)
@ -1526,43 +1527,31 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc)
return false;
}
static void set_shadow(PixmapPtr pixmap, struct kgem_bo *bo, RegionPtr region)
static void set_shadow(struct sna *sna, RegionPtr region)
{
struct sna_pixmap *priv = sna_pixmap(pixmap);
struct wait_for_shadow *wait;
struct sna_pixmap *priv = sna_pixmap(sna->front);
DBG(("%s: waiting for region %dx[(%d, %d), (%d, %d)] on handle=%d\n",
assert(priv->gpu_bo);
assert(sna->mode.shadow);
DBG(("%s: waiting for region %dx[(%d, %d), (%d, %d)], front handle=%d, shadow handle=%d\n",
__FUNCTION__,
RegionNumRects(region),
region->extents.x1, region->extents.y1,
region->extents.x2, region->extents.y2,
bo->handle));
priv->gpu_bo->handle, sna->mode.shadow->handle));
assert(priv->pinned & PIN_SCANOUT);
assert((priv->pinned & PIN_PRIME) == 0);
assert(bo != priv->gpu_bo);
assert(priv->gpu_bo);
wait = priv->move_to_gpu_data;
if (wait != NULL) {
assert(priv->move_to_gpu = wait_for_shadow);
assert(priv->pinned & PIN_SCANOUT);
assert(wait->bo == bo);
RegionUnion(&wait->region, &wait->region, region);
return;
}
assert(sna->mode.shadow != priv->gpu_bo);
assert(priv->move_to_gpu == NULL);
wait = malloc(sizeof(*wait));
if (wait != NULL) {
wait->bo = kgem_bo_reference(bo);
RegionNull(&wait->region);
RegionCopy(&wait->region, region);
priv->move_to_gpu = wait_for_shadow;
priv->move_to_gpu_data = wait;
}
RegionNull(&sna->mode.shadow_region);
RegionCopy(&sna->mode.shadow_region, region);
priv->pinned |= PIN_SCANOUT;
priv->move_to_gpu = wait_for_shadow;
priv->move_to_gpu_data = sna;
}
static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
@ -1666,7 +1655,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
}
sna->mode.shadow = shadow;
set_shadow(sna->front, shadow, &region);
set_shadow(sna, &region);
}
} else
sna_crtc_disable_shadow(sna, sna_crtc);
@ -5943,11 +5932,7 @@ fixup_shadow:
if (sna->mode.flip_active) {
assert(old == sna->mode.shadow);
assert(old->refcnt >= 1);
set_shadow(sna->front, old, region);
assert(new->refcnt >= 1);
kgem_bo_destroy(&sna->kgem, old);
sna->mode.shadow = kgem_bo_reference(new);
set_shadow(sna, region);
}
} else
kgem_submit(&sna->kgem);