diff options
-rw-r--r-- | src/mesa/state_tracker/st_atom_array.c | 98 |
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); } |