/* $XFree86: xc/programs/Xserver/GL/glx/glxcmds.c,v 1.12 2004/01/28 18:11:50 alanh Exp $ */ /* ** License Applicability. Except to the extent portions of this file are ** made subject to an alternative license as permitted in the SGI Free ** Software License B, Version 1.1 (the "License"), the contents of this ** file are subject only to the provisions of the License. You may not use ** this file except in compliance with the License. You may obtain a copy ** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600 ** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at: ** ** http://oss.sgi.com/projects/FreeB ** ** Note that, as provided in the License, the Software is distributed on an ** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS ** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND ** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A ** PARTICULAR PURPOSE, AND NON-INFRINGEMENT. ** ** Original Code. The Original Code is: OpenGL Sample Implementation, ** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics, ** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc. ** Copyright in any portions created by third parties is as indicated ** elsewhere herein. All Rights Reserved. ** ** Additional Notice Provisions: The application programming interfaces ** established by SGI in conjunction with the Original Code are The ** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released ** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version ** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X ** Window System(R) (Version 1.3), released October 19, 1998. This software ** was created using the OpenGL(R) version 1.2.1 Sample Implementation ** published by SGI, but has not been independently verified as being ** compliant with the OpenGL(R) version 1.2.1 Specification. ** */ #define NEED_REPLIES #define FONT_PCF #ifdef HAVE_DIX_CONFIG_H #include #endif #include #include "glxserver.h" #include #include #include "g_disptab.h" #include #include #include "g_disptab_EXT.h" #include "glxutil.h" #include "glxext.h" #include "GL/glx_ansic.h" #include "glcontextmodes.h" #include "glapitable.h" #include "glapi.h" #include "glthread.h" #include "dispatch.h" /************************************************************************/ static int __glXGetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc); static int __glXCreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc); static int __glXCreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc); static int __glXMakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc); static int __glXBindSwapBarrierSGIX(__GLXclientState *cl, GLbyte *pc); static int __glXQueryMaxSwapBarriersSGIX(__GLXclientState *cl, GLbyte *pc); static int __glxQueryHyperpipeNetworkSGIX(__GLXclientState *cl, GLbyte *pc); static int __glxDestroyHyperpipeConfigSGIX (__GLXclientState *cl, GLbyte *pc); static int __glxQueryHyperpipeConfigSGIX(__GLXclientState *cl, GLbyte *pc); static int __glxHyperpipeConfigSGIX(__GLXclientState *cl, GLbyte *pc); /************************************************************************/ /** * Create a GL context with the given properties. This routine is used * to implement \c glXCreateContext, \c glXCreateNewContext, and * \c glXCreateContextWithConfigSGIX. This works becuase of the hack way * that GLXFBConfigs are implemented. Basically, the FBConfigID is the * same as the VisualID. */ int DoCreateContext(__GLXclientState *cl, GLXContextID gcId, GLXContextID shareList, VisualID visual, GLuint screen, GLboolean isDirect) { ClientPtr client = cl->client; VisualPtr pVisual; ScreenPtr pScreen; __GLXcontext *glxc, *shareglxc; __GLcontextModes *modes; __GLXscreenInfo *pGlxScreen; void *share; GLint i; LEGAL_NEW_RESOURCE(gcId, client); /* ** Check if screen exists. */ if (screen >= screenInfo.numScreens) { client->errorValue = screen; return BadValue; } pScreen = screenInfo.screens[screen]; pGlxScreen = &__glXActiveScreens[screen]; /* ** Check if the visual ID is valid for this screen. */ pVisual = pScreen->visuals; for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { if (pVisual->vid == visual) { break; } } if (i == pScreen->numVisuals) { client->errorValue = visual; return BadValue; } /* ** Get configuration of the visual. This assumes that the ** glXActiveScreens structure contains visual configurations only for the ** subset of Visuals that are supported by this implementation of the ** OpenGL. */ modes = _gl_context_modes_find_visual( pGlxScreen->modes, visual ); if (modes == NULL) { /* ** Visual not support on this screen by this OpenGL implementation. */ client->errorValue = visual; return BadValue; } /* ** Find the display list space that we want to share. ** ** NOTE: In a multithreaded X server, we would need to keep a reference ** count for each display list so that if one client detroyed a list that ** another client was using, the list would not really be freed until it ** was no longer in use. Since this sample implementation has no support ** for multithreaded servers, we don't do this. */ if (shareList == None) { share = 0; } else { shareglxc = (__GLXcontext *) LookupIDByType(shareList, __glXContextRes); if (!shareglxc) { client->errorValue = shareList; return __glXBadContext; } if (shareglxc->isDirect) { /* ** NOTE: no support for sharing display lists between direct ** contexts, even if they are in the same address space. */ #if 0 /* Disabling this code seems to allow shared display lists * and texture objects to work. We'll leave it disabled for now. */ client->errorValue = shareList; return BadMatch; #endif } else { /* ** Create an indirect context regardless of what the client asked ** for; this way we can share display list space with shareList. */ isDirect = GL_FALSE; } share = shareglxc->driContext.private; } /* ** Allocate memory for the new context */ glxc = (__GLXcontext *) __glXMalloc(sizeof(__GLXcontext)); if (!glxc) { return BadAlloc; } __glXMemset(glxc, 0, sizeof(__GLXcontext)); /* ** Initially, setup the part of the context that could be used by ** a GL core that needs windowing information (e.g., Mesa). */ glxc->pScreen = pScreen; glxc->pGlxScreen = pGlxScreen; glxc->pVisual = pVisual; glxc->modes = modes; if (!isDirect) { glxc->driContext.private = (*pGlxScreen->driScreen.createNewContext)(NULL, modes, 0, share, &glxc->driContext); if (glxc->driContext.private == NULL) { __glXFree(glxc); client->errorValue = gcId; return BadAlloc; } glxc->driContext.mode = modes; } else { /* ** Don't need local GL context for a direct context. */ glxc->driContext.private = NULL; } /* ** Register this context as a resource. */ if (!AddResource(gcId, __glXContextRes, (pointer)glxc)) { if (!isDirect) { (*glxc->driContext.destroyContext)(NULL, screen, glxc->driContext.private); } __glXFree(glxc); client->errorValue = gcId; return BadAlloc; } /* ** Finally, now that everything is working, setup the rest of the ** context. */ glxc->id = gcId; glxc->share_id = shareList; glxc->idExists = GL_TRUE; glxc->isCurrent = GL_FALSE; glxc->isDirect = isDirect; glxc->renderMode = GL_RENDER; return Success; } int __glXCreateContext(__GLXclientState *cl, GLbyte *pc) { xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; return DoCreateContext( cl, req->context, req->shareList, req->visual, req->screen, req->isDirect ); } int __glXCreateNewContext(__GLXclientState *cl, GLbyte *pc) { xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc; return DoCreateContext( cl, req->context, req->shareList, req->fbconfig, req->screen, req->isDirect ); } int __glXCreateContextWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) { xGLXCreateContextWithConfigSGIXReq *req = (xGLXCreateContextWithConfigSGIXReq *) pc; return DoCreateContext( cl, req->context, req->shareList, req->fbconfig, req->screen, req->isDirect ); } /* ** Destroy a GL context as an X resource. */ int __glXDestroyContext(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc; GLXContextID gcId = req->context; __GLXcontext *glxc; glxc = (__GLXcontext *) LookupIDByType(gcId, __glXContextRes); if (glxc) { /* ** Just free the resource; don't actually destroy the context, ** because it might be in use. The ** destroy method will be called by the resource destruction routine ** if necessary. */ FreeResourceByType(gcId, __glXContextRes, FALSE); return Success; } else { client->errorValue = gcId; return __glXBadContext; } } /*****************************************************************************/ /* ** For each client, the server keeps a table of all the contexts that are ** current for that client (each thread of a client may have its own current ** context). These routines add, change, and lookup contexts in the table. */ /* ** Add a current context, and return the tag that will be used to refer to it. */ static int AddCurrentContext(__GLXclientState *cl, __GLXcontext *glxc) { int i; int num = cl->numCurrentContexts; __GLXcontext **table = cl->currentContexts; if (!glxc) return -1; /* ** Try to find an empty slot and use it. */ for (i=0; i < num; i++) { if (!table[i]) { table[i] = glxc; return i+1; } } /* ** Didn't find a free slot, so we'll have to grow the table. */ if (!num) { table = (__GLXcontext **) __glXMalloc(sizeof(__GLXcontext *)); } else { table = (__GLXcontext **) __glXRealloc(table, (num+1)*sizeof(__GLXcontext *)); } table[num] = glxc; cl->currentContexts = table; cl->numCurrentContexts++; return num+1; } /* ** Given a tag, change the current context for the corresponding entry. */ static void ChangeCurrentContext(__GLXclientState *cl, __GLXcontext *glxc, GLXContextTag tag) { __GLXcontext **table = cl->currentContexts; table[tag-1] = glxc; } /* ** For this implementation we have chosen to simply use the index of the ** context's entry in the table as the context tag. A tag must be greater ** than 0. */ __GLXcontext *__glXLookupContextByTag(__GLXclientState *cl, GLXContextTag tag) { int num = cl->numCurrentContexts; if (tag < 1 || tag > num) { return 0; } else { return cl->currentContexts[tag-1]; } } /*****************************************************************************/ static void StopUsingContext(__GLXcontext *glxc) { if (glxc) { if (glxc == __glXLastContext) { /* Tell server GL library */ __glXLastContext = 0; } glxc->isCurrent = GL_FALSE; if (!glxc->idExists) { __glXFreeContext(glxc); } } } static void StartUsingContext(__GLXclientState *cl, __GLXcontext *glxc) { glxc->isCurrent = GL_TRUE; } /*****************************************************************************/ /* ** Make an OpenGL context and drawable current. */ int __glXMakeCurrent(__GLXclientState *cl, GLbyte *pc) { xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc; return DoMakeCurrent( cl, req->drawable, req->drawable, req->context, req->oldContextTag ); } int __glXMakeContextCurrent(__GLXclientState *cl, GLbyte *pc) { xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc; return DoMakeCurrent( cl, req->drawable, req->readdrawable, req->context, req->oldContextTag ); } int __glXMakeCurrentReadSGI(__GLXclientState *cl, GLbyte *pc) { xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc; return DoMakeCurrent( cl, req->drawable, req->readable, req->context, req->oldContextTag ); } /** * Given a drawable ID, get the associated drawable and / or pixmap. * * If the specified drawable ID is not a pixmap, \c ppPixmap will be set * to \c NULL on return. In either case, \c ppDraw will be set to a drawable. * In the case where the drawable ID is a pixmap, \c ppDraw will be set to * the drawable associated with that pixmap. * * \param glxc Associated GLX context. * \param drawId ID of the drawable. * \param ppDraw Location to store the pointer to the drawable. * \param ppPixmap Location to store the pointer to the pixmap. * \param client Pointer to the client state. * \return Zero is returned on success. Otherwise a GLX / X11 protocol error * is returned. * * \notes This function will need some modification when support pbuffers * is added. */ static int GetDrawableOrPixmap( __GLXcontext *glxc, GLXDrawable drawId, DrawablePtr *ppDraw, __GLXpixmap **ppPixmap, ClientPtr client ) { DrawablePtr pDraw; __GLXpixmap *drawPixmap = NULL; pDraw = (DrawablePtr) LookupDrawable(drawId, client); if (pDraw) { if (pDraw->type == DRAWABLE_WINDOW) { /* ** Drawable is an X Window. */ WindowPtr pWin = (WindowPtr)pDraw; VisualID vid = wVisual(pWin); /* ** Check if window and context are similar. */ if ((vid != glxc->pVisual->vid) || (pWin->drawable.pScreen != glxc->pScreen)) { client->errorValue = drawId; return BadMatch; } } else { /* ** An X Pixmap is not allowed as a parameter (a GLX Pixmap ** is, but it must first be created with glxCreateGLXPixmap). */ client->errorValue = drawId; return __glXBadDrawable; } } else { drawPixmap = (__GLXpixmap *) LookupIDByType(drawId, __glXPixmapRes); if (drawPixmap) { /* ** Check if pixmap and context are similar. */ if (drawPixmap->pScreen != glxc->pScreen || drawPixmap->modes->visualID != glxc->modes->visualID) { client->errorValue = drawId; return BadMatch; } pDraw = drawPixmap->pDraw; } else { /* ** Drawable is neither a Window nor a GLXPixmap. */ client->errorValue = drawId; return __glXBadDrawable; } } *ppPixmap = drawPixmap; *ppDraw = pDraw; return 0; } int DoMakeCurrent( __GLXclientState *cl, GLXDrawable drawId, GLXDrawable readId, GLXContextID contextId, GLXContextTag tag ) { ClientPtr client = cl->client; DrawablePtr pDraw; DrawablePtr pRead; xGLXMakeCurrentReply reply; __GLXpixmap *drawPixmap = NULL; __GLXpixmap *readPixmap = NULL; __GLXcontext *glxc, *prevglxc; __GLXdrawablePrivate *drawPriv = NULL; __GLXdrawablePrivate *readPriv = NULL; GLint error; GLuint mask; /* ** If one is None and the other isn't, it's a bad match. */ mask = (drawId == None) ? (1 << 0) : 0; mask |= (readId == None) ? (1 << 1) : 0; mask |= (contextId == None) ? (1 << 2) : 0; if ( (mask != 0x00) && (mask != 0x07) ) { return BadMatch; } /* ** Lookup old context. If we have one, it must be in a usable state. */ if (tag != 0) { prevglxc = __glXLookupContextByTag(cl, tag); if (!prevglxc) { /* ** Tag for previous context is invalid. */ return __glXBadContextTag; } if (prevglxc->renderMode != GL_RENDER) { /* Oops. Not in render mode render. */ client->errorValue = prevglxc->id; return __glXBadContextState; } } else { prevglxc = 0; } /* ** Lookup new context. It must not be current for someone else. */ if (contextId != None) { int status; glxc = (__GLXcontext *) LookupIDByType(contextId, __glXContextRes); if (!glxc) { client->errorValue = contextId; return __glXBadContext; } if ((glxc != prevglxc) && glxc->isCurrent) { /* Context is current to somebody else */ return BadAccess; } assert( drawId != None ); assert( readId != None ); status = GetDrawableOrPixmap( glxc, drawId, & pDraw, & drawPixmap, client ); if ( status != 0 ) { return status; } if ( readId != drawId ) { status = GetDrawableOrPixmap( glxc, readId, & pRead, & readPixmap, client ); if ( status != 0 ) { return status; } } else { pRead = pDraw; } /* FIXME: Finish refactoring this. - idr */ /* get the drawable private */ if (pDraw) { drawPriv = __glXGetDrawablePrivate(pDraw, drawId, glxc->modes); if (drawPriv == NULL) { return __glXBadDrawable; } } if (pRead != pDraw) { readPriv = __glXGetDrawablePrivate(pRead, readId, glxc->modes); if (readPriv == NULL) { return __glXBadDrawable; } } else { readPriv = drawPriv; } } else { /* Switching to no context. Ignore new drawable. */ glxc = 0; pDraw = 0; pRead = 0; } if (prevglxc) { /* ** Flush the previous context if needed. */ if (__GLX_HAS_UNFLUSHED_CMDS(prevglxc)) { if (__glXForceCurrent(cl, tag, (int *)&error)) { CALL_Flush( GET_DISPATCH(), () ); __GLX_NOTE_FLUSHED_CMDS(prevglxc); } else { return error; } } /* ** Make the previous context not current. */ /* FIXME-KRH: this is where we need the looseContext function * in the DRIcontext interface. */ if (!(*prevglxc->driContext.unbindContext)(NULL, prevglxc->pScreen->myNum, prevglxc->drawPriv->drawId, /* prev draw */ prevglxc->readPriv->drawId, /* prev read */ &prevglxc->driContext)) { return __glXBadContext; } __glXDeassociateContext(prevglxc); } if ((glxc != 0) && !glxc->isDirect) { /* make the context current */ if (!(*glxc->driContext.bindContext)(NULL, glxc->pScreen->myNum, drawId, readId, &glxc->driContext)) { return __glXBadContext; } /* FIXME: Is this assignment ok? Why wasn't it here already? */ __glXLastContext = glxc; __glXAssociateContext(glxc, drawPriv, readPriv); } if (prevglxc) { if (prevglxc->drawPixmap) { if (prevglxc->readPixmap && prevglxc->drawPixmap != prevglxc->readPixmap) { /* ** The previous drawable was a glx pixmap, release it. */ prevglxc->readPixmap->refcnt--; if (!prevglxc->readPixmap->idExists && !prevglxc->readPixmap->refcnt) { PixmapPtr pPixmap = (PixmapPtr) prevglxc->readPixmap->pDraw; /* ** The DestroyPixmap routine should decrement the ** refcount of the X pixmap and free only if it's zero. */ (*prevglxc->readPixmap->pScreen->DestroyPixmap)(pPixmap); __glXFree(prevglxc->readPixmap); } } /* ** The previous drawable was a glx pixmap, release it. */ prevglxc->drawPixmap->refcnt--; if (!prevglxc->drawPixmap->idExists && !prevglxc->drawPixmap->refcnt) { PixmapPtr pPixmap = (PixmapPtr) prevglxc->drawPixmap->pDraw; /* ** The DestroyPixmap routine should decrement the ** refcount of the X pixmap and free only if it's zero. */ (*prevglxc->drawPixmap->pScreen->DestroyPixmap)(pPixmap); __glXFree(prevglxc->drawPixmap); } prevglxc->drawPixmap = NULL; } ChangeCurrentContext(cl, glxc, tag); StopUsingContext(prevglxc); } else { tag = AddCurrentContext(cl, glxc); } if (glxc) { if (drawPixmap) { drawPixmap->refcnt++; glxc->drawPixmap = drawPixmap; } if (readPixmap && (readPixmap != drawPixmap)) { readPixmap->refcnt++; glxc->readPixmap = readPixmap; } StartUsingContext(cl, glxc); reply.contextTag = tag; } else { reply.contextTag = 0; } reply.length = 0; reply.type = X_Reply; reply.sequenceNumber = client->sequence; if (client->swapped) { __glXSwapMakeCurrentReply(client, &reply); } else { WriteToClient(client, sz_xGLXMakeCurrentReply, (char *)&reply); } return Success; } int __glXIsDirect(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXIsDirectReq *req = (xGLXIsDirectReq *) pc; xGLXIsDirectReply reply; __GLXcontext *glxc; /* ** Find the GL context. */ glxc = (__GLXcontext *) LookupIDByType(req->context, __glXContextRes); if (!glxc) { client->errorValue = req->context; return __glXBadContext; } reply.isDirect = glxc->isDirect; reply.length = 0; reply.type = X_Reply; reply.sequenceNumber = client->sequence; if (client->swapped) { __glXSwapIsDirectReply(client, &reply); } else { WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); } return Success; } int __glXQueryVersion(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) pc; xGLXQueryVersionReply reply; GLuint major, minor; major = req->majorVersion; minor = req->minorVersion; (void)major; (void)minor; /* ** Server should take into consideration the version numbers sent by the ** client if it wants to work with older clients; however, in this ** implementation the server just returns its version number. */ reply.majorVersion = GLX_SERVER_MAJOR_VERSION; reply.minorVersion = GLX_SERVER_MINOR_VERSION; reply.length = 0; reply.type = X_Reply; reply.sequenceNumber = client->sequence; if (client->swapped) { __glXSwapQueryVersionReply(client, &reply); } else { WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply); } return Success; } int __glXWaitGL(__GLXclientState *cl, GLbyte *pc) { xGLXWaitGLReq *req = (xGLXWaitGLReq *)pc; int error; if (!__glXForceCurrent(cl, req->contextTag, &error)) { return error; } CALL_Finish( GET_DISPATCH(), () ); return Success; } int __glXWaitX(__GLXclientState *cl, GLbyte *pc) { xGLXWaitXReq *req = (xGLXWaitXReq *)pc; int error; if (!__glXForceCurrent(cl, req->contextTag, &error)) { return error; } /* ** In a multithreaded server that had separate X and GL threads, we would ** have to wait for the X thread to finish before returning. As it stands, ** this sample implementation only supports singlethreaded servers, and ** nothing needs to be done here. */ return Success; } int __glXCopyContext(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc; GLXContextID source = req->source; GLXContextID dest = req->dest; GLXContextTag tag = req->contextTag; __GLXcontext *src, *dst; int error; /* ** Check that each context exists. */ src = (__GLXcontext *) LookupIDByType(source, __glXContextRes); if (!src) { client->errorValue = source; return __glXBadContext; } dst = (__GLXcontext *) LookupIDByType(dest, __glXContextRes); if (!dst) { client->errorValue = dest; return __glXBadContext; } /* ** They must be in the same address space, and same screen. ** NOTE: no support for direct rendering contexts here. */ if (src->isDirect || dst->isDirect || (src->pGlxScreen != dst->pGlxScreen)) { client->errorValue = source; return BadMatch; } /* ** The destination context must not be current for any client. */ if (dst->isCurrent) { client->errorValue = dest; return BadAccess; } if (tag) { __GLXcontext *tagcx = __glXLookupContextByTag(cl, tag); if (!tagcx) { return __glXBadContextTag; } if (tagcx != src) { /* ** This would be caused by a faulty implementation of the client ** library. */ return BadMatch; } /* ** In this case, glXCopyContext 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 copy is executed. */ CALL_Finish( GET_DISPATCH(), () ); __GLX_NOTE_FLUSHED_CMDS(tagcx); } else { return error; } } #if 0 /* FIXME: We probably need to add DRIcontext::copyContext for * this. */ /* ** Issue copy. The only reason for failure is a bad mask. */ if (!(*dst->gc->exports.copyContext)((__GLcontext *)dst->gc, (__GLcontext *)src->gc, mask)) { client->errorValue = mask; return BadValue; } #endif return Success; } int DoGetVisualConfigs(__GLXclientState *cl, unsigned screen, GLboolean do_swap) { ClientPtr client = cl->client; xGLXGetVisualConfigsReply reply; __GLXscreenInfo *pGlxScreen; __GLcontextModes *modes; CARD32 buf[__GLX_TOTAL_CONFIG]; int p; __GLX_DECLARE_SWAP_VARIABLES; __GLX_DECLARE_SWAP_ARRAY_VARIABLES; if (screen >= screenInfo.numScreens) { /* The client library must send a valid screen number. */ client->errorValue = screen; return BadValue; } pGlxScreen = &__glXActiveScreens[screen]; reply.numVisuals = pGlxScreen->numUsableVisuals; reply.numProps = __GLX_TOTAL_CONFIG; reply.length = (pGlxScreen->numUsableVisuals * __GLX_SIZE_CARD32 * __GLX_TOTAL_CONFIG) >> 2; reply.type = X_Reply; reply.sequenceNumber = client->sequence; if ( do_swap ) { __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.numVisuals); __GLX_SWAP_INT(&reply.numProps); } WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char *)&reply); for ( modes = pGlxScreen->modes ; modes != NULL ; modes = modes->next ) { if (modes->visualID == 0) { /* not a usable visual */ continue; } p = 0; buf[p++] = modes->visualID; buf[p++] = _gl_convert_to_x_visual_type( modes->visualType ); buf[p++] = modes->rgbMode; buf[p++] = modes->redBits; buf[p++] = modes->greenBits; buf[p++] = modes->blueBits; buf[p++] = modes->alphaBits; buf[p++] = modes->accumRedBits; buf[p++] = modes->accumGreenBits; buf[p++] = modes->accumBlueBits; buf[p++] = modes->accumAlphaBits; buf[p++] = modes->doubleBufferMode; buf[p++] = modes->stereoMode; buf[p++] = modes->rgbBits; buf[p++] = modes->depthBits; buf[p++] = modes->stencilBits; buf[p++] = modes->numAuxBuffers; buf[p++] = modes->level; /* ** Add token/value pairs for extensions. */ buf[p++] = GLX_VISUAL_CAVEAT_EXT; buf[p++] = modes->visualRating; buf[p++] = GLX_TRANSPARENT_TYPE; buf[p++] = modes->transparentPixel; buf[p++] = GLX_TRANSPARENT_RED_VALUE; buf[p++] = modes->transparentRed; buf[p++] = GLX_TRANSPARENT_GREEN_VALUE; buf[p++] = modes->transparentGreen; buf[p++] = GLX_TRANSPARENT_BLUE_VALUE; buf[p++] = modes->transparentBlue; buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE; buf[p++] = modes->transparentAlpha; buf[p++] = GLX_TRANSPARENT_INDEX_VALUE; buf[p++] = modes->transparentIndex; if ( do_swap ) { __GLX_SWAP_INT_ARRAY(buf, __GLX_TOTAL_CONFIG); } WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_TOTAL_CONFIG, (char *)buf); } return Success; } int __glXGetVisualConfigs(__GLXclientState *cl, GLbyte *pc) { xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc; return DoGetVisualConfigs( cl, req->screen, GL_FALSE ); } #define __GLX_TOTAL_FBCONFIG_ATTRIBS (28) #define __GLX_FBCONFIG_ATTRIBS_LENGTH (__GLX_TOTAL_FBCONFIG_ATTRIBS * 2) /** * Send the set of GLXFBConfigs to the client. There is not currently * and interface into the driver on the server-side to get GLXFBConfigs, * so we "invent" some based on the \c __GLXvisualConfig structures that * the driver does supply. * * The reply format for both \c glXGetFBConfigs and \c glXGetFBConfigsSGIX * is the same, so this routine pulls double duty. */ int DoGetFBConfigs(__GLXclientState *cl, unsigned screen, GLboolean do_swap) { ClientPtr client = cl->client; xGLXGetFBConfigsReply reply; __GLXscreenInfo *pGlxScreen; CARD32 buf[__GLX_FBCONFIG_ATTRIBS_LENGTH]; int p; __GLcontextModes *modes; __GLX_DECLARE_SWAP_VARIABLES; __GLX_DECLARE_SWAP_ARRAY_VARIABLES; if (screen >= screenInfo.numScreens) { /* The client library must send a valid screen number. */ client->errorValue = screen; return BadValue; } pGlxScreen = &__glXActiveScreens[screen]; reply.numFBConfigs = pGlxScreen->numUsableVisuals; reply.numAttribs = __GLX_TOTAL_FBCONFIG_ATTRIBS; reply.length = (__GLX_FBCONFIG_ATTRIBS_LENGTH * reply.numFBConfigs); reply.type = X_Reply; reply.sequenceNumber = client->sequence; if ( do_swap ) { __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.numFBConfigs); __GLX_SWAP_INT(&reply.numAttribs); } WriteToClient(client, sz_xGLXGetFBConfigsReply, (char *)&reply); for ( modes = pGlxScreen->modes ; modes != NULL ; modes = modes->next ) { if (modes->visualID == 0) { /* not a usable visual */ continue; } p = 0; #define WRITE_PAIR(tag,value) \ do { buf[p++] = tag ; buf[p++] = value ; } while( 0 ) WRITE_PAIR( GLX_VISUAL_ID, modes->visualID ); WRITE_PAIR( GLX_FBCONFIG_ID, modes->visualID ); WRITE_PAIR( GLX_X_RENDERABLE, GL_TRUE ); WRITE_PAIR( GLX_RGBA, modes->rgbMode ); WRITE_PAIR( GLX_DOUBLEBUFFER, modes->doubleBufferMode ); WRITE_PAIR( GLX_STEREO, modes->stereoMode ); WRITE_PAIR( GLX_BUFFER_SIZE, modes->rgbBits ); WRITE_PAIR( GLX_LEVEL, modes->level ); WRITE_PAIR( GLX_AUX_BUFFERS, modes->numAuxBuffers ); WRITE_PAIR( GLX_RED_SIZE, modes->redBits ); WRITE_PAIR( GLX_GREEN_SIZE, modes->greenBits ); WRITE_PAIR( GLX_BLUE_SIZE, modes->blueBits ); WRITE_PAIR( GLX_ALPHA_SIZE, modes->alphaBits ); WRITE_PAIR( GLX_ACCUM_RED_SIZE, modes->accumRedBits ); WRITE_PAIR( GLX_ACCUM_GREEN_SIZE, modes->accumGreenBits ); WRITE_PAIR( GLX_ACCUM_BLUE_SIZE, modes->accumBlueBits ); WRITE_PAIR( GLX_ACCUM_ALPHA_SIZE, modes->accumAlphaBits ); WRITE_PAIR( GLX_DEPTH_SIZE, modes->depthBits ); WRITE_PAIR( GLX_STENCIL_SIZE, modes->stencilBits ); WRITE_PAIR( GLX_X_VISUAL_TYPE, modes->visualType ); /* ** Add token/value pairs for extensions. */ WRITE_PAIR( GLX_CONFIG_CAVEAT, modes->visualRating ); WRITE_PAIR( GLX_TRANSPARENT_TYPE, modes->transparentPixel ); WRITE_PAIR( GLX_TRANSPARENT_RED_VALUE, modes->transparentRed ); WRITE_PAIR( GLX_TRANSPARENT_GREEN_VALUE, modes->transparentGreen ); WRITE_PAIR( GLX_TRANSPARENT_BLUE_VALUE, modes->transparentBlue ); WRITE_PAIR( GLX_TRANSPARENT_ALPHA_VALUE, modes->transparentAlpha ); WRITE_PAIR( GLX_TRANSPARENT_INDEX_VALUE, modes->transparentIndex ); WRITE_PAIR( GLX_SWAP_METHOD_OML, modes->swapMethod ); if ( do_swap ) { __GLX_SWAP_INT_ARRAY(buf, __GLX_FBCONFIG_ATTRIBS_LENGTH); } WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_FBCONFIG_ATTRIBS_LENGTH, (char *)buf); } return Success; } int __glXGetFBConfigs(__GLXclientState *cl, GLbyte *pc) { xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc; return DoGetFBConfigs( cl, req->screen, GL_FALSE ); } int __glXGetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc) { xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc; return DoGetFBConfigs( cl, req->screen, GL_FALSE ); } /* ** Create a GLX Pixmap from an X Pixmap. */ int DoCreateGLXPixmap(__GLXclientState *cl, VisualID visual, GLuint screenNum, XID pixmapId, XID glxpixmapId) { ClientPtr client = cl->client; DrawablePtr pDraw; ScreenPtr pScreen; VisualPtr pVisual; __GLXpixmap *pGlxPixmap; __GLXscreenInfo *pGlxScreen; __GLcontextModes *modes; int i; LEGAL_NEW_RESOURCE(glxpixmapId, client); pDraw = (DrawablePtr) LookupDrawable(pixmapId, client); if (!pDraw || pDraw->type != DRAWABLE_PIXMAP) { client->errorValue = pixmapId; return BadPixmap; } /* ** Check if screen of visual matches screen of pixmap. */ pScreen = pDraw->pScreen; if (screenNum != pScreen->myNum) { return BadMatch; } /* ** Find the VisualRec for this visual. */ pVisual = pScreen->visuals; for (i=0; i < pScreen->numVisuals; i++, pVisual++) { if (pVisual->vid == visual) { break; } } if (i == pScreen->numVisuals) { client->errorValue = visual; return BadValue; } /* ** Check if depth of visual matches depth of pixmap. */ if (pVisual->nplanes != pDraw->depth) { return BadMatch; } /* ** Get configuration of the visual. */ pGlxScreen = &__glXActiveScreens[screenNum]; #if 0 modes = _gl_context_modes_find_visual( pGlxScreen->modes, visual ); if (modes == NULL) { /* ** Visual not support on this screen by this OpenGL implementation. */ client->errorValue = visual; return BadValue; } #endif pGlxPixmap = (__GLXpixmap *) __glXMalloc(sizeof(__GLXpixmap)); if (!pGlxPixmap) { return BadAlloc; } if (!(AddResource(glxpixmapId, __glXPixmapRes, pGlxPixmap))) { return BadAlloc; } pGlxPixmap->pDraw = pDraw; pGlxPixmap->pGlxScreen = pGlxScreen; pGlxPixmap->pScreen = pScreen; pGlxPixmap->idExists = True; pGlxPixmap->refcnt = 0; pGlxPixmap->modes = modes; /* ** Bump the ref count on the X pixmap so it won't disappear. */ ((PixmapPtr) pDraw)->refcnt++; return Success; } int __glXCreateGLXPixmap(__GLXclientState *cl, GLbyte *pc) { xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc; return DoCreateGLXPixmap( cl, req->visual, req->screen, req->pixmap, req->glxpixmap ); } int __glXCreatePixmap(__GLXclientState *cl, GLbyte *pc) { xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc; return DoCreateGLXPixmap( cl, req->fbconfig, req->screen, req->pixmap, req->glxpixmap ); } int __glXCreateGLXPixmapWithConfigSGIX(__GLXclientState *cl, GLbyte *pc) { xGLXCreateGLXPixmapWithConfigSGIXReq *req = (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc; return DoCreateGLXPixmap( cl, req->fbconfig, req->screen, req->pixmap, req->glxpixmap ); } /** * Destroy a GLX pixmap. This function is used for both * \c glXDestroyGLXPixmap and \c glXDestroyPixmap. */ int __glXDestroyGLXPixmap(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc; XID glxpixmap = req->glxpixmap; /* ** Check if it's a valid GLX pixmap. */ if (!LookupIDByType(glxpixmap, __glXPixmapRes)) { client->errorValue = glxpixmap; return __glXBadPixmap; } FreeResource(glxpixmap, FALSE); return Success; } /*****************************************************************************/ /* ** NOTE: There is no portable implementation for swap buffers as of ** this time that is of value. Consequently, this code must be ** implemented by somebody other than SGI. */ int __glXSwapBuffers(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; DrawablePtr pDraw; xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc; GLXContextTag tag = req->contextTag; XID drawId = req->drawable; __GLXpixmap *pGlxPixmap; __GLXcontext *glxc = NULL; int error; /* ** 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; } /* ** 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. */ CALL_Finish( GET_DISPATCH(), () ); __GLX_NOTE_FLUSHED_CMDS(glxc); } else { return error; } } if (pDraw) { __GLXdrawablePrivate *glxPriv; if (glxc) { glxPriv = __glXGetDrawablePrivate(pDraw, drawId, glxc->modes); if (glxPriv == NULL) { return __glXBadDrawable; } } else { glxPriv = __glXFindDrawablePrivate(drawId); if (glxPriv == NULL) { /* This is a window we've never seen before, do nothing */ return Success; } } { __DRIscreen *driScreen; __DRIdrawable *driDraw; driScreen = &__glXgetActiveScreen(pDraw->pScreen->myNum)->driScreen; driDraw = (driScreen->getDrawable)(NULL, drawId, driScreen->private); CALL_Finish( GET_DISPATCH(), () ); (*driDraw->swapBuffers)(NULL, driDraw->private); } } return Success; } int __glXQueryContextInfoEXT(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; __GLXcontext *ctx; xGLXQueryContextInfoEXTReq *req; xGLXQueryContextInfoEXTReply reply; int nProps; int *sendBuf, *pSendBuf; int nReplyBytes; req = (xGLXQueryContextInfoEXTReq *)pc; ctx = (__GLXcontext *) LookupIDByType(req->context, __glXContextRes); if (!ctx) { client->errorValue = req->context; return __glXBadContext; } nProps = 3; reply.length = nProps << 1; reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.n = nProps; nReplyBytes = reply.length << 2; sendBuf = (int *)__glXMalloc((size_t)nReplyBytes); if (sendBuf == NULL) { return __glXBadContext; /* XXX: Is this correct? */ } pSendBuf = sendBuf; *pSendBuf++ = GLX_SHARE_CONTEXT_EXT; *pSendBuf++ = (int)(ctx->share_id); *pSendBuf++ = GLX_VISUAL_ID_EXT; *pSendBuf++ = (int)(ctx->pVisual->vid); *pSendBuf++ = GLX_SCREEN_EXT; *pSendBuf++ = (int)(ctx->pScreen->myNum); if (client->swapped) { __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf); } else { WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, (char *)&reply); WriteToClient(client, nReplyBytes, (char *)sendBuf); } __glXFree((char *)sendBuf); return Success; } static void FillAlphaChannel (PixmapPtr pixmap) { int i, j; CARD32 *pixels = (CARD32 *)pixmap->devPrivate.ptr; CARD32 rowstride = pixmap->devKind / 4; CARD32 x, y; x = pixmap->drawable.x; y = pixmap->drawable.y; for (i = y; i < pixmap->drawable.height + y; ++i) { for (j = x; j < pixmap->drawable.width + x; ++j) { int index = i * rowstride + j; pixels[index] |= 0xFF000000; } } } int __glXBindTexImageEXT(__GLXclientState *cl, GLbyte *pc) { xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; ClientPtr client = cl->client; PixmapPtr pixmap; __GLXpixmap *pGlxPixmap; GLXDrawable drawId; int buffer; int error; int bpp; pc += __GLX_VENDPRIV_HDR_SIZE; drawId = *((CARD32 *) (pc)); buffer = *((INT32 *) (pc + 4)); if (buffer != GLX_FRONT_LEFT_EXT) return __glXBadPixmap; if (!__glXForceCurrent (cl, req->contextTag, &error)) return error; pGlxPixmap = (__GLXpixmap *)LookupIDByType(drawId, __glXPixmapRes); if (!pGlxPixmap) { client->errorValue = drawId; return __glXBadPixmap; } pixmap = (PixmapPtr) pGlxPixmap->pDraw; bpp = pixmap->drawable.depth == 24 ? 4 : 2; /* XXX 24bpp packed, 8, etc */ CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, pixmap->devKind / bpp) ); CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, pixmap->drawable.y) ); CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, pixmap->drawable.x) ); if (bpp == 4) FillAlphaChannel(pixmap); CALL_TexImage2D( GET_DISPATCH(), ( GL_TEXTURE_RECTANGLE_ARB, 0, bpp == 4 ? 4 : 3, pixmap->drawable.width, pixmap->drawable.height, 0, bpp == 4 ? GL_BGRA : GL_RGB, bpp == 4 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5, pixmap->devPrivate.ptr ) ); return Success; } int __glXReleaseTexImageEXT(__GLXclientState *cl, GLbyte *pc) { xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc; ClientPtr client = cl->client; __GLXpixmap *pGlxPixmap; GLXDrawable drawId; int buffer; int error; pc += __GLX_VENDPRIV_HDR_SIZE; drawId = *((CARD32 *) (pc)); buffer = *((INT32 *) (pc + 4)); if (!__glXForceCurrent (cl, req->contextTag, &error)) return error; pGlxPixmap = (__GLXpixmap *)LookupIDByType(drawId, __glXPixmapRes); if (!pGlxPixmap) { client->errorValue = drawId; return __glXBadDrawable; } return Success; } /************************************************************************/ /* ** Render and Renderlarge are not in the GLX API. They are used by the GLX ** client library to send batches of GL rendering commands. */ /* ** Execute all the drawing commands in a request. */ int __glXRender(__GLXclientState *cl, GLbyte *pc) { xGLXRenderReq *req; ClientPtr client= cl->client; int left, cmdlen, error; int commandsDone; CARD16 opcode; __GLXrenderHeader *hdr; __GLXcontext *glxc; /* ** NOTE: much of this code also appears in the byteswapping version of this ** routine, __glXSwapRender(). Any changes made here should also be ** duplicated there. */ req = (xGLXRenderReq *) pc; glxc = __glXForceCurrent(cl, req->contextTag, &error); if (!glxc) { return error; } commandsDone = 0; pc += sz_xGLXRenderReq; left = (req->length << 2) - sz_xGLXRenderReq; while (left > 0) { __GLXrenderSizeData *entry; int extra; void (* proc)(GLbyte *); /* ** Verify that the header length and the overall length agree. ** Also, each command must be word aligned. */ hdr = (__GLXrenderHeader *) pc; cmdlen = hdr->length; opcode = hdr->opcode; /* ** Check for core opcodes and grab entry data. */ if ( (opcode >= __GLX_MIN_RENDER_OPCODE) && (opcode <= __GLX_MAX_RENDER_OPCODE) ) { entry = &__glXRenderSizeTable[opcode]; proc = __glXRenderTable[opcode]; #if __GLX_MAX_RENDER_OPCODE_EXT > __GLX_MIN_RENDER_OPCODE_EXT } else if ( (opcode >= __GLX_MIN_RENDER_OPCODE_EXT) && (opcode <= __GLX_MAX_RENDER_OPCODE_EXT) ) { entry = &__glXRenderSizeTable_EXT[opcode - __GLX_MIN_RENDER_OPCODE_EXT]; proc = __glXRenderTable_EXT[opcode - __GLX_MIN_RENDER_OPCODE_EXT]; #endif /* __GLX_MAX_RENDER_OPCODE_EXT > __GLX_MIN_RENDER_OPCODE_EXT */ } else { client->errorValue = commandsDone; return __glXBadRenderRequest; } if (!entry->bytes) { /* unused opcode */ client->errorValue = commandsDone; return __glXBadRenderRequest; } if (entry->varsize) { /* variable size command */ extra = (*entry->varsize)(pc + __GLX_RENDER_HDR_SIZE, False); if (extra < 0) { extra = 0; } if (cmdlen != __GLX_PAD(entry->bytes + extra)) { return BadLength; } } else { /* constant size command */ if (cmdlen != __GLX_PAD(entry->bytes)) { return BadLength; } } if (left < cmdlen) { return BadLength; } /* ** Skip over the header and execute the command. We allow the ** caller to trash the command memory. This is useful especially ** for things that require double alignment - they can just shift ** the data towards lower memory (trashing the header) by 4 bytes ** and achieve the required alignment. */ (*proc)(pc + __GLX_RENDER_HDR_SIZE); pc += cmdlen; left -= cmdlen; commandsDone++; } __GLX_NOTE_UNFLUSHED_CMDS(glxc); return Success; } /* ** Execute a large rendering request (one that spans multiple X requests). */ int __glXRenderLarge(__GLXclientState *cl, GLbyte *pc) { xGLXRenderLargeReq *req; ClientPtr client= cl->client; GLuint dataBytes; void (*proc)(GLbyte *); __GLXrenderLargeHeader *hdr; __GLXcontext *glxc; int error; CARD16 opcode; /* ** NOTE: much of this code also appears in the byteswapping version of this ** routine, __glXSwapRenderLarge(). Any changes made here should also be ** duplicated there. */ req = (xGLXRenderLargeReq *) pc; glxc = __glXForceCurrent(cl, req->contextTag, &error); if (!glxc) { /* Reset in case this isn't 1st request. */ __glXResetLargeCommandStatus(cl); return error; } dataBytes = req->dataBytes; /* ** Check the request length. */ if ((req->length << 2) != __GLX_PAD(dataBytes) + sz_xGLXRenderLargeReq) { client->errorValue = req->length; /* Reset in case this isn't 1st request. */ __glXResetLargeCommandStatus(cl); return BadLength; } pc += sz_xGLXRenderLargeReq; if (cl->largeCmdRequestsSoFar == 0) { __GLXrenderSizeData *entry; int extra, cmdlen; /* ** This is the first request of a multi request command. ** Make enough space in the buffer, then copy the entire request. */ if (req->requestNumber != 1) { client->errorValue = req->requestNumber; return __glXBadLargeRequest; } hdr = (__GLXrenderLargeHeader *) pc; cmdlen = hdr->length; opcode = hdr->opcode; /* ** Check for core opcodes and grab entry data. */ if ( (opcode >= __GLX_MIN_RENDER_OPCODE) && (opcode <= __GLX_MAX_RENDER_OPCODE) ) { entry = &__glXRenderSizeTable[opcode]; #if __GLX_MAX_RENDER_OPCODE_EXT > __GLX_MIN_RENDER_OPCODE_EXT } else if ( (opcode >= __GLX_MIN_RENDER_OPCODE_EXT) && (opcode <= __GLX_MAX_RENDER_OPCODE_EXT) ) { opcode -= __GLX_MIN_RENDER_OPCODE_EXT; entry = &__glXRenderSizeTable_EXT[opcode]; #endif /* __GLX_MAX_RENDER_OPCODE_EXT > __GLX_MIN_RENDER_OPCODE_EXT */ } else { client->errorValue = opcode; return __glXBadLargeRequest; } if (!entry->bytes) { /* unused opcode */ client->errorValue = opcode; return __glXBadLargeRequest; } if (entry->varsize) { /* ** If it's a variable-size command (a command whose length must ** be computed from its parameters), all the parameters needed ** will be in the 1st request, so it's okay to do this. */ extra = (*entry->varsize)(pc + __GLX_RENDER_LARGE_HDR_SIZE, False); if (extra < 0) { extra = 0; } /* large command's header is 4 bytes longer, so add 4 */ if (cmdlen != __GLX_PAD(entry->bytes + 4 + extra)) { return BadLength; } } else { /* constant size command */ if (cmdlen != __GLX_PAD(entry->bytes + 4)) { return BadLength; } } /* ** Make enough space in the buffer, then copy the entire request. */ if (cl->largeCmdBufSize < cmdlen) { if (!cl->largeCmdBuf) { cl->largeCmdBuf = (GLbyte *) __glXMalloc((size_t)cmdlen); } else { cl->largeCmdBuf = (GLbyte *) __glXRealloc(cl->largeCmdBuf, (size_t)cmdlen); } if (!cl->largeCmdBuf) { return BadAlloc; } cl->largeCmdBufSize = cmdlen; } __glXMemcpy(cl->largeCmdBuf, pc, dataBytes); cl->largeCmdBytesSoFar = dataBytes; cl->largeCmdBytesTotal = cmdlen; cl->largeCmdRequestsSoFar = 1; cl->largeCmdRequestsTotal = req->requestTotal; return Success; } else { /* ** We are receiving subsequent (i.e. not the first) requests of a ** multi request command. */ /* ** Check the request number and the total request count. */ if (req->requestNumber != cl->largeCmdRequestsSoFar + 1) { client->errorValue = req->requestNumber; __glXResetLargeCommandStatus(cl); return __glXBadLargeRequest; } if (req->requestTotal != cl->largeCmdRequestsTotal) { client->errorValue = req->requestTotal; __glXResetLargeCommandStatus(cl); return __glXBadLargeRequest; } /* ** Check that we didn't get too much data. */ if ((cl->largeCmdBytesSoFar + dataBytes) > cl->largeCmdBytesTotal) { client->errorValue = dataBytes; __glXResetLargeCommandStatus(cl); return __glXBadLargeRequest; } __glXMemcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes); cl->largeCmdBytesSoFar += dataBytes; cl->largeCmdRequestsSoFar++; if (req->requestNumber == cl->largeCmdRequestsTotal) { /* ** This is the last request; it must have enough bytes to complete ** the command. */ /* NOTE: the two pad macros have been added below; they are needed ** because the client library pads the total byte count, but not ** the per-request byte counts. The Protocol Encoding says the ** total byte count should not be padded, so a proposal will be ** made to the ARB to relax the padding constraint on the total ** byte count, thus preserving backward compatibility. Meanwhile, ** the padding done below fixes a bug that did not allow ** large commands of odd sizes to be accepted by the server. */ if (__GLX_PAD(cl->largeCmdBytesSoFar) != __GLX_PAD(cl->largeCmdBytesTotal)) { client->errorValue = dataBytes; __glXResetLargeCommandStatus(cl); return __glXBadLargeRequest; } hdr = (__GLXrenderLargeHeader *) cl->largeCmdBuf; opcode = hdr->opcode; /* ** Use the opcode to index into the procedure table. */ if ( (opcode >= __GLX_MIN_RENDER_OPCODE) && (opcode <= __GLX_MAX_RENDER_OPCODE) ) { proc = __glXRenderTable[opcode]; #if __GLX_MAX_RENDER_OPCODE_EXT > __GLX_MIN_RENDER_OPCODE_EXT } else if ( (opcode >= __GLX_MIN_RENDER_OPCODE_EXT) && (opcode <= __GLX_MAX_RENDER_OPCODE_EXT) ) { opcode -= __GLX_MIN_RENDER_OPCODE_EXT; proc = __glXRenderTable_EXT[opcode]; #endif /* __GLX_MAX_RENDER_OPCODE_EXT > __GLX_MIN_RENDER_OPCODE_EXT */ } else { client->errorValue = opcode; return __glXBadLargeRequest; } /* ** Skip over the header and execute the command. */ (*proc)(cl->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE); __GLX_NOTE_UNFLUSHED_CMDS(glxc); /* ** Reset for the next RenderLarge series. */ __glXResetLargeCommandStatus(cl); } else { /* ** This is neither the first nor the last request. */ } return Success; } } extern RESTYPE __glXSwapBarrierRes; static int __glXBindSwapBarrierSGIX(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXBindSwapBarrierSGIXReq *req = (xGLXBindSwapBarrierSGIXReq *) pc; XID drawable = req->drawable; int barrier = req->barrier; DrawablePtr pDraw = (DrawablePtr) LookupDrawable(drawable, client); int screen = pDraw->pScreen->myNum; if (pDraw && (pDraw->type == DRAWABLE_WINDOW)) { if (__glXSwapBarrierFuncs && __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc) { int ret = __glXSwapBarrierFuncs[screen].bindSwapBarrierFunc(screen, drawable, barrier); if (ret == Success) { if (barrier) /* add source for cleanup when drawable is gone */ AddResource(drawable, __glXSwapBarrierRes, (pointer)screen); else /* delete source */ FreeResourceByType(drawable, __glXSwapBarrierRes, FALSE); } return ret; } } client->errorValue = drawable; return __glXBadDrawable; } static int __glXQueryMaxSwapBarriersSGIX(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXQueryMaxSwapBarriersSGIXReq *req = (xGLXQueryMaxSwapBarriersSGIXReq *) pc; xGLXQueryMaxSwapBarriersSGIXReply reply; int screen = req->screen; if (__glXSwapBarrierFuncs && __glXSwapBarrierFuncs[screen].queryMaxSwapBarriersFunc) reply.max = __glXSwapBarrierFuncs[screen].queryMaxSwapBarriersFunc(screen); else reply.max = 0; reply.length = 0; reply.type = X_Reply; reply.sequenceNumber = client->sequence; if (client->swapped) { __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_SHORT(&reply.sequenceNumber); } WriteToClient(client, sz_xGLXQueryMaxSwapBarriersSGIXReply, (char *) &reply); return Success; } #define GLX_BAD_HYPERPIPE_SGIX 92 static int __glxQueryHyperpipeNetworkSGIX(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXQueryHyperpipeNetworkSGIXReq * req = (xGLXQueryHyperpipeNetworkSGIXReq *) pc; xGLXQueryHyperpipeNetworkSGIXReply reply; int screen = req->screen; void *rdata = NULL; int length=0; int npipes=0; int n= 0; if (__glXHyperpipeFuncs && __glXHyperpipeFuncs[screen].queryHyperpipeNetworkFunc != NULL) { rdata = (__glXHyperpipeFuncs[screen].queryHyperpipeNetworkFunc(screen, &npipes, &n)); } length = __GLX_PAD(n) >> 2; reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.length = length; reply.n = n; reply.npipes = npipes; if (client->swapped) { __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.n); __GLX_SWAP_INT(&reply.npipes); } WriteToClient(client, sz_xGLXQueryHyperpipeNetworkSGIXReply, (char *) &reply); WriteToClient(client, length << 2, (char *)rdata); return Success; } static int __glxDestroyHyperpipeConfigSGIX (__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXDestroyHyperpipeConfigSGIXReq * req = (xGLXDestroyHyperpipeConfigSGIXReq *) pc; xGLXDestroyHyperpipeConfigSGIXReply reply; int screen = req->screen; int success = GLX_BAD_HYPERPIPE_SGIX; int hpId ; hpId = req->hpId; if (__glXHyperpipeFuncs && __glXHyperpipeFuncs[screen].destroyHyperpipeConfigFunc != NULL) { success = __glXHyperpipeFuncs[screen].destroyHyperpipeConfigFunc(screen, hpId); } reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.length = __GLX_PAD(0) >> 2; reply.n = 0; reply.success = success; if (client->swapped) { __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_SHORT(&reply.sequenceNumber); } WriteToClient(client, sz_xGLXDestroyHyperpipeConfigSGIXReply, (char *) &reply); return Success; } static int __glxQueryHyperpipeConfigSGIX(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXQueryHyperpipeConfigSGIXReq * req = (xGLXQueryHyperpipeConfigSGIXReq *) pc; xGLXQueryHyperpipeConfigSGIXReply reply; int screen = req->screen; void *rdata = NULL; int length; int npipes=0; int n= 0; int hpId; hpId = req->hpId; if (__glXHyperpipeFuncs && __glXHyperpipeFuncs[screen].queryHyperpipeConfigFunc != NULL) { rdata = __glXHyperpipeFuncs[screen].queryHyperpipeConfigFunc(screen, hpId,&npipes, &n); } length = __GLX_PAD(n) >> 2; reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.length = length; reply.n = n; reply.npipes = npipes; if (client->swapped) { __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.n); __GLX_SWAP_INT(&reply.npipes); } WriteToClient(client, sz_xGLXQueryHyperpipeConfigSGIXReply, (char *) &reply); WriteToClient(client, length << 2, (char *)rdata); return Success; } static int __glxHyperpipeConfigSGIX(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXHyperpipeConfigSGIXReq * req = (xGLXHyperpipeConfigSGIXReq *) pc; xGLXHyperpipeConfigSGIXReply reply; int screen = req->screen; void *rdata; int npipes=0, networkId; int hpId=-1; networkId = (int)req->networkId; npipes = (int)req->npipes; rdata = (void *)(req +1); if (__glXHyperpipeFuncs && __glXHyperpipeFuncs[screen].hyperpipeConfigFunc != NULL) { __glXHyperpipeFuncs[screen].hyperpipeConfigFunc(screen,networkId, &hpId, &npipes, (void *) rdata); } reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.length = __GLX_PAD(0) >> 2; reply.n = 0; reply.npipes = npipes; reply.hpId = hpId; if (client->swapped) { __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.npipes); __GLX_SWAP_INT(&reply.hpId); } WriteToClient(client, sz_xGLXHyperpipeConfigSGIXReply, (char *) &reply); return Success; } /************************************************************************/ /* ** No support is provided for the vendor-private requests other than ** allocating the entry points in the dispatch table. */ int __glXVendorPrivate(__GLXclientState *cl, GLbyte *pc) { xGLXVendorPrivateReq *req; GLint vendorcode; req = (xGLXVendorPrivateReq *) pc; vendorcode = req->vendorCode; #ifndef __DARWIN__ switch( vendorcode ) { case X_GLvop_SampleMaskSGIS: CALL_SampleMaskSGIS( GET_DISPATCH(), (*(GLfloat *)(pc + 4), *(GLboolean *)(pc + 8)) ); return Success; case X_GLvop_SamplePatternSGIS: CALL_SamplePatternSGIS( GET_DISPATCH(), (*(GLenum *)(pc + 4)) ); return Success; case X_GLXvop_BindSwapBarrierSGIX: return __glXBindSwapBarrierSGIX(cl, pc); case X_GLXvop_BindTexImageEXT: return __glXBindTexImageEXT(cl, pc); case X_GLXvop_ReleaseTexImageEXT: return __glXReleaseTexImageEXT(cl, pc); } #endif if ((vendorcode >= __GLX_MIN_VENDPRIV_OPCODE_EXT) && (vendorcode <= __GLX_MAX_VENDPRIV_OPCODE_EXT)) { (*__glXVendorPrivTable_EXT[vendorcode-__GLX_MIN_VENDPRIV_OPCODE_EXT]) (cl, (GLbyte*)req); return Success; } /* ** This sample implemention does not support any private requests. */ cl->client->errorValue = req->vendorCode; return __glXUnsupportedPrivateRequest; } int __glXVendorPrivateWithReply(__GLXclientState *cl, GLbyte *pc) { xGLXVendorPrivateWithReplyReq *req; GLint vendorcode; req = (xGLXVendorPrivateWithReplyReq *) pc; vendorcode = req->vendorCode; switch (vendorcode) { case X_GLXvop_QueryContextInfoEXT: return __glXQueryContextInfoEXT(cl, pc); case X_GLXvop_MakeCurrentReadSGI: return __glXMakeCurrentReadSGI(cl, pc); case X_GLXvop_QueryMaxSwapBarriersSGIX: return __glXQueryMaxSwapBarriersSGIX(cl, pc); case X_GLXvop_QueryHyperpipeNetworkSGIX: return __glxQueryHyperpipeNetworkSGIX(cl, pc); case X_GLXvop_QueryHyperpipeConfigSGIX: return __glxQueryHyperpipeConfigSGIX(cl, pc); case X_GLXvop_DestroyHyperpipeConfigSGIX: return __glxDestroyHyperpipeConfigSGIX(cl, pc); case X_GLXvop_HyperpipeConfigSGIX: return __glxHyperpipeConfigSGIX(cl, pc); case X_GLXvop_GetFBConfigsSGIX: return __glXGetFBConfigsSGIX(cl, pc); case X_GLXvop_CreateContextWithConfigSGIX: return __glXCreateContextWithConfigSGIX(cl, pc); case X_GLXvop_CreateGLXPixmapWithConfigSGIX: return __glXCreateGLXPixmapWithConfigSGIX(cl, pc); default: break; } if ((vendorcode >= __GLX_MIN_VENDPRIV_OPCODE_EXT) && (vendorcode <= __GLX_MAX_VENDPRIV_OPCODE_EXT)) { return (*__glXVendorPrivTable_EXT[vendorcode-__GLX_MIN_VENDPRIV_OPCODE_EXT]) (cl, (GLbyte*)req); } cl->client->errorValue = vendorcode; return __glXUnsupportedPrivateRequest; } int __glXQueryExtensionsString(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc; xGLXQueryExtensionsStringReply reply; GLuint screen; size_t n, length; const char *ptr; char *buf; screen = req->screen; /* ** Check if screen exists. */ if (screen >= screenInfo.numScreens) { client->errorValue = screen; return BadValue; } ptr = __glXActiveScreens[screen].GLXextensions; n = __glXStrlen(ptr) + 1; length = __GLX_PAD(n) >> 2; reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.length = length; reply.n = n; if ((buf = (char *) __glXMalloc(length << 2)) == NULL) { return BadAlloc; } __glXStrncpy(buf, ptr, n); if (client->swapped) { glxSwapQueryExtensionsStringReply(client, &reply, buf); } else { WriteToClient(client, sz_xGLXQueryExtensionsStringReply,(char *)&reply); WriteToClient(client, (int)(length << 2), (char *)buf); } __glXFree(buf); return Success; } int __glXQueryServerString(__GLXclientState *cl, GLbyte *pc) { ClientPtr client = cl->client; xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc; xGLXQueryServerStringReply reply; int name; GLuint screen; size_t n, length; const char *ptr; char *buf; name = req->name; screen = req->screen; /* ** Check if screen exists. */ if (screen >= screenInfo.numScreens) { client->errorValue = screen; return BadValue; } switch(name) { case GLX_VENDOR: ptr = __glXActiveScreens[screen].GLXvendor; break; case GLX_VERSION: ptr = __glXActiveScreens[screen].GLXversion; break; case GLX_EXTENSIONS: ptr = __glXActiveScreens[screen].GLXextensions; break; default: return BadValue; } n = __glXStrlen(ptr) + 1; length = __GLX_PAD(n) >> 2; reply.type = X_Reply; reply.sequenceNumber = client->sequence; reply.length = length; reply.n = n; if ((buf = (char *) Xalloc(length << 2)) == NULL) { return BadAlloc; } __glXStrncpy(buf, ptr, n); if (client->swapped) { glxSwapQueryServerStringReply(client, &reply, buf); } else { WriteToClient(client, sz_xGLXQueryServerStringReply, (char *)&reply); WriteToClient(client, (int)(length << 2), buf); } __glXFree(buf); return Success; } int __glXClientInfo(__GLXclientState *cl, GLbyte *pc) { xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc; const char *buf; cl->GLClientmajorVersion = req->major; cl->GLClientminorVersion = req->minor; if (cl->GLClientextensions) __glXFree(cl->GLClientextensions); buf = (const char *)(req+1); cl->GLClientextensions = __glXStrdup(buf); return Success; }