summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nv40/nv40_context.h17
-rw-r--r--src/gallium/drivers/nv40/nv40_fragprog.c127
-rw-r--r--src/gallium/drivers/nv40/nv40_fragtex.c2
-rw-r--r--src/gallium/drivers/nv40/nv40_state.c5
-rw-r--r--src/gallium/drivers/nv40/nv40_state.h1
-rw-r--r--src/gallium/drivers/nv40/nv40_state_emit.c26
6 files changed, 97 insertions, 81 deletions
diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h
index 432204b8252..ce0933fea4a 100644
--- a/src/gallium/drivers/nv40/nv40_context.h
+++ b/src/gallium/drivers/nv40/nv40_context.h
@@ -37,6 +37,7 @@
#define NV40_NEW_UCP (1 << 12)
#define NV40_FALLBACK_TNL (1 << 0)
+#define NV40_FALLBACK_RAST (1 << 1)
struct nv40_channel_context {
struct nouveau_winsys *nvws;
@@ -72,6 +73,8 @@ struct nv40_state {
unsigned enabled;
struct nouveau_stateobj *so;
} stipple;
+
+ struct nouveau_stateobj *fragprog;
};
struct nv40_context {
@@ -96,6 +99,8 @@ struct nv40_context {
struct pipe_scissor_state scissor;
unsigned stipple[32];
struct pipe_clip_state clip;
+ struct nv40_fragment_program *fragprog;
+ struct pipe_buffer *constbuf[PIPE_SHADER_TYPES];
} pipe_state;
struct nv40_state state;
@@ -119,13 +124,6 @@ struct nv40_context {
struct pipe_buffer *constant_buf;
} vertprog;
- struct {
- struct nv40_fragment_program *active;
-
- struct nv40_fragment_program *current;
- struct pipe_buffer *constant_buf;
- } fragprog;
-
struct pipe_vertex_buffer vtxbuf[PIPE_ATTRIB_MAX];
struct pipe_vertex_element vtxelt[PIPE_ATTRIB_MAX];
};
@@ -161,10 +159,6 @@ extern void nv40_vertprog_destroy(struct nv40_context *,
struct nv40_vertex_program *);
/* nv40_fragprog.c */
-extern void nv40_fragprog_translate(struct nv40_context *,
- struct nv40_fragment_program *);
-extern void nv40_fragprog_bind(struct nv40_context *,
- struct nv40_fragment_program *);
extern void nv40_fragprog_destroy(struct nv40_context *,
struct nv40_fragment_program *);
@@ -177,6 +171,7 @@ extern void nv40_state_tex_update(struct nv40_context *nv40);
extern struct nv40_state_entry nv40_state_clip;
extern struct nv40_state_entry nv40_state_scissor;
extern struct nv40_state_entry nv40_state_stipple;
+extern struct nv40_state_entry nv40_state_fragprog;
/* nv40_vbo.c */
extern boolean nv40_draw_arrays(struct pipe_context *, unsigned mode,
diff --git a/src/gallium/drivers/nv40/nv40_fragprog.c b/src/gallium/drivers/nv40/nv40_fragprog.c
index 07a418c1e9f..bfc75eb4620 100644
--- a/src/gallium/drivers/nv40/nv40_fragprog.c
+++ b/src/gallium/drivers/nv40/nv40_fragprog.c
@@ -668,7 +668,7 @@ nv40_fragprog_parse_decl_output(struct nv40_fpc *fpc,
return TRUE;
}
-void
+static void
nv40_fragprog_translate(struct nv40_context *nv40,
struct nv40_fragment_program *fp)
{
@@ -750,72 +750,66 @@ nv40_fragprog_translate(struct nv40_context *nv40,
fp->insn[fpc->inst_offset + 3] = 0x00000000;
fp->translated = TRUE;
- fp->on_hw = FALSE;
out_err:
tgsi_parse_free(&parse);
free(fpc);
}
-void
-nv40_fragprog_bind(struct nv40_context *nv40, struct nv40_fragment_program *fp)
+static void
+nv40_fragprog_upload(struct nv40_context *nv40,
+ struct nv40_fragment_program *fp)
{
struct pipe_winsys *ws = nv40->pipe.winsys;
- struct nouveau_stateobj *so;
+ const uint32_t le = 1;
+ uint32_t *map;
int i;
- if (!fp->translated) {
- nv40_fragprog_translate(nv40, fp);
- if (!fp->translated)
- assert(0);
- }
+ map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
- if (fp->nr_consts) {
- float *map = ws->buffer_map(ws, nv40->fragprog.constant_buf,
- PIPE_BUFFER_USAGE_CPU_READ);
- for (i = 0; i < fp->nr_consts; i++) {
- struct nv40_fragment_program_data *fpd = &fp->consts[i];
- uint32_t *p = &fp->insn[fpd->offset];
- uint32_t *cb = (uint32_t *)&map[fpd->index * 4];
+#if 0
+ for (i = 0; i < fp->insn_len; i++) {
+ NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
+ }
+#endif
- if (!memcmp(p, cb, 4 * sizeof(float)))
- continue;
- memcpy(p, cb, 4 * sizeof(float));
- fp->on_hw = 0;
+ if ((*(const uint8_t *)&le)) {
+ for (i = 0; i < fp->insn_len; i++) {
+ map[i] = fp->insn[i];
+ }
+ } else {
+ /* Weird swapping for big-endian chips */
+ for (i = 0; i < fp->insn_len; i++) {
+ map[i] = ((fp->insn[i] & 0xffff) << 16) |
+ ((fp->insn[i] >> 16) & 0xffff);
}
- ws->buffer_unmap(ws, nv40->fragprog.constant_buf);
}
- if (!fp->on_hw) {
- const uint32_t le = 1;
- uint32_t *map;
-
- if (!fp->buffer)
- fp->buffer = ws->buffer_create(ws, 0x100, 0,
- fp->insn_len * 4);
- map = ws->buffer_map(ws, fp->buffer,
- PIPE_BUFFER_USAGE_CPU_WRITE);
+ ws->buffer_unmap(ws, fp->buffer);
+}
-#if 0
- for (i = 0; i < fp->insn_len; i++) {
- NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
- }
-#endif
+static boolean
+nv40_fragprog_validate(struct nv40_context *nv40)
+{
+ struct nv40_fragment_program *fp = nv40->pipe_state.fragprog;
+ struct pipe_buffer *constbuf =
+ nv40->pipe_state.constbuf[PIPE_SHADER_FRAGMENT];
+ struct pipe_winsys *ws = nv40->pipe.winsys;
+ struct nouveau_stateobj *so;
+ unsigned new_program = FALSE;
+ int i;
- if ((*(const uint8_t *)&le)) {
- for (i = 0; i < fp->insn_len; i++) {
- map[i] = fp->insn[i];
- }
- } else {
- /* Weird swapping for big-endian chips */
- for (i = 0; i < fp->insn_len; i++) {
- map[i] = ((fp->insn[i] & 0xffff) << 16) |
- ((fp->insn[i] >> 16) & 0xffff);
- }
- }
+ if (fp->translated)
+ goto update_constants;
- ws->buffer_unmap(ws, fp->buffer);
- fp->on_hw = TRUE;
+ nv40_fragprog_translate(nv40, fp);
+ if (!fp->translated) {
+ nv40->fallback |= NV40_FALLBACK_RAST;
+ return FALSE;
}
+ new_program = TRUE;
+
+ fp->buffer = ws->buffer_create(ws, 0x100, 0, fp->insn_len * 4);
+ nv40_fragprog_upload(nv40, fp);
so = so_new(4, 1);
so_method(so, nv40->hw->curie, NV40TCL_FP_ADDRESS, 1);
@@ -824,12 +818,33 @@ nv40_fragprog_bind(struct nv40_context *nv40, struct nv40_fragment_program *fp)
NV40TCL_FP_ADDRESS_DMA0, NV40TCL_FP_ADDRESS_DMA1);
so_method(so, nv40->hw->curie, NV40TCL_FP_CONTROL, 1);
so_data (so, fp->fp_control);
-
- so_emit(nv40->nvws, so);
so_ref(so, &fp->so);
so_ref(NULL, &so);
- nv40->fragprog.active = fp;
+update_constants:
+ if (fp->nr_consts) {
+ boolean new_consts = FALSE;
+ float *map;
+
+ map = ws->buffer_map(ws, constbuf, PIPE_BUFFER_USAGE_CPU_READ);
+ for (i = 0; i < fp->nr_consts; i++) {
+ struct nv40_fragment_program_data *fpd = &fp->consts[i];
+ uint32_t *p = &fp->insn[fpd->offset];
+ uint32_t *cb = (uint32_t *)&map[fpd->index * 4];
+
+ if (!memcmp(p, cb, 4 * sizeof(float)))
+ continue;
+ memcpy(p, cb, 4 * sizeof(float));
+ new_consts = TRUE;
+ }
+ ws->buffer_unmap(ws, constbuf);
+
+ if (new_consts)
+ nv40_fragprog_upload(nv40, fp);
+ }
+
+ so_ref(fp->so, &nv40->state.fragprog);
+ return new_program;
}
void
@@ -840,3 +855,11 @@ nv40_fragprog_destroy(struct nv40_context *nv40,
free(fp->insn);
}
+struct nv40_state_entry nv40_state_fragprog = {
+ .validate = nv40_fragprog_validate,
+ .dirty = {
+ .pipe = NV40_NEW_FRAGPROG,
+ .hw = NV40_NEW_FRAGPROG
+ }
+};
+
diff --git a/src/gallium/drivers/nv40/nv40_fragtex.c b/src/gallium/drivers/nv40/nv40_fragtex.c
index 5af5fbe7465..811f3098ba7 100644
--- a/src/gallium/drivers/nv40/nv40_fragtex.c
+++ b/src/gallium/drivers/nv40/nv40_fragtex.c
@@ -125,7 +125,7 @@ nv40_fragtex_build(struct nv40_context *nv40, int unit)
void
nv40_fragtex_bind(struct nv40_context *nv40)
{
- struct nv40_fragment_program *fp = nv40->fragprog.active;
+ struct nv40_fragment_program *fp = nv40->pipe_state.fragprog;
unsigned samplers, unit;
samplers = nv40->fp_samplers & ~fp->samplers;
diff --git a/src/gallium/drivers/nv40/nv40_state.c b/src/gallium/drivers/nv40/nv40_state.c
index c203b002403..2886c6b0dc4 100644
--- a/src/gallium/drivers/nv40/nv40_state.c
+++ b/src/gallium/drivers/nv40/nv40_state.c
@@ -523,9 +523,8 @@ static void
nv40_fp_state_bind(struct pipe_context *pipe, void *hwcso)
{
struct nv40_context *nv40 = nv40_context(pipe);
- struct nv40_fragment_program *fp = hwcso;
- nv40->fragprog.current = fp;
+ nv40->pipe_state.fragprog = hwcso;
nv40->dirty |= NV40_NEW_FRAGPROG;
}
@@ -578,7 +577,7 @@ nv40_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
nv40->dirty |= NV40_NEW_VERTPROG;
} else
if (shader == PIPE_SHADER_FRAGMENT) {
- nv40->fragprog.constant_buf = buf->buffer;
+ nv40->pipe_state.constbuf[PIPE_SHADER_FRAGMENT] = buf->buffer;
nv40->dirty |= NV40_NEW_FRAGPROG;
}
}
diff --git a/src/gallium/drivers/nv40/nv40_state.h b/src/gallium/drivers/nv40/nv40_state.h
index e82ab9de98a..2701294a077 100644
--- a/src/gallium/drivers/nv40/nv40_state.h
+++ b/src/gallium/drivers/nv40/nv40_state.h
@@ -50,7 +50,6 @@ struct nv40_fragment_program {
const struct pipe_shader_state *pipe;
boolean translated;
- boolean on_hw;
unsigned samplers;
uint32_t *insn;
diff --git a/src/gallium/drivers/nv40/nv40_state_emit.c b/src/gallium/drivers/nv40/nv40_state_emit.c
index b5d0d68d6b1..e10e178432e 100644
--- a/src/gallium/drivers/nv40/nv40_state_emit.c
+++ b/src/gallium/drivers/nv40/nv40_state_emit.c
@@ -19,21 +19,14 @@ nv40_state_emit_dummy_relocs(struct nv40_context *nv40)
continue;
so_emit_reloc_markers(nv40->nvws, nv40->so_fragtex[i]);
}
- so_emit_reloc_markers(nv40->nvws, nv40->fragprog.active->so);
-}
-
-static boolean
-nv40_state_clip_validate(struct nv40_context *nv40)
-{
- if (nv40->pipe_state.clip.nr)
- nv40->fallback |= NV40_FALLBACK_TNL;
- return FALSE;
+ so_emit_reloc_markers(nv40->nvws, nv40->state.fragprog);
}
static struct nv40_state_entry *render_states[] = {
&nv40_state_clip,
&nv40_state_scissor,
&nv40_state_stipple,
+ &nv40_state_fragprog,
NULL
};
@@ -65,6 +58,15 @@ nv40_state_validate(struct nv40_context *nv40)
!(nv40->fallback & NV40_FALLBACK_TNL)) {
NOUVEAU_ERR("XXX: swtnl->hwtnl\n");
}
+
+ if (nv40->fallback & NV40_FALLBACK_RAST &&
+ !(last_fallback & NV40_FALLBACK_RAST)) {
+ NOUVEAU_ERR("XXX: hwrast->swrast\n");
+ } else
+ if (last_fallback & NV40_FALLBACK_RAST &&
+ !(nv40->fallback & NV40_FALLBACK_RAST)) {
+ NOUVEAU_ERR("XXX: swrast->hwrast\n");
+ }
}
void
@@ -100,10 +102,8 @@ nv40_emit_hw_state(struct nv40_context *nv40)
nv40->hw_dirty &= ~NV40_NEW_STIPPLE;
}
- if (nv40->dirty & NV40_NEW_FRAGPROG) {
- nv40_fragprog_bind(nv40, nv40->fragprog.current);
- /*XXX: clear NV40_NEW_FRAGPROG if no new program uploaded */
- }
+ if (nv40->hw_dirty & NV40_NEW_FRAGPROG)
+ so_emit(nv40->nvws, nv40->state.fragprog);
if (nv40->dirty_samplers || (nv40->dirty & NV40_NEW_FRAGPROG)) {
nv40_fragtex_bind(nv40);