diff options
author | Ian Romanick <[email protected]> | 2005-02-22 22:36:31 +0000 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2005-02-22 22:36:31 +0000 |
commit | fdb07636f2e6324c5250cd5ee97778b7f5933bea (patch) | |
tree | 7914282adbac014b4d48b8ab78c03c73b6a72052 /src/glx/x11/vertarr.c | |
parent | cb83f62e307be90532fcc58a0e5dd3e8cc7411b2 (diff) |
Added __glExtensionBiIsEnabled and __GLXcontext::gl_extension_bits. This
enables libGL to query which extension are exported to applications.
Refactored array-query functionality (from glGet*v) in src/glx/x11/single2.c.
Massive re-write of indirect vertex array support. The most noticable
effect is that glDrawElements now generates DrawArrays protocol. The
side-effects (and the main reasons for the re-work) are that it is much
easier to add support for new arrays (e.g., GL_VERTEX_ATTRIB_ARRAY,
GL_WEIGHT_ARRAY_ARB, etc.) and it is much easier to add support for the new
DrawArrays protocol (required to support ARB_vertex_buffer_object).
These changes were primarilly tested with progs/demos/isosurf.
Diffstat (limited to 'src/glx/x11/vertarr.c')
-rw-r--r-- | src/glx/x11/vertarr.c | 960 |
1 files changed, 3 insertions, 957 deletions
diff --git a/src/glx/x11/vertarr.c b/src/glx/x11/vertarr.c index 5da30a3fdbd..77c51468ec5 100644 --- a/src/glx/x11/vertarr.c +++ b/src/glx/x11/vertarr.c @@ -34,134 +34,10 @@ ** */ -#include <assert.h> #include "glxclient.h" -#include "packrender.h" #include "indirect.h" -#include <string.h> -#include <limits.h> /* INT_MAX */ +#include "indirect_vertex_array.h" -/* macros for setting function pointers */ -#define __GL_VERTEX_FUNC(NAME, let) \ - case GL_##NAME: \ - if (size == 2) \ - vertexPointer->proc = (void (*)(const void *))__indirect_glVertex2##let##v; \ - else if (size == 3) \ - vertexPointer->proc = (void (*)(const void *))__indirect_glVertex3##let##v; \ - else if (size == 4) \ - vertexPointer->proc = (void (*)(const void *))__indirect_glVertex4##let##v; \ - break - -#define __GL_NORMAL_FUNC(NAME, let) \ - case GL_##NAME: \ - normalPointer->proc = (void (*)(const void *))__indirect_glNormal3##let##v; \ - break - -#define __GL_COLOR_FUNC(NAME, let) \ - case GL_##NAME: \ - if (size == 3) \ - colorPointer->proc = (void (*)(const void *))__indirect_glColor3##let##v; \ - else if (size == 4)\ - colorPointer->proc = (void (*)(const void *))__indirect_glColor4##let##v; \ - break - -#define __GL_SEC_COLOR_FUNC(NAME, let) \ - case GL_##NAME: \ - seccolorPointer->proc = (void (*)(const void *))__indirect_glSecondaryColor3##let##vEXT; \ - -#define __GL_FOG_FUNC(NAME, let) \ - case GL_##NAME: \ - fogPointer->proc = (void (*)(const void *))__indirect_glFogCoord##let##vEXT; \ - -#define __GL_INDEX_FUNC(NAME, let) \ - case GL_##NAME: \ - indexPointer->proc = (void (*)(const void *))__indirect_glIndex##let##v; \ - break - -#define __GL_TEXTURE_FUNC(NAME, let) \ - case GL_##NAME: \ - if (size == 1) { \ - texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord1##let##v; \ - texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord1##let##vARB; \ - } else if (size == 2) { \ - texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord2##let##v; \ - texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord2##let##vARB; \ - } else if (size == 3) { \ - texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord3##let##v; \ - texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord2##let##vARB; \ - } else if (size == 4) { \ - texCoordPointer->proc = (void (*)(const void *))__indirect_glTexCoord4##let##v; \ - texCoordPointer->mtex_proc = (void (*)(GLenum, const void *))__indirect_glMultiTexCoord4##let##vARB; \ - } break - -/** - * Table of sizes, in bytes, of a GL types. All of the type enums are be in - * the range 0x1400 - 0x140F. That includes types added by extensions (i.e., - * \c GL_HALF_FLOAT_NV). This elements of this table correspond to the - * type enums masked with 0x0f. - * - * \notes - * \c GL_HAVE_FLOAT_NV is not included. Neither are \c GL_2_BYTES, - * \c GL_3_BYTES, or \c GL_4_BYTES. - */ -static const GLuint __glXTypeSize_table[16] = { - 1, 1, 2, 2, 4, 4, 4, 0, 0, 0, 8, 0, 0, 0, 0, 0 -}; - -#define __glXTypeSize(e) ((((e) & ~0x0f) != 0x1400) \ - ? 0 : __glXTypeSize_table[ (e) & 0x0f ]) - - -/** - * Initialize vertex array state for a GLX context. - * - * \param gc GLX context whose vertex array state is to be initialized. - * - * \todo - * Someone is going to have to check the spec. This function takes greate - * care to initialize the \c size and \c type fields to "correct" values - * for each array. I'm not sure this is necessary. I think it should be - * acceptable to just \c memset the whole \c arrays and \c texCoord arrays - * to zero and be done with it. The spec may say something to the contrary, - * however. - */ -void __glXInitVertexArrayState(__GLXcontext *gc) -{ - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertArrayState *va = &state->vertArray; - GLint i; - - va->enables = 0; - va->texture_enables = 0; - - for ( i = 0 ; i < __GLX_MAX_ARRAYS ; i++ ) { - va->arrays[ i ].proc = NULL; - va->arrays[ i ].skip = 0; - va->arrays[ i ].ptr = 0; - va->arrays[ i ].size = 1; - va->arrays[ i ].type = GL_FLOAT; - va->arrays[ i ].stride = 0; - } - - va->arrays[ edgeFlag_ARRAY ].type = GL_UNSIGNED_BYTE;; - - va->arrays[ secondaryColor_ARRAY ].size = 3; - va->arrays[ color_ARRAY ].size = 4; - va->arrays[ normal_ARRAY ].size = 3; - va->arrays[ vertex_ARRAY ].size = 4; - - for ( i = 0 ; i < __GLX_MAX_TEXTURE_UNITS ; i++ ) { - va->texCoord[ i ].proc = NULL; - va->texCoord[ i ].skip = 0; - va->texCoord[ i ].ptr = 0; - va->texCoord[ i ].size = 4; - va->texCoord[ i ].type = GL_FLOAT; - va->texCoord[ i ].stride = 0; - } - - va->maxElementsVertices = INT_MAX; - va->maxElementsIndices = INT_MAX; -} /*****************************************************************************/ @@ -214,296 +90,6 @@ void __indirect_glVertexPointerEXT(GLint size, GLenum type, GLsizei stride, /*****************************************************************************/ -void __indirect_glVertexPointer(GLint size, GLenum type, GLsizei stride, - const GLvoid *pointer) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertexArrayPointerState *vertexPointer = &state->vertArray.arrays[ vertex_ARRAY ]; - - /* Check arguments */ - if (size < 2 || size > 4 || stride < 0) { - __glXSetError(gc, GL_INVALID_VALUE); - return; - } - - /* Choose appropriate api proc */ - switch(type) { - __GL_VERTEX_FUNC(SHORT, s); - __GL_VERTEX_FUNC(INT, i); - __GL_VERTEX_FUNC(FLOAT, f); - __GL_VERTEX_FUNC(DOUBLE, d); - default: - __glXSetError(gc, GL_INVALID_ENUM); - return; - } - - vertexPointer->size = size; - vertexPointer->type = type; - vertexPointer->stride = stride; - vertexPointer->ptr = pointer; - - /* Set internal state */ - if (stride == 0) { - vertexPointer->skip = __glXTypeSize(type) * size; - } else { - vertexPointer->skip = stride; - } -} - -void __indirect_glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertexArrayPointerState *normalPointer = &state->vertArray.arrays[ normal_ARRAY ]; - - /* Check arguments */ - if (stride < 0) { - __glXSetError(gc, GL_INVALID_VALUE); - return; - } - - /* Choose appropriate api proc */ - switch(type) { - __GL_NORMAL_FUNC(BYTE, b); - __GL_NORMAL_FUNC(SHORT, s); - __GL_NORMAL_FUNC(INT, i); - __GL_NORMAL_FUNC(FLOAT, f); - __GL_NORMAL_FUNC(DOUBLE, d); - default: - __glXSetError(gc, GL_INVALID_ENUM); - return; - } - - normalPointer->type = type; - normalPointer->stride = stride; - normalPointer->ptr = pointer; - - /* Set internal state */ - if (stride == 0) { - normalPointer->skip = 3 * __glXTypeSize(type); - } else { - normalPointer->skip = stride; - } -} - -void __indirect_glColorPointer(GLint size, GLenum type, GLsizei stride, - const GLvoid *pointer) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertexArrayPointerState *colorPointer = &state->vertArray.arrays[ color_ARRAY ]; - - /* Check arguments */ - if (stride < 0) { - __glXSetError(gc, GL_INVALID_VALUE); - return; - } - - /* Choose appropriate api proc */ - switch(type) { - __GL_COLOR_FUNC(BYTE, b); - __GL_COLOR_FUNC(UNSIGNED_BYTE, ub); - __GL_COLOR_FUNC(SHORT, s); - __GL_COLOR_FUNC(UNSIGNED_SHORT, us); - __GL_COLOR_FUNC(INT, i); - __GL_COLOR_FUNC(UNSIGNED_INT, ui); - __GL_COLOR_FUNC(FLOAT, f); - __GL_COLOR_FUNC(DOUBLE, d); - default: - __glXSetError(gc, GL_INVALID_ENUM); - return; - } - - colorPointer->size = size; - colorPointer->type = type; - colorPointer->stride = stride; - colorPointer->ptr = pointer; - - /* Set internal state */ - if (stride == 0) { - colorPointer->skip = size * __glXTypeSize(type); - } else { - colorPointer->skip = stride; - } -} - -void __indirect_glIndexPointer(GLenum type, GLsizei stride, const GLvoid *pointer) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertexArrayPointerState *indexPointer = &state->vertArray.arrays[ index_ARRAY ]; - - /* Check arguments */ - if (stride < 0) { - __glXSetError(gc, GL_INVALID_VALUE); - return; - } - - /* Choose appropriate api proc */ - switch(type) { - __GL_INDEX_FUNC(UNSIGNED_BYTE, ub); - __GL_INDEX_FUNC(SHORT, s); - __GL_INDEX_FUNC(INT, i); - __GL_INDEX_FUNC(FLOAT, f); - __GL_INDEX_FUNC(DOUBLE, d); - default: - __glXSetError(gc, GL_INVALID_ENUM); - return; - } - - indexPointer->type = type; - indexPointer->stride = stride; - indexPointer->ptr = pointer; - - /* Set internal state */ - if (stride == 0) { - indexPointer->skip = __glXTypeSize(type); - } else { - indexPointer->skip = stride; - } -} - -void __indirect_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, - const GLvoid *pointer) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertexArrayPointerState *texCoordPointer = - &state->vertArray.texCoord[state->vertArray.activeTexture]; - - /* Check arguments */ - if (size < 1 || size > 4 || stride < 0) { - __glXSetError(gc, GL_INVALID_VALUE); - return; - } - - /* Choose appropriate api proc */ - switch(type) { - __GL_TEXTURE_FUNC(SHORT, s); - __GL_TEXTURE_FUNC(INT, i); - __GL_TEXTURE_FUNC(FLOAT, f); - __GL_TEXTURE_FUNC(DOUBLE, d); - default: - __glXSetError(gc, GL_INVALID_ENUM); - return; - } - - texCoordPointer->size = size; - texCoordPointer->type = type; - texCoordPointer->stride = stride; - texCoordPointer->ptr = pointer; - - /* Set internal state */ - if (stride == 0) { - texCoordPointer->skip = __glXTypeSize(type) * size; - } else { - texCoordPointer->skip = stride; - } -} - -void __indirect_glEdgeFlagPointer(GLsizei stride, const GLvoid *pointer) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertexArrayPointerState *edgeFlagPointer = &state->vertArray.arrays[ edgeFlag_ARRAY ]; - - /* Check arguments */ - if (stride < 0) { - __glXSetError(gc, GL_INVALID_VALUE); - return; - } - - /* Choose appropriate api proc */ - edgeFlagPointer->proc = (void (*)(const void *))__indirect_glEdgeFlagv; - - edgeFlagPointer->stride = stride; - edgeFlagPointer->ptr = pointer; - - /* Set internal state */ - if (stride == 0) { - edgeFlagPointer->skip = sizeof(GLboolean); - } else { - edgeFlagPointer->skip = stride; - } - -} - -void __indirect_glSecondaryColorPointerEXT(GLint size, GLenum type, GLsizei stride, - const GLvoid * pointer ) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertexArrayPointerState *seccolorPointer = &state->vertArray.arrays[ secondaryColor_ARRAY ]; - - /* Check arguments */ - if ( (stride < 0) || (size != 3) ) { - __glXSetError(gc, GL_INVALID_VALUE); - return; - } - - /* Choose appropriate api proc */ - switch(type) { - __GL_SEC_COLOR_FUNC(BYTE, b); - __GL_SEC_COLOR_FUNC(UNSIGNED_BYTE, ub); - __GL_SEC_COLOR_FUNC(SHORT, s); - __GL_SEC_COLOR_FUNC(UNSIGNED_SHORT, us); - __GL_SEC_COLOR_FUNC(INT, i); - __GL_SEC_COLOR_FUNC(UNSIGNED_INT, ui); - __GL_SEC_COLOR_FUNC(FLOAT, f); - __GL_SEC_COLOR_FUNC(DOUBLE, d); - default: - __glXSetError(gc, GL_INVALID_ENUM); - return; - } - - seccolorPointer->size = size; - seccolorPointer->type = type; - seccolorPointer->stride = stride; - seccolorPointer->ptr = pointer; - - /* Set internal state */ - if (stride == 0) { - seccolorPointer->skip = size * __glXTypeSize(type); - } else { - seccolorPointer->skip = stride; - } -} - -void __indirect_glFogCoordPointerEXT(GLenum type, GLsizei stride, const GLvoid * pointer) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertexArrayPointerState *fogPointer = &state->vertArray.arrays[ fogCoord_ARRAY ]; - - /* Check arguments */ - if (stride < 0) { - __glXSetError(gc, GL_INVALID_VALUE); - return; - } - - /* Choose appropriate api proc */ - switch(type) { - __GL_FOG_FUNC(FLOAT, f); - __GL_FOG_FUNC(DOUBLE, d); - default: - __glXSetError(gc, GL_INVALID_ENUM); - return; - } - - fogPointer->size = 1; - fogPointer->type = type; - fogPointer->stride = stride; - fogPointer->ptr = pointer; - - /* Set internal state */ - if (stride == 0) { - fogPointer->skip = __glXTypeSize(type); - } else { - fogPointer->skip = stride; - } -} - void __indirect_glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer) { __GLXcontext *gc = __glXGetCurrentContext(); @@ -642,8 +228,8 @@ void __indirect_glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid trueStride = (stride == 0) ? size : stride; - state->vertArray.enables = 0; - state->vertArray.texture_enables = 0; + __glXArrayDisableAll( state ); + if (tEnable) { __indirect_glEnableClientState(GL_TEXTURE_COORD_ARRAY); __indirect_glTexCoordPointer(tSize, tType, trueStride, (const char *)pointer); @@ -659,543 +245,3 @@ void __indirect_glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid __indirect_glEnableClientState(GL_VERTEX_ARRAY); __indirect_glVertexPointer(vSize, vType, trueStride, (const char *)pointer+vOffset); } - -/*****************************************************************************/ - -void __indirect_glArrayElement(GLint i) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertArrayState *va = &state->vertArray; - GLint j; - - - if (IS_TEXARRAY_ENABLED(state, 0)) { - (*va->texCoord[0].proc)(va->texCoord[0].ptr+i*va->texCoord[0].skip); - } - - /* Multitexturing is handled specially because the protocol - * requires an extra parameter. - */ - for (j=1; j<__GLX_MAX_TEXTURE_UNITS; ++j) { - if (IS_TEXARRAY_ENABLED(state, j)) { - (*va->texCoord[j].mtex_proc)(GL_TEXTURE0 + j, va->texCoord[j].ptr+i*va->texCoord[j].skip); - } - } - - for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) { - if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) { - (*va->arrays[ j ].proc)(va->arrays[ j ].ptr+i*va->arrays[ j ].skip); - } - } -} - - -struct array_info { - __GLXdispatchDrawArraysComponentHeader ai; - GLsizei bytes; - const GLubyte *ptr; - GLsizei skip; -}; - - -/** - * Initialize a \c array_info structure for each array that is enabled in - * \c state. Determine how many arrays are enabled, and store the result - * in \c num_arrays. Determine how big each vertex is, and store the result - * in \c total_vertex_size. - * - * \returns The size of the final request. This is the size, in bytes, of - * the DrawArrays header, the ARRAY_INFO structures, and all the vertex data. - * This value \b assumes a \c X_GLXRender command is used. The true size - * will be 4 bytes larger if a \c X_GLXRenderLarge command is used. - */ -static GLuint -prep_arrays(const __GLXattribute * const state, struct array_info * arrays, - GLint count, - GLsizei *num_arrays, GLsizei *total_vertex_size) -{ - GLsizei na = 0; - GLsizei vs = 0; - -#define ASSIGN_ARRAY_INFO(state, enum_name, arr) \ - do { \ - arrays[ na ].ai.datatype = state->vertArray. arr .type ; \ - arrays[ na ].ai.numVals = state->vertArray. arr .size ; \ - arrays[ na ].ai.component = GL_ ## enum_name ## _ARRAY; \ -\ - arrays[ na ].bytes = state->vertArray. arr .size \ - * __glXTypeSize( state->vertArray. arr .type ); \ - arrays[ na ].ptr = state->vertArray. arr .ptr; \ - arrays[ na ].skip = state->vertArray. arr .skip; \ -\ - vs += __GLX_PAD(arrays[ na ].bytes); \ - na++; \ - } while( 0 ) - -#define ADD_ARRAY_IF_ENABLED(state, enum_name, arr) \ - do { if ( IS_ARRAY_ENABLED(state, arr) ) { \ - ASSIGN_ARRAY_INFO(state, enum_name, arrays[ arr ## _ARRAY ] ); \ - } } while( 0 ) - - ADD_ARRAY_IF_ENABLED(state, VERTEX, vertex); - ADD_ARRAY_IF_ENABLED(state, NORMAL, normal); - ADD_ARRAY_IF_ENABLED(state, COLOR, color); - ADD_ARRAY_IF_ENABLED(state, SECONDARY_COLOR, secondaryColor); - ADD_ARRAY_IF_ENABLED(state, FOG_COORD, fogCoord); - ADD_ARRAY_IF_ENABLED(state, EDGE_FLAG, edgeFlag); - ADD_ARRAY_IF_ENABLED(state, INDEX, index); - - /* The standard DrawArrays protocol *only* supports a single array of - * texture coordinates. - */ - if ( IS_TEXARRAY_ENABLED(state, 0) ) { - ASSIGN_ARRAY_INFO(state, TEXTURE_COORD, texCoord[0]); - } - - *num_arrays = na; - *total_vertex_size = vs; - - return __GLX_PAD((__GLX_COMPONENT_HDR_SIZE * na) - + (vs * count) - + __GLX_DRAWARRAYS_CMD_HDR_SIZE); -} - - -/** - * Emits the vertex data for the DrawArrays GLX protocol. - */ -static GLsizei -emit_vertex(GLubyte * data, const struct array_info * arrays, - GLsizei num_arrays, GLint element, GLsizei offset) -{ - GLint i; - - for ( i = 0 ; i < num_arrays ; i++ ) { - (void) memcpy( data + offset, - arrays[i].ptr + (arrays[i].skip * element), - arrays[i].bytes ); - offset += __GLX_PAD(arrays[i].bytes); - } - - return offset; -} - - -static void -emit_header(GLubyte * pc, const struct array_info * arrays, - GLsizei num_arrays, GLsizei count, GLenum mode) -{ - __GLXdispatchDrawArraysComponentHeader *arrayInfo; - GLsizei i; - - __GLX_PUT_LONG(0, count); - __GLX_PUT_LONG(4, num_arrays); - __GLX_PUT_LONG(8, mode); - - arrayInfo = (__GLXdispatchDrawArraysComponentHeader *) - (pc + __GLX_DRAWARRAYS_HDR_SIZE); - - - /* Write the ARRAY_INFO data. - */ - - for ( i = 0 ; i < num_arrays ; i++ ) { - arrayInfo[i] = arrays[i].ai; - } -} - - -/** - * Emit GLX DrawArrays protocol using a GLXRender packet. - */ -static void -emit_Render_DrawArrays(__GLXcontext * gc, const struct array_info * arrays, - GLsizei first, GLsizei count, GLsizei num_arrays, GLenum mode, - GLsizei cmdlen, GLsizei total_vertex_size) -{ - GLubyte * pc = gc->pc; - GLsizei offset; - GLsizei i; - - __GLX_BEGIN_VARIABLE(X_GLrop_DrawArrays, cmdlen); - emit_header(pc + 4, arrays, num_arrays, count, mode); - - - /* Write the actual array data. - */ - - offset = __GLX_DRAWARRAYS_CMD_HDR_SIZE - + (num_arrays * __GLX_COMPONENT_HDR_SIZE); - for ( i = 0 ; i < count ; i++ ) { - offset = emit_vertex(pc, arrays, num_arrays, i + first, offset); - } - - __GLX_END(cmdlen); -} - - -/** - * Emit GLX DrawArrays protocol using a GLXRenderLarge packet. - */ -static void -emit_RenderLarge_DrawArrays(__GLXcontext * gc, const struct array_info * arrays, - GLsizei first, GLsizei count, GLsizei num_arrays, GLenum mode, - GLsizei cmdlen, GLsizei total_vertex_size) -{ - GLubyte * pc = gc->pc; - GLsizei offset; - GLsizei i; - GLint maxSize; - GLint totalRequests; - GLint requestNumber; - GLsizei elements_per_request; - - - /* Calculate the maximum amount of data can be stuffed into a single - * packet. sz_xGLXRenderReq is added because bufSize is the maximum - * packet size minus sz_xGLXRenderReq. - * - * The important value here is elements_per_request. This is the number - * of complete array elements that will fit in a single buffer. There - * may be some wasted space at the end of the buffer, but splitting - * elements across buffer boundries would be painful. - */ - - maxSize = (gc->bufSize + sz_xGLXRenderReq) - sz_xGLXRenderLargeReq; - - elements_per_request = maxSize / total_vertex_size; - - totalRequests = ((count + (elements_per_request - 1)) - / elements_per_request) + 1; - - - /* Fill in the header data and send it away. - */ - - __GLX_BEGIN_VARIABLE_LARGE(X_GLrop_DrawArrays, cmdlen+4); - emit_header(pc + 8, arrays, num_arrays, count, mode); - - gc->pc = pc + (__GLX_DRAWARRAYS_CMD_HDR_SIZE + 4) - + (__GLX_COMPONENT_HDR_SIZE * num_arrays); - __glXSendLargeChunk(gc, 1, totalRequests, gc->buf, gc->pc - gc->buf); - - - /* Write the actual array data. - */ - offset = 0; - requestNumber = 2; - for ( i = 0 ; i < count ; i++ ) { - if ( i == elements_per_request ) { - __glXSendLargeChunk(gc, requestNumber, totalRequests, - gc->buf, offset); - requestNumber++; - offset = 0; - - count -= i; - first += i; - i = 0; - } - - offset = emit_vertex(gc->buf, arrays, num_arrays, i + first, offset); - } - - /* If the buffer isn't empty, emit the last, partial request. - */ - if ( offset != 0 ) { - assert(requestNumber == totalRequests); - __glXSendLargeChunk(gc, requestNumber, totalRequests, gc->buf, offset); - } - - gc->pc = gc->buf; -} - - -/** - * Emit DrawArrays protocol. This function acts as a switch betteen - * \c emit_Render_DrawArrays and \c emit_RenderLarge_DrawArrays depending - * on how much array data is to be sent. - */ -static void -emit_DrawArraysEXT(const __GLXattribute * const state, - GLint first, GLsizei count, GLenum mode) -{ - struct array_info arrays[32]; - GLsizei num_arrays; - GLsizei total_vertex_size; - __GLXcontext *gc = __glXGetCurrentContext(); - GLuint cmdlen; - - - /* Determine how big the final request will be. This depends on a number - * of factors. It depends on how many array elemets there are (which is - * the passed-in 'count'), how many arrays are enabled, how many elements - * are in each array entry, and what the types are for each array. - */ - - cmdlen = prep_arrays(state, arrays, count, & num_arrays, - & total_vertex_size); - - - /* If the data payload and the protocol header is too large for a Render - * command, use a RenderLarge command. - */ - if (cmdlen > gc->maxSmallRenderCommandSize) { - emit_RenderLarge_DrawArrays(gc, arrays, first, count, num_arrays, - mode, cmdlen, total_vertex_size); - } - else { - emit_Render_DrawArrays(gc, arrays, first, count, num_arrays, - mode, cmdlen, total_vertex_size); - } -} - - -/** - * Emit a DrawArrays call using the old "protocol." This isn't really - * DrawArrays protocol at all. It just simulates DrawArrays by using - * immediate-mode vertex calls. Very, very slow for large arrays, but works - * with every GLX server. - */ -static void -emit_DrawArrays_old(const __GLXattribute * const state, - GLint first, GLsizei count, GLenum mode) -{ - const __GLXvertArrayState *va = &state->vertArray; - const GLubyte *vaPtr[__GLX_MAX_ARRAYS]; - const GLubyte *tcaPtr[__GLX_MAX_TEXTURE_UNITS]; - GLint i, j; - - /* - ** Set up pointers for quick array traversal. - */ - - (void) memset( vaPtr, 0, sizeof(vaPtr) ); - (void) memset( tcaPtr, 0, sizeof(tcaPtr) ); - - for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) { - if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) { - vaPtr[ j ] = va->arrays[ j ].ptr + first * va->arrays[ j ].skip; - } - } - - for ( j = 0 ; j < __GLX_MAX_TEXTURE_UNITS ; j++ ) { - if (IS_TEXARRAY_ENABLED(state, j)) - tcaPtr[ j ] = va->texCoord[ j ].ptr + first * va->texCoord[ j ].skip; - } - - __indirect_glBegin(mode); - for (i = 0; i < count; i++) { - if (IS_TEXARRAY_ENABLED(state, 0)) { - (*va->texCoord[0].proc)(tcaPtr[0]); - tcaPtr[0] += va->texCoord[0].skip; - } - - /* Multitexturing is handled specially because the protocol - * requires an extra parameter. - */ - for (j=1; j<__GLX_MAX_TEXTURE_UNITS; ++j) { - if (IS_TEXARRAY_ENABLED(state, j)) { - (*va->texCoord[j].mtex_proc)(GL_TEXTURE0 + j, tcaPtr[j]); - tcaPtr[j] += va->texCoord[j].skip; - } - } - - for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) { - if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) { - (*va->arrays[ j ].proc)(vaPtr[ j ]); - vaPtr[ j ] += va->arrays[ j ].skip; - } - } - } - __indirect_glEnd(); -} - - -/** - * Validate that the \c mode and \c count parameters to \c glDrawArrays or - * \c glDrawElements are valid. If the arguments are not valid, then an - * error code is set in the GLX context. - * - * \returns \c GL_TRUE if the arguments are valide, \c GL_FALSE if they are - * not. - */ -static GLboolean -glx_validate_array_args(__GLXcontext *gc, GLenum mode, GLsizei count) -{ - switch(mode) { - case GL_POINTS: - case GL_LINE_STRIP: - case GL_LINE_LOOP: - case GL_LINES: - case GL_TRIANGLE_STRIP: - case GL_TRIANGLE_FAN: - case GL_TRIANGLES: - case GL_QUAD_STRIP: - case GL_QUADS: - case GL_POLYGON: - break; - default: - __glXSetError(gc, GL_INVALID_ENUM); - return GL_FALSE; - } - - if (count < 0) { - __glXSetError(gc, GL_INVALID_VALUE); - return GL_FALSE; - } - - return GL_TRUE; -} - - -void __indirect_glDrawArrays(GLenum mode, GLint first, GLsizei count) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - const __GLXattribute * state = - (const __GLXattribute *)(gc->client_state_private); - - - if ( ! glx_validate_array_args(gc, mode, count) ) { - return; - } - - /* The "true" DrawArrays protocol does not support generic attributes, - * multiple vertex arrays, or multiple texture coordinate arrays. - */ - if ( state->NoDrawArraysProtocol - || (state->vertArray.texture_enables > 1) ) { - emit_DrawArrays_old(state, first, count, mode); - } - else { - emit_DrawArraysEXT(state, first, count, mode); - } -} - - -/** - * \todo Modify this to use the "true" DrawArrays protocol if possible. This - * would probably require refactoring out parts of \c emit_DrawArraysEXT into - * more general functions that could be used in either place. - */ -void __indirect_glDrawElements(GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - __GLXvertArrayState *va = &state->vertArray; - const GLubyte *iPtr1 = NULL; - const GLushort *iPtr2 = NULL; - const GLuint *iPtr3 = NULL; - GLint i, j, offset = 0; - - if ( ! glx_validate_array_args(gc, mode, count) ) { - return; - } - - switch (type) { - case GL_UNSIGNED_BYTE: - iPtr1 = (const GLubyte *)indices; - break; - case GL_UNSIGNED_SHORT: - iPtr2 = (const GLushort *)indices; - break; - case GL_UNSIGNED_INT: - iPtr3 = (const GLuint *)indices; - break; - default: - __glXSetError(gc, GL_INVALID_ENUM); - return; - } - - __indirect_glBegin(mode); - for (i = 0; i < count; i++) { - switch (type) { - case GL_UNSIGNED_BYTE: - offset = (GLint)(*iPtr1++); - break; - case GL_UNSIGNED_SHORT: - offset = (GLint)(*iPtr2++); - break; - case GL_UNSIGNED_INT: - offset = (GLint)(*iPtr3++); - break; - } - - if (IS_TEXARRAY_ENABLED(state, 0)) { - (*va->texCoord[0].proc)(va->texCoord[0].ptr+ - (offset*va->texCoord[0].skip)); - } - - /* Multitexturing is handled specially because the protocol - * requires an extra parameter. - */ - for (j=1; j<__GLX_MAX_TEXTURE_UNITS; ++j) { - if (IS_TEXARRAY_ENABLED(state, j)) { - (*va->texCoord[j].mtex_proc)(GL_TEXTURE0 + j, - va->texCoord[j].ptr+ - (offset*va->texCoord[j].skip)); - } - } - - for ( j = 0 ; j < __GLX_MAX_ARRAYS ; j++ ) { - if (IS_ARRAY_ENABLED_BY_INDEX(state, j)) { - (*va->arrays[ j ].proc)(va->arrays[ j ].ptr - +(offset*va->arrays[ j ].skip)); - } - } - } - __indirect_glEnd(); -} - -void __indirect_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, - GLsizei count, GLenum type, - const GLvoid *indices) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - - if (end < start) { - __glXSetError(gc, GL_INVALID_VALUE); - return; - } - - __indirect_glDrawElements(mode,count,type,indices); -} - -void __indirect_glMultiDrawArraysEXT(GLenum mode, GLint *first, GLsizei *count, - GLsizei primcount) -{ - GLsizei i; - - for(i=0; i<primcount; i++) { - if ( count[i] > 0 ) { - __indirect_glDrawArrays( mode, first[i], count[i] ); - } - } -} - -void __indirect_glMultiDrawElementsEXT(GLenum mode, const GLsizei *count, - GLenum type, const GLvoid ** indices, - GLsizei primcount) -{ - GLsizei i; - - for(i=0; i<primcount; i++) { - if ( count[i] > 0 ) { - __indirect_glDrawElements( mode, count[i], type, indices[i] ); - } - } -} - -void __indirect_glClientActiveTextureARB(GLenum texture) -{ - __GLXcontext *gc = __glXGetCurrentContext(); - __GLXattribute * state = (__GLXattribute *)(gc->client_state_private); - GLint unit = (GLint) texture - GL_TEXTURE0; - - if (unit < 0 || __GLX_MAX_TEXTURE_UNITS <= unit) { - __glXSetError(gc, GL_INVALID_ENUM); - return; - } - state->vertArray.activeTexture = unit; -} |