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