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