From 6d28bf917fb1d741d90fd3f05c22769376021fca Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Fri, 16 Jul 2010 04:35:58 +0800 Subject: gallium: Implement draw_vbo and set_index_buffer for all drivers. Some drivers define a generic function that is called by all drawing functions. To implement draw_vbo for such drivers, either draw_vbo calls the generic function or the prototype of the generic function is changed to match draw_vbo. Other drivers have no such generic function. draw_vbo is implemented by calling either draw_arrays and draw_elements. For most drivers, set_index_buffer does not mark the state dirty for tracking. Instead, the index buffer state is emitted whenever draw_vbo is called, just like the case with draw_elements. It surely can be improved. --- src/gallium/drivers/r300/r300_context.h | 2 + src/gallium/drivers/r300/r300_render.c | 142 ++++++++++++++-------- src/gallium/drivers/r300/r300_render_stencilref.c | 22 ++++ src/gallium/drivers/r300/r300_state.c | 18 +++ 4 files changed, 133 insertions(+), 51 deletions(-) (limited to 'src/gallium/drivers/r300') diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index b4256c6278..7c77a46016 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -524,6 +524,8 @@ struct r300_context { struct r300_vertex_element_state *velems; bool any_user_vbs; + struct pipe_index_buffer index_buffer; + /* Vertex info for Draw. */ struct vertex_info vertex_info; diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index bae02135da..da96098cc4 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -33,6 +33,7 @@ #include "util/u_memory.h" #include "util/u_upload_mgr.h" #include "util/u_prim.h" +#include "util/u_draw_quad.h" #include "r300_cs.h" #include "r300_context.h" @@ -638,26 +639,56 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, } } +static void r300_draw_vbo(struct pipe_context* pipe, + const struct pipe_draw_info *info) +{ + struct r300_context* r300 = r300_context(pipe); + + if (info->indexed && r300->index_buffer.buffer) { + unsigned offset; + + assert(r300->index_buffer.offset % r300->index_buffer.index_size == 0); + offset = r300->index_buffer.offset / r300->index_buffer.index_size; + + r300_draw_range_elements(pipe, + r300->index_buffer.buffer, + r300->index_buffer.index_size, + info->index_bias, + info->min_index, + info->max_index, + info->mode, + info->start + offset, + info->count); + } + else { + r300_draw_arrays(pipe, + info->mode, + info->start, + info->count); + } +} + /**************************************************************************** * The rest of this file is for SW TCL rendering only. Please be polite and * * keep these functions separated so that they are easier to locate. ~C. * ***************************************************************************/ -/* SW TCL arrays, using Draw. */ -static void r300_swtcl_draw_arrays(struct pipe_context* pipe, - unsigned mode, - unsigned start, - unsigned count) +/* SW TCL elements, using Draw. */ +static void r300_swtcl_draw_vbo(struct pipe_context* pipe, + const struct pipe_draw_info *info) { struct r300_context* r300 = r300_context(pipe); struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; + struct pipe_transfer *ib_transfer; + unsigned count = info->count; int i; + void* indices = NULL; if (r300->skip_rendering) { return; } - if (!u_trim_pipe_prim(mode, &count)) { + if (!u_trim_pipe_prim(info->mode, &count)) { return; } @@ -667,13 +698,25 @@ static void r300_swtcl_draw_arrays(struct pipe_context* pipe, void* buf = pipe_buffer_map(pipe, r300->vertex_buffer[i].buffer, PIPE_TRANSFER_READ, - &vb_transfer[i]); + &vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, buf); } - draw_set_mapped_element_buffer(r300->draw, 0, 0, NULL); + if (info->indexed && r300->index_buffer.buffer) { + indices = pipe_buffer_map(pipe, r300->index_buffer.buffer, + PIPE_TRANSFER_READ, &ib_transfer); + if (indices) + indices += r300->index_buffer.offset; + } + + draw_set_mapped_element_buffer_range(r300->draw, (indices) ? + r300->index_buffer.index_size : 0, + info->index_bias, + info->min_index, + info->max_index, + indices); - draw_arrays(r300->draw, mode, start, count); + draw_arrays(r300->draw, info->mode, info->start, count); /* XXX Not sure whether this is the best fix. * It prevents CS from being rejected and weird assertion failures. */ @@ -681,9 +724,15 @@ static void r300_swtcl_draw_arrays(struct pipe_context* pipe, for (i = 0; i < r300->vertex_buffer_count; i++) { pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, - vb_transfer[i]); + vb_transfer[i]); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); } + + if (ib_transfer) { + pipe_buffer_unmap(pipe, r300->index_buffer.buffer, ib_transfer); + draw_set_mapped_element_buffer_range(r300->draw, 0, 0, info->start, + info->start + count - 1, NULL); + } } /* SW TCL elements, using Draw. */ @@ -698,51 +747,40 @@ static void r300_swtcl_draw_range_elements(struct pipe_context* pipe, unsigned count) { struct r300_context* r300 = r300_context(pipe); - struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS]; - struct pipe_transfer *ib_transfer; - int i; - void* indices; - - if (r300->skip_rendering) { - return; - } - - if (!u_trim_pipe_prim(mode, &count)) { - return; + struct pipe_draw_info info; + struct pipe_index_buffer saved_ib, ib; + + util_draw_init_info(&info); + info.mode = mode; + info.start = start; + info.count = count; + info.index_bias = indexBias; + info.min_index = minIndex; + info.max_index = maxIndex; + + if (indexBuffer) { + info.indexed = TRUE; + + saved_ib = r300->index_buffer; + ib.buffer = indexBuffer; + ib.offset = 0; + ib.index_size = indexSize; + pipe->set_index_buffer(pipe, &ib); } - r300_update_derived_state(r300); - - for (i = 0; i < r300->vertex_buffer_count; i++) { - void* buf = pipe_buffer_map(pipe, - r300->vertex_buffer[i].buffer, - PIPE_TRANSFER_READ, - &vb_transfer[i]); - draw_set_mapped_vertex_buffer(r300->draw, i, buf); - } - - indices = pipe_buffer_map(pipe, indexBuffer, - PIPE_TRANSFER_READ, &ib_transfer); - draw_set_mapped_element_buffer_range(r300->draw, indexSize, indexBias, - minIndex, maxIndex, indices); - - draw_arrays(r300->draw, mode, start, count); - - /* XXX Not sure whether this is the best fix. - * It prevents CS from being rejected and weird assertion failures. */ - draw_flush(r300->draw); + r300_swtcl_draw_vbo(pipe, &info); - for (i = 0; i < r300->vertex_buffer_count; i++) { - pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer, - vb_transfer[i]); - draw_set_mapped_vertex_buffer(r300->draw, i, NULL); - } + if (indexBuffer) + pipe->set_index_buffer(pipe, &saved_ib); +} - pipe_buffer_unmap(pipe, indexBuffer, - ib_transfer); - draw_set_mapped_element_buffer_range(r300->draw, 0, 0, - start, start + count - 1, - NULL); +static void r300_swtcl_draw_arrays(struct pipe_context* pipe, + unsigned mode, + unsigned start, + unsigned count) +{ + r300_swtcl_draw_range_elements(pipe, NULL, 0, 0, + start, start + count -1, mode, start, count); } /* Object for rendering using Draw. */ @@ -1148,9 +1186,11 @@ void r300_init_render_functions(struct r300_context *r300) if (r300->screen->caps.has_tcl) { r300->context.draw_arrays = r300_draw_arrays; r300->context.draw_range_elements = r300_draw_range_elements; + r300->context.draw_vbo = r300_draw_vbo; } else { r300->context.draw_arrays = r300_swtcl_draw_arrays; r300->context.draw_range_elements = r300_swtcl_draw_range_elements; + r300->context.draw_vbo = r300_swtcl_draw_vbo; } r300->context.resource_resolve = r300_resource_resolve; diff --git a/src/gallium/drivers/r300/r300_render_stencilref.c b/src/gallium/drivers/r300/r300_render_stencilref.c index 9a6b4e12ff..6d801cf159 100644 --- a/src/gallium/drivers/r300/r300_render_stencilref.c +++ b/src/gallium/drivers/r300/r300_render_stencilref.c @@ -42,6 +42,9 @@ struct r300_stencilref_context { unsigned indexSize, int indexBias, unsigned minIndex, unsigned maxIndex, unsigned mode, unsigned start, unsigned count); + void (*draw_vbo)(struct pipe_context *pipe, + const struct pipe_draw_info *info); + uint32_t rs_cull_mode; uint32_t zb_stencilrefmask; ubyte ref_value_front; @@ -144,6 +147,23 @@ static void r300_stencilref_draw_range_elements( } } +static void r300_stencilref_draw_vbo(struct pipe_context *pipe, + const struct pipe_draw_info *info) +{ + struct r300_context *r300 = r300_context(pipe); + struct r300_stencilref_context *sr = r300->stencilref_fallback; + + if (!r300_stencilref_needed(r300)) { + sr->draw_vbo(pipe, info); + } else { + r300_stencilref_begin(r300); + sr->draw_vbo(pipe, info); + r300_stencilref_switch_side(r300); + sr->draw_vbo(pipe, info); + r300_stencilref_end(r300); + } +} + void r300_plug_in_stencil_ref_fallback(struct r300_context *r300) { r300->stencilref_fallback = CALLOC_STRUCT(r300_stencilref_context); @@ -151,8 +171,10 @@ void r300_plug_in_stencil_ref_fallback(struct r300_context *r300) /* Save original draw functions. */ r300->stencilref_fallback->draw_arrays = r300->context.draw_arrays; r300->stencilref_fallback->draw_range_elements = r300->context.draw_range_elements; + r300->stencilref_fallback->draw_vbo = r300->context.draw_vbo; /* Override the draw functions. */ r300->context.draw_arrays = r300_stencilref_draw_arrays; r300->context.draw_range_elements = r300_stencilref_draw_range_elements; + r300->context.draw_vbo = r300_stencilref_draw_vbo; } diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 3e221f2e02..bccd7d7859 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -1505,6 +1505,23 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, r300->vertex_buffer_count = count; } +static void r300_set_index_buffer(struct pipe_context* pipe, + const struct pipe_index_buffer *ib) +{ + struct r300_context* r300 = r300_context(pipe); + + if (ib) { + pipe_resource_reference(&r300->index_buffer.buffer, ib->buffer); + memcpy(&r300->index_buffer, ib, sizeof(r300->index_buffer)); + } + else { + pipe_resource_reference(&r300->index_buffer.buffer, NULL); + memset(&r300->index_buffer, 0, sizeof(r300->index_buffer)); + } + + /* TODO make this more like a state */ +} + /* Initialize the PSC tables. */ static void r300_vertex_psc(struct r300_vertex_element_state *velems) { @@ -1852,6 +1869,7 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.set_viewport_state = r300_set_viewport_state; r300->context.set_vertex_buffers = r300_set_vertex_buffers; + r300->context.set_index_buffer = r300_set_index_buffer; r300->context.create_vertex_elements_state = r300_create_vertex_elements_state; r300->context.bind_vertex_elements_state = r300_bind_vertex_elements_state; -- cgit v1.2.3