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