summaryrefslogtreecommitdiffstats
path: root/src/gallium/winsys/nouveau
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/winsys/nouveau')
-rw-r--r--src/gallium/winsys/nouveau/drm/Makefile11
-rw-r--r--src/gallium/winsys/nouveau/drm/nouveau_dri.h28
-rw-r--r--src/gallium/winsys/nouveau/drm/nouveau_drm_api.c160
-rw-r--r--src/gallium/winsys/nouveau/drm/nouveau_drm_api.h31
4 files changed, 230 insertions, 0 deletions
diff --git a/src/gallium/winsys/nouveau/drm/Makefile b/src/gallium/winsys/nouveau/drm/Makefile
new file mode 100644
index 00000000000..71029858f75
--- /dev/null
+++ b/src/gallium/winsys/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/nouveau/drm/nouveau_dri.h b/src/gallium/winsys/nouveau/drm/nouveau_dri.h
new file mode 100644
index 00000000000..1207c2d609c
--- /dev/null
+++ b/src/gallium/winsys/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/nouveau/drm/nouveau_drm_api.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_api.c
new file mode 100644
index 00000000000..37f33875a5b
--- /dev/null
+++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_api.c
@@ -0,0 +1,160 @@
+#include "pipe/p_context.h"
+#include "pipe/p_state.h"
+#include "util/u_format.h"
+#include "util/u_memory.h"
+#include "util/u_inlines.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_resource *pt = NULL;
+ struct pipe_resource tmpl;
+ struct winsys_handle whandle;
+ unsigned bind = (PIPE_BIND_SCANOUT |
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_BLIT_DESTINATION |
+ PIPE_BIND_BLIT_SOURCE);
+
+ memset(&tmpl, 0, sizeof(tmpl));
+ tmpl.bind = bind;
+ tmpl.target = PIPE_TEXTURE_2D;
+ tmpl.last_level = 0;
+ tmpl.depth0 = 1;
+ tmpl.format = format;
+ tmpl.width0 = width;
+ tmpl.height0 = height;
+
+ memset(&whandle, 0, sizeof(whandle));
+ whandle.stride = pitch;
+ whandle.handle = handle;
+
+ pt = pscreen->resource_from_handle(pscreen, &tmpl, &whandle);
+ if (!pt)
+ return NULL;
+
+ ps = pscreen->get_tex_surface(pscreen, pt, 0, 0, 0, bind);
+
+ /* we don't need the texture from this point on */
+ pipe_resource_reference(&pt, NULL);
+ return ps;
+}
+
+static struct pipe_surface *
+nouveau_dri1_front_surface(struct pipe_screen *screen)
+{
+ return nouveau_winsys_screen(screen)->front;
+}
+
+static struct dri1_api nouveau_dri1_api = {
+ nouveau_dri1_front_surface,
+};
+
+static void
+nouveau_drm_destroy_winsys(struct pipe_winsys *s)
+{
+ struct nouveau_winsys *nv_winsys = nouveau_winsys(s);
+ struct nouveau_screen *nv_screen= nouveau_screen(nv_winsys->pscreen);
+ nouveau_device_close(&nv_screen->device);
+ FREE(nv_winsys);
+}
+
+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 0x30:
+ case 0x40:
+ case 0x60:
+ init = nvfx_screen_create;
+ break;
+ case 0x50:
+ 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;
+ ws->destroy = nouveau_drm_destroy_winsys;
+
+ nvws->pscreen = init(ws, dev);
+ if (!nvws->pscreen) {
+ ws->destroy(ws);
+ return NULL;
+ }
+
+ if (arg && arg->mode == DRM_CREATE_DRI1) {
+ struct nouveau_dri *nvdri = dri1->ddx_info;
+ enum pipe_format format;
+
+ if (nvdri->bpp == 16)
+ format = PIPE_FORMAT_B5G6R5_UNORM;
+ else
+ format = PIPE_FORMAT_B8G8R8A8_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 drm_api nouveau_drm_api_hooks = {
+ .name = "nouveau",
+ .driver_name = "nouveau",
+ .create_screen = nouveau_drm_create_screen,
+ .destroy = NULL,
+};
+
+struct drm_api *
+drm_api_create() {
+ return &nouveau_drm_api_hooks;
+}
+
diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_api.h b/src/gallium/winsys/nouveau/drm/nouveau_drm_api.h
new file mode 100644
index 00000000000..a91aad7df8e
--- /dev/null
+++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_api.h
@@ -0,0 +1,31 @@
+#ifndef __NOUVEAU_DRM_API_H__
+#define __NOUVEAU_DRM_API_H__
+
+#include "state_tracker/drm_api.h"
+#include "state_tracker/dri1_api.h"
+
+#include "util/u_simple_screen.h"
+
+#include "nouveau_dri.h"
+
+struct nouveau_winsys {
+ struct pipe_winsys base;
+
+ struct pipe_screen *pscreen;
+
+ 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