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