1 /* 2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) 3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice including the dates of first publication and 13 * either this permission notice or a reference to 14 * http://oss.sgi.com/projects/FreeB/ 15 * shall be included 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 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 * SOFTWARE. 24 * 25 * Except as contained in this notice, the name of Silicon Graphics, Inc. 26 * shall not be used in advertising or otherwise to promote the sale, use or 27 * other dealings in this Software without prior written authorization from 28 * Silicon Graphics, Inc. 29 */ 30 31 #include <stdio.h> 32 #include <assert.h> 33 #include "glxclient.h" 34 #include "packsingle.h" 35 #include "glxextensions.h" 36 #include "indirect.h" 37 #include "indirect_vertex_array.h" 38 #include "glapi.h" 39 #ifdef USE_XCB 40 #include <xcb/xcb.h> 41 #include <xcb/glx.h> 42 #include <X11/Xlib-xcb.h> 43 #endif /* USE_XCB */ 44 45 #if !defined(__GNUC__) 46 # define __builtin_expect(x, y) x 47 #endif 48 49 /* Used for GL_ARB_transpose_matrix */ 50 static void 51 TransposeMatrixf(GLfloat m[16]) 52 { 53 int i, j; 54 for (i = 0; i < 4; i++) { 55 for (j = 0; j < i; j++) { 56 GLfloat tmp = m[i * 4 + j]; 57 m[i * 4 + j] = m[j * 4 + i]; 58 m[j * 4 + i] = tmp; 59 } 60 } 61 } 62 63 /* Used for GL_ARB_transpose_matrix */ 64 static void 65 TransposeMatrixb(GLboolean m[16]) 66 { 67 int i, j; 68 for (i = 0; i < 4; i++) { 69 for (j = 0; j < i; j++) { 70 GLboolean tmp = m[i * 4 + j]; 71 m[i * 4 + j] = m[j * 4 + i]; 72 m[j * 4 + i] = tmp; 73 } 74 } 75 } 76 77 /* Used for GL_ARB_transpose_matrix */ 78 static void 79 TransposeMatrixd(GLdouble m[16]) 80 { 81 int i, j; 82 for (i = 0; i < 4; i++) { 83 for (j = 0; j < i; j++) { 84 GLdouble tmp = m[i * 4 + j]; 85 m[i * 4 + j] = m[j * 4 + i]; 86 m[j * 4 + i] = tmp; 87 } 88 } 89 } 90 91 /* Used for GL_ARB_transpose_matrix */ 92 static void 93 TransposeMatrixi(GLint m[16]) 94 { 95 int i, j; 96 for (i = 0; i < 4; i++) { 97 for (j = 0; j < i; j++) { 98 GLint tmp = m[i * 4 + j]; 99 m[i * 4 + j] = m[j * 4 + i]; 100 m[j * 4 + i] = tmp; 101 } 102 } 103 } 104 105 106 /** 107 * Remap a transpose-matrix enum to a non-transpose-matrix enum. Enums 108 * that are not transpose-matrix enums are unaffected. 109 */ 110 static GLenum 111 RemapTransposeEnum(GLenum e) 112 { 113 switch (e) { 114 case GL_TRANSPOSE_MODELVIEW_MATRIX: 115 case GL_TRANSPOSE_PROJECTION_MATRIX: 116 case GL_TRANSPOSE_TEXTURE_MATRIX: 117 return e - (GL_TRANSPOSE_MODELVIEW_MATRIX - GL_MODELVIEW_MATRIX); 118 case GL_TRANSPOSE_COLOR_MATRIX: 119 return GL_COLOR_MATRIX; 120 default: 121 return e; 122 }; 123 } 124 125 126 GLenum 127 __indirect_glGetError(void) 128 { 129 __GLX_SINGLE_DECLARE_VARIABLES(); 130 GLuint retval = GL_NO_ERROR; 131 xGLXGetErrorReply reply; 132 133 if (gc->error) { 134 /* Use internal error first */ 135 retval = gc->error; 136 gc->error = GL_NO_ERROR; 137 return retval; 138 } 139 140 __GLX_SINGLE_LOAD_VARIABLES(); 141 __GLX_SINGLE_BEGIN(X_GLsop_GetError, 0); 142 __GLX_SINGLE_READ_XREPLY(); 143 retval = reply.error; 144 __GLX_SINGLE_END(); 145 146 return retval; 147 } 148 149 150 /** 151 * Get the selected attribute from the client state. 152 * 153 * \returns 154 * On success \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned. 155 */ 156 static GLboolean 157 get_client_data(struct glx_context * gc, GLenum cap, GLintptr * data) 158 { 159 GLboolean retval = GL_TRUE; 160 __GLXattribute *state = (__GLXattribute *) (gc->client_state_private); 161 const GLint tex_unit = __glXGetActiveTextureUnit(state); 162 163 164 switch (cap) { 165 case GL_VERTEX_ARRAY: 166 case GL_NORMAL_ARRAY: 167 case GL_COLOR_ARRAY: 168 case GL_INDEX_ARRAY: 169 case GL_EDGE_FLAG_ARRAY: 170 case GL_SECONDARY_COLOR_ARRAY: 171 case GL_FOG_COORD_ARRAY: 172 retval = __glXGetArrayEnable(state, cap, 0, data); 173 break; 174 175 case GL_VERTEX_ARRAY_SIZE: 176 retval = __glXGetArraySize(state, GL_VERTEX_ARRAY, 0, data); 177 break; 178 case GL_COLOR_ARRAY_SIZE: 179 retval = __glXGetArraySize(state, GL_COLOR_ARRAY, 0, data); 180 break; 181 case GL_SECONDARY_COLOR_ARRAY_SIZE: 182 retval = __glXGetArraySize(state, GL_SECONDARY_COLOR_ARRAY, 0, data); 183 break; 184 185 case GL_VERTEX_ARRAY_TYPE: 186 retval = __glXGetArrayType(state, GL_VERTEX_ARRAY, 0, data); 187 break; 188 case GL_NORMAL_ARRAY_TYPE: 189 retval = __glXGetArrayType(state, GL_NORMAL_ARRAY, 0, data); 190 break; 191 case GL_INDEX_ARRAY_TYPE: 192 retval = __glXGetArrayType(state, GL_INDEX_ARRAY, 0, data); 193 break; 194 case GL_COLOR_ARRAY_TYPE: 195 retval = __glXGetArrayType(state, GL_COLOR_ARRAY, 0, data); 196 break; 197 case GL_SECONDARY_COLOR_ARRAY_TYPE: 198 retval = __glXGetArrayType(state, GL_SECONDARY_COLOR_ARRAY, 0, data); 199 break; 200 case GL_FOG_COORD_ARRAY_TYPE: 201 retval = __glXGetArrayType(state, GL_FOG_COORD_ARRAY, 0, data); 202 break; 203 204 case GL_VERTEX_ARRAY_STRIDE: 205 retval = __glXGetArrayStride(state, GL_VERTEX_ARRAY, 0, data); 206 break; 207 case GL_NORMAL_ARRAY_STRIDE: 208 retval = __glXGetArrayStride(state, GL_NORMAL_ARRAY, 0, data); 209 break; 210 case GL_INDEX_ARRAY_STRIDE: 211 retval = __glXGetArrayStride(state, GL_INDEX_ARRAY, 0, data); 212 break; 213 case GL_EDGE_FLAG_ARRAY_STRIDE: 214 retval = __glXGetArrayStride(state, GL_EDGE_FLAG_ARRAY, 0, data); 215 break; 216 case GL_COLOR_ARRAY_STRIDE: 217 retval = __glXGetArrayStride(state, GL_COLOR_ARRAY, 0, data); 218 break; 219 case GL_SECONDARY_COLOR_ARRAY_STRIDE: 220 retval = __glXGetArrayStride(state, GL_SECONDARY_COLOR_ARRAY, 0, data); 221 break; 222 case GL_FOG_COORD_ARRAY_STRIDE: 223 retval = __glXGetArrayStride(state, GL_FOG_COORD_ARRAY, 0, data); 224 break; 225 226 case GL_TEXTURE_COORD_ARRAY: 227 retval = 228 __glXGetArrayEnable(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data); 229 break; 230 case GL_TEXTURE_COORD_ARRAY_SIZE: 231 retval = 232 __glXGetArraySize(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data); 233 break; 234 case GL_TEXTURE_COORD_ARRAY_TYPE: 235 retval = 236 __glXGetArrayType(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data); 237 break; 238 case GL_TEXTURE_COORD_ARRAY_STRIDE: 239 retval = 240 __glXGetArrayStride(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data); 241 break; 242 243 case GL_MAX_ELEMENTS_VERTICES: 244 case GL_MAX_ELEMENTS_INDICES: 245 retval = GL_TRUE; 246 *data = ~0UL; 247 break; 248 249 250 case GL_PACK_ROW_LENGTH: 251 *data = (GLintptr) state->storePack.rowLength; 252 break; 253 case GL_PACK_IMAGE_HEIGHT: 254 *data = (GLintptr) state->storePack.imageHeight; 255 break; 256 case GL_PACK_SKIP_ROWS: 257 *data = (GLintptr) state->storePack.skipRows; 258 break; 259 case GL_PACK_SKIP_PIXELS: 260 *data = (GLintptr) state->storePack.skipPixels; 261 break; 262 case GL_PACK_SKIP_IMAGES: 263 *data = (GLintptr) state->storePack.skipImages; 264 break; 265 case GL_PACK_ALIGNMENT: 266 *data = (GLintptr) state->storePack.alignment; 267 break; 268 case GL_PACK_SWAP_BYTES: 269 *data = (GLintptr) state->storePack.swapEndian; 270 break; 271 case GL_PACK_LSB_FIRST: 272 *data = (GLintptr) state->storePack.lsbFirst; 273 break; 274 case GL_UNPACK_ROW_LENGTH: 275 *data = (GLintptr) state->storeUnpack.rowLength; 276 break; 277 case GL_UNPACK_IMAGE_HEIGHT: 278 *data = (GLintptr) state->storeUnpack.imageHeight; 279 break; 280 case GL_UNPACK_SKIP_ROWS: 281 *data = (GLintptr) state->storeUnpack.skipRows; 282 break; 283 case GL_UNPACK_SKIP_PIXELS: 284 *data = (GLintptr) state->storeUnpack.skipPixels; 285 break; 286 case GL_UNPACK_SKIP_IMAGES: 287 *data = (GLintptr) state->storeUnpack.skipImages; 288 break; 289 case GL_UNPACK_ALIGNMENT: 290 *data = (GLintptr) state->storeUnpack.alignment; 291 break; 292 case GL_UNPACK_SWAP_BYTES: 293 *data = (GLintptr) state->storeUnpack.swapEndian; 294 break; 295 case GL_UNPACK_LSB_FIRST: 296 *data = (GLintptr) state->storeUnpack.lsbFirst; 297 break; 298 case GL_CLIENT_ATTRIB_STACK_DEPTH: 299 *data = (GLintptr) (gc->attributes.stackPointer - gc->attributes.stack); 300 break; 301 case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: 302 *data = (GLintptr) __GL_CLIENT_ATTRIB_STACK_DEPTH; 303 break; 304 case GL_CLIENT_ACTIVE_TEXTURE: 305 *data = (GLintptr) (tex_unit + GL_TEXTURE0); 306 break; 307 308 default: 309 retval = GL_FALSE; 310 break; 311 } 312 313 314 return retval; 315 } 316 317 318 void 319 __indirect_glGetBooleanv(GLenum val, GLboolean * b) 320 { 321 const GLenum origVal = val; 322 __GLX_SINGLE_DECLARE_VARIABLES(); 323 xGLXSingleReply reply; 324 325 val = RemapTransposeEnum(val); 326 327 __GLX_SINGLE_LOAD_VARIABLES(); 328 __GLX_SINGLE_BEGIN(X_GLsop_GetBooleanv, 4); 329 __GLX_SINGLE_PUT_LONG(0, val); 330 __GLX_SINGLE_READ_XREPLY(); 331 __GLX_SINGLE_GET_SIZE(compsize); 332 333 if (compsize == 0) { 334 /* 335 ** Error occured; don't modify user's buffer. 336 */ 337 } 338 else { 339 GLintptr data; 340 341 /* 342 ** We still needed to send the request to the server in order to 343 ** find out whether it was legal to make a query (it's illegal, 344 ** for example, to call a query between glBegin() and glEnd()). 345 */ 346 347 if (get_client_data(gc, val, &data)) { 348 *b = (GLboolean) data; 349 } 350 else { 351 /* 352 ** Not a local value, so use what we got from the server. 353 */ 354 if (compsize == 1) { 355 __GLX_SINGLE_GET_CHAR(b); 356 } 357 else { 358 __GLX_SINGLE_GET_CHAR_ARRAY(b, compsize); 359 if (val != origVal) { 360 /* matrix transpose */ 361 TransposeMatrixb(b); 362 } 363 } 364 } 365 } 366 __GLX_SINGLE_END(); 367 } 368 369 void 370 __indirect_glGetDoublev(GLenum val, GLdouble * d) 371 { 372 const GLenum origVal = val; 373 __GLX_SINGLE_DECLARE_VARIABLES(); 374 xGLXSingleReply reply; 375 376 val = RemapTransposeEnum(val); 377 378 __GLX_SINGLE_LOAD_VARIABLES(); 379 __GLX_SINGLE_BEGIN(X_GLsop_GetDoublev, 4); 380 __GLX_SINGLE_PUT_LONG(0, val); 381 __GLX_SINGLE_READ_XREPLY(); 382 __GLX_SINGLE_GET_SIZE(compsize); 383 384 if (compsize == 0) { 385 /* 386 ** Error occured; don't modify user's buffer. 387 */ 388 } 389 else { 390 GLintptr data; 391 392 /* 393 ** We still needed to send the request to the server in order to 394 ** find out whether it was legal to make a query (it's illegal, 395 ** for example, to call a query between glBegin() and glEnd()). 396 */ 397 398 if (get_client_data(gc, val, &data)) { 399 *d = (GLdouble) data; 400 } 401 else { 402 /* 403 ** Not a local value, so use what we got from the server. 404 */ 405 if (compsize == 1) { 406 __GLX_SINGLE_GET_DOUBLE(d); 407 } 408 else { 409 __GLX_SINGLE_GET_DOUBLE_ARRAY(d, compsize); 410 if (val != origVal) { 411 /* matrix transpose */ 412 TransposeMatrixd(d); 413 } 414 } 415 } 416 } 417 __GLX_SINGLE_END(); 418 } 419 420 void 421 __indirect_glGetFloatv(GLenum val, GLfloat * f) 422 { 423 const GLenum origVal = val; 424 __GLX_SINGLE_DECLARE_VARIABLES(); 425 xGLXSingleReply reply; 426 427 val = RemapTransposeEnum(val); 428 429 __GLX_SINGLE_LOAD_VARIABLES(); 430 __GLX_SINGLE_BEGIN(X_GLsop_GetFloatv, 4); 431 __GLX_SINGLE_PUT_LONG(0, val); 432 __GLX_SINGLE_READ_XREPLY(); 433 __GLX_SINGLE_GET_SIZE(compsize); 434 435 if (compsize == 0) { 436 /* 437 ** Error occured; don't modify user's buffer. 438 */ 439 } 440 else { 441 GLintptr data; 442 443 /* 444 ** We still needed to send the request to the server in order to 445 ** find out whether it was legal to make a query (it's illegal, 446 ** for example, to call a query between glBegin() and glEnd()). 447 */ 448 449 if (get_client_data(gc, val, &data)) { 450 *f = (GLfloat) data; 451 } 452 else { 453 /* 454 ** Not a local value, so use what we got from the server. 455 */ 456 if (compsize == 1) { 457 __GLX_SINGLE_GET_FLOAT(f); 458 } 459 else { 460 __GLX_SINGLE_GET_FLOAT_ARRAY(f, compsize); 461 if (val != origVal) { 462 /* matrix transpose */ 463 TransposeMatrixf(f); 464 } 465 } 466 } 467 } 468 __GLX_SINGLE_END(); 469 } 470 471 void 472 __indirect_glGetIntegerv(GLenum val, GLint * i) 473 { 474 const GLenum origVal = val; 475 __GLX_SINGLE_DECLARE_VARIABLES(); 476 xGLXSingleReply reply; 477 478 val = RemapTransposeEnum(val); 479 480 __GLX_SINGLE_LOAD_VARIABLES(); 481 __GLX_SINGLE_BEGIN(X_GLsop_GetIntegerv, 4); 482 __GLX_SINGLE_PUT_LONG(0, val); 483 __GLX_SINGLE_READ_XREPLY(); 484 __GLX_SINGLE_GET_SIZE(compsize); 485 486 if (compsize == 0) { 487 /* 488 ** Error occured; don't modify user's buffer. 489 */ 490 } 491 else { 492 GLintptr data; 493 494 /* 495 ** We still needed to send the request to the server in order to 496 ** find out whether it was legal to make a query (it's illegal, 497 ** for example, to call a query between glBegin() and glEnd()). 498 */ 499 500 if (get_client_data(gc, val, &data)) { 501 *i = (GLint) data; 502 } 503 else { 504 /* 505 ** Not a local value, so use what we got from the server. 506 */ 507 if (compsize == 1) { 508 __GLX_SINGLE_GET_LONG(i); 509 } 510 else { 511 __GLX_SINGLE_GET_LONG_ARRAY(i, compsize); 512 if (val != origVal) { 513 /* matrix transpose */ 514 TransposeMatrixi(i); 515 } 516 } 517 } 518 } 519 __GLX_SINGLE_END(); 520 } 521 522 /* 523 ** Send all pending commands to server. 524 */ 525 void 526 __indirect_glFlush(void) 527 { 528 __GLX_SINGLE_DECLARE_VARIABLES(); 529 530 if (!dpy) 531 return; 532 533 __GLX_SINGLE_LOAD_VARIABLES(); 534 __GLX_SINGLE_BEGIN(X_GLsop_Flush, 0); 535 __GLX_SINGLE_END(); 536 537 /* And finally flush the X protocol data */ 538 XFlush(dpy); 539 } 540 541 void 542 __indirect_glFeedbackBuffer(GLsizei size, GLenum type, GLfloat * buffer) 543 { 544 __GLX_SINGLE_DECLARE_VARIABLES(); 545 546 if (!dpy) 547 return; 548 549 __GLX_SINGLE_LOAD_VARIABLES(); 550 __GLX_SINGLE_BEGIN(X_GLsop_FeedbackBuffer, 8); 551 __GLX_SINGLE_PUT_LONG(0, size); 552 __GLX_SINGLE_PUT_LONG(4, type); 553 __GLX_SINGLE_END(); 554 555 gc->feedbackBuf = buffer; 556 } 557 558 void 559 __indirect_glSelectBuffer(GLsizei numnames, GLuint * buffer) 560 { 561 __GLX_SINGLE_DECLARE_VARIABLES(); 562 563 if (!dpy) 564 return; 565 566 __GLX_SINGLE_LOAD_VARIABLES(); 567 __GLX_SINGLE_BEGIN(X_GLsop_SelectBuffer, 4); 568 __GLX_SINGLE_PUT_LONG(0, numnames); 569 __GLX_SINGLE_END(); 570 571 gc->selectBuf = buffer; 572 } 573 574 GLint 575 __indirect_glRenderMode(GLenum mode) 576 { 577 __GLX_SINGLE_DECLARE_VARIABLES(); 578 GLint retval = 0; 579 xGLXRenderModeReply reply; 580 581 if (!dpy) 582 return -1; 583 584 __GLX_SINGLE_LOAD_VARIABLES(); 585 __GLX_SINGLE_BEGIN(X_GLsop_RenderMode, 4); 586 __GLX_SINGLE_PUT_LONG(0, mode); 587 __GLX_SINGLE_READ_XREPLY(); 588 __GLX_SINGLE_GET_RETVAL(retval, GLint); 589 590 if (reply.newMode != mode) { 591 /* 592 ** Switch to new mode did not take effect, therefore an error 593 ** occured. When an error happens the server won't send us any 594 ** other data. 595 */ 596 } 597 else { 598 /* Read the feedback or selection data */ 599 if (gc->renderMode == GL_FEEDBACK) { 600 __GLX_SINGLE_GET_SIZE(compsize); 601 __GLX_SINGLE_GET_FLOAT_ARRAY(gc->feedbackBuf, compsize); 602 } 603 else if (gc->renderMode == GL_SELECT) { 604 __GLX_SINGLE_GET_SIZE(compsize); 605 __GLX_SINGLE_GET_LONG_ARRAY(gc->selectBuf, compsize); 606 } 607 gc->renderMode = mode; 608 } 609 __GLX_SINGLE_END(); 610 611 return retval; 612 } 613 614 void 615 __indirect_glFinish(void) 616 { 617 __GLX_SINGLE_DECLARE_VARIABLES(); 618 xGLXSingleReply reply; 619 620 __GLX_SINGLE_LOAD_VARIABLES(); 621 __GLX_SINGLE_BEGIN(X_GLsop_Finish, 0); 622 __GLX_SINGLE_READ_XREPLY(); 623 __GLX_SINGLE_END(); 624 } 625 626 627 /** 628 * Extract the major and minor version numbers from a version string. 629 */ 630 static void 631 version_from_string(const char *ver, int *major_version, int *minor_version) 632 { 633 const char *end; 634 long major; 635 long minor; 636 637 major = strtol(ver, (char **) &end, 10); 638 minor = strtol(end + 1, NULL, 10); 639 *major_version = major; 640 *minor_version = minor; 641 } 642 643 644 const GLubyte * 645 __indirect_glGetString(GLenum name) 646 { 647 struct glx_context *gc = __glXGetCurrentContext(); 648 Display *dpy = gc->currentDpy; 649 GLubyte *s = NULL; 650 651 if (!dpy) 652 return 0; 653 654 /* 655 ** Return the cached copy if the string has already been fetched 656 */ 657 switch (name) { 658 case GL_VENDOR: 659 if (gc->vendor) 660 return gc->vendor; 661 break; 662 case GL_RENDERER: 663 if (gc->renderer) 664 return gc->renderer; 665 break; 666 case GL_VERSION: 667 if (gc->version) 668 return gc->version; 669 break; 670 case GL_EXTENSIONS: 671 if (gc->extensions) 672 return gc->extensions; 673 break; 674 default: 675 __glXSetError(gc, GL_INVALID_ENUM); 676 return 0; 677 } 678 679 /* 680 ** Get requested string from server 681 */ 682 683 (void) __glXFlushRenderBuffer(gc, gc->pc); 684 s = (GLubyte *) __glXGetString(dpy, gc->majorOpcode, gc->currentContextTag, 685 name); 686 if (!s) { 687 /* Throw data on the floor */ 688 __glXSetError(gc, GL_OUT_OF_MEMORY); 689 } 690 else { 691 /* 692 ** Update local cache 693 */ 694 switch (name) { 695 case GL_VENDOR: 696 gc->vendor = s; 697 break; 698 699 case GL_RENDERER: 700 gc->renderer = s; 701 break; 702 703 case GL_VERSION:{ 704 int client_major; 705 int client_minor; 706 707 version_from_string((char *) s, 708 &gc->server_major, &gc->server_minor); 709 __glXGetGLVersion(&client_major, &client_minor); 710 711 if ((gc->server_major < client_major) 712 || ((gc->server_major == client_major) 713 && (gc->server_minor <= client_minor))) { 714 gc->version = s; 715 } 716 else { 717 /* Allow 7 bytes for the client-side GL version. This allows 718 * for upto version 999.999. I'm not holding my breath for 719 * that one! The extra 4 is for the ' ()\0' that will be 720 * added. 721 */ 722 const size_t size = 7 + strlen((char *) s) + 4; 723 724 gc->version = Xmalloc(size); 725 if (gc->version == NULL) { 726 /* If we couldn't allocate memory for the new string, 727 * make a best-effort and just copy the client-side version 728 * to the string and use that. It probably doesn't 729 * matter what is done here. If there not memory available 730 * for a short string, the system is probably going to die 731 * soon anyway. 732 */ 733 snprintf((char *) s, strlen((char *) s) + 1, "%u.%u", 734 client_major, client_minor); 735 gc->version = s; 736 } 737 else { 738 snprintf((char *) gc->version, size, "%u.%u (%s)", 739 client_major, client_minor, s); 740 Xfree(s); 741 s = gc->version; 742 } 743 } 744 break; 745 } 746 747 case GL_EXTENSIONS:{ 748 int major = 1; 749 int minor = 0; 750 751 /* This code is currently disabled. I was reminded that some 752 * vendors intentionally exclude some extensions from their 753 * extension string that are part of the core version they 754 * advertise. In particular, on Nvidia drivers this means that 755 * the functionality is supported by the driver, but is not 756 * hardware accelerated. For example, a TNT will show core 757 * version 1.5, but most of the post-1.2 functionality is a 758 * software fallback. 759 * 760 * I don't want to break applications that rely on this odd 761 * behavior. At the same time, the code is written and tested, 762 * so I didn't want to throw it away. Therefore, the code is here 763 * but disabled. In the future, we may wish to and an environment 764 * variable to enable it. 765 */ 766 767 #if 0 768 /* Call glGetString just to make sure that gc->server_major and 769 * gc->server_minor are set. This version may be higher than we 770 * can completely support, but it may imply support for some 771 * extensions that we can support. 772 * 773 * For example, at the time of this writing, the client-side 774 * library only supports upto core GL version 1.2. However, cubic 775 * textures, multitexture, multisampling, and some other 1.3 776 * features are supported. If the server reports back version 777 * 1.3, but does not report all of those extensions, we will 778 * enable them. 779 */ 780 (void *) glGetString(GL_VERSION); 781 major = gc->server_major, minor = gc->server_minor; 782 #endif 783 784 __glXCalculateUsableGLExtensions(gc, (char *) s, major, minor); 785 XFree(s); 786 s = gc->extensions; 787 break; 788 } 789 } 790 } 791 return s; 792 } 793 794 GLboolean 795 __indirect_glIsEnabled(GLenum cap) 796 { 797 __GLX_SINGLE_DECLARE_VARIABLES(); 798 __GLXattribute *state = (__GLXattribute *) (gc->client_state_private); 799 xGLXSingleReply reply; 800 GLboolean retval = 0; 801 GLintptr enable; 802 803 if (!dpy) 804 return 0; 805 806 switch (cap) { 807 case GL_VERTEX_ARRAY: 808 case GL_NORMAL_ARRAY: 809 case GL_COLOR_ARRAY: 810 case GL_INDEX_ARRAY: 811 case GL_EDGE_FLAG_ARRAY: 812 case GL_SECONDARY_COLOR_ARRAY: 813 case GL_FOG_COORD_ARRAY: 814 retval = __glXGetArrayEnable(state, cap, 0, &enable); 815 assert(retval); 816 return (GLboolean) enable; 817 break; 818 case GL_TEXTURE_COORD_ARRAY: 819 retval = __glXGetArrayEnable(state, GL_TEXTURE_COORD_ARRAY, 820 __glXGetActiveTextureUnit(state), &enable); 821 assert(retval); 822 return (GLboolean) enable; 823 break; 824 } 825 826 __GLX_SINGLE_LOAD_VARIABLES(); 827 __GLX_SINGLE_BEGIN(X_GLsop_IsEnabled, 4); 828 __GLX_SINGLE_PUT_LONG(0, cap); 829 __GLX_SINGLE_READ_XREPLY(); 830 __GLX_SINGLE_GET_RETVAL(retval, GLboolean); 831 __GLX_SINGLE_END(); 832 return retval; 833 } 834 835 void 836 __indirect_glGetPointerv(GLenum pname, void **params) 837 { 838 struct glx_context *gc = __glXGetCurrentContext(); 839 __GLXattribute *state = (__GLXattribute *) (gc->client_state_private); 840 Display *dpy = gc->currentDpy; 841 842 if (!dpy) 843 return; 844 845 switch (pname) { 846 case GL_VERTEX_ARRAY_POINTER: 847 case GL_NORMAL_ARRAY_POINTER: 848 case GL_COLOR_ARRAY_POINTER: 849 case GL_INDEX_ARRAY_POINTER: 850 case GL_EDGE_FLAG_ARRAY_POINTER: 851 __glXGetArrayPointer(state, pname - GL_VERTEX_ARRAY_POINTER 852 + GL_VERTEX_ARRAY, 0, params); 853 return; 854 case GL_TEXTURE_COORD_ARRAY_POINTER: 855 __glXGetArrayPointer(state, GL_TEXTURE_COORD_ARRAY, 856 __glXGetActiveTextureUnit(state), params); 857 return; 858 case GL_SECONDARY_COLOR_ARRAY_POINTER: 859 case GL_FOG_COORD_ARRAY_POINTER: 860 __glXGetArrayPointer(state, pname - GL_FOG_COORD_ARRAY_POINTER 861 + GL_FOG_COORD_ARRAY, 0, params); 862 return; 863 case GL_FEEDBACK_BUFFER_POINTER: 864 *params = (void *) gc->feedbackBuf; 865 return; 866 case GL_SELECTION_BUFFER_POINTER: 867 *params = (void *) gc->selectBuf; 868 return; 869 default: 870 __glXSetError(gc, GL_INVALID_ENUM); 871 return; 872 } 873 } 874 875 876 877 /** 878 * This was previously auto-generated, but we need to special-case 879 * how we handle writing into the 'residences' buffer when n%4!=0. 880 */ 881 #define X_GLsop_AreTexturesResident 143 882 GLboolean 883 __indirect_glAreTexturesResident(GLsizei n, const GLuint * textures, 884 GLboolean * residences) 885 { 886 struct glx_context *const gc = __glXGetCurrentContext(); 887 Display *const dpy = gc->currentDpy; 888 GLboolean retval = (GLboolean) 0; 889 if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) { 890 #ifdef USE_XCB 891 xcb_connection_t *c = XGetXCBConnection(dpy); 892 (void) __glXFlushRenderBuffer(gc, gc->pc); 893 xcb_glx_are_textures_resident_reply_t *reply = 894 xcb_glx_are_textures_resident_reply(c, 895 xcb_glx_are_textures_resident 896 (c, gc->currentContextTag, n, 897 textures), NULL); 898 (void) memcpy(residences, xcb_glx_are_textures_resident_data(reply), 899 xcb_glx_are_textures_resident_data_length(reply) * 900 sizeof(GLboolean)); 901 retval = reply->ret_val; 902 free(reply); 903 #else 904 const GLuint cmdlen = 4 + __GLX_PAD((n * 4)); 905 GLubyte const *pc = 906 __glXSetupSingleRequest(gc, X_GLsop_AreTexturesResident, cmdlen); 907 (void) memcpy((void *) (pc + 0), (void *) (&n), 4); 908 (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4)); 909 if (n & 3) { 910 /* n is not a multiple of four. 911 * When reply_is_always_array is TRUE, __glXReadReply() will 912 * put a multiple of four bytes into the dest buffer. If the 913 * caller's buffer is not a multiple of four in size, we'll write 914 * out of bounds. So use a temporary buffer that's a few bytes 915 * larger. 916 */ 917 GLboolean *res4 = malloc((n + 3) & ~3); 918 retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE); 919 memcpy(residences, res4, n); 920 free(res4); 921 } 922 else { 923 retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE); 924 } 925 UnlockDisplay(dpy); 926 SyncHandle(); 927 #endif /* USE_XCB */ 928 } 929 return retval; 930 } 931 932 933 /** 934 * This was previously auto-generated, but we need to special-case 935 * how we handle writing into the 'residences' buffer when n%4!=0. 936 */ 937 #define X_GLvop_AreTexturesResidentEXT 11 938 GLboolean 939 glAreTexturesResidentEXT(GLsizei n, const GLuint * textures, 940 GLboolean * residences) 941 { 942 struct glx_context *const gc = __glXGetCurrentContext(); 943 944 if (gc->isDirect) { 945 const _glapi_proc *const table = (_glapi_proc *) GET_DISPATCH(); 946 PFNGLARETEXTURESRESIDENTEXTPROC p = 947 (PFNGLARETEXTURESRESIDENTEXTPROC) table[332]; 948 949 return p(n, textures, residences); 950 } 951 else { 952 struct glx_context *const gc = __glXGetCurrentContext(); 953 Display *const dpy = gc->currentDpy; 954 GLboolean retval = (GLboolean) 0; 955 const GLuint cmdlen = 4 + __GLX_PAD((n * 4)); 956 if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) { 957 GLubyte const *pc = 958 __glXSetupVendorRequest(gc, X_GLXVendorPrivateWithReply, 959 X_GLvop_AreTexturesResidentEXT, 960 cmdlen); 961 (void) memcpy((void *) (pc + 0), (void *) (&n), 4); 962 (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4)); 963 if (n & 3) { 964 /* see comments in __indirect_glAreTexturesResident() */ 965 GLboolean *res4 = malloc((n + 3) & ~3); 966 retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE); 967 memcpy(residences, res4, n); 968 free(res4); 969 } 970 else { 971 retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE); 972 } 973 UnlockDisplay(dpy); 974 SyncHandle(); 975 } 976 return retval; 977 } 978 } 979