glxext.c 19.7 KB
Newer Older
Dave Airlie's avatar
Dave Airlie committed
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
 * 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.
 */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
30

31 32 33 34
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif

35
#include <string.h>
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
36 37 38
#include "glxserver.h"
#include <windowstr.h>
#include <propertyst.h>
39
#include <registry.h>
40
#include "privates.h"
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
41
#include <os.h>
42
#include "extinit.h"
43
#include "glx_extinit.h"
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
44 45 46
#include "unpack.h"
#include "glxutil.h"
#include "glxext.h"
47 48
#include "indirect_table.h"
#include "indirect_util.h"
49
#include "glxvndabi.h"
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
50

51 52 53
/*
** X resources.
*/
54
static int glxGeneration;
55 56 57
RESTYPE __glXContextRes;
RESTYPE __glXDrawableRes;

58
static DevPrivateKeyRec glxClientPrivateKeyRec;
59

60
#define glxClientPrivateKey (&glxClientPrivateKeyRec)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
61 62 63 64 65

/*
** Forward declarations.
*/
static int __glXDispatch(ClientPtr);
66
static GLboolean __glXFreeContext(__GLXcontext * cx);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
67 68 69 70

/*
** Reset state used to keep track of large (multi-request) commands.
*/
71 72
void
__glXResetLargeCommandStatus(__GLXclientState * cl)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
73 74 75 76 77 78 79 80
{
    cl->largeCmdBytesSoFar = 0;
    cl->largeCmdBytesTotal = 0;
    cl->largeCmdRequestsSoFar = 0;
    cl->largeCmdRequestsTotal = 0;
}

/*
81
 * This procedure is called when the client who created the context goes away
82 83 84
 * OR when glXDestroyContext is called. If the context is current for a client
 * the dispatch layer will have moved the context struct to a fake resource ID
 * and cx here will be NULL. Otherwise we really free the context.
85
 */
86 87
static int
ContextGone(__GLXcontext * cx, XID id)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
88
{
89 90 91 92
    if (!cx)
        return TRUE;

    if (!cx->currentClient)
93
        __glXFreeContext(cx);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
94

95
    return TRUE;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
96 97
}

98 99 100 101
static __GLXcontext *glxPendingDestroyContexts;
static __GLXcontext *glxAllContexts;
static int glxBlockClients;

102 103 104 105
/*
** Destroy routine that gets called when a drawable is freed.  A drawable
** contains the ancillary buffers needed for rendering.
*/
106 107
static Bool
DrawableGone(__GLXdrawable * glxPriv, XID xid)
108
{
109
    __GLXcontext *c, *next;
110

111 112 113 114 115 116 117 118 119
    if (glxPriv->type == GLX_DRAWABLE_WINDOW) {
        /* If this was created by glXCreateWindow, free the matching resource */
        if (glxPriv->drawId != glxPriv->pDraw->id) {
            if (xid == glxPriv->drawId)
                FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE);
            else
                FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE);
        }
        /* otherwise this window was implicitly created by MakeCurrent */
120 121
    }

122
    for (c = glxAllContexts; c; c = next) {
123
        next = c->next;
124 125
        if (c->currentClient &&
		(c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
126 127
            /* flush the context */
            glFlush();
128
            /* just force a re-bind the next time through */
129
            (*c->loseCurrent) (c);
130
            lastGLContext = NULL;
131 132 133 134 135
        }
        if (c->drawPriv == glxPriv)
            c->drawPriv = NULL;
        if (c->readPriv == glxPriv)
            c->readPriv = NULL;
136
    }
137

138 139
    /* drop our reference to any backing pixmap */
    if (glxPriv->type == GLX_DRAWABLE_PIXMAP)
140
        glxPriv->pDraw->pScreen->DestroyPixmap((PixmapPtr) glxPriv->pDraw);
141

142
    glxPriv->destroy(glxPriv);
143

144
    return TRUE;
145 146
}

147 148
Bool
__glXAddContext(__GLXcontext * cx)
149
{
150 151
    /* Register this context as a resource.
     */
152
    if (!AddResource(cx->id, __glXContextRes, (void *)cx)) {
153
	return FALSE;
154 155
    }

156 157
    cx->next = glxAllContexts;
    glxAllContexts = cx;
158
    return TRUE;
159 160
}

