nv40: get fragprog onto new state mechanism
authorBen Skeggs <skeggsb@gmail.com>
Mon, 18 Feb 2008 06:07:59 +0000 (17:07 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Mon, 18 Feb 2008 06:07:59 +0000 (17:07 +1100)
src/gallium/drivers/nv40/nv40_context.h
src/gallium/drivers/nv40/nv40_fragprog.c
src/gallium/drivers/nv40/nv40_fragtex.c
src/gallium/drivers/nv40/nv40_state.c
src/gallium/drivers/nv40/nv40_state.h
src/gallium/drivers/nv40/nv40_state_emit.c

index 432204b825270b3d27fedf9a0d35dc28bc6bcaab..ce0933fea4ac059303558fdec3a239d9137d21d1 100644 (file)
@@ -37,6 +37,7 @@
 #define NV40_NEW_UCP           (1 << 12)
 
 #define NV40_FALLBACK_TNL (1 << 0)
+#define NV40_FALLBACK_RAST (1 << 1)
 
 struct nv40_channel_context {
        struct nouveau_winsys *nvws;
@@ -72,6 +73,8 @@ struct nv40_state {
                unsigned enabled;
                struct nouveau_stateobj *so;
        } stipple;
+
+       struct nouveau_stateobj *fragprog;
 };
 
 struct nv40_context {
@@ -96,6 +99,8 @@ struct nv40_context {
                struct pipe_scissor_state scissor;
                unsigned stipple[32];
                struct pipe_clip_state clip;
+               struct nv40_fragment_program *fragprog;
+               struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
        } pipe_state;
 
        struct nv40_state state;
@@ -119,13 +124,6 @@ struct nv40_context {
                struct pipe_buffer *constant_buf;
        } vertprog;
 
-       struct {
-               struct nv40_fragment_program *active;
-
-               struct nv40_fragment_program *current;
-               struct pipe_buffer *constant_buf;
-       } fragprog;
-
        struct pipe_vertex_buffer  vtxbuf[PIPE_ATTRIB_MAX];
        struct pipe_vertex_element vtxelt[PIPE_ATTRIB_MAX];
 };
@@ -161,10 +159,6 @@ extern void nv40_vertprog_destroy(struct nv40_context *,
                                  struct nv40_vertex_program *);
 
 /* nv40_fragprog.c */
-extern void nv40_fragprog_translate(struct nv40_context *,
-                                   struct nv40_fragment_program *);
-extern void nv40_fragprog_bind(struct nv40_context *,
-                              struct nv40_fragment_program *);
 extern void nv40_fragprog_destroy(struct nv40_context *,
                                  struct nv40_fragment_program *);
 
@@ -177,6 +171,7 @@ extern void nv40_state_tex_update(struct nv40_context *nv40);
 extern struct nv40_state_entry nv40_state_clip;
 extern struct nv40_state_entry nv40_state_scissor;
 extern struct nv40_state_entry nv40_state_stipple;
+extern struct nv40_state_entry nv40_state_fragprog;
 
 /* nv40_vbo.c */
 extern boolean nv40_draw_arrays(struct pipe_context *, unsigned mode,
index 07a418c1e9fdc83d57fdd3f1ab737fa6f0f14af6..bfc75eb462016cdbec3a7602183fadf9dedf5ad7 100644 (file)
@@ -668,7 +668,7 @@ nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc,
        return TRUE;
 }
 
-void
+static void
 nv40_fragprog_translate(struct nv40_context *nv40,
                        struct nv40_fragment_program *fp)
 {
@@ -750,72 +750,66 @@ nv40_fragprog_translate(struct nv40_context *nv40,
        fp->insn[fpc->inst_offset + 3] = 0x00000000;
        
        fp->translated = TRUE;
-       fp->on_hw = FALSE;
 out_err:
        tgsi_parse_free(&parse);
        free(fpc);
 }
 
-void
-nv40_fragprog_bind(struct nv40_context *nv40, struct nv40_fragment_program *fp)
+static void
+nv40_fragprog_upload(struct nv40_context *nv40,
+                    struct nv40_fragment_program *fp)
 {
        struct pipe_winsys *ws = nv40->pipe.winsys;
-       struct nouveau_stateobj *so;
+       const uint32_t le = 1;
+       uint32_t *map;
        int i;
 
-       if (!fp->translated) {
-               nv40_fragprog_translate(nv40, fp);
-               if (!fp->translated)
-                       assert(0);
-       }
+       map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
 
-       if (fp->nr_consts) {
-               float *map = ws->buffer_map(ws, nv40->fragprog.constant_buf,
-                                           PIPE_BUFFER_USAGE_CPU_READ);
-               for (i = 0; i < fp->nr_consts; i++) {
-                       struct nv40_fragment_program_data *fpd = &fp->consts[i];
-                       uint32_t *p = &fp->insn[fpd->offset];
-                       uint32_t *cb = (uint32_t *)&map[fpd->index * 4];
+#if 0
+       for (i = 0; i < fp->insn_len; i++) {
+               NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
+       }
+#endif
 
-                       if (!memcmp(p, cb, 4 * sizeof(float)))
-                               continue;
-                       memcpy(p, cb, 4 * sizeof(float));
-                       fp->on_hw = 0;
+       if ((*(const uint8_t *)&le)) {
+               for (i = 0; i < fp->insn_len; i++) {
+                       map[i] = fp->insn[i];
+               }
+       } else {
+               /* Weird swapping for big-endian chips */
+               for (i = 0; i < fp->insn_len; i++) {
+                       map[i] = ((fp->insn[i] & 0xffff) << 16) |
+                                 ((fp->insn[i] >> 16) & 0xffff);
                }
-               ws->buffer_unmap(ws, nv40->fragprog.constant_buf);
        }
 
-       if (!fp->on_hw) {
-               const uint32_t le = 1;
-               uint32_t *map;
-
-               if (!fp->buffer)
-                       fp->buffer = ws->buffer_create(ws, 0x100, 0,
-                                                      fp->insn_len * 4);
-               map = ws->buffer_map(ws, fp->buffer,
-                                    PIPE_BUFFER_USAGE_CPU_WRITE);
+       ws->buffer_unmap(ws, fp->buffer);
+}
 
-#if 0
-               for (i = 0; i < fp->insn_len; i++) {
-                       NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
-               }
-#endif
+static boolean
+nv40_fragprog_validate(struct nv40_context *nv40)
+{
+       struct nv40_fragment_program *fp = nv40->pipe_state.fragprog;
+       struct pipe_buffer *constbuf =
+               nv40->pipe_state.constbuf[PIPE_SHADER_FRAGMENT];
+       struct pipe_winsys *ws = nv40->pipe.winsys;
+       struct nouveau_stateobj *so;
+       unsigned new_program = FALSE;
+       int i;
 
-               if ((*(const uint8_t *)&le)) {
-                       for (i = 0; i < fp->insn_len; i++) {
-                               map[i] = fp->insn[i];
-                       }
-               } else {
-                       /* Weird swapping for big-endian chips */
-                       for (i = 0; i < fp->insn_len; i++) {
-                               map[i] = ((fp->insn[i] & 0xffff) << 16) |
-                                         ((fp->insn[i] >> 16) & 0xffff);
-                       }
-               }
+       if (fp->translated)
+               goto update_constants;
 
-               ws->buffer_unmap(ws, fp->buffer);
-               fp->on_hw = TRUE;
+       nv40_fragprog_translate(nv40, fp);
+       if (!fp->translated) {
+               nv40->fallback |= NV40_FALLBACK_RAST;
+               return FALSE;
        }
+       new_program = TRUE;
+
+       fp->buffer = ws->buffer_create(ws, 0x100, 0, fp->insn_len * 4);
+       nv40_fragprog_upload(nv40, fp);
 
        so = so_new(4, 1);
        so_method(so, nv40->hw->curie, NV40TCL_FP_ADDRESS, 1);
@@ -824,12 +818,33 @@ nv40_fragprog_bind(struct nv40_context *nv40, struct nv40_fragment_program *fp)
                  NV40TCL_FP_ADDRESS_DMA0, NV40TCL_FP_ADDRESS_DMA1);
        so_method(so, nv40->hw->curie, NV40TCL_FP_CONTROL, 1);
        so_data  (so, fp->fp_control);
-
-       so_emit(nv40->nvws, so);
        so_ref(so, &fp->so);
        so_ref(NULL, &so);
 
-       nv40->fragprog.active = fp;
+update_constants:
+       if (fp->nr_consts) {
+               boolean new_consts = FALSE;
+               float *map;
+               
+               map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ);
+               for (i = 0; i < fp->nr_consts; i++) {
+                       struct nv40_fragment_program_data *fpd = &fp->consts[i];
+                       uint32_t *p = &fp->insn[fpd->offset];
+                       uint32_t *cb = (uint32_t *)&map[fpd->index * 4];
+
+                       if (!memcmp(p, cb, 4 * sizeof(float)))
+                               continue;
+                       memcpy(p, cb, 4 * sizeof(float));
+                       new_consts = TRUE;
+               }
+               ws->buffer_unmap(ws, constbuf);
+
+               if (new_consts)
+                       nv40_fragprog_upload(nv40, fp);
+       }
+
+       so_ref(fp->so, &nv40->state.fragprog);
+       return new_program;
 }
 
 void
@@ -840,3 +855,11 @@ nv40_fragprog_destroy(struct nv40_context *nv40,
                free(fp->insn);
 }
 
+struct nv40_state_entry nv40_state_fragprog = {
+       .validate = nv40_fragprog_validate,
+       .dirty = {
+               .pipe = NV40_NEW_FRAGPROG,
+               .hw = NV40_NEW_FRAGPROG
+       }
+};
+
index 5af5fbe74658d83b9e022f1e59e7a3ee916e4977..811f3098ba7702082218c67860d7bb676ed9ed47 100644 (file)
@@ -125,7 +125,7 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit)
 void
 nv40_fragtex_bind(struct nv40_context *nv40)
 {
-       struct nv40_fragment_program *fp = nv40->fragprog.active;
+       struct nv40_fragment_program *fp = nv40->pipe_state.fragprog;
        unsigned samplers, unit;
 
        samplers = nv40->fp_samplers & ~fp->samplers;
index c203b00240314bdd48842ab90976a2959c8535ab..2886c6b0dc42194d5f8b653f1986ee4a77fe94c0 100644 (file)
@@ -523,9 +523,8 @@ static void
 nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso)
 {
        struct nv40_context *nv40 = nv40_context(pipe);
-       struct nv40_fragment_program *fp = hwcso;
 
-       nv40->fragprog.current = fp;
+       nv40->pipe_state.fragprog = hwcso;
        nv40->dirty |= NV40_NEW_FRAGPROG;
 }
 
@@ -578,7 +577,7 @@ nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
                nv40->dirty |= NV40_NEW_VERTPROG;
        } else
        if (shader == PIPE_SHADER_FRAGMENT) {
-               nv40->fragprog.constant_buf = buf->buffer;
+               nv40->pipe_state.constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
                nv40->dirty |= NV40_NEW_FRAGPROG;
        }
 }
