2006-11-26 11:13:41 -07:00
|
|
|
/*
|
|
|
|
** The contents of this file are subject to the GLX Public License Version 1.0
|
|
|
|
** (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, 2011 N. Shoreline Blvd., Mountain View, CA 94043
|
|
|
|
** or at http://www.sgi.com/software/opensource/glx/license.html.
|
|
|
|
**
|
|
|
|
** Software distributed under the License is distributed on an "AS IS"
|
|
|
|
** basis. ALL WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY
|
|
|
|
** IMPLIED WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR
|
|
|
|
** PURPOSE OR OF NON- INFRINGEMENT. See the License for the specific
|
|
|
|
** language governing rights and limitations under the License.
|
|
|
|
**
|
|
|
|
** The Original Software is GLX version 1.2 source code, released February,
|
|
|
|
** 1999. The developer of the Original Software is Silicon Graphics, Inc.
|
|
|
|
** Those portions of the Subject Software created by Silicon Graphics, Inc.
|
|
|
|
** are Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved.
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define NEED_REPLIES
|
|
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
|
|
#include <dix-config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
#include "glxserver.h"
|
|
|
|
#include <windowstr.h>
|
|
|
|
#include <propertyst.h>
|
2008-11-02 08:26:08 -07:00
|
|
|
#include "privates.h"
|
2006-11-26 11:13:41 -07:00
|
|
|
#include <os.h>
|
|
|
|
#include "g_disptab.h"
|
|
|
|
#include "unpack.h"
|
|
|
|
#include "glxutil.h"
|
|
|
|
#include "glxext.h"
|
|
|
|
#include "indirect_table.h"
|
|
|
|
#include "indirect_util.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
** The last context used by the server. It is the context that is current
|
|
|
|
** from the server's perspective.
|
|
|
|
*/
|
|
|
|
__GLXcontext *__glXLastContext;
|
|
|
|
|
|
|
|
/*
|
|
|
|
** X resources.
|
|
|
|
*/
|
|
|
|
RESTYPE __glXContextRes;
|
|
|
|
RESTYPE __glXDrawableRes;
|
|
|
|
RESTYPE __glXSwapBarrierRes;
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Reply for most singles.
|
|
|
|
*/
|
|
|
|
xGLXSingleReply __glXReply;
|
|
|
|
|
2008-11-02 08:26:08 -07:00
|
|
|
static DevPrivateKey glxClientPrivateKey = &glxClientPrivateKey;
|
2006-11-26 11:13:41 -07:00
|
|
|
|
2007-11-24 10:55:21 -07:00
|
|
|
/*
|
|
|
|
** Client that called into GLX dispatch.
|
|
|
|
*/
|
|
|
|
ClientPtr __pGlxClient;
|
|
|
|
|
2006-11-26 11:13:41 -07:00
|
|
|
/*
|
|
|
|
** Forward declarations.
|
|
|
|
*/
|
|
|
|
static int __glXDispatch(ClientPtr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Called when the extension is reset.
|
|
|
|
*/
|
|
|
|
static void ResetExtension(ExtensionEntry* extEntry)
|
|
|
|
{
|
|
|
|
__glXFlushContextCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Reset state used to keep track of large (multi-request) commands.
|
|
|
|
*/
|
|
|
|
void __glXResetLargeCommandStatus(__GLXclientState *cl)
|
|
|
|
{
|
|
|
|
cl->largeCmdBytesSoFar = 0;
|
|
|
|
cl->largeCmdBytesTotal = 0;
|
|
|
|
cl->largeCmdRequestsSoFar = 0;
|
|
|
|
cl->largeCmdRequestsTotal = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Destroy routine that gets called when a drawable is freed. A drawable
|
|
|
|
** contains the ancillary buffers needed for rendering.
|
|
|
|
*/
|
|
|
|
static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
|
|
|
|
{
|
2008-11-02 08:26:08 -07:00
|
|
|
ScreenPtr pScreen = glxPriv->pDraw->pScreen;
|
2006-11-26 11:13:41 -07:00
|
|
|
|
2008-11-02 08:26:08 -07:00
|
|
|
switch (glxPriv->type) {
|
|
|
|
case GLX_DRAWABLE_PIXMAP:
|
|
|
|
case GLX_DRAWABLE_PBUFFER:
|
|
|
|
(*pScreen->DestroyPixmap)((PixmapPtr) glxPriv->pDraw);
|
|
|
|
break;
|
2006-11-26 11:13:41 -07:00
|
|
|
}
|
|
|
|
|
2008-11-02 08:26:08 -07:00
|
|
|
glxPriv->pDraw = NULL;
|
|
|
|
glxPriv->drawId = 0;
|
2006-11-26 11:13:41 -07:00
|
|
|
__glXUnrefDrawable(glxPriv);
|
|
|
|
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __GLXcontext *glxPendingDestroyContexts;
|
|
|
|
static int glxServerLeaveCount;
|
|
|
|
static int glxBlockClients;
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Free a context.
|
|
|
|
*/
|
|
|
|
GLboolean __glXFreeContext(__GLXcontext *cx)
|
|
|
|
{
|
|
|
|
if (cx->idExists || cx->isCurrent) return GL_FALSE;
|
|
|
|
|
|
|
|
if (cx->feedbackBuf) xfree(cx->feedbackBuf);
|
|
|
|
if (cx->selectBuf) xfree(cx->selectBuf);
|
|
|
|
if (cx == __glXLastContext) {
|
|
|
|
__glXFlushContextCache();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We can get here through both regular dispatching from
|
|
|
|
* __glXDispatch() or as a callback from the resource manager. In
|
|
|
|
* the latter case we need to lift the DRI lock manually. */
|
|
|
|
|
2006-12-16 13:09:36 -07:00
|
|
|
if (!glxBlockClients) {
|
2007-11-24 10:55:21 -07:00
|
|
|
__glXleaveServer(GL_FALSE);
|
2006-11-26 11:13:41 -07:00
|
|
|
cx->destroy(cx);
|
2007-11-24 10:55:21 -07:00
|
|
|
__glXenterServer(GL_FALSE);
|
2006-11-26 11:13:41 -07:00
|
|
|
} else {
|
|
|
|
cx->next = glxPendingDestroyContexts;
|
|
|
|
glxPendingDestroyContexts = cx;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern RESTYPE __glXSwapBarrierRes;
|
|
|
|
|
|
|
|
static int SwapBarrierGone(int screen, XID drawable)
|
|
|
|
{
|
2008-11-02 08:26:08 -07:00
|
|
|
__GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
|
|
|
|
|
|
|
|
if (pGlxScreen->swapBarrierFuncs) {
|
|
|
|
pGlxScreen->swapBarrierFuncs->bindSwapBarrierFunc(screen, drawable, 0);
|
2006-11-26 11:13:41 -07:00
|
|
|
}
|
|
|
|
FreeResourceByType(drawable, __glXSwapBarrierRes, FALSE);
|
|
|
|
return True;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
|
|
** These routines can be used to check whether a particular GL command
|
|
|
|
** has caused an error. Specifically, we use them to check whether a
|
|
|
|
** given query has caused an error, in which case a zero-length data
|
|
|
|
** reply is sent to the client.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static GLboolean errorOccured = GL_FALSE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
** The GL was will call this routine if an error occurs.
|
|
|
|
*/
|
2007-11-24 10:55:21 -07:00
|
|
|
void __glXErrorCallBack(GLenum code)
|
2006-11-26 11:13:41 -07:00
|
|
|
{
|
|
|
|
errorOccured = GL_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Clear the error flag before calling the GL command.
|
|
|
|
*/
|
|
|
|
void __glXClearErrorOccured(void)
|
|
|
|
{
|
|
|
|
errorOccured = GL_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Check if the GL command caused an error.
|
|
|
|
*/
|
|
|
|
GLboolean __glXErrorOccured(void)
|
|
|
|
{
|
|
|
|
return errorOccured;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __glXErrorBase;
|
|
|
|
|
|
|
|
int __glXError(int error)
|
|
|
|
{
|
|
|
|
return __glXErrorBase + error;
|
|
|
|
}
|
|
|
|
|
2008-11-02 08:26:08 -07:00
|
|
|
__GLXclientState *
|
|
|
|
glxGetClient(ClientPtr pClient)
|
|
|
|
{
|
|
|
|
return dixLookupPrivate(&pClient->devPrivates, glxClientPrivateKey);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
glxClientCallback (CallbackListPtr *list,
|
|
|
|
pointer closure,
|
|
|
|
pointer data)
|
|
|
|
{
|
|
|
|
NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
|
|
|
|
ClientPtr pClient = clientinfo->client;
|
|
|
|
__GLXclientState *cl = glxGetClient(pClient);
|
|
|
|
__GLXcontext *cx;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
switch (pClient->clientState) {
|
|
|
|
case ClientStateRunning:
|
|
|
|
/*
|
|
|
|
** By default, assume that the client supports
|
|
|
|
** GLX major version 1 minor version 0 protocol.
|
|
|
|
*/
|
|
|
|
cl->GLClientmajorVersion = 1;
|
|
|
|
cl->GLClientminorVersion = 0;
|
|
|
|
cl->client = pClient;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case ClientStateGone:
|
|
|
|
for (i = 0; i < cl->numCurrentContexts; i++) {
|
|
|
|
cx = cl->currentContexts[i];
|
|
|
|
if (cx) {
|
|
|
|
cx->isCurrent = GL_FALSE;
|
|
|
|
if (!cx->idExists)
|
|
|
|
__glXFreeContext(cx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cl->returnBuf) xfree(cl->returnBuf);
|
|
|
|
if (cl->largeCmdBuf) xfree(cl->largeCmdBuf);
|
|
|
|
if (cl->currentContexts) xfree(cl->currentContexts);
|
|
|
|
if (cl->GLClientextensions) xfree(cl->GLClientextensions);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-11-26 11:13:41 -07:00
|
|
|
/************************************************************************/
|
|
|
|
|
2008-11-02 08:26:08 -07:00
|
|
|
static __GLXprovider *__glXProviderStack;
|
|
|
|
|
|
|
|
void GlxPushProvider(__GLXprovider *provider)
|
|
|
|
{
|
|
|
|
provider->next = __glXProviderStack;
|
|
|
|
__glXProviderStack = provider;
|
|
|
|
}
|
|
|
|
|
2006-11-26 11:13:41 -07:00
|
|
|
/*
|
|
|
|
** Initialize the GLX extension.
|
|
|
|
*/
|
|
|
|
void GlxExtensionInit(void)
|
|
|
|
{
|
|
|
|
ExtensionEntry *extEntry;
|
2008-11-02 08:26:08 -07:00
|
|
|
ScreenPtr pScreen;
|
2006-11-26 11:13:41 -07:00
|
|
|
int i;
|
2008-11-02 08:26:08 -07:00
|
|
|
__GLXprovider *p;
|
|
|
|
Bool glx_provided = False;
|
2006-11-26 11:13:41 -07:00
|
|
|
|
|
|
|
__glXContextRes = CreateNewResourceType((DeleteType)ContextGone);
|
|
|
|
__glXDrawableRes = CreateNewResourceType((DeleteType)DrawableGone);
|
|
|
|
__glXSwapBarrierRes = CreateNewResourceType((DeleteType)SwapBarrierGone);
|
|
|
|
|
2008-11-02 08:26:08 -07:00
|
|
|
if (!dixRequestPrivate(glxClientPrivateKey, sizeof (__GLXclientState)))
|
|
|
|
return;
|
|
|
|
if (!AddCallback (&ClientStateCallback, glxClientCallback, 0))
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < screenInfo.numScreens; i++) {
|
|
|
|
pScreen = screenInfo.screens[i];
|
|
|
|
|
|
|
|
for (p = __glXProviderStack; p != NULL; p = p->next) {
|
|
|
|
if (p->screenProbe(pScreen) != NULL) {
|
|
|
|
LogMessage(X_INFO,
|
|
|
|
"GLX: Initialized %s GL provider for screen %d\n",
|
|
|
|
p->name, i);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!p)
|
|
|
|
LogMessage(X_INFO,
|
|
|
|
"GLX: no usable GL providers found for screen %d\n", i);
|
|
|
|
else
|
|
|
|
glx_provided = True;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* don't register extension if GL is not provided on any screen */
|
|
|
|
if (!glx_provided)
|
|
|
|
return;
|
|
|
|
|
2006-11-26 11:13:41 -07:00
|
|
|
/*
|
|
|
|
** Add extension to server extensions.
|
|
|
|
*/
|
|
|
|
extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS,
|
|
|
|
__GLX_NUMBER_ERRORS, __glXDispatch,
|
|
|
|
__glXDispatch, 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
void __glXFlushContextCache(void)
|
|
|
|
{
|
|
|
|
__glXLastContext = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Make a context the current one for the GL (in this implementation, there
|
|
|
|
** is only one instance of the GL, and we use it to serve all GL clients by
|
|
|
|
** switching it between different contexts). While we are at it, look up
|
|
|
|
** a context by its tag and return its (__GLXcontext *).
|
|
|
|
*/
|
|
|
|
__GLXcontext *__glXForceCurrent(__GLXclientState *cl, GLXContextTag tag,
|
|
|
|
int *error)
|
|
|
|
{
|
|
|
|
__GLXcontext *cx;
|
|
|
|
|
|
|
|
/*
|
|
|
|
** See if the context tag is legal; it is managed by the extension,
|
|
|
|
** so if it's invalid, we have an implementation error.
|
|
|
|
*/
|
|
|
|
cx = (__GLXcontext *) __glXLookupContextByTag(cl, tag);
|
|
|
|
if (!cx) {
|
|
|
|
cl->client->errorValue = tag;
|
|
|
|
*error = __glXError(GLXBadContextTag);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cx->isDirect) {
|
|
|
|
if (cx->drawPriv == NULL) {
|
|
|
|
/*
|
|
|
|
** The drawable has vanished. It must be a window, because only
|
|
|
|
** windows can be destroyed from under us; GLX pixmaps are
|
|
|
|
** refcounted and don't go away until no one is using them.
|
|
|
|
*/
|
|
|
|
*error = __glXError(GLXBadCurrentWindow);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cx == __glXLastContext) {
|
|
|
|
/* No need to re-bind */
|
|
|
|
return cx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Make this context the current one for the GL. */
|
|
|
|
if (!cx->isDirect) {
|
|
|
|
if (!(*cx->forceCurrent)(cx)) {
|
|
|
|
/* Bind failed, and set the error code. Bummer */
|
|
|
|
cl->client->errorValue = cx->id;
|
|
|
|
*error = __glXError(GLXBadContextState);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
__glXLastContext = cx;
|
|
|
|
return cx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
void glxSuspendClients(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2008-11-02 08:26:08 -07:00
|
|
|
for (i = 1; i < currentMaxClients; i++) {
|
|
|
|
if (clients[i] && glxGetClient(clients[i])->inUse)
|
|
|
|
IgnoreClient(clients[i]);
|
2006-11-26 11:13:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
glxBlockClients = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void glxResumeClients(void)
|
|
|
|
{
|
|
|
|
__GLXcontext *cx, *next;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
glxBlockClients = FALSE;
|
|
|
|
|
2008-11-02 08:26:08 -07:00
|
|
|
for (i = 1; i < currentMaxClients; i++) {
|
|
|
|
if (clients[i] && glxGetClient(clients[i])->inUse)
|
|
|
|
AttendClient(clients[i]);
|
2006-11-26 11:13:41 -07:00
|
|
|
}
|
|
|
|
|
2007-11-24 10:55:21 -07:00
|
|
|
__glXleaveServer(GL_FALSE);
|
2006-11-26 11:13:41 -07:00
|
|
|
for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) {
|
|
|
|
next = cx->next;
|
|
|
|
|
|
|
|
cx->destroy(cx);
|
|
|
|
}
|
|
|
|
glxPendingDestroyContexts = NULL;
|
2007-11-24 10:55:21 -07:00
|
|
|
__glXenterServer(GL_FALSE);
|
2006-11-26 11:13:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-11-24 10:55:21 -07:00
|
|
|
__glXnopEnterServer(GLboolean rendering)
|
2006-11-26 11:13:41 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-11-24 10:55:21 -07:00
|
|
|
__glXnopLeaveServer(GLboolean rendering)
|
2006-11-26 11:13:41 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2007-11-24 10:55:21 -07:00
|
|
|
static void (*__glXenterServerFunc)(GLboolean) = __glXnopEnterServer;
|
|
|
|
static void (*__glXleaveServerFunc)(GLboolean) = __glXnopLeaveServer;
|
2006-11-26 11:13:41 -07:00
|
|
|
|
2007-11-24 10:55:21 -07:00
|
|
|
void __glXsetEnterLeaveServerFuncs(void (*enter)(GLboolean),
|
|
|
|
void (*leave)(GLboolean))
|
2006-11-26 11:13:41 -07:00
|
|
|
{
|
|
|
|
__glXenterServerFunc = enter;
|
|
|
|
__glXleaveServerFunc = leave;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-11-24 10:55:21 -07:00
|
|
|
void __glXenterServer(GLboolean rendering)
|
2006-11-26 11:13:41 -07:00
|
|
|
{
|
|
|
|
glxServerLeaveCount--;
|
|
|
|
|
|
|
|
if (glxServerLeaveCount == 0)
|
2007-11-24 10:55:21 -07:00
|
|
|
(*__glXenterServerFunc)(rendering);
|
2006-11-26 11:13:41 -07:00
|
|
|
}
|
|
|
|
|
2007-11-24 10:55:21 -07:00
|
|
|
void __glXleaveServer(GLboolean rendering)
|
2006-11-26 11:13:41 -07:00
|
|
|
{
|
|
|
|
if (glxServerLeaveCount == 0)
|
2007-11-24 10:55:21 -07:00
|
|
|
(*__glXleaveServerFunc)(rendering);
|
2006-11-26 11:13:41 -07:00
|
|
|
|
|
|
|
glxServerLeaveCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Top level dispatcher; all commands are executed from here down.
|
|
|
|
*/
|
|
|
|
static int __glXDispatch(ClientPtr client)
|
|
|
|
{
|
|
|
|
REQUEST(xGLXSingleReq);
|
|
|
|
CARD8 opcode;
|
|
|
|
__GLXdispatchSingleProcPtr proc;
|
|
|
|
__GLXclientState *cl;
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
opcode = stuff->glxCode;
|
2008-11-02 08:26:08 -07:00
|
|
|
cl = glxGetClient(client);
|
|
|
|
/* Mark it in use so we suspend it on VT switch. */
|
|
|
|
cl->inUse = TRUE;
|
2006-11-26 11:13:41 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
** If we're expecting a glXRenderLarge request, this better be one.
|
|
|
|
*/
|
|
|
|
if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) {
|
|
|
|
client->errorValue = stuff->glxCode;
|
|
|
|
return __glXError(GLXBadLargeRequest);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If we're currently blocking GLX clients, just put this guy to
|
|
|
|
* sleep, reset the request and return. */
|
|
|
|
if (glxBlockClients) {
|
|
|
|
ResetCurrentRequest(client);
|
|
|
|
client->sequence--;
|
|
|
|
IgnoreClient(client);
|
|
|
|
return(client->noClientException);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Use the opcode to index into the procedure table.
|
|
|
|
*/
|
|
|
|
proc = (__GLXdispatchSingleProcPtr) __glXGetProtocolDecodeFunction(& Single_dispatch_info,
|
|
|
|
opcode,
|
|
|
|
client->swapped);
|
|
|
|
if (proc != NULL) {
|
2007-11-24 10:55:21 -07:00
|
|
|
GLboolean rendering = opcode <= X_GLXRenderLarge;
|
|
|
|
__glXleaveServer(rendering);
|
|
|
|
|
|
|
|
__pGlxClient = client;
|
2006-11-26 11:13:41 -07:00
|
|
|
|
|
|
|
retval = (*proc)(cl, (GLbyte *) stuff);
|
|
|
|
|
2007-11-24 10:55:21 -07:00
|
|
|
__glXenterServer(rendering);
|
2006-11-26 11:13:41 -07:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
retval = BadRequest;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|