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