[mesa patch v3 1/3] dri2: Event driven buffer validation.
Francisco Jerez
currojerez at riseup.net
Fri Jan 22 06:30:56 PST 2010
When a buffer invalidation event is received from the X server, the
"invalidate" hook of the DRI2 flush extension is executed: A generic
implementation (dri2InvalidateDrawable) is provided that just bumps
the "pStamp" sequence number in __DRIdrawableRec.
For old servers not supporting buffer invalidation events, the
invalidate hook will be called after flushing the fake front/back
buffer (that's typically once per frame -- not a lot worse than the
situation we were in before).
Backwards compatibility should be preserved with version 2 of the
flush extension, but the "flushInvalidate" callback has been marked as
deprecated.
Note that this bumps the required dri2proto version to 2.3.
---
configure.ac | 2 +-
include/GL/internal/dri_interface.h | 16 ++++++++++-
src/glx/x11/dri2.c | 10 ++++++-
src/glx/x11/dri2.h | 3 ++
src/glx/x11/dri2_glx.c | 37 ++++++++++++++++++++-----
src/glx/x11/glx_pbuffer.c | 4 ---
src/glx/x11/glxclient.h | 4 +++
src/glx/x11/glxcmds.c | 4 ---
src/mesa/drivers/dri/common/dri_util.c | 15 ++++++++++-
src/mesa/drivers/dri/common/dri_util.h | 8 +++--
src/mesa/drivers/dri/intel/intel_context.c | 1 -
src/mesa/drivers/dri/intel/intel_screen.c | 2 +-
src/mesa/drivers/dri/intel/intel_tex_image.c | 4 ++-
13 files changed, 84 insertions(+), 26 deletions(-)
diff --git a/configure.ac b/configure.ac
index 6ae526d..0efbeb0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@ AC_CANONICAL_HOST
dnl Versions for external dependencies
LIBDRM_REQUIRED=2.4.15
LIBDRM_RADEON_REQUIRED=2.4.17
-DRI2PROTO_REQUIRED=2.2
+DRI2PROTO_REQUIRED=2.3
GLPROTO_REQUIRED=1.4.11
dnl Check for progs
diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h
index ec6238f..e818744 100644
--- a/include/GL/internal/dri_interface.h
+++ b/include/GL/internal/dri_interface.h
@@ -262,7 +262,7 @@ struct __DRItexBufferExtensionRec {
* Used by drivers that implement DRI2
*/
#define __DRI2_FLUSH "DRI2_Flush"
-#define __DRI2_FLUSH_VERSION 2
+#define __DRI2_FLUSH_VERSION 3
struct __DRI2flushExtensionRec {
__DRIextension base;
void (*flush)(__DRIdrawable *drawable);
@@ -273,11 +273,25 @@ struct __DRI2flushExtensionRec {
* getBuffers/getBuffersWithFormat before it starts rendering
* again.
*
+ * This function is only called when \c SwapBuffers is the reason
+ * buffers have become invalid, and it's deprecated in favor of
+ * \c ::invalidate.
+ *
* \param drawable the drawable to flush and invalidate
*
* \since 2
*/
void (*flushInvalidate)(__DRIdrawable *drawable);
+
+ /**
+ * Ask the driver to call getBuffers/getBuffersWithFormat before
+ * it starts rendering again.
+ *
+ * \param drawable the drawable to invalidate
+ *
+ * \since 3
+ */
+ void (*invalidate)(__DRIdrawable *drawable);
};
diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c
index 2cb5d34..4a84066 100644
--- a/src/glx/x11/dri2.c
+++ b/src/glx/x11/dri2.c
@@ -81,7 +81,7 @@ static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
dri2Info,
dri2ExtensionName,
&dri2ExtensionHooks,
- 0, NULL)
+ DRI2NumberEvents, NULL)
static Bool
DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
@@ -95,6 +95,7 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
{
GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event;
xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
+
switch (awire->type) {
case DRI2_EXCHANGE_COMPLETE:
aevent->event_type = GLX_EXCHANGE_COMPLETE;
@@ -115,6 +116,13 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo;
return True;
}
+ case DRI2_InvalidateBuffers:
+ {
+ xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
+
+ DRI2InvalidateBuffers(dpy, awire->drawable);
+ return False;
+ }
default:
/* client doesn't support server event */
break;
diff --git a/src/glx/x11/dri2.h b/src/glx/x11/dri2.h
index 114e9f8..943ac59 100644
--- a/src/glx/x11/dri2.h
+++ b/src/glx/x11/dri2.h
@@ -103,4 +103,7 @@ DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
extern void
DRI2SwapInterval(Display *dpy, XID drawable, int interval);
+extern void
+DRI2InvalidateBuffers(Display *dpy, XID drawable);
+
#endif
diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c
index 7b0c52b..73f988d 100644
--- a/src/glx/x11/dri2_glx.c
+++ b/src/glx/x11/dri2_glx.c
@@ -67,6 +67,7 @@ struct __GLXDRIdisplayPrivateRec
int driMinor;
int driPatch;
int swapAvailable;
+ int invalidateAvailable;
};
struct __GLXDRIcontextPrivateRec
@@ -310,12 +311,18 @@ dri2WaitGL(__GLXDRIdrawable * pdraw)
XFixesDestroyRegion(pdraw->psc->dpy, region);
}
-
static void
-dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate)
+dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
{
- (void) driDrawable;
- dri2WaitGL((__GLXDRIdrawable *) loaderPrivate);
+ __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
+ __GLXdisplayPrivate *priv = __glXInitialize(pdraw->base.psc->dpy);
+ __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)priv->dri2Display;
+
+ /* Old servers don't send invalidate events */
+ if (!pdp->invalidateAvailable)
+ DRI2InvalidateBuffers(priv->dpy, pdraw->base.xDrawable);
+
+ dri2WaitGL(loaderPrivate);
}
@@ -375,6 +382,10 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
(*pdraw->psc->f->flush)(pdraw->driDrawable);
#endif
+ /* Old servers don't send invalidate events */
+ if (!pdp->invalidateAvailable)
+ DRI2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable);
+
/* Old servers can't handle swapbuffers */
if (!pdp->swapAvailable) {
dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
@@ -385,7 +396,7 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
remainder, &ret);
#if __DRI2_FLUSH_VERSION >= 2
- if (pdraw->psc->f)
+ if (pdraw->psc->f && pdraw->psc->f->flushInvalidate)
(*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
#endif
@@ -483,6 +494,17 @@ static const __DRIextension *loader_extensions_old[] = {
NULL
};
+_X_HIDDEN void
+DRI2InvalidateBuffers(Display *dpy, XID drawable)
+{
+ __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
+
+#if __DRI2_FLUSH_VERSION >= 3
+ if (pdraw && pdraw->psc->f)
+ pdraw->psc->f->invalidate(pdraw->driDrawable);
+#endif
+}
+
static __GLXDRIscreen *
dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
__GLXdisplayPrivate * priv)
@@ -640,9 +662,8 @@ dri2CreateDisplay(Display * dpy)
}
pdp->driPatch = 0;
- pdp->swapAvailable = 0;
- if (pdp->driMinor >= 2)
- pdp->swapAvailable = 1;
+ pdp->swapAvailable = (pdp->driMinor >= 2);
+ pdp->invalidateAvailable = (pdp->driMinor >= 3);
pdp->base.destroyDisplay = dri2DestroyDisplay;
pdp->base.createScreen = dri2CreateScreen;
diff --git a/src/glx/x11/glx_pbuffer.c b/src/glx/x11/glx_pbuffer.c
index 501500a..15dffed 100644
--- a/src/glx/x11/glx_pbuffer.c
+++ b/src/glx/x11/glx_pbuffer.c
@@ -188,10 +188,6 @@ DestroyPbuffer(Display * dpy, GLXDrawable drawable)
#ifdef GLX_DIRECT_RENDERING
-extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
- GLXDrawable drawable,
- int *const scrn_num);
-
static GLenum
determineTextureTarget(const int *attribs, int numAttribs)
{
diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h
index ded4f5a..970cbe0 100644
--- a/src/glx/x11/glxclient.h
+++ b/src/glx/x11/glxclient.h
@@ -793,6 +793,10 @@ extern GLboolean __glXGetMscRateOML(Display * dpy, GLXDrawable drawable,
GLboolean
__driGetMscRateOML(__DRIdrawable * draw,
int32_t * numerator, int32_t * denominator, void *private);
+
+extern __GLXDRIdrawable *
+GetGLXDRIDrawable(Display *dpy, GLXDrawable drawable, int *const scrn_num);
+
#endif
#endif /* !__GLX_client_h__ */
diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c
index c3be974..da0dcf1 100644
--- a/src/glx/x11/glxcmds.c
+++ b/src/glx/x11/glxcmds.c
@@ -105,10 +105,6 @@ GarbageCollectDRIDrawables(Display * dpy, __GLXscreenConfigs * sc)
XSetErrorHandler(oldXErrorHandler);
}
-extern __GLXDRIdrawable *GetGLXDRIDrawable(Display * dpy,
- GLXDrawable drawable,
- int *const scrn_num);
-
/**
* Get the __DRIdrawable for the drawable associated with a GLXContext
*
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
index 3649c29..705681e 100644
--- a/src/mesa/drivers/dri/common/dri_util.c
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -454,7 +454,6 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
pdp->driScreenPriv = psp;
pdp->driContextPriv = &psp->dummyContextPriv;
- pdp->validBuffers = GL_FALSE;
if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes,
renderType == GLX_PIXMAP_BIT)) {
@@ -488,6 +487,9 @@ dri2CreateNewDrawable(__DRIscreen *screen,
pdraw->pClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
pdraw->pBackClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
+ pdraw->pStamp = _mesa_malloc(sizeof(unsigned int));
+ *pdraw->pStamp = pdraw->lastStamp + 1;
+
return pdraw;
}
@@ -515,6 +517,11 @@ static void dri_put_drawable(__DRIdrawable *pdp)
_mesa_free(pdp->pBackClipRects);
pdp->pBackClipRects = NULL;
}
+ if (psp->dri2.enabled && pdp->pStamp) {
+ _mesa_free(pdp->pStamp);
+ pdp->pStamp = NULL;
+
+ }
_mesa_free(pdp);
}
}
@@ -948,4 +955,10 @@ driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust,
return usage;
}
+void
+dri2InvalidateDrawable(__DRIdrawable *drawable)
+{
+ (*drawable->pStamp)++;
+}
+
/*@}*/
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
index 95df702..d473091 100644
--- a/src/mesa/drivers/dri/common/dri_util.h
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -295,7 +295,8 @@ struct __DRIdrawableRec {
unsigned int index;
/**
- * Pointer to the "drawable has changed ID" stamp in the SAREA.
+ * Pointer to the "drawable has changed ID" stamp in the SAREA (or
+ * in malloc'ed memory if DRI2 is being used).
*/
unsigned int *pStamp;
@@ -376,8 +377,6 @@ struct __DRIdrawableRec {
* GLX_MESA_swap_control.
*/
unsigned int swap_interval;
-
- GLboolean validBuffers;
};
/**
@@ -550,4 +549,7 @@ driCalculateSwapUsage( __DRIdrawable *dPriv,
extern GLint
driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 );
+extern void
+dri2InvalidateDrawable(__DRIdrawable *drawable);
+
#endif /* _DRI_UTIL_H_ */
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index d52fe2e..b4891b1 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -376,7 +376,6 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
}
}
- drawable->validBuffers = GL_TRUE;
driUpdateFramebufferSize(&intel->ctx, drawable);
}
diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c
index 6c2cb3b..74a4a13 100644
--- a/src/mesa/drivers/dri/intel/intel_screen.c
+++ b/src/mesa/drivers/dri/intel/intel_screen.c
@@ -131,7 +131,6 @@ intelDRI2FlushInvalidate(__DRIdrawable *drawable)
struct intel_context *intel = drawable->driContextPriv->driverPrivate;
intelDRI2Flush(drawable);
- drawable->validBuffers = GL_FALSE;
/* We're using FlushInvalidate as an indicator that a frame is
* done. It's only called immediately after SwapBuffers, so it
@@ -157,6 +156,7 @@ static const struct __DRI2flushExtensionRec intelFlushExtension = {
{ __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
intelDRI2Flush,
intelDRI2FlushInvalidate,
+ dri2InvalidateDrawable,
};
static const __DRIextension *intelScreenExtensions[] = {
diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c
index 6f41eaf..0ecafab 100644
--- a/src/mesa/drivers/dri/intel/intel_tex_image.c
+++ b/src/mesa/drivers/dri/intel/intel_tex_image.c
@@ -742,8 +742,10 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
if (!intelObj)
return;
- if (!dPriv->validBuffers)
+ if (dPriv->lastStamp != *dPriv->pStamp) {
+ dPriv->lastStamp = *dPriv->pStamp;
intel_update_renderbuffers(pDRICtx, dPriv);
+ }
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);
/* If the region isn't set, then intel_update_renderbuffers was unable
--
1.6.4.4
More information about the xorg-devel
mailing list