dri2: support glXWaitX & glXWaitGL by using fake front buffer.
authorAlan Hourihane <alanh@vmware.com>
Mon, 16 Feb 2009 11:44:40 +0000 (11:44 +0000)
committerAlan Hourihane <alanh@vmware.com>
Mon, 16 Feb 2009 11:47:05 +0000 (11:47 +0000)
src/glx/x11/dri2_glx.c
src/glx/x11/dri_glx.c
src/glx/x11/glxclient.h
src/glx/x11/glxcmds.c

index b878f05ddac3480c016315571e3daf3f78e8c799..776a14f614aa950e5f315d5841a046ea5ad1bd24 100644 (file)
@@ -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.*/
index 44724d2c7d0ffce3ed21a356afca549eb4c3cc36..3089aa172856dce6bf00bf47a839f31391230405 100644 (file)
@@ -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;
 }
index 9332eb64d3b738cc9bec9ce99896359b30b5c3b6..3e70759a6c4e6091e3ac03e9a14e5cf8cbe507d7 100644 (file)
@@ -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 {
index c68b6ac4efef75bec5d2197e9737d3f64722a1d6..fc0e593cb35bfbd3e0433a0c74085764e66261d7 100644 (file)
@@ -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