dri2: Event driven buffer validation.

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 before flushing the fake front/back
buffer (that's typically once per frame -- not a lot worse than the
situation we were in before).

No effort has been made on preserving backwards compatibility with
version 2 of the flush extension, but I think it's acceptable because
AFAIK no released stack is making use of it.

Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
This commit is contained in:
Francisco Jerez
2010-02-08 19:27:56 +01:00
committed by Kristian Høgsberg
parent 925b901ba3
commit 61d26bc82e
9 changed files with 65 additions and 35 deletions

View File

@@ -269,22 +269,20 @@ struct __DRItexBufferExtensionRec {
* Used by drivers that implement DRI2 * Used by drivers that implement DRI2
*/ */
#define __DRI2_FLUSH "DRI2_Flush" #define __DRI2_FLUSH "DRI2_Flush"
#define __DRI2_FLUSH_VERSION 2 #define __DRI2_FLUSH_VERSION 3
struct __DRI2flushExtensionRec { struct __DRI2flushExtensionRec {
__DRIextension base; __DRIextension base;
void (*flush)(__DRIdrawable *drawable); void (*flush)(__DRIdrawable *drawable);
/** /**
* Flush all rendering queue in the driver to the drm and * Ask the driver to call getBuffers/getBuffersWithFormat before
* invalidate all buffers. The driver will call out to * it starts rendering again.
* getBuffers/getBuffersWithFormat before it starts rendering
* again.
* *
* \param drawable the drawable to flush and invalidate * \param drawable the drawable to invalidate
* *
* \since 2 * \since 3
*/ */
void (*flushInvalidate)(__DRIdrawable *drawable); void (*invalidate)(__DRIdrawable *drawable);
}; };

View File

@@ -81,7 +81,7 @@ static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
dri2Info, dri2Info,
dri2ExtensionName, dri2ExtensionName,
&dri2ExtensionHooks, &dri2ExtensionHooks,
1, NULL) DRI2NumberEvents, NULL)
static Bool static Bool
DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
@@ -126,7 +126,15 @@ DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
return True; return True;
} }
#endif #endif
#ifdef DRI2_InvalidateBuffers
case DRI2_InvalidateBuffers:
{
xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
dri2InvalidateBuffers(dpy, awire->drawable);
return False;
}
#endif
default: default:
/* client doesn't support server event */ /* client doesn't support server event */
break; break;

View File

@@ -67,6 +67,7 @@ struct __GLXDRIdisplayPrivateRec
int driMinor; int driMinor;
int driPatch; int driPatch;
int swapAvailable; int swapAvailable;
int invalidateAvailable;
}; };
struct __GLXDRIcontextPrivateRec struct __GLXDRIcontextPrivateRec
@@ -310,12 +311,18 @@ dri2WaitGL(__GLXDRIdrawable * pdraw)
XFixesDestroyRegion(pdraw->psc->dpy, region); XFixesDestroyRegion(pdraw->psc->dpy, region);
} }
static void static void
dri2FlushFrontBuffer(__DRIdrawable * driDrawable, void *loaderPrivate) dri2FlushFrontBuffer(__DRIdrawable *driDrawable, void *loaderPrivate)
{ {
(void) driDrawable; __GLXDRIdrawablePrivate *pdraw = loaderPrivate;
dri2WaitGL((__GLXDRIdrawable *) 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); (*pdraw->psc->f->flush)(pdraw->driDrawable);
#endif #endif
/* Old servers don't send invalidate events */
if (!pdp->invalidateAvailable)
dri2InvalidateBuffers(dpyPriv->dpy, pdraw->xDrawable);
/* Old servers can't handle swapbuffers */ /* Old servers can't handle swapbuffers */
if (!pdp->swapAvailable) { if (!pdp->swapAvailable) {
dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
@@ -386,11 +397,6 @@ dri2SwapBuffers(__GLXDRIdrawable *pdraw, int64_t target_msc, int64_t divisor,
remainder, &ret); remainder, &ret);
#endif #endif
#if __DRI2_FLUSH_VERSION >= 2
if (pdraw->psc->f)
(*pdraw->psc->f->flushInvalidate)(pdraw->driDrawable);
#endif
return ret; return ret;
} }
@@ -485,6 +491,17 @@ static const __DRIextension *loader_extensions_old[] = {
NULL 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 * static __GLXDRIscreen *
dri2CreateScreen(__GLXscreenConfigs * psc, int screen, dri2CreateScreen(__GLXscreenConfigs * psc, int screen,
__GLXdisplayPrivate * priv) __GLXdisplayPrivate * priv)
@@ -651,11 +668,8 @@ dri2CreateDisplay(Display * dpy)
} }
pdp->driPatch = 0; pdp->driPatch = 0;
pdp->swapAvailable = 0; pdp->swapAvailable = (pdp->driMinor >= 2);
#ifdef X_DRI2SwapBuffers pdp->invalidateAvailable = (pdp->driMinor >= 3);
if (pdp->driMinor >= 2)
pdp->swapAvailable = 1;
#endif
pdp->base.destroyDisplay = dri2DestroyDisplay; pdp->base.destroyDisplay = dri2DestroyDisplay;
pdp->base.createScreen = dri2CreateScreen; pdp->base.createScreen = dri2CreateScreen;

