#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,
+ 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 & NV30_NEW_VERTPROG) {
- nv30_vertprog_bind(nv30, nv30->vertprog.current);
- nv30->dirty &= ~NV30_NEW_VERTPROG;
+ if (nv30->dirty & e->dirty.pipe) {
+ if (e->validate(nv30)) {
+ nv30->state.dirty |= (1ULL << e->dirty.hw);
+ }
+ }
+
+ states++;
}
- nv30->dirty_samplers = 0;
+/* TODO: uncomment when finished converting
+ nv30->dirty = 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
- */
+void
+nv30_emit_hw_state(struct nv30_context *nv30)
+{
+ struct nv30_state *state = &nv30->state;
+ struct nv30_screen *screen = nv30->screen;
+ unsigned i, samplers;
+ uint64 states;
- /* 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);
- }
+ 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);
+ }
- 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);
+ screen->cur_pctx = nv30->pctx_id;
}
- 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);*/
+ 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);
}
- /* Texture images */
- for (i = 0; i < 16; i++) {
- if (!(nv30->fp_samplers & (1 << i)))
+ 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;
- 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);
+ so_emit_reloc_markers(nv30->nvws,
+ state->hw[NV30_STATE_FRAGTEX0+i]);
+ samplers &= ~(1ULL << i);
}
-
- /* 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);
+ so_emit_reloc_markers(nv30->nvws, state->hw[NV30_STATE_FRAGPROG]);
}
+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;
+}