161 162
static void
__glXRemoveFromContextList(__GLXcontext * cx)
163
{
164 165 166
    __GLXcontext *c, *prev;

    if (cx == glxAllContexts)
167
        glxAllContexts = cx->next;
168
    else {
169 170 171 172 173 174
        prev = glxAllContexts;
        for (c = glxAllContexts; c; c = c->next) {
            if (c == cx)
                prev->next = c->next;
            prev = c;
        }
175
    }
176
}
Kristian Høgsberg's avatar
Kristian Høgsberg committed
177

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
178 179 180
/*
** Free a context.
*/
181
static GLboolean
182
__glXFreeContext(__GLXcontext * cx)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
183
{
184
    if (cx->idExists || cx->currentClient)
185 186
        return GL_FALSE;

187 188
    __glXRemoveFromContextList(cx);

189 190
    free(cx->feedbackBuf);
    free(cx->selectBuf);
191 192
    if (cx == lastGLContext) {
        lastGLContext = NULL;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
193 194
    }

195 196 197 198
    /* 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. */

199
    if (!glxBlockClients) {
200 201 202 203 204
        cx->destroy(cx);
    }
    else {
        cx->next = glxPendingDestroyContexts;
        glxPendingDestroyContexts = cx;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
205
    }
206

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
    return GL_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.
*/
224 225
void
__glXErrorCallBack(GLenum code)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
226 227 228 229 230 231 232
{
    errorOccured = GL_TRUE;
}

/*
** Clear the error flag before calling the GL command.
*/
233 234
void
__glXClearErrorOccured(void)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
235 236 237 238 239 240 241
{
    errorOccured = GL_FALSE;
}

/*
** Check if the GL command caused an error.
*/
242 243
GLboolean
__glXErrorOccured(void)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
244 245 246 247
{
    return errorOccured;
}

248
static int __glXErrorBase;
249
int __glXEventBase;
250

251 252
int
__glXError(int error)
253 254 255 256
{
    return __glXErrorBase + error;
}

257 258 259
__GLXclientState *
glxGetClient(ClientPtr pClient)
{
260
    return dixLookupPrivate(&pClient->devPrivates, glxClientPrivateKey);
261 262 263
}

static void
264
glxClientCallback(CallbackListPtr *list, void *closure, void *data)
265
{
266 267 268
    NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
    ClientPtr pClient = clientinfo->client;
    __GLXclientState *cl = glxGetClient(pClient);
269 270 271

    switch (pClient->clientState) {
    case ClientStateGone:
272 273 274
        free(cl->returnBuf);
        free(cl->largeCmdBuf);
        free(cl->GLClientextensions);
275 276
        cl->returnBuf = NULL;
        cl->GLClientextensions = NULL;
277
        break;
278 279

    default:
280
        break;
281 282 283
    }
}

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
284 285
/************************************************************************/

286
static __GLXprovider *__glXProviderStack = &__glXDRISWRastProvider;
287

288 289
void
GlxPushProvider(__GLXprovider * provider)
290 291 292 293 294
{
    provider->next = __glXProviderStack;
    __glXProviderStack = provider;
}

295 296 297 298 299 300 301 302 303 304
static Bool
checkScreenVisuals(void)
{
    int i, j;

    for (i = 0; i < screenInfo.numScreens; i++) {
        ScreenPtr screen = screenInfo.screens[i];
        for (j = 0; j < screen->numVisuals; j++) {
            if (screen->visuals[j].class == TrueColor ||
                screen->visuals[j].class == DirectColor)
305
                return TRUE;
306 307 308
        }
    }

309
    return FALSE;
310 311
}

312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
static void
GetGLXDrawableBytes(void *value, XID id, ResourceSizePtr size)
{
    __GLXdrawable *draw = value;

    size->resourceSize = 0;
    size->pixmapRefSize = 0;
    size->refCnt = 1;

    if (draw->type == GLX_DRAWABLE_PIXMAP) {
        SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
        ResourceSizeRec pixmapSize = { 0, };
        pixmapSizeFunc((PixmapPtr)draw->pDraw, draw->pDraw->id, &pixmapSize);
        size->pixmapRefSize += pixmapSize.pixmapRefSize;
    }
}

329 330
static void
xorgGlxCloseExtension(const ExtensionEntry *extEntry)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
331
{
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
    lastGLContext = NULL;
}

static int
xorgGlxHandleRequest(ClientPtr client)
{
    return __glXDispatch(client);
}

static ScreenPtr
screenNumToScreen(int screen)
{
    if (screen < 0 || screen >= screenInfo.numScreens)
        return NULL;

    return screenInfo.screens[screen];
}

static int
maybe_swap32(ClientPtr client, int x)
{
    return client->swapped ? bswap_32(x) : x;
}

static GlxServerVendor *
vendorForScreen(ClientPtr client, int screen)
{
    screen = maybe_swap32(client, screen);

    return glxServer.getVendorForScreen(client, screenNumToScreen(screen));
}

/* this ought to be generated */
static int
xorgGlxThunkRequest(ClientPtr client)
{
    REQUEST(xGLXVendorPrivateReq);
    CARD32 vendorCode = maybe_swap32(client, stuff->vendorCode);
    GlxServerVendor *vendor = NULL;
    XID resource = 0;
    int ret;

    switch (vendorCode) {
    case X_GLXvop_QueryContextInfoEXT: {
        xGLXQueryContextInfoEXTReq *req = (void *)stuff;
        REQUEST_AT_LEAST_SIZE(*req);
        if (!(vendor = glxServer.getXIDMap(maybe_swap32(client, req->context))))
            return __glXError(GLXBadContext);
        break;
        }

    case X_GLXvop_GetFBConfigsSGIX: {
        xGLXGetFBConfigsSGIXReq *req = (void *)stuff;
        REQUEST_AT_LEAST_SIZE(*req);
        if (!(vendor = vendorForScreen(client, req->screen)))
            return BadValue;
        break;
        }

    case X_GLXvop_CreateContextWithConfigSGIX: {
        xGLXCreateContextWithConfigSGIXReq *req = (void *)stuff;
        REQUEST_AT_LEAST_SIZE(*req);
        resource = maybe_swap32(client, req->context);
        if (!(vendor = vendorForScreen(client, req->screen)))
            return BadValue;
        break;
        }

    case X_GLXvop_CreateGLXPixmapWithConfigSGIX: {
        xGLXCreateGLXPixmapWithConfigSGIXReq *req = (void *)stuff;
        REQUEST_AT_LEAST_SIZE(*req);
        resource = maybe_swap32(client, req->glxpixmap);
        if (!(vendor = vendorForScreen(client, req->screen)))
            return BadValue;
        break;
        }

    case X_GLXvop_CreateGLXPbufferSGIX: {
        xGLXCreateGLXPbufferSGIXReq *req = (void *)stuff;
        REQUEST_AT_LEAST_SIZE(*req);
        resource = maybe_swap32(client, req->pbuffer);
        if (!(vendor = vendorForScreen(client, req->screen)))
            return BadValue;
        break;
        }

    /* same offset for the drawable for these three */
    case X_GLXvop_DestroyGLXPbufferSGIX:
    case X_GLXvop_ChangeDrawableAttributesSGIX:
    case X_GLXvop_GetDrawableAttributesSGIX: {
        xGLXGetDrawableAttributesSGIXReq *req = (void *)stuff;
        REQUEST_AT_LEAST_SIZE(*req);
        if (!(vendor = glxServer.getXIDMap(maybe_swap32(client,
                                                        req->drawable))))
            return __glXError(GLXBadDrawable);
        break;
        }
429

430 431 432 433 434 435 436 437 438
    /* most things just use the standard context tag */
    default: {
        /* size checked by vnd layer already */
        GLXContextTag tag = maybe_swap32(client, stuff->contextTag);
        vendor = glxServer.getContextTag(client, tag);
        if (!vendor)
            return __glXError(GLXBadContextTag);
        break;
        }
439 440
    }

441 442 443 444 445 446
    /* If we're creating a resource, add the map now */
    if (resource) {
        LEGAL_NEW_RESOURCE(resource, client);
        if (!glxServer.addXIDMap(resource, vendor))
            return BadAlloc;
    }
447

448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
    ret = glxServer.forwardRequest(vendor, client);

    if (ret == Success && vendorCode == X_GLXvop_DestroyGLXPbufferSGIX) {
        xGLXDestroyGLXPbufferSGIXReq *req = (void *)stuff;
        glxServer.removeXIDMap(maybe_swap32(client, req->pbuffer));
    }

    if (ret != Success)
        glxServer.removeXIDMap(resource);

    return ret;
}

static GlxServerDispatchProc
xorgGlxGetDispatchAddress(CARD8 minorOpcode, CARD32 vendorCode)
{
    /* we don't support any other GLX opcodes */
    if (minorOpcode != X_GLXVendorPrivate &&
        minorOpcode != X_GLXVendorPrivateWithReply)
        return NULL;

    /* we only support some vendor private requests */
    if (!__glXGetProtocolDecodeFunction(&VendorPriv_dispatch_info, vendorCode,
                                        FALSE))
        return NULL;

    return xorgGlxThunkRequest;
}

static Bool
xorgGlxServerPreInit(const ExtensionEntry *extEntry)
{
    if (glxGeneration != serverGeneration) {
        /* Mesa requires at least one True/DirectColor visual */
        if (!checkScreenVisuals())
            return FALSE;

        __glXContextRes = CreateNewResourceType((DeleteType) ContextGone,
                                                "GLXContext");
        __glXDrawableRes = CreateNewResourceType((DeleteType) DrawableGone,
                                                 "GLXDrawable");
        if (!__glXContextRes || !__glXDrawableRes)
            return FALSE;

        if (!dixRegisterPrivateKey
            (&glxClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(__GLXclientState)))
            return FALSE;
        if (!AddCallback(&ClientStateCallback, glxClientCallback, 0))
            return FALSE;

        __glXErrorBase = extEntry->errorBase;
        __glXEventBase = extEntry->eventBase;

        SetResourceTypeSizeFunc(__glXDrawableRes, GetGLXDrawableBytes);
#if PRESENT
        __glXregisterPresentCompleteNotify();
#endif

        glxGeneration = serverGeneration;
    }

    return glxGeneration == serverGeneration;
}

static GlxServerVendor *glvnd_vendor = NULL;

static GlxServerVendor *
xorgGlxInitGLVNDVendor(void)
{
    if (glvnd_vendor == NULL) {
        GlxServerImports *imports = NULL;
        imports = glxServer.allocateServerImports();

        if (imports != NULL) {
            imports->extensionCloseDown = xorgGlxCloseExtension;
            imports->handleRequest = xorgGlxHandleRequest;
            imports->getDispatchAddress = xorgGlxGetDispatchAddress;
            imports->makeCurrent = xorgGlxMakeCurrent;
            glvnd_vendor = glxServer.createVendor(imports);
            glxServer.freeServerImports(imports);
        }
    }
    return glvnd_vendor;
}
532

533 534 535 536 537
static void
xorgGlxServerInit(CallbackListPtr *pcbl, void *param, void *ext)
{
    const ExtensionEntry *extEntry = ext;
    int i;
538

539
    if (!xorgGlxServerPreInit(extEntry)) {
540
        return;
541 542 543
    }

    if (!xorgGlxInitGLVNDVendor()) {
544
        return;
545
    }
546

547
    for (i = 0; i < screenInfo.numScreens; i++) {
548 549
        ScreenPtr pScreen = screenInfo.screens[i];
        __GLXprovider *p;
550

551 552 553 554 555
        if (glxServer.getVendorForScreen(NULL, pScreen) != NULL) {
            // There's already a vendor registered.
            LogMessage(X_INFO, "GLX: Another vendor is already registered for screen %d\n", i);
            continue;
        }
556

557 558
        for (p = __glXProviderStack; p != NULL; p = p->next) {
            __GLXscreen *glxScreen = p->screenProbe(pScreen);
559 560 561 562 563 564 565 566 567
            if (glxScreen != NULL) {
                LogMessage(X_INFO,
                           "GLX: Initialized %s GL provider for screen %d\n",
                           p->name, i);
                break;
            }

        }

568 569 570
        if (p) {
            glxServer.setScreenVendor(pScreen, glvnd_vendor);
        } else {
571 572
            LogMessage(X_INFO,
                       "GLX: no usable GL providers found for screen %d\n", i);
573
        }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
574
    }
575
}
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
576

577 578 579 580
Bool
xorgGlxCreateVendor(void)
{
    return AddCallback(glxServer.extensionInitCallback, xorgGlxServerInit, NULL);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
581 582 583 584 585 586 587 588 589 590
}

/************************************************************************/

/*
** 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 *).
*/
591 592
__GLXcontext *
__glXForceCurrent(__GLXclientState * cl, GLXContextTag tag, int *error)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
593 594 595 596
{
    __GLXcontext *cx;

    /*
597 598 599
     ** See if the context tag is legal; it is managed by the extension,
     ** so if it's invalid, we have an implementation error.
     */
Adam Jackson's avatar
Adam Jackson committed
600
    cx = __glXLookupContextByTag(cl, tag);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
601
    if (!cx) {
602 603 604
        cl->client->errorValue = tag;
        *error = __glXError(GLXBadContextTag);
        return 0;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
605 606 607
    }

    if (!cx->isDirect) {
608 609 610 611 612 613 614 615 616
        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;
        }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
617
    }
618 619 620

    if (cx->wait && (*cx->wait) (cx, cl, error))
        return NULL;
621

622
    if (cx == lastGLContext) {
623 624
        /* No need to re-bind */
        return cx;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
625 626 627 628
    }

    /* Make this context the current one for the GL. */
    if (!cx->isDirect) {
629 630 631 632 633 634
        /*
         * If it is being forced, it means that this context was already made
         * current. So it cannot just be made current again without decrementing
         * refcount's
         */
        (*cx->loseCurrent) (cx);
635
        lastGLContext = cx;
636 637
        if (!(*cx->makeCurrent) (cx)) {
            /* Bind failed, and set the error code.  Bummer */
638
            lastGLContext = NULL;
639 640 641 642
            cl->client->errorValue = cx->id;
            *error = __glXError(GLXBadContextState);
            return 0;
        }
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
643 644 645 646 647 648
    }
    return cx;
}

