From 511dc295f82c61acefe026d0f4de43d4a31dbf90 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Mon, 10 Oct 2011 16:38:19 +0200 Subject: dri2: Implement a throttle dri extension. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The X server has limited throttle support on the server side, but doing this in the client has some benefits: 1) X server throttling is per client. Client side throttling can be done per drawable. 2) It's easier to control the throttling based on what client is run, for example using "driconf". 3) X server throttling requires drm swap complete events. So implement a dri2 throttling extension intended to be used by direct rendering clients. Signed-off-by: Thomas Hellstrom Reviewed-by: Jakob Bornecrantz Reviewed-by: Michel Dänzer --- src/glx/dri2_glx.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) (limited to 'src/glx/dri2_glx.c') diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c index 01e3fd6cea0..940626c2020 100644 --- a/src/glx/dri2_glx.c +++ b/src/glx/dri2_glx.c @@ -85,6 +85,7 @@ struct dri2_screen { const __DRI2flushExtension *f; const __DRI2configQueryExtension *config; const __DRItexBufferExtension *texBuffer; + const __DRI2throttleExtension *throttle; const __DRIconfig **driver_configs; void *driver; @@ -368,8 +369,32 @@ dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust, #endif /* X_DRI2WaitMSC */ +/** + * dri2Throttle - Request driver throttling + * + * This function uses the DRI2 throttle extension to give the + * driver the opportunity to throttle on flush front, copysubbuffer + * and swapbuffers. + */ +static void +dri2Throttle(struct dri2_screen *psc, + struct dri2_drawable *draw, + enum __DRI2throttleReason reason) +{ + if (psc->throttle) { + struct glx_context *gc = __glXGetCurrentContext(); + struct dri2_context *dri2Ctx = (struct dri2_context *)gc; + __DRIcontext *ctx = + (dri2Ctx) ? dri2Ctx->driContext : NULL; + + psc->throttle->throttle(ctx, draw->driDrawable, reason); + } +} + static void -dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) +__dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, + int width, int height, + enum __DRI2throttleReason reason) { struct dri2_drawable *priv = (struct dri2_drawable *) pdraw; struct dri2_screen *psc = (struct dri2_screen *) pdraw->psc; @@ -390,6 +415,8 @@ dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) (*psc->f->flush) (priv->driDrawable); #endif + dri2Throttle(psc, priv, reason); + region = XFixesCreateRegion(psc->base.dpy, &xrect, 1); DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region, DRI2BufferFrontLeft, DRI2BufferBackLeft); @@ -404,6 +431,15 @@ dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height) XFixesDestroyRegion(psc->base.dpy, region); } +static void +dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, + int width, int height) +{ + __dri2CopySubBuffer(pdraw, x, y, width, height, + __DRI2_THROTTLE_COPYSUBBUFFER); +} + + static void dri2_copy_drawable(struct dri2_drawable *priv, int dest, int src) { @@ -458,6 +494,7 @@ dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) struct dri2_display *pdp; struct glx_context *gc; struct dri2_drawable *pdraw = loaderPrivate; + struct dri2_screen *psc; if (!pdraw) return; @@ -465,10 +502,14 @@ dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate) if (!pdraw->base.psc) return; - priv = __glXInitialize(pdraw->base.psc->dpy); + psc = (struct dri2_screen *) pdraw->base.psc; + + priv = __glXInitialize(psc->base.dpy); pdp = (struct dri2_display *) priv->dri2Display; gc = __glXGetCurrentContext(); + dri2Throttle(psc, pdraw, __DRI2_THROTTLE_FLUSHFRONT); + /* Old servers don't send invalidate events */ if (!pdp->invalidateAvailable) dri2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable); @@ -548,7 +589,8 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, /* Old servers can't handle swapbuffers */ if (!pdp->swapAvailable) { - dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); + __dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height, + __DRI2_THROTTLE_SWAPBUFFER); } else { #ifdef X_DRI2SwapBuffers #ifdef __DRI2_FLUSH @@ -561,6 +603,8 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor, } #endif + dri2Throttle(psc, priv, __DRI2_THROTTLE_SWAPBUFFER); + DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable, target_msc, divisor, remainder, &ret); #endif @@ -802,6 +846,9 @@ dri2BindExtensions(struct dri2_screen *psc, const __DRIextension **extensions) if ((strcmp(extensions[i]->name, __DRI2_CONFIG_QUERY) == 0)) psc->config = (__DRI2configQueryExtension *) extensions[i]; + + if (((strcmp(extensions[i]->name, __DRI2_THROTTLE) == 0))) + psc->throttle = (__DRI2throttleExtension *) extensions[i]; } } -- cgit v1.2.3