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