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