/************************************************************************/

649 650
void
glxSuspendClients(void)
Kristian Høgsberg's avatar
Kristian Høgsberg committed
651 652
{
    int i;
653

654
    for (i = 1; i < currentMaxClients; i++) {
655
        if (glxGetClient(clients[i])->client)
656
            IgnoreClient(clients[i]);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
657 658 659 660 661
    }

    glxBlockClients = TRUE;
}

662 663
void
glxResumeClients(void)
Kristian Høgsberg's avatar
Kristian Høgsberg committed
664 665 666 667 668 669
{
    __GLXcontext *cx, *next;
    int i;

    glxBlockClients = FALSE;

670
    for (i = 1; i < currentMaxClients; i++) {
671
        if (glxGetClient(clients[i])->client)
672
            AttendClient(clients[i]);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
673 674 675
    }

    for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) {
676
        next = cx->next;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
677

678
        cx->destroy(cx);
Kristian Høgsberg's avatar
Kristian Høgsberg committed
679 680 681
    }
    glxPendingDestroyContexts = NULL;
}
682

683
static glx_gpa_proc _get_proc_address;
684 685

void
686
__glXsetGetProcAddress(glx_gpa_proc get_proc_address)
687 688 689 690 691 692
{
    _get_proc_address = get_proc_address;
}

