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