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