summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-03-03 14:43:21 +1000
committerBen Skeggs <bskeggs@redhat.com>2010-03-10 16:29:58 +1000
commite1d015fe222a3f6f942426c39fb1a17188df8d57 (patch)
tree393856ee4899e39b1e0b27f5dbd3582c516c8b0f /src/gallium
parent62ab89785b55e60b978dc2b32995676859299c80 (diff)
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.
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/nv50/nv50_clear.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h2
-rw-r--r--src/gallium/drivers/nv50/nv50_state_validate.c39
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c12
4 files changed, 38 insertions, 17 deletions
diff --git a/src/gallium/drivers/nv50/nv50_clear.c b/src/gallium/drivers/nv50/nv50_clear.c
index e0b2d2880b0..8afc95c9fc6 100644
--- a/src/gallium/drivers/nv50/nv50_clear.c
+++ b/src/gallium/drivers/nv50/nv50_clear.c
@@ -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) {
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index 5fa39111148..ef0e99f0b12 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -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,
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
index abdb9a55c85..b01a3d87de6 100644
--- a/src/gallium/drivers/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -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);
diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c
index 3e540013c42..ce2e479cfda 100644
--- a/src/gallium/drivers/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nv50/nv50_vbo.c
@@ -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);