glx_api.c revision 37be707f57df72071a43b9899dec063730c338f5
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 case GLX_SAMPLES_ARB: 836 parselist++; 837 if (*parselist++ != 0) { 838 /* ms not supported */ 839 return NULL; 840 } 841 break; 842 843 /* 844 * FBConfig attribs. 845 */ 846 case GLX_RENDER_TYPE: 847 if (!fbConfig) 848 return NULL; 849 parselist++; 850 if (*parselist & GLX_RGBA_BIT) { 851 rgb_flag = GL_TRUE; 852 } 853 else if (*parselist & GLX_COLOR_INDEX_BIT) { 854 rgb_flag = GL_FALSE; 855 } 856 else if (*parselist == 0) { 857 rgb_flag = GL_TRUE; 858 } 859 parselist++; 860 break; 861 case GLX_DRAWABLE_TYPE: 862 if (!fbConfig) 863 return NULL; 864 parselist++; 865 if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) { 866 return NULL; /* bad bit */ 867 } 868 parselist++; 869 break; 870 case GLX_FBCONFIG_ID: 871 case GLX_VISUAL_ID: 872 if (!fbConfig) 873 return NULL; 874 parselist++; 875 desiredVisualID = *parselist++; 876 break; 877 case GLX_X_RENDERABLE: 878 case GLX_MAX_PBUFFER_WIDTH: 879 case GLX_MAX_PBUFFER_HEIGHT: 880 case GLX_MAX_PBUFFER_PIXELS: 881 if (!fbConfig) 882 return NULL; /* invalid config option */ 883 parselist += 2; /* ignore the parameter */ 884 break; 885 886#ifdef GLX_EXT_texture_from_pixmap 887 case GLX_BIND_TO_TEXTURE_RGB_EXT: 888 parselist++; /*skip*/ 889 break; 890 case GLX_BIND_TO_TEXTURE_RGBA_EXT: 891 parselist++; /*skip*/ 892 break; 893 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 894 parselist++; /*skip*/ 895 break; 896 case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 897 parselist++; 898 if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT | 899 GLX_TEXTURE_2D_BIT_EXT | 900 GLX_TEXTURE_RECTANGLE_BIT_EXT)) { 901 /* invalid bit */ 902 return NULL; 903 } 904 break; 905 case GLX_Y_INVERTED_EXT: 906 parselist++; /*skip*/ 907 break; 908#endif 909 910 case None: 911 /* end of list */ 912 break; 913 914 default: 915 /* undefined attribute */ 916 _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()", 917 *parselist); 918 return NULL; 919 } 920 } 921 922 (void) caveat; 923 924 925 /* 926 * Since we're only simulating the GLX extension this function will never 927 * find any real GL visuals. Instead, all we can do is try to find an RGB 928 * or CI visual of appropriate depth. Other requested attributes such as 929 * double buffering, depth buffer, etc. will be associated with the X 930 * visual and stored in the VisualTable[]. 931 */ 932 if (desiredVisualID != -1) { 933 /* try to get a specific visual, by visualID */ 934 XVisualInfo temp; 935 int n; 936 temp.visualid = desiredVisualID; 937 temp.screen = screen; 938 vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n); 939 if (vis) { 940 /* give the visual some useful GLX attributes */ 941 double_flag = GL_TRUE; 942 rgb_flag = GL_TRUE; 943 } 944 } 945 else if (level==0) { 946 /* normal color planes */ 947 /* Get an RGB visual */ 948 int min_rgb = min_red + min_green + min_blue; 949 if (min_rgb>1 && min_rgb<8) { 950 /* a special case to be sure we can get a monochrome visual */ 951 min_rgb = 1; 952 } 953 vis = choose_x_visual( dpy, screen, min_rgb, visual_type ); 954 } 955 else { 956 _mesa_warning(NULL, "overlay not supported"); 957 return NULL; 958 } 959 960 if (vis) { 961 /* Note: we're not exactly obeying the glXChooseVisual rules here. 962 * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the 963 * largest depth buffer size, which is 32bits/value. Instead, we 964 * return 16 to maintain performance with earlier versions of Mesa. 965 */ 966 if (stencil_size > 0) 967 depth_size = 24; /* if Z and stencil, always use 24+8 format */ 968 else if (depth_size > 24) 969 depth_size = 32; 970 else if (depth_size > 16) 971 depth_size = 24; 972 else if (depth_size > 0) { 973 depth_size = default_depth_bits(); 974 } 975 976 if (!alpha_flag) { 977 alpha_flag = default_alpha_bits() > 0; 978 } 979 980 /* we only support one size of stencil and accum buffers. */ 981 if (stencil_size > 0) 982 stencil_size = 8; 983 984 if (accumRedSize > 0 || 985 accumGreenSize > 0 || 986 accumBlueSize > 0 || 987 accumAlphaSize > 0) { 988 989 accumRedSize = 990 accumGreenSize = 991 accumBlueSize = default_accum_bits(); 992 993 accumAlphaSize = alpha_flag ? accumRedSize : 0; 994 } 995 996 xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, 997 stereo_flag, depth_size, stencil_size, 998 accumRedSize, accumGreenSize, 999 accumBlueSize, accumAlphaSize, level, numAux ); 1000 } 1001 1002 return xmvis; 1003} 1004 1005 1006PUBLIC XVisualInfo * 1007glXChooseVisual( Display *dpy, int screen, int *list ) 1008{ 1009 XMesaVisual xmvis; 1010 1011 /* register ourselves as an extension on this display */ 1012 register_with_display(dpy); 1013 1014 xmvis = choose_visual(dpy, screen, list, GL_FALSE); 1015 if (xmvis) { 1016 /* create a new vishandle - the cached one may be stale */ 1017 xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo)); 1018 if (xmvis->vishandle) { 1019 memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); 1020 } 1021 return xmvis->vishandle; 1022 } 1023 else 1024 return NULL; 1025} 1026 1027 1028/** 1029 * Helper function used by other glXCreateContext functions. 1030 */ 1031static GLXContext 1032create_context(Display *dpy, XMesaVisual xmvis, 1033 XMesaContext shareCtx, Bool direct, 1034 unsigned major, unsigned minor, 1035 unsigned profileMask, unsigned contextFlags) 1036{ 1037 GLXContext glxCtx; 1038 1039 if (!dpy || !xmvis) 1040 return 0; 1041 1042 glxCtx = CALLOC_STRUCT(__GLXcontextRec); 1043 if (!glxCtx) 1044 return 0; 1045 1046 /* deallocate unused windows/buffers */ 1047#if 0 1048 XMesaGarbageCollect(); 1049#endif 1050 1051 glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx, major, minor, 1052 profileMask, contextFlags); 1053 if (!glxCtx->xmesaContext) { 1054 free(glxCtx); 1055 return NULL; 1056 } 1057 1058 glxCtx->isDirect = DEFAULT_DIRECT; 1059 glxCtx->currentDpy = dpy; 1060 glxCtx->xid = (XID) glxCtx; /* self pointer */ 1061 1062 return glxCtx; 1063} 1064 1065 1066PUBLIC GLXContext 1067glXCreateContext( Display *dpy, XVisualInfo *visinfo, 1068 GLXContext shareCtx, Bool direct ) 1069{ 1070 XMesaVisual xmvis; 1071 1072 xmvis = find_glx_visual( dpy, visinfo ); 1073 if (!xmvis) { 1074 /* This visual wasn't found with glXChooseVisual() */ 1075 xmvis = create_glx_visual( dpy, visinfo ); 1076 if (!xmvis) { 1077 /* unusable visual */ 1078 return NULL; 1079 } 1080 } 1081 1082 return create_context(dpy, xmvis, 1083 shareCtx ? shareCtx->xmesaContext : NULL, 1084 direct, 1085 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0); 1086} 1087 1088 1089/* XXX these may have to be removed due to thread-safety issues. */ 1090static GLXContext MakeCurrent_PrevContext = 0; 1091static GLXDrawable MakeCurrent_PrevDrawable = 0; 1092static GLXDrawable MakeCurrent_PrevReadable = 0; 1093static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0; 1094static XMesaBuffer MakeCurrent_PrevReadBuffer = 0; 1095 1096 1097/* GLX 1.3 and later */ 1098PUBLIC Bool 1099glXMakeContextCurrent( Display *dpy, GLXDrawable draw, 1100 GLXDrawable read, GLXContext ctx ) 1101{ 1102 GLXContext glxCtx = ctx; 1103 static boolean firsttime = 1, no_rast = 0; 1104 1105 if (firsttime) { 1106 no_rast = getenv("SP_NO_RAST") != NULL; 1107 firsttime = 0; 1108 } 1109 1110 if (ctx && draw && read) { 1111 XMesaBuffer drawBuffer, readBuffer; 1112 XMesaContext xmctx = glxCtx->xmesaContext; 1113 1114 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */ 1115 if (ctx == MakeCurrent_PrevContext 1116 && draw == MakeCurrent_PrevDrawable) { 1117 drawBuffer = MakeCurrent_PrevDrawBuffer; 1118 } 1119 else { 1120 drawBuffer = XMesaFindBuffer( dpy, draw ); 1121 } 1122 if (!drawBuffer) { 1123 /* drawable must be a new window! */ 1124 drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw ); 1125 if (!drawBuffer) { 1126 /* Out of memory, or context/drawable depth mismatch */ 1127 return False; 1128 } 1129 } 1130 1131 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */ 1132 if (ctx == MakeCurrent_PrevContext 1133 && read == MakeCurrent_PrevReadable) { 1134 readBuffer = MakeCurrent_PrevReadBuffer; 1135 } 1136 else { 1137 readBuffer = XMesaFindBuffer( dpy, read ); 1138 } 1139 if (!readBuffer) { 1140 /* drawable must be a new window! */ 1141 readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read ); 1142 if (!readBuffer) { 1143 /* Out of memory, or context/drawable depth mismatch */ 1144 return False; 1145 } 1146 } 1147 1148 if (no_rast && 1149 MakeCurrent_PrevContext == ctx && 1150 MakeCurrent_PrevDrawable == draw && 1151 MakeCurrent_PrevReadable == read && 1152 MakeCurrent_PrevDrawBuffer == drawBuffer && 1153 MakeCurrent_PrevReadBuffer == readBuffer) 1154 return True; 1155 1156 MakeCurrent_PrevContext = ctx; 1157 MakeCurrent_PrevDrawable = draw; 1158 MakeCurrent_PrevReadable = read; 1159 MakeCurrent_PrevDrawBuffer = drawBuffer; 1160 MakeCurrent_PrevReadBuffer = readBuffer; 1161 1162 /* Now make current! */ 1163 if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { 1164 ctx->currentDpy = dpy; 1165 ctx->currentDrawable = draw; 1166 ctx->currentReadable = read; 1167 SetCurrentContext(ctx); 1168 return True; 1169 } 1170 else { 1171 return False; 1172 } 1173 } 1174 else if (!ctx && !draw && !read) { 1175 /* release current context w/out assigning new one. */ 1176 XMesaMakeCurrent2( NULL, NULL, NULL ); 1177 MakeCurrent_PrevContext = 0; 1178 MakeCurrent_PrevDrawable = 0; 1179 MakeCurrent_PrevReadable = 0; 1180 MakeCurrent_PrevDrawBuffer = 0; 1181 MakeCurrent_PrevReadBuffer = 0; 1182 SetCurrentContext(NULL); 1183 return True; 1184 } 1185 else { 1186 /* The args must either all be non-zero or all zero. 1187 * This is an error. 1188 */ 1189 return False; 1190 } 1191} 1192 1193 1194PUBLIC Bool 1195glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) 1196{ 1197 return glXMakeContextCurrent( dpy, drawable, drawable, ctx ); 1198} 1199 1200 1201PUBLIC GLXContext 1202glXGetCurrentContext(void) 1203{ 1204 return GetCurrentContext(); 1205} 1206 1207 1208PUBLIC Display * 1209glXGetCurrentDisplay(void) 1210{ 1211 GLXContext glxCtx = glXGetCurrentContext(); 1212 1213 return glxCtx ? glxCtx->currentDpy : NULL; 1214} 1215 1216 1217PUBLIC Display * 1218glXGetCurrentDisplayEXT(void) 1219{ 1220 return glXGetCurrentDisplay(); 1221} 1222 1223 1224PUBLIC GLXDrawable 1225glXGetCurrentDrawable(void) 1226{ 1227 GLXContext gc = glXGetCurrentContext(); 1228 return gc ? gc->currentDrawable : 0; 1229} 1230 1231 1232PUBLIC GLXDrawable 1233glXGetCurrentReadDrawable(void) 1234{ 1235 GLXContext gc = glXGetCurrentContext(); 1236 return gc ? gc->currentReadable : 0; 1237} 1238 1239 1240PUBLIC GLXDrawable 1241glXGetCurrentReadDrawableSGI(void) 1242{ 1243 return glXGetCurrentReadDrawable(); 1244} 1245 1246 1247PUBLIC GLXPixmap 1248glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) 1249{ 1250 XMesaVisual v; 1251 XMesaBuffer b; 1252 1253 v = find_glx_visual( dpy, visinfo ); 1254 if (!v) { 1255 v = create_glx_visual( dpy, visinfo ); 1256 if (!v) { 1257 /* unusable visual */ 1258 return 0; 1259 } 1260 } 1261 1262 b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); 1263 if (!b) { 1264 return 0; 1265 } 1266 return b->ws.drawable; 1267} 1268 1269 1270/*** GLX_MESA_pixmap_colormap ***/ 1271 1272PUBLIC GLXPixmap 1273glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, 1274 Pixmap pixmap, Colormap cmap ) 1275{ 1276 XMesaVisual v; 1277 XMesaBuffer b; 1278 1279 v = find_glx_visual( dpy, visinfo ); 1280 if (!v) { 1281 v = create_glx_visual( dpy, visinfo ); 1282 if (!v) { 1283 /* unusable visual */ 1284 return 0; 1285 } 1286 } 1287 1288 b = XMesaCreatePixmapBuffer( v, pixmap, cmap ); 1289 if (!b) { 1290 return 0; 1291 } 1292 return b->ws.drawable; 1293} 1294 1295 1296PUBLIC void 1297glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) 1298{ 1299 XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); 1300 if (b) { 1301 XMesaDestroyBuffer(b); 1302 } 1303 else if (_mesa_getenv("MESA_DEBUG")) { 1304 _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); 1305 } 1306} 1307 1308 1309PUBLIC void 1310glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, 1311 unsigned long mask ) 1312{ 1313 XMesaContext xm_src = src->xmesaContext; 1314 XMesaContext xm_dst = dst->xmesaContext; 1315 (void) dpy; 1316 if (MakeCurrent_PrevContext == src) { 1317 glFlush(); 1318 } 1319 XMesaCopyContext(xm_src, xm_dst, mask); 1320} 1321 1322 1323PUBLIC Bool 1324glXQueryExtension( Display *dpy, int *errorBase, int *eventBase ) 1325{ 1326 int op, ev, err; 1327 /* Mesa's GLX isn't really an X extension but we try to act like one. */ 1328 if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err)) 1329 ev = err = 0; 1330 if (errorBase) 1331 *errorBase = err; 1332 if (eventBase) 1333 *eventBase = ev; 1334 return True; /* we're faking GLX so always return success */ 1335} 1336 1337 1338PUBLIC void 1339glXDestroyContext( Display *dpy, GLXContext ctx ) 1340{ 1341 GLXContext glxCtx = ctx; 1342 (void) dpy; 1343 MakeCurrent_PrevContext = 0; 1344 MakeCurrent_PrevDrawable = 0; 1345 MakeCurrent_PrevReadable = 0; 1346 MakeCurrent_PrevDrawBuffer = 0; 1347 MakeCurrent_PrevReadBuffer = 0; 1348 XMesaDestroyContext( glxCtx->xmesaContext ); 1349 XMesaGarbageCollect(); 1350 free(glxCtx); 1351} 1352 1353 1354PUBLIC Bool 1355glXIsDirect( Display *dpy, GLXContext ctx ) 1356{ 1357 GLXContext glxCtx = ctx; 1358 (void) ctx; 1359 return glxCtx->isDirect; 1360} 1361 1362 1363 1364PUBLIC void 1365glXSwapBuffers( Display *dpy, GLXDrawable drawable ) 1366{ 1367 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); 1368 static boolean firsttime = 1, no_rast = 0; 1369 1370 if (firsttime) { 1371 no_rast = getenv("SP_NO_RAST") != NULL; 1372 firsttime = 0; 1373 } 1374 1375 if (no_rast) 1376 return; 1377 1378 if (buffer) { 1379 XMesaSwapBuffers(buffer); 1380 } 1381 else if (_mesa_getenv("MESA_DEBUG")) { 1382 _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n", 1383 (int) drawable); 1384 } 1385} 1386 1387 1388 1389/*** GLX_MESA_copy_sub_buffer ***/ 1390 1391PUBLIC void 1392glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, 1393 int x, int y, int width, int height) 1394{ 1395 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); 1396 if (buffer) { 1397 XMesaCopySubBuffer(buffer, x, y, width, height); 1398 } 1399 else if (_mesa_getenv("MESA_DEBUG")) { 1400 _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n"); 1401 } 1402} 1403 1404 1405PUBLIC Bool 1406glXQueryVersion( Display *dpy, int *maj, int *min ) 1407{ 1408 (void) dpy; 1409 /* Return GLX version, not Mesa version */ 1410 assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION); 1411 *maj = CLIENT_MAJOR_VERSION; 1412 *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION ); 1413 return True; 1414} 1415 1416 1417/* 1418 * Query the GLX attributes of the given XVisualInfo. 1419 */ 1420static int 1421get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) 1422{ 1423 ASSERT(xmvis); 1424 switch(attrib) { 1425 case GLX_USE_GL: 1426 if (fbconfig) 1427 return GLX_BAD_ATTRIBUTE; 1428 *value = (int) True; 1429 return 0; 1430 case GLX_BUFFER_SIZE: 1431 *value = xmvis->visinfo->depth; 1432 return 0; 1433 case GLX_LEVEL: 1434 *value = xmvis->mesa_visual.level; 1435 return 0; 1436 case GLX_RGBA: 1437 if (fbconfig) 1438 return GLX_BAD_ATTRIBUTE; 1439 if (xmvis->mesa_visual.rgbMode) { 1440 *value = True; 1441 } 1442 else { 1443 *value = False; 1444 } 1445 return 0; 1446 case GLX_DOUBLEBUFFER: 1447 *value = (int) xmvis->mesa_visual.doubleBufferMode; 1448 return 0; 1449 case GLX_STEREO: 1450 *value = (int) xmvis->mesa_visual.stereoMode; 1451 return 0; 1452 case GLX_AUX_BUFFERS: 1453 *value = xmvis->mesa_visual.numAuxBuffers; 1454 return 0; 1455 case GLX_RED_SIZE: 1456 *value = xmvis->mesa_visual.redBits; 1457 return 0; 1458 case GLX_GREEN_SIZE: 1459 *value = xmvis->mesa_visual.greenBits; 1460 return 0; 1461 case GLX_BLUE_SIZE: 1462 *value = xmvis->mesa_visual.blueBits; 1463 return 0; 1464 case GLX_ALPHA_SIZE: 1465 *value = xmvis->mesa_visual.alphaBits; 1466 return 0; 1467 case GLX_DEPTH_SIZE: 1468 *value = xmvis->mesa_visual.depthBits; 1469 return 0; 1470 case GLX_STENCIL_SIZE: 1471 *value = xmvis->mesa_visual.stencilBits; 1472 return 0; 1473 case GLX_ACCUM_RED_SIZE: 1474 *value = xmvis->mesa_visual.accumRedBits; 1475 return 0; 1476 case GLX_ACCUM_GREEN_SIZE: 1477 *value = xmvis->mesa_visual.accumGreenBits; 1478 return 0; 1479 case GLX_ACCUM_BLUE_SIZE: 1480 *value = xmvis->mesa_visual.accumBlueBits; 1481 return 0; 1482 case GLX_ACCUM_ALPHA_SIZE: 1483 *value = xmvis->mesa_visual.accumAlphaBits; 1484 return 0; 1485 1486 /* 1487 * GLX_EXT_visual_info extension 1488 */ 1489 case GLX_X_VISUAL_TYPE_EXT: 1490 switch (xmvis->visinfo->CLASS) { 1491 case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0; 1492 case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0; 1493 case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0; 1494 case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0; 1495 case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0; 1496 case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0; 1497 } 1498 return 0; 1499 case GLX_TRANSPARENT_TYPE_EXT: 1500 /* normal planes */ 1501 *value = GLX_NONE_EXT; 1502 return 0; 1503 case GLX_TRANSPARENT_INDEX_VALUE_EXT: 1504 /* undefined */ 1505 return 0; 1506 case GLX_TRANSPARENT_RED_VALUE_EXT: 1507 /* undefined */ 1508 return 0; 1509 case GLX_TRANSPARENT_GREEN_VALUE_EXT: 1510 /* undefined */ 1511 return 0; 1512 case GLX_TRANSPARENT_BLUE_VALUE_EXT: 1513 /* undefined */ 1514 return 0; 1515 case GLX_TRANSPARENT_ALPHA_VALUE_EXT: 1516 /* undefined */ 1517 return 0; 1518 1519 /* 1520 * GLX_EXT_visual_info extension 1521 */ 1522 case GLX_VISUAL_CAVEAT_EXT: 1523 /* test for zero, just in case */ 1524 if (xmvis->mesa_visual.visualRating > 0) 1525 *value = xmvis->mesa_visual.visualRating; 1526 else 1527 *value = GLX_NONE_EXT; 1528 return 0; 1529 1530 /* 1531 * GLX_ARB_multisample 1532 */ 1533 case GLX_SAMPLE_BUFFERS_ARB: 1534 *value = 0; 1535 return 0; 1536 case GLX_SAMPLES_ARB: 1537 *value = 0; 1538 return 0; 1539 1540 /* 1541 * For FBConfigs: 1542 */ 1543 case GLX_SCREEN_EXT: 1544 if (!fbconfig) 1545 return GLX_BAD_ATTRIBUTE; 1546 *value = xmvis->visinfo->screen; 1547 break; 1548 case GLX_DRAWABLE_TYPE: /*SGIX too */ 1549 if (!fbconfig) 1550 return GLX_BAD_ATTRIBUTE; 1551 *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; 1552 break; 1553 case GLX_RENDER_TYPE_SGIX: 1554 if (!fbconfig) 1555 return GLX_BAD_ATTRIBUTE; 1556 if (xmvis->mesa_visual.rgbMode) 1557 *value = GLX_RGBA_BIT; 1558 else 1559 *value = GLX_COLOR_INDEX_BIT; 1560 break; 1561 case GLX_X_RENDERABLE_SGIX: 1562 if (!fbconfig) 1563 return GLX_BAD_ATTRIBUTE; 1564 *value = True; /* XXX really? */ 1565 break; 1566 case GLX_FBCONFIG_ID_SGIX: 1567 if (!fbconfig) 1568 return GLX_BAD_ATTRIBUTE; 1569 *value = xmvis->visinfo->visualid; 1570 break; 1571 case GLX_MAX_PBUFFER_WIDTH: 1572 if (!fbconfig) 1573 return GLX_BAD_ATTRIBUTE; 1574 /* XXX or MAX_WIDTH? */ 1575 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen); 1576 break; 1577 case GLX_MAX_PBUFFER_HEIGHT: 1578 if (!fbconfig) 1579 return GLX_BAD_ATTRIBUTE; 1580 *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen); 1581 break; 1582 case GLX_MAX_PBUFFER_PIXELS: 1583 if (!fbconfig) 1584 return GLX_BAD_ATTRIBUTE; 1585 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) * 1586 DisplayHeight(xmvis->display, xmvis->visinfo->screen); 1587 break; 1588 case GLX_VISUAL_ID: 1589 if (!fbconfig) 1590 return GLX_BAD_ATTRIBUTE; 1591 *value = xmvis->visinfo->visualid; 1592 break; 1593 1594#ifdef GLX_EXT_texture_from_pixmap 1595 case GLX_BIND_TO_TEXTURE_RGB_EXT: 1596 *value = True; /*XXX*/ 1597 break; 1598 case GLX_BIND_TO_TEXTURE_RGBA_EXT: 1599 /* XXX review */ 1600 *value = xmvis->mesa_visual.alphaBits > 0 ? True : False; 1601 break; 1602 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: 1603 *value = True; /*XXX*/ 1604 break; 1605 case GLX_BIND_TO_TEXTURE_TARGETS_EXT: 1606 *value = (GLX_TEXTURE_1D_BIT_EXT | 1607 GLX_TEXTURE_2D_BIT_EXT | 1608 GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/ 1609 break; 1610 case GLX_Y_INVERTED_EXT: 1611 *value = True; /*XXX*/ 1612 break; 1613#endif 1614 1615 default: 1616 return GLX_BAD_ATTRIBUTE; 1617 } 1618 return Success; 1619} 1620 1621 1622PUBLIC int 1623glXGetConfig( Display *dpy, XVisualInfo *visinfo, 1624 int attrib, int *value ) 1625{ 1626 XMesaVisual xmvis; 1627 int k; 1628 if (!dpy || !visinfo) 1629 return GLX_BAD_ATTRIBUTE; 1630 1631 xmvis = find_glx_visual( dpy, visinfo ); 1632 if (!xmvis) { 1633 /* this visual wasn't obtained with glXChooseVisual */ 1634 xmvis = create_glx_visual( dpy, visinfo ); 1635 if (!xmvis) { 1636 /* this visual can't be used for GL rendering */ 1637 if (attrib==GLX_USE_GL) { 1638 *value = (int) False; 1639 return 0; 1640 } 1641 else { 1642 return GLX_BAD_VISUAL; 1643 } 1644 } 1645 } 1646 1647 k = get_config(xmvis, attrib, value, GL_FALSE); 1648 return k; 1649} 1650 1651 1652PUBLIC void 1653glXWaitGL( void ) 1654{ 1655 XMesaContext xmesa = XMesaGetCurrentContext(); 1656 XMesaFlush( xmesa ); 1657} 1658 1659 1660 1661PUBLIC void 1662glXWaitX( void ) 1663{ 1664 XMesaContext xmesa = XMesaGetCurrentContext(); 1665 XMesaFlush( xmesa ); 1666} 1667 1668 1669static const char * 1670get_extensions( void ) 1671{ 1672 return EXTENSIONS; 1673} 1674 1675 1676 1677/* GLX 1.1 and later */ 1678PUBLIC const char * 1679glXQueryExtensionsString( Display *dpy, int screen ) 1680{ 1681 (void) dpy; 1682 (void) screen; 1683 return get_extensions(); 1684} 1685 1686 1687 1688/* GLX 1.1 and later */ 1689PUBLIC const char * 1690glXQueryServerString( Display *dpy, int screen, int name ) 1691{ 1692 static char version[1000]; 1693 sprintf(version, "%d.%d %s", 1694 SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name()); 1695 1696 (void) dpy; 1697 (void) screen; 1698 1699 switch (name) { 1700 case GLX_EXTENSIONS: 1701 return get_extensions(); 1702 case GLX_VENDOR: 1703 return VENDOR; 1704 case GLX_VERSION: 1705 return version; 1706 default: 1707 return NULL; 1708 } 1709} 1710 1711 1712 1713/* GLX 1.1 and later */ 1714PUBLIC const char * 1715glXGetClientString( Display *dpy, int name ) 1716{ 1717 static char version[1000]; 1718 sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, 1719 CLIENT_MINOR_VERSION, xmesa_get_name()); 1720 1721 (void) dpy; 1722 1723 switch (name) { 1724 case GLX_EXTENSIONS: 1725 return get_extensions(); 1726 case GLX_VENDOR: 1727 return VENDOR; 1728 case GLX_VERSION: 1729 return version; 1730 default: 1731 return NULL; 1732 } 1733} 1734 1735 1736 1737/* 1738 * GLX 1.3 and later 1739 */ 1740 1741 1742PUBLIC int 1743glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, 1744 int attribute, int *value) 1745{ 1746 XMesaVisual v = (XMesaVisual) config; 1747 (void) dpy; 1748 (void) config; 1749 1750 if (!dpy || !config || !value) 1751 return -1; 1752 1753 return get_config(v, attribute, value, GL_TRUE); 1754} 1755 1756 1757PUBLIC GLXFBConfig * 1758glXGetFBConfigs( Display *dpy, int screen, int *nelements ) 1759{ 1760 XVisualInfo *visuals, visTemplate; 1761 const long visMask = VisualScreenMask; 1762 int i; 1763 1764 /* Get list of all X visuals */ 1765 visTemplate.screen = screen; 1766 visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements); 1767 if (*nelements > 0) { 1768 XMesaVisual *results; 1769 results = (XMesaVisual *) malloc(*nelements * sizeof(XMesaVisual)); 1770 if (!results) { 1771 *nelements = 0; 1772 return NULL; 1773 } 1774 for (i = 0; i < *nelements; i++) { 1775 results[i] = create_glx_visual(dpy, visuals + i); 1776 if (!results[i]) { 1777 *nelements = i; 1778 break; 1779 } 1780 } 1781 return (GLXFBConfig *) results; 1782 } 1783 return NULL; 1784} 1785 1786 1787PUBLIC GLXFBConfig * 1788glXChooseFBConfig(Display *dpy, int screen, 1789 const int *attribList, int *nitems) 1790{ 1791 XMesaVisual xmvis; 1792 1793 /* register ourselves as an extension on this display */ 1794 register_with_display(dpy); 1795 1796 if (!attribList || !attribList[0]) { 1797 /* return list of all configs (per GLX_SGIX_fbconfig spec) */ 1798 return glXGetFBConfigs(dpy, screen, nitems); 1799 } 1800 1801 xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); 1802 if (xmvis) { 1803 GLXFBConfig *config = (GLXFBConfig *) malloc(sizeof(XMesaVisual)); 1804 if (!config) { 1805 *nitems = 0; 1806 return NULL; 1807 } 1808 *nitems = 1; 1809 config[0] = (GLXFBConfig) xmvis; 1810 return (GLXFBConfig *) config; 1811 } 1812 else { 1813 *nitems = 0; 1814 return NULL; 1815 } 1816} 1817 1818 1819PUBLIC XVisualInfo * 1820glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) 1821{ 1822 if (dpy && config) { 1823 XMesaVisual xmvis = (XMesaVisual) config; 1824#if 0 1825 return xmvis->vishandle; 1826#else 1827 /* create a new vishandle - the cached one may be stale */ 1828 xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo)); 1829 if (xmvis->vishandle) { 1830 memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); 1831 } 1832 return xmvis->vishandle; 1833#endif 1834 } 1835 else { 1836 return NULL; 1837 } 1838} 1839 1840 1841PUBLIC GLXWindow 1842glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, 1843 const int *attribList) 1844{ 1845 XMesaVisual xmvis = (XMesaVisual) config; 1846 XMesaBuffer xmbuf; 1847 if (!xmvis) 1848 return 0; 1849 1850 xmbuf = XMesaCreateWindowBuffer(xmvis, win); 1851 if (!xmbuf) 1852 return 0; 1853 1854 (void) dpy; 1855 (void) attribList; /* Ignored in GLX 1.3 */ 1856 1857 return win; /* A hack for now */ 1858} 1859 1860 1861PUBLIC void 1862glXDestroyWindow( Display *dpy, GLXWindow window ) 1863{ 1864 XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window); 1865 if (b) 1866 XMesaDestroyBuffer(b); 1867 /* don't destroy X window */ 1868} 1869 1870 1871/* XXX untested */ 1872PUBLIC GLXPixmap 1873glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, 1874 const int *attribList) 1875{ 1876 XMesaVisual v = (XMesaVisual) config; 1877 XMesaBuffer b; 1878 const int *attr; 1879 int target = 0, format = 0, mipmap = 0; 1880 int value; 1881 1882 if (!dpy || !config || !pixmap) 1883 return 0; 1884 1885 for (attr = attribList; attr && *attr; attr++) { 1886 switch (*attr) { 1887 case GLX_TEXTURE_FORMAT_EXT: 1888 attr++; 1889 switch (*attr) { 1890 case GLX_TEXTURE_FORMAT_NONE_EXT: 1891 case GLX_TEXTURE_FORMAT_RGB_EXT: 1892 case GLX_TEXTURE_FORMAT_RGBA_EXT: 1893 format = *attr; 1894 break; 1895 default: 1896 /* error */ 1897 return 0; 1898 } 1899 break; 1900 case GLX_TEXTURE_TARGET_EXT: 1901 attr++; 1902 switch (*attr) { 1903 case GLX_TEXTURE_1D_EXT: 1904 case GLX_TEXTURE_2D_EXT: 1905 case GLX_TEXTURE_RECTANGLE_EXT: 1906 target = *attr; 1907 break; 1908 default: 1909 /* error */ 1910 return 0; 1911 } 1912 break; 1913 case GLX_MIPMAP_TEXTURE_EXT: 1914 attr++; 1915 if (*attr) 1916 mipmap = 1; 1917 break; 1918 default: 1919 /* error */ 1920 return 0; 1921 } 1922 } 1923 1924 if (format == GLX_TEXTURE_FORMAT_RGB_EXT) { 1925 if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT, 1926 &value, GL_TRUE) != Success 1927 || !value) { 1928 return 0; /* error! */ 1929 } 1930 } 1931 else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) { 1932 if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT, 1933 &value, GL_TRUE) != Success 1934 || !value) { 1935 return 0; /* error! */ 1936 } 1937 } 1938 if (mipmap) { 1939 if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT, 1940 &value, GL_TRUE) != Success 1941 || !value) { 1942 return 0; /* error! */ 1943 } 1944 } 1945 if (target == GLX_TEXTURE_1D_EXT) { 1946 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1947 &value, GL_TRUE) != Success 1948 || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) { 1949 return 0; /* error! */ 1950 } 1951 } 1952 else if (target == GLX_TEXTURE_2D_EXT) { 1953 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1954 &value, GL_TRUE) != Success 1955 || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) { 1956 return 0; /* error! */ 1957 } 1958 } 1959 if (target == GLX_TEXTURE_RECTANGLE_EXT) { 1960 if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, 1961 &value, GL_TRUE) != Success 1962 || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) { 1963 return 0; /* error! */ 1964 } 1965 } 1966 1967 if (format || target || mipmap) { 1968 /* texture from pixmap */ 1969 b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap); 1970 } 1971 else { 1972 b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); 1973 } 1974 if (!b) { 1975 return 0; 1976 } 1977 1978 return pixmap; 1979} 1980 1981 1982PUBLIC void 1983glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) 1984{ 1985 XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap); 1986 if (b) 1987 XMesaDestroyBuffer(b); 1988 /* don't destroy X pixmap */ 1989} 1990 1991 1992PUBLIC GLXPbuffer 1993glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList) 1994{ 1995 XMesaVisual xmvis = (XMesaVisual) config; 1996 XMesaBuffer xmbuf; 1997 const int *attrib; 1998 int width = 0, height = 0; 1999 GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; 2000 2001 (void) dpy; 2002 2003 for (attrib = attribList; *attrib; attrib++) { 2004 switch (*attrib) { 2005 case GLX_PBUFFER_WIDTH: 2006 attrib++; 2007 width = *attrib; 2008 break; 2009 case GLX_PBUFFER_HEIGHT: 2010 attrib++; 2011 height = *attrib; 2012 break; 2013 case GLX_PRESERVED_CONTENTS: 2014 attrib++; 2015 preserveContents = *attrib; 2016 break; 2017 case GLX_LARGEST_PBUFFER: 2018 attrib++; 2019 useLargest = *attrib; 2020 break; 2021 default: 2022 return 0; 2023 } 2024 } 2025 2026 if (width == 0 || height == 0) 2027 return 0; 2028 2029 if (width > PBUFFER_MAX_SIZE || height > PBUFFER_MAX_SIZE) { 2030 /* If allocation would have failed and GLX_LARGEST_PBUFFER is set, 2031 * allocate the largest possible buffer. 2032 */ 2033 if (useLargest) { 2034 width = PBUFFER_MAX_SIZE; 2035 height = PBUFFER_MAX_SIZE; 2036 } 2037 } 2038 2039 xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); 2040 /* A GLXPbuffer handle must be an X Drawable because that's what 2041 * glXMakeCurrent takes. 2042 */ 2043 if (xmbuf) { 2044 xmbuf->largestPbuffer = useLargest; 2045 xmbuf->preservedContents = preserveContents; 2046 return (GLXPbuffer) xmbuf->ws.drawable; 2047 } 2048 else { 2049 return 0; 2050 } 2051} 2052 2053 2054PUBLIC void 2055glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) 2056{ 2057 XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); 2058 if (b) { 2059 XMesaDestroyBuffer(b); 2060 } 2061} 2062 2063 2064PUBLIC void 2065glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, 2066 unsigned int *value) 2067{ 2068 GLuint width, height; 2069 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); 2070 if (!xmbuf) 2071 return; 2072 2073 /* make sure buffer's dimensions are up to date */ 2074 xmesa_get_window_size(dpy, xmbuf, &width, &height); 2075 2076 switch (attribute) { 2077 case GLX_WIDTH: 2078 *value = width; 2079 break; 2080 case GLX_HEIGHT: 2081 *value = height; 2082 break; 2083 case GLX_PRESERVED_CONTENTS: 2084 *value = xmbuf->preservedContents; 2085 break; 2086 case GLX_LARGEST_PBUFFER: 2087 *value = xmbuf->largestPbuffer; 2088 break; 2089 case GLX_FBCONFIG_ID: 2090 *value = xmbuf->xm_visual->visinfo->visualid; 2091 return; 2092#ifdef GLX_EXT_texture_from_pixmap 2093 case GLX_TEXTURE_FORMAT_EXT: 2094 *value = xmbuf->TextureFormat; 2095 break; 2096 case GLX_TEXTURE_TARGET_EXT: 2097 *value = xmbuf->TextureTarget; 2098 break; 2099 case GLX_MIPMAP_TEXTURE_EXT: 2100 *value = xmbuf->TextureMipmap; 2101 break; 2102#endif 2103 2104 default: 2105 return; /* raise BadValue error */ 2106 } 2107} 2108 2109 2110PUBLIC GLXContext 2111glXCreateNewContext( Display *dpy, GLXFBConfig config, 2112 int renderType, GLXContext shareCtx, Bool direct ) 2113{ 2114 XMesaVisual xmvis = (XMesaVisual) config; 2115 2116 if (!dpy || !config || 2117 (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) 2118 return 0; 2119 2120 return create_context(dpy, xmvis, 2121 shareCtx ? shareCtx->xmesaContext : NULL, 2122 direct, 2123 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0); 2124} 2125 2126 2127PUBLIC int 2128glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) 2129{ 2130 GLXContext glxCtx = ctx; 2131 XMesaContext xmctx = glxCtx->xmesaContext; 2132 2133 (void) dpy; 2134 (void) ctx; 2135 2136 switch (attribute) { 2137 case GLX_FBCONFIG_ID: 2138 *value = xmctx->xm_visual->visinfo->visualid; 2139 break; 2140 case GLX_RENDER_TYPE: 2141 if (xmctx->xm_visual->mesa_visual.rgbMode) 2142 *value = GLX_RGBA_TYPE; 2143 else 2144 *value = GLX_COLOR_INDEX_TYPE; 2145 break; 2146 case GLX_SCREEN: 2147 *value = 0; 2148 return Success; 2149 default: 2150 return GLX_BAD_ATTRIBUTE; 2151 } 2152 return 0; 2153} 2154 2155 2156PUBLIC void 2157glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) 2158{ 2159 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2160 if (xmbuf) 2161 xmbuf->selectedEvents = mask; 2162} 2163 2164 2165PUBLIC void 2166glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask) 2167{ 2168 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2169 if (xmbuf) 2170 *mask = xmbuf->selectedEvents; 2171 else 2172 *mask = 0; 2173} 2174 2175 2176 2177/*** GLX_SGI_swap_control ***/ 2178 2179PUBLIC int 2180glXSwapIntervalSGI(int interval) 2181{ 2182 (void) interval; 2183 return 0; 2184} 2185 2186 2187 2188/*** GLX_SGI_video_sync ***/ 2189 2190static unsigned int FrameCounter = 0; 2191 2192PUBLIC int 2193glXGetVideoSyncSGI(unsigned int *count) 2194{ 2195 /* this is a bogus implementation */ 2196 *count = FrameCounter++; 2197 return 0; 2198} 2199 2200PUBLIC int 2201glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) 2202{ 2203 if (divisor <= 0 || remainder < 0) 2204 return GLX_BAD_VALUE; 2205 /* this is a bogus implementation */ 2206 FrameCounter++; 2207 while (FrameCounter % divisor != remainder) 2208 FrameCounter++; 2209 *count = FrameCounter; 2210 return 0; 2211} 2212 2213 2214 2215/*** GLX_SGI_make_current_read ***/ 2216 2217PUBLIC Bool 2218glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, 2219 GLXContext ctx) 2220{ 2221 return glXMakeContextCurrent( dpy, draw, read, ctx ); 2222} 2223 2224/* not used 2225static GLXDrawable 2226glXGetCurrentReadDrawableSGI(void) 2227{ 2228 return 0; 2229} 2230*/ 2231 2232 2233/*** GLX_SGIX_video_source ***/ 2234#if defined(_VL_H) 2235 2236PUBLIC GLXVideoSourceSGIX 2237glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, 2238 VLPath path, int nodeClass, VLNode drainNode) 2239{ 2240 (void) dpy; 2241 (void) screen; 2242 (void) server; 2243 (void) path; 2244 (void) nodeClass; 2245 (void) drainNode; 2246 return 0; 2247} 2248 2249PUBLIC void 2250glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) 2251{ 2252 (void) dpy; 2253 (void) src; 2254} 2255 2256#endif 2257 2258 2259/*** GLX_EXT_import_context ***/ 2260 2261PUBLIC void 2262glXFreeContextEXT(Display *dpy, GLXContext context) 2263{ 2264 (void) dpy; 2265 (void) context; 2266} 2267 2268PUBLIC GLXContextID 2269glXGetContextIDEXT(const GLXContext context) 2270{ 2271 (void) context; 2272 return 0; 2273} 2274 2275PUBLIC GLXContext 2276glXImportContextEXT(Display *dpy, GLXContextID contextID) 2277{ 2278 (void) dpy; 2279 (void) contextID; 2280 return 0; 2281} 2282 2283PUBLIC int 2284glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, 2285 int *value) 2286{ 2287 (void) dpy; 2288 (void) context; 2289 (void) attribute; 2290 (void) value; 2291 return 0; 2292} 2293 2294 2295 2296/*** GLX_SGIX_fbconfig ***/ 2297 2298PUBLIC int 2299glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, 2300 int attribute, int *value) 2301{ 2302 return glXGetFBConfigAttrib(dpy, config, attribute, value); 2303} 2304 2305PUBLIC GLXFBConfigSGIX * 2306glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, 2307 int *nelements) 2308{ 2309 return (GLXFBConfig *) glXChooseFBConfig(dpy, screen, 2310 attrib_list, nelements); 2311} 2312 2313 2314PUBLIC GLXPixmap 2315glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, 2316 Pixmap pixmap) 2317{ 2318 XMesaVisual xmvis = (XMesaVisual) config; 2319 XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); 2320 return xmbuf->ws.drawable; /* need to return an X ID */ 2321} 2322 2323 2324PUBLIC GLXContext 2325glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, 2326 int renderType, GLXContext shareCtx, 2327 Bool direct) 2328{ 2329 XMesaVisual xmvis = (XMesaVisual) config; 2330 2331 if (!dpy || !config || 2332 (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) 2333 return 0; 2334 2335 return create_context(dpy, xmvis, 2336 shareCtx ? shareCtx->xmesaContext : NULL, 2337 direct, 2338 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0); 2339} 2340 2341 2342PUBLIC XVisualInfo * 2343glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) 2344{ 2345 return glXGetVisualFromFBConfig(dpy, config); 2346} 2347 2348 2349PUBLIC GLXFBConfigSGIX 2350glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) 2351{ 2352 XMesaVisual xmvis = find_glx_visual(dpy, vis); 2353 if (!xmvis) { 2354 /* This visual wasn't found with glXChooseVisual() */ 2355 xmvis = create_glx_visual(dpy, vis); 2356 } 2357 2358 return (GLXFBConfigSGIX) xmvis; 2359} 2360 2361 2362 2363/*** GLX_SGIX_pbuffer ***/ 2364 2365PUBLIC GLXPbufferSGIX 2366glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, 2367 unsigned int width, unsigned int height, 2368 int *attribList) 2369{ 2370 XMesaVisual xmvis = (XMesaVisual) config; 2371 XMesaBuffer xmbuf; 2372 const int *attrib; 2373 GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; 2374 2375 (void) dpy; 2376 2377 for (attrib = attribList; attrib && *attrib; attrib++) { 2378 switch (*attrib) { 2379 case GLX_PRESERVED_CONTENTS_SGIX: 2380 attrib++; 2381 preserveContents = *attrib; /* ignored */ 2382 break; 2383 case GLX_LARGEST_PBUFFER_SGIX: 2384 attrib++; 2385 useLargest = *attrib; /* ignored */ 2386 break; 2387 default: 2388 return 0; 2389 } 2390 } 2391 2392 /* not used at this time */ 2393 (void) useLargest; 2394 (void) preserveContents; 2395 2396 xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); 2397 /* A GLXPbuffer handle must be an X Drawable because that's what 2398 * glXMakeCurrent takes. 2399 */ 2400 return (GLXPbuffer) xmbuf->ws.drawable; 2401} 2402 2403 2404PUBLIC void 2405glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) 2406{ 2407 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); 2408 if (xmbuf) { 2409 XMesaDestroyBuffer(xmbuf); 2410 } 2411} 2412 2413 2414PUBLIC int 2415glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, 2416 unsigned int *value) 2417{ 2418 const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); 2419 2420 if (!xmbuf) { 2421 /* Generate GLXBadPbufferSGIX for bad pbuffer */ 2422 return 0; 2423 } 2424 2425 switch (attribute) { 2426 case GLX_PRESERVED_CONTENTS_SGIX: 2427 *value = True; 2428 break; 2429 case GLX_LARGEST_PBUFFER_SGIX: 2430 *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf); 2431 break; 2432 case GLX_WIDTH_SGIX: 2433 *value = xmesa_buffer_width(xmbuf); 2434 break; 2435 case GLX_HEIGHT_SGIX: 2436 *value = xmesa_buffer_height(xmbuf); 2437 break; 2438 case GLX_EVENT_MASK_SGIX: 2439 *value = 0; /* XXX might be wrong */ 2440 break; 2441 default: 2442 *value = 0; 2443 } 2444 return 0; 2445} 2446 2447 2448PUBLIC void 2449glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) 2450{ 2451 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2452 if (xmbuf) { 2453 /* Note: we'll never generate clobber events */ 2454 xmbuf->selectedEvents = mask; 2455 } 2456} 2457 2458 2459PUBLIC void 2460glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, 2461 unsigned long *mask) 2462{ 2463 XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); 2464 if (xmbuf) { 2465 *mask = xmbuf->selectedEvents; 2466 } 2467 else { 2468 *mask = 0; 2469 } 2470} 2471 2472 2473 2474/*** GLX_SGI_cushion ***/ 2475 2476PUBLIC void 2477glXCushionSGI(Display *dpy, Window win, float cushion) 2478{ 2479 (void) dpy; 2480 (void) win; 2481 (void) cushion; 2482} 2483 2484 2485 2486/*** GLX_SGIX_video_resize ***/ 2487 2488PUBLIC int 2489glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel, 2490 Window window) 2491{ 2492 (void) dpy; 2493 (void) screen; 2494 (void) channel; 2495 (void) window; 2496 return 0; 2497} 2498 2499PUBLIC int 2500glXChannelRectSGIX(Display *dpy, int screen, int channel, 2501 int x, int y, int w, int h) 2502{ 2503 (void) dpy; 2504 (void) screen; 2505 (void) channel; 2506 (void) x; 2507 (void) y; 2508 (void) w; 2509 (void) h; 2510 return 0; 2511} 2512 2513PUBLIC int 2514glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, 2515 int *x, int *y, int *w, int *h) 2516{ 2517 (void) dpy; 2518 (void) screen; 2519 (void) channel; 2520 (void) x; 2521 (void) y; 2522 (void) w; 2523 (void) h; 2524 return 0; 2525} 2526 2527PUBLIC int 2528glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, 2529 int *dx, int *dy, int *dw, int *dh) 2530{ 2531 (void) dpy; 2532 (void) screen; 2533 (void) channel; 2534 (void) dx; 2535 (void) dy; 2536 (void) dw; 2537 (void) dh; 2538 return 0; 2539} 2540 2541PUBLIC int 2542glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) 2543{ 2544 (void) dpy; 2545 (void) screen; 2546 (void) channel; 2547 (void) synctype; 2548 return 0; 2549} 2550 2551 2552 2553/*** GLX_SGIX_dmbuffer **/ 2554 2555#if defined(_DM_BUFFER_H_) 2556PUBLIC Bool 2557glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, 2558 DMparams *params, DMbuffer dmbuffer) 2559{ 2560 (void) dpy; 2561 (void) pbuffer; 2562 (void) params; 2563 (void) dmbuffer; 2564 return False; 2565} 2566#endif 2567 2568 2569/*** GLX_SGIX_swap_group ***/ 2570 2571PUBLIC void 2572glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) 2573{ 2574 (void) dpy; 2575 (void) drawable; 2576 (void) member; 2577} 2578 2579 2580 2581/*** GLX_SGIX_swap_barrier ***/ 2582 2583PUBLIC void 2584glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) 2585{ 2586 (void) dpy; 2587 (void) drawable; 2588 (void) barrier; 2589} 2590 2591PUBLIC Bool 2592glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) 2593{ 2594 (void) dpy; 2595 (void) screen; 2596 (void) max; 2597 return False; 2598} 2599 2600 2601 2602/*** GLX_SUN_get_transparent_index ***/ 2603 2604PUBLIC Status 2605glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, 2606 long *pTransparent) 2607{ 2608 (void) dpy; 2609 (void) overlay; 2610 (void) underlay; 2611 (void) pTransparent; 2612 return 0; 2613} 2614 2615 2616 2617/*** GLX_MESA_release_buffers ***/ 2618 2619/* 2620 * Release the depth, stencil, accum buffers attached to a GLXDrawable 2621 * (a window or pixmap) prior to destroying the GLXDrawable. 2622 */ 2623PUBLIC Bool 2624glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) 2625{ 2626 XMesaBuffer b = XMesaFindBuffer(dpy, d); 2627 if (b) { 2628 XMesaDestroyBuffer(b); 2629 return True; 2630 } 2631 return False; 2632} 2633 2634/*** GLX_EXT_texture_from_pixmap ***/ 2635 2636PUBLIC void 2637glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, 2638 const int *attrib_list) 2639{ 2640 XMesaBuffer b = XMesaFindBuffer(dpy, drawable); 2641 if (b) 2642 XMesaBindTexImage(dpy, b, buffer, attrib_list); 2643} 2644 2645PUBLIC void 2646glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) 2647{ 2648 XMesaBuffer b = XMesaFindBuffer(dpy, drawable); 2649 if (b) 2650 XMesaReleaseTexImage(dpy, b, buffer); 2651} 2652 2653 2654 2655/*** GLX_ARB_create_context ***/ 2656 2657GLXContext 2658glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config, 2659 GLXContext shareCtx, Bool direct, 2660 const int *attrib_list) 2661{ 2662 XMesaVisual xmvis = (XMesaVisual) config; 2663 int majorVersion = 1, minorVersion = 0; 2664 int contextFlags = 0x0; 2665 int profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB; 2666 int renderType = GLX_RGBA_TYPE; 2667 unsigned i; 2668 Bool done = False; 2669 const int contextFlagsAll = (GLX_CONTEXT_DEBUG_BIT_ARB | 2670 GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB); 2671 2672 /* parse attrib_list */ 2673 for (i = 0; !done && attrib_list && attrib_list[i]; i++) { 2674 switch (attrib_list[i]) { 2675 case GLX_CONTEXT_MAJOR_VERSION_ARB: 2676 majorVersion = attrib_list[++i]; 2677 break; 2678 case GLX_CONTEXT_MINOR_VERSION_ARB: 2679 minorVersion = attrib_list[++i]; 2680 break; 2681 case GLX_CONTEXT_FLAGS_ARB: 2682 contextFlags = attrib_list[++i]; 2683 break; 2684 case GLX_CONTEXT_PROFILE_MASK_ARB: 2685 profileMask = attrib_list[++i]; 2686 break; 2687 case GLX_RENDER_TYPE: 2688 renderType = attrib_list[++i]; 2689 break; 2690 case 0: 2691 /* end of list */ 2692 done = True; 2693 break; 2694 default: 2695 /* bad attribute */ 2696 /* XXX generate BadValue X Error */ 2697 return NULL; 2698 } 2699 } 2700 2701 /* check contextFlags */ 2702 if (contextFlags & ~contextFlagsAll) { 2703 return NULL; /* generate BadValue X Error */ 2704 } 2705 2706 /* check profileMask */ 2707 if (profileMask != GLX_CONTEXT_CORE_PROFILE_BIT_ARB && 2708 profileMask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) { 2709 return NULL; /* generate BadValue X Error */ 2710 } 2711 2712 /* check version (generate BadMatch if bad) */ 2713 switch (majorVersion) { 2714 case 1: 2715 if (minorVersion < 0 || minorVersion > 5) 2716 return NULL; 2717 break; 2718 case 2: 2719 if (minorVersion < 0 || minorVersion > 1) 2720 return NULL; 2721 break; 2722 case 3: 2723 if (minorVersion < 0 || minorVersion > 2) 2724 return NULL; 2725 break; 2726 case 4: 2727 if (minorVersion < 0 || minorVersion > 0) 2728 return NULL; 2729 break; 2730 default: 2731 return NULL; 2732 } 2733 2734 if ((contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) && 2735 majorVersion < 3) 2736 return NULL; /* generate GLXBadProfileARB */ 2737 2738 if (renderType == GLX_COLOR_INDEX_TYPE && majorVersion >= 3) 2739 return NULL; /* generate BadMatch */ 2740 2741 return create_context(dpy, xmvis, 2742 shareCtx ? shareCtx->xmesaContext : NULL, 2743 direct, 2744 majorVersion, minorVersion, 2745 profileMask, contextFlags); 2746} 2747