diff options
author | Ben Skeggs <skeggsb@gmail.com> | 2007-12-09 20:38:08 +1100 |
---|---|---|
committer | Ben Skeggs <skeggsb@gmail.com> | 2007-12-09 20:38:08 +1100 |
commit | 62bbf8db873716c56ca089dbba59d1d3980563b5 (patch) | |
tree | cc06a01ad33039183fd616ee2f0e3e1072883943 /src | |
parent | b8965bee404cb36ccd97ac089fbd3ffc63268080 (diff) |
nouveau: use "indirect" push buffers
Diffstat (limited to 'src')
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/Makefile | 2 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c | 1 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h | 4 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c | 45 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h | 76 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c | 135 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h | 18 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c | 177 | ||||
-rw-r--r-- | src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c | 34 | ||||
-rw-r--r-- | src/mesa/pipe/nouveau/nouveau_resource.h | 37 | ||||
-rw-r--r-- | src/mesa/pipe/nouveau/nouveau_winsys.h | 12 |
11 files changed, 474 insertions, 67 deletions
diff --git a/src/mesa/drivers/dri/nouveau_winsys/Makefile b/src/mesa/drivers/dri/nouveau_winsys/Makefile index 9b8a33b725..fe9a9668b1 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/Makefile +++ b/src/mesa/drivers/dri/nouveau_winsys/Makefile @@ -17,9 +17,11 @@ DRIVER_SOURCES = \ nouveau_context.c \ nouveau_device.c \ nouveau_dma.c \ + nouveau_fence.c \ nouveau_grobj.c \ nouveau_lock.c \ nouveau_notifier.c \ + nouveau_pushbuf.c \ nouveau_screen.c \ nouveau_swapbuffers.c \ nouveau_winsys.c \ diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c index ef41020b72..64136775da 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c @@ -91,6 +91,7 @@ nouveau_channel_alloc(struct nouveau_device *userdev, uint32_t fb_ctxdma, malloc(sizeof(struct nouveau_bo_reloc) * chan->max_relocs); nouveau_dma_channel_init(&chan->base); + nouveau_pushbuf_init(&chan->base); *userchan = &chan->base; return 0; diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h index 7033ff7ae9..cd59b7cc43 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h @@ -44,6 +44,7 @@ struct nouveau_context { struct nouveau_bo *reloc_head; /* Hardware context */ + uint32_t *pushbuf; struct nouveau_channel *channel; struct nouveau_notifier *sync_notifier; struct nouveau_grobj *NvNull; @@ -98,4 +99,7 @@ extern void UNLOCK_HARDWARE(struct nouveau_context *); extern int nouveau_surface_init_nv04(struct nouveau_context *); extern int nouveau_surface_init_nv50(struct nouveau_context *); +extern uint32_t *nouveau_pipe_dma_beginp(struct nouveau_grobj *, int, int); +extern void nouveau_pipe_dma_kickoff(struct nouveau_channel *); + #endif diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c index 6e123c4473..6e32d739ab 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c @@ -141,35 +141,6 @@ nouveau_dma_kickoff(struct nouveau_channel *userchan) if (chan->dma.cur == chan->dma.put) return; - if (chan->num_relocs) { - nouveau_bo_validate(userchan); - - for (i = 0; i < chan->num_relocs; i++) { - struct nouveau_bo_reloc *r = &chan->relocs[i]; - uint32_t push; - - if (r->flags & NOUVEAU_BO_LOW) { - push = r->bo->base.offset + r->data; - } else - if (r->flags & NOUVEAU_BO_HIGH) { - push = (r->bo->base.offset + r->data) >> 32; - } else { - push = r->data; - } - - if (r->flags & NOUVEAU_BO_OR) { - if (r->bo->base.flags & NOUVEAU_BO_VRAM) - push |= r->vor; - else - push |= r->tor; - } - - *r->ptr = push; - } - - chan->num_relocs = 0; - } - #ifdef NOUVEAU_DMA_DEBUG if (chan->dma.push_free) { NOUVEAU_ERR("Packet incomplete: %d left\n", chan->dma.push_free); @@ -178,8 +149,20 @@ nouveau_dma_kickoff(struct nouveau_channel *userchan) #endif #ifdef NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF - for (i = chan->dma.put; i < chan->dma.cur; i++) - NOUVEAU_MSG("0x%08x\n", chan->pushbuf[i]); + for (i = chan->dma.put; i < chan->dma.cur; i++) { + NOUVEAU_MSG("0x%08x 0x%08x\n", (i<<2)+chan->dma.base, + chan->pushbuf[i]); + if ((chan->pushbuf[i] & 0xf0000000) == 0x20000000) { + int n = (((chan->pushbuf[i] & 0x0fffffff) - + chan->dma.base) / 4); + + do { + NOUVEAU_MSG("\t0x%08x 0x%08x\n", + (n<<2)+chan->dma.base, + chan->pushbuf[n]); + } while ((chan->pushbuf[n++]&0xf0000000) != 0x20000000); + } + } #endif put_offset = (chan->dma.cur << 2) + chan->dma.base; diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h index df98890f8e..4f467406dd 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h @@ -32,6 +32,7 @@ #include "pipe/nouveau/nouveau_grobj.h" #include "pipe/nouveau/nouveau_notifier.h" #include "pipe/nouveau/nouveau_bo.h" +#include "pipe/nouveau/nouveau_resource.h" struct nouveau_device_priv { struct nouveau_device base; @@ -59,6 +60,61 @@ nouveau_device_get_param(struct nouveau_device *, uint64_t param, uint64_t *v); extern int nouveau_device_set_param(struct nouveau_device *, uint64_t param, uint64_t val); +struct nouveau_fence { + struct nouveau_channel *channel; +}; + +struct nouveau_fence_priv { + struct nouveau_fence base; + int refcount; + + struct nouveau_fence *next; + + uint32_t sequence; + int emitted; + int signalled; +}; +#define nouveau_fence(n) ((struct nouveau_fence_priv *)(n)) + +extern int +nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **); + +extern int +nouveau_fence_ref(struct nouveau_fence *, struct nouveau_fence **); + +extern void +nouveau_fence_del(struct nouveau_fence **); + +extern void +nouveau_fence_emit(struct nouveau_fence *); + +extern int +nouveau_fence_wait(struct nouveau_fence **); + +extern void +nouveau_fence_flush(struct nouveau_channel *); + +struct nouveau_pushbuf { + struct nouveau_channel *channel; + unsigned remaining; + uint32_t *cur; +}; + +struct nouveau_pushbuf_priv { + struct nouveau_pushbuf base; + struct nouveau_pushbuf *next; + + struct nouveau_resource *res; + struct nouveau_fence *fence; +}; +#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n)) + +extern int +nouveau_pushbuf_init(struct nouveau_channel *); + +extern int +nouveau_pushbuf_flush(struct nouveau_channel *); + struct nouveau_channel_priv { struct nouveau_channel base; @@ -95,6 +151,14 @@ struct nouveau_channel_priv { 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; + + struct nouveau_resource *pb_heap; + struct nouveau_pushbuf *pb_head; + struct nouveau_pushbuf *pb_tail; }; #define nouveau_channel(n) ((struct nouveau_channel_priv *)(n)) @@ -148,6 +212,8 @@ nouveau_notifier_wait_status(struct nouveau_notifier *, int id, int status, struct nouveau_bo_priv { struct nouveau_bo base; + struct nouveau_fence *fence; + struct drm_nouveau_mem_alloc drm; void *map; @@ -203,4 +269,14 @@ nouveau_bo_emit_reloc(struct nouveau_channel *chan, void *ptr, extern void nouveau_bo_validate(struct nouveau_channel *); +extern int +nouveau_resource_init(struct nouveau_resource **heap, int size); + +extern int +nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv, + struct nouveau_resource **); + +extern void +nouveau_resource_free(struct nouveau_resource **); + #endif diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c new file mode 100644 index 0000000000..842b38f913 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c @@ -0,0 +1,135 @@ +/* + * Copyright 2007 Nouveau Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <stdlib.h> +#include <errno.h> + +#include "nouveau_drmif.h" +#include "nouveau_dma.h" +#include "nouveau_local.h" + +int +nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **fence) +{ + struct nouveau_fence_priv *nvfence; + + if (!chan || !fence || *fence) + return -EINVAL; + + nvfence = calloc(1, sizeof(struct nouveau_fence_priv)); + if (!nvfence) + return -ENOMEM; + nvfence->base.channel = chan; + nvfence->refcount = 1; + + *fence = &nvfence->base; + return 0; +} + +int +nouveau_fence_ref(struct nouveau_fence *ref, struct nouveau_fence **fence) +{ + struct nouveau_fence_priv *nvfence; + + if (!ref || !fence || *fence) + return -EINVAL; + nvfence = nouveau_fence(ref); + nvfence->refcount++; + + *fence = &nvfence->base; + return 0; +} + +void +nouveau_fence_del(struct nouveau_fence **fence) +{ + struct nouveau_fence_priv *nvfence; + + if (!fence || !*fence) + return; + nvfence = nouveau_fence(*fence); + *fence = NULL; + + if (--nvfence->refcount <= 0) { + if (nvfence->emitted && !nvfence->signalled) + nouveau_fence_wait((void *)&nvfence); + free(nvfence); + } +} + +void +nouveau_fence_emit(struct nouveau_fence *fence) +{ + struct nouveau_channel_priv *nvchan = nouveau_channel(fence->channel); + struct nouveau_fence_priv *nvfence = nouveau_fence(fence); + + nvfence->emitted = 1; + nvfence->sequence = ++nvchan->fence_sequence; + if (nvfence->sequence == 0xffffffff) + NOUVEAU_ERR("AII wrap unhandled\n"); + + BEGIN_RING_CH(&nvchan->base, nvchan->subchannel[0].grobj, 0x50, 1); + OUT_RING_CH (&nvchan->base, nvfence->sequence); + + if (nvchan->fence_tail) { + nouveau_fence(nvchan->fence_tail)->next = fence; + } else { + nvchan->fence_head = fence; + } + nvchan->fence_tail = fence; +} + +void +nouveau_fence_flush(struct nouveau_channel *chan) +{ + struct nouveau_channel_priv *nvchan = nouveau_channel(chan); + struct nouveau_fence_priv *nvfence = nouveau_fence(nvchan->fence_head); + uint32_t sequence = *nvchan->ref_cnt; + + while (nvchan->fence_head && nvfence->sequence <= sequence) { + nvfence->signalled = 1; + + nvchan->fence_head = nvfence->next; + if (nvchan->fence_head == NULL) + nvchan->fence_tail = NULL; + nvfence = nouveau_fence(nvchan->fence_head); + } +} + +int +nouveau_fence_wait(struct nouveau_fence **fence) +{ + struct nouveau_fence_priv *nvfence; + + if (!fence || !*fence) + return -EINVAL; + nvfence = nouveau_fence(*fence); + + if (nvfence->emitted) { + while (!nvfence->signalled) + nouveau_fence_flush(nvfence->base.channel); + } + nouveau_fence_del(fence); + + return 0; +} + diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h index 4ada5d014b..2534a8ea6f 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h @@ -26,15 +26,16 @@ /* Push buffer access macros */ #define BEGIN_RING(obj,mthd,size) do { \ - BEGIN_RING_CH(nv->channel, nv->obj, (mthd), (size)); \ + nv->pushbuf = nouveau_pipe_dma_beginp(nv->obj, (mthd), (size)); \ } while(0) #define OUT_RING(data) do { \ - OUT_RING_CH(nv->channel, (data)); \ + (*nv->pushbuf++) = (data); \ } while(0) #define OUT_RINGp(src,size) do { \ - OUT_RINGp_CH(nv->channel, (src), (size)); \ + memcpy(nv->pushbuf, (src), (size)<<2); \ + nv->pushbuf += (size); \ } while(0) #define OUT_RINGf(data) do { \ @@ -43,18 +44,13 @@ OUT_RING(c.u); \ } while(0) -#define WAIT_RING(size) do { \ - WAIT_RING_CH(nv->channel, (size)); \ -} while(0) - #define FIRE_RING() do { \ - FIRE_RING_CH(nv->channel); \ + nouveau_pipe_dma_kickoff(nv->channel); \ } while(0) #define OUT_RELOC(bo,data,flags,vor,tor) do { \ - struct nouveau_channel_priv *chan = nouveau_channel(nv->channel); \ - nouveau_bo_emit_reloc(nv->channel, &chan->pushbuf[chan->dma.cur], \ - (void*)(bo), (data), (flags), (vor), (tor)); \ + nouveau_bo_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 new file mode 100644 index 0000000000..75d41d6c14 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c @@ -0,0 +1,177 @@ +/* + * Copyright 2007 Nouveau Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <stdlib.h> +#include <errno.h> +#include <assert.h> + +#include "nouveau_drmif.h" +#include "nouveau_dma.h" + +int +nouveau_pushbuf_init(struct nouveau_channel *chan) +{ + struct nouveau_channel_priv *nvchan = nouveau_channel(chan); + + if (!nvchan) + return -EINVAL; + + /* Everything except first 4KiB of the push buffer is managed by us */ + if (nouveau_resource_init(&nvchan->pb_heap, + nvchan->drm.cmdbuf_size - 4096)) + return -EINVAL; + + /* Shrink master ring to 4KiB */ + assert(nvchan->dma.cur <= (4096/4)); + nvchan->dma.max = (4096 / 4) - 2; + nvchan->dma.free = nvchan->dma.max - nvchan->dma.cur; + + return 0; +} + +/* This would be our TTM "superioctl" */ +int +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; + + if (!nvpb) + goto out_realloc; + + if (nvpb->base.remaining == nvpb->res->size / 4) + return 0; + + ret = nouveau_fence_new(chan, &nvpb->fence); + if (ret) + return ret; + + /* Validate buffers */ + nouveau_bo_validate(chan); + + /* Apply relocations */ + if (nvchan->num_relocs) { + for (i = 0; i < nvchan->num_relocs; i++) { + struct nouveau_bo_reloc *r = &nvchan->relocs[i]; + uint32_t push; + + if (r->flags & NOUVEAU_BO_LOW) { + push = r->bo->base.offset + r->data; + } else + if (r->flags & NOUVEAU_BO_HIGH) { + push = (r->bo->base.offset + r->data) >> 32; + } else { + push = r->data; + } + + if (r->flags & NOUVEAU_BO_OR) { + if (r->bo->base.flags & NOUVEAU_BO_VRAM) + push |= r->vor; + else + push |= r->tor; + } + + *r->ptr = push; + } + + nvchan->num_relocs = 0; + } + + /* Emit JMP to indirect pushbuf */ + if (nvchan->dma.free < 1) + WAIT_RING_CH(chan, 1); + nvchan->dma.free -= 1; + OUT_RING_CH(chan, 0x20000000 | (nvpb->res->start + 4096)); + + /* Add JMP back to master pushbuf from indirect pushbuf */ + (*nvpb->base.cur++) = + 0x20000000 | ((nvchan->dma.cur << 2) + nvchan->dma.base); + + /* Fence */ + nouveau_fence_emit(nvpb->fence); + + /* Kickoff */ + FIRE_RING_CH(chan); + + /* Allocate space for next push buffer */ +out_realloc: + nvpb = calloc(1, sizeof(struct nouveau_pushbuf_priv)); + if (!nvpb) + return -ENOMEM; + + if (nouveau_resource_alloc(nvchan->pb_heap, 0x2000, NULL, &nvpb->res)) { + struct nouveau_pushbuf_priv *e; + int nr = 0; + + /* Update fences */ + nouveau_fence_flush(chan); + + /* Free any push buffers that have already been executed */ + e = nouveau_pushbuf(nvchan->pb_head); + while (e && e->fence) { + if (!e->fence || !nouveau_fence(e->fence)->signalled) + break; + nouveau_fence_del(&e->fence); + nouveau_resource_free(&e->res); + nr++; + + nvchan->pb_head = e->next; + if (nvchan->pb_head == NULL) + nvchan->pb_tail = NULL; + free(e); + e = nouveau_pushbuf(nvchan->pb_head); + } + + /* We didn't free any buffers above. As a last resort, busy + * wait on the oldest buffer becoming available. + */ + if (!nr) { + e = nouveau_pushbuf(nvchan->pb_head); + nouveau_fence_wait(&e->fence); + nouveau_resource_free(&e->res); + + nvchan->pb_head = e->next; + if (nvchan->pb_head == NULL) + nvchan->pb_tail = NULL; + free(e); + } + + if (nouveau_resource_alloc(nvchan->pb_heap, 0x2000, nvpb, + &nvpb->res)) + assert(0); + } + + nvpb->base.channel = chan; + nvpb->base.remaining = nvpb->res->size / 4; + nvpb->base.cur = &nvchan->pushbuf[(nvpb->res->start + 4096)/4]; + + if (nvchan->pb_tail) { + nouveau_pushbuf(nvchan->pb_tail)->next = & nvpb->base; + } else { + nvchan->pb_head = &nvpb->base; + } + nvchan->pb_tail = &nvpb->base; + + 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 6ef81ccb86..77d9e710db 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c @@ -5,7 +5,7 @@ #include "pipe/nouveau/nouveau_winsys.h" -static int +int nouveau_resource_init(struct nouveau_resource **heap, int size) { struct nouveau_resource *r; @@ -20,7 +20,7 @@ nouveau_resource_init(struct nouveau_resource **heap, int size) return 0; } -static int +int nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv, struct nouveau_resource **res) { @@ -58,7 +58,7 @@ nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv, return 1; } -static void +void nouveau_resource_free(struct nouveau_resource **res) { struct nouveau_resource *r; @@ -108,25 +108,31 @@ nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass, grclass, grobj); } -static uint32_t * +uint32_t * nouveau_pipe_dma_beginp(struct nouveau_grobj *grobj, int mthd, int size) { - struct nouveau_channel_priv *chan = nouveau_channel(grobj->channel); + struct nouveau_channel_priv *nvchan = nouveau_channel(grobj->channel); uint32_t *pushbuf; - BEGIN_RING_CH(&chan->base, grobj, mthd, size); - pushbuf = &chan->pushbuf[chan->dma.cur]; - chan->dma.cur += size; -#ifdef NOUVEAU_DMA_DEBUG - chan->dma.push_free -= size; -#endif + if (!nvchan->pb_tail || nvchan->pb_tail->remaining < (size + 1)) + nouveau_pushbuf_flush(grobj->channel); + + if (grobj->bound == NOUVEAU_GROBJ_UNBOUND) + nouveau_dma_subc_bind(grobj); + nvchan->subchannel[grobj->subc].seq = nvchan->subc_sequence++; + + pushbuf = nvchan->pb_tail->cur; + nvchan->pb_tail->cur += (size + 1); + nvchan->pb_tail->remaining -= (size + 1); + + (*pushbuf++) = ((grobj->subc << 13) | (size << 18) | mthd); return pushbuf; } -static void -nouveau_pipe_dma_kickoff(struct nouveau_channel *userchan) +void +nouveau_pipe_dma_kickoff(struct nouveau_channel *chan) { - FIRE_RING_CH(userchan); + nouveau_pushbuf_flush(chan); } static int diff --git a/src/mesa/pipe/nouveau/nouveau_resource.h b/src/mesa/pipe/nouveau/nouveau_resource.h new file mode 100644 index 0000000000..1af7961d30 --- /dev/null +++ b/src/mesa/pipe/nouveau/nouveau_resource.h @@ -0,0 +1,37 @@ +/* + * Copyright 2007 Nouveau Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF + * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __NOUVEAU_RESOURCE_H__ +#define __NOUVEAU_RESOURCE_H__ + +struct nouveau_resource { + struct nouveau_resource *prev; + struct nouveau_resource *next; + + int in_use; + void *priv; + + unsigned int start; + unsigned int size; +}; + +#endif diff --git a/src/mesa/pipe/nouveau/nouveau_winsys.h b/src/mesa/pipe/nouveau/nouveau_winsys.h index a274e23af5..ce1744c2ee 100644 --- a/src/mesa/pipe/nouveau/nouveau_winsys.h +++ b/src/mesa/pipe/nouveau/nouveau_winsys.h @@ -10,17 +10,7 @@ #include "pipe/nouveau/nouveau_class.h" #include "pipe/nouveau/nouveau_grobj.h" #include "pipe/nouveau/nouveau_notifier.h" - -struct nouveau_resource { - struct nouveau_resource *prev; - struct nouveau_resource *next; - - boolean in_use; - void *priv; - - uint start; - uint size; -}; +#include "pipe/nouveau/nouveau_resource.h" struct nouveau_winsys { struct nouveau_context *nv; |