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