summaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2007-11-23 18:54:11 +1100
committerBen Skeggs <skeggsb@gmail.com>2007-11-23 18:54:19 +1100
commit558f3abb49475ba0aad585e7fb0c07121aecde6f (patch)
tree5553c9e561ddf359858a4cddc8228a387746081c /src/mesa/drivers
parentdd1500b8b436dc4a009455489ade7dcf65f03d07 (diff)
nv40: support for keeping multiple vtxprogs on the hw at the same time.
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c
index a2e85a0aa7..bdc89b9531 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c
@@ -4,6 +4,89 @@
#include "pipe/nouveau/nouveau_winsys.h"
static int
+nouveau_resource_init(struct nouveau_resource **heap, int size)
+{
+ struct nouveau_resource *r;
+
+ r = calloc(1, sizeof(struct nouveau_resource));
+ if (!r)
+ return 1;
+
+ r->start = 0;
+ r->size = size;
+ *heap = r;
+ return 0;
+}
+
+static int
+nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv,
+ struct nouveau_resource **res)
+{
+ struct nouveau_resource *r;
+
+ if (!heap || !size || !res || *res)
+ return 1;
+
+ while (heap) {
+ if (!heap->in_use && heap->size >= size) {
+ r = calloc(1, sizeof(struct nouveau_resource));
+ if (!r)
+ return 1;
+
+ r->start = (heap->start + heap->size) - size;
+ r->size = size;
+ r->in_use = TRUE;
+ r->priv = priv;
+
+ heap->size -= size;
+
+ r->next = heap->next;
+ if (heap->next)
+ heap->next->prev = r;
+ r->prev = heap;
+ heap->next = r;
+
+ *res = r;
+ return 0;
+ }
+
+ heap = heap->next;
+ }
+
+ return 1;
+}
+
+static void
+nouveau_resource_free(struct nouveau_resource **res)
+{
+ struct nouveau_resource *r;
+
+ if (!res || !*res)
+ return;
+ r = *res;
+
+ if (r->prev && !r->prev->in_use) {
+ r->prev->next = r->next;
+ if (r->next)
+ r->next->prev = r->prev;
+ r->prev->size += r->size;
+ free(r);
+ } else
+ if (r->next && !r->next->in_use) {
+ r->next->prev = r->prev;
+ if (r->prev)
+ r->prev->next = r->next;
+ r->next->size += r->size;
+ r->next->start = r->start;
+ free(r);
+ } else {
+ r->in_use = FALSE;
+ }
+
+ *res = NULL;
+}
+
+static int
nouveau_pipe_notifier_alloc(struct nouveau_winsys *nvws, int count,
struct nouveau_notifier **notify)
{
@@ -67,6 +150,10 @@ nouveau_pipe_create(struct nouveau_context *nv)
nvws->nv = nv;
nvws->channel = nv->channel;
+ nvws->res_init = nouveau_resource_init;
+ nvws->res_alloc = nouveau_resource_alloc;
+ nvws->res_free = nouveau_resource_free;
+
nvws->begin_ring = nouveau_pipe_dma_beginp;
nvws->out_reloc = nouveau_bo_emit_reloc;
nvws->fire_ring = nouveau_pipe_dma_kickoff;