| /* |
| * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008) |
| * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice including the dates of first publication and |
| * either this permission notice or a reference to |
| * http://oss.sgi.com/projects/FreeB/ |
| * shall be included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF |
| * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| * |
| * Except as contained in this notice, the name of Silicon Graphics, Inc. |
| * shall not be used in advertising or otherwise to promote the sale, use or |
| * other dealings in this Software without prior written authorization from |
| * Silicon Graphics, Inc. |
| */ |
| |
| #include <stdio.h> |
| #include <assert.h> |
| #include "glxclient.h" |
| #include "packsingle.h" |
| #include "glxextensions.h" |
| #include "indirect.h" |
| #include "indirect_vertex_array.h" |
| #include "glapi.h" |
| #include <xcb/xcb.h> |
| #include <xcb/glx.h> |
| #include <X11/Xlib-xcb.h> |
| |
| #if !defined(__GNUC__) |
| # define __builtin_expect(x, y) x |
| #endif |
| |
| /* Used for GL_ARB_transpose_matrix */ |
| static void |
| TransposeMatrixf(GLfloat m[16]) |
| { |
| int i, j; |
| for (i = 0; i < 4; i++) { |
| for (j = 0; j < i; j++) { |
| GLfloat tmp = m[i * 4 + j]; |
| m[i * 4 + j] = m[j * 4 + i]; |
| m[j * 4 + i] = tmp; |
| } |
| } |
| } |
| |
| /* Used for GL_ARB_transpose_matrix */ |
| static void |
| TransposeMatrixb(GLboolean m[16]) |
| { |
| int i, j; |
| for (i = 0; i < 4; i++) { |
| for (j = 0; j < i; j++) { |
| GLboolean tmp = m[i * 4 + j]; |
| m[i * 4 + j] = m[j * 4 + i]; |
| m[j * 4 + i] = tmp; |
| } |
| } |
| } |
| |
| /* Used for GL_ARB_transpose_matrix */ |
| static void |
| TransposeMatrixd(GLdouble m[16]) |
| { |
| int i, j; |
| for (i = 0; i < 4; i++) { |
| for (j = 0; j < i; j++) { |
| GLdouble tmp = m[i * 4 + j]; |
| m[i * 4 + j] = m[j * 4 + i]; |
| m[j * 4 + i] = tmp; |
| } |
| } |
| } |
| |
| /* Used for GL_ARB_transpose_matrix */ |
| static void |
| TransposeMatrixi(GLint m[16]) |
| { |
| int i, j; |
| for (i = 0; i < 4; i++) { |
| for (j = 0; j < i; j++) { |
| GLint tmp = m[i * 4 + j]; |
| m[i * 4 + j] = m[j * 4 + i]; |
| m[j * 4 + i] = tmp; |
| } |
| } |
| } |
| |
| |
| /** |
| * Remap a transpose-matrix enum to a non-transpose-matrix enum. Enums |
| * that are not transpose-matrix enums are unaffected. |
| */ |
| static GLenum |
| RemapTransposeEnum(GLenum e) |
| { |
| switch (e) { |
| case GL_TRANSPOSE_MODELVIEW_MATRIX: |
| case GL_TRANSPOSE_PROJECTION_MATRIX: |
| case GL_TRANSPOSE_TEXTURE_MATRIX: |
| return e - (GL_TRANSPOSE_MODELVIEW_MATRIX - GL_MODELVIEW_MATRIX); |
| case GL_TRANSPOSE_COLOR_MATRIX: |
| return GL_COLOR_MATRIX; |
| default: |
| return e; |
| }; |
| } |
| |
| |
| GLenum |
| __indirect_glGetError(void) |
| { |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| GLuint retval = GL_NO_ERROR; |
| xGLXGetErrorReply reply; |
| |
| if (gc->error) { |
| /* Use internal error first */ |
| retval = gc->error; |
| gc->error = GL_NO_ERROR; |
| return retval; |
| } |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_GetError, 0); |
| __GLX_SINGLE_READ_XREPLY(); |
| retval = reply.error; |
| __GLX_SINGLE_END(); |
| |
| return retval; |
| } |
| |
| |
| /** |
| * Get the selected attribute from the client state. |
| * |
| * \returns |
| * On success \c GL_TRUE is returned. Otherwise, \c GL_FALSE is returned. |
| */ |
| static GLboolean |
| get_client_data(struct glx_context * gc, GLenum cap, GLintptr * data) |
| { |
| GLboolean retval = GL_TRUE; |
| __GLXattribute *state = (__GLXattribute *) (gc->client_state_private); |
| const GLint tex_unit = __glXGetActiveTextureUnit(state); |
| |
| |
| switch (cap) { |
| case GL_VERTEX_ARRAY: |
| case GL_NORMAL_ARRAY: |
| case GL_COLOR_ARRAY: |
| case GL_INDEX_ARRAY: |
| case GL_EDGE_FLAG_ARRAY: |
| case GL_SECONDARY_COLOR_ARRAY: |
| case GL_FOG_COORD_ARRAY: |
| retval = __glXGetArrayEnable(state, cap, 0, data); |
| break; |
| |
| case GL_VERTEX_ARRAY_SIZE: |
| retval = __glXGetArraySize(state, GL_VERTEX_ARRAY, 0, data); |
| break; |
| case GL_COLOR_ARRAY_SIZE: |
| retval = __glXGetArraySize(state, GL_COLOR_ARRAY, 0, data); |
| break; |
| case GL_SECONDARY_COLOR_ARRAY_SIZE: |
| retval = __glXGetArraySize(state, GL_SECONDARY_COLOR_ARRAY, 0, data); |
| break; |
| |
| case GL_VERTEX_ARRAY_TYPE: |
| retval = __glXGetArrayType(state, GL_VERTEX_ARRAY, 0, data); |
| break; |
| case GL_NORMAL_ARRAY_TYPE: |
| retval = __glXGetArrayType(state, GL_NORMAL_ARRAY, 0, data); |
| break; |
| case GL_INDEX_ARRAY_TYPE: |
| retval = __glXGetArrayType(state, GL_INDEX_ARRAY, 0, data); |
| break; |
| case GL_COLOR_ARRAY_TYPE: |
| retval = __glXGetArrayType(state, GL_COLOR_ARRAY, 0, data); |
| break; |
| case GL_SECONDARY_COLOR_ARRAY_TYPE: |
| retval = __glXGetArrayType(state, GL_SECONDARY_COLOR_ARRAY, 0, data); |
| break; |
| case GL_FOG_COORD_ARRAY_TYPE: |
| retval = __glXGetArrayType(state, GL_FOG_COORD_ARRAY, 0, data); |
| break; |
| |
| case GL_VERTEX_ARRAY_STRIDE: |
| retval = __glXGetArrayStride(state, GL_VERTEX_ARRAY, 0, data); |
| break; |
| case GL_NORMAL_ARRAY_STRIDE: |
| retval = __glXGetArrayStride(state, GL_NORMAL_ARRAY, 0, data); |
| break; |
| case GL_INDEX_ARRAY_STRIDE: |
| retval = __glXGetArrayStride(state, GL_INDEX_ARRAY, 0, data); |
| break; |
| case GL_EDGE_FLAG_ARRAY_STRIDE: |
| retval = __glXGetArrayStride(state, GL_EDGE_FLAG_ARRAY, 0, data); |
| break; |
| case GL_COLOR_ARRAY_STRIDE: |
| retval = __glXGetArrayStride(state, GL_COLOR_ARRAY, 0, data); |
| break; |
| case GL_SECONDARY_COLOR_ARRAY_STRIDE: |
| retval = __glXGetArrayStride(state, GL_SECONDARY_COLOR_ARRAY, 0, data); |
| break; |
| case GL_FOG_COORD_ARRAY_STRIDE: |
| retval = __glXGetArrayStride(state, GL_FOG_COORD_ARRAY, 0, data); |
| break; |
| |
| case GL_TEXTURE_COORD_ARRAY: |
| retval = |
| __glXGetArrayEnable(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data); |
| break; |
| case GL_TEXTURE_COORD_ARRAY_SIZE: |
| retval = |
| __glXGetArraySize(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data); |
| break; |
| case GL_TEXTURE_COORD_ARRAY_TYPE: |
| retval = |
| __glXGetArrayType(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data); |
| break; |
| case GL_TEXTURE_COORD_ARRAY_STRIDE: |
| retval = |
| __glXGetArrayStride(state, GL_TEXTURE_COORD_ARRAY, tex_unit, data); |
| break; |
| |
| case GL_MAX_ELEMENTS_VERTICES: |
| case GL_MAX_ELEMENTS_INDICES: |
| retval = GL_TRUE; |
| *data = ~0UL; |
| break; |
| |
| |
| case GL_PACK_ROW_LENGTH: |
| *data = (GLintptr) state->storePack.rowLength; |
| break; |
| case GL_PACK_IMAGE_HEIGHT: |
| *data = (GLintptr) state->storePack.imageHeight; |
| break; |
| case GL_PACK_SKIP_ROWS: |
| *data = (GLintptr) state->storePack.skipRows; |
| break; |
| case GL_PACK_SKIP_PIXELS: |
| *data = (GLintptr) state->storePack.skipPixels; |
| break; |
| case GL_PACK_SKIP_IMAGES: |
| *data = (GLintptr) state->storePack.skipImages; |
| break; |
| case GL_PACK_ALIGNMENT: |
| *data = (GLintptr) state->storePack.alignment; |
| break; |
| case GL_PACK_SWAP_BYTES: |
| *data = (GLintptr) state->storePack.swapEndian; |
| break; |
| case GL_PACK_LSB_FIRST: |
| *data = (GLintptr) state->storePack.lsbFirst; |
| break; |
| case GL_UNPACK_ROW_LENGTH: |
| *data = (GLintptr) state->storeUnpack.rowLength; |
| break; |
| case GL_UNPACK_IMAGE_HEIGHT: |
| *data = (GLintptr) state->storeUnpack.imageHeight; |
| break; |
| case GL_UNPACK_SKIP_ROWS: |
| *data = (GLintptr) state->storeUnpack.skipRows; |
| break; |
| case GL_UNPACK_SKIP_PIXELS: |
| *data = (GLintptr) state->storeUnpack.skipPixels; |
| break; |
| case GL_UNPACK_SKIP_IMAGES: |
| *data = (GLintptr) state->storeUnpack.skipImages; |
| break; |
| case GL_UNPACK_ALIGNMENT: |
| *data = (GLintptr) state->storeUnpack.alignment; |
| break; |
| case GL_UNPACK_SWAP_BYTES: |
| *data = (GLintptr) state->storeUnpack.swapEndian; |
| break; |
| case GL_UNPACK_LSB_FIRST: |
| *data = (GLintptr) state->storeUnpack.lsbFirst; |
| break; |
| case GL_CLIENT_ATTRIB_STACK_DEPTH: |
| *data = (GLintptr) (gc->attributes.stackPointer - gc->attributes.stack); |
| break; |
| case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH: |
| *data = (GLintptr) __GL_CLIENT_ATTRIB_STACK_DEPTH; |
| break; |
| case GL_CLIENT_ACTIVE_TEXTURE: |
| *data = (GLintptr) (tex_unit + GL_TEXTURE0); |
| break; |
| |
| default: |
| retval = GL_FALSE; |
| break; |
| } |
| |
| |
| return retval; |
| } |
| |
| |
| void |
| __indirect_glGetBooleanv(GLenum val, GLboolean * b) |
| { |
| const GLenum origVal = val; |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| xGLXSingleReply reply; |
| |
| val = RemapTransposeEnum(val); |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_GetBooleanv, 4); |
| __GLX_SINGLE_PUT_LONG(0, val); |
| __GLX_SINGLE_READ_XREPLY(); |
| __GLX_SINGLE_GET_SIZE(compsize); |
| |
| if (compsize == 0) { |
| /* |
| ** Error occurred; don't modify user's buffer. |
| */ |
| } |
| else { |
| GLintptr data; |
| |
| /* |
| ** We still needed to send the request to the server in order to |
| ** find out whether it was legal to make a query (it's illegal, |
| ** for example, to call a query between glBegin() and glEnd()). |
| */ |
| |
| if (get_client_data(gc, val, &data)) { |
| *b = (GLboolean) data; |
| } |
| else { |
| /* |
| ** Not a local value, so use what we got from the server. |
| */ |
| if (compsize == 1) { |
| __GLX_SINGLE_GET_CHAR(b); |
| } |
| else { |
| __GLX_SINGLE_GET_CHAR_ARRAY(b, compsize); |
| if (val != origVal) { |
| /* matrix transpose */ |
| TransposeMatrixb(b); |
| } |
| } |
| } |
| } |
| __GLX_SINGLE_END(); |
| } |
| |
| void |
| __indirect_glGetDoublev(GLenum val, GLdouble * d) |
| { |
| const GLenum origVal = val; |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| xGLXSingleReply reply; |
| |
| val = RemapTransposeEnum(val); |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_GetDoublev, 4); |
| __GLX_SINGLE_PUT_LONG(0, val); |
| __GLX_SINGLE_READ_XREPLY(); |
| __GLX_SINGLE_GET_SIZE(compsize); |
| |
| if (compsize == 0) { |
| /* |
| ** Error occurred; don't modify user's buffer. |
| */ |
| } |
| else { |
| GLintptr data; |
| |
| /* |
| ** We still needed to send the request to the server in order to |
| ** find out whether it was legal to make a query (it's illegal, |
| ** for example, to call a query between glBegin() and glEnd()). |
| */ |
| |
| if (get_client_data(gc, val, &data)) { |
| *d = (GLdouble) data; |
| } |
| else { |
| /* |
| ** Not a local value, so use what we got from the server. |
| */ |
| if (compsize == 1) { |
| __GLX_SINGLE_GET_DOUBLE(d); |
| } |
| else { |
| __GLX_SINGLE_GET_DOUBLE_ARRAY(d, compsize); |
| if (val != origVal) { |
| /* matrix transpose */ |
| TransposeMatrixd(d); |
| } |
| } |
| } |
| } |
| __GLX_SINGLE_END(); |
| } |
| |
| void |
| __indirect_glGetFloatv(GLenum val, GLfloat * f) |
| { |
| const GLenum origVal = val; |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| xGLXSingleReply reply; |
| |
| val = RemapTransposeEnum(val); |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_GetFloatv, 4); |
| __GLX_SINGLE_PUT_LONG(0, val); |
| __GLX_SINGLE_READ_XREPLY(); |
| __GLX_SINGLE_GET_SIZE(compsize); |
| |
| if (compsize == 0) { |
| /* |
| ** Error occurred; don't modify user's buffer. |
| */ |
| } |
| else { |
| GLintptr data; |
| |
| /* |
| ** We still needed to send the request to the server in order to |
| ** find out whether it was legal to make a query (it's illegal, |
| ** for example, to call a query between glBegin() and glEnd()). |
| */ |
| |
| if (get_client_data(gc, val, &data)) { |
| *f = (GLfloat) data; |
| } |
| else { |
| /* |
| ** Not a local value, so use what we got from the server. |
| */ |
| if (compsize == 1) { |
| __GLX_SINGLE_GET_FLOAT(f); |
| } |
| else { |
| __GLX_SINGLE_GET_FLOAT_ARRAY(f, compsize); |
| if (val != origVal) { |
| /* matrix transpose */ |
| TransposeMatrixf(f); |
| } |
| } |
| } |
| } |
| __GLX_SINGLE_END(); |
| } |
| |
| void |
| __indirect_glGetIntegerv(GLenum val, GLint * i) |
| { |
| const GLenum origVal = val; |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| xGLXSingleReply reply; |
| |
| val = RemapTransposeEnum(val); |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_GetIntegerv, 4); |
| __GLX_SINGLE_PUT_LONG(0, val); |
| __GLX_SINGLE_READ_XREPLY(); |
| __GLX_SINGLE_GET_SIZE(compsize); |
| |
| if (compsize == 0) { |
| /* |
| ** Error occurred; don't modify user's buffer. |
| */ |
| } |
| else { |
| GLintptr data; |
| |
| /* |
| ** We still needed to send the request to the server in order to |
| ** find out whether it was legal to make a query (it's illegal, |
| ** for example, to call a query between glBegin() and glEnd()). |
| */ |
| |
| if (get_client_data(gc, val, &data)) { |
| *i = (GLint) data; |
| } |
| else { |
| /* |
| ** Not a local value, so use what we got from the server. |
| */ |
| if (compsize == 1) { |
| __GLX_SINGLE_GET_LONG(i); |
| } |
| else { |
| __GLX_SINGLE_GET_LONG_ARRAY(i, compsize); |
| if (val != origVal) { |
| /* matrix transpose */ |
| TransposeMatrixi(i); |
| } |
| } |
| } |
| } |
| __GLX_SINGLE_END(); |
| } |
| |
| /* |
| ** Send all pending commands to server. |
| */ |
| void |
| __indirect_glFlush(void) |
| { |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| |
| if (!dpy) |
| return; |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_Flush, 0); |
| __GLX_SINGLE_END(); |
| |
| /* And finally flush the X protocol data */ |
| XFlush(dpy); |
| } |
| |
| void |
| __indirect_glFeedbackBuffer(GLsizei size, GLenum type, GLfloat * buffer) |
| { |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| |
| if (!dpy) |
| return; |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_FeedbackBuffer, 8); |
| __GLX_SINGLE_PUT_LONG(0, size); |
| __GLX_SINGLE_PUT_LONG(4, type); |
| __GLX_SINGLE_END(); |
| |
| gc->feedbackBuf = buffer; |
| } |
| |
| void |
| __indirect_glSelectBuffer(GLsizei numnames, GLuint * buffer) |
| { |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| |
| if (!dpy) |
| return; |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_SelectBuffer, 4); |
| __GLX_SINGLE_PUT_LONG(0, numnames); |
| __GLX_SINGLE_END(); |
| |
| gc->selectBuf = buffer; |
| } |
| |
| GLint |
| __indirect_glRenderMode(GLenum mode) |
| { |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| GLint retval = 0; |
| xGLXRenderModeReply reply; |
| |
| if (!dpy) |
| return -1; |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_RenderMode, 4); |
| __GLX_SINGLE_PUT_LONG(0, mode); |
| __GLX_SINGLE_READ_XREPLY(); |
| __GLX_SINGLE_GET_RETVAL(retval, GLint); |
| |
| if (reply.newMode != mode) { |
| /* |
| ** Switch to new mode did not take effect, therefore an error |
| ** occurred. When an error happens the server won't send us any |
| ** other data. |
| */ |
| } |
| else { |
| /* Read the feedback or selection data */ |
| if (gc->renderMode == GL_FEEDBACK) { |
| __GLX_SINGLE_GET_SIZE(compsize); |
| __GLX_SINGLE_GET_FLOAT_ARRAY(gc->feedbackBuf, compsize); |
| } |
| else if (gc->renderMode == GL_SELECT) { |
| __GLX_SINGLE_GET_SIZE(compsize); |
| __GLX_SINGLE_GET_LONG_ARRAY(gc->selectBuf, compsize); |
| } |
| gc->renderMode = mode; |
| } |
| __GLX_SINGLE_END(); |
| |
| return retval; |
| } |
| |
| void |
| __indirect_glFinish(void) |
| { |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| xGLXSingleReply reply; |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_Finish, 0); |
| __GLX_SINGLE_READ_XREPLY(); |
| __GLX_SINGLE_END(); |
| } |
| |
| |
| /** |
| * Extract the major and minor version numbers from a version string. |
| */ |
| static void |
| version_from_string(const char *ver, int *major_version, int *minor_version) |
| { |
| const char *end; |
| long major; |
| long minor; |
| |
| major = strtol(ver, (char **) &end, 10); |
| minor = strtol(end + 1, NULL, 10); |
| *major_version = major; |
| *minor_version = minor; |
| } |
| |
| |
| const GLubyte * |
| __indirect_glGetString(GLenum name) |
| { |
| struct glx_context *gc = __glXGetCurrentContext(); |
| Display *dpy = gc->currentDpy; |
| GLubyte *s = NULL; |
| |
| if (!dpy) |
| return 0; |
| |
| /* |
| ** Return the cached copy if the string has already been fetched |
| */ |
| switch (name) { |
| case GL_VENDOR: |
| if (gc->vendor) |
| return gc->vendor; |
| break; |
| case GL_RENDERER: |
| if (gc->renderer) |
| return gc->renderer; |
| break; |
| case GL_VERSION: |
| if (gc->version) |
| return gc->version; |
| break; |
| case GL_EXTENSIONS: |
| if (gc->extensions) |
| return gc->extensions; |
| break; |
| default: |
| __glXSetError(gc, GL_INVALID_ENUM); |
| return 0; |
| } |
| |
| /* |
| ** Get requested string from server |
| */ |
| |
| (void) __glXFlushRenderBuffer(gc, gc->pc); |
| s = (GLubyte *) __glXGetString(dpy, gc->majorOpcode, gc->currentContextTag, |
| name); |
| if (!s) { |
| /* Throw data on the floor */ |
| __glXSetError(gc, GL_OUT_OF_MEMORY); |
| } |
| else { |
| /* |
| ** Update local cache |
| */ |
| switch (name) { |
| case GL_VENDOR: |
| gc->vendor = s; |
| break; |
| |
| case GL_RENDERER: |
| gc->renderer = s; |
| break; |
| |
| case GL_VERSION:{ |
| int client_major; |
| int client_minor; |
| |
| version_from_string((char *) s, |
| &gc->server_major, &gc->server_minor); |
| __glXGetGLVersion(&client_major, &client_minor); |
| |
| if ((gc->server_major < client_major) |
| || ((gc->server_major == client_major) |
| && (gc->server_minor <= client_minor))) { |
| gc->version = s; |
| } |
| else { |
| /* Allow 7 bytes for the client-side GL version. This allows |
| * for upto version 999.999. I'm not holding my breath for |
| * that one! The extra 4 is for the ' ()\0' that will be |
| * added. |
| */ |
| const size_t size = 7 + strlen((char *) s) + 4; |
| |
| gc->version = malloc(size); |
| if (gc->version == NULL) { |
| /* If we couldn't allocate memory for the new string, |
| * make a best-effort and just copy the client-side version |
| * to the string and use that. It probably doesn't |
| * matter what is done here. If there not memory available |
| * for a short string, the system is probably going to die |
| * soon anyway. |
| */ |
| snprintf((char *) s, strlen((char *) s) + 1, "%u.%u", |
| client_major, client_minor); |
| gc->version = s; |
| } |
| else { |
| snprintf((char *) gc->version, size, "%u.%u (%s)", |
| client_major, client_minor, s); |
| free(s); |
| s = gc->version; |
| } |
| } |
| break; |
| } |
| |
| case GL_EXTENSIONS:{ |
| int major = 1; |
| int minor = 0; |
| |
| /* This code is currently disabled. I was reminded that some |
| * vendors intentionally exclude some extensions from their |
| * extension string that are part of the core version they |
| * advertise. In particular, on Nvidia drivers this means that |
| * the functionality is supported by the driver, but is not |
| * hardware accelerated. For example, a TNT will show core |
| * version 1.5, but most of the post-1.2 functionality is a |
| * software fallback. |
| * |
| * I don't want to break applications that rely on this odd |
| * behavior. At the same time, the code is written and tested, |
| * so I didn't want to throw it away. Therefore, the code is here |
| * but disabled. In the future, we may wish to and an environment |
| * variable to enable it. |
| */ |
| |
| #if 0 |
| /* Call glGetString just to make sure that gc->server_major and |
| * gc->server_minor are set. This version may be higher than we |
| * can completely support, but it may imply support for some |
| * extensions that we can support. |
| * |
| * For example, at the time of this writing, the client-side |
| * library only supports upto core GL version 1.2. However, cubic |
| * textures, multitexture, multisampling, and some other 1.3 |
| * features are supported. If the server reports back version |
| * 1.3, but does not report all of those extensions, we will |
| * enable them. |
| */ |
| (void *) glGetString(GL_VERSION); |
| major = gc->server_major, minor = gc->server_minor; |
| #endif |
| |
| __glXCalculateUsableGLExtensions(gc, (char *) s, major, minor); |
| free(s); |
| s = gc->extensions; |
| break; |
| } |
| } |
| } |
| return s; |
| } |
| |
| GLboolean |
| __indirect_glIsEnabled(GLenum cap) |
| { |
| __GLX_SINGLE_DECLARE_VARIABLES(); |
| __GLXattribute *state = (__GLXattribute *) (gc->client_state_private); |
| xGLXSingleReply reply; |
| GLboolean retval = 0; |
| GLintptr enable; |
| |
| if (!dpy) |
| return 0; |
| |
| switch (cap) { |
| case GL_VERTEX_ARRAY: |
| case GL_NORMAL_ARRAY: |
| case GL_COLOR_ARRAY: |
| case GL_INDEX_ARRAY: |
| case GL_EDGE_FLAG_ARRAY: |
| case GL_SECONDARY_COLOR_ARRAY: |
| case GL_FOG_COORD_ARRAY: |
| retval = __glXGetArrayEnable(state, cap, 0, &enable); |
| assert(retval); |
| return (GLboolean) enable; |
| break; |
| case GL_TEXTURE_COORD_ARRAY: |
| retval = __glXGetArrayEnable(state, GL_TEXTURE_COORD_ARRAY, |
| __glXGetActiveTextureUnit(state), &enable); |
| assert(retval); |
| return (GLboolean) enable; |
| break; |
| } |
| |
| __GLX_SINGLE_LOAD_VARIABLES(); |
| __GLX_SINGLE_BEGIN(X_GLsop_IsEnabled, 4); |
| __GLX_SINGLE_PUT_LONG(0, cap); |
| __GLX_SINGLE_READ_XREPLY(); |
| __GLX_SINGLE_GET_RETVAL(retval, GLboolean); |
| __GLX_SINGLE_END(); |
| return retval; |
| } |
| |
| void |
| __indirect_glGetPointerv(GLenum pname, void **params) |
| { |
| struct glx_context *gc = __glXGetCurrentContext(); |
| __GLXattribute *state = (__GLXattribute *) (gc->client_state_private); |
| Display *dpy = gc->currentDpy; |
| |
| if (!dpy) |
| return; |
| |
| switch (pname) { |
| case GL_VERTEX_ARRAY_POINTER: |
| case GL_NORMAL_ARRAY_POINTER: |
| case GL_COLOR_ARRAY_POINTER: |
| case GL_INDEX_ARRAY_POINTER: |
| case GL_EDGE_FLAG_ARRAY_POINTER: |
| __glXGetArrayPointer(state, pname - GL_VERTEX_ARRAY_POINTER |
| + GL_VERTEX_ARRAY, 0, params); |
| return; |
| case GL_TEXTURE_COORD_ARRAY_POINTER: |
| __glXGetArrayPointer(state, GL_TEXTURE_COORD_ARRAY, |
| __glXGetActiveTextureUnit(state), params); |
| return; |
| case GL_SECONDARY_COLOR_ARRAY_POINTER: |
| case GL_FOG_COORD_ARRAY_POINTER: |
| __glXGetArrayPointer(state, pname - GL_FOG_COORD_ARRAY_POINTER |
| + GL_FOG_COORD_ARRAY, 0, params); |
| return; |
| case GL_FEEDBACK_BUFFER_POINTER: |
| *params = (void *) gc->feedbackBuf; |
| return; |
| case GL_SELECTION_BUFFER_POINTER: |
| *params = (void *) gc->selectBuf; |
| return; |
| default: |
| __glXSetError(gc, GL_INVALID_ENUM); |
| return; |
| } |
| } |
| |
| |
| |
| /** |
| * This was previously auto-generated, but we need to special-case |
| * how we handle writing into the 'residences' buffer when n%4!=0. |
| */ |
| #define X_GLsop_AreTexturesResident 143 |
| GLboolean |
| __indirect_glAreTexturesResident(GLsizei n, const GLuint * textures, |
| GLboolean * residences) |
| { |
| struct glx_context *const gc = __glXGetCurrentContext(); |
| Display *const dpy = gc->currentDpy; |
| GLboolean retval = (GLboolean) 0; |
| if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) { |
| xcb_connection_t *c = XGetXCBConnection(dpy); |
| xcb_glx_are_textures_resident_reply_t *reply; |
| (void) __glXFlushRenderBuffer(gc, gc->pc); |
| reply = |
| xcb_glx_are_textures_resident_reply(c, |
| xcb_glx_are_textures_resident |
| (c, gc->currentContextTag, n, |
| textures), NULL); |
| (void) memcpy(residences, xcb_glx_are_textures_resident_data(reply), |
| xcb_glx_are_textures_resident_data_length(reply) * |
| sizeof(GLboolean)); |
| retval = reply->ret_val; |
| free(reply); |
| } |
| return retval; |
| } |
| |
| |
| /** |
| * This was previously auto-generated, but we need to special-case |
| * how we handle writing into the 'residences' buffer when n%4!=0. |
| */ |
| #define X_GLvop_AreTexturesResidentEXT 11 |
| GLboolean |
| glAreTexturesResidentEXT(GLsizei n, const GLuint * textures, |
| GLboolean * residences) |
| { |
| struct glx_context *const gc = __glXGetCurrentContext(); |
| |
| if (gc->isDirect) { |
| const _glapi_proc *const table = (_glapi_proc *) GET_DISPATCH(); |
| PFNGLARETEXTURESRESIDENTEXTPROC p = |
| (PFNGLARETEXTURESRESIDENTEXTPROC) table[332]; |
| |
| return p(n, textures, residences); |
| } |
| else { |
| struct glx_context *const gc = __glXGetCurrentContext(); |
| Display *const dpy = gc->currentDpy; |
| GLboolean retval = (GLboolean) 0; |
| const GLuint cmdlen = 4 + __GLX_PAD((n * 4)); |
| if (__builtin_expect((n >= 0) && (dpy != NULL), 1)) { |
| GLubyte const *pc = |
| __glXSetupVendorRequest(gc, X_GLXVendorPrivateWithReply, |
| X_GLvop_AreTexturesResidentEXT, |
| cmdlen); |
| (void) memcpy((void *) (pc + 0), (void *) (&n), 4); |
| (void) memcpy((void *) (pc + 4), (void *) (textures), (n * 4)); |
| if (n & 3) { |
| /* see comments in __indirect_glAreTexturesResident() */ |
| GLboolean *res4 = malloc((n + 3) & ~3); |
| retval = (GLboolean) __glXReadReply(dpy, 1, res4, GL_TRUE); |
| memcpy(residences, res4, n); |
| free(res4); |
| } |
| else { |
| retval = (GLboolean) __glXReadReply(dpy, 1, residences, GL_TRUE); |
| } |
| UnlockDisplay(dpy); |
| SyncHandle(); |
| } |
| return retval; |
| } |
| } |