-static GLboolean
-is_interleaved_arrays(const struct st_vertex_program *vp,
- const struct st_vp_variant *vpv,
- const struct gl_client_array **arrays)
-{
- GLuint attr;
- const struct gl_buffer_object *firstBufObj = NULL;
- GLint firstStride = -1;
- const GLubyte *firstPtr = NULL;
- GLboolean userSpaceBuffer = GL_FALSE;
-
- for (attr = 0; attr < vpv->num_inputs; attr++) {
- const GLuint mesaAttr = vp->index_to_input[attr];
- const struct gl_client_array *array = arrays[mesaAttr];
- const struct gl_buffer_object *bufObj = array->BufferObj;
- const GLsizei stride = array->StrideB; /* in bytes */
-
- if (attr == 0) {
- /* save info about the first array */
- firstStride = stride;
- firstPtr = array->Ptr;
- firstBufObj = bufObj;
- userSpaceBuffer = !bufObj || !bufObj->Name;
- }
- else {
- /* check if other arrays interleave with the first, in same buffer */
- if (stride != firstStride)
- return GL_FALSE; /* strides don't match */
-
- if (bufObj != firstBufObj)
- return GL_FALSE; /* arrays in different VBOs */
-
- if (abs(array->Ptr - firstPtr) > firstStride)
- return GL_FALSE; /* arrays start too far apart */
-
- if ((!bufObj || !_mesa_is_bufferobj(bufObj)) != userSpaceBuffer)
- return GL_FALSE; /* mix of VBO and user-space arrays */
- }
- }
-
- return GL_TRUE;
-}
-
-
-/**
- * Set up for drawing interleaved arrays that all live in one VBO
- * or all live in user space.
- * \param vbuffer returns vertex buffer info
- * \param velements returns vertex element info
- */
-static void
-setup_interleaved_attribs(struct gl_context *ctx,
- const struct st_vertex_program *vp,
- const struct st_vp_variant *vpv,
- const struct gl_client_array **arrays,
- struct pipe_vertex_buffer *vbuffer,
- struct pipe_vertex_element velements[],
- unsigned max_index,
- unsigned num_instances)
-{
- struct st_context *st = st_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 */
- if (vpv->num_inputs) {
- low_addr = arrays[vp->index_to_input[0]]->Ptr;
-
- for (attr = 1; attr < vpv->num_inputs; attr++) {
- const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr;
- low_addr = MIN2(low_addr, start);
- }
- }
-
- 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;
- velements[attr].src_format = st_pipe_vertex_format(array->Type,
- array->Size,
- array->Format,
- array->Normalized);
- assert(velements[attr].src_format);
- }
-}
-
-
-/**
- * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
- * vertex attribute.
- * \param vbuffer returns vertex buffer info
- * \param velements returns vertex element info
- */
-static void
-setup_non_interleaved_attribs(struct gl_context *ctx,
- const struct st_vertex_program *vp,
- const struct st_vp_variant *vpv,
- const struct gl_client_array **arrays,
- struct pipe_vertex_buffer vbuffer[],
- struct pipe_vertex_element velements[],
- unsigned max_index,
- unsigned num_instances)
-{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
- GLuint attr;
-
- 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;
- GLuint element_size = array->_ElementSize;
- GLsizei stride = array->StrideB;
-
- assert(element_size == array->Size * _mesa_sizeof_type(array->Type));
-
- if (bufobj && _mesa_is_bufferobj(bufobj)) {
- /* Attribute data is in a VBO.
- * Recall that for VBOs, the gl_client_array->Ptr field is
- * really an offset from the start of the VBO, not a pointer.
- */
- struct st_buffer_object *stobj = st_buffer_object(bufobj);
- assert(stobj->buffer);
-
- vbuffer[attr].buffer = NULL;
- pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer);
- vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr);
- }
- else {
- /* wrap user data */
- uint bytes;
- void *ptr;
-
- if (array->Ptr) {
- uint divisor = array->InstanceDivisor;
- uint last_index = divisor ? num_instances / divisor : max_index;
-
- bytes = stride * last_index + element_size;
-
- ptr = (void *) array->Ptr;
- }
- else {
- /* no array, use ctx->Current.Attrib[] value */
- bytes = element_size = sizeof(ctx->Current.Attrib[0]);
- ptr = (void *) ctx->Current.Attrib[mesaAttr];
- stride = 0;
- }
-
- assert(ptr);
- assert(bytes);
-
- vbuffer[attr].buffer =
- pipe_user_buffer_create(pipe->screen, ptr, bytes,
- PIPE_BIND_VERTEX_BUFFER);
-
- vbuffer[attr].buffer_offset = 0;
-
- /* Track user vertex buffers. */
- pipe_resource_reference(&st->user_attrib[attr].buffer, vbuffer[attr].buffer);
- st->user_attrib[attr].element_size = element_size;
- st->user_attrib[attr].stride = stride;
- st->num_user_attribs = MAX2(st->num_user_attribs, attr + 1);
- }
-
- /* common-case setup */
- vbuffer[attr].stride = stride; /* in bytes */
-
- velements[attr].src_offset = 0;
- velements[attr].instance_divisor = array->InstanceDivisor;
- velements[attr].vertex_buffer_index = attr;
- velements[attr].src_format = st_pipe_vertex_format(array->Type,
- array->Size,
- array->Format,
- array->Normalized);
- assert(velements[attr].src_format);
- }
-}
-
-
-static void
-setup_index_buffer(struct gl_context *ctx,