dri2: support glXWaitX & glXWaitGL by using fake front buffer.

This commit is contained in:
Alan Hourihane
2009-02-16 11:44:40 +00:00
parent 18f20b70b1
commit 63b51b5cf1
4 changed files with 81 additions and 6 deletions

View File

@@ -77,6 +77,9 @@ struct __GLXDRIdrawablePrivateRec {
int bufferCount; int bufferCount;
int width, height; int width, height;
unsigned long configureSeqno; unsigned long configureSeqno;
int have_back;
int have_front;
int have_fake_front;
}; };
static void dri2DestroyContext(__GLXDRIcontext *context, static void dri2DestroyContext(__GLXDRIcontext *context,
@@ -196,6 +199,10 @@ static void dri2CopySubBuffer(__GLXDRIdrawable *pdraw,
XRectangle xrect; XRectangle xrect;
XserverRegion region; XserverRegion region;
/* Check we have the right attachments */
if (!(priv->have_front && priv->have_back))
return;
xrect.x = x; xrect.x = x;
xrect.y = priv->height - y - height; xrect.y = priv->height - y - height;
xrect.width = width; xrect.width = width;
@@ -214,6 +221,47 @@ static void dri2SwapBuffers(__GLXDRIdrawable *pdraw)
dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height); dri2CopySubBuffer(pdraw, 0, 0, priv->width, priv->height);
} }
static void dri2WaitX(__GLXDRIdrawable *pdraw)
{
__GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
XRectangle xrect;
XserverRegion region;
/* Check we have the right attachments */
if (!(priv->have_fake_front && priv->have_front))
return;
xrect.x = 0;
xrect.y = 0;
xrect.width = priv->width;
xrect.height = priv->height;
region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
DRI2CopyRegion(pdraw->psc->dpy, pdraw->drawable, region,
DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);
XFixesDestroyRegion(pdraw->psc->dpy, region);
}
static void dri2WaitGL(__GLXDRIdrawable *pdraw)
{
__GLXDRIdrawablePrivate *priv = (__GLXDRIdrawablePrivate *) pdraw;
XRectangle xrect;
XserverRegion region;
if (!(priv->have_fake_front && priv->have_front))
return;
xrect.x = 0;
xrect.y = 0;
xrect.width = priv->width;
xrect.height = priv->height;
region = XFixesCreateRegion(pdraw->psc->dpy, &xrect, 1);
DRI2CopyRegion(pdraw->psc->dpy, pdraw->drawable, region,
DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
XFixesDestroyRegion(pdraw->psc->dpy, region);
}
static void dri2DestroyScreen(__GLXscreenConfigs *psc) static void dri2DestroyScreen(__GLXscreenConfigs *psc)
{ {
/* Free the direct rendering per screen data */ /* Free the direct rendering per screen data */
@@ -261,6 +309,9 @@ dri2GetBuffers(__DRIdrawable *driDrawable,
pdraw->width = *width; pdraw->width = *width;
pdraw->height = *height; pdraw->height = *height;
pdraw->bufferCount = *out_count; pdraw->bufferCount = *out_count;
pdraw->have_front = 0;
pdraw->have_fake_front = 0;
pdraw->have_back = 0;
/* This assumes the DRI2 buffer attachment tokens matches the /* This assumes the DRI2 buffer attachment tokens matches the
* __DRIbuffer tokens. */ * __DRIbuffer tokens. */
@@ -270,6 +321,12 @@ dri2GetBuffers(__DRIdrawable *driDrawable,
pdraw->buffers[i].pitch = buffers[i].pitch; pdraw->buffers[i].pitch = buffers[i].pitch;
pdraw->buffers[i].cpp = buffers[i].cpp; pdraw->buffers[i].cpp = buffers[i].cpp;
pdraw->buffers[i].flags = buffers[i].flags; pdraw->buffers[i].flags = buffers[i].flags;
if (pdraw->buffers[i].attachment == __DRI_BUFFER_FRONT_LEFT)
pdraw->have_front = 1;
if (pdraw->buffers[i].attachment == __DRI_BUFFER_FAKE_FRONT_LEFT)
pdraw->have_fake_front = 1;
if (pdraw->buffers[i].attachment == __DRI_BUFFER_BACK_LEFT)
pdraw->have_back = 1;
} }
Xfree(buffers); Xfree(buffers);
@@ -366,6 +423,8 @@ static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen,
psp->createContext = dri2CreateContext; psp->createContext = dri2CreateContext;
psp->createDrawable = dri2CreateDrawable; psp->createDrawable = dri2CreateDrawable;
psp->swapBuffers = dri2SwapBuffers; psp->swapBuffers = dri2SwapBuffers;
psp->waitGL = dri2WaitGL;
psp->waitX = dri2WaitX;
/* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always
* available.*/ * available.*/

View File

@@ -655,6 +655,8 @@ static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen,
psp->createContext = driCreateContext; psp->createContext = driCreateContext;
psp->createDrawable = driCreateDrawable; psp->createDrawable = driCreateDrawable;
psp->swapBuffers = driSwapBuffers; psp->swapBuffers = driSwapBuffers;
psp->waitX = NULL;
psp->waitGL = NULL;
return psp; return psp;
} }

View File

@@ -139,6 +139,8 @@ struct __GLXDRIscreenRec {
void (*swapBuffers)(__GLXDRIdrawable *pdraw); void (*swapBuffers)(__GLXDRIdrawable *pdraw);
void (*copySubBuffer)(__GLXDRIdrawable *pdraw, void (*copySubBuffer)(__GLXDRIdrawable *pdraw,
int x, int y, int width, int height); int x, int y, int width, int height);
void (*waitX)(__GLXDRIdrawable *pdraw);
void (*waitGL)(__GLXDRIdrawable *pdraw);
}; };
struct __GLXDRIcontextRec { struct __GLXDRIcontextRec {

View File

@@ -611,11 +611,15 @@ PUBLIC void glXWaitGL(void)
#ifdef GLX_DIRECT_RENDERING #ifdef GLX_DIRECT_RENDERING
if (gc->driContext) { if (gc->driContext) {
/* This bit of ugliness unwraps the glFinish function */ int screen;
#ifdef glFinish __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen);
#undef glFinish
#endif if ( pdraw != NULL ) {
glFinish(); __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
glFlush();
if (psc->driScreen->waitGL != NULL)
(*psc->driScreen->waitGL)(pdraw);
}
return; return;
} }
#endif #endif
@@ -647,7 +651,15 @@ PUBLIC void glXWaitX(void)
#ifdef GLX_DIRECT_RENDERING #ifdef GLX_DIRECT_RENDERING
if (gc->driContext) { if (gc->driContext) {
XSync(dpy, False); int screen;
__GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen);
if ( pdraw != NULL ) {
__GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen);
if (psc->driScreen->waitX != NULL)
(*psc->driScreen->waitX)(pdraw);
} else
XSync(dpy, False);
return; return;
} }
#endif #endif