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