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