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