nv30, nv40: non-trivially unify nv[34]0_state_emit.c
authorLuca Barbieri <luca@luca-barbieri.com>
Sun, 21 Feb 2010 10:33:15 +0000 (11:33 +0100)
committerYounes Manton <younes.m@gmail.com>
Mon, 15 Mar 2010 04:03:01 +0000 (00:03 -0400)
The files are the same except for swtnl support on nv40 and for
texture cache flushing on nv40.

Unify them, and use a macro to define 4 versions of render_states,
for all combinations of nvfx and hwtnl/swtnl.

14 files changed:
src/gallium/drivers/nv30/Makefile
src/gallium/drivers/nv30/nv30_context.c
src/gallium/drivers/nv30/nv30_context.h
src/gallium/drivers/nv30/nv30_state_emit.c [deleted file]
src/gallium/drivers/nv30/nv30_vbo.c
src/gallium/drivers/nv40/Makefile
src/gallium/drivers/nv40/nv40_context.c
src/gallium/drivers/nv40/nv40_context.h
src/gallium/drivers/nv40/nv40_draw.c
src/gallium/drivers/nv40/nv40_state_emit.c [deleted file]
src/gallium/drivers/nv40/nv40_vbo.c
src/gallium/drivers/nvfx/Makefile
src/gallium/drivers/nvfx/nvfx_context.h
src/gallium/drivers/nvfx/nvfx_state_emit.c [new file with mode: 0644]

index f18295cefc21241a5ce64bc4442cc43a9446b6d6..3067e45062848b35a1aa136bd7bca8ca669bab5a 100644 (file)
@@ -13,7 +13,6 @@ C_SOURCES = \
        nv30_screen.c \
        nv30_state.c \
        nv30_state_blend.c \
-       nv30_state_emit.c \
        nv30_state_fb.c \
        nv30_state_rasterizer.c \
        nv30_state_scissor.c \
index ee2c465bc6d6e4300bc56a0f0e222bfaf573bc9f..6fe8cb3e324e70356380ef54b1a3e633240a33a2 100644 (file)
@@ -69,7 +69,7 @@ nv30_create(struct pipe_screen *pscreen, void *priv)
        nvfx->pipe.is_buffer_referenced = nouveau_is_buffer_referenced;
 
        screen->base.channel->user_private = nvfx;
-       screen->base.channel->flush_notify = nv30_state_flush_notify;
+       screen->base.channel->flush_notify = nvfx_state_flush_notify;
 
        nvfx->is_nv4x = screen->is_nv4x;
 
