glxcmds.c revision 83cfd353
1/*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
30
31#ifdef HAVE_DIX_CONFIG_H
32#include <dix-config.h>
33#endif
34
35#include <string.h>
36#include <assert.h>
37
38#include "glxserver.h"
39#include <GL/glxtokens.h>
40#include <unpack.h>
41#include <pixmapstr.h>
42#include <windowstr.h>
43#include "glxutil.h"
44#include "glxext.h"
45#include "indirect_dispatch.h"
46#include "indirect_table.h"
47#include "indirect_util.h"
48
49static char GLXServerVendorName[] = "SGI";
50
51_X_HIDDEN int
52validGlxScreen(ClientPtr client, int screen, __GLXscreen ** pGlxScreen,
53               int *err)
54{
55    /*
56     ** Check if screen exists.
57     */
58    if (screen < 0 || screen >= screenInfo.numScreens) {
59        client->errorValue = screen;
60        *err = BadValue;
61        return FALSE;
62    }
63    *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
64
65    return TRUE;
66}
67
68_X_HIDDEN int
69validGlxFBConfig(ClientPtr client, __GLXscreen * pGlxScreen, XID id,
70                 __GLXconfig ** config, int *err)
71{
72    __GLXconfig *m;
73
74    for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next)
75        if (m->fbconfigID == id) {
76            *config = m;
77            return TRUE;
78        }
79
80    client->errorValue = id;
81    *err = __glXError(GLXBadFBConfig);
82
83    return FALSE;
84}
85
86static int
87validGlxVisual(ClientPtr client, __GLXscreen * pGlxScreen, XID id,
88               __GLXconfig ** config, int *err)
89{
90    int i;
91
92    for (i = 0; i < pGlxScreen->numVisuals; i++)
93        if (pGlxScreen->visuals[i]->visualID == id) {
94            *config = pGlxScreen->visuals[i];
95            return TRUE;
96        }
97
98    client->errorValue = id;
99    *err = BadValue;
100
101    return FALSE;
102}
103
104static int
105validGlxFBConfigForWindow(ClientPtr client, __GLXconfig * config,
106                          DrawablePtr pDraw, int *err)
107{
108    ScreenPtr pScreen = pDraw->pScreen;
109    VisualPtr pVisual = NULL;
110    XID vid;
111    int i;
112
113    vid = wVisual((WindowPtr) pDraw);
114    for (i = 0; i < pScreen->numVisuals; i++) {
115        if (pScreen->visuals[i].vid == vid) {
116            pVisual = &pScreen->visuals[i];
117            break;
118        }
119    }
120
121    /* FIXME: What exactly should we check here... */
122    if (pVisual->class != glxConvertToXVisualType(config->visualType) ||
123        !(config->drawableType & GLX_WINDOW_BIT)) {
124        client->errorValue = pDraw->id;
125        *err = BadMatch;
126        return FALSE;
127    }
128
129    return TRUE;
130}
131
132_X_HIDDEN int
133validGlxContext(ClientPtr client, XID id, int access_mode,
134                __GLXcontext ** context, int *err)
135{
136    *err = dixLookupResourceByType((void **) context, id,
137                                   __glXContextRes, client, access_mode);
138    if (*err != Success || (*context)->idExists == GL_FALSE) {
139        client->errorValue = id;
140        if (*err == BadValue || *err == Success)
141            *err = __glXError(GLXBadContext);
142        return FALSE;
143    }
144
145    return TRUE;
146}
147
148static int
149validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
150                 __GLXdrawable ** drawable, int *err)
151{
152    int rc;
153
154    rc = dixLookupResourceByType((void **) drawable, id,
155                                 __glXDrawableRes, client, access_mode);
156    if (rc != Success && rc != BadValue) {
157        *err = rc;
158        client->errorValue = id;
159        return FALSE;
160    }
161
162    /* If the ID of the glx drawable we looked up doesn't match the id
163     * we looked for, it's because we looked it up under the X
164     * drawable ID (see DoCreateGLXDrawable). */
165    if (rc == BadValue ||
166        (*drawable)->drawId != id ||
167        (type != GLX_DRAWABLE_ANY && type != (*drawable)->type)) {
168        client->errorValue = id;
169        switch (type) {
170        case GLX_DRAWABLE_WINDOW:
171            *err = __glXError(GLXBadWindow);
172            return FALSE;
173        case GLX_DRAWABLE_PIXMAP:
174            *err = __glXError(GLXBadPixmap);
175            return FALSE;
176        case GLX_DRAWABLE_PBUFFER:
177            *err = __glXError(GLXBadPbuffer);
178            return FALSE;
179        case GLX_DRAWABLE_ANY:
180            *err = __glXError(GLXBadDrawable);
181            return FALSE;
182        }
183    }
184
185    return TRUE;
186}
187
188void
189__glXContextDestroy(__GLXcontext * context)
190{
191    lastGLContext = NULL;
192}
193
194static void
195__glXdirectContextDestroy(__GLXcontext * context)
196{
197    __glXContextDestroy(context);
198    free(context);
199}
200
201static int
202__glXdirectContextLoseCurrent(__GLXcontext * context)
203{
204    return GL_TRUE;
205}
206
207_X_HIDDEN __GLXcontext *
208__glXdirectContextCreate(__GLXscreen * screen,
209                         __GLXconfig * modes, __GLXcontext * shareContext)
210{
211    __GLXcontext *context;
212
213    context = calloc(1, sizeof(__GLXcontext));
214    if (context == NULL)
215        return NULL;
216
217    context->destroy = __glXdirectContextDestroy;
218    context->loseCurrent = __glXdirectContextLoseCurrent;
219
220    return context;
221}
222
223/**
224 * Create a GL context with the given properties.  This routine is used
225 * to implement \c glXCreateContext, \c glXCreateNewContext, and
226 * \c glXCreateContextWithConfigSGIX.  This works becuase of the hack way
227 * that GLXFBConfigs are implemented.  Basically, the FBConfigID is the
228 * same as the VisualID.
229 */
230
231static int
232DoCreateContext(__GLXclientState * cl, GLXContextID gcId,
233                GLXContextID shareList, __GLXconfig * config,
234                __GLXscreen * pGlxScreen, GLboolean isDirect)
235{
236    ClientPtr client = cl->client;
237    __GLXcontext *glxc, *shareglxc;
238    int err;
239
240    LEGAL_NEW_RESOURCE(gcId, client);
241
242    /*
243     ** Find the display list space that we want to share.
244     **
245     ** NOTE: In a multithreaded X server, we would need to keep a reference
246     ** count for each display list so that if one client detroyed a list that
247     ** another client was using, the list would not really be freed until it
248     ** was no longer in use.  Since this sample implementation has no support
249     ** for multithreaded servers, we don't do this.
250     */
251    if (shareList == None) {
252        shareglxc = 0;
253    }
254    else {
255        if (!validGlxContext(client, shareList, DixReadAccess,
256                             &shareglxc, &err))
257            return err;
258
259        /* Page 26 (page 32 of the PDF) of the GLX 1.4 spec says:
260         *
261         *     "The server context state for all sharing contexts must exist
262         *     in a single address space or a BadMatch error is generated."
263         *
264         * If the share context is indirect, force the new context to also be
265         * indirect.  If the shard context is direct but the new context
266         * cannot be direct, generate BadMatch.
267         */
268        if (shareglxc->isDirect && !isDirect) {
269            client->errorValue = shareList;
270            return BadMatch;
271        }
272        else if (!shareglxc->isDirect) {
273            /*
274             ** Create an indirect context regardless of what the client asked
275             ** for; this way we can share display list space with shareList.
276             */
277            isDirect = GL_FALSE;
278        }
279    }
280
281    /*
282     ** Allocate memory for the new context
283     */
284    if (!isDirect) {
285        /* Only allow creating indirect GLX contexts if allowed by
286         * server command line.  Indirect GLX is of limited use (since
287         * it's only GL 1.4), it's slower than direct contexts, and
288         * it's a massive attack surface for buffer overflow type
289         * errors.
290         */
291        if (!enableIndirectGLX) {
292            client->errorValue = isDirect;
293            return BadValue;
294        }
295
296        /* Without any attributes, the only error that the driver should be
297         * able to generate is BadAlloc.  As result, just drop the error
298         * returned from the driver on the floor.
299         */
300        glxc = pGlxScreen->createContext(pGlxScreen, config, shareglxc,
301                                         0, NULL, &err);
302    }
303    else
304        glxc = __glXdirectContextCreate(pGlxScreen, config, shareglxc);
305    if (!glxc) {
306        return BadAlloc;
307    }
308
309    /* Initialize the GLXcontext structure.
310     */
311    glxc->pGlxScreen = pGlxScreen;
312    glxc->config = config;
313    glxc->id = gcId;
314    glxc->share_id = shareList;
315    glxc->idExists = GL_TRUE;
316    glxc->currentClient = NULL;
317    glxc->isDirect = isDirect;
318    glxc->hasUnflushedCommands = GL_FALSE;
319    glxc->renderMode = GL_RENDER;
320    glxc->feedbackBuf = NULL;
321    glxc->feedbackBufSize = 0;
322    glxc->selectBuf = NULL;
323    glxc->selectBufSize = 0;
324    glxc->drawPriv = NULL;
325    glxc->readPriv = NULL;
326
327    /* The GLX_ARB_create_context_robustness spec says:
328     *
329     *     "The default value for GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
330     *     is GLX_NO_RESET_NOTIFICATION_ARB."
331     *
332     * Without using glXCreateContextAttribsARB, there is no way to specify a
333     * non-default reset notification strategy.
334     */
335    glxc->resetNotificationStrategy = GLX_NO_RESET_NOTIFICATION_ARB;
336
337#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
338    /* The GLX_ARB_context_flush_control spec says:
339     *
340     *     "The default value [for GLX_CONTEXT_RELEASE_BEHAVIOR] is
341     *     CONTEXT_RELEASE_BEHAVIOR_FLUSH, and may in some cases be changed
342     *     using platform-specific context creation extensions."
343     *
344     * Without using glXCreateContextAttribsARB, there is no way to specify a
345     * non-default release behavior.
346     */
347    glxc->releaseBehavior = GLX_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB;
348#endif
349
350    /* Add the new context to the various global tables of GLX contexts.
351     */
352    if (!__glXAddContext(glxc)) {
353        (*glxc->destroy) (glxc);
354        client->errorValue = gcId;
355        return BadAlloc;
356    }
357
358    return Success;
359}
360
361int
362__glXDisp_CreateContext(__GLXclientState * cl, GLbyte * pc)
363{
364    ClientPtr client = cl->client;
365    xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
366    __GLXconfig *config;
367    __GLXscreen *pGlxScreen;
368    int err;
369
370    REQUEST_SIZE_MATCH(xGLXCreateContextReq);
371
372    if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
373        return err;
374    if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
375        return err;
376
377    return DoCreateContext(cl, req->context, req->shareList,
378                           config, pGlxScreen, req->isDirect);
379}
380
381int
382__glXDisp_CreateNewContext(__GLXclientState * cl, GLbyte * pc)
383{
384    ClientPtr client = cl->client;
385    xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc;
386    __GLXconfig *config;
387    __GLXscreen *pGlxScreen;
388    int err;
389
390    REQUEST_SIZE_MATCH(xGLXCreateNewContextReq);
391
392    if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
393        return err;
394    if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
395        return err;
396
397    return DoCreateContext(cl, req->context, req->shareList,
398                           config, pGlxScreen, req->isDirect);
399}
400
401int
402__glXDisp_CreateContextWithConfigSGIX(__GLXclientState * cl, GLbyte * pc)
403{
404    ClientPtr client = cl->client;
405    xGLXCreateContextWithConfigSGIXReq *req =
406        (xGLXCreateContextWithConfigSGIXReq *) pc;
407    __GLXconfig *config;
408    __GLXscreen *pGlxScreen;
409    int err;
410
411    REQUEST_SIZE_MATCH(xGLXCreateContextWithConfigSGIXReq);
412
413    if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
414        return err;
415    if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
416        return err;
417
418    return DoCreateContext(cl, req->context, req->shareList,
419                           config, pGlxScreen, req->isDirect);
420}
421
422int
423__glXDisp_DestroyContext(__GLXclientState * cl, GLbyte * pc)
424{
425    ClientPtr client = cl->client;
426    xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) pc;
427    __GLXcontext *glxc;
428    int err;
429
430    REQUEST_SIZE_MATCH(xGLXDestroyContextReq);
431
432    if (!validGlxContext(cl->client, req->context, DixDestroyAccess,
433                         &glxc, &err))
434        return err;
435
436    glxc->idExists = GL_FALSE;
437    if (!glxc->currentClient)
438        FreeResourceByType(req->context, __glXContextRes, FALSE);
439
440    return Success;
441}
442
443/*
444 * This will return "deleted" contexts, ie, where idExists is GL_FALSE.
445 * Contrast validGlxContext, which will not.  We're cheating here and
446 * using the XID as the context tag, which is fine as long as we defer
447 * actually destroying the context until it's no longer referenced, and
448 * block clients from trying to MakeCurrent on contexts that are on the
449 * way to destruction.  Notice that DoMakeCurrent calls validGlxContext
450 * for new contexts but __glXLookupContextByTag for previous contexts.
451 */
452__GLXcontext *
453__glXLookupContextByTag(__GLXclientState * cl, GLXContextTag tag)
454{
455    __GLXcontext *ret;
456
457    if (dixLookupResourceByType((void **) &ret, tag, __glXContextRes,
458                                cl->client, DixUseAccess) == Success)
459        return ret;
460
461    return NULL;
462}
463
464/*****************************************************************************/
465
466static void
467StopUsingContext(__GLXcontext * glxc)
468{
469    if (glxc) {
470        glxc->currentClient = NULL;
471        if (!glxc->idExists) {
472            FreeResourceByType(glxc->id, __glXContextRes, FALSE);
473        }
474    }
475}
476
477static void
478StartUsingContext(__GLXclientState * cl, __GLXcontext * glxc)
479{
480    glxc->currentClient = cl->client;
481}
482
483/**
484 * This is a helper function to handle the legacy (pre GLX 1.3) cases
485 * where passing an X window to glXMakeCurrent is valid.  Given a
486 * resource ID, look up the GLX drawable if available, otherwise, make
487 * sure it's an X window and create a GLX drawable one the fly.
488 */
489static __GLXdrawable *
490__glXGetDrawable(__GLXcontext * glxc, GLXDrawable drawId, ClientPtr client,
491                 int *error)
492{
493    DrawablePtr pDraw;
494    __GLXdrawable *pGlxDraw;
495    int rc;
496
497    if (validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
498                         DixWriteAccess, &pGlxDraw, &rc)) {
499        if (glxc != NULL && pGlxDraw->config != glxc->config) {
500            client->errorValue = drawId;
501            *error = BadMatch;
502            return NULL;
503        }
504
505        return pGlxDraw;
506    }
507
508    /* No active context and an unknown drawable, bail. */
509    if (glxc == NULL) {
510        client->errorValue = drawId;
511        *error = BadMatch;
512        return NULL;
513    }
514
515    /* The drawId wasn't a GLX drawable.  Make sure it's a window and
516     * create a GLXWindow for it.  Check that the drawable screen
517     * matches the context screen and that the context fbconfig is
518     * compatible with the window visual. */
519
520    rc = dixLookupDrawable(&pDraw, drawId, client, 0, DixGetAttrAccess);
521    if (rc != Success || pDraw->type != DRAWABLE_WINDOW) {
522        client->errorValue = drawId;
523        *error = __glXError(GLXBadDrawable);
524        return NULL;
525    }
526
527    if (pDraw->pScreen != glxc->pGlxScreen->pScreen) {
528        client->errorValue = pDraw->pScreen->myNum;
529        *error = BadMatch;
530        return NULL;
531    }
532
533    if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error))
534        return NULL;
535
536    pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen,
537                                                pDraw, drawId,
538                                                GLX_DRAWABLE_WINDOW,
539                                                drawId, glxc->config);
540    if (!pGlxDraw) {
541	*error = BadAlloc;
542	return NULL;
543    }
544
545    /* since we are creating the drawablePrivate, drawId should be new */
546    if (!AddResource(drawId, __glXDrawableRes, pGlxDraw)) {
547        *error = BadAlloc;
548        return NULL;
549    }
550
551    return pGlxDraw;
552}
553
554/*****************************************************************************/
555/*
556** Make an OpenGL context and drawable current.
557*/
558
559static int
560DoMakeCurrent(__GLXclientState * cl,
561              GLXDrawable drawId, GLXDrawable readId,
562              GLXContextID contextId, GLXContextTag tag)
563{
564    ClientPtr client = cl->client;
565    xGLXMakeCurrentReply reply;
566    __GLXcontext *glxc, *prevglxc;
567    __GLXdrawable *drawPriv = NULL;
568    __GLXdrawable *readPriv = NULL;
569    int error;
570    GLuint mask;
571
572    /*
573     ** If one is None and the other isn't, it's a bad match.
574     */
575
576    mask = (drawId == None) ? (1 << 0) : 0;
577    mask |= (readId == None) ? (1 << 1) : 0;
578    mask |= (contextId == None) ? (1 << 2) : 0;
579
580    if ((mask != 0x00) && (mask != 0x07)) {
581        return BadMatch;
582    }
583
584    /*
585     ** Lookup old context.  If we have one, it must be in a usable state.
586     */
587    if (tag != 0) {
588        prevglxc = __glXLookupContextByTag(cl, tag);
589        if (!prevglxc) {
590            /*
591             ** Tag for previous context is invalid.
592             */
593            return __glXError(GLXBadContextTag);
594        }
595        if (prevglxc->renderMode != GL_RENDER) {
596            /* Oops.  Not in render mode render. */
597            client->errorValue = prevglxc->id;
598            return __glXError(GLXBadContextState);
599        }
600    }
601    else {
602        prevglxc = 0;
603    }
604
605    /*
606     ** Lookup new context.  It must not be current for someone else.
607     */
608    if (contextId != None) {
609        int status;
610
611        if (!validGlxContext(client, contextId, DixUseAccess, &glxc, &error))
612            return error;
613        if ((glxc != prevglxc) && glxc->currentClient) {
614            /* Context is current to somebody else */
615            return BadAccess;
616        }
617
618        assert(drawId != None);
619        assert(readId != None);
620
621        drawPriv = __glXGetDrawable(glxc, drawId, client, &status);
622        if (drawPriv == NULL)
623            return status;
624
625        readPriv = __glXGetDrawable(glxc, readId, client, &status);
626        if (readPriv == NULL)
627            return status;
628
629    }
630    else {
631        /* Switching to no context.  Ignore new drawable. */
632        glxc = 0;
633        drawPriv = 0;
634        readPriv = 0;
635    }
636
637    if (prevglxc) {
638        /*
639         ** Flush the previous context if needed.
640         */
641        Bool need_flush = GL_TRUE;
642#ifdef GLX_CONTEXT_RELEASE_BEHAVIOR_ARB
643        if (prevglxc->releaseBehavior == GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB)
644            need_flush = GL_FALSE;
645#endif
646        if (prevglxc->hasUnflushedCommands && need_flush) {
647            if (__glXForceCurrent(cl, tag, (int *) &error)) {
648                glFlush();
649                prevglxc->hasUnflushedCommands = GL_FALSE;
650            }
651            else {
652                return error;
653            }
654        }
655
656        /*
657         ** Make the previous context not current.
658         */
659        if (!(*prevglxc->loseCurrent) (prevglxc)) {
660            return __glXError(GLXBadContext);
661        }
662        lastGLContext = NULL;
663        if (!prevglxc->isDirect) {
664            prevglxc->drawPriv = NULL;
665            prevglxc->readPriv = NULL;
666        }
667    }
668
669    if ((glxc != 0) && !glxc->isDirect) {
670
671        glxc->drawPriv = drawPriv;
672        glxc->readPriv = readPriv;
673
674        /* make the context current */
675        lastGLContext = glxc;
676        if (!(*glxc->makeCurrent) (glxc)) {
677            lastGLContext = NULL;
678            glxc->drawPriv = NULL;
679            glxc->readPriv = NULL;
680            return __glXError(GLXBadContext);
681        }
682
683        glxc->currentClient = client;
684    }
685
686    StopUsingContext(prevglxc);
687
688    reply = (xGLXMakeCurrentReply) {
689        .type = X_Reply,
690        .sequenceNumber = client->sequence,
691        .length = 0,
692        .contextTag = 0
693    };
694
695    if (glxc) {
696        StartUsingContext(cl, glxc);
697        reply.contextTag = glxc->id;
698    }
699
700    if (client->swapped) {
701        __glXSwapMakeCurrentReply(client, &reply);
702    }
703    else {
704        WriteToClient(client, sz_xGLXMakeCurrentReply, &reply);
705    }
706    return Success;
707}
708
709int
710__glXDisp_MakeCurrent(__GLXclientState * cl, GLbyte * pc)
711{
712    ClientPtr client = cl->client;
713    xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) pc;
714
715    REQUEST_SIZE_MATCH(xGLXMakeCurrentReq);
716
717    return DoMakeCurrent(cl, req->drawable, req->drawable,
718                         req->context, req->oldContextTag);
719}
720
721int
722__glXDisp_MakeContextCurrent(__GLXclientState * cl, GLbyte * pc)
723{
724    ClientPtr client = cl->client;
725    xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) pc;
726
727    REQUEST_SIZE_MATCH(xGLXMakeContextCurrentReq);
728
729    return DoMakeCurrent(cl, req->drawable, req->readdrawable,
730                         req->context, req->oldContextTag);
731}
732
733int
734__glXDisp_MakeCurrentReadSGI(__GLXclientState * cl, GLbyte * pc)
735{
736    ClientPtr client = cl->client;
737    xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) pc;
738
739    REQUEST_SIZE_MATCH(xGLXMakeCurrentReadSGIReq);
740
741    return DoMakeCurrent(cl, req->drawable, req->readable,
742                         req->context, req->oldContextTag);
743}
744
745int
746__glXDisp_IsDirect(__GLXclientState * cl, GLbyte * pc)
747{
748    ClientPtr client = cl->client;
749    xGLXIsDirectReq *req = (xGLXIsDirectReq *) pc;
750    xGLXIsDirectReply reply;
751    __GLXcontext *glxc;
752    int err;
753
754    REQUEST_SIZE_MATCH(xGLXIsDirectReq);
755
756    if (!validGlxContext(cl->client, req->context, DixReadAccess, &glxc, &err))
757        return err;
758
759    reply = (xGLXIsDirectReply) {
760        .type = X_Reply,
761        .sequenceNumber = client->sequence,
762        .length = 0,
763        .isDirect = glxc->isDirect
764    };
765
766    if (client->swapped) {
767        __glXSwapIsDirectReply(client, &reply);
768    }
769    else {
770        WriteToClient(client, sz_xGLXIsDirectReply, &reply);
771    }
772
773    return Success;
774}
775
776int
777__glXDisp_QueryVersion(__GLXclientState * cl, GLbyte * pc)
778{
779    ClientPtr client = cl->client;
780    xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) pc;
781    xGLXQueryVersionReply reply;
782    GLuint major, minor;
783
784    REQUEST_SIZE_MATCH(xGLXQueryVersionReq);
785
786    major = req->majorVersion;
787    minor = req->minorVersion;
788    (void) major;
789    (void) minor;
790
791    /*
792     ** Server should take into consideration the version numbers sent by the
793     ** client if it wants to work with older clients; however, in this
794     ** implementation the server just returns its version number.
795     */
796    reply = (xGLXQueryVersionReply) {
797        .type = X_Reply,
798        .sequenceNumber = client->sequence,
799        .length = 0,
800        .majorVersion = glxMajorVersion,
801        .minorVersion = glxMinorVersion
802    };
803
804    if (client->swapped) {
805        __glXSwapQueryVersionReply(client, &reply);
806    }
807    else {
808        WriteToClient(client, sz_xGLXQueryVersionReply, &reply);
809    }
810    return Success;
811}
812
813int
814__glXDisp_WaitGL(__GLXclientState * cl, GLbyte * pc)
815{
816    ClientPtr client = cl->client;
817    xGLXWaitGLReq *req = (xGLXWaitGLReq *) pc;
818    GLXContextTag tag;
819    __GLXcontext *glxc = NULL;
820    int error;
821
822    REQUEST_SIZE_MATCH(xGLXWaitGLReq);
823
824    tag = req->contextTag;
825    if (tag) {
826        glxc = __glXLookupContextByTag(cl, tag);
827        if (!glxc)
828            return __glXError(GLXBadContextTag);
829
830        if (!__glXForceCurrent(cl, req->contextTag, &error))
831            return error;
832
833        glFinish();
834    }
835
836    if (glxc && glxc->drawPriv->waitGL)
837        (*glxc->drawPriv->waitGL) (glxc->drawPriv);
838
839    return Success;
840}
841
842int
843__glXDisp_WaitX(__GLXclientState * cl, GLbyte * pc)
844{
845    ClientPtr client = cl->client;
846    xGLXWaitXReq *req = (xGLXWaitXReq *) pc;
847    GLXContextTag tag;
848    __GLXcontext *glxc = NULL;
849    int error;
850
851    REQUEST_SIZE_MATCH(xGLXWaitXReq);
852
853    tag = req->contextTag;
854    if (tag) {
855        glxc = __glXLookupContextByTag(cl, tag);
856        if (!glxc)
857            return __glXError(GLXBadContextTag);
858
859        if (!__glXForceCurrent(cl, req->contextTag, &error))
860            return error;
861    }
862
863    if (glxc && glxc->drawPriv->waitX)
864        (*glxc->drawPriv->waitX) (glxc->drawPriv);
865
866    return Success;
867}
868
869int
870__glXDisp_CopyContext(__GLXclientState * cl, GLbyte * pc)
871{
872    ClientPtr client = cl->client;
873    xGLXCopyContextReq *req = (xGLXCopyContextReq *) pc;
874    GLXContextID source;
875    GLXContextID dest;
876    GLXContextTag tag;
877    unsigned long mask;
878    __GLXcontext *src, *dst;
879    int error;
880
881    REQUEST_SIZE_MATCH(xGLXCopyContextReq);
882
883    source = req->source;
884    dest = req->dest;
885    tag = req->contextTag;
886    mask = req->mask;
887    if (!validGlxContext(cl->client, source, DixReadAccess, &src, &error))
888        return error;
889    if (!validGlxContext(cl->client, dest, DixWriteAccess, &dst, &error))
890        return error;
891
892    /*
893     ** They must be in the same address space, and same screen.
894     ** NOTE: no support for direct rendering contexts here.
895     */
896    if (src->isDirect || dst->isDirect || (src->pGlxScreen != dst->pGlxScreen)) {
897        client->errorValue = source;
898        return BadMatch;
899    }
900
901    /*
902     ** The destination context must not be current for any client.
903     */
904    if (dst->currentClient) {
905        client->errorValue = dest;
906        return BadAccess;
907    }
908
909    if (tag) {
910        __GLXcontext *tagcx = __glXLookupContextByTag(cl, tag);
911
912        if (!tagcx) {
913            return __glXError(GLXBadContextTag);
914        }
915        if (tagcx != src) {
916            /*
917             ** This would be caused by a faulty implementation of the client
918             ** library.
919             */
920            return BadMatch;
921        }
922        /*
923         ** In this case, glXCopyContext is in both GL and X streams, in terms
924         ** of sequentiality.
925         */
926        if (__glXForceCurrent(cl, tag, &error)) {
927            /*
928             ** Do whatever is needed to make sure that all preceding requests
929             ** in both streams are completed before the copy is executed.
930             */
931            glFinish();
932            tagcx->hasUnflushedCommands = GL_FALSE;
933        }
934        else {
935            return error;
936        }
937    }
938    /*
939     ** Issue copy.  The only reason for failure is a bad mask.
940     */
941    if (!(*dst->copy) (dst, src, mask)) {
942        client->errorValue = mask;
943        return BadValue;
944    }
945    return Success;
946}
947
948enum {
949    GLX_VIS_CONFIG_UNPAIRED = 18,
950    GLX_VIS_CONFIG_PAIRED = 22
951};
952
953enum {
954    GLX_VIS_CONFIG_TOTAL = GLX_VIS_CONFIG_UNPAIRED + GLX_VIS_CONFIG_PAIRED
955};
956
957int
958__glXDisp_GetVisualConfigs(__GLXclientState * cl, GLbyte * pc)
959{
960    xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) pc;
961    ClientPtr client = cl->client;
962    xGLXGetVisualConfigsReply reply;
963    __GLXscreen *pGlxScreen;
964    __GLXconfig *modes;
965    CARD32 buf[GLX_VIS_CONFIG_TOTAL];
966    int p, i, err;
967
968    __GLX_DECLARE_SWAP_VARIABLES;
969    __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
970
971    REQUEST_SIZE_MATCH(xGLXGetVisualConfigsReq);
972
973    if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
974        return err;
975
976    reply = (xGLXGetVisualConfigsReply) {
977        .type = X_Reply,
978        .sequenceNumber = client->sequence,
979        .length = (pGlxScreen->numVisuals *
980                   __GLX_SIZE_CARD32 * GLX_VIS_CONFIG_TOTAL) >> 2,
981        .numVisuals = pGlxScreen->numVisuals,
982        .numProps = GLX_VIS_CONFIG_TOTAL
983    };
984
985    if (client->swapped) {
986        __GLX_SWAP_SHORT(&reply.sequenceNumber);
987        __GLX_SWAP_INT(&reply.length);
988        __GLX_SWAP_INT(&reply.numVisuals);
989        __GLX_SWAP_INT(&reply.numProps);
990    }
991
992    WriteToClient(client, sz_xGLXGetVisualConfigsReply, &reply);
993
994    for (i = 0; i < pGlxScreen->numVisuals; i++) {
995        modes = pGlxScreen->visuals[i];
996
997        p = 0;
998        buf[p++] = modes->visualID;
999        buf[p++] = glxConvertToXVisualType(modes->visualType);
1000        buf[p++] = (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE;
1001
1002        buf[p++] = modes->redBits;
1003        buf[p++] = modes->greenBits;
1004        buf[p++] = modes->blueBits;
1005        buf[p++] = modes->alphaBits;
1006        buf[p++] = modes->accumRedBits;
1007        buf[p++] = modes->accumGreenBits;
1008        buf[p++] = modes->accumBlueBits;
1009        buf[p++] = modes->accumAlphaBits;
1010
1011        buf[p++] = modes->doubleBufferMode;
1012        buf[p++] = modes->stereoMode;
1013
1014        buf[p++] = modes->rgbBits;
1015        buf[p++] = modes->depthBits;
1016        buf[p++] = modes->stencilBits;
1017        buf[p++] = modes->numAuxBuffers;
1018        buf[p++] = modes->level;
1019
1020        assert(p == GLX_VIS_CONFIG_UNPAIRED);
1021        /*
1022         ** Add token/value pairs for extensions.
1023         */
1024        buf[p++] = GLX_VISUAL_CAVEAT_EXT;
1025        buf[p++] = modes->visualRating;
1026        buf[p++] = GLX_TRANSPARENT_TYPE;
1027        buf[p++] = modes->transparentPixel;
1028        buf[p++] = GLX_TRANSPARENT_RED_VALUE;
1029        buf[p++] = modes->transparentRed;
1030        buf[p++] = GLX_TRANSPARENT_GREEN_VALUE;
1031        buf[p++] = modes->transparentGreen;
1032        buf[p++] = GLX_TRANSPARENT_BLUE_VALUE;
1033        buf[p++] = modes->transparentBlue;
1034        buf[p++] = GLX_TRANSPARENT_ALPHA_VALUE;
1035        buf[p++] = modes->transparentAlpha;
1036        buf[p++] = GLX_TRANSPARENT_INDEX_VALUE;
1037        buf[p++] = modes->transparentIndex;
1038        buf[p++] = GLX_SAMPLES_SGIS;
1039        buf[p++] = modes->samples;
1040        buf[p++] = GLX_SAMPLE_BUFFERS_SGIS;
1041        buf[p++] = modes->sampleBuffers;
1042        /* Add attribute only if its value is not default. */
1043        if (modes->sRGBCapable != GL_FALSE) {
1044            buf[p++] = GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT;
1045            buf[p++] = modes->sRGBCapable;
1046        }
1047        /* Don't add visualSelectGroup (GLX_VISUAL_SELECT_GROUP_SGIX)?
1048         * Pad the remaining place with zeroes, so that attributes count is constant. */
1049        while (p < GLX_VIS_CONFIG_TOTAL) {
1050            buf[p++] = 0;
1051            buf[p++] = 0;
1052        }
1053
1054        assert(p == GLX_VIS_CONFIG_TOTAL);
1055        if (client->swapped) {
1056            __GLX_SWAP_INT_ARRAY(buf, p);
1057        }
1058        WriteToClient(client, __GLX_SIZE_CARD32 * p, buf);
1059    }
1060    return Success;
1061}
1062
1063#define __GLX_TOTAL_FBCONFIG_ATTRIBS (44)
1064#define __GLX_FBCONFIG_ATTRIBS_LENGTH (__GLX_TOTAL_FBCONFIG_ATTRIBS * 2)
1065/**
1066 * Send the set of GLXFBConfigs to the client.  There is not currently
1067 * and interface into the driver on the server-side to get GLXFBConfigs,
1068 * so we "invent" some based on the \c __GLXvisualConfig structures that
1069 * the driver does supply.
1070 *
1071 * The reply format for both \c glXGetFBConfigs and \c glXGetFBConfigsSGIX
1072 * is the same, so this routine pulls double duty.
1073 */
1074
1075static int
1076DoGetFBConfigs(__GLXclientState * cl, unsigned screen)
1077{
1078    ClientPtr client = cl->client;
1079    xGLXGetFBConfigsReply reply;
1080    __GLXscreen *pGlxScreen;
1081    CARD32 buf[__GLX_FBCONFIG_ATTRIBS_LENGTH];
1082    int p, err;
1083    __GLXconfig *modes;
1084
1085    __GLX_DECLARE_SWAP_VARIABLES;
1086    __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
1087
1088    if (!validGlxScreen(cl->client, screen, &pGlxScreen, &err))
1089        return err;
1090
1091    reply = (xGLXGetFBConfigsReply) {
1092        .type = X_Reply,
1093        .sequenceNumber = client->sequence,
1094        .length = __GLX_FBCONFIG_ATTRIBS_LENGTH * pGlxScreen->numFBConfigs,
1095        .numFBConfigs = pGlxScreen->numFBConfigs,
1096        .numAttribs = __GLX_TOTAL_FBCONFIG_ATTRIBS
1097    };
1098
1099    if (client->swapped) {
1100        __GLX_SWAP_SHORT(&reply.sequenceNumber);
1101        __GLX_SWAP_INT(&reply.length);
1102        __GLX_SWAP_INT(&reply.numFBConfigs);
1103        __GLX_SWAP_INT(&reply.numAttribs);
1104    }
1105
1106    WriteToClient(client, sz_xGLXGetFBConfigsReply, &reply);
1107
1108    for (modes = pGlxScreen->fbconfigs; modes != NULL; modes = modes->next) {
1109        p = 0;
1110
1111#define WRITE_PAIR(tag,value) \
1112    do { buf[p++] = tag ; buf[p++] = value ; } while( 0 )
1113
1114        WRITE_PAIR(GLX_VISUAL_ID, modes->visualID);
1115        WRITE_PAIR(GLX_FBCONFIG_ID, modes->fbconfigID);
1116        WRITE_PAIR(GLX_X_RENDERABLE, GL_TRUE);
1117
1118        WRITE_PAIR(GLX_RGBA,
1119                   (modes->renderType & GLX_RGBA_BIT) ? GL_TRUE : GL_FALSE);
1120        WRITE_PAIR(GLX_RENDER_TYPE, modes->renderType);
1121        WRITE_PAIR(GLX_DOUBLEBUFFER, modes->doubleBufferMode);
1122        WRITE_PAIR(GLX_STEREO, modes->stereoMode);
1123
1124        WRITE_PAIR(GLX_BUFFER_SIZE, modes->rgbBits);
1125        WRITE_PAIR(GLX_LEVEL, modes->level);
1126        WRITE_PAIR(GLX_AUX_BUFFERS, modes->numAuxBuffers);
1127        WRITE_PAIR(GLX_RED_SIZE, modes->redBits);
1128        WRITE_PAIR(GLX_GREEN_SIZE, modes->greenBits);
1129        WRITE_PAIR(GLX_BLUE_SIZE, modes->blueBits);
1130        WRITE_PAIR(GLX_ALPHA_SIZE, modes->alphaBits);
1131        WRITE_PAIR(GLX_ACCUM_RED_SIZE, modes->accumRedBits);
1132        WRITE_PAIR(GLX_ACCUM_GREEN_SIZE, modes->accumGreenBits);
1133        WRITE_PAIR(GLX_ACCUM_BLUE_SIZE, modes->accumBlueBits);
1134        WRITE_PAIR(GLX_ACCUM_ALPHA_SIZE, modes->accumAlphaBits);
1135        WRITE_PAIR(GLX_DEPTH_SIZE, modes->depthBits);
1136        WRITE_PAIR(GLX_STENCIL_SIZE, modes->stencilBits);
1137        WRITE_PAIR(GLX_X_VISUAL_TYPE, modes->visualType);
1138        WRITE_PAIR(GLX_CONFIG_CAVEAT, modes->visualRating);
1139        WRITE_PAIR(GLX_TRANSPARENT_TYPE, modes->transparentPixel);
1140        WRITE_PAIR(GLX_TRANSPARENT_RED_VALUE, modes->transparentRed);
1141        WRITE_PAIR(GLX_TRANSPARENT_GREEN_VALUE, modes->transparentGreen);
1142        WRITE_PAIR(GLX_TRANSPARENT_BLUE_VALUE, modes->transparentBlue);
1143        WRITE_PAIR(GLX_TRANSPARENT_ALPHA_VALUE, modes->transparentAlpha);
1144        WRITE_PAIR(GLX_TRANSPARENT_INDEX_VALUE, modes->transparentIndex);
1145        WRITE_PAIR(GLX_SWAP_METHOD_OML, modes->swapMethod);
1146        WRITE_PAIR(GLX_SAMPLES_SGIS, modes->samples);
1147        WRITE_PAIR(GLX_SAMPLE_BUFFERS_SGIS, modes->sampleBuffers);
1148        WRITE_PAIR(GLX_VISUAL_SELECT_GROUP_SGIX, modes->visualSelectGroup);
1149        WRITE_PAIR(GLX_DRAWABLE_TYPE, modes->drawableType);
1150        WRITE_PAIR(GLX_BIND_TO_TEXTURE_RGB_EXT, modes->bindToTextureRgb);
1151        WRITE_PAIR(GLX_BIND_TO_TEXTURE_RGBA_EXT, modes->bindToTextureRgba);
1152        WRITE_PAIR(GLX_BIND_TO_MIPMAP_TEXTURE_EXT, modes->bindToMipmapTexture);
1153        WRITE_PAIR(GLX_BIND_TO_TEXTURE_TARGETS_EXT,
1154                   modes->bindToTextureTargets);
1155	/* can't report honestly until mesa is fixed */
1156	WRITE_PAIR(GLX_Y_INVERTED_EXT, GLX_DONT_CARE);
1157	if (modes->drawableType & GLX_PBUFFER_BIT) {
1158	    WRITE_PAIR(GLX_MAX_PBUFFER_WIDTH, modes->maxPbufferWidth);
1159	    WRITE_PAIR(GLX_MAX_PBUFFER_HEIGHT, modes->maxPbufferHeight);
1160	    WRITE_PAIR(GLX_MAX_PBUFFER_PIXELS, modes->maxPbufferPixels);
1161	    WRITE_PAIR(GLX_OPTIMAL_PBUFFER_WIDTH_SGIX,
1162		       modes->optimalPbufferWidth);
1163	    WRITE_PAIR(GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX,
1164		       modes->optimalPbufferHeight);
1165	}
1166        /* Add attribute only if its value is not default. */
1167        if (modes->sRGBCapable != GL_FALSE) {
1168            WRITE_PAIR(GLX_FRAMEBUFFER_SRGB_CAPABLE_EXT, modes->sRGBCapable);
1169        }
1170        /* Pad the remaining place with zeroes, so that attributes count is constant. */
1171        while (p < __GLX_FBCONFIG_ATTRIBS_LENGTH) {
1172            WRITE_PAIR(0, 0);
1173        }
1174        assert(p == __GLX_FBCONFIG_ATTRIBS_LENGTH);
1175
1176        if (client->swapped) {
1177            __GLX_SWAP_INT_ARRAY(buf, __GLX_FBCONFIG_ATTRIBS_LENGTH);
1178        }
1179        WriteToClient(client, __GLX_SIZE_CARD32 * __GLX_FBCONFIG_ATTRIBS_LENGTH,
1180                      (char *) buf);
1181    }
1182    return Success;
1183}
1184
1185int
1186__glXDisp_GetFBConfigs(__GLXclientState * cl, GLbyte * pc)
1187{
1188    ClientPtr client = cl->client;
1189    xGLXGetFBConfigsReq *req = (xGLXGetFBConfigsReq *) pc;
1190
1191    REQUEST_SIZE_MATCH(xGLXGetFBConfigsReq);
1192    return DoGetFBConfigs(cl, req->screen);
1193}
1194
1195int
1196__glXDisp_GetFBConfigsSGIX(__GLXclientState * cl, GLbyte * pc)
1197{
1198    ClientPtr client = cl->client;
1199    xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *) pc;
1200
1201    /* work around mesa bug, don't use REQUEST_SIZE_MATCH */
1202    REQUEST_AT_LEAST_SIZE(xGLXGetFBConfigsSGIXReq);
1203    return DoGetFBConfigs(cl, req->screen);
1204}
1205
1206GLboolean
1207__glXDrawableInit(__GLXdrawable * drawable,
1208                  __GLXscreen * screen, DrawablePtr pDraw, int type,
1209                  XID drawId, __GLXconfig * config)
1210{
1211    drawable->pDraw = pDraw;
1212    drawable->type = type;
1213    drawable->drawId = drawId;
1214    drawable->otherId = 0;
1215    drawable->config = config;
1216    drawable->eventMask = 0;
1217
1218    return GL_TRUE;
1219}
1220
1221void
1222__glXDrawableRelease(__GLXdrawable * drawable)
1223{
1224}
1225
1226static int
1227DoCreateGLXDrawable(ClientPtr client, __GLXscreen * pGlxScreen,
1228                    __GLXconfig * config, DrawablePtr pDraw, XID drawableId,
1229                    XID glxDrawableId, int type)
1230{
1231    __GLXdrawable *pGlxDraw;
1232
1233    if (pGlxScreen->pScreen != pDraw->pScreen)
1234        return BadMatch;
1235
1236    pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw,
1237                                          drawableId, type,
1238                                          glxDrawableId, config);
1239    if (pGlxDraw == NULL)
1240        return BadAlloc;
1241
1242    if (!AddResource(glxDrawableId, __glXDrawableRes, pGlxDraw))
1243        return BadAlloc;
1244
1245    /*
1246     * Windows aren't refcounted, so track both the X and the GLX window
1247     * so we get called regardless of destruction order.
1248     */
1249    // XXXMRG xorg-server 1.10
1250    if (drawableId != glxDrawableId && (type == GLX_DRAWABLE_WINDOW /*|| type == GLX_DRAWABLE_PIXMAP*/) &&
1251        !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw))
1252	/*pGlxDraw->destroy (pGlxDraw);*/
1253        return BadAlloc;
1254
1255    return Success;
1256}
1257
1258static int
1259DoCreateGLXPixmap(ClientPtr client, __GLXscreen * pGlxScreen,
1260                  __GLXconfig * config, XID drawableId, XID glxDrawableId)
1261{
1262    DrawablePtr pDraw;
1263    int err;
1264
1265    LEGAL_NEW_RESOURCE(glxDrawableId, client);
1266
1267    err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess);
1268    if (err != Success) {
1269        client->errorValue = drawableId;
1270        return err;
1271    }
1272    if (pDraw->type != DRAWABLE_PIXMAP) {
1273        client->errorValue = drawableId;
1274        return BadPixmap;
1275    }
1276
1277    err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId,
1278                              glxDrawableId, GLX_DRAWABLE_PIXMAP);
1279
1280    if (err == Success)
1281        ((PixmapPtr) pDraw)->refcnt++;
1282
1283    return err;
1284}
1285
1286static void
1287determineTextureTarget(ClientPtr client, XID glxDrawableID,
1288                       CARD32 *attribs, CARD32 numAttribs)
1289{
1290    GLenum target = 0;
1291    GLenum format = 0;
1292    int i, err;
1293    __GLXdrawable *pGlxDraw;
1294
1295    if (!validGlxDrawable(client, glxDrawableID, GLX_DRAWABLE_PIXMAP,
1296                          DixWriteAccess, &pGlxDraw, &err))
1297        /* We just added it in CreatePixmap, so we should never get here. */
1298        return;
1299
1300    for (i = 0; i < numAttribs; i++) {
1301        if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) {
1302            switch (attribs[2 * i + 1]) {
1303            case GLX_TEXTURE_2D_EXT:
1304                target = GL_TEXTURE_2D;
1305                break;
1306            case GLX_TEXTURE_RECTANGLE_EXT:
1307                target = GL_TEXTURE_RECTANGLE_ARB;
1308                break;
1309            }
1310        }
1311
1312        if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
1313            format = attribs[2 * i + 1];
1314    }
1315
1316    if (!target) {
1317        int w = pGlxDraw->pDraw->width, h = pGlxDraw->pDraw->height;
1318
1319        if (h & (h - 1) || w & (w - 1))
1320            target = GL_TEXTURE_RECTANGLE_ARB;
1321        else
1322            target = GL_TEXTURE_2D;
1323    }
1324
1325    pGlxDraw->target = target;
1326    pGlxDraw->format = format;
1327}
1328
1329int
1330__glXDisp_CreateGLXPixmap(__GLXclientState * cl, GLbyte * pc)
1331{
1332    ClientPtr client = cl->client;
1333    xGLXCreateGLXPixmapReq *req = (xGLXCreateGLXPixmapReq *) pc;
1334    __GLXconfig *config;
1335    __GLXscreen *pGlxScreen;
1336    int err;
1337
1338    REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapReq);
1339
1340    if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
1341        return err;
1342    if (!validGlxVisual(cl->client, pGlxScreen, req->visual, &config, &err))
1343        return err;
1344
1345    return DoCreateGLXPixmap(cl->client, pGlxScreen, config,
1346                             req->pixmap, req->glxpixmap);
1347}
1348
1349int
1350__glXDisp_CreatePixmap(__GLXclientState * cl, GLbyte * pc)
1351{
1352    ClientPtr client = cl->client;
1353    xGLXCreatePixmapReq *req = (xGLXCreatePixmapReq *) pc;
1354    __GLXconfig *config;
1355    __GLXscreen *pGlxScreen;
1356    int err;
1357
1358    REQUEST_AT_LEAST_SIZE(xGLXCreatePixmapReq);
1359    if (req->numAttribs > (UINT32_MAX >> 3)) {
1360        client->errorValue = req->numAttribs;
1361        return BadValue;
1362    }
1363    REQUEST_FIXED_SIZE(xGLXCreatePixmapReq, req->numAttribs << 3);
1364
1365    if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
1366        return err;
1367    if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
1368        return err;
1369
1370    err = DoCreateGLXPixmap(cl->client, pGlxScreen, config,
1371                            req->pixmap, req->glxpixmap);
1372    if (err != Success)
1373        return err;
1374
1375    determineTextureTarget(cl->client, req->glxpixmap,
1376                           (CARD32 *) (req + 1), req->numAttribs);
1377
1378    return Success;
1379}
1380
1381int
1382__glXDisp_CreateGLXPixmapWithConfigSGIX(__GLXclientState * cl, GLbyte * pc)
1383{
1384    ClientPtr client = cl->client;
1385    xGLXCreateGLXPixmapWithConfigSGIXReq *req =
1386        (xGLXCreateGLXPixmapWithConfigSGIXReq *) pc;
1387    __GLXconfig *config;
1388    __GLXscreen *pGlxScreen;
1389    int err;
1390
1391    REQUEST_SIZE_MATCH(xGLXCreateGLXPixmapWithConfigSGIXReq);
1392
1393    if (!validGlxScreen(cl->client, req->screen, &pGlxScreen, &err))
1394        return err;
1395    if (!validGlxFBConfig(cl->client, pGlxScreen, req->fbconfig, &config, &err))
1396        return err;
1397
1398    return DoCreateGLXPixmap(cl->client, pGlxScreen,
1399                             config, req->pixmap, req->glxpixmap);
1400}
1401
1402static int
1403DoDestroyDrawable(__GLXclientState * cl, XID glxdrawable, int type)
1404{
1405    __GLXdrawable *pGlxDraw;
1406    int err;
1407
1408    if (!validGlxDrawable(cl->client, glxdrawable, type,
1409                          DixDestroyAccess, &pGlxDraw, &err))
1410        return err;
1411
1412    FreeResource(glxdrawable, FALSE);
1413
1414    return Success;
1415}
1416
1417int
1418__glXDisp_DestroyGLXPixmap(__GLXclientState * cl, GLbyte * pc)
1419{
1420    ClientPtr client = cl->client;
1421    xGLXDestroyGLXPixmapReq *req = (xGLXDestroyGLXPixmapReq *) pc;
1422
1423    REQUEST_SIZE_MATCH(xGLXDestroyGLXPixmapReq);
1424
1425    return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
1426}
1427
1428int
1429__glXDisp_DestroyPixmap(__GLXclientState * cl, GLbyte * pc)
1430{
1431    ClientPtr client = cl->client;
1432    xGLXDestroyPixmapReq *req = (xGLXDestroyPixmapReq *) pc;
1433
1434    /* should be REQUEST_SIZE_MATCH, but mesa's glXDestroyPixmap used to set
1435     * length to 3 instead of 2 */
1436    REQUEST_AT_LEAST_SIZE(xGLXDestroyPixmapReq);
1437
1438    return DoDestroyDrawable(cl, req->glxpixmap, GLX_DRAWABLE_PIXMAP);
1439}
1440
1441static int
1442DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
1443                int width, int height, XID glxDrawableId)
1444{
1445    __GLXconfig *config;
1446    __GLXscreen *pGlxScreen;
1447    PixmapPtr pPixmap;
1448    int err;
1449
1450    LEGAL_NEW_RESOURCE(glxDrawableId, client);
1451
1452    if (!validGlxScreen(client, screenNum, &pGlxScreen, &err))
1453        return err;
1454    if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err))
1455        return err;
1456
1457    __glXenterServer(GL_FALSE);
1458    pPixmap = (*pGlxScreen->pScreen->CreatePixmap) (pGlxScreen->pScreen,
1459                                                    width, height,
1460                                                    config->rgbBits, 0);
1461    __glXleaveServer(GL_FALSE);
1462    if (!pPixmap)
1463        return BadAlloc;
1464
1465    /* Assign the pixmap the same id as the pbuffer and add it as a
1466     * resource so it and the DRI2 drawable will be reclaimed when the
1467     * pbuffer is destroyed. */
1468    pPixmap->drawable.id = glxDrawableId;
1469    if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap))
1470        return BadAlloc;
1471
1472    return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
1473                               glxDrawableId, glxDrawableId,
1474                               GLX_DRAWABLE_PBUFFER);
1475}
1476
1477int
1478__glXDisp_CreatePbuffer(__GLXclientState * cl, GLbyte * pc)
1479{
1480    ClientPtr client = cl->client;
1481    xGLXCreatePbufferReq *req = (xGLXCreatePbufferReq *) pc;
1482    CARD32 *attrs;
1483    int width, height, i;
1484
1485    REQUEST_AT_LEAST_SIZE(xGLXCreatePbufferReq);
1486    if (req->numAttribs > (UINT32_MAX >> 3)) {
1487        client->errorValue = req->numAttribs;
1488        return BadValue;
1489    }
1490    REQUEST_FIXED_SIZE(xGLXCreatePbufferReq, req->numAttribs << 3);
1491
1492    attrs = (CARD32 *) (req + 1);
1493    width = 0;
1494    height = 0;
1495
1496    for (i = 0; i < req->numAttribs; i++) {
1497        switch (attrs[i * 2]) {
1498        case GLX_PBUFFER_WIDTH:
1499            width = attrs[i * 2 + 1];
1500            break;
1501        case GLX_PBUFFER_HEIGHT:
1502            height = attrs[i * 2 + 1];
1503            break;
1504        case GLX_LARGEST_PBUFFER:
1505            /* FIXME: huh... */
1506            break;
1507        }
1508    }
1509
1510    return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
1511                           width, height, req->pbuffer);
1512}
1513
1514int
1515__glXDisp_CreateGLXPbufferSGIX(__GLXclientState * cl, GLbyte * pc)
1516{
1517    ClientPtr client = cl->client;
1518    xGLXCreateGLXPbufferSGIXReq *req = (xGLXCreateGLXPbufferSGIXReq *) pc;
1519
1520    REQUEST_AT_LEAST_SIZE(xGLXCreateGLXPbufferSGIXReq);
1521
1522    /*
1523     * We should really handle attributes correctly, but this extension
1524     * is so rare I have difficulty caring.
1525     */
1526    return DoCreatePbuffer(cl->client, req->screen, req->fbconfig,
1527                           req->width, req->height, req->pbuffer);
1528}
1529
1530int
1531__glXDisp_DestroyPbuffer(__GLXclientState * cl, GLbyte * pc)
1532{
1533    ClientPtr client = cl->client;
1534    xGLXDestroyPbufferReq *req = (xGLXDestroyPbufferReq *) pc;
1535
1536    REQUEST_SIZE_MATCH(xGLXDestroyPbufferReq);
1537
1538    return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
1539}
1540
1541int
1542__glXDisp_DestroyGLXPbufferSGIX(__GLXclientState * cl, GLbyte * pc)
1543{
1544    ClientPtr client = cl->client;
1545    xGLXDestroyGLXPbufferSGIXReq *req = (xGLXDestroyGLXPbufferSGIXReq *) pc;
1546
1547    REQUEST_SIZE_MATCH(xGLXDestroyGLXPbufferSGIXReq);
1548
1549    return DoDestroyDrawable(cl, req->pbuffer, GLX_DRAWABLE_PBUFFER);
1550}
1551
1552static int
1553DoChangeDrawableAttributes(ClientPtr client, XID glxdrawable,
1554                           int numAttribs, CARD32 *attribs)
1555{
1556    __GLXdrawable *pGlxDraw;
1557    int i, err;
1558
1559    if (!validGlxDrawable(client, glxdrawable, GLX_DRAWABLE_ANY,
1560                          DixSetAttrAccess, &pGlxDraw, &err))
1561        return err;
1562
1563    for (i = 0; i < numAttribs; i++) {
1564        switch (attribs[i * 2]) {
1565        case GLX_EVENT_MASK:
1566            /* All we do is to record the event mask so we can send it
1567             * back when queried.  We never actually clobber the
1568             * pbuffers, so we never need to send out the event. */
1569            pGlxDraw->eventMask = attribs[i * 2 + 1];
1570            break;
1571        }
1572    }
1573
1574    return Success;
1575}
1576
1577int
1578__glXDisp_ChangeDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
1579{
1580    ClientPtr client = cl->client;
1581    xGLXChangeDrawableAttributesReq *req =
1582        (xGLXChangeDrawableAttributesReq *) pc;
1583
1584    REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesReq);
1585    if (req->numAttribs > (UINT32_MAX >> 3)) {
1586        client->errorValue = req->numAttribs;
1587        return BadValue;
1588    }
1589#if 0
1590    /* mesa sends an additional 8 bytes */
1591    REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesReq, req->numAttribs << 3);
1592#else
1593    if (((sizeof(xGLXChangeDrawableAttributesReq) +
1594          (req->numAttribs << 3)) >> 2) < client->req_len)
1595        return BadLength;
1596#endif
1597
1598    return DoChangeDrawableAttributes(cl->client, req->drawable,
1599                                      req->numAttribs, (CARD32 *) (req + 1));
1600}
1601
1602int
1603__glXDisp_ChangeDrawableAttributesSGIX(__GLXclientState * cl, GLbyte * pc)
1604{
1605    ClientPtr client = cl->client;
1606    xGLXChangeDrawableAttributesSGIXReq *req =
1607        (xGLXChangeDrawableAttributesSGIXReq *) pc;
1608
1609    REQUEST_AT_LEAST_SIZE(xGLXChangeDrawableAttributesSGIXReq);
1610    if (req->numAttribs > (UINT32_MAX >> 3)) {
1611        client->errorValue = req->numAttribs;
1612        return BadValue;
1613    }
1614    REQUEST_FIXED_SIZE(xGLXChangeDrawableAttributesSGIXReq,
1615                       req->numAttribs << 3);
1616
1617    return DoChangeDrawableAttributes(cl->client, req->drawable,
1618                                      req->numAttribs, (CARD32 *) (req + 1));
1619}
1620
1621int
1622__glXDisp_CreateWindow(__GLXclientState * cl, GLbyte * pc)
1623{
1624    xGLXCreateWindowReq *req = (xGLXCreateWindowReq *) pc;
1625    __GLXconfig *config;
1626    __GLXscreen *pGlxScreen;
1627    ClientPtr client = cl->client;
1628    DrawablePtr pDraw;
1629    int err;
1630
1631    REQUEST_AT_LEAST_SIZE(xGLXCreateWindowReq);
1632    if (req->numAttribs > (UINT32_MAX >> 3)) {
1633        client->errorValue = req->numAttribs;
1634        return BadValue;
1635    }
1636    REQUEST_FIXED_SIZE(xGLXCreateWindowReq, req->numAttribs << 3);
1637
1638    LEGAL_NEW_RESOURCE(req->glxwindow, client);
1639
1640    if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
1641        return err;
1642    if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err))
1643        return err;
1644
1645    err = dixLookupDrawable(&pDraw, req->window, client, 0, DixAddAccess);
1646    if (err != Success || pDraw->type != DRAWABLE_WINDOW) {
1647        client->errorValue = req->window;
1648        return BadWindow;
1649    }
1650
1651    if (!validGlxFBConfigForWindow(client, config, pDraw, &err))
1652        return err;
1653
1654    return DoCreateGLXDrawable(client, pGlxScreen, config,
1655                               pDraw, req->window,
1656                               req->glxwindow, GLX_DRAWABLE_WINDOW);
1657}
1658
1659int
1660__glXDisp_DestroyWindow(__GLXclientState * cl, GLbyte * pc)
1661{
1662    ClientPtr client = cl->client;
1663    xGLXDestroyWindowReq *req = (xGLXDestroyWindowReq *) pc;
1664
1665    /* mesa's glXDestroyWindow used to set length to 3 instead of 2 */
1666    REQUEST_AT_LEAST_SIZE(xGLXDestroyWindowReq);
1667
1668    return DoDestroyDrawable(cl, req->glxwindow, GLX_DRAWABLE_WINDOW);
1669}
1670
1671/*****************************************************************************/
1672
1673/*
1674** NOTE: There is no portable implementation for swap buffers as of
1675** this time that is of value.  Consequently, this code must be
1676** implemented by somebody other than SGI.
1677*/
1678int
1679__glXDisp_SwapBuffers(__GLXclientState * cl, GLbyte * pc)
1680{
1681    ClientPtr client = cl->client;
1682    xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc;
1683    GLXContextTag tag;
1684    XID drawId;
1685    __GLXcontext *glxc = NULL;
1686    __GLXdrawable *pGlxDraw;
1687    int error;
1688
1689    REQUEST_SIZE_MATCH(xGLXSwapBuffersReq);
1690
1691    tag = req->contextTag;
1692    drawId = req->drawable;
1693    if (tag) {
1694        glxc = __glXLookupContextByTag(cl, tag);
1695        if (!glxc) {
1696            return __glXError(GLXBadContextTag);
1697        }
1698        /*
1699         ** The calling thread is swapping its current drawable.  In this case,
1700         ** glxSwapBuffers is in both GL and X streams, in terms of
1701         ** sequentiality.
1702         */
1703        if (__glXForceCurrent(cl, tag, &error)) {
1704            /*
1705             ** Do whatever is needed to make sure that all preceding requests
1706             ** in both streams are completed before the swap is executed.
1707             */
1708            glFinish();
1709            glxc->hasUnflushedCommands = GL_FALSE;
1710        }
1711        else {
1712            return error;
1713        }
1714    }
1715
1716    pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
1717    if (pGlxDraw == NULL)
1718        return error;
1719
1720    if (pGlxDraw->type == DRAWABLE_WINDOW &&
1721        (*pGlxDraw->swapBuffers) (cl->client, pGlxDraw) == GL_FALSE)
1722        return __glXError(GLXBadDrawable);
1723
1724    return Success;
1725}
1726
1727static int
1728DoQueryContext(__GLXclientState * cl, GLXContextID gcId)
1729{
1730    ClientPtr client = cl->client;
1731    __GLXcontext *ctx;
1732    xGLXQueryContextInfoEXTReply reply;
1733    int nProps = 3;
1734    int sendBuf[nProps * 2];
1735    int nReplyBytes;
1736    int err;
1737
1738    if (!validGlxContext(cl->client, gcId, DixReadAccess, &ctx, &err))
1739        return err;
1740
1741    reply = (xGLXQueryContextInfoEXTReply) {
1742        .type = X_Reply,
1743        .sequenceNumber = client->sequence,
1744        .length = nProps << 1,
1745        .n = nProps
1746    };
1747
1748    nReplyBytes = reply.length << 2;
1749    sendBuf[0] = GLX_SHARE_CONTEXT_EXT;
1750    sendBuf[1] = (int) (ctx->share_id);
1751    sendBuf[2] = GLX_VISUAL_ID_EXT;
1752    sendBuf[3] = (int) (ctx->config->visualID);
1753    sendBuf[4] = GLX_SCREEN_EXT;
1754    sendBuf[5] = (int) (ctx->pGlxScreen->pScreen->myNum);
1755
1756    if (client->swapped) {
1757        __glXSwapQueryContextInfoEXTReply(client, &reply, sendBuf);
1758    }
1759    else {
1760        WriteToClient(client, sz_xGLXQueryContextInfoEXTReply, &reply);
1761        WriteToClient(client, nReplyBytes, sendBuf);
1762    }
1763
1764    return Success;
1765}
1766
1767int
1768__glXDisp_QueryContextInfoEXT(__GLXclientState * cl, GLbyte * pc)
1769{
1770    ClientPtr client = cl->client;
1771    xGLXQueryContextInfoEXTReq *req = (xGLXQueryContextInfoEXTReq *) pc;
1772
1773    REQUEST_SIZE_MATCH(xGLXQueryContextInfoEXTReq);
1774
1775    return DoQueryContext(cl, req->context);
1776}
1777
1778int
1779__glXDisp_QueryContext(__GLXclientState * cl, GLbyte * pc)
1780{
1781    ClientPtr client = cl->client;
1782    xGLXQueryContextReq *req = (xGLXQueryContextReq *) pc;
1783
1784    REQUEST_SIZE_MATCH(xGLXQueryContextReq);
1785
1786    return DoQueryContext(cl, req->context);
1787}
1788
1789int
1790__glXDisp_BindTexImageEXT(__GLXclientState * cl, GLbyte * pc)
1791{
1792    xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
1793    ClientPtr client = cl->client;
1794    __GLXcontext *context;
1795    __GLXdrawable *pGlxDraw;
1796    GLXDrawable drawId;
1797    int buffer;
1798    int error;
1799    CARD32 num_attribs;
1800
1801    if ((sizeof(xGLXVendorPrivateReq) + 12) >> 2 > client->req_len)
1802        return BadLength;
1803
1804    pc += __GLX_VENDPRIV_HDR_SIZE;
1805
1806    drawId = *((CARD32 *) (pc));
1807    buffer = *((INT32 *) (pc + 4));
1808    num_attribs = *((CARD32 *) (pc + 8));
1809    if (num_attribs > (UINT32_MAX >> 3)) {
1810        client->errorValue = num_attribs;
1811        return BadValue;
1812    }
1813    REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 12 + (num_attribs << 3));
1814
1815    if (buffer != GLX_FRONT_LEFT_EXT)
1816        return __glXError(GLXBadPixmap);
1817
1818    context = __glXForceCurrent(cl, req->contextTag, &error);
1819    if (!context)
1820        return error;
1821
1822    if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
1823                          DixReadAccess, &pGlxDraw, &error))
1824        return error;
1825
1826    if (!context->textureFromPixmap)
1827        return __glXError(GLXUnsupportedPrivateRequest);
1828
1829    return context->textureFromPixmap->bindTexImage(context, buffer, pGlxDraw);
1830}
1831
1832int
1833__glXDisp_ReleaseTexImageEXT(__GLXclientState * cl, GLbyte * pc)
1834{
1835    xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
1836    ClientPtr client = cl->client;
1837    __GLXdrawable *pGlxDraw;
1838    __GLXcontext *context;
1839    GLXDrawable drawId;
1840    int buffer;
1841    int error;
1842
1843    REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 8);
1844
1845    pc += __GLX_VENDPRIV_HDR_SIZE;
1846
1847    drawId = *((CARD32 *) (pc));
1848    buffer = *((INT32 *) (pc + 4));
1849
1850    context = __glXForceCurrent(cl, req->contextTag, &error);
1851    if (!context)
1852        return error;
1853
1854    if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_PIXMAP,
1855                          DixReadAccess, &pGlxDraw, &error))
1856        return error;
1857
1858    if (!context->textureFromPixmap)
1859        return __glXError(GLXUnsupportedPrivateRequest);
1860
1861    return context->textureFromPixmap->releaseTexImage(context,
1862                                                       buffer, pGlxDraw);
1863}
1864
1865int
1866__glXDisp_CopySubBufferMESA(__GLXclientState * cl, GLbyte * pc)
1867{
1868    xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
1869    GLXContextTag tag = req->contextTag;
1870    __GLXcontext *glxc = NULL;
1871    __GLXdrawable *pGlxDraw;
1872    ClientPtr client = cl->client;
1873    GLXDrawable drawId;
1874    int error;
1875    int x, y, width, height;
1876
1877    (void) client;
1878    (void) req;
1879
1880    REQUEST_FIXED_SIZE(xGLXVendorPrivateReq, 20);
1881
1882    pc += __GLX_VENDPRIV_HDR_SIZE;
1883
1884    drawId = *((CARD32 *) (pc));
1885    x = *((INT32 *) (pc + 4));
1886    y = *((INT32 *) (pc + 8));
1887    width = *((INT32 *) (pc + 12));
1888    height = *((INT32 *) (pc + 16));
1889
1890    if (tag) {
1891        glxc = __glXLookupContextByTag(cl, tag);
1892        if (!glxc) {
1893            return __glXError(GLXBadContextTag);
1894        }
1895        /*
1896         ** The calling thread is swapping its current drawable.  In this case,
1897         ** glxSwapBuffers is in both GL and X streams, in terms of
1898         ** sequentiality.
1899         */
1900        if (__glXForceCurrent(cl, tag, &error)) {
1901            /*
1902             ** Do whatever is needed to make sure that all preceding requests
1903             ** in both streams are completed before the swap is executed.
1904             */
1905            glFinish();
1906            glxc->hasUnflushedCommands = GL_FALSE;
1907        }
1908        else {
1909            return error;
1910        }
1911    }
1912
1913    pGlxDraw = __glXGetDrawable(glxc, drawId, client, &error);
1914    if (!pGlxDraw)
1915        return error;
1916
1917    if (pGlxDraw == NULL ||
1918        pGlxDraw->type != GLX_DRAWABLE_WINDOW ||
1919        pGlxDraw->copySubBuffer == NULL)
1920        return __glXError(GLXBadDrawable);
1921
1922    (*pGlxDraw->copySubBuffer) (pGlxDraw, x, y, width, height);
1923
1924    return Success;
1925}
1926
1927/* hack for old glxext.h */
1928#ifndef GLX_STEREO_TREE_EXT
1929#define GLX_STEREO_TREE_EXT                 0x20F5
1930#endif
1931
1932/*
1933** Get drawable attributes
1934*/
1935static int
1936DoGetDrawableAttributes(__GLXclientState * cl, XID drawId)
1937{
1938    ClientPtr client = cl->client;
1939    xGLXGetDrawableAttributesReply reply;
1940    __GLXdrawable *pGlxDraw = NULL;
1941    DrawablePtr pDraw;
1942    CARD32 attributes[18];
1943    int num = 0, error;
1944
1945    if (!validGlxDrawable(client, drawId, GLX_DRAWABLE_ANY,
1946                          DixGetAttrAccess, &pGlxDraw, &error)) {
1947        /* hack for GLX 1.2 naked windows */
1948        int err = dixLookupWindow((WindowPtr *)&pDraw, drawId, client,
1949                                  DixGetAttrAccess);
1950        if (err != Success)
1951            return error;
1952    }
1953    if (pGlxDraw)
1954        pDraw = pGlxDraw->pDraw;
1955
1956#define ATTRIB(a, v) do { \
1957    attributes[2*num] = (a); \
1958    attributes[2*num+1] = (v); \
1959    num++; \
1960    } while (0)
1961
1962    ATTRIB(GLX_Y_INVERTED_EXT, GL_FALSE);
1963    ATTRIB(GLX_WIDTH, pDraw->width);
1964    ATTRIB(GLX_HEIGHT, pDraw->height);
1965    ATTRIB(GLX_SCREEN, pDraw->pScreen->myNum);
1966    if (pGlxDraw) {
1967        ATTRIB(GLX_TEXTURE_TARGET_EXT,
1968               pGlxDraw->target == GL_TEXTURE_2D ?
1969                GLX_TEXTURE_2D_EXT : GLX_TEXTURE_RECTANGLE_EXT);
1970        ATTRIB(GLX_EVENT_MASK, pGlxDraw->eventMask);
1971        ATTRIB(GLX_FBCONFIG_ID, pGlxDraw->config->fbconfigID);
1972        if (pGlxDraw->type == GLX_DRAWABLE_PBUFFER) {
1973            ATTRIB(GLX_PRESERVED_CONTENTS, GL_TRUE);
1974        }
1975        if (pGlxDraw->type == GLX_DRAWABLE_WINDOW) {
1976            ATTRIB(GLX_STEREO_TREE_EXT, 0);
1977        }
1978    }
1979#undef ATTRIB
1980
1981    reply = (xGLXGetDrawableAttributesReply) {
1982        .type = X_Reply,
1983        .sequenceNumber = client->sequence,
1984        .length = num << 1,
1985        .numAttribs = num
1986    };
1987
1988    if (client->swapped) {
1989        __glXSwapGetDrawableAttributesReply(client, &reply, attributes);
1990    }
1991    else {
1992        WriteToClient(client, sz_xGLXGetDrawableAttributesReply, &reply);
1993        WriteToClient(client, reply.length * sizeof(CARD32), attributes);
1994    }
1995
1996    return Success;
1997}
1998
1999int
2000__glXDisp_GetDrawableAttributes(__GLXclientState * cl, GLbyte * pc)
2001{
2002    ClientPtr client = cl->client;
2003    xGLXGetDrawableAttributesReq *req = (xGLXGetDrawableAttributesReq *) pc;
2004
2005    /* this should be REQUEST_SIZE_MATCH, but mesa sends an additional 4 bytes */
2006    REQUEST_AT_LEAST_SIZE(xGLXGetDrawableAttributesReq);
2007
2008    return DoGetDrawableAttributes(cl, req->drawable);
2009}
2010
2011int
2012__glXDisp_GetDrawableAttributesSGIX(__GLXclientState * cl, GLbyte * pc)
2013{
2014    ClientPtr client = cl->client;
2015    xGLXGetDrawableAttributesSGIXReq *req =
2016        (xGLXGetDrawableAttributesSGIXReq *) pc;
2017
2018    REQUEST_SIZE_MATCH(xGLXGetDrawableAttributesSGIXReq);
2019
2020    return DoGetDrawableAttributes(cl, req->drawable);
2021}
2022
2023/************************************************************************/
2024
2025/*
2026** Render and Renderlarge are not in the GLX API.  They are used by the GLX
2027** client library to send batches of GL rendering commands.
2028*/
2029
2030/*
2031** Execute all the drawing commands in a request.
2032*/
2033int
2034__glXDisp_Render(__GLXclientState * cl, GLbyte * pc)
2035{
2036    xGLXRenderReq *req;
2037    ClientPtr client = cl->client;
2038    int left, cmdlen, error;
2039    int commandsDone;
2040    CARD16 opcode;
2041    __GLXrenderHeader *hdr;
2042    __GLXcontext *glxc;
2043
2044    __GLX_DECLARE_SWAP_VARIABLES;
2045
2046    REQUEST_AT_LEAST_SIZE(xGLXRenderReq);
2047
2048    req = (xGLXRenderReq *) pc;
2049    if (client->swapped) {
2050        __GLX_SWAP_SHORT(&req->length);
2051        __GLX_SWAP_INT(&req->contextTag);
2052    }
2053
2054    glxc = __glXForceCurrent(cl, req->contextTag, &error);
2055    if (!glxc) {
2056        return error;
2057    }
2058
2059    commandsDone = 0;
2060    pc += sz_xGLXRenderReq;
2061    left = (req->length << 2) - sz_xGLXRenderReq;
2062    while (left > 0) {
2063        __GLXrenderSizeData entry;
2064        int extra = 0;
2065        __GLXdispatchRenderProcPtr proc;
2066        int err;
2067
2068        if (left < sizeof(__GLXrenderHeader))
2069            return BadLength;
2070
2071        /*
2072         ** Verify that the header length and the overall length agree.
2073         ** Also, each command must be word aligned.
2074         */
2075        hdr = (__GLXrenderHeader *) pc;
2076        if (client->swapped) {
2077            __GLX_SWAP_SHORT(&hdr->length);
2078            __GLX_SWAP_SHORT(&hdr->opcode);
2079        }
2080        cmdlen = hdr->length;
2081        opcode = hdr->opcode;
2082
2083        if (left < cmdlen)
2084            return BadLength;
2085
2086        /*
2087         ** Check for core opcodes and grab entry data.
2088         */
2089        err = __glXGetProtocolSizeData(&Render_dispatch_info, opcode, &entry);
2090        proc = (__GLXdispatchRenderProcPtr)
2091            __glXGetProtocolDecodeFunction(&Render_dispatch_info,
2092                                           opcode, client->swapped);
2093
2094        if ((err < 0) || (proc == NULL)) {
2095            client->errorValue = commandsDone;
2096            return __glXError(GLXBadRenderRequest);
2097        }
2098
2099        if (cmdlen < entry.bytes) {
2100            return BadLength;
2101        }
2102
2103        if (entry.varsize) {
2104            /* variable size command */
2105            extra = (*entry.varsize) (pc + __GLX_RENDER_HDR_SIZE,
2106                                      client->swapped,
2107                                      left - __GLX_RENDER_HDR_SIZE);
2108            if (extra < 0) {
2109                return BadLength;
2110            }
2111        }
2112
2113        if (cmdlen != safe_pad(safe_add(entry.bytes, extra))) {
2114            return BadLength;
2115        }
2116
2117        /*
2118         ** Skip over the header and execute the command.  We allow the
2119         ** caller to trash the command memory.  This is useful especially
2120         ** for things that require double alignment - they can just shift
2121         ** the data towards lower memory (trashing the header) by 4 bytes
2122         ** and achieve the required alignment.
2123         */
2124        (*proc) (pc + __GLX_RENDER_HDR_SIZE);
2125        pc += cmdlen;
2126        left -= cmdlen;
2127        commandsDone++;
2128    }
2129    glxc->hasUnflushedCommands = GL_TRUE;
2130    return Success;
2131}
2132
2133/*
2134** Execute a large rendering request (one that spans multiple X requests).
2135*/
2136int
2137__glXDisp_RenderLarge(__GLXclientState * cl, GLbyte * pc)
2138{
2139    xGLXRenderLargeReq *req;
2140    ClientPtr client = cl->client;
2141    size_t dataBytes;
2142    __GLXrenderLargeHeader *hdr;
2143    __GLXcontext *glxc;
2144    int error;
2145    CARD16 opcode;
2146
2147    __GLX_DECLARE_SWAP_VARIABLES;
2148
2149    REQUEST_AT_LEAST_SIZE(xGLXRenderLargeReq);
2150
2151    req = (xGLXRenderLargeReq *) pc;
2152    if (client->swapped) {
2153        __GLX_SWAP_SHORT(&req->length);
2154        __GLX_SWAP_INT(&req->contextTag);
2155        __GLX_SWAP_INT(&req->dataBytes);
2156        __GLX_SWAP_SHORT(&req->requestNumber);
2157        __GLX_SWAP_SHORT(&req->requestTotal);
2158    }
2159
2160    glxc = __glXForceCurrent(cl, req->contextTag, &error);
2161    if (!glxc) {
2162        /* Reset in case this isn't 1st request. */
2163        __glXResetLargeCommandStatus(cl);
2164        return error;
2165    }
2166    if (safe_pad(req->dataBytes) < 0)
2167        return BadLength;
2168    dataBytes = req->dataBytes;
2169
2170    /*
2171     ** Check the request length.
2172     */
2173    if ((req->length << 2) != safe_pad(dataBytes) + sz_xGLXRenderLargeReq) {
2174        client->errorValue = req->length;
2175        /* Reset in case this isn't 1st request. */
2176        __glXResetLargeCommandStatus(cl);
2177        return BadLength;
2178    }
2179    pc += sz_xGLXRenderLargeReq;
2180
2181    if (cl->largeCmdRequestsSoFar == 0) {
2182        __GLXrenderSizeData entry;
2183        int extra = 0;
2184        int left = (req->length << 2) - sz_xGLXRenderLargeReq;
2185        int cmdlen;
2186        int err;
2187
2188        /*
2189         ** This is the first request of a multi request command.
2190         ** Make enough space in the buffer, then copy the entire request.
2191         */
2192        if (req->requestNumber != 1) {
2193            client->errorValue = req->requestNumber;
2194            return __glXError(GLXBadLargeRequest);
2195        }
2196
2197        if (dataBytes < __GLX_RENDER_LARGE_HDR_SIZE)
2198            return BadLength;
2199
2200        hdr = (__GLXrenderLargeHeader *) pc;
2201        if (client->swapped) {
2202            __GLX_SWAP_INT(&hdr->length);
2203            __GLX_SWAP_INT(&hdr->opcode);
2204        }
2205        opcode = hdr->opcode;
2206        if ((cmdlen = safe_pad(hdr->length)) < 0)
2207            return BadLength;
2208
2209        /*
2210         ** Check for core opcodes and grab entry data.
2211         */
2212        err = __glXGetProtocolSizeData(&Render_dispatch_info, opcode, &entry);
2213        if (err < 0) {
2214            client->errorValue = opcode;
2215            return __glXError(GLXBadLargeRequest);
2216        }
2217
2218        if (entry.varsize) {
2219            /*
2220             ** If it's a variable-size command (a command whose length must
2221             ** be computed from its parameters), all the parameters needed
2222             ** will be in the 1st request, so it's okay to do this.
2223             */
2224            extra = (*entry.varsize) (pc + __GLX_RENDER_LARGE_HDR_SIZE,
2225                                      client->swapped,
2226                                      left - __GLX_RENDER_LARGE_HDR_SIZE);
2227            if (extra < 0) {
2228                return BadLength;
2229            }
2230        }
2231
2232        /* the +4 is safe because we know entry.bytes is small */
2233        if (cmdlen != safe_pad(safe_add(entry.bytes + 4, extra))) {
2234            return BadLength;
2235        }
2236
2237        /*
2238         ** Make enough space in the buffer, then copy the entire request.
2239         */
2240        if (cl->largeCmdBufSize < cmdlen) {
2241	    GLbyte *newbuf = cl->largeCmdBuf;
2242
2243	    if (!(newbuf = realloc(newbuf, cmdlen)))
2244		return BadAlloc;
2245
2246	    cl->largeCmdBuf = newbuf;
2247            cl->largeCmdBufSize = cmdlen;
2248        }
2249        memcpy(cl->largeCmdBuf, pc, dataBytes);
2250
2251        cl->largeCmdBytesSoFar = dataBytes;
2252        cl->largeCmdBytesTotal = cmdlen;
2253        cl->largeCmdRequestsSoFar = 1;
2254        cl->largeCmdRequestsTotal = req->requestTotal;
2255        return Success;
2256
2257    }
2258    else {
2259        /*
2260         ** We are receiving subsequent (i.e. not the first) requests of a
2261         ** multi request command.
2262         */
2263        int bytesSoFar; /* including this packet */
2264
2265        /*
2266         ** Check the request number and the total request count.
2267         */
2268        if (req->requestNumber != cl->largeCmdRequestsSoFar + 1) {
2269            client->errorValue = req->requestNumber;
2270            __glXResetLargeCommandStatus(cl);
2271            return __glXError(GLXBadLargeRequest);
2272        }
2273        if (req->requestTotal != cl->largeCmdRequestsTotal) {
2274            client->errorValue = req->requestTotal;
2275            __glXResetLargeCommandStatus(cl);
2276            return __glXError(GLXBadLargeRequest);
2277        }
2278
2279        /*
2280         ** Check that we didn't get too much data.
2281         */
2282        if ((bytesSoFar = safe_add(cl->largeCmdBytesSoFar, dataBytes)) < 0) {
2283            client->errorValue = dataBytes;
2284            __glXResetLargeCommandStatus(cl);
2285            return __glXError(GLXBadLargeRequest);
2286        }
2287
2288        if (bytesSoFar > cl->largeCmdBytesTotal) {
2289            client->errorValue = dataBytes;
2290            __glXResetLargeCommandStatus(cl);
2291            return __glXError(GLXBadLargeRequest);
2292        }
2293
2294        memcpy(cl->largeCmdBuf + cl->largeCmdBytesSoFar, pc, dataBytes);
2295        cl->largeCmdBytesSoFar += dataBytes;
2296        cl->largeCmdRequestsSoFar++;
2297
2298        if (req->requestNumber == cl->largeCmdRequestsTotal) {
2299            __GLXdispatchRenderProcPtr proc;
2300
2301            /*
2302             ** This is the last request; it must have enough bytes to complete
2303             ** the command.
2304             */
2305            /* NOTE: the pad macro below is needed because the client library
2306             ** pads the total byte count, but not the per-request byte counts.
2307             ** The Protocol Encoding says the total byte count should not be
2308             ** padded, so a proposal will be made to the ARB to relax the
2309             ** padding constraint on the total byte count, thus preserving
2310             ** backward compatibility.  Meanwhile, the padding done below
2311             ** fixes a bug that did not allow large commands of odd sizes to
2312             ** be accepted by the server.
2313             */
2314            if (safe_pad(cl->largeCmdBytesSoFar) != cl->largeCmdBytesTotal) {
2315                client->errorValue = dataBytes;
2316                __glXResetLargeCommandStatus(cl);
2317                return __glXError(GLXBadLargeRequest);
2318            }
2319            hdr = (__GLXrenderLargeHeader *) cl->largeCmdBuf;
2320            /*
2321             ** The opcode and length field in the header had already been
2322             ** swapped when the first request was received.
2323             **
2324             ** Use the opcode to index into the procedure table.
2325             */
2326            opcode = hdr->opcode;
2327
2328            proc = (__GLXdispatchRenderProcPtr)
2329                __glXGetProtocolDecodeFunction(&Render_dispatch_info, opcode,
2330                                               client->swapped);
2331            if (proc == NULL) {
2332                client->errorValue = opcode;
2333                return __glXError(GLXBadLargeRequest);
2334            }
2335
2336            /*
2337             ** Skip over the header and execute the command.
2338             */
2339            (*proc) (cl->largeCmdBuf + __GLX_RENDER_LARGE_HDR_SIZE);
2340            glxc->hasUnflushedCommands = GL_TRUE;
2341
2342            /*
2343             ** Reset for the next RenderLarge series.
2344             */
2345            __glXResetLargeCommandStatus(cl);
2346        }
2347        else {
2348            /*
2349             ** This is neither the first nor the last request.
2350             */
2351        }
2352        return Success;
2353    }
2354}
2355
2356/************************************************************************/
2357
2358/*
2359** No support is provided for the vendor-private requests other than
2360** allocating the entry points in the dispatch table.
2361*/
2362
2363int
2364__glXDisp_VendorPrivate(__GLXclientState * cl, GLbyte * pc)
2365{
2366    ClientPtr client = cl->client;
2367    xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
2368    GLint vendorcode = req->vendorCode;
2369    __GLXdispatchVendorPrivProcPtr proc;
2370
2371    REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
2372
2373    proc = (__GLXdispatchVendorPrivProcPtr)
2374        __glXGetProtocolDecodeFunction(&VendorPriv_dispatch_info,
2375                                       vendorcode, 0);
2376    if (proc != NULL) {
2377        (*proc) (cl, (GLbyte *) req);
2378        return Success;
2379    }
2380
2381    cl->client->errorValue = req->vendorCode;
2382    return __glXError(GLXUnsupportedPrivateRequest);
2383}
2384
2385int
2386__glXDisp_VendorPrivateWithReply(__GLXclientState * cl, GLbyte * pc)
2387{
2388    ClientPtr client = cl->client;
2389    xGLXVendorPrivateReq *req = (xGLXVendorPrivateReq *) pc;
2390    GLint vendorcode = req->vendorCode;
2391    __GLXdispatchVendorPrivProcPtr proc;
2392
2393    REQUEST_AT_LEAST_SIZE(xGLXVendorPrivateReq);
2394
2395    proc = (__GLXdispatchVendorPrivProcPtr)
2396        __glXGetProtocolDecodeFunction(&VendorPriv_dispatch_info,
2397                                       vendorcode, 0);
2398    if (proc != NULL) {
2399        return (*proc) (cl, (GLbyte *) req);
2400    }
2401
2402    cl->client->errorValue = vendorcode;
2403    return __glXError(GLXUnsupportedPrivateRequest);
2404}
2405
2406int
2407__glXDisp_QueryExtensionsString(__GLXclientState * cl, GLbyte * pc)
2408{
2409    ClientPtr client = cl->client;
2410    xGLXQueryExtensionsStringReq *req = (xGLXQueryExtensionsStringReq *) pc;
2411    xGLXQueryExtensionsStringReply reply;
2412    __GLXscreen *pGlxScreen;
2413    size_t n, length;
2414    char *buf;
2415    int err;
2416
2417    REQUEST_SIZE_MATCH(xGLXQueryExtensionsStringReq);
2418
2419    if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
2420        return err;
2421
2422    n = strlen(pGlxScreen->GLXextensions) + 1;
2423    length = __GLX_PAD(n) >> 2;
2424    reply = (xGLXQueryExtensionsStringReply) {
2425        .type = X_Reply,
2426        .sequenceNumber = client->sequence,
2427        .length = length,
2428        .n = n
2429    };
2430
2431    /* Allocate buffer to make sure it's a multiple of 4 bytes big. */
2432    buf = calloc(length, 4);
2433    if (buf == NULL)
2434        return BadAlloc;
2435    memcpy(buf, pGlxScreen->GLXextensions, n);
2436
2437    if (client->swapped) {
2438        glxSwapQueryExtensionsStringReply(client, &reply, buf);
2439    }
2440    else {
2441        WriteToClient(client, sz_xGLXQueryExtensionsStringReply, &reply);
2442        WriteToClient(client, (int) (length << 2), buf);
2443    }
2444
2445    free(buf);
2446    return Success;
2447}
2448
2449int
2450__glXDisp_QueryServerString(__GLXclientState * cl, GLbyte * pc)
2451{
2452    ClientPtr client = cl->client;
2453    xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) pc;
2454    xGLXQueryServerStringReply reply;
2455    size_t n, length;
2456    const char *ptr;
2457    char *buf;
2458    __GLXscreen *pGlxScreen;
2459    int err;
2460    char ver_str[16];
2461
2462    REQUEST_SIZE_MATCH(xGLXQueryServerStringReq);
2463
2464    if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
2465        return err;
2466
2467    switch (req->name) {
2468    case GLX_VENDOR:
2469        ptr = GLXServerVendorName;
2470        break;
2471    case GLX_VERSION:
2472        /* Return to the server version rather than the screen version
2473         * to prevent confusion when they do not match.
2474         */
2475        snprintf(ver_str, 16, "%d.%d", glxMajorVersion, glxMinorVersion);
2476        ptr = ver_str;
2477        break;
2478    case GLX_EXTENSIONS:
2479        ptr = pGlxScreen->GLXextensions;
2480        break;
2481    default:
2482        return BadValue;
2483    }
2484
2485    n = strlen(ptr) + 1;
2486    length = __GLX_PAD(n) >> 2;
2487    reply = (xGLXQueryServerStringReply) {
2488        .type = X_Reply,
2489        .sequenceNumber = client->sequence,
2490        .length = length,
2491        .n = n
2492    };
2493
2494    buf = calloc(length, 4);
2495    if (buf == NULL) {
2496        return BadAlloc;
2497    }
2498    memcpy(buf, ptr, n);
2499
2500    if (client->swapped) {
2501        glxSwapQueryServerStringReply(client, &reply, buf);
2502    }
2503    else {
2504        WriteToClient(client, sz_xGLXQueryServerStringReply, &reply);
2505        WriteToClient(client, (int) (length << 2), buf);
2506    }
2507
2508    free(buf);
2509    return Success;
2510}
2511
2512int
2513__glXDisp_ClientInfo(__GLXclientState * cl, GLbyte * pc)
2514{
2515    ClientPtr client = cl->client;
2516    xGLXClientInfoReq *req = (xGLXClientInfoReq *) pc;
2517    const char *buf;
2518
2519    REQUEST_AT_LEAST_SIZE(xGLXClientInfoReq);
2520
2521    buf = (const char *) (req + 1);
2522    if (!memchr(buf, 0, (client->req_len << 2) - sizeof(xGLXClientInfoReq)))
2523        return BadLength;
2524
2525    free(cl->GLClientextensions);
2526    cl->GLClientextensions = strdup(buf);
2527
2528    return Success;
2529}
2530
2531#include <GL/glxtokens.h>
2532
2533void
2534__glXsendSwapEvent(__GLXdrawable *drawable, int type, CARD64 ust,
2535                   CARD64 msc, CARD32 sbc)
2536{
2537    ClientPtr client = clients[CLIENT_ID(drawable->drawId)];
2538
2539    xGLXBufferSwapComplete2 wire =  {
2540        .type = __glXEventBase + GLX_BufferSwapComplete
2541    };
2542
2543    if (!client)
2544        return;
2545
2546    if (!(drawable->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK))
2547        return;
2548
2549    wire.event_type = type;
2550    wire.drawable = drawable->drawId;
2551    wire.ust_hi = ust >> 32;
2552    wire.ust_lo = ust & 0xffffffff;
2553    wire.msc_hi = msc >> 32;
2554    wire.msc_lo = msc & 0xffffffff;
2555    wire.sbc = sbc;
2556
2557    WriteEventsToClient(client, 1, (xEvent *) &wire);
2558}
2559
2560#if PRESENT
2561static void
2562__glXpresentCompleteNotify(WindowPtr window, CARD8 present_kind, CARD8 present_mode,
2563                           CARD32 serial, uint64_t ust, uint64_t msc)
2564{
2565    __GLXdrawable *drawable;
2566    int glx_type;
2567    int rc;
2568
2569    if (present_kind != PresentCompleteKindPixmap)
2570        return;
2571
2572    rc = dixLookupResourceByType((void **) &drawable, window->drawable.id,
2573                                 __glXDrawableRes, serverClient, DixGetAttrAccess);
2574
2575    if (rc != Success)
2576        return;
2577
2578    if (present_mode == PresentCompleteModeFlip)
2579        glx_type = GLX_FLIP_COMPLETE_INTEL;
2580    else
2581        glx_type = GLX_BLIT_COMPLETE_INTEL;
2582
2583    __glXsendSwapEvent(drawable, glx_type, ust, msc, serial);
2584}
2585
2586#include <present.h>
2587
2588void
2589__glXregisterPresentCompleteNotify(void)
2590{
2591    present_register_complete_notify(__glXpresentCompleteNotify);
2592}
2593#endif
2594