glx_api.c revision 7be3e507317a0e731fef91a1505f8500e8d1c050
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{ 1028 GLXContext glxCtx; 1029 1030 if (!dpy || !xmvis) 1031 return 0; 1032 1033 glxCtx = CALLOC_STRUCT(__GLXcontextRec); 1034 if (!glxCtx) 1035 return 0; 1036 1037 /* deallocate unused windows/buffers */ 1038#if 0 1039 XMesaGarbageCollect(); 1040#endif 1041 1042 glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx); 1043 if (!glxCtx->xmesaContext) { 1044 free(glxCtx); 1045 return NULL; 1046 } 1047 1048 glxCtx->isDirect = DEFAULT_DIRECT; 1049 glxCtx->currentDpy = dpy; 1050 glxCtx->xid = (XID) glxCtx; /* self pointer */ 1051 1052 return glxCtx; 1053} 1054 1055 1056PUBLIC GLXContext 1057glXCreateContext( Display *dpy, XVisualInfo *visinfo, 1058 GLXContext shareCtx, Bool direct ) 1059{ 1060 XMesaVisual xmvis; 1061 1062 xmvis = find_glx_visual( dpy, visinfo ); 1063 if (!xmvis) { 1064 /* This visual wasn't found with glXChooseVisual() */ 1065 xmvis = create_glx_visual( dpy, visinfo ); 1066 if (!xmvis) { 1067 /* unusable visual */ 1068 return NULL; 1069 } 1070 } 1071 1072 return create_context(dpy, xmvis, 1073 shareCtx ? shareCtx->xmesaContext : NULL, 1074 direct); 1075} 1076 1077 1078/* XXX these may have to be removed due to thread-safety issues. */ 1079static GLXContext MakeCurrent_PrevContext = 0; 1080static GLXDrawable MakeCurrent_PrevDrawable = 0; 1081static GLXDrawable MakeCurrent_PrevReadable = 0; 1082static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0; 1083static XMesaBuffer MakeCurrent_PrevReadBuffer = 0; 1084 1085 1086/* GLX 1.3 and later */ 1087PUBLIC Bool 1088glXMakeContextCurrent( Display *dpy, GLXDrawable draw, 1089 GLXDrawable read, GLXContext ctx ) 1090{ 1091 GLXContext glxCtx = ctx; 1092 static boolean firsttime = 1, no_rast = 0; 1093 1094 if (firsttime) { 1095 no_rast = getenv("SP_NO_RAST") != NULL; 1096 firsttime = 0; 1097 } 1098 1099 if (ctx && draw && read) { 1100 XMesaBuffer drawBuffer, readBuffer; 1101 XMesaContext xmctx = glxCtx->xmesaContext; 1102 1103 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */ 1104 if (ctx == MakeCurrent_PrevContext 1105 && draw == MakeCurrent_PrevDrawable) { 1106 drawBuffer = MakeCurrent_PrevDrawBuffer; 1107 } 1108 else { 1109 drawBuffer = XMesaFindBuffer( dpy, draw ); 1110 } 1111 if (!drawBuffer) { 1112 /* drawable must be a new window! */ 1113 drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw ); 1114 if (!drawBuffer) { 1115 /* Out of memory, or context/drawable depth mismatch */ 1116 return False; 1117 } 1118 } 1119 1120 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */ 1121 if (ctx == MakeCurrent_PrevContext 1122 && read == MakeCurrent_PrevReadable) { 1123 readBuffer = MakeCurrent_PrevReadBuffer; 1124 } 1125 else { 1126 readBuffer = XMesaFindBuffer( dpy, read ); 1127 } 1128 if (!readBuffer) { 1129 /* drawable must be a new window! */ 1130 readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read ); 1131 if (!readBuffer) { 1132 /* Out of memory, or context/drawable depth mismatch */ 1133 return False; 1134 } 1135 } 1136 1137 if (no_rast && 1138 MakeCurrent_PrevContext == ctx && 1139 MakeCurrent_PrevDrawable == draw && 1140 MakeCurrent_PrevReadable == read && 1141 MakeCurrent_PrevDrawBuffer == drawBuffer && 1142 MakeCurrent_PrevReadBuffer == readBuffer) 1143 return True; 1144 1145 MakeCurrent_PrevContext = ctx; 1146 MakeCurrent_PrevDrawable = draw; 1147 MakeCurrent_PrevReadable = read; 1148 MakeCurrent_PrevDrawBuffer = drawBuffer; 1149 MakeCurrent_PrevReadBuffer = readBuffer; 1150 1151 /* Now make current! */ 1152 if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { 1153 ctx->currentDpy = dpy; 1154 ctx->currentDrawable = draw; 1155 ctx->currentReadable = read; 1156 SetCurrentContext(ctx); 1157 return True; 1158 } 1159 else { 1160 return False; 1161 } 1162 } 1163 else if (!ctx && !draw && !read) { 1164 /* release current context w/out assigning new one. */ 1165 XMesaMakeCurrent2( NULL, NULL, NULL ); 1166 MakeCurrent_PrevContext = 0; 1167 MakeCurrent_PrevDrawable = 0; 1168 MakeCurrent_PrevReadable = 0; 1169 MakeCurrent_PrevDrawBuffer = 0; 1170 MakeCurrent_PrevReadBuffer = 0; 1171 SetCurrentContext(NULL); 1172 return True; 1173 } 1174 else { 1175 /* The args must either all be non-zero or all zero. 1176 * This is an error. 1177 */ 1178 return False; 1179 } 1180} 1181 1182 1183PUBLIC Bool 1184glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) 1185{ 1186 return glXMakeContextCurrent( dpy, drawable, drawable, ctx ); 1187} 1188 1189 1190PUBLIC GLXContext 1191glXGetCurrentContext(void) 1192{ 1193 return GetCurrentContext(); 1194} 1195 1196 1197PUBLIC Display * 1198glXGetCurrentDisplay(void) 1199{ 1200 GLXContext glxCtx = glXGetCurrentContext(); 1201 1202 return glxCtx ? glxCtx->currentDpy : NULL; 1203} 1204 1205 1206PUBLIC Display * 1207glXGetCurrentDisplayEXT(void) 1208{ 1209 return glXGetCurrentDisplay(); 1210} 1211 1212 1213PUBLIC GLXDrawable 1214glXGetCurrentDrawable(void) 1215{ 1216 GLXContext gc = glXGetCurrentContext(); 1217 return gc ? gc->currentDrawable : 0; 1218} 1219 1220 1221PUBLIC GLXDrawable 1222glXGetCurrentReadDrawable(void) 1223{ 1224 GLXContext gc = glXGetCurrentContext(); 1225 return gc ? gc->currentReadable : 0; 1226} 1227 1228 1229PUBLIC GLXDrawable 1230glXGetCurrentReadDrawableSGI(void) 1231{ 1232 return glXGetCurrentReadDrawable(); 1233} 1234 1235 1236PUBLIC GLXPixmap 1237glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) 1238{ 1239 XMesaVisual v; 1240 XMesaBuffer b; 1241 1242 v = find_glx_visual( dpy, visinfo ); 1243 if (!v) { 1244 v = create_glx_visual( dpy, visinfo ); 1245 if (!v) { 1246 /* unusable visual */ 1247 return 0; 1248 } 1249 } 1250 1251 b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); 1252 if (!b) { 1253 return 0; 1254 } 1255 return b->drawable; 1256} 1257 1258 1259/*** GLX_MESA_pixmap_colormap ***/ 1260 1261PUBLIC GLXPixmap 1262glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, 1263 Pixmap pixmap, Colormap cmap ) 1264{ 1265 XMesaVisual v; 1266 XMesaBuffer b; 1267 1268 v = find_glx_visual( dpy, visinfo ); 1269 if (!v) { 1270 v = create_glx_visual( dpy, visinfo ); 1271 if (!v) { 1272 /* unusable visual */ 1273 return 0; 1274 } 1275 } 1276 1277 b = XMesaCreatePixmapBuffer( v, pixmap, cmap ); 1278 if (!b) { 1279 return 0; 1280 } 1281 return b->drawable; 1282} 1283 1284 1285PUBLIC void 1286glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) 1287{ 1288 XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); 1289 if (b) { 1290 XMesaDestroyBuffer(b); 1291 } 1292 else if (_mesa_getenv("MESA_DEBUG")) { 1293 _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); 1294 } 1295} 1296 1297 1298PUBLIC void 1299glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, 1300 unsigned long mask ) 1301{ 1302 XMesaContext xm_src = src->xmesaContext; 1303 XMesaContext xm_dst = dst->xmesaContext; 1304 (void) dpy; 1305 if (MakeCurrent_PrevContext == src) { 1306 glFlush(); 1307 } 1308 XMesaCopyContext(xm_src, xm_dst, mask); 1309} 1310 1311 1312PUBLIC Bool 1313glXQueryExtension( Display *dpy, int *errorBase, int *eventBase ) 1314{ 1315 int op, ev, err; 1316 /* Mesa's GLX isn't really an X extension but we try to act like one. */ 1317 if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err)) 1318 ev = err = 0; 1319 if (errorBase) 1320 *errorBase = err; 1321 if (eventBase) 1322 *eventBase = ev; 1323 return True; /* we're faking GLX so always return success */ 1324} 1325 1326 1327PUBLIC void 1328glXDestroyContext( Display *dpy, GLXContext ctx ) 1329{ 1330 GLXContext glxCtx = ctx; 1331 (void) dpy; 1332 MakeCurrent_PrevContext = 0; 1333 MakeCurrent_PrevDrawable = 0; 1334 MakeCurrent_PrevReadable = 0; 1335 MakeCurrent_PrevDrawBuffer = 0; 1336 MakeCurrent_PrevReadBuffer = 0; 1337 XMesaDestroyContext( glxCtx->xmesaContext ); 1338 XMesaGarbageCollect(); 1339 free(glxCtx); 1340} 1341 1342 1343PUBLIC Bool 1344glXIsDirect( Display *dpy, GLXContext ctx ) 1345{ 1346 GLXContext glxCtx = ctx; 1347 (void) ctx; 1348 return glxCtx->isDirect; 1349} 1350 1351 1352 1353PUBLIC void 1354glXSwapBuffers( Display *dpy, GLXDrawable drawable ) 1355{ 1356 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); 1357 static boolean firsttime = 1, no_rast = 0; 1358 1359 if (firsttime) { 1360 no_rast = getenv("SP_NO_RAST") != NULL; 1361 firsttime = 0; 1362 } 1363 1364 if (no_rast) 1365 return; 1366 1367 if (buffer) { 1368 XMesaSwapBuffers(buffer); 1369 } 1370 else if (_mesa_getenv("MESA_DEBUG")) { 1371 _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n", 1372 (int) drawable); 1373 } 1374} 1375 1376 1377 1378/*** GLX_MESA_copy_sub_buffer ***/ 1379 1380PUBLIC void 1381glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, 1382 int x, int y, int width, int height) 1383{ 1384 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); 1385 if (buffer) { 1386 XMesaCopySubBuffer(buffer, x, y, width, height); 1387 } 1388 else if (_mesa_getenv("MESA_DEBUG")) { 1389 _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n"); 1390 } 1391} 1392 1393 1394PUBLIC Bool 1395glXQueryVersion( Display *dpy, int *maj, int *min ) 1396{ 1397 (void) dpy; 1398 /* Return GLX version, not Mesa version */ 1399 assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION); 1400 *maj = CLIENT_MAJOR_VERSION; 1401 *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION ); 1402 return True; 1403} 1404 1405 1406/* 1407 * Query the GLX attributes of the given XVisualInfo. 1408 */ 1409static int 1410get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) 1411{ 1412 ASSERT(xmvis); 1413 switch(attrib) { 1414 case GLX_USE_GL: 1415 if (fbconfig) 1416 return GLX_BAD_ATTRIBUTE; 1417 *value = (int) True; 1418 return 0; 1419 case GLX_BUFFER_SIZE: 1420 *value = xmvis->visinfo->depth; 1421 return 0; 1422 case GLX_LEVEL: 1423 *value = xmvis->mesa_visual.level; 1424 return 0; 1425 case GLX_RGBA: 1426 if (fbconfig) 1427 return GLX_BAD_ATTRIBUTE; 1428 if (xmvis->mesa_visual.rgbMode) { 1429 *value = True; 1430 } 1431 else { 1432 *value = False; 1433 } 1434 return 0; 1435 case GLX_DOUBLEBUFFER: 1436 *value = (int) xmvis->mesa_visual.doubleBufferMode; 1437 return 0; 1438 case GLX_STEREO: 1439 *value = (int) xmvis->mesa_visual.stereoMode; 1440 return 0; 1441 case GLX_AUX_BUFFERS: 1442 *value = xmvis->mesa_visual.numAuxBuffers; 1443 return 0; 1444 case GLX_RED_SIZE: 1445 *value = xmvis->mesa_visual.redBits; 1446 return 0; 1447 case GLX_GREEN_SIZE: 1448 *value = xmvis->mesa_visual.greenBits; 1449 return 0; 1450 case GLX_BLUE_SIZE: 1451 *value = xmvis->mesa_visual.blueBits; 1452 return 0; 1453 case GLX_ALPHA_SIZE: 1454 *value = xmvis->mesa_visual.alphaBits; 1455 return 0; 1456 case GLX_DEPTH_SIZE: 1457 *value = xmvis->mesa_visual.depthBits; 1458 return 0; 1459 case GLX_STENCIL_SIZE: 1460 *value = xmvis->mesa_visual.stencilBits; 1461 return 0; 1462 case GLX_ACCUM_RED_SIZE: 1463 *value = xmvis->mesa_visual.accumRedBits; 1464 return 0; 1465 case GLX_ACCUM_GREEN_SIZE: 1466 *value = xmvis->mesa_visual.accumGreenBits; 1467 return 0; 1468 case GLX_ACCUM_BLUE_SIZE: 1469 *value = xmvis->mesa_visual.accumBlueBits; 1470 return 0; 1471 case GLX_ACCUM_ALPHA_SIZE: 1472 *value = xmvis->mesa_visual.accumAlphaBits; 1473 return 0; 1474 1475 /* 1476 * GLX_EXT_visual_info extension 1477 */ 1478 case GLX_X_VISUAL_TYPE_EXT: 1479 switch (xmvis->visinfo->CLASS) { 1480 case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0; 1481 case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0; 1482 case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0; 1483 case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0; 1484 case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0; 1485 case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0; 1486 } 1487 return 0; 1488 case GLX_TRANSPARENT_TYPE_EXT: 1489 /* normal planes */ 1490 *value = GLX_NONE_EXT; 1491 return 0; 1492 case GLX_TRANSPARENT_INDEX_VALUE_EXT: 1493 /* undefined */ 1494 return 0; 1495 case GLX_TRANSPARENT_RED_VALUE_EXT: 1496 /* undefined */ 1497 return 0; 1498 case GLX_TRANSPARENT_GREEN_VALUE_EXT: 1499 /* undefined */ 1500 return 0; 1501 case GLX_TRANSPARENT_BLUE_VALUE_EXT: 1502 /* undefined */ 1503 return 0; 1504 case GLX_TRANSPARENT_ALPHA_VALUE_EXT: 1505 /* undefined */ 1506 return 0; 1507 1508 /* 1509 * GLX_EXT_visual_info extension 1510 */ 1511 case GLX_VISUAL_CAVEAT_EXT: 1512 /* test for zero, just in case */ 1513 if (xmvis->mesa_visual.visualRating > 0) 1514 *value = xmvis->mesa_visual.visualRating; 1515 else 1516 *value = GLX_NONE_EXT; 1517 return 0; 1518 1519 /* 1520 * GLX_ARB_multisample 1521 */ 1522 case GLX_SAMPLE_BUFFERS_ARB: 1523 *value = 0; 1524 return 0; 1525 case GLX_SAMPLES_ARB: 1526 *value = 0; 1527 return 0; 1528 1529 /* 1530 * For FBConfigs: 1531 */ 1532 case GLX_SCREEN_EXT: 1533 if (!fbconfig) 1534 return GLX_BAD_ATTRIBUTE; 1535 *value = xmvis->visinfo->screen; 1536 break; 1537 case GLX_DRAWABLE_TYPE: /*SGIX too */ 1538 if (!fbconfig) 1539 return GLX_BAD_ATTRIBUTE; 1540 *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 1541 break; 1542 case GLX_RENDER_TYPE_SGIX: 1543 if (!fbconfig) 1544 return GLX_BAD_ATTRIBUTE; 1545 if (xmvis->mesa_visual.rgbMode) 1546 *value = GLX_RGBA_BIT; 1547 else 1548 *value = GLX_COLOR_INDEX_BIT; 1549 break; 1550 case GLX_X_RENDERABLE_SGIX: 1551 if (!fbconfig) 1552 return GLX_BAD_ATTRIBUTE; 1553 *value = True; /* XXX really? */ 1554 break; 1555 case GLX_FBCONFIG_ID_SGIX: 1556 if (!fbconfig) 1557 return GLX_BAD_ATTRIBUTE; 1558 *value = xmvis->visinfo->visualid; 1559 break; 1560 case GLX_MAX_PBUFFER_WIDTH: 1561 if (!fbconfig) 1562 return GLX_BAD_ATTRIBUTE; 1563 /* XXX or MAX_WIDTH? */ 1564 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen); 1565 break; 1566 case GLX_MAX_PBUFFER_HEIGHT: 1567 if (!fbconfig) 1568 return GLX_BAD_ATTRIBUTE; 1569 *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen); 1570 break; 1571 case GLX_MAX_PBUFFER_PIXELS: 1572 if (!fbconfig) 1573 return GLX_BAD_ATTRIBUTE; 1574 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) * 1575 DisplayHeight(xmvis->display, xmvis->visinfo->screen); 1576 break; 1577 case GLX_VISUAL_ID: 1578 if (!fbconfig) 1579 return GLX_BAD_ATTRIBUTE; 1580 *value = xmvis->visinfo->visualid; 1581 break; 1582 1583#ifdef GLX_EXT_texture_from_pixmap 1584 case GLX_BIND_TO_TEXTURE_RGB_EXT: 1585 *value = True; /*XXX*/ 1586 break; 1587 case GLX_BIND_TO_TEXTURE_RGBA_EXT: 1588 /* XXX review */ 1589 *value = xmvis->mesa_visual.alphaBits > 0 ? True : False; 1590 break; 1591 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 1592 *value = True; /*XXX*/ 1593 break; 1594 case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 1595 *value = (GLX_TEXTURE_1D_BIT_EXT | 1596 GLX_TEXTURE_2D_BIT_EXT | 1597 GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/ 1598 break; 1599 case GLX_Y_INVERTED_EXT: 1600 *value = True; /*XXX*/ 1601 break; 1602#endif 1603 1604 default: 1605 return GLX_BAD_ATTRIBUTE; 1606 } 1607 return Success; 1608} 1609 1610 1611PUBLIC int 1612glXGetConfig( Display *dpy, XVisualInfo *visinfo, 1613 int attrib, int *value ) 1614{ 1615 XMesaVisual xmvis; 1616 int k; 1617 if (!dpy || !visinfo) 1618 return GLX_BAD_ATTRIBUTE; 1619 1620 xmvis = find_glx_visual( dpy, visinfo ); 1621 if (!xmvis) { 1622 /* this visual wasn't obtained with glXChooseVisual */ 1623 xmvis = create_glx_visual( dpy, visinfo ); 1624 if (!xmvis) { 1625 /* this visual can't be used for GL rendering */ 1626 if (attrib==GLX_USE_GL) { 1627 *value = (int) False; 1628 return 0; 1629 } 1630 else { 1631 return GLX_BAD_VISUAL; 1632 } 1633 } 1634 } 1635 1636 k = get_config(xmvis, attrib, value, GL_FALSE); 1637 return k; 1638} 1639 1640 1641PUBLIC void 1642glXWaitGL( void ) 1643{ 1644 XMesaContext xmesa = XMesaGetCurrentContext(); 1645 XMesaFlush( xmesa ); 1646} 1647 1648 1649 1650PUBLIC void 1651glXWaitX( void ) 1652{ 1653 XMesaContext xmesa = XMesaGetCurrentContext(); 1654 XMesaFlush( xmesa ); 1655} 1656 1657 1658static const char * 1659get_extensions( void ) 1660{ 1661 return EXTENSIONS; 1662} 1663 1664 1665 1666/* GLX 1.1 and later */ 1667PUBLIC const char * 1668glXQueryExtensionsString( Display *dpy, int screen ) 1669{ 1670 (void) dpy; 1671 (void) screen; 1672 return get_extensions(); 1673} 1674 1675 1676 1677/* GLX 1.1 and later */ 1678PUBLIC const char * 1679glXQueryServerString( Display *dpy, int screen, int name ) 1680{ 1681 static char version[1000]; 1682 sprintf(version, "%d.%d %s", 1683 SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name()); 1684 1685 (void) dpy; 1686 (void) screen; 1687 1688 switch (name) { 1689 case GLX_EXTENSIONS: 1690 return get_extensions(); 1691 case GLX_VENDOR: 1692 return VENDOR; 1693 case GLX_VERSION: 1694 return version; 1695 default: 1696 return NULL; 1697 } 1698} 1699 1700 1701 1702/* GLX 1.1 and later */ 1703PUBLIC const char * 1704glXGetClientString( Display *dpy, int name ) 1705{ 1706 static char version[1000]; 1707 sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, 1708 CLIENT_MINOR_VERSION, xmesa_get_name()); 1709 1710 (void) dpy; 1711 1712 switch (name) { 1713 case GLX_EXTENSIONS: 1714 return get_extensions(); 1715 case GLX_VENDOR: 1716 return VENDOR; 1717 case GLX_VERSION: 1718 return version; 1719 default: 1720 return NULL; 1721 } 1722} 1723 1724 1725 1726/* 1727 * GLX 1.3 and later 1728 */ 1729 1730 1731PUBLIC int 1732glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, 1733 int attribute, int *value) 1734{ 1735 XMesaVisual v = (XMesaVisual) config; 1736 (void) dpy; 1737 (void) config; 1738 1739 if (!dpy || !config || !value) 1740 return -1; 1741 1742 return get_config(v, attribute, value, GL_TRUE); 1743} 1744 1745 1746PUBLIC GLXFBConfig * 1747glXGetFBConfigs( Display *dpy, int screen, int *nelements ) 1748{ 1749 XVisualInfo *visuals, visTemplate; 1750 const long visMask = VisualScreenMask; 1751 int i; 1752 1753 /* Get list of all X visuals */ 1754 visTemplate.screen = screen; 1755 visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements); 1756 if (*nelements > 0) { 1757 XMesaVisual *results; 1758 results = (XMesaVisual *) malloc(*nelements * sizeof(XMesaVisual)); 1759 if (!results) { 1760 *nelements = 0; 1761 return NULL; 1762 } 1763 for (i = 0; i < *nelements; i++) { 1764 results[i] = create_glx_visual(dpy, visuals + i); 1765 if (!results[i]) { 1766 *nelements = i; 1767 break; 1768 } 1769 } 1770 return (GLXFBConfig *) results; 1771 } 1772 return NULL; 1773} 1774 1775 1776PUBLIC GLXFBConfig * 1777glXChooseFBConfig(Display *dpy, int screen, 1778 const int *attribList, int *nitems) 1779{ 1780 XMesaVisual xmvis; 1781 1782 if (!attribList || !attribList[0]) { 1783 /* return list of all configs (per GLX_SGIX_fbconfig spec) */ 1784 return glXGetFBConfigs(dpy, screen, nitems); 1785 } 1786 1787 xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); 1788 if (xmvis) { 1789 GLXFBConfig *config = (GLXFBConfig *) malloc(sizeof(XMesaVisual)); 1790 if (!config) { 1791 *nitems = 0; 1792 return NULL; 1793 } 1794 *nitems = 1; 1795 config[0] = (GLXFBConfig) xmvis; 1796 return (GLXFBConfig *) config; 1797 } 1798 else { 1799 *nitems = 0; 1800 return NULL; 1801 } 1802} 1803 1804 1805PUBLIC XVisualInfo * 1806glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) 1807{ 1808 if (dpy && config) { 1809 XMesaVisual xmvis = (XMesaVisual) config; 1810#if 0 1811 return xmvis->vishandle; 1812#else 1813 /* create a new vishandle - the cached one may be stale */ 1814 xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo)); 1815 if (xmvis->vishandle) { 1816 memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); 1817 } 1818 return xmvis->vishandle; 1819#endif 1820 } 1821 else { 1822 return NULL; 1823 } 1824} 1825 1826 1827PUBLIC GLXWindow 1828glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, 1829 const int *attribList) 1830{ 1831 XMesaVisual xmvis = (XMesaVisual) config; 1832 XMesaBuffer xmbuf; 1833 if (!xmvis) 1834 return 0; 1835 1836 xmbuf = XMesaCreateWindowBuffer(xmvis, win); 1837 if (!xmbuf) 1838 return 0; 1839 1840 (void) dpy; 1841 (void) attribList; /* Ignored in GLX 1.3 */ 1842 1843 return win; /* A hack for now */ 1844} 1845 1846 1847PUBLIC void 1848glXDestroyWindow( Display *dpy, GLXWindow window ) 1849{ 1850 XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window); 1851 if (b) 1852 XMesaDestroyBuffer(b); 1853 /* don't destroy X window */ 1854} 1855 1856 1857/* XXX untested */ 1858PUBLIC GLXPixmap 1859glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, 1860 const int *attribList) 1861{ 1862 XMesaVisual v = (XMesaVisual) config; 1863 XMesaBuffer b; 1864 const int *attr; 1865 int target = 0, format = 0, mipmap = 0; 1866 int value; 1867 1868 if (!dpy || !config || !pixmap) 1869 return 0; 1870 1871 for (attr = attribList; attr && *attr; attr++) { 1872 switch (*attr) { 1873 case GLX_TEXTURE_FORMAT_EXT: 1874 attr++; 1875 switch (*attr) { 1876 case GLX_TEXTURE_FORMAT_NONE_EXT: 1877 case GLX_TEXTURE_FORMAT_RGB_EXT: 1878 case GLX_TEXTURE_FORMAT_RGBA_EXT: 1879 format = *attr; 1880 break; 1881 default: 1882 /* error */ 1883 return 0; 1884 } 1885 break; 1886 case GLX_TEXTURE_TARGET_EXT: 1887 attr++; 1888 switch (*attr) { 1889 case GLX_TEXTURE_1D_EXT: 1890 case GLX_TEXTURE_2D_EXT: 1891 case GLX_TEXTURE_RECTANGLE_EXT: 1892 target = *attr; 1893 break; 1894 default: 1895 /* error */ 1896 return 0; 1897 } 1898 break; 1899 case GLX_MIPMAP_TEXTURE_EXT: 1900 attr++; 1901 if (*attr) 1902 mipmap = 1; 1903 break; 1904 default: 1905 /* error */ 1906 return 0; 1907 } 1908 } 1909 1910 if (format == GLX_TEXTURE_FORMAT_RGB_EXT) { 1911 if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT, 1912 &value, GL_TRUE) != Success 1913 || !value) { 1914 return 0; /* error! */ 1915 } 1916 } 1917 else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) { 1918 if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT, 1919 &value, GL_TRUE) != Success 1920 || !value) { 1921 return 0; /* error! */ 1922 } 1923 } 1924 if (mipmap) { 1925 if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT, 1926 &value, GL_TRUE) != Success 1927 || !value) { 1928 return 0; /* error! */ 1929 } 1930 } 1931 if (target == GLX_TEXTURE_1D_EXT) { 1932 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1933 &value, GL_TRUE) != Success 1934 || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) { 1935 return 0; /* error! */ 1936 } 1937 } 1938 else if (target == GLX_TEXTURE_2D_EXT) { 1939 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1940 &value, GL_TRUE) != Success 1941 || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) { 1942 return 0; /* error! */ 1943 } 1944 } 1945 if (target == GLX_TEXTURE_RECTANGLE_EXT) { 1946 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1947 &value, GL_TRUE) != Success 1948 || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) { 1949 return 0; /* error! */ 1950 } 1951 } 1952 1953 if (format || target || mipmap) { 1954 /* texture from pixmap */ 1955 b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap); 1956 } 1957 else { 1958 b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); 1959 } 1960 if (!b) { 1961 return 0; 1962 } 1963 1964 return pixmap; 1965} 1966 1967 1968PUBLIC void 1969glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) 1970{ 1971 XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap); 1972 if (b) 1973 XMesaDestroyBuffer(b); 1974 /* don't destroy X pixmap */ 1975} 1976 1977 1978PUBLIC GLXPbuffer 1979glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList) 1980{ 1981 XMesaVisual xmvis = (XMesaVisual) config; 1982 XMesaBuffer xmbuf; 1983 const int *attrib; 1984 int width = 0, height = 0; 1985 GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; 1986 1987 (void) dpy; 1988 1989 for (attrib = attribList; *attrib; attrib++) { 1990 switch (*attrib) { 1991 case GLX_PBUFFER_WIDTH: 1992 attrib++; 1993 width = *attrib; 1994 break; 1995 case GLX_PBUFFER_HEIGHT: 1996 attrib++; 1997 height = *attrib; 1998 break; 1999 case GLX_PRESERVED_CONTENTS: 2000 attrib++; 2001 preserveContents = *attrib; 2002 break; 2003 case GLX_LARGEST_PBUFFER: 2004 attrib++; 2005 useLargest = *attrib; 2006 break; 2007 default: 2008 return 0; 2009 } 2010 } 2011 2012 if (width == 0 || height == 0) 2013 return 0; 2014 2015 if (width > MAX_WIDTH || height > MAX_HEIGHT) { 2016 /* If allocation would have failed and GLX_LARGEST_PBUFFER is set, 2017 * allocate the largest possible buffer. 2018 */ 2019 if (useLargest) { 2020 width = MAX_WIDTH; 2021 height = MAX_HEIGHT; 2022 } 2023 } 2024 2025 xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); 2026 /* A GLXPbuffer handle must be an X Drawable because that's what 2027 * glXMakeCurrent takes. 2028 */ 2029 if (xmbuf) { 2030 xmbuf->largestPbuffer = useLargest; 2031 xmbuf->preservedContents = preserveContents; 2032 return (GLXPbuffer) xmbuf->drawable; 2033 } 2034 else { 2035 return 0; 2036 } 2037} 2038 2039 2040PUBLIC void 2041glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) 2042{ 2043 XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); 2044 if (b) { 2045 XMesaDestroyBuffer(b); 2046 } 2047} 2048 2049 2050PUBLIC void 2051glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, 2052 unsigned int *value) 2053{ 2054 GLuint width, height; 2055 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); 2056 if (!xmbuf) 2057 return; 2058 2059 /* make sure buffer's dimensions are up to date */ 2060 xmesa_get_window_size(dpy, xmbuf, &width, &height); 2061 2062 switch (attribute) { 2063 case GLX_WIDTH: 2064 *value = width; 2065 break; 2066 case GLX_HEIGHT: 2067 *value = height; 2068 break; 2069 case GLX_PRESERVED_CONTENTS: 2070 *value = xmbuf->preservedContents; 2071 break; 2072 case GLX_LARGEST_PBUFFER: 2073 *value = xmbuf->largestPbuffer; 2074 break; 2075 case GLX_FBCONFIG_ID: 2076 *value = xmbuf->xm_visual->visinfo->visualid; 2077 return; 2078#ifdef GLX_EXT_texture_from_pixmap 2079 case GLX_TEXTURE_FORMAT_EXT: 2080 *value = xmbuf->TextureFormat; 2081 break; 2082 case GLX_TEXTURE_TARGET_EXT: 2083 *value = xmbuf->TextureTarget; 2084 break; 2085 case GLX_MIPMAP_TEXTURE_EXT: 2086 *value = xmbuf->TextureMipmap; 2087 break; 2088#endif 2089 2090 default: 2091 return; /* raise BadValue error */ 2092 } 2093} 2094 2095 2096PUBLIC GLXContext 2097glXCreateNewContext( Display *dpy, GLXFBConfig config, 2098 int renderType, GLXContext shareCtx, Bool direct ) 2099{ 2100 XMesaVisual xmvis = (XMesaVisual) config; 2101 2102 if (!dpy || !config || 2103 (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) 2104 return 0; 2105 2106 return create_context(dpy, xmvis, 2107 shareCtx ? shareCtx->xmesaContext : NULL, 2108 direct); 2109} 2110 2111 2112PUBLIC int 2113glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) 2114{ 2115 GLXContext glxCtx = ctx; 2116 XMesaContext xmctx = glxCtx->xmesaContext; 2117 2118 (void) dpy; 2119 (void) ctx; 2120 2121 switch (attribute) { 2122 case GLX_FBCONFIG_ID: 2123 *value = xmctx->xm_visual->visinfo->visualid; 2124 break; 2125 case GLX_RENDER_TYPE: 2126 if (xmctx->xm_visual->mesa_visual.rgbMode) 2127 *value = GLX_RGBA_TYPE; 2128 else 2129 *value = GLX_COLOR_INDEX_TYPE; 2130 break; 2131 case GLX_SCREEN: 2132 *value = 0; 2133 return Success; 2134 default: 2135 return GLX_BAD_ATTRIBUTE; 2136 } 2137 return 0; 2138} 2139 2140 2141PUBLIC void 2142glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) 2143{ 2144 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2145 if (xmbuf) 2146 xmbuf->selectedEvents = mask; 2147} 2148 2149 2150PUBLIC void 2151glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask) 2152{ 2153 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2154 if (xmbuf) 2155 *mask = xmbuf->selectedEvents; 2156 else 2157 *mask = 0; 2158} 2159 2160 2161 2162/*** GLX_SGI_swap_control ***/ 2163 2164PUBLIC int 2165glXSwapIntervalSGI(int interval) 2166{ 2167 (void) interval; 2168 return 0; 2169} 2170 2171 2172 2173/*** GLX_SGI_video_sync ***/ 2174 2175static unsigned int FrameCounter = 0; 2176 2177PUBLIC int 2178glXGetVideoSyncSGI(unsigned int *count) 2179{ 2180 /* this is a bogus implementation */ 2181 *count = FrameCounter++; 2182 return 0; 2183} 2184 2185PUBLIC int 2186glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 2187{ 2188 if (divisor <= 0 || remainder < 0) 2189 return GLX_BAD_VALUE; 2190 /* this is a bogus implementation */ 2191 FrameCounter++; 2192 while (FrameCounter % divisor != remainder) 2193 FrameCounter++; 2194 *count = FrameCounter; 2195 return 0; 2196} 2197 2198 2199 2200/*** GLX_SGI_make_current_read ***/ 2201 2202PUBLIC Bool 2203glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, 2204 GLXContext ctx) 2205{ 2206 return glXMakeContextCurrent( dpy, draw, read, ctx ); 2207} 2208 2209/* not used 2210static GLXDrawable 2211glXGetCurrentReadDrawableSGI(void) 2212{ 2213 return 0; 2214} 2215*/ 2216 2217 2218/*** GLX_SGIX_video_source ***/ 2219#if defined(_VL_H) 2220 2221PUBLIC GLXVideoSourceSGIX 2222glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, 2223 VLPath path, int nodeClass, VLNode drainNode) 2224{ 2225 (void) dpy; 2226 (void) screen; 2227 (void) server; 2228 (void) path; 2229 (void) nodeClass; 2230 (void) drainNode; 2231 return 0; 2232} 2233 2234PUBLIC void 2235glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) 2236{ 2237 (void) dpy; 2238 (void) src; 2239} 2240 2241#endif 2242 2243 2244/*** GLX_EXT_import_context ***/ 2245 2246PUBLIC void 2247glXFreeContextEXT(Display *dpy, GLXContext context) 2248{ 2249 (void) dpy; 2250 (void) context; 2251} 2252 2253PUBLIC GLXContextID 2254glXGetContextIDEXT(const GLXContext context) 2255{ 2256 (void) context; 2257 return 0; 2258} 2259 2260PUBLIC GLXContext 2261glXImportContextEXT(Display *dpy, GLXContextID contextID) 2262{ 2263 (void) dpy; 2264 (void) contextID; 2265 return 0; 2266} 2267 2268PUBLIC int 2269glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, 2270 int *value) 2271{ 2272 (void) dpy; 2273 (void) context; 2274 (void) attribute; 2275 (void) value; 2276 return 0; 2277} 2278 2279 2280 2281/*** GLX_SGIX_fbconfig ***/ 2282 2283PUBLIC int 2284glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, 2285 int attribute, int *value) 2286{ 2287 return glXGetFBConfigAttrib(dpy, config, attribute, value); 2288} 2289 2290PUBLIC GLXFBConfigSGIX * 2291glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, 2292 int *nelements) 2293{ 2294 return (GLXFBConfig *) glXChooseFBConfig(dpy, screen, 2295 attrib_list, nelements); 2296} 2297 2298 2299PUBLIC GLXPixmap 2300glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, 2301 Pixmap pixmap) 2302{ 2303 XMesaVisual xmvis = (XMesaVisual) config; 2304 XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); 2305 return xmbuf->drawable; /* need to return an X ID */ 2306} 2307 2308 2309PUBLIC GLXContext 2310glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, 2311 int renderType, GLXContext shareCtx, 2312 Bool direct) 2313{ 2314 XMesaVisual xmvis = (XMesaVisual) config; 2315 2316 if (!dpy || !config || 2317 (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) 2318 return 0; 2319 2320 return create_context(dpy, xmvis, 2321 shareCtx ? shareCtx->xmesaContext : NULL, 2322 direct); 2323} 2324 2325 2326PUBLIC XVisualInfo * 2327glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) 2328{ 2329 return glXGetVisualFromFBConfig(dpy, config); 2330} 2331 2332 2333PUBLIC GLXFBConfigSGIX 2334glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) 2335{ 2336 XMesaVisual xmvis = find_glx_visual(dpy, vis); 2337 if (!xmvis) { 2338 /* This visual wasn't found with glXChooseVisual() */ 2339 xmvis = create_glx_visual(dpy, vis); 2340 } 2341 2342 return (GLXFBConfigSGIX) xmvis; 2343} 2344 2345 2346 2347/*** GLX_SGIX_pbuffer ***/ 2348 2349PUBLIC GLXPbufferSGIX 2350glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, 2351 unsigned int width, unsigned int height, 2352 int *attribList) 2353{ 2354 XMesaVisual xmvis = (XMesaVisual) config; 2355 XMesaBuffer xmbuf; 2356 const int *attrib; 2357 GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; 2358 2359 (void) dpy; 2360 2361 for (attrib = attribList; attrib && *attrib; attrib++) { 2362 switch (*attrib) { 2363 case GLX_PRESERVED_CONTENTS_SGIX: 2364 attrib++; 2365 preserveContents = *attrib; /* ignored */ 2366 break; 2367 case GLX_LARGEST_PBUFFER_SGIX: 2368 attrib++; 2369 useLargest = *attrib; /* ignored */ 2370 break; 2371 default: 2372 return 0; 2373 } 2374 } 2375 2376 /* not used at this time */ 2377 (void) useLargest; 2378 (void) preserveContents; 2379 2380 xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); 2381 /* A GLXPbuffer handle must be an X Drawable because that's what 2382 * glXMakeCurrent takes. 2383 */ 2384 return (GLXPbuffer) xmbuf->drawable; 2385} 2386 2387 2388PUBLIC void 2389glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) 2390{ 2391 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); 2392 if (xmbuf) { 2393 XMesaDestroyBuffer(xmbuf); 2394 } 2395} 2396 2397 2398PUBLIC int 2399glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, 2400 unsigned int *value) 2401{ 2402 const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); 2403 2404 if (!xmbuf) { 2405 /* Generate GLXBadPbufferSGIX for bad pbuffer */ 2406 return 0; 2407 } 2408 2409 switch (attribute) { 2410 case GLX_PRESERVED_CONTENTS_SGIX: 2411 *value = True; 2412 break; 2413 case GLX_LARGEST_PBUFFER_SGIX: 2414 *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf); 2415 break; 2416 case GLX_WIDTH_SGIX: 2417 *value = xmesa_buffer_width(xmbuf); 2418 break; 2419 case GLX_HEIGHT_SGIX: 2420 *value = xmesa_buffer_height(xmbuf); 2421 break; 2422 case GLX_EVENT_MASK_SGIX: 2423 *value = 0; /* XXX might be wrong */ 2424 break; 2425 default: 2426 *value = 0; 2427 } 2428 return 0; 2429} 2430 2431 2432PUBLIC void 2433glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) 2434{ 2435 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2436 if (xmbuf) { 2437 /* Note: we'll never generate clobber events */ 2438 xmbuf->selectedEvents = mask; 2439 } 2440} 2441 2442 2443PUBLIC void 2444glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, 2445 unsigned long *mask) 2446{ 2447 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2448 if (xmbuf) { 2449 *mask = xmbuf->selectedEvents; 2450 } 2451 else { 2452 *mask = 0; 2453 } 2454} 2455 2456 2457 2458/*** GLX_SGI_cushion ***/ 2459 2460PUBLIC void 2461glXCushionSGI(Display *dpy, Window win, float cushion) 2462{ 2463 (void) dpy; 2464 (void) win; 2465 (void) cushion; 2466} 2467 2468 2469 2470/*** GLX_SGIX_video_resize ***/ 2471 2472PUBLIC int 2473glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel, 2474 Window window) 2475{ 2476 (void) dpy; 2477 (void) screen; 2478 (void) channel; 2479 (void) window; 2480 return 0; 2481} 2482 2483PUBLIC int 2484glXChannelRectSGIX(Display *dpy, int screen, int channel, 2485 int x, int y, int w, int h) 2486{ 2487 (void) dpy; 2488 (void) screen; 2489 (void) channel; 2490 (void) x; 2491 (void) y; 2492 (void) w; 2493 (void) h; 2494 return 0; 2495} 2496 2497PUBLIC int 2498glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, 2499 int *x, int *y, int *w, int *h) 2500{ 2501 (void) dpy; 2502 (void) screen; 2503 (void) channel; 2504 (void) x; 2505 (void) y; 2506 (void) w; 2507 (void) h; 2508 return 0; 2509} 2510 2511PUBLIC int 2512glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, 2513 int *dx, int *dy, int *dw, int *dh) 2514{ 2515 (void) dpy; 2516 (void) screen; 2517 (void) channel; 2518 (void) dx; 2519 (void) dy; 2520 (void) dw; 2521 (void) dh; 2522 return 0; 2523} 2524 2525PUBLIC int 2526glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) 2527{ 2528 (void) dpy; 2529 (void) screen; 2530 (void) channel; 2531 (void) synctype; 2532 return 0; 2533} 2534 2535 2536 2537/*** GLX_SGIX_dmbuffer **/ 2538 2539#if defined(_DM_BUFFER_H_) 2540PUBLIC Bool 2541glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, 2542 DMparams *params, DMbuffer dmbuffer) 2543{ 2544 (void) dpy; 2545 (void) pbuffer; 2546 (void) params; 2547 (void) dmbuffer; 2548 return False; 2549} 2550#endif 2551 2552 2553/*** GLX_SGIX_swap_group ***/ 2554 2555PUBLIC void 2556glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) 2557{ 2558 (void) dpy; 2559 (void) drawable; 2560 (void) member; 2561} 2562 2563 2564 2565/*** GLX_SGIX_swap_barrier ***/ 2566 2567PUBLIC void 2568glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) 2569{ 2570 (void) dpy; 2571 (void) drawable; 2572 (void) barrier; 2573} 2574 2575PUBLIC Bool 2576glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) 2577{ 2578 (void) dpy; 2579 (void) screen; 2580 (void) max; 2581 return False; 2582} 2583 2584 2585 2586/*** GLX_SUN_get_transparent_index ***/ 2587 2588PUBLIC Status 2589glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, 2590 long *pTransparent) 2591{ 2592 (void) dpy; 2593 (void) overlay; 2594 (void) underlay; 2595 (void) pTransparent; 2596 return 0; 2597} 2598 2599 2600 2601/*** GLX_MESA_release_buffers ***/ 2602 2603/* 2604 * Release the depth, stencil, accum buffers attached to a GLXDrawable 2605 * (a window or pixmap) prior to destroying the GLXDrawable. 2606 */ 2607PUBLIC Bool 2608glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) 2609{ 2610 XMesaBuffer b = XMesaFindBuffer(dpy, d); 2611 if (b) { 2612 XMesaDestroyBuffer(b); 2613 return True; 2614 } 2615 return False; 2616} 2617 2618/*** GLX_EXT_texture_from_pixmap ***/ 2619 2620PUBLIC void 2621glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, 2622 const int *attrib_list) 2623{ 2624 XMesaBuffer b = XMesaFindBuffer(dpy, drawable); 2625 if (b) 2626 XMesaBindTexImage(dpy, b, buffer, attrib_list); 2627} 2628 2629PUBLIC void 2630glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) 2631{ 2632 XMesaBuffer b = XMesaFindBuffer(dpy, drawable); 2633 if (b) 2634 XMesaReleaseTexImage(dpy, b, buffer); 2635} 2636