struct vbo_save_primitive_store *prim_store;
};
+
+/**
+ * Is the vertex lists's buffer offset an exact multiple of the
+ * vertex size (in bytes)? This is used to check for a vertex array /
+ * drawing optimization.
+ */
+static inline bool
+aligned_vertex_buffer_offset(const struct vbo_save_vertex_list *node)
+{
+ unsigned vertex_size = node->vertex_size * sizeof(GLfloat); /* in bytes */
+ return vertex_size != 0 && node->buffer_offset % vertex_size == 0;
+}
+
+
/* These buffers should be a reasonable size to support upload to
* hardware. Current vbo implementation will re-upload on any
* changes, so don't make too big or apps which dynamically create
save->prim_store = alloc_prim_store();
}
+ /*
+ * If the vertex buffer offset is a multiple of the vertex size,
+ * we can use the _mesa_prim::start value to indicate where the
+ * vertices starts, instead of the buffer offset. Also see the
+ * bind_vertex_list() function.
+ */
+ if (aligned_vertex_buffer_offset(node)) {
+ const unsigned start_offset =
+ node->buffer_offset / (node->vertex_size * sizeof(GLfloat));
+ for (unsigned i = 0; i < save->prim_count; i++) {
+ save->prims[i].start += start_offset;
+ }
+ }
+
/* Reset our structures for the next run of vertices:
*/
reset_counters(ctx);
memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
memcpy(node_attrtype, node->attrtype, sizeof(node->attrtype));
+ if (aligned_vertex_buffer_offset(node)) {
+ /* 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.
+ */
+ buffer_offset = 0;
+ }
+
/* Install the default (ie Current) attributes first, then overlay
* all active ones.
*/