typedef struct __DRIdri2ExtensionRec __DRIdri2Extension;
typedef struct __DRIdri2LoaderExtensionRec __DRIdri2LoaderExtension;
typedef struct __DRI2flushExtensionRec __DRI2flushExtension;
+typedef struct __DRI2throttleExtensionRec __DRI2throttleExtension;
/*@}*/
};
+/**
+ * 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.
const __DRI2flushExtension *f;
const __DRI2configQueryExtension *config;
const __DRItexBufferExtension *texBuffer;
+ const __DRI2throttleExtension *throttle;
const __DRIconfig **driver_configs;
void *driver;
#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;
(*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);
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)
{
struct dri2_display *pdp;
struct glx_context *gc;
struct dri2_drawable *pdraw = loaderPrivate;
+ struct dri2_screen *psc;
if (!pdraw)
return;
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);
/* 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
}
#endif
+ dri2Throttle(psc, priv, __DRI2_THROTTLE_SWAPBUFFER);
+
DRI2SwapBuffers(psc->base.dpy, pdraw->xDrawable,
target_msc, divisor, remainder, &ret);
#endif
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];
}
}