summaryrefslogtreecommitdiffstats
path: root/src/gallium
diff options
context:
space:
mode:
authorBen Skeggs <[email protected]>2008-02-16 21:27:53 +1100
committerBen Skeggs <[email protected]>2008-02-18 12:46:25 +1100
commit5e091b573aa0a0c45f8ff34429f2a9d4198bb80a (patch)
tree0f5466954eeed371b00d5487989e1602398435c7 /src/gallium
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')
-rw-r--r--src/gallium/drivers/nv40/nv40_context.h19
-rw-r--r--src/gallium/drivers/nv40/nv40_state.c23
-rw-r--r--src/gallium/drivers/nv40/nv40_state_emit.c65
3 files changed, 91 insertions, 16 deletions
diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h
index f511759e3be..c4523112dbc 100644
--- a/src/gallium/drivers/nv40/nv40_context.h
+++ b/src/gallium/drivers/nv40/nv40_context.h
@@ -54,6 +54,11 @@ struct nv40_channel_context {
struct nouveau_resource *vp_data_heap;
};
+struct nv40_rasterizer_state {
+ struct pipe_rasterizer_state pipe;
+ struct nouveau_stateobj *so;
+};
+
struct nv40_context {
struct pipe_context pipe;
struct nouveau_winsys *nvws;
@@ -63,7 +68,8 @@ struct nv40_context {
int chipset;
- uint32_t dirty;
+ unsigned dirty;
+ unsigned hw_dirty;
struct nv40_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
struct nv40_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
@@ -71,14 +77,23 @@ struct nv40_context {
unsigned fp_samplers;
unsigned vp_samplers;
+ struct {
+ struct pipe_scissor_state scissor;
+ } pipe_state;
+
+ struct {
+ unsigned scissor_enabled;
+ struct nouveau_stateobj *scissor;
+ } state;
+
struct nouveau_stateobj *so_framebuffer;
struct nouveau_stateobj *so_fragtex[16];
struct nouveau_stateobj *so_vtxbuf;
struct nouveau_stateobj *so_blend;
+ struct nv40_rasterizer_state *rasterizer;
struct nouveau_stateobj *so_rast;
struct nouveau_stateobj *so_zsa;
struct nouveau_stateobj *so_bcol;
- struct nouveau_stateobj *so_scissor;
struct nouveau_stateobj *so_viewport;
struct nouveau_stateobj *so_stipple;
diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c
index 713f31dbb12..bb9b6b139f0 100644
--- a/src/gallium/drivers/nv40/nv40_state.c
+++ b/src/gallium/drivers/nv40/nv40_state.c
@@ -278,12 +278,12 @@ nv40_rasterizer_state_create(struct pipe_context *pipe,
const struct pipe_rasterizer_state *cso)
{
struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_rasterizer_state *rsso = MALLOC(sizeof(*rsso));
struct nouveau_stateobj *so = so_new(32, 0);
/*XXX: ignored:
* light_twoside
* offset_cw/ccw -nohw
- * scissor
* point_smooth -nohw
* multisample
* offset_units / offset_scale
@@ -362,24 +362,29 @@ nv40_rasterizer_state_create(struct pipe_context *pipe,
so_data(so, 0);
}
- return (void *)so;
+ rsso->so = so;
+ rsso->pipe = *cso;
+ return (void *)rsso;
}
static void
nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_rasterizer_state *rsso = hwcso;
- so_ref(hwcso, &nv40->so_rast);
+ so_ref(rsso->so, &nv40->so_rast);
+ nv40->rasterizer = rsso;
nv40->dirty |= NV40_NEW_RAST;
}
static void
nv40_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
{
- struct nouveau_stateobj *so = hwcso;
+ struct nv40_rasterizer_state *rsso = hwcso;
- so_ref(NULL, &so);
+ so_ref(NULL, &rsso->so);
+ free(rsso);
}
static void *
@@ -723,14 +728,8 @@ nv40_set_scissor_state(struct pipe_context *pipe,
const struct pipe_scissor_state *s)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nouveau_stateobj *so = so_new(3, 0);
- so_method(so, nv40->hw->curie, NV40TCL_SCISSOR_HORIZ, 2);
- so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
- so_data (so, ((s->maxy - s->miny) << 16) | s->miny);
-
- so_ref(so, &nv40->so_scissor);
- so_ref(NULL, &so);
+ nv40->pipe_state.scissor = *s;
nv40->dirty |= NV40_NEW_SCISSOR;
}
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
index a10c9955480..74306fe22b3 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);