nv40: ensure scissor gets disabled where necessary
authorBen Skeggs <skeggsb@gmail.com>
Sat, 16 Feb 2008 10:27:53 +0000 (21:27 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Mon, 18 Feb 2008 01:46:25 +0000 (12:46 +1100)
Fixes progs/demos/lodbias.

Makes a complete mess of things, but now there's a motivation to finish
this off :)

src/gallium/drivers/nv40/nv40_context.h
src/gallium/drivers/nv40/nv40_state.c
src/gallium/drivers/nv40/nv40_state_emit.c

index f511759e3be8f5bf4da4a3dbea71b0dea0e8390b..c4523112dbc01bde89094b5409340fe251dc5533 100644 (file)
@@ -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;
 
index 713f31dbb126a28bbfe311172b3456d3d9449c3e..bb9b6b139f068baf5f29fd710f9bd1ac6a362705 100644 (file)
@@ -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;
 }
 
index a10c9955480485fe4f529c342c7a56a9366cefeb..74306fe22b399356620ac50ac38edda00cf58808 100644 (file)
@@ -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);