summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/r300/r300_render.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r300/r300_render.c')
-rw-r--r--src/gallium/drivers/r300/r300_render.c257
1 files changed, 158 insertions, 99 deletions
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 7c3a7902a4..e1f61982be 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -114,16 +114,79 @@ static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300,
return color_control;
}
+static void r500_emit_index_offset(struct r300_context *r300, int index_bias)
+{
+ CS_LOCALS(r300);
+
+ if (r300->screen->caps.is_r500 &&
+ r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) {
+ BEGIN_CS(2);
+ OUT_CS_REG(R500_VAP_INDEX_OFFSET,
+ (index_bias & 0xFFFFFF) | (index_bias < 0 ? 1<<24 : 0));
+ END_CS;
+ } else {
+ if (index_bias) {
+ fprintf(stderr, "r300: Non-zero index bias is unsupported "
+ "on this hardware.\n");
+ assert(0);
+ }
+ }
+}
+
+enum r300_prepare_flags {
+ PREP_FIRST_DRAW = (1 << 0),
+ PREP_VALIDATE_VBOS = (1 << 1),
+ PREP_EMIT_AOS = (1 << 2),
+ PREP_INDEXED = (1 << 3)
+};
+
/* Check if the requested number of dwords is available in the CS and
- * if not, flush. Return TRUE if the flush occured. */
-static boolean r300_reserve_cs_space(struct r300_context *r300,
- unsigned dwords)
+ * if not, flush. Then validate buffers and emit dirty state.
+ * Return TRUE if flush occured. */
+static void r300_prepare_for_rendering(struct r300_context *r300,
+ enum r300_prepare_flags flags,
+ struct pipe_resource *index_buffer,
+ unsigned cs_dwords,
+ unsigned aos_offset,
+ int index_bias)
{
- if (!r300->rws->check_cs(r300->rws, dwords)) {
+ boolean flushed = FALSE;
+ boolean first_draw = flags & PREP_FIRST_DRAW;
+ boolean emit_aos = flags & PREP_EMIT_AOS;
+
+ /* Stencil ref fallback. */
+ if (r300->stencil_ref_bf_fallback) {
+ cs_dwords = cs_dwords * 2 + 10;
+ }
+
+ /* Add dirty state, index offset, and AOS. */
+ if (first_draw) {
+ cs_dwords += r300_get_num_dirty_dwords(r300);
+
+ if (r300->screen->caps.is_r500)
+ cs_dwords += 2; /* emit_index_offset */
+
+ if (emit_aos)
+ cs_dwords += 55; /* emit_aos */
+ }
+
+ /* Emitted in flush. */
+ cs_dwords += 26; /* emit_query_end */
+
+ /* Reserve requested CS space. */
+ if (!r300->rws->check_cs(r300->rws, cs_dwords)) {
r300->context.flush(&r300->context, 0, NULL);
- return TRUE;
+ flushed = TRUE;
+ }
+
+ /* Validate buffers and emit dirty state if needed. */
+ if (first_draw || flushed) {
+ r300_emit_buffer_validate(r300, flags & PREP_VALIDATE_VBOS, index_buffer);
+ r300_emit_dirty_state(r300);
+ r500_emit_index_offset(r300, index_bias);
+ if (emit_aos)
+ r300_emit_aos(r300, aos_offset, flags & PREP_INDEXED);
}
- return FALSE;
}
static boolean immd_is_good_idea(struct r300_context *r300,
@@ -135,7 +198,15 @@ static boolean immd_is_good_idea(struct r300_context *r300,
unsigned vertex_element_count = r300->velems->count;
unsigned i, vbi;
- if (count > 10 || DBG_ON(r300, DBG_NO_IMMD)) {
+ if (DBG_ON(r300, DBG_NO_IMMD)) {
+ return FALSE;
+ }
+
+ if (r300->draw) {
+ return FALSE;
+ }
+
+ if (count > 10) {
return FALSE;
}
@@ -166,24 +237,6 @@ static boolean immd_is_good_idea(struct r300_context *r300,
* after resolving fallback issues (e.g. stencil ref two-sided). *
****************************************************************************/
-static boolean r500_emit_index_offset(struct r300_context *r300, int indexBias)
-{
- CS_LOCALS(r300);
-
- if (r300->screen->caps.is_r500 &&
- r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0)) {
- BEGIN_CS(2);
- OUT_CS_REG(R500_VAP_INDEX_OFFSET,
- (indexBias & 0xFFFFFF) | (indexBias < 0 ? 1<<24 : 0));
- END_CS;
- } else {
- if (indexBias)
- return FALSE; /* Can't do anything :( */
- }
-
- return TRUE;
-}
-
void r500_emit_draw_arrays_immediate(struct r300_context *r300,
unsigned mode,
unsigned start,
@@ -235,11 +288,7 @@ void r500_emit_draw_arrays_immediate(struct r300_context *r300,
dwords = 9 + count * vertex_size;
- r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2 + dwords);
- r300_emit_buffer_validate(r300, FALSE, NULL);
- r300_emit_dirty_state(r300);
-
- r500_emit_index_offset(r300, 0);
+ r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0);
BEGIN_CS(dwords);
OUT_CS_REG(R300_GA_COLOR_CONTROL,
@@ -291,8 +340,6 @@ void r500_emit_draw_arrays(struct r300_context *r300,
return;
}
- r500_emit_index_offset(r300, 0);
-
BEGIN_CS(7 + (alt_num_verts ? 2 : 0));
if (alt_num_verts) {
OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count);
@@ -312,7 +359,6 @@ void r500_emit_draw_arrays(struct r300_context *r300,
void r500_emit_draw_elements(struct r300_context *r300,
struct pipe_resource* indexBuffer,
unsigned indexSize,
- int indexBias,
unsigned minIndex,
unsigned maxIndex,
unsigned mode,
@@ -335,12 +381,6 @@ void r500_emit_draw_elements(struct r300_context *r300,
DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n",
count, minIndex, maxIndex);
- if (!r500_emit_index_offset(r300, indexBias)) {
- fprintf(stderr, "r300: Got a non-zero index bias, "
- "refusing to render.\n");
- return;
- }
-
BEGIN_CS(13 + (alt_num_verts ? 2 : 0));
if (alt_num_verts) {
OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count);
@@ -457,7 +497,6 @@ void r300_emit_draw_arrays(struct r300_context *r300,
void r300_emit_draw_elements(struct r300_context *r300,
struct pipe_resource* indexBuffer,
unsigned indexSize,
- int indexBias,
unsigned minIndex,
unsigned maxIndex,
unsigned mode,
@@ -465,14 +504,14 @@ void r300_emit_draw_elements(struct r300_context *r300,
unsigned count)
{
if (!r300->stencil_ref_bf_fallback) {
- r500_emit_draw_elements(r300, indexBuffer, indexSize, indexBias,
+ r500_emit_draw_elements(r300, indexBuffer, indexSize,
minIndex, maxIndex, mode, start, count);
} else {
r300_begin_stencil_ref_fallback(r300);
- r500_emit_draw_elements(r300, indexBuffer, indexSize, indexBias,
+ r500_emit_draw_elements(r300, indexBuffer, indexSize,
minIndex, maxIndex, mode, start, count);
r300_switch_stencil_ref_side(r300);
- r500_emit_draw_elements(r300, indexBuffer, indexSize, indexBias,
+ r500_emit_draw_elements(r300, indexBuffer, indexSize,
minIndex, maxIndex, mode, start, count);
r300_end_stencil_ref_fallback(r300);
}
@@ -576,36 +615,33 @@ void r300_draw_range_elements(struct pipe_context* pipe,
}
r300_update_derived_state(r300);
-
r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count);
- /* 128 dwords for emit_aos and emit_draw_elements */
- r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128);
- r300_emit_buffer_validate(r300, TRUE, indexBuffer);
- r300_emit_dirty_state(r300);
- r300_emit_aos(r300, 0, TRUE);
+ /* 15 dwords for emit_draw_elements */
+ r300_prepare_for_rendering(r300,
+ PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED,
+ indexBuffer, 15, 0, indexBias);
u_upload_flush(r300->upload_vb);
u_upload_flush(r300->upload_ib);
if (alt_num_verts || count <= 65535) {
- r300->emit_draw_elements(r300, indexBuffer, indexSize, indexBias,
+ r300->emit_draw_elements(r300, indexBuffer, indexSize,
minIndex, maxIndex, mode, start, count);
} else {
do {
short_count = MIN2(count, 65534);
- r300->emit_draw_elements(r300, indexBuffer, indexSize, indexBias,
+ r300->emit_draw_elements(r300, indexBuffer, indexSize,
minIndex, maxIndex,
mode, start, short_count);
start += short_count;
count -= short_count;
- /* 16 spare dwords are enough for emit_draw_elements.
- * Also reserve some space for emit_query_end. */
- if (count && r300_reserve_cs_space(r300, 74)) {
- r300_emit_buffer_validate(r300, TRUE, indexBuffer);
- r300_emit_dirty_state(r300);
- r300_emit_aos(r300, 0, TRUE);
+ /* 15 dwords for emit_draw_elements */
+ if (count) {
+ r300_prepare_for_rendering(r300,
+ PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED,
+ indexBuffer, 15, 0, indexBias);
}
} while (count);
}
@@ -650,30 +686,25 @@ void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
if (immd_is_good_idea(r300, count)) {
r300->emit_draw_arrays_immediate(r300, mode, start, count);
} else {
- /* Make sure there are at least 128 spare dwords in the command buffer.
- * (most of it being consumed by emit_aos) */
- r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 128);
- r300_emit_buffer_validate(r300, TRUE, NULL);
- r300_emit_dirty_state(r300);
+ /* 9 spare dwords for emit_draw_arrays. */
+ r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS,
+ NULL, 9, start, 0);
if (alt_num_verts || count <= 65535) {
- r300_emit_aos(r300, start, FALSE);
r300->emit_draw_arrays(r300, mode, count);
} else {
do {
short_count = MIN2(count, 65535);
- r300_emit_aos(r300, start, FALSE);
r300->emit_draw_arrays(r300, mode, short_count);
start += short_count;
count -= short_count;
- /* Again, we emit both AOS and draw_arrays so there should be
- * at least 128 spare dwords.
- * Also reserve some space for emit_query_end. */
- if (count && r300_reserve_cs_space(r300, 186)) {
- r300_emit_buffer_validate(r300, TRUE, NULL);
- r300_emit_dirty_state(r300);
+ /* 9 spare dwords for emit_draw_arrays. */
+ if (count) {
+ r300_prepare_for_rendering(r300,
+ PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9,
+ start, 0);
}
} while (count);
}
@@ -704,6 +735,8 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe,
return;
}
+ 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,
@@ -716,6 +749,10 @@ void r300_swtcl_draw_arrays(struct pipe_context* pipe,
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);
+
for (i = 0; i < r300->vertex_buffer_count; i++) {
pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
vb_transfer[i]);
@@ -748,6 +785,8 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe,
return;
}
+ 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,
@@ -763,6 +802,10 @@ void r300_swtcl_draw_range_elements(struct pipe_context* pipe,
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);
+
for (i = 0; i < r300->vertex_buffer_count; i++) {
pipe_buffer_unmap(pipe, r300->vertex_buffer[i].buffer,
vb_transfer[i]);
@@ -796,7 +839,7 @@ struct r300_render {
size_t vbo_max_used;
void * vbo_ptr;
- struct pipe_transfer *vbo_transfer;
+ struct pipe_transfer *vbo_transfer;
};
static INLINE struct r300_render*
@@ -811,8 +854,6 @@ r300_render_get_vertex_info(struct vbuf_render* render)
struct r300_render* r300render = r300_render(render);
struct r300_context* r300 = r300render->r300;
- r300_update_derived_state(r300);
-
return &r300->vertex_info;
}
@@ -860,10 +901,6 @@ static void r300_render_unmap_vertices(struct vbuf_render* render,
{
struct r300_render* r300render = r300_render(render);
struct pipe_context* context = &r300render->r300->context;
- CS_LOCALS(r300render->r300);
- BEGIN_CS(2);
- OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max);
- END_CS;
r300render->vbo_max_used = MAX2(r300render->vbo_max_used,
r300render->vertex_size * (max + 1));
@@ -895,42 +932,64 @@ static void r500_render_draw_arrays(struct vbuf_render* render,
{
struct r300_render* r300render = r300_render(render);
struct r300_context* r300 = r300render->r300;
+ uint8_t* ptr;
+ unsigned i;
+ unsigned dwords = 6;
CS_LOCALS(r300);
- r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + 2);
- r300_emit_buffer_validate(r300, FALSE, NULL);
- r300_emit_dirty_state(r300);
+ (void) i; (void) ptr;
+
+ r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0);
DBG(r300, DBG_DRAW, "r300: Doing vbuf render, count %d\n", count);
- r500_emit_index_offset(r300, 0);
+ /* Uncomment to dump all VBOs rendered through this interface.
+ * Slow and noisy!
+ ptr = pipe_buffer_map(&r300render->r300->context,
+ r300render->vbo, PIPE_TRANSFER_READ,
+ &r300render->vbo_transfer);
- BEGIN_CS(2);
+ for (i = 0; i < count; i++) {
+ printf("r300: Vertex %d\n", i);
+ draw_dump_emitted_vertex(&r300->vertex_info, ptr);
+ ptr += r300->vertex_info.size * 4;
+ printf("\n");
+ }
+
+ pipe_buffer_unmap(&r300render->r300->context, r300render->vbo,
+ r300render->vbo_transfer);
+ */
+
+ BEGIN_CS(dwords);
+ OUT_CS_REG(R300_GA_COLOR_CONTROL,
+ r300_provoking_vertex_fixes(r300, r300render->prim));
+ OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count - 1);
OUT_CS_PKT3(R300_PACKET3_3D_DRAW_VBUF_2, 0);
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_LIST | (count << 16) |
r300render->hwprim);
END_CS;
}
-static void r500_render_draw(struct vbuf_render* render,
- const ushort* indices,
- uint count)
+static void r500_render_draw_elements(struct vbuf_render* render,
+ const ushort* indices,
+ uint count)
{
struct r300_render* r300render = r300_render(render);
struct r300_context* r300 = r300render->r300;
int i;
- unsigned dwords = 2 + (count+1)/2;
+ unsigned dwords = 6 + (count+1)/2;
+ unsigned max_index = (r300render->vbo_size - r300render->vbo_offset) /
+ (r300render->r300->vertex_info.size * 4) - 1;
CS_LOCALS(r300);
- r300_reserve_cs_space(r300, r300_get_num_dirty_dwords(r300) + dwords);
- r300_emit_buffer_validate(r300, FALSE, NULL);
- r300_emit_dirty_state(r300);
-
- r500_emit_index_offset(r300, 0);
+ r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0);
BEGIN_CS(dwords);
+ OUT_CS_REG(R300_GA_COLOR_CONTROL,
+ r300_provoking_vertex_fixes(r300, r300render->prim));
+ OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, max_index);
OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, (count+1)/2);
OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) |
r300render->hwprim);
@@ -960,19 +1019,19 @@ static void r300_render_draw_arrays(struct vbuf_render* render,
}
}
-static void r300_render_draw(struct vbuf_render* render,
- const ushort* indices,
- uint count)
+static void r300_render_draw_elements(struct vbuf_render* render,
+ const ushort* indices,
+ uint count)
{
struct r300_context* r300 = r300_render(render)->r300;
if (!r300->stencil_ref_bf_fallback) {
- r500_render_draw(render, indices, count);
+ r500_render_draw_elements(render, indices, count);
} else {
r300_begin_stencil_ref_fallback(r300);
- r500_render_draw(render, indices, count);
+ r500_render_draw_elements(render, indices, count);
r300_switch_stencil_ref_side(r300);
- r500_render_draw(render, indices, count);
+ r500_render_draw_elements(render, indices, count);
r300_end_stencil_ref_fallback(r300);
}
}
@@ -998,10 +1057,10 @@ static struct vbuf_render* r300_render_create(struct r300_context* r300)
r300render->base.unmap_vertices = r300_render_unmap_vertices;
r300render->base.set_primitive = r300_render_set_primitive;
if (r300->screen->caps.is_r500) {
- r300render->base.draw = r500_render_draw;
+ r300render->base.draw_elements = r500_render_draw_elements;
r300render->base.draw_arrays = r500_render_draw_arrays;
} else {
- r300render->base.draw = r300_render_draw;
+ r300render->base.draw_elements = r300_render_draw_elements;
r300render->base.draw_arrays = r300_render_draw_arrays;
}
r300render->base.release_vertices = r300_render_release_vertices;