diff options
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 19 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.h | 6 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_render.c | 100 |
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; |