summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/r300/r300_emit.c19
-rw-r--r--src/gallium/drivers/r300/r300_emit.h6
-rw-r--r--src/gallium/drivers/r300/r300_render.c100
3 files changed, 73 insertions, 52 deletions
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index 232259e21d1..2583b93c484 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -1137,9 +1137,9 @@ void r300_emit_texture_cache_inval(struct r300_context* r300, unsigned size, voi
END_CS;
}
-void r300_emit_buffer_validate(struct r300_context *r300,
- boolean do_validate_vertex_buffers,
- struct pipe_resource *index_buffer)
+boolean r300_emit_buffer_validate(struct r300_context *r300,
+ boolean do_validate_vertex_buffers,
+ struct pipe_resource *index_buffer)
{
struct pipe_framebuffer_state* fb =
(struct pipe_framebuffer_state*)r300->fb_state.state;
@@ -1150,7 +1150,6 @@ void r300_emit_buffer_validate(struct r300_context *r300,
struct pipe_vertex_element *velem = r300->velems->velem;
struct pipe_resource *pbuf;
unsigned i;
- boolean invalid = FALSE;
/* upload buffers first */
if (r300->screen->caps.has_tcl && r300->any_user_vbs) {
@@ -1161,7 +1160,6 @@ void r300_emit_buffer_validate(struct r300_context *r300,
/* Clean out BOs. */
r300->rws->cs_reset_buffers(r300->cs);
-validate:
/* Color buffers... */
for (i = 0; i < fb->nr_cbufs; i++) {
tex = r300_texture(fb->cbufs[i]->texture);
@@ -1208,15 +1206,10 @@ validate:
r300_buffer(index_buffer)->domain, 0);
if (!r300->rws->cs_validate(r300->cs)) {
- r300->context.flush(&r300->context, 0, NULL);
- if (invalid) {
- /* Well, hell. */
- fprintf(stderr, "r300: Stuck in validation loop, gonna quit now.\n");
- abort();
- }
- invalid = TRUE;
- goto validate;
+ return FALSE;
}
+
+ return TRUE;
}
unsigned r300_get_num_dirty_dwords(struct r300_context *r300)
diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h
index bae25256346..278dbcb4c7c 100644
--- a/src/gallium/drivers/r300/r300_emit.h
+++ b/src/gallium/drivers/r300/r300_emit.h
@@ -121,8 +121,8 @@ unsigned r300_get_num_cs_end_dwords(struct r300_context *r300);
/* Emit all dirty state. */
void r300_emit_dirty_state(struct r300_context* r300);
-void r300_emit_buffer_validate(struct r300_context *r300,
- boolean do_validate_vertex_buffers,
- struct pipe_resource *index_buffer);
+boolean r300_emit_buffer_validate(struct r300_context *r300,
+ boolean do_validate_vertex_buffers,
+ struct pipe_resource *index_buffer);
#endif /* R300_EMIT_H */
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index dd2442a801a..aa45ee3abfd 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -187,12 +187,12 @@ enum r300_prepare_flags {
* \param aos_offset The offset passed to emit_aos.
* \param index_bias The index bias to emit.
*/
-static void r300_prepare_for_rendering(struct r300_context *r300,
- enum r300_prepare_flags flags,
- struct pipe_resource *index_buffer,
- unsigned cs_dwords,
- int aos_offset,
- int index_bias)
+static boolean r300_prepare_for_rendering(struct r300_context *r300,
+ enum r300_prepare_flags flags,
+ struct pipe_resource *index_buffer,
+ unsigned cs_dwords,
+ int aos_offset,
+ int index_bias)
{
boolean flushed = FALSE;
boolean first_draw = flags & PREP_FIRST_DRAW;
@@ -225,7 +225,13 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
/* Validate buffers and emit dirty state if needed. */
if (first_draw || flushed) {
- r300_emit_buffer_validate(r300, flags & PREP_VALIDATE_VBOS, index_buffer);
+ if (!r300_emit_buffer_validate(r300, flags & PREP_VALIDATE_VBOS,
+ index_buffer)) {
+ fprintf(stderr, "r300: CS space validation failed. "
+ "(not enough memory?) Skipping rendering.\n");
+ return FALSE;
+ }
+
r300_emit_dirty_state(r300);
if (hw_index_bias) {
if (r300->screen->caps.has_tcl)
@@ -240,6 +246,8 @@ static void r300_prepare_for_rendering(struct r300_context *r300,
if (emit_aos_swtcl)
r300_emit_aos_swtcl(r300, indexed);
}
+
+ return TRUE;
}
static boolean immd_is_good_idea(struct r300_context *r300,
@@ -300,11 +308,14 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
struct pipe_vertex_element* velem;
struct pipe_vertex_buffer* vbuf;
unsigned vertex_element_count = r300->velems->count;
- unsigned i, v, vbi, dwords;
+ unsigned i, v, vbi;
/* Size of the vertex, in dwords. */
unsigned vertex_size = r300->velems->vertex_size_dwords;
+ /* The number of dwords for this draw operation. */
+ unsigned dwords = 9 + count * vertex_size;
+
/* Size of the vertex element, in dwords. */
unsigned size[PIPE_MAX_ATTRIBS];
@@ -319,6 +330,9 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
CS_LOCALS(r300);
+ if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0))
+ return;
+
/* Calculate the vertex size, offsets, strides etc. and map the buffers. */
for (i = 0; i < vertex_element_count; i++) {
velem = &r300->velems->velem[i];
@@ -338,10 +352,6 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
mapelem[i] = map[vbi] + (velem->src_offset / 4);
}
- dwords = 9 + count * vertex_size;
-
- 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, mode));
@@ -517,10 +527,12 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count, &new_offset);
start = new_offset;
- /* 15 dwords for emit_draw_elements */
- r300_prepare_for_rendering(r300,
- PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED,
- indexBuffer, 15, buffer_offset, indexBias);
+
+ /* 15 dwords for emit_draw_elements. Give up if the function fails. */
+ if (!r300_prepare_for_rendering(r300,
+ PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS |
+ PREP_INDEXED, indexBuffer, 15, buffer_offset, indexBias))
+ goto done;
if (alt_num_verts || count <= 65535) {
r300_emit_draw_elements(r300, indexBuffer, indexSize,
@@ -537,13 +549,15 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
/* 15 dwords for emit_draw_elements */
if (count) {
- r300_prepare_for_rendering(r300,
- PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED,
- indexBuffer, 15, buffer_offset, indexBias);
+ if (!r300_prepare_for_rendering(r300,
+ PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED,
+ indexBuffer, 15, buffer_offset, indexBias))
+ goto done;
}
} while (count);
}
+done:
if (indexBuffer != orgIndexBuffer) {
pipe_resource_reference( &indexBuffer, NULL );
}
@@ -582,9 +596,11 @@ static 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 {
- /* 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);
+ /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */
+ if (!r300_prepare_for_rendering(r300,
+ PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS,
+ NULL, 9, start, 0))
+ goto done;
if (alt_num_verts || count <= 65535) {
r300_emit_draw_arrays(r300, mode, count);
@@ -596,16 +612,18 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
start += short_count;
count -= short_count;
- /* 9 spare dwords for emit_draw_arrays. */
+ /* 9 spare dwords for emit_draw_arrays. Give up if the function fails. */
if (count) {
- r300_prepare_for_rendering(r300,
- PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9,
- start, 0);
+ if (!r300_prepare_for_rendering(r300,
+ PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9,
+ start, 0))
+ goto done;
}
} while (count);
}
}
+done:
if (translate) {
r300_end_vertex_translate(r300);
}
@@ -833,8 +851,10 @@ static void r300_render_draw_arrays(struct vbuf_render* render,
CS_LOCALS(r300);
(void) i; (void) ptr;
- r300_prepare_for_rendering(r300, PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL,
- NULL, dwords, 0, 0);
+ if (!r300_prepare_for_rendering(r300,
+ PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL,
+ NULL, dwords, 0, 0))
+ return;
DBG(r300, DBG_DRAW, "r300: render_draw_arrays (count: %d)\n", count);
@@ -885,9 +905,11 @@ static void r300_render_draw_elements(struct vbuf_render* render,
*
* Below we manage the CS space manually because there may be more
* indices than it can fit in CS. */
- r300_prepare_for_rendering(r300,
- PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED,
- NULL, 256, 0, 0);
+ if (!r300_prepare_for_rendering(r300,
+ PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED,
+ NULL, 256, 0, 0))
+ return;
+
end_cs_dwords = r300_get_num_cs_end_dwords(r300);
while (count) {
@@ -916,9 +938,11 @@ static void r300_render_draw_elements(struct vbuf_render* render,
count -= short_count;
if (count) {
- r300_prepare_for_rendering(r300,
- PREP_EMIT_AOS_SWTCL | PREP_INDEXED,
- NULL, 256, 0, 0);
+ if (!r300_prepare_for_rendering(r300,
+ PREP_EMIT_AOS_SWTCL | PREP_INDEXED,
+ NULL, 256, 0, 0))
+ return;
+
end_cs_dwords = r300_get_num_cs_end_dwords(r300);
}
}
@@ -987,7 +1011,9 @@ void r300_draw_flush_vbuf(struct r300_context *r300)
* End of SW TCL functions *
***************************************************************************/
-/* If we used a quad to draw a rectangle, the pixels on the main diagonal
+/* This functions is used to draw a rectangle for the blitter module.
+ *
+ * If we rendered a quad, the pixels on the main diagonal
* would be computed and stored twice, which makes the clear/copy codepaths
* somewhat inefficient. Instead we use a rectangular point sprite. */
static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
@@ -1017,7 +1043,8 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
r300->clip_state.dirty = FALSE;
r300->viewport_state.dirty = FALSE;
- r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0);
+ if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0))
+ goto done;
DBG(r300, DBG_DRAW, "r300: draw_rectangle\n");
@@ -1061,6 +1088,7 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter,
}
END_CS;
+done:
/* Restore the state. */
r300->clip_state.dirty = TRUE;
r300->rs_state.dirty = TRUE;