summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nv40/nv40_state_emit.c
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2008-02-16 21:27:53 +1100
committerBen Skeggs <skeggsb@gmail.com>2008-02-18 12:46:25 +1100
commit5e091b573aa0a0c45f8ff34429f2a9d4198bb80a (patch)
tree0f5466954eeed371b00d5487989e1602398435c7 /src/gallium/drivers/nv40/nv40_state_emit.c
parent9a6c39bd2e857398199f46f302a70317a70e3a8d (diff)
nv40: ensure scissor gets disabled where necessary
Fixes progs/demos/lodbias. Makes a complete mess of things, but now there's a motivation to finish this off :)
Diffstat (limited to 'src/gallium/drivers/nv40/nv40_state_emit.c')
-rw-r--r--src/gallium/drivers/nv40/nv40_state_emit.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
index a10c995548..74306fe22b 100644
--- a/src/gallium/drivers/nv40/nv40_state_emit.c
+++ b/src/gallium/drivers/nv40/nv40_state_emit.c
@@ -22,9 +22,68 @@ nv40_state_emit_dummy_relocs(struct nv40_context *nv40)
so_emit_reloc_markers(nv40->nvws, nv40->fragprog.active->so);
}
+static boolean
+nv40_state_scissor_validate(struct nv40_context *nv40)
+{
+ struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
+ struct pipe_scissor_state *s = &nv40->pipe_state.scissor;
+ struct nouveau_stateobj *so;
+
+ if (nv40->state.scissor &&
+ (rast->scissor == 0 && nv40->state.scissor_enabled == 0))
+ return FALSE;
+
+ so = so_new(3, 0);
+ so_method(so, nv40->hw->curie, NV40TCL_SCISSOR_HORIZ, 2);
+ if (rast->scissor) {
+ so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
+ so_data (so, ((s->maxy - s->miny) << 16) | s->miny);
+ } else {
+ so_data (so, 4096 << 16);
+ so_data (so, 4096 << 16);
+ }
+
+ so_ref(so, &nv40->state.scissor);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv40_state_atom {
+ boolean (*validate)(struct nv40_context *nv40);
+ struct {
+ unsigned pipe;
+ unsigned hw;
+ } dirty;
+};
+
+static struct nv40_state_atom states[] = {
+ {
+ .validate = nv40_state_scissor_validate,
+ .dirty = {
+ .pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST,
+ .hw = NV40_NEW_SCISSOR,
+ }
+ }
+};
+
+static void
+nv40_state_validate(struct nv40_context *nv40)
+{
+ unsigned i;
+
+ for (i = 0; i < sizeof(states) / sizeof(states[0]); i++) {
+ if (nv40->dirty & states[i].dirty.pipe) {
+ if (states[i].validate(nv40))
+ nv40->hw_dirty |= states[i].dirty.hw;
+ }
+ }
+}
+
void
nv40_emit_hw_state(struct nv40_context *nv40)
{
+ nv40_state_validate(nv40);
+
if (nv40->dirty & NV40_NEW_FB)
so_emit(nv40->nvws, nv40->so_framebuffer);
@@ -40,8 +99,10 @@ nv40_emit_hw_state(struct nv40_context *nv40)
if (nv40->dirty & NV40_NEW_BCOL)
so_emit(nv40->nvws, nv40->so_bcol);
- if (nv40->dirty & NV40_NEW_SCISSOR)
- so_emit(nv40->nvws, nv40->so_scissor);
+ if (nv40->hw_dirty & NV40_NEW_SCISSOR) {
+ so_emit(nv40->nvws, nv40->state.scissor);
+ nv40->hw_dirty &= ~NV40_NEW_SCISSOR;
+ }
if (nv40->dirty & NV40_NEW_VIEWPORT)
so_emit(nv40->nvws, nv40->so_viewport);