diff options
Diffstat (limited to 'hw/dmx/glxProxy/glxext.c')
-rw-r--r-- | hw/dmx/glxProxy/glxext.c | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/hw/dmx/glxProxy/glxext.c b/hw/dmx/glxProxy/glxext.c new file mode 100644 index 0000000..7f63b6b --- /dev/null +++ b/hw/dmx/glxProxy/glxext.c @@ -0,0 +1,496 @@ +/* + * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) + * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice including the dates of first publication and + * either this permission notice or a reference to + * http://oss.sgi.com/projects/FreeB/ + * shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Except as contained in this notice, the name of Silicon Graphics, Inc. + * shall not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization from + * Silicon Graphics, Inc. + */ + +#ifdef HAVE_DMX_CONFIG_H +#include <dmx-config.h> +#endif + +#include "dmx.h" + +#include "glxserver.h" +#include <windowstr.h> +#include <propertyst.h> +#include <os.h> +#include "g_disptab.h" +#include "glxutil.h" +#include "glxext.h" +#include "glxvisuals.h" +#include "micmap.h" +#include "glxswap.h" + +/* +** Stubs to satisfy miinitext.c references. +*/ +typedef int __GLXprovider; +__GLXprovider __glXDRISWRastProvider; +void GlxPushProvider(__GLXprovider *provider) { } + +/* +** Forward declarations. +*/ +static int __glXSwapDispatch(ClientPtr); +static int __glXDispatch(ClientPtr); + +/* +** Called when the extension is reset. +*/ +static void ResetExtension(ExtensionEntry* extEntry) +{ + __glXFlushContextCache(); + __glXScreenReset(); + SwapBarrierReset(); +} + +/* +** Initialize the per-client context storage. +*/ +static void ResetClientState(int clientIndex) +{ + __GLXclientState *cl = __glXClients[clientIndex]; + Display **keep_be_displays; + int i; + + free(cl->returnBuf); + free(cl->currentContexts); + free(cl->currentDrawables); + free(cl->largeCmdBuf); + + for (i=0; i< screenInfo.numScreens; i++) { + if (cl->be_displays[i]) + XCloseDisplay( cl->be_displays[i] ); + } + + keep_be_displays = cl->be_displays; + memset(cl, 0, sizeof(__GLXclientState)); + cl->be_displays = keep_be_displays; + + /* + ** By default, assume that the client supports + ** GLX major version 1 minor version 0 protocol. + */ + cl->GLClientmajorVersion = 1; + cl->GLClientminorVersion = 0; + free(cl->GLClientextensions); + + memset(cl->be_displays, 0, screenInfo.numScreens * sizeof(Display *)); +} + + +/* +** This procedure is called when the client who created the context goes +** away OR when glXDestroyContext is called. In either case, all we do is +** flag that the ID is no longer valid, and (maybe) free the context. +** use. +*/ +static int ContextGone(__GLXcontext* cx, XID id) +{ + cx->idExists = GL_FALSE; + if (!cx->isCurrent) { + __glXFreeContext(cx); + } + + return True; +} + +/* +** Free a client's state. +*/ +static int ClientGone(int clientIndex, XID id) +{ + __GLXcontext *cx; + __GLXclientState *cl = __glXClients[clientIndex]; + int i; + + if (cl) { + /* + ** Free all the contexts that are current for this client. + */ + for (i=0; i < cl->numCurrentContexts; i++) { + cx = cl->currentContexts[i]; + if (cx) { + cx->isCurrent = GL_FALSE; + if (!cx->idExists) { + __glXFreeContext(cx); + } + } + } + /* + ** Re-initialize the client state structure. Don't free it because + ** we'll probably get another client with this index and use the struct + ** again. There is a maximum of MAXCLIENTS of these structures. + */ + ResetClientState(clientIndex); + } + + return True; +} + +/* +** Free a GLX Pixmap. +*/ +void __glXFreeGLXPixmap( __GLXpixmap *pGlxPixmap ) +{ + if (!pGlxPixmap->idExists && + !pGlxPixmap->refcnt) { + + PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; + + /* + ** The DestroyPixmap routine should decrement the refcount and free + ** only if it's zero. + */ + (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); + free(pGlxPixmap->be_xids); + free(pGlxPixmap); + } + +} + +static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) +{ + + pGlxPixmap->idExists = False; + __glXFreeGLXPixmap( pGlxPixmap ); + + return True; +} + +void __glXFreeGLXWindow(__glXWindow *pGlxWindow) +{ + if (!pGlxWindow->idExists && !pGlxWindow->refcnt) { + WindowPtr pWindow = (WindowPtr) pGlxWindow->pDraw; + WindowPtr ret; + + dixLookupResourceByType((pointer) &ret, + pWindow->drawable.id, RT_WINDOW, + NullClient, DixUnknownAccess); + if (ret == pWindow) { + (*pGlxWindow->pScreen->DestroyWindow)(pWindow); + } + + free(pGlxWindow); + } +} + +static void WindowGone(__glXWindow *pGlxWindow, XID id) +{ + pGlxWindow->idExists = False; + __glXFreeGLXWindow(pGlxWindow); +} + +void __glXFreeGLXPbuffer(__glXPbuffer *pGlxPbuffer) +{ + if (!pGlxPbuffer->idExists && !pGlxPbuffer->refcnt) { + free(pGlxPbuffer->be_xids); + free(pGlxPbuffer); + } +} + +static void PbufferGone(__glXPbuffer *pGlxPbuffer, XID id) +{ + pGlxPbuffer->idExists = False; + __glXFreeGLXPbuffer(pGlxPbuffer); +} + +/* +** Free a context. +*/ +GLboolean __glXFreeContext(__GLXcontext *cx) +{ + if (cx->idExists || cx->isCurrent) return GL_FALSE; + + free(cx->feedbackBuf); + free(cx->selectBuf); + free(cx->real_ids); + free(cx->real_vids); + + if (cx->pGlxPixmap) { + /* + ** The previous drawable was a glx pixmap, release it. + */ + cx->pGlxPixmap->refcnt--; + __glXFreeGLXPixmap( cx->pGlxPixmap ); + cx->pGlxPixmap = 0; + } + + if (cx->pGlxReadPixmap) { + /* + ** The previous drawable was a glx pixmap, release it. + */ + cx->pGlxReadPixmap->refcnt--; + __glXFreeGLXPixmap( cx->pGlxReadPixmap ); + cx->pGlxReadPixmap = 0; + } + + if (cx->pGlxWindow) { + /* + ** The previous drawable was a glx window, release it. + */ + cx->pGlxWindow->refcnt--; + __glXFreeGLXWindow( cx->pGlxWindow ); + cx->pGlxWindow = 0; + } + + if (cx->pGlxReadWindow) { + /* + ** The previous drawable was a glx window, release it. + */ + cx->pGlxReadWindow->refcnt--; + __glXFreeGLXWindow( cx->pGlxReadWindow ); + cx->pGlxReadWindow = 0; + } + + free(cx); + + if (cx == __glXLastContext) { + __glXFlushContextCache(); + } + + return GL_TRUE; +} + +/* +** Initialize the GLX extension. +*/ +void GlxExtensionInit(void) +{ + ExtensionEntry *extEntry; + int i; + int glxSupported = 1; + + /* + // do not initialize GLX extension if GLX is not supported + // by ALL back-end servers. + */ + for (i=0; i<screenInfo.numScreens; i++) { + glxSupported &= (dmxScreens[i].glxMajorOpcode > 0); + } + + if (!glxSupported || !dmxGLXProxy) { + return; + } + + __glXContextRes = CreateNewResourceType((DeleteType)ContextGone, + "GLXContext"); + __glXClientRes = CreateNewResourceType((DeleteType)ClientGone, + "GLXClient"); + __glXPixmapRes = CreateNewResourceType((DeleteType)PixmapGone, + "GLXPixmap"); + __glXWindowRes = CreateNewResourceType((DeleteType)WindowGone, + "GLXWindow"); + __glXPbufferRes = CreateNewResourceType((DeleteType)PbufferGone, + "GLXPbuffer"); + + if (!__glXContextRes || !__glXClientRes || !__glXPixmapRes || + !__glXWindowRes || !__glXPbufferRes) + return; + + /* + ** Add extension to server extensions. + */ + extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, + __GLX_NUMBER_ERRORS, __glXDispatch, + __glXSwapDispatch, ResetExtension, + StandardMinorOpcode); + if (!extEntry) { + FatalError("__glXExtensionInit: AddExtensions failed\n"); + return; + } + /* + if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { + ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); + return; + } + */ + + __glXerrorBase = extEntry->errorBase; + __glXBadContext = extEntry->errorBase + GLXBadContext; + __glXBadContextState = extEntry->errorBase + GLXBadContextState; + __glXBadDrawable = extEntry->errorBase + GLXBadDrawable; + __glXBadPixmap = extEntry->errorBase + GLXBadPixmap; + __glXBadContextTag = extEntry->errorBase + GLXBadContextTag; + __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow; + __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest; + __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest; + __glXUnsupportedPrivateRequest = extEntry->errorBase + + GLXUnsupportedPrivateRequest; + __glXBadFBConfig = extEntry->errorBase + GLXBadFBConfig; + __glXBadPbuffer = extEntry->errorBase + GLXBadPbuffer; + + /* + ** Initialize table of client state. There is never a client 0. + */ + for (i=1; i <= MAXCLIENTS; i++) { + __glXClients[i] = 0; + } + + /* + ** Initialize screen specific data. + */ + __glXScreenInit(screenInfo.numScreens); + + /* + ** Initialize swap barrier support. + */ + SwapBarrierInit(); +} + +/************************************************************************/ + +Bool __glXCoreType(void) +{ + return 0; +} + +/************************************************************************/ + +void __glXFlushContextCache(void) +{ + __glXLastContext = 0; +} + +/************************************************************************/ + +/* +** Top level dispatcher; all commands are executed from here down. +*/ +static int __glXDispatch(ClientPtr client) +{ + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = calloc(1, sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + + cl->be_displays = calloc(screenInfo.numScreens, sizeof(Display *)); + if (!cl->be_displays) { + free( cl ); + return BadAlloc; + } + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->largeCmdRequestsTotal = 0; + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSingleTable[opcode]; + return (*proc)(cl, (GLbyte *) stuff); +} + +static int __glXSwapDispatch(ClientPtr client) +{ + REQUEST(xGLXSingleReq); + CARD8 opcode; + int (*proc)(__GLXclientState *cl, GLbyte *pc); + __GLXclientState *cl; + + opcode = stuff->glxCode; + cl = __glXClients[client->index]; + if (!cl) { + cl = calloc(1, sizeof(__GLXclientState)); + __glXClients[client->index] = cl; + if (!cl) { + return BadAlloc; + } + + cl->be_displays = calloc(screenInfo.numScreens, sizeof(Display *)); + if (!cl->be_displays) { + free( cl ); + return BadAlloc; + } + } + + if (!cl->inUse) { + /* + ** This is first request from this client. Associate a resource + ** with the client so we will be notified when the client dies. + */ + XID xid = FakeClientID(client->index); + if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { + return BadAlloc; + } + ResetClientState(client->index); + cl->inUse = GL_TRUE; + cl->client = client; + } + + /* + ** Check for valid opcode. + */ + if (opcode >= __GLX_SINGLE_TABLE_SIZE) { + return BadRequest; + } + + /* + ** Use the opcode to index into the procedure table. + */ + proc = __glXSwapSingleTable[opcode]; + return (*proc)(cl, (GLbyte *) stuff); +} + +int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) +{ + return BadRequest; +} + +void __glXNoSuchRenderOpcode(GLbyte *pc) +{ + return; +} + |