summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mesa/state_tracker/st_atom_array.c98
1 files changed, 50 insertions, 48 deletions
diff --git a/src/mesa/state_tracker/st_atom_array.c b/src/mesa/state_tracker/st_atom_array.c
index 1c2cfa791cd..e5b949fbaec 100644
--- a/src/mesa/state_tracker/st_atom_array.c
+++ b/src/mesa/state_tracker/st_atom_array.c
@@ -386,6 +386,7 @@ static void init_velement(struct pipe_vertex_element *velement,
}
static void init_velement_lowered(struct st_context *st,
+ const struct st_vertex_program *vp,
struct pipe_vertex_element *velements,
int src_offset, int format,
int instance_divisor, int vbo_index,
@@ -396,23 +397,33 @@ static void init_velement_lowered(struct st_context *st,
if (doubles) {
int lower_format;
- if (nr_components == 1)
+ if (nr_components < 2)
lower_format = PIPE_FORMAT_R32G32_UINT;
- else if (nr_components >= 2)
+ else
lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
init_velement(&velements[idx], src_offset,
lower_format, instance_divisor, vbo_index);
idx++;
- if (nr_components > 2) {
- if (nr_components == 3)
- lower_format = PIPE_FORMAT_R32G32_UINT;
- else if (nr_components >= 4)
- lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+ if (idx < vp->num_inputs &&
+ vp->index_to_input[idx] == ST_DOUBLE_ATTRIB_PLACEHOLDER) {
+ if (nr_components >= 3) {
+ if (nr_components == 3)
+ lower_format = PIPE_FORMAT_R32G32_UINT;
+ else
+ lower_format = PIPE_FORMAT_R32G32B32A32_UINT;
+
+ init_velement(&velements[idx], src_offset + 4 * sizeof(float),
+ lower_format, instance_divisor, vbo_index);
+ } else {
+ /* The values here are undefined. Fill in some conservative
+ * dummy values.
+ */
+ init_velement(&velements[idx], src_offset, PIPE_FORMAT_R32G32_UINT,
+ instance_divisor, vbo_index);
+ }
- init_velement(&velements[idx], src_offset + 4 * sizeof(float),
- lower_format, instance_divisor, vbo_index);
idx++;
}
} else {
@@ -435,10 +446,9 @@ setup_interleaved_attribs(struct st_context *st,
const struct st_vp_variant *vpv,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer *vbuffer,
- struct pipe_vertex_element velements[],
- unsigned *num_velements)
+ struct pipe_vertex_element velements[])
{
- GLuint attr, attr_idx;
+ GLuint attr;
const GLubyte *low_addr = NULL;
GLboolean usingVBO; /* all arrays in a VBO? */
struct gl_buffer_object *bufobj;
@@ -481,15 +491,13 @@ setup_interleaved_attribs(struct st_context *st,
/* are the arrays in user space? */
usingVBO = _mesa_is_bufferobj(bufobj);
- attr_idx = 0;
- for (attr = 0; attr < vpv->num_inputs; attr++) {
+ for (attr = 0; attr < vpv->num_inputs;) {
const struct gl_client_array *array;
unsigned src_offset;
unsigned src_format;
array = get_client_array(vp, arrays, attr);
- if (!array)
- continue;
+ assert(array);
src_offset = (unsigned) (array->Ptr - low_addr);
assert(array->_ElementSize ==
@@ -501,13 +509,11 @@ setup_interleaved_attribs(struct st_context *st,
array->Normalized,
array->Integer);
- init_velement_lowered(st, velements, src_offset, src_format,
+ init_velement_lowered(st, vp, velements, src_offset, src_format,
array->InstanceDivisor, 0,
- array->Size, array->Doubles, &attr_idx);
+ array->Size, array->Doubles, &attr);
}
- *num_velements = attr_idx;
-
/*
* Return the vbuffer info and setup user-space attrib info, if needed.
*/
@@ -554,25 +560,25 @@ setup_non_interleaved_attribs(struct st_context *st,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer vbuffer[],
struct pipe_vertex_element velements[],
- unsigned *num_velements)
+ unsigned *num_vbuffers)
{
struct gl_context *ctx = st->ctx;
- GLuint attr, attr_idx = 0;
+ GLuint attr;
- for (attr = 0; attr < vpv->num_inputs; attr++) {
+ *num_vbuffers = 0;
+
+ for (attr = 0; attr < vpv->num_inputs;) {
const GLuint mesaAttr = vp->index_to_input[attr];
const struct gl_client_array *array;
struct gl_buffer_object *bufobj;
GLsizei stride;
unsigned src_format;
+ unsigned bufidx;
array = get_client_array(vp, arrays, attr);
- if (!array) {
- vbuffer[attr].buffer = NULL;
- vbuffer[attr].user_buffer = NULL;
- vbuffer[attr].buffer_offset = 0;
- continue;
- }
+ assert(array);
+
+ bufidx = (*num_vbuffers)++;
stride = array->StrideB;
bufobj = array->BufferObj;
@@ -590,9 +596,9 @@ setup_non_interleaved_attribs(struct st_context *st,
return FALSE; /* out-of-memory error probably */
}
- vbuffer[attr].buffer = stobj->buffer;
- vbuffer[attr].user_buffer = NULL;
- vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr);
+ vbuffer[bufidx].buffer = stobj->buffer;
+ vbuffer[bufidx].user_buffer = NULL;
+ vbuffer[bufidx].buffer_offset = pointer_to_offset(array->Ptr);
}
else {
/* wrap user data */
@@ -609,13 +615,13 @@ setup_non_interleaved_attribs(struct st_context *st,
assert(ptr);
- vbuffer[attr].buffer = NULL;
- vbuffer[attr].user_buffer = ptr;
- vbuffer[attr].buffer_offset = 0;
+ vbuffer[bufidx].buffer = NULL;
+ vbuffer[bufidx].user_buffer = ptr;
+ vbuffer[bufidx].buffer_offset = 0;
}
/* common-case setup */
- vbuffer[attr].stride = stride; /* in bytes */
+ vbuffer[bufidx].stride = stride; /* in bytes */
src_format = st_pipe_vertex_format(array->Type,
array->Size,
@@ -623,13 +629,11 @@ setup_non_interleaved_attribs(struct st_context *st,
array->Normalized,
array->Integer);
- init_velement_lowered(st, velements, 0, src_format,
- array->InstanceDivisor, attr,
- array->Size, array->Doubles, &attr_idx);
-
+ init_velement_lowered(st, vp, velements, 0, src_format,
+ array->InstanceDivisor, bufidx,
+ array->Size, array->Doubles, &attr);
}
- *num_velements = attr_idx;
return TRUE;
}
@@ -641,7 +645,7 @@ static void update_array(struct st_context *st)
const struct st_vp_variant *vpv;
struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
- unsigned num_vbuffers, num_velements;
+ unsigned num_vbuffers;
st->vertex_array_out_of_memory = FALSE;
@@ -659,23 +663,21 @@ static void update_array(struct st_context *st)
* Setup the vbuffer[] and velements[] arrays.
*/
if (is_interleaved_arrays(vp, vpv, arrays)) {
- if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements, &num_velements)) {
+ if (!setup_interleaved_attribs(st, vp, vpv, arrays, vbuffer, velements)) {
st->vertex_array_out_of_memory = TRUE;
return;
}
num_vbuffers = 1;
- if (num_velements == 0)
+ if (vpv->num_inputs == 0)
num_vbuffers = 0;
}
else {
if (!setup_non_interleaved_attribs(st, vp, vpv, arrays, vbuffer,
- velements, &num_velements)) {
+ velements, &num_vbuffers)) {
st->vertex_array_out_of_memory = TRUE;
return;
}
-
- num_vbuffers = vpv->num_inputs;
}
cso_set_vertex_buffers(st->cso_context, 0, num_vbuffers, vbuffer);
@@ -685,7 +687,7 @@ static void update_array(struct st_context *st)
st->last_num_vbuffers - num_vbuffers, NULL);
}
st->last_num_vbuffers = num_vbuffers;
- cso_set_vertex_elements(st->cso_context, num_velements, velements);
+ cso_set_vertex_elements(st->cso_context, vpv->num_inputs, velements);
}