summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorChia-I Wu <[email protected]>2010-07-16 04:35:58 +0800
committerChia-I Wu <[email protected]>2010-07-29 13:45:30 +0800
commit6d28bf917fb1d741d90fd3f05c22769376021fca (patch)
tree9b8724b30658d61426297113136c2d23c0c62f14 /src/gallium/drivers
parentc5e9d3114a80d6d35a2f4e65783cdc75fcc2deac (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')
-rw-r--r--src/gallium/drivers/cell/ppu/cell_context.h1
-rw-r--r--src/gallium/drivers/cell/ppu/cell_draw_arrays.c69
-rw-r--r--src/gallium/drivers/cell/ppu/cell_state_vertex.c16
-rw-r--r--src/gallium/drivers/failover/fo_context.c61
-rw-r--r--src/gallium/drivers/failover/fo_context.h2
-rw-r--r--src/gallium/drivers/failover/fo_state.c18
-rw-r--r--src/gallium/drivers/failover/fo_state_emit.c5
-rw-r--r--src/gallium/drivers/galahad/glhd_context.c47
-rw-r--r--src/gallium/drivers/i915/i915_context.c70
-rw-r--r--src/gallium/drivers/i915/i915_context.h1
-rw-r--r--src/gallium/drivers/i915/i915_state.c14
-rw-r--r--src/gallium/drivers/i965/brw_context.h1
-rw-r--r--src/gallium/drivers/i965/brw_draw.c87
-rw-r--r--src/gallium/drivers/i965/brw_draw_upload.c7
-rw-r--r--src/gallium/drivers/i965/brw_pipe_vertex.c31
-rw-r--r--src/gallium/drivers/identity/id_context.c30
-rw-r--r--src/gallium/drivers/llvmpipe/lp_context.h1
-rw-r--r--src/gallium/drivers/llvmpipe/lp_draw_arrays.c90
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_vertex.c14
-rw-r--r--src/gallium/drivers/nv50/nv50_context.c1
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h3
-rw-r--r--src/gallium/drivers/nv50/nv50_state.c15
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c31
-rw-r--r--src/gallium/drivers/nvfx/nvfx_context.c1
-rw-r--r--src/gallium/drivers/nvfx/nvfx_context.h5
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state.c15
-rw-r--r--src/gallium/drivers/nvfx/nvfx_vbo.c39
-rw-r--r--src/gallium/drivers/r300/r300_context.h2
-rw-r--r--src/gallium/drivers/r300/r300_render.c142
-rw-r--r--src/gallium/drivers/r300/r300_render_stencilref.c22
-rw-r--r--src/gallium/drivers/r300/r300_state.c18
-rw-r--r--src/gallium/drivers/r600/r600_context.c1
-rw-r--r--src/gallium/drivers/r600/r600_context.h3
-rw-r--r--src/gallium/drivers/r600/r600_draw.c27
-rw-r--r--src/gallium/drivers/r600/r600_state.c18
-rw-r--r--src/gallium/drivers/rbug/rbug_context.c34
-rw-r--r--src/gallium/drivers/softpipe/sp_context.c2
-rw-r--r--src/gallium/drivers/softpipe/sp_context.h1
-rw-r--r--src/gallium/drivers/softpipe/sp_draw_arrays.c92
-rw-r--r--src/gallium/drivers/softpipe/sp_state.h7
-rw-r--r--src/gallium/drivers/softpipe/sp_state_vertex.c14
-rw-r--r--src/gallium/drivers/svga/svga_context.h1
-rw-r--r--src/gallium/drivers/svga/svga_pipe_draw.c24
-rw-r--r--src/gallium/drivers/svga/svga_pipe_vertex.c19
-rw-r--r--src/gallium/drivers/trace/tr_context.c52
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.c20
-rw-r--r--src/gallium/drivers/trace/tr_dump_state.h2
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 dc46e59a2d3..d1aee62ba1e 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 6a1e4d8a646..e06226fbfe3 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 69152b6cbf3..4e3701cd0ac 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 9c9c1bdc452..1048d58313d 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 9d3e0d0dba0..1afa6c9ceed 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 12e42379f98..c265f381b67 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 147f23269ca..7f434ff9d68 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 ab6f17b3ab8..6473f2d499b 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 2af9bdac956..ca07b3e2351 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 b210cb130d0..3ae61d0ea70 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 e767aa9f8f0..385c3b2d2d3 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 94c9c443f05..56d351f97d1 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 4625c2048f9..fa7d047e0bd 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 337eee8cd9c..ebeb1e146aa 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 4a120a51dad..007239efc40 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 67be895b385..e10d3a14130 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 b2643ab33cd..50f9091c3ca 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 625d0c8a8c9..b6dbb9d288e 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 113f13db018..d86e66b4fb8 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 915a9254025..3fc39c11372 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 12c4a93a9bd..a7c2b5d4874 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 42c5a583189..ec0c0ff2838 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 864cb09352a..11ffc182c2d 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 6d2dc4d5bf6..f30795f69af 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 e48f9f3aa88..d6cd272eed5 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 30322d46d93..cd58e439d71 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 520bae5aed2..23a59b589b9 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 b4256c62786..7c77a46016d 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 bae02135da9..da96098cc44 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 9a6b4e12ff1..6d801cf1594 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 3e221f2e02d..bccd7d78591 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 4c7b67ea52c..2c2bd4672be 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 1f03b202eec..9427c19d059 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 b248beaf8c6..eeaa677edbd 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 ff5df855c62..57879e8d8b8 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 e0dd5cf8c2b..c748073b2a2 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 12ef98aac75..fa1fae6f006 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 53115a827d0..c5f53cfa61a 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 9e727c93811..2855f55a0e1 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 7d6b86dce04..f04b0a5d31e 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 462f4d2655e..880a7c7cd26 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 9a46de643fd..67a7614c8af 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 58e930d9835..fceaa83d701 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 23808ad08e0..86c79459f3e 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 55dd6cf8837..91c9bf09999 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 1727c2a0206..bd9a9bfaf16 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 e614e8355e3..2e70f4e1c74 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);