From 5339591e282328e683e4ae222a72535ae87fb4cf Mon Sep 17 00:00:00 2001 From: David Reveman Date: Mon, 13 Mar 2006 15:53:26 +0000 Subject: [PATCH] CopySubBufferMESA support --- ChangeLog | 9 ++++ GL/glx/glxcmds.c | 107 +++++++++++++++++++++++++++++++++++++- GL/glx/glxcmdsswap.c | 34 ++++++++++++ GL/glx/glxdrawable.h | 1 + GL/glx/glxdri.c | 33 ++++++++++-- GL/glx/glxscreens.c | 1 + GL/mesa/X/xf86glx.c | 18 +++++++ hw/xgl/glxext/xglglxext.c | 90 ++++++++++++++++++++++++++++++-- 8 files changed, 286 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index 85316fcb4..1d078cd33 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2006-03-13 David Reveman + + * GL/mesa/X/xf86glx.c: + * GL/glx/glxscreens.c: + * GL/glx/glxdri.c: + * GL/glx/glxdrawable.h: + * GL/glx/glxcmdsswap.c: + * GL/glx/glxcmds.c: CopySubBufferMESA support. + 2006-03-13 Matthias Hopf Needed for 'make distcheck': diff --git a/GL/glx/glxcmds.c b/GL/glx/glxcmds.c index a88cacfca..b4f0fa0ff 100644 --- a/GL/glx/glxcmds.c +++ b/GL/glx/glxcmds.c @@ -1363,7 +1363,7 @@ int __glXSwapBuffers(__GLXclientState *cl, GLbyte *pc) if (!glxc) { return __glXBadContextTag; } -#if 0 //XGL +#if 0 /*XGL */ /* ** The calling thread is swapping its current drawable. In this case, ** glxSwapBuffers is in both GL and X streams, in terms of @@ -1407,6 +1407,107 @@ int __glXSwapBuffers(__GLXclientState *cl, GLbyte *pc) return Success; } +int __glXCopySubBufferMESA(__GLXclientState *cl, GLbyte *pc) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; + ClientPtr client = cl->client; + GLXContextTag tag = req->contextTag; + GLXDrawable drawId; + DrawablePtr pDraw; + __GLXpixmap *pGlxPixmap; + __GLXcontext *glxc = NULL; + int x, y, w, h; + int error; + + pc += __GLX_VENDPRIV_HDR_SIZE; + + drawId = *((CARD32 *) (pc)); + x = *((INT32 *) (pc + 4)); + y = *((INT32 *) (pc + 8)); + w = *((INT32 *) (pc + 12)); + h = *((INT32 *) (pc + 16)); + + /* + ** Check that the GLX drawable is valid. + */ + pDraw = (DrawablePtr) LookupDrawable(drawId, client); + if (pDraw) { + if (pDraw->type == DRAWABLE_WINDOW) { + /* + ** Drawable is an X window. + */ + } else { + /* + ** Drawable is an X pixmap, which is not allowed. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + } else { + pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId, + __glXPixmapRes); + if (pGlxPixmap) { + /* + ** Drawable is a GLX pixmap. + */ + } else { + /* + ** Drawable is neither a X window nor a GLX pixmap. + */ + client->errorValue = drawId; + return __glXBadDrawable; + } + } + + if (tag) { + glxc = __glXLookupContextByTag(cl, tag); + if (!glxc) { + return __glXBadContextTag; + } +#if 0 /*XGL */ + /* + ** The calling thread is swapping its current drawable. In this case, + ** glxSwapBuffers is in both GL and X streams, in terms of + ** sequentiality. + * + if (__glXForceCurrent(cl, tag, &error)) { + * + ** Do whatever is needed to make sure that all preceding requests + ** in both streams are completed before the swap is executed. + * + (*__glRenderTable->Finish)(); + __GLX_NOTE_FLUSHED_CMDS(glxc); + } else { + return error; + } + */ +#endif + } + + if (pDraw) { + __GLXdrawable *glxPriv; + + if (glxc) { + glxPriv = __glXGetDrawable(glxc, pDraw, drawId); + if (glxPriv == NULL) { + return __glXBadDrawable; + } + } + else { + glxPriv = __glXFindDrawable(drawId); + if (glxPriv == NULL) { + /* This is a window we've never seen before, do nothing */ + return Success; + } + } + + if ((*glxPriv->copySubBuffer)(glxPriv, x, y, w, h) == GL_FALSE) { + return __glXBadDrawable; + } + } + + return Success; +} int __glXQueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc) { @@ -2329,6 +2430,8 @@ static int __glxHyperpipeConfigSGIX(__GLXclientState *cl, GLbyte *pc) ** allocating the entry points in the dispatch table. */ +#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ + int __glXVendorPrivate(__GLXclientState *cl, GLbyte *pc) { xGLXVendorPrivateReq *req; @@ -2352,6 +2455,8 @@ int __glXVendorPrivate(__GLXclientState *cl, GLbyte *pc) return __glXBindTexImageEXT(cl, pc); case X_GLXvop_ReleaseTexImageEXT: return __glXReleaseTexImageEXT(cl, pc); + case X_GLXvop_CopySubBufferMESA: + return __glXCopySubBufferMESA(cl, pc); } #endif diff --git a/GL/glx/glxcmdsswap.c b/GL/glx/glxcmdsswap.c index 067de998c..7307a83e0 100644 --- a/GL/glx/glxcmdsswap.c +++ b/GL/glx/glxcmdsswap.c @@ -327,6 +327,36 @@ int __glXSwapSwapBuffers(__GLXclientState *cl, GLbyte *pc) return __glXSwapBuffers(cl, pc); } +int __glXSwapCopySubBufferMESA(__GLXclientState *cl, GLbyte *pc) +{ + xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; + CARD32 *drawId; + INT32 *x; + INT32 *y; + INT32 *w; + INT32 *h; + + __GLX_DECLARE_SWAP_VARIABLES; + + pc += __GLX_VENDPRIV_HDR_SIZE; + + drawId = ((CARD32 *) (pc)); + x = ((INT32 *) (pc + 4)); + y = ((INT32 *) (pc + 8)); + w = ((INT32 *) (pc + 12)); + h = ((INT32 *) (pc + 16)); + + __GLX_SWAP_SHORT(&req->length); + __GLX_SWAP_INT(&req->contextTag); + __GLX_SWAP_INT(drawId); + __GLX_SWAP_INT(x); + __GLX_SWAP_INT(y); + __GLX_SWAP_INT(w); + __GLX_SWAP_INT(h); + + return __glXCopySubBufferMESA(cl, (GLbyte *)pc); +} + int __glXSwapUseXFont(__GLXclientState *cl, GLbyte *pc) { xGLXUseXFontReq *req = (xGLXUseXFontReq *) pc; @@ -1058,6 +1088,8 @@ int __glXSwapRenderLarge(__GLXclientState *cl, GLbyte *pc) ** allocating these entry points in the dispatch table. */ +#define X_GLXvop_CopySubBufferMESA 5154 /* temporary */ + int __glXSwapVendorPrivate(__GLXclientState *cl, GLbyte *pc) { xGLXVendorPrivateReq *req; @@ -1087,6 +1119,8 @@ int __glXSwapVendorPrivate(__GLXclientState *cl, GLbyte *pc) return __glXSwapBindTexImageEXT(cl, pc); case X_GLXvop_ReleaseTexImageEXT: return __glXSwapReleaseTexImageEXT(cl, pc); + case X_GLXvop_CopySubBufferMESA: + return __glXSwapCopySubBufferMESA(cl, pc); } #endif diff --git a/GL/glx/glxdrawable.h b/GL/glx/glxdrawable.h index 2d5d07a79..3e9cc8613 100644 --- a/GL/glx/glxdrawable.h +++ b/GL/glx/glxdrawable.h @@ -56,6 +56,7 @@ struct __GLXdrawable { void (*destroy)(__GLXdrawable *private); GLboolean (*resize)(__GLXdrawable *private); GLboolean (*swapBuffers)(__GLXdrawable *); + GLboolean (*copySubBuffer)(__GLXdrawable *, int, int, int, int); /* ** list of drawable private structs diff --git a/GL/glx/glxdri.c b/GL/glx/glxdri.c index 960bf93df..0ec307e15 100644 --- a/GL/glx/glxdri.c +++ b/GL/glx/glxdri.c @@ -177,6 +177,32 @@ __glXDRIdrawableSwapBuffers(__GLXdrawable *basePrivate) return TRUE; } +static GLboolean +__glXDRIdrawableCopySubBuffer(__GLXdrawable *basePrivate, + int x, + int y, + int width, + int height) +{ + __GLXDRIdrawable *private = (__GLXDRIdrawable *) basePrivate; + __GLXDRIscreen *screen; + + /* FIXME: We're jumping through hoops here to get the DRIdrawable + * which the dri driver tries to keep to it self... cf. FIXME in + * createDrawable. */ + + screen = (__GLXDRIscreen *) __glXgetActiveScreen(private->base.pDraw->pScreen->myNum); + private->driDrawable = (screen->driScreen.getDrawable)(NULL, + private->base.drawId, + screen->driScreen.private); + + (*private->driDrawable->copySubBuffer)(NULL, + private->driDrawable->private, + x, y, width, height); + + return TRUE; +} + static __GLXdrawable * __glXDRIcontextCreateDrawable(__GLXcontext *context, DrawablePtr pDraw, @@ -195,9 +221,10 @@ __glXDRIcontextCreateDrawable(__GLXcontext *context, return NULL; } - private->base.destroy = __glXDRIdrawableDestroy; - private->base.resize = __glXDRIdrawableResize; - private->base.swapBuffers = __glXDRIdrawableSwapBuffers; + private->base.destroy = __glXDRIdrawableDestroy; + private->base.resize = __glXDRIdrawableResize; + private->base.swapBuffers = __glXDRIdrawableSwapBuffers; + private->base.copySubBuffer = __glXDRIdrawableCopySubBuffer; #if 0 /* FIXME: It would only be natural that we called diff --git a/GL/glx/glxscreens.c b/GL/glx/glxscreens.c index e7e3e9e08..dda0b2375 100644 --- a/GL/glx/glxscreens.c +++ b/GL/glx/glxscreens.c @@ -141,6 +141,7 @@ static char GLXServerExtensions[] = "GLX_SGIX_swap_barrier " #endif "GLX_SGIX_fbconfig " + "GLX_MESA_copy_sub_buffer " ; __GLXscreen **__glXActiveScreens; diff --git a/GL/mesa/X/xf86glx.c b/GL/mesa/X/xf86glx.c index f8f915edb..ce09cf3e3 100644 --- a/GL/mesa/X/xf86glx.c +++ b/GL/mesa/X/xf86glx.c @@ -137,6 +137,23 @@ __glXMesaDrawableSwapBuffers(__GLXdrawable *base) return GL_TRUE; } +static GLboolean +__glXMesaDrawableCopySubBuffer(__GLXdrawable *base, + int x, + int y, + int width, + int height) +{ + __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base; + + __glXenterServer(); + + XMesaCopySubBuffer (glxPriv->xm_buf, x, y, width, height); + + __glXleaveServer(); + + return GL_TRUE; +} static __GLXdrawable * __glXMesaContextCreateDrawable(__GLXcontext *context, @@ -161,6 +178,7 @@ __glXMesaContextCreateDrawable(__GLXcontext *context, glxPriv->base.destroy = __glXMesaDrawableDestroy; glxPriv->base.resize = __glXMesaDrawableResize; glxPriv->base.swapBuffers = __glXMesaDrawableSwapBuffers; + glxPriv->base.copySubBuffer = __glXMesaDrawableCopySubBuffer; pGlxScreen = context->pGlxScreen; diff --git a/hw/xgl/glxext/xglglxext.c b/hw/xgl/glxext/xglglxext.c index cf40caa4d..eeff825a5 100644 --- a/hw/xgl/glxext/xglglxext.c +++ b/hw/xgl/glxext/xglglxext.c @@ -55,6 +55,7 @@ extern __GLXprovider *__xglMesaProvider; typedef struct _xglGLScreen { __GLXscreen base; __GLXscreen *mesaScreen; + char *GLXextensions; } xglGLScreenRec, *xglGLScreenPtr; typedef struct _xglGLBuffer { @@ -5219,6 +5220,60 @@ xglSwapBuffers (__GLXdrawable *drawable) return status; } +static GLboolean +xglCopySubBuffer (__GLXdrawable *drawable, + int x, + int y, + int width, + int height) +{ + xglGLBufferPtr pBufferPriv = (xglGLBufferPtr) drawable; + __GLXdrawable *mesaDrawable = pBufferPriv->mesaDrawable; + DrawablePtr pDrawable = pBufferPriv->pDrawable; + GLboolean status = GL_TRUE; + + if (pDrawable) + { + glitz_surface_t *surface; + int xOff, yOff; + GCPtr pGC = pBufferPriv->pGC; + RegionRec region; + BoxRec box; + + XGL_SCREEN_PRIV (pGC->pScreen); + + XGL_GET_DRAWABLE (pDrawable, surface, xOff, yOff); + + box.x1 = pDrawable->x + x; + box.y2 = pDrawable->height - y; + box.x2 = box.x1 + width; + box.y1 = box.y2 - height; + + REGION_INIT (pGC->pScreen, ®ion, &box, 1); + REGION_INTERSECT (pDrawable->pScreen, ®ion, + pGC->pCompositeClip, ®ion); + + glitz_drawable_swap_buffer_region (pBufferPriv->drawable, + xOff, yOff, (glitz_box_t *) + REGION_RECTS (®ion), + REGION_NUM_RECTS (®ion)); + + xglAddBitDamage (pDrawable, ®ion); + DamageDamageRegion (pDrawable, ®ion); + REGION_SUBTRACT (pGC->pScreen, &pBufferPriv->damage, + &pBufferPriv->damage, ®ion); + + REGION_UNINIT (pGC->pScreen, ®ion); + } + else if (mesaDrawable) + { + status = (*mesaDrawable->copySubBuffer) (mesaDrawable, + x, y, width, height); + } + + return status; +} + static GLboolean xglResizeDrawable (__GLXdrawable *drawable) { @@ -5425,9 +5480,10 @@ xglCreateDrawable (__GLXcontext *context, pBufferPriv->pPixmap = NULL; pBufferPriv->pGC = NULL; - pBufferPriv->base.destroy = xglDestroyDrawable; - pBufferPriv->base.resize = xglResizeDrawable; - pBufferPriv->base.swapBuffers = xglSwapBuffers; + pBufferPriv->base.destroy = xglDestroyDrawable; + pBufferPriv->base.resize = xglResizeDrawable; + pBufferPriv->base.swapBuffers = xglSwapBuffers; + pBufferPriv->base.copySubBuffer = xglCopySubBuffer; pBufferPriv->drawable = NULL; pBufferPriv->backSurface = NULL; @@ -6157,6 +6213,9 @@ xglScreenDestroy (__GLXscreen *screen) if (mesaScreen) GlxScreenDestroy (mesaScreen); + if (pScreen->GLXextensions) + xfree (pScreen->GLXextensions); + xfree (pScreen); } @@ -6190,6 +6249,31 @@ xglScreenProbe (ScreenPtr pScreen) screen->base.GLXversion = screen->mesaScreen->GLXversion; screen->base.GLXextensions = screen->mesaScreen->GLXextensions; + /* Remove GLX_MESA_copy_sub_buffer from GLX extension string if + glitz can't efficiently support it */ + if (!(glitz_drawable_get_features (pScreenPriv->drawable) & + GLITZ_FEATURE_COPY_SUB_BUFFER_MASK)) + { + screen->GLXextensions = strdup (screen->mesaScreen->GLXextensions); + if (screen->GLXextensions) + { + char *s; + + s = strstr (screen->GLXextensions, "GLX_MESA_copy_sub_buffer "); + if (s) + { + int n, n2; + + n = strlen ("GLX_MESA_copy_sub_buffer "); + n2 = strlen (s); + + memmove (s, s + n, n2 - n + 1); + } + + screen->base.GLXextensions = screen->GLXextensions; + } + } + screen->base.WrappedPositionWindow = screen->mesaScreen->WrappedPositionWindow;