summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/drm/nouveau
diff options
context:
space:
mode:
authorChia-I Wu <olvaffe@gmail.com>2009-09-15 14:16:22 +0800
committerChia-I Wu <olvaffe@gmail.com>2009-09-15 14:16:22 +0800
commite2ba90a9cc762cf00a168f0a59d31e7dc52fc42e (patch)
treefe3206d7602ad935296884742980f3c4d30bd867 /src/gallium/winsys/drm/nouveau
parent11a4292d4eb515813b82b8d688a318adef66b3e6 (diff)
parentb4b8800315637d9218a81c76f09df7d601710d29 (diff)
Merge commit 'eee/mesa-es' into android
Diffstat (limited to 'src/gallium/winsys/drm/nouveau')
-rw-r--r--src/gallium/winsys/drm/nouveau/Makefile12
-rw-r--r--src/gallium/winsys/drm/nouveau/dri/Makefile27
-rw-r--r--src/gallium/winsys/drm/nouveau/drm/Makefile11
-rw-r--r--src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h28
-rw-r--r--src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c263
-rw-r--r--src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h34
6 files changed, 375 insertions, 0 deletions
diff --git a/src/gallium/winsys/drm/nouveau/Makefile b/src/gallium/winsys/drm/nouveau/Makefile
new file mode 100644
index 0000000000..6c9cbef26d
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/Makefile
@@ -0,0 +1,12 @@
+# src/gallium/winsys/drm/nouveau/Makefile
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+SUBDIRS = drm $(GALLIUM_STATE_TRACKERS_DIRS)
+
+default install clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir && $(MAKE) $@) || exit 1; \
+ fi \
+ done
diff --git a/src/gallium/winsys/drm/nouveau/dri/Makefile b/src/gallium/winsys/drm/nouveau/dri/Makefile
new file mode 100644
index 0000000000..0937f68c34
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/dri/Makefile
@@ -0,0 +1,27 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nouveau_dri.so
+
+PIPE_DRIVERS = \
+ $(TOP)/src/gallium/state_trackers/dri/libdridrm.a \
+ $(TOP)/src/gallium/winsys/drm/nouveau/drm/libnouveaudrm.a \
+ $(TOP)/src/gallium/drivers/nv04/libnv04.a \
+ $(TOP)/src/gallium/drivers/nv10/libnv10.a \
+ $(TOP)/src/gallium/drivers/nv20/libnv20.a \
+ $(TOP)/src/gallium/drivers/nv30/libnv30.a \
+ $(TOP)/src/gallium/drivers/nv40/libnv40.a \
+ $(TOP)/src/gallium/drivers/nv50/libnv50.a \
+ $(TOP)/src/gallium/drivers/nouveau/libnouveau.a
+
+DRIVER_SOURCES =
+
+C_SOURCES = \
+ $(COMMON_GALLIUM_SOURCES) \
+ $(DRIVER_SOURCES)
+
+include ../../Makefile.template
+
+DRI_LIB_DEPS += $(shell pkg-config libdrm_nouveau --libs)
+
+symlinks:
diff --git a/src/gallium/winsys/drm/nouveau/drm/Makefile b/src/gallium/winsys/drm/nouveau/drm/Makefile
new file mode 100644
index 0000000000..54c3b26c75
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/drm/Makefile
@@ -0,0 +1,11 @@
+TOP = ../../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = nouveaudrm
+
+C_SOURCES = nouveau_drm_api.c
+
+LIBRARY_INCLUDES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-I)
+LIBRARY_DEFINES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-other)
+
+include ../../../../Makefile.template
diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h b/src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h
new file mode 100644
index 0000000000..1207c2d609
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h
@@ -0,0 +1,28 @@
+#ifndef _NOUVEAU_DRI_
+#define _NOUVEAU_DRI_
+
+#include "xf86drm.h"
+#include "drm.h"
+#include "nouveau_drm.h"
+
+struct nouveau_dri {
+ uint32_t device_id; /**< \brief PCI device ID */
+ uint32_t width; /**< \brief width in pixels of display */
+ uint32_t height; /**< \brief height in scanlines of display */
+ uint32_t depth; /**< \brief depth of display (8, 15, 16, 24) */
+ uint32_t bpp; /**< \brief bit depth of display (8, 16, 24, 32) */
+
+ uint32_t bus_type; /**< \brief ths bus type */
+ uint32_t bus_mode; /**< \brief bus mode (used for AGP, maybe also for PCI-E ?) */
+
+ uint32_t front_offset; /**< \brief front buffer offset */
+ uint32_t front_pitch; /**< \brief front buffer pitch */
+ uint32_t back_offset; /**< \brief private back buffer offset */
+ uint32_t back_pitch; /**< \brief private back buffer pitch */
+ uint32_t depth_offset; /**< \brief private depth buffer offset */
+ uint32_t depth_pitch; /**< \brief private depth buffer pitch */
+
+};
+
+#endif
+
diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
new file mode 100644
index 0000000000..091cbbcfed
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c
@@ -0,0 +1,263 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "util/u_memory.h"
+
+#include "nouveau_drm_api.h"
+
+#include "nouveau_drmif.h"
+#include "nouveau_channel.h"
+#include "nouveau_bo.h"
+
+#include "nouveau/nouveau_winsys.h"
+#include "nouveau/nouveau_screen.h"
+
+static struct pipe_surface *
+dri_surface_from_handle(struct drm_api *api, struct pipe_screen *pscreen,
+ unsigned handle, enum pipe_format format,
+ unsigned width, unsigned height, unsigned pitch)
+{
+ struct pipe_surface *ps = NULL;
+ struct pipe_texture *pt = NULL;
+ struct pipe_texture tmpl;
+
+ memset(&tmpl, 0, sizeof(tmpl));
+ tmpl.tex_usage = PIPE_TEXTURE_USAGE_PRIMARY |
+ NOUVEAU_TEXTURE_USAGE_LINEAR;
+ tmpl.target = PIPE_TEXTURE_2D;
+ tmpl.last_level = 0;
+ tmpl.depth[0] = 1;
+ tmpl.format = format;
+ tmpl.width[0] = width;
+ tmpl.height[0] = height;
+ pf_get_block(tmpl.format, &tmpl.block);
+
+ pt = api->texture_from_shared_handle(api, pscreen, &tmpl,
+ "front buffer", pitch, handle);
+ if (!pt)
+ return NULL;
+
+ ps = pscreen->get_tex_surface(pscreen, pt, 0, 0, 0,
+ PIPE_BUFFER_USAGE_GPU_READ |
+ PIPE_BUFFER_USAGE_GPU_WRITE);
+
+ /* we don't need the texture from this point on */
+ pipe_texture_reference(&pt, NULL);
+ return ps;
+}
+
+static struct pipe_surface *
+nouveau_dri1_front_surface(struct pipe_context *pipe)
+{
+ return nouveau_winsys_screen(pipe->screen)->front;
+}
+
+static struct dri1_api nouveau_dri1_api = {
+ nouveau_dri1_front_surface,
+};
+
+static struct pipe_screen *
+nouveau_drm_create_screen(struct drm_api *api, int fd,
+ struct drm_create_screen_arg *arg)
+{
+ struct dri1_create_screen_arg *dri1 = (void *)arg;
+ struct nouveau_winsys *nvws;
+ struct pipe_winsys *ws;
+ struct nouveau_device *dev = NULL;
+ struct pipe_screen *(*init)(struct pipe_winsys *,
+ struct nouveau_device *);
+ int ret;
+
+ ret = nouveau_device_open_existing(&dev, 0, fd, 0);
+ if (ret)
+ return NULL;
+
+ switch (dev->chipset & 0xf0) {
+ case 0x00:
+ init = nv04_screen_create;
+ break;
+ case 0x10:
+ init = nv10_screen_create;
+ break;
+ case 0x20:
+ init = nv20_screen_create;
+ break;
+ case 0x30:
+ init = nv30_screen_create;
+ break;
+ case 0x40:
+ case 0x60:
+ init = nv40_screen_create;
+ break;
+ case 0x80:
+ case 0x90:
+ case 0xa0:
+ init = nv50_screen_create;
+ break;
+ default:
+ debug_printf("%s: unknown chipset nv%02x\n", __func__,
+ dev->chipset);
+ return NULL;
+ }
+
+ nvws = CALLOC_STRUCT(nouveau_winsys);
+ if (!nvws) {
+ nouveau_device_close(&dev);
+ return NULL;
+ }
+ ws = &nvws->base;
+
+ nvws->pscreen = init(ws, dev);
+ if (!nvws->pscreen) {
+ ws->destroy(ws);
+ return NULL;
+ }
+
+ if (arg->mode == DRM_CREATE_DRI1) {
+ struct nouveau_dri *nvdri = dri1->ddx_info;
+ enum pipe_format format;
+
+ if (nvdri->bpp == 16)
+ format = PIPE_FORMAT_R5G6B5_UNORM;
+ else
+ format = PIPE_FORMAT_A8R8G8B8_UNORM;
+
+ nvws->front = dri_surface_from_handle(api, nvws->pscreen,
+ nvdri->front_offset,
+ format, nvdri->width,
+ nvdri->height,
+ nvdri->front_pitch *
+ (nvdri->bpp / 8));
+ if (!nvws->front) {
+ debug_printf("%s: error referencing front buffer\n",
+ __func__);
+ ws->destroy(ws);
+ return NULL;
+ }
+
+ dri1->api = &nouveau_dri1_api;
+ }
+
+ return nvws->pscreen;
+}
+
+static struct pipe_context *
+nouveau_drm_create_context(struct drm_api *api, struct pipe_screen *pscreen)
+{
+ struct nouveau_winsys *nvws = nouveau_winsys_screen(pscreen);
+ struct pipe_context *(*init)(struct pipe_screen *, unsigned);
+ unsigned chipset = nouveau_screen(pscreen)->device->chipset;
+ int i;
+
+ switch (chipset & 0xf0) {
+ case 0x00:
+ init = nv04_create;
+ break;
+ case 0x10:
+ init = nv10_create;
+ break;
+ case 0x20:
+ init = nv20_create;
+ break;
+ case 0x30:
+ init = nv30_create;
+ break;
+ case 0x40:
+ case 0x60:
+ init = nv40_create;
+ break;
+ case 0x80:
+ case 0x90:
+ case 0xa0:
+ init = nv50_create;
+ break;
+ default:
+ debug_printf("%s: unknown chipset nv%02x\n", __func__, chipset);
+ return NULL;
+ }
+
+ /* Find a free slot for a pipe context, allocate a new one if needed */
+ for (i = 0; i < nvws->nr_pctx; i++) {
+ if (nvws->pctx[i] == NULL)
+ break;
+ }
+
+ if (i == nvws->nr_pctx) {
+ nvws->nr_pctx++;
+ nvws->pctx = realloc(nvws->pctx,
+ sizeof(*nvws->pctx) * nvws->nr_pctx);
+ }
+
+ nvws->pctx[i] = init(pscreen, i);
+ return nvws->pctx[i];
+}
+
+static struct pipe_texture *
+nouveau_drm_pt_from_name(struct drm_api *api, struct pipe_screen *pscreen,
+ struct pipe_texture *templ, const char *name,
+ unsigned stride, unsigned handle)
+{
+ struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ struct pipe_buffer *pb;
+ int ret;
+
+ pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*));
+ if (!pb)
+ return NULL;
+
+ ret = nouveau_bo_handle_ref(dev, handle, (struct nouveau_bo**)(pb+1));
+ if (ret) {
+ debug_printf("%s: ref name 0x%08x failed with %d\n",
+ __func__, handle, ret);
+ FREE(pb);
+ return NULL;
+ }
+
+ pipe_reference_init(&pb->reference, 1);
+ pb->screen = pscreen;
+ pb->alignment = 0;
+ pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE |
+ PIPE_BUFFER_USAGE_CPU_READ_WRITE;
+ pb->size = nouveau_bo(pb)->size;
+ return pscreen->texture_blanket(pscreen, templ, &stride, pb);
+}
+
+static boolean
+nouveau_drm_name_from_pt(struct drm_api *api, struct pipe_screen *pscreen,
+ struct pipe_texture *pt, unsigned *stride,
+ unsigned *handle)
+{
+ struct nouveau_miptree *mt = nouveau_miptree(pt);
+
+ if (!mt || !mt->bo)
+ return false;
+
+ return nouveau_bo_handle_get(mt->bo, handle) == 0;
+}
+
+static boolean
+nouveau_drm_handle_from_pt(struct drm_api *api, struct pipe_screen *pscreen,
+ struct pipe_texture *pt, unsigned *stride,
+ unsigned *handle)
+{
+ struct nouveau_miptree *mt = nouveau_miptree(pt);
+
+ if (!mt || !mt->bo)
+ return false;
+
+ *handle = mt->bo->handle;
+ return true;
+}
+
+struct drm_api drm_api_hooks = {
+ .create_screen = nouveau_drm_create_screen,
+ .create_context = nouveau_drm_create_context,
+ .texture_from_shared_handle = nouveau_drm_pt_from_name,
+ .shared_handle_from_texture = nouveau_drm_name_from_pt,
+ .local_handle_from_texture = nouveau_drm_handle_from_pt,
+};
+
+struct drm_api *
+drm_api_create() {
+ return &drm_api_hooks;
+}
+
diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h
new file mode 100644
index 0000000000..e61e0e0957
--- /dev/null
+++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h
@@ -0,0 +1,34 @@
+#ifndef __NOUVEAU_DRM_API_H__
+#define __NOUVEAU_DRM_API_H__
+
+#include "state_tracker/drm_api.h"
+#include "state_tracker/dri1_api.h"
+
+#include "pipe/internal/p_winsys_screen.h"
+
+#include "nouveau_dri.h"
+
+struct nouveau_winsys {
+ struct pipe_winsys base;
+
+ struct pipe_screen *pscreen;
+
+ unsigned nr_pctx;
+ struct pipe_context **pctx;
+
+ struct pipe_surface *front;
+};
+
+static INLINE struct nouveau_winsys *
+nouveau_winsys(struct pipe_winsys *ws)
+{
+ return (struct nouveau_winsys *)ws;
+}
+
+static INLINE struct nouveau_winsys *
+nouveau_winsys_screen(struct pipe_screen *pscreen)
+{
+ return nouveau_winsys(pscreen->winsys);
+}
+
+#endif