diff options
author | Chia-I Wu <olv@lunarg.com> | 2010-07-16 04:35:58 +0800 |
---|---|---|
committer | Chia-I Wu <olv@lunarg.com> | 2010-07-29 13:45:30 +0800 |
commit | 6d28bf917fb1d741d90fd3f05c22769376021fca (patch) | |
tree | 9b8724b30658d61426297113136c2d23c0c62f14 /src/gallium/drivers | |
parent | c5e9d3114a80d6d35a2f4e65783cdc75fcc2deac (diff) |
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.
Diffstat (limited to 'src/gallium/drivers')
47 files changed, 974 insertions, 202 deletions
diff --git a/src/gallium/drivers/cell/ppu/cell_context.h b/src/gallium/drivers/cell/ppu/cell_context.h index dc46e59a2d..d1aee62ba1 100644 --- a/src/gallium/drivers/cell/ppu/cell_context.h +++ b/src/gallium/drivers/cell/ppu/cell_context.h @@ -132,6 +132,7 @@ struct cell_context struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; uint num_vertex_buffers; + struct pipe_index_buffer index_buffer; ubyte *cbuf_map[PIPE_MAX_COLOR_BUFS]; ubyte *zsbuf_map; diff --git a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c index 6a1e4d8a64..e06226fbfe 100644 --- a/src/gallium/drivers/cell/ppu/cell_draw_arrays.c +++ b/src/gallium/drivers/cell/ppu/cell_draw_arrays.c @@ -34,6 +34,7 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" #include "util/u_inlines.h" +#include "util/u_draw_quad.h" #include "cell_context.h" #include "cell_draw_arrays.h" @@ -56,16 +57,11 @@ * XXX should the element buffer be specified/bound with a separate function? */ static void -cell_draw_range_elements(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned min_index, - unsigned max_index, - unsigned mode, unsigned start, unsigned count) +cell_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) { struct cell_context *cell = cell_context(pipe); struct draw_context *draw = cell->draw; + void *mapped_indices = NULL; unsigned i; if (cell->dirty) @@ -83,18 +79,20 @@ cell_draw_range_elements(struct pipe_context *pipe, draw_set_mapped_vertex_buffer(draw, i, buf); } /* Map index buffer, if present */ - if (indexBuffer) { - void *mapped_indexes = cell_resource(indexBuffer)->data; - draw_set_mapped_element_buffer(draw, indexSize, indexBias, mapped_indexes); - } - else { - /* no index/element buffer */ - draw_set_mapped_element_buffer(draw, 0, 0, NULL); + if (info->indexed && cell->index_buffer.buffer) { + mapped_indices = cell_resource(cell->index_buffer.buffer)->data; + mapped_indices += cell->index_buffer.offset; } + draw_set_mapped_element_buffer_range(draw, (mapped_indices) ? + lp->index_buffer.index_size : 0, + info->index_bias, + info->min_index, + info->max_index, + mapped_indices); /* draw! */ - draw_arrays(draw, mode, start, count); + draw_arrays(draw, info->mode, info->start, info->count); /* * unmap vertex/index buffers - will cause draw module to flush @@ -102,7 +100,7 @@ cell_draw_range_elements(struct pipe_context *pipe, for (i = 0; i < cell->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); } - if (indexBuffer) { + if (mapped_indices) { draw_set_mapped_element_buffer(draw, 0, 0, NULL); } @@ -116,6 +114,44 @@ cell_draw_range_elements(struct pipe_context *pipe, static void +cell_draw_range_elements(struct pipe_context *pipe, + struct pipe_resource *indexBuffer, + unsigned indexSize, + int indexBias, + unsigned min_index, + unsigned max_index, + unsigned mode, unsigned start, unsigned count) +{ + struct cell_context *cell = cell_context(pipe); + 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 = min_index; + info.max_index = max_index; + + if (indexBuffer) { + info.indexed = TRUE; + saved_ib = cell->index_buffer; + + ib.buffer = indexBuffer; + ib.offset = 0; + ib.index_size = indexSize; + pipe->set_index_buffer(pipe, &ib); + } + + cell_draw_vbo(pipe, &info); + + if (indexBuffer) + pipe->set_index_buffer(pipe, &saved_ib); +} + + +static void cell_draw_elements(struct pipe_context *pipe, struct pipe_resource *indexBuffer, unsigned indexSize, int indexBias, @@ -142,5 +178,6 @@ cell_init_draw_functions(struct cell_context *cell) cell->pipe.draw_arrays = cell_draw_arrays; cell->pipe.draw_elements = cell_draw_elements; cell->pipe.draw_range_elements = cell_draw_range_elements; + cell->pipe.draw_vbo = cell_draw_vbo; } diff --git a/src/gallium/drivers/cell/ppu/cell_state_vertex.c b/src/gallium/drivers/cell/ppu/cell_state_vertex.c index 69152b6cbf..4e3701cd0a 100644 --- a/src/gallium/drivers/cell/ppu/cell_state_vertex.c +++ b/src/gallium/drivers/cell/ppu/cell_state_vertex.c @@ -91,10 +91,26 @@ cell_set_vertex_buffers(struct pipe_context *pipe, } +static void +cell_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct cell_context *cell = cell_context(pipe); + + if (ib) + memcpy(&cell->index_buffer, ib, sizeof(cell->index_buffer)); + else + memset(&cell->index_buffer, 0, sizeof(cell->index_buffer)); + + /* TODO make this more like a state */ +} + + void cell_init_vertex_functions(struct cell_context *cell) { cell->pipe.set_vertex_buffers = cell_set_vertex_buffers; + cell->pipe.set_index_buffer = cell_set_index_buffer; cell->pipe.create_vertex_elements_state = cell_create_vertex_elements_state; cell->pipe.bind_vertex_elements_state = cell_bind_vertex_elements_state; cell->pipe.delete_vertex_elements_state = cell_delete_vertex_elements_state; diff --git a/src/gallium/drivers/failover/fo_context.c b/src/gallium/drivers/failover/fo_context.c index 9c9c1bdc45..1048d58313 100644 --- a/src/gallium/drivers/failover/fo_context.c +++ b/src/gallium/drivers/failover/fo_context.c @@ -28,6 +28,7 @@ #include "pipe/p_defines.h" #include "util/u_memory.h" +#include "util/u_draw_quad.h" #include "pipe/p_context.h" #include "fo_context.h" @@ -50,13 +51,8 @@ void failover_fail_over( struct failover_context *failover ) } -static void failover_draw_elements( struct pipe_context *pipe, - struct pipe_resource *indexResource, - unsigned indexSize, - int indexBias, - unsigned prim, - unsigned start, - unsigned count) +static void failover_draw_vbo( struct pipe_context *pipe, + const struct pipe_draw_info *info) { struct failover_context *failover = failover_context( pipe ); @@ -70,13 +66,7 @@ static void failover_draw_elements( struct pipe_context *pipe, /* Try hardware: */ if (failover->mode == FO_HW) { - failover->hw->draw_elements( failover->hw, - indexResource, - indexSize, - indexBias, - prim, - start, - count ); + failover->hw->draw_vbo( failover->hw, info ); } /* Possibly try software: @@ -88,13 +78,7 @@ static void failover_draw_elements( struct pipe_context *pipe, failover_state_emit( failover ); } - failover->sw->draw_elements( failover->sw, - indexResource, - indexSize, - indexBias, - prim, - start, - count ); + failover->sw->draw_vbo( failover->sw, info ); /* Be ready to switch back to hardware rendering without an * intervening flush. Unlikely to be much performance impact to @@ -105,6 +89,40 @@ static void failover_draw_elements( struct pipe_context *pipe, } +static void failover_draw_elements( struct pipe_context *pipe, + struct pipe_resource *indexResource, + unsigned indexSize, + int indexBias, + unsigned prim, + unsigned start, + unsigned count) +{ + struct failover_context *failover = failover_context( pipe ); + struct pipe_draw_info info; + struct pipe_index_buffer saved_ib, ib; + + util_draw_init_info(&info); + info.mode = prim; + info.start = start; + info.count = count; + + if (indexResource) { + info.indexed = TRUE; + saved_ib = failover->index_buffer; + + ib.buffer = indexResource; + ib.offset = 0; + ib.index_size = indexSize; + pipe->set_index_buffer(pipe, &ib); + } + + failover_draw_vbo(pipe, &info); + + if (indexResource) + pipe->set_index_buffer(pipe, &saved_ib); +} + + static void failover_draw_arrays( struct pipe_context *pipe, unsigned prim, unsigned start, unsigned count) { @@ -145,6 +163,7 @@ struct pipe_context *failover_create( struct pipe_context *hw, failover->pipe.draw_arrays = failover_draw_arrays; failover->pipe.draw_elements = failover_draw_elements; + failover->pipe.draw_vbo = failover_draw_vbo; failover->pipe.clear = hw->clear; failover->pipe.clear_render_target = hw->clear_render_target; failover->pipe.clear_depth_stencil = hw->clear_depth_stencil; diff --git a/src/gallium/drivers/failover/fo_context.h b/src/gallium/drivers/failover/fo_context.h index 9d3e0d0dba..1afa6c9cee 100644 --- a/src/gallium/drivers/failover/fo_context.h +++ b/src/gallium/drivers/failover/fo_context.h @@ -56,6 +56,7 @@ #define FO_NEW_VERTEX_BUFFER 0x40000 #define FO_NEW_VERTEX_ELEMENT 0x80000 #define FO_NEW_SAMPLE_MASK 0x100000 +#define FO_NEW_INDEX_BUFFER 0x200000 @@ -97,6 +98,7 @@ struct failover_context { struct pipe_scissor_state scissor; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; + struct pipe_index_buffer index_buffer; uint num_vertex_buffers; diff --git a/src/gallium/drivers/failover/fo_state.c b/src/gallium/drivers/failover/fo_state.c index 12e42379f9..c265f381b6 100644 --- a/src/gallium/drivers/failover/fo_state.c +++ b/src/gallium/drivers/failover/fo_state.c @@ -583,6 +583,23 @@ failover_set_vertex_buffers(struct pipe_context *pipe, } +static void +failover_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct failover_context *failover = failover_context(pipe); + + if (ib) + memcpy(&failover->index_buffer, ib, sizeof(failover->index_buffer)); + else + memset(&failover->index_buffer, 0, sizeof(failover->index_buffer)); + + failover->dirty |= FO_NEW_INDEX_BUFFER; + failover->sw->set_index_buffer( failover->sw, ib ); + failover->hw->set_index_buffer( failover->hw, ib ); +} + + void failover_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index, @@ -635,6 +652,7 @@ failover_init_state_functions( struct failover_context *failover ) failover->pipe.set_vertex_sampler_views = failover_set_vertex_sampler_views; failover->pipe.set_viewport_state = failover_set_viewport_state; failover->pipe.set_vertex_buffers = failover_set_vertex_buffers; + failover->pipe.set_index_buffer = failover_set_index_buffer; failover->pipe.set_constant_buffer = failover_set_constant_buffer; failover->pipe.create_sampler_view = failover_create_sampler_view; failover->pipe.sampler_view_destroy = failover_sampler_view_destroy; diff --git a/src/gallium/drivers/failover/fo_state_emit.c b/src/gallium/drivers/failover/fo_state_emit.c index 147f23269c..7f434ff9d6 100644 --- a/src/gallium/drivers/failover/fo_state_emit.c +++ b/src/gallium/drivers/failover/fo_state_emit.c @@ -135,5 +135,10 @@ failover_state_emit( struct failover_context *failover ) failover->vertex_buffers ); } + if (failover->dirty & FO_NEW_INDEX_BUFFER) { + failover->sw->set_index_buffer( failover->sw, + &failover->index_buffer ); + } + failover->dirty = 0; } diff --git a/src/gallium/drivers/galahad/glhd_context.c b/src/gallium/drivers/galahad/glhd_context.c index ab6f17b3ab..6473f2d499 100644 --- a/src/gallium/drivers/galahad/glhd_context.c +++ b/src/gallium/drivers/galahad/glhd_context.c @@ -112,6 +112,16 @@ galahad_draw_range_elements(struct pipe_context *_pipe, count); } +static void +galahad_draw_vbo(struct pipe_context *_pipe, + const struct pipe_draw_info *info) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + + pipe->draw_vbo(pipe, info); +} + static struct pipe_query * galahad_create_query(struct pipe_context *_pipe, unsigned query_type) @@ -650,6 +660,41 @@ galahad_set_vertex_buffers(struct pipe_context *_pipe, num_buffers, buffers); } + +static void +galahad_set_index_buffer(struct pipe_context *_pipe, + const struct pipe_index_buffer *_ib) +{ + struct galahad_context *glhd_pipe = galahad_context(_pipe); + struct pipe_context *pipe = glhd_pipe->pipe; + struct pipe_index_buffer unwrapped_ib, *ib = NULL; + + if (_ib->buffer) { + switch (_ib->index_size) { + case 1: + case 2: + case 4: + break; + default: + glhd_warn("index buffer %p has unrecognized index size %d", + _ib->buffer, _ib->index_size); + break; + } + } + else if (_ib->offset || _ib->index_size) { + glhd_warn("non-indexed state with index offset %d and index size %d", + _ib->offset, _ib->index_size); + } + + if (_ib) { + unwrapped_ib = *_ib; + unwrapped_ib.buffer = galahad_resource_unwrap(_ib->buffer); + ib = &unwrapped_ib; + } + + pipe->set_index_buffer(pipe, ib); +} + static void galahad_resource_copy_region(struct pipe_context *_pipe, struct pipe_resource *_dst, @@ -937,6 +982,7 @@ galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) glhd_pipe->base.draw_arrays = galahad_draw_arrays; glhd_pipe->base.draw_elements = galahad_draw_elements; glhd_pipe->base.draw_range_elements = galahad_draw_range_elements; + glhd_pipe->base.draw_vbo = galahad_draw_vbo; glhd_pipe->base.create_query = galahad_create_query; glhd_pipe->base.destroy_query = galahad_destroy_query; glhd_pipe->base.begin_query = galahad_begin_query; @@ -976,6 +1022,7 @@ galahad_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) glhd_pipe->base.set_fragment_sampler_views = galahad_set_fragment_sampler_views; glhd_pipe->base.set_vertex_sampler_views = galahad_set_vertex_sampler_views; glhd_pipe->base.set_vertex_buffers = galahad_set_vertex_buffers; + glhd_pipe->base.set_index_buffer = galahad_set_index_buffer; glhd_pipe->base.resource_copy_region = galahad_resource_copy_region; glhd_pipe->base.clear = galahad_clear; glhd_pipe->base.clear_render_target = galahad_clear_render_target; diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index 2af9bdac95..ca07b3e235 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -36,6 +36,7 @@ #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "util/u_memory.h" +#include "util/u_draw_quad.h" #include "pipe/p_screen.h" @@ -45,16 +46,11 @@ static void -i915_draw_range_elements(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned min_index, - unsigned max_index, - unsigned prim, unsigned start, unsigned count) +i915_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) { struct i915_context *i915 = i915_context(pipe); struct draw_context *draw = i915->draw; + void *mapped_indices = NULL; unsigned i; if (i915->dirty) @@ -71,16 +67,18 @@ i915_draw_range_elements(struct pipe_context *pipe, /* * Map index buffer, if present */ - if (indexBuffer) { - void *mapped_indexes = i915_buffer(indexBuffer)->data; - draw_set_mapped_element_buffer_range(draw, indexSize, indexBias, - min_index, - max_index, - mapped_indexes); - } else { - draw_set_mapped_element_buffer(draw, 0, 0, NULL); + if (info->indexed && i915->index_buffer.buffer) { + mapped_indices = i915_buffer(i915->index_buffer.buffer)->data; + mapped_indices += i915->index_buffer.offset; } + draw_set_mapped_element_buffer_range(draw, (mapped_indices) ? + i915->index_buffer.index_size : 0, + info->index_bias, + info->min_index, + info->max_index, + mapped_indices); + draw_set_mapped_constant_buffer(draw, PIPE_SHADER_VERTEX, 0, i915->current.constants[PIPE_SHADER_VERTEX], @@ -90,7 +88,7 @@ i915_draw_range_elements(struct pipe_context *pipe, /* * Do the drawing */ - draw_arrays(i915->draw, prim, start, count); + draw_arrays(i915->draw, info->mode, info->start, info->count); /* * unmap vertex/index buffers @@ -99,12 +97,49 @@ i915_draw_range_elements(struct pipe_context *pipe, draw_set_mapped_vertex_buffer(draw, i, NULL); } - if (indexBuffer) { + if (mapped_indices) { draw_set_mapped_element_buffer(draw, 0, 0, NULL); } } static void +i915_draw_range_elements(struct pipe_context *pipe, + struct pipe_resource *indexBuffer, + unsigned indexSize, + int indexBias, + unsigned min_index, + unsigned max_index, + unsigned prim, unsigned start, unsigned count) +{ + struct i915_context *i915 = i915_context(pipe); + struct pipe_draw_info info; + struct pipe_index_buffer saved_ib, ib; + + util_draw_init_info(&info); + info.mode = prim; + info.start = start; + info.count = count; + info.index_bias = indexBias; + info.min_index = min_index; + info.max_index = max_index; + + if (indexBuffer) { + info.indexed = TRUE; + saved_ib = i915->index_buffer; + + ib.buffer = indexBuffer; + ib.offset = 0; + ib.index_size = indexSize; + pipe->set_index_buffer(pipe, &ib); + } + + i915_draw_vbo(pipe, &info); + + if (indexBuffer) + pipe->set_index_buffer(pipe, &saved_ib); +} + +static void i915_draw_elements(struct pipe_context *pipe, struct pipe_resource *indexBuffer, unsigned indexSize, int indexBias, @@ -171,6 +206,7 @@ i915_create_context(struct pipe_screen *screen, void *priv) i915->base.draw_arrays = i915_draw_arrays; i915->base.draw_elements = i915_draw_elements; i915->base.draw_range_elements = i915_draw_range_elements; + i915->base.draw_vbo = i915_draw_vbo; /* * Create drawing context and plug our rendering stage into it. diff --git a/src/gallium/drivers/i915/i915_context.h b/src/gallium/drivers/i915/i915_context.h index b210cb130d..3ae61d0ea7 100644 --- a/src/gallium/drivers/i915/i915_context.h +++ b/src/gallium/drivers/i915/i915_context.h @@ -221,6 +221,7 @@ struct i915_context struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + struct pipe_index_buffer index_buffer; unsigned dirty; diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index e767aa9f8f..385c3b2d2d 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -812,6 +812,19 @@ i915_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) FREE( velems ); } +static void i915_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct i915_context *i915 = i915_context(pipe); + + if (ib) + memcpy(&i915->index_buffer, ib, sizeof(i915->index_buffer)); + else + memset(&i915->index_buffer, 0, sizeof(i915->index_buffer)); + + /* TODO make this more like a state */ +} + static void i915_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) @@ -860,4 +873,5 @@ i915_init_state_functions( struct i915_context *i915 ) i915->base.sampler_view_destroy = i915_sampler_view_destroy; i915->base.set_viewport_state = i915_set_viewport_state; i915->base.set_vertex_buffers = i915_set_vertex_buffers; + i915->base.set_index_buffer = i915_set_index_buffer; } diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h index 94c9c443f0..56d351f97d 100644 --- a/src/gallium/drivers/i965/brw_context.h +++ b/src/gallium/drivers/i965/brw_context.h @@ -576,6 +576,7 @@ struct brw_context */ struct pipe_resource *index_buffer; unsigned index_size; + unsigned index_offset; /* Updates are signalled by PIPE_NEW_INDEX_RANGE: */ diff --git a/src/gallium/drivers/i965/brw_draw.c b/src/gallium/drivers/i965/brw_draw.c index 4625c2048f..fa7d047e0b 100644 --- a/src/gallium/drivers/i965/brw_draw.c +++ b/src/gallium/drivers/i965/brw_draw.c @@ -29,6 +29,7 @@ #include "util/u_inlines.h" #include "util/u_prim.h" #include "util/u_upload_mgr.h" +#include "util/u_draw_quad.h" #include "brw_draw.h" #include "brw_defines.h" @@ -142,7 +143,7 @@ static int brw_emit_prim(struct brw_context *brw, */ static int try_draw_range_elements(struct brw_context *brw, - struct pipe_resource *index_buffer, + boolean indexed, unsigned hw_prim, unsigned start, unsigned count) { @@ -165,7 +166,7 @@ try_draw_range_elements(struct brw_context *brw, if (ret) return ret; - ret = brw_emit_prim(brw, start, count, index_buffer != NULL, hw_prim); + ret = brw_emit_prim(brw, start, count, indexed, hw_prim); if (ret) return ret; @@ -177,62 +178,87 @@ try_draw_range_elements(struct brw_context *brw, static void -brw_draw_range_elements(struct pipe_context *pipe, - struct pipe_resource *index_buffer, - unsigned index_size, int index_bias, - unsigned min_index, - unsigned max_index, - unsigned mode, unsigned start, unsigned count) +brw_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) { struct brw_context *brw = brw_context(pipe); int ret; uint32_t hw_prim; - hw_prim = brw_set_prim(brw, mode); + hw_prim = brw_set_prim(brw, info->mode); if (BRW_DEBUG & DEBUG_PRIMS) debug_printf("PRIM: %s start %d count %d index_buffer %p\n", - u_prim_name(mode), start, count, (void *)index_buffer); - - assert(index_bias == 0); + u_prim_name(info->mode), info->start, info->count, + (void *) brw->curr.index_buffer); - /* Potentially trigger upload of new index buffer. - * - * XXX: do we need to go through state validation to achieve this? - * Could just call upload code directly. - */ - if (brw->curr.index_buffer != index_buffer || - brw->curr.index_size != index_size) { - pipe_resource_reference( &brw->curr.index_buffer, index_buffer ); - brw->curr.index_size = index_size; - brw->state.dirty.mesa |= PIPE_NEW_INDEX_BUFFER; - } + assert(info->index_bias == 0); - /* XXX: do we really care? + /* Potentially trigger upload of new index buffer range. + * XXX: do we really care? */ - if (brw->curr.min_index != min_index || - brw->curr.max_index != max_index) + if (brw->curr.min_index != info->min_index || + brw->curr.max_index != info->max_index) { - brw->curr.min_index = min_index; - brw->curr.max_index = max_index; + brw->curr.min_index = info->min_index; + brw->curr.max_index = info->max_index; brw->state.dirty.mesa |= PIPE_NEW_INDEX_RANGE; } /* Make a first attempt at drawing: */ - ret = try_draw_range_elements(brw, index_buffer, hw_prim, start, count ); + ret = try_draw_range_elements(brw, info->indexed, + hw_prim, info->start, info->count); /* Otherwise, flush and retry: */ if (ret != 0) { brw_context_flush( brw ); - ret = try_draw_range_elements(brw, index_buffer, hw_prim, start, count ); + ret = try_draw_range_elements(brw, info->indexed, + hw_prim, info->start, info->count); assert(ret == 0); } } static void +brw_draw_range_elements(struct pipe_context *pipe, + struct pipe_resource *index_buffer, + unsigned index_size, int index_bias, + unsigned min_index, + unsigned max_index, + unsigned mode, unsigned start, unsigned count) +{ + struct brw_context *brw = brw_context(pipe); + 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 = index_bias; + info.min_index = min_index; + info.max_index = max_index; + + if (index_buffer) { + info.indexed = TRUE; + saved_ib.buffer = brw->curr.index_buffer; + saved_ib.offset = brw->curr.index_offset; + saved_ib.index_size = brw->curr.index_size; + + ib.buffer = index_buffer; + ib.offset = 0; + ib.index_size = index_size; + pipe->set_index_buffer(pipe, &ib); + } + + brw_draw_vbo(pipe, &info); + + if (index_buffer) + pipe->set_index_buffer(pipe, &saved_ib); +} + +static void brw_draw_elements(struct pipe_context *pipe, struct pipe_resource *index_buffer, unsigned index_size, int index_bias, @@ -262,6 +288,7 @@ boolean brw_draw_init( struct brw_context *brw ) brw->base.draw_arrays = brw_draw_arrays; brw->base.draw_elements = brw_draw_elements; brw->base.draw_range_elements = brw_draw_range_elements; + brw->base.draw_vbo = brw_draw_vbo; /* Create helpers for uploading data in user buffers: */ diff --git a/src/gallium/drivers/i965/brw_draw_upload.c b/src/gallium/drivers/i965/brw_draw_upload.c index 337eee8cd9..ebeb1e146a 100644 --- a/src/gallium/drivers/i965/brw_draw_upload.c +++ b/src/gallium/drivers/i965/brw_draw_upload.c @@ -231,7 +231,7 @@ static int brw_prepare_indices(struct brw_context *brw) struct pipe_resource *upload_buf = NULL; struct brw_winsys_buffer *bo = NULL; GLuint offset; - GLuint index_size; + GLuint index_size, index_offset; GLuint ib_size; int ret; @@ -246,13 +246,14 @@ static int brw_prepare_indices(struct brw_context *brw) ib_size = index_buffer->width0; index_size = brw->curr.index_size; + index_offset = brw->curr.index_offset; /* Turn userbuffer into a proper hardware buffer? */ if (brw_buffer_is_user_buffer(index_buffer)) { ret = u_upload_buffer( brw->vb.upload_index, - 0, + index_offset, ib_size, index_buffer, &offset, @@ -269,7 +270,7 @@ static int brw_prepare_indices(struct brw_context *brw) else { bo = brw_buffer(index_buffer)->bo; ib_size = bo->size; - offset = 0; + offset = index_offset; } /* Use CMD_3D_PRIM's start_vertex_offset to avoid re-uploading the diff --git a/src/gallium/drivers/i965/brw_pipe_vertex.c b/src/gallium/drivers/i965/brw_pipe_vertex.c index 4a120a51da..007239efc4 100644 --- a/src/gallium/drivers/i965/brw_pipe_vertex.c +++ b/src/gallium/drivers/i965/brw_pipe_vertex.c @@ -274,10 +274,41 @@ static void brw_set_vertex_buffers(struct pipe_context *pipe, } +static void brw_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct brw_context *brw = brw_context(pipe); + + if (ib) { + if (brw->curr.index_buffer == ib->buffer && + brw->curr.index_offset == ib->offset && + brw->curr.index_size == ib->index_size) + return; + + pipe_resource_reference(&brw->curr.index_buffer, ib->buffer); + brw->curr.index_offset = ib->offset; + brw->curr.index_size = ib->index_size; + } + else { + if (!brw->curr.index_buffer && + !brw->curr.index_offset && + !brw->curr.index_size) + return; + + pipe_resource_reference(&brw->curr.index_buffer, NULL); + brw->curr.index_offset = 0; + brw->curr.index_size = 0; + } + + brw->state.dirty.mesa |= PIPE_NEW_INDEX_BUFFER; +} + + void brw_pipe_vertex_init( struct brw_context *brw ) { brw->base.set_vertex_buffers = brw_set_vertex_buffers; + brw->base.set_index_buffer = brw_set_index_buffer; brw->base.create_vertex_elements_state = brw_create_vertex_elements_state; brw->base.bind_vertex_elements_state = brw_bind_vertex_elements_state; brw->base.delete_vertex_elements_state = brw_delete_vertex_elements_state; diff --git a/src/gallium/drivers/identity/id_context.c b/src/gallium/drivers/identity/id_context.c index 67be895b38..e10d3a1413 100644 --- a/src/gallium/drivers/identity/id_context.c +++ b/src/gallium/drivers/identity/id_context.c @@ -110,6 +110,16 @@ identity_draw_range_elements(struct pipe_context *_pipe, count); } +static void +identity_draw_vbo(struct pipe_context *_pipe, + const struct pipe_draw_info *info) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + + pipe->draw_vbo(pipe, info); +} + static struct pipe_query * identity_create_query(struct pipe_context *_pipe, unsigned query_type) @@ -611,6 +621,24 @@ identity_set_vertex_buffers(struct pipe_context *_pipe, num_buffers, buffers); } + +static void +identity_set_index_buffer(struct pipe_context *_pipe, + const struct pipe_index_buffer *_ib) +{ + struct identity_context *id_pipe = identity_context(_pipe); + struct pipe_context *pipe = id_pipe->pipe; + struct pipe_index_buffer unwrapped_ib, *ib = NULL; + + if (_ib) { + unwrapped_ib = *_ib; + unwrapped_ib.buffer = identity_resource_unwrap(_ib->buffer); + ib = &unwrapped_ib; + } + + pipe->set_index_buffer(pipe, ib); +} + static void identity_resource_copy_region(struct pipe_context *_pipe, struct pipe_resource *_dst, @@ -892,6 +920,7 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.draw_arrays = identity_draw_arrays; id_pipe->base.draw_elements = identity_draw_elements; id_pipe->base.draw_range_elements = identity_draw_range_elements; + id_pipe->base.draw_vbo = identity_draw_vbo; id_pipe->base.create_query = identity_create_query; id_pipe->base.destroy_query = identity_destroy_query; id_pipe->base.begin_query = identity_begin_query; @@ -931,6 +960,7 @@ identity_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) id_pipe->base.set_fragment_sampler_views = identity_set_fragment_sampler_views; id_pipe->base.set_vertex_sampler_views = identity_set_vertex_sampler_views; id_pipe->base.set_vertex_buffers = identity_set_vertex_buffers; + id_pipe->base.set_index_buffer = identity_set_index_buffer; id_pipe->base.resource_copy_region = identity_resource_copy_region; id_pipe->base.clear = identity_clear; id_pipe->base.clear_render_target = identity_clear_render_target; diff --git a/src/gallium/drivers/llvmpipe/lp_context.h b/src/gallium/drivers/llvmpipe/lp_context.h index b2643ab33c..50f9091c3c 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.h +++ b/src/gallium/drivers/llvmpipe/lp_context.h @@ -77,6 +77,7 @@ struct llvmpipe_context { struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + struct pipe_index_buffer index_buffer; struct { struct llvmpipe_resource *buffer[PIPE_MAX_SO_BUFFERS]; int offset[PIPE_MAX_SO_BUFFERS]; diff --git a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c index 625d0c8a8c..b6dbb9d288 100644 --- a/src/gallium/drivers/llvmpipe/lp_draw_arrays.c +++ b/src/gallium/drivers/llvmpipe/lp_draw_arrays.c @@ -34,6 +34,7 @@ #include "pipe/p_defines.h" #include "pipe/p_context.h" #include "util/u_prim.h" +#include "util/u_draw_quad.h" #include "lp_context.h" #include "lp_state.h" @@ -49,20 +50,11 @@ * the drawing to the 'draw' module. */ static void -llvmpipe_draw_range_elements_instanced(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count, - unsigned startInstance, - unsigned instanceCount) +llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) { struct llvmpipe_context *lp = llvmpipe_context(pipe); struct draw_context *draw = lp->draw; + void *mapped_indices = NULL; unsigned i; if (lp->dirty) @@ -77,27 +69,25 @@ llvmpipe_draw_range_elements_instanced(struct pipe_context *pipe, } /* Map index buffer, if present */ - if (indexBuffer) { - void *mapped_indexes = llvmpipe_resource_data(indexBuffer); - draw_set_mapped_element_buffer_range(draw, - indexSize, - indexBias, - minIndex, - maxIndex, - mapped_indexes); - } - else { - /* no index/element buffer */ - draw_set_mapped_element_buffer_range(draw, 0, 0, start, - start + count - 1, NULL); + if (info->indexed && lp->index_buffer.buffer) { + mapped_indices = llvmpipe_resource_data(lp->index_buffer.buffer); + mapped_indices += lp->index_buffer.offset; } + + draw_set_mapped_element_buffer_range(draw, (mapped_indices) ? + lp->index_buffer.index_size : 0, + info->index_bias, + info->min_index, + info->max_index, + mapped_indices); + llvmpipe_prepare_vertex_sampling(lp, lp->num_vertex_sampler_views, lp->vertex_sampler_views); /* draw! */ - draw_arrays_instanced(draw, mode, start, count, - startInstance, instanceCount); + draw_arrays_instanced(draw, info->mode, info->start, info->count, + info->start_instance, info->instance_count); /* * unmap vertex/index buffers @@ -105,7 +95,7 @@ llvmpipe_draw_range_elements_instanced(struct pipe_context *pipe, for (i = 0; i < lp->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); } - if (indexBuffer) { + if (mapped_indices) { draw_set_mapped_element_buffer(draw, 0, 0, NULL); } llvmpipe_cleanup_vertex_sampling(lp); @@ -120,6 +110,50 @@ llvmpipe_draw_range_elements_instanced(struct pipe_context *pipe, static void +llvmpipe_draw_range_elements_instanced(struct pipe_context *pipe, + struct pipe_resource *indexBuffer, + unsigned indexSize, + int indexBias, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount) +{ + struct llvmpipe_context *lp = llvmpipe_context(pipe); + 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.start_instance = startInstance; + info.instance_count = instanceCount; + + info.index_bias = indexBias; + info.min_index = minIndex; + info.max_index = maxIndex; + + if (indexBuffer) { + info.indexed = TRUE; + saved_ib = lp->index_buffer; + + ib.buffer = indexBuffer; + ib.offset = 0; + ib.index_size = indexSize; + pipe->set_index_buffer(pipe, &ib); + } + + llvmpipe_draw_vbo(pipe, &info); + + if (indexBuffer) + pipe->set_index_buffer(pipe, &saved_ib); +} + +static void llvmpipe_draw_arrays_instanced(struct pipe_context *pipe, unsigned mode, unsigned start, @@ -227,4 +261,6 @@ llvmpipe_init_draw_funcs(struct llvmpipe_context *llvmpipe) llvmpipe->pipe.draw_range_elements = llvmpipe_draw_range_elements; llvmpipe->pipe.draw_arrays_instanced = llvmpipe_draw_arrays_instanced; llvmpipe->pipe.draw_elements_instanced = llvmpipe_draw_elements_instanced; + + llvmpipe->pipe.draw_vbo = llvmpipe_draw_vbo; } diff --git a/src/gallium/drivers/llvmpipe/lp_state_vertex.c b/src/gallium/drivers/llvmpipe/lp_state_vertex.c index 113f13db01..d86e66b4fb 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_vertex.c +++ b/src/gallium/drivers/llvmpipe/lp_state_vertex.c @@ -89,6 +89,19 @@ llvmpipe_set_vertex_buffers(struct pipe_context *pipe, } +static void +llvmpipe_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); + + if (ib) + memcpy(&llvmpipe->index_buffer, ib, sizeof(llvmpipe->index_buffer)); + else + memset(&llvmpipe->index_buffer, 0, sizeof(llvmpipe->index_buffer)); + + /* TODO make this more like a state */ +} void llvmpipe_init_vertex_funcs(struct llvmpipe_context *llvmpipe) @@ -98,4 +111,5 @@ llvmpipe_init_vertex_funcs(struct llvmpipe_context *llvmpipe) llvmpipe->pipe.delete_vertex_elements_state = llvmpipe_delete_vertex_elements_state; llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers; + llvmpipe->pipe.set_index_buffer = llvmpipe_set_index_buffer; } diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index 915a925402..3fc39c1137 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -86,6 +86,7 @@ nv50_create(struct pipe_screen *pscreen, void *priv) nv50->pipe.draw_arrays_instanced = nv50_draw_arrays_instanced; nv50->pipe.draw_elements = nv50_draw_elements; nv50->pipe.draw_elements_instanced = nv50_draw_elements_instanced; + nv50->pipe.draw_vbo = nv50_draw_vbo; nv50->pipe.clear = nv50_clear; nv50->pipe.flush = nv50_flush; diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index 12c4a93a9b..a7c2b5d487 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -148,6 +148,7 @@ struct nv50_context { struct pipe_resource *constbuf[PIPE_SHADER_TYPES]; struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS]; unsigned vtxbuf_nr; + struct pipe_index_buffer idxbuf; struct nv50_vtxelt_stateobj *vtxelt; struct nv50_sampler_stateobj *sampler[3][PIPE_MAX_SAMPLERS]; unsigned sampler_nr[3]; @@ -197,6 +198,8 @@ extern void nv50_draw_elements_instanced(struct pipe_context *pipe, unsigned count, unsigned startInstance, unsigned instanceCount); +extern void nv50_draw_vbo(struct pipe_context *pipe, + const struct pipe_draw_info *info); extern void nv50_vtxelt_construct(struct nv50_vtxelt_stateobj *cso); extern struct nouveau_stateobj *nv50_vbo_validate(struct nv50_context *nv50); diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index 42c5a58318..ec0c0ff283 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -742,6 +742,20 @@ nv50_set_vertex_buffers(struct pipe_context *pipe, unsigned count, nv50->dirty |= NV50_NEW_ARRAYS; } +static void +nv50_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct nv50_context *nv50 = nv50_context(pipe); + + if (ib) + memcpy(&nv50->idxbuf, ib, sizeof(nv50->idxbuf)); + else + memset(&nv50->idxbuf, 0, sizeof(nv50->idxbuf)); + + /* TODO make this more like a state */ +} + static void * nv50_vtxelts_state_create(struct pipe_context *pipe, unsigned num_elements, @@ -827,5 +841,6 @@ nv50_init_state_functions(struct nv50_context *nv50) nv50->pipe.bind_vertex_elements_state = nv50_vtxelts_state_bind; nv50->pipe.set_vertex_buffers = nv50_set_vertex_buffers; + nv50->pipe.set_index_buffer = nv50_set_index_buffer; } diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c index 864cb09352..11ffc182c2 100644 --- a/src/gallium/drivers/nv50/nv50_vbo.c +++ b/src/gallium/drivers/nv50/nv50_vbo.c @@ -473,6 +473,37 @@ nv50_draw_elements(struct pipe_context *pipe, mode, start, count, 0, 1); } +void +nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) +{ + struct nv50_context *nv50 = nv50_context(pipe); + + if (info->indexed && nv50->idxbuf.buffer) { + unsigned offset; + + assert(nv50->idxbuf.offset % nv50->idxbuf.index_size == 0); + offset = nv50->idxbuf.offset / nv50->idxbuf.index_size; + + nv50_draw_elements_instanced(pipe, + nv50->idxbuf.buffer, + nv50->idxbuf.index_size, + info->index_bias, + info->mode, + info->start + offset, + info->count, + info->start_instance, + info->instance_count); + } + else { + nv50_draw_arrays_instanced(pipe, + info->mode, + info->start, + info->count, + info->start_instance, + info->instance_count); + } +} + static INLINE boolean nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib, struct nouveau_stateobj **pso, diff --git a/src/gallium/drivers/nvfx/nvfx_context.c b/src/gallium/drivers/nvfx/nvfx_context.c index 6d2dc4d5bf..f30795f69a 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.c +++ b/src/gallium/drivers/nvfx/nvfx_context.c @@ -57,6 +57,7 @@ nvfx_create(struct pipe_screen *pscreen, void *priv) nvfx->pipe.destroy = nvfx_destroy; nvfx->pipe.draw_arrays = nvfx_draw_arrays; nvfx->pipe.draw_elements = nvfx_draw_elements; + nvfx->pipe.draw_vbo = nvfx_draw_vbo; nvfx->pipe.clear = nvfx_clear; nvfx->pipe.flush = nvfx_flush; diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h index e48f9f3aa8..d6cd272eed 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.h +++ b/src/gallium/drivers/nvfx/nvfx_context.h @@ -121,7 +121,8 @@ struct nvfx_context { struct pipe_stencil_ref stencil_ref; struct pipe_viewport_state viewport; struct pipe_framebuffer_state framebuffer; - struct pipe_resource *idxbuf; + struct pipe_index_buffer idxbuf; + struct pipe_resource *idxbuf_buffer; unsigned idxbuf_format; struct nvfx_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS]; struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; @@ -242,6 +243,8 @@ extern void nvfx_draw_elements(struct pipe_context *pipe, unsigned indexSize, int indexBias, unsigned mode, unsigned start, unsigned count); +extern void nvfx_draw_vbo(struct pipe_context *pipe, + const struct pipe_draw_info *info); /* nvfx_vertprog.c */ extern boolean nvfx_vertprog_validate(struct nvfx_context *nvfx); diff --git a/src/gallium/drivers/nvfx/nvfx_state.c b/src/gallium/drivers/nvfx/nvfx_state.c index 30322d46d9..cd58e439d7 100644 --- a/src/gallium/drivers/nvfx/nvfx_state.c +++ b/src/gallium/drivers/nvfx/nvfx_state.c @@ -555,6 +555,20 @@ nvfx_set_vertex_buffers(struct pipe_context *pipe, unsigned count, nvfx->draw_dirty |= NVFX_NEW_ARRAYS; } +static void +nvfx_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + if (ib) + memcpy(&nvfx->idxbuf, ib, sizeof(nvfx->idxbuf)); + else + memset(&nvfx->idxbuf, 0, sizeof(nvfx->idxbuf)); + + /* TODO make this more like a state */ +} + static void * nvfx_vtxelts_state_create(struct pipe_context *pipe, unsigned num_elements, @@ -635,4 +649,5 @@ nvfx_init_state_functions(struct nvfx_context *nvfx) nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind; nvfx->pipe.set_vertex_buffers = nvfx_set_vertex_buffers; + nvfx->pipe.set_index_buffer = nvfx_set_index_buffer; } diff --git a/src/gallium/drivers/nvfx/nvfx_vbo.c b/src/gallium/drivers/nvfx/nvfx_vbo.c index 520bae5aed..23a59b589b 100644 --- a/src/gallium/drivers/nvfx/nvfx_vbo.c +++ b/src/gallium/drivers/nvfx/nvfx_vbo.c @@ -85,7 +85,7 @@ nvfx_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_resource *ib, unsigned type; if (!ib) { - nvfx->idxbuf = NULL; + nvfx->idxbuf_buffer = NULL; nvfx->idxbuf_format = 0xdeadbeef; return FALSE; } @@ -104,10 +104,10 @@ nvfx_vbo_set_idxbuf(struct nvfx_context *nvfx, struct pipe_resource *ib, return FALSE; } - if (ib != nvfx->idxbuf || + if (ib != nvfx->idxbuf_buffer || type != nvfx->idxbuf_format) { nvfx->dirty |= NVFX_NEW_ARRAYS; - nvfx->idxbuf = ib; + nvfx->idxbuf_buffer = ib; nvfx->idxbuf_format = type; } @@ -491,11 +491,38 @@ nvfx_draw_elements(struct pipe_context *pipe, pipe->flush(pipe, 0, NULL); } +void +nvfx_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + + if (info->indexed && nvfx->idxbuf.buffer) { + unsigned offset; + + assert(nvfx->idxbuf.offset % nvfx->idxbuf.index_size == 0); + offset = nvfx->idxbuf.offset / nvfx->idxbuf.index_size; + + nvfx_draw_elements(pipe, + nvfx->idxbuf.buffer, + nvfx->idxbuf.index_size, + info->index_bias, + info->mode, + info->start + offset, + info->count); + } + else { + nvfx_draw_arrays(pipe, + info->mode, + info->start, + info->count); + } +} + boolean nvfx_vbo_validate(struct nvfx_context *nvfx) { struct nouveau_channel* chan = nvfx->screen->base.channel; - struct pipe_resource *ib = nvfx->idxbuf; + struct pipe_resource *ib = nvfx->idxbuf_buffer; unsigned ib_format = nvfx->idxbuf_format; int i; int elements = MAX2(nvfx->vtxelt->num_elements, nvfx->hw_vtxelt_nr); @@ -610,10 +637,10 @@ nvfx_vbo_relocate(struct nvfx_context *nvfx) } } - if(nvfx->idxbuf) + if(nvfx->idxbuf_buffer) { unsigned ib_flags = nvfx->screen->index_buffer_reloc_flags | NOUVEAU_BO_RD | NOUVEAU_BO_DUMMY; - struct nouveau_bo* bo = nvfx_resource(nvfx->idxbuf)->bo; + struct nouveau_bo* bo = nvfx_resource(nvfx->idxbuf_buffer)->bo; assert(nvfx->screen->index_buffer_reloc_flags); 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; diff --git a/src/gallium/drivers/r600/r600_context.c b/src/gallium/drivers/r600/r600_context.c index 4c7b67ea52..2c2bd4672b 100644 --- a/src/gallium/drivers/r600/r600_context.c +++ b/src/gallium/drivers/r600/r600_context.c @@ -316,6 +316,7 @@ struct pipe_context *r600_create_context(struct pipe_screen *screen, void *priv) rctx->context.draw_arrays = r600_draw_arrays; rctx->context.draw_elements = r600_draw_elements; rctx->context.draw_range_elements = r600_draw_range_elements; + rctx->context.draw_vbo = r600_draw_vbo; rctx->context.flush = r600_flush; /* Easy accessing of screen/winsys. */ diff --git a/src/gallium/drivers/r600/r600_context.h b/src/gallium/drivers/r600/r600_context.h index 1f03b202ee..9427c19d05 100644 --- a/src/gallium/drivers/r600/r600_context.h +++ b/src/gallium/drivers/r600/r600_context.h @@ -157,6 +157,7 @@ struct r600_context { struct r600_context_state *vs_sampler_view[PIPE_MAX_ATTRIBS]; struct r600_vertex_element *vertex_elements; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + struct pipe_index_buffer index_buffer; }; #if 0 @@ -201,6 +202,8 @@ void r600_draw_range_elements(struct pipe_context *ctx, unsigned index_size, int index_bias, unsigned min_index, unsigned max_index, unsigned mode, unsigned start, unsigned count); +void r600_draw_vbo(struct pipe_context *ctx, + const struct pipe_draw_info *info); void r600_init_blit_functions(struct r600_context *rctx); void r600_init_state_functions(struct r600_context *rctx); diff --git a/src/gallium/drivers/r600/r600_draw.c b/src/gallium/drivers/r600/r600_draw.c index b248beaf8c..eeaa677edb 100644 --- a/src/gallium/drivers/r600/r600_draw.c +++ b/src/gallium/drivers/r600/r600_draw.c @@ -225,3 +225,30 @@ void r600_draw_arrays(struct pipe_context *ctx, unsigned mode, draw.index_buffer = NULL; r600_draw_common(&draw); } + +void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *info) +{ + struct r600_context *rctx = r600_context(ctx); + struct r600_draw draw; + + assert(info->index_bias == 0); + + draw.ctx = ctx; + draw.mode = info->mode; + draw.start = info->start; + draw.count = info->count; + if (info->indexed && rctx->index_buffer.buffer) { + draw.index_size = rctx->index_buffer.index_size; + draw.index_buffer = rctx->index_buffer.buffer; + + assert(rctx->index_buffer.offset % + rctx->index_buffer.index_size == 0); + draw.start += rctx->index_buffer.offset / + rctx->index_buffer.index_size; + } + else { + draw.index_size = 0; + draw.index_buffer = NULL; + } + r600_draw_common(&draw); +} diff --git a/src/gallium/drivers/r600/r600_state.c b/src/gallium/drivers/r600/r600_state.c index ff5df855c6..57879e8d8b 100644 --- a/src/gallium/drivers/r600/r600_state.c +++ b/src/gallium/drivers/r600/r600_state.c @@ -404,6 +404,23 @@ static void r600_set_vertex_buffers(struct pipe_context *ctx, rctx->nvertex_buffer = count; } +static void r600_set_index_buffer(struct pipe_context *ctx, + const struct pipe_index_buffer *ib) +{ + struct r600_context *rctx = r600_context(ctx); + + if (ib) { + pipe_resource_reference(&rctx->index_buffer.buffer, ib->buffer); + memcpy(&rctx->index_buffer, ib, sizeof(rctx->index_buffer)); + } + else { + pipe_resource_reference(&rctx->index_buffer.buffer, NULL); + memset(&rctx->index_buffer, 0, sizeof(rctx->index_buffer)); + } + + /* TODO make this more like a state */ +} + static void r600_set_viewport_state(struct pipe_context *ctx, const struct pipe_viewport_state *state) { @@ -449,6 +466,7 @@ void r600_init_state_functions(struct r600_context *rctx) rctx->context.set_scissor_state = r600_set_scissor_state; rctx->context.set_stencil_ref = r600_set_stencil_ref; rctx->context.set_vertex_buffers = r600_set_vertex_buffers; + rctx->context.set_index_buffer = r600_set_index_buffer; rctx->context.set_vertex_sampler_views = r600_set_vs_sampler_view; rctx->context.set_viewport_state = r600_set_viewport_state; rctx->context.sampler_view_destroy = r600_sampler_view_destroy; diff --git a/src/gallium/drivers/rbug/rbug_context.c b/src/gallium/drivers/rbug/rbug_context.c index e0dd5cf8c2..c748073b2a 100644 --- a/src/gallium/drivers/rbug/rbug_context.c +++ b/src/gallium/drivers/rbug/rbug_context.c @@ -185,6 +185,21 @@ rbug_draw_range_elements(struct pipe_context *_pipe, pipe_mutex_unlock(rb_pipe->draw_mutex); } +static void +rbug_draw_vbo(struct pipe_context *_pipe, const struct pipe_draw_info *info) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + + pipe_mutex_lock(rb_pipe->draw_mutex); + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_BEFORE); + + pipe->draw_vbo(pipe, info); + + rbug_draw_block_locked(rb_pipe, RBUG_BLOCK_AFTER); + pipe_mutex_unlock(rb_pipe->draw_mutex); +} + static struct pipe_query * rbug_create_query(struct pipe_context *_pipe, unsigned query_type) @@ -745,6 +760,23 @@ rbug_set_vertex_buffers(struct pipe_context *_pipe, } static void +rbug_set_index_buffer(struct pipe_context *_pipe, + const struct pipe_index_buffer *_ib) +{ + struct rbug_context *rb_pipe = rbug_context(_pipe); + struct pipe_context *pipe = rb_pipe->pipe; + struct pipe_index_buffer unwrapped_ib, *ib = NULL; + + if (_ib) { + unwrapped_ib = *_ib; + unwrapped_ib.buffer = rbug_resource_unwrap(_ib->buffer); + ib = &unwrapped_ib; + } + + pipe->set_index_buffer(pipe, ib); +} + +static void rbug_set_sample_mask(struct pipe_context *_pipe, unsigned sample_mask) { @@ -1043,6 +1075,7 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) rb_pipe->base.draw_arrays = rbug_draw_arrays; rb_pipe->base.draw_elements = rbug_draw_elements; rb_pipe->base.draw_range_elements = rbug_draw_range_elements; + rb_pipe->base.draw_vbo = rbug_draw_vbo; rb_pipe->base.create_query = rbug_create_query; rb_pipe->base.destroy_query = rbug_destroy_query; rb_pipe->base.begin_query = rbug_begin_query; @@ -1084,6 +1117,7 @@ rbug_context_create(struct pipe_screen *_screen, struct pipe_context *pipe) rb_pipe->base.set_fragment_sampler_views = rbug_set_fragment_sampler_views; rb_pipe->base.set_vertex_sampler_views = rbug_set_vertex_sampler_views; rb_pipe->base.set_vertex_buffers = rbug_set_vertex_buffers; + rb_pipe->base.set_index_buffer = rbug_set_index_buffer; rb_pipe->base.set_sample_mask = rbug_set_sample_mask; rb_pipe->base.resource_copy_region = rbug_resource_copy_region; rb_pipe->base.clear = rbug_clear; diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index 12ef98aac7..fa1fae6f00 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -282,12 +282,14 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; softpipe->pipe.set_stream_output_buffers = softpipe_set_stream_output_buffers; softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers; + softpipe->pipe.set_index_buffer = softpipe_set_index_buffer; softpipe->pipe.draw_arrays = softpipe_draw_arrays; softpipe->pipe.draw_elements = softpipe_draw_elements; softpipe->pipe.draw_range_elements = softpipe_draw_range_elements; softpipe->pipe.draw_arrays_instanced = softpipe_draw_arrays_instanced; softpipe->pipe.draw_elements_instanced = softpipe_draw_elements_instanced; + softpipe->pipe.draw_vbo = softpipe_draw_vbo; softpipe->pipe.draw_stream_output = softpipe_draw_stream_output; softpipe->pipe.clear = softpipe_clear; diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index 53115a827d..c5f53cfa61 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -82,6 +82,7 @@ struct softpipe_context { struct pipe_sampler_view *geometry_sampler_views[PIPE_MAX_GEOMETRY_SAMPLERS]; struct pipe_viewport_state viewport; struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + struct pipe_index_buffer index_buffer; struct { struct softpipe_resource *buffer[PIPE_MAX_SO_BUFFERS]; int offset[PIPE_MAX_SO_BUFFERS]; diff --git a/src/gallium/drivers/softpipe/sp_draw_arrays.c b/src/gallium/drivers/softpipe/sp_draw_arrays.c index 9e727c9381..2855f55a0e 100644 --- a/src/gallium/drivers/softpipe/sp_draw_arrays.c +++ b/src/gallium/drivers/softpipe/sp_draw_arrays.c @@ -35,6 +35,7 @@ #include "pipe/p_context.h" #include "util/u_inlines.h" #include "util/u_prim.h" +#include "util/u_draw_quad.h" #include "sp_context.h" #include "sp_query.h" @@ -111,27 +112,19 @@ softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode) * When the min/max element indexes aren't known, minIndex should be 0 * and maxIndex should be ~0. */ -static void -softpipe_draw_range_elements_instanced(struct pipe_context *pipe, - struct pipe_resource *indexBuffer, - unsigned indexSize, - int indexBias, - unsigned minIndex, - unsigned maxIndex, - unsigned mode, - unsigned start, - unsigned count, - unsigned startInstance, - unsigned instanceCount) +void +softpipe_draw_vbo(struct pipe_context *pipe, + const struct pipe_draw_info *info) { struct softpipe_context *sp = softpipe_context(pipe); struct draw_context *draw = sp->draw; + void *mapped_indices = NULL; unsigned i; if (!softpipe_check_render_cond(sp)) return; - sp->reduced_api_prim = u_reduced_prim(mode); + sp->reduced_api_prim = u_reduced_prim(info->mode); if (sp->dirty) { softpipe_update_derived(sp); @@ -146,31 +139,27 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe, } /* Map index buffer, if present */ - if (indexBuffer) { - void *mapped_indexes = softpipe_resource(indexBuffer)->data; - draw_set_mapped_element_buffer_range(draw, - indexSize, - indexBias, - minIndex, - maxIndex, - mapped_indexes); - } else { - /* no index/element buffer */ - draw_set_mapped_element_buffer_range(draw, - 0, 0, - start, - start + count - 1, - NULL); + if (info->indexed && sp->index_buffer.buffer) { + mapped_indices = softpipe_resource(sp->index_buffer.buffer)->data; + mapped_indices += sp->index_buffer.offset; } + draw_set_mapped_element_buffer_range(draw, (mapped_indices) ? + sp->index_buffer.index_size : 0, + info->index_bias, + info->min_index, + info->max_index, + mapped_indices); + /* draw! */ - draw_arrays_instanced(draw, mode, start, count, startInstance, instanceCount); + draw_arrays_instanced(draw, info->mode, info->start, info->count, + info->start_instance, info->instance_count); /* unmap vertex/index buffers - will cause draw module to flush */ for (i = 0; i < sp->num_vertex_buffers; i++) { draw_set_mapped_vertex_buffer(draw, i, NULL); } - if (indexBuffer) { + if (mapped_indices) { draw_set_mapped_element_buffer(draw, 0, 0, NULL); } @@ -185,6 +174,49 @@ softpipe_draw_range_elements_instanced(struct pipe_context *pipe, sp->dirty_render_cache = TRUE; } +static void +softpipe_draw_range_elements_instanced(struct pipe_context *pipe, + struct pipe_resource *indexBuffer, + unsigned indexSize, + int indexBias, + unsigned minIndex, + unsigned maxIndex, + unsigned mode, + unsigned start, + unsigned count, + unsigned startInstance, + unsigned instanceCount) +{ + struct softpipe_context *sp = softpipe_context(pipe); + 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.start_instance = startInstance; + info.instance_count = instanceCount; + info.index_bias = indexBias; + info.min_index = minIndex; + info.max_index = maxIndex; + + if (indexBuffer) { + info.indexed = TRUE; + + saved_ib = sp->index_buffer; + ib.buffer = indexBuffer; + ib.offset = 0; + ib.index_size = indexSize; + pipe->set_index_buffer(pipe, &ib); + } + + softpipe_draw_vbo(pipe, &info); + + if (indexBuffer) + pipe->set_index_buffer(pipe, &saved_ib); +} + void softpipe_draw_range_elements(struct pipe_context *pipe, diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 7d6b86dce0..f04b0a5d31 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -221,6 +221,9 @@ void softpipe_set_vertex_buffers(struct pipe_context *, unsigned count, const struct pipe_vertex_buffer *); +void softpipe_set_index_buffer(struct pipe_context *, + const struct pipe_index_buffer *); + void softpipe_update_derived( struct softpipe_context *softpipe ); @@ -260,6 +263,10 @@ softpipe_draw_elements_instanced(struct pipe_context *pipe, unsigned startInstance, unsigned instanceCount); +void +softpipe_draw_vbo(struct pipe_context *pipe, + const struct pipe_draw_info *info); + void softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode); void diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c index 462f4d2655..880a7c7cd2 100644 --- a/src/gallium/drivers/softpipe/sp_state_vertex.c +++ b/src/gallium/drivers/softpipe/sp_state_vertex.c @@ -88,3 +88,17 @@ softpipe_set_vertex_buffers(struct pipe_context *pipe, draw_set_vertex_buffers(softpipe->draw, count, buffers); } + +void +softpipe_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + if (ib) + memcpy(&softpipe->index_buffer, ib, sizeof(softpipe->index_buffer)); + else + memset(&softpipe->index_buffer, 0, sizeof(softpipe->index_buffer)); + + /* TODO make this more like a state */ +} diff --git a/src/gallium/drivers/svga/svga_context.h b/src/gallium/drivers/svga/svga_context.h index 9a46de643f..67a7614c8a 100644 --- a/src/gallium/drivers/svga/svga_context.h +++ b/src/gallium/drivers/svga/svga_context.h @@ -190,6 +190,7 @@ struct svga_state struct svga_vertex_shader *vs; struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS]; + struct pipe_index_buffer ib; struct pipe_resource *cb[PIPE_SHADER_TYPES]; struct pipe_framebuffer_state framebuffer; diff --git a/src/gallium/drivers/svga/svga_pipe_draw.c b/src/gallium/drivers/svga/svga_pipe_draw.c index 58e930d983..fceaa83d70 100644 --- a/src/gallium/drivers/svga/svga_pipe_draw.c +++ b/src/gallium/drivers/svga/svga_pipe_draw.c @@ -248,10 +248,34 @@ svga_draw_arrays( struct pipe_context *pipe, start, count); } +static void +svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) +{ + struct svga_context *svga = svga_context(pipe); + + if (info->indexed && svga->curr.ib.buffer) { + unsigned offset; + + assert(svga->curr.ib.offset % svga->curr.ib.index_size == 0); + offset = svga->curr.ib.offset / svga->curr.ib.index_size; + + svga_draw_range_elements(pipe, svga->curr.ib.buffer, + svga->curr.ib.index_size, info->index_bias, + info->min_index, info->max_index, + info->mode, info->start + offset, info->count); + } + else { + svga_draw_range_elements(pipe, NULL, 0, 0, + info->min_index, info->max_index, + info->mode, info->start, info->count); + } +} + void svga_init_draw_functions( struct svga_context *svga ) { svga->pipe.draw_arrays = svga_draw_arrays; svga->pipe.draw_elements = svga_draw_elements; svga->pipe.draw_range_elements = svga_draw_range_elements; + svga->pipe.draw_vbo = svga_draw_vbo; } diff --git a/src/gallium/drivers/svga/svga_pipe_vertex.c b/src/gallium/drivers/svga/svga_pipe_vertex.c index 23808ad08e..86c79459f3 100644 --- a/src/gallium/drivers/svga/svga_pipe_vertex.c +++ b/src/gallium/drivers/svga/svga_pipe_vertex.c @@ -66,6 +66,24 @@ static void svga_set_vertex_buffers(struct pipe_context *pipe, } +static void svga_set_index_buffer(struct pipe_context *pipe, + const struct pipe_index_buffer *ib) +{ + struct svga_context *svga = svga_context(pipe); + + if (ib) { + pipe_resource_reference(&svga->curr.ib.buffer, ib->buffer); + memcpy(&svga->curr.ib, ib, sizeof(svga->curr.ib)); + } + else { + pipe_resource_reference(&svga->curr.ib.buffer, NULL); + memset(&svga->curr.ib, 0, sizeof(svga->curr.ib)); + } + + /* TODO make this more like a state */ +} + + static void * svga_create_vertex_elements_state(struct pipe_context *pipe, unsigned count, @@ -109,6 +127,7 @@ void svga_cleanup_vertex_state( struct svga_context *svga ) void svga_init_vertex_functions( struct svga_context *svga ) { svga->pipe.set_vertex_buffers = svga_set_vertex_buffers; + svga->pipe.set_index_buffer = svga_set_index_buffer; svga->pipe.create_vertex_elements_state = svga_create_vertex_elements_state; svga->pipe.bind_vertex_elements_state = svga_bind_vertex_elements_state; svga->pipe.delete_vertex_elements_state = svga_delete_vertex_elements_state; diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index 55dd6cf883..91c9bf0999 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -167,6 +167,32 @@ trace_context_draw_range_elements(struct pipe_context *_pipe, } +static INLINE void +trace_context_draw_vbo(struct pipe_context *_pipe, + const struct pipe_draw_info *info) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + + trace_dump_call_begin("pipe_context", "draw_vbo"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(bool, info->indexed); + trace_dump_arg(uint, info->mode); + trace_dump_arg(uint, info->start); + trace_dump_arg(uint, info->count); + trace_dump_arg(uint, info->start_instance); + trace_dump_arg(uint, info->instance_count); + trace_dump_arg(int, info->index_bias); + trace_dump_arg(uint, info->min_index); + trace_dump_arg(uint, info->max_index); + + pipe->draw_vbo(pipe, info); + + trace_dump_call_end(); +} + + static INLINE struct pipe_query * trace_context_create_query(struct pipe_context *_pipe, unsigned query_type) @@ -1045,6 +1071,30 @@ trace_context_set_vertex_buffers(struct pipe_context *_pipe, static INLINE void +trace_context_set_index_buffer(struct pipe_context *_pipe, + const struct pipe_index_buffer *_ib) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + struct pipe_index_buffer unwrapped_ib, *ib = NULL; + + if (_ib) { + unwrapped_ib = *_ib; + unwrapped_ib.buffer = trace_resource_unwrap(tr_ctx, _ib->buffer); + ib = &unwrapped_ib; + } + + trace_dump_call_begin("pipe_context", "set_index_buffer"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(index_buffer, ib); + + pipe->set_index_buffer(pipe, ib); + + trace_dump_call_end(); +} + +static INLINE void trace_context_resource_copy_region(struct pipe_context *_pipe, struct pipe_resource *dst, struct pipe_subresource subdst, @@ -1436,6 +1486,7 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.draw_arrays = trace_context_draw_arrays; tr_ctx->base.draw_elements = trace_context_draw_elements; tr_ctx->base.draw_range_elements = trace_context_draw_range_elements; + tr_ctx->base.draw_vbo = trace_context_draw_vbo; tr_ctx->base.create_query = trace_context_create_query; tr_ctx->base.destroy_query = trace_context_destroy_query; tr_ctx->base.begin_query = trace_context_begin_query; @@ -1477,6 +1528,7 @@ trace_context_create(struct trace_screen *tr_scr, tr_ctx->base.create_sampler_view = trace_create_sampler_view; tr_ctx->base.sampler_view_destroy = trace_sampler_view_destroy; tr_ctx->base.set_vertex_buffers = trace_context_set_vertex_buffers; + tr_ctx->base.set_index_buffer = trace_context_set_index_buffer; tr_ctx->base.resource_copy_region = trace_context_resource_copy_region; tr_ctx->base.clear = trace_context_clear; tr_ctx->base.clear_render_target = trace_context_clear_render_target; diff --git a/src/gallium/drivers/trace/tr_dump_state.c b/src/gallium/drivers/trace/tr_dump_state.c index 1727c2a020..bd9a9bfaf1 100644 --- a/src/gallium/drivers/trace/tr_dump_state.c +++ b/src/gallium/drivers/trace/tr_dump_state.c @@ -533,6 +533,26 @@ void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state) } +void trace_dump_index_buffer(const struct pipe_index_buffer *state) +{ + if (!trace_dumping_enabled_locked()) + return; + + if(!state) { + trace_dump_null(); + return; + } + + trace_dump_struct_begin("pipe_index_buffer"); + + trace_dump_member(uint, state, index_size); + trace_dump_member(uint, state, offset); + trace_dump_member(resource_ptr, state, buffer); + + trace_dump_struct_end(); +} + + void trace_dump_vertex_element(const struct pipe_vertex_element *state) { if (!trace_dumping_enabled_locked()) diff --git a/src/gallium/drivers/trace/tr_dump_state.h b/src/gallium/drivers/trace/tr_dump_state.h index e614e8355e..2e70f4e1c7 100644 --- a/src/gallium/drivers/trace/tr_dump_state.h +++ b/src/gallium/drivers/trace/tr_dump_state.h @@ -75,6 +75,8 @@ void trace_dump_transfer(const struct pipe_transfer *state); void trace_dump_vertex_buffer(const struct pipe_vertex_buffer *state); +void trace_dump_index_buffer(const struct pipe_index_buffer *state); + void trace_dump_vertex_element(const struct pipe_vertex_element *state); |