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