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 (at) bolthole.com) 34 * Better glXGetConfig() support: Armin Liebchen (liebchen (at) asylum.cs.utah.edu) 35 * Further visual-handling refinements: Wolfram Gloger 36 * (wmglo (at) 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 */ 98 struct 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 112 static XMesaVisual *VisualTable = NULL; 113 static int NumVisuals = 0; 114 115 116 /* 117 * This struct and some code fragments borrowed 118 * from Mark Kilgard's GLUT library. 119 */ 120 typedef 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 */ 145 static GLboolean 146 is_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 */ 176 static OverlayInfo * 177 GetOverlayInfo(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 */ 224 static int 225 level_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 */ 264 static XMesaVisual 265 save_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 */ 369 static GLint 370 default_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 381 static GLint 382 default_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 393 static GLint 394 default_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 */ 409 static XMesaVisual 410 create_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 8, /* 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 */ 451 static XMesaVisual 452 find_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 */ 481 static int 482 transparent_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 */ 521 static XVisualInfo * 522 get_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 */ 575 static XVisualInfo * 576 get_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 */ 618 static XVisualInfo * 619 choose_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 */ 708 static XVisualInfo * 709 choose_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 */ 810 static void 811 destroy_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 */ 830 static int 831 close_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 */ 843 static _XExtension * 844 lookup_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 */ 860 static void 861 register_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 */ 889 static XMesaVisual 890 choose_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 if (fbConfig && 921 parselist[1] == GLX_DONT_CARE && 922 parselist[0] != GLX_LEVEL) { 923 /* For glXChooseFBConfig(), skip attributes whose value is 924 * GLX_DONT_CARE (-1), unless it's GLX_LEVEL (which can legitimately be 925 * a negative value). 926 * 927 * From page 17 (23 of the pdf) of the GLX 1.4 spec: 928 * GLX DONT CARE may be specified for all attributes except GLX LEVEL. 929 */ 930 parselist += 2; 931 continue; 932 } 933 934 switch (*parselist) { 935 case GLX_USE_GL: 936 if (fbConfig) { 937 /* invalid token */ 938 return NULL; 939 } 940 else { 941 /* skip */ 942 parselist++; 943 } 944 break; 945 case GLX_BUFFER_SIZE: 946 parselist++; 947 min_ci = *parselist++; 948 break; 949 case GLX_LEVEL: 950 parselist++; 951 level = *parselist++; 952 break; 953 case GLX_RGBA: 954 if (fbConfig) { 955 /* invalid token */ 956 return NULL; 957 } 958 else { 959 rgb_flag = GL_TRUE; 960 parselist++; 961 } 962 break; 963 case GLX_DOUBLEBUFFER: 964 parselist++; 965 if (fbConfig) { 966 double_flag = *parselist++; 967 } 968 else { 969 double_flag = GL_TRUE; 970 } 971 break; 972 case GLX_STEREO: 973 parselist++; 974 if (fbConfig) { 975 stereo_flag = *parselist++; 976 } 977 else { 978 stereo_flag = GL_TRUE; 979 } 980 break; 981 case GLX_AUX_BUFFERS: 982 parselist++; 983 numAux = *parselist++; 984 if (numAux > MAX_AUX_BUFFERS) 985 return NULL; 986 break; 987 case GLX_RED_SIZE: 988 parselist++; 989 min_red = *parselist++; 990 break; 991 case GLX_GREEN_SIZE: 992 parselist++; 993 min_green = *parselist++; 994 break; 995 case GLX_BLUE_SIZE: 996 parselist++; 997 min_blue = *parselist++; 998 break; 999 case GLX_ALPHA_SIZE: 1000 parselist++; 1001 { 1002 GLint size = *parselist++; 1003 alpha_flag = size ? GL_TRUE : GL_FALSE; 1004 } 1005 break; 1006 case GLX_DEPTH_SIZE: 1007 parselist++; 1008 depth_size = *parselist++; 1009 break; 1010 case GLX_STENCIL_SIZE: 1011 parselist++; 1012 stencil_size = *parselist++; 1013 break; 1014 case GLX_ACCUM_RED_SIZE: 1015 parselist++; 1016 { 1017 GLint size = *parselist++; 1018 accumRedSize = MAX2( accumRedSize, size ); 1019 } 1020 break; 1021 case GLX_ACCUM_GREEN_SIZE: 1022 parselist++; 1023 { 1024 GLint size = *parselist++; 1025 accumGreenSize = MAX2( accumGreenSize, size ); 1026 } 1027 break; 1028 case GLX_ACCUM_BLUE_SIZE: 1029 parselist++; 1030 { 1031 GLint size = *parselist++; 1032 accumBlueSize = MAX2( accumBlueSize, size ); 1033 } 1034 break; 1035 case GLX_ACCUM_ALPHA_SIZE: 1036 parselist++; 1037 { 1038 GLint size = *parselist++; 1039 accumAlphaSize = MAX2( accumAlphaSize, size ); 1040 } 1041 break; 1042 1043 /* 1044 * GLX_EXT_visual_info extension 1045 */ 1046 case GLX_X_VISUAL_TYPE_EXT: 1047 parselist++; 1048 visual_type = *parselist++; 1049 break; 1050 case GLX_TRANSPARENT_TYPE_EXT: 1051 parselist++; 1052 trans_type = *parselist++; 1053 break; 1054 case GLX_TRANSPARENT_INDEX_VALUE_EXT: 1055 parselist++; 1056 trans_value = *parselist++; 1057 break; 1058 case GLX_TRANSPARENT_RED_VALUE_EXT: 1059 case GLX_TRANSPARENT_GREEN_VALUE_EXT: 1060 case GLX_TRANSPARENT_BLUE_VALUE_EXT: 1061 case GLX_TRANSPARENT_ALPHA_VALUE_EXT: 1062 /* ignore */ 1063 parselist++; 1064 parselist++; 1065 break; 1066 1067 /* 1068 * GLX_EXT_visual_info extension 1069 */ 1070 case GLX_VISUAL_CAVEAT_EXT: 1071 parselist++; 1072 caveat = *parselist++; /* ignored for now */ 1073 break; 1074 1075 /* 1076 * GLX_ARB_multisample 1077 */ 1078 case GLX_SAMPLE_BUFFERS_ARB: 1079 case GLX_SAMPLES_ARB: 1080 parselist++; 1081 if (*parselist++ != 0) 1082 /* ms not supported */ 1083 return NULL; 1084 break; 1085 1086 /* 1087 * FBConfig attribs. 1088 */ 1089 case GLX_RENDER_TYPE: 1090 if (!fbConfig) 1091 return NULL; 1092 parselist++; 1093 if (*parselist & GLX_RGBA_BIT) { 1094 rgb_flag = GL_TRUE; 1095 } 1096 else if (*parselist & GLX_COLOR_INDEX_BIT) { 1097 rgb_flag = GL_FALSE; 1098 } 1099 else if (*parselist == 0) { 1100 rgb_flag = GL_TRUE; 1101 } 1102 parselist++; 1103 break; 1104 case GLX_DRAWABLE_TYPE: 1105 if (!fbConfig) 1106 return NULL; 1107 parselist++; 1108 if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) { 1109 return NULL; /* bad bit */ 1110 } 1111 parselist++; 1112 break; 1113 case GLX_FBCONFIG_ID: 1114 case GLX_VISUAL_ID: 1115 if (!fbConfig) 1116 return NULL; 1117 parselist++; 1118 desiredVisualID = *parselist++; 1119 break; 1120 case GLX_X_RENDERABLE: 1121 case GLX_MAX_PBUFFER_WIDTH: 1122 case GLX_MAX_PBUFFER_HEIGHT: 1123 case GLX_MAX_PBUFFER_PIXELS: 1124 if (!fbConfig) 1125 return NULL; 1126 parselist += 2; 1127 /* ignore */ 1128 break; 1129 1130 #ifdef GLX_EXT_texture_from_pixmap 1131 case GLX_BIND_TO_TEXTURE_RGB_EXT: 1132 parselist++; /*skip*/ 1133 break; 1134 case GLX_BIND_TO_TEXTURE_RGBA_EXT: 1135 parselist++; /*skip*/ 1136 break; 1137 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 1138 parselist++; /*skip*/ 1139 break; 1140 case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 1141 parselist++; 1142 if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT | 1143 GLX_TEXTURE_2D_BIT_EXT | 1144 GLX_TEXTURE_RECTANGLE_BIT_EXT)) { 1145 /* invalid bit */ 1146 return NULL; 1147 } 1148 break; 1149 case GLX_Y_INVERTED_EXT: 1150 parselist++; /*skip*/ 1151 break; 1152 #endif 1153 1154 case None: 1155 /* end of list */ 1156 break; 1157 1158 default: 1159 /* undefined attribute */ 1160 _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()", 1161 *parselist); 1162 return NULL; 1163 } 1164 } 1165 1166 if (!rgb_flag) 1167 return NULL; 1168 1169 (void) caveat; 1170 (void) min_ci; 1171 1172 /* 1173 * Since we're only simulating the GLX extension this function will never 1174 * find any real GL visuals. Instead, all we can do is try to find an RGB 1175 * or CI visual of appropriate depth. Other requested attributes such as 1176 * double buffering, depth buffer, etc. will be associated with the X 1177 * visual and stored in the VisualTable[]. 1178 */ 1179 if (desiredVisualID != -1) { 1180 /* try to get a specific visual, by visualID */ 1181 XVisualInfo temp; 1182 int n; 1183 temp.visualid = desiredVisualID; 1184 temp.screen = screen; 1185 vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n); 1186 if (vis) { 1187 /* give the visual some useful GLX attributes */ 1188 double_flag = GL_TRUE; 1189 if (vis->depth <= 8) 1190 return NULL; 1191 depth_size = default_depth_bits(); 1192 stencil_size = 8; 1193 /* XXX accum??? */ 1194 } 1195 } 1196 else { 1197 /* RGB visual */ 1198 int min_rgb = min_red + min_green + min_blue; 1199 if (min_rgb>1 && min_rgb<8) { 1200 /* a special case to be sure we can get a monochrome visual */ 1201 min_rgb = 1; 1202 } 1203 1204 if (level==0) { 1205 vis = choose_x_visual(dpy, screen, min_rgb, visual_type); 1206 } 1207 else { 1208 vis = choose_x_overlay_visual(dpy, screen, level, 1209 trans_type, trans_value, min_rgb, visual_type); 1210 } 1211 } 1212 1213 if (vis) { 1214 /* Note: we're not exactly obeying the glXChooseVisual rules here. 1215 * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the 1216 * largest depth buffer size, which is 32bits/value. Instead, we 1217 * return 16 to maintain performance with earlier versions of Mesa. 1218 */ 1219 if (depth_size > 24) 1220 depth_size = 32; 1221 else if (depth_size > 16) 1222 depth_size = 24; 1223 else if (depth_size > 0) { 1224 depth_size = default_depth_bits(); 1225 } 1226 1227 if (!alpha_flag) { 1228 alpha_flag = default_alpha_bits() > 0; 1229 } 1230 1231 /* we only support one size of stencil and accum buffers. */ 1232 if (stencil_size > 0) 1233 stencil_size = 8; 1234 if (accumRedSize > 0 || accumGreenSize > 0 || accumBlueSize > 0 || 1235 accumAlphaSize > 0) { 1236 accumRedSize = 1237 accumGreenSize = 1238 accumBlueSize = default_accum_bits(); 1239 accumAlphaSize = alpha_flag ? accumRedSize : 0; 1240 } 1241 1242 xmvis = save_glx_visual( dpy, vis, alpha_flag, double_flag, 1243 stereo_flag, depth_size, stencil_size, 1244 accumRedSize, accumGreenSize, 1245 accumBlueSize, accumAlphaSize, level, numAux ); 1246 } 1247 1248 return xmvis; 1249 } 1250 1251 1252 static XVisualInfo * 1253 Fake_glXChooseVisual( Display *dpy, int screen, int *list ) 1254 { 1255 XMesaVisual xmvis; 1256 1257 /* register ourselves as an extension on this display */ 1258 register_with_display(dpy); 1259 1260 xmvis = choose_visual(dpy, screen, list, GL_FALSE); 1261 if (xmvis) { 1262 #if 0 1263 return xmvis->vishandle; 1264 #else 1265 /* create a new vishandle - the cached one may be stale */ 1266 xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo)); 1267 if (xmvis->vishandle) { 1268 memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); 1269 } 1270 return xmvis->vishandle; 1271 #endif 1272 } 1273 else 1274 return NULL; 1275 } 1276 1277 1278 /** 1279 * Init basic fields of a new fake_glx_context. 1280 */ 1281 static void 1282 init_glx_context(struct fake_glx_context *glxCtx, Display *dpy) 1283 { 1284 /* Always return True. See if anyone's confused... */ 1285 GLboolean direct = GL_TRUE; 1286 1287 glxCtx->xmesaContext->direct = direct; 1288 glxCtx->glxContext.isDirect = direct; 1289 glxCtx->glxContext.currentDpy = dpy; 1290 glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ 1291 1292 assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); 1293 } 1294 1295 1296 1297 static GLXContext 1298 Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, 1299 GLXContext share_list, Bool direct ) 1300 { 1301 XMesaVisual xmvis; 1302 struct fake_glx_context *glxCtx; 1303 struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list; 1304 1305 if (!dpy || !visinfo) 1306 return 0; 1307 1308 glxCtx = CALLOC_STRUCT(fake_glx_context); 1309 if (!glxCtx) 1310 return 0; 1311 1312 /* deallocate unused windows/buffers */ 1313 #if 0 1314 XMesaGarbageCollect(dpy); 1315 #endif 1316 1317 xmvis = find_glx_visual( dpy, visinfo ); 1318 if (!xmvis) { 1319 /* This visual wasn't found with glXChooseVisual() */ 1320 xmvis = create_glx_visual( dpy, visinfo ); 1321 if (!xmvis) { 1322 /* unusable visual */ 1323 free(glxCtx); 1324 return NULL; 1325 } 1326 } 1327 1328 glxCtx->xmesaContext = XMesaCreateContext(xmvis, 1329 shareCtx ? shareCtx->xmesaContext : NULL); 1330 if (!glxCtx->xmesaContext) { 1331 free(glxCtx); 1332 return NULL; 1333 } 1334 1335 init_glx_context(glxCtx, dpy); 1336 1337 return (GLXContext) glxCtx; 1338 } 1339 1340 1341 /* XXX these may have to be removed due to thread-safety issues. */ 1342 static GLXContext MakeCurrent_PrevContext = 0; 1343 static GLXDrawable MakeCurrent_PrevDrawable = 0; 1344 static GLXDrawable MakeCurrent_PrevReadable = 0; 1345 static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0; 1346 static XMesaBuffer MakeCurrent_PrevReadBuffer = 0; 1347 1348 1349 /* GLX 1.3 and later */ 1350 static Bool 1351 Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, 1352 GLXDrawable read, GLXContext ctx ) 1353 { 1354 struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; 1355 1356 if (ctx && draw && read) { 1357 XMesaBuffer drawBuffer, readBuffer; 1358 XMesaContext xmctx = glxCtx->xmesaContext; 1359 1360 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */ 1361 if (ctx == MakeCurrent_PrevContext 1362 && draw == MakeCurrent_PrevDrawable) { 1363 drawBuffer = MakeCurrent_PrevDrawBuffer; 1364 } 1365 else { 1366 drawBuffer = XMesaFindBuffer( dpy, draw ); 1367 } 1368 if (!drawBuffer) { 1369 /* drawable must be a new window! */ 1370 drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw ); 1371 if (!drawBuffer) { 1372 /* Out of memory, or context/drawable depth mismatch */ 1373 return False; 1374 } 1375 } 1376 1377 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */ 1378 if (ctx == MakeCurrent_PrevContext 1379 && read == MakeCurrent_PrevReadable) { 1380 readBuffer = MakeCurrent_PrevReadBuffer; 1381 } 1382 else { 1383 readBuffer = XMesaFindBuffer( dpy, read ); 1384 } 1385 if (!readBuffer) { 1386 /* drawable must be a new window! */ 1387 readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read ); 1388 if (!readBuffer) { 1389 /* Out of memory, or context/drawable depth mismatch */ 1390 return False; 1391 } 1392 } 1393 1394 MakeCurrent_PrevContext = ctx; 1395 MakeCurrent_PrevDrawable = draw; 1396 MakeCurrent_PrevReadable = read; 1397 MakeCurrent_PrevDrawBuffer = drawBuffer; 1398 MakeCurrent_PrevReadBuffer = readBuffer; 1399 1400 /* Now make current! */ 1401 if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { 1402 ((__GLXcontext *) ctx)->currentDpy = dpy; 1403 ((__GLXcontext *) ctx)->currentDrawable = draw; 1404 ((__GLXcontext *) ctx)->currentReadable = read; 1405 return True; 1406 } 1407 else { 1408 return False; 1409 } 1410 } 1411 else if (!ctx && !draw && !read) { 1412 /* release current context w/out assigning new one. */ 1413 XMesaMakeCurrent( NULL, NULL ); 1414 MakeCurrent_PrevContext = 0; 1415 MakeCurrent_PrevDrawable = 0; 1416 MakeCurrent_PrevReadable = 0; 1417 MakeCurrent_PrevDrawBuffer = 0; 1418 MakeCurrent_PrevReadBuffer = 0; 1419 return True; 1420 } 1421 else { 1422 /* The args must either all be non-zero or all zero. 1423 * This is an error. 1424 */ 1425 return False; 1426 } 1427 } 1428 1429 1430 static Bool 1431 Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) 1432 { 1433 return Fake_glXMakeContextCurrent( dpy, drawable, drawable, ctx ); 1434 } 1435 1436 1437 static GLXPixmap 1438 Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) 1439 { 1440 XMesaVisual v; 1441 XMesaBuffer b; 1442 1443 v = find_glx_visual( dpy, visinfo ); 1444 if (!v) { 1445 v = create_glx_visual( dpy, visinfo ); 1446 if (!v) { 1447 /* unusable visual */ 1448 return 0; 1449 } 1450 } 1451 1452 b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); 1453 if (!b) { 1454 return 0; 1455 } 1456 return b->frontxrb->pixmap; 1457 } 1458 1459 1460 /*** GLX_MESA_pixmap_colormap ***/ 1461 1462 static GLXPixmap 1463 Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, 1464 Pixmap pixmap, Colormap cmap ) 1465 { 1466 XMesaVisual v; 1467 XMesaBuffer b; 1468 1469 v = find_glx_visual( dpy, visinfo ); 1470 if (!v) { 1471 v = create_glx_visual( dpy, visinfo ); 1472 if (!v) { 1473 /* unusable visual */ 1474 return 0; 1475 } 1476 } 1477 1478 b = XMesaCreatePixmapBuffer( v, pixmap, cmap ); 1479 if (!b) { 1480 return 0; 1481 } 1482 return b->frontxrb->pixmap; 1483 } 1484 1485 1486 static void 1487 Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) 1488 { 1489 XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); 1490 if (b) { 1491 XMesaDestroyBuffer(b); 1492 } 1493 else if (_mesa_getenv("MESA_DEBUG")) { 1494 _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); 1495 } 1496 } 1497 1498 1499 static void 1500 Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, 1501 unsigned long mask ) 1502 { 1503 struct fake_glx_context *fakeSrc = (struct fake_glx_context *) src; 1504 struct fake_glx_context *fakeDst = (struct fake_glx_context *) dst; 1505 XMesaContext xm_src = fakeSrc->xmesaContext; 1506 XMesaContext xm_dst = fakeDst->xmesaContext; 1507 (void) dpy; 1508 if (MakeCurrent_PrevContext == src) { 1509 _mesa_Flush(); 1510 } 1511 _mesa_copy_context( &(xm_src->mesa), &(xm_dst->mesa), (GLuint) mask ); 1512 } 1513 1514 1515 static Bool 1516 Fake_glXQueryExtension( Display *dpy, int *errorBase, int *eventBase ) 1517 { 1518 int op, ev, err; 1519 /* Mesa's GLX isn't really an X extension but we try to act like one. */ 1520 if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err)) 1521 ev = err = 0; 1522 if (errorBase) 1523 *errorBase = err; 1524 if (eventBase) 1525 *eventBase = ev; 1526 return True; /* we're faking GLX so always return success */ 1527 } 1528 1529 1530 extern void _kw_ungrab_all( Display *dpy ); 1531 void _kw_ungrab_all( Display *dpy ) 1532 { 1533 XUngrabPointer( dpy, CurrentTime ); 1534 XUngrabKeyboard( dpy, CurrentTime ); 1535 } 1536 1537 1538 static void 1539 Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) 1540 { 1541 struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; 1542 (void) dpy; 1543 MakeCurrent_PrevContext = 0; 1544 MakeCurrent_PrevDrawable = 0; 1545 MakeCurrent_PrevReadable = 0; 1546 MakeCurrent_PrevDrawBuffer = 0; 1547 MakeCurrent_PrevReadBuffer = 0; 1548 XMesaDestroyContext( glxCtx->xmesaContext ); 1549 XMesaGarbageCollect(dpy); 1550 free(glxCtx); 1551 } 1552 1553 1554 static Bool 1555 Fake_glXIsDirect( Display *dpy, GLXContext ctx ) 1556 { 1557 struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; 1558 (void) dpy; 1559 return glxCtx->xmesaContext->direct; 1560 } 1561 1562 1563 1564 static void 1565 Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) 1566 { 1567 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); 1568 1569 if (buffer) { 1570 XMesaSwapBuffers(buffer); 1571 } 1572 else if (_mesa_getenv("MESA_DEBUG")) { 1573 _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n", 1574 (int) drawable); 1575 } 1576 } 1577 1578 1579 1580 /*** GLX_MESA_copy_sub_buffer ***/ 1581 1582 static void 1583 Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, 1584 int x, int y, int width, int height ) 1585 { 1586 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); 1587 if (buffer) { 1588 XMesaCopySubBuffer(buffer, x, y, width, height); 1589 } 1590 else if (_mesa_getenv("MESA_DEBUG")) { 1591 _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n"); 1592 } 1593 } 1594 1595 1596 static Bool 1597 Fake_glXQueryVersion( Display *dpy, int *maj, int *min ) 1598 { 1599 (void) dpy; 1600 /* Return GLX version, not Mesa version */ 1601 assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION); 1602 *maj = CLIENT_MAJOR_VERSION; 1603 *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION ); 1604 return True; 1605 } 1606 1607 1608 /* 1609 * Query the GLX attributes of the given XVisualInfo. 1610 */ 1611 static int 1612 get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) 1613 { 1614 ASSERT(xmvis); 1615 switch(attrib) { 1616 case GLX_USE_GL: 1617 if (fbconfig) 1618 return GLX_BAD_ATTRIBUTE; 1619 *value = (int) True; 1620 return 0; 1621 case GLX_BUFFER_SIZE: 1622 *value = xmvis->visinfo->depth; 1623 return 0; 1624 case GLX_LEVEL: 1625 *value = xmvis->mesa_visual.level; 1626 return 0; 1627 case GLX_RGBA: 1628 if (fbconfig) 1629 return GLX_BAD_ATTRIBUTE; 1630 if (xmvis->mesa_visual.rgbMode) { 1631 *value = True; 1632 } 1633 else { 1634 *value = False; 1635 } 1636 return 0; 1637 case GLX_DOUBLEBUFFER: 1638 *value = (int) xmvis->mesa_visual.doubleBufferMode; 1639 return 0; 1640 case GLX_STEREO: 1641 *value = (int) xmvis->mesa_visual.stereoMode; 1642 return 0; 1643 case GLX_AUX_BUFFERS: 1644 *value = xmvis->mesa_visual.numAuxBuffers; 1645 return 0; 1646 case GLX_RED_SIZE: 1647 *value = xmvis->mesa_visual.redBits; 1648 return 0; 1649 case GLX_GREEN_SIZE: 1650 *value = xmvis->mesa_visual.greenBits; 1651 return 0; 1652 case GLX_BLUE_SIZE: 1653 *value = xmvis->mesa_visual.blueBits; 1654 return 0; 1655 case GLX_ALPHA_SIZE: 1656 *value = xmvis->mesa_visual.alphaBits; 1657 return 0; 1658 case GLX_DEPTH_SIZE: 1659 *value = xmvis->mesa_visual.depthBits; 1660 return 0; 1661 case GLX_STENCIL_SIZE: 1662 *value = xmvis->mesa_visual.stencilBits; 1663 return 0; 1664 case GLX_ACCUM_RED_SIZE: 1665 *value = xmvis->mesa_visual.accumRedBits; 1666 return 0; 1667 case GLX_ACCUM_GREEN_SIZE: 1668 *value = xmvis->mesa_visual.accumGreenBits; 1669 return 0; 1670 case GLX_ACCUM_BLUE_SIZE: 1671 *value = xmvis->mesa_visual.accumBlueBits; 1672 return 0; 1673 case GLX_ACCUM_ALPHA_SIZE: 1674 *value = xmvis->mesa_visual.accumAlphaBits; 1675 return 0; 1676 1677 /* 1678 * GLX_EXT_visual_info extension 1679 */ 1680 case GLX_X_VISUAL_TYPE_EXT: 1681 switch (xmvis->visinfo->CLASS) { 1682 case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0; 1683 case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0; 1684 case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0; 1685 case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0; 1686 case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0; 1687 case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0; 1688 } 1689 return 0; 1690 case GLX_TRANSPARENT_TYPE_EXT: 1691 if (xmvis->mesa_visual.level==0) { 1692 /* normal planes */ 1693 *value = GLX_NONE_EXT; 1694 } 1695 else if (xmvis->mesa_visual.level>0) { 1696 /* overlay */ 1697 if (xmvis->mesa_visual.rgbMode) { 1698 *value = GLX_TRANSPARENT_RGB_EXT; 1699 } 1700 else { 1701 *value = GLX_TRANSPARENT_INDEX_EXT; 1702 } 1703 } 1704 else if (xmvis->mesa_visual.level<0) { 1705 /* underlay */ 1706 *value = GLX_NONE_EXT; 1707 } 1708 return 0; 1709 case GLX_TRANSPARENT_INDEX_VALUE_EXT: 1710 { 1711 int pixel = transparent_pixel( xmvis ); 1712 if (pixel>=0) { 1713 *value = pixel; 1714 } 1715 /* else undefined */ 1716 } 1717 return 0; 1718 case GLX_TRANSPARENT_RED_VALUE_EXT: 1719 /* undefined */ 1720 return 0; 1721 case GLX_TRANSPARENT_GREEN_VALUE_EXT: 1722 /* undefined */ 1723 return 0; 1724 case GLX_TRANSPARENT_BLUE_VALUE_EXT: 1725 /* undefined */ 1726 return 0; 1727 case GLX_TRANSPARENT_ALPHA_VALUE_EXT: 1728 /* undefined */ 1729 return 0; 1730 1731 /* 1732 * GLX_EXT_visual_info extension 1733 */ 1734 case GLX_VISUAL_CAVEAT_EXT: 1735 /* test for zero, just in case */ 1736 if (xmvis->mesa_visual.visualRating > 0) 1737 *value = xmvis->mesa_visual.visualRating; 1738 else 1739 *value = GLX_NONE_EXT; 1740 return 0; 1741 1742 /* 1743 * GLX_ARB_multisample 1744 */ 1745 case GLX_SAMPLE_BUFFERS_ARB: 1746 *value = 0; 1747 return 0; 1748 case GLX_SAMPLES_ARB: 1749 *value = 0; 1750 return 0; 1751 1752 /* 1753 * For FBConfigs: 1754 */ 1755 case GLX_SCREEN_EXT: 1756 if (!fbconfig) 1757 return GLX_BAD_ATTRIBUTE; 1758 *value = xmvis->visinfo->screen; 1759 break; 1760 case GLX_DRAWABLE_TYPE: /*SGIX too */ 1761 if (!fbconfig) 1762 return GLX_BAD_ATTRIBUTE; 1763 *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 1764 break; 1765 case GLX_RENDER_TYPE_SGIX: 1766 if (!fbconfig) 1767 return GLX_BAD_ATTRIBUTE; 1768 if (xmvis->mesa_visual.rgbMode) 1769 *value = GLX_RGBA_BIT; 1770 else 1771 *value = GLX_COLOR_INDEX_BIT; 1772 break; 1773 case GLX_X_RENDERABLE_SGIX: 1774 if (!fbconfig) 1775 return GLX_BAD_ATTRIBUTE; 1776 *value = True; /* XXX really? */ 1777 break; 1778 case GLX_FBCONFIG_ID_SGIX: 1779 if (!fbconfig) 1780 return GLX_BAD_ATTRIBUTE; 1781 *value = xmvis->visinfo->visualid; 1782 break; 1783 case GLX_MAX_PBUFFER_WIDTH: 1784 if (!fbconfig) 1785 return GLX_BAD_ATTRIBUTE; 1786 /* XXX or MAX_WIDTH? */ 1787 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen); 1788 break; 1789 case GLX_MAX_PBUFFER_HEIGHT: 1790 if (!fbconfig) 1791 return GLX_BAD_ATTRIBUTE; 1792 *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen); 1793 break; 1794 case GLX_MAX_PBUFFER_PIXELS: 1795 if (!fbconfig) 1796 return GLX_BAD_ATTRIBUTE; 1797 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) * 1798 DisplayHeight(xmvis->display, xmvis->visinfo->screen); 1799 break; 1800 case GLX_VISUAL_ID: 1801 if (!fbconfig) 1802 return GLX_BAD_ATTRIBUTE; 1803 *value = xmvis->visinfo->visualid; 1804 break; 1805 1806 #ifdef GLX_EXT_texture_from_pixmap 1807 case GLX_BIND_TO_TEXTURE_RGB_EXT: 1808 *value = True; /*XXX*/ 1809 break; 1810 case GLX_BIND_TO_TEXTURE_RGBA_EXT: 1811 /* XXX review */ 1812 *value = xmvis->mesa_visual.alphaBits > 0 ? True : False; 1813 break; 1814 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 1815 *value = True; /*XXX*/ 1816 break; 1817 case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 1818 *value = (GLX_TEXTURE_1D_BIT_EXT | 1819 GLX_TEXTURE_2D_BIT_EXT | 1820 GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/ 1821 break; 1822 case GLX_Y_INVERTED_EXT: 1823 *value = True; /*XXX*/ 1824 break; 1825 #endif 1826 1827 default: 1828 return GLX_BAD_ATTRIBUTE; 1829 } 1830 return Success; 1831 } 1832 1833 1834 static int 1835 Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, 1836 int attrib, int *value ) 1837 { 1838 XMesaVisual xmvis; 1839 int k; 1840 if (!dpy || !visinfo) 1841 return GLX_BAD_ATTRIBUTE; 1842 1843 xmvis = find_glx_visual( dpy, visinfo ); 1844 if (!xmvis) { 1845 /* this visual wasn't obtained with glXChooseVisual */ 1846 xmvis = create_glx_visual( dpy, visinfo ); 1847 if (!xmvis) { 1848 /* this visual can't be used for GL rendering */ 1849 if (attrib==GLX_USE_GL) { 1850 *value = (int) False; 1851 return 0; 1852 } 1853 else { 1854 return GLX_BAD_VISUAL; 1855 } 1856 } 1857 } 1858 1859 k = get_config(xmvis, attrib, value, GL_FALSE); 1860 return k; 1861 } 1862 1863 1864 static void 1865 Fake_glXWaitGL( void ) 1866 { 1867 XMesaContext xmesa = XMesaGetCurrentContext(); 1868 XMesaFlush( xmesa ); 1869 } 1870 1871 1872 1873 static void 1874 Fake_glXWaitX( void ) 1875 { 1876 XMesaContext xmesa = XMesaGetCurrentContext(); 1877 XMesaFlush( xmesa ); 1878 } 1879 1880 1881 static const char * 1882 get_extensions( void ) 1883 { 1884 return EXTENSIONS + 23; /* skip "GLX_MESA_set_3dfx_mode" */ 1885 } 1886 1887 1888 1889 /* GLX 1.1 and later */ 1890 static const char * 1891 Fake_glXQueryExtensionsString( Display *dpy, int screen ) 1892 { 1893 (void) dpy; 1894 (void) screen; 1895 return get_extensions(); 1896 } 1897 1898 1899 1900 /* GLX 1.1 and later */ 1901 static const char * 1902 Fake_glXQueryServerString( Display *dpy, int screen, int name ) 1903 { 1904 static char version[1000]; 1905 sprintf(version, "%d.%d %s", 1906 SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION); 1907 1908 (void) dpy; 1909 (void) screen; 1910 1911 switch (name) { 1912 case GLX_EXTENSIONS: 1913 return get_extensions(); 1914 case GLX_VENDOR: 1915 return VENDOR; 1916 case GLX_VERSION: 1917 return version; 1918 default: 1919 return NULL; 1920 } 1921 } 1922 1923 1924 1925 /* GLX 1.1 and later */ 1926 static const char * 1927 Fake_glXGetClientString( Display *dpy, int name ) 1928 { 1929 static char version[1000]; 1930 sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, 1931 CLIENT_MINOR_VERSION, MESA_GLX_VERSION); 1932 1933 (void) dpy; 1934 1935 switch (name) { 1936 case GLX_EXTENSIONS: 1937 return get_extensions(); 1938 case GLX_VENDOR: 1939 return VENDOR; 1940 case GLX_VERSION: 1941 return version; 1942 default: 1943 return NULL; 1944 } 1945 } 1946 1947 1948 1949 /* 1950 * GLX 1.3 and later 1951 */ 1952 1953 1954 static int 1955 Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config, 1956 int attribute, int *value ) 1957 { 1958 XMesaVisual v = (XMesaVisual) config; 1959 (void) dpy; 1960 (void) config; 1961 1962 if (!dpy || !config || !value) 1963 return -1; 1964 1965 return get_config(v, attribute, value, GL_TRUE); 1966 } 1967 1968 1969 static GLXFBConfig * 1970 Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements ) 1971 { 1972 XVisualInfo *visuals, visTemplate; 1973 const long visMask = VisualScreenMask; 1974 int i; 1975 1976 /* Get list of all X visuals */ 1977 visTemplate.screen = screen; 1978 visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements); 1979 if (*nelements > 0) { 1980 XMesaVisual *results; 1981 results = (XMesaVisual *) malloc(*nelements * sizeof(XMesaVisual)); 1982 if (!results) { 1983 *nelements = 0; 1984 return NULL; 1985 } 1986 for (i = 0; i < *nelements; i++) { 1987 results[i] = create_glx_visual(dpy, visuals + i); 1988 } 1989 return (GLXFBConfig *) results; 1990 } 1991 return NULL; 1992 } 1993 1994 1995 static GLXFBConfig * 1996 Fake_glXChooseFBConfig( Display *dpy, int screen, 1997 const int *attribList, int *nitems ) 1998 { 1999 XMesaVisual xmvis; 2000 2001 /* register ourselves as an extension on this display */ 2002 register_with_display(dpy); 2003 2004 if (!attribList || !attribList[0]) { 2005 /* return list of all configs (per GLX_SGIX_fbconfig spec) */ 2006 return Fake_glXGetFBConfigs(dpy, screen, nitems); 2007 } 2008 2009 xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); 2010 if (xmvis) { 2011 GLXFBConfig *config = (GLXFBConfig *) malloc(sizeof(XMesaVisual)); 2012 if (!config) { 2013 *nitems = 0; 2014 return NULL; 2015 } 2016 *nitems = 1; 2017 config[0] = (GLXFBConfig) xmvis; 2018 return (GLXFBConfig *) config; 2019 } 2020 else { 2021 *nitems = 0; 2022 return NULL; 2023 } 2024 } 2025 2026 2027 static XVisualInfo * 2028 Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) 2029 { 2030 if (dpy && config) { 2031 XMesaVisual xmvis = (XMesaVisual) config; 2032 #if 0 2033 return xmvis->vishandle; 2034 #else 2035 /* create a new vishandle - the cached one may be stale */ 2036 xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo)); 2037 if (xmvis->vishandle) { 2038 memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); 2039 } 2040 return xmvis->vishandle; 2041 #endif 2042 } 2043 else { 2044 return NULL; 2045 } 2046 } 2047 2048 2049 static GLXWindow 2050 Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, 2051 const int *attribList ) 2052 { 2053 XMesaVisual xmvis = (XMesaVisual) config; 2054 XMesaBuffer xmbuf; 2055 if (!xmvis) 2056 return 0; 2057 2058 xmbuf = XMesaCreateWindowBuffer(xmvis, win); 2059 if (!xmbuf) 2060 return 0; 2061 2062 (void) dpy; 2063 (void) attribList; /* Ignored in GLX 1.3 */ 2064 2065 return win; /* A hack for now */ 2066 } 2067 2068 2069 static void 2070 Fake_glXDestroyWindow( Display *dpy, GLXWindow window ) 2071 { 2072 XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable) window); 2073 if (b) 2074 XMesaDestroyBuffer(b); 2075 /* don't destroy X window */ 2076 } 2077 2078 2079 /* XXX untested */ 2080 static GLXPixmap 2081 Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, 2082 const int *attribList ) 2083 { 2084 XMesaVisual v = (XMesaVisual) config; 2085 XMesaBuffer b; 2086 const int *attr; 2087 int target = 0, format = 0, mipmap = 0; 2088 int value; 2089 2090 if (!dpy || !config || !pixmap) 2091 return 0; 2092 2093 for (attr = attribList; attr && *attr; attr++) { 2094 switch (*attr) { 2095 case GLX_TEXTURE_FORMAT_EXT: 2096 attr++; 2097 switch (*attr) { 2098 case GLX_TEXTURE_FORMAT_NONE_EXT: 2099 case GLX_TEXTURE_FORMAT_RGB_EXT: 2100 case GLX_TEXTURE_FORMAT_RGBA_EXT: 2101 format = *attr; 2102 break; 2103 default: 2104 /* error */ 2105 return 0; 2106 } 2107 break; 2108 case GLX_TEXTURE_TARGET_EXT: 2109 attr++; 2110 switch (*attr) { 2111 case GLX_TEXTURE_1D_EXT: 2112 case GLX_TEXTURE_2D_EXT: 2113 case GLX_TEXTURE_RECTANGLE_EXT: 2114 target = *attr; 2115 break; 2116 default: 2117 /* error */ 2118 return 0; 2119 } 2120 break; 2121 case GLX_MIPMAP_TEXTURE_EXT: 2122 attr++; 2123 if (*attr) 2124 mipmap = 1; 2125 break; 2126 default: 2127 /* error */ 2128 return 0; 2129 } 2130 } 2131 2132 if (format == GLX_TEXTURE_FORMAT_RGB_EXT) { 2133 if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT, 2134 &value, GL_TRUE) != Success 2135 || !value) { 2136 return 0; /* error! */ 2137 } 2138 } 2139 else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) { 2140 if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT, 2141 &value, GL_TRUE) != Success 2142 || !value) { 2143 return 0; /* error! */ 2144 } 2145 } 2146 if (mipmap) { 2147 if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT, 2148 &value, GL_TRUE) != Success 2149 || !value) { 2150 return 0; /* error! */ 2151 } 2152 } 2153 if (target == GLX_TEXTURE_1D_EXT) { 2154 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 2155 &value, GL_TRUE) != Success 2156 || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) { 2157 return 0; /* error! */ 2158 } 2159 } 2160 else if (target == GLX_TEXTURE_2D_EXT) { 2161 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 2162 &value, GL_TRUE) != Success 2163 || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) { 2164 return 0; /* error! */ 2165 } 2166 } 2167 if (target == GLX_TEXTURE_RECTANGLE_EXT) { 2168 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 2169 &value, GL_TRUE) != Success 2170 || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) { 2171 return 0; /* error! */ 2172 } 2173 } 2174 2175 if (format || target || mipmap) { 2176 /* texture from pixmap */ 2177 b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap); 2178 } 2179 else { 2180 b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); 2181 } 2182 if (!b) { 2183 return 0; 2184 } 2185 2186 return pixmap; 2187 } 2188 2189 2190 static void 2191 Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) 2192 { 2193 XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable)pixmap); 2194 if (b) 2195 XMesaDestroyBuffer(b); 2196 /* don't destroy X pixmap */ 2197 } 2198 2199 2200 static GLXPbuffer 2201 Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config, 2202 const int *attribList ) 2203 { 2204 XMesaVisual xmvis = (XMesaVisual) config; 2205 XMesaBuffer xmbuf; 2206 const int *attrib; 2207 int width = 0, height = 0; 2208 GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; 2209 2210 (void) dpy; 2211 2212 for (attrib = attribList; *attrib; attrib++) { 2213 switch (*attrib) { 2214 case GLX_PBUFFER_WIDTH: 2215 attrib++; 2216 width = *attrib; 2217 break; 2218 case GLX_PBUFFER_HEIGHT: 2219 attrib++; 2220 height = *attrib; 2221 break; 2222 case GLX_PRESERVED_CONTENTS: 2223 attrib++; 2224 preserveContents = *attrib; 2225 break; 2226 case GLX_LARGEST_PBUFFER: 2227 attrib++; 2228 useLargest = *attrib; 2229 break; 2230 default: 2231 return 0; 2232 } 2233 } 2234 2235 if (width == 0 || height == 0) 2236 return 0; 2237 2238 if (width > SWRAST_MAX_WIDTH || height > SWRAST_MAX_HEIGHT) { 2239 /* If allocation would have failed and GLX_LARGEST_PBUFFER is set, 2240 * allocate the largest possible buffer. 2241 */ 2242 if (useLargest) { 2243 width = SWRAST_MAX_WIDTH; 2244 height = SWRAST_MAX_HEIGHT; 2245 } 2246 } 2247 2248 xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); 2249 /* A GLXPbuffer handle must be an X Drawable because that's what 2250 * glXMakeCurrent takes. 2251 */ 2252 if (xmbuf) { 2253 xmbuf->largestPbuffer = useLargest; 2254 xmbuf->preservedContents = preserveContents; 2255 return (GLXPbuffer) xmbuf->frontxrb->pixmap; 2256 } 2257 else { 2258 return 0; 2259 } 2260 } 2261 2262 2263 static void 2264 Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) 2265 { 2266 XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); 2267 if (b) { 2268 XMesaDestroyBuffer(b); 2269 } 2270 } 2271 2272 2273 static void 2274 Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, 2275 unsigned int *value ) 2276 { 2277 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); 2278 if (!xmbuf) 2279 return; 2280 2281 /* make sure buffer's dimensions are up to date */ 2282 xmesa_check_and_update_buffer_size(NULL, xmbuf); 2283 2284 switch (attribute) { 2285 case GLX_WIDTH: 2286 *value = xmbuf->mesa_buffer.Width; 2287 break; 2288 case GLX_HEIGHT: 2289 *value = xmbuf->mesa_buffer.Height; 2290 break; 2291 case GLX_PRESERVED_CONTENTS: 2292 *value = xmbuf->preservedContents; 2293 break; 2294 case GLX_LARGEST_PBUFFER: 2295 *value = xmbuf->largestPbuffer; 2296 break; 2297 case GLX_FBCONFIG_ID: 2298 *value = xmbuf->xm_visual->visinfo->visualid; 2299 return; 2300 #ifdef GLX_EXT_texture_from_pixmap 2301 case GLX_TEXTURE_FORMAT_EXT: 2302 *value = xmbuf->TextureFormat; 2303 break; 2304 case GLX_TEXTURE_TARGET_EXT: 2305 *value = xmbuf->TextureTarget; 2306 break; 2307 case GLX_MIPMAP_TEXTURE_EXT: 2308 *value = xmbuf->TextureMipmap; 2309 break; 2310 #endif 2311 2312 default: 2313 return; /* raise BadValue error */ 2314 } 2315 } 2316 2317 2318 static GLXContext 2319 Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, 2320 int renderType, GLXContext shareList, Bool direct ) 2321 { 2322 struct fake_glx_context *glxCtx; 2323 struct fake_glx_context *shareCtx = (struct fake_glx_context *) shareList; 2324 XMesaVisual xmvis = (XMesaVisual) config; 2325 2326 if (!dpy || !config || 2327 (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) 2328 return 0; 2329 2330 glxCtx = CALLOC_STRUCT(fake_glx_context); 2331 if (!glxCtx) 2332 return 0; 2333 2334 /* deallocate unused windows/buffers */ 2335 XMesaGarbageCollect(dpy); 2336 2337 glxCtx->xmesaContext = XMesaCreateContext(xmvis, 2338 shareCtx ? shareCtx->xmesaContext : NULL); 2339 if (!glxCtx->xmesaContext) { 2340 free(glxCtx); 2341 return NULL; 2342 } 2343 2344 init_glx_context(glxCtx, dpy); 2345 2346 return (GLXContext) glxCtx; 2347 } 2348 2349 2350 static int 2351 Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) 2352 { 2353 struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; 2354 XMesaContext xmctx = glxCtx->xmesaContext; 2355 2356 (void) dpy; 2357 (void) ctx; 2358 2359 switch (attribute) { 2360 case GLX_FBCONFIG_ID: 2361 *value = xmctx->xm_visual->visinfo->visualid; 2362 break; 2363 case GLX_RENDER_TYPE: 2364 *value = GLX_RGBA_TYPE; 2365 break; 2366 case GLX_SCREEN: 2367 *value = 0; 2368 return Success; 2369 default: 2370 return GLX_BAD_ATTRIBUTE; 2371 } 2372 return 0; 2373 } 2374 2375 2376 static void 2377 Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) 2378 { 2379 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2380 if (xmbuf) 2381 xmbuf->selectedEvents = mask; 2382 } 2383 2384 2385 static void 2386 Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable, 2387 unsigned long *mask ) 2388 { 2389 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2390 if (xmbuf) 2391 *mask = xmbuf->selectedEvents; 2392 else 2393 *mask = 0; 2394 } 2395 2396 2397 2398 /*** GLX_SGI_swap_control ***/ 2399 2400 static int 2401 Fake_glXSwapIntervalSGI(int interval) 2402 { 2403 (void) interval; 2404 return 0; 2405 } 2406 2407 2408 2409 /*** GLX_SGI_video_sync ***/ 2410 2411 static unsigned int FrameCounter = 0; 2412 2413 static int 2414 Fake_glXGetVideoSyncSGI(unsigned int *count) 2415 { 2416 /* this is a bogus implementation */ 2417 *count = FrameCounter++; 2418 return 0; 2419 } 2420 2421 static int 2422 Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 2423 { 2424 if (divisor <= 0 || remainder < 0) 2425 return GLX_BAD_VALUE; 2426 /* this is a bogus implementation */ 2427 FrameCounter++; 2428 while (FrameCounter % divisor != remainder) 2429 FrameCounter++; 2430 *count = FrameCounter; 2431 return 0; 2432 } 2433 2434 2435 2436 /*** GLX_SGI_make_current_read ***/ 2437 2438 static Bool 2439 Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) 2440 { 2441 return Fake_glXMakeContextCurrent( dpy, draw, read, ctx ); 2442 } 2443 2444 /* not used 2445 static GLXDrawable 2446 Fake_glXGetCurrentReadDrawableSGI(void) 2447 { 2448 return 0; 2449 } 2450 */ 2451 2452 2453 /*** GLX_SGIX_video_source ***/ 2454 #if defined(_VL_H) 2455 2456 static GLXVideoSourceSGIX 2457 Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) 2458 { 2459 (void) dpy; 2460 (void) screen; 2461 (void) server; 2462 (void) path; 2463 (void) nodeClass; 2464 (void) drainNode; 2465 return 0; 2466 } 2467 2468 static void 2469 Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) 2470 { 2471 (void) dpy; 2472 (void) src; 2473 } 2474 2475 #endif 2476 2477 2478 /*** GLX_EXT_import_context ***/ 2479 2480 static void 2481 Fake_glXFreeContextEXT(Display *dpy, GLXContext context) 2482 { 2483 (void) dpy; 2484 (void) context; 2485 } 2486 2487 static GLXContextID 2488 Fake_glXGetContextIDEXT(const GLXContext context) 2489 { 2490 (void) context; 2491 return 0; 2492 } 2493 2494 static GLXContext 2495 Fake_glXImportContextEXT(Display *dpy, GLXContextID contextID) 2496 { 2497 (void) dpy; 2498 (void) contextID; 2499 return 0; 2500 } 2501 2502 static int 2503 Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value) 2504 { 2505 (void) dpy; 2506 (void) context; 2507 (void) attribute; 2508 (void) value; 2509 return 0; 2510 } 2511 2512 2513 2514 /*** GLX_SGIX_fbconfig ***/ 2515 2516 static int 2517 Fake_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) 2518 { 2519 return Fake_glXGetFBConfigAttrib(dpy, config, attribute, value); 2520 } 2521 2522 static GLXFBConfigSGIX * 2523 Fake_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) 2524 { 2525 return (GLXFBConfig *) Fake_glXChooseFBConfig(dpy, screen, attrib_list, nelements); 2526 } 2527 2528 2529 static GLXPixmap 2530 Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) 2531 { 2532 XMesaVisual xmvis = (XMesaVisual) config; 2533 XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); 2534 return xmbuf->frontxrb->pixmap; /* need to return an X ID */ 2535 } 2536 2537 2538 static GLXContext 2539 Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) 2540 { 2541 XMesaVisual xmvis = (XMesaVisual) config; 2542 struct fake_glx_context *glxCtx; 2543 struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list; 2544 2545 glxCtx = CALLOC_STRUCT(fake_glx_context); 2546 if (!glxCtx) 2547 return 0; 2548 2549 /* deallocate unused windows/buffers */ 2550 XMesaGarbageCollect(dpy); 2551 2552 glxCtx->xmesaContext = XMesaCreateContext(xmvis, 2553 shareCtx ? shareCtx->xmesaContext : NULL); 2554 if (!glxCtx->xmesaContext) { 2555 free(glxCtx); 2556 return NULL; 2557 } 2558 2559 init_glx_context(glxCtx, dpy); 2560 2561 return (GLXContext) glxCtx; 2562 } 2563 2564 2565 static XVisualInfo * 2566 Fake_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) 2567 { 2568 return Fake_glXGetVisualFromFBConfig(dpy, config); 2569 } 2570 2571 2572 static GLXFBConfigSGIX 2573 Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) 2574 { 2575 XMesaVisual xmvis = find_glx_visual(dpy, vis); 2576 if (!xmvis) { 2577 /* This visual wasn't found with glXChooseVisual() */ 2578 xmvis = create_glx_visual(dpy, vis); 2579 } 2580 2581 return (GLXFBConfigSGIX) xmvis; 2582 } 2583 2584 2585 2586 /*** GLX_SGIX_pbuffer ***/ 2587 2588 static GLXPbufferSGIX 2589 Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, 2590 unsigned int width, unsigned int height, 2591 int *attribList) 2592 { 2593 XMesaVisual xmvis = (XMesaVisual) config; 2594 XMesaBuffer xmbuf; 2595 const int *attrib; 2596 GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; 2597 2598 (void) dpy; 2599 2600 for (attrib = attribList; attrib && *attrib; attrib++) { 2601 switch (*attrib) { 2602 case GLX_PRESERVED_CONTENTS_SGIX: 2603 attrib++; 2604 preserveContents = *attrib; /* ignored */ 2605 break; 2606 case GLX_LARGEST_PBUFFER_SGIX: 2607 attrib++; 2608 useLargest = *attrib; /* ignored */ 2609 break; 2610 default: 2611 return 0; 2612 } 2613 } 2614 2615 /* not used at this time */ 2616 (void) useLargest; 2617 (void) preserveContents; 2618 2619 xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); 2620 /* A GLXPbuffer handle must be an X Drawable because that's what 2621 * glXMakeCurrent takes. 2622 */ 2623 return (GLXPbuffer) xmbuf->frontxrb->pixmap; 2624 } 2625 2626 2627 static void 2628 Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) 2629 { 2630 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); 2631 if (xmbuf) { 2632 XMesaDestroyBuffer(xmbuf); 2633 } 2634 } 2635 2636 2637 static int 2638 Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value) 2639 { 2640 const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); 2641 2642 if (!xmbuf) { 2643 /* Generate GLXBadPbufferSGIX for bad pbuffer */ 2644 return 0; 2645 } 2646 2647 switch (attribute) { 2648 case GLX_PRESERVED_CONTENTS_SGIX: 2649 *value = xmbuf->preservedContents; 2650 break; 2651 case GLX_LARGEST_PBUFFER_SGIX: 2652 *value = xmbuf->largestPbuffer; 2653 break; 2654 case GLX_WIDTH_SGIX: 2655 *value = xmbuf->mesa_buffer.Width; 2656 break; 2657 case GLX_HEIGHT_SGIX: 2658 *value = xmbuf->mesa_buffer.Height; 2659 break; 2660 case GLX_EVENT_MASK_SGIX: 2661 *value = 0; /* XXX might be wrong */ 2662 break; 2663 default: 2664 *value = 0; 2665 } 2666 return 0; 2667 } 2668 2669 2670 static void 2671 Fake_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) 2672 { 2673 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2674 if (xmbuf) { 2675 /* Note: we'll never generate clobber events */ 2676 xmbuf->selectedEvents = mask; 2677 } 2678 } 2679 2680 2681 static void 2682 Fake_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask) 2683 { 2684 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2685 if (xmbuf) { 2686 *mask = xmbuf->selectedEvents; 2687 } 2688 else { 2689 *mask = 0; 2690 } 2691 } 2692 2693 2694 2695 /*** GLX_SGI_cushion ***/ 2696 2697 static void 2698 Fake_glXCushionSGI(Display *dpy, Window win, float cushion) 2699 { 2700 (void) dpy; 2701 (void) win; 2702 (void) cushion; 2703 } 2704 2705 2706 2707 /*** GLX_SGIX_video_resize ***/ 2708 2709 static int 2710 Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) 2711 { 2712 (void) dpy; 2713 (void) screen; 2714 (void) channel; 2715 (void) window; 2716 return 0; 2717 } 2718 2719 static int 2720 Fake_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h) 2721 { 2722 (void) dpy; 2723 (void) screen; 2724 (void) channel; 2725 (void) x; 2726 (void) y; 2727 (void) w; 2728 (void) h; 2729 return 0; 2730 } 2731 2732 static int 2733 Fake_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h) 2734 { 2735 (void) dpy; 2736 (void) screen; 2737 (void) channel; 2738 (void) x; 2739 (void) y; 2740 (void) w; 2741 (void) h; 2742 return 0; 2743 } 2744 2745 static int 2746 Fake_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh) 2747 { 2748 (void) dpy; 2749 (void) screen; 2750 (void) channel; 2751 (void) dx; 2752 (void) dy; 2753 (void) dw; 2754 (void) dh; 2755 return 0; 2756 } 2757 2758 static int 2759 Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) 2760 { 2761 (void) dpy; 2762 (void) screen; 2763 (void) channel; 2764 (void) synctype; 2765 return 0; 2766 } 2767 2768 2769 2770 /*** GLX_SGIX_dmbuffer **/ 2771 2772 #if defined(_DM_BUFFER_H_) 2773 static Bool 2774 Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) 2775 { 2776 (void) dpy; 2777 (void) pbuffer; 2778 (void) params; 2779 (void) dmbuffer; 2780 return False; 2781 } 2782 #endif 2783 2784 2785 /*** GLX_SGIX_swap_group ***/ 2786 2787 static void 2788 Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) 2789 { 2790 (void) dpy; 2791 (void) drawable; 2792 (void) member; 2793 } 2794 2795 2796 2797 /*** GLX_SGIX_swap_barrier ***/ 2798 2799 static void 2800 Fake_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) 2801 { 2802 (void) dpy; 2803 (void) drawable; 2804 (void) barrier; 2805 } 2806 2807 static Bool 2808 Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) 2809 { 2810 (void) dpy; 2811 (void) screen; 2812 (void) max; 2813 return False; 2814 } 2815 2816 2817 2818 /*** GLX_SUN_get_transparent_index ***/ 2819 2820 static Status 2821 Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) 2822 { 2823 (void) dpy; 2824 (void) overlay; 2825 (void) underlay; 2826 (void) pTransparent; 2827 return 0; 2828 } 2829 2830 2831 2832 /*** GLX_MESA_release_buffers ***/ 2833 2834 /* 2835 * Release the depth, stencil, accum buffers attached to a GLXDrawable 2836 * (a window or pixmap) prior to destroying the GLXDrawable. 2837 */ 2838 static Bool 2839 Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) 2840 { 2841 XMesaBuffer b = XMesaFindBuffer(dpy, d); 2842 if (b) { 2843 XMesaDestroyBuffer(b); 2844 return True; 2845 } 2846 return False; 2847 } 2848 2849 2850 2851 /*** GLX_MESA_set_3dfx_mode ***/ 2852 2853 static Bool 2854 Fake_glXSet3DfxModeMESA( int mode ) 2855 { 2856 return XMesaSetFXmode( mode ); 2857 } 2858 2859 2860 2861 /*** GLX_NV_vertex_array range ***/ 2862 static void * 2863 Fake_glXAllocateMemoryNV( GLsizei size, 2864 GLfloat readFrequency, 2865 GLfloat writeFrequency, 2866 GLfloat priority ) 2867 { 2868 (void) size; 2869 (void) readFrequency; 2870 (void) writeFrequency; 2871 (void) priority; 2872 return NULL; 2873 } 2874 2875 2876 static void 2877 Fake_glXFreeMemoryNV( GLvoid *pointer ) 2878 { 2879 (void) pointer; 2880 } 2881 2882 2883 /*** GLX_MESA_agp_offset ***/ 2884 2885 static GLuint 2886 Fake_glXGetAGPOffsetMESA( const GLvoid *pointer ) 2887 { 2888 (void) pointer; 2889 return ~0; 2890 } 2891 2892 2893 /*** GLX_EXT_texture_from_pixmap ***/ 2894 2895 static void 2896 Fake_glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, 2897 const int *attrib_list) 2898 { 2899 XMesaBuffer b = XMesaFindBuffer(dpy, drawable); 2900 if (b) 2901 XMesaBindTexImage(dpy, b, buffer, attrib_list); 2902 } 2903 2904 static void 2905 Fake_glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) 2906 { 2907 XMesaBuffer b = XMesaFindBuffer(dpy, drawable); 2908 if (b) 2909 XMesaReleaseTexImage(dpy, b, buffer); 2910 } 2911 2912 2913 /* silence warning */ 2914 extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void); 2915 2916 2917 /** 2918 * Create a new GLX API dispatch table with its function pointers 2919 * initialized to point to Mesa's "fake" GLX API functions. 2920 * Note: there's a similar function (_real_GetGLXDispatchTable) that 2921 * returns a new dispatch table with all pointers initalized to point 2922 * to "real" GLX functions (which understand GLX wire protocol, etc). 2923 */ 2924 struct _glxapi_table * 2925 _mesa_GetGLXDispatchTable(void) 2926 { 2927 static struct _glxapi_table glx; 2928 2929 /* be sure our dispatch table size <= libGL's table */ 2930 { 2931 GLuint size = sizeof(struct _glxapi_table) / sizeof(void *); 2932 (void) size; 2933 assert(_glxapi_get_dispatch_table_size() >= size); 2934 } 2935 2936 /* initialize the whole table to no-ops */ 2937 _glxapi_set_no_op_table(&glx); 2938 2939 /* now initialize the table with the functions I implement */ 2940 glx.ChooseVisual = Fake_glXChooseVisual; 2941 glx.CopyContext = Fake_glXCopyContext; 2942 glx.CreateContext = Fake_glXCreateContext; 2943 glx.CreateGLXPixmap = Fake_glXCreateGLXPixmap; 2944 glx.DestroyContext = Fake_glXDestroyContext; 2945 glx.DestroyGLXPixmap = Fake_glXDestroyGLXPixmap; 2946 glx.GetConfig = Fake_glXGetConfig; 2947 /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/ 2948 /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/ 2949 glx.IsDirect = Fake_glXIsDirect; 2950 glx.MakeCurrent = Fake_glXMakeCurrent; 2951 glx.QueryExtension = Fake_glXQueryExtension; 2952 glx.QueryVersion = Fake_glXQueryVersion; 2953 glx.SwapBuffers = Fake_glXSwapBuffers; 2954 glx.UseXFont = Fake_glXUseXFont; 2955 glx.WaitGL = Fake_glXWaitGL; 2956 glx.WaitX = Fake_glXWaitX; 2957 2958 /*** GLX_VERSION_1_1 ***/ 2959 glx.GetClientString = Fake_glXGetClientString; 2960 glx.QueryExtensionsString = Fake_glXQueryExtensionsString; 2961 glx.QueryServerString = Fake_glXQueryServerString; 2962 2963 /*** GLX_VERSION_1_2 ***/ 2964 /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/ 2965 2966 /*** GLX_VERSION_1_3 ***/ 2967 glx.ChooseFBConfig = Fake_glXChooseFBConfig; 2968 glx.CreateNewContext = Fake_glXCreateNewContext; 2969 glx.CreatePbuffer = Fake_glXCreatePbuffer; 2970 glx.CreatePixmap = Fake_glXCreatePixmap; 2971 glx.CreateWindow = Fake_glXCreateWindow; 2972 glx.DestroyPbuffer = Fake_glXDestroyPbuffer; 2973 glx.DestroyPixmap = Fake_glXDestroyPixmap; 2974 glx.DestroyWindow = Fake_glXDestroyWindow; 2975 /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/ 2976 glx.GetFBConfigAttrib = Fake_glXGetFBConfigAttrib; 2977 glx.GetFBConfigs = Fake_glXGetFBConfigs; 2978 glx.GetSelectedEvent = Fake_glXGetSelectedEvent; 2979 glx.GetVisualFromFBConfig = Fake_glXGetVisualFromFBConfig; 2980 glx.MakeContextCurrent = Fake_glXMakeContextCurrent; 2981 glx.QueryContext = Fake_glXQueryContext; 2982 glx.QueryDrawable = Fake_glXQueryDrawable; 2983 glx.SelectEvent = Fake_glXSelectEvent; 2984 2985 /*** GLX_SGI_swap_control ***/ 2986 glx.SwapIntervalSGI = Fake_glXSwapIntervalSGI; 2987 2988 /*** GLX_SGI_video_sync ***/ 2989 glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI; 2990 glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI; 2991 2992 /*** GLX_SGI_make_current_read ***/ 2993 glx.MakeCurrentReadSGI = Fake_glXMakeCurrentReadSGI; 2994 /*glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI;*/ 2995 2996 /*** GLX_SGIX_video_source ***/ 2997 #if defined(_VL_H) 2998 glx.CreateGLXVideoSourceSGIX = Fake_glXCreateGLXVideoSourceSGIX; 2999 glx.DestroyGLXVideoSourceSGIX = Fake_glXDestroyGLXVideoSourceSGIX; 3000 #endif 3001 3002 /*** GLX_EXT_import_context ***/ 3003 glx.FreeContextEXT = Fake_glXFreeContextEXT; 3004 glx.GetContextIDEXT = Fake_glXGetContextIDEXT; 3005 /*glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT;*/ 3006 glx.ImportContextEXT = Fake_glXImportContextEXT; 3007 glx.QueryContextInfoEXT = Fake_glXQueryContextInfoEXT; 3008 3009 /*** GLX_SGIX_fbconfig ***/ 3010 glx.GetFBConfigAttribSGIX = Fake_glXGetFBConfigAttribSGIX; 3011 glx.ChooseFBConfigSGIX = Fake_glXChooseFBConfigSGIX; 3012 glx.CreateGLXPixmapWithConfigSGIX = Fake_glXCreateGLXPixmapWithConfigSGIX; 3013 glx.CreateContextWithConfigSGIX = Fake_glXCreateContextWithConfigSGIX; 3014 glx.GetVisualFromFBConfigSGIX = Fake_glXGetVisualFromFBConfigSGIX; 3015 glx.GetFBConfigFromVisualSGIX = Fake_glXGetFBConfigFromVisualSGIX; 3016 3017 /*** GLX_SGIX_pbuffer ***/ 3018 glx.CreateGLXPbufferSGIX = Fake_glXCreateGLXPbufferSGIX; 3019 glx.DestroyGLXPbufferSGIX = Fake_glXDestroyGLXPbufferSGIX; 3020 glx.QueryGLXPbufferSGIX = Fake_glXQueryGLXPbufferSGIX; 3021 glx.SelectEventSGIX = Fake_glXSelectEventSGIX; 3022 glx.GetSelectedEventSGIX = Fake_glXGetSelectedEventSGIX; 3023 3024 /*** GLX_SGI_cushion ***/ 3025 glx.CushionSGI = Fake_glXCushionSGI; 3026 3027 /*** GLX_SGIX_video_resize ***/ 3028 glx.BindChannelToWindowSGIX = Fake_glXBindChannelToWindowSGIX; 3029 glx.ChannelRectSGIX = Fake_glXChannelRectSGIX; 3030 glx.QueryChannelRectSGIX = Fake_glXQueryChannelRectSGIX; 3031 glx.QueryChannelDeltasSGIX = Fake_glXQueryChannelDeltasSGIX; 3032 glx.ChannelRectSyncSGIX = Fake_glXChannelRectSyncSGIX; 3033 3034 /*** GLX_SGIX_dmbuffer **/ 3035 #if defined(_DM_BUFFER_H_) 3036 glx.AssociateDMPbufferSGIX = NULL; 3037 #endif 3038 3039 /*** GLX_SGIX_swap_group ***/ 3040 glx.JoinSwapGroupSGIX = Fake_glXJoinSwapGroupSGIX; 3041 3042 /*** GLX_SGIX_swap_barrier ***/ 3043 glx.BindSwapBarrierSGIX = Fake_glXBindSwapBarrierSGIX; 3044 glx.QueryMaxSwapBarriersSGIX = Fake_glXQueryMaxSwapBarriersSGIX; 3045 3046 /*** GLX_SUN_get_transparent_index ***/ 3047 glx.GetTransparentIndexSUN = Fake_glXGetTransparentIndexSUN; 3048 3049 /*** GLX_MESA_copy_sub_buffer ***/ 3050 glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA; 3051 3052 /*** GLX_MESA_release_buffers ***/ 3053 glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA; 3054 3055 /*** GLX_MESA_pixmap_colormap ***/ 3056 glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA; 3057 3058 /*** GLX_MESA_set_3dfx_mode ***/ 3059 glx.Set3DfxModeMESA = Fake_glXSet3DfxModeMESA; 3060 3061 /*** GLX_NV_vertex_array_range ***/ 3062 glx.AllocateMemoryNV = Fake_glXAllocateMemoryNV; 3063 glx.FreeMemoryNV = Fake_glXFreeMemoryNV; 3064 3065 /*** GLX_MESA_agp_offset ***/ 3066 glx.GetAGPOffsetMESA = Fake_glXGetAGPOffsetMESA; 3067 3068 /*** GLX_EXT_texture_from_pixmap ***/ 3069 glx.BindTexImageEXT = Fake_glXBindTexImageEXT; 3070 glx.ReleaseTexImageEXT = Fake_glXReleaseTexImageEXT; 3071 3072 return &glx; 3073 } 3074