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