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