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