Fixes progs/demos/lodbias.
Makes a complete mess of things, but now there's a motivation to finish
this off :)
struct nouveau_resource *vp_data_heap;
};
+struct nv40_rasterizer_state {
+ struct pipe_rasterizer_state pipe;
+ struct nouveau_stateobj *so;
+};
+
struct nv40_context {
struct pipe_context pipe;
struct nouveau_winsys *nvws;
int chipset;
- uint32_t dirty;
+ unsigned dirty;
+ unsigned hw_dirty;
struct nv40_sampler_state *tex_sampler[PIPE_MAX_SAMPLERS];
struct nv40_miptree *tex_miptree[PIPE_MAX_SAMPLERS];
unsigned fp_samplers;
unsigned vp_samplers;
+ struct {
+ struct pipe_scissor_state scissor;
+ } pipe_state;
+
+ struct {
+ unsigned scissor_enabled;
+ struct nouveau_stateobj *scissor;
+ } state;
+
struct nouveau_stateobj *so_framebuffer;
struct nouveau_stateobj *so_fragtex[16];
struct nouveau_stateobj *so_vtxbuf;
struct nouveau_stateobj *so_blend;
+ struct nv40_rasterizer_state *rasterizer;
struct nouveau_stateobj *so_rast;
struct nouveau_stateobj *so_zsa;
struct nouveau_stateobj *so_bcol;
- struct nouveau_stateobj *so_scissor;
struct nouveau_stateobj *so_viewport;
struct nouveau_stateobj *so_stipple;
const struct pipe_rasterizer_state *cso)
{
struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_rasterizer_state *rsso = MALLOC(sizeof(*rsso));
struct nouveau_stateobj *so = so_new(32, 0);
/*XXX: ignored:
* light_twoside
* offset_cw/ccw -nohw
- * scissor
* point_smooth -nohw
* multisample
* offset_units / offset_scale
so_data(so, 0);
}
- return (void *)so;
+ rsso->so = so;
+ rsso->pipe = *cso;
+ return (void *)rsso;
}
static void
nv40_rasterizer_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv40_context *nv40 = nv40_context(pipe);
+ struct nv40_rasterizer_state *rsso = hwcso;
- so_ref(hwcso, &nv40->so_rast);
+ so_ref(rsso->so, &nv40->so_rast);
+ nv40->rasterizer = rsso;
nv40->dirty |= NV40_NEW_RAST;
}
static void
nv40_rasterizer_state_delete(struct pipe_context *pipe, void *hwcso)
{
- struct nouveau_stateobj *so = hwcso;
+ struct nv40_rasterizer_state *rsso = hwcso;
- so_ref(NULL, &so);
+ so_ref(NULL, &rsso->so);
+ free(rsso);
}
static void *
const struct pipe_scissor_state *s)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nouveau_stateobj *so = so_new(3, 0);
- so_method(so, nv40->hw->curie, NV40TCL_SCISSOR_HORIZ, 2);
- so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
- so_data (so, ((s->maxy - s->miny) << 16) | s->miny);
-
- so_ref(so, &nv40->so_scissor);
- so_ref(NULL, &so);
+ nv40->pipe_state.scissor = *s;
nv40->dirty |= NV40_NEW_SCISSOR;
}
so_emit_reloc_markers(nv40->nvws, nv40->fragprog.active->so);
}
+static boolean
+nv40_state_scissor_validate(struct nv40_context *nv40)
+{
+ struct pipe_rasterizer_state *rast = &nv40->rasterizer->pipe;
+ struct pipe_scissor_state *s = &nv40->pipe_state.scissor;
+ struct nouveau_stateobj *so;
+
+ if (nv40->state.scissor &&
+ (rast->scissor == 0 && nv40->state.scissor_enabled == 0))
+ return FALSE;
+
+ so = so_new(3, 0);
+ so_method(so, nv40->hw->curie, NV40TCL_SCISSOR_HORIZ, 2);
+ if (rast->scissor) {
+ so_data (so, ((s->maxx - s->minx) << 16) | s->minx);
+ so_data (so, ((s->maxy - s->miny) << 16) | s->miny);
+ } else {
+ so_data (so, 4096 << 16);
+ so_data (so, 4096 << 16);
+ }
+
+ so_ref(so, &nv40->state.scissor);
+ so_ref(NULL, &so);
+ return TRUE;
+}
+
+struct nv40_state_atom {
+ boolean (*validate)(struct nv40_context *nv40);
+ struct {
+ unsigned pipe;
+ unsigned hw;
+ } dirty;
+};
+
+static struct nv40_state_atom states[] = {
+ {
+ .validate = nv40_state_scissor_validate,
+ .dirty = {
+ .pipe = NV40_NEW_SCISSOR | NV40_NEW_RAST,
+ .hw = NV40_NEW_SCISSOR,
+ }
+ }
+};
+
+static void
+nv40_state_validate(struct nv40_context *nv40)
+{
+ unsigned i;
+
+ for (i = 0; i < sizeof(states) / sizeof(states[0]); i++) {
+ if (nv40->dirty & states[i].dirty.pipe) {
+ if (states[i].validate(nv40))
+ nv40->hw_dirty |= states[i].dirty.hw;
+ }
+ }
+}
+
void
nv40_emit_hw_state(struct nv40_context *nv40)
{
+ nv40_state_validate(nv40);
+
if (nv40->dirty & NV40_NEW_FB)
so_emit(nv40->nvws, nv40->so_framebuffer);
if (nv40->dirty & NV40_NEW_BCOL)
so_emit(nv40->nvws, nv40->so_bcol);
- if (nv40->dirty & NV40_NEW_SCISSOR)
- so_emit(nv40->nvws, nv40->so_scissor);
+ if (nv40->hw_dirty & NV40_NEW_SCISSOR) {
+ so_emit(nv40->nvws, nv40->state.scissor);
+ nv40->hw_dirty &= ~NV40_NEW_SCISSOR;
+ }
if (nv40->dirty & NV40_NEW_VIEWPORT)
so_emit(nv40->nvws, nv40->so_viewport);