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