summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/nouveau
diff options
context:
space:
mode:
authorMaarten Maathuis <[email protected]>2009-12-04 22:58:22 +0100
committerMaarten Maathuis <[email protected]>2009-12-14 19:31:54 +0100
commit41b52aa3362665e08bdc2f75cc9bfdc4debc6eb0 (patch)
tree9de6cd29f35f46afc937ddf8bd71cd3fce415ca9 /src/gallium/drivers/nouveau
parent2677f199a547f6e44d964b8c34dd7f60d9523ab2 (diff)
nouveau: avoid running out of relocs
- Added flush notify functions for NV30 and NV40. - Flushing mid frame will call flush notify, which will resubmit all relocs. - We don't try to recover from reloc failure yet.
Diffstat (limited to 'src/gallium/drivers/nouveau')
-rw-r--r--src/gallium/drivers/nouveau/nouveau_stateobj.h49
1 files changed, 39 insertions, 10 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h b/src/gallium/drivers/nouveau/nouveau_stateobj.h
index 62990f9b6a6..9aee9e49566 100644
--- a/src/gallium/drivers/nouveau/nouveau_stateobj.h
+++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h
@@ -112,20 +112,30 @@ so_emit(struct nouveau_channel *chan, struct nouveau_stateobj *so)
{
struct nouveau_pushbuf *pb = chan->pushbuf;
unsigned nr, i;
+ int ret = 0;
nr = so->cur - so->push;
- if (pb->remaining < nr)
- nouveau_pushbuf_flush(chan, nr);
+ /* This will flush if we need space.
+ * We don't actually need the marker.
+ */
+ if ((ret = nouveau_pushbuf_marker_emit(chan, nr, so->cur_reloc))) {
+ debug_printf("so_emit failed marker emit with error %d\n", ret);
+ return;
+ }
pb->remaining -= nr;
memcpy(pb->cur, so->push, nr * 4);
for (i = 0; i < so->cur_reloc; i++) {
struct nouveau_stateobj_reloc *r = &so->reloc[i];
- nouveau_pushbuf_emit_reloc(chan, pb->cur + r->offset,
+ if ((ret = nouveau_pushbuf_emit_reloc(chan, pb->cur + r->offset,
r->bo, r->data, 0, r->flags,
- r->vor, r->tor);
+ r->vor, r->tor))) {
+ debug_printf("so_emit failed reloc with error %d\n", ret);
+ goto out;
+ }
}
+out:
pb->cur += nr;
}
@@ -134,26 +144,45 @@ so_emit_reloc_markers(struct nouveau_channel *chan, struct nouveau_stateobj *so)
{
struct nouveau_pushbuf *pb = chan->pushbuf;
unsigned i;
+ int ret = 0;
if (!so)
return;
i = so->cur_reloc << 1;
- if (pb->remaining < i)
- nouveau_pushbuf_flush(chan, i);
+ /* This will flush if we need space.
+ * We don't actually need the marker.
+ */
+ if ((ret = nouveau_pushbuf_marker_emit(chan, i, i))) {
+ debug_printf("so_emit_reloc_markers failed marker emit with" \
+ "error %d\n", ret);
+ return;
+ }
pb->remaining -= i;
for (i = 0; i < so->cur_reloc; i++) {
struct nouveau_stateobj_reloc *r = &so->reloc[i];
- nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->packet, 0,
+ if ((ret = nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo,
+ r->packet, 0,
(r->flags & (NOUVEAU_BO_VRAM |
NOUVEAU_BO_GART |
NOUVEAU_BO_RDWR)) |
- NOUVEAU_BO_DUMMY, 0, 0);
- nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->data, 0,
+ NOUVEAU_BO_DUMMY, 0, 0))) {
+ debug_printf("so_emit_reloc_markers failed reloc" \
+ "with error %d\n", ret);
+ pb->remaining += ((so->cur_reloc - i) << 1);
+ return;
+ }
+ if ((ret = nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo,
+ r->data, 0,
r->flags | NOUVEAU_BO_DUMMY,
- r->vor, r->tor);
+ r->vor, r->tor))) {
+ debug_printf("so_emit_reloc_markers failed reloc" \
+ "with error %d\n", ret);
+ pb->remaining += ((so->cur_reloc - i) << 1) - 1;
+ return;
+ }
}
}