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