static void svga_vbuf_submit_state( struct svga_vbuf_render *svga_render ) { struct svga_context *svga = svga_render->svga; SVGA3dVertexDecl vdecl[PIPE_MAX_ATTRIBS]; enum pipe_error ret; int i; /* if the vdecl or vbuf hasn't changed do nothing */ if (!svga->swtnl.new_vdecl) return; memcpy(vdecl, svga_render->vdecl, sizeof(vdecl)); /* flush the hw state */ ret = svga_hwtnl_flush(svga->hwtnl); if (ret != PIPE_OK) { svga_context_flush(svga, NULL); ret = svga_hwtnl_flush(svga->hwtnl); /* if we hit this path we might become synced with hw */ svga->swtnl.new_vbuf = TRUE; assert(ret == 0); } svga_hwtnl_reset_vdecl(svga->hwtnl, svga_render->vdecl_count); for (i = 0; i < svga_render->vdecl_count; i++) { vdecl[i].array.offset += svga_render->vdecl_offset; svga_hwtnl_vdecl( svga->hwtnl, i, &vdecl[i], svga_render->vbuf ); } /* We have already taken care of flatshading, so let the hwtnl * module use whatever is most convenient: */ if (svga->state.sw.need_pipeline) { svga_hwtnl_set_flatshade(svga->hwtnl, FALSE, FALSE); svga_hwtnl_set_unfilled(svga->hwtnl, PIPE_POLYGON_MODE_FILL); } else { svga_hwtnl_set_flatshade( svga->hwtnl, svga->curr.rast->templ.flatshade, svga->curr.rast->templ.flatshade_first ); svga_hwtnl_set_unfilled( svga->hwtnl, svga->curr.rast->hw_unfilled ); } svga->swtnl.new_vdecl = FALSE; }
static int emit_hw_vs_vdecl( struct svga_context *svga, unsigned dirty ) { const struct pipe_vertex_element *ve = svga->curr.ve; SVGA3dVertexDecl decl; unsigned i; assert(svga->curr.num_vertex_elements >= svga->curr.vs->base.info.file_count[TGSI_FILE_INPUT]); svga_hwtnl_reset_vdecl( svga->hwtnl, svga->curr.num_vertex_elements ); for (i = 0; i < svga->curr.num_vertex_elements; i++) { const struct pipe_vertex_buffer *vb = &svga->curr.vb[ve[i].vertex_buffer_index]; unsigned usage, index; svga_generate_vdecl_semantics( i, &usage, &index ); /* SVGA_NEW_VELEMENT */ decl.identity.type = svga->state.sw.ve_format[i]; decl.identity.method = SVGA3D_DECLMETHOD_DEFAULT; decl.identity.usage = usage; decl.identity.usageIndex = index; decl.array.stride = vb->stride; decl.array.offset = (vb->buffer_offset + ve[i].src_offset); svga_hwtnl_vdecl( svga->hwtnl, i, &decl, vb->buffer ); } return 0; }
static enum pipe_error emit_hw_vs_vdecl(struct svga_context *svga, unsigned dirty) { const struct pipe_vertex_element *ve = svga->curr.velems->velem; unsigned i; unsigned neg_bias = 0; assert(svga->curr.velems->count >= svga->curr.vs->base.info.file_count[TGSI_FILE_INPUT]); /* specify number of vertex element declarations to come */ svga_hwtnl_reset_vdecl( svga->hwtnl, svga->curr.velems->count ); /** * We can't set the VDECL offset to something negative, so we * must calculate a common negative additional index bias, and modify * the VDECL offsets accordingly so they *all* end up positive. * * Note that the exact value of the negative index bias is not that * important, since we compensate for it when we calculate the vertex * buffer offset below. The important thing is that all vertex buffer * offsets remain positive. * * Note that we use a negative bias variable in order to make the * rounding maths more easy to follow, and to avoid int / unsigned * confusion. */ for (i = 0; i < svga->curr.velems->count; i++) { const struct pipe_vertex_buffer *vb = &svga->curr.vb[ve[i].vertex_buffer_index]; const struct svga_buffer *buffer; unsigned int offset = vb->buffer_offset + ve[i].src_offset; if (!vb->buffer) continue; buffer = svga_buffer(vb->buffer); if (buffer->uploaded.start > offset) { unsigned tmp_neg_bias = buffer->uploaded.start - offset; if (vb->stride) tmp_neg_bias = (tmp_neg_bias + vb->stride - 1) / vb->stride; neg_bias = MAX2(neg_bias, tmp_neg_bias); } } for (i = 0; i < svga->curr.velems->count; i++) { const struct pipe_vertex_buffer *vb = &svga->curr.vb[ve[i].vertex_buffer_index]; unsigned usage, index; const struct svga_buffer *buffer; SVGA3dVertexDecl decl; if (!vb->buffer) continue; buffer = svga_buffer(vb->buffer); svga_generate_vdecl_semantics( i, &usage, &index ); /* SVGA_NEW_VELEMENT */ decl.identity.type = svga->state.sw.ve_format[i]; decl.identity.method = SVGA3D_DECLMETHOD_DEFAULT; decl.identity.usage = usage; decl.identity.usageIndex = index; decl.array.stride = vb->stride; /* Compensate for partially uploaded vbo, and * for the negative index bias. */ decl.array.offset = (vb->buffer_offset + ve[i].src_offset + neg_bias * vb->stride - buffer->uploaded.start); assert(decl.array.offset >= 0); svga_hwtnl_vdecl( svga->hwtnl, i, &decl, buffer->uploaded.buffer ? buffer->uploaded.buffer : vb->buffer ); } svga_hwtnl_set_index_bias( svga->hwtnl, -(int) neg_bias ); return PIPE_OK; }