diff options
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r-- | src/gallium/drivers/r300/r300_blit.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_context.c | 10 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_context.h | 14 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.c | 107 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_emit.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_flush.c | 23 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_fs.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_render.c | 259 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_resource.c | 8 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen.c | 53 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen_buffer.c | 16 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_screen_buffer.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state.c | 69 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_state_derived.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture.c | 15 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_texture_desc.c | 6 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_transfer.c | 23 | ||||
-rw-r--r-- | src/gallium/drivers/r300/r300_winsys.h | 13 |
18 files changed, 386 insertions, 248 deletions
diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index 6391ea7f3be..37b635fd120 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -263,7 +263,7 @@ static void r300_clear(struct pipe_context* pipe, /* Reserve CS space. */ if (dwords > (R300_MAX_CMDBUF_DWORDS - r300->cs->cdw)) { - r300->context.flush(&r300->context, 0, NULL); + r300_flush(&r300->context, R300_FLUSH_ASYNC, NULL); } /* Emit clear packets. */ @@ -447,11 +447,11 @@ static void r300_resource_copy_region(struct pipe_context *pipe, !pipe->screen->is_format_supported(pipe->screen, src->format, src->target, src->nr_samples, - PIPE_BIND_SAMPLER_VIEW, 0) || + PIPE_BIND_SAMPLER_VIEW) || !pipe->screen->is_format_supported(pipe->screen, dst->format, dst->target, dst->nr_samples, - PIPE_BIND_RENDER_TARGET, 0))) { + PIPE_BIND_RENDER_TARGET))) { switch (util_format_get_blocksize(old_dst.format)) { case 1: new_dst.format = PIPE_FORMAT_I8_UNORM; diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index b8db6fb6c12..720d666d98c 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -78,10 +78,8 @@ static void r300_release_referenced_objects(struct r300_context *r300) NULL); } - /* The dummy VBO. */ + /* Manually-created vertex buffers. */ pipe_resource_reference(&r300->dummy_vb, NULL); - - /* The SWTCL VBO. */ pipe_resource_reference(&r300->vbo, NULL); /* If there are any queries pending or not destroyed, remove them now. */ @@ -141,11 +139,11 @@ static void r300_destroy_context(struct pipe_context* context) FREE(r300); } -void r300_flush_cb(void *data) +static void r300_flush_callback(void *data, unsigned flags) { struct r300_context* const cs_context_copy = data; - cs_context_copy->context.flush(&cs_context_copy->context, 0, NULL); + r300_flush(&cs_context_copy->context, flags, NULL); } #define R300_INIT_ATOM(atomname, atomsize) \ @@ -455,7 +453,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300_init_render_functions(r300); r300_init_states(&r300->context); - rws->cs_set_flush(r300->cs, r300_flush_cb, r300); + rws->cs_set_flush(r300->cs, r300_flush_callback, r300); /* The KIL opcode needs the first texture unit to be enabled * on r3xx-r4xx. In order to calm down the CS checker, we bind this diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 58e1094e339..e395f41290e 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -65,7 +65,10 @@ struct r300_aa_state { }; struct r300_blend_state { - uint32_t cb[8]; + struct pipe_blend_state state; + + uint32_t cb_clamp[8]; + uint32_t cb_noclamp[8]; uint32_t cb_no_readwrite[8]; }; @@ -610,6 +613,8 @@ struct r300_context { boolean vertex_arrays_dirty; boolean vertex_arrays_indexed; int vertex_arrays_offset; + int vertex_arrays_instance_id; + boolean instancing_enabled; }; #define foreach_atom(r300, atom) \ @@ -663,8 +668,6 @@ static INLINE void r300_mark_atom_dirty(struct r300_context *r300, struct pipe_context* r300_create_context(struct pipe_screen* screen, void *priv); -void r300_flush_cb(void *data); - /* Context initialization. */ struct draw_stage* r300_draw_stage(struct r300_context* r300); void r300_init_blit_functions(struct r300_context *r300); @@ -679,6 +682,11 @@ void r300_decompress_zmask(struct r300_context *r300); void r300_decompress_zmask_locked_unsafe(struct r300_context *r300); void r300_decompress_zmask_locked(struct r300_context *r300); +/* r300_flush.c */ +void r300_flush(struct pipe_context *pipe, + unsigned flags, + struct pipe_fence_handle **fence); + /* r300_hyperz.c */ void r300_update_hyperz_state(struct r300_context* r300); diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c index e3945b72d7a..e17a907e77e 100644 --- a/src/gallium/drivers/r300/r300_emit.c +++ b/src/gallium/drivers/r300/r300_emit.c @@ -45,7 +45,10 @@ void r300_emit_blend_state(struct r300_context* r300, CS_LOCALS(r300); if (fb->nr_cbufs) { - WRITE_CS_TABLE(blend->cb, size); + if (fb->cbufs[0]->format == PIPE_FORMAT_R16G16B16A16_FLOAT) + WRITE_CS_TABLE(blend->cb_noclamp, size); + else + WRITE_CS_TABLE(blend->cb_clamp, size); } else { WRITE_CS_TABLE(blend->cb_no_readwrite, size); } @@ -794,7 +797,8 @@ void r300_emit_textures_state(struct r300_context *r300, END_CS; } -void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed) +void r300_emit_vertex_arrays(struct r300_context* r300, int offset, + boolean indexed, int instance_id) { struct pipe_vertex_buffer *vbuf = r300->vbuf_mgr->vertex_buffer; struct pipe_resource **valid_vbuf = r300->vbuf_mgr->real_vertex_buffer; @@ -804,39 +808,92 @@ void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean inde unsigned vertex_array_count = r300->velems->count; unsigned packet_size = (vertex_array_count * 3 + 1) / 2; struct pipe_vertex_buffer *vb1, *vb2; - unsigned *hw_format_size; - unsigned size1, size2; + unsigned *hw_format_size = r300->velems->format_size; + unsigned size1, size2, offset1, offset2, stride1, stride2; CS_LOCALS(r300); BEGIN_CS(2 + packet_size + vertex_array_count * 2); OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size); OUT_CS(vertex_array_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0)); - hw_format_size = r300->velems->format_size; + if (instance_id == -1) { + /* Non-instanced arrays. This ignores instance_divisor and instance_id. */ + 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]; + size2 = hw_format_size[i+1]; + + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | + R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); + OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); + } - 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]; - size2 = hw_format_size[i+1]; + if (vertex_array_count & 1) { + vb1 = &vbuf[velem[i].vertex_buffer_index]; + size1 = hw_format_size[i]; - OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) | - R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride)); - OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); - OUT_CS(vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride); - } + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); + OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); + } - if (vertex_array_count & 1) { - vb1 = &vbuf[velem[i].vertex_buffer_index]; - size1 = hw_format_size[i]; + for (i = 0; i < vertex_array_count; i++) { + buf = r300_resource(valid_vbuf[velem[i].vertex_buffer_index]); + OUT_CS_RELOC(buf); + } + } else { + /* Instanced arrays. */ + 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]; + size2 = hw_format_size[i+1]; + + if (velem[i].instance_divisor) { + stride1 = 0; + offset1 = vb1->buffer_offset + velem[i].src_offset + + (instance_id / velem[i].instance_divisor) * vb1->stride; + } else { + stride1 = vb1->stride; + offset1 = vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride; + } + if (velem[i+1].instance_divisor) { + stride2 = 0; + offset2 = vb2->buffer_offset + velem[i+1].src_offset + + (instance_id / velem[i+1].instance_divisor) * vb2->stride; + } else { + stride2 = vb2->stride; + offset2 = vb2->buffer_offset + velem[i+1].src_offset + offset * vb2->stride; + } - OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride)); - OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride); - } + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(stride1) | + R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(stride2)); + OUT_CS(offset1); + OUT_CS(offset2); + } + + if (vertex_array_count & 1) { + vb1 = &vbuf[velem[i].vertex_buffer_index]; + size1 = hw_format_size[i]; + + if (velem[i].instance_divisor) { + stride1 = 0; + offset1 = vb1->buffer_offset + velem[i].src_offset + + (instance_id / velem[i].instance_divisor) * vb1->stride; + } else { + stride1 = vb1->stride; + offset1 = vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride; + } - for (i = 0; i < vertex_array_count; i++) { - buf = r300_resource(valid_vbuf[velem[i].vertex_buffer_index]); - OUT_CS_RELOC(buf); + OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(stride1)); + OUT_CS(offset1); + } + + for (i = 0; i < vertex_array_count; i++) { + buf = r300_resource(valid_vbuf[velem[i].vertex_buffer_index]); + OUT_CS_RELOC(buf); + } } END_CS; } @@ -1164,7 +1221,7 @@ validate: if (flushed) return FALSE; - r300->context.flush(&r300->context, 0, NULL); + r300_flush(&r300->context, R300_FLUSH_ASYNC, NULL); flushed = TRUE; goto validate; } diff --git a/src/gallium/drivers/r300/r300_emit.h b/src/gallium/drivers/r300/r300_emit.h index acea51d942f..6c1c9d2fb13 100644 --- a/src/gallium/drivers/r300/r300_emit.h +++ b/src/gallium/drivers/r300/r300_emit.h @@ -31,7 +31,8 @@ struct r300_vertex_program_code; uint32_t pack_float24(float f); -void r300_emit_vertex_arrays(struct r300_context* r300, int offset, boolean indexed); +void r300_emit_vertex_arrays(struct r300_context* r300, int offset, + boolean indexed, int instance_id); void r300_emit_blend_state(struct r300_context* r300, unsigned size, void* state); diff --git a/src/gallium/drivers/r300/r300_flush.c b/src/gallium/drivers/r300/r300_flush.c index 9c41a1383ce..b3d0d344ec4 100644 --- a/src/gallium/drivers/r300/r300_flush.c +++ b/src/gallium/drivers/r300/r300_flush.c @@ -31,9 +31,10 @@ #include "r300_cs.h" #include "r300_emit.h" -static void r300_flush(struct pipe_context* pipe, - unsigned flags, - struct pipe_fence_handle** fence) + +void r300_flush(struct pipe_context *pipe, + unsigned flags, + struct pipe_fence_handle **fence) { struct r300_context *r300 = r300_context(pipe); struct r300_atom *atom; @@ -61,7 +62,7 @@ static void r300_flush(struct pipe_context* pipe, r500_emit_index_bias(r300, 0); r300->flush_counter++; - r300->rws->cs_flush(r300->cs); + r300->rws->cs_flush(r300->cs, flags); r300->dirty_hw = 0; /* New kitchen sink, baby. */ @@ -83,20 +84,22 @@ static void r300_flush(struct pipe_context* pipe, * and we cannot emit an empty CS. We must write some regs then. */ CS_LOCALS(r300); OUT_CS_REG(RB3D_COLOR_CHANNEL_MASK, 0); - r300->rws->cs_flush(r300->cs); + r300->rws->cs_flush(r300->cs, flags); } else { /* Even if hw is not dirty, we should at least reset the CS in case * the space checking failed for the first draw operation. */ - r300->rws->cs_flush(r300->cs); + r300->rws->cs_flush(r300->cs, flags); } } +} - if (flags & PIPE_FLUSH_FRAME) { - r300->rws->cs_sync_flush(r300->cs); - } +static void r300_flush_wrapped(struct pipe_context *pipe, + struct pipe_fence_handle **fence) +{ + r300_flush(pipe, 0, fence); } void r300_init_flush_functions(struct r300_context* r300) { - r300->context.flush = r300_flush; + r300->context.flush = r300_flush_wrapped; } diff --git a/src/gallium/drivers/r300/r300_fs.c b/src/gallium/drivers/r300/r300_fs.c index cec7473009a..4c502fefb3f 100644 --- a/src/gallium/drivers/r300/r300_fs.c +++ b/src/gallium/drivers/r300/r300_fs.c @@ -149,6 +149,8 @@ static void get_external_state( unsigned i; unsigned char *swizzle; + state->frag_clamp = 0; + for (i = 0; i < texstate->sampler_state_count; i++) { struct r300_sampler_state *s = texstate->sampler_states[i]; struct r300_sampler_view *v = texstate->sampler_views[i]; diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 0ec4a225865..26594dabe42 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -177,7 +177,7 @@ 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_EMIT_STATES = (1 << 0), /* call emit_dirty_state and friends? */ PREP_VALIDATE_VBOS = (1 << 1), /* validate VBOs? */ PREP_EMIT_AOS = (1 << 2), /* call emit_vertex_arrays? */ PREP_EMIT_AOS_SWTCL = (1 << 3), /* call emit_vertex_arrays_swtcl? */ @@ -193,11 +193,11 @@ enum r300_prepare_flags { * \return TRUE if the CS was flushed */ static boolean r300_reserve_cs_dwords(struct r300_context *r300, - enum r300_prepare_flags flags, - unsigned cs_dwords) + enum r300_prepare_flags flags, + unsigned cs_dwords) { boolean flushed = FALSE; - boolean first_draw = flags & PREP_FIRST_DRAW; + boolean first_draw = flags & PREP_EMIT_STATES; boolean emit_vertex_arrays = flags & PREP_EMIT_AOS; boolean emit_vertex_arrays_swtcl = flags & PREP_EMIT_AOS_SWTCL; @@ -219,7 +219,7 @@ static boolean r300_reserve_cs_dwords(struct r300_context *r300, /* Reserve requested CS space. */ if (cs_dwords > (R300_MAX_CMDBUF_DWORDS - r300->cs->cdw)) { - r300->context.flush(&r300->context, 0, NULL); + r300_flush(&r300->context, R300_FLUSH_ASYNC, NULL); flushed = TRUE; } @@ -233,15 +233,16 @@ static boolean r300_reserve_cs_dwords(struct r300_context *r300, * \param index_buffer The index buffer to validate. The parameter may be NULL. * \param buffer_offset The offset passed to emit_vertex_arrays. * \param index_bias The index bias to emit. + * \param instance_id Index of instance to render * \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 buffer_offset, - int index_bias) + int index_bias, int instance_id) { - boolean first_draw = flags & PREP_FIRST_DRAW; + boolean first_draw = flags & PREP_EMIT_STATES; boolean emit_vertex_arrays = flags & PREP_EMIT_AOS; boolean emit_vertex_arrays_swtcl = flags & PREP_EMIT_AOS_SWTCL; boolean indexed = flags & PREP_INDEXED; @@ -267,12 +268,14 @@ static boolean r300_emit_states(struct r300_context *r300, if (emit_vertex_arrays && (r300->vertex_arrays_dirty || r300->vertex_arrays_indexed != indexed || - r300->vertex_arrays_offset != buffer_offset)) { - r300_emit_vertex_arrays(r300, buffer_offset, indexed); + r300->vertex_arrays_offset != buffer_offset || + r300->vertex_arrays_instance_id != instance_id)) { + r300_emit_vertex_arrays(r300, buffer_offset, indexed, instance_id); r300->vertex_arrays_dirty = FALSE; r300->vertex_arrays_indexed = indexed; r300->vertex_arrays_offset = buffer_offset; + r300->vertex_arrays_instance_id = instance_id; } if (emit_vertex_arrays_swtcl) @@ -291,6 +294,7 @@ static boolean r300_emit_states(struct r300_context *r300, * \param cs_dwords The number of dwords to reserve in CS. * \param buffer_offset The offset passed to emit_vertex_arrays. * \param index_bias The index bias to emit. + * \param instance_id The instance to render. * \return TRUE if rendering should be skipped */ static boolean r300_prepare_for_rendering(struct r300_context *r300, @@ -298,13 +302,15 @@ static boolean r300_prepare_for_rendering(struct r300_context *r300, struct pipe_resource *index_buffer, unsigned cs_dwords, int buffer_offset, - int index_bias) + int index_bias, + int instance_id) { + /* Make sure there is enough space in the command stream and emit states. */ if (r300_reserve_cs_dwords(r300, flags, cs_dwords)) - flags |= PREP_FIRST_DRAW; + flags |= PREP_EMIT_STATES; return r300_emit_states(r300, flags, index_buffer, buffer_offset, - index_bias); + index_bias, instance_id); } static boolean immd_is_good_idea(struct r300_context *r300, @@ -352,8 +358,7 @@ static boolean immd_is_good_idea(struct r300_context *r300, ****************************************************************************/ static void r300_draw_arrays_immediate(struct r300_context *r300, - unsigned mode, unsigned start, - unsigned count) + const struct pipe_draw_info *info) { struct pipe_vertex_element* velem; struct pipe_vertex_buffer* vbuf; @@ -364,7 +369,7 @@ static void r300_draw_arrays_immediate(struct r300_context *r300, unsigned vertex_size = r300->velems->vertex_size_dwords; /* The number of dwords for this draw operation. */ - unsigned dwords = 4 + count * vertex_size; + unsigned dwords = 4 + info->count * vertex_size; /* Size of the vertex element, in dwords. */ unsigned size[PIPE_MAX_ATTRIBS]; @@ -379,7 +384,7 @@ static void r300_draw_arrays_immediate(struct r300_context *r300, CS_LOCALS(r300); - if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0)) + if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) return; /* Calculate the vertex size, offsets, strides etc. and map the buffers. */ @@ -395,21 +400,21 @@ static void r300_draw_arrays_immediate(struct r300_context *r300, map[vbi] = (uint32_t*)r300->rws->buffer_map( r300_resource(r300->vbuf_mgr->real_vertex_buffer[vbi])->buf, r300->cs, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED); - map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * start; + map[vbi] += (vbuf->buffer_offset / 4) + stride[i] * info->start; } mapelem[i] = map[vbi] + (velem->src_offset / 4); } - r300_emit_draw_init(r300, mode, 0, count-1); + r300_emit_draw_init(r300, info->mode, 0, info->count-1); BEGIN_CS(dwords); OUT_CS_REG(R300_VAP_VTX_SIZE, vertex_size); - OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, count * vertex_size); - OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (count << 16) | - r300_translate_primitive(mode)); + OUT_CS_PKT3(R300_PACKET3_3D_DRAW_IMMD_2, info->count * vertex_size); + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_VERTEX_EMBEDDED | (info->count << 16) | + r300_translate_primitive(info->mode)); /* Emit vertices. */ - for (v = 0; v < count; v++) { + for (v = 0; v < info->count; v++) { for (i = 0; i < vertex_element_count; i++) { OUT_CS_TABLE(&mapelem[i][stride[i] * v], size[i]); } @@ -456,8 +461,8 @@ static void r300_emit_draw_arrays(struct r300_context *r300, static void r300_emit_draw_elements(struct r300_context *r300, struct pipe_resource* indexBuffer, unsigned indexSize, - unsigned minIndex, - unsigned maxIndex, + unsigned min_index, + unsigned max_index, unsigned mode, unsigned start, unsigned count, @@ -467,16 +472,16 @@ static void r300_emit_draw_elements(struct r300_context *r300, boolean alt_num_verts = count > 65535; CS_LOCALS(r300); - if (count >= (1 << 24) || maxIndex >= (1 << 24)) { + if (count >= (1 << 24) || max_index >= (1 << 24)) { fprintf(stderr, "r300: Got a huge number of vertices: %i, " - "refusing to render (maxIndex: %i).\n", count, maxIndex); + "refusing to render (max_index: %i).\n", count, max_index); return; } DBG(r300, DBG_DRAW, "r300: Indexbuf of %u indices, min %u max %u\n", - count, minIndex, maxIndex); + count, min_index, max_index); - r300_emit_draw_init(r300, mode, minIndex, maxIndex); + r300_emit_draw_init(r300, mode, min_index, max_index); /* If start is odd, render the first triangle with indices embedded * in the command stream. This will increase start by 3 and make it @@ -527,24 +532,23 @@ static void r300_emit_draw_elements(struct r300_context *r300, } static void r300_draw_elements_immediate(struct r300_context *r300, - int indexBias, unsigned minIndex, - unsigned maxIndex, unsigned mode, - unsigned start, unsigned count) + const struct pipe_draw_info *info) { uint8_t *ptr1; uint16_t *ptr2; uint32_t *ptr4; unsigned index_size = r300->index_buffer.index_size; - unsigned i, count_dwords = index_size == 4 ? count : (count + 1) / 2; + unsigned i, count_dwords = index_size == 4 ? info->count : + (info->count + 1) / 2; CS_LOCALS(r300); /* 19 dwords for r300_draw_elements_immediate. Give up if the function fails. */ if (!r300_prepare_for_rendering(r300, - PREP_FIRST_DRAW | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | - PREP_INDEXED, NULL, 2+count_dwords, 0, indexBias)) + PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | + PREP_INDEXED, NULL, 2+count_dwords, 0, info->index_bias, -1)) return; - r300_emit_draw_init(r300, mode, minIndex, maxIndex); + r300_emit_draw_init(r300, info->mode, info->min_index, info->max_index); BEGIN_CS(2 + count_dwords); OUT_CS_PKT3(R300_PACKET3_3D_DRAW_INDX_2, count_dwords); @@ -552,42 +556,42 @@ static void r300_draw_elements_immediate(struct r300_context *r300, switch (index_size) { case 1: ptr1 = r300_resource(r300->index_buffer.buffer)->b.user_ptr; - ptr1 += start; + ptr1 += info->start; - OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | - r300_translate_primitive(mode)); + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (info->count << 16) | + r300_translate_primitive(info->mode)); - if (indexBias && !r300->screen->caps.is_r500) { - for (i = 0; i < count-1; i += 2) - OUT_CS(((ptr1[i+1] + indexBias) << 16) | - (ptr1[i] + indexBias)); + if (info->index_bias && !r300->screen->caps.is_r500) { + for (i = 0; i < info->count-1; i += 2) + OUT_CS(((ptr1[i+1] + info->index_bias) << 16) | + (ptr1[i] + info->index_bias)); - if (count & 1) - OUT_CS(ptr1[i] + indexBias); + if (info->count & 1) + OUT_CS(ptr1[i] + info->index_bias); } else { - for (i = 0; i < count-1; i += 2) + for (i = 0; i < info->count-1; i += 2) OUT_CS(((ptr1[i+1]) << 16) | (ptr1[i] )); - if (count & 1) + if (info->count & 1) OUT_CS(ptr1[i]); } break; case 2: ptr2 = (uint16_t*)r300_resource(r300->index_buffer.buffer)->b.user_ptr; - ptr2 += start; + ptr2 += info->start; - OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | - r300_translate_primitive(mode)); + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (info->count << 16) | + r300_translate_primitive(info->mode)); - if (indexBias && !r300->screen->caps.is_r500) { - for (i = 0; i < count-1; i += 2) - OUT_CS(((ptr2[i+1] + indexBias) << 16) | - (ptr2[i] + indexBias)); + if (info->index_bias && !r300->screen->caps.is_r500) { + for (i = 0; i < info->count-1; i += 2) + OUT_CS(((ptr2[i+1] + info->index_bias) << 16) | + (ptr2[i] + info->index_bias)); - if (count & 1) - OUT_CS(ptr2[i] + indexBias); + if (info->count & 1) + OUT_CS(ptr2[i] + info->index_bias); } else { OUT_CS_TABLE(ptr2, count_dwords); } @@ -595,15 +599,15 @@ static void r300_draw_elements_immediate(struct r300_context *r300, case 4: ptr4 = (uint32_t*)r300_resource(r300->index_buffer.buffer)->b.user_ptr; - ptr4 += start; + ptr4 += info->start; - OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (count << 16) | + OUT_CS(R300_VAP_VF_CNTL__PRIM_WALK_INDICES | (info->count << 16) | R300_VAP_VF_CNTL__INDEX_SIZE_32bit | - r300_translate_primitive(mode)); + r300_translate_primitive(info->mode)); - if (indexBias && !r300->screen->caps.is_r500) { - for (i = 0; i < count; i++) - OUT_CS(ptr4[i] + indexBias); + if (info->index_bias && !r300->screen->caps.is_r500) { + for (i = 0; i < info->count; i++) + OUT_CS(ptr4[i] + info->index_bias); } else { OUT_CS_TABLE(ptr4, count_dwords); } @@ -612,21 +616,23 @@ static void r300_draw_elements_immediate(struct r300_context *r300, END_CS; } -static void r300_draw_elements(struct r300_context *r300, int indexBias, - unsigned minIndex, unsigned maxIndex, - unsigned mode, unsigned start, unsigned count) +static void r300_draw_elements(struct r300_context *r300, + const struct pipe_draw_info *info, + int instance_id) { struct pipe_resource *indexBuffer = r300->index_buffer.buffer; unsigned indexSize = r300->index_buffer.index_size; struct pipe_resource* orgIndexBuffer = indexBuffer; + unsigned start = info->start; + unsigned count = info->count; boolean alt_num_verts = r300->screen->caps.is_r500 && count > 65536; unsigned short_count; int buffer_offset = 0, index_offset = 0; /* for index bias emulation */ uint16_t indices3[3]; - if (indexBias && !r300->screen->caps.is_r500) { - r300_split_index_bias(r300, indexBias, &buffer_offset, &index_offset); + if (info->index_bias && !r300->screen->caps.is_r500) { + r300_split_index_bias(r300, info->index_bias, &buffer_offset, &index_offset); } r300_translate_index_buffer(r300, &indexBuffer, &indexSize, index_offset, @@ -641,7 +647,7 @@ static void r300_draw_elements(struct r300_context *r300, int indexBias, PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED); - if (mode == PIPE_PRIM_TRIANGLES) { + if (info->mode == PIPE_PRIM_TRIANGLES) { memcpy(indices3, ptr + start, 6); } else { /* Copy the mapped index buffer directly to the upload buffer. @@ -660,13 +666,15 @@ static void r300_draw_elements(struct r300_context *r300, int indexBias, /* 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, 19, buffer_offset, indexBias)) + PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_AOS | + PREP_INDEXED, indexBuffer, 19, buffer_offset, info->index_bias, + instance_id)) goto done; if (alt_num_verts || count <= 65535) { - r300_emit_draw_elements(r300, indexBuffer, indexSize, - minIndex, maxIndex, mode, start, count, indices3); + r300_emit_draw_elements(r300, indexBuffer, indexSize, info->min_index, + info->max_index, info->mode, start, count, + indices3); } else { do { if (indexSize == 2 && (start & 1)) @@ -675,8 +683,8 @@ static void r300_draw_elements(struct r300_context *r300, int indexBias, short_count = MIN2(count, 65534); r300_emit_draw_elements(r300, indexBuffer, indexSize, - minIndex, maxIndex, - mode, start, short_count, indices3); + info->min_index, info->max_index, + info->mode, start, short_count, indices3); start += short_count; count -= short_count; @@ -685,7 +693,8 @@ static void r300_draw_elements(struct r300_context *r300, int indexBias, if (count) { if (!r300_prepare_for_rendering(r300, PREP_VALIDATE_VBOS | PREP_EMIT_AOS | PREP_INDEXED, - indexBuffer, 19, buffer_offset, indexBias)) + indexBuffer, 19, buffer_offset, info->index_bias, + instance_id)) goto done; } } while (count); @@ -697,25 +706,28 @@ done: } } -static void r300_draw_arrays(struct r300_context *r300, unsigned mode, - unsigned start, unsigned count) +static void r300_draw_arrays(struct r300_context *r300, + const struct pipe_draw_info *info, + int instance_id) { boolean alt_num_verts = r300->screen->caps.is_r500 && - count > 65536; + info->count > 65536; + unsigned start = info->start; + unsigned count = info->count; unsigned short_count; /* 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)) + PREP_EMIT_STATES | PREP_VALIDATE_VBOS | PREP_EMIT_AOS, + NULL, 9, start, 0, instance_id)) return; if (alt_num_verts || count <= 65535) { - r300_emit_draw_arrays(r300, mode, count); + r300_emit_draw_arrays(r300, info->mode, count); } else { do { short_count = MIN2(count, 65535); - r300_emit_draw_arrays(r300, mode, short_count); + r300_emit_draw_arrays(r300, info->mode, short_count); start += short_count; count -= short_count; @@ -724,53 +736,78 @@ static void r300_draw_arrays(struct r300_context *r300, unsigned mode, if (count) { if (!r300_prepare_for_rendering(r300, PREP_VALIDATE_VBOS | PREP_EMIT_AOS, NULL, 9, - start, 0)) + start, 0, instance_id)) return; } } while (count); } } +static void r300_draw_arrays_instanced(struct r300_context *r300, + const struct pipe_draw_info *info) +{ + int i; + + for (i = 0; i < info->instance_count; i++) + r300_draw_arrays(r300, info, i); +} + +static void r300_draw_elements_instanced(struct r300_context *r300, + const struct pipe_draw_info *info) +{ + int i; + + for (i = 0; i < info->instance_count; i++) + r300_draw_elements(r300, info, i); +} + static void r300_draw_vbo(struct pipe_context* pipe, - const struct pipe_draw_info *info) + const struct pipe_draw_info *dinfo) { struct r300_context* r300 = r300_context(pipe); - unsigned count = info->count; + struct pipe_draw_info info = *dinfo; boolean buffers_updated, uploader_flushed; - boolean indexed = info->indexed && r300->index_buffer.buffer; - unsigned start_indexed = info->start + r300->index_buffer.offset; - int max_index = MIN2(r300->vbuf_mgr->max_index, info->max_index); + + info.indexed = info.indexed && r300->index_buffer.buffer; if (r300->skip_rendering || - !u_trim_pipe_prim(info->mode, &count)) { + !u_trim_pipe_prim(info.mode, &info.count)) { return; } r300_update_derived_state(r300); /* Start the vbuf manager and update buffers if needed. */ - u_vbuf_mgr_draw_begin(r300->vbuf_mgr, info, + u_vbuf_mgr_draw_begin(r300->vbuf_mgr, &info, &buffers_updated, &uploader_flushed); if (buffers_updated) { r300->vertex_arrays_dirty = TRUE; } /* Draw. */ - if (indexed) { - if (count <= 8 && - r300_resource(r300->index_buffer.buffer)->b.user_ptr) { - r300_draw_elements_immediate(r300, info->index_bias, - info->min_index, max_index, - info->mode, start_indexed, count); + if (info.indexed) { + info.start += r300->index_buffer.offset; + info.max_index = MIN2(r300->vbuf_mgr->max_index, info.max_index); + + if (info.instance_count <= 1) { + if (info.count <= 8 && + r300_resource(r300->index_buffer.buffer)->b.user_ptr) { + r300_draw_elements_immediate(r300, &info); + } else { + r300_draw_elements(r300, &info, -1); + } } else { - r300_draw_elements(r300, info->index_bias, info->min_index, - max_index, info->mode, start_indexed, count); + r300_draw_elements_instanced(r300, &info); } } else { - if (immd_is_good_idea(r300, count)) { - r300_draw_arrays_immediate(r300, info->mode, info->start, count); + if (info.instance_count <= 1) { + if (immd_is_good_idea(r300, info.count)) { + r300_draw_arrays_immediate(r300, &info); + } else { + r300_draw_arrays(r300, &info, -1); + } } else { - r300_draw_arrays(r300, info->mode, info->start, count); + r300_draw_arrays_instanced(r300, &info); } } @@ -805,7 +842,7 @@ static void r300_swtcl_draw_vbo(struct pipe_context* pipe, r300_update_derived_state(r300); r300_reserve_cs_dwords(r300, - PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | + PREP_EMIT_STATES | PREP_EMIT_AOS_SWTCL | (indexed ? PREP_INDEXED : 0), indexed ? 256 : 6); @@ -987,13 +1024,13 @@ static void r300_render_draw_arrays(struct vbuf_render* render, if (r300->draw_first_emitted) { if (!r300_prepare_for_rendering(r300, - PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL, - NULL, dwords, 0, 0)) + PREP_EMIT_STATES | PREP_EMIT_AOS_SWTCL, + NULL, dwords, 0, 0, -1)) return; } else { if (!r300_emit_states(r300, - PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL, - NULL, 0, 0)) + PREP_EMIT_STATES | PREP_EMIT_AOS_SWTCL, + NULL, 0, 0, -1)) return; } @@ -1027,13 +1064,13 @@ static void r300_render_draw_elements(struct vbuf_render* render, if (r300->draw_first_emitted) { if (!r300_prepare_for_rendering(r300, - PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED, - NULL, 256, 0, 0)) + PREP_EMIT_STATES | PREP_EMIT_AOS_SWTCL | PREP_INDEXED, + NULL, 256, 0, 0, -1)) return; } else { if (!r300_emit_states(r300, - PREP_FIRST_DRAW | PREP_EMIT_AOS_SWTCL | PREP_INDEXED, - NULL, 0, 0)) + PREP_EMIT_STATES | PREP_EMIT_AOS_SWTCL | PREP_INDEXED, + NULL, 0, 0, -1)) return; } @@ -1070,7 +1107,7 @@ static void r300_render_draw_elements(struct vbuf_render* render, if (count) { if (!r300_prepare_for_rendering(r300, PREP_EMIT_AOS_SWTCL | PREP_INDEXED, - NULL, 256, 0, 0)) + NULL, 256, 0, 0, -1)) return; end_cs_dwords = r300_get_num_cs_end_dwords(r300); @@ -1174,7 +1211,7 @@ static void r300_blitter_draw_rectangle(struct blitter_context *blitter, r300->clip_state.dirty = FALSE; r300->viewport_state.dirty = FALSE; - if (!r300_prepare_for_rendering(r300, PREP_FIRST_DRAW, NULL, dwords, 0, 0)) + if (!r300_prepare_for_rendering(r300, PREP_EMIT_STATES, NULL, dwords, 0, 0, -1)) goto done; DBG(r300, DBG_DRAW, "r300: draw_rectangle\n"); diff --git a/src/gallium/drivers/r300/r300_resource.c b/src/gallium/drivers/r300/r300_resource.c index f3d8c5b889f..6593474b1f0 100644 --- a/src/gallium/drivers/r300/r300_resource.c +++ b/src/gallium/drivers/r300/r300_resource.c @@ -38,13 +38,6 @@ r300_resource_create(struct pipe_screen *screen, } -static unsigned r300_resource_is_referenced_by_cs(struct pipe_context *context, - struct pipe_resource *buf, - unsigned level, int layer) -{ - return r300_buffer_is_referenced(context, buf); -} - void r300_init_resource_functions(struct r300_context *r300) { r300->context.get_transfer = u_get_transfer_vtbl; @@ -53,7 +46,6 @@ void r300_init_resource_functions(struct r300_context *r300) r300->context.transfer_unmap = u_transfer_unmap_vtbl; r300->context.transfer_destroy = u_transfer_destroy_vtbl; r300->context.transfer_inline_write = u_transfer_inline_write_vtbl; - r300->context.is_resource_referenced = r300_resource_is_referenced_by_cs; r300->context.create_surface = r300_create_surface; r300->context.surface_destroy = r300_surface_destroy; } diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 52d0247fbfd..8a69628c53e 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -24,6 +24,7 @@ #include "util/u_format.h" #include "util/u_format_s3tc.h" #include "util/u_memory.h" +#include "os/os_time.h" #include "r300_context.h" #include "r300_texture.h" @@ -112,6 +113,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_MIRROR_CLAMP: case PIPE_CAP_TEXTURE_MIRROR_REPEAT: case PIPE_CAP_BLEND_EQUATION_SEPARATE: + case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR: return 1; case PIPE_CAP_TEXTURE_SWIZZLE: return util_format_s3tc_enabled ? r300screen->caps.dxtc_swizzle : 1; @@ -124,12 +126,15 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_DEPTH_CLAMP: case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: case PIPE_CAP_SHADER_STENCIL_EXPORT: - case PIPE_CAP_STREAM_OUTPUT: - case PIPE_CAP_PRIMITIVE_RESTART: - case PIPE_CAP_INSTANCED_DRAWING: case PIPE_CAP_ARRAY_TEXTURES: return 0; + /* SWTCL-only features. */ + case PIPE_CAP_STREAM_OUTPUT: + case PIPE_CAP_PRIMITIVE_RESTART: + case PIPE_CAP_TGSI_INSTANCEID: + return !r300screen->caps.has_tcl; + /* Texturing. */ case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS: case PIPE_CAP_MAX_COMBINED_SAMPLERS: @@ -301,8 +306,7 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, enum pipe_format format, enum pipe_texture_target target, unsigned sample_count, - unsigned usage, - unsigned geom_flags) + unsigned usage) { struct r300_winsys_screen *rws = r300_screen(screen)->rws; uint32_t retval = 0; @@ -314,9 +318,13 @@ static boolean r300_is_format_supported(struct pipe_screen* screen, format == PIPE_FORMAT_B10G10R10A2_UNORM || format == PIPE_FORMAT_R10SG10SB10SA2U_NORM; boolean is_ati1n = format == PIPE_FORMAT_RGTC1_UNORM || - format == PIPE_FORMAT_RGTC1_SNORM; + format == PIPE_FORMAT_RGTC1_SNORM || + format == PIPE_FORMAT_LATC1_UNORM || + format == PIPE_FORMAT_LATC1_SNORM; boolean is_ati2n = format == PIPE_FORMAT_RGTC2_UNORM || - format == PIPE_FORMAT_RGTC2_SNORM; + format == PIPE_FORMAT_RGTC2_SNORM || + format == PIPE_FORMAT_LATC2_UNORM || + format == PIPE_FORMAT_LATC2_SNORM; boolean is_half_float = format == PIPE_FORMAT_R16_FLOAT || format == PIPE_FORMAT_R16G16_FLOAT || format == PIPE_FORMAT_R16G16B16_FLOAT || @@ -414,25 +422,40 @@ static void r300_fence_reference(struct pipe_screen *screen, (struct r300_winsys_bo*)fence); } -static int r300_fence_signalled(struct pipe_screen *screen, - struct pipe_fence_handle *fence, - unsigned flags) +static boolean r300_fence_signalled(struct pipe_screen *screen, + struct pipe_fence_handle *fence) { struct r300_winsys_screen *rws = r300_screen(screen)->rws; struct r300_winsys_bo *rfence = (struct r300_winsys_bo*)fence; - return !rws->buffer_is_busy(rfence) ? 0 : 1; /* 0 == success */ + return !rws->buffer_is_busy(rfence); } -static int r300_fence_finish(struct pipe_screen *screen, - struct pipe_fence_handle *fence, - unsigned flags) +static boolean r300_fence_finish(struct pipe_screen *screen, + struct pipe_fence_handle *fence, + uint64_t timeout) { struct r300_winsys_screen *rws = r300_screen(screen)->rws; struct r300_winsys_bo *rfence = (struct r300_winsys_bo*)fence; + if (timeout != PIPE_TIMEOUT_INFINITE) { + int64_t start_time = os_time_get(); + + /* Convert to microseconds. */ + timeout /= 1000; + + /* Wait in a loop. */ + while (rws->buffer_is_busy(rfence)) { + if (os_time_get() - start_time >= timeout) { + return FALSE; + } + os_time_sleep(10); + } + return TRUE; + } + rws->buffer_wait(rfence); - return 0; /* 0 == success */ + return TRUE; } struct pipe_screen* r300_screen_create(struct r300_winsys_screen *rws) diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index 1045911f3ae..986ae384fbf 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -33,21 +33,6 @@ #include "r300_screen_buffer.h" #include "r300_winsys.h" -unsigned r300_buffer_is_referenced(struct pipe_context *context, - struct pipe_resource *buf) -{ - struct r300_context *r300 = r300_context(context); - struct r300_resource *rbuf = r300_resource(buf); - - if (rbuf->b.user_ptr || rbuf->constant_buffer) - return PIPE_UNREFERENCED; - - if (r300->rws->cs_is_buffer_referenced(r300->cs, rbuf->cs_buf)) - return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; - - return PIPE_UNREFERENCED; -} - void r300_upload_index_buffer(struct r300_context *r300, struct pipe_resource **index_buffer, unsigned index_size, unsigned *start, @@ -181,7 +166,6 @@ static const struct u_resource_vtbl r300_buffer_vtbl = { NULL, /* get_handle */ r300_buffer_destroy, /* resource_destroy */ - NULL, /* is_buffer_referenced */ r300_buffer_get_transfer, /* get_transfer */ r300_buffer_transfer_destroy, /* transfer_destroy */ r300_buffer_transfer_map, /* transfer_map */ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h index 14bee460d5b..cdbc4425fcb 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.h +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -49,9 +49,6 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, void *ptr, unsigned size, unsigned bind); -unsigned r300_buffer_is_referenced(struct pipe_context *context, - struct pipe_resource *buf); - /* Inline functions. */ static INLINE struct r300_buffer *r300_buffer(struct pipe_resource *buffer) diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 2b0c8750554..ecb4fc691cc 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -188,13 +188,16 @@ static void* r300_create_blend_state(struct pipe_context* pipe, struct r300_screen* r300screen = r300_screen(pipe->screen); struct r300_blend_state* blend = CALLOC_STRUCT(r300_blend_state); uint32_t blend_control = 0; /* R300_RB3D_CBLEND: 0x4e04 */ + uint32_t blend_control_noclamp = 0; /* R300_RB3D_CBLEND: 0x4e04 */ uint32_t alpha_blend_control = 0; /* R300_RB3D_ABLEND: 0x4e08 */ + uint32_t alpha_blend_control_noclamp = 0; /* R300_RB3D_ABLEND: 0x4e08 */ uint32_t color_channel_mask = 0; /* R300_RB3D_COLOR_CHANNEL_MASK: 0x4e0c */ uint32_t rop = 0; /* R300_RB3D_ROPCNTL: 0x4e18 */ uint32_t dither = 0; /* R300_RB3D_DITHER_CTL: 0x4e50 */ - boolean clamp = TRUE; CB_LOCALS; + blend->state = *state; + if (state->rt[0].blend_enable) { unsigned eqRGB = state->rt[0].rgb_func; @@ -207,10 +210,14 @@ static void* r300_create_blend_state(struct pipe_context* pipe, /* despite the name, ALPHA_BLEND_ENABLE has nothing to do with alpha, * this is just the crappy D3D naming */ - blend_control = R300_ALPHA_BLEND_ENABLE | - r300_translate_blend_function(eqRGB, clamp) | + blend_control = blend_control_noclamp = + R300_ALPHA_BLEND_ENABLE | ( r300_translate_blend_factor(srcRGB) << R300_SRC_BLEND_SHIFT) | ( r300_translate_blend_factor(dstRGB) << R300_DST_BLEND_SHIFT); + blend_control |= + r300_translate_blend_function(eqRGB, TRUE); + blend_control_noclamp |= + r300_translate_blend_function(eqRGB, FALSE); /* Optimization: some operations do not require the destination color. * @@ -232,6 +239,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, srcRGB == PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE) { /* Enable reading from the colorbuffer. */ blend_control |= R300_READ_ENABLE; + blend_control_noclamp |= R300_READ_ENABLE; if (r300screen->caps.is_r500) { /* Optimization: Depending on incoming pixels, we can @@ -269,8 +277,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, * * Equations other than ADD are rarely used and therefore won't be * optimized. */ - if (clamp && - (eqRGB == PIPE_BLEND_ADD || eqRGB == PIPE_BLEND_REVERSE_SUBTRACT) && + if ((eqRGB == PIPE_BLEND_ADD || eqRGB == PIPE_BLEND_REVERSE_SUBTRACT) && (eqA == PIPE_BLEND_ADD || eqA == PIPE_BLEND_REVERSE_SUBTRACT)) { /* ADD: X+Y * REVERSE_SUBTRACT: Y-X @@ -308,10 +315,14 @@ static void* r300_create_blend_state(struct pipe_context* pipe, /* separate alpha */ if (srcA != srcRGB || dstA != dstRGB || eqA != eqRGB) { blend_control |= R300_SEPARATE_ALPHA_ENABLE; - alpha_blend_control = - r300_translate_blend_function(eqA, clamp) | + blend_control_noclamp |= R300_SEPARATE_ALPHA_ENABLE; + alpha_blend_control = alpha_blend_control_noclamp = (r300_translate_blend_factor(srcA) << R300_SRC_BLEND_SHIFT) | (r300_translate_blend_factor(dstA) << R300_DST_BLEND_SHIFT); + alpha_blend_control |= + r300_translate_blend_function(eqA, TRUE); + alpha_blend_control_noclamp |= + r300_translate_blend_function(eqA, FALSE); } } @@ -348,7 +359,7 @@ static void* r300_create_blend_state(struct pipe_context* pipe, */ /* Build a command buffer. */ - BEGIN_CB(blend->cb, 8); + BEGIN_CB(blend->cb_clamp, 8); OUT_CB_REG(R300_RB3D_ROPCNTL, rop); OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3); OUT_CB(blend_control); @@ -357,6 +368,16 @@ static void* r300_create_blend_state(struct pipe_context* pipe, OUT_CB_REG(R300_RB3D_DITHER_CTL, dither); END_CB; + /* Build a command buffer. */ + BEGIN_CB(blend->cb_noclamp, 8); + OUT_CB_REG(R300_RB3D_ROPCNTL, rop); + OUT_CB_REG_SEQ(R300_RB3D_CBLEND, 3); + OUT_CB(blend_control_noclamp); + OUT_CB(alpha_blend_control_noclamp); + OUT_CB(color_channel_mask); + OUT_CB_REG(R300_RB3D_DITHER_CTL, dither); + END_CB; + /* The same as above, but with no colorbuffer reads and writes. */ BEGIN_CB(blend->cb_no_readwrite, 8); OUT_CB_REG(R300_RB3D_ROPCNTL, rop); @@ -377,6 +398,10 @@ static void r300_bind_blend_state(struct pipe_context* pipe, struct r300_context* r300 = r300_context(pipe); UPDATE_STATE(state, r300->blend_state); + + if (r300->fs.state && r300_pick_fragment_shader(r300)) { + r300_mark_fs_code_dirty(r300); + } } /* Free blend state. */ @@ -836,10 +861,9 @@ r300_set_framebuffer_state(struct pipe_context* pipe, } } - /* If nr_cbufs is changed from zero to non-zero or vice versa... */ - if (!!old_state->nr_cbufs != !!state->nr_cbufs) { - r300_mark_atom_dirty(r300, &r300->blend_state); - } + /* Need to reset clamping or colormask. */ + r300_mark_atom_dirty(r300, &r300->blend_state); + /* If zsbuf is set from NULL to non-NULL or vice versa.. */ if (!!old_state->zsbuf != !!state->zsbuf) { r300_mark_atom_dirty(r300, &r300->dsa_state); @@ -1593,12 +1617,6 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems) enum pipe_format format; unsigned i; - if (velems->count > 16) { - fprintf(stderr, "r300: More than 16 vertex elements are not supported," - " requested %i, using 16.\n", velems->count); - velems->count = 16; - } - /* Vertex shaders have no semantics on their inputs, * so PSC should just route stuff based on the vertex elements, * and not on attrib information. */ @@ -1649,9 +1667,12 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe, dummy_attrib.src_format = PIPE_FORMAT_R8G8B8A8_UNORM; attribs = &dummy_attrib; count = 1; + } else if (count > 16) { + fprintf(stderr, "r300: More than 16 vertex elements are not supported," + " requested %i, using 16.\n", count); + count = 16; } - assert(count <= PIPE_MAX_ATTRIBS); velems = CALLOC_STRUCT(r300_vertex_element_state); if (!velems) return NULL; @@ -1849,6 +1870,14 @@ static void r300_set_constant_buffer(struct pipe_context *pipe, } } +static void r300_texture_barrier(struct pipe_context *pipe) +{ + struct r300_context *r300 = r300_context(pipe); + + r300_mark_atom_dirty(r300, &r300->gpu_flush); + r300_mark_atom_dirty(r300, &r300->texture_cache_inval); +} + void r300_init_state_functions(struct r300_context* r300) { r300->context.create_blend_state = r300_create_blend_state; @@ -1904,4 +1933,6 @@ void r300_init_state_functions(struct r300_context* r300) r300->context.create_vs_state = r300_create_vs_state; r300->context.bind_vs_state = r300_bind_vs_state; r300->context.delete_vs_state = r300_delete_vs_state; + + r300->context.texture_barrier = r300_texture_barrier; } diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c index a1e116f4b61..ec00e2552ca 100644 --- a/src/gallium/drivers/r300/r300_state_derived.c +++ b/src/gallium/drivers/r300/r300_state_derived.c @@ -644,16 +644,20 @@ static uint32_t r300_get_border_color(enum pipe_format format, switch (format) { case PIPE_FORMAT_RGTC1_SNORM: case PIPE_FORMAT_RGTC1_UNORM: + case PIPE_FORMAT_LATC1_SNORM: + case PIPE_FORMAT_LATC1_UNORM: /* Add 1/32 to round the border color instead of truncating. */ /* The Y component is used for the border color. */ border_swizzled[1] = border_swizzled[2] + 1.0f/32; util_pack_color(border_swizzled, PIPE_FORMAT_B4G4R4A4_UNORM, &uc); return uc.ui; case PIPE_FORMAT_RGTC2_SNORM: + case PIPE_FORMAT_LATC2_SNORM: border_swizzled[0] = border_swizzled[2]; util_pack_color(border_swizzled, PIPE_FORMAT_R8G8B8A8_SNORM, &uc); return uc.ui; case PIPE_FORMAT_RGTC2_UNORM: + case PIPE_FORMAT_LATC2_UNORM: util_pack_color(border_swizzled, PIPE_FORMAT_B8G8R8A8_UNORM, &uc); return uc.ui; default: diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index 86ad0b8b8e0..c650fb7ed37 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -174,9 +174,11 @@ uint32_t r300_translate_texformat(enum pipe_format format, if (util_format_is_compressed(format) && dxtc_swizzle && format != PIPE_FORMAT_RGTC2_UNORM && - format != PIPE_FORMAT_RGTC2_SNORM) { + format != PIPE_FORMAT_RGTC2_SNORM && + format != PIPE_FORMAT_LATC2_UNORM && + format != PIPE_FORMAT_LATC2_SNORM) { result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view, - dxtc_swizzle); + TRUE); } else { result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view, FALSE); @@ -209,13 +211,19 @@ uint32_t r300_translate_texformat(enum pipe_format format, if (desc->layout == UTIL_FORMAT_LAYOUT_RGTC) { switch (format) { case PIPE_FORMAT_RGTC1_SNORM: + case PIPE_FORMAT_LATC1_SNORM: result |= sign_bit[1]; + case PIPE_FORMAT_LATC1_UNORM: case PIPE_FORMAT_RGTC1_UNORM: return R500_TX_FORMAT_ATI1N | result; + case PIPE_FORMAT_RGTC2_SNORM: + case PIPE_FORMAT_LATC2_SNORM: result |= sign_bit[2] | sign_bit[3]; case PIPE_FORMAT_RGTC2_UNORM: + case PIPE_FORMAT_LATC2_UNORM: return R400_TX_FORMAT_ATI2N | result; + default: return ~0; /* Unsupported/unknown. */ } @@ -363,6 +371,8 @@ uint32_t r500_tx_format_msb_bit(enum pipe_format format) switch (format) { case PIPE_FORMAT_RGTC1_UNORM: case PIPE_FORMAT_RGTC1_SNORM: + case PIPE_FORMAT_LATC1_UNORM: + case PIPE_FORMAT_LATC1_SNORM: case PIPE_FORMAT_X8Z24_UNORM: case PIPE_FORMAT_S8_USCALED_Z24_UNORM: return R500_TXFORMAT_MSB; @@ -742,7 +752,6 @@ static const struct u_resource_vtbl r300_texture_vtbl = { NULL, /* get_handle */ r300_texture_destroy, /* resource_destroy */ - NULL, /* is_resource_referenced */ r300_texture_get_transfer, /* get_transfer */ r300_texture_transfer_destroy, /* transfer_destroy */ r300_texture_transfer_map, /* transfer_map */ diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c index 3846fb8b6b3..2910666dd51 100644 --- a/src/gallium/drivers/r300/r300_texture_desc.c +++ b/src/gallium/drivers/r300/r300_texture_desc.c @@ -315,7 +315,7 @@ static unsigned r300_pixels_to_dwords(unsigned stride, unsigned height, unsigned xblock, unsigned yblock) { - return (align(stride, xblock) * align(height, yblock)) / (xblock * yblock); + return (util_align_npot(stride, xblock) * align(height, yblock)) / (xblock * yblock); } static void r300_setup_hyperz_properties(struct r300_screen *screen, @@ -390,7 +390,7 @@ static void r300_setup_hyperz_properties(struct r300_screen *screen, tex->tex.zcomp8x8[i] = zcompsize == 8; tex->tex.zmask_stride_in_pixels[i] = - align(stride, zmask_blocks_x_per_dw[pipes-1] * zcompsize); + util_align_npot(stride, zmask_blocks_x_per_dw[pipes-1] * zcompsize); } else { tex->tex.zmask_dwords[i] = 0; tex->tex.zcomp8x8[i] = FALSE; @@ -398,7 +398,7 @@ static void r300_setup_hyperz_properties(struct r300_screen *screen, } /* Now setup HIZ. */ - stride = align(stride, hiz_align_x[pipes-1]); + stride = util_align_npot(stride, hiz_align_x[pipes-1]); height = align(height, hiz_align_y[pipes-1]); /* Get the HIZ buffer size in dwords. */ diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c index 30de9ec1e32..65c5095be6a 100644 --- a/src/gallium/drivers/r300/r300_transfer.c +++ b/src/gallium/drivers/r300/r300_transfer.c @@ -72,7 +72,8 @@ static void r300_copy_into_tiled_texture(struct pipe_context *ctx, transfer->box.x, transfer->box.y, transfer->box.z, &r300transfer->linear_texture->b.b.b, 0, &src_box); - ctx->flush(ctx, 0, NULL); + /* XXX remove this. */ + r300_flush(ctx, 0, NULL); } struct pipe_transfer* @@ -100,7 +101,8 @@ r300_texture_get_transfer(struct pipe_context *ctx, } blittable = desc->layout == UTIL_FORMAT_LAYOUT_PLAIN || - desc->layout == UTIL_FORMAT_LAYOUT_S3TC; + desc->layout == UTIL_FORMAT_LAYOUT_S3TC || + desc->layout == UTIL_FORMAT_LAYOUT_RGTC; trans = CALLOC_STRUCT(r300_transfer); if (trans) { @@ -151,7 +153,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, if (!trans->linear_texture) { /* Oh crap, the thing can't create the texture. * Let's flush and try again. */ - ctx->flush(ctx, 0, NULL); + r300_flush(ctx, 0, NULL); trans->linear_texture = r300_resource( ctx->screen->resource_create(ctx->screen, @@ -175,13 +177,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, assert(!trans->linear_texture->tex.microtile && !trans->linear_texture->tex.macrotile[0]); - /* Set the stride. - * - * Even though we are using an internal texture for this, - * the transfer level, box and usage parameters still reflect - * the arguments received to get_transfer. We just do the - * right thing internally. - */ + /* Set the stride. */ trans->transfer.stride = trans->linear_texture->tex.stride_in_bytes[0]; @@ -191,7 +187,7 @@ r300_texture_get_transfer(struct pipe_context *ctx, r300_copy_from_tiled_texture(ctx, trans); /* Always referenced in the blit. */ - ctx->flush(ctx, 0, NULL); + r300_flush(ctx, 0, NULL); } return &trans->transfer; } @@ -201,8 +197,9 @@ r300_texture_get_transfer(struct pipe_context *ctx, trans->transfer.stride = tex->tex.stride_in_bytes[level]; trans->offset = r300_texture_get_offset(tex, level, box->z); - if (referenced_cs) - ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL); + if (referenced_cs && + !(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) + r300_flush(ctx, 0, NULL); return &trans->transfer; } return NULL; diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index c0b66899f8b..3a6798a5423 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -35,6 +35,7 @@ #include "pipe/p_state.h" #define R300_MAX_CMDBUF_DWORDS (16 * 1024) +#define R300_FLUSH_ASYNC (1 << 0) struct winsys_handle; struct r300_winsys_screen; @@ -265,15 +266,9 @@ struct r300_winsys_screen { * Flush a command stream. * * \param cs A command stream to flush. + * \param flags, R300_FLUSH_ASYNC or 0. */ - void (*cs_flush)(struct r300_winsys_cs *cs); - - /** - * Wait until the last flush is completed. - * - * \param cs A command stream. - */ - void (*cs_sync_flush)(struct r300_winsys_cs *cs); + void (*cs_flush)(struct r300_winsys_cs *cs, unsigned flags); /** * Set a flush callback which is called from winsys when flush is @@ -284,7 +279,7 @@ struct r300_winsys_screen { * \param user A user pointer that will be passed to the flush callback. */ void (*cs_set_flush)(struct r300_winsys_cs *cs, - void (*flush)(void *), + void (*flush)(void *ctx, unsigned flags), void *user); /** |