View File

@@ -182,6 +182,8 @@ struct __GLXDRIdrawableRec
extern __GLXDRIdisplay *driswCreateDisplay(Display * dpy); extern __GLXDRIdisplay *driswCreateDisplay(Display * dpy);
extern __GLXDRIdisplay *driCreateDisplay(Display * dpy); extern __GLXDRIdisplay *driCreateDisplay(Display * dpy);
extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy); extern __GLXDRIdisplay *dri2CreateDisplay(Display * dpy);
extern void dri2InvalidateBuffers(Display *dpy, XID drawable);
extern void DRI_glXUseXFont(Font font, int first, int count, int listbase); extern void DRI_glXUseXFont(Font font, int first, int count, int listbase);

View File

@@ -454,7 +454,6 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
pdp->driScreenPriv = psp; pdp->driScreenPriv = psp;
pdp->driContextPriv = &psp->dummyContextPriv; pdp->driContextPriv = &psp->dummyContextPriv;
pdp->validBuffers = GL_FALSE;
if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes, if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, &config->modes,
renderType == GLX_PIXMAP_BIT)) { renderType == GLX_PIXMAP_BIT)) {
@@ -488,6 +487,9 @@ dri2CreateNewDrawable(__DRIscreen *screen,
pdraw->pClipRects = &pdraw->dri2.clipRect; pdraw->pClipRects = &pdraw->dri2.clipRect;
pdraw->pBackClipRects = &pdraw->dri2.clipRect; pdraw->pBackClipRects = &pdraw->dri2.clipRect;
pdraw->pStamp = &pdraw->dri2.stamp;
*pdraw->pStamp = pdraw->lastStamp + 1;
return pdraw; return pdraw;
} }
@@ -949,4 +951,10 @@ driCalculateSwapUsage( __DRIdrawable *dPriv, int64_t last_swap_ust,
return usage; return usage;
} }
void
dri2InvalidateDrawable(__DRIdrawable *drawable)
{
drawable->dri2.stamp++;
}
/*@}*/ /*@}*/

View File

@@ -295,7 +295,8 @@ struct __DRIdrawableRec {
unsigned int index; 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
* to dri2.stamp if DRI2 is being used).
*/ */
unsigned int *pStamp; unsigned int *pStamp;
@@ -377,9 +378,8 @@ struct __DRIdrawableRec {
*/ */
unsigned int swap_interval; unsigned int swap_interval;
GLboolean validBuffers;
struct { struct {
unsigned int stamp;
drm_clip_rect_t clipRect; drm_clip_rect_t clipRect;
} dri2; } dri2;
}; };
@@ -559,4 +559,7 @@ driCalculateSwapUsage( __DRIdrawable *dPriv,
extern GLint extern GLint
driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 ); driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 );
extern void
dri2InvalidateDrawable(__DRIdrawable *drawable);
#endif /* _DRI_UTIL_H_ */ #endif /* _DRI_UTIL_H_ */

View File

@@ -366,8 +366,8 @@ intel_update_renderbuffers(__DRIcontext *context, __DRIdrawable *drawable)
} }
} }
drawable->validBuffers = GL_TRUE;
driUpdateFramebufferSize(&intel->ctx, drawable); driUpdateFramebufferSize(&intel->ctx, drawable);
drawable->lastStamp = drawable->dri2.stamp;
} }
void void

View File

@@ -123,22 +123,19 @@ intelDRI2Flush(__DRIdrawable *drawable)
} }
static void static void
intelDRI2FlushInvalidate(__DRIdrawable *drawable) intelDRI2Invalidate(__DRIdrawable *drawable)
{ {
struct intel_context *intel = drawable->driContextPriv->driverPrivate; struct intel_context *intel = drawable->driContextPriv->driverPrivate;
intel->using_dri2_swapbuffers = GL_TRUE; intel->using_dri2_swapbuffers = GL_TRUE;
dri2InvalidateDrawable(drawable);
intelDRI2Flush(drawable);
drawable->validBuffers = GL_FALSE;
intel_update_renderbuffers(intel->driContext, drawable); intel_update_renderbuffers(intel->driContext, drawable);
} }
static const struct __DRI2flushExtensionRec intelFlushExtension = { static const struct __DRI2flushExtensionRec intelFlushExtension = {
{ __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
intelDRI2Flush, intelDRI2Flush,
intelDRI2FlushInvalidate, intelDRI2Invalidate,
}; };
static const __DRIextension *intelScreenExtensions[] = { static const __DRIextension *intelScreenExtensions[] = {

View File

@@ -748,7 +748,7 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
if (!intelObj) if (!intelObj)
return; return;
if (!dPriv->validBuffers) if (dPriv->lastStamp != *dPriv->pStamp)
intel_update_renderbuffers(pDRICtx, dPriv); intel_update_renderbuffers(pDRICtx, dPriv);
rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT); rb = intel_get_renderbuffer(fb, BUFFER_FRONT_LEFT);