From 04a54f69a8085ab3fe11a8713bd8b6b16ed1db27 Mon Sep 17 00:00:00 2001 From: Jesse Barnes Date: Thu, 16 Jul 2009 09:01:17 -0400 Subject: DRI2: add support for new DRI2 protocol requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support the new DRI2 2.2 protocol requests: DRI2SwapBuffers, DRI2GetMSC, DRI2WaitMSC, DRI2WaitSBC and DRI2SwapInterval. These requests allow the server to support the SGI_video_sync, SGI_swap_interval, and OML_sync_control GLX extensions if DDX support is present. The new DDX APIs are documented in dri2.h. Reviewed-by: Kristian Høgsberg Reviewed-by: Adam Jackson Signed-off-by: Jesse Barnes --- glx/glxcmds.c | 2 +- glx/glxcontext.h | 4 ++++ glx/glxdrawable.h | 2 +- glx/glxdri.c | 2 +- glx/glxdri2.c | 61 +++++++++++++++++++++++++++++++++++++++++++---------- glx/glxdriswrast.c | 2 +- glx/glxext.c | 3 +++ glx/glxserver.h | 18 +++++++--------- glx/swap_interval.c | 7 +++--- 9 files changed, 73 insertions(+), 28 deletions(-) (limited to 'glx') diff --git a/glx/glxcmds.c b/glx/glxcmds.c index eedab652f..77afbf4b1 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -1481,7 +1481,7 @@ int __glXDisp_SwapBuffers(__GLXclientState *cl, GLbyte *pc) return error; if (pGlxDraw->type == DRAWABLE_WINDOW && - (*pGlxDraw->swapBuffers)(pGlxDraw) == GL_FALSE) + (*pGlxDraw->swapBuffers)(cl->client, pGlxDraw) == GL_FALSE) return __glXError(GLXBadDrawable); return Success; diff --git a/glx/glxcontext.h b/glx/glxcontext.h index 70a14115d..79bc083a8 100644 --- a/glx/glxcontext.h +++ b/glx/glxcontext.h @@ -55,6 +55,10 @@ struct __GLXcontext { unsigned long mask); int (*forceCurrent) (__GLXcontext *context); + Bool (*wait) (__GLXcontext *context, + __GLXclientState *cl, + int *error); + __GLXtextureFromPixmap *textureFromPixmap; /* diff --git a/glx/glxdrawable.h b/glx/glxdrawable.h index 3f165ed4f..2a365c505 100644 --- a/glx/glxdrawable.h +++ b/glx/glxdrawable.h @@ -45,7 +45,7 @@ enum { struct __GLXdrawable { void (*destroy)(__GLXdrawable *private); - GLboolean (*swapBuffers)(__GLXdrawable *); + GLboolean (*swapBuffers)(ClientPtr client, __GLXdrawable *); void (*copySubBuffer)(__GLXdrawable *drawable, int x, int y, int w, int h); void (*waitX)(__GLXdrawable *); diff --git a/glx/glxdri.c b/glx/glxdri.c index 6122653b0..21e44d12d 100644 --- a/glx/glxdri.c +++ b/glx/glxdri.c @@ -245,7 +245,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable) } static GLboolean -__glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate) +__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *basePrivate) { __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate; __GLXDRIscreen *screen = diff --git a/glx/glxdri2.c b/glx/glxdri2.c index ed7dc80ba..58e4684fe 100644 --- a/glx/glxdri2.c +++ b/glx/glxdri2.c @@ -70,6 +70,7 @@ struct __GLXDRIscreen { const __DRIcoreExtension *core; const __DRIdri2Extension *dri2; + const __DRI2flushExtension *flush; const __DRIcopySubBufferExtension *copySubBuffer; const __DRIswapControlExtension *swapControl; const __DRItexBufferExtension *texBuffer; @@ -132,17 +133,6 @@ __glXDRIdrawableCopySubBuffer(__GLXdrawable *drawable, DRI2BufferFrontLeft, DRI2BufferBackLeft); } -static GLboolean -__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable) -{ - __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; - - __glXDRIdrawableCopySubBuffer(drawable, 0, 0, - private->width, private->height); - - return TRUE; -} - static void __glXDRIdrawableWaitX(__GLXdrawable *drawable) { @@ -177,9 +167,37 @@ __glXDRIdrawableWaitGL(__GLXdrawable *drawable) DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); } +/* + * Copy or flip back to front, honoring the swap interval if possible. + * + * If the kernel supports it, we request an event for the frame when the + * swap should happen, then perform the copy when we receive it. + */ +static GLboolean +__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable) +{ + __GLXDRIdrawable *priv = (__GLXDRIdrawable *) drawable; + __GLXDRIscreen *screen = priv->screen; + CARD64 unused; + + if (screen->flush) + (*screen->flush->flushInvalidate)(priv->driDrawable); + + if (DRI2SwapBuffers(client, drawable->pDraw, 0, 0, 0, &unused, + NULL, drawable->pDraw) != Success) + return FALSE; + + return TRUE; +} + static int __glXDRIdrawableSwapInterval(__GLXdrawable *drawable, int interval) { + if (interval <= 0) /* || interval > BIGNUM? */ + return GLX_BAD_VALUE; + + DRI2SwapInterval(drawable->pDraw, interval); + return 0; } @@ -241,6 +259,18 @@ __glXDRIcontextForceCurrent(__GLXcontext *baseContext) read->driDrawable); } +static Bool +__glXDRIcontextWait(__GLXcontext *baseContext, + __GLXclientState *cl, int *error) +{ + if (DRI2WaitSwap(cl->client, baseContext->drawPriv->pDraw)) { + *error = cl->client->noClientException; + return TRUE; + } + + return FALSE; +} + #ifdef __DRI_TEX_BUFFER static int @@ -346,6 +376,7 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen, context->base.copy = __glXDRIcontextCopy; context->base.forceCurrent = __glXDRIcontextForceCurrent; context->base.textureFromPixmap = &__glXDRItextureFromPixmap; + context->base.wait = __glXDRIcontextWait; context->driContext = (*screen->dri2->createNewContext)(screen->driScreen, @@ -581,6 +612,14 @@ initializeExtensions(__GLXDRIscreen *screen) LogMessage(X_INFO, "AIGLX: GLX_EXT_texture_from_pixmap backed by buffer objects\n"); } #endif + +#ifdef __DRI2_FLUSH + if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 && + extensions[i]->version >= __DRI2_FLUSH_VERSION) { + screen->flush = (__DRI2flushExtension *) extensions[i]; + } +#endif + /* Ignore unknown extensions */ } } diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c index 20f9f90d6..c647d83ca 100644 --- a/glx/glxdriswrast.c +++ b/glx/glxdriswrast.c @@ -108,7 +108,7 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable) } static GLboolean -__glXDRIdrawableSwapBuffers(__GLXdrawable *drawable) +__glXDRIdrawableSwapBuffers(ClientPtr client, __GLXdrawable *drawable) { __GLXDRIdrawable *private = (__GLXDRIdrawable *) drawable; const __DRIcoreExtension *core = private->screen->core; diff --git a/glx/glxext.c b/glx/glxext.c index 751ea7297..913c624f2 100644 --- a/glx/glxext.c +++ b/glx/glxext.c @@ -446,6 +446,9 @@ __GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag, } } + if (cx->wait && (*cx->wait)(cx, cl, error)) + return NULL; + if (cx == __glXLastContext) { /* No need to re-bind */ return cx; diff --git a/glx/glxserver.h b/glx/glxserver.h index 80f1b28f9..10c4889e1 100644 --- a/glx/glxserver.h +++ b/glx/glxserver.h @@ -56,7 +56,14 @@ #include #include -/* For glxscreens.h */ +/* +** GLX resources. +*/ +typedef XID GLXContextID; +typedef XID GLXPixmap; +typedef XID GLXDrawable; + +typedef struct __GLXclientStateRec __GLXclientState; typedef struct __GLXdrawable __GLXdrawable; typedef struct __GLXcontext __GLXcontext; @@ -71,15 +78,6 @@ typedef struct __GLXcontext __GLXcontext; #define False 0 #endif -/* -** GLX resources. -*/ -typedef XID GLXContextID; -typedef XID GLXPixmap; -typedef XID GLXDrawable; - -typedef struct __GLXclientStateRec __GLXclientState; - extern __GLXscreen *glxGetScreen(ScreenPtr pScreen); extern __GLXclientState *glxGetClient(ClientPtr pClient); diff --git a/glx/swap_interval.c b/glx/swap_interval.c index 3a5242022..0bae3247e 100644 --- a/glx/swap_interval.c +++ b/glx/swap_interval.c @@ -53,8 +53,6 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap) cx = __glXLookupContextByTag(cl, tag); - LogMessage(X_ERROR, "%s: cx = %p, GLX screen = %p\n", __func__, - cx, (cx == NULL) ? NULL : cx->pGlxScreen); if ((cx == NULL) || (cx->pGlxScreen == NULL)) { client->errorValue = tag; return __glXError(GLXBadContext); @@ -68,7 +66,7 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap) if (cx->drawPriv == NULL) { client->errorValue = tag; - return __glXError(GLXBadDrawable); + return BadValue; } pc += __GLX_VENDPRIV_HDR_SIZE; @@ -76,6 +74,9 @@ int DoSwapInterval(__GLXclientState *cl, GLbyte *pc, int do_swap) ? bswap_32(*(int *)(pc + 0)) : *(int *)(pc + 0); + if (interval <= 0) + return BadValue; + (void) (*cx->pGlxScreen->swapInterval)(cx->drawPriv, interval); return Success; } -- cgit v1.2.3