summaryrefslogtreecommitdiff
path: root/src/mesa/vbo/vbo_save_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/vbo/vbo_save_api.c')
-rw-r--r--src/mesa/vbo/vbo_save_api.c529
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);
}