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