diff options
author | Ben Skeggs <skeggsb@gmail.com> | 2007-12-09 21:44:46 +1100 |
---|---|---|
committer | Ben Skeggs <skeggsb@gmail.com> | 2007-12-09 21:44:46 +1100 |
commit | f58f4e0f0ecc6c7079ef52f4a417707843507fab (patch) | |
tree | 06b2914da5be97537ae76e424ea60a41609bf3ab /src/mesa/drivers | |
parent | 62bbf8db873716c56ca089dbba59d1d3980563b5 (diff) |
nouveau: relocs are per-pushbuf, not per-channel
Diffstat (limited to 'src/mesa/drivers')
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; |