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 48/* 49** Stubs to satisfy miinitext.c references. 50*/ 51typedef int __GLXprovider; 52__GLXprovider __glXDRISWRastProvider; 53void GlxPushProvider(__GLXprovider *provider) { } 54 55/* 56** Forward declarations. 57*/ 58static int __glXSwapDispatch(ClientPtr); 59static int __glXDispatch(ClientPtr); 60 61/* 62** Called when the extension is reset. 63*/ 64static void ResetExtension(ExtensionEntry* extEntry) 65{ 66 __glXFlushContextCache(); 67 __glXScreenReset(); 68 SwapBarrierReset(); 69} 70 71/* 72** Initialize the per-client context storage. 73*/ 74static void ResetClientState(int clientIndex) 75{ 76 __GLXclientState *cl = __glXClients[clientIndex]; 77 Display **keep_be_displays; 78 int i; 79 80 free(cl->returnBuf); 81 free(cl->currentContexts); 82 free(cl->currentDrawables); 83 free(cl->largeCmdBuf); 84 85 for (i=0; i< screenInfo.numScreens; i++) { 86 if (cl->be_displays[i]) 87 XCloseDisplay( cl->be_displays[i] ); 88 } 89 90 keep_be_displays = cl->be_displays; 91 memset(cl, 0, sizeof(__GLXclientState)); 92 cl->be_displays = keep_be_displays; 93 94 /* 95 ** By default, assume that the client supports 96 ** GLX major version 1 minor version 0 protocol. 97 */ 98 cl->GLClientmajorVersion = 1; 99 cl->GLClientminorVersion = 0; 100 free(cl->GLClientextensions); 101 102 memset(cl->be_displays, 0, screenInfo.numScreens * sizeof(Display *)); 103} 104 105 106/* 107** This procedure is called when the client who created the context goes 108** away OR when glXDestroyContext is called. In either case, all we do is 109** flag that the ID is no longer valid, and (maybe) free the context. 110** use. 111*/ 112static int ContextGone(__GLXcontext* cx, XID id) 113{ 114 cx->idExists = GL_FALSE; 115 if (!cx->isCurrent) { 116 __glXFreeContext(cx); 117 } 118 119 return True; 120} 121 122/* 123** Free a client's state. 124*/ 125static int ClientGone(int clientIndex, XID id) 126{ 127 __GLXcontext *cx; 128 __GLXclientState *cl = __glXClients[clientIndex]; 129 int i; 130 131 if (cl) { 132 /* 133 ** Free all the contexts that are current for this client. 134 */ 135 for (i=0; i < cl->numCurrentContexts; i++) { 136 cx = cl->currentContexts[i]; 137 if (cx) { 138 cx->isCurrent = GL_FALSE; 139 if (!cx->idExists) { 140 __glXFreeContext(cx); 141 } 142 } 143 } 144 /* 145 ** Re-initialize the client state structure. Don't free it because 146 ** we'll probably get another client with this index and use the struct 147 ** again. There is a maximum of MAXCLIENTS of these structures. 148 */ 149 ResetClientState(clientIndex); 150 } 151 152 return True; 153} 154 155/* 156** Free a GLX Pixmap. 157*/ 158void __glXFreeGLXPixmap( __GLXpixmap *pGlxPixmap ) 159{ 160 if (!pGlxPixmap->idExists && 161 !pGlxPixmap->refcnt) { 162 163 PixmapPtr pPixmap = (PixmapPtr) pGlxPixmap->pDraw; 164 165 /* 166 ** The DestroyPixmap routine should decrement the refcount and free 167 ** only if it's zero. 168 */ 169 (*pGlxPixmap->pScreen->DestroyPixmap)(pPixmap); 170 free(pGlxPixmap->be_xids); 171 free(pGlxPixmap); 172 } 173 174} 175 176static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id) 177{ 178 179 pGlxPixmap->idExists = False; 180 __glXFreeGLXPixmap( pGlxPixmap ); 181 182 return True; 183} 184 185void __glXFreeGLXWindow(__glXWindow *pGlxWindow) 186{ 187 if (!pGlxWindow->idExists && !pGlxWindow->refcnt) { 188 WindowPtr pWindow = (WindowPtr) pGlxWindow->pDraw; 189 WindowPtr ret; 190 191 dixLookupResourceByType((pointer) &ret, 192 pWindow->drawable.id, RT_WINDOW, 193 NullClient, DixUnknownAccess); 194 if (ret == pWindow) { 195 (*pGlxWindow->pScreen->DestroyWindow)(pWindow); 196 } 197 198 free(pGlxWindow); 199 } 200} 201 202static void WindowGone(__glXWindow *pGlxWindow, XID id) 203{ 204 pGlxWindow->idExists = False; 205 __glXFreeGLXWindow(pGlxWindow); 206} 207 208void __glXFreeGLXPbuffer(__glXPbuffer *pGlxPbuffer) 209{ 210 if (!pGlxPbuffer->idExists && !pGlxPbuffer->refcnt) { 211 free(pGlxPbuffer->be_xids); 212 free(pGlxPbuffer); 213 } 214} 215 216static void PbufferGone(__glXPbuffer *pGlxPbuffer, XID id) 217{ 218 pGlxPbuffer->idExists = False; 219 __glXFreeGLXPbuffer(pGlxPbuffer); 220} 221 222/* 223** Free a context. 224*/ 225GLboolean __glXFreeContext(__GLXcontext *cx) 226{ 227 if (cx->idExists || cx->isCurrent) return GL_FALSE; 228 229 free(cx->feedbackBuf); 230 free(cx->selectBuf); 231 free(cx->real_ids); 232 free(cx->real_vids); 233 234 if (cx->pGlxPixmap) { 235 /* 236 ** The previous drawable was a glx pixmap, release it. 237 */ 238 cx->pGlxPixmap->refcnt--; 239 __glXFreeGLXPixmap( cx->pGlxPixmap ); 240 cx->pGlxPixmap = 0; 241 } 242 243 if (cx->pGlxReadPixmap) { 244 /* 245 ** The previous drawable was a glx pixmap, release it. 246 */ 247 cx->pGlxReadPixmap->refcnt--; 248 __glXFreeGLXPixmap( cx->pGlxReadPixmap ); 249 cx->pGlxReadPixmap = 0; 250 } 251 252 if (cx->pGlxWindow) { 253 /* 254 ** The previous drawable was a glx window, release it. 255 */ 256 cx->pGlxWindow->refcnt--; 257 __glXFreeGLXWindow( cx->pGlxWindow ); 258 cx->pGlxWindow = 0; 259 } 260 261 if (cx->pGlxReadWindow) { 262 /* 263 ** The previous drawable was a glx window, release it. 264 */ 265 cx->pGlxReadWindow->refcnt--; 266 __glXFreeGLXWindow( cx->pGlxReadWindow ); 267 cx->pGlxReadWindow = 0; 268 } 269 270 free(cx); 271 272 if (cx == __glXLastContext) { 273 __glXFlushContextCache(); 274 } 275 276 return GL_TRUE; 277} 278 279/* 280** Initialize the GLX extension. 281*/ 282void 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 367Bool __glXCoreType(void) 368{ 369 return 0; 370} 371 372/************************************************************************/ 373 374void __glXFlushContextCache(void) 375{ 376 __glXLastContext = 0; 377} 378 379/************************************************************************/ 380 381/* 382** Top level dispatcher; all commands are executed from here down. 383*/ 384static int __glXDispatch(ClientPtr client) 385{ 386 REQUEST(xGLXSingleReq); 387 CARD8 opcode; 388 int (*proc)(__GLXclientState *cl, GLbyte *pc); 389 __GLXclientState *cl; 390 391 opcode = stuff->glxCode; 392 cl = __glXClients[client->index]; 393 if (!cl) { 394 cl = calloc(1, sizeof(__GLXclientState)); 395 __glXClients[client->index] = cl; 396 if (!cl) { 397 return BadAlloc; 398 } 399 400 cl->be_displays = calloc(screenInfo.numScreens, sizeof(Display *)); 401 if (!cl->be_displays) { 402 free( cl ); 403 return BadAlloc; 404 } 405 } 406 407 if (!cl->inUse) { 408 /* 409 ** This is first request from this client. Associate a resource 410 ** with the client so we will be notified when the client dies. 411 */ 412 XID xid = FakeClientID(client->index); 413 if (!AddResource( xid, __glXClientRes, (pointer)(long)client->index)) { 414 return BadAlloc; 415 } 416 ResetClientState(client->index); 417 cl->largeCmdRequestsTotal = 0; 418 cl->inUse = GL_TRUE; 419 cl->client = client; 420 } 421 422 /* 423 ** Check for valid opcode. 424 */ 425 if (opcode >= __GLX_SINGLE_TABLE_SIZE) { 426 return BadRequest; 427 } 428 429 /* 430 ** Use the opcode to index into the procedure table. 431 */ 432 proc = __glXSingleTable[opcode]; 433 return (*proc)(cl, (GLbyte *) stuff); 434} 435 436static int __glXSwapDispatch(ClientPtr client) 437{ 438 REQUEST(xGLXSingleReq); 439 CARD8 opcode; 440 int (*proc)(__GLXclientState *cl, GLbyte *pc); 441 __GLXclientState *cl; 442 443 opcode = stuff->glxCode; 444 cl = __glXClients[client->index]; 445 if (!cl) { 446 cl = calloc(1, sizeof(__GLXclientState)); 447 __glXClients[client->index] = cl; 448 if (!cl) { 449 return BadAlloc; 450 } 451 452 cl->be_displays = calloc(screenInfo.numScreens, sizeof(Display *)); 453 if (!cl->be_displays) { 454 free( cl ); 455 return BadAlloc; 456 } 457 } 458 459 if (!cl->inUse) { 460 /* 461 ** This is first request from this client. Associate a resource 462 ** with the client so we will be notified when the client dies. 463 */ 464 XID xid = FakeClientID(client->index); 465 if (!AddResource( xid, __glXClientRes, (pointer)(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 487int __glXNoSuchSingleOpcode(__GLXclientState *cl, GLbyte *pc) 488{ 489 return BadRequest; 490} 491 492void __glXNoSuchRenderOpcode(GLbyte *pc) 493{ 494 return; 495} 496 497