diff options
Diffstat (limited to 'src/mesa/vbo/vbo_save_api.c')
-rw-r--r-- | src/mesa/vbo/vbo_save_api.c | 529 |
1 files changed, 295 insertions, 234 deletions
diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index de4a6fe32f5..583f79e09dd 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -100,7 +100,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "main/glheader.h" +#include "util/glheader.h" #include "main/arrayobj.h" #include "main/bufferobj.h" #include "main/context.h" @@ -110,19 +110,20 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "main/macros.h" #include "main/draw_validate.h" #include "main/api_arrayelt.h" -#include "main/vtxfmt.h" #include "main/dispatch.h" #include "main/state.h" #include "main/varray.h" #include "util/bitscan.h" #include "util/u_memory.h" #include "util/hash_table.h" +#include "gallium/auxiliary/indices/u_indices.h" +#include "util/u_prim.h" #include "gallium/include/pipe/p_state.h" -#include "vbo_noop.h" #include "vbo_private.h" - +#include "api_exec_decl.h" +#include "api_save.h" #ifdef ERROR #undef ERROR @@ -140,14 +141,6 @@ _save_EvalCoord1f(GLfloat u); static void GLAPIENTRY _save_EvalCoord2f(GLfloat u, GLfloat v); -static void -handle_out_of_memory(struct gl_context *ctx) -{ - struct vbo_save_context *save = &vbo_context(ctx)->save; - _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt); - save->out_of_memory = true; -} - /* * NOTE: Old 'parity' issue is gone, but copying can still be * wrong-footed on replay. @@ -168,8 +161,13 @@ copy_vertices(struct gl_context *ctx, assert(save->copied.buffer == NULL); save->copied.buffer = malloc(sizeof(fi_type) * sz * prim->count); - return vbo_copy_vertices(ctx, prim->mode, prim->start, &prim->count, - prim->begin, sz, true, save->copied.buffer, src); + unsigned r = vbo_copy_vertices(ctx, prim->mode, prim->start, &prim->count, + prim->begin, sz, true, save->copied.buffer, src); + if (!r) { + free(save->copied.buffer); + save->copied.buffer = NULL; + } + return r; } @@ -320,14 +318,14 @@ compare_vao(gl_vertex_processing_mode mode, const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr]; if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off) return false; - if (attrib->Format.Type != tp) + if (attrib->Format.User.Type != tp) return false; - if (attrib->Format.Size != size[vbo_attr]) + if (attrib->Format.User.Size != size[vbo_attr]) return false; - assert(attrib->Format.Format == GL_RGBA); - assert(attrib->Format.Normalized == GL_FALSE); - assert(attrib->Format.Integer == vbo_attrtype_to_integer_flag(tp)); - assert(attrib->Format.Doubles == vbo_attrtype_to_double_flag(tp)); + assert(!attrib->Format.User.Bgra); + assert(attrib->Format.User.Normalized == GL_FALSE); + assert(attrib->Format.User.Integer == vbo_attrtype_to_integer_flag(tp)); + assert(attrib->Format.User.Doubles == vbo_attrtype_to_double_flag(tp)); assert(attrib->BufferBindingIndex == 0); } @@ -391,7 +389,8 @@ update_vao(struct gl_context *ctx, assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0); /* Finalize and freeze the VAO */ - _mesa_set_vao_immutable(ctx, *vao); + _mesa_update_vao_derived_arrays(ctx, *vao, true); + (*vao)->SharedAndImmutable = true; } static void wrap_filled_vertex(struct gl_context *ctx); @@ -419,9 +418,8 @@ grow_vertex_storage(struct gl_context *ctx, int vertex_count) save->vertex_store->buffer_in_ram = realloc(save->vertex_store->buffer_in_ram, save->vertex_store->buffer_in_ram_size); if (save->vertex_store->buffer_in_ram == NULL) - handle_out_of_memory(ctx); + save->out_of_memory = true; } - } struct vertex_key { @@ -526,7 +524,6 @@ compile_vertex_list(struct gl_context *ctx) if (!node) return; - memset(node, 0, sizeof(struct vbo_save_vertex_list)); node->cold = calloc(1, sizeof(*node->cold)); /* Make sure the pointer is aligned to the size of a pointer */ @@ -562,7 +559,7 @@ compile_vertex_list(struct gl_context *ctx) current_size * sizeof(GLfloat)); } else { _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation"); - handle_out_of_memory(ctx); + save->out_of_memory = true; } } } @@ -601,10 +598,11 @@ compile_vertex_list(struct gl_context *ctx) node->cold->min_index = node->cold->prims[0].start; node->cold->max_index = end - 1; - int max_index_count = total_vert_count * 2; - - int size = max_index_count * sizeof(uint32_t); - uint32_t* indices = (uint32_t*) malloc(size); + /* converting primitive types may result in many more indices */ + bool all_prims_supported = (ctx->Const.DriverSupportedPrimMask & BITFIELD_MASK(MESA_PRIM_COUNT)) == BITFIELD_MASK(MESA_PRIM_COUNT); + int max_index_count = total_vert_count * (all_prims_supported ? 2 : 3); + uint32_t* indices = (uint32_t*) malloc(max_index_count * sizeof(uint32_t)); + void *tmp_indices = all_prims_supported ? NULL : malloc(max_index_count * sizeof(uint32_t)); struct _mesa_prim *merged_prims = NULL; int idx = 0; @@ -626,16 +624,44 @@ compile_vertex_list(struct gl_context *ctx) for (unsigned i = 0; i < node->cold->prim_count; i++) { assert(original_prims[i].basevertex == 0); GLubyte mode = original_prims[i].mode; + bool converted_prim = false; + unsigned index_size; + bool outputting_quads = !!(ctx->Const.DriverSupportedPrimMask & + (BITFIELD_MASK(MESA_PRIM_QUADS) | BITFIELD_MASK(MESA_PRIM_QUAD_STRIP))); + unsigned verts_per_primitive = outputting_quads ? 4 : 3; int vertex_count = original_prims[i].count; if (!vertex_count) { continue; } + /* Increase indices storage if the original estimation was too small. */ + if (idx + verts_per_primitive * vertex_count > max_index_count) { + max_index_count = max_index_count + verts_per_primitive * vertex_count; + indices = (uint32_t*) realloc(indices, max_index_count * sizeof(uint32_t)); + tmp_indices = all_prims_supported ? NULL : realloc(tmp_indices, max_index_count * sizeof(uint32_t)); + } + /* Line strips may get converted to lines */ if (mode == GL_LINE_STRIP) mode = GL_LINES; + if (!(ctx->Const.DriverSupportedPrimMask & BITFIELD_BIT(mode))) { + unsigned new_count; + u_generate_func trans_func; + enum mesa_prim pmode = (enum mesa_prim)mode; + u_index_generator(ctx->Const.DriverSupportedPrimMask, + pmode, original_prims[i].start, vertex_count, + PV_LAST, PV_LAST, + &pmode, &index_size, &new_count, + &trans_func); + if (new_count > 0) + trans_func(original_prims[i].start, new_count, tmp_indices); + vertex_count = new_count; + mode = (GLubyte)pmode; + converted_prim = true; + } + /* If 2 consecutive prims use the same mode => merge them. */ bool merge_prims = last_valid_prim >= 0 && mode == merged_prims[last_valid_prim].mode && @@ -643,6 +669,8 @@ compile_vertex_list(struct gl_context *ctx) mode != GL_QUAD_STRIP && mode != GL_POLYGON && mode != GL_PATCHES; +/* index generation uses uint16_t if the index count is small enough */ +#define CAST_INDEX(BASE, SIZE, IDX) ((SIZE == 2 ? (uint32_t)(((uint16_t*)BASE)[IDX]) : ((uint32_t*)BASE)[IDX])) /* To be able to merge consecutive triangle strips we need to insert * a degenerate triangle. */ @@ -653,14 +681,16 @@ compile_vertex_list(struct gl_context *ctx) unsigned tri_count = merged_prims[last_valid_prim].count - 2; indices[idx] = indices[idx - 1]; - indices[idx + 1] = add_vertex(save, vertex_to_index, original_prims[i].start, + indices[idx + 1] = add_vertex(save, vertex_to_index, + converted_prim ? CAST_INDEX(tmp_indices, index_size, 0) : original_prims[i].start, temp_vertices_buffer, &max_index); idx += 2; merged_prims[last_valid_prim].count += 2; if (tri_count % 2) { /* Add another index to preserve winding order */ - indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start, + indices[idx++] = add_vertex(save, vertex_to_index, + converted_prim ? CAST_INDEX(tmp_indices, index_size, 0) : original_prims[i].start, temp_vertices_buffer, &max_index); merged_prims[last_valid_prim].count++; } @@ -678,24 +708,40 @@ compile_vertex_list(struct gl_context *ctx) (original_prims[i + 1].mode == GL_LINE_STRIP || original_prims[i + 1].mode == GL_LINES)))) { for (unsigned j = 0; j < vertex_count; j++) { - indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j, + indices[idx++] = add_vertex(save, vertex_to_index, + converted_prim ? CAST_INDEX(tmp_indices, index_size, j) : original_prims[i].start + j, temp_vertices_buffer, &max_index); /* Repeat all but the first/last indices. */ if (j && j != vertex_count - 1) { - indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j, + indices[idx++] = add_vertex(save, vertex_to_index, + converted_prim ? CAST_INDEX(tmp_indices, index_size, j) : original_prims[i].start + j, temp_vertices_buffer, &max_index); } } } else { /* We didn't convert to LINES, so restore the original mode */ - mode = original_prims[i].mode; + if (!converted_prim) + mode = original_prims[i].mode; for (unsigned j = 0; j < vertex_count; j++) { - indices[idx++] = add_vertex(save, vertex_to_index, original_prims[i].start + j, + indices[idx++] = add_vertex(save, vertex_to_index, + converted_prim ? CAST_INDEX(tmp_indices, index_size, j) : original_prims[i].start + j, temp_vertices_buffer, &max_index); } } + /* Duplicate the last vertex for incomplete primitives */ + if (vertex_count > 0) { + unsigned min_vert = u_prim_vertex_count(mode)->min; + for (unsigned j = vertex_count; j < min_vert; j++) { + indices[idx++] = add_vertex(save, vertex_to_index, + converted_prim ? CAST_INDEX(tmp_indices, index_size, vertex_count - 1) : + original_prims[i].start + vertex_count - 1, + temp_vertices_buffer, &max_index); + } + } + +#undef CAST_INDEX if (merge_prims) { /* Update vertex count. */ merged_prims[last_valid_prim].count += idx - start; @@ -709,9 +755,10 @@ compile_vertex_list(struct gl_context *ctx) merged_prims[last_valid_prim].count = idx - start; } merged_prims[last_valid_prim].mode = mode; - } - assert(idx > 0 && idx <= max_index_count); + /* converted prims will filter incomplete primitives and may have no indices */ + assert((idx > 0 || converted_prim) && idx <= max_index_count); + } unsigned merged_prim_count = last_valid_prim + 1; node->cold->ib.ptr = NULL; @@ -741,17 +788,18 @@ compile_vertex_list(struct gl_context *ctx) if (total_bytes_needed > available_bytes) { if (save->current_bo) _mesa_reference_buffer_object(ctx, &save->current_bo, NULL); - save->current_bo = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1); - bool success = ctx->Driver.BufferData(ctx, - GL_ELEMENT_ARRAY_BUFFER_ARB, - MAX2(total_bytes_needed, VBO_SAVE_BUFFER_SIZE), - NULL, - GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT, - save->current_bo); + save->current_bo = _mesa_bufferobj_alloc(ctx, VBO_BUF_ID + 1); + bool success = _mesa_bufferobj_data(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + MAX2(total_bytes_needed, VBO_SAVE_BUFFER_SIZE), + NULL, + GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT | + MESA_GALLIUM_VERTEX_STATE_STORAGE, + save->current_bo); if (!success) { _mesa_reference_buffer_object(ctx, &save->current_bo, NULL); _mesa_error(ctx, GL_OUT_OF_MEMORY, "IB allocation"); - handle_out_of_memory(ctx); + save->out_of_memory = true; } else { save->current_bo_bytes_used = 0; available_bytes = save->current_bo->Size; @@ -796,33 +844,36 @@ compile_vertex_list(struct gl_context *ctx) _mesa_reference_buffer_object(ctx, &node->cold->ib.obj, save->current_bo); /* Upload the vertices first (see buffer_offset) */ - ctx->Driver.BufferSubData(ctx, - save->current_bo_bytes_used, - total_vert_count * save->vertex_size * sizeof(fi_type), - vertex_to_index ? temp_vertices_buffer : save->vertex_store->buffer_in_ram, - node->cold->ib.obj); + _mesa_bufferobj_subdata(ctx, + save->current_bo_bytes_used, + total_vert_count * save->vertex_size * sizeof(fi_type), + vertex_to_index ? temp_vertices_buffer : save->vertex_store->buffer_in_ram, + node->cold->ib.obj); save->current_bo_bytes_used += total_vert_count * save->vertex_size * sizeof(fi_type); + node->cold->bo_bytes_used = save->current_bo_bytes_used; if (vertex_to_index) { _mesa_hash_table_destroy(vertex_to_index, _free_entry); free(temp_vertices_buffer); } - /* Since we're append the indices to an existing buffer, we need to adjust the start value of each + /* Since we append the indices to an existing buffer, we need to adjust the start value of each * primitive (not the indices themselves). */ - save->current_bo_bytes_used += align(save->current_bo_bytes_used, 4) - save->current_bo_bytes_used; - int indices_offset = save->current_bo_bytes_used / 4; - for (int i = 0; i < merged_prim_count; i++) { - merged_prims[i].start += indices_offset; + if (!ctx->ListState.Current.UseLoopback) { + save->current_bo_bytes_used += align(save->current_bo_bytes_used, 4) - save->current_bo_bytes_used; + int indices_offset = save->current_bo_bytes_used / 4; + for (int i = 0; i < merged_prim_count; i++) { + merged_prims[i].start += indices_offset; + } } /* Then upload the indices. */ if (node->cold->ib.obj) { - ctx->Driver.BufferSubData(ctx, - save->current_bo_bytes_used, - idx * sizeof(uint32_t), - indices, - node->cold->ib.obj); + _mesa_bufferobj_subdata(ctx, + save->current_bo_bytes_used, + idx * sizeof(uint32_t), + indices, + node->cold->ib.obj); save->current_bo_bytes_used += idx * sizeof(uint32_t); } else { node->cold->vertex_count = 0; @@ -830,56 +881,59 @@ compile_vertex_list(struct gl_context *ctx) } /* Prepare for DrawGallium */ - memset(&node->merged.info, 0, sizeof(struct pipe_draw_info)); + memset(&node->cold->info, 0, sizeof(struct pipe_draw_info)); /* The other info fields will be updated in vbo_save_playback_vertex_list */ - node->merged.info.index_size = 4; - node->merged.info.instance_count = 1; - node->merged.info.index.gl_bo = node->cold->ib.obj; + node->cold->info.index_size = 4; + node->cold->info.instance_count = 1; + node->cold->info.index.resource = node->cold->ib.obj->buffer; if (merged_prim_count == 1) { - node->merged.info.mode = merged_prims[0].mode; - node->merged.start_count.start = merged_prims[0].start; - node->merged.start_count.count = merged_prims[0].count; - node->merged.start_count.index_bias = 0; - node->merged.mode = NULL; + node->cold->info.mode = merged_prims[0].mode; + node->start_count.start = merged_prims[0].start; + node->start_count.count = merged_prims[0].count; + node->start_count.index_bias = 0; + node->modes = NULL; } else { - node->merged.mode = malloc(merged_prim_count * sizeof(unsigned char)); - node->merged.start_counts = malloc(merged_prim_count * sizeof(struct pipe_draw_start_count_bias)); + node->modes = malloc(merged_prim_count * sizeof(unsigned char)); + node->start_counts = malloc(merged_prim_count * sizeof(struct pipe_draw_start_count_bias)); for (unsigned i = 0; i < merged_prim_count; i++) { - node->merged.start_counts[i].start = merged_prims[i].start; - node->merged.start_counts[i].count = merged_prims[i].count; - node->merged.start_counts[i].index_bias = 0; - node->merged.mode[i] = merged_prims[i].mode; + node->start_counts[i].start = merged_prims[i].start; + node->start_counts[i].count = merged_prims[i].count; + node->start_counts[i].index_bias = 0; + node->modes[i] = merged_prims[i].mode; } } - node->merged.num_draws = merged_prim_count; - if (node->merged.num_draws > 1) { + node->num_draws = merged_prim_count; + if (node->num_draws > 1) { bool same_mode = true; - for (unsigned i = 1; i < node->merged.num_draws && same_mode; i++) { - same_mode = node->merged.mode[i] == node->merged.mode[0]; + for (unsigned i = 1; i < node->num_draws && same_mode; i++) { + same_mode = node->modes[i] == node->modes[0]; } if (same_mode) { /* All primitives use the same mode, so we can simplify a bit */ - node->merged.info.mode = node->merged.mode[0]; - free(node->merged.mode); - node->merged.mode = NULL; + node->cold->info.mode = node->modes[0]; + free(node->modes); + node->modes = NULL; } } free(indices); + free(tmp_indices); free(merged_prims); end: + node->draw_begins = node->cold->prims[0].begin; if (!save->current_bo) { - save->current_bo = ctx->Driver.NewBufferObject(ctx, VBO_BUF_ID + 1); - bool success = ctx->Driver.BufferData(ctx, - GL_ELEMENT_ARRAY_BUFFER_ARB, - VBO_SAVE_BUFFER_SIZE, - NULL, - GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT, - save->current_bo); + save->current_bo = _mesa_bufferobj_alloc(ctx, VBO_BUF_ID + 1); + bool success = _mesa_bufferobj_data(ctx, + GL_ELEMENT_ARRAY_BUFFER_ARB, + VBO_SAVE_BUFFER_SIZE, + NULL, + GL_STATIC_DRAW_ARB, GL_MAP_WRITE_BIT | + MESA_GALLIUM_VERTEX_STATE_STORAGE, + save->current_bo); if (!success) - handle_out_of_memory(ctx); + save->out_of_memory = true; } GLuint offsets[VBO_ATTRIB_MAX]; @@ -896,37 +950,45 @@ end: save->current_bo, buffer_offset, stride, save->enabled, save->attrsz, save->attrtype, offsets); /* Reference the vao in the dlist */ - node->VAO[vpm] = NULL; - _mesa_reference_vao(ctx, &node->VAO[vpm], save->VAO[vpm]); + node->cold->VAO[vpm] = NULL; + _mesa_reference_vao(ctx, &node->cold->VAO[vpm], save->VAO[vpm]); } + /* Prepare for draw_vertex_state. */ + if (node->num_draws && ctx->Const.HasDrawVertexState) { + for (unsigned i = 0; i < VP_MODE_MAX; i++) { + uint32_t enabled_attribs = _vbo_get_vao_filter(i) & + node->cold->VAO[i]->_EnabledWithMapMode; + + node->state[i] = + st_create_gallium_vertex_state(ctx, node->cold->VAO[i], + node->cold->ib.obj, + enabled_attribs); + node->private_refcount[i] = 0; + node->enabled_attribs[i] = enabled_attribs; + } + + node->ctx = ctx; + node->mode = node->cold->info.mode; + assert(node->cold->info.index_size == 4); + } /* Deal with GL_COMPILE_AND_EXECUTE: */ if (ctx->ExecuteFlag) { - struct _glapi_table *dispatch = GET_DISPATCH(); - - _glapi_set_dispatch(ctx->Exec); - /* _vbo_loopback_vertex_list doesn't use the index buffer, so we have to - * use buffer_in_ram instead of current_bo which contains all vertices instead - * of the deduplicated vertices only in the !UseLoopback case. + * use buffer_in_ram (which contains all vertices) instead of current_bo + * (which contains deduplicated vertices *when* UseLoopback is false). * * The problem is that the VAO offset is based on current_bo's layout, * so we have to use a temp value. */ - struct gl_vertex_array_object *vao = node->VAO[VP_MODE_SHADER]; + struct gl_vertex_array_object *vao = node->cold->VAO[VP_MODE_SHADER]; GLintptr original = vao->BufferBinding[0].Offset; - if (!ctx->ListState.Current.UseLoopback) { - GLintptr new_offset = 0; - /* 'start_offset' has been added to all primitives 'start', so undo it here. */ - new_offset -= start_offset * stride; - vao->BufferBinding[0].Offset = new_offset; - } + /* 'start_offset' has been added to all primitives 'start', so undo it here. */ + vao->BufferBinding[0].Offset = -(GLintptr)(start_offset * stride); _vbo_loopback_vertex_list(ctx, node, save->vertex_store->buffer_in_ram); vao->BufferBinding[0].Offset = original; - - _glapi_set_dispatch(dispatch); } /* Reset our structures for the next run of vertices: @@ -1117,7 +1179,9 @@ upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz) grow_vertex_storage(ctx, save->copied.nr); fi_type *dest = save->vertex_store->buffer_in_ram; - /* Need to note this and fix up at runtime (or loopback): + /* Need to note this and fix up later. This can be done in + * ATTR_UNION (by copying the new attribute values to the + * vertices we're copying here) or at runtime (or loopback). */ if (attr != VBO_ATTRIB_POS && save->currentsz[attr][0] == 0) { assert(oldsz == 0); @@ -1176,13 +1240,14 @@ upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz) * For example, after seeing one or more glTexCoord2f() calls we * get a glTexCoord4f() or glTexCoord1f() call. */ -static void +static bool fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint sz, GLenum newType) { struct vbo_save_context *save = &vbo_context(ctx)->save; + bool new_attr_is_bigger = sz > save->attrsz[attr]; - if (sz > save->attrsz[attr] || + if (new_attr_is_bigger || newType != save->attrtype[attr]) { /* New size is larger. Need to flush existing vertices and get * an enlarged vertex format. @@ -1203,6 +1268,8 @@ fixup_vertex(struct gl_context *ctx, GLuint attr, save->active_sz[attr] = sz; grow_vertex_storage(ctx, 1); + + return new_attr_is_bigger; } @@ -1256,8 +1323,31 @@ do { \ struct vbo_save_context *save = &vbo_context(ctx)->save; \ int sz = (sizeof(C) / sizeof(GLfloat)); \ \ - if (save->active_sz[A] != N) \ - fixup_vertex(ctx, A, N * sz, T); \ + if (save->active_sz[A] != N) { \ + bool had_dangling_ref = save->dangling_attr_ref; \ + if (fixup_vertex(ctx, A, N * sz, T) && \ + !had_dangling_ref && save->dangling_attr_ref && \ + A != VBO_ATTRIB_POS) { \ + fi_type *dest = save->vertex_store->buffer_in_ram; \ + /* Copy the new attr values to the already copied \ + * vertices. \ + */ \ + for (int i = 0; i < save->copied.nr; i++) { \ + GLbitfield64 enabled = save->enabled; \ + while (enabled) { \ + const int j = u_bit_scan64(&enabled); \ + if (j == A) { \ + if (N>0) ((C*) dest)[0] = V0; \ + if (N>1) ((C*) dest)[1] = V1; \ + if (N>2) ((C*) dest)[2] = V2; \ + if (N>3) ((C*) dest)[3] = V3; \ + } \ + dest += save->attrsz[j]; \ + } \ + } \ + save->dangling_attr_ref = false; \ + } \ + } \ \ { \ C *dest = (C *)save->attrptr[A]; \ @@ -1278,11 +1368,8 @@ do { \ save->vertex_store->used += save->vertex_size; \ unsigned used_next = (save->vertex_store->used + \ save->vertex_size) * sizeof(float); \ - if (used_next > save->vertex_store->buffer_in_ram_size) { \ + if (used_next > save->vertex_store->buffer_in_ram_size) \ grow_vertex_storage(ctx, get_vertex_count(save)); \ - assert(used_next <= \ - save->vertex_store->buffer_in_ram_size); \ - } \ } \ } while (0) @@ -1349,6 +1436,10 @@ _save_Materialfv(GLenum face, GLenum pname, const GLfloat *params) } +static void +vbo_init_dispatch_save_begin_end(struct gl_context *ctx); + + /* Cope with EvalCoord/CallList called within a begin/end object: * -- Flush current buffer * -- Fallback to opcodes for the rest of the begin/end object. @@ -1380,10 +1471,10 @@ dlist_fallback(struct gl_context *ctx) copy_to_current(ctx); reset_vertex(ctx); if (save->out_of_memory) { - _mesa_install_save_vtxfmt(ctx, &save->vtxfmt); + vbo_install_save_vtxfmt_noop(ctx); } else { - _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); + _mesa_init_dispatch_save_begin_end(ctx); } ctx->Driver.SaveNeedFlush = GL_FALSE; } @@ -1394,7 +1485,7 @@ _save_EvalCoord1f(GLfloat u) { GET_CURRENT_CONTEXT(ctx); dlist_fallback(ctx); - CALL_EvalCoord1f(ctx->Save, (u)); + CALL_EvalCoord1f(ctx->Dispatch.Save, (u)); } static void GLAPIENTRY @@ -1402,7 +1493,7 @@ _save_EvalCoord1fv(const GLfloat * v) { GET_CURRENT_CONTEXT(ctx); dlist_fallback(ctx); - CALL_EvalCoord1fv(ctx->Save, (v)); + CALL_EvalCoord1fv(ctx->Dispatch.Save, (v)); } static void GLAPIENTRY @@ -1410,7 +1501,7 @@ _save_EvalCoord2f(GLfloat u, GLfloat v) { GET_CURRENT_CONTEXT(ctx); dlist_fallback(ctx); - CALL_EvalCoord2f(ctx->Save, (u, v)); + CALL_EvalCoord2f(ctx->Dispatch.Save, (u, v)); } static void GLAPIENTRY @@ -1418,7 +1509,7 @@ _save_EvalCoord2fv(const GLfloat * v) { GET_CURRENT_CONTEXT(ctx); dlist_fallback(ctx); - CALL_EvalCoord2fv(ctx->Save, (v)); + CALL_EvalCoord2fv(ctx->Dispatch.Save, (v)); } static void GLAPIENTRY @@ -1426,7 +1517,7 @@ _save_EvalPoint1(GLint i) { GET_CURRENT_CONTEXT(ctx); dlist_fallback(ctx); - CALL_EvalPoint1(ctx->Save, (i)); + CALL_EvalPoint1(ctx->Dispatch.Save, (i)); } static void GLAPIENTRY @@ -1434,7 +1525,7 @@ _save_EvalPoint2(GLint i, GLint j) { GET_CURRENT_CONTEXT(ctx); dlist_fallback(ctx); - CALL_EvalPoint2(ctx->Save, (i, j)); + CALL_EvalPoint2(ctx->Dispatch.Save, (i, j)); } static void GLAPIENTRY @@ -1442,7 +1533,7 @@ _save_CallList(GLuint l) { GET_CURRENT_CONTEXT(ctx); dlist_fallback(ctx); - CALL_CallList(ctx->Save, (l)); + CALL_CallList(ctx->Dispatch.Save, (l)); } static void GLAPIENTRY @@ -1450,7 +1541,7 @@ _save_CallLists(GLsizei n, GLenum type, const GLvoid * v) { GET_CURRENT_CONTEXT(ctx); dlist_fallback(ctx); - CALL_CallLists(ctx->Save, (n, type, v)); + CALL_CallLists(ctx->Dispatch.Save, (n, type, v)); } @@ -1479,7 +1570,7 @@ vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode, save->no_current_update = no_current_update; - _mesa_install_save_vtxfmt(ctx, &save->vtxfmt); + vbo_init_dispatch_save_begin_end(ctx); /* We need to call vbo_save_SaveFlushVertices() if there's state change */ ctx->Driver.SaveNeedFlush = GL_TRUE; @@ -1502,10 +1593,10 @@ _save_End(void) * as opcodes. */ if (save->out_of_memory) { - _mesa_install_save_vtxfmt(ctx, &save->vtxfmt); + vbo_install_save_vtxfmt_noop(ctx); } else { - _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); + _mesa_init_dispatch_save_begin_end(ctx); } } @@ -1537,22 +1628,17 @@ _save_PrimitiveRestartNV(void) bool no_current_update = save->no_current_update; /* restart primitive */ - CALL_End(ctx->CurrentServerDispatch, ()); + CALL_End(ctx->Dispatch.Current, ()); vbo_save_NotifyBegin(ctx, curPrim, no_current_update); } } -/* Unlike the functions above, these are to be hooked into the vtxfmt - * maintained in ctx->ListState, active when the list is known or - * suspected to be outside any begin/end primitive. - * Note: OBE = Outside Begin/End - */ -static void GLAPIENTRY -_save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) +void GLAPIENTRY +save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) { GET_CURRENT_CONTEXT(ctx); - struct _glapi_table *dispatch = ctx->CurrentServerDispatch; + struct _glapi_table *dispatch = ctx->Dispatch.Current; vbo_save_NotifyBegin(ctx, GL_QUADS, false); CALL_Vertex2f(dispatch, (x1, y1)); @@ -1563,50 +1649,44 @@ _save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2) } -static void GLAPIENTRY -_save_OBE_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2) +void GLAPIENTRY +save_Rectdv(const GLdouble *v1, const GLdouble *v2) { - _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); + save_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); } -static void GLAPIENTRY -_save_OBE_Rectdv(const GLdouble *v1, const GLdouble *v2) +void GLAPIENTRY +save_Rectfv(const GLfloat *v1, const GLfloat *v2) { - _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); + save_Rectf(v1[0], v1[1], v2[0], v2[1]); } -static void GLAPIENTRY -_save_OBE_Rectfv(const GLfloat *v1, const GLfloat *v2) +void GLAPIENTRY +save_Recti(GLint x1, GLint y1, GLint x2, GLint y2) { - _save_OBE_Rectf(v1[0], v1[1], v2[0], v2[1]); + save_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); } -static void GLAPIENTRY -_save_OBE_Recti(GLint x1, GLint y1, GLint x2, GLint y2) +void GLAPIENTRY +save_Rectiv(const GLint *v1, const GLint *v2) { - _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); + save_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); } -static void GLAPIENTRY -_save_OBE_Rectiv(const GLint *v1, const GLint *v2) +void GLAPIENTRY +save_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) { - _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); + save_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); } -static void GLAPIENTRY -_save_OBE_Rects(GLshort x1, GLshort y1, GLshort x2, GLshort y2) +void GLAPIENTRY +save_Rectsv(const GLshort *v1, const GLshort *v2) { - _save_OBE_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2); + save_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); } -static void GLAPIENTRY -_save_OBE_Rectsv(const GLshort *v1, const GLshort *v2) -{ - _save_OBE_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]); -} - -static void GLAPIENTRY -_save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count) +void GLAPIENTRY +save_DrawArrays(GLenum mode, GLint start, GLsizei count) { GET_CURRENT_CONTEXT(ctx); struct gl_vertex_array_object *vao = ctx->Array.VAO; @@ -1636,15 +1716,15 @@ _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count) for (i = 0; i < count; i++) _mesa_array_element(ctx, start + i); - CALL_End(ctx->CurrentServerDispatch, ()); + CALL_End(ctx->Dispatch.Current, ()); _mesa_vao_unmap_arrays(ctx, vao); } -static void GLAPIENTRY -_save_OBE_MultiDrawArrays(GLenum mode, const GLint *first, - const GLsizei *count, GLsizei primcount) +void GLAPIENTRY +save_MultiDrawArrays(GLenum mode, const GLint *first, + const GLsizei *count, GLsizei primcount) { GET_CURRENT_CONTEXT(ctx); GLint i; @@ -1674,7 +1754,7 @@ _save_OBE_MultiDrawArrays(GLenum mode, const GLint *first, for (i = 0; i < primcount; i++) { if (count[i] > 0) { - _save_OBE_DrawArrays(mode, first[i], count[i]); + save_DrawArrays(mode, first[i], count[i]); } } } @@ -1695,7 +1775,7 @@ array_element(struct gl_context *ctx, */ if (ctx->Array._PrimitiveRestart[index_size_shift] && elt == ctx->Array._RestartIndex[index_size_shift]) { - CALL_PrimitiveRestartNV(ctx->CurrentServerDispatch, ()); + CALL_PrimitiveRestartNV(ctx->Dispatch.Current, ()); return; } @@ -1706,9 +1786,9 @@ array_element(struct gl_context *ctx, /* Could do better by copying the arrays and element list intact and * then emitting an indexed prim at runtime. */ -static void GLAPIENTRY -_save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, - const GLvoid * indices, GLint basevertex) +void GLAPIENTRY +save_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices, GLint basevertex) { GET_CURRENT_CONTEXT(ctx); struct vbo_save_context *save = &vbo_context(ctx)->save; @@ -1765,21 +1845,21 @@ _save_OBE_DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, break; } - CALL_End(ctx->CurrentServerDispatch, ()); + CALL_End(ctx->Dispatch.Current, ()); _mesa_vao_unmap(ctx, vao); } -static void GLAPIENTRY -_save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type, - const GLvoid * indices) +void GLAPIENTRY +save_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices) { - _save_OBE_DrawElementsBaseVertex(mode, count, type, indices, 0); + save_DrawElementsBaseVertex(mode, count, type, indices, 0); } -static void GLAPIENTRY -_save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end, +void GLAPIENTRY +save_DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid * indices) { @@ -1810,16 +1890,31 @@ _save_OBE_DrawRangeElements(GLenum mode, GLuint start, GLuint end, if (save->out_of_memory) return; - _save_OBE_DrawElements(mode, count, type, indices); + save_DrawElements(mode, count, type, indices); } +void GLAPIENTRY +save_DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices, GLint basevertex) +{ + GET_CURRENT_CONTEXT(ctx); + + if (end < start) { + _mesa_compile_error(ctx, GL_INVALID_VALUE, + "glDrawRangeElementsBaseVertex(end < start)"); + return; + } + + save_DrawElementsBaseVertex(mode, count, type, indices, basevertex); +} -static void GLAPIENTRY -_save_OBE_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, - const GLvoid * const *indices, GLsizei primcount) +void GLAPIENTRY +save_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, + const GLvoid * const *indices, GLsizei primcount) { GET_CURRENT_CONTEXT(ctx); - struct _glapi_table *dispatch = ctx->CurrentServerDispatch; + struct _glapi_table *dispatch = ctx->Dispatch.Current; GLsizei i; int vertcount = 0; @@ -1836,15 +1931,15 @@ _save_OBE_MultiDrawElements(GLenum mode, const GLsizei *count, GLenum type, } -static void GLAPIENTRY -_save_OBE_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, - GLenum type, - const GLvoid * const *indices, - GLsizei primcount, - const GLint *basevertex) +void GLAPIENTRY +save_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, + GLenum type, + const GLvoid * const *indices, + GLsizei primcount, + const GLint *basevertex) { GET_CURRENT_CONTEXT(ctx); - struct _glapi_table *dispatch = ctx->CurrentServerDispatch; + struct _glapi_table *dispatch = ctx->Dispatch.Current; GLsizei i; int vertcount = 0; @@ -1864,49 +1959,18 @@ _save_OBE_MultiDrawElementsBaseVertex(GLenum mode, const GLsizei *count, static void -vtxfmt_init(struct gl_context *ctx) +vbo_init_dispatch_save_begin_end(struct gl_context *ctx) { - struct vbo_save_context *save = &vbo_context(ctx)->save; - GLvertexformat *vfmt = &save->vtxfmt; - -#define NAME_AE(x) _ae_##x +#define NAME_AE(x) _mesa_##x #define NAME_CALLLIST(x) _save_##x #define NAME(x) _save_##x -#define NAME_ES(x) _save_##x##ARB +#define NAME_ES(x) _save_##x -#include "vbo_init_tmp.h" + struct _glapi_table *tab = ctx->Dispatch.Save; + #include "api_beginend_init.h" } -/** - * Initialize the dispatch table with the VBO functions for display - * list compilation. - */ -void -vbo_initialize_save_dispatch(const struct gl_context *ctx, - struct _glapi_table *exec) -{ - SET_DrawArrays(exec, _save_OBE_DrawArrays); - SET_MultiDrawArrays(exec, _save_OBE_MultiDrawArrays); - SET_DrawElements(exec, _save_OBE_DrawElements); - SET_DrawElementsBaseVertex(exec, _save_OBE_DrawElementsBaseVertex); - SET_DrawRangeElements(exec, _save_OBE_DrawRangeElements); - SET_MultiDrawElementsEXT(exec, _save_OBE_MultiDrawElements); - SET_MultiDrawElementsBaseVertex(exec, _save_OBE_MultiDrawElementsBaseVertex); - SET_Rectf(exec, _save_OBE_Rectf); - SET_Rectd(exec, _save_OBE_Rectd); - SET_Rectdv(exec, _save_OBE_Rectdv); - SET_Rectfv(exec, _save_OBE_Rectfv); - SET_Recti(exec, _save_OBE_Recti); - SET_Rectiv(exec, _save_OBE_Rectiv); - SET_Rects(exec, _save_OBE_Rects); - SET_Rectsv(exec, _save_OBE_Rectsv); - - /* Note: other glDraw functins aren't compiled into display lists */ -} - - - void vbo_save_SaveFlushVertices(struct gl_context *ctx) { @@ -1976,7 +2040,7 @@ vbo_save_EndList(struct gl_context *ctx) * etc. received between here and the next begin will be compiled * as opcodes. */ - _mesa_install_save_vtxfmt(ctx, &ctx->ListState.ListVtxfmt); + _mesa_init_dispatch_save_begin_end(ctx); } assert(save->vertex_size == 0); @@ -1992,10 +2056,8 @@ current_init(struct gl_context *ctx) GLint i; for (i = VBO_ATTRIB_POS; i <= VBO_ATTRIB_EDGEFLAG; i++) { - const GLuint j = i - VBO_ATTRIB_POS; - assert(j < VERT_ATTRIB_MAX); - save->currentsz[i] = &ctx->ListState.ActiveAttribSize[j]; - save->current[i] = (fi_type *) ctx->ListState.CurrentAttrib[j]; + save->currentsz[i] = &ctx->ListState.ActiveAttribSize[i]; + save->current[i] = (fi_type *) ctx->ListState.CurrentAttrib[i]; } for (i = VBO_ATTRIB_FIRST_MATERIAL; i <= VBO_ATTRIB_LAST_MATERIAL; i++) { @@ -2015,6 +2077,5 @@ vbo_save_api_init(struct vbo_save_context *save) { struct gl_context *ctx = gl_context_from_vbo_save(save); - vtxfmt_init(ctx); current_init(ctx); } |