summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/state_tracker/st_draw.c107
1 files changed, 76 insertions, 31 deletions
diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c
index a2bff044eea..ff3008a5fc0 100644
--- a/src/mesa/state_tracker/st_draw.c
+++ b/src/mesa/state_tracker/st_draw.c
@@ -353,9 +353,26 @@ setup_interleaved_attribs(struct gl_context *ctx,
struct pipe_context *pipe = st->pipe;
GLuint attr;
const GLubyte *low_addr = NULL;
-
- /* Find the lowest address of the arrays we're drawing */
+ GLboolean usingVBO; /* all arrays in a VBO? */
+ struct gl_buffer_object *bufobj;
+ GLuint user_buffer_size = 0;
+ GLuint vertex_size = 0; /* bytes per vertex, in bytes */
+ GLsizei stride;
+
+ /* Find the lowest address of the arrays we're drawing,
+ * Init bufobj and stride.
+ */
if (vpv->num_inputs) {
+ const GLuint mesaAttr0 = vp->index_to_input[0];
+ const struct gl_client_array *array = arrays[mesaAttr0];
+
+ /* Since we're doing interleaved arrays, we know there'll be at most
+ * one buffer object and the stride will be the same for all arrays.
+ * Grab them now.
+ */
+ bufobj = array->BufferObj;
+ stride = array->StrideB;
+
low_addr = arrays[vp->index_to_input[0]]->Ptr;
for (attr = 1; attr < vpv->num_inputs; attr++) {
@@ -363,44 +380,24 @@ setup_interleaved_attribs(struct gl_context *ctx,
low_addr = MIN2(low_addr, start);
}
}
+ else {
+ /* not sure we'll ever have zero inputs, but play it safe */
+ bufobj = NULL;
+ stride = 0;
+ low_addr = 0;
+ }
+
+ /* are the arrays in user space? */
+ usingVBO = bufobj && _mesa_is_bufferobj(bufobj);
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
const struct gl_client_array *array = arrays[mesaAttr];
- struct gl_buffer_object *bufobj = array->BufferObj;
- struct st_buffer_object *stobj = st_buffer_object(bufobj);
unsigned src_offset = (unsigned) (array->Ptr - low_addr);
GLuint element_size = array->_ElementSize;
- GLsizei stride = array->StrideB;
assert(element_size == array->Size * _mesa_sizeof_type(array->Type));
- if (attr == 0) {
- if (bufobj && _mesa_is_bufferobj(bufobj)) {
- vbuffer->buffer = NULL;
- pipe_resource_reference(&vbuffer->buffer, stobj->buffer);
- vbuffer->buffer_offset = pointer_to_offset(low_addr);
- }
- else {
- uint divisor = array->InstanceDivisor;
- uint last_index = divisor ? num_instances / divisor : max_index;
- uint bytes = src_offset + stride * last_index + element_size;
-
- vbuffer->buffer = pipe_user_buffer_create(pipe->screen,
- (void*) low_addr,
- bytes,
- PIPE_BIND_VERTEX_BUFFER);
- vbuffer->buffer_offset = 0;
-
- /* Track user vertex buffers. */
- pipe_resource_reference(&st->user_attrib[0].buffer, vbuffer->buffer);
- st->user_attrib[0].element_size = element_size;
- st->user_attrib[0].stride = stride;
- st->num_user_attribs = 1;
- }
- vbuffer->stride = stride; /* in bytes */
- }
-
velements[attr].src_offset = src_offset;
velements[attr].instance_divisor = array->InstanceDivisor;
velements[attr].vertex_buffer_index = 0;
@@ -409,6 +406,54 @@ setup_interleaved_attribs(struct gl_context *ctx,
array->Format,
array->Normalized);
assert(velements[attr].src_format);
+
+ if (!usingVBO) {
+ /* how many bytes referenced by this attribute array? */
+ uint divisor = array->InstanceDivisor;
+ uint last_index = divisor ? num_instances / divisor : max_index;
+ uint bytes = src_offset + stride * last_index + element_size;
+
+ user_buffer_size = MAX2(user_buffer_size, bytes);
+
+ /* update vertex size */
+ vertex_size = MAX2(vertex_size, src_offset + element_size);
+ }
+ }
+
+ /*
+ * Return the vbuffer info and setup user-space attrib info, if needed.
+ */
+ if (vpv->num_inputs == 0) {
+ /* just defensive coding here */
+ vbuffer->buffer = NULL;
+ vbuffer->buffer_offset = 0;
+ vbuffer->stride = 0;
+ st->num_user_attribs = 0;
+ }
+ else if (usingVBO) {
+ /* all interleaved arrays in a VBO */
+ struct st_buffer_object *stobj = st_buffer_object(bufobj);
+
+ vbuffer->buffer = NULL;
+ pipe_resource_reference(&vbuffer->buffer, stobj->buffer);
+ vbuffer->buffer_offset = pointer_to_offset(low_addr);
+ vbuffer->stride = stride;
+ st->num_user_attribs = 0;
+ }
+ else {
+ /* all interleaved arrays in user memory */
+ vbuffer->buffer = pipe_user_buffer_create(pipe->screen,
+ (void*) low_addr,
+ user_buffer_size,
+ PIPE_BIND_VERTEX_BUFFER);
+ vbuffer->buffer_offset = 0;
+ vbuffer->stride = stride;
+
+ /* Track user vertex buffers. */
+ pipe_resource_reference(&st->user_attrib[0].buffer, vbuffer->buffer);
+ st->user_attrib[0].element_size = vertex_size;
+ st->user_attrib[0].stride = stride;
+ st->num_user_attribs = 1;
}
}