Merge commit 'origin/gallium-0.2' into gallium-xlib-rework
[mesa.git] / src / gallium / drivers / nv30 / nv30_state_emit.c
index eda2fd45f569e24ff3112f4cef2a3e84188ac95e..9480695d6e57b1a147286cf3c84a16d306b81d5c 100644 (file)
 #include "nv30_context.h"
 #include "nv30_state.h"
 
-void
-nv30_emit_hw_state(struct nv30_context *nv30)
+static struct nv30_state_entry *render_states[] = {
+       &nv30_state_framebuffer,
+       &nv30_state_rasterizer,
+       &nv30_state_scissor,
+       &nv30_state_stipple,
+       &nv30_state_fragprog,
+       &nv30_state_fragtex,
+       &nv30_state_vertprog,
+       &nv30_state_blend,
+       &nv30_state_blend_colour,
+       &nv30_state_zsa,
+       &nv30_state_viewport,
+       &nv30_state_vbo,
+       NULL
+};
+
+static void
+nv30_state_do_validate(struct nv30_context *nv30,
+                      struct nv30_state_entry **states)
 {
-       int i;
+       const struct pipe_framebuffer_state *fb = &nv30->framebuffer;
+       unsigned i;
 
-       if (nv30->dirty & NV30_NEW_FRAGPROG) {
-               nv30_fragprog_bind(nv30, nv30->fragprog.current);
-               /*XXX: clear NV30_NEW_FRAGPROG if no new program uploaded */
-       }
+       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;
 
-       if (nv30->dirty_samplers || (nv30->dirty & NV30_NEW_FRAGPROG)) {
-               nv30_fragtex_bind(nv30);
-/*
-               BEGIN_RING(rankine, NV34TCL_TX_CACHE_CTL, 1);
-               OUT_RING  (2);
-               BEGIN_RING(rankine, NV34TCL_TX_CACHE_CTL, 1);
-               OUT_RING  (1);*/
-               nv30->dirty &= ~NV30_NEW_FRAGPROG;
-       }
+       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);
+                       }
+               }
 
-       if (nv30->dirty & NV30_NEW_VERTPROG) {
-               nv30_vertprog_bind(nv30, nv30->vertprog.current);
-               nv30->dirty &= ~NV30_NEW_VERTPROG;
+               states++;
        }
+       nv30->dirty = 0;
+}
 
-       nv30->dirty_samplers = 0;
+void
+nv30_state_emit(struct nv30_context *nv30)
+{
+       struct nv30_state *state = &nv30->state;
+       struct nv30_screen *screen = nv30->screen;
+       unsigned i, samplers;
+       uint64_t states;
 
-       /* 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
-        */
+       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);
+               }
 
-       /* 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);
+               screen->cur_pctx = nv30->pctx_id;
        }
 
-       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);
+       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->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);*/
+       state->dirty = 0;
+
+       so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FB]);
+       for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
+               if (!(samplers & (1 << i)))
+                       continue;
+               so_emit_reloc_markers(nv30->nvws,
+                                     state->hw[NV30_STATE_FRAGTEX0+i]);
+               samplers &= ~(1ULL << i);
        }
+       so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FRAGPROG]);
+       if (state->hw[NV30_STATE_VTXBUF] /*&& nv30->render_mode == HW*/)
+               so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_VTXBUF]);
+}
 
-       /* Texture images, emitted in nv30_fragtex_build */
+boolean
+nv30_state_validate(struct nv30_context *nv30)
+{
 #if 0
-       for (i = 0; i < 16; i++) {
-               if (!(nv30->fp_samplers & (1 << i)))
-                       continue;
-               BEGIN_RING(rankine, NV34TCL_TX_OFFSET(i), 2);
-               OUT_RELOCl(nv30->tex[i].buffer, 0, NOUVEAU_BO_VRAM |
-                          NOUVEAU_BO_GART | NOUVEAU_BO_RD);
-               OUT_RELOCd(nv30->tex[i].buffer, nv30->tex[i].format,
-                          NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD |
-                          NOUVEAU_BO_OR, NV34TCL_TX_FORMAT_DMA0,
-                          NV34TCL_TX_FORMAT_DMA1);
+       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
-
-       /* Fragment program */
-       BEGIN_RING(rankine, NV34TCL_FP_ACTIVE_PROGRAM, 1);
-       OUT_RELOC (nv30->fragprog.active->buffer, 0, NOUVEAU_BO_VRAM |
-                  NOUVEAU_BO_GART | NOUVEAU_BO_RD | NOUVEAU_BO_LOW |
-                  NOUVEAU_BO_OR, NV34TCL_FP_ACTIVE_PROGRAM_DMA0,
-                  NV34TCL_FP_ACTIVE_PROGRAM_DMA1);
+       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;
 }
-