xref: /OK3568_Linux_fs/external/xserver/glx/glxext.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3*4882a593Smuzhiyun  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
6*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
7*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
8*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
10*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * The above copyright notice including the dates of first publication and
13*4882a593Smuzhiyun  * either this permission notice or a reference to
14*4882a593Smuzhiyun  * http://oss.sgi.com/projects/FreeB/
15*4882a593Smuzhiyun  * shall be included in all copies or substantial portions of the Software.
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18*4882a593Smuzhiyun  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20*4882a593Smuzhiyun  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21*4882a593Smuzhiyun  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22*4882a593Smuzhiyun  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23*4882a593Smuzhiyun  * SOFTWARE.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * Except as contained in this notice, the name of Silicon Graphics, Inc.
26*4882a593Smuzhiyun  * shall not be used in advertising or otherwise to promote the sale, use or
27*4882a593Smuzhiyun  * other dealings in this Software without prior written authorization from
28*4882a593Smuzhiyun  * Silicon Graphics, Inc.
29*4882a593Smuzhiyun  */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
32*4882a593Smuzhiyun #include <dix-config.h>
33*4882a593Smuzhiyun #endif
34*4882a593Smuzhiyun 
35*4882a593Smuzhiyun #include <string.h>
36*4882a593Smuzhiyun #include "glxserver.h"
37*4882a593Smuzhiyun #include <windowstr.h>
38*4882a593Smuzhiyun #include <propertyst.h>
39*4882a593Smuzhiyun #include <registry.h>
40*4882a593Smuzhiyun #include "privates.h"
41*4882a593Smuzhiyun #include <os.h>
42*4882a593Smuzhiyun #include "extinit.h"
43*4882a593Smuzhiyun #include "glx_extinit.h"
44*4882a593Smuzhiyun #include "unpack.h"
45*4882a593Smuzhiyun #include "glxutil.h"
46*4882a593Smuzhiyun #include "glxext.h"
47*4882a593Smuzhiyun #include "indirect_table.h"
48*4882a593Smuzhiyun #include "indirect_util.h"
49*4882a593Smuzhiyun #include "glxvndabi.h"
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun /*
52*4882a593Smuzhiyun ** X resources.
53*4882a593Smuzhiyun */
54*4882a593Smuzhiyun static int glxGeneration;
55*4882a593Smuzhiyun RESTYPE __glXContextRes;
56*4882a593Smuzhiyun RESTYPE __glXDrawableRes;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun static DevPrivateKeyRec glxClientPrivateKeyRec;
59*4882a593Smuzhiyun static GlxServerVendor *glvnd_vendor = NULL;
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #define glxClientPrivateKey (&glxClientPrivateKeyRec)
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun /*
64*4882a593Smuzhiyun ** Forward declarations.
65*4882a593Smuzhiyun */
66*4882a593Smuzhiyun static int __glXDispatch(ClientPtr);
67*4882a593Smuzhiyun static GLboolean __glXFreeContext(__GLXcontext * cx);
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun /*
70*4882a593Smuzhiyun  * This procedure is called when the client who created the context goes away
71*4882a593Smuzhiyun  * OR when glXDestroyContext is called. If the context is current for a client
72*4882a593Smuzhiyun  * the dispatch layer will have moved the context struct to a fake resource ID
73*4882a593Smuzhiyun  * and cx here will be NULL. Otherwise we really free the context.
74*4882a593Smuzhiyun  */
75*4882a593Smuzhiyun static int
ContextGone(__GLXcontext * cx,XID id)76*4882a593Smuzhiyun ContextGone(__GLXcontext * cx, XID id)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun     if (!cx)
79*4882a593Smuzhiyun         return TRUE;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun     if (!cx->currentClient)
82*4882a593Smuzhiyun         __glXFreeContext(cx);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun     return TRUE;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun static __GLXcontext *glxPendingDestroyContexts;
88*4882a593Smuzhiyun static __GLXcontext *glxAllContexts;
89*4882a593Smuzhiyun static int glxBlockClients;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun /*
92*4882a593Smuzhiyun ** Destroy routine that gets called when a drawable is freed.  A drawable
93*4882a593Smuzhiyun ** contains the ancillary buffers needed for rendering.
94*4882a593Smuzhiyun */
95*4882a593Smuzhiyun static Bool
DrawableGone(__GLXdrawable * glxPriv,XID xid)96*4882a593Smuzhiyun DrawableGone(__GLXdrawable * glxPriv, XID xid)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun     __GLXcontext *c, *next;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun     if (glxPriv->type == GLX_DRAWABLE_WINDOW) {
101*4882a593Smuzhiyun         /* If this was created by glXCreateWindow, free the matching resource */
102*4882a593Smuzhiyun         if (glxPriv->drawId != glxPriv->pDraw->id) {
103*4882a593Smuzhiyun             if (xid == glxPriv->drawId)
104*4882a593Smuzhiyun                 FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE);
105*4882a593Smuzhiyun             else
106*4882a593Smuzhiyun                 FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE);
107*4882a593Smuzhiyun         }
108*4882a593Smuzhiyun         /* otherwise this window was implicitly created by MakeCurrent */
109*4882a593Smuzhiyun     }
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun     for (c = glxAllContexts; c; c = next) {
112*4882a593Smuzhiyun         next = c->next;
113*4882a593Smuzhiyun         if (c->currentClient &&
114*4882a593Smuzhiyun 		(c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
115*4882a593Smuzhiyun             /* flush the context */
116*4882a593Smuzhiyun             glFlush();
117*4882a593Smuzhiyun             /* just force a re-bind the next time through */
118*4882a593Smuzhiyun             (*c->loseCurrent) (c);
119*4882a593Smuzhiyun             lastGLContext = NULL;
120*4882a593Smuzhiyun         }
121*4882a593Smuzhiyun         if (c->drawPriv == glxPriv)
122*4882a593Smuzhiyun             c->drawPriv = NULL;
123*4882a593Smuzhiyun         if (c->readPriv == glxPriv)
124*4882a593Smuzhiyun             c->readPriv = NULL;
125*4882a593Smuzhiyun     }
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun     /* drop our reference to any backing pixmap */
128*4882a593Smuzhiyun     if (glxPriv->type == GLX_DRAWABLE_PIXMAP)
129*4882a593Smuzhiyun         glxPriv->pDraw->pScreen->DestroyPixmap((PixmapPtr) glxPriv->pDraw);
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun     glxPriv->destroy(glxPriv);
132*4882a593Smuzhiyun 
133*4882a593Smuzhiyun     return TRUE;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun Bool
__glXAddContext(__GLXcontext * cx)137*4882a593Smuzhiyun __glXAddContext(__GLXcontext * cx)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun     /* Register this context as a resource.
140*4882a593Smuzhiyun      */
141*4882a593Smuzhiyun     if (!AddResource(cx->id, __glXContextRes, (void *)cx)) {
142*4882a593Smuzhiyun 	return FALSE;
143*4882a593Smuzhiyun     }
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun     cx->next = glxAllContexts;
146*4882a593Smuzhiyun     glxAllContexts = cx;
147*4882a593Smuzhiyun     return TRUE;
148*4882a593Smuzhiyun }
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun static void
__glXRemoveFromContextList(__GLXcontext * cx)151*4882a593Smuzhiyun __glXRemoveFromContextList(__GLXcontext * cx)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun     __GLXcontext *c, *prev;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun     if (cx == glxAllContexts)
156*4882a593Smuzhiyun         glxAllContexts = cx->next;
157*4882a593Smuzhiyun     else {
158*4882a593Smuzhiyun         prev = glxAllContexts;
159*4882a593Smuzhiyun         for (c = glxAllContexts; c; c = c->next) {
160*4882a593Smuzhiyun             if (c == cx)
161*4882a593Smuzhiyun                 prev->next = c->next;
162*4882a593Smuzhiyun             prev = c;
163*4882a593Smuzhiyun         }
164*4882a593Smuzhiyun     }
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun /*
168*4882a593Smuzhiyun ** Free a context.
169*4882a593Smuzhiyun */
170*4882a593Smuzhiyun static GLboolean
__glXFreeContext(__GLXcontext * cx)171*4882a593Smuzhiyun __glXFreeContext(__GLXcontext * cx)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun     if (cx->idExists || cx->currentClient)
174*4882a593Smuzhiyun         return GL_FALSE;
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun     __glXRemoveFromContextList(cx);
177*4882a593Smuzhiyun 
178*4882a593Smuzhiyun     free(cx->feedbackBuf);
179*4882a593Smuzhiyun     free(cx->selectBuf);
180*4882a593Smuzhiyun     free(cx->largeCmdBuf);
181*4882a593Smuzhiyun     if (cx == lastGLContext) {
182*4882a593Smuzhiyun         lastGLContext = NULL;
183*4882a593Smuzhiyun     }
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun     /* We can get here through both regular dispatching from
186*4882a593Smuzhiyun      * __glXDispatch() or as a callback from the resource manager.  In
187*4882a593Smuzhiyun      * the latter case we need to lift the DRI lock manually. */
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun     if (!glxBlockClients) {
190*4882a593Smuzhiyun         cx->destroy(cx);
191*4882a593Smuzhiyun     }
192*4882a593Smuzhiyun     else {
193*4882a593Smuzhiyun         cx->next = glxPendingDestroyContexts;
194*4882a593Smuzhiyun         glxPendingDestroyContexts = cx;
195*4882a593Smuzhiyun     }
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun     return GL_TRUE;
198*4882a593Smuzhiyun }
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun /************************************************************************/
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun /*
203*4882a593Smuzhiyun ** These routines can be used to check whether a particular GL command
204*4882a593Smuzhiyun ** has caused an error.  Specifically, we use them to check whether a
205*4882a593Smuzhiyun ** given query has caused an error, in which case a zero-length data
206*4882a593Smuzhiyun ** reply is sent to the client.
207*4882a593Smuzhiyun */
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun static GLboolean errorOccured = GL_FALSE;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun /*
212*4882a593Smuzhiyun ** The GL was will call this routine if an error occurs.
213*4882a593Smuzhiyun */
214*4882a593Smuzhiyun void
__glXErrorCallBack(GLenum code)215*4882a593Smuzhiyun __glXErrorCallBack(GLenum code)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun     errorOccured = GL_TRUE;
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun /*
221*4882a593Smuzhiyun ** Clear the error flag before calling the GL command.
222*4882a593Smuzhiyun */
223*4882a593Smuzhiyun void
__glXClearErrorOccured(void)224*4882a593Smuzhiyun __glXClearErrorOccured(void)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun     errorOccured = GL_FALSE;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun /*
230*4882a593Smuzhiyun ** Check if the GL command caused an error.
231*4882a593Smuzhiyun */
232*4882a593Smuzhiyun GLboolean
__glXErrorOccured(void)233*4882a593Smuzhiyun __glXErrorOccured(void)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun     return errorOccured;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun static int __glXErrorBase;
239*4882a593Smuzhiyun int __glXEventBase;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun int
__glXError(int error)242*4882a593Smuzhiyun __glXError(int error)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun     return __glXErrorBase + error;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun __GLXclientState *
glxGetClient(ClientPtr pClient)248*4882a593Smuzhiyun glxGetClient(ClientPtr pClient)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun     return dixLookupPrivate(&pClient->devPrivates, glxClientPrivateKey);
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun static void
glxClientCallback(CallbackListPtr * list,void * closure,void * data)254*4882a593Smuzhiyun glxClientCallback(CallbackListPtr *list, void *closure, void *data)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun     NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
257*4882a593Smuzhiyun     ClientPtr pClient = clientinfo->client;
258*4882a593Smuzhiyun     __GLXclientState *cl = glxGetClient(pClient);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun     switch (pClient->clientState) {
261*4882a593Smuzhiyun     case ClientStateGone:
262*4882a593Smuzhiyun         free(cl->returnBuf);
263*4882a593Smuzhiyun         free(cl->GLClientextensions);
264*4882a593Smuzhiyun         cl->returnBuf = NULL;
265*4882a593Smuzhiyun         cl->GLClientextensions = NULL;
266*4882a593Smuzhiyun         break;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun     default:
269*4882a593Smuzhiyun         break;
270*4882a593Smuzhiyun     }
271*4882a593Smuzhiyun }
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun /************************************************************************/
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun static __GLXprovider *__glXProviderStack = &__glXDRISWRastProvider;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun void
GlxPushProvider(__GLXprovider * provider)278*4882a593Smuzhiyun GlxPushProvider(__GLXprovider * provider)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun     provider->next = __glXProviderStack;
281*4882a593Smuzhiyun     __glXProviderStack = provider;
282*4882a593Smuzhiyun }
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun static Bool
checkScreenVisuals(void)285*4882a593Smuzhiyun checkScreenVisuals(void)
286*4882a593Smuzhiyun {
287*4882a593Smuzhiyun     int i, j;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numScreens; i++) {
290*4882a593Smuzhiyun         ScreenPtr screen = screenInfo.screens[i];
291*4882a593Smuzhiyun         for (j = 0; j < screen->numVisuals; j++) {
292*4882a593Smuzhiyun             if ((screen->visuals[j].class == TrueColor ||
293*4882a593Smuzhiyun                  screen->visuals[j].class == DirectColor) &&
294*4882a593Smuzhiyun                 screen->visuals[j].nplanes > 12)
295*4882a593Smuzhiyun                 return TRUE;
296*4882a593Smuzhiyun         }
297*4882a593Smuzhiyun     }
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun     return FALSE;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun static void
GetGLXDrawableBytes(void * value,XID id,ResourceSizePtr size)303*4882a593Smuzhiyun GetGLXDrawableBytes(void *value, XID id, ResourceSizePtr size)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun     __GLXdrawable *draw = value;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun     size->resourceSize = 0;
308*4882a593Smuzhiyun     size->pixmapRefSize = 0;
309*4882a593Smuzhiyun     size->refCnt = 1;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun     if (draw->type == GLX_DRAWABLE_PIXMAP) {
312*4882a593Smuzhiyun         SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP);
313*4882a593Smuzhiyun         ResourceSizeRec pixmapSize = { 0, };
314*4882a593Smuzhiyun         pixmapSizeFunc((PixmapPtr)draw->pDraw, draw->pDraw->id, &pixmapSize);
315*4882a593Smuzhiyun         size->pixmapRefSize += pixmapSize.pixmapRefSize;
316*4882a593Smuzhiyun     }
317*4882a593Smuzhiyun }
318*4882a593Smuzhiyun 
319*4882a593Smuzhiyun static void
xorgGlxCloseExtension(const ExtensionEntry * extEntry)320*4882a593Smuzhiyun xorgGlxCloseExtension(const ExtensionEntry *extEntry)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun     if (glvnd_vendor != NULL) {
323*4882a593Smuzhiyun         glxServer.destroyVendor(glvnd_vendor);
324*4882a593Smuzhiyun         glvnd_vendor = NULL;
325*4882a593Smuzhiyun     }
326*4882a593Smuzhiyun     lastGLContext = NULL;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun static int
xorgGlxHandleRequest(ClientPtr client)330*4882a593Smuzhiyun xorgGlxHandleRequest(ClientPtr client)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun     return __glXDispatch(client);
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun static ScreenPtr
screenNumToScreen(int screen)336*4882a593Smuzhiyun screenNumToScreen(int screen)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun     if (screen < 0 || screen >= screenInfo.numScreens)
339*4882a593Smuzhiyun         return NULL;
340*4882a593Smuzhiyun 
341*4882a593Smuzhiyun     return screenInfo.screens[screen];
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
344*4882a593Smuzhiyun static int
maybe_swap32(ClientPtr client,int x)345*4882a593Smuzhiyun maybe_swap32(ClientPtr client, int x)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun     return client->swapped ? bswap_32(x) : x;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun 
350*4882a593Smuzhiyun static GlxServerVendor *
vendorForScreen(ClientPtr client,int screen)351*4882a593Smuzhiyun vendorForScreen(ClientPtr client, int screen)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun     screen = maybe_swap32(client, screen);
354*4882a593Smuzhiyun 
355*4882a593Smuzhiyun     return glxServer.getVendorForScreen(client, screenNumToScreen(screen));
356*4882a593Smuzhiyun }
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun /* this ought to be generated */
359*4882a593Smuzhiyun static int
xorgGlxThunkRequest(ClientPtr client)360*4882a593Smuzhiyun xorgGlxThunkRequest(ClientPtr client)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun     REQUEST(xGLXVendorPrivateReq);
363*4882a593Smuzhiyun     CARD32 vendorCode = maybe_swap32(client, stuff->vendorCode);
364*4882a593Smuzhiyun     GlxServerVendor *vendor = NULL;
365*4882a593Smuzhiyun     XID resource = 0;
366*4882a593Smuzhiyun     int ret;
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun     switch (vendorCode) {
369*4882a593Smuzhiyun     case X_GLXvop_QueryContextInfoEXT: {
370*4882a593Smuzhiyun         xGLXQueryContextInfoEXTReq *req = (void *)stuff;
371*4882a593Smuzhiyun         REQUEST_AT_LEAST_SIZE(*req);
372*4882a593Smuzhiyun         if (!(vendor = glxServer.getXIDMap(maybe_swap32(client, req->context))))
373*4882a593Smuzhiyun             return __glXError(GLXBadContext);
374*4882a593Smuzhiyun         break;
375*4882a593Smuzhiyun         }
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun     case X_GLXvop_GetFBConfigsSGIX: {
378*4882a593Smuzhiyun         xGLXGetFBConfigsSGIXReq *req = (void *)stuff;
379*4882a593Smuzhiyun         REQUEST_AT_LEAST_SIZE(*req);
380*4882a593Smuzhiyun         if (!(vendor = vendorForScreen(client, req->screen)))
381*4882a593Smuzhiyun             return BadValue;
382*4882a593Smuzhiyun         break;
383*4882a593Smuzhiyun         }
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun     case X_GLXvop_CreateContextWithConfigSGIX: {
386*4882a593Smuzhiyun         xGLXCreateContextWithConfigSGIXReq *req = (void *)stuff;
387*4882a593Smuzhiyun         REQUEST_AT_LEAST_SIZE(*req);
388*4882a593Smuzhiyun         resource = maybe_swap32(client, req->context);
389*4882a593Smuzhiyun         if (!(vendor = vendorForScreen(client, req->screen)))
390*4882a593Smuzhiyun             return BadValue;
391*4882a593Smuzhiyun         break;
392*4882a593Smuzhiyun         }
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun     case X_GLXvop_CreateGLXPixmapWithConfigSGIX: {
395*4882a593Smuzhiyun         xGLXCreateGLXPixmapWithConfigSGIXReq *req = (void *)stuff;
396*4882a593Smuzhiyun         REQUEST_AT_LEAST_SIZE(*req);
397*4882a593Smuzhiyun         resource = maybe_swap32(client, req->glxpixmap);
398*4882a593Smuzhiyun         if (!(vendor = vendorForScreen(client, req->screen)))
399*4882a593Smuzhiyun             return BadValue;
400*4882a593Smuzhiyun         break;
401*4882a593Smuzhiyun         }
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun     case X_GLXvop_CreateGLXPbufferSGIX: {
404*4882a593Smuzhiyun         xGLXCreateGLXPbufferSGIXReq *req = (void *)stuff;
405*4882a593Smuzhiyun         REQUEST_AT_LEAST_SIZE(*req);
406*4882a593Smuzhiyun         resource = maybe_swap32(client, req->pbuffer);
407*4882a593Smuzhiyun         if (!(vendor = vendorForScreen(client, req->screen)))
408*4882a593Smuzhiyun             return BadValue;
409*4882a593Smuzhiyun         break;
410*4882a593Smuzhiyun         }
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun     /* same offset for the drawable for these three */
413*4882a593Smuzhiyun     case X_GLXvop_DestroyGLXPbufferSGIX:
414*4882a593Smuzhiyun     case X_GLXvop_ChangeDrawableAttributesSGIX:
415*4882a593Smuzhiyun     case X_GLXvop_GetDrawableAttributesSGIX: {
416*4882a593Smuzhiyun         xGLXGetDrawableAttributesSGIXReq *req = (void *)stuff;
417*4882a593Smuzhiyun         REQUEST_AT_LEAST_SIZE(*req);
418*4882a593Smuzhiyun         if (!(vendor = glxServer.getXIDMap(maybe_swap32(client,
419*4882a593Smuzhiyun                                                         req->drawable))))
420*4882a593Smuzhiyun             return __glXError(GLXBadDrawable);
421*4882a593Smuzhiyun         break;
422*4882a593Smuzhiyun         }
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun     /* most things just use the standard context tag */
425*4882a593Smuzhiyun     default: {
426*4882a593Smuzhiyun         /* size checked by vnd layer already */
427*4882a593Smuzhiyun         GLXContextTag tag = maybe_swap32(client, stuff->contextTag);
428*4882a593Smuzhiyun         vendor = glxServer.getContextTag(client, tag);
429*4882a593Smuzhiyun         if (!vendor)
430*4882a593Smuzhiyun             return __glXError(GLXBadContextTag);
431*4882a593Smuzhiyun         break;
432*4882a593Smuzhiyun         }
433*4882a593Smuzhiyun     }
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun     /* If we're creating a resource, add the map now */
436*4882a593Smuzhiyun     if (resource) {
437*4882a593Smuzhiyun         LEGAL_NEW_RESOURCE(resource, client);
438*4882a593Smuzhiyun         if (!glxServer.addXIDMap(resource, vendor))
439*4882a593Smuzhiyun             return BadAlloc;
440*4882a593Smuzhiyun     }
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun     ret = glxServer.forwardRequest(vendor, client);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun     if (ret == Success && vendorCode == X_GLXvop_DestroyGLXPbufferSGIX) {
445*4882a593Smuzhiyun         xGLXDestroyGLXPbufferSGIXReq *req = (void *)stuff;
446*4882a593Smuzhiyun         glxServer.removeXIDMap(maybe_swap32(client, req->pbuffer));
447*4882a593Smuzhiyun     }
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun     if (ret != Success)
450*4882a593Smuzhiyun         glxServer.removeXIDMap(resource);
451*4882a593Smuzhiyun 
452*4882a593Smuzhiyun     return ret;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun static GlxServerDispatchProc
xorgGlxGetDispatchAddress(CARD8 minorOpcode,CARD32 vendorCode)456*4882a593Smuzhiyun xorgGlxGetDispatchAddress(CARD8 minorOpcode, CARD32 vendorCode)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun     /* we don't support any other GLX opcodes */
459*4882a593Smuzhiyun     if (minorOpcode != X_GLXVendorPrivate &&
460*4882a593Smuzhiyun         minorOpcode != X_GLXVendorPrivateWithReply)
461*4882a593Smuzhiyun         return NULL;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun     /* we only support some vendor private requests */
464*4882a593Smuzhiyun     if (!__glXGetProtocolDecodeFunction(&VendorPriv_dispatch_info, vendorCode,
465*4882a593Smuzhiyun                                         FALSE))
466*4882a593Smuzhiyun         return NULL;
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun     return xorgGlxThunkRequest;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun static Bool
xorgGlxServerPreInit(const ExtensionEntry * extEntry)472*4882a593Smuzhiyun xorgGlxServerPreInit(const ExtensionEntry *extEntry)
473*4882a593Smuzhiyun {
474*4882a593Smuzhiyun     if (glxGeneration != serverGeneration) {
475*4882a593Smuzhiyun         /* Mesa requires at least one True/DirectColor visual */
476*4882a593Smuzhiyun         if (!checkScreenVisuals())
477*4882a593Smuzhiyun             return FALSE;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun         __glXContextRes = CreateNewResourceType((DeleteType) ContextGone,
480*4882a593Smuzhiyun                                                 "GLXContext");
481*4882a593Smuzhiyun         __glXDrawableRes = CreateNewResourceType((DeleteType) DrawableGone,
482*4882a593Smuzhiyun                                                  "GLXDrawable");
483*4882a593Smuzhiyun         if (!__glXContextRes || !__glXDrawableRes)
484*4882a593Smuzhiyun             return FALSE;
485*4882a593Smuzhiyun 
486*4882a593Smuzhiyun         if (!dixRegisterPrivateKey
487*4882a593Smuzhiyun             (&glxClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(__GLXclientState)))
488*4882a593Smuzhiyun             return FALSE;
489*4882a593Smuzhiyun         if (!AddCallback(&ClientStateCallback, glxClientCallback, 0))
490*4882a593Smuzhiyun             return FALSE;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun         __glXErrorBase = extEntry->errorBase;
493*4882a593Smuzhiyun         __glXEventBase = extEntry->eventBase;
494*4882a593Smuzhiyun 
495*4882a593Smuzhiyun         SetResourceTypeSizeFunc(__glXDrawableRes, GetGLXDrawableBytes);
496*4882a593Smuzhiyun #if PRESENT
497*4882a593Smuzhiyun         __glXregisterPresentCompleteNotify();
498*4882a593Smuzhiyun #endif
499*4882a593Smuzhiyun 
500*4882a593Smuzhiyun         glxGeneration = serverGeneration;
501*4882a593Smuzhiyun     }
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun     return glxGeneration == serverGeneration;
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun static void
xorgGlxInitGLVNDVendor(void)507*4882a593Smuzhiyun xorgGlxInitGLVNDVendor(void)
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun     if (glvnd_vendor == NULL) {
510*4882a593Smuzhiyun         GlxServerImports *imports = NULL;
511*4882a593Smuzhiyun         imports = glxServer.allocateServerImports();
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun         if (imports != NULL) {
514*4882a593Smuzhiyun             imports->extensionCloseDown = xorgGlxCloseExtension;
515*4882a593Smuzhiyun             imports->handleRequest = xorgGlxHandleRequest;
516*4882a593Smuzhiyun             imports->getDispatchAddress = xorgGlxGetDispatchAddress;
517*4882a593Smuzhiyun             imports->makeCurrent = xorgGlxMakeCurrent;
518*4882a593Smuzhiyun             glvnd_vendor = glxServer.createVendor(imports);
519*4882a593Smuzhiyun             glxServer.freeServerImports(imports);
520*4882a593Smuzhiyun         }
521*4882a593Smuzhiyun     }
522*4882a593Smuzhiyun }
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun static void
xorgGlxServerInit(CallbackListPtr * pcbl,void * param,void * ext)525*4882a593Smuzhiyun xorgGlxServerInit(CallbackListPtr *pcbl, void *param, void *ext)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun     const ExtensionEntry *extEntry = ext;
528*4882a593Smuzhiyun     int i;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun     if (!xorgGlxServerPreInit(extEntry)) {
531*4882a593Smuzhiyun         return;
532*4882a593Smuzhiyun     }
533*4882a593Smuzhiyun 
534*4882a593Smuzhiyun     xorgGlxInitGLVNDVendor();
535*4882a593Smuzhiyun     if (!glvnd_vendor) {
536*4882a593Smuzhiyun         return;
537*4882a593Smuzhiyun     }
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numScreens; i++) {
540*4882a593Smuzhiyun         ScreenPtr pScreen = screenInfo.screens[i];
541*4882a593Smuzhiyun         __GLXprovider *p;
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun         if (glxServer.getVendorForScreen(NULL, pScreen) != NULL) {
544*4882a593Smuzhiyun             // There's already a vendor registered.
545*4882a593Smuzhiyun             LogMessage(X_INFO, "GLX: Another vendor is already registered for screen %d\n", i);
546*4882a593Smuzhiyun             continue;
547*4882a593Smuzhiyun         }
548*4882a593Smuzhiyun 
549*4882a593Smuzhiyun         for (p = __glXProviderStack; p != NULL; p = p->next) {
550*4882a593Smuzhiyun             __GLXscreen *glxScreen = p->screenProbe(pScreen);
551*4882a593Smuzhiyun             if (glxScreen != NULL) {
552*4882a593Smuzhiyun                 LogMessage(X_INFO,
553*4882a593Smuzhiyun                            "GLX: Initialized %s GL provider for screen %d\n",
554*4882a593Smuzhiyun                            p->name, i);
555*4882a593Smuzhiyun                 break;
556*4882a593Smuzhiyun             }
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun         }
559*4882a593Smuzhiyun 
560*4882a593Smuzhiyun         if (p) {
561*4882a593Smuzhiyun             glxServer.setScreenVendor(pScreen, glvnd_vendor);
562*4882a593Smuzhiyun         } else {
563*4882a593Smuzhiyun             LogMessage(X_INFO,
564*4882a593Smuzhiyun                        "GLX: no usable GL providers found for screen %d\n", i);
565*4882a593Smuzhiyun         }
566*4882a593Smuzhiyun     }
567*4882a593Smuzhiyun }
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun Bool
xorgGlxCreateVendor(void)570*4882a593Smuzhiyun xorgGlxCreateVendor(void)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun     return AddCallback(glxServer.extensionInitCallback, xorgGlxServerInit, NULL);
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun /************************************************************************/
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun /*
578*4882a593Smuzhiyun ** Make a context the current one for the GL (in this implementation, there
579*4882a593Smuzhiyun ** is only one instance of the GL, and we use it to serve all GL clients by
580*4882a593Smuzhiyun ** switching it between different contexts).  While we are at it, look up
581*4882a593Smuzhiyun ** a context by its tag and return its (__GLXcontext *).
582*4882a593Smuzhiyun */
583*4882a593Smuzhiyun __GLXcontext *
__glXForceCurrent(__GLXclientState * cl,GLXContextTag tag,int * error)584*4882a593Smuzhiyun __glXForceCurrent(__GLXclientState * cl, GLXContextTag tag, int *error)
585*4882a593Smuzhiyun {
586*4882a593Smuzhiyun     ClientPtr client = cl->client;
587*4882a593Smuzhiyun     REQUEST(xGLXSingleReq);
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun     __GLXcontext *cx;
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun     /*
592*4882a593Smuzhiyun      ** See if the context tag is legal; it is managed by the extension,
593*4882a593Smuzhiyun      ** so if it's invalid, we have an implementation error.
594*4882a593Smuzhiyun      */
595*4882a593Smuzhiyun     cx = __glXLookupContextByTag(cl, tag);
596*4882a593Smuzhiyun     if (!cx) {
597*4882a593Smuzhiyun         cl->client->errorValue = tag;
598*4882a593Smuzhiyun         *error = __glXError(GLXBadContextTag);
599*4882a593Smuzhiyun         return 0;
600*4882a593Smuzhiyun     }
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun     /* If we're expecting a glXRenderLarge request, this better be one. */
603*4882a593Smuzhiyun     if (cx->largeCmdRequestsSoFar != 0 && stuff->glxCode != X_GLXRenderLarge) {
604*4882a593Smuzhiyun         client->errorValue = stuff->glxCode;
605*4882a593Smuzhiyun         *error = __glXError(GLXBadLargeRequest);
606*4882a593Smuzhiyun         return 0;
607*4882a593Smuzhiyun     }
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun     if (!cx->isDirect) {
610*4882a593Smuzhiyun         if (cx->drawPriv == NULL) {
611*4882a593Smuzhiyun             /*
612*4882a593Smuzhiyun              ** The drawable has vanished.  It must be a window, because only
613*4882a593Smuzhiyun              ** windows can be destroyed from under us; GLX pixmaps are
614*4882a593Smuzhiyun              ** refcounted and don't go away until no one is using them.
615*4882a593Smuzhiyun              */
616*4882a593Smuzhiyun             *error = __glXError(GLXBadCurrentWindow);
617*4882a593Smuzhiyun             return 0;
618*4882a593Smuzhiyun         }
619*4882a593Smuzhiyun     }
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun     if (cx->wait && (*cx->wait) (cx, cl, error))
622*4882a593Smuzhiyun         return NULL;
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun     if (cx == lastGLContext) {
625*4882a593Smuzhiyun         /* No need to re-bind */
626*4882a593Smuzhiyun         return cx;
627*4882a593Smuzhiyun     }
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun     /* Make this context the current one for the GL. */
630*4882a593Smuzhiyun     if (!cx->isDirect) {
631*4882a593Smuzhiyun         /*
632*4882a593Smuzhiyun          * If it is being forced, it means that this context was already made
633*4882a593Smuzhiyun          * current. So it cannot just be made current again without decrementing
634*4882a593Smuzhiyun          * refcount's
635*4882a593Smuzhiyun          */
636*4882a593Smuzhiyun         (*cx->loseCurrent) (cx);
637*4882a593Smuzhiyun         lastGLContext = cx;
638*4882a593Smuzhiyun         if (!(*cx->makeCurrent) (cx)) {
639*4882a593Smuzhiyun             /* Bind failed, and set the error code.  Bummer */
640*4882a593Smuzhiyun             lastGLContext = NULL;
641*4882a593Smuzhiyun             cl->client->errorValue = cx->id;
642*4882a593Smuzhiyun             *error = __glXError(GLXBadContextState);
643*4882a593Smuzhiyun             return 0;
644*4882a593Smuzhiyun         }
645*4882a593Smuzhiyun     }
646*4882a593Smuzhiyun     return cx;
647*4882a593Smuzhiyun }
648*4882a593Smuzhiyun 
649*4882a593Smuzhiyun /************************************************************************/
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun void
glxSuspendClients(void)652*4882a593Smuzhiyun glxSuspendClients(void)
653*4882a593Smuzhiyun {
654*4882a593Smuzhiyun     int i;
655*4882a593Smuzhiyun 
656*4882a593Smuzhiyun     for (i = 1; i < currentMaxClients; i++) {
657*4882a593Smuzhiyun         if (clients[i] && glxGetClient(clients[i])->client)
658*4882a593Smuzhiyun             IgnoreClient(clients[i]);
659*4882a593Smuzhiyun     }
660*4882a593Smuzhiyun 
661*4882a593Smuzhiyun     glxBlockClients = TRUE;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun 
664*4882a593Smuzhiyun void
glxResumeClients(void)665*4882a593Smuzhiyun glxResumeClients(void)
666*4882a593Smuzhiyun {
667*4882a593Smuzhiyun     __GLXcontext *cx, *next;
668*4882a593Smuzhiyun     int i;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun     glxBlockClients = FALSE;
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun     for (i = 1; i < currentMaxClients; i++) {
673*4882a593Smuzhiyun         if (clients[i] && glxGetClient(clients[i])->client)
674*4882a593Smuzhiyun             AttendClient(clients[i]);
675*4882a593Smuzhiyun     }
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun     for (cx = glxPendingDestroyContexts; cx != NULL; cx = next) {
678*4882a593Smuzhiyun         next = cx->next;
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun         cx->destroy(cx);
681*4882a593Smuzhiyun     }
682*4882a593Smuzhiyun     glxPendingDestroyContexts = NULL;
683*4882a593Smuzhiyun }
684*4882a593Smuzhiyun 
685*4882a593Smuzhiyun static glx_gpa_proc _get_proc_address;
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun void
__glXsetGetProcAddress(glx_gpa_proc get_proc_address)688*4882a593Smuzhiyun __glXsetGetProcAddress(glx_gpa_proc get_proc_address)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun     _get_proc_address = get_proc_address;
691*4882a593Smuzhiyun }
692*4882a593Smuzhiyun 
__glGetProcAddress(const char * proc)693*4882a593Smuzhiyun void *__glGetProcAddress(const char *proc)
694*4882a593Smuzhiyun {
695*4882a593Smuzhiyun     void *ret = (void *) _get_proc_address(proc);
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun     return ret ? ret : (void *) NoopDDA;
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun 
700*4882a593Smuzhiyun /*
701*4882a593Smuzhiyun ** Top level dispatcher; all commands are executed from here down.
702*4882a593Smuzhiyun */
703*4882a593Smuzhiyun static int
__glXDispatch(ClientPtr client)704*4882a593Smuzhiyun __glXDispatch(ClientPtr client)
705*4882a593Smuzhiyun {
706*4882a593Smuzhiyun     REQUEST(xGLXSingleReq);
707*4882a593Smuzhiyun     CARD8 opcode;
708*4882a593Smuzhiyun     __GLXdispatchSingleProcPtr proc;
709*4882a593Smuzhiyun     __GLXclientState *cl;
710*4882a593Smuzhiyun     int retval = BadRequest;
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun     opcode = stuff->glxCode;
713*4882a593Smuzhiyun     cl = glxGetClient(client);
714*4882a593Smuzhiyun 
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun     if (!cl->client)
717*4882a593Smuzhiyun         cl->client = client;
718*4882a593Smuzhiyun 
719*4882a593Smuzhiyun     /* If we're currently blocking GLX clients, just put this guy to
720*4882a593Smuzhiyun      * sleep, reset the request and return. */
721*4882a593Smuzhiyun     if (glxBlockClients) {
722*4882a593Smuzhiyun         ResetCurrentRequest(client);
723*4882a593Smuzhiyun         client->sequence--;
724*4882a593Smuzhiyun         IgnoreClient(client);
725*4882a593Smuzhiyun         return Success;
726*4882a593Smuzhiyun     }
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun     /*
729*4882a593Smuzhiyun      ** Use the opcode to index into the procedure table.
730*4882a593Smuzhiyun      */
731*4882a593Smuzhiyun     proc = __glXGetProtocolDecodeFunction(&Single_dispatch_info, opcode,
732*4882a593Smuzhiyun                                           client->swapped);
733*4882a593Smuzhiyun     if (proc != NULL)
734*4882a593Smuzhiyun         retval = (*proc) (cl, (GLbyte *) stuff);
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun     return retval;
737*4882a593Smuzhiyun }
738