summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2012-01-30 01:23:14 +0100
committerMarek Olšák <[email protected]>2012-01-31 23:12:30 +0100
commit2fe521fa419ee153afb6295289dc5e95d3229858 (patch)
treeca48e074d01cde425d4bb289a974960977016d95 /src
parent621e0db71c5ddcb379171064a4f720c9cf01e888 (diff)
r600g: add a new simple API for state emission
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/r600/r600_hw_context.c6
-rw-r--r--src/gallium/drivers/r600/r600_pipe.c2
-rw-r--r--src/gallium/drivers/r600/r600_pipe.h42
-rw-r--r--src/gallium/drivers/r600/r600_state_common.c4
4 files changed, 54 insertions, 0 deletions
diff --git a/src/gallium/drivers/r600/r600_hw_context.c b/src/gallium/drivers/r600/r600_hw_context.c
index aa01d0d3c5f..3399466f9ad 100644
--- a/src/gallium/drivers/r600/r600_hw_context.c
+++ b/src/gallium/drivers/r600/r600_hw_context.c
@@ -931,11 +931,17 @@ out_err:
void r600_need_cs_space(struct r600_context *ctx, unsigned num_dw,
boolean count_draw_in)
{
+ struct r600_atom *state;
+
/* The number of dwords we already used in the CS so far. */
num_dw += ctx->cs->cdw;
if (count_draw_in) {
/* The number of dwords all the dirty states would take. */
+ LIST_FOR_EACH_ENTRY(state, &ctx->dirty_states, head) {
+ num_dw += state->num_dw;
+ }
+
num_dw += ctx->pm4_dirty_cdwords;
/* The upper-bound of how much a draw command would take. */
diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c
index bd68eff8f73..b92762526cd 100644
--- a/src/gallium/drivers/r600/r600_pipe.c
+++ b/src/gallium/drivers/r600/r600_pipe.c
@@ -282,6 +282,8 @@ static struct pipe_context *r600_create_context(struct pipe_screen *screen, void
return NULL;
}
+ LIST_INITHEAD(&rctx->dirty_states);
+
r600_get_backend_mask(rctx); /* this emits commands and must be last */
return &rctx->context;
diff --git a/src/gallium/drivers/r600/r600_pipe.h b/src/gallium/drivers/r600/r600_pipe.h
index 0aaec4be9b0..78b6d83fe30 100644
--- a/src/gallium/drivers/r600/r600_pipe.h
+++ b/src/gallium/drivers/r600/r600_pipe.h
@@ -48,6 +48,25 @@
#define R600_BIG_ENDIAN 0
#endif
+enum r600_atom_flags {
+ /* When set, atoms are added at the beginning of the dirty list
+ * instead of the end. */
+ EMIT_EARLY = (1 << 0)
+};
+
+/* This encapsulates a state or an operation which can emitted into the GPU
+ * command stream. It's not limited to states only, it can be used for anything
+ * that wants to write commands into the CS (e.g. cache flushes). */
+struct r600_atom {
+ void (*emit)(struct r600_context *ctx, struct r600_atom *state);
+
+ unsigned num_dw;
+ enum r600_atom_flags flags;
+ bool dirty;
+
+ struct list_head head;
+};
+
enum r600_pipe_state_id {
R600_PIPE_STATE_BLEND = 0,
R600_PIPE_STATE_BLEND_COLOR,
@@ -251,6 +270,9 @@ struct r600_context {
unsigned default_ps_gprs, default_vs_gprs;
+ /* States based on r600_state. */
+ struct list_head dirty_states;
+
/* Below are variables from the old r600_context.
*/
struct radeon_winsys_cs *cs;
@@ -290,6 +312,26 @@ struct r600_context {
unsigned *vs_so_stride_in_dw;
};
+static INLINE void r600_emit_atom(struct r600_context *rctx, struct r600_atom *atom)
+{
+ atom->emit(rctx, atom);
+ atom->dirty = false;
+ if (atom->head.next && atom->head.prev)
+ LIST_DELINIT(&atom->head);
+}
+
+static INLINE void r600_atom_dirty(struct r600_context *rctx, struct r600_atom *state)
+{
+ if (!state->dirty) {
+ if (state->flags & EMIT_EARLY) {
+ LIST_ADD(&state->head, &rctx->dirty_states);
+ } else {
+ LIST_ADDTAIL(&state->head, &rctx->dirty_states);
+ }
+ state->dirty = true;
+ }
+}
+
/* evergreen_state.c */
void evergreen_init_state_functions(struct r600_context *rctx);
void evergreen_init_config(struct r600_context *rctx);
diff --git a/src/gallium/drivers/r600/r600_state_common.c b/src/gallium/drivers/r600/r600_state_common.c
index c3a8e3da098..0c06ad05319 100644
--- a/src/gallium/drivers/r600/r600_state_common.c
+++ b/src/gallium/drivers/r600/r600_state_common.c
@@ -671,6 +671,7 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
struct pipe_index_buffer ib = {};
unsigned prim, mask, ls_mask = 0;
struct r600_block *dirty_block = NULL, *next_block = NULL;
+ struct r600_atom *state = NULL, *next_state = NULL;
if ((!info.count && (info.indexed || !info.count_from_stream_output)) ||
(info.indexed && !rctx->vbuf_mgr->index_buffer.buffer) ||
@@ -788,6 +789,9 @@ void r600_draw_vbo(struct pipe_context *ctx, const struct pipe_draw_info *dinfo)
/* Emit states. */
r600_need_cs_space(rctx, 0, TRUE);
+ LIST_FOR_EACH_ENTRY_SAFE(state, next_state, &rctx->dirty_states, head) {
+ r600_emit_atom(rctx, state);
+ }
LIST_FOR_EACH_ENTRY_SAFE(dirty_block, next_block, &rctx->dirty,list) {
r600_context_block_emit_dirty(rctx, dirty_block);
}