summaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-12-09 21:44:46 +1100
committerBen Skeggs <skeggsb@gmail.com>2007-12-09 21:44:46 +1100
commitf58f4e0f0ecc6c7079ef52f4a417707843507fab (patch)
tree06b2914da5be97537ae76e424ea60a41609bf3ab /src/mesa/drivers
parent62bbf8db873716c56ca089dbba59d1d3980563b5 (diff)
nouveau: relocs are per-pushbuf, not per-channel
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c90
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c8
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h60
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h4
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c87
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c2
6 files changed, 136 insertions, 115 deletions
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c
index f1981b9777..fd6d05b7fa 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c
@@ -232,47 +232,6 @@ nouveau_bo_unmap(struct nouveau_bo *userbo)
userbo->map = NULL;
}
-void
-nouveau_bo_emit_reloc(struct nouveau_channel *userchan, void *ptr,
- struct nouveau_bo *userbo, uint32_t data, uint32_t flags,
- uint32_t vor, uint32_t tor)
-{
- struct nouveau_channel_priv *chan = nouveau_channel(userchan);
- struct nouveau_bo_priv *bo = nouveau_bo(userbo);
- struct nouveau_bo_reloc *r;
- int i, on_list = 0;
-
- for (i = 0; i < chan->nr_buffers; i++) {
- if (chan->buffers[i].bo == bo) {
- on_list = 1;
- break;
- }
- }
-
- if (i >= 128)
- return;
-
- if (on_list) {
- chan->buffers[i].flags &= (flags | NOUVEAU_BO_RDWR);
- chan->buffers[i].flags |= (flags & NOUVEAU_BO_RDWR);
- } else {
- chan->buffers[i].bo = bo;
- chan->buffers[i].flags = flags;
- chan->nr_buffers++;
- }
-
- if (chan->num_relocs >= chan->max_relocs)
- FIRE_RING_CH(userchan);
- r = &chan->relocs[chan->num_relocs++];
-
- r->ptr = ptr;
- r->bo = bo;
- r->data = data;
- r->flags = flags;
- r->vor = vor;
- r->tor = tor;
-}
-
static int
nouveau_bo_upload(struct nouveau_bo_priv *bo)
{
@@ -280,35 +239,30 @@ nouveau_bo_upload(struct nouveau_bo_priv *bo)
return 0;
}
-void
-nouveau_bo_validate(struct nouveau_channel *userchan)
+int
+nouveau_bo_validate(struct nouveau_channel *chan, struct nouveau_bo *bo,
+ uint32_t flags)
{
- struct nouveau_channel_priv *chan = nouveau_channel(userchan);
- int i;
-
- for (i = 0; i < chan->nr_buffers; i++) {
- struct nouveau_bo_priv *bo = chan->buffers[i].bo;
-
- if (!bo->drm.size) {
- nouveau_bo_realloc_gpu(bo, chan->buffers[i].flags,
- bo->base.size);
- nouveau_bo_upload(bo);
- } else
- if (bo->user || bo->base.map)
- nouveau_bo_upload(bo);
-
- if (!bo->user && !bo->base.map) {
- free(bo->sysmem);
- bo->sysmem = NULL;
- }
+ struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+
+ if (!nvbo->drm.size) {
+ nouveau_bo_realloc_gpu(nvbo, flags, nvbo->base.size);
+ nouveau_bo_upload(nvbo);
+ } else
+ if (nvbo->user || nvbo->base.map)
+ nouveau_bo_upload(nvbo);
+
+ if (!nvbo->user && !nvbo->base.map) {
+ free(nvbo->sysmem);
+ nvbo->sysmem = NULL;
+ }
+ nvbo->base.offset = nvbo->drm.offset;
+ if (nvbo->drm.flags & NOUVEAU_MEM_AGP)
+ nvbo->base.flags = NOUVEAU_BO_GART;
+ else
+ nvbo->base.flags = NOUVEAU_BO_VRAM;
- bo->base.offset = bo->drm.offset;
- if (bo->drm.flags & NOUVEAU_MEM_AGP)
- bo->base.flags = NOUVEAU_BO_GART;
- else
- bo->base.flags = NOUVEAU_BO_VRAM;
- }
- chan->nr_buffers = 0;
+ return 0;
}
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c
index 64136775da..c4558e5573 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c
@@ -85,11 +85,6 @@ nouveau_channel_alloc(struct nouveau_device *userdev, uint32_t fb_ctxdma,
return ret;
}
- chan->max_relocs = chan->drm.cmdbuf_size / 4;
- chan->num_relocs = 0;
- chan->relocs =
- malloc(sizeof(struct nouveau_bo_reloc) * chan->max_relocs);
-
nouveau_dma_channel_init(&chan->base);
nouveau_pushbuf_init(&chan->base);
@@ -115,9 +110,6 @@ nouveau_channel_free(struct nouveau_channel **userchan)
FIRE_RING_CH(&chan->base);
- if (chan->relocs)
- free(chan->relocs);
-
nouveau_grobj_free(&chan->base.vram);
nouveau_grobj_free(&chan->base.gart);
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h
index 4f467406dd..8af0b9d5cd 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h
@@ -94,6 +94,24 @@ nouveau_fence_wait(struct nouveau_fence **);
extern void
nouveau_fence_flush(struct nouveau_channel *);
+struct nouveau_pushbuf_reloc {
+ uint64_t next;
+ uint64_t handle;
+ uint32_t *ptr;
+ uint32_t flags;
+ uint32_t data;
+ uint32_t vor;
+ uint32_t tor;
+};
+
+struct nouveau_pushbuf_bo {
+ uint64_t next;
+ uint64_t handle;
+ uint64_t flags;
+ uint64_t relocs;
+ int nr_relocs;
+};
+
struct nouveau_pushbuf {
struct nouveau_channel *channel;
unsigned remaining;
@@ -106,8 +124,17 @@ struct nouveau_pushbuf_priv {
struct nouveau_resource *res;
struct nouveau_fence *fence;
+
+ uint64_t buffers;
+ int nr_buffers;
};
#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n))
+#define pbbo_to_ptr(o) ((uint64_t)(unsigned long)(o))
+#define ptr_to_pbbo(h) ((struct nouveau_pushbuf_bo *)(unsigned long)(h))
+#define pbrel_to_ptr(o) ((uint64_t)(unsigned long)(o))
+#define ptr_to_pbrel(h) ((struct nouveau_pushbuf_reloc *)(unsigned long)(h))
+#define bo_to_ptr(o) ((uint64_t)(unsigned long)(o))
+#define ptr_to_bo(h) ((struct nouveau_bo_priv *)(unsigned long)(h))
extern int
nouveau_pushbuf_init(struct nouveau_channel *);
@@ -115,6 +142,11 @@ nouveau_pushbuf_init(struct nouveau_channel *);
extern int
nouveau_pushbuf_flush(struct nouveau_channel *);
+extern int
+nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
+ struct nouveau_bo *, uint32_t data, uint32_t flags,
+ uint32_t vor, uint32_t tor);
+
struct nouveau_channel_priv {
struct nouveau_channel base;
@@ -142,16 +174,6 @@ struct nouveau_channel_priv {
int push_free;
} dma;
- struct {
- struct nouveau_bo_priv *bo;
- uint32_t flags;
- } buffers[128];
- int nr_buffers;
-
- struct nouveau_bo_reloc *relocs;
- int num_relocs;
- int max_relocs;
-
struct nouveau_fence *fence_head;
struct nouveau_fence *fence_tail;
uint32_t fence_sequence;
@@ -222,14 +244,6 @@ struct nouveau_bo_priv {
int refcount;
};
-
-struct nouveau_bo_reloc {
- struct nouveau_bo_priv *bo;
- uint32_t *ptr;
- uint32_t flags;
- uint32_t data, vor, tor;
-};
-
#define nouveau_bo(n) ((struct nouveau_bo_priv *)(n))
extern int
@@ -261,13 +275,9 @@ nouveau_bo_map(struct nouveau_bo *, uint32_t flags);
extern void
nouveau_bo_unmap(struct nouveau_bo *);
-extern void
-nouveau_bo_emit_reloc(struct nouveau_channel *chan, void *ptr,
- struct nouveau_bo *, uint32_t data, uint32_t flags,
- uint32_t vor, uint32_t tor);
-
-extern void
-nouveau_bo_validate(struct nouveau_channel *);
+extern int
+nouveau_bo_validate(struct nouveau_channel *, struct nouveau_bo *,
+ uint32_t flags);
extern int
nouveau_resource_init(struct nouveau_resource **heap, int size);
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h
index 2534a8ea6f..1978edea02 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h
@@ -49,8 +49,8 @@
} while(0)
#define OUT_RELOC(bo,data,flags,vor,tor) do { \
- nouveau_bo_emit_reloc(nv->channel, nv->pushbuf, (void*)(bo), (data), \
- (flags), (vor), (tor)); \
+ nouveau_pushbuf_emit_reloc(nv->channel, nv->pushbuf, (void*)(bo), \
+ (data), (flags), (vor), (tor)); \
OUT_RING(0); \
} while(0)
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c
index 75d41d6c14..4a964cb82b 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c
@@ -54,7 +54,8 @@ nouveau_pushbuf_flush(struct nouveau_channel *chan)
{
struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(nvchan->pb_tail);
- int i, ret;
+ struct nouveau_pushbuf_bo *pbbo;
+ int ret;
if (!nvpb)
goto out_realloc;
@@ -66,36 +67,42 @@ nouveau_pushbuf_flush(struct nouveau_channel *chan)
if (ret)
return ret;
- /* Validate buffers */
- nouveau_bo_validate(chan);
+ /* Validate buffers + apply relocations */
+ while ((pbbo = ptr_to_pbbo(nvpb->buffers))) {
+ struct nouveau_pushbuf_reloc *r;
+ struct nouveau_bo *bo = &ptr_to_bo(pbbo->handle)->base;
- /* Apply relocations */
- if (nvchan->num_relocs) {
- for (i = 0; i < nvchan->num_relocs; i++) {
- struct nouveau_bo_reloc *r = &nvchan->relocs[i];
+ ret = nouveau_bo_validate(chan, bo, pbbo->flags);
+ assert (ret == 0);
+
+ while ((r = ptr_to_pbrel(pbbo->relocs))) {
uint32_t push;
if (r->flags & NOUVEAU_BO_LOW) {
- push = r->bo->base.offset + r->data;
+ push = bo->offset + r->data;
} else
if (r->flags & NOUVEAU_BO_HIGH) {
- push = (r->bo->base.offset + r->data) >> 32;
+ push = (bo->offset + r->data) >> 32;
} else {
push = r->data;
}
if (r->flags & NOUVEAU_BO_OR) {
- if (r->bo->base.flags & NOUVEAU_BO_VRAM)
+ if (bo->flags & NOUVEAU_BO_VRAM)
push |= r->vor;
else
push |= r->tor;
}
*r->ptr = push;
+ pbbo->relocs = r->next;
+ free(r);
}
- nvchan->num_relocs = 0;
+ nvpb->buffers = pbbo->next;
+ free(pbbo);
}
+ nvpb->nr_buffers = 0;
/* Emit JMP to indirect pushbuf */
if (nvchan->dma.free < 1)
@@ -175,3 +182,61 @@ out_realloc:
return 0;
}
+static struct nouveau_pushbuf_bo *
+nouveau_pushbuf_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
+{
+ struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+ struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(nvchan->pb_tail);
+ struct nouveau_pushbuf_bo *pbbo = ptr_to_pbbo(nvpb->buffers);
+
+ while (pbbo) {
+ if (pbbo->handle == bo->handle)
+ return pbbo;
+ pbbo = ptr_to_pbbo(pbbo->next);
+ }
+
+ pbbo = malloc(sizeof(struct nouveau_pushbuf_bo));
+ pbbo->next = nvpb->buffers;
+ nvpb->buffers = pbbo_to_ptr(pbbo);
+ nvpb->nr_buffers++;
+
+ pbbo->handle = bo_to_ptr(bo);
+ pbbo->flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
+ pbbo->relocs = 0;
+ pbbo->nr_relocs = 0;
+ return pbbo;
+}
+
+int
+nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
+ struct nouveau_bo *bo, uint32_t data, uint32_t flags,
+ uint32_t vor, uint32_t tor)
+{
+ struct nouveau_pushbuf_bo *pbbo;
+ struct nouveau_pushbuf_reloc *r;
+
+ if (!chan)
+ return -EINVAL;
+
+ pbbo = nouveau_pushbuf_emit_buffer(chan, bo);
+ if (!pbbo)
+ return -EFAULT;
+
+ r = malloc(sizeof(struct nouveau_pushbuf_reloc));
+ r->next = pbbo->relocs;
+ pbbo->relocs = pbrel_to_ptr(r);
+ pbbo->nr_relocs++;
+
+ pbbo->flags |= (flags & NOUVEAU_BO_RDWR);
+ pbbo->flags &= (flags | NOUVEAU_BO_RDWR);
+
+ r->handle = bo_to_ptr(r);
+ r->ptr = ptr;
+ r->flags = flags;
+ r->data = data;
+ r->vor = vor;
+ r->tor = tor;
+
+ return 0;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c
index 77d9e710db..9919272ebe 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c
@@ -204,7 +204,7 @@ nouveau_pipe_create(struct nouveau_context *nv)
nvws->res_free = nouveau_resource_free;
nvws->begin_ring = nouveau_pipe_dma_beginp;
- nvws->out_reloc = nouveau_bo_emit_reloc;
+ nvws->out_reloc = nouveau_pushbuf_emit_reloc;
nvws->fire_ring = nouveau_pipe_dma_kickoff;
nvws->grobj_alloc = nouveau_pipe_grobj_alloc;