diff options
author | Chia-I Wu <olvaffe@gmail.com> | 2009-09-15 14:16:22 +0800 |
---|---|---|
committer | Chia-I Wu <olvaffe@gmail.com> | 2009-09-15 14:16:22 +0800 |
commit | e2ba90a9cc762cf00a168f0a59d31e7dc52fc42e (patch) | |
tree | fe3206d7602ad935296884742980f3c4d30bd867 /src/gallium/winsys/drm/nouveau | |
parent | 11a4292d4eb515813b82b8d688a318adef66b3e6 (diff) | |
parent | b4b8800315637d9218a81c76f09df7d601710d29 (diff) |
Merge commit 'eee/mesa-es' into android
Diffstat (limited to 'src/gallium/winsys/drm/nouveau')
-rw-r--r-- | src/gallium/winsys/drm/nouveau/Makefile | 12 | ||||
-rw-r--r-- | src/gallium/winsys/drm/nouveau/dri/Makefile | 27 | ||||
-rw-r--r-- | src/gallium/winsys/drm/nouveau/drm/Makefile | 11 | ||||
-rw-r--r-- | src/gallium/winsys/drm/nouveau/drm/nouveau_dri.h | 28 | ||||
-rw-r--r-- | src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c | 263 | ||||
-rw-r--r-- | src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h | 34 |
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 |