nv40: get fragprog onto new state mechanism
This commit is contained in:
parent
56045da083
commit
4a9cb97bbf
|
@ -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,
|
||||
|
|
|
@ -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,73 +750,67 @@ 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);
|
||||
}
|
||||
|
||||
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 (!memcmp(p, cb, 4 * sizeof(float)))
|
||||
continue;
|
||||
memcpy(p, cb, 4 * sizeof(float));
|
||||
fp->on_hw = 0;
|
||||
}
|
||||
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);
|
||||
map = ws->buffer_map(ws, fp->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
|
||||
|
||||
#if 0
|
||||
for (i = 0; i < fp->insn_len; i++) {
|
||||
NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
|
||||
}
|
||||
for (i = 0; i < fp->insn_len; i++) {
|
||||
NOUVEAU_ERR("%d 0x%08x\n", i, fp->insn[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
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 ((*(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, fp->buffer);
|
||||
fp->on_hw = TRUE;
|
||||
}
|
||||
|
||||
ws->buffer_unmap(ws, fp->buffer);
|
||||
}
|
||||
|
||||
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 (fp->translated)
|
||||
goto update_constants;
|
||||
|
||||
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);
|
||||
so_reloc (so, fp->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_GART |
|
||||
|
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,6 @@ struct nv40_fragment_program {
|
|||
const struct pipe_shader_state *pipe;
|
||||
|
||||
boolean translated;
|
||||
boolean on_hw;
|
||||
unsigned samplers;
|
||||
|
||||
uint32_t *insn;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue