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