nv50: ensure enough room for state changes in current pushbuf

Also allows the nv50_state_validate() caller to request a minimum amount
of space that itself requires, not all callers accurately use this yet
but the simple cases are now accounted for.

Rendering will also be dropped on the floor if validate fails now.
This commit is contained in:
Ben Skeggs
2010-03-03 14:43:21 +10:00
parent 62ab89785b
commit e1d015fe22
4 changed files with 38 additions and 17 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ nv50_clear(struct pipe_context *pipe, unsigned buffers,
struct pipe_framebuffer_state *fb = &nv50->framebuffer;
unsigned mode = 0, i;
if (!nv50_state_validate(nv50))
if (!nv50_state_validate(nv50, 64))
return;
if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
+1 -1
View File
@@ -229,7 +229,7 @@ extern void nv50_program_destroy(struct nv50_context *nv50,
struct nv50_program *p);
/* nv50_state_validate.c */
extern boolean nv50_state_validate(struct nv50_context *nv50);
extern boolean nv50_state_validate(struct nv50_context *nv50, unsigned dwords);
extern void nv50_state_flush_notify(struct nouveau_channel *chan);
extern void nv50_so_init_sifc(struct nv50_context *nv50,
+28 -11
View File
@@ -405,19 +405,11 @@ nv50_state_flush_notify(struct nouveau_channel *chan)
}
boolean
nv50_state_validate(struct nv50_context *nv50)
nv50_state_validate(struct nv50_context *nv50, unsigned nr_dwords)
{
struct nouveau_channel *chan = nv50->screen->base.channel;
int i;
if (nv50->screen->cur_ctx != nv50) {
for (i = 0; i < validate_list_len; i++) {
if (nv50->state.hw[i])
nv50->state.hw_dirty |= (1 << i);
}
nv50->screen->cur_ctx = nv50;
}
unsigned nr_relocs = 0;
int ret, i;
for (i = 0; i < validate_list_len; i++) {
struct state_validate *validate = &validate_list[i];
@@ -430,12 +422,37 @@ nv50_state_validate(struct nv50_context *nv50)
if (!so)
continue;
nr_dwords += (so->total + so->cur);
nr_relocs += so->cur_reloc;
so_ref(so, &nv50->state.hw[i]);
so_ref(NULL, &so);
nv50->state.hw_dirty |= (1 << i);
}
nv50->dirty = 0;
if (nv50->screen->cur_ctx != nv50) {
for (i = 0; i < validate_list_len; i++) {
if (!nv50->state.hw[i] ||
(nv50->state.hw_dirty & (1 << i)))
continue;
nr_dwords += (nv50->state.hw[i]->total +
nv50->state.hw[i]->cur);
nr_relocs += nv50->state.hw[i]->cur_reloc;
nv50->state.hw_dirty |= (1 << i);
}
nv50->screen->cur_ctx = nv50;
}
ret = MARK_RING(chan, nr_dwords, nr_relocs);
if (ret) {
debug_printf("MARK_RING(%d, %d) failed: %d\n",
nr_dwords, nr_relocs, ret);
return FALSE;
}
while (nv50->state.hw_dirty) {
i = ffs(nv50->state.hw_dirty) - 1;
nv50->state.hw_dirty &= ~(1 << i);
+8 -4
View File
@@ -425,7 +425,8 @@ nv50_draw_arrays_instanced(struct pipe_context *pipe,
if (!NV50_USING_LOATHED_EDGEFLAG(nv50))
nv50_upload_user_vbufs(nv50);
nv50_state_validate(nv50);
if (!nv50_state_validate(nv50, 0))
return;
nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step);
@@ -477,7 +478,8 @@ nv50_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
struct nouveau_grobj *tesla = nv50->screen->tesla;
boolean ret;
nv50_state_validate(nv50);
if (!nv50_state_validate(nv50, 11))
return;
BEGIN_RING(chan, tesla, 0x142c, 1);
OUT_RING (chan, 0);
@@ -633,7 +635,8 @@ nv50_draw_elements_instanced(struct pipe_context *pipe,
if (!NV50_USING_LOATHED_EDGEFLAG(nv50))
nv50_upload_user_vbufs(nv50);
nv50_state_validate(nv50);
if (!nv50_state_validate(nv50, 0))
return;
nz_divisors = init_per_instance_arrays(nv50, startInstance, pos, step);
@@ -677,7 +680,8 @@ nv50_draw_elements(struct pipe_context *pipe,
struct pipe_screen *pscreen = pipe->screen;
void *map;
nv50_state_validate(nv50);
if (!nv50_state_validate(nv50, 14))
return;
BEGIN_RING(chan, tesla, 0x142c, 1);
OUT_RING (chan, 0);