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.
This commit is contained in:
Ben Skeggs 2009-03-18 08:22:35 +10:00
parent b46fcf25be
commit e00ae524e2
26 changed files with 505 additions and 746 deletions

View file

@ -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;

View file

@ -2,7 +2,7 @@
TOP = ../../../../..
include $(TOP)/configs/current
SUBDIRS = common dri
SUBDIRS = drm dri dri2
default install clean:
@for dir in $(SUBDIRS) ; do \

View file

@ -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

View file

@ -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? */
}

View file

@ -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

View file

@ -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

View file

@ -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);
}

View file

@ -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

View file

@ -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

View file

@ -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;
}

View file

@ -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) \

View file

@ -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);

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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:

View file

@ -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

View file

@ -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,
};

View file

@ -0,0 +1,5 @@
#ifndef __NOUVEAU_DRM_API_H__
#define __NOUVEAU_DRM_API_H__
#include "state_tracker/drm_api.h"
#endif

View file

@ -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;
}

View file

@ -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;
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->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;
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->fence_reference = nouveau_pipe_fence_reference;
pws->fence_signalled = nouveau_pipe_fence_signalled;
pws->fence_finish = nouveau_pipe_fence_finish;
nvpws->base.fence_reference = nouveau_pipe_fence_reference;
nvpws->base.fence_signalled = nouveau_pipe_fence_signalled;
nvpws->base.fence_finish = nouveau_pipe_fence_finish;
pws->get_name = nouveau_get_name;
pws->destroy = nouveau_destroy;
return &nvpws->pws;
nvpws->base.get_name = nouveau_get_name;
nvpws->base.destroy = nouveau_destroy;
return &nvpws->base;
}

View file

@ -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