X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fvbo%2Fvbo_exec_array.c;h=bf97956286a8b92365f84b3def857c8f47d26de9;hb=7a6eba54d064cadf15f93df2c1748cf5e474ef03;hp=8f5c26920b997abbe3d6868e306f3bb186a48d85;hpb=01e238e5d51dabd28646356de825aa43a7290373;p=mesa.git diff --git a/src/mesa/vbo/vbo_exec_array.c b/src/mesa/vbo/vbo_exec_array.c index 8f5c26920b9..bf97956286a 100644 --- a/src/mesa/vbo/vbo_exec_array.c +++ b/src/mesa/vbo/vbo_exec_array.c @@ -25,54 +25,65 @@ * **************************************************************************/ -#include "glheader.h" -#include "context.h" -#include "state.h" -#include "api_validate.h" -#include "api_noop.h" -#include "dispatch.h" +#include "main/glheader.h" +#include "main/context.h" +#include "main/state.h" +#include "main/api_validate.h" +#include "main/api_noop.h" +#include "main/varray.h" +#include "glapi/dispatch.h" #include "vbo_context.h" -static GLuint get_max_index( GLuint count, GLuint type, - const GLvoid *indices ) +/* Compute min and max elements for drawelements calls. + */ +static void get_minmax_index( GLuint count, GLuint type, + const GLvoid *indices, + GLuint *min_index, + GLuint *max_index) { - GLint i; + GLuint i; - /* Compute max element. This is only needed for upload of non-VBO, - * non-constant data elements. - * - * XXX: Postpone this calculation until it is known that it is - * needed. Otherwise could scan this pointlessly in the all-vbo - * case. - */ switch(type) { case GL_UNSIGNED_INT: { const GLuint *ui_indices = (const GLuint *)indices; - GLuint max_ui = 0; - for (i = 0; i < count; i++) - if (ui_indices[i] > max_ui) - max_ui = ui_indices[i]; - return max_ui; + GLuint max_ui = ui_indices[0]; + GLuint min_ui = ui_indices[0]; + for (i = 1; i < count; i++) { + if (ui_indices[i] > max_ui) max_ui = ui_indices[i]; + if (ui_indices[i] < min_ui) min_ui = ui_indices[i]; + } + *min_index = min_ui; + *max_index = max_ui; + break; } case GL_UNSIGNED_SHORT: { const GLushort *us_indices = (const GLushort *)indices; - GLuint max_us = 0; - for (i = 0; i < count; i++) - if (us_indices[i] > max_us) - max_us = us_indices[i]; - return max_us; + GLuint max_us = us_indices[0]; + GLuint min_us = us_indices[0]; + for (i = 1; i < count; i++) { + if (us_indices[i] > max_us) max_us = us_indices[i]; + if (us_indices[i] < min_us) min_us = us_indices[i]; + } + *min_index = min_us; + *max_index = max_us; + break; } case GL_UNSIGNED_BYTE: { const GLubyte *ub_indices = (const GLubyte *)indices; - GLuint max_ub = 0; - for (i = 0; i < count; i++) - if (ub_indices[i] > max_ub) - max_ub = ub_indices[i]; - return max_ub; + GLuint max_ub = ub_indices[0]; + GLuint min_ub = ub_indices[0]; + for (i = 1; i < count; i++) { + if (ub_indices[i] > max_ub) max_ub = ub_indices[i]; + if (ub_indices[i] < min_ub) min_ub = ub_indices[i]; + } + *min_index = min_ub; + *max_index = max_ub; + break; } default: - return 0; + assert(0); + break; } } @@ -96,10 +107,14 @@ static void bind_array_obj( GLcontext *ctx ) exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &ctx->Array.ArrayObj->SecondaryColor; exec->array.legacy_array[VERT_ATTRIB_FOG] = &ctx->Array.ArrayObj->FogCoord; exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &ctx->Array.ArrayObj->Index; - exec->array.legacy_array[VBO_ATTRIB_EDGEFLAG] = &ctx->Array.ArrayObj->EdgeFlag; + if (ctx->Array.ArrayObj->PointSize.Enabled) { + /* this aliases COLOR_INDEX */ + exec->array.legacy_array[VERT_ATTRIB_POINT_SIZE] = &ctx->Array.ArrayObj->PointSize; + } + exec->array.legacy_array[VERT_ATTRIB_EDGEFLAG] = &ctx->Array.ArrayObj->EdgeFlag; for (i = 0; i < 8; i++) - exec->array.legacy_array[VBO_ATTRIB_TEX0 + i] = &ctx->Array.ArrayObj->TexCoord[i]; + exec->array.legacy_array[VERT_ATTRIB_TEX0 + i] = &ctx->Array.ArrayObj->TexCoord[i]; for (i = 0; i < VERT_ATTRIB_MAX; i++) exec->array.generic_array[i] = &ctx->Array.ArrayObj->VertexAttrib[i]; @@ -117,8 +132,6 @@ static void recalculate_input_bindings( GLcontext *ctx ) exec->array.program_mode = get_program_mode(ctx); exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled; - /* TODO: Get rid of NV_program (please!). - */ switch (exec->array.program_mode) { case VP_NONE: /* When no vertex program is active, we put the material values @@ -139,8 +152,8 @@ static void recalculate_input_bindings( GLcontext *ctx ) /* Could use just about anything, just to fill in the empty * slots: */ - for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX; i++) - inputs[i] = &vbo->generic_currval[i - VERT_ATTRIB_GENERIC0]; + for (i = MAT_ATTRIB_MAX; i < VERT_ATTRIB_MAX - VERT_ATTRIB_GENERIC0; i++) + inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; break; case VP_NV: @@ -188,7 +201,7 @@ static void recalculate_input_bindings( GLcontext *ctx ) } for (i = 0; i < 16; i++) { - if (exec->array.generic_array[0]->Enabled) + if (exec->array.generic_array[i]->Enabled) inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i]; else inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; @@ -237,37 +250,23 @@ vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) if (ctx->NewState) _mesa_update_state( ctx ); + if (!vbo_validate_shaders(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawArrays(bad shader)"); + return; + } + bind_arrays( ctx ); prim[0].begin = 1; prim[0].end = 1; prim[0].weak = 0; prim[0].pad = 0; + prim[0].mode = mode; + prim[0].start = start; + prim[0].count = count; + prim[0].indexed = 0; - if (exec->array.inputs[0]->BufferObj->Name) { - /* Use vertex attribute as a hint to tell us if we expect all - * arrays to be in VBO's and if so, don't worry about avoiding - * the upload of elements < start. - */ - prim[0].mode = mode; - prim[0].start = start; - prim[0].count = count; - prim[0].indexed = 0; - - vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, 0, start + count ); - } - else { - /* If not using VBO's, we don't want to upload any more elements - * than necessary from the arrays as they will not be valid next - * time the application tries to draw with them. - */ - prim[0].mode = mode; - prim[0].start = 0; - prim[0].count = count; - prim[0].indexed = 0; - - vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count ); - } + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count - 1 ); } @@ -290,25 +289,19 @@ vbo_exec_DrawRangeElements(GLenum mode, if (ctx->NewState) _mesa_update_state( ctx ); - + + if (!vbo_validate_shaders(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawRangeElements(bad shader)"); + return; + } + + bind_arrays( ctx ); + ib.count = count; ib.type = type; ib.obj = ctx->Array.ElementArrayBufferObj; ib.ptr = indices; - if (ctx->Array.ElementArrayBufferObj->Name) { - /* Use the fact that indices are in a VBO as a hint that the - * program has put all the arrays in VBO's and we don't have to - * worry about performance implications of start > 0. - * - * XXX: consider passing start as min_index to draw_prims instead. - */ - ib.rebase = 0; - } - else { - ib.rebase = start; - } - prim[0].begin = 1; prim[0].end = 1; prim[0].weak = 0; @@ -318,36 +311,72 @@ vbo_exec_DrawRangeElements(GLenum mode, prim[0].count = count; prim[0].indexed = 1; - vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, ib.rebase, end+1 ); -} + /* Need to give special consideration to rendering a range of + * indices starting somewhere above zero. Typically the + * application is issuing multiple DrawRangeElements() to draw + * successive primitives layed out linearly in the vertex arrays. + * Unless the vertex arrays are all in a VBO (or locked as with + * CVA), the OpenGL semantics imply that we need to re-read or + * re-upload the vertex data on each draw call. + * + * In the case of hardware tnl, we want to avoid starting the + * upload at zero, as it will mean every draw call uploads an + * increasing amount of not-used vertex data. Worse - in the + * software tnl module, all those vertices might be transformed and + * lit but never rendered. + * + * If we just upload or transform the vertices in start..end, + * however, the indices will be incorrect. + * + * At this level, we don't know exactly what the requirements of + * the backend are going to be, though it will likely boil down to + * either: + * + * 1) Do nothing, everything is in a VBO and is processed once + * only. + * + * 2) Adjust the indices and vertex arrays so that start becomes + * zero. + * + * Rather than doing anything here, I'll provide a helper function + * for the latter case elsewhere. + */ + vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, start, end ); +} static void GLAPIENTRY vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) { GET_CURRENT_CONTEXT(ctx); - GLuint max_index; + GLuint min_index = 0; + GLuint max_index = 0; if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) return; + if (!vbo_validate_shaders(ctx)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glDrawElements(bad shader)"); + return; + } + if (ctx->Array.ElementArrayBufferObj->Name) { const GLvoid *map = ctx->Driver.MapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, - GL_DYNAMIC_READ_ARB, + GL_READ_ONLY, ctx->Array.ElementArrayBufferObj); - max_index = get_max_index(count, type, ADD_POINTERS(map, indices)); + get_minmax_index(count, type, ADD_POINTERS(map, indices), &min_index, &max_index); ctx->Driver.UnmapBuffer(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, ctx->Array.ElementArrayBufferObj); } else { - max_index = get_max_index(count, type, indices); + get_minmax_index(count, type, indices, &min_index, &max_index); } - vbo_exec_DrawRangeElements(mode, 0, max_index, count, type, indices); + vbo_exec_DrawRangeElements(mode, min_index, max_index, count, type, indices); } @@ -360,8 +389,6 @@ vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *ind void vbo_exec_array_init( struct vbo_exec_context *exec ) { - GLcontext *ctx = exec->ctx; - #if 1 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays; exec->vtxfmt.DrawElements = vbo_exec_DrawElements; @@ -371,14 +398,36 @@ void vbo_exec_array_init( struct vbo_exec_context *exec ) exec->vtxfmt.DrawElements = _mesa_noop_DrawElements; exec->vtxfmt.DrawRangeElements = _mesa_noop_DrawRangeElements; #endif - - exec->array.index_obj = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB); } void vbo_exec_array_destroy( struct vbo_exec_context *exec ) { - GLcontext *ctx = exec->ctx; + /* nothing to do */ +} + + +/* This API entrypoint is not ordinarily used */ +void GLAPIENTRY +_mesa_DrawArrays(GLenum mode, GLint first, GLsizei count) +{ + vbo_exec_DrawArrays(mode, first, count); +} + + +/* This API entrypoint is not ordinarily used */ +void GLAPIENTRY +_mesa_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices) +{ + vbo_exec_DrawElements(mode, count, type, indices); +} - ctx->Driver.DeleteBuffer(ctx, exec->array.index_obj); + +/* This API entrypoint is not ordinarily used */ +void GLAPIENTRY +_mesa_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, + GLenum type, const GLvoid *indices) +{ + vbo_exec_DrawRangeElements(mode, start, end, count, type, indices); }