glx_api.c revision 8329f4db6124de0578bd1def39f0d5845a9025af
1d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)/* 2d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * Mesa 3-D graphics library 3d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * Version: 7.6 4d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * 5d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 6d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 7d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * 8d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 9d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * copy of this software and associated documentation files (the "Software"), 10d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * to deal in the Software without restriction, including without limitation 11d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * and/or sell copies of the Software, and to permit persons to whom the 13d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * Software is furnished to do so, subject to the following conditions: 14d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * 15d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * The above copyright notice and this permission notice shall be included 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27/** 28 * "Fake" GLX API implemented in terms of the XMesa*() functions. 29 */ 30 31 32 33#define GLX_GLXEXT_PROTOTYPES 34#include "GL/glx.h" 35 36#include "xm_api.h" 37 38 39/* This indicates the client-side GLX API and GLX encoder version. */ 40#define CLIENT_MAJOR_VERSION 1 41#define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */ 42 43/* This indicates the server-side GLX decoder version. 44 * GLX 1.4 indicates OpenGL 1.3 support 45 */ 46#define SERVER_MAJOR_VERSION 1 47#define SERVER_MINOR_VERSION 4 48 49/* Who implemented this GLX? */ 50#define VENDOR "Brian Paul" 51 52#define EXTENSIONS \ 53 "GLX_MESA_copy_sub_buffer " \ 54 "GLX_MESA_pixmap_colormap " \ 55 "GLX_MESA_release_buffers " \ 56 "GLX_ARB_get_proc_address " \ 57 "GLX_EXT_texture_from_pixmap " \ 58 "GLX_EXT_visual_info " \ 59 "GLX_EXT_visual_rating " \ 60 /*"GLX_SGI_video_sync "*/ \ 61 "GLX_SGIX_fbconfig " \ 62 "GLX_SGIX_pbuffer " 63 64#define DEFAULT_DIRECT GL_TRUE 65 66 67 68/** 69 * The GLXContext typedef is defined as a pointer to this structure. 70 */ 71struct __GLXcontextRec 72{ 73 Display *currentDpy; 74 GLboolean isDirect; 75 GLXDrawable currentDrawable; 76 GLXDrawable currentReadable; 77 XID xid; 78 79 XMesaContext xmesaContext; 80}; 81 82 83 84static pipe_tsd ContextTSD; 85 86/** Set current context for calling thread */ 87static void 88SetCurrentContext(GLXContext c) 89{ 90 pipe_tsd_set(&ContextTSD, c); 91} 92 93/** Get current context for calling thread */ 94static GLXContext 95GetCurrentContext(void) 96{ 97 return pipe_tsd_get(&ContextTSD); 98} 99 100 101 102/**********************************************************************/ 103/*** GLX Visual Code ***/ 104/**********************************************************************/ 105 106#define DONT_CARE -1 107 108 109static XMesaVisual *VisualTable = NULL; 110static int NumVisuals = 0; 111 112 113 114/* Macro to handle c_class vs class field name in XVisualInfo struct */ 115#if defined(__cplusplus) || defined(c_plusplus) 116#define CLASS c_class 117#else 118#define CLASS class 119#endif 120 121 122 123/* 124 * Test if the given XVisualInfo is usable for Mesa rendering. 125 */ 126static GLboolean 127is_usable_visual( XVisualInfo *vinfo ) 128{ 129 switch (vinfo->CLASS) { 130 case StaticGray: 131 case GrayScale: 132 /* Any StaticGray/GrayScale visual works in RGB or CI mode */ 133 return GL_TRUE; 134 case StaticColor: 135 case PseudoColor: 136 /* Any StaticColor/PseudoColor visual of at least 4 bits */ 137 if (vinfo->depth>=4) { 138 return GL_TRUE; 139 } 140 else { 141 return GL_FALSE; 142 } 143 case TrueColor: 144 case DirectColor: 145 /* Any depth of TrueColor or DirectColor works in RGB mode */ 146 return GL_TRUE; 147 default: 148 /* This should never happen */ 149 return GL_FALSE; 150 } 151} 152 153 154/* 155 * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the 156 * configuration in our list of GLX visuals. 157 */ 158static XMesaVisual 159save_glx_visual( Display *dpy, XVisualInfo *vinfo, 160 GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag, 161 GLboolean stereoFlag, 162 GLint depth_size, GLint stencil_size, 163 GLint accumRedSize, GLint accumGreenSize, 164 GLint accumBlueSize, GLint accumAlphaSize, 165 GLint level, GLint numAuxBuffers ) 166{ 167 GLboolean ximageFlag = GL_TRUE; 168 XMesaVisual xmvis; 169 GLint i; 170 GLboolean comparePointers; 171 172 if (dbFlag) { 173 /* Check if the MESA_BACK_BUFFER env var is set */ 174 char *backbuffer = _mesa_getenv("MESA_BACK_BUFFER"); 175 if (backbuffer) { 176 if (backbuffer[0]=='p' || backbuffer[0]=='P') { 177 ximageFlag = GL_FALSE; 178 } 179 else if (backbuffer[0]=='x' || backbuffer[0]=='X') { 180 ximageFlag = GL_TRUE; 181 } 182 else { 183 _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage."); 184 } 185 } 186 } 187 188 if (stereoFlag) { 189 /* stereo not supported */ 190 return NULL; 191 } 192 193 if (stencil_size > 0 && depth_size > 0) 194 depth_size = 24; 195 196 /* Comparing IDs uses less memory but sometimes fails. */ 197 /* XXX revisit this after 3.0 is finished. */ 198 if (_mesa_getenv("MESA_GLX_VISUAL_HACK")) 199 comparePointers = GL_TRUE; 200 else 201 comparePointers = GL_FALSE; 202 203 /* Force the visual to have an alpha channel */ 204 if (rgbFlag && _mesa_getenv("MESA_GLX_FORCE_ALPHA")) 205 alphaFlag = GL_TRUE; 206 207 /* First check if a matching visual is already in the list */ 208 for (i=0; i<NumVisuals; i++) { 209 XMesaVisual v = VisualTable[i]; 210 if (v->display == dpy 211 && v->mesa_visual.level == level 212 && v->mesa_visual.numAuxBuffers == numAuxBuffers 213 && v->ximage_flag == ximageFlag 214 && v->mesa_visual.rgbMode == rgbFlag 215 && v->mesa_visual.doubleBufferMode == dbFlag 216 && v->mesa_visual.stereoMode == stereoFlag 217 && (v->mesa_visual.alphaBits > 0) == alphaFlag 218 && (v->mesa_visual.depthBits >= depth_size || depth_size == 0) 219 && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0) 220 && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0) 221 && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0) 222 && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0) 223 && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) { 224 /* now either compare XVisualInfo pointers or visual IDs */ 225 if ((!comparePointers && v->visinfo->visualid == vinfo->visualid) 226 || (comparePointers && v->vishandle == vinfo)) { 227 return v; 228 } 229 } 230 } 231 232 /* Create a new visual and add it to the list. */ 233 234 xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag, 235 stereoFlag, ximageFlag, 236 depth_size, stencil_size, 237 accumRedSize, accumBlueSize, 238 accumBlueSize, accumAlphaSize, 0, level, 239 GLX_NONE_EXT ); 240 if (xmvis) { 241 /* Save a copy of the pointer now so we can find this visual again 242 * if we need to search for it in find_glx_visual(). 243 */ 244 xmvis->vishandle = vinfo; 245 /* Allocate more space for additional visual */ 246 VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable, 247 sizeof(XMesaVisual) * NumVisuals, 248 sizeof(XMesaVisual) * (NumVisuals + 1)); 249 /* add xmvis to the list */ 250 VisualTable[NumVisuals] = xmvis; 251 NumVisuals++; 252 /* XXX minor hack, because XMesaCreateVisual doesn't support an 253 * aux buffers parameter. 254 */ 255 xmvis->mesa_visual.numAuxBuffers = numAuxBuffers; 256 } 257 return xmvis; 258} 259 260 261/** 262 * Return the default number of bits for the Z buffer. 263 * If defined, use the MESA_GLX_DEPTH_BITS env var value. 264 * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant. 265 * XXX probably do the same thing for stencil, accum, etc. 266 */ 267static GLint 268default_depth_bits(void) 269{ 270 int zBits; 271 const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS"); 272 if (zEnv) 273 zBits = atoi(zEnv); 274 else 275 zBits = DEFAULT_SOFTWARE_DEPTH_BITS; 276 return zBits; 277} 278 279static GLint 280default_alpha_bits(void) 281{ 282 int aBits; 283 const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS"); 284 if (aEnv) 285 aBits = atoi(aEnv); 286 else 287 aBits = 0; 288 return aBits; 289} 290 291static GLint 292default_accum_bits(void) 293{ 294 return 16; 295} 296 297 298 299/* 300 * Create a GLX visual from a regular XVisualInfo. 301 * This is called when Fake GLX is given an XVisualInfo which wasn't 302 * returned by glXChooseVisual. Since this is the first time we're 303 * considering this visual we'll take a guess at reasonable values 304 * for depth buffer size, stencil size, accum size, etc. 305 * This is the best we can do with a client-side emulation of GLX. 306 */ 307static XMesaVisual 308create_glx_visual( Display *dpy, XVisualInfo *visinfo ) 309{ 310 GLint zBits = default_depth_bits(); 311 GLint accBits = default_accum_bits(); 312 GLboolean alphaFlag = default_alpha_bits() > 0; 313 314 if (is_usable_visual( visinfo )) { 315 /* Configure this visual as RGB, double-buffered, depth-buffered. */ 316 /* This is surely wrong for some people's needs but what else */ 317 /* can be done? They should use glXChooseVisual(). */ 318 return save_glx_visual( dpy, visinfo, 319 GL_TRUE, /* rgb */ 320 alphaFlag, /* alpha */ 321 GL_TRUE, /* double */ 322 GL_FALSE, /* stereo */ 323 zBits, 324 STENCIL_BITS, 325 accBits, /* r */ 326 accBits, /* g */ 327 accBits, /* b */ 328 accBits, /* a */ 329 0, /* level */ 330 0 /* numAux */ 331 ); 332 } 333 else { 334 _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n"); 335 return NULL; 336 } 337} 338 339 340 341/* 342 * Find the GLX visual associated with an XVisualInfo. 343 */ 344static XMesaVisual 345find_glx_visual( Display *dpy, XVisualInfo *vinfo ) 346{ 347 int i; 348 349 /* try to match visual id */ 350 for (i=0;i<NumVisuals;i++) { 351 if (VisualTable[i]->display==dpy 352 && VisualTable[i]->visinfo->visualid == vinfo->visualid) { 353 return VisualTable[i]; 354 } 355 } 356 357 /* if that fails, try to match pointers */ 358 for (i=0;i<NumVisuals;i++) { 359 if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) { 360 return VisualTable[i]; 361 } 362 } 363 364 return NULL; 365} 366 367 368/** 369 * Try to get an X visual which matches the given arguments. 370 */ 371static XVisualInfo * 372get_visual( Display *dpy, int scr, unsigned int depth, int xclass ) 373{ 374 XVisualInfo temp, *vis; 375 long mask; 376 int n; 377 unsigned int default_depth; 378 int default_class; 379 380 mask = VisualScreenMask | VisualDepthMask | VisualClassMask; 381 temp.screen = scr; 382 temp.depth = depth; 383 temp.CLASS = xclass; 384 385 default_depth = DefaultDepth(dpy,scr); 386 default_class = DefaultVisual(dpy,scr)->CLASS; 387 388 if (depth==default_depth && xclass==default_class) { 389 /* try to get root window's visual */ 390 temp.visualid = DefaultVisual(dpy,scr)->visualid; 391 mask |= VisualIDMask; 392 } 393 394 vis = XGetVisualInfo( dpy, mask, &temp, &n ); 395 396 /* In case bits/pixel > 24, make sure color channels are still <=8 bits. 397 * An SGI Infinite Reality system, for example, can have 30bpp pixels: 398 * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel. 399 */ 400 if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) { 401 if (_mesa_bitcount((GLuint) vis->red_mask ) <= 8 && 402 _mesa_bitcount((GLuint) vis->green_mask) <= 8 && 403 _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) { 404 return vis; 405 } 406 else { 407 XFree((void *) vis); 408 return NULL; 409 } 410 } 411 412 return vis; 413} 414 415 416/* 417 * Retrieve the value of the given environment variable and find 418 * the X visual which matches it. 419 * Input: dpy - the display 420 * screen - the screen number 421 * varname - the name of the environment variable 422 * Return: an XVisualInfo pointer to NULL if error. 423 */ 424static XVisualInfo * 425get_env_visual(Display *dpy, int scr, const char *varname) 426{ 427 char value[100], type[100]; 428 int depth, xclass = -1; 429 XVisualInfo *vis; 430 431 if (!_mesa_getenv( varname )) { 432 return NULL; 433 } 434 435 strncpy( value, _mesa_getenv(varname), 100 ); 436 value[99] = 0; 437 438 sscanf( value, "%s %d", type, &depth ); 439 440 if (strcmp(type,"TrueColor")==0) xclass = TrueColor; 441 else if (strcmp(type,"DirectColor")==0) xclass = DirectColor; 442 else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor; 443 else if (strcmp(type,"StaticColor")==0) xclass = StaticColor; 444 else if (strcmp(type,"GrayScale")==0) xclass = GrayScale; 445 else if (strcmp(type,"StaticGray")==0) xclass = StaticGray; 446 447 if (xclass>-1 && depth>0) { 448 vis = get_visual( dpy, scr, depth, xclass ); 449 if (vis) { 450 return vis; 451 } 452 } 453 454 _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.", 455 type, depth); 456 457 return NULL; 458} 459 460 461 462/* 463 * Select an X visual which satisfies the RGBA flag and minimum depth. 464 * Input: dpy, 465 * screen - X display and screen number 466 * min_depth - minimum visual depth 467 * preferred_class - preferred GLX visual class or DONT_CARE 468 * Return: pointer to an XVisualInfo or NULL. 469 */ 470static XVisualInfo * 471choose_x_visual( Display *dpy, int screen, int min_depth, 472 int preferred_class ) 473{ 474 XVisualInfo *vis; 475 int xclass, visclass = 0; 476 int depth; 477 478 /* First see if the MESA_RGB_VISUAL env var is defined */ 479 vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" ); 480 if (vis) { 481 return vis; 482 } 483 /* Otherwise, search for a suitable visual */ 484 if (preferred_class==DONT_CARE) { 485 for (xclass=0;xclass<6;xclass++) { 486 switch (xclass) { 487 case 0: visclass = TrueColor; break; 488 case 1: visclass = DirectColor; break; 489 case 2: visclass = PseudoColor; break; 490 case 3: visclass = StaticColor; break; 491 case 4: visclass = GrayScale; break; 492 case 5: visclass = StaticGray; break; 493 } 494 if (min_depth==0) { 495 /* start with shallowest */ 496 for (depth=0;depth<=32;depth++) { 497 if (visclass==TrueColor && depth==8) { 498 /* Special case: try to get 8-bit PseudoColor before */ 499 /* 8-bit TrueColor */ 500 vis = get_visual( dpy, screen, 8, PseudoColor ); 501 if (vis) { 502 return vis; 503 } 504 } 505 vis = get_visual( dpy, screen, depth, visclass ); 506 if (vis) { 507 return vis; 508 } 509 } 510 } 511 else { 512 /* start with deepest */ 513 for (depth=32;depth>=min_depth;depth--) { 514 if (visclass==TrueColor && depth==8) { 515 /* Special case: try to get 8-bit PseudoColor before */ 516 /* 8-bit TrueColor */ 517 vis = get_visual( dpy, screen, 8, PseudoColor ); 518 if (vis) { 519 return vis; 520 } 521 } 522 vis = get_visual( dpy, screen, depth, visclass ); 523 if (vis) { 524 return vis; 525 } 526 } 527 } 528 } 529 } 530 else { 531 /* search for a specific visual class */ 532 switch (preferred_class) { 533 case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break; 534 case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break; 535 case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break; 536 case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break; 537 case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break; 538 case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break; 539 default: return NULL; 540 } 541 if (min_depth==0) { 542 /* start with shallowest */ 543 for (depth=0;depth<=32;depth++) { 544 vis = get_visual( dpy, screen, depth, visclass ); 545 if (vis) { 546 return vis; 547 } 548 } 549 } 550 else { 551 /* start with deepest */ 552 for (depth=32;depth>=min_depth;depth--) { 553 vis = get_visual( dpy, screen, depth, visclass ); 554 if (vis) { 555 return vis; 556 } 557 } 558 } 559 } 560 561 /* didn't find a visual */ 562 return NULL; 563} 564 565 566 567 568/**********************************************************************/ 569/*** Display-related functions ***/ 570/**********************************************************************/ 571 572 573/** 574 * Free all XMesaVisuals which are associated with the given display. 575 */ 576static void 577destroy_visuals_on_display(Display *dpy) 578{ 579 int i; 580 for (i = 0; i < NumVisuals; i++) { 581 if (VisualTable[i]->display == dpy) { 582 /* remove this visual */ 583 int j; 584 free(VisualTable[i]); 585 for (j = i; j < NumVisuals - 1; j++) 586 VisualTable[j] = VisualTable[j + 1]; 587 NumVisuals--; 588 } 589 } 590} 591 592 593/** 594 * Called from XCloseDisplay() to let us free our display-related data. 595 */ 596static int 597close_display_callback(Display *dpy, XExtCodes *codes) 598{ 599 xmesa_destroy_buffers_on_display(dpy); 600 destroy_visuals_on_display(dpy); 601 return 0; 602} 603 604 605/** 606 * Look for the named extension on given display and return a pointer 607 * to the _XExtension data, or NULL if extension not found. 608 */ 609static _XExtension * 610lookup_extension(Display *dpy, const char *extName) 611{ 612 _XExtension *ext; 613 for (ext = dpy->ext_procs; ext; ext = ext->next) { 614 if (ext->name && strcmp(ext->name, extName) == 0) { 615 return ext; 616 } 617 } 618 return NULL; 619} 620 621 622/** 623 * Whenever we're given a new Display pointer, call this function to 624 * register our close_display_callback function. 625 */ 626static void 627register_with_display(Display *dpy) 628{ 629 const char *extName = "MesaGLX"; 630 _XExtension *ext; 631 632 ext = lookup_extension(dpy, extName); 633 if (!ext) { 634 XExtCodes *c = XAddExtension(dpy); 635 ext = dpy->ext_procs; /* new extension is at head of list */ 636 assert(c->extension == ext->codes.extension); 637 (void) c; 638 ext->name = _mesa_strdup(extName); 639 ext->close_display = close_display_callback; 640 } 641} 642 643 644/**********************************************************************/ 645/*** Begin Fake GLX API Functions ***/ 646/**********************************************************************/ 647 648 649/** 650 * Helper used by glXChooseVisual and glXChooseFBConfig. 651 * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for 652 * the later. 653 * In either case, the attribute list is terminated with the value 'None'. 654 */ 655static XMesaVisual 656choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) 657{ 658 const GLboolean rgbModeDefault = fbConfig; 659 const int *parselist; 660 XVisualInfo *vis; 661 int min_ci = 0; 662 int min_red=0, min_green=0, min_blue=0; 663 GLboolean rgb_flag = rgbModeDefault; 664 GLboolean alpha_flag = GL_FALSE; 665 GLboolean double_flag = GL_FALSE; 666 GLboolean stereo_flag = GL_FALSE; 667 GLint depth_size = 0; 668 GLint stencil_size = 0; 669 GLint accumRedSize = 0; 670 GLint accumGreenSize = 0; 671 GLint accumBlueSize = 0; 672 GLint accumAlphaSize = 0; 673 int level = 0; 674 int visual_type = DONT_CARE; 675 int trans_type = DONT_CARE; 676 int trans_value = DONT_CARE; 677 GLint caveat = DONT_CARE; 678 XMesaVisual xmvis = NULL; 679 int desiredVisualID = -1; 680 int numAux = 0; 681 682 xmesa_init( dpy ); 683 684 parselist = list; 685 686 while (*parselist) { 687 688 switch (*parselist) { 689 case GLX_USE_GL: 690 if (fbConfig) { 691 /* invalid token */ 692 return NULL; 693 } 694 else { 695 /* skip */ 696 parselist++; 697 } 698 break; 699 case GLX_BUFFER_SIZE: 700 parselist++; 701 min_ci = *parselist++; 702 break; 703 case GLX_LEVEL: 704 parselist++; 705 level = *parselist++; 706 break; 707 case GLX_RGBA: 708 if (fbConfig) { 709 /* invalid token */ 710 return NULL; 711 } 712 else { 713 rgb_flag = GL_TRUE; 714 parselist++; 715 } 716 break; 717 case GLX_DOUBLEBUFFER: 718 parselist++; 719 if (fbConfig) { 720 double_flag = *parselist++; 721 } 722 else { 723 double_flag = GL_TRUE; 724 } 725 break; 726 case GLX_STEREO: 727 parselist++; 728 if (fbConfig) { 729 stereo_flag = *parselist++; 730 } 731 else { 732 stereo_flag = GL_TRUE; 733 } 734 break; 735 case GLX_AUX_BUFFERS: 736 parselist++; 737 numAux = *parselist++; 738 if (numAux > MAX_AUX_BUFFERS) 739 return NULL; 740 break; 741 case GLX_RED_SIZE: 742 parselist++; 743 min_red = *parselist++; 744 break; 745 case GLX_GREEN_SIZE: 746 parselist++; 747 min_green = *parselist++; 748 break; 749 case GLX_BLUE_SIZE: 750 parselist++; 751 min_blue = *parselist++; 752 break; 753 case GLX_ALPHA_SIZE: 754 parselist++; 755 { 756 GLint size = *parselist++; 757 alpha_flag = size ? GL_TRUE : GL_FALSE; 758 } 759 break; 760 case GLX_DEPTH_SIZE: 761 parselist++; 762 depth_size = *parselist++; 763 break; 764 case GLX_STENCIL_SIZE: 765 parselist++; 766 stencil_size = *parselist++; 767 break; 768 case GLX_ACCUM_RED_SIZE: 769 parselist++; 770 { 771 GLint size = *parselist++; 772 accumRedSize = MAX2( accumRedSize, size ); 773 } 774 break; 775 case GLX_ACCUM_GREEN_SIZE: 776 parselist++; 777 { 778 GLint size = *parselist++; 779 accumGreenSize = MAX2( accumGreenSize, size ); 780 } 781 break; 782 case GLX_ACCUM_BLUE_SIZE: 783 parselist++; 784 { 785 GLint size = *parselist++; 786 accumBlueSize = MAX2( accumBlueSize, size ); 787 } 788 break; 789 case GLX_ACCUM_ALPHA_SIZE: 790 parselist++; 791 { 792 GLint size = *parselist++; 793 accumAlphaSize = MAX2( accumAlphaSize, size ); 794 } 795 break; 796 797 /* 798 * GLX_EXT_visual_info extension 799 */ 800 case GLX_X_VISUAL_TYPE_EXT: 801 parselist++; 802 visual_type = *parselist++; 803 break; 804 case GLX_TRANSPARENT_TYPE_EXT: 805 parselist++; 806 trans_type = *parselist++; 807 break; 808 case GLX_TRANSPARENT_INDEX_VALUE_EXT: 809 parselist++; 810 trans_value = *parselist++; 811 break; 812 case GLX_TRANSPARENT_RED_VALUE_EXT: 813 case GLX_TRANSPARENT_GREEN_VALUE_EXT: 814 case GLX_TRANSPARENT_BLUE_VALUE_EXT: 815 case GLX_TRANSPARENT_ALPHA_VALUE_EXT: 816 /* ignore */ 817 parselist++; 818 parselist++; 819 break; 820 821 /* 822 * GLX_EXT_visual_info extension 823 */ 824 case GLX_VISUAL_CAVEAT_EXT: 825 parselist++; 826 caveat = *parselist++; /* ignored for now */ 827 break; 828 829 /* 830 * GLX_ARB_multisample 831 */ 832 case GLX_SAMPLE_BUFFERS_ARB: 833 /* ms not supported */ 834 return NULL; 835 case GLX_SAMPLES_ARB: 836 /* ms not supported */ 837 return NULL; 838 839 /* 840 * FBConfig attribs. 841 */ 842 case GLX_RENDER_TYPE: 843 if (!fbConfig) 844 return NULL; 845 parselist++; 846 if (*parselist & GLX_RGBA_BIT) { 847 rgb_flag = GL_TRUE; 848 } 849 else if (*parselist & GLX_COLOR_INDEX_BIT) { 850 rgb_flag = GL_FALSE; 851 } 852 else if (*parselist == 0) { 853 rgb_flag = GL_TRUE; 854 } 855 parselist++; 856 break; 857 case GLX_DRAWABLE_TYPE: 858 if (!fbConfig) 859 return NULL; 860 parselist++; 861 if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) { 862 return NULL; /* bad bit */ 863 } 864 parselist++; 865 break; 866 case GLX_FBCONFIG_ID: 867 if (!fbConfig) 868 return NULL; 869 parselist++; 870 desiredVisualID = *parselist++; 871 break; 872 case GLX_X_RENDERABLE: 873 if (!fbConfig) 874 return NULL; 875 parselist += 2; 876 /* ignore */ 877 break; 878 879#ifdef GLX_EXT_texture_from_pixmap 880 case GLX_BIND_TO_TEXTURE_RGB_EXT: 881 parselist++; /*skip*/ 882 break; 883 case GLX_BIND_TO_TEXTURE_RGBA_EXT: 884 parselist++; /*skip*/ 885 break; 886 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 887 parselist++; /*skip*/ 888 break; 889 case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 890 parselist++; 891 if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT | 892 GLX_TEXTURE_2D_BIT_EXT | 893 GLX_TEXTURE_RECTANGLE_BIT_EXT)) { 894 /* invalid bit */ 895 return NULL; 896 } 897 break; 898 case GLX_Y_INVERTED_EXT: 899 parselist++; /*skip*/ 900 break; 901#endif 902 903 case None: 904 /* end of list */ 905 break; 906 907 default: 908 /* undefined attribute */ 909 _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()", 910 *parselist); 911 return NULL; 912 } 913 } 914 915 (void) caveat; 916 917 918 /* 919 * Since we're only simulating the GLX extension this function will never 920 * find any real GL visuals. Instead, all we can do is try to find an RGB 921 * or CI visual of appropriate depth. Other requested attributes such as 922 * double buffering, depth buffer, etc. will be associated with the X 923 * visual and stored in the VisualTable[]. 924 */ 925 if (desiredVisualID != -1) { 926 /* try to get a specific visual, by visualID */ 927 XVisualInfo temp; 928 int n; 929 temp.visualid = desiredVisualID; 930 temp.screen = screen; 931 vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n); 932 if (vis) { 933 /* give the visual some useful GLX attributes */ 934 double_flag = GL_TRUE; 935 rgb_flag = GL_TRUE; 936 } 937 } 938 else if (level==0) { 939 /* normal color planes */ 940 /* Get an RGB visual */ 941 int min_rgb = min_red + min_green + min_blue; 942 if (min_rgb>1 && min_rgb<8) { 943 /* a special case to be sure we can get a monochrome visual */ 944 min_rgb = 1; 945 } 946 vis = choose_x_visual( dpy, screen, min_rgb, visual_type ); 947 } 948 else { 949 _mesa_warning(NULL, "overlay not supported"); 950 return NULL; 951 } 952 953 if (vis) { 954 /* Note: we're not exactly obeying the glXChooseVisual rules here. 955 * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the 956 * largest depth buffer size, which is 32bits/value. Instead, we 957 * return 16 to maintain performance with earlier versions of Mesa. 958 */ 959 if (stencil_size > 0) 960 depth_size = 24; /* if Z and stencil, always use 24+8 format */ 961 else if (depth_size > 24) 962 depth_size = 32; 963 else if (depth_size > 16) 964 depth_size = 24; 965 else if (depth_size > 0) { 966 depth_size = default_depth_bits(); 967 } 968 969 if (!alpha_flag) { 970 alpha_flag = default_alpha_bits() > 0; 971 } 972 973 /* we only support one size of stencil and accum buffers. */ 974 if (stencil_size > 0) 975 stencil_size = STENCIL_BITS; 976 977 if (accumRedSize > 0 || 978 accumGreenSize > 0 || 979 accumBlueSize > 0 || 980 accumAlphaSize > 0) { 981 982 accumRedSize = 983 accumGreenSize = 984 accumBlueSize = default_accum_bits(); 985 986 accumAlphaSize = alpha_flag ? accumRedSize : 0; 987 } 988 989 xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, 990 stereo_flag, depth_size, stencil_size, 991 accumRedSize, accumGreenSize, 992 accumBlueSize, accumAlphaSize, level, numAux ); 993 } 994 995 return xmvis; 996} 997 998 999PUBLIC XVisualInfo * 1000glXChooseVisual( Display *dpy, int screen, int *list ) 1001{ 1002 XMesaVisual xmvis; 1003 1004 /* register ourselves as an extension on this display */ 1005 register_with_display(dpy); 1006 1007 xmvis = choose_visual(dpy, screen, list, GL_FALSE); 1008 if (xmvis) { 1009 /* create a new vishandle - the cached one may be stale */ 1010 xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo)); 1011 if (xmvis->vishandle) { 1012 memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); 1013 } 1014 return xmvis->vishandle; 1015 } 1016 else 1017 return NULL; 1018} 1019 1020 1021PUBLIC GLXContext 1022glXCreateContext( Display *dpy, XVisualInfo *visinfo, 1023 GLXContext share_list, Bool direct ) 1024{ 1025 XMesaVisual xmvis; 1026 GLXContext glxCtx; 1027 GLXContext shareCtx = share_list; 1028 1029 if (!dpy || !visinfo) 1030 return 0; 1031 1032 glxCtx = CALLOC_STRUCT(__GLXcontextRec); 1033 if (!glxCtx) 1034 return 0; 1035 1036 /* deallocate unused windows/buffers */ 1037#if 0 1038 XMesaGarbageCollect(); 1039#endif 1040 1041 xmvis = find_glx_visual( dpy, visinfo ); 1042 if (!xmvis) { 1043 /* This visual wasn't found with glXChooseVisual() */ 1044 xmvis = create_glx_visual( dpy, visinfo ); 1045 if (!xmvis) { 1046 /* unusable visual */ 1047 free(glxCtx); 1048 return NULL; 1049 } 1050 } 1051 1052 glxCtx->xmesaContext = XMesaCreateContext(xmvis, 1053 shareCtx ? shareCtx->xmesaContext : NULL); 1054 if (!glxCtx->xmesaContext) { 1055 free(glxCtx); 1056 return NULL; 1057 } 1058 1059 glxCtx->isDirect = DEFAULT_DIRECT; 1060 glxCtx->currentDpy = dpy; 1061 glxCtx->xid = (XID) glxCtx; /* self pointer */ 1062 1063 return glxCtx; 1064} 1065 1066 1067/* XXX these may have to be removed due to thread-safety issues. */ 1068static GLXContext MakeCurrent_PrevContext = 0; 1069static GLXDrawable MakeCurrent_PrevDrawable = 0; 1070static GLXDrawable MakeCurrent_PrevReadable = 0; 1071static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0; 1072static XMesaBuffer MakeCurrent_PrevReadBuffer = 0; 1073 1074 1075/* GLX 1.3 and later */ 1076PUBLIC Bool 1077glXMakeContextCurrent( Display *dpy, GLXDrawable draw, 1078 GLXDrawable read, GLXContext ctx ) 1079{ 1080 GLXContext glxCtx = ctx; 1081 static boolean firsttime = 1, no_rast = 0; 1082 1083 if (firsttime) { 1084 no_rast = getenv("SP_NO_RAST") != NULL; 1085 firsttime = 0; 1086 } 1087 1088 if (ctx && draw && read) { 1089 XMesaBuffer drawBuffer, readBuffer; 1090 XMesaContext xmctx = glxCtx->xmesaContext; 1091 1092 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */ 1093 if (ctx == MakeCurrent_PrevContext 1094 && draw == MakeCurrent_PrevDrawable) { 1095 drawBuffer = MakeCurrent_PrevDrawBuffer; 1096 } 1097 else { 1098 drawBuffer = XMesaFindBuffer( dpy, draw ); 1099 } 1100 if (!drawBuffer) { 1101 /* drawable must be a new window! */ 1102 drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw ); 1103 if (!drawBuffer) { 1104 /* Out of memory, or context/drawable depth mismatch */ 1105 return False; 1106 } 1107 } 1108 1109 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */ 1110 if (ctx == MakeCurrent_PrevContext 1111 && read == MakeCurrent_PrevReadable) { 1112 readBuffer = MakeCurrent_PrevReadBuffer; 1113 } 1114 else { 1115 readBuffer = XMesaFindBuffer( dpy, read ); 1116 } 1117 if (!readBuffer) { 1118 /* drawable must be a new window! */ 1119 readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read ); 1120 if (!readBuffer) { 1121 /* Out of memory, or context/drawable depth mismatch */ 1122 return False; 1123 } 1124 } 1125 1126 if (no_rast && 1127 MakeCurrent_PrevContext == ctx && 1128 MakeCurrent_PrevDrawable == draw && 1129 MakeCurrent_PrevReadable == read && 1130 MakeCurrent_PrevDrawBuffer == drawBuffer && 1131 MakeCurrent_PrevReadBuffer == readBuffer) 1132 return True; 1133 1134 MakeCurrent_PrevContext = ctx; 1135 MakeCurrent_PrevDrawable = draw; 1136 MakeCurrent_PrevReadable = read; 1137 MakeCurrent_PrevDrawBuffer = drawBuffer; 1138 MakeCurrent_PrevReadBuffer = readBuffer; 1139 1140 /* Now make current! */ 1141 if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { 1142 ctx->currentDpy = dpy; 1143 ctx->currentDrawable = draw; 1144 ctx->currentReadable = read; 1145 SetCurrentContext(ctx); 1146 return True; 1147 } 1148 else { 1149 return False; 1150 } 1151 } 1152 else if (!ctx && !draw && !read) { 1153 /* release current context w/out assigning new one. */ 1154 XMesaMakeCurrent2( NULL, NULL, NULL ); 1155 MakeCurrent_PrevContext = 0; 1156 MakeCurrent_PrevDrawable = 0; 1157 MakeCurrent_PrevReadable = 0; 1158 MakeCurrent_PrevDrawBuffer = 0; 1159 MakeCurrent_PrevReadBuffer = 0; 1160 SetCurrentContext(NULL); 1161 return True; 1162 } 1163 else { 1164 /* The args must either all be non-zero or all zero. 1165 * This is an error. 1166 */ 1167 return False; 1168 } 1169} 1170 1171 1172PUBLIC Bool 1173glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) 1174{ 1175 return glXMakeContextCurrent( dpy, drawable, drawable, ctx ); 1176} 1177 1178 1179PUBLIC GLXContext 1180glXGetCurrentContext(void) 1181{ 1182 return GetCurrentContext(); 1183} 1184 1185 1186PUBLIC Display * 1187glXGetCurrentDisplay(void) 1188{ 1189 GLXContext glxCtx = glXGetCurrentContext(); 1190 1191 return glxCtx ? glxCtx->currentDpy : NULL; 1192} 1193 1194 1195PUBLIC Display * 1196glXGetCurrentDisplayEXT(void) 1197{ 1198 return glXGetCurrentDisplay(); 1199} 1200 1201 1202PUBLIC GLXDrawable 1203glXGetCurrentDrawable(void) 1204{ 1205 GLXContext gc = glXGetCurrentContext(); 1206 return gc ? gc->currentDrawable : 0; 1207} 1208 1209 1210PUBLIC GLXDrawable 1211glXGetCurrentReadDrawable(void) 1212{ 1213 GLXContext gc = glXGetCurrentContext(); 1214 return gc ? gc->currentReadable : 0; 1215} 1216 1217 1218PUBLIC GLXDrawable 1219glXGetCurrentReadDrawableSGI(void) 1220{ 1221 return glXGetCurrentReadDrawable(); 1222} 1223 1224 1225PUBLIC GLXPixmap 1226glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) 1227{ 1228 XMesaVisual v; 1229 XMesaBuffer b; 1230 1231 v = find_glx_visual( dpy, visinfo ); 1232 if (!v) { 1233 v = create_glx_visual( dpy, visinfo ); 1234 if (!v) { 1235 /* unusable visual */ 1236 return 0; 1237 } 1238 } 1239 1240 b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); 1241 if (!b) { 1242 return 0; 1243 } 1244 return b->drawable; 1245} 1246 1247 1248/*** GLX_MESA_pixmap_colormap ***/ 1249 1250PUBLIC GLXPixmap 1251glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, 1252 Pixmap pixmap, Colormap cmap ) 1253{ 1254 XMesaVisual v; 1255 XMesaBuffer b; 1256 1257 v = find_glx_visual( dpy, visinfo ); 1258 if (!v) { 1259 v = create_glx_visual( dpy, visinfo ); 1260 if (!v) { 1261 /* unusable visual */ 1262 return 0; 1263 } 1264 } 1265 1266 b = XMesaCreatePixmapBuffer( v, pixmap, cmap ); 1267 if (!b) { 1268 return 0; 1269 } 1270 return b->drawable; 1271} 1272 1273 1274PUBLIC void 1275glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) 1276{ 1277 XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); 1278 if (b) { 1279 XMesaDestroyBuffer(b); 1280 } 1281 else if (_mesa_getenv("MESA_DEBUG")) { 1282 _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); 1283 } 1284} 1285 1286 1287PUBLIC void 1288glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, 1289 unsigned long mask ) 1290{ 1291 XMesaContext xm_src = src->xmesaContext; 1292 XMesaContext xm_dst = dst->xmesaContext; 1293 (void) dpy; 1294 if (MakeCurrent_PrevContext == src) { 1295 glFlush(); 1296 } 1297 XMesaCopyContext(xm_src, xm_dst, mask); 1298} 1299 1300 1301PUBLIC Bool 1302glXQueryExtension( Display *dpy, int *errorBase, int *eventBase ) 1303{ 1304 int op, ev, err; 1305 /* Mesa's GLX isn't really an X extension but we try to act like one. */ 1306 if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err)) 1307 ev = err = 0; 1308 if (errorBase) 1309 *errorBase = err; 1310 if (eventBase) 1311 *eventBase = ev; 1312 return True; /* we're faking GLX so always return success */ 1313} 1314 1315 1316PUBLIC void 1317glXDestroyContext( Display *dpy, GLXContext ctx ) 1318{ 1319 GLXContext glxCtx = ctx; 1320 (void) dpy; 1321 MakeCurrent_PrevContext = 0; 1322 MakeCurrent_PrevDrawable = 0; 1323 MakeCurrent_PrevReadable = 0; 1324 MakeCurrent_PrevDrawBuffer = 0; 1325 MakeCurrent_PrevReadBuffer = 0; 1326 XMesaDestroyContext( glxCtx->xmesaContext ); 1327 XMesaGarbageCollect(); 1328 free(glxCtx); 1329} 1330 1331 1332PUBLIC Bool 1333glXIsDirect( Display *dpy, GLXContext ctx ) 1334{ 1335 GLXContext glxCtx = ctx; 1336 (void) ctx; 1337 return glxCtx->isDirect; 1338} 1339 1340 1341 1342PUBLIC void 1343glXSwapBuffers( Display *dpy, GLXDrawable drawable ) 1344{ 1345 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); 1346 static boolean firsttime = 1, no_rast = 0; 1347 1348 if (firsttime) { 1349 no_rast = getenv("SP_NO_RAST") != NULL; 1350 firsttime = 0; 1351 } 1352 1353 if (no_rast) 1354 return; 1355 1356 if (buffer) { 1357 XMesaSwapBuffers(buffer); 1358 } 1359 else if (_mesa_getenv("MESA_DEBUG")) { 1360 _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n", 1361 (int) drawable); 1362 } 1363} 1364 1365 1366 1367/*** GLX_MESA_copy_sub_buffer ***/ 1368 1369PUBLIC void 1370glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, 1371 int x, int y, int width, int height) 1372{ 1373 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); 1374 if (buffer) { 1375 XMesaCopySubBuffer(buffer, x, y, width, height); 1376 } 1377 else if (_mesa_getenv("MESA_DEBUG")) { 1378 _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n"); 1379 } 1380} 1381 1382 1383PUBLIC Bool 1384glXQueryVersion( Display *dpy, int *maj, int *min ) 1385{ 1386 (void) dpy; 1387 /* Return GLX version, not Mesa version */ 1388 assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION); 1389 *maj = CLIENT_MAJOR_VERSION; 1390 *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION ); 1391 return True; 1392} 1393 1394 1395/* 1396 * Query the GLX attributes of the given XVisualInfo. 1397 */ 1398static int 1399get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) 1400{ 1401 ASSERT(xmvis); 1402 switch(attrib) { 1403 case GLX_USE_GL: 1404 if (fbconfig) 1405 return GLX_BAD_ATTRIBUTE; 1406 *value = (int) True; 1407 return 0; 1408 case GLX_BUFFER_SIZE: 1409 *value = xmvis->visinfo->depth; 1410 return 0; 1411 case GLX_LEVEL: 1412 *value = xmvis->mesa_visual.level; 1413 return 0; 1414 case GLX_RGBA: 1415 if (fbconfig) 1416 return GLX_BAD_ATTRIBUTE; 1417 if (xmvis->mesa_visual.rgbMode) { 1418 *value = True; 1419 } 1420 else { 1421 *value = False; 1422 } 1423 return 0; 1424 case GLX_DOUBLEBUFFER: 1425 *value = (int) xmvis->mesa_visual.doubleBufferMode; 1426 return 0; 1427 case GLX_STEREO: 1428 *value = (int) xmvis->mesa_visual.stereoMode; 1429 return 0; 1430 case GLX_AUX_BUFFERS: 1431 *value = xmvis->mesa_visual.numAuxBuffers; 1432 return 0; 1433 case GLX_RED_SIZE: 1434 *value = xmvis->mesa_visual.redBits; 1435 return 0; 1436 case GLX_GREEN_SIZE: 1437 *value = xmvis->mesa_visual.greenBits; 1438 return 0; 1439 case GLX_BLUE_SIZE: 1440 *value = xmvis->mesa_visual.blueBits; 1441 return 0; 1442 case GLX_ALPHA_SIZE: 1443 *value = xmvis->mesa_visual.alphaBits; 1444 return 0; 1445 case GLX_DEPTH_SIZE: 1446 *value = xmvis->mesa_visual.depthBits; 1447 return 0; 1448 case GLX_STENCIL_SIZE: 1449 *value = xmvis->mesa_visual.stencilBits; 1450 return 0; 1451 case GLX_ACCUM_RED_SIZE: 1452 *value = xmvis->mesa_visual.accumRedBits; 1453 return 0; 1454 case GLX_ACCUM_GREEN_SIZE: 1455 *value = xmvis->mesa_visual.accumGreenBits; 1456 return 0; 1457 case GLX_ACCUM_BLUE_SIZE: 1458 *value = xmvis->mesa_visual.accumBlueBits; 1459 return 0; 1460 case GLX_ACCUM_ALPHA_SIZE: 1461 *value = xmvis->mesa_visual.accumAlphaBits; 1462 return 0; 1463 1464 /* 1465 * GLX_EXT_visual_info extension 1466 */ 1467 case GLX_X_VISUAL_TYPE_EXT: 1468 switch (xmvis->visinfo->CLASS) { 1469 case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0; 1470 case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0; 1471 case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0; 1472 case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0; 1473 case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0; 1474 case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0; 1475 } 1476 return 0; 1477 case GLX_TRANSPARENT_TYPE_EXT: 1478 /* normal planes */ 1479 *value = GLX_NONE_EXT; 1480 return 0; 1481 case GLX_TRANSPARENT_INDEX_VALUE_EXT: 1482 /* undefined */ 1483 return 0; 1484 case GLX_TRANSPARENT_RED_VALUE_EXT: 1485 /* undefined */ 1486 return 0; 1487 case GLX_TRANSPARENT_GREEN_VALUE_EXT: 1488 /* undefined */ 1489 return 0; 1490 case GLX_TRANSPARENT_BLUE_VALUE_EXT: 1491 /* undefined */ 1492 return 0; 1493 case GLX_TRANSPARENT_ALPHA_VALUE_EXT: 1494 /* undefined */ 1495 return 0; 1496 1497 /* 1498 * GLX_EXT_visual_info extension 1499 */ 1500 case GLX_VISUAL_CAVEAT_EXT: 1501 /* test for zero, just in case */ 1502 if (xmvis->mesa_visual.visualRating > 0) 1503 *value = xmvis->mesa_visual.visualRating; 1504 else 1505 *value = GLX_NONE_EXT; 1506 return 0; 1507 1508 /* 1509 * GLX_ARB_multisample 1510 */ 1511 case GLX_SAMPLE_BUFFERS_ARB: 1512 *value = 0; 1513 return 0; 1514 case GLX_SAMPLES_ARB: 1515 *value = 0; 1516 return 0; 1517 1518 /* 1519 * For FBConfigs: 1520 */ 1521 case GLX_SCREEN_EXT: 1522 if (!fbconfig) 1523 return GLX_BAD_ATTRIBUTE; 1524 *value = xmvis->visinfo->screen; 1525 break; 1526 case GLX_DRAWABLE_TYPE: /*SGIX too */ 1527 if (!fbconfig) 1528 return GLX_BAD_ATTRIBUTE; 1529 *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 1530 break; 1531 case GLX_RENDER_TYPE_SGIX: 1532 if (!fbconfig) 1533 return GLX_BAD_ATTRIBUTE; 1534 if (xmvis->mesa_visual.rgbMode) 1535 *value = GLX_RGBA_BIT; 1536 else 1537 *value = GLX_COLOR_INDEX_BIT; 1538 break; 1539 case GLX_X_RENDERABLE_SGIX: 1540 if (!fbconfig) 1541 return GLX_BAD_ATTRIBUTE; 1542 *value = True; /* XXX really? */ 1543 break; 1544 case GLX_FBCONFIG_ID_SGIX: 1545 if (!fbconfig) 1546 return GLX_BAD_ATTRIBUTE; 1547 *value = xmvis->visinfo->visualid; 1548 break; 1549 case GLX_MAX_PBUFFER_WIDTH: 1550 if (!fbconfig) 1551 return GLX_BAD_ATTRIBUTE; 1552 /* XXX or MAX_WIDTH? */ 1553 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen); 1554 break; 1555 case GLX_MAX_PBUFFER_HEIGHT: 1556 if (!fbconfig) 1557 return GLX_BAD_ATTRIBUTE; 1558 *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen); 1559 break; 1560 case GLX_MAX_PBUFFER_PIXELS: 1561 if (!fbconfig) 1562 return GLX_BAD_ATTRIBUTE; 1563 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) * 1564 DisplayHeight(xmvis->display, xmvis->visinfo->screen); 1565 break; 1566 case GLX_VISUAL_ID: 1567 if (!fbconfig) 1568 return GLX_BAD_ATTRIBUTE; 1569 *value = xmvis->visinfo->visualid; 1570 break; 1571 1572#ifdef GLX_EXT_texture_from_pixmap 1573 case GLX_BIND_TO_TEXTURE_RGB_EXT: 1574 *value = True; /*XXX*/ 1575 break; 1576 case GLX_BIND_TO_TEXTURE_RGBA_EXT: 1577 /* XXX review */ 1578 *value = xmvis->mesa_visual.alphaBits > 0 ? True : False; 1579 break; 1580 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 1581 *value = True; /*XXX*/ 1582 break; 1583 case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 1584 *value = (GLX_TEXTURE_1D_BIT_EXT | 1585 GLX_TEXTURE_2D_BIT_EXT | 1586 GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/ 1587 break; 1588 case GLX_Y_INVERTED_EXT: 1589 *value = True; /*XXX*/ 1590 break; 1591#endif 1592 1593 default: 1594 return GLX_BAD_ATTRIBUTE; 1595 } 1596 return Success; 1597} 1598 1599 1600PUBLIC int 1601glXGetConfig( Display *dpy, XVisualInfo *visinfo, 1602 int attrib, int *value ) 1603{ 1604 XMesaVisual xmvis; 1605 int k; 1606 if (!dpy || !visinfo) 1607 return GLX_BAD_ATTRIBUTE; 1608 1609 xmvis = find_glx_visual( dpy, visinfo ); 1610 if (!xmvis) { 1611 /* this visual wasn't obtained with glXChooseVisual */ 1612 xmvis = create_glx_visual( dpy, visinfo ); 1613 if (!xmvis) { 1614 /* this visual can't be used for GL rendering */ 1615 if (attrib==GLX_USE_GL) { 1616 *value = (int) False; 1617 return 0; 1618 } 1619 else { 1620 return GLX_BAD_VISUAL; 1621 } 1622 } 1623 } 1624 1625 k = get_config(xmvis, attrib, value, GL_FALSE); 1626 return k; 1627} 1628 1629 1630PUBLIC void 1631glXWaitGL( void ) 1632{ 1633 XMesaContext xmesa = XMesaGetCurrentContext(); 1634 XMesaFlush( xmesa ); 1635} 1636 1637 1638 1639PUBLIC void 1640glXWaitX( void ) 1641{ 1642 XMesaContext xmesa = XMesaGetCurrentContext(); 1643 XMesaFlush( xmesa ); 1644} 1645 1646 1647static const char * 1648get_extensions( void ) 1649{ 1650 return EXTENSIONS; 1651} 1652 1653 1654 1655/* GLX 1.1 and later */ 1656PUBLIC const char * 1657glXQueryExtensionsString( Display *dpy, int screen ) 1658{ 1659 (void) dpy; 1660 (void) screen; 1661 return get_extensions(); 1662} 1663 1664 1665 1666/* GLX 1.1 and later */ 1667PUBLIC const char * 1668glXQueryServerString( Display *dpy, int screen, int name ) 1669{ 1670 static char version[1000]; 1671 sprintf(version, "%d.%d %s", 1672 SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name()); 1673 1674 (void) dpy; 1675 (void) screen; 1676 1677 switch (name) { 1678 case GLX_EXTENSIONS: 1679 return get_extensions(); 1680 case GLX_VENDOR: 1681 return VENDOR; 1682 case GLX_VERSION: 1683 return version; 1684 default: 1685 return NULL; 1686 } 1687} 1688 1689 1690 1691/* GLX 1.1 and later */ 1692PUBLIC const char * 1693glXGetClientString( Display *dpy, int name ) 1694{ 1695 static char version[1000]; 1696 sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, 1697 CLIENT_MINOR_VERSION, xmesa_get_name()); 1698 1699 (void) dpy; 1700 1701 switch (name) { 1702 case GLX_EXTENSIONS: 1703 return get_extensions(); 1704 case GLX_VENDOR: 1705 return VENDOR; 1706 case GLX_VERSION: 1707 return version; 1708 default: 1709 return NULL; 1710 } 1711} 1712 1713 1714 1715/* 1716 * GLX 1.3 and later 1717 */ 1718 1719 1720PUBLIC int 1721glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, 1722 int attribute, int *value) 1723{ 1724 XMesaVisual v = (XMesaVisual) config; 1725 (void) dpy; 1726 (void) config; 1727 1728 if (!dpy || !config || !value) 1729 return -1; 1730 1731 return get_config(v, attribute, value, GL_TRUE); 1732} 1733 1734 1735PUBLIC GLXFBConfig * 1736glXGetFBConfigs( Display *dpy, int screen, int *nelements ) 1737{ 1738 XVisualInfo *visuals, visTemplate; 1739 const long visMask = VisualScreenMask; 1740 int i; 1741 1742 /* Get list of all X visuals */ 1743 visTemplate.screen = screen; 1744 visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements); 1745 if (*nelements > 0) { 1746 XMesaVisual *results; 1747 results = (XMesaVisual *) malloc(*nelements * sizeof(XMesaVisual)); 1748 if (!results) { 1749 *nelements = 0; 1750 return NULL; 1751 } 1752 for (i = 0; i < *nelements; i++) { 1753 results[i] = create_glx_visual(dpy, visuals + i); 1754 if (!results[i]) { 1755 *nelements = i; 1756 break; 1757 } 1758 } 1759 return (GLXFBConfig *) results; 1760 } 1761 return NULL; 1762} 1763 1764 1765PUBLIC GLXFBConfig * 1766glXChooseFBConfig(Display *dpy, int screen, 1767 const int *attribList, int *nitems) 1768{ 1769 XMesaVisual xmvis; 1770 1771 if (!attribList || !attribList[0]) { 1772 /* return list of all configs (per GLX_SGIX_fbconfig spec) */ 1773 return glXGetFBConfigs(dpy, screen, nitems); 1774 } 1775 1776 xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); 1777 if (xmvis) { 1778 GLXFBConfig *config = (GLXFBConfig *) malloc(sizeof(XMesaVisual)); 1779 if (!config) { 1780 *nitems = 0; 1781 return NULL; 1782 } 1783 *nitems = 1; 1784 config[0] = (GLXFBConfig) xmvis; 1785 return (GLXFBConfig *) config; 1786 } 1787 else { 1788 *nitems = 0; 1789 return NULL; 1790 } 1791} 1792 1793 1794PUBLIC XVisualInfo * 1795glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) 1796{ 1797 if (dpy && config) { 1798 XMesaVisual xmvis = (XMesaVisual) config; 1799#if 0 1800 return xmvis->vishandle; 1801#else 1802 /* create a new vishandle - the cached one may be stale */ 1803 xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo)); 1804 if (xmvis->vishandle) { 1805 memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); 1806 } 1807 return xmvis->vishandle; 1808#endif 1809 } 1810 else { 1811 return NULL; 1812 } 1813} 1814 1815 1816PUBLIC GLXWindow 1817glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, 1818 const int *attribList) 1819{ 1820 XMesaVisual xmvis = (XMesaVisual) config; 1821 XMesaBuffer xmbuf; 1822 if (!xmvis) 1823 return 0; 1824 1825 xmbuf = XMesaCreateWindowBuffer(xmvis, win); 1826 if (!xmbuf) 1827 return 0; 1828 1829 (void) dpy; 1830 (void) attribList; /* Ignored in GLX 1.3 */ 1831 1832 return win; /* A hack for now */ 1833} 1834 1835 1836PUBLIC void 1837glXDestroyWindow( Display *dpy, GLXWindow window ) 1838{ 1839 XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window); 1840 if (b) 1841 XMesaDestroyBuffer(b); 1842 /* don't destroy X window */ 1843} 1844 1845 1846/* XXX untested */ 1847PUBLIC GLXPixmap 1848glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, 1849 const int *attribList) 1850{ 1851 XMesaVisual v = (XMesaVisual) config; 1852 XMesaBuffer b; 1853 const int *attr; 1854 int target = 0, format = 0, mipmap = 0; 1855 int value; 1856 1857 if (!dpy || !config || !pixmap) 1858 return 0; 1859 1860 for (attr = attribList; attr && *attr; attr++) { 1861 switch (*attr) { 1862 case GLX_TEXTURE_FORMAT_EXT: 1863 attr++; 1864 switch (*attr) { 1865 case GLX_TEXTURE_FORMAT_NONE_EXT: 1866 case GLX_TEXTURE_FORMAT_RGB_EXT: 1867 case GLX_TEXTURE_FORMAT_RGBA_EXT: 1868 format = *attr; 1869 break; 1870 default: 1871 /* error */ 1872 return 0; 1873 } 1874 break; 1875 case GLX_TEXTURE_TARGET_EXT: 1876 attr++; 1877 switch (*attr) { 1878 case GLX_TEXTURE_1D_EXT: 1879 case GLX_TEXTURE_2D_EXT: 1880 case GLX_TEXTURE_RECTANGLE_EXT: 1881 target = *attr; 1882 break; 1883 default: 1884 /* error */ 1885 return 0; 1886 } 1887 break; 1888 case GLX_MIPMAP_TEXTURE_EXT: 1889 attr++; 1890 if (*attr) 1891 mipmap = 1; 1892 break; 1893 default: 1894 /* error */ 1895 return 0; 1896 } 1897 } 1898 1899 if (format == GLX_TEXTURE_FORMAT_RGB_EXT) { 1900 if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT, 1901 &value, GL_TRUE) != Success 1902 || !value) { 1903 return 0; /* error! */ 1904 } 1905 } 1906 else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) { 1907 if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT, 1908 &value, GL_TRUE) != Success 1909 || !value) { 1910 return 0; /* error! */ 1911 } 1912 } 1913 if (mipmap) { 1914 if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT, 1915 &value, GL_TRUE) != Success 1916 || !value) { 1917 return 0; /* error! */ 1918 } 1919 } 1920 if (target == GLX_TEXTURE_1D_EXT) { 1921 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1922 &value, GL_TRUE) != Success 1923 || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) { 1924 return 0; /* error! */ 1925 } 1926 } 1927 else if (target == GLX_TEXTURE_2D_EXT) { 1928 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1929 &value, GL_TRUE) != Success 1930 || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) { 1931 return 0; /* error! */ 1932 } 1933 } 1934 if (target == GLX_TEXTURE_RECTANGLE_EXT) { 1935 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1936 &value, GL_TRUE) != Success 1937 || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) { 1938 return 0; /* error! */ 1939 } 1940 } 1941 1942 if (format || target || mipmap) { 1943 /* texture from pixmap */ 1944 b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap); 1945 } 1946 else { 1947 b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); 1948 } 1949 if (!b) { 1950 return 0; 1951 } 1952 1953 return pixmap; 1954} 1955 1956 1957PUBLIC void 1958glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) 1959{ 1960 XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap); 1961 if (b) 1962 XMesaDestroyBuffer(b); 1963 /* don't destroy X pixmap */ 1964} 1965 1966 1967PUBLIC GLXPbuffer 1968glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList) 1969{ 1970 XMesaVisual xmvis = (XMesaVisual) config; 1971 XMesaBuffer xmbuf; 1972 const int *attrib; 1973 int width = 0, height = 0; 1974 GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; 1975 1976 (void) dpy; 1977 1978 for (attrib = attribList; *attrib; attrib++) { 1979 switch (*attrib) { 1980 case GLX_PBUFFER_WIDTH: 1981 attrib++; 1982 width = *attrib; 1983 break; 1984 case GLX_PBUFFER_HEIGHT: 1985 attrib++; 1986 height = *attrib; 1987 break; 1988 case GLX_PRESERVED_CONTENTS: 1989 attrib++; 1990 preserveContents = *attrib; 1991 break; 1992 case GLX_LARGEST_PBUFFER: 1993 attrib++; 1994 useLargest = *attrib; 1995 break; 1996 default: 1997 return 0; 1998 } 1999 } 2000 2001 if (width == 0 || height == 0) 2002 return 0; 2003 2004 if (width > MAX_WIDTH || height > MAX_HEIGHT) { 2005 /* If allocation would have failed and GLX_LARGEST_PBUFFER is set, 2006 * allocate the largest possible buffer. 2007 */ 2008 if (useLargest) { 2009 width = MAX_WIDTH; 2010 height = MAX_HEIGHT; 2011 } 2012 } 2013 2014 xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); 2015 /* A GLXPbuffer handle must be an X Drawable because that's what 2016 * glXMakeCurrent takes. 2017 */ 2018 if (xmbuf) { 2019 xmbuf->largestPbuffer = useLargest; 2020 xmbuf->preservedContents = preserveContents; 2021 return (GLXPbuffer) xmbuf->drawable; 2022 } 2023 else { 2024 return 0; 2025 } 2026} 2027 2028 2029PUBLIC void 2030glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) 2031{ 2032 XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); 2033 if (b) { 2034 XMesaDestroyBuffer(b); 2035 } 2036} 2037 2038 2039PUBLIC void 2040glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, 2041 unsigned int *value) 2042{ 2043 GLuint width, height; 2044 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); 2045 if (!xmbuf) 2046 return; 2047 2048 /* make sure buffer's dimensions are up to date */ 2049 xmesa_get_window_size(dpy, xmbuf, &width, &height); 2050 2051 switch (attribute) { 2052 case GLX_WIDTH: 2053 *value = width; 2054 break; 2055 case GLX_HEIGHT: 2056 *value = height; 2057 break; 2058 case GLX_PRESERVED_CONTENTS: 2059 *value = xmbuf->preservedContents; 2060 break; 2061 case GLX_LARGEST_PBUFFER: 2062 *value = xmbuf->largestPbuffer; 2063 break; 2064 case GLX_FBCONFIG_ID: 2065 *value = xmbuf->xm_visual->visinfo->visualid; 2066 return; 2067#ifdef GLX_EXT_texture_from_pixmap 2068 case GLX_TEXTURE_FORMAT_EXT: 2069 *value = xmbuf->TextureFormat; 2070 break; 2071 case GLX_TEXTURE_TARGET_EXT: 2072 *value = xmbuf->TextureTarget; 2073 break; 2074 case GLX_MIPMAP_TEXTURE_EXT: 2075 *value = xmbuf->TextureMipmap; 2076 break; 2077#endif 2078 2079 default: 2080 return; /* raise BadValue error */ 2081 } 2082} 2083 2084 2085PUBLIC GLXContext 2086glXCreateNewContext( Display *dpy, GLXFBConfig config, 2087 int renderType, GLXContext shareList, Bool direct ) 2088{ 2089 GLXContext glxCtx; 2090 GLXContext shareCtx = shareList; 2091 XMesaVisual xmvis = (XMesaVisual) config; 2092 2093 if (!dpy || !config || 2094 (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) 2095 return 0; 2096 2097 glxCtx = CALLOC_STRUCT(__GLXcontextRec); 2098 if (!glxCtx) 2099 return 0; 2100 2101 /* deallocate unused windows/buffers */ 2102 XMesaGarbageCollect(); 2103 2104 glxCtx->xmesaContext = XMesaCreateContext(xmvis, 2105 shareCtx ? shareCtx->xmesaContext : NULL); 2106 if (!glxCtx->xmesaContext) { 2107 free(glxCtx); 2108 return NULL; 2109 } 2110 2111 glxCtx->isDirect = DEFAULT_DIRECT; 2112 glxCtx->currentDpy = dpy; 2113 glxCtx->xid = (XID) glxCtx; /* self pointer */ 2114 2115 return glxCtx; 2116} 2117 2118 2119PUBLIC int 2120glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) 2121{ 2122 GLXContext glxCtx = ctx; 2123 XMesaContext xmctx = glxCtx->xmesaContext; 2124 2125 (void) dpy; 2126 (void) ctx; 2127 2128 switch (attribute) { 2129 case GLX_FBCONFIG_ID: 2130 *value = xmctx->xm_visual->visinfo->visualid; 2131 break; 2132 case GLX_RENDER_TYPE: 2133 if (xmctx->xm_visual->mesa_visual.rgbMode) 2134 *value = GLX_RGBA_TYPE; 2135 else 2136 *value = GLX_COLOR_INDEX_TYPE; 2137 break; 2138 case GLX_SCREEN: 2139 *value = 0; 2140 return Success; 2141 default: 2142 return GLX_BAD_ATTRIBUTE; 2143 } 2144 return 0; 2145} 2146 2147 2148PUBLIC void 2149glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) 2150{ 2151 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2152 if (xmbuf) 2153 xmbuf->selectedEvents = mask; 2154} 2155 2156 2157PUBLIC void 2158glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask) 2159{ 2160 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2161 if (xmbuf) 2162 *mask = xmbuf->selectedEvents; 2163 else 2164 *mask = 0; 2165} 2166 2167 2168 2169/*** GLX_SGI_swap_control ***/ 2170 2171PUBLIC int 2172glXSwapIntervalSGI(int interval) 2173{ 2174 (void) interval; 2175 return 0; 2176} 2177 2178 2179 2180/*** GLX_SGI_video_sync ***/ 2181 2182static unsigned int FrameCounter = 0; 2183 2184PUBLIC int 2185glXGetVideoSyncSGI(unsigned int *count) 2186{ 2187 /* this is a bogus implementation */ 2188 *count = FrameCounter++; 2189 return 0; 2190} 2191 2192PUBLIC int 2193glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 2194{ 2195 if (divisor <= 0 || remainder < 0) 2196 return GLX_BAD_VALUE; 2197 /* this is a bogus implementation */ 2198 FrameCounter++; 2199 while (FrameCounter % divisor != remainder) 2200 FrameCounter++; 2201 *count = FrameCounter; 2202 return 0; 2203} 2204 2205 2206 2207/*** GLX_SGI_make_current_read ***/ 2208 2209PUBLIC Bool 2210glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, 2211 GLXContext ctx) 2212{ 2213 return glXMakeContextCurrent( dpy, draw, read, ctx ); 2214} 2215 2216/* not used 2217static GLXDrawable 2218glXGetCurrentReadDrawableSGI(void) 2219{ 2220 return 0; 2221} 2222*/ 2223 2224 2225/*** GLX_SGIX_video_source ***/ 2226#if defined(_VL_H) 2227 2228PUBLIC GLXVideoSourceSGIX 2229glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, 2230 VLPath path, int nodeClass, VLNode drainNode) 2231{ 2232 (void) dpy; 2233 (void) screen; 2234 (void) server; 2235 (void) path; 2236 (void) nodeClass; 2237 (void) drainNode; 2238 return 0; 2239} 2240 2241PUBLIC void 2242glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) 2243{ 2244 (void) dpy; 2245 (void) src; 2246} 2247 2248#endif 2249 2250 2251/*** GLX_EXT_import_context ***/ 2252 2253PUBLIC void 2254glXFreeContextEXT(Display *dpy, GLXContext context) 2255{ 2256 (void) dpy; 2257 (void) context; 2258} 2259 2260PUBLIC GLXContextID 2261glXGetContextIDEXT(const GLXContext context) 2262{ 2263 (void) context; 2264 return 0; 2265} 2266 2267PUBLIC GLXContext 2268glXImportContextEXT(Display *dpy, GLXContextID contextID) 2269{ 2270 (void) dpy; 2271 (void) contextID; 2272 return 0; 2273} 2274 2275PUBLIC int 2276glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, 2277 int *value) 2278{ 2279 (void) dpy; 2280 (void) context; 2281 (void) attribute; 2282 (void) value; 2283 return 0; 2284} 2285 2286 2287 2288/*** GLX_SGIX_fbconfig ***/ 2289 2290PUBLIC int 2291glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, 2292 int attribute, int *value) 2293{ 2294 return glXGetFBConfigAttrib(dpy, config, attribute, value); 2295} 2296 2297PUBLIC GLXFBConfigSGIX * 2298glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, 2299 int *nelements) 2300{ 2301 return (GLXFBConfig *) glXChooseFBConfig(dpy, screen, 2302 attrib_list, nelements); 2303} 2304 2305 2306PUBLIC GLXPixmap 2307glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, 2308 Pixmap pixmap) 2309{ 2310 XMesaVisual xmvis = (XMesaVisual) config; 2311 XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); 2312 return xmbuf->drawable; /* need to return an X ID */ 2313} 2314 2315 2316PUBLIC GLXContext 2317glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, 2318 int render_type, GLXContext share_list, 2319 Bool direct) 2320{ 2321 XMesaVisual xmvis = (XMesaVisual) config; 2322 GLXContext glxCtx; 2323 GLXContext shareCtx = share_list; 2324 2325 glxCtx = CALLOC_STRUCT(__GLXcontextRec); 2326 if (!glxCtx) 2327 return 0; 2328 2329 /* deallocate unused windows/buffers */ 2330 XMesaGarbageCollect(); 2331 2332 glxCtx->xmesaContext = XMesaCreateContext(xmvis, 2333 shareCtx ? shareCtx->xmesaContext : NULL); 2334 if (!glxCtx->xmesaContext) { 2335 free(glxCtx); 2336 return NULL; 2337 } 2338 2339 glxCtx->isDirect = DEFAULT_DIRECT; 2340 glxCtx->currentDpy = dpy; 2341 glxCtx->xid = (XID) glxCtx; /* self pointer */ 2342 2343 return glxCtx; 2344} 2345 2346 2347PUBLIC XVisualInfo * 2348glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) 2349{ 2350 return glXGetVisualFromFBConfig(dpy, config); 2351} 2352 2353 2354PUBLIC GLXFBConfigSGIX 2355glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) 2356{ 2357 XMesaVisual xmvis = find_glx_visual(dpy, vis); 2358 if (!xmvis) { 2359 /* This visual wasn't found with glXChooseVisual() */ 2360 xmvis = create_glx_visual(dpy, vis); 2361 } 2362 2363 return (GLXFBConfigSGIX) xmvis; 2364} 2365 2366 2367 2368/*** GLX_SGIX_pbuffer ***/ 2369 2370PUBLIC GLXPbufferSGIX 2371glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, 2372 unsigned int width, unsigned int height, 2373 int *attribList) 2374{ 2375 XMesaVisual xmvis = (XMesaVisual) config; 2376 XMesaBuffer xmbuf; 2377 const int *attrib; 2378 GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; 2379 2380 (void) dpy; 2381 2382 for (attrib = attribList; attrib && *attrib; attrib++) { 2383 switch (*attrib) { 2384 case GLX_PRESERVED_CONTENTS_SGIX: 2385 attrib++; 2386 preserveContents = *attrib; /* ignored */ 2387 break; 2388 case GLX_LARGEST_PBUFFER_SGIX: 2389 attrib++; 2390 useLargest = *attrib; /* ignored */ 2391 break; 2392 default: 2393 return 0; 2394 } 2395 } 2396 2397 /* not used at this time */ 2398 (void) useLargest; 2399 (void) preserveContents; 2400 2401 xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); 2402 /* A GLXPbuffer handle must be an X Drawable because that's what 2403 * glXMakeCurrent takes. 2404 */ 2405 return (GLXPbuffer) xmbuf->drawable; 2406} 2407 2408 2409PUBLIC void 2410glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) 2411{ 2412 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); 2413 if (xmbuf) { 2414 XMesaDestroyBuffer(xmbuf); 2415 } 2416} 2417 2418 2419PUBLIC int 2420glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, 2421 unsigned int *value) 2422{ 2423 const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); 2424 2425 if (!xmbuf) { 2426 /* Generate GLXBadPbufferSGIX for bad pbuffer */ 2427 return 0; 2428 } 2429 2430 switch (attribute) { 2431 case GLX_PRESERVED_CONTENTS_SGIX: 2432 *value = True; 2433 break; 2434 case GLX_LARGEST_PBUFFER_SGIX: 2435 *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf); 2436 break; 2437 case GLX_WIDTH_SGIX: 2438 *value = xmesa_buffer_width(xmbuf); 2439 break; 2440 case GLX_HEIGHT_SGIX: 2441 *value = xmesa_buffer_height(xmbuf); 2442 break; 2443 case GLX_EVENT_MASK_SGIX: 2444 *value = 0; /* XXX might be wrong */ 2445 break; 2446 default: 2447 *value = 0; 2448 } 2449 return 0; 2450} 2451 2452 2453PUBLIC void 2454glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) 2455{ 2456 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2457 if (xmbuf) { 2458 /* Note: we'll never generate clobber events */ 2459 xmbuf->selectedEvents = mask; 2460 } 2461} 2462 2463 2464PUBLIC void 2465glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, 2466 unsigned long *mask) 2467{ 2468 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2469 if (xmbuf) { 2470 *mask = xmbuf->selectedEvents; 2471 } 2472 else { 2473 *mask = 0; 2474 } 2475} 2476 2477 2478 2479/*** GLX_SGI_cushion ***/ 2480 2481PUBLIC void 2482glXCushionSGI(Display *dpy, Window win, float cushion) 2483{ 2484 (void) dpy; 2485 (void) win; 2486 (void) cushion; 2487} 2488 2489 2490 2491/*** GLX_SGIX_video_resize ***/ 2492 2493PUBLIC int 2494glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel, 2495 Window window) 2496{ 2497 (void) dpy; 2498 (void) screen; 2499 (void) channel; 2500 (void) window; 2501 return 0; 2502} 2503 2504PUBLIC int 2505glXChannelRectSGIX(Display *dpy, int screen, int channel, 2506 int x, int y, int w, int h) 2507{ 2508 (void) dpy; 2509 (void) screen; 2510 (void) channel; 2511 (void) x; 2512 (void) y; 2513 (void) w; 2514 (void) h; 2515 return 0; 2516} 2517 2518PUBLIC int 2519glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, 2520 int *x, int *y, int *w, int *h) 2521{ 2522 (void) dpy; 2523 (void) screen; 2524 (void) channel; 2525 (void) x; 2526 (void) y; 2527 (void) w; 2528 (void) h; 2529 return 0; 2530} 2531 2532PUBLIC int 2533glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, 2534 int *dx, int *dy, int *dw, int *dh) 2535{ 2536 (void) dpy; 2537 (void) screen; 2538 (void) channel; 2539 (void) dx; 2540 (void) dy; 2541 (void) dw; 2542 (void) dh; 2543 return 0; 2544} 2545 2546PUBLIC int 2547glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) 2548{ 2549 (void) dpy; 2550 (void) screen; 2551 (void) channel; 2552 (void) synctype; 2553 return 0; 2554} 2555 2556 2557 2558/*** GLX_SGIX_dmbuffer **/ 2559 2560#if defined(_DM_BUFFER_H_) 2561PUBLIC Bool 2562glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, 2563 DMparams *params, DMbuffer dmbuffer) 2564{ 2565 (void) dpy; 2566 (void) pbuffer; 2567 (void) params; 2568 (void) dmbuffer; 2569 return False; 2570} 2571#endif 2572 2573 2574/*** GLX_SGIX_swap_group ***/ 2575 2576PUBLIC void 2577glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) 2578{ 2579 (void) dpy; 2580 (void) drawable; 2581 (void) member; 2582} 2583 2584 2585 2586/*** GLX_SGIX_swap_barrier ***/ 2587 2588PUBLIC void 2589glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) 2590{ 2591 (void) dpy; 2592 (void) drawable; 2593 (void) barrier; 2594} 2595 2596PUBLIC Bool 2597glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) 2598{ 2599 (void) dpy; 2600 (void) screen; 2601 (void) max; 2602 return False; 2603} 2604 2605 2606 2607/*** GLX_SUN_get_transparent_index ***/ 2608 2609PUBLIC Status 2610glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, 2611 long *pTransparent) 2612{ 2613 (void) dpy; 2614 (void) overlay; 2615 (void) underlay; 2616 (void) pTransparent; 2617 return 0; 2618} 2619 2620 2621 2622/*** GLX_MESA_release_buffers ***/ 2623 2624/* 2625 * Release the depth, stencil, accum buffers attached to a GLXDrawable 2626 * (a window or pixmap) prior to destroying the GLXDrawable. 2627 */ 2628PUBLIC Bool 2629glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) 2630{ 2631 XMesaBuffer b = XMesaFindBuffer(dpy, d); 2632 if (b) { 2633 XMesaDestroyBuffer(b); 2634 return True; 2635 } 2636 return False; 2637} 2638 2639/*** GLX_EXT_texture_from_pixmap ***/ 2640 2641PUBLIC void 2642glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, 2643 const int *attrib_list) 2644{ 2645 XMesaBuffer b = XMesaFindBuffer(dpy, drawable); 2646 if (b) 2647 XMesaBindTexImage(dpy, b, buffer, attrib_list); 2648} 2649 2650PUBLIC void 2651glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) 2652{ 2653 XMesaBuffer b = XMesaFindBuffer(dpy, drawable); 2654 if (b) 2655 XMesaReleaseTexImage(dpy, b, buffer); 2656} 2657