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