1706f2543Smrg/* 2706f2543Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3706f2543Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. 4706f2543Smrg * 5706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 6706f2543Smrg * copy of this software and associated documentation files (the "Software"), 7706f2543Smrg * to deal in the Software without restriction, including without limitation 8706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 10706f2543Smrg * Software is furnished to do so, subject to the following conditions: 11706f2543Smrg * 12706f2543Smrg * The above copyright notice including the dates of first publication and 13706f2543Smrg * either this permission notice or a reference to 14706f2543Smrg * http://oss.sgi.com/projects/FreeB/ 15706f2543Smrg * shall be included in all copies or substantial portions of the Software. 16706f2543Smrg * 17706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18706f2543Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20706f2543Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21706f2543Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22706f2543Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23706f2543Smrg * SOFTWARE. 24706f2543Smrg * 25706f2543Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc. 26706f2543Smrg * shall not be used in advertising or otherwise to promote the sale, use or 27706f2543Smrg * other dealings in this Software without prior written authorization from 28706f2543Smrg * Silicon Graphics, Inc. 29706f2543Smrg */ 30706f2543Smrg 31706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 32706f2543Smrg#include <dix-config.h> 33706f2543Smrg#endif 34706f2543Smrg 35706f2543Smrg#include <string.h> 36706f2543Smrg#include "glxserver.h" 37706f2543Smrg#include <windowstr.h> 38706f2543Smrg#include <propertyst.h> 39706f2543Smrg#include <registry.h> 40706f2543Smrg#include "privates.h" 41706f2543Smrg#include <os.h> 42706f2543Smrg#include "unpack.h" 43706f2543Smrg#include "glxutil.h" 44706f2543Smrg#include "glxext.h" 45706f2543Smrg#include "indirect_table.h" 46706f2543Smrg#include "indirect_util.h" 47706f2543Smrg 48706f2543Smrg/* 49706f2543Smrg** The last context used by the server. It is the context that is current 50706f2543Smrg** from the server's perspective. 51706f2543Smrg*/ 52706f2543Smrg__GLXcontext *__glXLastContext; 53706f2543Smrg__GLXcontext *__glXContextList; 54706f2543Smrg 55706f2543Smrg/* 56706f2543Smrg** X resources. 57706f2543Smrg*/ 58706f2543SmrgRESTYPE __glXContextRes; 59706f2543SmrgRESTYPE __glXDrawableRes; 60706f2543Smrg 61706f2543Smrg/* 62706f2543Smrg** Reply for most singles. 63706f2543Smrg*/ 64706f2543SmrgxGLXSingleReply __glXReply; 65706f2543Smrg 66706f2543Smrgstatic DevPrivateKeyRec glxClientPrivateKeyRec; 67706f2543Smrg#define glxClientPrivateKey (&glxClientPrivateKeyRec) 68706f2543Smrg 69706f2543Smrg/* 70706f2543Smrg** Client that called into GLX dispatch. 71706f2543Smrg*/ 72706f2543SmrgClientPtr __pGlxClient; 73706f2543Smrg 74706f2543Smrg/* 75706f2543Smrg** Forward declarations. 76706f2543Smrg*/ 77706f2543Smrgstatic int __glXDispatch(ClientPtr); 78706f2543Smrg 79706f2543Smrg/* 80706f2543Smrg** Called when the extension is reset. 81706f2543Smrg*/ 82706f2543Smrgstatic void ResetExtension(ExtensionEntry* extEntry) 83706f2543Smrg{ 84706f2543Smrg __glXFlushContextCache(); 85706f2543Smrg} 86706f2543Smrg 87706f2543Smrg/* 88706f2543Smrg** Reset state used to keep track of large (multi-request) commands. 89706f2543Smrg*/ 90706f2543Smrgvoid __glXResetLargeCommandStatus(__GLXclientState *cl) 91706f2543Smrg{ 92706f2543Smrg cl->largeCmdBytesSoFar = 0; 93706f2543Smrg cl->largeCmdBytesTotal = 0; 94706f2543Smrg cl->largeCmdRequestsSoFar = 0; 95706f2543Smrg cl->largeCmdRequestsTotal = 0; 96706f2543Smrg} 97706f2543Smrg 98706f2543Smrg/* 99706f2543Smrg** This procedure is called when the client who created the context goes 100706f2543Smrg** away OR when glXDestroyContext is called. In either case, all we do is 101706f2543Smrg** flag that the ID is no longer valid, and (maybe) free the context. 102706f2543Smrg** use. 103706f2543Smrg*/ 104706f2543Smrgstatic int ContextGone(__GLXcontext* cx, XID id) 105706f2543Smrg{ 106706f2543Smrg cx->idExists = GL_FALSE; 107706f2543Smrg if (!cx->isCurrent) { 108706f2543Smrg __glXFreeContext(cx); 109706f2543Smrg } 110706f2543Smrg 111706f2543Smrg return True; 112706f2543Smrg} 113706f2543Smrg 114706f2543Smrgstatic __GLXcontext *glxPendingDestroyContexts; 115706f2543Smrgstatic __GLXcontext *glxAllContexts; 116706f2543Smrgstatic int glxServerLeaveCount; 117706f2543Smrgstatic int glxBlockClients; 118706f2543Smrg 119706f2543Smrg/* 120706f2543Smrg** Destroy routine that gets called when a drawable is freed. A drawable 121706f2543Smrg** contains the ancillary buffers needed for rendering. 122706f2543Smrg*/ 123706f2543Smrgstatic Bool DrawableGone(__GLXdrawable *glxPriv, XID xid) 124706f2543Smrg{ 125706f2543Smrg __GLXcontext *c, *next; 126706f2543Smrg 127706f2543Smrg if (glxPriv->type == GLX_DRAWABLE_WINDOW || glxPriv->type == GLX_DRAWABLE_PIXMAP) { 128706f2543Smrg /* If this was created by glXCreateWindow, free the matching resource */ 129706f2543Smrg if (glxPriv->otherId) { 130706f2543Smrg XID other = glxPriv->otherId; 131706f2543Smrg glxPriv->otherId = 0; 132706f2543Smrg if (xid == other) 133706f2543Smrg FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE); 134706f2543Smrg else 135706f2543Smrg FreeResourceByType(other, __glXDrawableRes, TRUE); 136706f2543Smrg } 137706f2543Smrg /* otherwise this window was implicitly created by MakeCurrent */ 138706f2543Smrg } 139706f2543Smrg 140706f2543Smrg for (c = glxAllContexts; c; c = next) { 141706f2543Smrg next = c->next; 142706f2543Smrg if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) { 143706f2543Smrg (*c->loseCurrent)(c); 144706f2543Smrg c->isCurrent = GL_FALSE; 145706f2543Smrg if (c == __glXLastContext) 146706f2543Smrg __glXFlushContextCache(); 147706f2543Smrg } 148706f2543Smrg if (c->drawPriv == glxPriv) 149706f2543Smrg c->drawPriv = NULL; 150706f2543Smrg if (c->readPriv == glxPriv) 151706f2543Smrg c->readPriv = NULL; 152706f2543Smrg } 153706f2543Smrg 154706f2543Smrg /* drop our reference to any backing pixmap */ 155706f2543Smrg if (glxPriv->type == GLX_DRAWABLE_PIXMAP) 156706f2543Smrg glxPriv->pDraw->pScreen->DestroyPixmap((PixmapPtr)glxPriv->pDraw); 157706f2543Smrg 158706f2543Smrg glxPriv->destroy(glxPriv); 159706f2543Smrg 160706f2543Smrg return True; 161706f2543Smrg} 162706f2543Smrg 163706f2543Smrgvoid __glXAddToContextList(__GLXcontext *cx) 164706f2543Smrg{ 165706f2543Smrg cx->next = glxAllContexts; 166706f2543Smrg glxAllContexts = cx; 167706f2543Smrg} 168706f2543Smrg 169706f2543Smrgstatic void __glXRemoveFromContextList(__GLXcontext *cx) 170706f2543Smrg{ 171706f2543Smrg __GLXcontext *c, *prev; 172706f2543Smrg 173706f2543Smrg if (cx == glxAllContexts) 174706f2543Smrg glxAllContexts = cx->next; 175706f2543Smrg else { 176706f2543Smrg prev = glxAllContexts; 177706f2543Smrg for (c = glxAllContexts; c; c = c->next) { 178706f2543Smrg if (c == cx) 179706f2543Smrg prev->next = c->next; 180706f2543Smrg prev = c; 181706f2543Smrg } 182706f2543Smrg } 183706f2543Smrg} 184706f2543Smrg 185706f2543Smrg/* 186706f2543Smrg** Free a context. 187706f2543Smrg*/ 188706f2543SmrgGLboolean __glXFreeContext(__GLXcontext *cx) 189706f2543Smrg{ 190706f2543Smrg if (cx->idExists || cx->isCurrent) return GL_FALSE; 191706f2543Smrg 192706f2543Smrg free(cx->feedbackBuf); 193706f2543Smrg free(cx->selectBuf); 194706f2543Smrg if (cx == __glXLastContext) { 195706f2543Smrg __glXFlushContextCache(); 196706f2543Smrg } 197706f2543Smrg 198706f2543Smrg __glXRemoveFromContextList(cx); 199706f2543Smrg 200706f2543Smrg /* We can get here through both regular dispatching from 201706f2543Smrg * __glXDispatch() or as a callback from the resource manager. In 202706f2543Smrg * the latter case we need to lift the DRI lock manually. */ 203706f2543Smrg 204706f2543Smrg if (!glxBlockClients) { 205706f2543Smrg __glXleaveServer(GL_FALSE); 206706f2543Smrg cx->destroy(cx); 207706f2543Smrg __glXenterServer(GL_FALSE); 208706f2543Smrg } else { 209706f2543Smrg cx->next = glxPendingDestroyContexts; 210706f2543Smrg glxPendingDestroyContexts = cx; 211706f2543Smrg } 212706f2543Smrg 213706f2543Smrg return GL_TRUE; 214706f2543Smrg} 215706f2543Smrg 216706f2543Smrg/************************************************************************/ 217706f2543Smrg 218706f2543Smrg/* 219706f2543Smrg** These routines can be used to check whether a particular GL command 220706f2543Smrg** has caused an error. Specifically, we use them to check whether a 221706f2543Smrg** given query has caused an error, in which case a zero-length data 222706f2543Smrg** reply is sent to the client. 223706f2543Smrg*/ 224706f2543Smrg 225706f2543Smrgstatic GLboolean errorOccured = GL_FALSE; 226706f2543Smrg 227706f2543Smrg/* 228706f2543Smrg** The GL was will call this routine if an error occurs. 229706f2543Smrg*/ 230706f2543Smrgvoid __glXErrorCallBack(GLenum code) 231706f2543Smrg{ 232706f2543Smrg errorOccured = GL_TRUE; 233706f2543Smrg} 234706f2543Smrg 235706f2543Smrg/* 236706f2543Smrg** Clear the error flag before calling the GL command. 237706f2543Smrg*/ 238706f2543Smrgvoid __glXClearErrorOccured(void) 239706f2543Smrg{ 240706f2543Smrg errorOccured = GL_FALSE; 241706f2543Smrg} 242706f2543Smrg 243706f2543Smrg/* 244706f2543Smrg** Check if the GL command caused an error. 245706f2543Smrg*/ 246706f2543SmrgGLboolean __glXErrorOccured(void) 247706f2543Smrg{ 248706f2543Smrg return errorOccured; 249706f2543Smrg} 250706f2543Smrg 251706f2543Smrgstatic int __glXErrorBase; 252706f2543Smrgint __glXEventBase; 253706f2543Smrg 254706f2543Smrgint __glXError(int error) 255706f2543Smrg{ 256706f2543Smrg return __glXErrorBase + error; 257706f2543Smrg} 258706f2543Smrg 259706f2543Smrg__GLXclientState * 260706f2543SmrgglxGetClient(ClientPtr pClient) 261706f2543Smrg{ 262706f2543Smrg return dixLookupPrivate(&pClient->devPrivates, glxClientPrivateKey); 263706f2543Smrg} 264706f2543Smrg 265706f2543Smrgstatic void 266706f2543SmrgglxClientCallback (CallbackListPtr *list, 267706f2543Smrg pointer closure, 268706f2543Smrg pointer data) 269706f2543Smrg{ 270706f2543Smrg NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; 271706f2543Smrg ClientPtr pClient = clientinfo->client; 272706f2543Smrg __GLXclientState *cl = glxGetClient(pClient); 273706f2543Smrg 274706f2543Smrg switch (pClient->clientState) { 275706f2543Smrg case ClientStateRunning: 276706f2543Smrg /* 277706f2543Smrg ** By default, assume that the client supports 278706f2543Smrg ** GLX major version 1 minor version 0 protocol. 279706f2543Smrg */ 280706f2543Smrg cl->GLClientmajorVersion = 1; 281706f2543Smrg cl->GLClientminorVersion = 0; 282706f2543Smrg cl->client = pClient; 283706f2543Smrg break; 284706f2543Smrg 285706f2543Smrg case ClientStateGone: 286706f2543Smrg free(cl->returnBuf); 287706f2543Smrg free(cl->largeCmdBuf); 288706f2543Smrg free(cl->GLClientextensions); 289706f2543Smrg break; 290706f2543Smrg 291706f2543Smrg default: 292706f2543Smrg break; 293706f2543Smrg } 294706f2543Smrg} 295706f2543Smrg 296706f2543Smrg/************************************************************************/ 297706f2543Smrg 298706f2543Smrgstatic __GLXprovider *__glXProviderStack; 299706f2543Smrg 300706f2543Smrgvoid GlxPushProvider(__GLXprovider *provider) 301706f2543Smrg{ 302706f2543Smrg provider->next = __glXProviderStack; 303706f2543Smrg __glXProviderStack = provider; 304706f2543Smrg} 305706f2543Smrg 306706f2543Smrg/* 307706f2543Smrg** Initialize the GLX extension. 308706f2543Smrg*/ 309706f2543Smrgvoid GlxExtensionInit(void) 310706f2543Smrg{ 311706f2543Smrg ExtensionEntry *extEntry; 312706f2543Smrg ScreenPtr pScreen; 313706f2543Smrg int i; 314706f2543Smrg __GLXprovider *p; 315706f2543Smrg Bool glx_provided = False; 316706f2543Smrg 317706f2543Smrg __glXContextRes = CreateNewResourceType((DeleteType)ContextGone, 318706f2543Smrg "GLXContext"); 319706f2543Smrg __glXDrawableRes = CreateNewResourceType((DeleteType)DrawableGone, 320706f2543Smrg "GLXDrawable"); 321706f2543Smrg if (!__glXContextRes || !__glXDrawableRes) 322706f2543Smrg return; 323706f2543Smrg 324706f2543Smrg if (!dixRegisterPrivateKey(&glxClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (__GLXclientState))) 325706f2543Smrg return; 326706f2543Smrg if (!AddCallback (&ClientStateCallback, glxClientCallback, 0)) 327706f2543Smrg return; 328706f2543Smrg 329706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) { 330706f2543Smrg pScreen = screenInfo.screens[i]; 331706f2543Smrg 332706f2543Smrg for (p = __glXProviderStack; p != NULL; p = p->next) { 333706f2543Smrg __GLXscreen *glxScreen; 334706f2543Smrg 335706f2543Smrg glxScreen = p->screenProbe(pScreen); 336706f2543Smrg if (glxScreen != NULL) { 337706f2543Smrg if (glxScreen->GLXminor < glxMinorVersion) 338706f2543Smrg glxMinorVersion = glxScreen->GLXminor; 339706f2543Smrg LogMessage(X_INFO, 340706f2543Smrg "GLX: Initialized %s GL provider for screen %d\n", 341706f2543Smrg p->name, i); 342706f2543Smrg break; 343706f2543Smrg } 344706f2543Smrg 345706f2543Smrg } 346706f2543Smrg 347706f2543Smrg if (!p) 348706f2543Smrg LogMessage(X_INFO, 349706f2543Smrg "GLX: no usable GL providers found for screen %d\n", i); 350706f2543Smrg else 351706f2543Smrg glx_provided = True; 352706f2543Smrg } 353706f2543Smrg 354706f2543Smrg /* don't register extension if GL is not provided on any screen */ 355706f2543Smrg if (!glx_provided) 356706f2543Smrg return; 357706f2543Smrg 358706f2543Smrg /* 359706f2543Smrg ** Add extension to server extensions. 360706f2543Smrg */ 361706f2543Smrg extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS, 362706f2543Smrg __GLX_NUMBER_ERRORS, __glXDispatch, 363706f2543Smrg __glXDispatch, ResetExtension, 364706f2543Smrg StandardMinorOpcode); 365706f2543Smrg if (!extEntry) { 366706f2543Smrg FatalError("__glXExtensionInit: AddExtensions failed\n"); 367706f2543Smrg return; 368706f2543Smrg } 369706f2543Smrg if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) { 370706f2543Smrg ErrorF("__glXExtensionInit: AddExtensionAlias failed\n"); 371706f2543Smrg return; 372706f2543Smrg } 373706f2543Smrg 374706f2543Smrg __glXErrorBase = extEntry->errorBase; 375706f2543Smrg __glXEventBase = extEntry->eventBase; 376706f2543Smrg} 377706f2543Smrg 378706f2543Smrg/************************************************************************/ 379706f2543Smrg 380706f2543Smrgvoid __glXFlushContextCache(void) 381706f2543Smrg{ 382706f2543Smrg __glXLastContext = 0; 383706f2543Smrg} 384706f2543Smrg 385706f2543Smrg/* 386706f2543Smrg** Make a context the current one for the GL (in this implementation, there 387706f2543Smrg** is only one instance of the GL, and we use it to serve all GL clients by 388706f2543Smrg** switching it between different contexts). While we are at it, look up 389706f2543Smrg** a context by its tag and return its (__GLXcontext *). 390706f2543Smrg*/ 391706f2543Smrg__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag, 392706f2543Smrg int *error) 393706f2543Smrg{ 394706f2543Smrg __GLXcontext *cx; 395706f2543Smrg 396706f2543Smrg /* 397706f2543Smrg ** See if the context tag is legal; it is managed by the extension, 398706f2543Smrg ** so if it's invalid, we have an implementation error. 399706f2543Smrg */ 400706f2543Smrg cx = (__GLXcontext *) __glXLookupContextByTag(cl, tag); 401706f2543Smrg if (!cx) { 402706f2543Smrg cl->client->errorValue = tag; 403706f2543Smrg *error = __glXError(GLXBadContextTag); 404706f2543Smrg return 0; 405706f2543Smrg } 406706f2543Smrg 407706f2543Smrg if (!cx->isDirect) { 408706f2543Smrg if (cx->drawPriv == NULL) { 409706f2543Smrg /* 410706f2543Smrg ** The drawable has vanished. It must be a window, because only 411706f2543Smrg ** windows can be destroyed from under us; GLX pixmaps are 412706f2543Smrg ** refcounted and don't go away until no one is using them. 413706f2543Smrg */ 414706f2543Smrg *error = __glXError(GLXBadCurrentWindow); 415706f2543Smrg return 0; 416706f2543Smrg } 417706f2543Smrg } 418706f2543Smrg 419706f2543Smrg if (cx->wait && (*cx->wait)(cx, cl, error)) 420706f2543Smrg return NULL; 421706f2543Smrg 422706f2543Smrg if (cx == __glXLastContext) { 423706f2543Smrg /* No need to re-bind */ 424706f2543Smrg return cx; 425706f2543Smrg } 426706f2543Smrg 427706f2543Smrg /* Make this context the current one for the GL. */ 428706f2543Smrg if (!cx->isDirect) { 429706f2543Smrg if (!(*cx->forceCurrent)(cx)) { 430706f2543Smrg /* Bind failed, and set the error code. Bummer */ 431706f2543Smrg cl->client->errorValue = cx->id; 432706f2543Smrg *error = __glXError(GLXBadContextState); 433706f2543Smrg return 0; 434706f2543Smrg } 435706f2543Smrg } 436706f2543Smrg __glXLastContext = cx; 437706f2543Smrg return cx; 438706f2543Smrg} 439706f2543Smrg 440706f2543Smrg/************************************************************************/ 441706f2543Smrg 442706f2543Smrgvoid glxSuspendClients(void) 443706f2543Smrg{ 444706f2543Smrg int i; 445706f2543Smrg 446706f2543Smrg for (i = 1; i < currentMaxClients; i++) { 447706f2543Smrg if (clients[i] && glxGetClient(clients[i])->inUse) 448706f2543Smrg IgnoreClient(clients[i]); 449706f2543Smrg } 450706f2543Smrg 451706f2543Smrg glxBlockClients = TRUE; 452706f2543Smrg} 453706f2543Smrg 454706f2543Smrgvoid glxResumeClients(void) 455706f2543Smrg{ 456706f2543Smrg __GLXcontext *cx, *next; 457706f2543Smrg int i; 458706f2543Smrg 459706f2543Smrg glxBlockClients = FALSE; 460706f2543Smrg 461706f2543Smrg for (i = 1; i < currentMaxClients; i++) { 462706f2543Smrg if (clients[i] && glxGetClient(clients[i])->inUse) 463706f2543Smrg AttendClient(clients[i]); 464706f2543Smrg } 465706f2543Smrg 466706f2543Smrg __glXleaveServer(GL_FALSE); 467706f2543Smrg for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) { 468706f2543Smrg next = cx->next; 469706f2543Smrg 470706f2543Smrg cx->destroy(cx); 471706f2543Smrg } 472706f2543Smrg glxPendingDestroyContexts = NULL; 473706f2543Smrg __glXenterServer(GL_FALSE); 474706f2543Smrg} 475706f2543Smrg 476706f2543Smrgstatic void 477706f2543Smrg__glXnopEnterServer(GLboolean rendering) 478706f2543Smrg{ 479706f2543Smrg} 480706f2543Smrg 481706f2543Smrgstatic void 482706f2543Smrg__glXnopLeaveServer(GLboolean rendering) 483706f2543Smrg{ 484706f2543Smrg} 485706f2543Smrg 486706f2543Smrgstatic void (*__glXenterServerFunc)(GLboolean) = __glXnopEnterServer; 487706f2543Smrgstatic void (*__glXleaveServerFunc)(GLboolean) = __glXnopLeaveServer; 488706f2543Smrg 489706f2543Smrgvoid __glXsetEnterLeaveServerFuncs(void (*enter)(GLboolean), 490706f2543Smrg void (*leave)(GLboolean)) 491706f2543Smrg{ 492706f2543Smrg __glXenterServerFunc = enter; 493706f2543Smrg __glXleaveServerFunc = leave; 494706f2543Smrg} 495706f2543Smrg 496706f2543Smrg 497706f2543Smrgvoid __glXenterServer(GLboolean rendering) 498706f2543Smrg{ 499706f2543Smrg glxServerLeaveCount--; 500706f2543Smrg 501706f2543Smrg if (glxServerLeaveCount == 0) 502706f2543Smrg (*__glXenterServerFunc)(rendering); 503706f2543Smrg} 504706f2543Smrg 505706f2543Smrgvoid __glXleaveServer(GLboolean rendering) 506706f2543Smrg{ 507706f2543Smrg if (glxServerLeaveCount == 0) 508706f2543Smrg (*__glXleaveServerFunc)(rendering); 509706f2543Smrg 510706f2543Smrg glxServerLeaveCount++; 511706f2543Smrg} 512706f2543Smrg 513706f2543Smrg/* 514706f2543Smrg** Top level dispatcher; all commands are executed from here down. 515706f2543Smrg*/ 516706f2543Smrgstatic int __glXDispatch(ClientPtr client) 517706f2543Smrg{ 518706f2543Smrg REQUEST(xGLXSingleReq); 519706f2543Smrg CARD8 opcode; 520706f2543Smrg __GLXdispatchSingleProcPtr proc; 521706f2543Smrg __GLXclientState *cl; 522706f2543Smrg int retval; 523706f2543Smrg 524706f2543Smrg opcode = stuff->glxCode; 525706f2543Smrg cl = glxGetClient(client); 526706f2543Smrg /* Mark it in use so we suspend it on VT switch. */ 527706f2543Smrg cl->inUse = TRUE; 528706f2543Smrg 529706f2543Smrg /* 530706f2543Smrg ** If we're expecting a glXRenderLarge request, this better be one. 531706f2543Smrg */ 532706f2543Smrg if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) { 533706f2543Smrg client->errorValue = stuff->glxCode; 534706f2543Smrg return __glXError(GLXBadLargeRequest); 535706f2543Smrg } 536706f2543Smrg 537706f2543Smrg /* If we're currently blocking GLX clients, just put this guy to 538706f2543Smrg * sleep, reset the request and return. */ 539706f2543Smrg if (glxBlockClients) { 540706f2543Smrg ResetCurrentRequest(client); 541706f2543Smrg client->sequence--; 542706f2543Smrg IgnoreClient(client); 543706f2543Smrg return Success; 544706f2543Smrg } 545706f2543Smrg 546706f2543Smrg /* 547706f2543Smrg ** Use the opcode to index into the procedure table. 548706f2543Smrg */ 549706f2543Smrg proc = (__GLXdispatchSingleProcPtr) __glXGetProtocolDecodeFunction(& Single_dispatch_info, 550706f2543Smrg opcode, 551706f2543Smrg client->swapped); 552706f2543Smrg if (proc != NULL) { 553706f2543Smrg GLboolean rendering = opcode <= X_GLXRenderLarge; 554706f2543Smrg __glXleaveServer(rendering); 555706f2543Smrg 556706f2543Smrg __pGlxClient = client; 557706f2543Smrg 558706f2543Smrg retval = (*proc)(cl, (GLbyte *) stuff); 559706f2543Smrg 560706f2543Smrg __glXenterServer(rendering); 561706f2543Smrg } 562706f2543Smrg else { 563706f2543Smrg retval = BadRequest; 564706f2543Smrg } 565706f2543Smrg 566706f2543Smrg return retval; 567706f2543Smrg} 568