#include "util/bitscan.h"
#include "util/u_memory.h"
+#include "gallium/include/pipe/p_state.h"
+
#include "vbo_noop.h"
#include "vbo_private.h"
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);
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;
}
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;
/* 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;
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++;
}
}
}
}
- 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 */
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:
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;
}
}
}