Tested-by: Dylan Baker <baker.dylan.c@xxxxxxxxx> On Wednesday, July 02, 2014 02:28:07 PM Keith Packard wrote: > A driver which doesn't have async flip support will queue up flips without any > way to replace them afterwards. This means we've got a scanout buffer pinned > as soon as we schedule a flip and so we need another buffer to keep from > stalling. > > When vblank_mode=0, if there are only three buffers we do: > > current scanout buffer = 0 at MSC 0 > > Render frame 1 to buffer 1 > PresentPixmap for buffer 1 at MSC 1 > > This is sitting down in the kernel waiting for vblank to > become the next scanout buffer > > Render frame 2 to buffer 2 > PresentPixmap for buffer 2 at MSC 1 > > This cannot be displayed at MSC 1 because the > kernel doesn't have any way to replace buffer 1 as the pending > scanout buffer. So, best case this will get displayed at MSC 2. > > Now we block after this, waiting for one of the three buffers to become idle. > We can't use buffer 0 because it is the scanout buffer. We can't use buffer 1 > because it's sitting in the kernel waiting to become the next scanout buffer > and we can't use buffer 2 because that's the most recent frame which will > become the next scanout buffer if the application doesn't manage to generate > another complete frame by MSC 2. > > With four buffers, we get: > > current scanout buffer = 0 at MSC 0 > > Render frame 1 to buffer 1 > PresentPixmap for buffer 1 at MSC 1 > > This is sitting down in the kernel waiting for vblank to > become the next scanout buffer > > Render frame 2 to buffer 2 > PresentPixmap for buffer 2 at MSC 1 > > This cannot be displayed at MSC 1 because the > kernel doesn't have any way to replace buffer 1 as the pending > scanout buffer. So, best case this will get displayed at MSC > 2. The X server will queue this swap until buffer 1 becomes > the scanout buffer. > > Render frame 3 to buffer 3 > PresentPixmap for buffer 3 at MSC 1 > > As soon as the X server sees this, it will replace the pending > buffer 2 swap with this swap and release buffer 2 back to the > application > > Render frame 4 to buffer 2 > PresentPixmap for buffer 2 at MSC 1 > > Now we're in a steady state, flipping between buffer 2 and 3 > waiting for one of them to be queued to the kernel. > > ... > > current scanout buffer = 1 at MSC 1 > > Now buffer 0 is free and (e.g.) buffer 2 is queued in > the kernel to be the scanout buffer at MSC 2 > > Render frames, flipping between buffer 0 and 3 > > When the system can replace a queued buffer, and we update Present to take > advantage of that, we can use three buffers and get: > > current scanout buffer = 0 at MSC 0 > > Render frame 1 to buffer 1 > PresentPixmap for buffer 1 at MSC 1 > > This is sitting waiting for vblank to become the next scanout > buffer > > Render frame 2 to buffer 2 > PresentPixmap for buffer 2 at MSC 1 > > Queue this for display at MSC 1 > 1. There are three possible results: > > 1) We're still before MSC 1. Buffer 1 is released, > buffer 2 is queued waiting for MSC 1. > > 2) We're now after MSC 1. Buffer 0 was released at MSC 1. > Buffer 1 is the current scanout buffer. > > a) If the user asked for a tearing update, we swap > scanout from buffer 1 to buffer 2 and release buffer > 1. > > b) If the user asked for non-tearing update, we > queue buffer 2 for the MSC 2. > > In all three cases, we have a buffer released (call it 'n'), > ready to receive the next frame. > > Render frame 3 to buffer n > PresentPixmap for buffer n > > If we're still before MSC 1, then we'll ask to present at MSC > 1. Otherwise, we'll ask to present at MSC 2. > > Present already does this if the driver offers async flips, however it does > this by waiting for the right vblank event and sending an async flip right at > that point. > > I've hacked the intel driver to offer this, but I get tearing at the top of > the screen. I think this is because flips are always done from within the > ring, and so the latency between the vblank event and the async flip happening > can cause tearing at the top of the screen. > > That's why I'm keying the need for the extra buffer on the lack of 2D > driver support for async flips. > > Signed-off-by: Keith Packard <keithp@xxxxxxxxxx> > --- > src/glx/dri3_glx.c | 20 +++++++++++++++++++- > src/glx/dri3_priv.h | 6 +++++- > 2 files changed, 24 insertions(+), 2 deletions(-) > > diff --git a/src/glx/dri3_glx.c b/src/glx/dri3_glx.c > index e3fc4de..753b8d8 100644 > --- a/src/glx/dri3_glx.c > +++ b/src/glx/dri3_glx.c > @@ -271,8 +271,11 @@ static void > dri3_update_num_back(struct dri3_drawable *priv) > { > priv->num_back = 1; > - if (priv->flipping) > + if (priv->flipping) { > + if (!priv->is_pixmap && !(priv->present_capabilities & XCB_PRESENT_CAPABILITY_ASYNC)) > + priv->num_back++; > priv->num_back++; > + } > if (priv->swap_interval == 0) > priv->num_back++; > } > @@ -976,6 +979,9 @@ dri3_update_drawable(__DRIdrawable *driDrawable, void *loaderPrivate) > xcb_get_geometry_reply_t *geom_reply; > xcb_void_cookie_t cookie; > xcb_generic_error_t *error; > + xcb_present_query_capabilities_cookie_t present_capabilities_cookie; > + xcb_present_query_capabilities_reply_t *present_capabilities_reply; > + > > /* Try to select for input on the window. > * > @@ -994,6 +1000,8 @@ dri3_update_drawable(__DRIdrawable *driDrawable, void *loaderPrivate) > XCB_PRESENT_EVENT_MASK_COMPLETE_NOTIFY| > XCB_PRESENT_EVENT_MASK_IDLE_NOTIFY); > > + present_capabilities_cookie = xcb_present_query_capabilities(c, priv->base.xDrawable); > + > /* Create an XCB event queue to hold present events outside of the usual > * application event queue > */ > @@ -1023,6 +1031,16 @@ dri3_update_drawable(__DRIdrawable *driDrawable, void *loaderPrivate) > > error = xcb_request_check(c, cookie); > > + present_capabilities_reply = xcb_present_query_capabilities_reply(c, > + present_capabilities_cookie, > + NULL); > + > + if (present_capabilities_reply) { > + priv->present_capabilities = present_capabilities_reply->capabilities; > + free(present_capabilities_reply); > + } else > + priv->present_capabilities = 0; > + > if (error) { > if (error->error_code != BadWindow) { > free(error); > diff --git a/src/glx/dri3_priv.h b/src/glx/dri3_priv.h > index c0e35ee..742db60 100644 > --- a/src/glx/dri3_priv.h > +++ b/src/glx/dri3_priv.h > @@ -147,7 +147,7 @@ struct dri3_context > __DRIcontext *driContext; > }; > > -#define DRI3_MAX_BACK 3 > +#define DRI3_MAX_BACK 4 > #define DRI3_BACK_ID(i) (i) > #define DRI3_FRONT_ID (DRI3_MAX_BACK) > > @@ -172,6 +172,10 @@ struct dri3_drawable { > uint8_t is_pixmap; > uint8_t flipping; > > + /* Present extension capabilities > + */ > + uint32_t present_capabilities; > + > /* SBC numbers are tracked by using the serial numbers > * in the present request and complete events > */ > -- > 2.0.0.rc4 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/mesa-dev
Attachment:
signature.asc
Description: This is a digitally signed message part.
_______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel