diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index db504cd1346..5012996da44 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -804,7 +804,8 @@ vbo_destroy_vertex_list(struct gl_context *ctx, struct vbo_save_vertex_list *nod free(node->prim_store); } - free(node->merged.prims); + free(node->merged.mode); + free(node->merged.start_count); _mesa_reference_buffer_object(ctx, &node->merged.ib.obj, NULL); free(node->current_data); diff --git a/src/mesa/vbo/vbo_save.h b/src/mesa/vbo/vbo_save.h index fba351c1f81..131f6ac82f4 100644 --- a/src/mesa/vbo/vbo_save.h +++ b/src/mesa/vbo/vbo_save.h @@ -69,10 +69,11 @@ struct vbo_save_vertex_list { GLuint min_index, max_index; struct { - struct _mesa_prim *prims; struct _mesa_index_buffer ib; - GLuint prim_count; - GLuint min_index, max_index; + struct pipe_draw_info info; + unsigned char *mode; + struct pipe_draw_start_count *start_count; + unsigned num_draws; } merged; struct vbo_save_primitive_store *prim_store; diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index 854daefe90a..411c274f5d4 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -84,6 +84,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "util/bitscan.h" #include "util/u_memory.h" +#include "gallium/include/pipe/p_state.h" + #include "vbo_noop.h" #include "vbo_private.h" @@ -534,6 +536,8 @@ compile_vertex_list(struct gl_context *ctx) if (!node) return; + memset(node, 0, sizeof(struct vbo_save_vertex_list)); + /* Make sure the pointer is aligned to the size of a pointer */ assert((GLintptr) node % sizeof(void *) == 0); @@ -574,9 +578,7 @@ compile_vertex_list(struct gl_context *ctx) node->vertex_count = save->vert_count; node->wrap_count = save->copied.nr; node->prims = save->prims; - node->merged.prims = NULL; node->merged.ib.obj = NULL; - node->merged.prim_count = 0; node->prim_count = save->prim_count; node->prim_store = save->prim_store; @@ -673,7 +675,7 @@ compile_vertex_list(struct gl_context *ctx) } int size = max_indices_count * sizeof(uint32_t); uint32_t* indices = (uint32_t*) malloc(size); - uint32_t max_index = 0, min_index = 0xFFFFFFFF; + struct _mesa_prim *merged_prims = NULL; int idx = 0; @@ -694,7 +696,7 @@ compile_vertex_list(struct gl_context *ctx) /* If 2 consecutive prims use the same mode => merge them. */ bool merge_prims = last_valid_prim >= 0 && - mode == node->merged.prims[last_valid_prim].mode && + mode == merged_prims[last_valid_prim].mode && mode != GL_LINE_LOOP && mode != GL_TRIANGLE_FAN && mode != GL_QUAD_STRIP && mode != GL_POLYGON && mode != GL_PATCHES; @@ -705,18 +707,18 @@ compile_vertex_list(struct gl_context *ctx) if (merge_prims && mode == GL_TRIANGLE_STRIP) { /* Insert a degenerate triangle */ - assert(node->merged.prims[last_valid_prim].mode == GL_TRIANGLE_STRIP); - unsigned tri_count = node->merged.prims[last_valid_prim].count - 2; + assert(merged_prims[last_valid_prim].mode == GL_TRIANGLE_STRIP); + unsigned tri_count = merged_prims[last_valid_prim].count - 2; indices[idx] = indices[idx - 1]; indices[idx + 1] = original_prims[i].start; idx += 2; - node->merged.prims[last_valid_prim].count += 2; + merged_prims[last_valid_prim].count += 2; if (tri_count % 2) { /* Add another index to preserve winding order */ indices[idx++] = original_prims[i].start; - node->merged.prims[last_valid_prim].count++; + merged_prims[last_valid_prim].count++; } } @@ -747,32 +749,27 @@ compile_vertex_list(struct gl_context *ctx) } } - min_index = MIN2(min_index, indices[start]); - max_index = MAX2(max_index, indices[idx - 1]); - if (merge_prims) { /* Update vertex count. */ - node->merged.prims[last_valid_prim].count += idx - start; + merged_prims[last_valid_prim].count += idx - start; } else { /* Keep this primitive */ last_valid_prim += 1; assert(last_valid_prim <= i); - node->merged.prims = realloc(node->merged.prims, (1 + last_valid_prim) * sizeof(struct _mesa_prim)); - node->merged.prims[last_valid_prim] = original_prims[i]; - node->merged.prims[last_valid_prim].start = indices_offset + start; - node->merged.prims[last_valid_prim].count = idx - start; + merged_prims = realloc(merged_prims, (1 + last_valid_prim) * sizeof(struct _mesa_prim)); + merged_prims[last_valid_prim] = original_prims[i]; + merged_prims[last_valid_prim].start = indices_offset + start; + merged_prims[last_valid_prim].count = idx - start; } - node->merged.prims[last_valid_prim].mode = mode; + merged_prims[last_valid_prim].mode = mode; } assert(idx > 0 && idx <= max_indices_count); - node->merged.prim_count = last_valid_prim + 1; + unsigned merged_prim_count = last_valid_prim + 1; node->merged.ib.ptr = NULL; node->merged.ib.count = idx; node->merged.ib.index_size_shift = (GL_UNSIGNED_INT - GL_UNSIGNED_BYTE) >> 1; - node->merged.min_index = min_index; - node->merged.max_index = max_index; if (!indices_offset) { /* Allocate a new index buffer */ @@ -804,7 +801,42 @@ compile_vertex_list(struct gl_context *ctx) node->prim_count = 0; } + /* Prepare for DrawGallium */ + memset(&node->merged.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->merged.ib.obj; + node->merged.start_count = malloc(merged_prim_count * sizeof(struct pipe_draw_start_count)); + if (merged_prim_count == 1) { + node->merged.info.mode = merged_prims[0].mode; + node->merged.mode = NULL; + } else { + node->merged.mode = malloc(merged_prim_count * sizeof(unsigned char)); + } + + for (unsigned i = 0; i < merged_prim_count; i++) { + node->merged.start_count[i].start = merged_prims[i].start; + node->merged.start_count[i].count = merged_prims[i].count; + if (merged_prim_count > 1) + node->merged.mode[i] = merged_prims[i].mode; + } + node->merged.num_draws = merged_prim_count; + if (node->merged.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]; + } + 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; + } + } + free(indices); + free(merged_prims); } /* Deal with GL_COMPILE_AND_EXECUTE: diff --git a/src/mesa/vbo/vbo_save_draw.c b/src/mesa/vbo/vbo_save_draw.c index 19ecc34145f..f2d1c898699 100644 --- a/src/mesa/vbo/vbo_save_draw.c +++ b/src/mesa/vbo/vbo_save_draw.c @@ -225,15 +225,27 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data) if (node->vertex_count > 0) { bool draw_using_merged_prim = (ctx->Const.AllowIncorrectPrimitiveId || ctx->_PrimitiveIDIsUnused) && - node->merged.prims; + node->merged.num_draws; if (!draw_using_merged_prim) { ctx->Driver.Draw(ctx, node->prims, node->prim_count, NULL, true, false, 0, node->min_index, node->max_index, 1, 0); } else { - ctx->Driver.Draw(ctx, node->merged.prims, node->merged.prim_count, - &node->merged.ib, true, - false, 0, node->merged.min_index, node->merged.max_index, 1, 0); + struct pipe_draw_info *info = (struct pipe_draw_info *) &node->merged.info; + info->vertices_per_patch = ctx->TessCtrlProgram.patch_vertices; + void *gl_bo = info->index.gl_bo; + if (node->merged.mode) { + ctx->Driver.DrawGalliumComplex(ctx, info, + node->merged.start_count, + node->merged.mode, + NULL, + node->merged.num_draws); + } else { + ctx->Driver.DrawGallium(ctx, info, + node->merged.start_count, + node->merged.num_draws); + } + info->index.gl_bo = gl_bo; } } }