From e00ae524e236afba1305150cacd634eaa1f5460b Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 18 Mar 2009 08:22:35 +1000 Subject: nouveau: rewrite winsys in terms of drm_api, support dri2 state tracker drm_api is a set of hooks used by the dri2 state tracker, this wraps our dri1 code around the same set of hooks. Currently the dri2 build will produce nouveau_dri2.so which you'll need to install as nouveau_dri.so if you wish to try it. The dri2 state tracker doesn't make it easy for a driver to support both paths in the same binary. --- src/gallium/drivers/nouveau/nouveau_winsys.h | 2 +- src/gallium/winsys/drm/nouveau/Makefile | 2 +- src/gallium/winsys/drm/nouveau/common/Makefile | 22 -- .../winsys/drm/nouveau/common/nouveau_context.c | 206 ------------- .../winsys/drm/nouveau/common/nouveau_context.h | 59 ---- .../winsys/drm/nouveau/common/nouveau_dri.h | 28 -- .../winsys/drm/nouveau/common/nouveau_local.h | 19 -- .../winsys/drm/nouveau/common/nouveau_lock.c | 72 ----- .../winsys/drm/nouveau/common/nouveau_screen.c | 31 -- .../winsys/drm/nouveau/common/nouveau_screen.h | 27 -- .../winsys/drm/nouveau/common/nouveau_winsys.c | 146 --------- .../drm/nouveau/common/nouveau_winsys_pipe.c | 251 ---------------- .../drm/nouveau/common/nouveau_winsys_pipe.h | 44 --- .../drm/nouveau/common/nouveau_winsys_softpipe.c | 101 ------- src/gallium/winsys/drm/nouveau/dri/Makefile | 8 +- .../winsys/drm/nouveau/dri/nouveau_context.c | 118 ++++++++ .../winsys/drm/nouveau/dri/nouveau_context.h | 53 ++++ .../winsys/drm/nouveau/dri/nouveau_context_dri.c | 124 -------- .../winsys/drm/nouveau/dri/nouveau_context_dri.h | 47 --- src/gallium/winsys/drm/nouveau/dri/nouveau_dri.h | 28 ++ src/gallium/winsys/drm/nouveau/dri/nouveau_lock.c | 73 +++++ .../winsys/drm/nouveau/dri/nouveau_screen.c | 329 +++++++++++++++++++++ .../winsys/drm/nouveau/dri/nouveau_screen.h | 16 + .../winsys/drm/nouveau/dri/nouveau_screen_dri.c | 259 ---------------- .../winsys/drm/nouveau/dri/nouveau_screen_dri.h | 13 - .../winsys/drm/nouveau/dri/nouveau_swapbuffers.c | 32 +- .../winsys/drm/nouveau/dri/nouveau_swapbuffers.h | 11 +- src/gallium/winsys/drm/nouveau/dri2/Makefile | 26 ++ src/gallium/winsys/drm/nouveau/drm/Makefile | 13 + .../winsys/drm/nouveau/drm/nouveau_drm_api.c | 194 ++++++++++++ .../winsys/drm/nouveau/drm/nouveau_drm_api.h | 5 + .../winsys/drm/nouveau/drm/nouveau_winsys.c | 94 ++++++ .../winsys/drm/nouveau/drm/nouveau_winsys_pipe.c | 204 +++++++++++++ .../winsys/drm/nouveau/drm/nouveau_winsys_pipe.h | 52 ++++ 34 files changed, 1234 insertions(+), 1475 deletions(-) delete mode 100644 src/gallium/winsys/drm/nouveau/common/Makefile delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_context.c delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_context.h delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_dri.h delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_local.h delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_lock.c delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_screen.c delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_screen.h delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.h delete mode 100644 src/gallium/winsys/drm/nouveau/common/nouveau_winsys_softpipe.c create mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_context.c create mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_context.h delete mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.c delete mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.h create mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_dri.h create mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_lock.c create mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_screen.c create mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_screen.h delete mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.c delete mode 100644 src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.h create mode 100644 src/gallium/winsys/drm/nouveau/dri2/Makefile create mode 100644 src/gallium/winsys/drm/nouveau/drm/Makefile create mode 100644 src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c create mode 100644 src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h create mode 100644 src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c create mode 100644 src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.c create mode 100644 src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.h (limited to 'src/gallium') diff --git a/src/gallium/drivers/nouveau/nouveau_winsys.h b/src/gallium/drivers/nouveau/nouveau_winsys.h index 4fcadbae3f9..ff7dd1c51c8 100644 --- a/src/gallium/drivers/nouveau/nouveau_winsys.h +++ b/src/gallium/drivers/nouveau/nouveau_winsys.h @@ -24,7 +24,7 @@ #define NOUVEAU_BUFFER_USAGE_TRANSFER (1 << 18) struct nouveau_winsys { - struct nouveau_context *nv; + struct pipe_winsys *ws; struct nouveau_channel *channel; diff --git a/src/gallium/winsys/drm/nouveau/Makefile b/src/gallium/winsys/drm/nouveau/Makefile index 652cf7146cb..f8c81358544 100644 --- a/src/gallium/winsys/drm/nouveau/Makefile +++ b/src/gallium/winsys/drm/nouveau/Makefile @@ -2,7 +2,7 @@ TOP = ../../../../.. include $(TOP)/configs/current -SUBDIRS = common dri +SUBDIRS = drm dri dri2 default install clean: @for dir in $(SUBDIRS) ; do \ diff --git a/src/gallium/winsys/drm/nouveau/common/Makefile b/src/gallium/winsys/drm/nouveau/common/Makefile deleted file mode 100644 index f675f7caf1e..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -TOP = ../../../../../.. -include $(TOP)/configs/current - -LIBNAME = nouveaudrm - -C_SOURCES = \ - nouveau_context.c \ - nouveau_lock.c \ - nouveau_screen.c \ - nouveau_winsys.c \ - nouveau_winsys_pipe.c \ - nouveau_winsys_softpipe.c - -LIBRARY_INCLUDES = $(shell pkg-config libdrm libdrm_nouveau --cflags-only-I) - -LIBRARY_DEFINES = $(shell pkg-config libdrm --cflags-only-other \ - && pkg-config libdrm --atleast-version=2.3.1 \ - && pkg-config libdrm_nouveau --exact-version=0.5 \ - && pkg-config libdrm_nouveau --cflags-only-other \ - && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP") - -include ../../../../Makefile.template diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_context.c b/src/gallium/winsys/drm/nouveau/common/nouveau_context.c deleted file mode 100644 index fbe57eacf2a..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_context.c +++ /dev/null @@ -1,206 +0,0 @@ -#include -#include -#include -#include -#include "nouveau_context.h" -#include "nouveau_dri.h" -#include "nouveau_local.h" -#include "nouveau_screen.h" -#include "nouveau_winsys_pipe.h" - -static void -nouveau_channel_context_destroy(struct nouveau_channel_context *nvc) -{ - nouveau_channel_free(&nvc->channel); - - FREE(nvc); -} - -static struct nouveau_channel_context * -nouveau_channel_context_create(struct nouveau_device *dev) -{ - struct nouveau_channel_context *nvc; - int ret; - - nvc = CALLOC_STRUCT(nouveau_channel_context); - if (!nvc) - return NULL; - - if ((ret = nouveau_channel_alloc(dev, 0x8003d001, 0x8003d002, - &nvc->channel))) { - NOUVEAU_ERR("Error creating GPU channel: %d\n", ret); - nouveau_channel_context_destroy(nvc); - return NULL; - } - - nvc->next_handle = 0x77000000; - return nvc; -} - -int -nouveau_context_init(struct nouveau_screen *nv_screen, - drm_context_t hHWContext, drmLock *sarea_lock, - struct nouveau_context *nv_share, - struct nouveau_context *nv) -{ - struct pipe_context *pipe = NULL; - struct nouveau_channel_context *nvc = NULL; - struct nouveau_device *dev = nv_screen->device; - int i; - - switch (dev->chipset & 0xf0) { - case 0x00: - /* NV04 */ - case 0x10: - case 0x20: - /* NV10 */ - case 0x30: - /* NV30 */ - case 0x40: - case 0x60: - /* NV40 */ - case 0x50: - case 0x80: - case 0x90: - /* G80 */ - break; - default: - NOUVEAU_ERR("Unsupported chipset: NV%02x\n", dev->chipset); - return 1; - } - - nv->nv_screen = nv_screen; - - { - struct nouveau_device_priv *nvdev = nouveau_device(dev); - - nvdev->ctx = hHWContext; - nvdev->lock = sarea_lock; - } - - /* Attempt to share a single channel between multiple contexts from - * a single process. - */ - nvc = nv_screen->nvc; - if (!nvc && nv_share) - nvc = nv_share->nvc; - - /*XXX: temporary - disable multi-context/single-channel on pre-NV4x */ - switch (dev->chipset & 0xf0) { - case 0x40: - case 0x60: - /* NV40 class */ - case 0x50: - case 0x80: - case 0x90: - /* G80 class */ - break; - default: - nvc = NULL; - break; - } - - if (!nvc) { - nvc = nouveau_channel_context_create(dev); - if (!nvc) { - NOUVEAU_ERR("Failed initialising GPU context\n"); - return 1; - } - nv_screen->nvc = nvc; - pipe_reference_init(&nvc->reference, 1); - } - - pipe_reference((struct pipe_reference**)&nv->nvc, &nvc->reference); - - /* Find a free slot for a pipe context, allocate a new one if needed */ - nv->pctx_id = -1; - for (i = 0; i < nvc->nr_pctx; i++) { - if (nvc->pctx[i] == NULL) { - nv->pctx_id = i; - break; - } - } - - if (nv->pctx_id < 0) { - nv->pctx_id = nvc->nr_pctx++; - nvc->pctx = - realloc(nvc->pctx, - sizeof(struct pipe_context *) * nvc->nr_pctx); - } - - /* Create pipe */ - if (!getenv("NOUVEAU_FORCE_SOFTPIPE")) { - struct pipe_screen *pscreen; - - pipe = nouveau_pipe_create(nv); - if (!pipe) { - NOUVEAU_ERR("Couldn't create hw pipe\n"); - return 1; - } - pscreen = nvc->pscreen; - - nv->cap.hw_vertex_buffer = - pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF); - nv->cap.hw_index_buffer = - pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF); - } - - if (!pipe) { - NOUVEAU_MSG("Using softpipe\n"); - pipe = nouveau_create_softpipe(nv); - if (!pipe) { - NOUVEAU_ERR("Error creating pipe, bailing\n"); - return 1; - } - } - - { - struct pipe_texture *fb_tex; - struct pipe_surface *fb_surf; - struct nouveau_pipe_buffer *fb_buf; - enum pipe_format format; - - fb_buf = calloc(1, sizeof(struct nouveau_pipe_buffer)); - pipe_reference_init(&fb_buf->base.reference, 1); - fb_buf->base.usage = PIPE_BUFFER_USAGE_PIXEL; - - nouveau_bo_handle_ref(dev, nv_screen->front_offset, &fb_buf->bo); - - if (nv_screen->front_cpp == 4) - format = PIPE_FORMAT_A8R8G8B8_UNORM; - else - format = PIPE_FORMAT_R5G6B5_UNORM; - - fb_surf = nouveau_surface_buffer_ref(nv, &fb_buf->base, format, - nv_screen->front_pitch / - nv_screen->front_cpp, - nv_screen->front_height, - nv_screen->front_pitch, - &fb_tex); - - nv->frontbuffer = fb_surf; - nv->frontbuffer_texture = fb_tex; - } - - pipe->priv = nv; - return 0; -} - -void -nouveau_context_cleanup(struct nouveau_context *nv) -{ - struct nouveau_channel_context *nvc = nv->nvc; - - assert(nv); - - if (nv->pctx_id >= 0) { - nvc->pctx[nv->pctx_id] = NULL; - if (pipe_reference((struct pipe_reference**)&nv->nvc, NULL)) { - nouveau_channel_context_destroy(nvc); - nv->nv_screen->nvc = NULL; - } - } - - /* XXX: Who cleans up the pipe? */ -} - diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_context.h b/src/gallium/winsys/drm/nouveau/common/nouveau_context.h deleted file mode 100644 index ba8fc3ad2df..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_context.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef __NOUVEAU_CONTEXT_H__ -#define __NOUVEAU_CONTEXT_H__ - -#include "nouveau/nouveau_winsys.h" -#include "nouveau_drmif.h" -#include "nouveau_device.h" -#include "nouveau_channel.h" -#include "nouveau_pushbuf.h" -#include "nouveau_bo.h" -#include "nouveau_grobj.h" -#include "nouveau_notifier.h" -#include "nouveau_class.h" -#include "nouveau_local.h" - -struct nouveau_channel_context { - struct pipe_reference reference; - struct pipe_screen *pscreen; - - unsigned cur_pctx; - unsigned nr_pctx; - struct pipe_context **pctx; - - struct nouveau_channel *channel; - unsigned next_handle; -}; - -struct nouveau_context { - int locked; - struct nouveau_screen *nv_screen; - struct pipe_surface *frontbuffer; - struct pipe_texture *frontbuffer_texture; - - struct { - int hw_vertex_buffer; - int hw_index_buffer; - } cap; - - /* Hardware context */ - struct nouveau_channel_context *nvc; - int pctx_id; -}; - -extern int nouveau_context_init(struct nouveau_screen *nv_screen, - drm_context_t hHWContext, drmLock *sarea_lock, - struct nouveau_context *nv_share, - struct nouveau_context *nv); -extern void nouveau_context_cleanup(struct nouveau_context *nv); - -extern void LOCK_HARDWARE(struct nouveau_context *); -extern void UNLOCK_HARDWARE(struct nouveau_context *); - -extern uint32_t *nouveau_pipe_dma_beginp(struct nouveau_grobj *, int, int); -extern void nouveau_pipe_dma_kickoff(struct nouveau_channel *); - -/* Must be provided by clients of common code */ -extern void -nouveau_contended_lock(struct nouveau_context *nv); - -#endif diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_dri.h b/src/gallium/winsys/drm/nouveau/common/nouveau_dri.h deleted file mode 100644 index 1207c2d609c..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_dri.h +++ /dev/null @@ -1,28 +0,0 @@ -#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/common/nouveau_local.h b/src/gallium/winsys/drm/nouveau/common/nouveau_local.h deleted file mode 100644 index 11175bce7a5..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_local.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __NOUVEAU_LOCAL_H__ -#define __NOUVEAU_LOCAL_H__ - -#include "pipe/p_compiler.h" -#include "nouveau_winsys_pipe.h" -#include - -/* Debug output */ -#define NOUVEAU_MSG(fmt, args...) do { \ - fprintf(stdout, "nouveau: "fmt, ##args); \ - fflush(stdout); \ -} while(0) - -#define NOUVEAU_ERR(fmt, args...) do { \ - fprintf(stderr, "%s:%d - "fmt, __func__, __LINE__, ##args); \ - fflush(stderr); \ -} while(0) - -#endif diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_lock.c b/src/gallium/winsys/drm/nouveau/common/nouveau_lock.c deleted file mode 100644 index e8cf051ed9e..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_lock.c +++ /dev/null @@ -1,72 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include -#include "nouveau_context.h" -#include "nouveau_screen.h" - -pipe_static_mutex(lockMutex); - -/* Lock the hardware and validate our state. - */ -void -LOCK_HARDWARE(struct nouveau_context *nv) -{ - struct nouveau_screen *nv_screen = nv->nv_screen; - struct nouveau_device *dev = nv_screen->device; - struct nouveau_device_priv *nvdev = nouveau_device(dev); - char __ret=0; - - assert(!nv->locked); - pipe_mutex_lock(lockMutex); - - DRM_CAS(nvdev->lock, nvdev->ctx, - (DRM_LOCK_HELD | nvdev->ctx), __ret); - - if (__ret) { - drmGetLock(nvdev->fd, nvdev->ctx, 0); - nouveau_contended_lock(nv); - } - nv->locked = 1; -} - -/* Unlock the hardware using the global current context - */ -void -UNLOCK_HARDWARE(struct nouveau_context *nv) -{ - struct nouveau_screen *nv_screen = nv->nv_screen; - struct nouveau_device *dev = nv_screen->device; - struct nouveau_device_priv *nvdev = nouveau_device(dev); - - assert(nv->locked); - nv->locked = 0; - - DRM_UNLOCK(nvdev->fd, nvdev->lock, nvdev->ctx); - - pipe_mutex_unlock(lockMutex); -} diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_screen.c b/src/gallium/winsys/drm/nouveau/common/nouveau_screen.c deleted file mode 100644 index 422fbf0207e..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_screen.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include "nouveau_dri.h" -#include "nouveau_local.h" -#include "nouveau_screen.h" - -int -nouveau_screen_init(struct nouveau_dri *nv_dri, int dev_fd, - struct nouveau_screen *nv_screen) -{ - int ret; - - ret = nouveau_device_open_existing(&nv_screen->device, 0, - dev_fd, 0); - if (ret) { - NOUVEAU_ERR("Failed opening nouveau device: %d\n", ret); - return 1; - } - - nv_screen->front_offset = nv_dri->front_offset; - nv_screen->front_pitch = nv_dri->front_pitch * (nv_dri->bpp / 8); - nv_screen->front_cpp = nv_dri->bpp / 8; - nv_screen->front_height = nv_dri->height; - - return 0; -} - -void -nouveau_screen_cleanup(struct nouveau_screen *nv_screen) -{ - nouveau_device_close(&nv_screen->device); -} diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_screen.h b/src/gallium/winsys/drm/nouveau/common/nouveau_screen.h deleted file mode 100644 index 3e68e219d86..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_screen.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __NOUVEAU_SCREEN_H__ -#define __NOUVEAU_SCREEN_H__ - -#include - -struct nouveau_device; -struct nouveau_dri; - -struct nouveau_screen { - struct nouveau_device *device; - - uint32_t front_offset; - uint32_t front_pitch; - uint32_t front_cpp; - uint32_t front_height; - - void *nvc; -}; - -int -nouveau_screen_init(struct nouveau_dri *nv_dri, int dev_fd, - struct nouveau_screen *nv_screen); - -void -nouveau_screen_cleanup(struct nouveau_screen *nv_screen); - -#endif diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c deleted file mode 100644 index 52c3b022475..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c +++ /dev/null @@ -1,146 +0,0 @@ -#include "util/u_memory.h" - -#include "nouveau_context.h" -#include "nouveau_screen.h" -#include "nouveau_winsys_pipe.h" - -#include "nouveau/nouveau_winsys.h" - -static int -nouveau_pipe_notifier_alloc(struct nouveau_winsys *nvws, int count, - struct nouveau_notifier **notify) -{ - struct nouveau_context *nv = nvws->nv; - - return nouveau_notifier_alloc(nv->nvc->channel, nv->nvc->next_handle++, - count, notify); -} - -static int -nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass, - struct nouveau_grobj **grobj) -{ - struct nouveau_context *nv = nvws->nv; - struct nouveau_channel *chan = nv->nvc->channel; - int ret; - - ret = nouveau_grobj_alloc(chan, nv->nvc->next_handle++, - grclass, grobj); - if (ret) - return ret; - - BEGIN_RING(chan, *grobj, 0x0000, 1); - OUT_RING (chan, (*grobj)->handle); - (*grobj)->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT; - return 0; -} - -static int -nouveau_pipe_push_reloc(struct nouveau_winsys *nvws, void *ptr, - struct pipe_buffer *buf, uint32_t data, - uint32_t flags, uint32_t vor, uint32_t tor) -{ - struct nouveau_bo *bo = nouveau_pipe_buffer(buf)->bo; - - return nouveau_pushbuf_emit_reloc(nvws->channel, ptr, bo, - data, flags, vor, tor); -} - -static int -nouveau_pipe_push_flush(struct nouveau_winsys *nvws, unsigned size, - struct pipe_fence_handle **fence) -{ - if (fence) - *fence = NULL; - - return nouveau_pushbuf_flush(nvws->channel, size); -} - -static struct nouveau_bo * -nouveau_pipe_get_bo(struct pipe_buffer *pb) -{ - return nouveau_pipe_buffer(pb)->bo; -} - -struct pipe_context * -nouveau_pipe_create(struct nouveau_context *nv) -{ - struct nouveau_channel_context *nvc = nv->nvc; - struct nouveau_winsys *nvws = CALLOC_STRUCT(nouveau_winsys); - struct pipe_screen *(*hws_create)(struct pipe_winsys *, - struct nouveau_winsys *); - struct pipe_context *(*hw_create)(struct pipe_screen *, unsigned); - struct pipe_winsys *ws; - unsigned chipset = nv->nv_screen->device->chipset; - - if (!nvws) - return NULL; - - switch (chipset & 0xf0) { - case 0x00: - hws_create = nv04_screen_create; - hw_create = nv04_create; - break; - case 0x10: - hws_create = nv10_screen_create; - hw_create = nv10_create; - break; - case 0x20: - hws_create = nv20_screen_create; - hw_create = nv20_create; - break; - case 0x30: - hws_create = nv30_screen_create; - hw_create = nv30_create; - break; - case 0x40: - case 0x60: - hws_create = nv40_screen_create; - hw_create = nv40_create; - break; - case 0x50: - case 0x80: - case 0x90: - hws_create = nv50_screen_create; - hw_create = nv50_create; - break; - default: - NOUVEAU_ERR("Unknown chipset NV%02x\n", chipset); - return NULL; - } - - nvws->nv = nv; - nvws->channel = nv->nvc->channel; - - nvws->res_init = nouveau_resource_init; - nvws->res_alloc = nouveau_resource_alloc; - nvws->res_free = nouveau_resource_free; - - nvws->push_reloc = nouveau_pipe_push_reloc; - nvws->push_flush = nouveau_pipe_push_flush; - - nvws->grobj_alloc = nouveau_pipe_grobj_alloc; - nvws->grobj_free = nouveau_grobj_free; - - nvws->notifier_alloc = nouveau_pipe_notifier_alloc; - nvws->notifier_free = nouveau_notifier_free; - nvws->notifier_reset = nouveau_notifier_reset; - nvws->notifier_status = nouveau_notifier_status; - nvws->notifier_retval = nouveau_notifier_return_val; - nvws->notifier_wait = nouveau_notifier_wait_status; - - nvws->get_bo = nouveau_pipe_get_bo; - - ws = nouveau_create_pipe_winsys(nv); - - if (!nvc->pscreen) { - nvc->pscreen = hws_create(ws, nvws); - if (!nvc->pscreen) { - NOUVEAU_ERR("Couldn't create hw screen\n"); - return NULL; - } - } - nvc->pctx[nv->pctx_id] = hw_create(nvc->pscreen, nv->pctx_id); - return nvc->pctx[nv->pctx_id]; -} - diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c deleted file mode 100644 index 24bbd4516f1..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c +++ /dev/null @@ -1,251 +0,0 @@ -#include "pipe/internal/p_winsys_screen.h" -#include -#include -#include -#include "nouveau_context.h" -#include "nouveau_local.h" -#include "nouveau_screen.h" -#include "nouveau_winsys_pipe.h" - -static const char * -nouveau_get_name(struct pipe_winsys *pws) -{ - return "Nouveau/DRI"; -} - -static uint32_t -nouveau_flags_from_usage(struct nouveau_context *nv, unsigned usage) -{ - struct nouveau_device *dev = nv->nv_screen->device; - uint32_t flags = NOUVEAU_BO_LOCAL; - - if (usage & NOUVEAU_BUFFER_USAGE_TRANSFER) - 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; - - switch (dev->chipset & 0xf0) { - case 0x50: - case 0x80: - case 0x90: - flags |= NOUVEAU_BO_TILED; - if (usage & NOUVEAU_BUFFER_USAGE_ZETA) - flags |= NOUVEAU_BO_ZTILE; - break; - default: - break; - } - } - - if (usage & PIPE_BUFFER_USAGE_VERTEX) { - if (nv->cap.hw_vertex_buffer) - flags |= NOUVEAU_BO_GART; - } - - if (usage & PIPE_BUFFER_USAGE_INDEX) { - if (nv->cap.hw_index_buffer) - flags |= NOUVEAU_BO_GART; - } - - return flags; -} - -static struct pipe_buffer * -nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment, - unsigned usage, unsigned size) -{ - struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws; - struct nouveau_context *nv = nvpws->nv; - struct nouveau_device *dev = nv->nv_screen->device; - struct nouveau_pipe_buffer *nvbuf; - uint32_t flags; - - nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer); - if (!nvbuf) - return NULL; - pipe_reference_init(&nvbuf->base.reference, 1); - nvbuf->base.alignment = alignment; - nvbuf->base.usage = usage; - nvbuf->base.size = size; - - flags = nouveau_flags_from_usage(nv, usage); - - if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) { - FREE(nvbuf); - return NULL; - } - - return &nvbuf->base; -} - -static struct pipe_buffer * -nouveau_pipe_bo_user_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) -{ - struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws; - struct nouveau_device *dev = nvpws->nv->nv_screen->device; - struct nouveau_pipe_buffer *nvbuf; - - nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer); - if (!nvbuf) - return NULL; - pipe_reference_init(&nvbuf->base.reference, 1); - nvbuf->base.size = bytes; - - if (nouveau_bo_user(dev, ptr, bytes, &nvbuf->bo)) { - FREE(nvbuf); - return NULL; - } - - return &nvbuf->base; -} - -static void -nouveau_pipe_bo_del(struct pipe_buffer *buf) -{ - struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf); - - nouveau_bo_ref(NULL, &nvbuf->bo); - FREE(nvbuf); -} - -static void * -nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf, - unsigned flags) -{ - struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf); - uint32_t map_flags = 0; - - if (flags & PIPE_BUFFER_USAGE_DONTBLOCK) { - /* Remove this when this code is modified to support DONTBLOCK - */ - return NULL; - } - - if (flags & PIPE_BUFFER_USAGE_CPU_READ) - map_flags |= NOUVEAU_BO_RD; - if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) - map_flags |= NOUVEAU_BO_WR; - -#if 0 - if (flags & PIPE_BUFFER_USAGE_DISCARD && - !(flags & PIPE_BUFFER_USAGE_CPU_READ) && - nouveau_bo_busy(nvbuf->bo, map_flags)) { - struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws; - struct nouveau_context *nv = nvpws->nv; - struct nouveau_device *dev = nv->nv_screen->device; - struct nouveau_bo *rename; - uint32_t flags = nouveau_flags_from_usage(nv, buf->usage); - - if (!nouveau_bo_new(dev, flags, buf->alignment, buf->size, &rename)) { - nouveau_bo_ref(NULL, &nvbuf->bo); - nvbuf->bo = rename; - } - } -#endif - - if (nouveau_bo_map(nvbuf->bo, map_flags)) - return NULL; - return nvbuf->bo->map; -} - -static void -nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) -{ - struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf); - - nouveau_bo_unmap(nvbuf->bo); -} - -static void -nouveau_pipe_fence_reference(struct pipe_winsys *ws, - struct pipe_fence_handle **ptr, - struct pipe_fence_handle *pfence) -{ - *ptr = pfence; -} - -static int -nouveau_pipe_fence_signalled(struct pipe_winsys *ws, - struct pipe_fence_handle *pfence, unsigned flag) -{ - return 0; -} - -static int -nouveau_pipe_fence_finish(struct pipe_winsys *ws, - struct pipe_fence_handle *pfence, unsigned flag) -{ - return 0; -} - -struct pipe_surface * -nouveau_surface_buffer_ref(struct nouveau_context *nv, struct pipe_buffer *pb, - enum pipe_format format, int w, int h, - unsigned pitch, struct pipe_texture **ppt) -{ - struct pipe_screen *pscreen = nv->nvc->pscreen; - struct pipe_texture tmpl, *pt; - struct pipe_surface *ps; - - memset(&tmpl, 0, sizeof(tmpl)); - tmpl.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - NOUVEAU_TEXTURE_USAGE_LINEAR; - tmpl.target = PIPE_TEXTURE_2D; - tmpl.width[0] = w; - tmpl.height[0] = h; - tmpl.depth[0] = 1; - tmpl.format = format; - pf_get_block(tmpl.format, &tmpl.block); - tmpl.nblocksx[0] = pf_get_nblocksx(&tmpl.block, w); - tmpl.nblocksy[0] = pf_get_nblocksy(&tmpl.block, h); - - pt = pscreen->texture_blanket(pscreen, &tmpl, &pitch, pb); - if (!pt) - return NULL; - - ps = pscreen->get_tex_surface(pscreen, pt, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); - - *ppt = pt; - return ps; -} - -static void -nouveau_destroy(struct pipe_winsys *pws) -{ - FREE(pws); -} - -struct pipe_winsys * -nouveau_create_pipe_winsys(struct nouveau_context *nv) -{ - struct nouveau_pipe_winsys *nvpws; - struct pipe_winsys *pws; - - nvpws = CALLOC_STRUCT(nouveau_pipe_winsys); - if (!nvpws) - return NULL; - nvpws->nv = nv; - pws = &nvpws->pws; - - pws->flush_frontbuffer = nouveau_flush_frontbuffer; - - pws->buffer_create = nouveau_pipe_bo_create; - pws->buffer_destroy = nouveau_pipe_bo_del; - pws->user_buffer_create = nouveau_pipe_bo_user_create; - pws->buffer_map = nouveau_pipe_bo_map; - pws->buffer_unmap = nouveau_pipe_bo_unmap; - - pws->fence_reference = nouveau_pipe_fence_reference; - pws->fence_signalled = nouveau_pipe_fence_signalled; - pws->fence_finish = nouveau_pipe_fence_finish; - - pws->get_name = nouveau_get_name; - pws->destroy = nouveau_destroy; - - return &nvpws->pws; -} diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.h b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.h deleted file mode 100644 index 1eb80434789..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef NOUVEAU_PIPE_WINSYS_H -#define NOUVEAU_PIPE_WINSYS_H - -#include "pipe/p_context.h" -#include "pipe/internal/p_winsys_screen.h" -#include "nouveau_context.h" - -struct nouveau_pipe_buffer { - struct pipe_buffer base; - struct nouveau_bo *bo; -}; - -static INLINE struct nouveau_pipe_buffer * -nouveau_pipe_buffer(struct pipe_buffer *buf) -{ - return (struct nouveau_pipe_buffer *)buf; -} - -struct nouveau_pipe_winsys { - struct pipe_winsys pws; - - struct nouveau_context *nv; -}; - -extern struct pipe_winsys * -nouveau_create_pipe_winsys(struct nouveau_context *nv); - -struct pipe_context * -nouveau_create_softpipe(struct nouveau_context *nv); - -struct pipe_context * -nouveau_pipe_create(struct nouveau_context *nv); - -/* Must be provided by clients of common code */ -extern void -nouveau_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surf, - void *context_private); - -struct pipe_surface * -nouveau_surface_buffer_ref(struct nouveau_context *nv, struct pipe_buffer *pb, - enum pipe_format format, int w, int h, - unsigned pitch, struct pipe_texture **ppt); - -#endif diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_softpipe.c b/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_softpipe.c deleted file mode 100644 index 396e4f2a2e6..00000000000 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_softpipe.c +++ /dev/null @@ -1,101 +0,0 @@ -/************************************************************************** - * - * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, - * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE - * USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * - **************************************************************************/ -/* - * Authors: Keith Whitwell - */ - -#include "pipe/internal/p_winsys_screen.h" -#include -#include -#include -#include -#include -#include "nouveau_context.h" -#include "nouveau_winsys_pipe.h" - -struct nouveau_softpipe_winsys { - struct softpipe_winsys sws; - struct nouveau_context *nv; -}; - -/** - * Return list of surface formats supported by this driver. - */ -static boolean -nouveau_is_format_supported(struct softpipe_winsys *sws, - enum pipe_format format) -{ - switch (format) { - case PIPE_FORMAT_A8R8G8B8_UNORM: - case PIPE_FORMAT_R5G6B5_UNORM: - case PIPE_FORMAT_Z24S8_UNORM: - return TRUE; - default: - break; - }; - - return FALSE; -} - -struct pipe_context * -nouveau_create_softpipe(struct nouveau_context *nv) -{ - struct nouveau_softpipe_winsys *nvsws; - struct pipe_screen *pscreen; - struct pipe_winsys *ws; - struct pipe_context *pipe; - - ws = nouveau_create_pipe_winsys(nv); - if (!ws) - return NULL; - pscreen = softpipe_create_screen(ws); - if (!pscreen) { - ws->destroy(ws); - return NULL; - } - nvsws = CALLOC_STRUCT(nouveau_softpipe_winsys); - if (!nvsws) { - ws->destroy(ws); - pscreen->destroy(pscreen); - return NULL; - } - - nvsws->sws.is_format_supported = nouveau_is_format_supported; - nvsws->nv = nv; - - pipe = softpipe_create(pscreen, ws, &nvsws->sws); - if (!pipe) { - ws->destroy(ws); - pscreen->destroy(pscreen); - FREE(nvsws); - return NULL; - } - - return pipe; -} - diff --git a/src/gallium/winsys/drm/nouveau/dri/Makefile b/src/gallium/winsys/drm/nouveau/dri/Makefile index a73e8d5cb4b..f7db6201fea 100644 --- a/src/gallium/winsys/drm/nouveau/dri/Makefile +++ b/src/gallium/winsys/drm/nouveau/dri/Makefile @@ -6,7 +6,7 @@ LIBNAME = nouveau_dri.so MINIGLX_SOURCES = PIPE_DRIVERS = \ - $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.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 \ @@ -15,10 +15,10 @@ PIPE_DRIVERS = \ $(TOP)/src/gallium/drivers/nv50/libnv50.a DRIVER_SOURCES = \ - nouveau_context_dri.c \ - nouveau_screen_dri.c \ + nouveau_context.c \ + nouveau_screen.c \ nouveau_swapbuffers.c \ - ../common/libnouveaudrm.a + nouveau_lock.c C_SOURCES = \ $(COMMON_GALLIUM_SOURCES) \ diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_context.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.c new file mode 100644 index 00000000000..deb6ffcff1c --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.c @@ -0,0 +1,118 @@ +#include
+#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "nouveau_context.h" +#include "nouveau_screen.h" + +#include "nouveau_drmif.h" + +GLboolean +nouveau_context_create(const __GLcontextModes *glVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate) +{ + __DRIscreenPrivate *driScrnPriv = driContextPriv->driScreenPriv; + struct nouveau_screen *nv_screen = driScrnPriv->private; + struct nouveau_context *nv; + struct pipe_context *pipe; + struct st_context *st_share = NULL; + + if (sharedContextPrivate) + st_share = ((struct nouveau_context *)sharedContextPrivate)->st; + + nv = CALLOC_STRUCT(nouveau_context); + if (!nv) + return GL_FALSE; + + { + struct nouveau_device_priv *nvdev = + nouveau_device(nv_screen->device); + + nvdev->ctx = driContextPriv->hHWContext; + nvdev->lock = (drmLock *)&driScrnPriv->pSAREA->lock; + } + + pipe = drm_api_hooks.create_context(nv_screen->pscreen); + if (!pipe) { + FREE(nv); + return GL_FALSE; + } + pipe->priv = nv; + + driContextPriv->driverPrivate = nv; + nv->dri_screen = driScrnPriv; + + driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache, + nv->dri_screen->myNum, "nouveau"); + + nv->st = st_create_context(pipe, glVis, st_share); + return GL_TRUE; +} + +void +nouveau_context_destroy(__DRIcontextPrivate *driContextPriv) +{ + struct nouveau_context *nv = driContextPriv->driverPrivate; + + assert(nv); + + st_finish(nv->st); + st_destroy_context(nv->st); + + FREE(nv); +} + +GLboolean +nouveau_context_bind(__DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv) +{ + struct nouveau_context *nv; + struct nouveau_framebuffer *draw, *read; + + if (!driContextPriv) { + st_make_current(NULL, NULL, NULL); + return GL_TRUE; + } + + nv = driContextPriv->driverPrivate; + draw = driDrawPriv->driverPrivate; + read = driReadPriv->driverPrivate; + + st_make_current(nv->st, draw->stfb, read->stfb); + + if ((nv->dri_drawable != driDrawPriv) || + (nv->last_stamp != driDrawPriv->lastStamp)) { + nv->dri_drawable = driDrawPriv; + st_resize_framebuffer(draw->stfb, driDrawPriv->w, + driDrawPriv->h); + nv->last_stamp = driDrawPriv->lastStamp; + } + + if (driDrawPriv != driReadPriv) { + st_resize_framebuffer(read->stfb, driReadPriv->w, + driReadPriv->h); + } + + return GL_TRUE; +} + +GLboolean +nouveau_context_unbind(__DRIcontextPrivate *driContextPriv) +{ + struct nouveau_context *nv = driContextPriv->driverPrivate; + (void)nv; + + st_flush(nv->st, 0, NULL); + return GL_TRUE; +} + diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_context.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.h new file mode 100644 index 00000000000..2779b092e64 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.h @@ -0,0 +1,53 @@ +#ifndef __NOUVEAU_CONTEXT_DRI_H__ +#define __NOUVEAU_CONTEXT_DRI_H__ + +#include +#include + +#include "nouveau/nouveau_winsys.h" + +#define NOUVEAU_ERR(fmt, args...) debug_printf("%s: "fmt, __func__, ##args) + +struct nouveau_framebuffer { + struct st_framebuffer *stfb; +}; + +struct nouveau_context { + struct st_context *st; + + /* DRI stuff */ + __DRIscreenPrivate *dri_screen; + __DRIdrawablePrivate *dri_drawable; + unsigned int last_stamp; + driOptionCache dri_option_cache; + drm_context_t drm_context; + drmLock drm_lock; + int locked; +}; + +extern GLboolean nouveau_context_create(const __GLcontextModes *, + __DRIcontextPrivate *, void *); +extern void nouveau_context_destroy(__DRIcontextPrivate *); +extern GLboolean nouveau_context_bind(__DRIcontextPrivate *, + __DRIdrawablePrivate *draw, + __DRIdrawablePrivate *read); +extern GLboolean nouveau_context_unbind(__DRIcontextPrivate *); + +extern void nouveau_contended_lock(struct nouveau_context *nv); +extern void LOCK_HARDWARE(struct nouveau_context *nv); +extern void UNLOCK_HARDWARE(struct nouveau_context *nv); + +#ifdef DEBUG +extern int __nouveau_debug; + +#define DEBUG_BO (1 << 0) + +#define DBG(flag, ...) do { \ + if (__nouveau_debug & (DEBUG_##flag)) \ + NOUVEAU_ERR(__VA_ARGS__); \ +} while(0) +#else +#define DBG(flag, ...) +#endif + +#endif diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.c deleted file mode 100644 index aacfe984d18..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.c +++ /dev/null @@ -1,124 +0,0 @@ -#include
-#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../common/nouveau_winsys_pipe.h" -#include "../common/nouveau_dri.h" -#include "../common/nouveau_local.h" -#include "nouveau_context_dri.h" -#include "nouveau_screen_dri.h" - -#ifdef DEBUG -static const struct dri_debug_control debug_control[] = { - { "bo", DEBUG_BO }, - { NULL, 0 } -}; -int __nouveau_debug = 0; -#endif - -GLboolean -nouveau_context_create(const __GLcontextModes *glVis, - __DRIcontextPrivate *driContextPriv, - void *sharedContextPrivate) -{ - __DRIscreenPrivate *driScrnPriv = driContextPriv->driScreenPriv; - struct nouveau_screen_dri *nv_screen = driScrnPriv->private; - struct nouveau_context_dri *nv = CALLOC_STRUCT(nouveau_context_dri); - struct st_context *st_share = NULL; - struct nouveau_context_dri *nv_share = NULL; - struct pipe_context *pipe; - - if (sharedContextPrivate) { - st_share = ((struct nouveau_context_dri *)sharedContextPrivate)->st; - nv_share = st_share->pipe->priv; - } - - if (nouveau_context_init(&nv_screen->base, driContextPriv->hHWContext, - (drmLock *)&driScrnPriv->pSAREA->lock, - &nv_share->base, &nv->base)) { - return GL_FALSE; - } - - pipe = nv->base.nvc->pctx[nv->base.pctx_id]; - driContextPriv->driverPrivate = (void *)nv; - //nv->nv_screen = nv_screen; - nv->dri_screen = driScrnPriv; - - driParseConfigFiles(&nv->dri_option_cache, &nv_screen->option_cache, - nv->dri_screen->myNum, "nouveau"); -#ifdef DEBUG - __nouveau_debug = driParseDebugString(getenv("NOUVEAU_DEBUG"), - debug_control); -#endif - - nv->st = st_create_context(pipe, glVis, st_share); - return GL_TRUE; -} - -void -nouveau_context_destroy(__DRIcontextPrivate *driContextPriv) -{ - struct nouveau_context_dri *nv = driContextPriv->driverPrivate; - - assert(nv); - - st_finish(nv->st); - st_destroy_context(nv->st); - - nouveau_context_cleanup(&nv->base); - - FREE(nv); -} - -GLboolean -nouveau_context_bind(__DRIcontextPrivate *driContextPriv, - __DRIdrawablePrivate *driDrawPriv, - __DRIdrawablePrivate *driReadPriv) -{ - struct nouveau_context_dri *nv; - struct nouveau_framebuffer *draw, *read; - - if (!driContextPriv) { - st_make_current(NULL, NULL, NULL); - return GL_TRUE; - } - - nv = driContextPriv->driverPrivate; - draw = driDrawPriv->driverPrivate; - read = driReadPriv->driverPrivate; - - st_make_current(nv->st, draw->stfb, read->stfb); - - if ((nv->dri_drawable != driDrawPriv) || - (nv->last_stamp != driDrawPriv->lastStamp)) { - nv->dri_drawable = driDrawPriv; - st_resize_framebuffer(draw->stfb, driDrawPriv->w, - driDrawPriv->h); - nv->last_stamp = driDrawPriv->lastStamp; - } - - if (driDrawPriv != driReadPriv) { - st_resize_framebuffer(read->stfb, driReadPriv->w, - driReadPriv->h); - } - - return GL_TRUE; -} - -GLboolean -nouveau_context_unbind(__DRIcontextPrivate *driContextPriv) -{ - struct nouveau_context_dri *nv = driContextPriv->driverPrivate; - (void)nv; - - st_flush(nv->st, 0, NULL); - return GL_TRUE; -} - diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.h deleted file mode 100644 index 64cf326411c..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef __NOUVEAU_CONTEXT_DRI_H__ -#define __NOUVEAU_CONTEXT_DRI_H__ - -#include -#include -#include -#include "../common/nouveau_context.h" - -struct nouveau_framebuffer { - struct st_framebuffer *stfb; -}; - -struct nouveau_context_dri { - struct nouveau_context base; - struct st_context *st; - - /* DRI stuff */ - __DRIscreenPrivate *dri_screen; - __DRIdrawablePrivate *dri_drawable; - unsigned int last_stamp; - driOptionCache dri_option_cache; - drm_context_t drm_context; - drmLock drm_lock; -}; - -extern GLboolean nouveau_context_create(const __GLcontextModes *, - __DRIcontextPrivate *, void *); -extern void nouveau_context_destroy(__DRIcontextPrivate *); -extern GLboolean nouveau_context_bind(__DRIcontextPrivate *, - __DRIdrawablePrivate *draw, - __DRIdrawablePrivate *read); -extern GLboolean nouveau_context_unbind(__DRIcontextPrivate *); - -#ifdef DEBUG -extern int __nouveau_debug; - -#define DEBUG_BO (1 << 0) - -#define DBG(flag, ...) do { \ - if (__nouveau_debug & (DEBUG_##flag)) \ - NOUVEAU_ERR(__VA_ARGS__); \ -} while(0) -#else -#define DBG(flag, ...) -#endif - -#endif diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_dri.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_dri.h new file mode 100644 index 00000000000..1207c2d609c --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/dri/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/dri/nouveau_lock.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_lock.c new file mode 100644 index 00000000000..92f5bd09c9d --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_lock.c @@ -0,0 +1,73 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include +#include "nouveau_context.h" +#include "nouveau_screen.h" +#include "nouveau_drmif.h" + +pipe_static_mutex(lockMutex); + +/* Lock the hardware and validate our state. + */ +void +LOCK_HARDWARE(struct nouveau_context *nv) +{ + struct nouveau_screen *nv_screen = nv->dri_screen->private; + struct nouveau_device *dev = nv_screen->device; + struct nouveau_device_priv *nvdev = nouveau_device(dev); + char __ret=0; + + assert(!nv->locked); + pipe_mutex_lock(lockMutex); + + DRM_CAS(nvdev->lock, nvdev->ctx, + (DRM_LOCK_HELD | nvdev->ctx), __ret); + + if (__ret) { + drmGetLock(nvdev->fd, nvdev->ctx, 0); + nouveau_contended_lock(nv); + } + nv->locked = 1; +} + +/* Unlock the hardware using the global current context + */ +void +UNLOCK_HARDWARE(struct nouveau_context *nv) +{ + struct nouveau_screen *nv_screen = nv->dri_screen->private; + struct nouveau_device *dev = nv_screen->device; + struct nouveau_device_priv *nvdev = nouveau_device(dev); + + assert(nv->locked); + nv->locked = 0; + + DRM_UNLOCK(nvdev->fd, nvdev->lock, nvdev->ctx); + + pipe_mutex_unlock(lockMutex); +} diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.c new file mode 100644 index 00000000000..c4cbbc21248 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.c @@ -0,0 +1,329 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include "nouveau_context.h" +#include "nouveau_screen.h" +#include "nouveau_swapbuffers.h" +#include "nouveau_dri.h" + +#include "nouveau_drm.h" +#include "nouveau_drmif.h" + +#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 12 +#error nouveau_drm.h version does not match expected version +#endif + +/* Extension stuff, enabling of extensions handled by Gallium's GL state + * tracker. But, we still need to define the entry points we want. + */ +#define need_GL_ARB_fragment_program +#define need_GL_ARB_multisample +#define need_GL_ARB_occlusion_query +#define need_GL_ARB_point_parameters +#define need_GL_ARB_shader_objects +#define need_GL_ARB_texture_compression +#define need_GL_ARB_vertex_program +#define need_GL_ARB_vertex_shader +#define need_GL_ARB_vertex_buffer_object +#define need_GL_EXT_compiled_vertex_array +#define need_GL_EXT_fog_coord +#define need_GL_EXT_secondary_color +#define need_GL_EXT_framebuffer_object +#define need_GL_VERSION_2_0 +#define need_GL_VERSION_2_1 +#include "extension_helper.h" + +const struct dri_extension card_extensions[] = +{ + { "GL_ARB_multisample", GL_ARB_multisample_functions }, + { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions }, + { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, + { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions }, + { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions }, + { "GL_ARB_shading_language_120", GL_VERSION_2_1_functions }, + { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions }, + { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, + { "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions }, + { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions }, + { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions }, + { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, + { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, + { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, + { NULL, 0 } +}; + +PUBLIC const char __driConfigOptions[] = +DRI_CONF_BEGIN +DRI_CONF_END; +static const GLuint __driNConfigOptions = 0; + +extern const struct dri_extension common_extensions[]; +extern const struct dri_extension nv40_extensions[]; + +static GLboolean +nouveau_create_buffer(__DRIscreenPrivate * driScrnPriv, + __DRIdrawablePrivate * driDrawPriv, + const __GLcontextModes *glVis, GLboolean pixmapBuffer) +{ + struct nouveau_framebuffer *nvfb; + enum pipe_format colour, depth, stencil; + + if (pixmapBuffer) + return GL_FALSE; + + nvfb = CALLOC_STRUCT(nouveau_framebuffer); + if (!nvfb) + return GL_FALSE; + + if (glVis->redBits == 5) + colour = PIPE_FORMAT_R5G6B5_UNORM; + else + colour = PIPE_FORMAT_A8R8G8B8_UNORM; + + if (glVis->depthBits == 16) + depth = PIPE_FORMAT_Z16_UNORM; + else if (glVis->depthBits == 24) + depth = PIPE_FORMAT_Z24S8_UNORM; + else + depth = PIPE_FORMAT_NONE; + + if (glVis->stencilBits == 8) + stencil = PIPE_FORMAT_Z24S8_UNORM; + else + stencil = PIPE_FORMAT_NONE; + + nvfb->stfb = st_create_framebuffer(glVis, colour, depth, stencil, + driDrawPriv->w, driDrawPriv->h, + (void*)nvfb); + if (!nvfb->stfb) { + free(nvfb); + return GL_FALSE; + } + + driDrawPriv->driverPrivate = (void *)nvfb; + return GL_TRUE; +} + +static void +nouveau_destroy_buffer(__DRIdrawablePrivate * driDrawPriv) +{ + struct nouveau_framebuffer *nvfb; + + nvfb = (struct nouveau_framebuffer *)driDrawPriv->driverPrivate; + st_unreference_framebuffer(nvfb->stfb); + free(nvfb); +} + +static __DRIconfig ** +nouveau_fill_in_modes(__DRIscreenPrivate *psp, + unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer) +{ + __DRIconfig **configs; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, + }; + + uint8_t depth_bits_array[3]; + uint8_t stencil_bits_array[3]; + uint8_t msaa_samples_array[1]; + + depth_bits_array[0] = 0; + depth_bits_array[1] = depth_bits; + depth_bits_array[2] = depth_bits; + + /* Just like with the accumulation buffer, always provide some modes + * with a stencil buffer. It will be a sw fallback, but some apps won't + * care about that. + */ + stencil_bits_array[0] = 0; + stencil_bits_array[1] = 0; + if (depth_bits == 24) + stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; + stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; + + msaa_samples_array[0] = 0; + + depth_buffer_factor = + ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; + back_buffer_factor = (have_back_buffer) ? 3 : 1; + + if (pixel_bits == 16) { + fb_format = GL_RGB; + fb_type = GL_UNSIGNED_SHORT_5_6_5; + } + else { + fb_format = GL_BGRA; + fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + configs = driCreateConfigs(fb_format, fb_type, + depth_bits_array, stencil_bits_array, + depth_buffer_factor, back_buffer_modes, + back_buffer_factor, msaa_samples_array, 1); + if (configs == NULL) { + fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__); + return NULL; + } + + return configs; +} + +static struct pipe_surface * +dri_surface_from_handle(struct pipe_screen *screen, + unsigned handle, + enum pipe_format format, + unsigned width, + unsigned height, + unsigned pitch) +{ + struct pipe_surface *surface = NULL; + struct pipe_texture *texture = NULL; + struct pipe_texture templat; + struct pipe_buffer *buf = NULL; + + buf = drm_api_hooks.buffer_from_handle(screen, "front buffer", handle); + if (!buf) + return NULL; + + memset(&templat, 0, sizeof(templat)); + templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; + templat.target = PIPE_TEXTURE_2D; + templat.last_level = 0; + templat.depth[0] = 1; + templat.format = format; + templat.width[0] = width; + templat.height[0] = height; + pf_get_block(templat.format, &templat.block); + + texture = screen->texture_blanket(screen, + &templat, + &pitch, + buf); + + /* we don't need the buffer from this point on */ + pipe_buffer_reference(&buf, NULL); + + if (!texture) + return NULL; + + surface = screen->get_tex_surface(screen, texture, 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(&texture, NULL); + return surface; +} + +static const __DRIconfig ** +nouveau_screen_create(__DRIscreenPrivate *psp) +{ + struct nouveau_dri *nv_dri = psp->pDevPriv; + struct nouveau_screen *nv_screen; + static const __DRIversion ddx_expected = + { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = + { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; + + if (!driCheckDriDdxDrmVersions2("nouveau", + &psp->dri_version, &dri_expected, + &psp->ddx_version, &ddx_expected, + &psp->drm_version, &drm_expected)) { + return NULL; + } + + if (drm_expected.patch != psp->drm_version.patch) { + fprintf(stderr, "Incompatible DRM patch level.\n" + "Expected: %d\n" "Current : %d\n", + drm_expected.patch, psp->drm_version.patch); + return NULL; + } + + driInitExtensions(NULL, card_extensions, GL_FALSE); + + if (psp->devPrivSize != sizeof(struct nouveau_dri)) { + NOUVEAU_ERR("DRI struct mismatch between DDX/DRI\n"); + return NULL; + } + + nv_screen = CALLOC_STRUCT(nouveau_screen); + if (!nv_screen) + return NULL; + + nouveau_device_open_existing(&nv_screen->device, 0, psp->fd, 0); + + nv_screen->pscreen = drm_api_hooks.create_screen(psp->fd, 0); + if (!nv_screen->pscreen) { + FREE(nv_screen); + return NULL; + } + nv_screen->pscreen->flush_frontbuffer = nouveau_flush_frontbuffer; + + { + enum pipe_format format; + + if (nv_dri->bpp == 16) + format = PIPE_FORMAT_R5G6B5_UNORM; + else + format = PIPE_FORMAT_A8R8G8B8_UNORM; + + nv_screen->fb = dri_surface_from_handle(nv_screen->pscreen, + nv_dri->front_offset, + format, + nv_dri->width, + nv_dri->height, + nv_dri->front_pitch * + nv_dri->bpp / 8); + } + + driParseOptionInfo(&nv_screen->option_cache, + __driConfigOptions, __driNConfigOptions); + + nv_screen->driScrnPriv = psp; + psp->private = (void *)nv_screen; + + return (const __DRIconfig **) + nouveau_fill_in_modes(psp, nv_dri->bpp, + (nv_dri->bpp == 16) ? 16 : 24, + (nv_dri->bpp == 16) ? 0 : 8, 1); +} + +static void +nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv) +{ + struct nouveau_screen *nv_screen = driScrnPriv->private; + + driScrnPriv->private = NULL; + FREE(nv_screen); +} + +const struct __DriverAPIRec +driDriverAPI = { + .InitScreen = nouveau_screen_create, + .DestroyScreen = nouveau_screen_destroy, + .CreateContext = nouveau_context_create, + .DestroyContext = nouveau_context_destroy, + .CreateBuffer = nouveau_create_buffer, + .DestroyBuffer = nouveau_destroy_buffer, + .SwapBuffers = nouveau_swap_buffers, + .MakeCurrent = nouveau_context_bind, + .UnbindContext = nouveau_context_unbind, + .CopySubBuffer = nouveau_copy_sub_buffer, + + .InitScreen2 = NULL, /* one day, I promise! */ +}; + diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.h new file mode 100644 index 00000000000..ac078f3c638 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.h @@ -0,0 +1,16 @@ +#ifndef __NOUVEAU_SCREEN_DRI_H__ +#define __NOUVEAU_SCREEN_DRI_H__ + +#include "xmlconfig.h" + +struct nouveau_screen { + __DRIscreenPrivate *driScrnPriv; + driOptionCache option_cache; + + struct nouveau_device *device; + + struct pipe_screen *pscreen; + struct pipe_surface *fb; +}; + +#endif diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.c deleted file mode 100644 index 964a9028aac..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include -#include - -#include -#include -#include -#include -#include "../common/nouveau_dri.h" -#include "../common/nouveau_local.h" -#include "nouveau_context_dri.h" -#include "nouveau_screen_dri.h" -#include "nouveau_swapbuffers.h" - -#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 12 -#error nouveau_drm.h version does not match expected version -#endif - -/* Extension stuff, enabling of extensions handled by Gallium's GL state - * tracker. But, we still need to define the entry points we want. - */ -#define need_GL_ARB_fragment_program -#define need_GL_ARB_multisample -#define need_GL_ARB_occlusion_query -#define need_GL_ARB_point_parameters -#define need_GL_ARB_shader_objects -#define need_GL_ARB_texture_compression -#define need_GL_ARB_vertex_program -#define need_GL_ARB_vertex_shader -#define need_GL_ARB_vertex_buffer_object -#define need_GL_EXT_compiled_vertex_array -#define need_GL_EXT_fog_coord -#define need_GL_EXT_secondary_color -#define need_GL_EXT_framebuffer_object -#define need_GL_VERSION_2_0 -#define need_GL_VERSION_2_1 -#include "extension_helper.h" - -const struct dri_extension card_extensions[] = -{ - { "GL_ARB_multisample", GL_ARB_multisample_functions }, - { "GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions }, - { "GL_ARB_point_parameters", GL_ARB_point_parameters_functions }, - { "GL_ARB_shader_objects", GL_ARB_shader_objects_functions }, - { "GL_ARB_shading_language_100", GL_VERSION_2_0_functions }, - { "GL_ARB_shading_language_120", GL_VERSION_2_1_functions }, - { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions }, - { "GL_ARB_vertex_program", GL_ARB_vertex_program_functions }, - { "GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions }, - { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions }, - { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions }, - { "GL_EXT_fog_coord", GL_EXT_fog_coord_functions }, - { "GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions }, - { "GL_EXT_secondary_color", GL_EXT_secondary_color_functions }, - { NULL, 0 } -}; - -PUBLIC const char __driConfigOptions[] = -DRI_CONF_BEGIN -DRI_CONF_END; -static const GLuint __driNConfigOptions = 0; - -extern const struct dri_extension common_extensions[]; -extern const struct dri_extension nv40_extensions[]; - -static GLboolean -nouveau_create_buffer(__DRIscreenPrivate * driScrnPriv, - __DRIdrawablePrivate * driDrawPriv, - const __GLcontextModes *glVis, GLboolean pixmapBuffer) -{ - struct nouveau_framebuffer *nvfb; - enum pipe_format colour, depth, stencil; - - if (pixmapBuffer) - return GL_FALSE; - - nvfb = CALLOC_STRUCT(nouveau_framebuffer); - if (!nvfb) - return GL_FALSE; - - if (glVis->redBits == 5) - colour = PIPE_FORMAT_R5G6B5_UNORM; - else - colour = PIPE_FORMAT_A8R8G8B8_UNORM; - - if (glVis->depthBits == 16) - depth = PIPE_FORMAT_Z16_UNORM; - else if (glVis->depthBits == 24) - depth = PIPE_FORMAT_Z24S8_UNORM; - else - depth = PIPE_FORMAT_NONE; - - if (glVis->stencilBits == 8) - stencil = PIPE_FORMAT_Z24S8_UNORM; - else - stencil = PIPE_FORMAT_NONE; - - nvfb->stfb = st_create_framebuffer(glVis, colour, depth, stencil, - driDrawPriv->w, driDrawPriv->h, - (void*)nvfb); - if (!nvfb->stfb) { - free(nvfb); - return GL_FALSE; - } - - driDrawPriv->driverPrivate = (void *)nvfb; - return GL_TRUE; -} - -static void -nouveau_destroy_buffer(__DRIdrawablePrivate * driDrawPriv) -{ - struct nouveau_framebuffer *nvfb; - - nvfb = (struct nouveau_framebuffer *)driDrawPriv->driverPrivate; - st_unreference_framebuffer(nvfb->stfb); - free(nvfb); -} - -static __DRIconfig ** -nouveau_fill_in_modes(__DRIscreenPrivate *psp, - unsigned pixel_bits, unsigned depth_bits, - unsigned stencil_bits, GLboolean have_back_buffer) -{ - __DRIconfig **configs; - unsigned depth_buffer_factor; - unsigned back_buffer_factor; - GLenum fb_format; - GLenum fb_type; - - static const GLenum back_buffer_modes[] = { - GLX_NONE, GLX_SWAP_UNDEFINED_OML, - }; - - uint8_t depth_bits_array[3]; - uint8_t stencil_bits_array[3]; - uint8_t msaa_samples_array[1]; - - depth_bits_array[0] = 0; - depth_bits_array[1] = depth_bits; - depth_bits_array[2] = depth_bits; - - /* Just like with the accumulation buffer, always provide some modes - * with a stencil buffer. It will be a sw fallback, but some apps won't - * care about that. - */ - stencil_bits_array[0] = 0; - stencil_bits_array[1] = 0; - if (depth_bits == 24) - stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits; - stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; - - msaa_samples_array[0] = 0; - - depth_buffer_factor = - ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; - back_buffer_factor = (have_back_buffer) ? 3 : 1; - - if (pixel_bits == 16) { - fb_format = GL_RGB; - fb_type = GL_UNSIGNED_SHORT_5_6_5; - } - else { - fb_format = GL_BGRA; - fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; - } - - configs = driCreateConfigs(fb_format, fb_type, - depth_bits_array, stencil_bits_array, - depth_buffer_factor, back_buffer_modes, - back_buffer_factor, msaa_samples_array, 1); - if (configs == NULL) { - fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", - __func__, __LINE__); - return NULL; - } - - return configs; -} - -static const __DRIconfig ** -nouveau_screen_create(__DRIscreenPrivate *psp) -{ - struct nouveau_dri *nv_dri = psp->pDevPriv; - struct nouveau_screen_dri *nv_screen; - static const __DRIversion ddx_expected = - { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; - static const __DRIversion dri_expected = { 4, 0, 0 }; - static const __DRIversion drm_expected = - { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; - - if (!driCheckDriDdxDrmVersions2("nouveau", - &psp->dri_version, &dri_expected, - &psp->ddx_version, &ddx_expected, - &psp->drm_version, &drm_expected)) { - return NULL; - } - - if (drm_expected.patch != psp->drm_version.patch) { - fprintf(stderr, "Incompatible DRM patch level.\n" - "Expected: %d\n" "Current : %d\n", - drm_expected.patch, psp->drm_version.patch); - return NULL; - } - - driInitExtensions(NULL, card_extensions, GL_FALSE); - - if (psp->devPrivSize != sizeof(struct nouveau_dri)) { - NOUVEAU_ERR("DRI struct mismatch between DDX/DRI\n"); - return NULL; - } - - nv_screen = CALLOC_STRUCT(nouveau_screen_dri); - if (!nv_screen) - return NULL; - - driParseOptionInfo(&nv_screen->option_cache, - __driConfigOptions, __driNConfigOptions); - - if (nouveau_screen_init(nv_dri, psp->fd, &nv_screen->base)) { - FREE(nv_screen); - return NULL; - } - - nv_screen->driScrnPriv = psp; - psp->private = (void *)nv_screen; - - return (const __DRIconfig **) - nouveau_fill_in_modes(psp, nv_dri->bpp, - (nv_dri->bpp == 16) ? 16 : 24, - (nv_dri->bpp == 16) ? 0 : 8, 1); -} - -static void -nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv) -{ - struct nouveau_screen_dri *nv_screen = driScrnPriv->private; - - driScrnPriv->private = NULL; - nouveau_screen_cleanup(&nv_screen->base); - FREE(nv_screen); -} - -const struct __DriverAPIRec -driDriverAPI = { - .InitScreen = nouveau_screen_create, - .DestroyScreen = nouveau_screen_destroy, - .CreateContext = nouveau_context_create, - .DestroyContext = nouveau_context_destroy, - .CreateBuffer = nouveau_create_buffer, - .DestroyBuffer = nouveau_destroy_buffer, - .SwapBuffers = nouveau_swap_buffers, - .MakeCurrent = nouveau_context_bind, - .UnbindContext = nouveau_context_unbind, - .CopySubBuffer = nouveau_copy_sub_buffer, - - .InitScreen2 = NULL, /* one day, I promise! */ -}; - diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.h deleted file mode 100644 index 1498087819c..00000000000 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __NOUVEAU_SCREEN_DRI_H__ -#define __NOUVEAU_SCREEN_DRI_H__ - -#include "../common/nouveau_screen.h" -#include "xmlconfig.h" - -struct nouveau_screen_dri { - struct nouveau_screen base; - __DRIscreenPrivate *driScrnPriv; - driOptionCache option_cache; -}; - -#endif diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c index 3cac722b4a8..9c841a0b2d0 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.c @@ -7,23 +7,25 @@ #include #include -#include "../common/nouveau_local.h" -#include "nouveau_context_dri.h" -#include "nouveau_screen_dri.h" +#include "nouveau_context.h" +#include "nouveau_screen.h" #include "nouveau_swapbuffers.h" +#include "nouveau_pushbuf.h" + void nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf, const drm_clip_rect_t *rect) { - struct nouveau_context_dri *nv = dPriv->driContextPriv->driverPrivate; - struct pipe_context *pipe = nv->base.nvc->pctx[nv->base.pctx_id]; + struct nouveau_context *nv = dPriv->driContextPriv->driverPrivate; + struct nouveau_screen *nv_screen = nv->dri_screen->private; + struct pipe_context *pipe = nv->st->pipe; drm_clip_rect_t *pbox; int nbox, i; - LOCK_HARDWARE(&nv->base); + LOCK_HARDWARE(nv); if (!dPriv->numClipRects) { - UNLOCK_HARDWARE(&nv->base); + UNLOCK_HARDWARE(nv); return; } pbox = dPriv->pClipRects; @@ -39,12 +41,12 @@ nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf, w = pbox->x2 - pbox->x1; h = pbox->y2 - pbox->y1; - pipe->surface_copy(pipe, nv->base.frontbuffer, - dx, dy, surf, sx, sy, w, h); + pipe->surface_copy(pipe, nv_screen->fb, dx, dy, surf, + sx, sy, w, h); } - FIRE_RING(nv->base.nvc->channel); - UNLOCK_HARDWARE(&nv->base); + pipe->flush(pipe, 0, NULL); + UNLOCK_HARDWARE(nv); if (nv->last_stamp != dPriv->lastStamp) { struct nouveau_framebuffer *nvfb = dPriv->driverPrivate; @@ -86,19 +88,19 @@ nouveau_swap_buffers(__DRIdrawablePrivate *dPriv) } void -nouveau_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surf, +nouveau_flush_frontbuffer(struct pipe_screen *pscreen, struct pipe_surface *ps, void *context_private) { - struct nouveau_context_dri *nv = context_private; + struct nouveau_context *nv = context_private; __DRIdrawablePrivate *dPriv = nv->dri_drawable; - nouveau_copy_buffer(dPriv, surf, NULL); + nouveau_copy_buffer(dPriv, ps, NULL); } void nouveau_contended_lock(struct nouveau_context *nv) { - struct nouveau_context_dri *nv_sub = (struct nouveau_context_dri*)nv; + struct nouveau_context *nv_sub = (struct nouveau_context*)nv; __DRIdrawablePrivate *dPriv = nv_sub->dri_drawable; __DRIscreenPrivate *sPriv = nv_sub->dri_screen; diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.h index 825d3da6da5..4ca9cc22831 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.h +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_swapbuffers.h @@ -1,10 +1,11 @@ #ifndef __NOUVEAU_SWAPBUFFERS_H__ #define __NOUVEAU_SWAPBUFFERS_H__ -extern void nouveau_copy_buffer(__DRIdrawablePrivate *, struct pipe_surface *, - const drm_clip_rect_t *); -extern void nouveau_copy_sub_buffer(__DRIdrawablePrivate *, - int x, int y, int w, int h); -extern void nouveau_swap_buffers(__DRIdrawablePrivate *); +void nouveau_copy_buffer(__DRIdrawablePrivate *, struct pipe_surface *, + const drm_clip_rect_t *); +void nouveau_copy_sub_buffer(__DRIdrawablePrivate *, int x, int y, int w, int h); +void nouveau_swap_buffers(__DRIdrawablePrivate *); +void nouveau_flush_frontbuffer(struct pipe_screen *, struct pipe_surface *, + void *context_private); #endif diff --git a/src/gallium/winsys/drm/nouveau/dri2/Makefile b/src/gallium/winsys/drm/nouveau/dri2/Makefile new file mode 100644 index 00000000000..728870d2e1d --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/dri2/Makefile @@ -0,0 +1,26 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = nouveau_dri2.so + +PIPE_DRIVERS = \ + $(TOP)/src/gallium/state_trackers/dri2/libdri2drm.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 + +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 00000000000..2da78d8690f --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/drm/Makefile @@ -0,0 +1,13 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBNAME = nouveaudrm + +C_SOURCES = nouveau_drm_api.c \ + nouveau_winsys_pipe.c \ + nouveau_winsys.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_drm_api.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c new file mode 100644 index 00000000000..c0127e803f1 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.c @@ -0,0 +1,194 @@ +#include "util/u_memory.h" + +#include "nouveau_drm_api.h" +#include "nouveau_winsys_pipe.h" + +#include "nouveau_drmif.h" +#include "nouveau_channel.h" +#include "nouveau_bo.h" + +static struct pipe_screen * +nouveau_drm_create_screen(int fd, int pciid) +{ + struct pipe_winsys *ws; + struct nouveau_winsys *nvws; + struct nouveau_device *dev = NULL; + struct pipe_screen *(*init)(struct pipe_winsys *, + struct nouveau_winsys *); + 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; + } + + ws = nouveau_pipe_winsys_new(dev); + if (!ws) { + nouveau_device_close(&dev); + return NULL; + } + + nvws = nouveau_winsys_new(ws); + if (!nvws) { + ws->destroy(ws); + return NULL; + } + + nouveau_pipe_winsys(ws)->pscreen = init(ws, nvws); + if (!nouveau_pipe_winsys(ws)->pscreen) { + ws->destroy(ws); + return NULL; + } + + return nouveau_pipe_winsys(ws)->pscreen; +} + +static struct pipe_context * +nouveau_drm_create_context(struct pipe_screen *pscreen) +{ + struct nouveau_pipe_winsys *nvpws = nouveau_screen(pscreen); + struct pipe_context *(*init)(struct pipe_screen *, unsigned); + unsigned chipset = nvpws->channel->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 < nvpws->nr_pctx; i++) { + if (nvpws->pctx[i] == NULL) + break; + } + + if (i == nvpws->nr_pctx) { + nvpws->nr_pctx++; + nvpws->pctx = realloc(nvpws->pctx, + sizeof(*nvpws->pctx) * nvpws->nr_pctx); + } + + nvpws->pctx[i] = init(pscreen, i); + return nvpws->pctx[i]; +} + +static boolean +nouveau_drm_pb_from_pt(struct pipe_texture *pt, struct pipe_buffer **ppb, + unsigned *stride) +{ + return false; +} + +static struct pipe_buffer * +nouveau_drm_pb_from_handle(struct pipe_screen *pscreen, const char *name, + unsigned handle) +{ + struct nouveau_pipe_winsys *nvpws = nouveau_screen(pscreen); + struct nouveau_device *dev = nvpws->channel->device; + struct nouveau_pipe_buffer *nvpb; + int ret; + + nvpb = CALLOC_STRUCT(nouveau_pipe_buffer); + if (!nvpb) + return NULL; + + ret = nouveau_bo_handle_ref(dev, handle, &nvpb->bo); + if (ret) { + debug_printf("%s: ref name 0x%08x failed with %d\n", + __func__, handle, ret); + FREE(nvpb); + return NULL; + } + + pipe_reference_init(&nvpb->base.reference, 1); + nvpb->base.screen = pscreen; + nvpb->base.alignment = 0; + nvpb->base.usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE | + PIPE_BUFFER_USAGE_CPU_READ_WRITE; + nvpb->base.size = nvpb->bo->size; + return &nvpb->base; +} + +static boolean +nouveau_drm_handle_from_pb(struct pipe_screen *pscreen, struct pipe_buffer *pb, + unsigned *handle) +{ + struct nouveau_pipe_buffer *nvpb = nouveau_pipe_buffer(pb); + + if (!nvpb) + return FALSE; + + *handle = nvpb->bo->handle; + return TRUE; +} + +static boolean +nouveau_drm_name_from_pb(struct pipe_screen *pscreen, struct pipe_buffer *pb, + unsigned *handle) +{ + struct nouveau_pipe_buffer *nvpb = nouveau_pipe_buffer(pb); + + if (!nvpb) + return FALSE; + + return nouveau_bo_handle_get(nvpb->bo, handle) == 0; +} + +struct drm_api drm_api_hooks = { + .create_screen = nouveau_drm_create_screen, + .create_context = nouveau_drm_create_context, + .buffer_from_texture = nouveau_drm_pb_from_pt, + .buffer_from_handle = nouveau_drm_pb_from_handle, + .handle_from_buffer = nouveau_drm_handle_from_pb, + .global_handle_from_buffer = nouveau_drm_name_from_pb, +}; + 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 00000000000..2782c83c0e7 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_drm_api.h @@ -0,0 +1,5 @@ +#ifndef __NOUVEAU_DRM_API_H__ +#define __NOUVEAU_DRM_API_H__ +#include "state_tracker/drm_api.h" + +#endif diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c new file mode 100644 index 00000000000..e3175fd7753 --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c @@ -0,0 +1,94 @@ +#include "util/u_memory.h" + +#include "nouveau_winsys_pipe.h" + +static int +nouveau_pipe_notifier_alloc(struct nouveau_winsys *nvws, int count, + struct nouveau_notifier **notify) +{ + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(nvws->ws); + + return nouveau_notifier_alloc(nvpws->channel, nvpws->next_handle++, + count, notify); +} + +static int +nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass, + struct nouveau_grobj **grobj) +{ + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(nvws->ws); + struct nouveau_channel *chan = nvpws->channel; + int ret; + + ret = nouveau_grobj_alloc(chan, nvpws->next_handle++, grclass, grobj); + if (ret) + return ret; + + BEGIN_RING(chan, *grobj, 0x0000, 1); + OUT_RING (chan, (*grobj)->handle); + (*grobj)->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT; + return 0; +} + +static int +nouveau_pipe_push_reloc(struct nouveau_winsys *nvws, void *ptr, + struct pipe_buffer *buf, uint32_t data, + uint32_t flags, uint32_t vor, uint32_t tor) +{ + struct nouveau_bo *bo = nouveau_pipe_buffer(buf)->bo; + + return nouveau_pushbuf_emit_reloc(nvws->channel, ptr, bo, + data, flags, vor, tor); +} + +static int +nouveau_pipe_push_flush(struct nouveau_winsys *nvws, unsigned size, + struct pipe_fence_handle **fence) +{ + if (fence) + *fence = NULL; + + return nouveau_pushbuf_flush(nvws->channel, size); +} + +static struct nouveau_bo * +nouveau_pipe_get_bo(struct pipe_buffer *pb) +{ + return nouveau_pipe_buffer(pb)->bo; +} + +struct nouveau_winsys * +nouveau_winsys_new(struct pipe_winsys *ws) +{ + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); + struct nouveau_winsys *nvws; + + nvws = CALLOC_STRUCT(nouveau_winsys); + if (!nvws) + return NULL; + + nvws->ws = ws; + nvws->channel = nvpws->channel; + + nvws->res_init = nouveau_resource_init; + nvws->res_alloc = nouveau_resource_alloc; + nvws->res_free = nouveau_resource_free; + + nvws->push_reloc = nouveau_pipe_push_reloc; + nvws->push_flush = nouveau_pipe_push_flush; + + nvws->grobj_alloc = nouveau_pipe_grobj_alloc; + nvws->grobj_free = nouveau_grobj_free; + + nvws->notifier_alloc = nouveau_pipe_notifier_alloc; + nvws->notifier_free = nouveau_notifier_free; + nvws->notifier_reset = nouveau_notifier_reset; + nvws->notifier_status = nouveau_notifier_status; + nvws->notifier_retval = nouveau_notifier_return_val; + nvws->notifier_wait = nouveau_notifier_wait_status; + + nvws->get_bo = nouveau_pipe_get_bo; + + return nvws; +} + diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.c new file mode 100644 index 00000000000..9e03a9f5dba --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.c @@ -0,0 +1,204 @@ +#include "pipe/internal/p_winsys_screen.h" +#include +#include +#include + +#include "nouveau_winsys_pipe.h" + +#include "nouveau_drmif.h" +#include "nouveau_bo.h" + +static const char * +nouveau_get_name(struct pipe_winsys *pws) +{ + return "Nouveau/DRI"; +} + +static uint32_t +nouveau_flags_from_usage(struct pipe_winsys *ws, unsigned usage) +{ + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); + struct pipe_screen *pscreen = nvpws->pscreen; + uint32_t flags = NOUVEAU_BO_LOCAL; + + if (usage & NOUVEAU_BUFFER_USAGE_TRANSFER) + 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; + + switch (nvpws->channel->device->chipset & 0xf0) { + case 0x50: + case 0x80: + case 0x90: + flags |= NOUVEAU_BO_TILED; + if (usage & NOUVEAU_BUFFER_USAGE_ZETA) + flags |= NOUVEAU_BO_ZTILE; + break; + default: + break; + } + } + + if (usage & PIPE_BUFFER_USAGE_VERTEX) { + if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF)) + flags |= NOUVEAU_BO_GART; + } + + if (usage & PIPE_BUFFER_USAGE_INDEX) { + if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF)) + flags |= NOUVEAU_BO_GART; + } + + return flags; +} + +static struct pipe_buffer * +nouveau_pipe_bo_create(struct pipe_winsys *ws, unsigned alignment, + unsigned usage, unsigned size) +{ + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); + struct nouveau_device *dev = nvpws->channel->device; + struct nouveau_pipe_buffer *nvbuf; + uint32_t flags; + + nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer); + if (!nvbuf) + return NULL; + pipe_reference_init(&nvbuf->base.reference, 1); + nvbuf->base.alignment = alignment; + nvbuf->base.usage = usage; + nvbuf->base.size = size; + + flags = nouveau_flags_from_usage(ws, usage); + if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) { + FREE(nvbuf); + return NULL; + } + + return &nvbuf->base; +} + +static struct pipe_buffer * +nouveau_pipe_bo_user_create(struct pipe_winsys *ws, void *ptr, unsigned bytes) +{ + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); + struct nouveau_device *dev = nvpws->channel->device; + struct nouveau_pipe_buffer *nvbuf; + + nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer); + if (!nvbuf) + return NULL; + pipe_reference_init(&nvbuf->base.reference, 1); + nvbuf->base.size = bytes; + + if (nouveau_bo_user(dev, ptr, bytes, &nvbuf->bo)) { + FREE(nvbuf); + return NULL; + } + + return &nvbuf->base; +} + +static void +nouveau_pipe_bo_del(struct pipe_buffer *buf) +{ + struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf); + + nouveau_bo_ref(NULL, &nvbuf->bo); + FREE(nvbuf); +} + +static void * +nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf, + unsigned flags) +{ + struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf); + uint32_t map_flags = 0; + + if (flags & PIPE_BUFFER_USAGE_CPU_READ) + map_flags |= NOUVEAU_BO_RD; + if (flags & PIPE_BUFFER_USAGE_CPU_WRITE) + map_flags |= NOUVEAU_BO_WR; + + if (nouveau_bo_map(nvbuf->bo, map_flags)) + return NULL; + return nvbuf->bo->map; +} + +static void +nouveau_pipe_bo_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) +{ + struct nouveau_pipe_buffer *nvbuf = nouveau_pipe_buffer(buf); + + nouveau_bo_unmap(nvbuf->bo); +} + +static void +nouveau_pipe_fence_reference(struct pipe_winsys *ws, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *pfence) +{ + *ptr = pfence; +} + +static int +nouveau_pipe_fence_signalled(struct pipe_winsys *ws, + struct pipe_fence_handle *pfence, unsigned flag) +{ + return 0; +} + +static int +nouveau_pipe_fence_finish(struct pipe_winsys *ws, + struct pipe_fence_handle *pfence, unsigned flag) +{ + return 0; +} + +static void +nouveau_destroy(struct pipe_winsys *ws) +{ + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); + + nouveau_device_close(&nvpws->channel->device); + FREE(nvpws); +} + +struct pipe_winsys * +nouveau_pipe_winsys_new(struct nouveau_device *dev) +{ + struct nouveau_pipe_winsys *nvpws; + int ret; + + nvpws = CALLOC_STRUCT(nouveau_pipe_winsys); + if (!nvpws) + return NULL; + + ret = nouveau_channel_alloc(dev, 0xbeef0201, 0xbeef0202, + &nvpws->channel); + if (ret) { + debug_printf("%s: error opening GPU channel: %d\n", + __func__, ret); + FREE(nvpws); + return NULL; + } + nvpws->next_handle = 0x77000000; + + nvpws->base.buffer_create = nouveau_pipe_bo_create; + nvpws->base.buffer_destroy = nouveau_pipe_bo_del; + nvpws->base.user_buffer_create = nouveau_pipe_bo_user_create; + nvpws->base.buffer_map = nouveau_pipe_bo_map; + nvpws->base.buffer_unmap = nouveau_pipe_bo_unmap; + + nvpws->base.fence_reference = nouveau_pipe_fence_reference; + nvpws->base.fence_signalled = nouveau_pipe_fence_signalled; + nvpws->base.fence_finish = nouveau_pipe_fence_finish; + + nvpws->base.get_name = nouveau_get_name; + nvpws->base.destroy = nouveau_destroy; + return &nvpws->base; +} diff --git a/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.h b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.h new file mode 100644 index 00000000000..10e1e269e8c --- /dev/null +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.h @@ -0,0 +1,52 @@ +#ifndef NOUVEAU_PIPE_WINSYS_H +#define NOUVEAU_PIPE_WINSYS_H + +#include "pipe/internal/p_winsys_screen.h" +#include "pipe/p_context.h" + +#include "nouveau/nouveau_winsys.h" + +#include "nouveau_device.h" + +struct nouveau_pipe_buffer { + struct pipe_buffer base; + struct nouveau_bo *bo; +}; + +static INLINE struct nouveau_pipe_buffer * +nouveau_pipe_buffer(struct pipe_buffer *buf) +{ + return (struct nouveau_pipe_buffer *)buf; +} + +struct nouveau_pipe_winsys { + struct pipe_winsys base; + + struct pipe_screen *pscreen; + + struct nouveau_channel *channel; + uint32_t next_handle; + + unsigned nr_pctx; + struct pipe_context **pctx; +}; + +static INLINE struct nouveau_pipe_winsys * +nouveau_pipe_winsys(struct pipe_winsys *ws) +{ + return (struct nouveau_pipe_winsys *)ws; +} + +static INLINE struct nouveau_pipe_winsys * +nouveau_screen(struct pipe_screen *pscreen) +{ + return nouveau_pipe_winsys(pscreen->winsys); +} + +struct pipe_winsys * +nouveau_pipe_winsys_new(struct nouveau_device *); + +struct nouveau_winsys * +nouveau_winsys_new(struct pipe_winsys *ws); + +#endif -- cgit v1.2.3