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