From 63b51b5cf17ddde09b72a2811296f37b9a4c5ad2 Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Mon, 16 Feb 2009 11:44:40 +0000 Subject: dri2: support glXWaitX & glXWaitGL by using fake front buffer. --- src/glx/x11/dri2_glx.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ src/glx/x11/dri_glx.c | 2 ++ src/glx/x11/glxclient.h | 2 ++ src/glx/x11/glxcmds.c | 24 +++++++++++++++----- 4 files changed, 81 insertions(+), 6 deletions(-) diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c index b878f05dda..776a14f614 100644 --- a/src/glx/x11/dri2_glx.c +++ b/src/glx/x11/dri2_glx.c @@ -77,6 +77,9 @@ struct __GLXDRIdrawablePrivateRec { int bufferCount; int width, height; unsigned long configureSeqno; + int have_back; + int have_front; + int have_fake_front; }; static void dri2DestroyContext(__GLXDRIcontext *context, @@ -196,6 +199,10 @@ static void dri2CopySubBuffer(__GLXDRIdrawable *pdraw, XRectangle xrect; XserverRegion region; + /* Check we have the right attachments */ + if (!(priv->have_front && priv->have_back)) + return; + xrect.x = x; xrect.y = priv->height - y - height; xrect.width = width; @@ -214,6 +221,47 @@ static void dri2SwapBuffers(__GLXDRIdrawable *pdraw) 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) { /* Free the direct rendering per screen data */ @@ -261,6 +309,9 @@ dri2GetBuffers(__DRIdrawable *driDrawable, pdraw->width = *width; pdraw->height = *height; 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 * __DRIbuffer tokens. */ @@ -270,6 +321,12 @@ dri2GetBuffers(__DRIdrawable *driDrawable, pdraw->buffers[i].pitch = buffers[i].pitch; pdraw->buffers[i].cpp = buffers[i].cpp; 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); @@ -366,6 +423,8 @@ static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen, psp->createContext = dri2CreateContext; psp->createDrawable = dri2CreateDrawable; psp->swapBuffers = dri2SwapBuffers; + psp->waitGL = dri2WaitGL; + psp->waitX = dri2WaitX; /* DRI2 suports SubBuffer through DRI2CopyRegion, so it's always * available.*/ diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c index 44724d2c7d..3089aa1728 100644 --- a/src/glx/x11/dri_glx.c +++ b/src/glx/x11/dri_glx.c @@ -655,6 +655,8 @@ static __GLXDRIscreen *driCreateScreen(__GLXscreenConfigs *psc, int screen, psp->createContext = driCreateContext; psp->createDrawable = driCreateDrawable; psp->swapBuffers = driSwapBuffers; + psp->waitX = NULL; + psp->waitGL = NULL; return psp; } diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h index 9332eb64d3..3e70759a6c 100644 --- a/src/glx/x11/glxclient.h +++ b/src/glx/x11/glxclient.h @@ -139,6 +139,8 @@ struct __GLXDRIscreenRec { void (*swapBuffers)(__GLXDRIdrawable *pdraw); void (*copySubBuffer)(__GLXDRIdrawable *pdraw, int x, int y, int width, int height); + void (*waitX)(__GLXDRIdrawable *pdraw); + void (*waitGL)(__GLXDRIdrawable *pdraw); }; struct __GLXDRIcontextRec { diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index c68b6ac4ef..fc0e593cb3 100644 --- a/src/glx/x11/glxcmds.c +++ b/src/glx/x11/glxcmds.c @@ -611,11 +611,15 @@ PUBLIC void glXWaitGL(void) #ifdef GLX_DIRECT_RENDERING if (gc->driContext) { -/* This bit of ugliness unwraps the glFinish function */ -#ifdef glFinish -#undef glFinish -#endif - glFinish(); + int screen; + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, gc->currentDrawable, &screen); + + if ( pdraw != NULL ) { + __GLXscreenConfigs * const psc = GetGLXScreenConfigs(dpy, screen); + glFlush(); + if (psc->driScreen->waitGL != NULL) + (*psc->driScreen->waitGL)(pdraw); + } return; } #endif @@ -647,7 +651,15 @@ PUBLIC void glXWaitX(void) #ifdef GLX_DIRECT_RENDERING 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; } #endif -- cgit v1.2.3