#include "util/bitscan.h"
#include "util/u_memory.h"
#include "util/hash_table.h"
-#include "util/indices/u_indices.h"
+#include "gallium/auxiliary/indices/u_indices.h"
+#include "util/u_prim.h"
#include "gallium/include/pipe/p_state.h"
#include "vbo_private.h"
-
-#include "state_tracker/st_cb_bufferobjects.h"
+#include "api_exec_decl.h"
+#include "api_save.h"
#ifdef ERROR
#undef ERROR
/* converting primitive types may result in many more indices */
bool all_prims_supported = (ctx->Const.DriverSupportedPrimMask & BITFIELD_MASK(PIPE_PRIM_MAX)) == BITFIELD_MASK(PIPE_PRIM_MAX);
int max_index_count = total_vert_count * (all_prims_supported ? 2 : 3);
-
- int size = max_index_count * sizeof(uint32_t);
- uint32_t* indices = (uint32_t*) malloc(size);
- void *tmp_indices = all_prims_supported ? NULL : malloc(size);
+ 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;
continue;
}
+ /* Increase indices storage if the original estimation was too small. */
+ if (idx + 3 * vertex_count > max_index_count) {
+ max_index_count = max_index_count + 3 * 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;
PV_LAST, PV_LAST,
&pmode, &index_size, &new_count,
&trans_func);
- if (new_count > 0) {
+ if (new_count > 0)
trans_func(original_prims[i].start, new_count, tmp_indices);
- vertex_count = new_count;
- mode = (GLubyte)pmode;
- converted_prim = true;
- }
+ vertex_count = new_count;
+ mode = (GLubyte)pmode;
+ converted_prim = true;
}
/* If 2 consecutive prims use the same mode => merge them. */
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;
}
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;
if (total_bytes_needed > available_bytes) {
if (save->current_bo)
_mesa_reference_buffer_object(ctx, &save->current_bo, NULL);
- save->current_bo = st_bufferobj_alloc(ctx, VBO_BUF_ID + 1);
- bool success = st_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);
+ 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");
_mesa_reference_buffer_object(ctx, &node->cold->ib.obj, save->current_bo);
/* Upload the vertices first (see buffer_offset) */
- st_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);
+ _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) {
- st_bufferobj_subdata(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;
node->draw_begins = node->cold->prims[0].begin;
if (!save->current_bo) {
- save->current_bo = st_bufferobj_alloc(ctx, VBO_BUF_ID + 1);
- bool success = st_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);
+ 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)
save->out_of_memory = true;
}
/* 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->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:
static void
-vbo_install_save_vtxfmt(struct gl_context *ctx);
+vbo_init_dispatch_save_begin_end(struct gl_context *ctx);
/* Cope with EvalCoord/CallList called within a begin/end object:
vbo_install_save_vtxfmt_noop(ctx);
}
else {
- _mesa_install_save_vtxfmt(ctx);
+ _mesa_init_dispatch_save_begin_end(ctx);
}
ctx->Driver.SaveNeedFlush = GL_FALSE;
}
save->no_current_update = no_current_update;
- vbo_install_save_vtxfmt(ctx);
+ vbo_init_dispatch_save_begin_end(ctx);
/* We need to call vbo_save_SaveFlushVertices() if there's state change */
ctx->Driver.SaveNeedFlush = GL_TRUE;
vbo_install_save_vtxfmt_noop(ctx);
}
else {
- _mesa_install_save_vtxfmt(ctx);
+ _mesa_init_dispatch_save_begin_end(ctx);
}
}
}
-/* 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
- */
void GLAPIENTRY
save_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
{
void GLAPIENTRY
-save_Rectd(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
-{
- save_Rectf((GLfloat) x1, (GLfloat) y1, (GLfloat) x2, (GLfloat) y2);
-}
-
-void GLAPIENTRY
save_Rectdv(const GLdouble *v1, const GLdouble *v2)
{
save_Rectf((GLfloat) v1[0], (GLfloat) v1[1], (GLfloat) v2[0], (GLfloat) v2[1]);
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);
+}
void GLAPIENTRY
-save_MultiDrawElementsEXT(GLenum mode, const GLsizei *count, GLenum type,
- const GLvoid * const *indices, GLsizei primcount)
+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;
static void
-vbo_install_save_vtxfmt(struct gl_context *ctx)
+vbo_init_dispatch_save_begin_end(struct gl_context *ctx)
{
#define NAME_AE(x) _mesa_##x
#define NAME_CALLLIST(x) _save_##x
#define NAME_ES(x) _save_##x
struct _glapi_table *tab = ctx->Save;
- #include "api_vtxfmt_init.h"
+ #include "api_beginend_init.h"
}
* etc. received between here and the next begin will be compiled
* as opcodes.
*/
- _mesa_install_save_vtxfmt(ctx);
+ _mesa_init_dispatch_save_begin_end(ctx);
}
assert(save->vertex_size == 0);