Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / dmx / glxProxy / glxext.c
CommitLineData
a09e091a
JB
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*/
53static int __glXSwapDispatch(ClientPtr);
54static int __glXDispatch(ClientPtr);
55
56/*
57** Called when the extension is reset.
58*/
59static void
60ResetExtension(ExtensionEntry * extEntry)
61{
62 __glXFlushContextCache();
63 __glXScreenReset();
64 SwapBarrierReset();
65}
66
67/*
68** Initialize the per-client context storage.
69*/
70static void
71ResetClientState(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*/
102static int
103ContextGone(__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*/
116static int
117ClientGone(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*/
150void
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
168static int
169PixmapGone(__GLXpixmap * pGlxPixmap, XID id)
170{
171
172 pGlxPixmap->idExists = False;
173 __glXFreeGLXPixmap(pGlxPixmap);
174
175 return True;
176}
177
178void
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
196static void
197WindowGone(__glXWindow * pGlxWindow, XID id)
198{
199 pGlxWindow->idExists = False;
200 __glXFreeGLXWindow(pGlxWindow);
201}
202
203void
204__glXFreeGLXPbuffer(__glXPbuffer * pGlxPbuffer)
205{
206 if (!pGlxPbuffer->idExists && !pGlxPbuffer->refcnt) {
207 free(pGlxPbuffer->be_xids);
208 free(pGlxPbuffer);
209 }
210}
211
212static void
213PbufferGone(__glXPbuffer * pGlxPbuffer, XID id)
214{
215 pGlxPbuffer->idExists = False;
216 __glXFreeGLXPbuffer(pGlxPbuffer);
217}
218
219/*
220** Free a context.
221*/
222GLboolean
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*/
281void
282GlxExtensionInit(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
367Bool
368__glXCoreType(void)
369{
370 return 0;
371}
372
373/************************************************************************/
374
375void
376__glXFlushContextCache(void)
377{
378 __glXLastContext = 0;
379}
380
381/************************************************************************/
382
383/*
384** Top level dispatcher; all commands are executed from here down.
385*/
386static 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
440static 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
493int
494__glXNoSuchSingleOpcode(__GLXclientState * cl, GLbyte * pc)
495{
496 return BadRequest;
497}
498
499void
500__glXNoSuchRenderOpcode(GLbyte * pc)
501{
502 return;
503}