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