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