sna: Reuse the same buffer when panning large CRTCs
Rather than alternating between a pair of fb each time, we can reuse the last shadow buffer so long as it remains the right size. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
911a0ad8d0
commit
65a23ef909
|
|
@ -120,7 +120,7 @@ struct sna_crtc {
|
|||
int dpms_mode;
|
||||
PixmapPtr slave_pixmap;
|
||||
DamagePtr slave_damage;
|
||||
struct kgem_bo *bo, *shadow_bo;
|
||||
struct kgem_bo *bo, *shadow_bo, *client_bo;
|
||||
struct sna_cursor *cursor;
|
||||
unsigned int last_cursor_size;
|
||||
uint32_t offset;
|
||||
|
|
@ -130,6 +130,8 @@ struct sna_crtc {
|
|||
uint8_t id;
|
||||
uint8_t pipe;
|
||||
|
||||
uint16_t shadow_bo_width, shadow_bo_height;
|
||||
|
||||
uint32_t rotation;
|
||||
struct plane {
|
||||
uint32_t id;
|
||||
|
|
@ -1121,17 +1123,17 @@ static bool wait_for_shadow(struct sna *sna,
|
|||
crtc->base->bounds.y1,
|
||||
crtc->base->bounds.x2,
|
||||
crtc->base->bounds.y2,
|
||||
crtc->shadow_bo->handle));
|
||||
crtc->client_bo->handle));
|
||||
|
||||
ret &= sna->render.copy_boxes(sna, GXcopy,
|
||||
&draw, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
|
||||
&draw, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
|
||||
&pixmap->drawable, priv->gpu_bo, 0, 0,
|
||||
&crtc->base->bounds, 1,
|
||||
0);
|
||||
}
|
||||
|
||||
kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
|
||||
crtc->shadow_bo = NULL;
|
||||
kgem_bo_destroy(&sna->kgem, crtc->client_bo);
|
||||
crtc->client_bo = NULL;
|
||||
list_del(&crtc->shadow_link);
|
||||
}
|
||||
}
|
||||
|
|
@ -1226,10 +1228,10 @@ static bool wait_for_shadow(struct sna *sna,
|
|||
crtc->base->bounds.y1,
|
||||
crtc->base->bounds.x2,
|
||||
crtc->base->bounds.y2,
|
||||
crtc->shadow_bo->handle));
|
||||
crtc->client_bo->handle));
|
||||
|
||||
ret = sna->render.copy_boxes(sna, GXcopy,
|
||||
&draw, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
|
||||
&draw, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
|
||||
&pixmap->drawable, bo, 0, 0,
|
||||
&crtc->base->bounds, 1,
|
||||
0);
|
||||
|
|
@ -1240,8 +1242,8 @@ static bool wait_for_shadow(struct sna *sna,
|
|||
RegionSubtract(&sna->mode.shadow_region, &sna->mode.shadow_region, ®ion);
|
||||
}
|
||||
|
||||
kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
|
||||
crtc->shadow_bo = NULL;
|
||||
kgem_bo_destroy(&sna->kgem, crtc->client_bo);
|
||||
crtc->client_bo = NULL;
|
||||
list_del(&crtc->shadow_link);
|
||||
}
|
||||
|
||||
|
|
@ -1433,7 +1435,7 @@ static bool sna_crtc_enable_shadow(struct sna *sna, struct sna_crtc *crtc)
|
|||
|
||||
static void sna_crtc_disable_override(struct sna *sna, struct sna_crtc *crtc)
|
||||
{
|
||||
if (crtc->shadow_bo == NULL)
|
||||
if (crtc->client_bo == NULL)
|
||||
return;
|
||||
|
||||
if (!crtc->transform) {
|
||||
|
|
@ -1445,13 +1447,13 @@ static void sna_crtc_disable_override(struct sna *sna, struct sna_crtc *crtc)
|
|||
tmp.bitsPerPixel = sna->front->drawable.bitsPerPixel;
|
||||
|
||||
sna->render.copy_boxes(sna, GXcopy,
|
||||
&tmp, crtc->shadow_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
|
||||
&tmp, crtc->client_bo, -crtc->base->bounds.x1, -crtc->base->bounds.y1,
|
||||
&sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
|
||||
&crtc->base->bounds, 1, 0);
|
||||
list_del(&crtc->shadow_link);
|
||||
}
|
||||
kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
|
||||
crtc->shadow_bo = NULL;
|
||||
kgem_bo_destroy(&sna->kgem, crtc->client_bo);
|
||||
crtc->client_bo = NULL;
|
||||
}
|
||||
|
||||
static void sna_crtc_disable_shadow(struct sna *sna, struct sna_crtc *crtc)
|
||||
|
|
@ -1499,6 +1501,10 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
|
|||
sna->mode.dirty = true;
|
||||
}
|
||||
|
||||
if (sna_crtc->shadow_bo) {
|
||||
kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
|
||||
sna_crtc->shadow_bo = NULL;
|
||||
}
|
||||
sna_crtc->transform = false;
|
||||
|
||||
assert(!sna_crtc->shadow);
|
||||
|
|
@ -1843,6 +1849,19 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
|
|||
DBG(("%s: attaching to per-crtc pixmap %dx%d\n",
|
||||
__FUNCTION__, crtc->mode.HDisplay, crtc->mode.VDisplay));
|
||||
|
||||
bo = sna_crtc->shadow_bo;
|
||||
if (bo) {
|
||||
if (sna_crtc->shadow_bo_width == crtc->mode.HDisplay &&
|
||||
sna_crtc->shadow_bo_height == crtc->mode.VDisplay) {
|
||||
DBG(("%s: reusing current shadow bo handle=%d\n",
|
||||
__FUNCTION__, bo->handle));
|
||||
goto out_shadow;
|
||||
}
|
||||
|
||||
kgem_bo_destroy(&sna->kgem, bo);
|
||||
sna_crtc->shadow_bo = NULL;
|
||||
}
|
||||
|
||||
tiling = I915_TILING_X;
|
||||
if (sna->kgem.gen == 071)
|
||||
tiled_limit = 16 * 1024 * 8;
|
||||
|
|
@ -1862,25 +1881,29 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
|
|||
scrn->bitsPerPixel,
|
||||
tiling, CREATE_SCANOUT);
|
||||
if (bo == NULL) {
|
||||
DBG(("%s: failed to allocate crtc scanout\n"));
|
||||
DBG(("%s: failed to allocate crtc scanout\n", __FUNCTION__));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!get_fb(sna, bo, crtc->mode.HDisplay, crtc->mode.VDisplay)) {
|
||||
DBG(("%s: failed to bind fb for crtc scanout\n"));
|
||||
DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
|
||||
kgem_bo_destroy(&sna->kgem, bo);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (__sna_pixmap_get_bo(sna->front)) {
|
||||
if (__sna_pixmap_get_bo(sna->front) && !crtc->transformPresent) {
|
||||
DrawableRec tmp;
|
||||
BoxRec b;
|
||||
|
||||
DBG(("%s: copying onto shadow CRTC: (%d, %d), (%d, %d), handle=%d\n",
|
||||
b.x1 = crtc->x;
|
||||
b.y1 = crtc->y;
|
||||
b.x2 = crtc->x + crtc->mode.HDisplay;
|
||||
b.y2 = crtc->y + crtc->mode.VDisplay;
|
||||
|
||||
DBG(("%s: copying onto shadow CRTC: (%d, %d)x(%d, %d), handle=%d\n",
|
||||
__FUNCTION__,
|
||||
crtc->bounds.x1,
|
||||
crtc->bounds.y1,
|
||||
crtc->bounds.x2,
|
||||
crtc->bounds.y2,
|
||||
b.x1, b.y1,
|
||||
b.x2, b.y2,
|
||||
bo->handle));
|
||||
|
||||
tmp.width = crtc->mode.HDisplay;
|
||||
|
|
@ -1890,26 +1913,34 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
|
|||
|
||||
(void)sna->render.copy_boxes(sna, GXcopy,
|
||||
&sna->front->drawable, __sna_pixmap_get_bo(sna->front), 0, 0,
|
||||
&tmp, bo, -crtc->bounds.x1, -crtc->bounds.y1,
|
||||
&crtc->bounds, 1,
|
||||
0);
|
||||
&tmp, bo, -b.x1, -b.y1,
|
||||
&b, 1, 0);
|
||||
}
|
||||
|
||||
sna_crtc->shadow_bo_width = crtc->mode.HDisplay;
|
||||
sna_crtc->shadow_bo_height = crtc->mode.VDisplay;
|
||||
sna_crtc->shadow_bo = bo;
|
||||
out_shadow:
|
||||
sna_crtc->transform = true;
|
||||
return bo;
|
||||
return kgem_bo_reference(bo);
|
||||
} else {
|
||||
if (sna_crtc->shadow_bo) {
|
||||
kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
|
||||
sna_crtc->shadow_bo = NULL;
|
||||
}
|
||||
|
||||
if (sna_crtc->slave_pixmap) {
|
||||
DBG(("%s: attaching to scanout pixmap\n", __FUNCTION__));
|
||||
bo = sna_pixmap_pin(sna_crtc->slave_pixmap, PIN_SCANOUT);
|
||||
if (bo == NULL) {
|
||||
DBG(("%s: failed to pin crtc scanout\n"));
|
||||
DBG(("%s: failed to pin crtc scanout\n", __FUNCTION__));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!get_fb(sna, bo,
|
||||
sna_crtc->slave_pixmap->drawable.width,
|
||||
sna_crtc->slave_pixmap->drawable.height)) {
|
||||
DBG(("%s: failed to bind fb for crtc scanout\n"));
|
||||
DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -1921,7 +1952,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
|
|||
}
|
||||
|
||||
if (!get_fb(sna, bo, scrn->virtualX, scrn->virtualY)) {
|
||||
DBG(("%s: failed to bind fb for crtc scanout\n"));
|
||||
DBG(("%s: failed to bind fb for crtc scanout\n", __FUNCTION__));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
|
@ -1931,7 +1962,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
|
|||
|
||||
DBG(("%s: enabling TearFree shadow\n", __FUNCTION__));
|
||||
if (!sna_crtc_enable_shadow(sna, sna_crtc)) {
|
||||
DBG(("%s: failed to enable crtc shadow\n"));
|
||||
DBG(("%s: failed to enable crtc shadow\n", __FUNCTION__));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1965,7 +1996,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc)
|
|||
if (!get_fb(sna, shadow,
|
||||
region.extents.x2,
|
||||
region.extents.y2)) {
|
||||
DBG(("%s: failed to bind fb for TearFeee shadow\n"));
|
||||
DBG(("%s: failed to bind fb for TearFeee shadow\n", __FUNCTION__));
|
||||
kgem_bo_destroy(&sna->kgem, shadow);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -2145,6 +2176,8 @@ __sna_crtc_set_mode(xf86CrtcPtr crtc)
|
|||
uint32_t saved_offset;
|
||||
bool saved_transform;
|
||||
|
||||
DBG(("%s\n", __FUNCTION__));
|
||||
|
||||
saved_bo = sna_crtc->bo;
|
||||
saved_transform = sna_crtc->transform;
|
||||
saved_offset = sna_crtc->offset;
|
||||
|
|
@ -5169,6 +5202,11 @@ fixup_flip:
|
|||
crtc->bo->active_scanout--;
|
||||
kgem_bo_destroy(&sna->kgem, crtc->bo);
|
||||
|
||||
if (crtc->shadow_bo) {
|
||||
kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
|
||||
crtc->shadow_bo = NULL;
|
||||
}
|
||||
|
||||
crtc->bo = kgem_bo_reference(bo);
|
||||
crtc->bo->active_scanout++;
|
||||
|
||||
|
|
@ -6723,11 +6761,11 @@ void sna_shadow_set_crtc(struct sna *sna,
|
|||
assert(sna_crtc);
|
||||
assert(!sna_crtc->transform);
|
||||
|
||||
if (sna_crtc->shadow_bo != bo) {
|
||||
if (sna_crtc->shadow_bo)
|
||||
kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
|
||||
if (sna_crtc->client_bo != bo) {
|
||||
if (sna_crtc->client_bo)
|
||||
kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
|
||||
|
||||
sna_crtc->shadow_bo = kgem_bo_reference(bo);
|
||||
sna_crtc->client_bo = kgem_bo_reference(bo);
|
||||
sna_crtc_damage(crtc);
|
||||
}
|
||||
|
||||
|
|
@ -6748,11 +6786,11 @@ void sna_shadow_unset_crtc(struct sna *sna,
|
|||
DBG(("%s: clearin shadow override for CRTC:%d\n",
|
||||
__FUNCTION__, sna_crtc->id));
|
||||
|
||||
if (sna_crtc->shadow_bo == NULL)
|
||||
if (sna_crtc->client_bo == NULL)
|
||||
return;
|
||||
|
||||
kgem_bo_destroy(&sna->kgem, sna_crtc->shadow_bo);
|
||||
sna_crtc->shadow_bo = NULL;
|
||||
kgem_bo_destroy(&sna->kgem, sna_crtc->client_bo);
|
||||
sna_crtc->client_bo = NULL;
|
||||
list_del(&sna_crtc->shadow_link);
|
||||
sna->mode.shadow_dirty = true;
|
||||
|
||||
|
|
@ -6884,7 +6922,7 @@ void sna_mode_redisplay(struct sna *sna)
|
|||
damage.extents = crtc->bounds;
|
||||
damage.data = NULL;
|
||||
|
||||
bo = sna_crtc->shadow_bo;
|
||||
bo = sna_crtc->client_bo;
|
||||
if (bo == NULL)
|
||||
bo = kgem_create_2d(&sna->kgem,
|
||||
crtc->mode.HDisplay,
|
||||
|
|
@ -6934,7 +6972,7 @@ disable1:
|
|||
}
|
||||
|
||||
kgem_bo_destroy(&sna->kgem, bo);
|
||||
sna_crtc->shadow_bo = NULL;
|
||||
sna_crtc->client_bo = NULL;
|
||||
continue;
|
||||
}
|
||||
sna->mode.flip_active++;
|
||||
|
|
@ -6945,7 +6983,7 @@ disable1:
|
|||
sna_crtc->flip_bo->active_scanout++;
|
||||
sna_crtc->flip_serial = sna_crtc->mode_serial;
|
||||
|
||||
sna_crtc->shadow_bo = kgem_bo_reference(sna_crtc->bo);
|
||||
sna_crtc->client_bo = kgem_bo_reference(sna_crtc->bo);
|
||||
} else {
|
||||
sna_crtc_redisplay(crtc, &damage, sna_crtc->bo);
|
||||
kgem_scanout_flush(&sna->kgem, sna_crtc->bo);
|
||||
|
|
@ -6992,14 +7030,14 @@ disable1:
|
|||
arg.crtc_id = crtc->id;
|
||||
arg.user_data = (uintptr_t)crtc;
|
||||
|
||||
if (crtc->shadow_bo) {
|
||||
if (crtc->client_bo) {
|
||||
DBG(("%s: apply shadow override bo for CRTC:%d on pipe=%d, handle=%d\n",
|
||||
__FUNCTION__, crtc->id, crtc->pipe, crtc->shadow_bo->handle));
|
||||
arg.fb_id = get_fb(sna, crtc->shadow_bo,
|
||||
__FUNCTION__, crtc->id, crtc->pipe, crtc->client_bo->handle));
|
||||
arg.fb_id = get_fb(sna, crtc->client_bo,
|
||||
crtc->base->mode.HDisplay,
|
||||
crtc->base->mode.VDisplay);
|
||||
assert(arg.fb_id != fb);
|
||||
flip_bo = crtc->shadow_bo;
|
||||
flip_bo = crtc->client_bo;
|
||||
x = y = 0;
|
||||
} else {
|
||||
if (fb == 0)
|
||||
|
|
@ -7047,6 +7085,11 @@ fixup_flip:
|
|||
crtc->bo->active_scanout--;
|
||||
kgem_bo_destroy(&sna->kgem, crtc->bo);
|
||||
|
||||
if (crtc->shadow_bo) {
|
||||
kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
|
||||
crtc->shadow_bo = NULL;
|
||||
}
|
||||
|
||||
crtc->bo = kgem_bo_reference(flip_bo);
|
||||
crtc->bo->active_scanout++;
|
||||
} else {
|
||||
|
|
@ -7152,6 +7195,11 @@ void sna_mode_wakeup(struct sna *sna)
|
|||
crtc->bo->active_scanout--;
|
||||
kgem_bo_destroy(&sna->kgem, crtc->bo);
|
||||
|
||||
if (crtc->shadow_bo) {
|
||||
kgem_bo_destroy(&sna->kgem, crtc->shadow_bo);
|
||||
crtc->shadow_bo = NULL;
|
||||
}
|
||||
|
||||
crtc->bo = crtc->flip_bo;
|
||||
crtc->flip_bo = NULL;
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue