[Mesa-dev] [PATCH] glx/dri3: Use four buffers until X driver supports async flips

Dylan Baker baker.dylan.c at gmail.com
Mon Sep 29 12:40:31 PDT 2014


Tested-by: Dylan Baker <baker.dylan.c at gmail.com>

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 at keithp.com>
> ---
>  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 at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 473 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20140929/68211387/attachment-0001.sig>


More information about the mesa-dev mailing list