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