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