index e82ab9de98aa049dc7a4bd1f0eaf4ad8bd2627e1..2701294a077a7e928565b518cb62a94ad361b4b0 100644 (file)
@@ -50,7 +50,6 @@ struct nv40_fragment_program {
        const struct pipe_shader_state *pipe;
 
        boolean translated;
-       boolean on_hw;
        unsigned samplers;
 
        uint32_t *insn;
index b5d0d68d6b167ca93941abee796e606f86f418df..e10e178432ed4084cddc207f0b7221e807ba446c 100644 (file)
@@ -19,21 +19,14 @@ nv40_state_emit_dummy_relocs(struct nv40_context *nv40)
                        continue;
                so_emit_reloc_markers(nv40->nvws, nv40->so_fragtex[i]);
        }
-       so_emit_reloc_markers(nv40->nvws, nv40->fragprog.active->so);
-}
-
-static boolean
-nv40_state_clip_validate(struct nv40_context *nv40)
-{
-       if (nv40->pipe_state.clip.nr)
-               nv40->fallback |= NV40_FALLBACK_TNL;
-       return FALSE;
+       so_emit_reloc_markers(nv40->nvws, nv40->state.fragprog);
 }
 
 static struct nv40_state_entry *render_states[] = {
        &nv40_state_clip,
        &nv40_state_scissor,
        &nv40_state_stipple,
+       &nv40_state_fragprog,
        NULL
 };
 
