diff options
Diffstat (limited to 'src/gallium/drivers/r300/r300_render.c')
-rw-r--r-- | src/gallium/drivers/r300/r300_render.c | 153 |
1 files changed, 114 insertions, 39 deletions
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 62e1456ed3..a4ac9ad9a7 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -37,7 +37,6 @@ #include "r300_reg.h" #include "r300_render.h" #include "r300_state_derived.h" -#include "r300_vbo.h" /* r300_render: Vertex and index buffer primitive emission. */ #define R300_MAX_VBO_SIZE (1024 * 1024) @@ -70,14 +69,67 @@ uint32_t r300_translate_primitive(unsigned prim) } } +static boolean r300_nothing_to_draw(struct r300_context *r300) +{ + return r300->rs_state->rs.scissor && + r300->scissor_state->scissor.empty_area; +} + +static uint32_t r300_provoking_vertex_fixes(struct r300_context *r300, + unsigned mode) +{ + uint32_t color_control = r300->rs_state->color_control; + + /* By default (see r300_state.c:r300_create_rs_state) color_control is + * initialized to provoking the first vertex. + * + * Triangle fans must be reduced to the second vertex, not the first, in + * Gallium flatshade-first mode, as per the GL spec. + * (http://www.opengl.org/registry/specs/ARB/provoking_vertex.txt) + * + * Quads never provoke correctly in flatshade-first mode. The first + * vertex is never considered as provoking, so only the second, third, + * and fourth vertices can be selected, and both "third" and "last" modes + * select the fourth vertex. This is probably due to D3D lacking quads. + * + * Similarly, polygons reduce to the first, not the last, vertex, when in + * "last" mode, and all other modes start from the second vertex. + * + * ~ C. + */ + + if (r300->rs_state->rs.flatshade_first) { + switch (mode) { + case PIPE_PRIM_TRIANGLE_FAN: + color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_SECOND; + break; + case PIPE_PRIM_QUADS: + case PIPE_PRIM_QUAD_STRIP: + case PIPE_PRIM_POLYGON: + color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; + break; + default: + color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_FIRST; + break; + } + } else { + color_control |= R300_GA_COLOR_CONTROL_PROVOKING_VERTEX_LAST; + } + + return color_control; +} + static void r300_emit_draw_arrays(struct r300_context *r300, unsigned mode, unsigned count) { CS_LOCALS(r300); - BEGIN_CS(4); - OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, count); + BEGIN_CS(8); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, mode)); + OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, 0); + 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) | r300_translate_primitive(mode)); @@ -102,7 +154,10 @@ static void r300_emit_draw_elements(struct r300_context *r300, assert((start * indexSize) % 4 == 0); assert(offset_dwords == 0); - BEGIN_CS(10); + BEGIN_CS(14); + OUT_CS_REG(R300_GA_COLOR_CONTROL, + r300_provoking_vertex_fixes(r300, mode)); + OUT_CS_REG(R300_VAP_VF_MIN_VTX_INDX, minIndex); OUT_CS_REG(R300_VAP_VF_MAX_VTX_INDX, maxIndex); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); if (indexSize == 4) { @@ -158,7 +213,7 @@ validate: } /* This is the fast-path drawing & emission for HW TCL. */ -boolean r300_draw_range_elements(struct pipe_context* pipe, +void r300_draw_range_elements(struct pipe_context* pipe, struct pipe_buffer* indexBuffer, unsigned indexSize, unsigned minIndex, @@ -170,22 +225,34 @@ boolean r300_draw_range_elements(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); if (!u_trim_pipe_prim(mode, &count)) { - return FALSE; + return; } if (count > 65535) { - return FALSE; + /* XXX: use aux/indices functions to split this into smaller + * primitives. + */ + return; + } + + if (r300_nothing_to_draw(r300)) { + return; } r300_update_derived_state(r300); if (!r300_setup_vertex_buffers(r300)) { - return FALSE; + return; } - setup_vertex_attributes(r300); + if (!r300->winsys->add_buffer(r300->winsys, indexBuffer, + RADEON_GEM_DOMAIN_GTT, 0)) { + return; + } - setup_index_buffer(r300, indexBuffer, indexSize); + if (!r300->winsys->validate(r300->winsys)) { + return; + } r300_emit_dirty_state(r300); @@ -193,48 +260,49 @@ boolean r300_draw_range_elements(struct pipe_context* pipe, r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count); - - return TRUE; } /* Simple helpers for context setup. Should probably be moved to util. */ -boolean r300_draw_elements(struct pipe_context* pipe, - struct pipe_buffer* indexBuffer, - unsigned indexSize, unsigned mode, - unsigned start, unsigned count) +void r300_draw_elements(struct pipe_context* pipe, + struct pipe_buffer* indexBuffer, + unsigned indexSize, unsigned mode, + unsigned start, unsigned count) { - return pipe->draw_range_elements(pipe, indexBuffer, indexSize, 0, ~0, - mode, start, count); + pipe->draw_range_elements(pipe, indexBuffer, indexSize, 0, ~0, + mode, start, count); } -boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode, +void r300_draw_arrays(struct pipe_context* pipe, unsigned mode, unsigned start, unsigned count) { struct r300_context* r300 = r300_context(pipe); if (!u_trim_pipe_prim(mode, &count)) { - return FALSE; + return; } if (count > 65535) { - return FALSE; + /* XXX: driver needs to handle this -- use the functions in + * aux/indices to split this into several smaller primitives. + */ + return; + } + + if (r300_nothing_to_draw(r300)) { + return; } r300_update_derived_state(r300); if (!r300_setup_vertex_buffers(r300)) { - return FALSE; + return; } - setup_vertex_attributes(r300); - r300_emit_dirty_state(r300); r300_emit_aos(r300, start); r300_emit_draw_arrays(r300, mode, count); - - return TRUE; } /**************************************************************************** @@ -243,7 +311,7 @@ boolean r300_draw_arrays(struct pipe_context* pipe, unsigned mode, ***************************************************************************/ /* SW TCL arrays, using Draw. */ -boolean r300_swtcl_draw_arrays(struct pipe_context* pipe, +void r300_swtcl_draw_arrays(struct pipe_context* pipe, unsigned mode, unsigned start, unsigned count) @@ -252,7 +320,11 @@ boolean r300_swtcl_draw_arrays(struct pipe_context* pipe, int i; if (!u_trim_pipe_prim(mode, &count)) { - return FALSE; + return; + } + + if (r300_nothing_to_draw(r300)) { + return; } for (i = 0; i < r300->vertex_buffer_count; i++) { @@ -265,8 +337,9 @@ boolean r300_swtcl_draw_arrays(struct pipe_context* pipe, draw_set_mapped_element_buffer(r300->draw, 0, NULL); draw_set_mapped_constant_buffer(r300->draw, - r300->shader_constants[PIPE_SHADER_VERTEX].constants, - r300->shader_constants[PIPE_SHADER_VERTEX].count * + PIPE_SHADER_VERTEX, + r300->shader_constants[PIPE_SHADER_VERTEX].constants, + r300->shader_constants[PIPE_SHADER_VERTEX].count * (sizeof(float) * 4)); draw_arrays(r300->draw, mode, start, count); @@ -275,12 +348,10 @@ boolean r300_swtcl_draw_arrays(struct pipe_context* pipe, pipe_buffer_unmap(pipe->screen, r300->vertex_buffer[i].buffer); draw_set_mapped_vertex_buffer(r300->draw, i, NULL); } - - return TRUE; } /* SW TCL elements, using Draw. */ -boolean r300_swtcl_draw_range_elements(struct pipe_context* pipe, +void r300_swtcl_draw_range_elements(struct pipe_context* pipe, struct pipe_buffer* indexBuffer, unsigned indexSize, unsigned minIndex, @@ -291,9 +362,14 @@ boolean r300_swtcl_draw_range_elements(struct pipe_context* pipe, { struct r300_context* r300 = r300_context(pipe); int i; + void* indices; if (!u_trim_pipe_prim(mode, &count)) { - return FALSE; + return; + } + + if (r300_nothing_to_draw(r300)) { + return; } for (i = 0; i < r300->vertex_buffer_count; i++) { @@ -303,12 +379,13 @@ boolean r300_swtcl_draw_range_elements(struct pipe_context* pipe, draw_set_mapped_vertex_buffer(r300->draw, i, buf); } - void* indices = pipe_buffer_map(pipe->screen, indexBuffer, - PIPE_BUFFER_USAGE_CPU_READ); + indices = pipe_buffer_map(pipe->screen, indexBuffer, + PIPE_BUFFER_USAGE_CPU_READ); draw_set_mapped_element_buffer_range(r300->draw, indexSize, minIndex, maxIndex, indices); draw_set_mapped_constant_buffer(r300->draw, + PIPE_SHADER_VERTEX, r300->shader_constants[PIPE_SHADER_VERTEX].constants, r300->shader_constants[PIPE_SHADER_VERTEX].count * (sizeof(float) * 4)); @@ -323,8 +400,6 @@ boolean r300_swtcl_draw_range_elements(struct pipe_context* pipe, pipe_buffer_unmap(pipe->screen, indexBuffer); draw_set_mapped_element_buffer_range(r300->draw, 0, start, start + count - 1, NULL); - - return TRUE; } /* Object for rendering using Draw. */ @@ -400,7 +475,7 @@ static void* r300_render_map_vertices(struct vbuf_render* render) r300render->vbo_ptr = pipe_buffer_map(screen, r300render->vbo, PIPE_BUFFER_USAGE_CPU_WRITE); - return (r300render->vbo_ptr + r300render->vbo_offset); + return ((uint8_t*)r300render->vbo_ptr + r300render->vbo_offset); } static void r300_render_unmap_vertices(struct vbuf_render* render, |