diff options
author | Ben Skeggs <[email protected]> | 2009-03-18 08:22:35 +1000 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2009-03-18 09:44:40 +1000 |
commit | e00ae524e236afba1305150cacd634eaa1f5460b (patch) | |
tree | e6173fc3a85b6f6b66691e4a880257a39764fd6e /src/gallium/winsys/drm | |
parent | b46fcf25be4d1d5a5d072fbce03c2490bf41203f (diff) |
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.
Diffstat (limited to 'src/gallium/winsys/drm')
25 files changed, 504 insertions, 745 deletions
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 <pipe/p_defines.h> -#include <pipe/p_context.h> -#include <pipe/p_screen.h> -#include <util/u_memory.h> -#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_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 <stdio.h> - -/* 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_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 <util/u_memory.h> -#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 <stdint.h> - -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_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 <keithw-at-tungstengraphics-dot-com> - */ - -#include "pipe/internal/p_winsys_screen.h" -#include <pipe/p_screen.h> -#include <pipe/p_defines.h> -#include <pipe/p_format.h> -#include <softpipe/sp_winsys.h> -#include <util/u_memory.h> -#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_dri.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.c index aacfe984d18..deb6ffcff1c 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.c +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.c @@ -5,23 +5,15 @@ #include <state_tracker/st_public.h> #include <state_tracker/st_context.h> +#include <state_tracker/drm_api.h> #include <pipe/p_defines.h> #include <pipe/p_context.h> #include <pipe/p_screen.h> -#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" +#include "nouveau_context.h" +#include "nouveau_screen.h" -#ifdef DEBUG -static const struct dri_debug_control debug_control[] = { - { "bo", DEBUG_BO }, - { NULL, 0 } -}; -int __nouveau_debug = 0; -#endif +#include "nouveau_drmif.h" GLboolean nouveau_context_create(const __GLcontextModes *glVis, @@ -29,34 +21,38 @@ nouveau_context_create(const __GLcontextModes *glVis, 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 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_dri *)sharedContextPrivate)->st; - nv_share = st_share->pipe->priv; + 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; } - if (nouveau_context_init(&nv_screen->base, driContextPriv->hHWContext, - (drmLock *)&driScrnPriv->pSAREA->lock, - &nv_share->base, &nv->base)) { + pipe = drm_api_hooks.create_context(nv_screen->pscreen); + if (!pipe) { + FREE(nv); return GL_FALSE; } + pipe->priv = nv; - pipe = nv->base.nvc->pctx[nv->base.pctx_id]; - driContextPriv->driverPrivate = (void *)nv; - //nv->nv_screen = nv_screen; + driContextPriv->driverPrivate = nv; 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; @@ -65,15 +61,13 @@ nouveau_context_create(const __GLcontextModes *glVis, void nouveau_context_destroy(__DRIcontextPrivate *driContextPriv) { - struct nouveau_context_dri *nv = driContextPriv->driverPrivate; + struct nouveau_context *nv = driContextPriv->driverPrivate; assert(nv); st_finish(nv->st); st_destroy_context(nv->st); - nouveau_context_cleanup(&nv->base); - FREE(nv); } @@ -82,7 +76,7 @@ nouveau_context_bind(__DRIcontextPrivate *driContextPriv, __DRIdrawablePrivate *driDrawPriv, __DRIdrawablePrivate *driReadPriv) { - struct nouveau_context_dri *nv; + struct nouveau_context *nv; struct nouveau_framebuffer *draw, *read; if (!driContextPriv) { @@ -115,7 +109,7 @@ nouveau_context_bind(__DRIcontextPrivate *driContextPriv, GLboolean nouveau_context_unbind(__DRIcontextPrivate *driContextPriv) { - struct nouveau_context_dri *nv = driContextPriv->driverPrivate; + struct nouveau_context *nv = driContextPriv->driverPrivate; (void)nv; st_flush(nv->st, 0, NULL); diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.h index 64cf326411c..2779b092e64 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_context_dri.h +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_context.h @@ -3,15 +3,16 @@ #include <dri_util.h> #include <xmlconfig.h> -#include <nouveau/nouveau_winsys.h> -#include "../common/nouveau_context.h" + +#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_dri { - struct nouveau_context base; +struct nouveau_context { struct st_context *st; /* DRI stuff */ @@ -21,6 +22,7 @@ struct nouveau_context_dri { driOptionCache dri_option_cache; drm_context_t drm_context; drmLock drm_lock; + int locked; }; extern GLboolean nouveau_context_create(const __GLcontextModes *, @@ -31,6 +33,10 @@ extern GLboolean nouveau_context_bind(__DRIcontextPrivate *, __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; diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_dri.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_dri.h index 1207c2d609c..1207c2d609c 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_dri.h +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_dri.h diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_lock.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_lock.c index e8cf051ed9e..92f5bd09c9d 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_lock.c +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_lock.c @@ -28,6 +28,7 @@ #include <pipe/p_thread.h> #include "nouveau_context.h" #include "nouveau_screen.h" +#include "nouveau_drmif.h" pipe_static_mutex(lockMutex); @@ -36,7 +37,7 @@ pipe_static_mutex(lockMutex); void LOCK_HARDWARE(struct nouveau_context *nv) { - struct nouveau_screen *nv_screen = nv->nv_screen; + 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; @@ -59,7 +60,7 @@ LOCK_HARDWARE(struct nouveau_context *nv) void UNLOCK_HARDWARE(struct nouveau_context *nv) { - struct nouveau_screen *nv_screen = nv->nv_screen; + struct nouveau_screen *nv_screen = nv->dri_screen->private; struct nouveau_device *dev = nv_screen->device; struct nouveau_device_priv *nvdev = nouveau_device(dev); diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.c b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.c index 964a9028aac..c4cbbc21248 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.c +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.c @@ -5,12 +5,15 @@ #include <pipe/p_context.h> #include <state_tracker/st_public.h> #include <state_tracker/st_cb_fbo.h> -#include <nouveau_drm.h> -#include "../common/nouveau_dri.h" -#include "../common/nouveau_local.h" -#include "nouveau_context_dri.h" -#include "nouveau_screen_dri.h" +#include <state_tracker/drm_api.h> + +#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 @@ -178,11 +181,58 @@ nouveau_fill_in_modes(__DRIscreenPrivate *psp, 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_dri *nv_screen; + struct nouveau_screen *nv_screen; static const __DRIversion ddx_expected = { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; static const __DRIversion dri_expected = { 4, 0, 0 }; @@ -210,17 +260,38 @@ nouveau_screen_create(__DRIscreenPrivate *psp) return NULL; } - nv_screen = CALLOC_STRUCT(nouveau_screen_dri); + nv_screen = CALLOC_STRUCT(nouveau_screen); if (!nv_screen) return NULL; - driParseOptionInfo(&nv_screen->option_cache, - __driConfigOptions, __driNConfigOptions); + nouveau_device_open_existing(&nv_screen->device, 0, psp->fd, 0); - if (nouveau_screen_init(nv_dri, psp->fd, &nv_screen->base)) { + 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; @@ -234,10 +305,9 @@ nouveau_screen_create(__DRIscreenPrivate *psp) static void nouveau_screen_destroy(__DRIscreenPrivate *driScrnPriv) { - struct nouveau_screen_dri *nv_screen = driScrnPriv->private; + struct nouveau_screen *nv_screen = driScrnPriv->private; driScrnPriv->private = NULL; - nouveau_screen_cleanup(&nv_screen->base); FREE(nv_screen); } diff --git a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.h b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.h index 1498087819c..ac078f3c638 100644 --- a/src/gallium/winsys/drm/nouveau/dri/nouveau_screen_dri.h +++ b/src/gallium/winsys/drm/nouveau/dri/nouveau_screen.h @@ -1,13 +1,16 @@ #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; +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_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 <state_tracker/st_context.h> #include <state_tracker/st_cb_fbo.h> -#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/common/nouveau_winsys.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c index 52c3b022475..e3175fd7753 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys.c +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys.c @@ -1,18 +1,14 @@ #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; + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(nvws->ws); - return nouveau_notifier_alloc(nv->nvc->channel, nv->nvc->next_handle++, + return nouveau_notifier_alloc(nvpws->channel, nvpws->next_handle++, count, notify); } @@ -20,12 +16,11 @@ 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; + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(nvws->ws); + struct nouveau_channel *chan = nvpws->channel; int ret; - ret = nouveau_grobj_alloc(chan, nv->nvc->next_handle++, - grclass, grobj); + ret = nouveau_grobj_alloc(chan, nvpws->next_handle++, grclass, grobj); if (ret) return ret; @@ -62,55 +57,18 @@ 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_winsys * +nouveau_winsys_new(struct pipe_winsys *ws) { - 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; + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); + struct nouveau_winsys *nvws; + nvws = CALLOC_STRUCT(nouveau_winsys); 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->ws = ws; + nvws->channel = nvpws->channel; nvws->res_init = nouveau_resource_init; nvws->res_alloc = nouveau_resource_alloc; @@ -131,16 +89,6 @@ nouveau_pipe_create(struct nouveau_context *nv) 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]; + return nvws; } diff --git a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.c index 24bbd4516f1..9e03a9f5dba 100644 --- a/src/gallium/winsys/drm/nouveau/common/nouveau_winsys_pipe.c +++ b/src/gallium/winsys/drm/nouveau/drm/nouveau_winsys_pipe.c @@ -2,11 +2,12 @@ #include <pipe/p_defines.h> #include <pipe/p_inlines.h> #include <util/u_memory.h> -#include "nouveau_context.h" -#include "nouveau_local.h" -#include "nouveau_screen.h" + #include "nouveau_winsys_pipe.h" +#include "nouveau_drmif.h" +#include "nouveau_bo.h" + static const char * nouveau_get_name(struct pipe_winsys *pws) { @@ -14,9 +15,10 @@ nouveau_get_name(struct pipe_winsys *pws) } static uint32_t -nouveau_flags_from_usage(struct nouveau_context *nv, unsigned usage) +nouveau_flags_from_usage(struct pipe_winsys *ws, unsigned usage) { - struct nouveau_device *dev = nv->nv_screen->device; + 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) @@ -28,7 +30,7 @@ nouveau_flags_from_usage(struct nouveau_context *nv, unsigned usage) if (!(usage & PIPE_BUFFER_USAGE_CPU_READ_WRITE)) flags |= NOUVEAU_BO_VRAM; - switch (dev->chipset & 0xf0) { + switch (nvpws->channel->device->chipset & 0xf0) { case 0x50: case 0x80: case 0x90: @@ -42,12 +44,12 @@ nouveau_flags_from_usage(struct nouveau_context *nv, unsigned usage) } if (usage & PIPE_BUFFER_USAGE_VERTEX) { - if (nv->cap.hw_vertex_buffer) + if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_VTXBUF)) flags |= NOUVEAU_BO_GART; } if (usage & PIPE_BUFFER_USAGE_INDEX) { - if (nv->cap.hw_index_buffer) + if (pscreen->get_param(pscreen, NOUVEAU_CAP_HW_IDXBUF)) flags |= NOUVEAU_BO_GART; } @@ -55,12 +57,11 @@ nouveau_flags_from_usage(struct nouveau_context *nv, unsigned usage) } static struct pipe_buffer * -nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment, +nouveau_pipe_bo_create(struct pipe_winsys *ws, 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_winsys *nvpws = nouveau_pipe_winsys(ws); + struct nouveau_device *dev = nvpws->channel->device; struct nouveau_pipe_buffer *nvbuf; uint32_t flags; @@ -72,8 +73,7 @@ nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment, nvbuf->base.usage = usage; nvbuf->base.size = size; - flags = nouveau_flags_from_usage(nv, usage); - + flags = nouveau_flags_from_usage(ws, usage); if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) { FREE(nvbuf); return NULL; @@ -83,10 +83,10 @@ nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment, } static struct pipe_buffer * -nouveau_pipe_bo_user_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) +nouveau_pipe_bo_user_create(struct pipe_winsys *ws, 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_winsys *nvpws = nouveau_pipe_winsys(ws); + struct nouveau_device *dev = nvpws->channel->device; struct nouveau_pipe_buffer *nvbuf; nvbuf = CALLOC_STRUCT(nouveau_pipe_buffer); @@ -119,34 +119,11 @@ nouveau_pipe_bo_map(struct pipe_winsys *pws, struct pipe_buffer *buf, 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; @@ -182,70 +159,46 @@ nouveau_pipe_fence_finish(struct pipe_winsys *ws, 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) +nouveau_destroy(struct pipe_winsys *ws) { - FREE(pws); + struct nouveau_pipe_winsys *nvpws = nouveau_pipe_winsys(ws); + + nouveau_device_close(&nvpws->channel->device); + FREE(nvpws); } struct pipe_winsys * -nouveau_create_pipe_winsys(struct nouveau_context *nv) +nouveau_pipe_winsys_new(struct nouveau_device *dev) { struct nouveau_pipe_winsys *nvpws; - struct pipe_winsys *pws; + int ret; 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; + 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; - pws->fence_reference = nouveau_pipe_fence_reference; - pws->fence_signalled = nouveau_pipe_fence_signalled; - pws->fence_finish = nouveau_pipe_fence_finish; + 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; - pws->get_name = nouveau_get_name; - pws->destroy = nouveau_destroy; + nvpws->base.fence_reference = nouveau_pipe_fence_reference; + nvpws->base.fence_signalled = nouveau_pipe_fence_signalled; + nvpws->base.fence_finish = nouveau_pipe_fence_finish; - return &nvpws->pws; + 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 |