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:

committed by
Kristian Høgsberg

parent
925b901ba3
commit
61d26bc82e
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -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++;
|
||||||
|
}
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
@@ -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_ */
|
||||||
|
@@ -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
|
||||||
|
@@ -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[] = {
|
||||||
|
@@ -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);
|
||||||
|
Reference in New Issue
Block a user