summaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2008-02-03 12:08:31 +1100
committerBen Skeggs <skeggsb@gmail.com>2008-02-15 13:50:29 +1100
commit705022f98c32c44b94411ea13dfe4cbc899f5a77 (patch)
treede1031e64b702e63faf0099c03bb520b3c5b00e0 /src/mesa/drivers
parent8bbedc3f4b7b281a60286ba573077a6e3e659f63 (diff)
nouveau: avoid relocations where possible.
Potential relocations are emitted as NOPs where they're needed. In the event a buffer moves, the pushbuf code will emit the relevant state changes into the NOPs. Just a start, more work is needed to get this looking how I want it to.
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h3
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c61
2 files changed, 39 insertions, 25 deletions
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h
index 7a539c81a9..59febca292 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h
@@ -61,9 +61,8 @@
} while(0)
#define OUT_RELOC(buf,data,flags,vor,tor) do { \
- nouveau_pipe_emit_reloc(nv->channel, nv->channel->pushbuf->cur, \
+ nouveau_pipe_emit_reloc(nv->channel, nv->channel->pushbuf->cur++, \
buf, (data), (flags), (vor), (tor)); \
- OUT_RING(0); \
} while(0)
/* Raw data + flags depending on FB/TT buffer */
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c
index a34a5c1866..7d5eddb92f 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c
@@ -96,6 +96,31 @@ nouveau_pushbuf_init(struct nouveau_channel *chan)
return 0;
}
+static uint32_t
+nouveau_pushbuf_calc_reloc(struct nouveau_bo *bo,
+ struct nouveau_pushbuf_reloc *r)
+{
+ uint32_t push;
+
+ if (r->flags & NOUVEAU_BO_LOW) {
+ push = bo->offset + r->data;
+ } else
+ if (r->flags & NOUVEAU_BO_HIGH) {
+ push = (bo->offset + r->data) >> 32;
+ } else {
+ push = r->data;
+ }
+
+ if (r->flags & NOUVEAU_BO_OR) {
+ if (bo->flags & NOUVEAU_BO_VRAM)
+ push |= r->vor;
+ else
+ push |= r->tor;
+ }
+
+ return push;
+}
+
/* This would be our TTM "superioctl" */
int
nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min)
@@ -133,34 +158,20 @@ nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min)
if (bo->offset == nouveau_bo(bo)->offset &&
bo->flags == nouveau_bo(bo)->flags) {
- /*XXX: could avoid reloc in this case, except with the
- * current design we'd confuse the GPU quite a bit
- * if we did this. Will fix soon.
- */
+ while ((r = ptr_to_pbrel(pbbo->relocs))) {
+ pbbo->relocs = r->next;
+ free(r);
+ }
+
+ nvpb->buffers = pbbo->next;
+ free(pbbo);
+ continue;
}
bo->offset = nouveau_bo(bo)->offset;
bo->flags = nouveau_bo(bo)->flags;
while ((r = ptr_to_pbrel(pbbo->relocs))) {
- uint32_t push;
-
- if (r->flags & NOUVEAU_BO_LOW) {
- push = bo->offset + r->data;
- } else
- if (r->flags & NOUVEAU_BO_HIGH) {
- push = (bo->offset + r->data) >> 32;
- } else {
- push = r->data;
- }
-
- if (r->flags & NOUVEAU_BO_OR) {
- if (bo->flags & NOUVEAU_BO_VRAM)
- push |= r->vor;
- else
- push |= r->tor;
- }
-
- *r->ptr = push;
+ *r->ptr = nouveau_pushbuf_calc_reloc(bo, r);
pbbo->relocs = r->next;
free(r);
}
@@ -241,6 +252,10 @@ nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
r->vor = vor;
r->tor = tor;
+ if (flags & NOUVEAU_BO_DUMMY)
+ *(uint32_t *)ptr = 0;
+ else
+ *(uint32_t *)ptr = nouveau_pushbuf_calc_reloc(bo, r);
return 0;
}