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