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