From 22cd7c873edd0b641e54e81d643ec6b0ea921f88 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 8 Jun 2014 08:46:27 +0100 Subject: [PATCH] sna/dri2: Explicitly drain the pending event queue before swapping As there may be some latency between the wakeup and the queue, do a final check if there is a pending vblank event before we decide whether to chain up or perform an immediate flip. Signed-off-by: Chris Wilson --- src/sna/sna_dri2.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/sna/sna_dri2.c b/src/sna/sna_dri2.c index a6f10139..314651e6 100644 --- a/src/sna/sna_dri2.c +++ b/src/sna/sna_dri2.c @@ -40,6 +40,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include #include "sna.h" #include "intel_options.h" @@ -209,13 +210,14 @@ struct dri2_window { static struct dri2_window *dri2_window(WindowPtr win) { + assert(win->drawable.type != DRAWABLE_PIXMAP); return ((void **)__get_private(win, sna_window_key))[1]; } static struct sna_dri2_event * -sna_dri2_window_get_chain(WindowPtr win) +dri2_chain(DrawablePtr d) { - struct dri2_window *priv = dri2_window(win); + struct dri2_window *priv = dri2_window((WindowPtr)d); assert(priv != NULL); return priv->chain; } @@ -246,8 +248,7 @@ sna_dri2_reuse_buffer(DrawablePtr draw, DRI2BufferPtr buffer) if (buffer->attachment == DRI2BufferBackLeft && draw->type != DRAWABLE_PIXMAP) { DBG(("%s: replacing back buffer\n", __FUNCTION__)); - sna_dri2_get_back(to_sna_from_drawable(draw), buffer, - sna_dri2_window_get_chain((WindowPtr)draw)); + sna_dri2_get_back(to_sna_from_drawable(draw), buffer, dri2_chain(draw)); assert(kgem_bo_flink(&to_sna_from_drawable(draw)->kgem, get_private(buffer)->bo) == buffer->name); assert(get_private(buffer)->bo->active_scanout == 0); @@ -1615,7 +1616,7 @@ static void chain_swap(struct sna *sna, struct sna_dri2_event *chain) if (chain->queued) /* too early! */ return; - assert(chain == sna_dri2_window_get_chain((WindowPtr)chain->draw)); + assert(chain == dri2_chain((WindowPtr)chain->draw)); DBG(("%s: chaining draw=%ld, type=%d\n", __FUNCTION__, (long)chain->draw->id, chain->type)); chain->queued = true; @@ -1826,11 +1827,11 @@ sna_dri2_immediate_blit(struct sna *sna, sync = false; DBG(("%s: emitting immediate blit, throttling client, synced? %d, chained? %d, send-event? %d\n", - __FUNCTION__, sync, sna_dri2_window_get_chain((WindowPtr)draw) != info, + __FUNCTION__, sync, dri2_chain(draw) != info, event)); info->type = SWAP_THROTTLE; - if (!sync || sna_dri2_window_get_chain((WindowPtr)draw) == info) { + if (!sync || dri2_chain(draw) == info) { DBG(("%s: no pending blit, starting chain\n", __FUNCTION__)); @@ -1923,7 +1924,7 @@ static void chain_flip(struct sna *sna) return; } - assert(chain == sna_dri2_window_get_chain((WindowPtr)chain->draw)); + assert(chain == dri2_chain(chain->draw)); chain->queued = true; if (can_flip(sna, chain->draw, chain->front, chain->back, chain->crtc) && @@ -2266,7 +2267,7 @@ sna_dri2_schedule_xchg(ClientPtr client, DrawablePtr draw, xf86CrtcPtr crtc, return false; sync = current_msc < *target_msc; - event = sna_dri2_window_get_chain((WindowPtr)draw) == NULL; + event = dri2_chain(draw) == NULL; if (!sync || event) { DBG(("%s: performing immediate xchg on pipe %d\n", __FUNCTION__, sna_crtc_to_pipe(crtc))); @@ -2313,6 +2314,14 @@ complete: return true; } +static bool has_pending_events(struct sna *sna) +{ + struct pollfd pfd; + pfd.fd = sna->kgem.fd; + pfd.events = POLLIN; + return poll(&pfd, 1, 0) == 1; +} + /* * ScheduleSwap is responsible for requesting a DRM vblank event for the * appropriate frame. @@ -2386,6 +2395,13 @@ sna_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front, goto blit; } + assert(draw->type != DRAWABLE_PIXMAP); + + while (dri2_chain(draw) && has_pending_events(sna)) { + DBG(("%s: flushing pending events\n", __FUNCTIONS__)); + sna_mode_wakeup(sna); + } + if (can_xchg(sna, draw, front, back) && sna_dri2_schedule_xchg(client, draw, crtc, front, back, target_msc, divisor, remainder,