Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / glxProxy / glxext.c
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
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
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
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
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
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
169 PixmapGone(__GLXpixmap * pGlxPixmap, XID id)
170 {
171
172 pGlxPixmap->idExists = False;
173 __glXFreeGLXPixmap(pGlxPixmap);
174
175 return True;
176 }
177
178 void
179 __glXFreeGLXWindow(__glXWindow * pGlxWindow)
180 {
181 if (!pGlxWindow->idExists && !pGlxWindow->refcnt) {
182 WindowPtr pWindow = (WindowPtr) pGlxWindow->pDraw;
183 WindowPtr ret;
184
185 dixLookupResourceByType((pointer) &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
197 WindowGone(__glXWindow * pGlxWindow, XID id)
198 {
199 pGlxWindow->idExists = False;
200 __glXFreeGLXWindow(pGlxWindow);
201 }
202
203 void
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
213 PbufferGone(__glXPbuffer * pGlxPbuffer, XID id)
214 {
215 pGlxPbuffer->idExists = False;
216 __glXFreeGLXPbuffer(pGlxPbuffer);
217 }
218
219 /*
220 ** Free a context.
221 */
222 GLboolean
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
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 if (!AddExtensionAlias(GLX_EXTENSION_ALIAS, extEntry)) {
328 ErrorF("__glXExtensionInit: AddExtensionAlias failed\n");
329 return;
330 }
331 */
332
333 __glXerrorBase = extEntry->errorBase;
334 __glXBadContext = extEntry->errorBase + GLXBadContext;
335 __glXBadContextState = extEntry->errorBase + GLXBadContextState;
336 __glXBadDrawable = extEntry->errorBase + GLXBadDrawable;
337 __glXBadPixmap = extEntry->errorBase + GLXBadPixmap;
338 __glXBadContextTag = extEntry->errorBase + GLXBadContextTag;
339 __glXBadCurrentWindow = extEntry->errorBase + GLXBadCurrentWindow;
340 __glXBadRenderRequest = extEntry->errorBase + GLXBadRenderRequest;
341 __glXBadLargeRequest = extEntry->errorBase + GLXBadLargeRequest;
342 __glXUnsupportedPrivateRequest = extEntry->errorBase +
343 GLXUnsupportedPrivateRequest;
344 __glXBadFBConfig = extEntry->errorBase + GLXBadFBConfig;
345 __glXBadPbuffer = extEntry->errorBase + GLXBadPbuffer;
346
347 /*
348 ** Initialize table of client state. There is never a client 0.
349 */
350 for (i = 1; i <= MAXCLIENTS; i++) {
351 __glXClients[i] = 0;
352 }
353
354 /*
355 ** Initialize screen specific data.
356 */
357 __glXScreenInit(screenInfo.numScreens);
358
359 /*
360 ** Initialize swap barrier support.
361 */
362 SwapBarrierInit();
363 }
364
365 /************************************************************************/
366
367 Bool
368 __glXCoreType(void)
369 {
370 return 0;
371 }
372
373 /************************************************************************/
374
375 void
376 __glXFlushContextCache(void)
377 {
378 __glXLastContext = 0;
379 }
380
381 /************************************************************************/
382
383 /*
384 ** Top level dispatcher; all commands are executed from here down.
385 */
386 static int
387 __glXDispatch(ClientPtr client)
388 {
389 REQUEST(xGLXSingleReq);
390 CARD8 opcode;
391 int (*proc) (__GLXclientState * cl, GLbyte * pc);
392 __GLXclientState *cl;
393
394 opcode = stuff->glxCode;
395 cl = __glXClients[client->index];
396 if (!cl) {
397 cl = calloc(1, sizeof(__GLXclientState));
398 __glXClients[client->index] = cl;
399 if (!cl) {
400 return BadAlloc;
401 }
402
403 cl->be_displays = calloc(screenInfo.numScreens, sizeof(Display *));
404 if (!cl->be_displays) {
405 free(cl);
406 return BadAlloc;
407 }
408 }
409
410 if (!cl->inUse) {
411 /*
412 ** This is first request from this client. Associate a resource
413 ** with the client so we will be notified when the client dies.
414 */
415 XID xid = FakeClientID(client->index);
416
417 if (!AddResource(xid, __glXClientRes, (pointer) (long) client->index)) {
418 return BadAlloc;
419 }
420 ResetClientState(client->index);
421 cl->largeCmdRequestsTotal = 0;
422 cl->inUse = GL_TRUE;
423 cl->client = client;
424 }
425
426 /*
427 ** Check for valid opcode.
428 */
429 if (opcode >= __GLX_SINGLE_TABLE_SIZE) {
430 return BadRequest;
431 }
432
433 /*
434 ** Use the opcode to index into the procedure table.
435 */
436 proc = __glXSingleTable[opcode];
437 return (*proc) (cl, (GLbyte *) stuff);
438 }
439
440 static int
441 __glXSwapDispatch(ClientPtr client)
442 {
443 REQUEST(xGLXSingleReq);
444 CARD8 opcode;
445 int (*proc) (__GLXclientState * cl, GLbyte * pc);
446 __GLXclientState *cl;
447
448 opcode = stuff->glxCode;
449 cl = __glXClients[client->index];
450 if (!cl) {
451 cl = calloc(1, sizeof(__GLXclientState));
452 __glXClients[client->index] = cl;
453 if (!cl) {
454 return BadAlloc;
455 }
456
457 cl->be_displays = calloc(screenInfo.numScreens, sizeof(Display *));
458 if (!cl->be_displays) {
459 free(cl);
460 return BadAlloc;
461 }
462 }
463
464 if (!cl->inUse) {
465 /*
466 ** This is first request from this client. Associate a resource
467 ** with the client so we will be notified when the client dies.
468 */
469 XID xid = FakeClientID(client->index);
470
471 if (!AddResource(xid, __glXClientRes, (pointer) (long) client->index)) {
472 return BadAlloc;
473 }
474 ResetClientState(client->index);
475 cl->inUse = GL_TRUE;
476 cl->client = client;
477 }
478
479 /*
480 ** Check for valid opcode.
481 */
482 if (opcode >= __GLX_SINGLE_TABLE_SIZE) {
483 return BadRequest;
484 }
485
486 /*
487 ** Use the opcode to index into the procedure table.
488 */
489 proc = __glXSwapSingleTable[opcode];
490 return (*proc) (cl, (GLbyte *) stuff);
491 }
492
493 int
494 __glXNoSuchSingleOpcode(__GLXclientState * cl, GLbyte * pc)
495 {
496 return BadRequest;
497 }
498
499 void
500 __glXNoSuchRenderOpcode(GLbyte * pc)
501 {
502 return;
503 }