#define NOUVEAU_MSG(fmt, args...) \
fprintf(stderr, "nouveau: "fmt, ##args);
+enum nv40_state_index {
+ NV40_STATE_CLIP = 1ULL,
+ NV40_STATE_SCISSOR = 2ULL,
+ NV40_STATE_STIPPLE = 3ULL,
+ NV40_STATE_FRAGPROG = 4ULL,
+ NV40_STATE_VERTPROG = 5ULL,
+ NV40_STATE_MAX = 6ULL
+};
+
#define NV40_NEW_BLEND (1 << 0)
#define NV40_NEW_RAST (1 << 1)
#define NV40_NEW_ZSA (1 << 2)
/* Vtxprog resources */
struct nouveau_resource *vp_exec_heap;
struct nouveau_resource *vp_data_heap;
+
+ /* Current 3D state of channel */
+ struct nouveau_stateobj *state[NV40_STATE_MAX];
};
struct nv40_rasterizer_state {
};
struct nv40_state {
- struct {
- unsigned enabled;
- struct nouveau_stateobj *so;
- } scissor;
-
- struct {
- unsigned enabled;
- struct nouveau_stateobj *so;
- } stipple;
+ unsigned scissor_enabled;
+ unsigned stipple_enabled;
- struct nouveau_stateobj *fragprog;
- struct nouveau_stateobj *vertprog;
+ struct nouveau_stateobj *hw[NV40_STATE_MAX];
};
struct nv40_context {
nv40_fragprog_upload(nv40, fp);
}
- if (fp->so != nv40->state.fragprog) {
- so_ref(fp->so, &nv40->state.fragprog);
+ if (fp->so != nv40->state.hw[NV40_STATE_FRAGPROG]) {
+ so_ref(fp->so, &nv40->state.hw[NV40_STATE_FRAGPROG]);
return TRUE;
}
.validate = nv40_fragprog_validate,
.dirty = {
.pipe = NV40_NEW_FRAGPROG,
- .hw = NV40_NEW_FRAGPROG
+ .hw = NV40_STATE_FRAGPROG
}
};
#include "nv40_context.h"
#include "nv40_state.h"
-/* Emit relocs for every referenced buffer.
- *
- * This is to ensure the bufmgr has an accurate idea of how
- * the buffer is used. These relocs appear in the push buffer as
- * NOPs, and will only be turned into state changes if a buffer
- * actually moves.
- */
-static void
-nv40_state_emit_dummy_relocs(struct nv40_context *nv40)
-{
- unsigned i;
-
- so_emit_reloc_markers(nv40->nvws, nv40->so_framebuffer);
- for (i = 0; i < 16; i++) {
- if (!(nv40->fp_samplers & (1 << i)))
- continue;
- so_emit_reloc_markers(nv40->nvws, nv40->so_fragtex[i]);
- }
- so_emit_reloc_markers(nv40->nvws, nv40->state.fragprog);
-}
-
static struct nv40_state_entry *render_states[] = {
&nv40_state_clip,
&nv40_state_scissor,
if (nv40->dirty & e->dirty.pipe) {
if (e->validate(nv40))
- nv40->hw_dirty |= e->dirty.hw;
+ nv40->hw_dirty |= (1 << e->dirty.hw);
}
states++;
}
}
+static void
+nv40_state_emit(struct nv40_context *nv40)
+{
+ unsigned i;
+
+ while (nv40->hw_dirty) {
+ unsigned idx = ffs(nv40->hw_dirty) - 1;
+ nv40->hw_dirty &= ~(1 << idx);
+
+ so_ref (nv40->state.hw[idx], &nv40->hw->state[idx]);
+ so_emit(nv40->nvws, nv40->hw->state[idx]);
+ }
+
+ so_emit_reloc_markers(nv40->nvws, nv40->so_framebuffer);
+ for (i = 0; i < 16; i++) {
+ if (!(nv40->fp_samplers & (1 << i)))
+ continue;
+ so_emit_reloc_markers(nv40->nvws, nv40->so_fragtex[i]);
+ }
+ so_emit_reloc_markers(nv40->nvws, nv40->state.hw[NV40_STATE_FRAGPROG]);
+}
+
void
nv40_emit_hw_state(struct nv40_context *nv40)
{
if (nv40->dirty & NV40_NEW_BCOL)
so_emit(nv40->nvws, nv40->so_bcol);
- if (nv40->hw_dirty & NV40_NEW_SCISSOR) {
- so_emit(nv40->nvws, nv40->state.scissor.so);
- nv40->hw_dirty &= ~NV40_NEW_SCISSOR;
- }
-
if (nv40->dirty & NV40_NEW_VIEWPORT)
so_emit(nv40->nvws, nv40->so_viewport);
- if (nv40->hw_dirty & NV40_NEW_STIPPLE) {
- so_emit(nv40->nvws, nv40->state.stipple.so);
- nv40->hw_dirty &= ~NV40_NEW_STIPPLE;
- }
-
- if (nv40->hw_dirty & NV40_NEW_FRAGPROG) {
- so_emit(nv40->nvws, nv40->state.fragprog);
- nv40->hw_dirty &= ~NV40_NEW_FRAGPROG;
- }
-
if (nv40->dirty_samplers || (nv40->dirty & NV40_NEW_FRAGPROG)) {
nv40_fragtex_bind(nv40);
nv40->dirty &= ~NV40_NEW_FRAGPROG;
}
- if (nv40->hw_dirty & NV40_NEW_VERTPROG) {
- so_emit(nv40->nvws, nv40->state.vertprog);
- nv40->hw_dirty &= ~NV40_NEW_VERTPROG;
- }
+ nv40_state_emit(nv40);
nv40->dirty_samplers = 0;
nv40->dirty = 0;
-
- nv40_state_emit_dummy_relocs(nv40);
}
struct pipe_scissor_state *s = &nv40->pipe_state.scissor;
struct nouveau_stateobj *so;
- if (nv40->state.scissor.so &&
- (rast->scissor == 0 && nv40->state.scissor.enabled == 0))
+ if (nv40->state.hw[NV40_STATE_SCISSOR] &&
+ (rast->scissor == 0 && nv40->state.scissor_enabled == 0))
return FALSE;
so = so_new(3, 0);
so_data (so, 4096 << 16);
}
- so_ref(so, &nv40->state.scissor.so);
+ so_ref(so, &nv40->state.hw[NV40_STATE_SCISSOR]);
so_ref(NULL, &so);
return TRUE;
}
.validate = nv40_state_scissor_validate,
.dirty = {
.pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST,
- .hw = NV40_NEW_SCISSOR
+ .hw = NV40_STATE_SCISSOR
}
};
struct nouveau_grobj *curie = nv40->hw->curie;
struct nouveau_stateobj *so;
- if (nv40->state.stipple.so && (rast->poly_stipple_enable == 0 &&
- nv40->state.stipple.enabled == 0))
+ if (nv40->state.hw[NV40_STATE_STIPPLE] &&
+ (rast->poly_stipple_enable == 0 && nv40->state.stipple_enabled == 0))
return FALSE;
if (rast->poly_stipple_enable) {
so_data (so, 0);
}
- so_ref(so, &nv40->state.stipple.so);
+ so_ref(so, &nv40->state.hw[NV40_STATE_STIPPLE]);
so_ref(NULL, &so);
return TRUE;
}
.validate = nv40_state_stipple_validate,
.dirty = {
.pipe = NV40_NEW_STIPPLE | NV40_NEW_RAST,
- .hw = NV40_NEW_STIPPLE
+ .hw = NV40_STATE_STIPPLE,
}
};
}
}
- if (vp->so != nv40->state.vertprog) {
- so_ref(vp->so, &nv40->state.vertprog);
+ if (vp->so != nv40->state.hw[NV40_STATE_VERTPROG]) {
+ so_ref(vp->so, &nv40->state.hw[NV40_STATE_VERTPROG]);
return TRUE;
}
.validate = nv40_vertprog_validate,
.dirty = {
.pipe = NV40_NEW_VERTPROG,
- .hw = NV40_NEW_VERTPROG
+ .hw = NV40_STATE_VERTPROG,
}
};