From: Francisco J. <cur...@ri...> - 2010-01-22 14:31:24
|
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 |