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