summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/r300/r300_context.c36
-rw-r--r--src/gallium/drivers/r300/r300_context.h9
-rw-r--r--src/gallium/drivers/r300/r300_emit.c18
-rw-r--r--src/gallium/drivers/r300/r300_state.c10
4 files changed, 55 insertions, 18 deletions
diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c
index 98a5bb8e5fd..5e4f6552c36 100644
--- a/src/gallium/drivers/r300/r300_context.c
+++ b/src/gallium/drivers/r300/r300_context.c
@@ -110,23 +110,33 @@ static void r300_flush_cb(void *data)
cs_context_copy->context.flush(&cs_context_copy->context, 0, NULL);
}
-#define R300_INIT_ATOM(name) \
- r300->name##_state.state = NULL; \
- r300->name##_state.emit = r300_emit_##name##_state; \
- r300->name##_state.dirty = FALSE; \
- insert_at_tail(&r300->atom_list, &r300->name##_state);
+#define R300_INIT_ATOM(atomname, atomsize) \
+ r300->atomname##_state.name = #atomname; \
+ r300->atomname##_state.state = NULL; \
+ r300->atomname##_state.size = atomsize; \
+ r300->atomname##_state.emit = r300_emit_##atomname##_state; \
+ r300->atomname##_state.dirty = FALSE; \
+ insert_at_tail(&r300->atom_list, &r300->atomname##_state);
static void r300_setup_atoms(struct r300_context* r300)
{
+ /* Create the actual atom list.
+ *
+ * Each atom is examined and emitted in the order it appears here, which
+ * can affect performance and conformance if not handled with care.
+ *
+ * Some atoms never change size, others change every emit. This is just
+ * an upper bound on each atom, to keep the emission machinery from
+ * underallocating space. */
make_empty_list(&r300->atom_list);
- R300_INIT_ATOM(ztop);
- R300_INIT_ATOM(blend);
- R300_INIT_ATOM(blend_color);
- R300_INIT_ATOM(clip);
- R300_INIT_ATOM(dsa);
- R300_INIT_ATOM(rs);
- R300_INIT_ATOM(scissor);
- R300_INIT_ATOM(viewport);
+ R300_INIT_ATOM(ztop, 2);
+ R300_INIT_ATOM(blend, 8);
+ R300_INIT_ATOM(blend_color, 3);
+ R300_INIT_ATOM(clip, 29);
+ R300_INIT_ATOM(dsa, 8);
+ R300_INIT_ATOM(rs, 22);
+ R300_INIT_ATOM(scissor, 3);
+ R300_INIT_ATOM(viewport, 9);
}
struct pipe_context* r300_create_context(struct pipe_screen* screen,
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 7e5de40ded8..682b9179c83 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -36,10 +36,19 @@ struct r300_fragment_shader;
struct r300_vertex_shader;
struct r300_atom {
+ /* List pointers. */
struct r300_atom *prev, *next;
+ /* Name, for debugging. */
+ const char* name;
+ /* Opaque state. */
void* state;
+ /* Emit the state to the context. */
void (*emit)(struct r300_context*, void*);
+ /* Upper bound on number of dwords to emit. */
+ unsigned size;
+ /* Whether this atom should be emitted. */
boolean dirty;
+ /* Another dirty flag that is never automatically cleared. */
boolean always_dirty;
};
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index ba04bd07cc8..9f93327e598 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -41,6 +41,7 @@ void r300_emit_blend_state(struct r300_context* r300, void* state)
{
struct r300_blend_state* blend = (struct r300_blend_state*)state;
CS_LOCALS(r300);
+
BEGIN_CS(8);
OUT_CS_REG(R300_RB3D_ROPCNTL, blend->rop);
OUT_CS_REG_SEQ(R300_RB3D_CBLEND, 3);
@@ -992,14 +993,23 @@ void r300_emit_dirty_state(struct r300_context* r300)
struct r300_screen* r300screen = r300_screen(r300->context.screen);
struct r300_texture* tex;
struct r300_atom* atom;
- int i, dirty_tex = 0;
+ unsigned i, dwords = 1024;
+ int dirty_tex = 0;
boolean invalid = FALSE;
- /* Check size of CS. */
- /* Make sure we have at least 8*1024 spare dwords. */
+ /* Check the required number of dwords against the space remaining in the
+ * current CS object. If we need more, then flush. */
+
+ foreach(atom, &r300->atom_list) {
+ if (atom->dirty || atom->always_dirty) {
+ dwords += atom->size;
+ }
+ }
+
+ /* Make sure we have at least 2*1024 spare dwords. */
/* XXX It would be nice to know the number of dwords we really need to
* XXX emit. */
- if (!r300->winsys->check_cs(r300->winsys, 8*1024)) {
+ if (!r300->winsys->check_cs(r300->winsys, dwords)) {
r300->context.flush(&r300->context, 0, NULL);
}
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index 00f1b231175..281ff684495 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -340,6 +340,7 @@ static void r300_set_blend_color(struct pipe_context* pipe,
const struct pipe_blend_color* color)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_screen* r300screen = r300_screen(pipe->screen);
struct r300_blend_color_state* state =
(struct r300_blend_color_state*)r300->blend_color_state.state;
union util_color uc;
@@ -355,6 +356,7 @@ static void r300_set_blend_color(struct pipe_context* pipe,
float_to_fixed10(color->color[2]) |
(float_to_fixed10(color->color[1]) << 16);
+ r300->blend_color_state.size = r300screen->caps->is_r500 ? 3 : 2;
r300->blend_color_state.dirty = TRUE;
}
@@ -365,11 +367,14 @@ static void r300_set_clip_state(struct pipe_context* pipe,
if (r300_screen(pipe->screen)->caps->has_tcl) {
memcpy(r300->clip_state.state, state, sizeof(struct pipe_clip_state));
- r300->clip_state.dirty = TRUE;
+ r300->clip_state.size = 29;
} else {
draw_flush(r300->draw);
draw_set_clip_state(r300->draw, state);
+ r300->clip_state.size = 2;
}
+
+ r300->clip_state.dirty = TRUE;
}
/* Create a new depth, stencil, and alpha state based on the CSO dsa state.
@@ -462,8 +467,10 @@ static void r300_bind_dsa_state(struct pipe_context* pipe,
void* state)
{
struct r300_context* r300 = r300_context(pipe);
+ struct r300_screen* r300screen = r300_screen(pipe->screen);
r300->dsa_state.state = state;
+ r300->dsa_state.size = r300screen->caps->is_r500 ? 8 : 6;
r300->dsa_state.dirty = TRUE;
}
@@ -839,6 +846,7 @@ static void r300_set_scissor_state(struct pipe_context* pipe,
memcpy(r300->scissor_state.state, state,
sizeof(struct pipe_scissor_state));
+
r300->scissor_state.dirty = TRUE;
}