#include "main/glheader.h"
+#include "main/arrayobj.h"
#include "main/bufferobj.h"
#include "main/context.h"
#include "main/dlist.h"
#include "main/enums.h"
#include "main/eval.h"
#include "main/macros.h"
-#include "main/api_validate.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 "vbo_context.h"
#include "vbo_noop.h"
+#include "vbo_private.h"
#ifdef ERROR
#undef ERROR
#endif
+/**
+ * Display list flag only used by this VBO code.
+ */
+#define DLIST_DANGLING_REFS 0x1
+
/* An interesting VBO number/name to help with debugging */
#define VBO_BUF_ID 12345
* wrong-footed on replay.
*/
static GLuint
-_save_copy_vertices(struct gl_context *ctx,
- const struct vbo_save_vertex_list *node,
- const fi_type * src_buffer)
+copy_vertices(struct gl_context *ctx,
+ const struct vbo_save_vertex_list *node,
+ const fi_type * src_buffer)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
- const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
- GLuint nr = prim->count;
+ struct _mesa_prim *prim = &node->prims[node->prim_count - 1];
GLuint sz = save->vertex_size;
const fi_type *src = src_buffer + prim->start * sz;
fi_type *dst = save->copied.buffer;
- GLuint ovf, i;
if (prim->end)
return 0;
- switch (prim->mode) {
- case GL_POINTS:
- return 0;
- case GL_LINES:
- ovf = nr & 1;
- for (i = 0; i < ovf; i++)
- memcpy(dst + i * sz, src + (nr - ovf + i) * sz,
- sz * sizeof(GLfloat));
- return i;
- case GL_TRIANGLES:
- ovf = nr % 3;
- for (i = 0; i < ovf; i++)
- memcpy(dst + i * sz, src + (nr - ovf + i) * sz,
- sz * sizeof(GLfloat));
- return i;
- case GL_QUADS:
- ovf = nr & 3;
- for (i = 0; i < ovf; i++)
- memcpy(dst + i * sz, src + (nr - ovf + i) * sz,
- sz * sizeof(GLfloat));
- return i;
- case GL_LINE_STRIP:
- if (nr == 0)
- return 0;
- else {
- memcpy(dst, src + (nr - 1) * sz, sz * sizeof(GLfloat));
- return 1;
- }
- case GL_LINE_LOOP:
- case GL_TRIANGLE_FAN:
- case GL_POLYGON:
- if (nr == 0)
- return 0;
- else if (nr == 1) {
- memcpy(dst, src + 0, sz * sizeof(GLfloat));
- return 1;
- }
- else {
- memcpy(dst, src + 0, sz * sizeof(GLfloat));
- memcpy(dst + sz, src + (nr - 1) * sz, sz * sizeof(GLfloat));
- return 2;
- }
- case GL_TRIANGLE_STRIP:
- case GL_QUAD_STRIP:
- switch (nr) {
- case 0:
- ovf = 0;
- break;
- case 1:
- ovf = 1;
- break;
- default:
- ovf = 2 + (nr & 1);
- break;
- }
- for (i = 0; i < ovf; i++)
- memcpy(dst + i * sz, src + (nr - ovf + i) * sz,
- sz * sizeof(GLfloat));
- return i;
- default:
- assert(0);
- return 0;
- }
+ return vbo_copy_vertices(ctx, prim->mode, prim, sz, true, dst, src);
}
_mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
}
- vertex_store->buffer = NULL;
+ vertex_store->buffer_map = NULL;
vertex_store->used = 0;
- vertex_store->refcount = 1;
return vertex_store;
}
free_vertex_store(struct gl_context *ctx,
struct vbo_save_vertex_store *vertex_store)
{
- assert(!vertex_store->buffer);
+ assert(!vertex_store->buffer_map);
if (vertex_store->bufferobj) {
_mesa_reference_buffer_object(ctx, &vertex_store->bufferobj, NULL);
GL_MAP_FLUSH_EXPLICIT_BIT);
assert(vertex_store->bufferobj);
- assert(!vertex_store->buffer); /* the buffer should not be mapped */
+ assert(!vertex_store->buffer_map); /* the buffer should not be mapped */
if (vertex_store->bufferobj->Size > 0) {
/* Map the remaining free space in the VBO */
MAP_INTERNAL);
if (range) {
/* compute address of start of whole buffer (needed elsewhere) */
- vertex_store->buffer = range - vertex_store->used;
- assert(vertex_store->buffer);
+ vertex_store->buffer_map = range - vertex_store->used;
+ assert(vertex_store->buffer_map);
return range;
}
else {
- vertex_store->buffer = NULL;
+ vertex_store->buffer_map = NULL;
return NULL;
}
}
ctx->Driver.UnmapBuffer(ctx, vertex_store->bufferobj, MAP_INTERNAL);
}
- vertex_store->buffer = NULL;
+ vertex_store->buffer_map = NULL;
}
static struct vbo_save_primitive_store *
-alloc_prim_store(struct gl_context *ctx)
+alloc_prim_store(void)
{
struct vbo_save_primitive_store *store =
CALLOC_STRUCT(vbo_save_primitive_store);
- (void) ctx;
store->used = 0;
store->refcount = 1;
return store;
static void
-_save_reset_counters(struct gl_context *ctx)
+reset_counters(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
- save->prim = save->prim_store->buffer + save->prim_store->used;
- save->buffer = save->vertex_store->buffer + save->vertex_store->used;
+ save->prims = save->prim_store->prims + save->prim_store->used;
+ save->buffer_map = save->vertex_store->buffer_map + save->vertex_store->used;
- assert(save->buffer == save->buffer_ptr);
+ assert(save->buffer_map == save->buffer_ptr);
if (save->vertex_size)
save->max_vert = (VBO_SAVE_BUFFER_SIZE - save->vertex_store->used) /
* previous prim.
*/
static void
-merge_prims(struct _mesa_prim *prim_list,
+merge_prims(struct gl_context *ctx, struct _mesa_prim *prim_list,
GLuint *prim_count)
{
GLuint i;
vbo_try_prim_conversion(this_prim);
- if (vbo_can_merge_prims(prev_prim, this_prim)) {
+ if (vbo_merge_draws(ctx, true, prev_prim, this_prim)) {
/* We've found a prim that just extend the previous one. Tack it
* onto the previous one, and let this primitive struct get dropped.
*/
- vbo_merge_prims(prev_prim, this_prim);
continue;
}
convert_line_loop_to_strip(struct vbo_save_context *save,
struct vbo_save_vertex_list *node)
{
- struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
+ struct _mesa_prim *prim = &node->prims[node->prim_count - 1];
assert(prim->mode == GL_LINE_LOOP);
*/
const GLuint sz = save->vertex_size;
/* 0th vertex: */
- const fi_type *src = save->buffer + prim->start * sz;
+ const fi_type *src = save->buffer_map + prim->start * sz;
/* end of buffer: */
- fi_type *dst = save->buffer + (prim->start + prim->count) * sz;
+ fi_type *dst = save->buffer_map + (prim->start + prim->count) * sz;
memcpy(dst, src, sz * sizeof(float));
prim->count++;
- node->count++;
+ node->vertex_count++;
save->vert_count++;
save->buffer_ptr += sz;
save->vertex_store->used += sz;
}
+/* Compare the present vao if it has the same setup. */
+static bool
+compare_vao(gl_vertex_processing_mode mode,
+ const struct gl_vertex_array_object *vao,
+ const struct gl_buffer_object *bo, GLintptr buffer_offset,
+ GLuint stride, GLbitfield64 vao_enabled,
+ const GLubyte size[VBO_ATTRIB_MAX],
+ const GLenum16 type[VBO_ATTRIB_MAX],
+ const GLuint offset[VBO_ATTRIB_MAX])
+{
+ if (!vao)
+ return false;
+
+ /* If the enabled arrays are not the same we are not equal. */
+ if (vao_enabled != vao->Enabled)
+ return false;
+
+ /* Check the buffer binding at 0 */
+ if (vao->BufferBinding[0].BufferObj != bo)
+ return false;
+ /* BufferBinding[0].Offset != buffer_offset is checked per attribute */
+ if (vao->BufferBinding[0].Stride != stride)
+ return false;
+ assert(vao->BufferBinding[0].InstanceDivisor == 0);
+
+ /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space */
+ const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
+
+ /* Now check the enabled arrays */
+ GLbitfield mask = vao_enabled;
+ while (mask) {
+ const int attr = u_bit_scan(&mask);
+ const unsigned char vbo_attr = vao_to_vbo_map[attr];
+ const GLenum16 tp = type[vbo_attr];
+ const GLintptr off = offset[vbo_attr] + buffer_offset;
+ const struct gl_array_attributes *attrib = &vao->VertexAttrib[attr];
+ if (attrib->RelativeOffset + vao->BufferBinding[0].Offset != off)
+ return false;
+ if (attrib->Format.Type != tp)
+ return false;
+ if (attrib->Format.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->BufferBindingIndex == 0);
+ }
+
+ return true;
+}
+
+
+/* Create or reuse the vao for the vertex processing mode. */
+static void
+update_vao(struct gl_context *ctx,
+ gl_vertex_processing_mode mode,
+ struct gl_vertex_array_object **vao,
+ struct gl_buffer_object *bo, GLintptr buffer_offset,
+ GLuint stride, GLbitfield64 vbo_enabled,
+ const GLubyte size[VBO_ATTRIB_MAX],
+ const GLenum16 type[VBO_ATTRIB_MAX],
+ const GLuint offset[VBO_ATTRIB_MAX])
+{
+ /* Compute the bitmasks of vao_enabled arrays */
+ GLbitfield vao_enabled = _vbo_get_vao_enabled_from_vbo(mode, vbo_enabled);
+
+ /*
+ * Check if we can possibly reuse the exisiting one.
+ * In the long term we should reset them when something changes.
+ */
+ if (compare_vao(mode, *vao, bo, buffer_offset, stride,
+ vao_enabled, size, type, offset))
+ return;
+
+ /* The initial refcount is 1 */
+ _mesa_reference_vao(ctx, vao, NULL);
+ *vao = _mesa_new_vao(ctx, ~((GLuint)0));
+
+ /*
+ * assert(stride <= ctx->Const.MaxVertexAttribStride);
+ * MaxVertexAttribStride is not set for drivers that does not
+ * expose GL 44 or GLES 31.
+ */
+
+ /* Bind the buffer object at binding point 0 */
+ _mesa_bind_vertex_buffer(ctx, *vao, 0, bo, buffer_offset, stride);
+
+ /* Retrieve the mapping from VBO_ATTRIB to VERT_ATTRIB space
+ * Note that the position/generic0 aliasing is done in the VAO.
+ */
+ const GLubyte *const vao_to_vbo_map = _vbo_attribute_alias_map[mode];
+ /* Now set the enable arrays */
+ GLbitfield mask = vao_enabled;
+ while (mask) {
+ const int vao_attr = u_bit_scan(&mask);
+ const GLubyte vbo_attr = vao_to_vbo_map[vao_attr];
+ assert(offset[vbo_attr] <= ctx->Const.MaxVertexAttribRelativeOffset);
+
+ _vbo_set_attrib_format(ctx, *vao, vao_attr, buffer_offset,
+ size[vbo_attr], type[vbo_attr], offset[vbo_attr]);
+ _mesa_vertex_attrib_binding(ctx, *vao, vao_attr, 0);
+ }
+ _mesa_enable_vertex_array_attribs(ctx, *vao, vao_enabled);
+ assert(vao_enabled == (*vao)->Enabled);
+ assert((vao_enabled & ~(*vao)->VertexAttribBufferMask) == 0);
+
+ /* Finalize and freeze the VAO */
+ _mesa_set_vao_immutable(ctx, *vao);
+}
+
+
/**
* Insert the active immediate struct onto the display list currently
* being built.
*/
static void
-_save_compile_vertex_list(struct gl_context *ctx)
+compile_vertex_list(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
struct vbo_save_vertex_list *node;
/* Duplicate our template, increment refcounts to the storage structs:
*/
- node->enabled = save->enabled;
- memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz));
- memcpy(node->attrtype, save->attrtype, sizeof(node->attrtype));
- node->vertex_size = save->vertex_size;
- node->buffer_offset =
- (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat);
- node->count = save->vert_count;
+ GLintptr old_offset = 0;
+ if (save->VAO[0]) {
+ old_offset = save->VAO[0]->BufferBinding[0].Offset
+ + save->VAO[0]->VertexAttrib[VERT_ATTRIB_POS].RelativeOffset;
+ }
+ const GLsizei stride = save->vertex_size*sizeof(GLfloat);
+ GLintptr buffer_offset =
+ (save->buffer_map - save->vertex_store->buffer_map) * sizeof(GLfloat);
+ assert(old_offset <= buffer_offset);
+ const GLintptr offset_diff = buffer_offset - old_offset;
+ GLuint start_offset = 0;
+ if (offset_diff > 0 && stride > 0 && offset_diff % stride == 0) {
+ /* The vertex size is an exact multiple of the buffer offset.
+ * This means that we can use zero-based vertex attribute pointers
+ * and specify the start of the primitive with the _mesa_prim::start
+ * field. This results in issuing several draw calls with identical
+ * vertex attribute information. This can result in fewer state
+ * changes in drivers. In particular, the Gallium CSO module will
+ * filter out redundant vertex buffer changes.
+ */
+ /* We cannot immediately update the primitives as some methods below
+ * still need the uncorrected start vertices
+ */
+ start_offset = offset_diff/stride;
+ assert(old_offset == buffer_offset - offset_diff);
+ buffer_offset = old_offset;
+ }
+ GLuint offsets[VBO_ATTRIB_MAX];
+ for (unsigned i = 0, offset = 0; i < VBO_ATTRIB_MAX; ++i) {
+ offsets[i] = offset;
+ offset += save->attrsz[i] * sizeof(GLfloat);
+ }
+ node->vertex_count = save->vert_count;
node->wrap_count = save->copied.nr;
- node->dangling_attr_ref = save->dangling_attr_ref;
- node->prim = save->prim;
+ node->prims = save->prims;
node->prim_count = save->prim_count;
- node->vertex_store = save->vertex_store;
node->prim_store = save->prim_store;
- node->vertex_store->refcount++;
+ /* Create a pair of VAOs for the possible VERTEX_PROCESSING_MODEs
+ * Note that this may reuse the previous one of possible.
+ */
+ for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm) {
+ /* create or reuse the vao */
+ update_vao(ctx, vpm, &save->VAO[vpm],
+ save->vertex_store->bufferobj, 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->prim_store->refcount++;
- if (node->prim[0].no_current_update) {
- node->current_size = 0;
+ if (save->no_current_update) {
node->current_data = NULL;
}
else {
- node->current_size = node->vertex_size - node->attrsz[0];
+ GLuint current_size = save->vertex_size - save->attrsz[0];
node->current_data = NULL;
- if (node->current_size) {
- /* If the malloc fails, we just pull the data out of the VBO
- * later instead.
- */
- node->current_data = malloc(node->current_size * sizeof(GLfloat));
+ if (current_size) {
+ node->current_data = malloc(current_size * sizeof(GLfloat));
if (node->current_data) {
- const char *buffer = (const char *) save->vertex_store->buffer;
- unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat);
+ const char *buffer = (const char *)save->buffer_map;
+ unsigned attr_offset = save->attrsz[0] * sizeof(GLfloat);
unsigned vertex_offset = 0;
- if (node->count)
- vertex_offset =
- (node->count - 1) * node->vertex_size * sizeof(GLfloat);
+ if (node->vertex_count)
+ vertex_offset = (node->vertex_count - 1) * stride;
- memcpy(node->current_data,
- buffer + node->buffer_offset + vertex_offset + attr_offset,
- node->current_size * sizeof(GLfloat));
+ memcpy(node->current_data, buffer + vertex_offset + attr_offset,
+ current_size * sizeof(GLfloat));
+ } else {
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "Current value allocation");
}
}
}
- assert(node->attrsz[VBO_ATTRIB_POS] != 0 || node->count == 0);
+ assert(save->attrsz[VBO_ATTRIB_POS] != 0 || node->vertex_count == 0);
if (save->dangling_attr_ref)
ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
- save->vertex_store->used += save->vertex_size * node->count;
+ save->vertex_store->used += save->vertex_size * node->vertex_count;
save->prim_store->used += node->prim_count;
/* Copy duplicated vertices
*/
- save->copied.nr = _save_copy_vertices(ctx, node, save->buffer);
+ save->copied.nr = copy_vertices(ctx, node, save->buffer_map);
- if (node->prim[node->prim_count - 1].mode == GL_LINE_LOOP) {
+ if (node->prims[node->prim_count - 1].mode == GL_LINE_LOOP) {
convert_line_loop_to_strip(save, node);
}
- merge_prims(node->prim, &node->prim_count);
+ merge_prims(ctx, node->prims, &node->prim_count);
+
+ /* Correct the primitive starts, we can only do this here as copy_vertices
+ * and convert_line_loop_to_strip above consume the uncorrected starts.
+ * On the other hand the _vbo_loopback_vertex_list call below needs the
+ * primitves to be corrected already.
+ */
+ for (unsigned i = 0; i < node->prim_count; i++) {
+ node->prims[i].start += start_offset;
+ }
/* Deal with GL_COMPILE_AND_EXECUTE:
*/
_glapi_set_dispatch(ctx->Exec);
- vbo_loopback_vertex_list(ctx,
- (const GLfloat *) ((const char *) save->
- vertex_store->buffer +
- node->buffer_offset),
- node->attrsz, node->prim, node->prim_count,
- node->wrap_count, node->vertex_size);
+ /* Note that the range of referenced vertices must be mapped already */
+ _vbo_loopback_vertex_list(ctx, node);
_glapi_set_dispatch(dispatch);
}
/* Release old reference:
*/
- save->vertex_store->refcount--;
- assert(save->vertex_store->refcount != 0);
+ free_vertex_store(ctx, save->vertex_store);
save->vertex_store = NULL;
+ /* When we have a new vbo, we will for sure need a new vao */
+ for (gl_vertex_processing_mode vpm = 0; vpm < VP_MODE_MAX; ++vpm)
+ _mesa_reference_vao(ctx, &save->VAO[vpm], NULL);
/* Allocate and map new store:
*/
}
else {
/* update buffer_ptr for next vertex */
- save->buffer_ptr = save->vertex_store->buffer + save->vertex_store->used;
+ save->buffer_ptr = save->vertex_store->buffer_map
+ + save->vertex_store->used;
}
if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
save->prim_store->refcount--;
assert(save->prim_store->refcount != 0);
- save->prim_store = alloc_prim_store(ctx);
+ save->prim_store = alloc_prim_store();
}
/* Reset our structures for the next run of vertices:
*/
- _save_reset_counters(ctx);
+ reset_counters(ctx);
}
* TODO -- If no new vertices have been stored, don't bother saving it.
*/
static void
-_save_wrap_buffers(struct gl_context *ctx)
+wrap_buffers(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLint i = save->prim_count - 1;
GLenum mode;
- GLboolean weak;
- GLboolean no_current_update;
assert(i < (GLint) save->prim_max);
assert(i >= 0);
/* Close off in-progress primitive.
*/
- save->prim[i].count = (save->vert_count - save->prim[i].start);
- mode = save->prim[i].mode;
- weak = save->prim[i].weak;
- no_current_update = save->prim[i].no_current_update;
+ save->prims[i].count = (save->vert_count - save->prims[i].start);
+ mode = save->prims[i].mode;
/* store the copied vertices, and allocate a new list.
*/
- _save_compile_vertex_list(ctx);
+ compile_vertex_list(ctx);
/* Restart interrupted primitive
*/
- save->prim[0].mode = mode;
- save->prim[0].weak = weak;
- save->prim[0].no_current_update = no_current_update;
- save->prim[0].begin = 0;
- save->prim[0].end = 0;
- save->prim[0].pad = 0;
- save->prim[0].start = 0;
- save->prim[0].count = 0;
- save->prim[0].num_instances = 1;
- save->prim[0].base_instance = 0;
- save->prim[0].is_indirect = 0;
+ save->prims[0].mode = mode;
+ save->prims[0].begin = 0;
+ save->prims[0].end = 0;
+ save->prims[0].start = 0;
+ save->prims[0].count = 0;
save->prim_count = 1;
}
* vertex_store struct.
*/
static void
-_save_wrap_filled_vertex(struct gl_context *ctx)
+wrap_filled_vertex(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
unsigned numComponents;
/* Emit a glEnd to close off the last vertex list.
*/
- _save_wrap_buffers(ctx);
+ wrap_buffers(ctx);
/* Copy stored stored vertices to start of new list.
*/
static void
-_save_copy_to_current(struct gl_context *ctx)
+copy_to_current(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
const int i = u_bit_scan64(&enabled);
assert(save->attrsz[i]);
- save->currentsz[i][0] = save->attrsz[i];
- COPY_CLEAN_4V_TYPE_AS_UNION(save->current[i], save->attrsz[i],
- save->attrptr[i], save->attrtype[i]);
+ if (save->attrtype[i] == GL_DOUBLE ||
+ save->attrtype[i] == GL_UNSIGNED_INT64_ARB)
+ memcpy(save->current[i], save->attrptr[i], save->attrsz[i] * sizeof(GLfloat));
+ else
+ COPY_CLEAN_4V_TYPE_AS_UNION(save->current[i], save->attrsz[i],
+ save->attrptr[i], save->attrtype[i]);
}
}
static void
-_save_copy_from_current(struct gl_context *ctx)
+copy_from_current(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLbitfield64 enabled = save->enabled & (~BITFIELD64_BIT(VBO_ATTRIB_POS));
save->attrptr[i][0] = save->current[i][0];
break;
case 0:
- assert(0);
- break;
+ unreachable("Unexpected vertex attribute size");
}
}
}
* Flush existing data, set new attrib size, replay copied vertices.
*/
static void
-_save_upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
+upgrade_vertex(struct gl_context *ctx, GLuint attr, GLuint newsz)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLuint oldsz;
* BEGIN in the new buffer.
*/
if (save->vert_count)
- _save_wrap_buffers(ctx);
+ wrap_buffers(ctx);
else
assert(save->copied.nr == 0);
* when the attribute already exists in the vertex and is having
* its size increased.
*/
- _save_copy_to_current(ctx);
+ copy_to_current(ctx);
/* Fix up sizes:
*/
/* Copy from current to repopulate the vertex with correct values.
*/
- _save_copy_from_current(ctx);
+ copy_from_current(ctx);
/* Replay stored vertices to translate them to new format here.
*
*/
if (save->copied.nr) {
const fi_type *data = save->copied.buffer;
- fi_type *dest = save->buffer;
+ fi_type *dest = save->buffer_map;
/* Need to note this and fix up at runtime (or loopback):
*/
* get a glTexCoord4f() or glTexCoord1f() call.
*/
static void
-save_fixup_vertex(struct gl_context *ctx, GLuint attr, GLuint sz)
+fixup_vertex(struct gl_context *ctx, GLuint attr,
+ GLuint sz, GLenum newType)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
- if (sz > save->attrsz[attr]) {
+ if (sz > save->attrsz[attr] ||
+ newType != save->attrtype[attr]) {
/* New size is larger. Need to flush existing vertices and get
* an enlarged vertex format.
*/
- _save_upgrade_vertex(ctx, attr, sz);
+ upgrade_vertex(ctx, attr, sz);
}
else if (sz < save->active_sz[attr]) {
GLuint i;
* commands such as glNormal3f() or glTexCoord2f().
*/
static void
-_save_reset_vertex(struct gl_context *ctx)
+reset_vertex(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
}
+/**
+ * If index=0, does glVertexAttrib*() alias glVertex() to emit a vertex?
+ * It depends on a few things, including whether we're inside or outside
+ * of glBegin/glEnd.
+ */
+static inline bool
+is_vertex_position(const struct gl_context *ctx, GLuint index)
+{
+ return (index == 0 &&
+ _mesa_attr_zero_aliases_vertex(ctx) &&
+ _mesa_inside_dlist_begin_end(ctx));
+}
+
+
#define ERROR(err) _mesa_compile_error(ctx, err, __func__);
#define ATTR_UNION(A, N, T, C, V0, V1, V2, V3) \
do { \
struct vbo_save_context *save = &vbo_context(ctx)->save; \
+ int sz = (sizeof(C) / sizeof(GLfloat)); \
\
if (save->active_sz[A] != N) \
- save_fixup_vertex(ctx, A, N); \
+ fixup_vertex(ctx, A, N * sz, T); \
\
{ \
C *dest = (C *)save->attrptr[A]; \
save->buffer_ptr += save->vertex_size; \
\
if (++save->vert_count >= save->max_vert) \
- _save_wrap_filled_vertex(ctx); \
+ wrap_filled_vertex(ctx); \
} \
} while (0)
if (save->prim_count > 0) {
/* Close off in-progress primitive. */
GLint i = save->prim_count - 1;
- save->prim[i].count = save->vert_count - save->prim[i].start;
+ save->prims[i].count = save->vert_count - save->prims[i].start;
}
/* Need to replay this display list with loopback,
*/
save->dangling_attr_ref = GL_TRUE;
- _save_compile_vertex_list(ctx);
+ compile_vertex_list(ctx);
}
- _save_copy_to_current(ctx);
- _save_reset_vertex(ctx);
- _save_reset_counters(ctx);
+ copy_to_current(ctx);
+ reset_vertex(ctx);
+ reset_counters(ctx);
if (save->out_of_memory) {
_mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
}
* Called when a glBegin is getting compiled into a display list.
* Updating of ctx->Driver.CurrentSavePrimitive is already taken care of.
*/
-GLboolean
-vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode)
+void
+vbo_save_NotifyBegin(struct gl_context *ctx, GLenum mode,
+ bool no_current_update)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
const GLuint i = save->prim_count++;
+ ctx->Driver.CurrentSavePrimitive = mode;
+
assert(i < save->prim_max);
- save->prim[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
- save->prim[i].begin = 1;
- save->prim[i].end = 0;
- save->prim[i].weak = (mode & VBO_SAVE_PRIM_WEAK) ? 1 : 0;
- save->prim[i].no_current_update =
- (mode & VBO_SAVE_PRIM_NO_CURRENT_UPDATE) ? 1 : 0;
- save->prim[i].pad = 0;
- save->prim[i].start = save->vert_count;
- save->prim[i].count = 0;
- save->prim[i].num_instances = 1;
- save->prim[i].base_instance = 0;
- save->prim[i].is_indirect = 0;
+ save->prims[i].mode = mode & VBO_SAVE_PRIM_MODE_MASK;
+ save->prims[i].begin = 1;
+ save->prims[i].end = 0;
+ save->prims[i].start = save->vert_count;
+ save->prims[i].count = 0;
+
+ save->no_current_update = no_current_update;
if (save->out_of_memory) {
_mesa_install_save_vtxfmt(ctx, &save->vtxfmt_noop);
/* We need to call vbo_save_SaveFlushVertices() if there's state change */
ctx->Driver.SaveNeedFlush = GL_TRUE;
-
- /* GL_TRUE means we've handled this glBegin here; don't compile a BEGIN
- * opcode into the display list.
- */
- return GL_TRUE;
}
const GLint i = save->prim_count - 1;
ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
- save->prim[i].end = 1;
- save->prim[i].count = (save->vert_count - save->prim[i].start);
+ save->prims[i].end = 1;
+ save->prims[i].count = (save->vert_count - save->prims[i].start);
if (i == (GLint) save->prim_max - 1) {
- _save_compile_vertex_list(ctx);
+ compile_vertex_list(ctx);
assert(save->copied.nr == 0);
}
static void GLAPIENTRY
_save_PrimitiveRestartNV(void)
{
- GLenum curPrim;
GET_CURRENT_CONTEXT(ctx);
+ struct vbo_save_context *save = &vbo_context(ctx)->save;
- curPrim = ctx->Driver.CurrentSavePrimitive;
-
- _save_End();
- _save_Begin(curPrim);
+ if (save->prim_count == 0) {
+ /* We're not inside a glBegin/End pair, so calling glPrimitiverRestartNV
+ * is an error.
+ */
+ _mesa_compile_error(ctx, GL_INVALID_OPERATION,
+ "glPrimitiveRestartNV called outside glBegin/End");
+ } else {
+ /* get current primitive mode */
+ GLenum curPrim = save->prims[save->prim_count - 1].mode;
+ bool no_current_update = save->no_current_update;
+
+ /* restart primitive */
+ CALL_End(GET_DISPATCH(), ());
+ vbo_save_NotifyBegin(ctx, curPrim, no_current_update);
+ }
}
_save_OBE_Rectf(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2)
{
GET_CURRENT_CONTEXT(ctx);
- vbo_save_NotifyBegin(ctx, GL_QUADS | VBO_SAVE_PRIM_WEAK);
+ vbo_save_NotifyBegin(ctx, GL_QUADS, false);
CALL_Vertex2f(GET_DISPATCH(), (x1, y1));
CALL_Vertex2f(GET_DISPATCH(), (x2, y1));
CALL_Vertex2f(GET_DISPATCH(), (x2, y2));
_save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count)
{
GET_CURRENT_CONTEXT(ctx);
+ struct gl_vertex_array_object *vao = ctx->Array.VAO;
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLint i;
if (save->out_of_memory)
return;
- _ae_map_vbos(ctx);
+ /* Make sure to process any VBO binding changes */
+ _mesa_update_state(ctx);
+
+ _mesa_vao_map_arrays(ctx, vao, GL_MAP_READ_BIT);
- vbo_save_NotifyBegin(ctx, (mode | VBO_SAVE_PRIM_WEAK
- | VBO_SAVE_PRIM_NO_CURRENT_UPDATE));
+ vbo_save_NotifyBegin(ctx, mode, true);
for (i = 0; i < count; i++)
- CALL_ArrayElement(GET_DISPATCH(), (start + i));
+ _mesa_array_element(ctx, start + i);
CALL_End(GET_DISPATCH(), ());
- _ae_unmap_vbos(ctx);
+ _mesa_vao_unmap_arrays(ctx, vao);
+}
+
+
+static void GLAPIENTRY
+_save_OBE_MultiDrawArrays(GLenum mode, const GLint *first,
+ const GLsizei *count, GLsizei primcount)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLint i;
+
+ if (!_mesa_is_valid_prim_mode(ctx, mode)) {
+ _mesa_compile_error(ctx, GL_INVALID_ENUM, "glMultiDrawArrays(mode)");
+ return;
+ }
+
+ if (primcount < 0) {
+ _mesa_compile_error(ctx, GL_INVALID_VALUE,
+ "glMultiDrawArrays(primcount<0)");
+ return;
+ }
+
+ for (i = 0; i < primcount; i++) {
+ if (count[i] < 0) {
+ _mesa_compile_error(ctx, GL_INVALID_VALUE,
+ "glMultiDrawArrays(count[i]<0)");
+ return;
+ }
+ }
+
+ for (i = 0; i < primcount; i++) {
+ if (count[i] > 0) {
+ _save_OBE_DrawArrays(mode, first[i], count[i]);
+ }
+ }
+}
+
+
+static void
+array_element(struct gl_context *ctx,
+ GLint basevertex, GLuint elt, unsigned index_size)
+{
+ /* Section 10.3.5 Primitive Restart:
+ * [...]
+ * When one of the *BaseVertex drawing commands specified in section 10.5
+ * is used, the primitive restart comparison occurs before the basevertex
+ * offset is added to the array index.
+ */
+ /* If PrimitiveRestart is enabled and the index is the RestartIndex
+ * then we call PrimitiveRestartNV and return.
+ */
+ if (ctx->Array._PrimitiveRestart &&
+ elt == ctx->Array._RestartIndex[index_size - 1]) {
+ CALL_PrimitiveRestartNV(GET_DISPATCH(), ());
+ return;
+ }
+
+ _mesa_array_element(ctx, basevertex + elt);
}
{
GET_CURRENT_CONTEXT(ctx);
struct vbo_save_context *save = &vbo_context(ctx)->save;
- struct gl_buffer_object *indexbuf = ctx->Array.VAO->IndexBufferObj;
+ struct gl_vertex_array_object *vao = ctx->Array.VAO;
+ struct gl_buffer_object *indexbuf = vao->IndexBufferObj;
GLint i;
if (!_mesa_is_valid_prim_mode(ctx, mode)) {
if (save->out_of_memory)
return;
- _ae_map_vbos(ctx);
+ /* Make sure to process any VBO binding changes */
+ _mesa_update_state(ctx);
+
+ _mesa_vao_map(ctx, vao, GL_MAP_READ_BIT);
- if (_mesa_is_bufferobj(indexbuf))
+ if (indexbuf)
indices =
ADD_POINTERS(indexbuf->Mappings[MAP_INTERNAL].Pointer, indices);
- vbo_save_NotifyBegin(ctx, (mode | VBO_SAVE_PRIM_WEAK |
- VBO_SAVE_PRIM_NO_CURRENT_UPDATE));
+ vbo_save_NotifyBegin(ctx, mode, true);
switch (type) {
case GL_UNSIGNED_BYTE:
for (i = 0; i < count; i++)
- CALL_ArrayElement(GET_DISPATCH(), (basevertex + ((GLubyte *) indices)[i]));
+ array_element(ctx, basevertex, ((GLubyte *) indices)[i], 1);
break;
case GL_UNSIGNED_SHORT:
for (i = 0; i < count; i++)
- CALL_ArrayElement(GET_DISPATCH(), (basevertex + ((GLushort *) indices)[i]));
+ array_element(ctx, basevertex, ((GLushort *) indices)[i], 2);
break;
case GL_UNSIGNED_INT:
for (i = 0; i < count; i++)
- CALL_ArrayElement(GET_DISPATCH(), (basevertex + ((GLuint *) indices)[i]));
+ array_element(ctx, basevertex, ((GLuint *) indices)[i], 4);
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glDrawElements(type)");
CALL_End(GET_DISPATCH(), ());
- _ae_unmap_vbos(ctx);
+ _mesa_vao_unmap(ctx, vao);
}
static void GLAPIENTRY
static void
-_save_vtxfmt_init(struct gl_context *ctx)
+vtxfmt_init(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLvertexformat *vfmt = &save->vtxfmt;
- vfmt->ArrayElement = _ae_ArrayElement;
-
- vfmt->Color3f = _save_Color3f;
- vfmt->Color3fv = _save_Color3fv;
- vfmt->Color4f = _save_Color4f;
- vfmt->Color4fv = _save_Color4fv;
- vfmt->EdgeFlag = _save_EdgeFlag;
- vfmt->End = _save_End;
- vfmt->PrimitiveRestartNV = _save_PrimitiveRestartNV;
- vfmt->FogCoordfEXT = _save_FogCoordfEXT;
- vfmt->FogCoordfvEXT = _save_FogCoordfvEXT;
- vfmt->Indexf = _save_Indexf;
- vfmt->Indexfv = _save_Indexfv;
- vfmt->Materialfv = _save_Materialfv;
- vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f;
- vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv;
- vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f;
- vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv;
- vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f;
- vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv;
- vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f;
- vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv;
- vfmt->Normal3f = _save_Normal3f;
- vfmt->Normal3fv = _save_Normal3fv;
- vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT;
- vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT;
- vfmt->TexCoord1f = _save_TexCoord1f;
- vfmt->TexCoord1fv = _save_TexCoord1fv;
- vfmt->TexCoord2f = _save_TexCoord2f;
- vfmt->TexCoord2fv = _save_TexCoord2fv;
- vfmt->TexCoord3f = _save_TexCoord3f;
- vfmt->TexCoord3fv = _save_TexCoord3fv;
- vfmt->TexCoord4f = _save_TexCoord4f;
- vfmt->TexCoord4fv = _save_TexCoord4fv;
- vfmt->Vertex2f = _save_Vertex2f;
- vfmt->Vertex2fv = _save_Vertex2fv;
- vfmt->Vertex3f = _save_Vertex3f;
- vfmt->Vertex3fv = _save_Vertex3fv;
- vfmt->Vertex4f = _save_Vertex4f;
- vfmt->Vertex4fv = _save_Vertex4fv;
- vfmt->VertexAttrib1fARB = _save_VertexAttrib1fARB;
- vfmt->VertexAttrib1fvARB = _save_VertexAttrib1fvARB;
- vfmt->VertexAttrib2fARB = _save_VertexAttrib2fARB;
- vfmt->VertexAttrib2fvARB = _save_VertexAttrib2fvARB;
- vfmt->VertexAttrib3fARB = _save_VertexAttrib3fARB;
- vfmt->VertexAttrib3fvARB = _save_VertexAttrib3fvARB;
- vfmt->VertexAttrib4fARB = _save_VertexAttrib4fARB;
- vfmt->VertexAttrib4fvARB = _save_VertexAttrib4fvARB;
-
- vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV;
- vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV;
- vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV;
- vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV;
- vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV;
- vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV;
- vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV;
- vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV;
-
- /* integer-valued */
- vfmt->VertexAttribI1i = _save_VertexAttribI1i;
- vfmt->VertexAttribI2i = _save_VertexAttribI2i;
- vfmt->VertexAttribI3i = _save_VertexAttribI3i;
- vfmt->VertexAttribI4i = _save_VertexAttribI4i;
- vfmt->VertexAttribI2iv = _save_VertexAttribI2iv;
- vfmt->VertexAttribI3iv = _save_VertexAttribI3iv;
- vfmt->VertexAttribI4iv = _save_VertexAttribI4iv;
-
- /* unsigned integer-valued */
- vfmt->VertexAttribI1ui = _save_VertexAttribI1ui;
- vfmt->VertexAttribI2ui = _save_VertexAttribI2ui;
- vfmt->VertexAttribI3ui = _save_VertexAttribI3ui;
- vfmt->VertexAttribI4ui = _save_VertexAttribI4ui;
- vfmt->VertexAttribI2uiv = _save_VertexAttribI2uiv;
- vfmt->VertexAttribI3uiv = _save_VertexAttribI3uiv;
- vfmt->VertexAttribI4uiv = _save_VertexAttribI4uiv;
-
- vfmt->VertexP2ui = _save_VertexP2ui;
- vfmt->VertexP3ui = _save_VertexP3ui;
- vfmt->VertexP4ui = _save_VertexP4ui;
- vfmt->VertexP2uiv = _save_VertexP2uiv;
- vfmt->VertexP3uiv = _save_VertexP3uiv;
- vfmt->VertexP4uiv = _save_VertexP4uiv;
-
- vfmt->TexCoordP1ui = _save_TexCoordP1ui;
- vfmt->TexCoordP2ui = _save_TexCoordP2ui;
- vfmt->TexCoordP3ui = _save_TexCoordP3ui;
- vfmt->TexCoordP4ui = _save_TexCoordP4ui;
- vfmt->TexCoordP1uiv = _save_TexCoordP1uiv;
- vfmt->TexCoordP2uiv = _save_TexCoordP2uiv;
- vfmt->TexCoordP3uiv = _save_TexCoordP3uiv;
- vfmt->TexCoordP4uiv = _save_TexCoordP4uiv;
-
- vfmt->MultiTexCoordP1ui = _save_MultiTexCoordP1ui;
- vfmt->MultiTexCoordP2ui = _save_MultiTexCoordP2ui;
- vfmt->MultiTexCoordP3ui = _save_MultiTexCoordP3ui;
- vfmt->MultiTexCoordP4ui = _save_MultiTexCoordP4ui;
- vfmt->MultiTexCoordP1uiv = _save_MultiTexCoordP1uiv;
- vfmt->MultiTexCoordP2uiv = _save_MultiTexCoordP2uiv;
- vfmt->MultiTexCoordP3uiv = _save_MultiTexCoordP3uiv;
- vfmt->MultiTexCoordP4uiv = _save_MultiTexCoordP4uiv;
-
- vfmt->NormalP3ui = _save_NormalP3ui;
- vfmt->NormalP3uiv = _save_NormalP3uiv;
-
- vfmt->ColorP3ui = _save_ColorP3ui;
- vfmt->ColorP4ui = _save_ColorP4ui;
- vfmt->ColorP3uiv = _save_ColorP3uiv;
- vfmt->ColorP4uiv = _save_ColorP4uiv;
-
- vfmt->SecondaryColorP3ui = _save_SecondaryColorP3ui;
- vfmt->SecondaryColorP3uiv = _save_SecondaryColorP3uiv;
-
- vfmt->VertexAttribP1ui = _save_VertexAttribP1ui;
- vfmt->VertexAttribP2ui = _save_VertexAttribP2ui;
- vfmt->VertexAttribP3ui = _save_VertexAttribP3ui;
- vfmt->VertexAttribP4ui = _save_VertexAttribP4ui;
-
- vfmt->VertexAttribP1uiv = _save_VertexAttribP1uiv;
- vfmt->VertexAttribP2uiv = _save_VertexAttribP2uiv;
- vfmt->VertexAttribP3uiv = _save_VertexAttribP3uiv;
- vfmt->VertexAttribP4uiv = _save_VertexAttribP4uiv;
-
- vfmt->VertexAttribL1d = _save_VertexAttribL1d;
- vfmt->VertexAttribL2d = _save_VertexAttribL2d;
- vfmt->VertexAttribL3d = _save_VertexAttribL3d;
- vfmt->VertexAttribL4d = _save_VertexAttribL4d;
-
- vfmt->VertexAttribL1dv = _save_VertexAttribL1dv;
- vfmt->VertexAttribL2dv = _save_VertexAttribL2dv;
- vfmt->VertexAttribL3dv = _save_VertexAttribL3dv;
- vfmt->VertexAttribL4dv = _save_VertexAttribL4dv;
-
- /* This will all require us to fallback to saving the list as opcodes:
- */
- vfmt->CallList = _save_CallList;
- vfmt->CallLists = _save_CallLists;
-
- vfmt->EvalCoord1f = _save_EvalCoord1f;
- vfmt->EvalCoord1fv = _save_EvalCoord1fv;
- vfmt->EvalCoord2f = _save_EvalCoord2f;
- vfmt->EvalCoord2fv = _save_EvalCoord2fv;
- vfmt->EvalPoint1 = _save_EvalPoint1;
- vfmt->EvalPoint2 = _save_EvalPoint2;
-
- /* These calls all generate GL_INVALID_OPERATION since this vtxfmt is
- * only used when we're inside a glBegin/End pair.
- */
- vfmt->Begin = _save_Begin;
+#define NAME_AE(x) _ae_##x
+#define NAME_CALLLIST(x) _save_##x
+#define NAME(x) _save_##x
+#define NAME_ES(x) _save_##x##ARB
+
+#include "vbo_init_tmp.h"
}
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);
return;
if (save->vert_count || save->prim_count)
- _save_compile_vertex_list(ctx);
+ compile_vertex_list(ctx);
- _save_copy_to_current(ctx);
- _save_reset_vertex(ctx);
- _save_reset_counters(ctx);
+ copy_to_current(ctx);
+ reset_vertex(ctx);
+ reset_counters(ctx);
ctx->Driver.SaveNeedFlush = GL_FALSE;
}
+/**
+ * Called from glNewList when we're starting to compile a display list.
+ */
void
vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
{
(void) mode;
if (!save->prim_store)
- save->prim_store = alloc_prim_store(ctx);
+ save->prim_store = alloc_prim_store();
if (!save->vertex_store)
save->vertex_store = alloc_vertex_store(ctx);
save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
- _save_reset_vertex(ctx);
- _save_reset_counters(ctx);
+ reset_vertex(ctx);
+ reset_counters(ctx);
ctx->Driver.SaveNeedFlush = GL_FALSE;
}
+/**
+ * Called from glEndList when we're finished compiling a display list.
+ */
void
vbo_save_EndList(struct gl_context *ctx)
{
if (save->prim_count > 0) {
GLint i = save->prim_count - 1;
ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
- save->prim[i].end = 0;
- save->prim[i].count = save->vert_count - save->prim[i].start;
+ save->prims[i].end = 0;
+ save->prims[i].count = save->vert_count - save->prims[i].start;
}
/* Make sure this vertex list gets replayed by the "loopback"
}
+/**
+ * Called from the display list code when we're about to execute a
+ * display list.
+ */
void
vbo_save_BeginCallList(struct gl_context *ctx, struct gl_display_list *dlist)
{
}
+/**
+ * Called from the display list code when we're finished executing a
+ * display list.
+ */
void
vbo_save_EndCallList(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
- if (ctx->ListState.CallDepth == 1) {
- /* This is correct: want to keep only the VBO_SAVE_FALLBACK
- * flag, if it is set:
- */
- save->replay_flags &= VBO_SAVE_FALLBACK;
- }
+ if (ctx->ListState.CallDepth == 1)
+ save->replay_flags = 0;
}
+/**
+ * Called by display list code when a display list is being deleted.
+ */
static void
vbo_destroy_vertex_list(struct gl_context *ctx, void *data)
{
struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data;
- (void) ctx;
- if (--node->vertex_store->refcount == 0)
- free_vertex_store(ctx, node->vertex_store);
+ for (gl_vertex_processing_mode vpm = VP_MODE_FF; vpm < VP_MODE_MAX; ++vpm)
+ _mesa_reference_vao(ctx, &node->VAO[vpm], NULL);
if (--node->prim_store->refcount == 0)
free(node->prim_store);
{
struct vbo_save_vertex_list *node = (struct vbo_save_vertex_list *) data;
GLuint i;
- struct gl_buffer_object *buffer = node->vertex_store ?
- node->vertex_store->bufferobj : NULL;
+ struct gl_buffer_object *buffer = node->VAO[0]->BufferBinding[0].BufferObj;
+ const GLuint vertex_size = _vbo_save_get_stride(node)/sizeof(GLfloat);
(void) ctx;
fprintf(f, "VBO-VERTEX-LIST, %u vertices, %d primitives, %d vertsize, "
"buffer %p\n",
- node->count, node->prim_count, node->vertex_size,
+ node->vertex_count, node->prim_count, vertex_size,
buffer);
for (i = 0; i < node->prim_count; i++) {
- struct _mesa_prim *prim = &node->prim[i];
- fprintf(f, " prim %d: %s%s %d..%d %s %s\n",
+ struct _mesa_prim *prim = &node->prims[i];
+ fprintf(f, " prim %d: %s %d..%d %s %s\n",
i,
_mesa_lookup_prim_by_nr(prim->mode),
- prim->weak ? " (weak)" : "",
prim->start,
prim->start + prim->count,
(prim->begin) ? "BEGIN" : "(wrap)",
* Called during context creation/init.
*/
static void
-_save_current_init(struct gl_context *ctx)
+current_init(struct gl_context *ctx)
{
struct vbo_save_context *save = &vbo_context(ctx)->save;
GLint i;
vbo_save_api_init(struct vbo_save_context *save)
{
struct gl_context *ctx = save->ctx;
- GLuint i;
save->opcode_vertex_list =
_mesa_dlist_alloc_opcode(ctx,
vbo_destroy_vertex_list,
vbo_print_vertex_list);
- _save_vtxfmt_init(ctx);
- _save_current_init(ctx);
- _mesa_noop_vtxfmt_init(&save->vtxfmt_noop);
-
- /* These will actually get set again when binding/drawing */
- for (i = 0; i < VBO_ATTRIB_MAX; i++)
- save->inputs[i] = &save->arrays[i];
+ vtxfmt_init(ctx);
+ current_init(ctx);
+ _mesa_noop_vtxfmt_init(ctx, &save->vtxfmt_noop);
}