void *__glGetProcAddress(const char *proc)
{
693
    void *ret = (void *) _get_proc_address(proc);
694

695
    return ret ? ret : (void *) NoopDDA;
696 697
}

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
698 699 700
/*
** Top level dispatcher; all commands are executed from here down.
*/
701 702
static int
__glXDispatch(ClientPtr client)
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
703 704 705
{
    REQUEST(xGLXSingleReq);
    CARD8 opcode;
706
    __GLXdispatchSingleProcPtr proc;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
707
    __GLXclientState *cl;
708
    int retval = BadRequest;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
709 710

    opcode = stuff->glxCode;
711
    cl = glxGetClient(client);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
712 713

    /*
714 715
     ** If we're expecting a glXRenderLarge request, this better be one.
     */
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
716
    if ((cl->largeCmdRequestsSoFar != 0) && (opcode != X_GLXRenderLarge)) {
717 718
        client->errorValue = stuff->glxCode;
        return __glXError(GLXBadLargeRequest);
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
719 720
    }

721 722 723
    if (!cl->client)
        cl->client = client;

Kristian Høgsberg's avatar
Kristian Høgsberg committed
724 725 726
    /* If we're currently blocking GLX clients, just put this guy to
     * sleep, reset the request and return. */
    if (glxBlockClients) {
727 728 729 730
        ResetCurrentRequest(client);
        client->sequence--;
        IgnoreClient(client);
        return Success;
Kristian Høgsberg's avatar
Kristian Høgsberg committed
731 732
    }

Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
733
    /*
734 735 736
     ** Use the opcode to index into the procedure table.
     */
    proc = __glXGetProtocolDecodeFunction(&Single_dispatch_info, opcode,
Adam Jackson's avatar
Adam Jackson committed
737
                                          client->swapped);
738
    if (proc != NULL)
739
        retval = (*proc) (cl, (GLbyte *) stuff);
740 741

    return retval;
Kaleb Keithley Keithley's avatar
Kaleb Keithley Keithley committed
742
}