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