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_DMX_CONFIG_H
32 #include <dmx-config.h>
33 #endif
34
35 #include "dmx.h"
36
37 #include "glxserver.h"
38 #include <windowstr.h>
39 #include <propertyst.h>
40 #include <os.h>
41 #include "g_disptab.h"
42 #include "glxutil.h"
43 #include "glxext.h"
44 #include "glxvisuals.h"
45 #include "micmap.h"
46 #include "glxswap.h"
47 #include "extinit.h"
48 #include "glx_extinit.h"
49
50 /*
51 ** Forward declarations.
52 */
53 static int __glXSwapDispatch(ClientPtr);
54 static int __glXDispatch(ClientPtr);
55
56 /*
57 ** Called when the extension is reset.
58 */
59 static void
ResetExtension(ExtensionEntry * extEntry)60 ResetExtension(ExtensionEntry * extEntry)
61 {
62 __glXFlushContextCache();
63 __glXScreenReset();
64 SwapBarrierReset();
65 }
66
67 /*
68 ** Initialize the per-client context storage.
69 */
70 static void
ResetClientState(int clientIndex)71 ResetClientState(int clientIndex)
72 {
73 __GLXclientState *cl = __glXClients[clientIndex];
74 Display **keep_be_displays;
75 int i;
76
77 free(cl->returnBuf);
78 free(cl->currentContexts);
79 free(cl->currentDrawables);
80 free(cl->largeCmdBuf);
81
82 for (i = 0; i < screenInfo.numScreens; i++) {
83 if (cl->be_displays[i])
84 XCloseDisplay(cl->be_displays[i]);
85 }
86
87 keep_be_displays = cl->be_displays;
88 memset(cl, 0, sizeof(__GLXclientState));
89 cl->be_displays = keep_be_displays;
90
91 free(cl->GLClientextensions);
92
93 memset(cl->be_displays, 0, screenInfo.numScreens * sizeof(Display *));
94 }
95
96 /*
97 ** This procedure is called when the client who created the context goes
98 ** away OR when glXDestroyContext is called. In either case, all we do is
99 ** flag that the ID is no longer valid, and (maybe) free the context.
100 ** use.
101 */
102 static int
ContextGone(__GLXcontext * cx,XID id)103 ContextGone(__GLXcontext * cx, XID id)
104 {
105 cx->idExists = GL_FALSE;
106 if (!cx->isCurrent) {
107 __glXFreeContext(cx);
108 }
109
110 return True;
111 }
112
113 /*
114 ** Free a client's state.
115 */
116 static int
ClientGone(int clientIndex,XID id)117 ClientGone(int clientIndex, XID id)
118 {
119 __GLXcontext *cx;
120 __GLXclientState *cl = __glXClients[clientIndex];
121 int i;
122
123 if (cl) {
124 /*
125 ** Free all the contexts that are current for this client.
126 */
127 for (i = 0; i < cl->numCurrentContexts; i++) {
128 cx = cl->currentContexts[i];
129 if (cx) {
130 cx->isCurrent = GL_FALSE;
131 if (!cx->idExists) {
132 __glXFreeContext(cx);
133 }
134 }
135 }
136 /*
137 ** Re-initialize the client state structure. Don't free it because
138 ** we'll probably get another client with this index and use the struct
139 ** again. There is a maximum of MAXCLIENTS of these structures.
140 */
141 ResetClientState(clientIndex);
142 }
143
144 return True;
145 }
146
147 /*
148 ** Free a GLX Pixmap.
149 */
150 void
__glXFreeGLXPixmap(__GLXpixmap * pGlxPixmap)151 __glXFreeGLXPixmap(__GLXpixmap * pGlxPixmap)
152 {
153 if (!pGlxPixmap->idExists && !pGlxPixmap->refcnt) {
154
155 PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw;
156
157 /*
158 ** The DestroyPixmap routine should decrement the refcount and free
159 ** only if it's zero.
160 */
161 (*pGlxPixmap->pScreen->DestroyPixmap) (pPixmap);
162 free(pGlxPixmap->be_xids);
163 free(pGlxPixmap);
164 }
165
166 }
167
168 static int
PixmapGone(__GLXpixmap * pGlxPixmap,XID id)169 PixmapGone(__GLXpixmap * pGlxPixmap, XID id)
170 {
171
172 pGlxPixmap->idExists = False;
173 __glXFreeGLXPixmap(pGlxPixmap);
174
175 return True;
176 }
177
178 void
__glXFreeGLXWindow(__glXWindow * pGlxWindow)179 __glXFreeGLXWindow(__glXWindow * pGlxWindow)
180 {
181 if (!pGlxWindow->idExists && !pGlxWindow->refcnt) {
182 WindowPtr pWindow = (WindowPtr) pGlxWindow->pDraw;
183 WindowPtr ret;
184
185 dixLookupResourceByType((void *) &ret,
186 pWindow->drawable.id, RT_WINDOW,
187 NullClient, DixUnknownAccess);
188 if (ret == pWindow) {
189 (*pGlxWindow->pScreen->DestroyWindow) (pWindow);
190 }
191
192 free(pGlxWindow);
193 }
194 }
195
196 static void
WindowGone(__glXWindow * pGlxWindow,XID id)197 WindowGone(__glXWindow * pGlxWindow, XID id)
198 {
199 pGlxWindow->idExists = False;
200 __glXFreeGLXWindow(pGlxWindow);
201 }
202
203 void
__glXFreeGLXPbuffer(__glXPbuffer * pGlxPbuffer)204 __glXFreeGLXPbuffer(__glXPbuffer * pGlxPbuffer)
205 {
206 if (!pGlxPbuffer->idExists && !pGlxPbuffer->refcnt) {
207 free(pGlxPbuffer->be_xids);
208 free(pGlxPbuffer);
209 }
210 }
211
212 static void
PbufferGone(__glXPbuffer * pGlxPbuffer,XID id)213 PbufferGone(__glXPbuffer * pGlxPbuffer, XID id)
214 {
215 pGlxPbuffer->idExists = False;
216 __glXFreeGLXPbuffer(pGlxPbuffer);
217 }
218
219 /*
220 ** Free a context.
221 */
222 GLboolean
__glXFreeContext(__GLXcontext * cx)223 __glXFreeContext(__GLXcontext * cx)
224 {
225 if (cx->idExists || cx->isCurrent)
226 return GL_FALSE;
227
228 free(cx->feedbackBuf);
229 free(cx->selectBuf);
230 free(cx->real_ids);
231 free(cx->real_vids);
232
233 if (cx->pGlxPixmap) {
234 /*
235 ** The previous drawable was a glx pixmap, release it.
236 */
237 cx->pGlxPixmap->refcnt--;
238 __glXFreeGLXPixmap(cx->pGlxPixmap);
239 cx->pGlxPixmap = 0;
240 }
241
242 if (cx->pGlxReadPixmap) {
243 /*
244 ** The previous drawable was a glx pixmap, release it.
245 */
246 cx->pGlxReadPixmap->refcnt--;
247 __glXFreeGLXPixmap(cx->pGlxReadPixmap);
248 cx->pGlxReadPixmap = 0;
249 }
250
251 if (cx->pGlxWindow) {
252 /*
253 ** The previous drawable was a glx window, release it.
254 */
255 cx->pGlxWindow->refcnt--;
256 __glXFreeGLXWindow(cx->pGlxWindow);
257 cx->pGlxWindow = 0;
258 }
259
260 if (cx->pGlxReadWindow) {
261 /*
262 ** The previous drawable was a glx window, release it.
263 */
264 cx->pGlxReadWindow->refcnt--;
265 __glXFreeGLXWindow(cx->pGlxReadWindow);
266 cx->pGlxReadWindow = 0;
267 }
268
269 free(cx);
270
271 if (cx == __glXLastContext) {
272 __glXFlushContextCache();
273 }
274
275 return GL_TRUE;
276 }
277
278 /*
279 ** Initialize the GLX extension.
280 */
281 void
GlxExtensionInit(void)282 GlxExtensionInit(void)
283 {
284 ExtensionEntry *extEntry;
285 int i;
286 int glxSupported = 1;
287
288 /*
289 // do not initialize GLX extension if GLX is not supported
290 // by ALL back-end servers.
291 */
292 for (i = 0; i < screenInfo.numScreens; i++) {
293 glxSupported &= (dmxScreens[i].glxMajorOpcode > 0);
294 }
295
296 if (!glxSupported || !dmxGLXProxy) {
297 return;
298 }
299
300 __glXContextRes = CreateNewResourceType((DeleteType) ContextGone,
301 "GLXContext");
302 __glXClientRes = CreateNewResourceType((DeleteType) ClientGone,
303 "GLXClient");
304 __glXPixmapRes = CreateNewResourceType((DeleteType) PixmapGone,
305 "GLXPixmap");
306 __glXWindowRes = CreateNewResourceType((DeleteType) WindowGone,
307 "GLXWindow");
308 __glXPbufferRes = CreateNewResourceType((DeleteType) PbufferGone,
309 "GLXPbuffer");
310
311 if (!__glXContextRes || !__glXClientRes || !__glXPixmapRes ||
312 !__glXWindowRes || !__glXPbufferRes)
313 return;
314
315 /*
316 ** Add extension to server extensions.
317 */
318 extEntry = AddExtension(GLX_EXTENSION_NAME, __GLX_NUMBER_EVENTS,
319 __GLX_NUMBER_ERRORS, __glXDispatch,
320 __glXSwapDispatch, ResetExtension,
321 StandardMinorOpcode);
322 if (!extEntry) {
323 FatalError("__glXExtensionInit: AddExtensions failed\n");
324 return;
325 }
326
327 __glXerrorBase = extEntry->errorBase;
328 __glXBadContext = extEntry->errorBase + GLXBadContext;
329 __glXBadContextState = extEntry->errorBase + GLXBadContextState;
330 __glXBadDrawable = extEntry->errorBase + GLXBadDrawable;
331 __glXBadPixmap = extEntry->errorBase + GLXBadPixmap;
332 __glXBadContextTag = extEntry->errorBase + GLXBadContextTag;
333 __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow;
334 __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest;
335 __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest;
336 __glXUnsupportedPrivateRequest = extEntry->errorBase +
337 GLXUnsupportedPrivateRequest;
338 __glXBadFBConfig = extEntry->errorBase + GLXBadFBConfig;
339 __glXBadPbuffer = extEntry->errorBase + GLXBadPbuffer;
340
341 /*
342 ** Initialize table of client state. There is never a client 0.
343 */
344 for (i = 1; i <= LimitClients; i++) {
345 __glXClients[i] = 0;
346 }
347
348 /*
349 ** Initialize screen specific data.
350 */
351 __glXScreenInit(screenInfo.numScreens);
352
353 /*
354 ** Initialize swap barrier support.
355 */
356 SwapBarrierInit();
357 }
358
359 /************************************************************************/
360
361 Bool
__glXCoreType(void)362 __glXCoreType(void)
363 {
364 return 0;
365 }
366
367 /************************************************************************/
368
369 void
__glXFlushContextCache(void)370 __glXFlushContextCache(void)
371 {
372 __glXLastContext = 0;
373 }
374
375 /************************************************************************/
376
377 /*
378 ** Top level dispatcher; all commands are executed from here down.
379 */
380 static int
__glXDispatch(ClientPtr client)381 __glXDispatch(ClientPtr client)
382 {
383 REQUEST(xGLXSingleReq);
384 CARD8 opcode;
385 int (*proc) (__GLXclientState * cl, GLbyte * pc);
386 __GLXclientState *cl;
387
388 opcode = stuff->glxCode;
389 cl = __glXClients[client->index];
390 if (!cl) {
391 cl = calloc(1, sizeof(__GLXclientState));
392 __glXClients[client->index] = cl;
393 if (!cl) {
394 return BadAlloc;
395 }
396
397 cl->be_displays = calloc(screenInfo.numScreens, sizeof(Display *));
398 if (!cl->be_displays) {
399 free(cl);
400 return BadAlloc;
401 }
402 }
403
404 if (!cl->inUse) {
405 /*
406 ** This is first request from this client. Associate a resource
407 ** with the client so we will be notified when the client dies.
408 */
409 XID xid = FakeClientID(client->index);
410
411 if (!AddResource(xid, __glXClientRes, (void *) (long) client->index)) {
412 return BadAlloc;
413 }
414 ResetClientState(client->index);
415 cl->largeCmdRequestsTotal = 0;
416 cl->inUse = GL_TRUE;
417 cl->client = client;
418 }
419
420 /*
421 ** Check for valid opcode.
422 */
423 if (opcode >= __GLX_SINGLE_TABLE_SIZE) {
424 return BadRequest;
425 }
426
427 /*
428 ** Use the opcode to index into the procedure table.
429 */
430 proc = __glXSingleTable[opcode];
431 return (*proc) (cl, (GLbyte *) stuff);
432 }
433
434 static int
__glXSwapDispatch(ClientPtr client)435 __glXSwapDispatch(ClientPtr client)
436 {
437 REQUEST(xGLXSingleReq);
438 CARD8 opcode;
439 int (*proc) (__GLXclientState * cl, GLbyte * pc);
440 __GLXclientState *cl;
441
442 opcode = stuff->glxCode;
443 cl = __glXClients[client->index];
444 if (!cl) {
445 cl = calloc(1, sizeof(__GLXclientState));
446 __glXClients[client->index] = cl;
447 if (!cl) {
448 return BadAlloc;
449 }
450
451 cl->be_displays = calloc(screenInfo.numScreens, sizeof(Display *));
452 if (!cl->be_displays) {
453 free(cl);
454 return BadAlloc;
455 }
456 }
457
458 if (!cl->inUse) {
459 /*
460 ** This is first request from this client. Associate a resource
461 ** with the client so we will be notified when the client dies.
462 */
463 XID xid = FakeClientID(client->index);
464
465 if (!AddResource(xid, __glXClientRes, (void *) (long) client->index)) {
466 return BadAlloc;
467 }
468 ResetClientState(client->index);
469 cl->inUse = GL_TRUE;
470 cl->client = client;
471 }
472
473 /*
474 ** Check for valid opcode.
475 */
476 if (opcode >= __GLX_SINGLE_TABLE_SIZE) {
477 return BadRequest;
478 }
479
480 /*
481 ** Use the opcode to index into the procedure table.
482 */
483 proc = __glXSwapSingleTable[opcode];
484 return (*proc) (cl, (GLbyte *) stuff);
485 }
486
487 int
__glXNoSuchSingleOpcode(__GLXclientState * cl,GLbyte * pc)488 __glXNoSuchSingleOpcode(__GLXclientState * cl, GLbyte * pc)
489 {
490 return BadRequest;
491 }
492
493 void
__glXNoSuchRenderOpcode(GLbyte * pc)494 __glXNoSuchRenderOpcode(GLbyte * pc)
495 {
496 return;
497 }
498