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