[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