From patchwork Mon Jan 19 11:00:45 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Wilson X-Patchwork-Id: 5657431 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 5EB66C058D for ; Mon, 19 Jan 2015 11:17:26 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6614E20131 for ; Mon, 19 Jan 2015 11:17:25 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id D5E882035B for ; Mon, 19 Jan 2015 11:17:22 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 323466E54C; Mon, 19 Jan 2015 03:17:17 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from relay.fireflyinternet.com (hostedrelay.fireflyinternet.com [109.228.30.76]) by gabe.freedesktop.org (Postfix) with ESMTP id 04DB26E051; Mon, 19 Jan 2015 03:17:15 -0800 (PST) X-Default-Received-SPF: pass (skip=forwardok (res=PASS)) x-ip-name=78.156.65.138; Received: from haswell.alporthouse.com (unverified [78.156.65.138]) by relay.fireflyinternet.com (FireflyRelay1) with ESMTP id 12848044-1305619 for multiple; Mon, 19 Jan 2015 11:00:54 +0000 From: Chris Wilson To: xorg-devel@lists.x.org, dri-devel@lists.freedesktop.org, mesa-dev@lists.freedesktop.org Subject: [mesa 9/9] glx/dri2: Implement getBufferAge Date: Mon, 19 Jan 2015 11:00:45 +0000 Message-Id: <1421665245-5994-10-git-send-email-chris@chris-wilson.co.uk> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1421665245-5994-1-git-send-email-chris@chris-wilson.co.uk> References: <1421665245-5994-1-git-send-email-chris@chris-wilson.co.uk> X-Authenticated-User: chris.alporthouse@surfanytime.net X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Within the DRI2GetBuffers return packet there is a 4-byte field that is currently unused by any driver, i.e. flags. With the co-operation of a suitably modified X server, we can pass the last SBC on which the buffer was defined (i.e. the last SwapBuffers for which it was used) and 0 if it is fresh (with a slight loss of precision). We can then compare the flags field of the DRIBuffer against the current swap buffers count and so compute the age of the back buffer (thus satisfying GLX_EXT_buffer_age). As we reuse a driver specific field within the DRI2GetBuffers packet, we first query whether the X/DDX are ready to supply the new value using a DRI2GetParam request. Another caveat is that we need to complete the SwapBuffers/GetBuffers roundtrip before reporting the back buffer age so that it tallies against the buffer used for rendering. As with all things X, there is a race between the query and the rendering where the buffer may be invalidated by the server. However, for the primary usecase (that of a compositing manager), the DRI2Drawable is only accessible to a single client mitigating the impact of the issue. Signed-off-by: Chris Wilson --- configure.ac | 2 +- src/glx/dri2_glx.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 870435c..ca1da86 100644 --- a/configure.ac +++ b/configure.ac @@ -65,7 +65,7 @@ LIBDRM_INTEL_REQUIRED=2.4.52 LIBDRM_NVVIEUX_REQUIRED=2.4.33 LIBDRM_NOUVEAU_REQUIRED="2.4.33 libdrm >= 2.4.41" LIBDRM_FREEDRENO_REQUIRED=2.4.57 -DRI2PROTO_REQUIRED=2.6 +DRI2PROTO_REQUIRED=2.9 DRI3PROTO_REQUIRED=1.0 PRESENTPROTO_REQUIRED=1.0 LIBUDEV_REQUIRED=151 diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c index 0577804..b43f115 100644 --- a/src/glx/dri2_glx.c +++ b/src/glx/dri2_glx.c @@ -917,6 +917,67 @@ dri2GetBuffersWithFormat(__DRIdrawable * driDrawable, } static int +dri2HasBufferAge(int screen, struct glx_display * priv) +{ + const struct dri2_display *const pdp = + (struct dri2_display *)priv->dri2Display; + CARD64 value; + + if (pdp->driMajor <= 1 && pdp->driMinor < 4) + return 0; + + value = 0; + if (!DRI2GetParam(priv->dpy, RootWindow(priv->dpy, screen), + DRI2ParamXHasBufferAge, &value)) + return 0; + + return value; +} + +static int +dri2GetBufferAge(__GLXDRIdrawable *pdraw) +{ + struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; + int i, age = 0; + + if (priv->swap_pending) { + unsigned int attachments[5]; + DRI2Buffer *buffers; + + for (i = 0; i < priv->bufferCount; i++) + attachments[i] = priv->buffers[i].attachment; + + buffers = DRI2GetBuffers(priv->base.psc->dpy, priv->base.xDrawable, + &priv->width, &priv->height, + attachments, i, &i); + if (buffers == NULL) + return 0; + + process_buffers(priv, buffers, i); + free(buffers); + + dri2XcbSwapBuffersComplete(priv); + } + + if (!priv->have_back) + return 0; + + for (i = 0; i < priv->bufferCount; i++) { + if (priv->buffers[i].attachment != __DRI_BUFFER_BACK_LEFT) + continue; + + if (priv->buffers[i].flags == 0) + continue; + + age = priv->last_swap_sbc - priv->buffers[i].flags + 1; + if (age < 0) + age = 0; + } + + return age; +} + +static int dri2SetSwapInterval(__GLXDRIdrawable *pdraw, int interval) { xcb_connection_t *c = XGetXCBConnection(pdraw->psc->dpy); @@ -1290,6 +1351,10 @@ dri2CreateScreen(int screen, struct glx_display * priv) psp->setSwapInterval = NULL; psp->getSwapInterval = NULL; psp->getBufferAge = NULL; + if (dri2HasBufferAge(screen, priv)) { + psp->getBufferAge = dri2GetBufferAge; + __glXEnableDirectExtension(&psc->base, "GLX_EXT_buffer_age"); + } if (pdp->driMinor >= 2) { psp->getDrawableMSC = dri2DrawableGetMSC;