sna/present: Integrate into TearFree, take 2
Following on from the previous attempt is the realisation that we can simply disable TearFree during a Present flip queue, and re-enable TearFree upon unflip. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
c30af937f8
commit
74553bf4d2
|
|
@ -311,13 +311,6 @@ struct sna {
|
|||
Bool (*rrGetInfo)(ScreenPtr, Rotation *);
|
||||
} mode;
|
||||
|
||||
struct sna_tearfree {
|
||||
struct notifier {
|
||||
void (*func)(struct sna *, void *);
|
||||
void *data;
|
||||
} hook[2];
|
||||
} tearfree;
|
||||
|
||||
struct {
|
||||
struct sna_cursor *cursors;
|
||||
xf86CursorInfoPtr info;
|
||||
|
|
@ -363,6 +356,7 @@ struct sna {
|
|||
bool open;
|
||||
#if HAVE_PRESENT
|
||||
uint64_t unflip;
|
||||
void *tearfree;
|
||||
#endif
|
||||
} present;
|
||||
|
||||
|
|
|
|||
|
|
@ -1398,39 +1398,24 @@ static bool sna_mode_enable_shadow(struct sna *sna)
|
|||
if (!sna->mode.shadow_damage)
|
||||
return false;
|
||||
|
||||
DamageRegister(&screen->GetScreenPixmap(screen)->drawable,
|
||||
sna->mode.shadow_damage);
|
||||
DamageRegister(&sna->front->drawable, sna->mode.shadow_damage);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline static PixmapPtr sna_screen_pixmap(struct sna *sna)
|
||||
{
|
||||
return to_screen_from_sna(sna)->GetScreenPixmap(to_screen_from_sna(sna));
|
||||
}
|
||||
|
||||
static void sna_mode_disable_shadow(struct sna *sna)
|
||||
{
|
||||
struct sna_pixmap *priv;
|
||||
struct notifier *nb;
|
||||
|
||||
if (!sna->mode.shadow_damage)
|
||||
return;
|
||||
|
||||
DBG(("%s\n", __FUNCTION__));
|
||||
|
||||
nb = &sna->tearfree.hook[0];
|
||||
if (nb->func) {
|
||||
nb->func(sna, nb->data);
|
||||
nb->func = NULL;
|
||||
}
|
||||
assert(sna->tearfree.hook[1].func == NULL);
|
||||
|
||||
priv = sna_pixmap(sna->front);
|
||||
if (priv->move_to_gpu == wait_for_shadow)
|
||||
priv->move_to_gpu(sna, priv, 0);
|
||||
|
||||
DamageUnregister(&sna_screen_pixmap(sna)->drawable,
|
||||
sna->mode.shadow_damage);
|
||||
DamageUnregister(&sna->front->drawable, sna->mode.shadow_damage);
|
||||
DamageDestroy(sna->mode.shadow_damage);
|
||||
sna->mode.shadow_damage = NULL;
|
||||
|
||||
|
|
@ -7121,14 +7106,6 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region, struct kgem_bo *bo)
|
|||
static void shadow_flip_handler(struct drm_event_vblank *e,
|
||||
void *data)
|
||||
{
|
||||
struct sna *sna = data;
|
||||
|
||||
if (sna->tearfree.hook[0].func)
|
||||
sna->tearfree.hook[0].func(sna, sna->tearfree.hook[0].data);
|
||||
|
||||
sna->tearfree.hook[0] = sna->tearfree.hook[1];
|
||||
sna->tearfree.hook[1].func = NULL;
|
||||
|
||||
sna_mode_redisplay(data);
|
||||
}
|
||||
|
||||
|
|
@ -7731,12 +7708,6 @@ fixup_flip:
|
|||
assert(old == sna->mode.shadow);
|
||||
assert(old->refcnt >= 1);
|
||||
set_shadow(sna, region);
|
||||
} else {
|
||||
if (sna->tearfree.hook[0].func) {
|
||||
sna->tearfree.hook[0].func(sna, sna->tearfree.hook[0].data);
|
||||
sna->tearfree.hook[0].func = NULL;
|
||||
}
|
||||
assert(sna->tearfree.hook[1].func == NULL);
|
||||
}
|
||||
} else
|
||||
kgem_submit(&sna->kgem);
|
||||
|
|
|
|||
|
|
@ -503,128 +503,6 @@ get_flip_bo(PixmapPtr pixmap)
|
|||
return priv->gpu_bo;
|
||||
}
|
||||
|
||||
static bool set_front(struct sna *sna, PixmapPtr pixmap)
|
||||
{
|
||||
RegionRec *damage;
|
||||
|
||||
DBG(("%s: pixmap=%ld\n", __FUNCTION__, pixmap->drawable.serialNumber));
|
||||
|
||||
if (pixmap == sna->front)
|
||||
return false;
|
||||
|
||||
sna_pixmap_discard_shadow_damage(sna_pixmap(sna->front), NULL);
|
||||
sna->front = pixmap;
|
||||
|
||||
/* We rely on unflip restoring the real front before any drawing */
|
||||
damage = DamageRegion(sna->mode.shadow_damage);
|
||||
RegionUninit(damage);
|
||||
damage->extents.x1 = 0;
|
||||
damage->extents.y1 = 0;
|
||||
damage->extents.x2 = pixmap->drawable.width;
|
||||
damage->extents.y2 = pixmap->drawable.height;
|
||||
damage->data = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
xchg_handler(struct sna *sna, void *data)
|
||||
{
|
||||
struct sna_present_event *info = data;
|
||||
const struct ust_msc *swap = sna_crtc_last_swap(info->crtc);
|
||||
|
||||
DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
|
||||
sna_crtc_to_pipe(info->crtc),
|
||||
swap->tv_sec, swap->tv_usec,
|
||||
(long long)swap->msc,
|
||||
(long long)info->target_msc, (long long)info->event_id));
|
||||
present_event_notify(info->event_id, swap_ust(swap), swap->msc);
|
||||
free(info);
|
||||
}
|
||||
|
||||
static Bool
|
||||
xchg(struct sna *sna,
|
||||
RRCrtcPtr crtc,
|
||||
uint64_t event_id,
|
||||
uint64_t target_msc,
|
||||
PixmapPtr pixmap,
|
||||
Bool sync_flip)
|
||||
{
|
||||
struct sna_present_event *info;
|
||||
bool queued;
|
||||
|
||||
DBG(("%s(pipe=%d, event=%lld, sync_flip=%d)\n",
|
||||
__FUNCTION__,
|
||||
pipe_from_crtc(crtc),
|
||||
(long long)event_id,
|
||||
sync_flip));
|
||||
|
||||
assert(sna->flags & SNA_TEAR_FREE);
|
||||
assert(sna->mode.shadow_damage);
|
||||
assert(sna_pixmap(pixmap) && sna_pixmap(pixmap)->gpu_bo);
|
||||
assert(sync_flip);
|
||||
|
||||
/* This effectively disables TearFree giving the client direct
|
||||
* access into the scanout with their Pixmap.
|
||||
*/
|
||||
queued = set_front(sna, pixmap);
|
||||
|
||||
info = malloc(sizeof(struct sna_present_event));
|
||||
if (info == NULL)
|
||||
return BadAlloc;
|
||||
|
||||
info->crtc = crtc->devPrivate;
|
||||
info->sna = sna;
|
||||
info->target_msc = target_msc;
|
||||
info->event_id = event_id;
|
||||
|
||||
if (queued) {
|
||||
struct notifier *nb;
|
||||
|
||||
nb = &sna->tearfree.hook[0];
|
||||
if (nb->func)
|
||||
nb++;
|
||||
if (nb->func) {
|
||||
DBG(("%s: executing existing notifier\n", __FUNCTION__));
|
||||
nb->func(sna, nb->data);
|
||||
}
|
||||
DBG(("%s: queueing tearfree notifier: sequence %d\n",
|
||||
__FUNCTION__, nb - &sna->tearfree.hook[0]));
|
||||
nb->func = xchg_handler;
|
||||
nb->data = info;
|
||||
} else {
|
||||
union drm_wait_vblank vbl;
|
||||
|
||||
DBG(("%s: queueing vblank notifier\n", __FUNCTION__));
|
||||
|
||||
VG_CLEAR(vbl);
|
||||
vbl.request.type =
|
||||
DRM_VBLANK_ABSOLUTE |
|
||||
DRM_VBLANK_EVENT |
|
||||
DRM_VBLANK_NEXTONMISS;
|
||||
vbl.request.sequence = target_msc;
|
||||
vbl.request.signal = (uintptr_t)MARK_PRESENT(info);
|
||||
if (sna_wait_vblank(sna, &vbl, sna_crtc_to_pipe(info->crtc))) {
|
||||
DBG(("%s: vblank enqueue failed\n", __FUNCTION__));
|
||||
if (!sna_fake_vblank(info)) {
|
||||
free(info);
|
||||
goto notify;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
notify:
|
||||
DBG(("%s: pipe=%d tv=%d.%06d msc=%lld (target=%lld), event=%lld complete\n", __FUNCTION__,
|
||||
pipe_from_crtc(crtc),
|
||||
gettime_ust64() / 1000000, gettime_ust64() % 1000000,
|
||||
(long long)sna_crtc_last_swap(crtc->devPrivate)->msc,
|
||||
(long long)target_msc, (long long)event_id));
|
||||
present_event_notify(event_id, gettime_ust64(), target_msc);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
sna_present_flip(RRCrtcPtr crtc,
|
||||
uint64_t event_id,
|
||||
|
|
@ -655,8 +533,11 @@ sna_present_flip(RRCrtcPtr crtc,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if (sna->flags & SNA_TEAR_FREE)
|
||||
return xchg(sna, crtc, event_id, target_msc, pixmap, sync_flip);
|
||||
if (sna->flags & SNA_TEAR_FREE) {
|
||||
sna->present.tearfree = sna->mode.shadow_damage;
|
||||
sna->mode.shadow_damage = NULL;
|
||||
sna->flags &= ~SNA_TEAR_FREE;
|
||||
}
|
||||
|
||||
if (sna->mode.flip_active) {
|
||||
DBG(("%s: flips still pending\n", __FUNCTION__));
|
||||
|
|
@ -674,6 +555,7 @@ sna_present_unflip(ScreenPtr screen, uint64_t event_id)
|
|||
{
|
||||
struct sna *sna = to_sna_from_screen(screen);
|
||||
struct kgem_bo *bo;
|
||||
bool ok;
|
||||
|
||||
DBG(("%s(event=%lld)\n", __FUNCTION__, (long long)event_id));
|
||||
if (sna->mode.front_active == 0 || sna->mode.rr_active) {
|
||||
|
|
@ -691,11 +573,6 @@ notify:
|
|||
return;
|
||||
}
|
||||
|
||||
if (sna->flags & SNA_TEAR_FREE) {
|
||||
set_front(sna, screen->GetScreenPixmap(screen));
|
||||
goto notify;
|
||||
}
|
||||
|
||||
if (sna->mode.flip_active) {
|
||||
DBG(("%s: %d outstanding flips, queueing unflip\n", __FUNCTION__, sna->mode.flip_active));
|
||||
assert(sna->present.unflip == 0);
|
||||
|
|
@ -711,13 +588,21 @@ reset_mode:
|
|||
goto notify;
|
||||
}
|
||||
|
||||
ok = false;
|
||||
if (sna->flags & SNA_HAS_ASYNC_FLIP) {
|
||||
DBG(("%s: trying async flip restore\n", __FUNCTION__));
|
||||
if (flip__async(sna, NULL, event_id, 0, bo))
|
||||
return;
|
||||
ok = flip__async(sna, NULL, event_id, 0, bo);
|
||||
}
|
||||
if (!ok)
|
||||
ok = flip(sna, NULL, event_id, 0, bo);
|
||||
|
||||
if (sna->present.tearfree) {
|
||||
sna->flags |= SNA_TEAR_FREE;
|
||||
sna->mode.shadow_damage = sna->present.tearfree;
|
||||
sna->present.tearfree = NULL;
|
||||
}
|
||||
|
||||
if (!flip(sna, NULL, event_id, 0, bo))
|
||||
if (!ok)
|
||||
goto reset_mode;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue