diff options
Diffstat (limited to 'src/mesa/vbo')
-rw-r--r-- | src/mesa/vbo/vbo_save.c | 37 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_save.h | 4 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_save_api.c | 132 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_save_draw.c | 64 |
4 files changed, 144 insertions, 93 deletions
diff --git a/src/mesa/vbo/vbo_save.c b/src/mesa/vbo/vbo_save.c index 19c40ec5307..f106cf279ad 100644 --- a/src/mesa/vbo/vbo_save.c +++ b/src/mesa/vbo/vbo_save.c @@ -27,6 +27,7 @@ #include "main/mtypes.h" +#include "main/arrayobj.h" #include "main/bufferobj.h" #include "vbo_private.h" @@ -44,32 +45,8 @@ void vbo_save_init( struct gl_context *ctx ) vbo_save_api_init( save ); - { - struct gl_vertex_array *arrays = save->arrays; - unsigned i; - - memcpy(arrays, &vbo->currval[VBO_ATTRIB_POS], - VERT_ATTRIB_FF_MAX * sizeof(arrays[0])); - for (i = 0; i < VERT_ATTRIB_FF_MAX; ++i) { - struct gl_vertex_array *array; - array = &arrays[VERT_ATTRIB_FF(i)]; - array->BufferObj = NULL; - _mesa_reference_buffer_object(ctx, &arrays->BufferObj, - vbo->currval[VBO_ATTRIB_POS+i].BufferObj); - } - - memcpy(arrays + VERT_ATTRIB_GENERIC(0), - &vbo->currval[VBO_ATTRIB_GENERIC0], - VERT_ATTRIB_GENERIC_MAX * sizeof(arrays[0])); - - for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; ++i) { - struct gl_vertex_array *array; - array = &arrays[VERT_ATTRIB_GENERIC(i)]; - array->BufferObj = NULL; - _mesa_reference_buffer_object(ctx, &array->BufferObj, - vbo->currval[VBO_ATTRIB_GENERIC0+i].BufferObj); - } - } + for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) + save->VAO[vpm] = NULL; ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; } @@ -79,7 +56,9 @@ void vbo_save_destroy( struct gl_context *ctx ) { struct vbo_context *vbo = vbo_context(ctx); struct vbo_save_context *save = &vbo->save; - GLuint i; + + for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) + _mesa_reference_vao(ctx, &save->VAO[vpm], NULL); if (save->prim_store) { if ( --save->prim_store->refcount == 0 ) { @@ -93,10 +72,6 @@ void vbo_save_destroy( struct gl_context *ctx ) save->vertex_store = NULL; } } - - for (i = 0; i < VBO_ATTRIB_MAX; i++) { - _mesa_reference_buffer_object(ctx, &save->arrays[i].BufferObj, NULL); - } } diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h index cb0bff23414..edbce3673d2 100644 --- a/src/mesa/vbo/vbo_save.h +++ b/src/mesa/vbo/vbo_save.h @@ -66,6 +66,7 @@ struct vbo_save_vertex_list { GLenum16 attrtype[VBO_ATTRIB_MAX]; GLuint offsets[VBO_ATTRIB_MAX]; GLuint vertex_size; /**< size in GLfloats */ + struct gl_vertex_array_object *VAO[VP_MODE_MAX]; /* Copy of the final vertex from node->vertex_store->bufferobj. * Keep this in regular (non-VBO) memory to avoid repeated @@ -140,14 +141,13 @@ struct vbo_save_context { struct gl_context *ctx; GLvertexformat vtxfmt; GLvertexformat vtxfmt_noop; /**< Used if out_of_memory is true */ - struct gl_vertex_array arrays[VBO_ATTRIB_MAX]; - const struct gl_vertex_array *inputs[VBO_ATTRIB_MAX]; GLbitfield64 enabled; /**< mask of enabled vbo arrays. */ GLubyte attrsz[VBO_ATTRIB_MAX]; /**< 1, 2, 3 or 4 */ GLenum16 attrtype[VBO_ATTRIB_MAX]; /**< GL_FLOAT, GL_INT, etc */ GLubyte active_sz[VBO_ATTRIB_MAX]; /**< 1, 2, 3 or 4 */ GLuint vertex_size; /**< size in GLfloats */ + struct gl_vertex_array_object *VAO[VP_MODE_MAX]; GLboolean out_of_memory; /**< True if last VBO allocation failed */ diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index fb51bdb84e4..1edf7b9dfa9 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -68,6 +68,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/glheader.h" +#include "main/arrayobj.h" #include "main/bufferobj.h" #include "main/context.h" #include "main/dlist.h" @@ -79,6 +80,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/vtxfmt.h" #include "main/dispatch.h" #include "main/state.h" +#include "main/varray.h" #include "util/bitscan.h" #include "vbo_noop.h" @@ -411,6 +413,112 @@ convert_line_loop_to_strip(struct vbo_save_context *save, } +/* Compare the present vao if it has the same setup. */ +static bool +compare_vao(gl_vertex_processing_mode mode, + const struct gl_vertex_array_object *vao, + const struct gl_buffer_object *bo, GLintptr buffer_offset, + GLuint stride, GLbitfield64 vao_enabled, + const GLubyte size[VBO_ATTRIB_MAX], + const GLenum16 type[VBO_ATTRIB_MAX], + const GLuint offset[VBO_ATTRIB_MAX]) +{ + if (!vao) + return false; + + /* If the enabled arrays are not the same we are not equal. */ + if (vao_enabled != vao->_Enabled) + return false; + + /* Check the buffer binding at 0 */ + if (vao->BufferBinding[0].BufferObj != bo) + return false; + /* BufferBinding[0].Offset != buffer_offset is checked per attribute */ + if (vao->BufferBinding[0].Stride != stride) + return false; + assert(vao->BufferBinding[0].InstanceDivisor == 0); + + /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */ + const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode]; + + /* Now check the enabled arrays */ + GLbitfield mask = vao_enabled; + while (mask) { + const int attr = u_bit_scan(&mask); + const unsigned char vbo_attr = vao_to_vbo_map[attr]; + const GLenum16 tp = type[vbo_attr]; + const GLintptr off = offset[vbo_attr] + buffer_offset; + const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr]; + if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off) + return false; + if (attrib->Type != tp) + return false; + if (attrib->Size != size[vbo_attr]) + return false; + assert(attrib->Format == GL_RGBA); + assert(attrib->Enabled == GL_TRUE); + assert(attrib->Normalized == GL_FALSE); + assert(attrib->Integer == vbo_attrtype_to_integer_flag(tp)); + assert(attrib->Doubles == vbo_attrtype_to_double_flag(tp)); + assert(attrib->BufferBindingIndex == 0); + } + + return true; +} + + +/* Create or reuse the vao for the vertex processing mode. */ +static void +update_vao(struct gl_context *ctx, + gl_vertex_processing_mode mode, + struct gl_vertex_array_object **vao, + struct gl_buffer_object *bo, GLintptr buffer_offset, + GLuint stride, GLbitfield64 vbo_enabled, + const GLubyte size[VBO_ATTRIB_MAX], + const GLenum16 type[VBO_ATTRIB_MAX], + const GLuint offset[VBO_ATTRIB_MAX]) +{ + /* Compute the bitmasks of vao_enabled arrays */ + GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled); + + /* + * Check if we can possibly reuse the exisiting one. + * In the long term we should reset them when something changes. + */ + if (compare_vao(mode, *vao, bo, buffer_offset, stride, + vao_enabled, size, type, offset)) + return; + + /* The initial refcount is 1 */ + _mesa_reference_vao(ctx, vao, NULL); + *vao = _mesa_new_vao(ctx, ~((GLuint)0)); + + /* Bind the buffer object at binding point 0 */ + _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride, false); + + /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space + * Note that the position/generic0 aliasing is done in the VAO. + */ + const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode]; + /* Now set the enable arrays */ + GLbitfield mask = vao_enabled; + while (mask) { + const int vao_attr = u_bit_scan(&mask); + const GLubyte vbo_attr = vao_to_vbo_map[vao_attr]; + + _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset, + size[vbo_attr], type[vbo_attr], offset[vbo_attr]); + _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0, false); + _mesa_enable_vertex_array_attrib(ctx, *vao, vao_attr, false); + } + assert(vao_enabled == (*vao)->_Enabled); + assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0); + + /* Finalize and freeze the VAO */ + _mesa_set_vao_immutable(ctx, *vao); +} + + /** * Insert the active immediate struct onto the display list currently * being built. @@ -420,6 +528,7 @@ compile_vertex_list(struct gl_context *ctx) { struct vbo_save_context *save = &vbo_context(ctx)->save; struct vbo_save_vertex_list *node; + GLintptr buffer_offset = 0; GLuint offset; unsigned i; @@ -470,6 +579,20 @@ compile_vertex_list(struct gl_context *ctx) node->vertex_store = save->vertex_store; node->prim_store = save->prim_store; + /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs + * Note that this may reuse the previous one of possible. + */ + for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) { + /* create or reuse the vao */ + update_vao(ctx, vpm, &save->VAO[vpm], + node->vertex_store->bufferobj, buffer_offset, + node->vertex_size*sizeof(GLfloat), node->enabled, + node->attrsz, node->attrtype, node->offsets); + /* Reference the vao in the dlist */ + node->VAO[vpm] = NULL; + _mesa_reference_vao(ctx, &node->VAO[vpm], save->VAO[vpm]); + } + node->vertex_store->refcount++; node->prim_store->refcount++; @@ -1700,7 +1823,9 @@ static void vbo_destroy_vertex_list(struct gl_context *ctx, void *data) { struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data; - (void) ctx; + + for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) + _mesa_reference_vao(ctx, &node->VAO[vpm], NULL); if (--node->vertex_store->refcount == 0) free_vertex_store(ctx, node->vertex_store); @@ -1773,7 +1898,6 @@ void vbo_save_api_init(struct vbo_save_context *save) { struct gl_context *ctx = save->ctx; - GLuint i; save->opcode_vertex_list = _mesa_dlist_alloc_opcode(ctx, @@ -1785,8 +1909,4 @@ vbo_save_api_init(struct vbo_save_context *save) vtxfmt_init(ctx); current_init(ctx); _mesa_noop_vtxfmt_init(&save->vtxfmt_noop); - - /* These will actually get set again when binding/drawing */ - for (i = 0; i < VBO_ATTRIB_MAX; i++) - save->inputs[i] = &save->arrays[i]; } diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 8c58fecf406..7cb67996689 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -129,58 +129,14 @@ playback_copy_to_current(struct gl_context *ctx, /** - * Treat the vertex storage as a VBO, define vertex arrays pointing - * into it: + * Set the appropriate VAO to draw. */ static void bind_vertex_list(struct gl_context *ctx, const struct vbo_save_vertex_list *node) { - struct vbo_context *vbo = vbo_context(ctx); - struct vbo_save_context *save = &vbo->save; - struct gl_vertex_array *arrays = save->arrays; - GLuint attr; - GLbitfield varying_inputs = 0x0; - - const gl_vertex_processing_mode processing_mode - = ctx->VertexProgram._VPMode; - const GLubyte * const map = _vbo_attribute_alias_map[processing_mode]; - - /* Grab VERT_ATTRIB_{POS,GENERIC0} from VBO_ATTRIB_POS */ - const gl_attribute_map_mode mode = ATTRIBUTE_MAP_MODE_POSITION; - const GLubyte *const array_map = _mesa_vao_attribute_map[mode]; - for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { - const GLuint src = map[array_map[attr]]; - const GLubyte size = node->attrsz[src]; - - if (size == 0) { - save->inputs[attr] = &vbo->currval[map[attr]]; - } else { - struct gl_vertex_array *array = &arrays[attr]; - const GLenum16 type = node->attrtype[src]; - - /* override the default array set above */ - save->inputs[attr] = array; - - array->Ptr = (const GLubyte *) NULL + node->offsets[src]; - array->Size = size; - array->StrideB = node->vertex_size * sizeof(GLfloat); - array->Type = type; - array->Integer = vbo_attrtype_to_integer_flag(type); - array->Format = GL_RGBA; - array->_ElementSize = size * sizeof(GLfloat); - _mesa_reference_buffer_object(ctx, - &array->BufferObj, - node->vertex_store->bufferobj); - - assert(array->BufferObj->Name); - - varying_inputs |= VERT_BIT(attr); - } - } - - _mesa_set_varying_vp_inputs(ctx, varying_inputs); - ctx->NewDriverState |= ctx->DriverFlags.NewArray; + const gl_vertex_processing_mode mode = ctx->VertexProgram._VPMode; + _mesa_set_draw_vao(ctx, node->VAO[mode], _vbo_get_vao_filter(mode)); } @@ -258,6 +214,9 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data) goto end; } + bind_vertex_list(ctx, node); + + /* Need that at least one time. */ if (ctx->NewState) _mesa_update_state(ctx); @@ -271,14 +230,11 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data) return; } - bind_vertex_list(ctx, node); - - _mesa_set_drawing_arrays(ctx, vbo->save.inputs); + /* Finally update the inputs array */ + _vbo_update_inputs(ctx, &vbo->draw_arrays); + _mesa_set_drawing_arrays(ctx, vbo->draw_arrays.inputs); - /* Again... - */ - if (ctx->NewState) - _mesa_update_state(ctx); + assert(ctx->NewState == 0); if (node->vertex_count > 0) { GLuint min_index = node->start_vertex; |