diff options
Diffstat (limited to 'src/glx/x11')
-rw-r--r-- | src/glx/x11/dri2.c | 2 | ||||
-rw-r--r-- | src/glx/x11/dri2_glx.c | 125 | ||||
-rw-r--r-- | src/glx/x11/dri_glx.c | 2 | ||||
-rw-r--r-- | src/glx/x11/glxclient.h | 3 | ||||
-rw-r--r-- | src/glx/x11/glxcmds.c | 24 | ||||
-rw-r--r-- | src/glx/x11/glxextensions.c | 2 |
6 files changed, 147 insertions, 11 deletions
diff --git a/src/glx/x11/dri2.c b/src/glx/x11/dri2.c index 3b48cd9c1ca..f967432b994 100644 --- a/src/glx/x11/dri2.c +++ b/src/glx/x11/dri2.c @@ -253,7 +253,7 @@ DRI2Buffer *DRI2GetBuffers(Display *dpy, XID drawable, *height = rep.height; *outCount = rep.count; - buffers = Xmalloc(count * sizeof buffers[0]); + buffers = Xmalloc(rep.count * sizeof buffers[0]); if (buffers == NULL) { _XEatData(dpy, rep.count * sizeof repBuffer); UnlockDisplay(dpy); diff --git a/src/glx/x11/dri2_glx.c b/src/glx/x11/dri2_glx.c index 2bee67780bd..776a14f614a 100644 --- a/src/glx/x11/dri2_glx.c +++ b/src/glx/x11/dri2_glx.c @@ -60,6 +60,9 @@ struct __GLXDRIdisplayPrivateRec { int driMajor; int driMinor; int driPatch; + + unsigned long configureSeqno; + Bool (*oldConfigProc)(Display *, XEvent *, xEvent *); }; struct __GLXDRIcontextPrivateRec { @@ -73,6 +76,10 @@ struct __GLXDRIdrawablePrivateRec { __DRIbuffer buffers[5]; int bufferCount; int width, height; + unsigned long configureSeqno; + int have_back; + int have_front; + int have_fake_front; }; static void dri2DestroyContext(__GLXDRIcontext *context, @@ -166,6 +173,8 @@ static __GLXDRIdrawable *dri2CreateDrawable(__GLXscreenConfigs *psc, pdraw->base.xDrawable = xDrawable; pdraw->base.drawable = drawable; pdraw->base.psc = psc; + pdraw->bufferCount = 0; + pdraw->configureSeqno = ~0; DRI2CreateDrawable(psc->dpy, xDrawable); @@ -190,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; @@ -208,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 */ @@ -223,9 +277,30 @@ dri2GetBuffers(__DRIdrawable *driDrawable, int *out_count, void *loaderPrivate) { __GLXDRIdrawablePrivate *pdraw = loaderPrivate; + __GLXdisplayPrivate *dpyPriv = __glXInitialize(pdraw->base.psc->dpy); + __GLXDRIdisplayPrivate *pdp = (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display; DRI2Buffer *buffers; int i; + /** + * Check if a ConfigureNotify has come in since we last asked for the + * buffers associated with this drawable. If not, we can assume that they're + * the same set at glViewport time, and save a synchronous round-trip to the + * X Server. + */ + if (pdraw->configureSeqno == pdp->configureSeqno && + count == pdraw->bufferCount) { + for (i = 0; i < count; i++) { + if (pdraw->buffers[i].attachment != attachments[i]) + break; + } + if (i == count) { + *out_count = pdraw->bufferCount; + return pdraw->buffers; + } + } + pdraw->configureSeqno = pdp->configureSeqno; + buffers = DRI2GetBuffers(pdraw->base.psc->dpy, pdraw->base.xDrawable, width, height, attachments, count, out_count); if (buffers == NULL) @@ -233,6 +308,10 @@ 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. */ @@ -242,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); @@ -282,8 +367,10 @@ static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen, return NULL; psc->driver = driOpenDriver(driverName); - if (psc->driver == NULL) + if (psc->driver == NULL) { + ErrorMessageF("driver pointer missing\n"); goto handle_error; + } extensions = dlsym(psc->driver, __DRI_DRIVER_EXTENSIONS); if (extensions == NULL) { @@ -309,11 +396,15 @@ static __GLXDRIscreen *dri2CreateScreen(__GLXscreenConfigs *psc, int screen, return NULL; } - if (drmGetMagic(psc->fd, &magic)) + if (drmGetMagic(psc->fd, &magic)) { + ErrorMessageF("failed to get magic\n"); return NULL; + } - if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) + if (!DRI2Authenticate(psc->dpy, RootWindow(psc->dpy, screen), magic)) { + ErrorMessageF("failed to authenticate magic %d\n", magic); return NULL; + } psc->__driScreen = psc->dri2->createNewScreen(screen, psc->fd, @@ -332,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.*/ @@ -359,6 +452,28 @@ static void dri2DestroyDisplay(__GLXDRIdisplay *dpy) Xfree(dpy); } +/** + * Makes a note on receiving ConfigureNotify that we need to re-check the + * DRI2 buffers, as window sizes may have resulted in reallocation. + */ +static Bool dri2ConfigureNotifyProc(Display *dpy, XEvent *re, xEvent *event) +{ + __GLXdisplayPrivate *dpyPriv = __glXInitialize(dpy); + __GLXDRIdisplayPrivate *pdp; + Bool ret; + + /* We should always be able to find our pdp, as it only gets torn down + * when the Display is torn down. + */ + pdp = (__GLXDRIdisplayPrivate *)dpyPriv->dri2Display; + + ret = pdp->oldConfigProc(dpy, re, event); + + pdp->configureSeqno = re->xconfigure.serial; + + return ret; +} + /* * Allocate, initialize and return a __DRIdisplayPrivate object. * This is called from __glXInitialize() when we are given a new @@ -381,7 +496,11 @@ _X_HIDDEN __GLXDRIdisplay *dri2CreateDisplay(Display *dpy) return NULL; } + pdp->oldConfigProc = XESetWireToEvent(dpy, ConfigureNotify, + dri2ConfigureNotifyProc); + pdp->driPatch = 0; + pdp->configureSeqno = 0; pdp->base.destroyDisplay = dri2DestroyDisplay; pdp->base.createScreen = dri2CreateScreen; diff --git a/src/glx/x11/dri_glx.c b/src/glx/x11/dri_glx.c index 44724d2c7d0..3089aa17285 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 467b0ebb7f9..3e70759a6c4 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 { @@ -602,6 +604,7 @@ extern void __glXSendLargeCommand(__GLXcontext *, const GLvoid *, GLint, const GLvoid *, GLint); /* Initialize the GLX extension for dpy */ +extern __GLXdisplayPrivate * __glXGetPrivateFromDisplay(Display *dpy); extern __GLXdisplayPrivate *__glXInitialize(Display*); extern void __glXPreferEGL(int state); diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index c68b6ac4efe..fc0e593cb35 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 diff --git a/src/glx/x11/glxextensions.c b/src/glx/x11/glxextensions.c index d061fa93336..051433a006c 100644 --- a/src/glx/x11/glxextensions.c +++ b/src/glx/x11/glxextensions.c @@ -99,7 +99,7 @@ static const struct extension_info known_glx_extensions[] = { { GLX(SGIS_color_range), VER(0,0), N, N, N, N }, { GLX(SGIS_multisample), VER(0,0), Y, Y, N, N }, { GLX(SGIX_fbconfig), VER(1,3), Y, Y, N, N }, - { GLX(SGIX_pbuffer), VER(1,3), Y, N, N, N }, + { GLX(SGIX_pbuffer), VER(1,3), Y, Y, N, N }, { GLX(SGIX_swap_barrier), VER(0,0), N, N, N, N }, { GLX(SGIX_swap_group), VER(0,0), N, N, N, N }, { GLX(SGIX_visual_select_group), VER(0,0), Y, Y, N, N }, |