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