@@ -65,6 +58,15 @@ nv40_state_validate(struct nv40_context *nv40)
            !(nv40->fallback & NV40_FALLBACK_TNL)) {
                NOUVEAU_ERR("XXX: swtnl->hwtnl\n");
        }
+
+       if (nv40->fallback & NV40_FALLBACK_RAST &&
+           !(last_fallback & NV40_FALLBACK_RAST)) {
+               NOUVEAU_ERR("XXX: hwrast->swrast\n");
+       } else
+       if (last_fallback & NV40_FALLBACK_RAST &&
+           !(nv40->fallback & NV40_FALLBACK_RAST)) {
+               NOUVEAU_ERR("XXX: swrast->hwrast\n");
+       }
 }
 
 void
@@ -100,10 +102,8 @@ nv40_emit_hw_state(struct nv40_context *nv40)
                nv40->hw_dirty &= ~NV40_NEW_STIPPLE;
        }
 
-       if (nv40->dirty & NV40_NEW_FRAGPROG) {
-               nv40_fragprog_bind(nv40, nv40->fragprog.current);
-               /*XXX: clear NV40_NEW_FRAGPROG if no new program uploaded */
-       }
+       if (nv40->hw_dirty & NV40_NEW_FRAGPROG)
+               so_emit(nv40->nvws, nv40->state.fragprog);
 
        if (nv40->dirty_samplers || (nv40->dirty & NV40_NEW_FRAGPROG)) {
                nv40_fragtex_bind(nv40);