summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/r300
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/r300')
-rw-r--r--src/gallium/drivers/r300/r300_blit.c6
-rw-r--r--src/gallium/drivers/r300/r300_context.c10
-rw-r--r--src/gallium/drivers/r300/r300_context.h14
-rw-r--r--src/gallium/drivers/r300/r300_emit.c107
-rw-r--r--src/gallium/drivers/r300/r300_emit.h3
-rw-r--r--src/gallium/drivers/r300/r300_flush.c23
-rw-r--r--src/gallium/drivers/r300/r300_fs.c2
-rw-r--r--src/gallium/drivers/r300/r300_render.c259
-rw-r--r--src/gallium/drivers/r300/r300_resource.c8
-rw-r--r--src/gallium/drivers/r300/r300_screen.c53
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.c16
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.h3
-rw-r--r--src/gallium/drivers/r300/r300_state.c69
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c4
-rw-r--r--src/gallium/drivers/r300/r300_texture.c15
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.c6
-rw-r--r--src/gallium/drivers/r300/r300_transfer.c23
-rw-r--r--src/gallium/drivers/r300/r300_winsys.h13
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);
/**