[Mesa-dev] [PATCH 1/3] dri2: Implement a throttle dri extension.

Thomas Hellstrom thellstrom at vmware.com
Tue Oct 11 06:44:44 PDT 2011


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 <thellstrom at vmware.com>
---
 include/GL/internal/dri_interface.h |   22 ++++++++++++++
 src/glx/dri2_glx.c                  |   54 +++++++++++++++++++++++++++++++++--
 2 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 8a9ca19..4f768f0 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -84,6 +84,7 @@ typedef struct __DRIbufferRec			__DRIbuffer;
 typedef struct __DRIdri2ExtensionRec		__DRIdri2Extension;
 typedef struct __DRIdri2LoaderExtensionRec	__DRIdri2LoaderExtension;
 typedef struct __DRI2flushExtensionRec	__DRI2flushExtension;
+typedef struct __DRI2throttleExtensionRec	__DRI2throttleExtension;
 
 /*@}*/
 
@@ -284,6 +285,27 @@ struct __DRI2flushExtensionRec {
 
 
 /**
+ * Extension that the driver uses to request
+ * throttle callbacks.
+ */
+
+#define __DRI2_THROTTLE "DRI2_Throttle"
+#define __DRI2_THROTTLE_VERSION 1
+
+enum __DRI2throttleReason {
+   __DRI2_THROTTLE_SWAPBUFFER,
+   __DRI2_THROTTLE_COPYSUBBUFFER,
+   __DRI2_THROTTLE_FLUSHFRONT
+};
+
+struct __DRI2throttleExtensionRec {
+   __DRIextension base;
+   void (*throttle)(__DRIcontext *ctx,
+		    __DRIdrawable *drawable,
+		    enum __DRI2throttleReason reason);
+};
+
+/**
  * XML document describing the configuration options supported by the
  * driver.
  */
diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c
index 01e3fd6..37da073 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;
@@ -369,7 +370,9 @@ dri2WaitForSBC(__GLXDRIdrawable *pdraw, int64_t target_sbc, int64_t *ust,
 #endif /* X_DRI2WaitMSC */
 
 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 +393,15 @@ dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height)
       (*psc->f->flush) (priv->driDrawable);
 #endif
 
+   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, priv->driDrawable, reason);
+   }
+
    region = XFixesCreateRegion(psc->base.dpy, &xrect, 1);
    DRI2CopyRegion(psc->base.dpy, pdraw->xDrawable, region,
                   DRI2BufferFrontLeft, DRI2BufferBackLeft);
@@ -405,6 +417,15 @@ dri2CopySubBuffer(__GLXDRIdrawable *pdraw, int x, int y, int width, int height)
 }
 
 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)
 {
    XRectangle xrect;
@@ -458,6 +479,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 +487,22 @@ 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();
 
+   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,
+			      pdraw->driDrawable,
+			      __DRI2_THROTTLE_FLUSHFRONT);
+   }
+
    /* Old servers don't send invalidate events */
    if (!pdp->invalidateAvailable)
        dri2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable);
@@ -548,7 +582,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
@@ -560,6 +595,16 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
        }
     }
 #endif
+       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,
+	                          priv->driDrawable,
+				  __DRI2_THROTTLE_SWAPBUFFER);
+       }
 
        DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable,
 		       target_msc, divisor, remainder, &ret);
@@ -802,6 +847,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];
    }
 }
 
-- 
1.7.4.4



More information about the mesa-dev mailing list