Merge remote branch 'upstream/gallium-0.1' into gallium-0.1
[mesa.git] / src / gallium / drivers / nv30 / nv30_state_emit.c
index 70b98836f0f0e8e10308cdb41a43cc552b56f3bf..eca1f0652cc68ed185e81618137d4d8aec10eb72 100644 (file)
@@ -1,10 +1,72 @@
 #include "nv30_context.h"
 #include "nv30_state.h"
 
+static struct nv30_state_entry *render_states[] = {
+       &nv30_state_framebuffer,
+       &nv30_state_rasterizer,
+       &nv30_state_scissor,
+       &nv30_state_stipple,
+       &nv30_state_blend,
+       &nv30_state_blend_colour,
+       &nv30_state_zsa,
+       &nv30_state_viewport,
+       NULL
+};
+
+static void
+nv30_state_do_validate(struct nv30_context *nv30,
+                      struct nv30_state_entry **states)
+{
+       const struct pipe_framebuffer_state *fb = &nv30->framebuffer;
+       unsigned i;
+
+       for (i = 0; i < fb->num_cbufs; i++)
+               fb->cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED;
+       if (fb->zsbuf)
+               fb->zsbuf->status = PIPE_SURFACE_STATUS_DEFINED;
+
+       while (*states) {
+               struct nv30_state_entry *e = *states;
+
+               if (nv30->dirty & e->dirty.pipe) {
+                       if (e->validate(nv30)) {
+                               nv30->state.dirty |= (1ULL << e->dirty.hw);
+                       }
+               }
+
+               states++;
+       }
+
+/*     TODO: uncomment when finished converting
+       nv30->dirty = 0;
+*/
+}
+
 void
 nv30_emit_hw_state(struct nv30_context *nv30)
 {
-       int i;
+       struct nv30_state *state = &nv30->state;
+       struct nv30_screen *screen = nv30->screen;
+       unsigned i;
+       uint64 states;
+
+       if (nv30->pctx_id != screen->cur_pctx) {
+               for (i = 0; i < NV30_STATE_MAX; i++) {
+                       if (state->hw[i] && screen->state[i] != state->hw[i])
+                               state->dirty |= (1ULL << i);
+               }
+
+               screen->cur_pctx = nv30->pctx_id;
+       }
+
+       for (i = 0, states = state->dirty; states; i++) {
+               if (!(states & (1ULL << i)))
+                       continue;
+               so_ref (state->hw[i], &nv30->screen->state[i]);
+               if (state->hw[i])
+                       so_emit(nv30->nvws, nv30->screen->state[i]);
+               states &= ~(1ULL << i);
+       }
 
        if (nv30->dirty & NV30_NEW_FRAGPROG) {
                nv30_fragprog_bind(nv30, nv30->fragprog.current);
@@ -28,39 +90,10 @@ nv30_emit_hw_state(struct nv30_context *nv30)
 
        nv30->dirty_samplers = 0;
 
-       /* Emit relocs for every referenced buffer.
-        * This is to ensure the bufmgr has an accurate idea of how
-        * the buffer is used.  This isn't very efficient, but we don't
-        * seem to take a significant performance hit.  Will be improved
-        * at some point.  Vertex arrays are emitted by nv30_vbo.c
-        */
-
-       /* Render targets */
-       if (nv30->rt_enable & NV34TCL_RT_ENABLE_COLOR0) {
-               BEGIN_RING(rankine, NV34TCL_DMA_COLOR0, 1);
-               OUT_RELOCo(nv30->rt[0], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-               BEGIN_RING(rankine, NV34TCL_COLOR0_OFFSET, 1);
-               OUT_RELOCl(nv30->rt[0], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-       }
+       so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FB]);
 
-       if (nv30->rt_enable & NV34TCL_RT_ENABLE_COLOR1) {
-               BEGIN_RING(rankine, NV34TCL_DMA_COLOR1, 1);
-               OUT_RELOCo(nv30->rt[1], NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-               BEGIN_RING(rankine, NV34TCL_COLOR1_OFFSET, 1);
-               OUT_RELOCl(nv30->rt[1], 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-       }
-
-       if (nv30->zeta) {
-               BEGIN_RING(rankine, NV34TCL_DMA_ZETA, 1);
-               OUT_RELOCo(nv30->zeta, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-               BEGIN_RING(rankine, NV34TCL_ZETA_OFFSET, 1);
-               OUT_RELOCl(nv30->zeta, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-               /* XXX allocate LMA */
-/*             BEGIN_RING(rankine, NV34TCL_LMA_DEPTH_OFFSET, 1);
-               OUT_RING(0);*/
-       }
-
-       /* Texture images */
+       /* Texture images, emitted in nv30_fragtex_build */
+#if 0
        for (i = 0; i < 16; i++) {
                if (!(nv30->fp_samplers & (1 << i)))
                        continue;
@@ -72,6 +105,7 @@ nv30_emit_hw_state(struct nv30_context *nv30)
                           NOUVEAU_BO_OR, NV34TCL_TX_FORMAT_DMA0,
                           NV34TCL_TX_FORMAT_DMA1);
        }
+#endif
 
        /* Fragment program */
        BEGIN_RING(rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1);
@@ -81,3 +115,35 @@ nv30_emit_hw_state(struct nv30_context *nv30)
                   NV34TCL_FP_ACTIVE_PROGRAM_DMA1);
 }
 
+boolean
+nv30_state_validate(struct nv30_context *nv30)
+{
+#if 0
+       boolean was_sw = nv30->fallback_swtnl ? TRUE : FALSE;
+
+       if (nv30->render_mode != HW) {
+               /* Don't even bother trying to go back to hw if none
+                * of the states that caused swtnl previously have changed.
+                */
+               if ((nv30->fallback_swtnl & nv30->dirty)
+                               != nv30->fallback_swtnl)
+                       return FALSE;
+
+               /* Attempt to go to hwtnl again */
+               nv30->pipe.flush(&nv30->pipe, 0, NULL);
+               nv30->dirty |= (NV30_NEW_VIEWPORT |
+                               NV30_NEW_VERTPROG |
+                               NV30_NEW_ARRAYS);
+               nv30->render_mode = HW;
+       }
+#endif
+       nv30_state_do_validate(nv30, render_states);
+#if 0
+       if (nv30->fallback_swtnl || nv30->fallback_swrast)
+               return FALSE;
+       
+       if (was_sw)
+               NOUVEAU_ERR("swtnl->hw\n");
+#endif
+       return TRUE;
+}