summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nvfx/nvfx_state_emit.c
diff options
context:
space:
mode:
authorLuca Barbieri <luca@luca-barbieri.com>2010-02-23 16:48:22 +0100
committerLuca Barbieri <luca@luca-barbieri.com>2010-04-12 12:21:25 +0200
commit330925d9118120863f5e76e01fdfa1a1f44be2b1 (patch)
treefeb63f5237b7d1cc2cd8ff8a0f3f90774c030cb9 /src/gallium/drivers/nvfx/nvfx_state_emit.c
parent26e40448becb07e292d269dc4d8fbc56caebba3c (diff)
nvfx: rework validation logic to use code and avoid stateobjs
This makes the code faster due to the lack of indirect calls and also makes it much easier to understand what is actually going on.
Diffstat (limited to 'src/gallium/drivers/nvfx/nvfx_state_emit.c')
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state_emit.c156
1 files changed, 77 insertions, 79 deletions
diff --git a/src/gallium/drivers/nvfx/nvfx_state_emit.c b/src/gallium/drivers/nvfx/nvfx_state_emit.c
index 2bc7927a69..4137849bf0 100644
--- a/src/gallium/drivers/nvfx/nvfx_state_emit.c
+++ b/src/gallium/drivers/nvfx/nvfx_state_emit.c
@@ -2,86 +2,92 @@
#include "nvfx_state.h"
#include "draw/draw_context.h"
-#define RENDER_STATES(name, vbo) \
-static struct nvfx_state_entry *name##render_states[] = { \
- &nvfx_state_framebuffer, \
- &nvfx_state_rasterizer, \
- &nvfx_state_scissor, \
- &nvfx_state_stipple, \
- &nvfx_state_fragprog, \
- &nvfx_state_fragtex, \
- &nvfx_state_vertprog, \
- &nvfx_state_blend, \
- &nvfx_state_blend_colour, \
- &nvfx_state_zsa, \
- &nvfx_state_sr, \
- &nvfx_state_viewport, \
- &nvfx_state_##vbo, \
- NULL \
-}
-
-RENDER_STATES(, vbo);
-RENDER_STATES(swtnl_, vtxfmt);
-
-static void
-nvfx_state_do_validate(struct nvfx_context *nvfx,
- struct nvfx_state_entry **states)
+static boolean
+nvfx_state_validate_common(struct nvfx_context *nvfx)
{
- 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);
+ struct nouveau_channel* chan = nvfx->screen->base.channel;
+ unsigned dirty = nvfx->dirty;
+
+ if(nvfx != nvfx->screen->cur_ctx)
+ dirty = ~0;
+
+ if(nvfx->render_mode == HW)
+ {
+ if(dirty & (NVFX_NEW_VERTPROG | NVFX_NEW_VERTCONST | NVFX_NEW_UCP))
+ {
+ if(!nvfx_vertprog_validate(nvfx))
+ return FALSE;
}
- states++;
+ if(dirty & (NVFX_NEW_ARRAYS))
+ {
+ if(!nvfx_vbo_validate(nvfx))
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* TODO: this looks a bit misdesigned */
+ if(dirty & (NVFX_NEW_VERTPROG | NVFX_NEW_UCP))
+ nvfx_vertprog_validate(nvfx);
+
+ if(dirty & (NVFX_NEW_ARRAYS | NVFX_NEW_FRAGPROG))
+ nvfx_vtxfmt_validate(nvfx);
}
- 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);
- }
+ if(dirty & NVFX_NEW_FB)
+ nvfx_state_framebuffer_validate(nvfx);
- screen->cur_ctx = nvfx;
- }
+ if(dirty & NVFX_NEW_RAST)
+ sb_emit(chan, nvfx->rasterizer->sb, nvfx->rasterizer->sb_len);
- 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(dirty & NVFX_NEW_SCISSOR)
+ nvfx_state_scissor_validate(nvfx);
+
+ if(dirty & NVFX_NEW_STIPPLE)
+ nvfx_state_stipple_validate(nvfx);
+
+ if(dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST))
+ nvfx_fragprog_validate(nvfx);
+
+ if(dirty & NVFX_NEW_SAMPLER)
+ nvfx_fragtex_validate(nvfx);
+
+ if(dirty & NVFX_NEW_BLEND)
+ sb_emit(chan, nvfx->blend->sb, nvfx->blend->sb_len);
+
+ if(dirty & NVFX_NEW_BCOL)
+ nvfx_state_blend_colour_validate(nvfx);
+
+ if(dirty & NVFX_NEW_ZSA)
+ sb_emit(chan, nvfx->zsa->sb, nvfx->zsa->sb_len);
+
+ if(dirty & NVFX_NEW_SR)
+ nvfx_state_sr_validate(nvfx);
+
+/* Having this depend on FB looks wrong, but it seems
+ necessary to make this work on nv3x
+ TODO: find the right fix
+*/
+ if(dirty & (NVFX_NEW_VIEWPORT | NVFX_NEW_FB))
+ nvfx_state_viewport_validate(nvfx);
/* 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);
- }
+ if((dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_SAMPLER)) && nvfx->is_nv4x) {
+ WAIT_RING(chan, 4);
+ OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
+ OUT_RING(chan, 2);
+ OUT_RING(chan, RING_3D(NV40TCL_TEX_CACHE_CTL, 1));
+ OUT_RING(chan, 1);
}
- state->dirty = 0;
+ nvfx->dirty = 0;
+ return TRUE;
+}
+void
+nvfx_state_emit(struct nvfx_context *nvfx)
+{
+ struct nouveau_channel* chan = nvfx->screen->base.channel;
/* we need to ensure there is enough space to output relocations in one go */
unsigned max_relocs = 0
+ 16 /* vertex buffers, incl. dma flag */
@@ -119,16 +125,13 @@ nvfx_state_validate(struct nvfx_context *nvfx)
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;
}
- nvfx_state_do_validate(nvfx, render_states);
-
- if (nvfx->fallback_swtnl || nvfx->fallback_swrast)
+ if(!nvfx_state_validate_common(nvfx))
return FALSE;
if (was_sw)
@@ -169,12 +172,7 @@ nvfx_state_validate_swtnl(struct nvfx_context *nvfx)
draw_set_vertex_elements(draw, nvfx->vtxelt->num_elements, nvfx->vtxelt->pipe);
}
- nvfx_state_do_validate(nvfx, swtnl_render_states);
-
- if (nvfx->fallback_swrast) {
- NOUVEAU_ERR("swtnl->swrast 0x%08x\n", nvfx->fallback_swrast);
- return FALSE;
- }
+ nvfx_state_validate_common(nvfx);
nvfx->draw_dirty = 0;
return TRUE;