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