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