summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/GL/internal/dri_interface.h22
-rw-r--r--src/glx/dri2_glx.c53
2 files changed, 72 insertions, 3 deletions
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index 8a9ca194913..4f768f0c829 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 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);
@@ -405,6 +432,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 +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];
}
}