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