diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-10-02 07:22:39 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-10-02 07:29:13 +0100 |
commit | a797c192adcc2b7aa9101089d3ee84b3e4f968ad (patch) | |
tree | 9ac48bb0e0b534df9da22f6acfbb3b68fc0996bb | |
parent | de7185bbf48ca2f617466b98328d0fdae4df1b44 (diff) |
sna/dri2: Disable tracking stale back buffers without reuse-notifications
If the Xorg does not support the ReuseNotify callback, and we use
double-bufferred pageflips, we set the stale flag on the backbuffer but
never clear it. This results in, for example, a compositor with Xorg-1.15
and Prime active from updating the framebuffer.
Reported-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_dri2.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index a43cdf1e..4ba2fd7c 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -249,25 +249,37 @@ inline static void *dri2_window_get_front(WindowPtr win) { return NULL; } #if DRI2INFOREC_VERSION < 6 -#define xorg_can_triple_buffer(ptr) 0 +#define xorg_can_triple_buffer() 0 #define swap_limit(d, l) false #else #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,904,0) /* Prime fixed for triple buffer support */ -#define xorg_can_triple_buffer(ptr) 1 +#define xorg_can_triple_buffer() 1 #elif XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,12,99,901,0) /* Before numGPUScreens was introduced */ -#define xorg_can_triple_buffer(ptr) 1 +#define xorg_can_triple_buffer() 1 #else /* Subject to crashers when combining triple buffering and Prime */ -inline static bool xorg_can_triple_buffer(struct sna *sna) +inline static bool xorg_can_triple_buffer(void) { return screenInfo.numGPUScreens == 0; } #endif +static void +mark_stale(DRI2BufferPtr back) +{ + /* If we have reuse notifications, we can track when the + * client tries to present an old buffer (one that has not + * been updated since the last swap) and avoid showing the + * stale frame. (This is mostly useful for tracking down + * driver bugs!) + */ + get_private(back)->stale = xorg_can_triple_buffer(); +} + static Bool sna_dri2_swap_limit_validate(DrawablePtr draw, int swap_limit) { @@ -1552,7 +1564,7 @@ sna_dri2_flip(struct sna *sna, struct sna_dri2_event *info) info->back->name = tmp_name; get_private(info->back)->bo = tmp_bo; - get_private(info->back)->stale = true; + mark_stale(info->back); assert(get_private(info->front)->bo->refcnt); assert(get_private(info->back)->bo->refcnt); @@ -1929,7 +1941,7 @@ sna_dri2_xchg(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back) get_private(front)->bo = back_bo; get_private(back)->bo = front_bo; - get_private(back)->stale = true; + mark_stale(back); tmp = front->name; front->name = back->name; @@ -2228,7 +2240,7 @@ void sna_dri2_vblank_handler(struct sna *sna, struct drm_event_vblank *event) __FUNCTION__, info->type, event->sequence, event->tv_sec, event->tv_usec)); - if (xorg_can_triple_buffer(sna)) { + if (xorg_can_triple_buffer()) { if (!sna_dri2_blit_complete(sna, info)) return; @@ -2348,7 +2360,7 @@ sna_dri2_flip_continue(struct sna *sna, struct sna_dri2_event *info) if (!sna_dri2_flip(sna, info)) return false; - if (!xorg_can_triple_buffer(sna)) { + if (!xorg_can_triple_buffer()) { sna_dri2_get_back(sna, info->draw, info->back, info); DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__)); frame_swap_complete(sna, info, DRI2_FLIP_COMPLETE); @@ -2386,7 +2398,7 @@ static void chain_flip(struct sna *sna) chain->back, chain->front, true); - if (xorg_can_triple_buffer(sna)) { + if (xorg_can_triple_buffer()) { union drm_wait_vblank vbl; VG_CLEAR(vbl); @@ -2499,7 +2511,7 @@ static int use_triple_buffer(struct sna *sna, ClientPtr client, bool async) return sna->flags & SNA_HAS_ASYNC_FLIP ? FLIP_ASYNC : FLIP_COMPLETE; } - if (xorg_can_triple_buffer(sna)) { + if (xorg_can_triple_buffer()) { DBG(("%s: triple buffer enabled, using FLIP_THROTTLE\n", __FUNCTION__)); return FLIP_THROTTLE; } @@ -2589,7 +2601,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc, } else { DBG(("%s: chaining flip\n", __FUNCTION__)); type = FLIP_THROTTLE; - if (xorg_can_triple_buffer(sna)) + if (xorg_can_triple_buffer()) info->mode = -type; else info->mode = -FLIP_COMPLETE; @@ -2631,7 +2643,7 @@ sna_dri2_schedule_flip(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc, swap_limit(draw, 1 + (type == FLIP_THROTTLE)); if (type >= FLIP_COMPLETE) { new_back: - if (!xorg_can_triple_buffer(sna)) + if (!xorg_can_triple_buffer()) sna_dri2_get_back(sna, draw, back, info); DBG(("%s: fake triple buffering, unblocking client\n", __FUNCTION__)); frame_swap_complete(sna, info, DRI2_EXCHANGE_COMPLETE); @@ -3316,7 +3328,7 @@ bool sna_dri2_open(struct sna *sna, ScreenPtr screen) #endif #if DRI2INFOREC_VERSION >= 6 - if (xorg_can_triple_buffer(sna)) { + if (xorg_can_triple_buffer()) { info.version = 6; info.SwapLimitValidate = sna_dri2_swap_limit_validate; info.ReuseBufferNotify = sna_dri2_reuse_buffer; |