summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nouveau
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nouveau')
-rw-r--r--src/gallium/drivers/nouveau/Makefile8
-rw-r--r--src/gallium/drivers/nouveau/nouveau_push.h39
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.c243
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.h25
-rw-r--r--src/gallium/drivers/nouveau/nouveau_stateobj.h44
-rw-r--r--src/gallium/drivers/nouveau/nouveau_winsys.h51
6 files changed, 330 insertions, 80 deletions
diff --git a/src/gallium/drivers/nouveau/Makefile b/src/gallium/drivers/nouveau/Makefile
new file mode 100644
index 0000000000..dbe8a6e7bf
--- /dev/null
+++ b/src/gallium/drivers/nouveau/Makefile
@@ -0,0 +1,8 @@
+TOP = ../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nouveau
+
+C_SOURCES = nouveau_screen.c
+
+include ../../Makefile.template
diff --git a/src/gallium/drivers/nouveau/nouveau_push.h b/src/gallium/drivers/nouveau/nouveau_push.h
index 54ef1c1291..9c235080a5 100644
--- a/src/gallium/drivers/nouveau/nouveau_push.h
+++ b/src/gallium/drivers/nouveau/nouveau_push.h
@@ -9,13 +9,13 @@
#define OUT_RING(data) do { \
NOUVEAU_PUSH_CONTEXT(pc); \
- (*pc->nvws->channel->pushbuf->cur++) = (data); \
+ (*pc->base.channel->pushbuf->cur++) = (data); \
} while(0)
#define OUT_RINGp(src,size) do { \
NOUVEAU_PUSH_CONTEXT(pc); \
- memcpy(pc->nvws->channel->pushbuf->cur, (src), (size) * 4); \
- pc->nvws->channel->pushbuf->cur += (size); \
+ memcpy(pc->base.channel->pushbuf->cur, (src), (size) * 4); \
+ pc->base.channel->pushbuf->cur += (size); \
} while(0)
#define OUT_RINGf(data) do { \
@@ -26,25 +26,35 @@
#define BEGIN_RING(obj,mthd,size) do { \
NOUVEAU_PUSH_CONTEXT(pc); \
- if (pc->nvws->channel->pushbuf->remaining < ((size) + 1)) \
- pc->nvws->push_flush(pc->nvws, ((size) + 1), NULL); \
+ struct nouveau_channel *chan = pc->base.channel; \
+ if (chan->pushbuf->remaining < ((size) + 1)) \
+ nouveau_pushbuf_flush(chan, ((size) + 1)); \
OUT_RING((pc->obj->subc << 13) | ((size) << 18) | (mthd)); \
- pc->nvws->channel->pushbuf->remaining -= ((size) + 1); \
+ chan->pushbuf->remaining -= ((size) + 1); \
} while(0)
#define BEGIN_RING_NI(obj,mthd,size) do { \
BEGIN_RING(obj, (mthd) | 0x40000000, (size)); \
} while(0)
+static inline void
+DO_FIRE_RING(struct nouveau_channel *chan, struct pipe_fence_handle **fence)
+{
+ nouveau_pushbuf_flush(chan, 0);
+ if (fence)
+ *fence = NULL;
+}
+
#define FIRE_RING(fence) do { \
NOUVEAU_PUSH_CONTEXT(pc); \
- pc->nvws->push_flush(pc->nvws, 0, fence); \
+ DO_FIRE_RING(pc->base.channel, fence); \
} while(0)
#define OUT_RELOC(bo,data,flags,vor,tor) do { \
NOUVEAU_PUSH_CONTEXT(pc); \
- pc->nvws->push_reloc(pc->nvws, pc->nvws->channel->pushbuf->cur++, \
- (bo), (data), (flags), (vor), (tor)); \
+ struct nouveau_channel *chan = pc->base.channel; \
+ nouveau_pushbuf_emit_reloc(chan, chan->pushbuf->cur++, nouveau_bo(bo), \
+ (data), 0, (flags), (vor), (tor)); \
} while(0)
/* Raw data + flags depending on FB/TT buffer */
@@ -55,8 +65,8 @@
/* FB/TT object handle */
#define OUT_RELOCo(bo,flags) do { \
OUT_RELOC((bo), 0, (flags) | NOUVEAU_BO_OR, \
- pc->nvws->channel->vram->handle, \
- pc->nvws->channel->gart->handle); \
+ pc->base.channel->vram->handle, \
+ pc->base.channel->gart->handle); \
} while(0)
/* Low 32-bits of offset */
@@ -72,11 +82,12 @@
/* A reloc which'll recombine into a NV_DMA_METHOD packet header */
#define OUT_RELOCm(bo, flags, obj, mthd, size) do { \
NOUVEAU_PUSH_CONTEXT(pc); \
- if (pc->nvws->channel->pushbuf->remaining < ((size) + 1)) \
- pc->nvws->push_flush(pc->nvws->channel, ((size) + 1), NULL); \
+ struct nouveau_channel *chan = pc->base.channel; \
+ if (chan->pushbuf->remaining < ((size) + 1)) \
+ nouveau_pushbuf_flush(chan, ((size) + 1)); \
OUT_RELOCd((bo), (pc->obj->subc << 13) | ((size) << 18) | (mthd), \
(flags), 0, 0); \
- pc->nvws->channel->pushbuf->remaining -= ((size) + 1); \
+ chan->pushbuf->remaining -= ((size) + 1); \
} while(0)
#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
new file mode 100644
index 0000000000..e4cf91c005
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -0,0 +1,243 @@
+#include <pipe/p_defines.h>
+#include <pipe/p_screen.h>
+#include <pipe/p_state.h>
+
+#include <util/u_memory.h>
+
+#include <errno.h>
+
+#include "nouveau/nouveau_bo.h"
+#include "nouveau_winsys.h"
+#include "nouveau_screen.h"
+
+static const char *
+nouveau_screen_get_name(struct pipe_screen *pscreen)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ static char buffer[128];
+
+ snprintf(buffer, sizeof(buffer), "NV%02X", dev->chipset);
+ return buffer;
+}
+
+static const char *
+nouveau_screen_get_vendor(struct pipe_screen *pscreen)
+{
+ return "nouveau";
+}
+
+static struct pipe_buffer *
+nouveau_screen_bo_skel(struct pipe_screen *pscreen, struct nouveau_bo *bo,
+ unsigned alignment, unsigned usage, unsigned size)
+{
+ struct pipe_buffer *pb;
+
+ pb = CALLOC(1, sizeof(struct pipe_buffer)+sizeof(struct nouveau_bo *));
+ if (!pb) {
+ nouveau_bo_ref(NULL, &bo);
+ return NULL;
+ }
+
+ pipe_reference_init(&pb->reference, 1);
+ pb->screen = pscreen;
+ pb->alignment = alignment;
+ pb->usage = usage;
+ pb->size = size;
+ *(struct nouveau_bo **)(pb + 1) = bo;
+ return pb;
+}
+
+static struct pipe_buffer *
+nouveau_screen_bo_new(struct pipe_screen *pscreen, unsigned alignment,
+ unsigned usage, unsigned size)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct nouveau_bo *bo = NULL;
+ uint32_t flags = NOUVEAU_BO_MAP;
+ int ret;
+
+ if (usage & NOUVEAU_BUFFER_USAGE_TRANSFER)
+ flags |= NOUVEAU_BO_GART;
+ else
+ if (usage & PIPE_BUFFER_USAGE_VERTEX) {
+ if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF))
+ flags |= NOUVEAU_BO_GART;
+ } else
+ if (usage & PIPE_BUFFER_USAGE_INDEX) {
+ if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF))
+ flags |= NOUVEAU_BO_GART;
+ }
+
+ if (usage & PIPE_BUFFER_USAGE_PIXEL) {
+ if (usage & NOUVEAU_BUFFER_USAGE_TEXTURE)
+ flags |= NOUVEAU_BO_GART;
+ if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE))
+ flags |= NOUVEAU_BO_VRAM;
+
+ if (dev->chipset == 0x50 || dev->chipset >= 0x80) {
+ flags |= NOUVEAU_BO_TILED;
+ if (usage & NOUVEAU_BUFFER_USAGE_ZETA)
+ flags |= NOUVEAU_BO_ZTILE;
+ }
+ }
+
+ ret = nouveau_bo_new(dev, flags, alignment, size, &bo);
+ if (ret)
+ return NULL;
+
+ return nouveau_screen_bo_skel(pscreen, bo, alignment, usage, size);
+}
+
+static struct pipe_buffer *
+nouveau_screen_bo_user(struct pipe_screen *pscreen, void *ptr, unsigned bytes)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct nouveau_bo *bo = NULL;
+ int ret;
+
+ ret = nouveau_bo_user(dev, ptr, bytes, &bo);
+ if (ret)
+ return NULL;
+
+ return nouveau_screen_bo_skel(pscreen, bo, 0, 0, bytes);
+}
+
+static inline uint32_t
+nouveau_screen_map_flags(unsigned pipe)
+{
+ uint32_t flags = 0;
+
+ if (pipe & PIPE_BUFFER_USAGE_CPU_READ)
+ flags |= NOUVEAU_BO_RD;
+ if (pipe & PIPE_BUFFER_USAGE_CPU_WRITE)
+ flags |= NOUVEAU_BO_WR;
+ if (pipe & PIPE_BUFFER_USAGE_DISCARD)
+ flags |= NOUVEAU_BO_INVAL;
+ if (pipe & PIPE_BUFFER_USAGE_DONTBLOCK)
+ flags |= NOUVEAU_BO_NOWAIT;
+ else
+ if (pipe & 0 /*PIPE_BUFFER_USAGE_UNSYNCHRONIZED*/)
+ flags |= NOUVEAU_BO_NOSYNC;
+
+ return flags;
+}
+
+static void *
+nouveau_screen_bo_map(struct pipe_screen *pscreen, struct pipe_buffer *pb,
+ unsigned usage)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+ int ret;
+
+ ret = nouveau_bo_map(bo, nouveau_screen_map_flags(usage));
+ if (ret) {
+ debug_printf("map failed: %d\n", ret);
+ return NULL;
+ }
+
+ return bo->map;
+}
+
+static void *
+nouveau_screen_bo_map_range(struct pipe_screen *pscreen, struct pipe_buffer *pb,
+ unsigned offset, unsigned length, unsigned usage)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+ uint32_t flags = nouveau_screen_map_flags(usage);
+ int ret;
+
+ ret = nouveau_bo_map_range(bo, offset, length, flags);
+ if (ret) {
+ if (!(flags & NOUVEAU_BO_NOWAIT) || ret != -EBUSY)
+ debug_printf("map_range failed: %d\n", ret);
+ return NULL;
+ }
+
+ return (char *)bo->map - offset; /* why gallium? why? */
+}
+
+static void
+nouveau_screen_bo_map_flush(struct pipe_screen *pscreen, struct pipe_buffer *pb,
+ unsigned offset, unsigned length)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+
+ nouveau_bo_map_flush(bo, offset, length);
+}
+
+static void
+nouveau_screen_bo_unmap(struct pipe_screen *pscreen, struct pipe_buffer *pb)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+
+ nouveau_bo_unmap(bo);
+}
+
+static void
+nouveau_screen_bo_del(struct pipe_buffer *pb)
+{
+ struct nouveau_bo *bo = nouveau_bo(pb);
+
+ nouveau_bo_ref(NULL, &bo);
+ FREE(pb);
+}
+
+static void
+nouveau_screen_fence_ref(struct pipe_screen *pscreen,
+ struct pipe_fence_handle **ptr,
+ struct pipe_fence_handle *pfence)
+{
+ *ptr = pfence;
+}
+
+static int
+nouveau_screen_fence_signalled(struct pipe_screen *screen,
+ struct pipe_fence_handle *pfence,
+ unsigned flags)
+{
+ return 0;
+}
+
+static int
+nouveau_screen_fence_finish(struct pipe_screen *screen,
+ struct pipe_fence_handle *pfence,
+ unsigned flags)
+{
+ return 0;
+}
+
+int
+nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
+{
+ struct pipe_screen *pscreen = &screen->base;
+ int ret;
+
+ ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202,
+ &screen->channel);
+ if (ret)
+ return ret;
+ screen->device = dev;
+
+ pscreen->get_name = nouveau_screen_get_name;
+ pscreen->get_vendor = nouveau_screen_get_vendor;
+
+ pscreen->buffer_create = nouveau_screen_bo_new;
+ pscreen->user_buffer_create = nouveau_screen_bo_user;
+ pscreen->buffer_map = nouveau_screen_bo_map;
+ pscreen->buffer_map_range = nouveau_screen_bo_map_range;
+ pscreen->buffer_flush_mapped_range = nouveau_screen_bo_map_flush;
+ pscreen->buffer_unmap = nouveau_screen_bo_unmap;
+ pscreen->buffer_destroy = nouveau_screen_bo_del;
+
+ pscreen->fence_reference = nouveau_screen_fence_ref;
+ pscreen->fence_signalled = nouveau_screen_fence_signalled;
+ pscreen->fence_finish = nouveau_screen_fence_finish;
+
+ return 0;
+}
+
+void
+nouveau_screen_fini(struct nouveau_screen *screen)
+{
+}
+
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h
new file mode 100644
index 0000000000..9968b07896
--- /dev/null
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -0,0 +1,25 @@
+#ifndef __NOUVEAU_SCREEN_H__
+#define __NOUVEAU_SCREEN_H__
+
+struct nouveau_screen {
+ struct pipe_screen base;
+ struct nouveau_device *device;
+ struct nouveau_channel *channel;
+};
+
+static inline struct nouveau_screen *
+nouveau_screen(struct pipe_screen *pscreen)
+{
+ return (struct nouveau_screen *)pscreen;
+}
+
+static inline struct nouveau_bo *
+nouveau_bo(struct pipe_buffer *pb)
+{
+ return pb ? *(struct nouveau_bo **)(pb + 1) : NULL;
+}
+
+int nouveau_screen_init(struct nouveau_screen *, struct nouveau_device *);
+void nouveau_screen_fini(struct nouveau_screen *);
+
+#endif
diff --git a/src/gallium/drivers/nouveau/nouveau_stateobj.h b/src/gallium/drivers/nouveau/nouveau_stateobj.h
index a54820e851..b595405357 100644
--- a/src/gallium/drivers/nouveau/nouveau_stateobj.h
+++ b/src/gallium/drivers/nouveau/nouveau_stateobj.h
@@ -4,7 +4,7 @@
#include "util/u_debug.h"
struct nouveau_stateobj_reloc {
- struct pipe_buffer *bo;
+ struct nouveau_bo *bo;
unsigned offset;
unsigned packet;
@@ -51,7 +51,7 @@ so_ref(struct nouveau_stateobj *ref, struct nouveau_stateobj **pso)
if (pipe_reference((struct pipe_reference**)pso, &ref->reference)) {
free(so->push);
for (i = 0; i < so->cur_reloc; i++)
- pipe_buffer_reference(&so->reloc[i].bo, NULL);
+ nouveau_bo_ref(NULL, &so->reloc[i].bo);
free(so->reloc);
free(so);
}
@@ -81,13 +81,13 @@ so_method(struct nouveau_stateobj *so, struct nouveau_grobj *gr,
}
static INLINE void
-so_reloc(struct nouveau_stateobj *so, struct pipe_buffer *bo,
+so_reloc(struct nouveau_stateobj *so, struct nouveau_bo *bo,
unsigned data, unsigned flags, unsigned vor, unsigned tor)
{
struct nouveau_stateobj_reloc *r = &so->reloc[so->cur_reloc++];
r->bo = NULL;
- pipe_buffer_reference(&r->bo, bo);
+ nouveau_bo_ref(bo, &r->bo);
r->offset = so->cur - so->push;
r->packet = so->cur_packet;
r->data = data;
@@ -107,50 +107,52 @@ so_dump(struct nouveau_stateobj *so)
}
static INLINE void
-so_emit(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
+so_emit(struct nouveau_channel *chan, struct nouveau_stateobj *so)
{
- struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
+ struct nouveau_pushbuf *pb = chan->pushbuf;
unsigned nr, i;
nr = so->cur - so->push;
if (pb->remaining < nr)
- nvws->push_flush(nvws, nr, NULL);
+ nouveau_pushbuf_flush(chan, nr);
pb->remaining -= nr;
memcpy(pb->cur, so->push, nr * 4);
for (i = 0; i < so->cur_reloc; i++) {
struct nouveau_stateobj_reloc *r = &so->reloc[i];
- nvws->push_reloc(nvws, pb->cur + r->offset, r->bo,
- r->data, r->flags, r->vor, r->tor);
+ nouveau_pushbuf_emit_reloc(chan, pb->cur + r->offset,
+ r->bo, r->data, 0, r->flags,
+ r->vor, r->tor);
}
pb->cur += nr;
}
static INLINE void
-so_emit_reloc_markers(struct nouveau_winsys *nvws, struct nouveau_stateobj *so)
+so_emit_reloc_markers(struct nouveau_channel *chan, struct nouveau_stateobj *so)
{
- struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
+ struct nouveau_pushbuf *pb = chan->pushbuf;
unsigned i;
if (!so)
return;
i = so->cur_reloc << 1;
- if (nvws->channel->pushbuf->remaining < i)
- nvws->push_flush(nvws, i, NULL);
- nvws->channel->pushbuf->remaining -= i;
+ if (pb->remaining < i)
+ nouveau_pushbuf_flush(chan, i);
+ pb->remaining -= i;
for (i = 0; i < so->cur_reloc; i++) {
struct nouveau_stateobj_reloc *r = &so->reloc[i];
- nvws->push_reloc(nvws, pb->cur++, r->bo, r->packet,
- (r->flags & (NOUVEAU_BO_VRAM |
- NOUVEAU_BO_GART |
- NOUVEAU_BO_RDWR)) |
- NOUVEAU_BO_DUMMY, 0, 0);
- nvws->push_reloc(nvws, pb->cur++, r->bo, r->data,
- r->flags | NOUVEAU_BO_DUMMY, r->vor, r->tor);
+ nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->packet, 0,
+ (r->flags & (NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_GART |
+ NOUVEAU_BO_RDWR)) |
+ NOUVEAU_BO_DUMMY, 0, 0);
+ nouveau_pushbuf_emit_reloc(chan, pb->cur++, r->bo, r->data, 0,
+ r->flags | NOUVEAU_BO_DUMMY,
+ r->vor, r->tor);
}
}
diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h
index ff7dd1c51c..42c77e5e77 100644
--- a/src/gallium/drivers/nouveau/nouveau_winsys.h
+++ b/src/gallium/drivers/nouveau/nouveau_winsys.h
@@ -23,77 +23,38 @@
#define NOUVEAU_BUFFER_USAGE_ZETA (1 << 17)
#define NOUVEAU_BUFFER_USAGE_TRANSFER (1 << 18)
-struct nouveau_winsys {
- struct pipe_winsys *ws;
-
- struct nouveau_channel *channel;
-
- int (*res_init)(struct nouveau_resource **heap, unsigned start,
- unsigned size);
- int (*res_alloc)(struct nouveau_resource *heap, int size, void *priv,
- struct nouveau_resource **);
- void (*res_free)(struct nouveau_resource **);
-
- int (*push_reloc)(struct nouveau_winsys *, void *ptr,
- struct pipe_buffer *, uint32_t data,
- uint32_t flags, uint32_t vor, uint32_t tor);
- int (*push_flush)(struct nouveau_winsys *, unsigned size,
- struct pipe_fence_handle **fence);
-
- int (*grobj_alloc)(struct nouveau_winsys *, int grclass,
- struct nouveau_grobj **);
- void (*grobj_free)(struct nouveau_grobj **);
-
- int (*notifier_alloc)(struct nouveau_winsys *, int count,
- struct nouveau_notifier **);
- void (*notifier_free)(struct nouveau_notifier **);
- void (*notifier_reset)(struct nouveau_notifier *, int id);
- uint32_t (*notifier_status)(struct nouveau_notifier *, int id);
- uint32_t (*notifier_retval)(struct nouveau_notifier *, int id);
- int (*notifier_wait)(struct nouveau_notifier *, int id,
- int status, double timeout);
-
- int (*surface_copy)(struct nouveau_winsys *, struct pipe_surface *,
- unsigned, unsigned, struct pipe_surface *,
- unsigned, unsigned, unsigned, unsigned);
- int (*surface_fill)(struct nouveau_winsys *, struct pipe_surface *,
- unsigned, unsigned, unsigned, unsigned, unsigned);
-
- struct nouveau_bo *(*get_bo)(struct pipe_buffer *);
-};
-
extern struct pipe_screen *
-nv04_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv04_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
extern struct pipe_context *
nv04_create(struct pipe_screen *, unsigned pctx_id);
extern struct pipe_screen *
-nv10_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv10_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
extern struct pipe_context *
nv10_create(struct pipe_screen *, unsigned pctx_id);
extern struct pipe_screen *
-nv20_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv20_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
extern struct pipe_context *
nv20_create(struct pipe_screen *, unsigned pctx_id);
extern struct pipe_screen *
-nv30_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv30_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
extern struct pipe_context *
nv30_create(struct pipe_screen *, unsigned pctx_id);
extern struct pipe_screen *
-nv40_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv40_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
extern struct pipe_context *
nv40_create(struct pipe_screen *, unsigned pctx_id);
extern struct pipe_screen *
-nv50_screen_create(struct pipe_winsys *ws, struct nouveau_winsys *);
+nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *);
extern struct pipe_context *
nv50_create(struct pipe_screen *, unsigned pctx_id);