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