index 9f28d49706fd00e8c999a17d3ae8e10e9396730d..a6767da4dc19e40d06908ec006a6b193991e6c3a 100644 (file)
@@ -24,9 +24,6 @@ extern void nv30_fragprog_destroy(struct nvfx_context *,
 extern void nv30_fragtex_bind(struct nvfx_context *);
 
 /* nv30_state.c and friends */
-extern boolean nv30_state_validate(struct nvfx_context *nvfx);
-extern void nv30_state_emit(struct nvfx_context *nvfx);
-extern void nv30_state_flush_notify(struct nouveau_channel *chan);
 extern struct nvfx_state_entry nv30_state_rasterizer;
 extern struct nvfx_state_entry nv30_state_scissor;
 extern struct nvfx_state_entry nv30_state_stipple;
diff --git a/src/gallium/drivers/nv30/nv30_state_emit.c b/src/gallium/drivers/nv30/nv30_state_emit.c
deleted file mode 100644 (file)
index 6df9361..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-#include "nv30_context.h"
-#include "nvfx_state.h"
-
-static struct nvfx_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_sr,
-       &nv30_state_viewport,
-       &nv30_state_vbo,
-       NULL
-};
-
-static void
-nv30_state_do_validate(struct nvfx_context *nvfx,
-                      struct nvfx_state_entry **states)
-{
-       while (*states) {
-               struct nvfx_state_entry *e = *states;
-
-               if (nvfx->dirty & e->dirty.pipe) {
-                       if (e->validate(nvfx))
-                               nvfx->state.dirty |= (1ULL << e->dirty.hw);
-               }
-
-               states++;
-       }
-       nvfx->dirty = 0;
-}
-
-void
-nv30_state_emit(struct nvfx_context *nvfx)
-{
-       struct nouveau_channel *chan = nvfx->screen->base.channel;
-       struct nvfx_state *state = &nvfx->state;
-       struct nvfx_screen *screen = nvfx->screen;
-       unsigned i;
-       uint64_t states;
-
-       /* XXX: racy!
-        */
-       if (nvfx != screen->cur_ctx) {
-               for (i = 0; i < NVFX_STATE_MAX; i++) {
-                       if (state->hw[i] && screen->state[i] != state->hw[i])
-                               state->dirty |= (1ULL << i);
-               }
-
-               screen->cur_ctx = nvfx;
-       }
-
-       for (i = 0, states = state->dirty; states; i++) {
-               if (!(states & (1ULL << i)))
-                       continue;
-               so_ref (state->hw[i], &nvfx->screen->state[i]);
-               if (state->hw[i])
-                       so_emit(chan, nvfx->screen->state[i]);
-               states &= ~(1ULL << i);
-       }
-
-       state->dirty = 0;
-}
-
-void
-nv30_state_flush_notify(struct nouveau_channel *chan)
-{
-       struct nvfx_context *nvfx = chan->user_private;
-       struct nvfx_state *state = &nvfx->state;
-       unsigned i, samplers;
-
-       so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FB]);
-       for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
-               if (!(samplers & (1 << i)))
-                       continue;
-               so_emit_reloc_markers(chan,
-                                     state->hw[NVFX_STATE_FRAGTEX0+i]);
-               samplers &= ~(1ULL << i);
-       }
-       so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FRAGPROG]);
-       if (state->hw[NVFX_STATE_VTXBUF] /*&& nvfx->render_mode == HW*/)
-               so_emit_reloc_markers(chan, state->hw[NVFX_STATE_VTXBUF]);
-}
-
-boolean
-nv30_state_validate(struct nvfx_context *nvfx)
-{
-#if 0
-       boolean was_sw = nvfx->fallback_swtnl ? TRUE : FALSE;
-
-       if (nvfx->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 ((nvfx->fallback_swtnl & nvfx->dirty)
-                               != nvfx->fallback_swtnl)
-                       return FALSE;
-
-               /* Attempt to go to hwtnl again */
-               nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
-               nvfx->dirty |= (NVFX_NEW_VIEWPORT |
-                               NVFX_NEW_VERTPROG |
-                               NVFX_NEW_ARRAYS);
-               nvfx->render_mode = HW;
-       }
-#endif
-       nv30_state_do_validate(nvfx, render_states);
-#if 0
-       if (nvfx->fallback_swtnl || nvfx->fallback_swrast)
-               return FALSE;
-       
-       if (was_sw)
-               NOUVEAU_ERR("swtnl->hw\n");
-#endif
-       return TRUE;
-}
index 119fa59890e4facae2e854a4c06436b120fd5f19..2b4401e5330ffa7ad1f54df18db770d675fc8145 100644 (file)
@@ -175,7 +175,7 @@ nv30_draw_arrays(struct pipe_context *pipe,
        unsigned restart = 0;
 
        nv30_vbo_set_idxbuf(nvfx, NULL, 0);
-       if (FORCE_SWTNL || !nv30_state_validate(nvfx)) {
+       if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) {
                /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
                                                mode, start, count);*/
                return;
@@ -184,7 +184,7 @@ nv30_draw_arrays(struct pipe_context *pipe,
        while (count) {
                unsigned vc, nr;
 
-               nv30_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256,
                                        mode, start, count, &restart);
@@ -238,7 +238,7 @@ nv30_draw_elements_u08(struct nvfx_context *nvfx, void *ib,
                uint8_t *elts = (uint8_t *)ib + start;
                unsigned vc, push, restart = 0;
 
-               nv30_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2,
                                        mode, start, count, &restart);
@@ -289,7 +289,7 @@ nv30_draw_elements_u16(struct nvfx_context *nvfx, void *ib,
                uint16_t *elts = (uint16_t *)ib + start;
                unsigned vc, push, restart = 0;
 
-               nv30_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2,
                                        mode, start, count, &restart);
@@ -340,7 +340,7 @@ nv30_draw_elements_u32(struct nvfx_context *nvfx, void *ib,
                uint32_t *elts = (uint32_t *)ib + start;
                unsigned vc, push, restart = 0;
 
-               nv30_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1,
                                        mode, start, count, &restart);
@@ -416,7 +416,7 @@ nv30_draw_elements_vbo(struct pipe_context *pipe,
        while (count) {
                unsigned nr, vc;
 
-               nv30_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256,
                                        mode, start, count, &restart);
@@ -465,7 +465,7 @@ nv30_draw_elements(struct pipe_context *pipe,
        boolean idxbuf;
 
        idxbuf = nv30_vbo_set_idxbuf(nvfx, indexBuffer, indexSize);
-       if (FORCE_SWTNL || !nv30_state_validate(nvfx)) {
+       if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) {
                /*return nv30_draw_elements_swtnl(pipe, NULL, 0,
                                                mode, start, count);*/
                return;
index 8d09ef807f878c785481d06b4fb60259c63e1564..b0c0c09d517e5959c08951f31d185afda452dbc0 100644 (file)
@@ -13,7 +13,6 @@ C_SOURCES = \
        nv40_screen.c \
        nv40_state.c \
        nv40_state_blend.c \
-       nv40_state_emit.c \
        nv40_state_fb.c \
        nv40_state_rasterizer.c \
        nv40_state_scissor.c \
index 9934b582eefe46e7240320989bce714a8f3ab2c3..12f57377cde938961386e9b111abb463d64d3f71 100644 (file)
@@ -69,7 +69,7 @@ nv40_create(struct pipe_screen *pscreen, void *priv)
        nvfx->pipe.is_buffer_referenced = nouveau_is_buffer_referenced;
 
        screen->base.channel->user_private = nvfx;
-       screen->base.channel->flush_notify = nv40_state_flush_notify;
+       screen->base.channel->flush_notify = nvfx_state_flush_notify;
 
        nvfx->is_nv4x = screen->is_nv4x;
 
index e7c6d5ad86d1dbfc4b6035d8d5626a9cf9ddd822..0b875bcb0659fbb04edbee5e35919773a52820c0 100644 (file)
@@ -28,10 +28,6 @@ extern void nv40_fragprog_destroy(struct nvfx_context *,
 extern void nv40_fragtex_bind(struct nvfx_context *);
 
 /* nv40_state.c and friends */
-extern boolean nv40_state_validate(struct nvfx_context *nvfx);
-extern boolean nv40_state_validate_swtnl(struct nvfx_context *nvfx);
-extern void nv40_state_emit(struct nvfx_context *nvfx);
-extern void nv40_state_flush_notify(struct nouveau_channel *chan);
 extern struct nvfx_state_entry nv40_state_rasterizer;
 extern struct nvfx_state_entry nv40_state_scissor;
 extern struct nvfx_state_entry nv40_state_stipple;
index cce1c64621d2b765f17828e4c5b205ddb4e9bf0c..87d2689d54b53af6bbc84fc60bec1a782e043c67 100644 (file)
@@ -98,7 +98,7 @@ nv40_render_prim(struct draw_stage *stage, struct prim_header *prim,
                        assert(0);
                }
                FIRE_RING(chan);
-               nv40_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
        }
 
        /* Switch primitive modes if necessary */
@@ -245,10 +245,10 @@ nv40_draw_elements_swtnl(struct pipe_context *pipe,
        unsigned i;
        void *map;
 
-       if (!nv40_state_validate_swtnl(nvfx))
+       if (!nvfx_state_validate_swtnl(nvfx))
                return;
        nvfx->state.dirty &= ~(1ULL << NVFX_STATE_VTXBUF);
-       nv40_state_emit(nvfx);
+       nvfx_state_emit(nvfx);
 
        for (i = 0; i < nvfx->vtxbuf_nr; i++) {
                map = pipe_buffer_map(pscreen, nvfx->vtxbuf[i].buffer,
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
deleted file mode 100644 (file)
index 5c437f9..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-#include "nv40_context.h"
-#include "nvfx_state.h"
-#include "draw/draw_context.h"
-
-static struct nvfx_state_entry *render_states[] = {
-       &nv40_state_framebuffer,
-       &nv40_state_rasterizer,
-       &nv40_state_scissor,
-       &nv40_state_stipple,
-       &nv40_state_fragprog,
-       &nv40_state_fragtex,
-       &nv40_state_vertprog,
-       &nv40_state_blend,
-       &nv40_state_blend_colour,
-       &nv40_state_zsa,
-       &nv40_state_sr,
-       &nv40_state_viewport,
-       &nv40_state_vbo,
-       NULL
-};
-
-static struct nvfx_state_entry *swtnl_states[] = {
-       &nv40_state_framebuffer,
-       &nv40_state_rasterizer,
-       &nv40_state_scissor,
-       &nv40_state_stipple,
-       &nv40_state_fragprog,
-       &nv40_state_fragtex,
-       &nv40_state_vertprog,
-       &nv40_state_blend,
-       &nv40_state_blend_colour,
-       &nv40_state_zsa,
-       &nv40_state_sr,
-       &nv40_state_viewport,
-       &nv40_state_vtxfmt,
-       NULL
-};
-
-static void
-nv40_state_do_validate(struct nvfx_context *nvfx,
-                      struct nvfx_state_entry **states)
-{
-       while (*states) {
-               struct nvfx_state_entry *e = *states;
-
-               if (nvfx->dirty & e->dirty.pipe) {
-                       if (e->validate(nvfx))
-                               nvfx->state.dirty |= (1ULL << e->dirty.hw);
-               }
-
-               states++;
-       }
-       nvfx->dirty = 0;
-}
-
-void
-nv40_state_emit(struct nvfx_context *nvfx)
-{
-       struct nvfx_state *state = &nvfx->state;
-       struct nvfx_screen *screen = nvfx->screen;
-       struct nouveau_channel *chan = screen->base.channel;
-       struct nouveau_grobj *eng3d = screen->eng3d;
-       unsigned i;
-       uint64_t states;
-
-       /* XXX: race conditions
-        */
-       if (nvfx != screen->cur_ctx) {
-               for (i = 0; i < NVFX_STATE_MAX; i++) {
-                       if (state->hw[i] && screen->state[i] != state->hw[i])
-                               state->dirty |= (1ULL << i);
-               }
-
-               screen->cur_ctx = nvfx;
-       }
-
-       for (i = 0, states = state->dirty; states; i++) {
-               if (!(states & (1ULL << i)))
-                       continue;
-               so_ref (state->hw[i], &nvfx->screen->state[i]);
-               if (state->hw[i])
-                       so_emit(chan, nvfx->screen->state[i]);
-               states &= ~(1ULL << i);
-       }
-
-       if (state->dirty & ((1ULL << NVFX_STATE_FRAGPROG) |
-                           (1ULL << NVFX_STATE_FRAGTEX0))) {
-               BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
-               OUT_RING  (chan, 2);
-               BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
-               OUT_RING  (chan, 1);
-       }
-
-       state->dirty = 0;
-}
-
-void
-nv40_state_flush_notify(struct nouveau_channel *chan)
-{
-       struct nvfx_context *nvfx = chan->user_private;
-       struct nvfx_state *state = &nvfx->state;
-       unsigned i, samplers;
-
-       so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FB]);
-       for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
-               if (!(samplers & (1 << i)))
-                       continue;
-               so_emit_reloc_markers(chan,
-                                     state->hw[NVFX_STATE_FRAGTEX0+i]);
-               samplers &= ~(1ULL << i);
-       }
-       so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FRAGPROG]);
-       if (state->hw[NVFX_STATE_VTXBUF] && nvfx->render_mode == HW)
-               so_emit_reloc_markers(chan, state->hw[NVFX_STATE_VTXBUF]);
-}
-
-boolean
-nv40_state_validate(struct nvfx_context *nvfx)
-{
-       boolean was_sw = nvfx->fallback_swtnl ? TRUE : FALSE;
-
-       if (nvfx->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 ((nvfx->fallback_swtnl & nvfx->dirty)
-                               != nvfx->fallback_swtnl)
-                       return FALSE;
-
-               /* Attempt to go to hwtnl again */
-               nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
-               nvfx->dirty |= (NVFX_NEW_VIEWPORT |
-                               NVFX_NEW_VERTPROG |
-                               NVFX_NEW_ARRAYS);
-               nvfx->render_mode = HW;
-       }
-
-       nv40_state_do_validate(nvfx, render_states);
-       if (nvfx->fallback_swtnl || nvfx->fallback_swrast)
-               return FALSE;
-       
-       if (was_sw)
-               NOUVEAU_ERR("swtnl->hw\n");
-
-       return TRUE;
-}
-
-boolean
-nv40_state_validate_swtnl(struct nvfx_context *nvfx)
-{
-       struct draw_context *draw = nvfx->draw;
-
-       /* Setup for swtnl */
-       if (nvfx->render_mode == HW) {
-               NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx->fallback_swtnl);
-               nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
-               nvfx->dirty |= (NVFX_NEW_VIEWPORT |
-                               NVFX_NEW_VERTPROG |
-                               NVFX_NEW_ARRAYS);
-               nvfx->render_mode = SWTNL;
-       }
-
-       if (nvfx->draw_dirty & NVFX_NEW_VERTPROG)
-               draw_bind_vertex_shader(draw, nvfx->vertprog->draw);
-
-       if (nvfx->draw_dirty & NVFX_NEW_RAST)
-               draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe);
-
-       if (nvfx->draw_dirty & NVFX_NEW_UCP)
-               draw_set_clip_state(draw, &nvfx->clip);
-
-       if (nvfx->draw_dirty & NVFX_NEW_VIEWPORT)
-               draw_set_viewport_state(draw, &nvfx->viewport);
-
-       if (nvfx->draw_dirty & NVFX_NEW_ARRAYS) {
-               draw_set_vertex_buffers(draw, nvfx->vtxbuf_nr, nvfx->vtxbuf);
-               draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe);
-       }
-
-       nv40_state_do_validate(nvfx, swtnl_states);
-       if (nvfx->fallback_swrast) {
-               NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx->fallback_swrast);
-               return FALSE;
-       }
-
-       nvfx->draw_dirty = 0;
-       return TRUE;
-}
-
index 0738d5c93b4f6b11c43afbe7337a0a8d53b4ce11..456b508d4380aa1086a62af01f2f12402f6ef258 100644 (file)
@@ -176,7 +176,7 @@ nv40_draw_arrays(struct pipe_context *pipe,
        unsigned restart;
 
        nv40_vbo_set_idxbuf(nvfx, NULL, 0);
-       if (FORCE_SWTNL || !nv40_state_validate(nvfx)) {
+       if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) {
                nv40_draw_elements_swtnl(pipe, NULL, 0,
                                          mode, start, count);
                 return;
@@ -185,7 +185,7 @@ nv40_draw_arrays(struct pipe_context *pipe,
        while (count) {
                unsigned vc, nr;
 
-               nv40_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256,
                                        mode, start, count, &restart);
@@ -239,7 +239,7 @@ nv40_draw_elements_u08(struct nvfx_context *nvfx, void *ib,
                uint8_t *elts = (uint8_t *)ib + start;
                unsigned vc, push, restart;
 
-               nv40_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2,
                                        mode, start, count, &restart);
@@ -290,7 +290,7 @@ nv40_draw_elements_u16(struct nvfx_context *nvfx, void *ib,
                uint16_t *elts = (uint16_t *)ib + start;
                unsigned vc, push, restart;
 
-               nv40_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 2,
                                        mode, start, count, &restart);
@@ -341,7 +341,7 @@ nv40_draw_elements_u32(struct nvfx_context *nvfx, void *ib,
                uint32_t *elts = (uint32_t *)ib + start;
                unsigned vc, push, restart;
 
-               nv40_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 5, 1,
                                        mode, start, count, &restart);
@@ -417,7 +417,7 @@ nv40_draw_elements_vbo(struct pipe_context *pipe,
        while (count) {
                unsigned nr, vc;
 
-               nv40_state_emit(nvfx);
+               nvfx_state_emit(nvfx);
 
                vc = nouveau_vbuf_split(AVAIL_RING(chan), 6, 256,
                                        mode, start, count, &restart);
@@ -466,7 +466,7 @@ nv40_draw_elements(struct pipe_context *pipe,
        boolean idxbuf;
 
        idxbuf = nv40_vbo_set_idxbuf(nvfx, indexBuffer, indexSize);
-       if (FORCE_SWTNL || !nv40_state_validate(nvfx)) {
+       if (FORCE_SWTNL || !nvfx_state_validate(nvfx)) {
                nv40_draw_elements_swtnl(pipe, NULL, 0,
                                          mode, start, count);
                 return;
index 699cbedbc84aefe1dc1121bdc6521a937b1a24d2..0eb1bebeb3096b8986f666654bbab9cad5849a22 100644 (file)
@@ -5,6 +5,7 @@ LIBNAME = nvfx
 
 C_SOURCES = \
        nvfx_clear.c \
+       nvfx_state_emit.c \
        nvfx_transfer.c
 
 include ../../Makefile.template
index 38d1142ff9703741784cec2c9c74f1dbc9c5941c..3d4bc6bbc937b9dbbd75950cdfeed045ce071dc0 100644 (file)
@@ -185,6 +185,12 @@ struct nvfx_state_entry {
 extern void nvfx_clear(struct pipe_context *pipe, unsigned buffers,
                       const float *rgba, double depth, unsigned stencil);
 
+/* nvfx_state_emit.c */
+extern void nvfx_state_flush_notify(struct nouveau_channel *chan);
+extern boolean nvfx_state_validate(struct nvfx_context *nvfx);
+extern boolean nvfx_state_validate_swtnl(struct nvfx_context *nvfx);
+extern void nvfx_state_emit(struct nvfx_context *nvfx);
+
 /* nvfx_transfer.c */
 extern void nvfx_init_transfer_functions(struct nvfx_context *nvfx);
 
diff --git a/src/gallium/drivers/nvfx/nvfx_state_emit.c b/src/gallium/drivers/nvfx/nvfx_state_emit.c
new file mode 100644 (file)
index 0000000..9582ba9
--- /dev/null
@@ -0,0 +1,188 @@
+#include "nv30/nv30_context.h"
+#include "nv40/nv40_context.h"
+#include "nvfx_state.h"
+#include "draw/draw_context.h"
+
+#define RENDER_STATES(name, nvxx, vbo) \
+static struct nvfx_state_entry *name##_render_states[] = { \
+       &nvxx##_state_framebuffer, \
+       &nvxx##_state_rasterizer, \
+       &nvxx##_state_scissor, \
+       &nvxx##_state_stipple, \
+       &nvxx##_state_fragprog, \
+       &nvxx##_state_fragtex, \
+       &nvxx##_state_vertprog, \
+       &nvxx##_state_blend, \
+       &nvxx##_state_blend_colour, \
+       &nvxx##_state_zsa, \
+       &nvxx##_state_sr, \
+       &nvxx##_state_viewport, \
+       &nvxx##_state_##vbo, \
+       NULL \
+}
+
+RENDER_STATES(nv30, nv30, vbo);
+RENDER_STATES(nv30_swtnl, nv30, vbo); /* TODO: replace with vtxfmt once draw is unified */
+RENDER_STATES(nv40, nv40, vbo);
+RENDER_STATES(nv40_swtnl, nv40, vtxfmt);
+
+static void
+nvfx_state_do_validate(struct nvfx_context *nvfx,
+                      struct nvfx_state_entry **states)
+{
+       while (*states) {
+               struct nvfx_state_entry *e = *states;
+
+               if (nvfx->dirty & e->dirty.pipe) {
+                       if (e->validate(nvfx))
+                               nvfx->state.dirty |= (1ULL << e->dirty.hw);
+               }
+
+               states++;
+       }
+       nvfx->dirty = 0;
+}
+
+void
+nvfx_state_emit(struct nvfx_context *nvfx)
+{
+       struct nvfx_state *state = &nvfx->state;
+       struct nvfx_screen *screen = nvfx->screen;
+       struct nouveau_channel *chan = screen->base.channel;
+       struct nouveau_grobj *eng3d = screen->eng3d;
+       unsigned i;
+       uint64_t states;
+
+       /* XXX: race conditions
+        */
+       if (nvfx != screen->cur_ctx) {
+               for (i = 0; i < NVFX_STATE_MAX; i++) {
+                       if (state->hw[i] && screen->state[i] != state->hw[i])
+                               state->dirty |= (1ULL << i);
+               }
+
+               screen->cur_ctx = nvfx;
+       }
+
+       for (i = 0, states = state->dirty; states; i++) {
+               if (!(states & (1ULL << i)))
+                       continue;
+               so_ref (state->hw[i], &nvfx->screen->state[i]);
+               if (state->hw[i])
+                       so_emit(chan, nvfx->screen->state[i]);
+               states &= ~(1ULL << i);
+       }
+
+       /* TODO: could nv30 need this or something similar too? */
+       if(nvfx->is_nv4x) {
+               if (state->dirty & ((1ULL << NVFX_STATE_FRAGPROG) |
+                                   (1ULL << NVFX_STATE_FRAGTEX0))) {
+                       BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
+                       OUT_RING  (chan, 2);
+                       BEGIN_RING(chan, eng3d, NV40TCL_TEX_CACHE_CTL, 1);
+                       OUT_RING  (chan, 1);
+               }
+       }
+       state->dirty = 0;
+}
+
+void
+nvfx_state_flush_notify(struct nouveau_channel *chan)
+{
+       struct nvfx_context *nvfx = chan->user_private;
+       struct nvfx_state *state = &nvfx->state;
+       unsigned i, samplers;
+
+       so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FB]);
+       for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
+               if (!(samplers & (1 << i)))
+                       continue;
+               so_emit_reloc_markers(chan,
+                                     state->hw[NVFX_STATE_FRAGTEX0+i]);
+               samplers &= ~(1ULL << i);
+       }
+       so_emit_reloc_markers(chan, state->hw[NVFX_STATE_FRAGPROG]);
+       if (state->hw[NVFX_STATE_VTXBUF] && nvfx->render_mode == HW)
+               so_emit_reloc_markers(chan, state->hw[NVFX_STATE_VTXBUF]);
+}
+
+boolean
+nvfx_state_validate(struct nvfx_context *nvfx)
+{
+       boolean was_sw = nvfx->fallback_swtnl ? TRUE : FALSE;
+
+       if (nvfx->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 ((nvfx->fallback_swtnl & nvfx->dirty)
+                               != nvfx->fallback_swtnl)
+                       return FALSE;
+
+               /* Attempt to go to hwtnl again */
+               nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
+               nvfx->dirty |= (NVFX_NEW_VIEWPORT |
+                               NVFX_NEW_VERTPROG |
+                               NVFX_NEW_ARRAYS);
+               nvfx->render_mode = HW;
+       }
+
+       if(!nvfx->is_nv4x)
+               nvfx_state_do_validate(nvfx, nv30_render_states);
+       else
+               nvfx_state_do_validate(nvfx, nv40_render_states);
+
+       if (nvfx->fallback_swtnl || nvfx->fallback_swrast)
+               return FALSE;
+
+       if (was_sw)
+               NOUVEAU_ERR("swtnl->hw\n");
+
+       return TRUE;
+}
+
+boolean
+nvfx_state_validate_swtnl(struct nvfx_context *nvfx)
+{
+       struct draw_context *draw = nvfx->draw;
+
+       /* Setup for swtnl */
+       if (nvfx->render_mode == HW) {
+               NOUVEAU_ERR("hw->swtnl 0x%08x\n", nvfx->fallback_swtnl);
+               nvfx->pipe.flush(&nvfx->pipe, 0, NULL);
+               nvfx->dirty |= (NVFX_NEW_VIEWPORT |
+                               NVFX_NEW_VERTPROG |
+                               NVFX_NEW_ARRAYS);
+               nvfx->render_mode = SWTNL;
+       }
+
+       if (nvfx->draw_dirty & NVFX_NEW_VERTPROG)
+               draw_bind_vertex_shader(draw, nvfx->vertprog->draw);
+
+       if (nvfx->draw_dirty & NVFX_NEW_RAST)
+               draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe);
+
+       if (nvfx->draw_dirty & NVFX_NEW_UCP)
+               draw_set_clip_state(draw, &nvfx->clip);
+
+       if (nvfx->draw_dirty & NVFX_NEW_VIEWPORT)
+               draw_set_viewport_state(draw, &nvfx->viewport);
+
+       if (nvfx->draw_dirty & NVFX_NEW_ARRAYS) {
+               draw_set_vertex_buffers(draw, nvfx->vtxbuf_nr, nvfx->vtxbuf);
+               draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe);
+       }
+
+       if(!nvfx->is_nv4x)
+               nvfx_state_do_validate(nvfx, nv30_swtnl_render_states);
+       else
+               nvfx_state_do_validate(nvfx, nv40_swtnl_render_states);
+
+       if (nvfx->fallback_swrast) {
+               NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx->fallback_swrast);
+               return FALSE;
+       }
+
+       nvfx->draw_dirty = 0;
+       return TRUE;
+}