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