diff options
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r-- | src/gallium/drivers/r300/r300_chipset.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_context.c | 20 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_context.h | 8 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 59 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_fs.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_fs.h | 9 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_reg.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_render.c | 124 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen.c | 12 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen_buffer.c | 93 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen_buffer.h | 11 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 38 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_derived.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 7 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_winsys.h | 5 |
16 files changed, 245 insertions, 162 deletions
diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 583e981a4d..2b183f62c5 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -366,7 +366,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) caps->family = CHIP_FAMILY_RV530; caps->num_vert_fpus = 5; caps->is_r500 = TRUE; - /*caps->hiz_ram = RV530_HIZ_LIMIT;*/ + caps->hiz_ram = RV530_HIZ_LIMIT; caps->zmask_ram = PIPE_ZMASK_SIZE; break; diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 67b011a145..7ba8e71055 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -35,7 +35,9 @@ #include "r300_screen_buffer.h" #include "r300_winsys.h" -#include <inttypes.h> +#ifdef HAVE_LLVM +#include "gallivm/lp_bld_init.h" +#endif static void r300_update_num_contexts(struct r300_screen *r300screen, int diff) @@ -103,9 +105,14 @@ static void r300_destroy_context(struct pipe_context* context) if (r300->blitter) util_blitter_destroy(r300->blitter); - if (r300->draw) + if (r300->draw) { draw_destroy(r300->draw); +#ifdef HAVE_LLVM + gallivm_destroy(r300->gallivm); +#endif + } + if (r300->upload_vb) u_upload_destroy(r300->upload_vb); if (r300->upload_ib) @@ -424,7 +431,12 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, if (!r300screen->caps.has_tcl) { /* Create a Draw. This is used for SW TCL. */ +#ifdef HAVE_LLVM + r300->gallivm = gallivm_create(); + r300->draw = draw_create_gallivm(&r300->context, r300->gallivm); +#else r300->draw = draw_create(&r300->context); +#endif if (r300->draw == NULL) goto fail; /* Enable our renderer. */ @@ -458,14 +470,14 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, goto fail; r300->upload_ib = u_upload_create(&r300->context, - 32 * 1024, 16, + 64 * 1024, 16, PIPE_BIND_INDEX_BUFFER); if (r300->upload_ib == NULL) goto fail; r300->upload_vb = u_upload_create(&r300->context, - 128 * 1024, 16, + 1024 * 1024, 16, PIPE_BIND_VERTEX_BUFFER); if (r300->upload_vb == NULL) goto fail; diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 39dcde0610..f3a3df08bc 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -459,6 +459,7 @@ struct r300_context { struct r300_screen *screen; /* Draw module. Used mostly for SW TCL. */ + struct gallivm_state *gallivm; struct draw_context* draw; /* Vertex buffer for SW TCL. */ struct pipe_resource* vbo; @@ -612,8 +613,8 @@ struct r300_context { int vs_const_base; /* AOS (PACKET3_3D_LOAD_VBPNTR) command buffer for the case offset=0. */ - uint32_t aos_cb[(16 * 3 + 1) / 2]; - boolean aos_dirty; + uint32_t vertex_arrays_cb[(16 * 3 + 1) / 2]; + boolean vertex_arrays_dirty; /* Whether any buffer (FB, textures, VBOs) has been set, but buffers * haven't been validated yet. */ @@ -697,7 +698,8 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias); enum r300_fb_state_change { R300_CHANGED_FB_STATE = 0, R300_CHANGED_CBZB_FLAG, - R300_CHANGED_ZCLEAR_FLAG + R300_CHANGED_ZCLEAR_FLAG, + R300_CHANGED_MULTIWRITE }; void r300_mark_fb_state_dirty(struct r300_context *r300, diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index 04a5bd92d1..e1a3714aac 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -26,7 +26,6 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_mm.h" -#include "util/u_simple_list.h" #include "r300_context.h" #include "r300_cb.h" @@ -370,6 +369,8 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) struct r300_surface* surf; unsigned i; boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ); + uint32_t rb3d_cctl = 0; + CS_LOCALS(r300); BEGIN_CS(size); @@ -377,11 +378,13 @@ void r300_emit_fb_state(struct r300_context* r300, unsigned size, void* state) /* NUM_MULTIWRITES replicates COLOR[0] to all colorbuffers, which is not * what we usually want. */ if (r300->screen->caps.is_r500) { - OUT_CS_REG(R300_RB3D_CCTL, - R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE); - } else { - OUT_CS_REG(R300_RB3D_CCTL, 0); + rb3d_cctl = R300_RB3D_CCTL_INDEPENDENT_COLORFORMAT_ENABLE_ENABLE; } + if (r300_fragment_shader_writes_all(r300_fs(r300))) { + rb3d_cctl |= R300_RB3D_CCTL_NUM_MULTIWRITES(fb->nr_cbufs); + } + + OUT_CS_REG(R300_RB3D_CCTL, rb3d_cctl); /* Set up colorbuffers. */ for (i = 0; i < fb->nr_cbufs; i++) { @@ -483,15 +486,21 @@ void r300_emit_fb_state_pipelined(struct r300_context *r300, { struct pipe_framebuffer_state* fb = (struct pipe_framebuffer_state*)r300->fb_state.state; - unsigned i; + unsigned i, num_cbufs = fb->nr_cbufs; CS_LOCALS(r300); + /* If we use the multiwrite feature, the colorbuffers 2,3,4 must be + * marked as UNUSED in the US block. */ + if (r300_fragment_shader_writes_all(r300_fs(r300))) { + num_cbufs = MIN2(num_cbufs, 1); + } + BEGIN_CS(size); /* Colorbuffer format in the US block. * (must be written after unpipelined regs) */ OUT_CS_REG_SEQ(R300_US_OUT_FMT_0, 4); - for (i = 0; i < fb->nr_cbufs; i++) { + for (i = 0; i < num_cbufs; i++) { OUT_CS(r300_surface(fb->cbufs[i])->format); } for (; i < 4; i++) { @@ -807,17 +816,17 @@ void r300_emit_textures_state(struct r300_context *r300, END_CS; } -static void r300_update_aos_cb(struct r300_context *r300, unsigned packet_size) +static void r300_update_vertex_arrays_cb(struct r300_context *r300, unsigned packet_size) { struct pipe_vertex_buffer *vb1, *vb2, *vbuf = r300->vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; unsigned *hw_format_size = r300->velems->hw_format_size; - unsigned size1, size2, aos_count = r300->velems->count; + unsigned size1, size2, vertex_array_count = r300->velems->count; int i; CB_LOCALS; - BEGIN_CB(r300->aos_cb, packet_size); - for (i = 0; i < aos_count - 1; i += 2) { + BEGIN_CB(r300->vertex_arrays_cb, packet_size); + for (i = 0; i < vertex_array_count - 1; i += 2) { vb1 = &vbuf[velem[i].vertex_buffer_index]; vb2 = &vbuf[velem[i+1].vertex_buffer_index]; size1 = hw_format_size[i]; @@ -829,7 +838,7 @@ static void r300_update_aos_cb(struct r300_context *r300, unsigned packet_size) OUT_CB(vb2->buffer_offset + velem[i+1].src_offset); } - if (aos_count & 1) { + if (vertex_array_count & 1) { vb1 = &vbuf[velem[i].vertex_buffer_index]; size1 = hw_format_size[i]; @@ -838,34 +847,34 @@ static void r300_update_aos_cb(struct r300_context *r300, unsigned packet_size) } END_CB; - r300->aos_dirty = FALSE; + r300->vertex_arrays_dirty = FALSE; } -void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) +void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed) { struct pipe_vertex_buffer *vbuf = r300->vertex_buffer; struct pipe_vertex_element *velem = r300->velems->velem; struct r300_buffer *buf; int i; - unsigned aos_count = r300->velems->count; - unsigned packet_size = (aos_count * 3 + 1) / 2; + unsigned vertex_array_count = r300->velems->count; + unsigned packet_size = (vertex_array_count * 3 + 1) / 2; CS_LOCALS(r300); - BEGIN_CS(2 + packet_size + aos_count * 2); + BEGIN_CS(2 + packet_size + vertex_array_count * 2); OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); - OUT_CS(aos_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); + OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); if (!offset) { - if (r300->aos_dirty) { - r300_update_aos_cb(r300, packet_size); + if (r300->vertex_arrays_dirty) { + r300_update_vertex_arrays_cb(r300, packet_size); } - OUT_CS_TABLE(r300->aos_cb, packet_size); + OUT_CS_TABLE(r300->vertex_arrays_cb, packet_size); } else { struct pipe_vertex_buffer *vb1, *vb2; unsigned *hw_format_size = r300->velems->hw_format_size; unsigned size1, size2; - for (i = 0; i < aos_count - 1; i += 2) { + for (i = 0; i < vertex_array_count - 1; i += 2) { vb1 = &vbuf[velem[i].vertex_buffer_index]; vb2 = &vbuf[velem[i+1].vertex_buffer_index]; size1 = hw_format_size[i]; @@ -877,7 +886,7 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); } - if (aos_count & 1) { + if (vertex_array_count & 1) { vb1 = &vbuf[velem[i].vertex_buffer_index]; size1 = hw_format_size[i]; @@ -886,14 +895,14 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed) } } - for (i = 0; i < aos_count; i++) { + for (i = 0; i < vertex_array_count; i++) { buf = r300_buffer(vbuf[velem[i].vertex_buffer_index].buffer); OUT_CS_BUF_RELOC_NO_OFFSET(&buf->b.b, buf->domain, 0); } END_CS; } -void r300_emit_aos_swtcl(struct r300_context *r300, boolean indexed) +void r300_emit_vertex_arrays_swtcl(struct r300_context *r300, boolean indexed) { CS_LOCALS(r300); diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index 278dbcb4c7..acea51d942 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -31,7 +31,7 @@ struct r300_vertex_program_code; uint32_t pack_float24(float f); -void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed); +void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed); void r300_emit_blend_state(struct r300_context* r300, unsigned size, void* state); @@ -86,7 +86,7 @@ void r300_emit_scissor_state(struct r300_context* r300, void r300_emit_textures_state(struct r300_context *r300, unsigned size, void *state); -void r300_emit_aos_swtcl(struct r300_context *r300, boolean indexed); +void r300_emit_vertex_arrays_swtcl(struct r300_context *r300, boolean indexed); void r300_emit_vap_invariant_state(struct r300_context *r300, unsigned size, void *state); diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index 2936c3486e..6d4091dc87 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -395,6 +395,13 @@ static void r300_translate_fragment_shader( find_output_registers(&compiler, shader); + shader->write_all = FALSE; + for (i = 0; i < shader->info.num_properties; i++) { + if (shader->info.properties[i].name == TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS) { + shader->write_all = TRUE; + } + } + if (compiler.Base.Debug & RC_DBG_LOG) { DBG(r300, DBG_FP, "r300: Initial fragment program\n"); tgsi_dump(tokens, 0); diff --git a/src/gallium/drivers/r300/r300_fs.h b/src/gallium/drivers/r300/r300_fs.h index 51bfa88c5e..c86a90b85a 100644 --- a/src/gallium/drivers/r300/r300_fs.h +++ b/src/gallium/drivers/r300/r300_fs.h @@ -54,6 +54,9 @@ struct r300_fragment_shader_code { uint32_t *cb_code; struct r300_fragment_shader_code* next; + + boolean write_all; + }; struct r300_fragment_shader { @@ -81,4 +84,10 @@ static INLINE boolean r300_fragment_shader_writes_depth(struct r300_fragment_sha return (fs->shader->code.writes_depth) ? TRUE : FALSE; } +static INLINE boolean r300_fragment_shader_writes_all(struct r300_fragment_shader *fs) +{ + if (!fs) + return FALSE; + return (fs->shader->write_all) ? TRUE : FALSE; +} #endif /* R300_FS_H */ diff --git a/src/gallium/drivers/r300/r300_reg.h b/src/gallium/drivers/r300/r300_reg.h index 613186e815..d1154dee40 100644 --- a/src/gallium/drivers/r300/r300_reg.h +++ b/src/gallium/drivers/r300/r300_reg.h @@ -2631,8 +2631,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R300_ZB_BW_CNTL 0x4f1c # define R300_HIZ_DISABLE (0 << 0) # define R300_HIZ_ENABLE (1 << 0) -# define R300_HIZ_MIN (0 << 1) -# define R300_HIZ_MAX (1 << 1) +# define R300_HIZ_MAX (0 << 1) +# define R300_HIZ_MIN (1 << 1) # define R300_FAST_FILL_DISABLE (0 << 2) # define R300_FAST_FILL_ENABLE (1 << 2) # define R300_RD_COMP_DISABLE (0 << 3) diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index f58d511e11..dd3b3c430a 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -130,7 +130,7 @@ void r500_emit_index_bias(struct r300_context *r300, int index_bias) /* This function splits the index bias value into two parts: * - buffer_offset: the value that can be safely added to buffer offsets - * in r300_emit_aos (it must yield a positive offset when added to + * in r300_emit_vertex_arrays (it must yield a positive offset when added to * a vertex buffer offset) * - index_offset: the value that must be manually subtracted from indices * in an index buffer to achieve negative offsets. */ @@ -166,8 +166,8 @@ static void r300_split_index_bias(struct r300_context *r300, int index_bias, enum r300_prepare_flags { PREP_FIRST_DRAW = (1 << 0), /* call emit_dirty_state and friends? */ PREP_VALIDATE_VBOS = (1 << 1), /* validate VBOs? */ - PREP_EMIT_AOS = (1 << 2), /* call emit_aos? */ - PREP_EMIT_AOS_SWTCL = (1 << 3), /* call emit_aos_swtcl? */ + PREP_EMIT_AOS = (1 << 2), /* call emit_vertex_arrays? */ + PREP_EMIT_AOS_SWTCL = (1 << 3), /* call emit_vertex_arrays_swtcl? */ PREP_INDEXED = (1 << 4) /* is this draw_elements? */ }; @@ -185,8 +185,8 @@ static boolean r300_reserve_cs_dwords(struct r300_context *r300, { boolean flushed = FALSE; boolean first_draw = flags & PREP_FIRST_DRAW; - boolean emit_aos = flags & PREP_EMIT_AOS; - boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL; + boolean emit_vertex_arrays = flags & PREP_EMIT_AOS; + boolean emit_vertex_arrays_swtcl = flags & PREP_EMIT_AOS_SWTCL; /* Add dirty state, index offset, and AOS. */ if (first_draw) { @@ -195,11 +195,11 @@ static boolean r300_reserve_cs_dwords(struct r300_context *r300, if (r300->screen->caps.index_bias_supported) cs_dwords += 2; /* emit_index_offset */ - if (emit_aos) - cs_dwords += 55; /* emit_aos */ + if (emit_vertex_arrays) + cs_dwords += 55; /* emit_vertex_arrays */ - if (emit_aos_swtcl) - cs_dwords += 7; /* emit_aos_swtcl */ + if (emit_vertex_arrays_swtcl) + cs_dwords += 7; /* emit_vertex_arrays_swtcl */ } cs_dwords += r300_get_num_cs_end_dwords(r300); @@ -218,19 +218,19 @@ static boolean r300_reserve_cs_dwords(struct r300_context *r300, * \param r300 The context. * \param flags See r300_prepare_flags. * \param index_buffer The index buffer to validate. The parameter may be NULL. - * \param aos_offset The offset passed to emit_aos. + * \param buffer_offset The offset passed to emit_vertex_arrays. * \param index_bias The index bias to emit. * \return TRUE if rendering should be skipped */ static boolean r300_emit_states(struct r300_context *r300, enum r300_prepare_flags flags, struct pipe_resource *index_buffer, - int aos_offset, + int buffer_offset, int index_bias) { boolean first_draw = flags & PREP_FIRST_DRAW; - boolean emit_aos = flags & PREP_EMIT_AOS; - boolean emit_aos_swtcl = flags & PREP_EMIT_AOS_SWTCL; + boolean emit_vertex_arrays = flags & PREP_EMIT_AOS; + boolean emit_vertex_arrays_swtcl = flags & PREP_EMIT_AOS_SWTCL; boolean indexed = flags & PREP_INDEXED; boolean validate_vbos = flags & PREP_VALIDATE_VBOS; @@ -264,11 +264,11 @@ static boolean r300_emit_states(struct r300_context *r300, r500_emit_index_bias(r300, 0); } - if (emit_aos) - r300_emit_aos(r300, aos_offset, indexed); + if (emit_vertex_arrays) + r300_emit_vertex_arrays(r300, buffer_offset, indexed); - if (emit_aos_swtcl) - r300_emit_aos_swtcl(r300, indexed); + if (emit_vertex_arrays_swtcl) + r300_emit_vertex_arrays_swtcl(r300, indexed); } return TRUE; @@ -281,7 +281,7 @@ static boolean r300_emit_states(struct r300_context *r300, * \param flags See r300_prepare_flags. * \param index_buffer The index buffer to validate. The parameter may be NULL. * \param cs_dwords The number of dwords to reserve in CS. - * \param aos_offset The offset passed to emit_aos. + * \param buffer_offset The offset passed to emit_vertex_arrays. * \param index_bias The index bias to emit. * \return TRUE if rendering should be skipped */ @@ -289,13 +289,13 @@ 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 buffer_offset, int index_bias) { if (r300_reserve_cs_dwords(r300, flags, cs_dwords)) flags |= PREP_FIRST_DRAW; - return r300_emit_states(r300, flags, index_buffer, aos_offset, index_bias); + return r300_emit_states(r300, flags, index_buffer, buffer_offset, index_bias); } static boolean immd_is_good_idea(struct r300_context *r300, @@ -467,10 +467,10 @@ static void r300_emit_draw_elements(struct r300_context *r300, unsigned maxIndex, unsigned mode, unsigned start, - unsigned count) + unsigned count, + uint16_t *imm_indices3) { - uint32_t count_dwords; - uint32_t offset_dwords = indexSize * start / sizeof(uint32_t); + uint32_t count_dwords, offset_dwords; boolean alt_num_verts = count > 65535; CS_LOCALS(r300); @@ -485,15 +485,39 @@ static void r300_emit_draw_elements(struct r300_context *r300, DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", count, minIndex, maxIndex); - BEGIN_CS(13 + (alt_num_verts ? 2 : 0)); - if (alt_num_verts) { - OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); - } + BEGIN_CS(5); OUT_CS_REG(R300_GA_COLOR_CONTROL, r300_provoking_vertex_fixes(r300, mode)); OUT_CS_REG_SEQ(R300_VAP_VF_MAX_VTX_INDX, 2); OUT_CS(maxIndex); OUT_CS(minIndex); + END_CS; + + /* If start is odd, render the first triangle with indices embedded + * in the command stream. This will increase start by 3 and make it + * even. We can then proceed without a fallback. */ + if (indexSize == 2 && (start & 1) && + mode == PIPE_PRIM_TRIANGLES) { + BEGIN_CS(4); + OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 2); + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (3 << 16) | + R300_VAP_VF_CNTL__PRIM_TRIANGLES); + OUT_CS(imm_indices3[1] << 16 | imm_indices3[0]); + OUT_CS(imm_indices3[2]); + END_CS; + + start += 3; + count -= 3; + if (!count) + return; + } + + offset_dwords = indexSize * start / sizeof(uint32_t); + + BEGIN_CS(8 + (alt_num_verts ? 2 : 0)); + if (alt_num_verts) { + OUT_CS_REG(R500_VAP_ALT_NUM_VERTICES, count); + } OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, 0); if (indexSize == 4) { count_dwords = count; @@ -541,7 +565,7 @@ static void r300_draw_range_elements(struct pipe_context* pipe, r300->rws->get_value(r300->rws, R300_VID_DRM_2_3_0); unsigned short_count; int buffer_offset = 0, index_offset = 0; /* for index bias emulation */ - unsigned new_offset; + uint16_t indices3[3]; if (indexBias && !r300->screen->caps.index_bias_supported) { r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset); @@ -553,43 +577,48 @@ static void r300_draw_range_elements(struct pipe_context* pipe, r300_update_derived_state(r300); /* Fallback for misaligned ushort indices. */ - if (indexSize == 2 && start % 2 == 1) { + if (indexSize == 2 && (start & 1) && + !r300_buffer_is_user_buffer(indexBuffer)) { struct pipe_transfer *transfer; struct pipe_resource *userbuf; + uint16_t *ptr = pipe_buffer_map(pipe, indexBuffer, PIPE_TRANSFER_READ, &transfer); - /* Copy the mapped index buffer directly to the upload buffer. - * The start index will be aligned simply from the fact that - * every sub-buffer in u_upload_mgr is aligned. */ - userbuf = pipe->screen->user_buffer_create(pipe->screen, - ptr + start, count * 2, - PIPE_BIND_INDEX_BUFFER); - indexBuffer = userbuf; - r300_upload_index_buffer(r300, &indexBuffer, indexSize, 0, count, &new_offset); - pipe_resource_reference(&userbuf, NULL); + if (mode == PIPE_PRIM_TRIANGLES) { + memcpy(indices3, ptr + start, 6); + } else { + /* Copy the mapped index buffer directly to the upload buffer. + * The start index will be aligned simply from the fact that + * every sub-buffer in u_upload_mgr is aligned. */ + userbuf = pipe->screen->user_buffer_create(pipe->screen, + ptr, count * 2, + PIPE_BIND_INDEX_BUFFER); + indexBuffer = userbuf; + r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count); + pipe_resource_reference(&userbuf, NULL); + } pipe_buffer_unmap(pipe, transfer); } else { - r300_upload_index_buffer(r300, &indexBuffer, indexSize, start, count, &new_offset); + if (r300_buffer_is_user_buffer(indexBuffer)) + r300_upload_index_buffer(r300, &indexBuffer, indexSize, &start, count); } - start = new_offset; - - /* 15 dwords for emit_draw_elements. Give up if the function fails. */ + /* 19 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)) + PREP_INDEXED, indexBuffer, 19, buffer_offset, indexBias)) goto done; if (alt_num_verts || count <= 65535) { r300_emit_draw_elements(r300, indexBuffer, indexSize, - minIndex, maxIndex, mode, start, count); + minIndex, maxIndex, mode, start, count, indices3); } else { do { short_count = MIN2(count, 65534); r300_emit_draw_elements(r300, indexBuffer, indexSize, minIndex, maxIndex, - mode, start, short_count); + mode, start, short_count, indices3); start += short_count; count -= short_count; @@ -598,7 +627,7 @@ static void r300_draw_range_elements(struct pipe_context* pipe, if (count) { if (!r300_prepare_for_rendering(r300, PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED, - indexBuffer, 15, buffer_offset, indexBias)) + indexBuffer, 19, buffer_offset, indexBias)) goto done; } } while (count); @@ -1041,8 +1070,7 @@ static struct vbuf_render* r300_render_create(struct r300_context* r300) r300render->r300 = r300; - /* XXX find real numbers plz */ - r300render->base.max_vertex_buffer_bytes = 128 * 1024; + r300render->base.max_vertex_buffer_bytes = 1024 * 1024; r300render->base.max_indices = 16 * 1024; r300render->base.get_vertex_info = r300_render_get_vertex_info; diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 921d6f1e67..c75aeaa10a 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -34,6 +34,10 @@ #include "draw/draw_context.h" +#ifdef HAVE_LLVM +#include "gallivm/lp_bld_init.h" +#endif + /* Return the identifier behind whom the brave coders responsible for this * amalgamation of code, sweat, and duct tape, routinely obscure their names. * @@ -309,7 +313,9 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, unsigned usage, unsigned geom_flags) { + struct r300_winsys_screen *rws = r300_screen(screen)->rws; uint32_t retval = 0; + boolean drm_2_8_0 = rws->get_value(rws, R300_VID_DRM_2_8_0); boolean is_r500 = r300_screen(screen)->caps.is_r500; boolean is_r400 = r300_screen(screen)->caps.is_r400; boolean is_color2101010 = format == PIPE_FORMAT_R10G10B10A2_UNORM || @@ -363,7 +369,7 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, PIPE_BIND_SCANOUT | PIPE_BIND_SHARED)) && /* 2101010 cannot be rendered to on non-r5xx. */ - (is_r500 || !is_color2101010) && + (!is_color2101010 || (is_r500 && drm_2_8_0)) && r300_is_colorbuffer_format_supported(format)) { retval |= usage & (PIPE_BIND_RENDER_TARGET | @@ -484,5 +490,9 @@ struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws) util_format_s3tc_init(); +#ifdef HAVE_LLVM + lp_build_init(); +#endif + return &r300screen->screen; } diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index 4436443522..f96998195a 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -56,72 +56,43 @@ static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context, return r300_buffer_is_referenced(context, buf, R300_REF_CS); } -/* External helper, not required to implent u_resource_vtbl: - */ -int r300_upload_index_buffer(struct r300_context *r300, - struct pipe_resource **index_buffer, - unsigned index_size, - unsigned start, - unsigned count, - unsigned *out_offset) +void r300_upload_index_buffer(struct r300_context *r300, + struct pipe_resource **index_buffer, + unsigned index_size, unsigned *start, + unsigned count) { - struct pipe_resource *upload_buffer = NULL; - unsigned index_offset = start * index_size; - int ret = 0; - - if (r300_buffer_is_user_buffer(*index_buffer)) { - ret = u_upload_buffer(r300->upload_ib, - index_offset, - count * index_size, - *index_buffer, - &index_offset, - &upload_buffer); - if (ret) { - goto done; - } - *index_buffer = upload_buffer; - *out_offset = index_offset / index_size; - } else - *out_offset = start; - - done: - // if (upload_buffer) - // pipe_resource_reference(&upload_buffer, NULL); - return ret; + unsigned index_offset; + uint8_t *ptr = r300_buffer(*index_buffer)->user_buffer; + + *index_buffer = NULL; + + u_upload_data(r300->upload_ib, + count * index_size, + ptr + (*start * index_size), + &index_offset, + index_buffer); + + *start = index_offset / index_size; } -/* External helper, not required to implement u_resource_vtbl: - */ -int r300_upload_user_buffers(struct r300_context *r300) +void r300_upload_user_buffers(struct r300_context *r300) { - enum pipe_error ret = PIPE_OK; - int i, nr; - - nr = r300->velems->count; + int i, nr = r300->velems->count; for (i = 0; i < nr; i++) { struct pipe_vertex_buffer *vb = &r300->vertex_buffer[r300->velems->velem[i].vertex_buffer_index]; if (r300_buffer_is_user_buffer(vb->buffer)) { - struct pipe_resource *upload_buffer = NULL; - unsigned offset = 0; /*vb->buffer_offset * 4;*/ - unsigned size = vb->buffer->width0; - unsigned upload_offset; - ret = u_upload_buffer(r300->upload_vb, - offset, size, - vb->buffer, - &upload_offset, &upload_buffer); - if (ret) - return ret; - - pipe_resource_reference(&vb->buffer, NULL); - vb->buffer = upload_buffer; - vb->buffer_offset = upload_offset; + u_upload_data(r300->upload_vb, + vb->buffer->width0, + r300_buffer(vb->buffer)->user_buffer, + &vb->buffer_offset, &vb->buffer); + r300->validate_buffers = TRUE; + r300->vertex_arrays_dirty = TRUE; } } - return ret; } static void r300_buffer_destroy(struct pipe_screen *screen, @@ -278,26 +249,26 @@ static void r300_buffer_transfer_inline_write(struct pipe_context *pipe, unsigned stride, unsigned layer_stride) { + struct r300_context *r300 = r300_context(pipe); + struct r300_winsys_screen *rws = r300->screen->rws; struct r300_buffer *rbuf = r300_buffer(resource); - struct pipe_transfer *transfer = NULL; uint8_t *map = NULL; if (rbuf->constant_buffer) { memcpy(rbuf->constant_buffer + box->x, data, box->width); return; } + assert(rbuf->user_buffer == NULL); - transfer = r300_buffer_get_transfer(pipe, resource, 0, - PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD, box); - map = r300_buffer_transfer_map(pipe, transfer); + map = rws->buffer_map(rws, rbuf->buf, r300->cs, + PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD | usage); - memcpy(map, data, box->width); + memcpy(map + box->x, data, box->width); - r300_buffer_transfer_unmap(pipe, transfer); - r300_buffer_transfer_destroy(pipe, transfer); + rws->buffer_unmap(rws, rbuf->buf); } -struct u_resource_vtbl r300_buffer_vtbl = +struct u_resource_vtbl r300_buffer_vtbl = { u_default_resource_get_handle, /* get_handle */ r300_buffer_destroy, /* resource_destroy */ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h index 0b3555dd81..fb0033c0f5 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.h +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -63,13 +63,12 @@ struct r300_buffer /* Functions. */ -int r300_upload_user_buffers(struct r300_context *r300); +void r300_upload_user_buffers(struct r300_context *r300); -int r300_upload_index_buffer(struct r300_context *r300, - struct pipe_resource **index_buffer, - unsigned index_size, - unsigned start, - unsigned count, unsigned *out_offset); +void r300_upload_index_buffer(struct r300_context *r300, + struct pipe_resource **index_buffer, + unsigned index_size, unsigned *start, + unsigned count); struct pipe_resource *r300_buffer_create(struct pipe_screen *screen, const struct pipe_resource *templ); diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index f902db54cc..f748fe5997 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -686,13 +686,22 @@ void r300_mark_fb_state_dirty(struct r300_context *r300, struct pipe_framebuffer_state *state = r300->fb_state.state; boolean can_hyperz = r300->rws->get_value(r300->rws, R300_CAN_HYPERZ); - /* What is marked as dirty depends on the enum r300_fb_state_change. */ r300_mark_atom_dirty(r300, &r300->gpu_flush); r300_mark_atom_dirty(r300, &r300->fb_state); - r300_mark_atom_dirty(r300, &r300->hyperz_state); + /* What is marked as dirty depends on the enum r300_fb_state_change. */ if (change == R300_CHANGED_FB_STATE) { r300_mark_atom_dirty(r300, &r300->aa_state); + } + + if (change == R300_CHANGED_FB_STATE || + change == R300_CHANGED_CBZB_FLAG || + change == R300_CHANGED_ZCLEAR_FLAG) { + r300_mark_atom_dirty(r300, &r300->hyperz_state); + } + + if (change == R300_CHANGED_FB_STATE || + change == R300_CHANGED_MULTIWRITE) { r300_mark_atom_dirty(r300, &r300->fb_state_pipelined); } @@ -876,16 +885,25 @@ static void r300_bind_fs_state(struct pipe_context* pipe, void* shader) { struct r300_context* r300 = r300_context(pipe); struct r300_fragment_shader* fs = (struct r300_fragment_shader*)shader; + struct pipe_framebuffer_state *fb = r300->fb_state.state; + boolean last_multi_write; if (fs == NULL) { r300->fs.state = NULL; return; } + last_multi_write = r300_fragment_shader_writes_all(r300_fs(r300)); + r300->fs.state = fs; r300_pick_fragment_shader(r300); r300_mark_fs_code_dirty(r300); + if (fb->nr_cbufs > 1 && + last_multi_write != r300_fragment_shader_writes_all(fs)) { + r300_mark_fb_state_dirty(r300, R300_CHANGED_MULTIWRITE); + } + r300_mark_atom_dirty(r300, &r300->rs_block_state); /* Will be updated before the emission. */ } @@ -1509,7 +1527,7 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, r300->any_user_vbs = any_user_buffer; r300->vertex_buffer_max_index = max_index; - r300->aos_dirty = TRUE; + r300->vertex_arrays_dirty = TRUE; r300->validate_buffers = TRUE; } else { /* SW TCL. */ @@ -1717,7 +1735,7 @@ static void r300_bind_vertex_elements_state(struct pipe_context *pipe, UPDATE_STATE(&velems->vertex_stream, r300->vertex_stream_state); r300->vertex_stream_state.size = (1 + velems->vertex_stream.count) * 2; - r300->aos_dirty = TRUE; + r300->vertex_arrays_dirty = TRUE; } static void r300_delete_vertex_elements_state(struct pipe_context *pipe, void *state) @@ -1809,6 +1827,7 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, { struct r300_context* r300 = r300_context(pipe); struct r300_constant_buffer *cbuf; + struct r300_buffer *rbuf = r300_buffer(buf); uint32_t *mapped; switch (shader) { @@ -1822,10 +1841,15 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, return; } - if (buf == NULL || buf->width0 == 0 || - (mapped = (uint32_t*)r300_buffer(buf)->constant_buffer) == NULL) { + if (buf == NULL || buf->width0 == 0) + return; + + if (rbuf->user_buffer) + mapped = (uint32_t*)rbuf->user_buffer; + else if (rbuf->constant_buffer) + mapped = (uint32_t*)rbuf->constant_buffer; + else return; - } if (shader == PIPE_SHADER_FRAGMENT || (shader == PIPE_SHADER_VERTEX && r300->screen->caps.has_tcl)) { diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index d5fc8ece25..d3985c11aa 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -645,6 +645,10 @@ static uint32_t r300_get_border_color(enum pipe_format format, } switch (desc->channel[0].size) { + case 2: + util_pack_color(border_swizzled, PIPE_FORMAT_B2G3R3_UNORM, &uc); + break; + case 4: util_pack_color(border_swizzled, PIPE_FORMAT_B4G4R4A4_UNORM, &uc); break; diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 6d86bc282f..6fdc504ed5 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -244,6 +244,11 @@ uint32_t r300_translate_texformat(enum pipe_format format, desc->channel[2].size == 6) { return R300_TX_FORMAT_Z6Y5X5 | result; } + if (desc->channel[0].size == 2 && + desc->channel[1].size == 3 && + desc->channel[2].size == 3) { + return R300_TX_FORMAT_Z3Y3X2 | result; + } return ~0; /* Unsupported/unknown. */ case 4: @@ -481,6 +486,8 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format) } else { if (desc->channel[i].size == 16) { modifier |= R300_US_OUT_FMT_C4_16; + } else if (desc->channel[i].size == 10) { + modifier |= R300_US_OUT_FMT_C4_10; } else { /* C4_8 seems to be used for the formats whose pixel size * is <= 32 bits. */ diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 0dd330d101..b8324afe51 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -51,8 +51,9 @@ enum r300_value_id { R300_VID_GB_PIPES, R300_VID_Z_PIPES, R300_VID_SQUARE_TILING_SUPPORT, - R300_VID_DRM_2_3_0, - R300_VID_DRM_2_6_0, + R300_VID_DRM_2_3_0, /* R500 VAP regs, MSPOS regs, fixed tex3D size checking */ + R300_VID_DRM_2_6_0, /* Hyper-Z, GB_Z_PEQ_CONFIG on rv350->r4xx, R500 FG_ALPHA_VALUE */ + R300_VID_DRM_2_8_0, /* R500 US_FORMAT regs, R500 ARGB2101010 colorbuffer */ R300_CAN_HYPERZ, }; |