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