summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/i965
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/i965
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/i965')
-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
4 files changed, 93 insertions, 33 deletions
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;