summaryrefslogtreecommitdiff
path: root/src/mesa/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r--src/mesa/drivers/common/driverfuncs.c37
-rw-r--r--src/mesa/drivers/common/driverfuncs.h4
-rw-r--r--src/mesa/drivers/dri/Makefile.template1
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c14
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h2
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_screen.c4
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c13
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_winsys.h17
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c60
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c63
-rw-r--r--src/mesa/drivers/dri/intel_winsys/intel_winsys_softpipe.c6
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/Makefile9
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c131
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c9
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_context.c50
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h44
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c44
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h135
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c135
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h18
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_lock.c15
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c257
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.c8
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.h2
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_swapbuffers.c24
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c85
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c61
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_softpipe.c6
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nv04_surface.c (renamed from src/mesa/drivers/dri/nouveau_winsys/nv04_region.c)130
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nv50_region.c51
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nv50_surface.c170
31 files changed, 988 insertions, 617 deletions
diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
index 96e5037fa5..ea0cc51d4a 100644
--- a/src/mesa/drivers/common/driverfuncs.c
+++ b/src/mesa/drivers/common/driverfuncs.c
@@ -260,43 +260,6 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
/**
- * Plug in Mesa's GLSL functions.
- */
-void
-_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
-{
- driver->AttachShader = _mesa_attach_shader;
- driver->BindAttribLocation = _mesa_bind_attrib_location;
- driver->CompileShader = _mesa_compile_shader;
- driver->CreateProgram = _mesa_create_program;
- driver->CreateShader = _mesa_create_shader;
- driver->DeleteProgram2 = _mesa_delete_program2;
- driver->DeleteShader = _mesa_delete_shader;
- driver->DetachShader = _mesa_detach_shader;
- driver->GetActiveAttrib = _mesa_get_active_attrib;
- driver->GetActiveUniform = _mesa_get_active_uniform;
- driver->GetAttachedShaders = _mesa_get_attached_shaders;
- driver->GetAttribLocation = _mesa_get_attrib_location;
- driver->GetHandle = _mesa_get_handle;
- driver->GetProgramiv = _mesa_get_programiv;
- driver->GetProgramInfoLog = _mesa_get_program_info_log;
- driver->GetShaderiv = _mesa_get_shaderiv;
- driver->GetShaderInfoLog = _mesa_get_shader_info_log;
- driver->GetShaderSource = _mesa_get_shader_source;
- driver->GetUniformfv = _mesa_get_uniformfv;
- driver->GetUniformLocation = _mesa_get_uniform_location;
- driver->IsProgram = _mesa_is_program;
- driver->IsShader = _mesa_is_shader;
- driver->LinkProgram = _mesa_link_program;
- driver->ShaderSource = _mesa_shader_source;
- driver->Uniform = _mesa_uniform;
- driver->UniformMatrix = _mesa_uniform_matrix;
- driver->UseProgram = _mesa_use_program;
- driver->ValidateProgram = _mesa_validate_program;
-}
-
-
-/**
* Call the ctx->Driver.* state functions with current values to initialize
* driver state.
* Only the Intel drivers use this so far.
diff --git a/src/mesa/drivers/common/driverfuncs.h b/src/mesa/drivers/common/driverfuncs.h
index 6ed23c4520..4c90ed12f6 100644
--- a/src/mesa/drivers/common/driverfuncs.h
+++ b/src/mesa/drivers/common/driverfuncs.h
@@ -31,10 +31,6 @@ _mesa_init_driver_functions(struct dd_function_table *driver);
extern void
-_mesa_init_glsl_driver_functions(struct dd_function_table *driver);
-
-
-extern void
_mesa_init_driver_state(GLcontext *ctx);
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template
index 37bf0a4977..1d0b0726db 100644
--- a/src/mesa/drivers/dri/Makefile.template
+++ b/src/mesa/drivers/dri/Makefile.template
@@ -3,7 +3,6 @@
MESA_MODULES = $(TOP)/src/mesa/libmesa.a
COMMON_SOURCES = \
- ../../common/driverfuncs.c \
../common/utils.c \
../common/texmem.c \
../common/vblank.c \
diff --git a/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c
index ed223977e2..49e04d81ec 100644
--- a/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c
@@ -307,6 +307,20 @@ intel_batchbuffer_flush(struct intel_batchbuffer *batch)
}
+void
+intel_batchbuffer_finish(struct intel_batchbuffer *batch)
+{
+ struct _DriFenceObject *fence = intel_batchbuffer_flush(batch);
+ if (fence) {
+ driFenceReference(fence);
+ driFenceFinish(fence,
+ DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW,
+ GL_FALSE);
+ driFenceUnReference(fence);
+ }
+}
+
+
/* This is the only way buffers get added to the validate list.
*/
boolean
diff --git a/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h
index 2c943e68e5..82feafa21f 100644
--- a/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h
+++ b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h
@@ -72,6 +72,8 @@ struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context *intel);
void intel_batchbuffer_free(struct intel_batchbuffer *batch);
+void intel_batchbuffer_finish(struct intel_batchbuffer *batch);
+
struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer
*batch);
diff --git a/src/mesa/drivers/dri/intel_winsys/intel_screen.c b/src/mesa/drivers/dri/intel_winsys/intel_screen.c
index 01460e5be3..1b520f7135 100644
--- a/src/mesa/drivers/dri/intel_winsys/intel_screen.c
+++ b/src/mesa/drivers/dri/intel_winsys/intel_screen.c
@@ -328,8 +328,8 @@ intelSetTexOffset(__DRIcontext *pDRICtx, int texname,
if (!stObj)
return;
- if (stObj->mt)
- st_miptree_release(intel->st->pipe, &stObj->mt);
+ if (stObj->pt)
+ st->pipe->texture_release(intel->st->pipe, &stObj->pt);
stObj->imageOverride = GL_TRUE;
stObj->depthOverride = depth;
diff --git a/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c b/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c
index 9fcb2dac27..454cd71f6c 100644
--- a/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c
+++ b/src/mesa/drivers/dri/intel_winsys/intel_swapbuffers.c
@@ -88,16 +88,15 @@ intelDisplaySurface(__DRIdrawablePrivate *dPriv,
const drm_clip_rect_t *pbox = dPriv->pClipRects;
const int pitch = intelScreen->front.pitch / intelScreen->front.cpp;
const int cpp = intelScreen->front.cpp;
- const struct pipe_region *srcRegion = surf->region;
- const int srcpitch = srcRegion->pitch;
+ const int srcpitch = surf->pitch;
int BR13, CMD;
int i;
- ASSERT(srcRegion);
- ASSERT(srcRegion->cpp == cpp);
+ ASSERT(surf->buffer);
+ ASSERT(surf->cpp == cpp);
DBG(SWAP, "screen pitch %d src surface pitch %d\n",
- pitch, srcRegion->pitch);
+ pitch, surf->pitch);
if (cpp == 2) {
BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
@@ -159,7 +158,7 @@ intelDisplaySurface(__DRIdrawablePrivate *dPriv,
assert(box.x1 < box.x2);
assert(box.y1 < box.y2);
- /* XXX this could be done with pipe->region_copy() */
+ /* XXX this could be done with pipe->surface_copy() */
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH(CMD);
OUT_BATCH(BR13);
@@ -171,7 +170,7 @@ intelDisplaySurface(__DRIdrawablePrivate *dPriv,
DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
OUT_BATCH((sbox.y1 << 16) | sbox.x1);
OUT_BATCH((srcpitch * cpp) & 0xffff);
- OUT_RELOC(dri_bo(srcRegion->buffer),
+ OUT_RELOC(dri_bo(surf->buffer),
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
diff --git a/src/mesa/drivers/dri/intel_winsys/intel_winsys.h b/src/mesa/drivers/dri/intel_winsys/intel_winsys.h
index f944cd23c3..89e63e0a79 100644
--- a/src/mesa/drivers/dri/intel_winsys/intel_winsys.h
+++ b/src/mesa/drivers/dri/intel_winsys/intel_winsys.h
@@ -32,9 +32,7 @@ struct intel_context;
struct pipe_context;
struct pipe_winsys;
struct pipe_buffer_handle;
-struct pipe_fence;
struct _DriBufferObject;
-struct _DriFenceObject;
struct pipe_winsys *
intel_create_pipe_winsys( int fd );
@@ -68,20 +66,5 @@ pipe_bo( struct _DriBufferObject *bo )
}
-/* Turn the pipe opaque buffer pointer into a dri_bufmgr opaque
- * buffer pointer...
- */
-static INLINE struct _DriFenceObject *
-dri_fo( struct pipe_fence *bo )
-{
- return (struct _DriFenceObject *)bo;
-}
-
-static INLINE struct pipe_fence *
-pipe_fo( struct _DriFenceObject *bo )
-{
- return (struct pipe_fence *)bo;
-}
-
#endif
diff --git a/src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c b/src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c
index d73b309fd4..8e0eea4392 100644
--- a/src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c
+++ b/src/mesa/drivers/dri/intel_winsys/intel_winsys_i915.c
@@ -111,62 +111,19 @@ static void intel_i915_batch_reloc( struct i915_winsys *sws,
-static void
-intel_i915_batch_flush( struct i915_winsys *sws,
- struct pipe_fence **fence )
+static void intel_i915_batch_flush( struct i915_winsys *sws )
{
struct intel_context *intel = intel_i915_winsys(sws)->intel;
- struct pipe_fence *tmp_fence;
-
- tmp_fence = pipe_fo(intel_batchbuffer_flush( intel->batch ));
-
- /* this also increases the fence reference count, which is not done inside
- * intel_batchbuffer_flush call above
- */
- sws->fence_reference(sws, fence, tmp_fence);
-}
-
-static void
-intel_i915_fence_reference( struct i915_winsys *sws,
- struct pipe_fence **dst_fence,
- struct pipe_fence *src_fence )
-{
- struct _DriFenceObject **dri_dst_fence = (struct _DriFenceObject **)dst_fence;
- struct _DriFenceObject *dri_src_fence = (struct _DriFenceObject *)src_fence;
-
- if(dri_src_fence)
- driFenceReference(dri_src_fence);
-
- if(*dri_dst_fence)
- driFenceUnReference(*dri_dst_fence);
-
- *dri_dst_fence = dri_src_fence;
+ intel_batchbuffer_flush( intel->batch );
+// if (0) intel_i915_batch_wait_idle( sws );
}
-static int
-intel_i915_fence_is_signalled( struct i915_winsys *sws,
- struct pipe_fence *fence )
+static void intel_i915_batch_finish( struct i915_winsys *sws )
{
- struct _DriFenceObject *dri_fence = dri_fo(fence);
- if (fence)
- return driFenceSignaled(dri_fence,
- DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW);
- return 1;
-}
-
-
-static int
-intel_i915_fence_wait( struct i915_winsys *sws,
- struct pipe_fence *fence )
-{
- struct _DriFenceObject *dri_fence = dri_fo(fence);
- if (fence)
- driFenceFinish(dri_fence,
- DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW,
- GL_FALSE);
- return 1;
+ struct intel_context *intel = intel_i915_winsys(sws)->intel;
+ intel_batchbuffer_finish( intel->batch );
}
@@ -186,10 +143,7 @@ intel_create_i915simple( struct intel_context *intel,
iws->winsys.batch_dword = intel_i915_batch_dword;
iws->winsys.batch_reloc = intel_i915_batch_reloc;
iws->winsys.batch_flush = intel_i915_batch_flush;
- iws->winsys.fence_reference = intel_i915_fence_reference;
- iws->winsys.fence_is_signalled = intel_i915_fence_is_signalled;
- iws->winsys.fence_wait = intel_i915_fence_wait;
-
+ iws->winsys.batch_finish = intel_i915_batch_finish;
iws->intel = intel;
/* Create the i915simple context:
diff --git a/src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c b/src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c
index ae02f98a78..1799e9b901 100644
--- a/src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c
+++ b/src/mesa/drivers/dri/intel_winsys/intel_winsys_pipe.c
@@ -135,13 +135,12 @@ static void intel_buffer_get_subdata(struct pipe_winsys *winsys,
* for all buffers.
*/
static struct pipe_buffer_handle *
-intel_buffer_create(struct pipe_winsys *winsys,
- unsigned alignment)
+intel_buffer_create(struct pipe_winsys *winsys, unsigned flags)
{
struct _DriBufferObject *buffer;
struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys);
driGenBuffers( iws->regionPool,
- "pipe buffer", 1, &buffer, alignment, 0, 0 );
+ "pipe buffer", 1, &buffer, 64, 0, 0 );
return pipe_bo(buffer);
}
@@ -173,14 +172,10 @@ intel_flush_frontbuffer( struct pipe_winsys *winsys,
}
-static struct pipe_region *
-intel_i915_region_alloc(struct pipe_winsys *winsys,
- unsigned cpp, unsigned width,
- unsigned height, unsigned flags)
+static unsigned
+intel_i915_surface_pitch(struct pipe_winsys *winsys,
+ unsigned cpp, unsigned width, unsigned flags)
{
- struct pipe_region *region = calloc(sizeof(*region), 1);
- const unsigned alignment = 64;
-
/* Choose a pitch to match hardware requirements - requires 64 byte
* alignment of render targets.
*
@@ -188,52 +183,17 @@ intel_i915_region_alloc(struct pipe_winsys *winsys,
* clearly want to be able to render to textures under some
* circumstances, but maybe not always a requirement.
*/
- unsigned pitch;
/* XXX is the pitch different for textures vs. drawables? */
if (flags & PIPE_SURFACE_FLAG_TEXTURE) /* or PIPE_SURFACE_FLAG_RENDER? */
- pitch = ((cpp * width + 63) & ~63) / cpp;
+ return ((cpp * width + 63) & ~63) / cpp;
else
- pitch = ((cpp * width + 63) & ~63) / cpp;
-
- region->cpp = cpp;
- region->pitch = pitch;
- region->height = height; /* needed? */
- region->refcount = 1;
-
- region->buffer = winsys->buffer_create( winsys, alignment );
-
- winsys->buffer_data( winsys,
- region->buffer,
- pitch * cpp * height,
- NULL,
- PIPE_BUFFER_USAGE_PIXEL );
-
- return region;
-}
-
-static void
-intel_i915_region_release(struct pipe_winsys *winsys,
- struct pipe_region **region)
-{
- if (!*region)
- return;
-
- assert((*region)->refcount > 0);
- (*region)->refcount--;
-
- if ((*region)->refcount == 0) {
- assert((*region)->map_refcount == 0);
-
- winsys->buffer_reference( winsys, &((*region)->buffer), NULL );
- free(*region);
- }
- *region = NULL;
+ return ((cpp * width + 63) & ~63) / cpp;
}
static struct pipe_surface *
-intel_i915_surface_alloc(struct pipe_winsys *winsys, unsigned format)
+intel_i915_surface_alloc(struct pipe_winsys *winsys, enum pipe_format format)
{
struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface);
if (surf) {
@@ -251,8 +211,8 @@ intel_i915_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
struct pipe_surface *surf = *s;
surf->refcount--;
if (surf->refcount == 0) {
- if (surf->region)
- winsys->region_release(winsys, &surf->region);
+ if (surf->buffer)
+ winsys->buffer_reference(winsys, &surf->buffer, NULL);
free(surf);
}
*s = NULL;
@@ -299,8 +259,7 @@ intel_create_pipe_winsys( int fd )
iws->winsys.flush_frontbuffer = intel_flush_frontbuffer;
iws->winsys.printf = intel_printf;
iws->winsys.get_name = intel_get_name;
- iws->winsys.region_alloc = intel_i915_region_alloc;
- iws->winsys.region_release = intel_i915_region_release;
+ iws->winsys.surface_pitch = intel_i915_surface_pitch;
iws->winsys.surface_alloc = intel_i915_surface_alloc;
iws->winsys.surface_release = intel_i915_surface_release;
diff --git a/src/mesa/drivers/dri/intel_winsys/intel_winsys_softpipe.c b/src/mesa/drivers/dri/intel_winsys/intel_winsys_softpipe.c
index 7a93546bc2..f9ed6253f1 100644
--- a/src/mesa/drivers/dri/intel_winsys/intel_winsys_softpipe.c
+++ b/src/mesa/drivers/dri/intel_winsys/intel_winsys_softpipe.c
@@ -48,9 +48,9 @@ static boolean
intel_is_format_supported(struct softpipe_winsys *sws, uint format)
{
switch(format) {
- case PIPE_FORMAT_U_A8_R8_G8_B8:
- case PIPE_FORMAT_U_R5_G6_B5:
- case PIPE_FORMAT_S8_Z24:
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
return TRUE;
default:
return FALSE;
diff --git a/src/mesa/drivers/dri/nouveau_winsys/Makefile b/src/mesa/drivers/dri/nouveau_winsys/Makefile
index 97b861526f..fe9a9668b1 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/Makefile
+++ b/src/mesa/drivers/dri/nouveau_winsys/Makefile
@@ -8,7 +8,8 @@ MINIGLX_SOURCES =
PIPE_DRIVERS = \
$(TOP)/src/mesa/pipe/softpipe/libsoftpipe.a \
- $(TOP)/src/mesa/pipe/nv40/libnv40.a
+ $(TOP)/src/mesa/pipe/nv40/libnv40.a \
+ $(TOP)/src/mesa/pipe/nv50/libnv50.a
DRIVER_SOURCES = \
nouveau_bo.c \
@@ -16,16 +17,18 @@ DRIVER_SOURCES = \
nouveau_context.c \
nouveau_device.c \
nouveau_dma.c \
+ nouveau_fence.c \
nouveau_grobj.c \
nouveau_lock.c \
nouveau_notifier.c \
+ nouveau_pushbuf.c \
nouveau_screen.c \
nouveau_swapbuffers.c \
nouveau_winsys.c \
nouveau_winsys_pipe.c \
nouveau_winsys_softpipe.c \
- nv04_region.c \
- nv50_region.c
+ nv04_surface.c \
+ nv50_surface.c
C_SOURCES = \
$(COMMON_SOURCES) \
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c
index 3b508cf92b..d684ab4d7c 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c
@@ -31,45 +31,12 @@
int
nouveau_bo_init(struct nouveau_device *userdev)
{
- struct nouveau_device_priv *nv = nouveau_device(userdev);
- struct nouveau_channel *chan;
- int ret;
-
- if ((ret = nouveau_channel_alloc(userdev, 0x80000001, 0x80000002,
- &nv->bufmgr.channel)))
- return ret;
- chan = nv->bufmgr.channel;
-
- if ((ret = nouveau_notifier_alloc(nv->bufmgr.channel, 0x80000003, 1,
- &nv->bufmgr.notify)))
- return ret;
-
- if ((ret = nouveau_grobj_alloc(nv->bufmgr.channel, 0x80000004, 0x39,
- &nv->bufmgr.m2mf)))
- return ret;
-
- nouveau_notifier_reset(nv->bufmgr.notify, 0);
- BEGIN_RING_CH(chan, nv->bufmgr.m2mf, 0x180, 1);
- OUT_RING_CH (chan, nv->bufmgr.notify->handle);
- BEGIN_RING_CH(chan, nv->bufmgr.m2mf, 0x104, 1);
- OUT_RING_CH (chan, 0);
- BEGIN_RING_CH(chan, nv->bufmgr.m2mf, 0x100, 1);
- OUT_RING_CH (chan, 0);
- FIRE_RING_CH (chan);
- if ((ret = nouveau_notifier_wait_status(nv->bufmgr.notify, 0, 0, 2000)))
- return ret;
-
return 0;
}
void
nouveau_bo_takedown(struct nouveau_device *userdev)
{
- struct nouveau_device_priv *nv = nouveau_device(userdev);
-
- nouveau_notifier_free(&nv->bufmgr.notify);
- nouveau_grobj_free(&nv->bufmgr.m2mf);
- nouveau_channel_free(&nv->bufmgr.channel);
}
static int
@@ -238,6 +205,9 @@ nouveau_bo_del(struct nouveau_bo **userbo)
if (--bo->refcount)
return;
+ if (bo->fence)
+ nouveau_fence_wait(&bo->fence);
+
nouveau_bo_realloc_gpu(bo, 0, 0);
if (bo->sysmem && !bo->user)
free(bo->sysmem);
@@ -265,83 +235,48 @@ nouveau_bo_unmap(struct nouveau_bo *userbo)
userbo->map = NULL;
}
-void
-nouveau_bo_emit_reloc(struct nouveau_channel *userchan, void *ptr,
- struct nouveau_bo *userbo, uint32_t data, uint32_t flags,
- uint32_t vor, uint32_t tor)
-{
- struct nouveau_channel_priv *chan = nouveau_channel(userchan);
- struct nouveau_bo_priv *bo = nouveau_bo(userbo);
- struct nouveau_bo_reloc *r;
- int i, on_list = 0;
-
- for (i = 0; i < chan->nr_buffers; i++) {
- if (chan->buffers[i].bo == bo) {
- on_list = 1;
- break;
- }
- }
-
- if (i >= 128)
- return;
-
- if (on_list) {
- chan->buffers[i].flags &= (flags | NOUVEAU_BO_RDWR);
- chan->buffers[i].flags |= (flags & NOUVEAU_BO_RDWR);
- } else {
- chan->buffers[i].bo = bo;
- chan->buffers[i].flags = flags;
- chan->nr_buffers++;
- }
-
- if (chan->num_relocs >= chan->max_relocs)
- FIRE_RING_CH(userchan);
- r = &chan->relocs[chan->num_relocs++];
-
- r->ptr = ptr;
- r->bo = bo;
- r->data = data;
- r->flags = flags;
- r->vor = vor;
- r->tor = tor;
-}
-
static int
nouveau_bo_upload(struct nouveau_bo_priv *bo)
{
+ if (bo->fence)
+ nouveau_fence_wait(&bo->fence);
memcpy(bo->map, bo->sysmem, bo->drm.size);
return 0;
}
-void
-nouveau_bo_validate(struct nouveau_channel *userchan)
+int
+nouveau_bo_validate(struct nouveau_channel *chan, struct nouveau_bo *bo,
+ struct nouveau_fence *fence, uint32_t flags)
{
- struct nouveau_channel_priv *chan = nouveau_channel(userchan);
- int i;
+ struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
- for (i = 0; i < chan->nr_buffers; i++) {
- struct nouveau_bo_priv *bo = chan->buffers[i].bo;
+ if (!nvbo->drm.size) {
+ nouveau_bo_realloc_gpu(nvbo, flags, nvbo->base.size);
+ nouveau_bo_upload(nvbo);
+ } else
+ if (nvbo->user) {
+ nouveau_bo_upload(nvbo);
+ } else
+ if (nvbo->base.map) {
+ nouveau_bo_upload(nvbo);
+ nvbo->sync_hack = 1;
+ }
- if (!bo->drm.size) {
- nouveau_bo_realloc_gpu(bo, chan->buffers[i].flags,
- bo->base.size);
- nouveau_bo_upload(bo);
- } else
- if (bo->user || bo->base.map)
- nouveau_bo_upload(bo);
+ if (!nvbo->user && !nvbo->base.map) {
+ free(nvbo->sysmem);
+ nvbo->sysmem = NULL;
+ }
- if (!bo->user && !bo->base.map) {
- free(bo->sysmem);
- bo->sysmem = NULL;
- }
+ if (nvbo->fence)
+ nouveau_fence_del(&nvbo->fence);
+ nouveau_fence_ref(fence, &nvbo->fence);
+ nvbo->base.offset = nvbo->drm.offset;
+ if (nvbo->drm.flags & NOUVEAU_MEM_AGP)
+ nvbo->base.flags = NOUVEAU_BO_GART;
+ else
+ nvbo->base.flags = NOUVEAU_BO_VRAM;
- bo->base.offset = bo->drm.offset;
- if (bo->drm.flags & NOUVEAU_MEM_AGP)
- bo->base.flags = NOUVEAU_BO_GART;
- else
- bo->base.flags = NOUVEAU_BO_VRAM;
- }
- chan->nr_buffers = 0;
+ return 0;
}
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c
index ef41020b72..c4558e5573 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_channel.c
@@ -85,12 +85,8 @@ nouveau_channel_alloc(struct nouveau_device *userdev, uint32_t fb_ctxdma,
return ret;
}
- chan->max_relocs = chan->drm.cmdbuf_size / 4;
- chan->num_relocs = 0;
- chan->relocs =
- malloc(sizeof(struct nouveau_bo_reloc) * chan->max_relocs);
-
nouveau_dma_channel_init(&chan->base);
+ nouveau_pushbuf_init(&chan->base);
*userchan = &chan->base;
return 0;
@@ -114,9 +110,6 @@ nouveau_channel_free(struct nouveau_channel **userchan)
FIRE_RING_CH(&chan->base);
- if (chan->relocs)
- free(chan->relocs);
-
nouveau_grobj_free(&chan->base.vram);
nouveau_grobj_free(&chan->base.gart);
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.c
index 67df43647a..03f1816c32 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.c
@@ -1,18 +1,8 @@
-#include "glheader.h"
-#include "context.h"
-#include "extensions.h"
-
-#include "tnl/tnl.h"
-#include "tnl/t_pipeline.h"
-#include "tnl/t_vertex.h"
-
-#include "drivers/common/driverfuncs.h"
-
-#include "drirenderbuffer.h"
+#include "main/glheader.h"
+#include "glapi/glthread.h"
+#include <GL/internal/glcore.h>
#include "state_tracker/st_public.h"
-#include "state_tracker/st_context.h"
-
#include "pipe/p_defines.h"
#include "pipe/p_context.h"
@@ -125,6 +115,36 @@ nouveau_context_create(const __GLcontextModes *glVis,
debug_control);
#endif
+ /*XXX: Hack up a fake region and buffer object for front buffer.
+ * This will go away with TTM, replaced with a simple reference
+ * of the front buffer handle passed to us by the DDX.
+ */
+ {
+ struct pipe_surface *fb_surf;
+ struct nouveau_bo_priv *fb_bo;
+
+ fb_bo = calloc(1, sizeof(struct nouveau_bo_priv));
+ fb_bo->drm.offset = nv_screen->front_offset;
+ fb_bo->drm.flags = NOUVEAU_MEM_FB;
+ fb_bo->drm.size = nv_screen->front_pitch *
+ nv_screen->front_height;
+ fb_bo->refcount = 1;
+ fb_bo->base.flags = NOUVEAU_BO_PIN | NOUVEAU_BO_VRAM;
+ fb_bo->base.offset = fb_bo->drm.offset;
+ fb_bo->base.handle = (unsigned long)fb_bo;
+ fb_bo->base.size = fb_bo->drm.size;
+ fb_bo->base.device = nv_screen->device;
+
+ fb_surf = calloc(1, sizeof(struct pipe_surface));
+ fb_surf->cpp = nv_screen->front_cpp;
+ fb_surf->pitch = nv_screen->front_pitch / fb_surf->cpp;
+ fb_surf->height = nv_screen->front_height;
+ fb_surf->refcount = 1;
+ fb_surf->buffer = (void *)fb_bo;
+
+ nv->frontbuffer = fb_surf;
+ }
+
if ((ret = nouveau_grobj_alloc(nv->channel, 0x00000000, 0x30,
&nv->NvNull))) {
NOUVEAU_ERR("Error creating NULL object: %d\n", ret);
@@ -139,9 +159,9 @@ nouveau_context_create(const __GLcontextModes *glVis,
}
if (nv->chipset < 0x50)
- ret = nouveau_region_init_nv04(nv);
+ ret = nouveau_surface_init_nv04(nv);
else
- ret = nouveau_region_init_nv50(nv);
+ ret = nouveau_surface_init_nv50(nv);
if (ret) {
return GL_FALSE;
}
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h
index f2557af935..cd59b7cc43 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_context.h
@@ -1,9 +1,6 @@
#ifndef __NOUVEAU_CONTEXT_H__
#define __NOUVEAU_CONTEXT_H__
-#include "glheader.h"
-#include "context.h"
-
#include "dri_util.h"
#include "xmlconfig.h"
@@ -31,6 +28,7 @@ struct nouveau_context {
drmLock drm_lock;
GLboolean locked;
struct nouveau_screen *nv_screen;
+ struct pipe_surface *frontbuffer;
/* Bufmgr */
struct {
@@ -46,6 +44,7 @@ struct nouveau_context {
struct nouveau_bo *reloc_head;
/* Hardware context */
+ uint32_t *pushbuf;
struct nouveau_channel *channel;
struct nouveau_notifier *sync_notifier;
struct nouveau_grobj *NvNull;
@@ -53,28 +52,26 @@ struct nouveau_context {
struct nouveau_grobj *NvImageBlit;
struct nouveau_grobj *NvGdiRect;
struct nouveau_grobj *NvM2MF;
+ struct nouveau_grobj *Nv2D;
uint32_t next_handle;
uint32_t next_sequence;
- /* pipe_region accel */
- int (*region_display)(void);
- int (*region_copy)(struct nouveau_context *, struct pipe_region *,
- unsigned, unsigned, unsigned, struct pipe_region *,
- unsigned, unsigned, unsigned, unsigned, unsigned);
- int (*region_fill)(struct nouveau_context *, struct pipe_region *,
- unsigned, unsigned, unsigned, unsigned, unsigned,
- unsigned);
- int (*region_data)(struct nouveau_context *, struct pipe_region *,
- unsigned, unsigned, unsigned, const void *,
- unsigned, unsigned, unsigned, unsigned, unsigned);
+ /* pipe_surface accel */
+ struct pipe_surface *surf_src, *surf_dst;
+ unsigned surf_src_offset, surf_dst_offset;
+ int (*surface_copy_prep)(struct nouveau_context *,
+ struct pipe_surface *dst,
+ struct pipe_surface *src);
+ void (*surface_copy)(struct nouveau_context *, unsigned dx, unsigned dy,
+ unsigned sx, unsigned sy, unsigned w, unsigned h);
+ void (*surface_copy_done)(struct nouveau_context *);
+ int (*surface_fill)(struct nouveau_context *, struct pipe_surface *,
+ unsigned, unsigned, unsigned, unsigned, unsigned);
+ int (*surface_data)(struct nouveau_context *, struct pipe_surface *,
+ unsigned, unsigned, const void *, unsigned,
+ unsigned, unsigned, unsigned, unsigned);
};
-static INLINE struct nouveau_context *
-nouveau_context(GLcontext *ctx)
-{
- return (struct nouveau_context *)ctx;
-}
-
extern GLboolean nouveau_context_create(const __GLcontextModes *,
__DRIcontextPrivate *, void *);
extern void nouveau_context_destroy(__DRIcontextPrivate *);
@@ -99,7 +96,10 @@ extern int __nouveau_debug;
extern void LOCK_HARDWARE(struct nouveau_context *);
extern void UNLOCK_HARDWARE(struct nouveau_context *);
-extern int nouveau_region_init_nv04(struct nouveau_context *);
-extern int nouveau_region_init_nv50(struct nouveau_context *);
+extern int nouveau_surface_init_nv04(struct nouveau_context *);
+extern int nouveau_surface_init_nv50(struct nouveau_context *);
+
+extern uint32_t *nouveau_pipe_dma_beginp(struct nouveau_grobj *, int, int);
+extern void nouveau_pipe_dma_kickoff(struct nouveau_channel *);
#endif
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c
index d323995903..6ec390ec76 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_dma.c
@@ -142,35 +142,6 @@ nouveau_dma_kickoff(struct nouveau_channel *userchan)
if (chan->dma.cur == chan->dma.put)
return;
- if (chan->num_relocs) {
- nouveau_bo_validate(userchan);
-
- for (i = 0; i < chan->num_relocs; i++) {
- struct nouveau_bo_reloc *r = &chan->relocs[i];
- uint32_t push;
-
- if (r->flags & NOUVEAU_BO_LOW) {
- push = r->bo->base.offset + r->data;
- } else
- if (r->flags & NOUVEAU_BO_HIGH) {
- push = (r->bo->base.offset + r->data) >> 32;
- } else {
- push = r->data;
- }
-
- if (r->flags & NOUVEAU_BO_OR) {
- if (r->bo->base.flags & NOUVEAU_BO_VRAM)
- push |= r->vor;
- else
- push |= r->tor;
- }
-
- *r->ptr = push;
- }
-
- chan->num_relocs = 0;
- }
-
#ifdef NOUVEAU_DMA_DEBUG
if (chan->dma.push_free) {
NOUVEAU_ERR("Packet incomplete: %d left\n", chan->dma.push_free);
@@ -179,8 +150,19 @@ nouveau_dma_kickoff(struct nouveau_channel *userchan)
#endif
#ifdef NOUVEAU_DMA_DUMP_POSTRELOC_PUSHBUF
- for (i = chan->dma.put; i < chan->dma.cur; i++)
- NOUVEAU_MSG("0x%08x\n", chan->pushbuf[i]);
+ for (i = chan->dma.put; i < chan->dma.cur; i++) {
+ NOUVEAU_MSG("0x%08x 0x%08x\n", (i<<2)+chan->dma.base,
+ chan->pushbuf[i]);
+ if ((chan->pushbuf[i] & 0xf0000000) == 0x20000000) {
+ int n = (((chan->pushbuf[i] & 0x0fffffff) -
+ chan->dma.base) / 4);
+ do {
+ NOUVEAU_MSG("\t0x%08x 0x%08x\n",
+ (n<<2)+chan->dma.base,
+ chan->pushbuf[n]);
+ } while ((chan->pushbuf[n++]&0xf0000000) != 0x20000000);
+ }
+ }
#endif
put_offset = (chan->dma.cur << 2) + chan->dma.base;
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h
index 1a21da6985..f176767f13 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h
@@ -32,6 +32,7 @@
#include "pipe/nouveau/nouveau_grobj.h"
#include "pipe/nouveau/nouveau_notifier.h"
#include "pipe/nouveau/nouveau_bo.h"
+#include "pipe/nouveau/nouveau_resource.h"
struct nouveau_device_priv {
struct nouveau_device base;
@@ -40,12 +41,6 @@ struct nouveau_device_priv {
drm_context_t ctx;
drmLock *lock;
int needs_close;
-
- struct {
- struct nouveau_channel *channel;
- struct nouveau_notifier *notify;
- struct nouveau_grobj *m2mf;
- } bufmgr;
};
#define nouveau_device(n) ((struct nouveau_device_priv *)(n))
@@ -65,6 +60,93 @@ nouveau_device_get_param(struct nouveau_device *, uint64_t param, uint64_t *v);
extern int
nouveau_device_set_param(struct nouveau_device *, uint64_t param, uint64_t val);
+struct nouveau_fence {
+ struct nouveau_channel *channel;
+};
+
+struct nouveau_fence_priv {
+ struct nouveau_fence base;
+ int refcount;
+
+ struct nouveau_fence *next;
+
+ uint32_t sequence;
+ int emitted;
+ int signalled;
+};
+#define nouveau_fence(n) ((struct nouveau_fence_priv *)(n))
+
+extern int
+nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **);
+
+extern int
+nouveau_fence_ref(struct nouveau_fence *, struct nouveau_fence **);
+
+extern void
+nouveau_fence_del(struct nouveau_fence **);
+
+extern void
+nouveau_fence_emit(struct nouveau_fence *);
+
+extern int
+nouveau_fence_wait(struct nouveau_fence **);
+
+extern void
+nouveau_fence_flush(struct nouveau_channel *);
+
+struct nouveau_pushbuf_reloc {
+ uint64_t next;
+ uint64_t handle;
+ uint32_t *ptr;
+ uint32_t flags;
+ uint32_t data;
+ uint32_t vor;
+ uint32_t tor;
+};
+
+struct nouveau_pushbuf_bo {
+ uint64_t next;
+ uint64_t handle;
+ uint64_t flags;
+ uint64_t relocs;
+ int nr_relocs;
+};
+
+struct nouveau_pushbuf {
+ struct nouveau_channel *channel;
+ unsigned remaining;
+ uint32_t *cur;
+};
+
+struct nouveau_pushbuf_priv {
+ struct nouveau_pushbuf base;
+ struct nouveau_pushbuf *next;
+
+ struct nouveau_resource *res;
+ struct nouveau_fence *fence;
+
+ uint64_t buffers;
+ int nr_buffers;
+};
+#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n))
+#define pbbo_to_ptr(o) ((uint64_t)(unsigned long)(o))
+#define ptr_to_pbbo(h) ((struct nouveau_pushbuf_bo *)(unsigned long)(h))
+#define pbrel_to_ptr(o) ((uint64_t)(unsigned long)(o))
+#define ptr_to_pbrel(h) ((struct nouveau_pushbuf_reloc *)(unsigned long)(h))
+#define bo_to_ptr(o) ((uint64_t)(unsigned long)(o))
+#define ptr_to_bo(h) ((struct nouveau_bo_priv *)(unsigned long)(h))
+
+extern int
+nouveau_pushbuf_init(struct nouveau_channel *);
+
+extern int
+nouveau_pushbuf_flush(struct nouveau_channel *);
+
+extern int
+nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
+ struct nouveau_bo *, uint32_t data, uint32_t flags,
+ uint32_t vor, uint32_t tor);
+
struct nouveau_channel_priv {
struct nouveau_channel base;
@@ -92,15 +174,13 @@ struct nouveau_channel_priv {
int push_free;
} dma;
- struct {
- struct nouveau_bo_priv *bo;
- uint32_t flags;
- } buffers[128];
- int nr_buffers;
+ struct nouveau_fence *fence_head;
+ struct nouveau_fence *fence_tail;
+ uint32_t fence_sequence;
- struct nouveau_bo_reloc *relocs;
- int num_relocs;
- int max_relocs;
+ struct nouveau_resource *pb_heap;
+ struct nouveau_pushbuf *pb_head;
+ struct nouveau_pushbuf *pb_tail;
};
#define nouveau_channel(n) ((struct nouveau_channel_priv *)(n))
@@ -154,6 +234,8 @@ nouveau_notifier_wait_status(struct nouveau_notifier *, int id, int status,
struct nouveau_bo_priv {
struct nouveau_bo base;
+ struct nouveau_fence *fence;
+
struct drm_nouveau_mem_alloc drm;
void *map;
@@ -161,15 +243,8 @@ struct nouveau_bo_priv {
int user;
int refcount;
+ int sync_hack;
};
-
-struct nouveau_bo_reloc {
- struct nouveau_bo_priv *bo;
- uint32_t *ptr;
- uint32_t flags;
- uint32_t data, vor, tor;
-};
-
#define nouveau_bo(n) ((struct nouveau_bo_priv *)(n))
extern int
@@ -201,12 +276,18 @@ nouveau_bo_map(struct nouveau_bo *, uint32_t flags);
extern void
nouveau_bo_unmap(struct nouveau_bo *);
-extern void
-nouveau_bo_emit_reloc(struct nouveau_channel *chan, void *ptr,
- struct nouveau_bo *, uint32_t data, uint32_t flags,
- uint32_t vor, uint32_t tor);
+extern int
+nouveau_bo_validate(struct nouveau_channel *, struct nouveau_bo *,
+ struct nouveau_fence *fence, uint32_t flags);
+
+extern int
+nouveau_resource_init(struct nouveau_resource **heap, int size);
+
+extern int
+nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv,
+ struct nouveau_resource **);
extern void
-nouveau_bo_validate(struct nouveau_channel *);
+nouveau_resource_free(struct nouveau_resource **);
#endif
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c
new file mode 100644
index 0000000000..842b38f913
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_fence.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS 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 <stdlib.h>
+#include <errno.h>
+
+#include "nouveau_drmif.h"
+#include "nouveau_dma.h"
+#include "nouveau_local.h"
+
+int
+nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **fence)
+{
+ struct nouveau_fence_priv *nvfence;
+
+ if (!chan || !fence || *fence)
+ return -EINVAL;
+
+ nvfence = calloc(1, sizeof(struct nouveau_fence_priv));
+ if (!nvfence)
+ return -ENOMEM;
+ nvfence->base.channel = chan;
+ nvfence->refcount = 1;
+
+ *fence = &nvfence->base;
+ return 0;
+}
+
+int
+nouveau_fence_ref(struct nouveau_fence *ref, struct nouveau_fence **fence)
+{
+ struct nouveau_fence_priv *nvfence;
+
+ if (!ref || !fence || *fence)
+ return -EINVAL;
+ nvfence = nouveau_fence(ref);
+ nvfence->refcount++;
+
+ *fence = &nvfence->base;
+ return 0;
+}
+
+void
+nouveau_fence_del(struct nouveau_fence **fence)
+{
+ struct nouveau_fence_priv *nvfence;
+
+ if (!fence || !*fence)
+ return;
+ nvfence = nouveau_fence(*fence);
+ *fence = NULL;
+
+ if (--nvfence->refcount <= 0) {
+ if (nvfence->emitted && !nvfence->signalled)
+ nouveau_fence_wait((void *)&nvfence);
+ free(nvfence);
+ }
+}
+
+void
+nouveau_fence_emit(struct nouveau_fence *fence)
+{
+ struct nouveau_channel_priv *nvchan = nouveau_channel(fence->channel);
+ struct nouveau_fence_priv *nvfence = nouveau_fence(fence);
+
+ nvfence->emitted = 1;
+ nvfence->sequence = ++nvchan->fence_sequence;
+ if (nvfence->sequence == 0xffffffff)
+ NOUVEAU_ERR("AII wrap unhandled\n");
+
+ BEGIN_RING_CH(&nvchan->base, nvchan->subchannel[0].grobj, 0x50, 1);
+ OUT_RING_CH (&nvchan->base, nvfence->sequence);
+
+ if (nvchan->fence_tail) {
+ nouveau_fence(nvchan->fence_tail)->next = fence;
+ } else {
+ nvchan->fence_head = fence;
+ }
+ nvchan->fence_tail = fence;
+}
+
+void
+nouveau_fence_flush(struct nouveau_channel *chan)
+{
+ struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+ struct nouveau_fence_priv *nvfence = nouveau_fence(nvchan->fence_head);
+ uint32_t sequence = *nvchan->ref_cnt;
+
+ while (nvchan->fence_head && nvfence->sequence <= sequence) {
+ nvfence->signalled = 1;
+
+ nvchan->fence_head = nvfence->next;
+ if (nvchan->fence_head == NULL)
+ nvchan->fence_tail = NULL;
+ nvfence = nouveau_fence(nvchan->fence_head);
+ }
+}
+
+int
+nouveau_fence_wait(struct nouveau_fence **fence)
+{
+ struct nouveau_fence_priv *nvfence;
+
+ if (!fence || !*fence)
+ return -EINVAL;
+ nvfence = nouveau_fence(*fence);
+
+ if (nvfence->emitted) {
+ while (!nvfence->signalled)
+ nouveau_fence_flush(nvfence->base.channel);
+ }
+ nouveau_fence_del(fence);
+
+ return 0;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h
index 4ada5d014b..1978edea02 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_local.h
@@ -26,15 +26,16 @@
/* Push buffer access macros */
#define BEGIN_RING(obj,mthd,size) do { \
- BEGIN_RING_CH(nv->channel, nv->obj, (mthd), (size)); \
+ nv->pushbuf = nouveau_pipe_dma_beginp(nv->obj, (mthd), (size)); \
} while(0)
#define OUT_RING(data) do { \
- OUT_RING_CH(nv->channel, (data)); \
+ (*nv->pushbuf++) = (data); \
} while(0)
#define OUT_RINGp(src,size) do { \
- OUT_RINGp_CH(nv->channel, (src), (size)); \
+ memcpy(nv->pushbuf, (src), (size)<<2); \
+ nv->pushbuf += (size); \
} while(0)
#define OUT_RINGf(data) do { \
@@ -43,18 +44,13 @@
OUT_RING(c.u); \
} while(0)
-#define WAIT_RING(size) do { \
- WAIT_RING_CH(nv->channel, (size)); \
-} while(0)
-
#define FIRE_RING() do { \
- FIRE_RING_CH(nv->channel); \
+ nouveau_pipe_dma_kickoff(nv->channel); \
} while(0)
#define OUT_RELOC(bo,data,flags,vor,tor) do { \
- struct nouveau_channel_priv *chan = nouveau_channel(nv->channel); \
- nouveau_bo_emit_reloc(nv->channel, &chan->pushbuf[chan->dma.cur], \
- (void*)(bo), (data), (flags), (vor), (tor)); \
+ nouveau_pushbuf_emit_reloc(nv->channel, nv->pushbuf, (void*)(bo), \
+ (data), (flags), (vor), (tor)); \
OUT_RING(0); \
} while(0)
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_lock.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_lock.c
index ffe7d01d66..9adb9ac854 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_lock.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_lock.c
@@ -25,18 +25,9 @@
*
**************************************************************************/
-
-#include "glheader.h"
-#include "context.h"
-#include "extensions.h"
-
-#include "state_tracker/st_public.h"
-#include "state_tracker/st_context.h"
-
-#include "drirenderbuffer.h"
-#include "vblank.h"
-#include "utils.h"
-#include "xmlpool.h" /* for symbolic values of enum-type options */
+#include "main/glheader.h"
+#include "glapi/glthread.h"
+#include <GL/internal/glcore.h>
#include "nouveau_context.h"
#include "nouveau_screen.h"
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c
new file mode 100644
index 0000000000..6cb06f8c37
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_pushbuf.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2007 Nouveau Project
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS 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 <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+#include "nouveau_drmif.h"
+#include "nouveau_dma.h"
+
+int
+nouveau_pushbuf_init(struct nouveau_channel *chan)
+{
+ struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+
+ if (!nvchan)
+ return -EINVAL;
+
+ /* Everything except first 4KiB of the push buffer is managed by us */
+ if (nouveau_resource_init(&nvchan->pb_heap,
+ nvchan->drm.cmdbuf_size - 4096))
+ return -EINVAL;
+
+ /* Shrink master ring to 4KiB */
+ assert(nvchan->dma.cur <= (4096/4));
+ nvchan->dma.max = (4096 / 4) - 2;
+ nvchan->dma.free = nvchan->dma.max - nvchan->dma.cur;
+
+ return 0;
+}
+
+/* This would be our TTM "superioctl" */
+int
+nouveau_pushbuf_flush(struct nouveau_channel *chan)
+{
+ struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+ struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(nvchan->pb_tail);
+ struct nouveau_pushbuf_bo *pbbo;
+ struct nouveau_fence *fence = NULL;
+ int sync_hack = 0;
+ int ret;
+
+ if (!nvpb)
+ goto out_realloc;
+
+ if (nvpb->base.remaining == nvpb->res->size / 4)
+ return 0;
+
+ ret = nouveau_fence_new(chan, &fence);
+ if (ret)
+ return ret;
+
+ /* Validate buffers + apply relocations */
+ while ((pbbo = ptr_to_pbbo(nvpb->buffers))) {
+ struct nouveau_pushbuf_reloc *r;
+ struct nouveau_bo *bo = &ptr_to_bo(pbbo->handle)->base;
+
+ ret = nouveau_bo_validate(chan, bo, fence, pbbo->flags);
+ assert (ret == 0);
+
+ sync_hack |= nouveau_bo(bo)->sync_hack;
+ nouveau_bo(bo)->sync_hack = 0;
+
+ while ((r = ptr_to_pbrel(pbbo->relocs))) {
+ uint32_t push;
+
+ if (r->flags & NOUVEAU_BO_LOW) {
+ push = bo->offset + r->data;
+ } else
+ if (r->flags & NOUVEAU_BO_HIGH) {
+ push = (bo->offset + r->data) >> 32;
+ } else {
+ push = r->data;
+ }
+
+ if (r->flags & NOUVEAU_BO_OR) {
+ if (bo->flags & NOUVEAU_BO_VRAM)
+ push |= r->vor;
+ else
+ push |= r->tor;
+ }
+
+ *r->ptr = push;
+ pbbo->relocs = r->next;
+ free(r);
+ }
+
+ nvpb->buffers = pbbo->next;
+ free(pbbo);
+ }
+ nvpb->nr_buffers = 0;
+
+ /* Emit JMP to indirect pushbuf */
+ if (nvchan->dma.free < 1)
+ WAIT_RING_CH(chan, 1);
+ nvchan->dma.free -= 1;
+#ifdef NOUVEAU_DMA_DEBUG
+ nvchan->dma.push_free = 1;
+#endif
+ OUT_RING_CH(chan, 0x20000000 | (nvpb->res->start + 4096));
+
+ /* Add JMP back to master pushbuf from indirect pushbuf */
+ (*nvpb->base.cur++) =
+ 0x20000000 | ((nvchan->dma.cur << 2) + nvchan->dma.base);
+
+ /* Fence */
+ nvpb->fence = fence;
+ nouveau_fence_emit(nvpb->fence);
+
+ /* Kickoff */
+ FIRE_RING_CH(chan);
+
+ /* Allocate space for next push buffer */
+out_realloc:
+ nvpb = calloc(1, sizeof(struct nouveau_pushbuf_priv));
+ if (!nvpb)
+ return -ENOMEM;
+
+ if (nouveau_resource_alloc(nvchan->pb_heap, 0x2000, NULL, &nvpb->res)) {
+ struct nouveau_pushbuf_priv *e;
+ int nr = 0;
+
+ /* Update fences */
+ nouveau_fence_flush(chan);
+
+ /* Free any push buffers that have already been executed */
+ e = nouveau_pushbuf(nvchan->pb_head);
+ while (e && e->fence) {
+ if (!e->fence || !nouveau_fence(e->fence)->signalled)
+ break;
+ nouveau_fence_del(&e->fence);
+ nouveau_resource_free(&e->res);
+ nr++;
+
+ nvchan->pb_head = e->next;
+ if (nvchan->pb_head == NULL)
+ nvchan->pb_tail = NULL;
+ free(e);
+ e = nouveau_pushbuf(nvchan->pb_head);
+ }
+
+ /* We didn't free any buffers above. As a last resort, busy
+ * wait on the oldest buffer becoming available.
+ */
+ if (!nr) {
+ e = nouveau_pushbuf(nvchan->pb_head);
+ nouveau_fence_wait(&e->fence);
+ nouveau_resource_free(&e->res);
+
+ nvchan->pb_head = e->next;
+ if (nvchan->pb_head == NULL)
+ nvchan->pb_tail = NULL;
+ free(e);
+ }
+
+ if (nouveau_resource_alloc(nvchan->pb_heap, 0x2000, nvpb,
+ &nvpb->res))
+ assert(0);
+ }
+
+ nvpb->base.channel = chan;
+ nvpb->base.remaining = nvpb->res->size / 4;
+ nvpb->base.cur = &nvchan->pushbuf[(nvpb->res->start + 4096)/4];
+
+ if (nvchan->pb_tail) {
+ nouveau_pushbuf(nvchan->pb_tail)->next = &nvpb->base;
+ } else {
+ nvchan->pb_head = &nvpb->base;
+ }
+ nvchan->pb_tail = &nvpb->base;
+
+ if (sync_hack) {
+ struct nouveau_fence *f = NULL;
+ nouveau_fence_ref(nvpb->fence, &f);
+ nouveau_fence_wait(&f);
+ }
+
+ return 0;
+}
+
+static struct nouveau_pushbuf_bo *
+nouveau_pushbuf_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
+{
+ struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
+ struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(nvchan->pb_tail);
+ struct nouveau_pushbuf_bo *pbbo = ptr_to_pbbo(nvpb->buffers);
+
+ while (pbbo) {
+ if (pbbo->handle == bo->handle)
+ return pbbo;
+ pbbo = ptr_to_pbbo(pbbo->next);
+ }
+
+ pbbo = malloc(sizeof(struct nouveau_pushbuf_bo));
+ pbbo->next = nvpb->buffers;
+ nvpb->buffers = pbbo_to_ptr(pbbo);
+ nvpb->nr_buffers++;
+
+ pbbo->handle = bo_to_ptr(bo);
+ pbbo->flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART;
+ pbbo->relocs = 0;
+ pbbo->nr_relocs = 0;
+ return pbbo;
+}
+
+int
+nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
+ struct nouveau_bo *bo, uint32_t data, uint32_t flags,
+ uint32_t vor, uint32_t tor)
+{
+ struct nouveau_pushbuf_bo *pbbo;
+ struct nouveau_pushbuf_reloc *r;
+
+ if (!chan)
+ return -EINVAL;
+
+ pbbo = nouveau_pushbuf_emit_buffer(chan, bo);
+ if (!pbbo)
+ return -EFAULT;
+
+ r = malloc(sizeof(struct nouveau_pushbuf_reloc));
+ r->next = pbbo->relocs;
+ pbbo->relocs = pbrel_to_ptr(r);
+ pbbo->nr_relocs++;
+
+ pbbo->flags |= (flags & NOUVEAU_BO_RDWR);
+ pbbo->flags &= (flags | NOUVEAU_BO_RDWR);
+
+ r->handle = bo_to_ptr(r);
+ r->ptr = ptr;
+ r->flags = flags;
+ r->data = data;
+ r->vor = vor;
+ r->tor = tor;
+
+ return 0;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.c
index 16c4324164..a1eed2e44a 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.c
@@ -1,9 +1,3 @@
-#include "glheader.h"
-#include "context.h"
-#include "framebuffer.h"
-#include "matrix.h"
-#include "renderbuffer.h"
-#include "simple_list.h"
#include "utils.h"
#include "vblank.h"
#include "xmlpool.h"
@@ -61,6 +55,8 @@ nouveau_screen_create(__DRIscreenPrivate *driScrnPriv)
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 GL_TRUE;
}
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.h
index e53cd873a7..019823bd44 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.h
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_screen.h
@@ -12,6 +12,8 @@ struct nouveau_screen {
uint32_t front_offset;
uint32_t front_pitch;
+ uint32_t front_cpp;
+ uint32_t front_height;
};
#endif
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_swapbuffers.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_swapbuffers.c
index 57598f9cab..91bf243f42 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_swapbuffers.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_swapbuffers.c
@@ -1,7 +1,10 @@
-#include "context.h"
+#include "main/glheader.h"
+#include "glapi/glthread.h"
+#include <GL/internal/glcore.h>
#include "pipe/p_context.h"
#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
#include "state_tracker/st_cb_fbo.h"
#include "nouveau_context.h"
@@ -14,8 +17,6 @@ nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
const drm_clip_rect_t *rect)
{
struct nouveau_context *nv = dPriv->driContextPriv->driverPrivate;
- struct nouveau_screen *nv_screen = nv->nv_screen;
- struct pipe_region *p_region = surf->region;
drm_clip_rect_t *pbox;
int nbox, i;
@@ -27,17 +28,7 @@ nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
pbox = dPriv->pClipRects;
nbox = dPriv->numClipRects;
- BEGIN_RING(NvCtxSurf2D, 0x184, 2);
- OUT_RELOCo(p_region->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
- OUT_RING (nv->channel->vram->handle);
-
- BEGIN_RING(NvCtxSurf2D, 0x300, 4);
- OUT_RING ((p_region->cpp == 4) ? 6 : 4);
- OUT_RING ((nv_screen->front_pitch << 16) |
- (p_region->pitch * p_region->cpp));
- OUT_RELOCl(p_region->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
- OUT_RING (nv_screen->front_offset);
-
+ nv->surface_copy_prep(nv, nv->frontbuffer, surf);
for (i = 0; i < nbox; i++, pbox++) {
int sx, sy, dx, dy, w, h;
@@ -48,10 +39,7 @@ nouveau_copy_buffer(__DRIdrawablePrivate *dPriv, struct pipe_surface *surf,
w = pbox->x2 - pbox->x1;
h = pbox->y2 - pbox->y1;
- BEGIN_RING(NvImageBlit, 0x300, 3);
- OUT_RING ((sy << 16) | sx);
- OUT_RING ((dy << 16) | dx);
- OUT_RING (( h << 16) | w);
+ nv->surface_copy(nv, dx, dy, sx, sy, w, h);
}
FIRE_RING();
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c
index bdc89b9531..9919272ebe 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys.c
@@ -1,9 +1,11 @@
+#include "pipe/p_util.h"
+
#include "nouveau_context.h"
#include "nouveau_winsys_pipe.h"
#include "pipe/nouveau/nouveau_winsys.h"
-static int
+int
nouveau_resource_init(struct nouveau_resource **heap, int size)
{
struct nouveau_resource *r;
@@ -18,7 +20,7 @@ nouveau_resource_init(struct nouveau_resource **heap, int size)
return 0;
}
-static int
+int
nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv,
struct nouveau_resource **res)
{
@@ -56,7 +58,7 @@ nouveau_resource_alloc(struct nouveau_resource *heap, int size, void *priv,
return 1;
}
-static void
+void
nouveau_resource_free(struct nouveau_resource **res)
{
struct nouveau_resource *r;
@@ -106,25 +108,68 @@ nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass,
grclass, grobj);
}
-static uint32_t *
+uint32_t *
nouveau_pipe_dma_beginp(struct nouveau_grobj *grobj, int mthd, int size)
{
- struct nouveau_channel_priv *chan = nouveau_channel(grobj->channel);
+ struct nouveau_channel_priv *nvchan = nouveau_channel(grobj->channel);
uint32_t *pushbuf;
- BEGIN_RING_CH(&chan->base, grobj, mthd, size);
- pushbuf = &chan->pushbuf[chan->dma.cur];
- chan->dma.cur += size;
-#ifdef NOUVEAU_DMA_DEBUG
- chan->dma.push_free -= size;
-#endif
+ if (!nvchan->pb_tail || nvchan->pb_tail->remaining < (size + 1))
+ nouveau_pushbuf_flush(grobj->channel);
+
+ if (grobj->bound == NOUVEAU_GROBJ_UNBOUND)
+ nouveau_dma_subc_bind(grobj);
+ nvchan->subchannel[grobj->subc].seq = nvchan->subc_sequence++;
+
+ pushbuf = nvchan->pb_tail->cur;
+ nvchan->pb_tail->cur += (size + 1);
+ nvchan->pb_tail->remaining -= (size + 1);
+
+ (*pushbuf++) = ((grobj->subc << 13) | (size << 18) | mthd);
return pushbuf;
}
-static void
-nouveau_pipe_dma_kickoff(struct nouveau_channel *userchan)
+void
+nouveau_pipe_dma_kickoff(struct nouveau_channel *chan)
+{
+ nouveau_pushbuf_flush(chan);
+}
+
+static int
+nouveau_pipe_surface_copy(struct nouveau_winsys *nvws, struct pipe_surface *dst,
+ unsigned dx, unsigned dy, struct pipe_surface *src,
+ unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+ struct nouveau_context *nv = nvws->nv;
+
+ if (nv->surface_copy_prep(nv, dst, src))
+ return 1;
+ nv->surface_copy(nv, dx, dy, sx, sy, w, h);
+ nv->surface_copy_done(nv);
+
+ return 0;
+}
+
+static int
+nouveau_pipe_surface_fill(struct nouveau_winsys *nvws, struct pipe_surface *dst,
+ unsigned dx, unsigned dy, unsigned w, unsigned h,
+ unsigned value)
+{
+ if (nvws->nv->surface_fill(nvws->nv, dst, dx, dy, w, h, value))
+ return 1;
+ return 0;
+}
+
+static int
+nouveau_pipe_surface_data(struct nouveau_winsys *nvws, struct pipe_surface *dst,
+ unsigned dx, unsigned dy, const void *src,
+ unsigned src_pitch, unsigned sx, unsigned sy,
+ unsigned w, unsigned h)
{
- FIRE_RING_CH(userchan);
+ if (nvws->nv->surface_data(nvws->nv, dst, dx, dy, src, src_pitch, sx,
+ sy, w, h))
+ return 1;
+ return 0;
}
struct pipe_context *
@@ -142,6 +187,10 @@ nouveau_pipe_create(struct nouveau_context *nv)
case 0x40:
hw_create = nv40_create;
break;
+ case 0x50:
+ case 0x80:
+ hw_create = nv50_create;
+ break;
default:
NOUVEAU_ERR("Unknown chipset NV%02x\n", (int)nv->chipset);
return NULL;
@@ -155,7 +204,7 @@ nouveau_pipe_create(struct nouveau_context *nv)
nvws->res_free = nouveau_resource_free;
nvws->begin_ring = nouveau_pipe_dma_beginp;
- nvws->out_reloc = nouveau_bo_emit_reloc;
+ nvws->out_reloc = nouveau_pushbuf_emit_reloc;
nvws->fire_ring = nouveau_pipe_dma_kickoff;
nvws->grobj_alloc = nouveau_pipe_grobj_alloc;
@@ -168,9 +217,9 @@ nouveau_pipe_create(struct nouveau_context *nv)
nvws->notifier_retval = nouveau_notifier_return_val;
nvws->notifier_wait = nouveau_notifier_wait_status;
- nvws->region_copy = nv->region_copy;
- nvws->region_fill = nv->region_fill;
- nvws->region_data = nv->region_data;
+ nvws->surface_copy = nouveau_pipe_surface_copy;
+ nvws->surface_fill = nouveau_pipe_surface_fill;
+ nvws->surface_data = nouveau_pipe_surface_data;
return hw_create(nouveau_create_pipe_winsys(nv), nvws, nv->chipset);
}
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c
index 0dd2cec2ca..adbf6b28e8 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c
@@ -1,5 +1,6 @@
#include "pipe/p_winsys.h"
#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
#include "nouveau_context.h"
#include "nouveau_device.h"
@@ -33,46 +34,18 @@ nouveau_get_name(struct pipe_winsys *pws)
return "Nouveau/DRI";
}
-static struct pipe_region *
-nouveau_region_alloc(struct pipe_winsys *ws, unsigned cpp,
- unsigned width, unsigned height, unsigned flags)
+static unsigned
+nouveau_surface_pitch(struct pipe_winsys *ws, unsigned cpp, unsigned width,
+ unsigned flags)
{
- struct pipe_region *region;
+ unsigned pitch = width * cpp;
- region = calloc(sizeof(*region), 1);
- region->cpp = cpp;
- region->pitch = ((cpp * width + 63) & ~63) / cpp;
- region->height = height;
- region->refcount = 1;
- region->buffer = ws->buffer_create(ws, 64);
-
- ws->buffer_data(ws, region->buffer, region->pitch * cpp * height, NULL,
- PIPE_BUFFER_USAGE_PIXEL);
- return region;
-}
-
-static void
-nouveau_region_release(struct pipe_winsys *pws, struct pipe_region **pregion)
-{
- struct pipe_region *region;
-
- if (!pregion || !*pregion)
- return;
- region = *pregion;
- *pregion = NULL;
-
- assert(region->refcount > 0);
- region->refcount--;
-
- if (region->refcount == 0) {
- assert(region->map_refcount == 0);
- pws->buffer_reference(pws, &region->buffer, NULL);
- free(region);
- }
+ pitch = (pitch + 63) & ~63;
+ return pitch / cpp;
}
static struct pipe_surface *
-nouveau_surface_alloc(struct pipe_winsys *pws, unsigned format)
+nouveau_surface_alloc(struct pipe_winsys *ws, unsigned format)
{
struct pipe_surface *surf;
@@ -82,19 +55,19 @@ nouveau_surface_alloc(struct pipe_winsys *pws, unsigned format)
surf->format = format;
surf->refcount = 1;
- surf->winsys = pws;
-
+ surf->winsys = ws;
return surf;
}
static void
-nouveau_surface_release(struct pipe_winsys *pws, struct pipe_surface **s)
+nouveau_surface_release(struct pipe_winsys *ws, struct pipe_surface **s)
{
- struct pipe_surface *surf = *s; *s = NULL;
+ struct pipe_surface *surf = *s;
- if (surf->refcount-- == 0) {
- if (surf->region)
- pws->region_release(pws, &surf->region);
+ *s = NULL;
+ if (--surf->refcount <= 0) {
+ if (surf->buffer)
+ ws->buffer_reference(ws, &surf->buffer, NULL);
free(surf);
}
}
@@ -229,9 +202,7 @@ nouveau_create_pipe_winsys(struct nouveau_context *nv)
pws->flush_frontbuffer = nouveau_flush_frontbuffer;
pws->printf = nouveau_printf;
- pws->region_alloc = nouveau_region_alloc;
- pws->region_release = nouveau_region_release;
-
+ pws->surface_pitch = nouveau_surface_pitch;
pws->surface_alloc = nouveau_surface_alloc;
pws->surface_release = nouveau_surface_release;
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_softpipe.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_softpipe.c
index c86575f187..ebce4ddede 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_softpipe.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_softpipe.c
@@ -49,9 +49,9 @@ static boolean
nouveau_is_format_supported(struct softpipe_winsys *sws, uint format)
{
switch (format) {
- case PIPE_FORMAT_U_A8_R8_G8_B8:
- case PIPE_FORMAT_U_R5_G6_B5:
- case PIPE_FORMAT_S8_Z24:
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
return TRUE;
default:
break;
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nv04_region.c b/src/mesa/drivers/dri/nouveau_winsys/nv04_surface.c
index 0fdb38e105..67e2514026 100644
--- a/src/mesa/drivers/dri/nouveau_winsys/nv04_region.c
+++ b/src/mesa/drivers/dri/nouveau_winsys/nv04_surface.c
@@ -26,26 +26,19 @@ nv04_rect_format(int cpp)
}
}
-static int
-nv04_region_display(void)
+static void
+nv04_surface_copy_m2mf(struct nouveau_context *nv, unsigned dx, unsigned dy,
+ unsigned sx, unsigned sy, unsigned w, unsigned h)
{
- NOUVEAU_ERR("unimplemented\n");
- return 0;
-}
+ struct pipe_surface *dst = nv->surf_dst;
+ struct pipe_surface *src = nv->surf_dst;
+ unsigned dst_offset, src_offset;
-static int
-nv04_region_copy_m2mf(struct nouveau_context *nv, struct pipe_region *dst,
- unsigned dst_offset, struct pipe_region *src,
- unsigned src_offset, unsigned line_len, unsigned height)
-{
- BEGIN_RING(NvM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
- OUT_RELOCo(src->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM |
- NOUVEAU_BO_RD);
- OUT_RELOCo(dst->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM |
- NOUVEAU_BO_WR);
+ dst_offset = dst->offset + (dy * dst->pitch + dx) * dst->cpp;
+ src_offset = src->offset + (sy * src->pitch + sx) * src->cpp;
- while (height) {
- int count = (height > 2047) ? 2047 : height;
+ while (h) {
+ int count = (h > 2047) ? 2047 : h;
BEGIN_RING(NvM2MF, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
OUT_RELOCl(src->buffer, src_offset, NOUVEAU_BO_VRAM |
@@ -54,32 +47,30 @@ nv04_region_copy_m2mf(struct nouveau_context *nv, struct pipe_region *dst,
NOUVEAU_BO_GART | NOUVEAU_BO_WR);
OUT_RING (src->pitch * src->cpp);
OUT_RING (dst->pitch * dst->cpp);
- OUT_RING (line_len);
+ OUT_RING (w * src->cpp);
OUT_RING (count);
OUT_RING (0x0101);
OUT_RING (0);
- height -= count;
+ h -= count;
src_offset += src->pitch * count;
dst_offset += dst->pitch * count;
}
+}
- nouveau_notifier_reset(nv->sync_notifier, 0);
- BEGIN_RING(NvM2MF, 0x104, 1);
- OUT_RING (0);
- BEGIN_RING(NvM2MF, 0x100, 1);
- OUT_RING (0);
- FIRE_RING();
- nouveau_notifier_wait_status(nv->sync_notifier, 0, 0, 2000);
-
- return 0;
+static void
+nv04_surface_copy_blit(struct nouveau_context *nv, unsigned dx, unsigned dy,
+ unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+ BEGIN_RING(NvImageBlit, 0x0300, 3);
+ OUT_RING ((sy << 16) | sx);
+ OUT_RING ((dy << 16) | dx);
+ OUT_RING (( h << 16) | w);
}
static int
-nv04_region_copy(struct nouveau_context *nv, struct pipe_region *dst,
- unsigned dst_offset, unsigned dx, unsigned dy,
- struct pipe_region *src, unsigned src_offset,
- unsigned sx, unsigned sy, unsigned w, unsigned h)
+nv04_surface_copy_prep(struct nouveau_context *nv, struct pipe_surface *dst,
+ struct pipe_surface *src)
{
int format;
@@ -89,11 +80,17 @@ nv04_region_copy(struct nouveau_context *nv, struct pipe_region *dst,
/* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
* to NV_MEMORY_TO_MEMORY_FORMAT in this case.
*/
- if ((src_offset & 63) || (dst_offset & 63)) {
- dst_offset += (dy * dst->pitch + dx) * dst->cpp;
- src_offset += (sy * src->pitch + sx) * src->cpp;
- return nv04_region_copy_m2mf(nv, dst, dst_offset, src,
- src_offset, w * src->cpp, h);
+ if ((src->offset & 63) || (dst->offset & 63)) {
+ BEGIN_RING(NvM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2);
+ OUT_RELOCo(src->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_RD);
+ OUT_RELOCo(dst->buffer, NOUVEAU_BO_GART | NOUVEAU_BO_VRAM |
+ NOUVEAU_BO_WR);
+
+ nv->surface_copy = nv04_surface_copy_m2mf;
+ nv->surf_dst = dst;
+ nv->surf_src = src;
+ return 0;
}
@@ -101,37 +98,31 @@ nv04_region_copy(struct nouveau_context *nv, struct pipe_region *dst,
NOUVEAU_ERR("Bad cpp = %d\n", dst->cpp);
return 1;
}
+ nv->surface_copy = nv04_surface_copy_blit;
BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE, 2);
OUT_RELOCo(src->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (format);
OUT_RING (((dst->pitch * dst->cpp) << 16) | (src->pitch * src->cpp));
- OUT_RELOCl(src->buffer, src_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
- OUT_RELOCl(dst->buffer, dst_offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(src->buffer, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
- BEGIN_RING(NvImageBlit, 0x0300, 3);
- OUT_RING ((sy << 16) | sx);
- OUT_RING ((dy << 16) | dx);
- OUT_RING (( h << 16) | w);
+ return 0;
+}
- nouveau_notifier_reset(nv->sync_notifier, 0);
- BEGIN_RING(NvGdiRect, 0x104, 1);
- OUT_RING (0);
- BEGIN_RING(NvGdiRect, 0x100, 1);
- OUT_RING (0);
+static void
+nv04_surface_copy_done(struct nouveau_context *nv)
+{
FIRE_RING();
- nouveau_notifier_wait_status(nv->sync_notifier, 0, 0, 2000);
-
- return 0;
}
static int
-nv04_region_fill(struct nouveau_context *nv,
- struct pipe_region *dst, unsigned dst_offset,
- unsigned dx, unsigned dy, unsigned w, unsigned h,
- unsigned value)
+nv04_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
+ unsigned dx, unsigned dy, unsigned w, unsigned h,
+ unsigned value)
{
int cs2d_format, gdirect_format;
@@ -151,8 +142,8 @@ nv04_region_fill(struct nouveau_context *nv,
BEGIN_RING(NvCtxSurf2D, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
OUT_RING (cs2d_format);
OUT_RING (((dst->pitch * dst->cpp) << 16) | (dst->pitch * dst->cpp));
- OUT_RELOCl(dst->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
- OUT_RELOCl(dst->buffer, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT, 1);
OUT_RING (gdirect_format);
@@ -163,29 +154,21 @@ nv04_region_fill(struct nouveau_context *nv,
OUT_RING ((dx << 16) | dy);
OUT_RING (( w << 16) | h);
- nouveau_notifier_reset(nv->sync_notifier, 0);
- BEGIN_RING(NvGdiRect, 0x104, 1);
- OUT_RING (0);
- BEGIN_RING(NvGdiRect, 0x100, 1);
- OUT_RING (0);
FIRE_RING();
- nouveau_notifier_wait_status(nv->sync_notifier, 0, 0, 2000);
-
return 0;
}
static int
-nv04_region_data(struct nouveau_context *nv, struct pipe_region *dst,
- unsigned dst_offset, unsigned dx, unsigned dy,
- const void *src, unsigned src_pitch,
- unsigned sx, unsigned sy, unsigned w, unsigned h)
+nv04_surface_data(struct nouveau_context *nv, struct pipe_surface *dst,
+ unsigned dx, unsigned dy, const void *src, unsigned src_pitch,
+ unsigned sx, unsigned sy, unsigned w, unsigned h)
{
NOUVEAU_ERR("unimplemented!!\n");
return 0;
}
int
-nouveau_region_init_nv04(struct nouveau_context *nv)
+nouveau_surface_init_nv04(struct nouveau_context *nv)
{
unsigned class;
int ret;
@@ -238,10 +221,11 @@ nouveau_region_init_nv04(struct nouveau_context *nv)
BEGIN_RING(NvGdiRect, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT, 1);
OUT_RING (NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE);
- nv->region_display = nv04_region_display;
- nv->region_copy = nv04_region_copy;
- nv->region_fill = nv04_region_fill;
- nv->region_data = nv04_region_data;
+ nv->surface_copy_prep = nv04_surface_copy_prep;
+ nv->surface_copy = nv04_surface_copy_blit;
+ nv->surface_copy_done = nv04_surface_copy_done;
+ nv->surface_fill = nv04_surface_fill;
+ nv->surface_data = nv04_surface_data;
return 0;
}
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nv50_region.c b/src/mesa/drivers/dri/nouveau_winsys/nv50_region.c
deleted file mode 100644
index c7450c5c8d..0000000000
--- a/src/mesa/drivers/dri/nouveau_winsys/nv50_region.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "pipe/p_context.h"
-
-#include "nouveau_context.h"
-
-static int
-nv50_region_display(void)
-{
- NOUVEAU_ERR("unimplemented\n");
- return 0;
-}
-
-static int
-nv50_region_copy(struct nouveau_context *nv, struct pipe_region *dst,
- unsigned dst_offset, unsigned dx, unsigned dy,
- struct pipe_region *src, unsigned src_offset,
- unsigned sx, unsigned sy, unsigned w, unsigned h)
-{
- NOUVEAU_ERR("unimplemented!!\n");
- return 0;
-}
-
-static int
-nv50_region_fill(struct nouveau_context *nv,
- struct pipe_region *dst, unsigned dst_offset,
- unsigned dx, unsigned dy, unsigned w, unsigned h,
- unsigned value)
-{
- NOUVEAU_ERR("unimplemented!!\n");
- return 0;
-}
-
-static int
-nv50_region_data(struct nouveau_context *nv, struct pipe_region *dst,
- unsigned dst_offset, unsigned dx, unsigned dy,
- const void *src, unsigned src_pitch,
- unsigned sx, unsigned sy, unsigned w, unsigned h)
-{
- NOUVEAU_ERR("unimplemented!!\n");
- return 0;
-}
-
-int
-nouveau_region_init_nv50(struct nouveau_context *nv)
-{
- nv->region_display = nv50_region_display;
- nv->region_copy = nv50_region_copy;
- nv->region_fill = nv50_region_fill;
- nv->region_data = nv50_region_data;
- return 0;
-}
-
diff --git a/src/mesa/drivers/dri/nouveau_winsys/nv50_surface.c b/src/mesa/drivers/dri/nouveau_winsys/nv50_surface.c
new file mode 100644
index 0000000000..2a95b1fcd3
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau_winsys/nv50_surface.c
@@ -0,0 +1,170 @@
+#include "pipe/p_context.h"
+
+#include "nouveau_context.h"
+
+static INLINE int
+nv50_format(int cpp)
+{
+ switch (cpp) {
+ case 4: return NV50_2D_DST_FORMAT_32BPP;
+ case 3: return NV50_2D_DST_FORMAT_24BPP;
+ case 2: return NV50_2D_DST_FORMAT_16BPP;
+ case 1: return NV50_2D_DST_FORMAT_8BPP;
+ default:
+ return -1;
+ }
+}
+
+static int
+nv50_surface_copy_prep(struct nouveau_context *nv,
+ struct pipe_surface *dst, struct pipe_surface *src)
+{
+ int surf_format;
+
+ assert(src->cpp == dst->cpp);
+
+ surf_format = nv50_format(dst->cpp);
+ assert(surf_format >= 0);
+
+ BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY0, 2);
+ OUT_RELOCo(src->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+ BEGIN_RING(Nv2D, NV50_2D_DST_FORMAT, 2);
+ OUT_RING (surf_format);
+ OUT_RING (1);
+ BEGIN_RING(Nv2D, NV50_2D_DST_PITCH, 5);
+ OUT_RING (dst->pitch * dst->cpp);
+ OUT_RING (dst->pitch);
+ OUT_RING (dst->height);
+ OUT_RELOCh(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(Nv2D, NV50_2D_CLIP_X, 4);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (dst->pitch);
+ OUT_RING (dst->height);
+
+ BEGIN_RING(Nv2D, NV50_2D_SRC_FORMAT, 2);
+ OUT_RING (surf_format);
+ OUT_RING (1);
+ BEGIN_RING(Nv2D, NV50_2D_SRC_PITCH, 5);
+ OUT_RING (src->pitch * src->cpp);
+ OUT_RING (src->pitch);
+ OUT_RING (src->height);
+ OUT_RELOCh(src->buffer, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+ OUT_RELOCl(src->buffer, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+
+ return 0;
+}
+
+static void
+nv50_surface_copy(struct nouveau_context *nv, unsigned dx, unsigned dy,
+ unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+ BEGIN_RING(Nv2D, 0x0110, 1);
+ OUT_RING (0);
+ BEGIN_RING(Nv2D, NV50_2D_BLIT_DST_X, 12);
+ OUT_RING (dx);
+ OUT_RING (dy);
+ OUT_RING (w);
+ OUT_RING (h);
+ OUT_RING (0);
+ OUT_RING (1);
+ OUT_RING (0);
+ OUT_RING (1);
+ OUT_RING (0);
+ OUT_RING (sx);
+ OUT_RING (0);
+ OUT_RING (sy);
+}
+
+static void
+nv50_surface_copy_done(struct nouveau_context *nv)
+{
+ FIRE_RING();
+}
+
+static int
+nv50_surface_fill(struct nouveau_context *nv, struct pipe_surface *dst,
+ unsigned dx, unsigned dy, unsigned w, unsigned h,
+ unsigned value)
+{
+ int surf_format, rect_format;
+
+ surf_format = nv50_format(dst->cpp);
+ if (surf_format < 0)
+ return 1;
+
+ rect_format = nv50_format(dst->cpp);
+ if (rect_format < 0)
+ return 1;
+
+ BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY1, 1);
+ OUT_RELOCo(dst->buffer, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(Nv2D, NV50_2D_DST_FORMAT, 2);
+ OUT_RING (surf_format);
+ OUT_RING (1);
+ BEGIN_RING(Nv2D, NV50_2D_DST_PITCH, 5);
+ OUT_RING (dst->pitch * dst->cpp);
+ OUT_RING (dst->pitch);
+ OUT_RING (dst->height);
+ OUT_RELOCh(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ OUT_RELOCl(dst->buffer, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+ BEGIN_RING(Nv2D, NV50_2D_CLIP_X, 4);
+ OUT_RING (0);
+ OUT_RING (0);
+ OUT_RING (dst->pitch);
+ OUT_RING (dst->height);
+
+ BEGIN_RING(Nv2D, 0x0580, 3);
+ OUT_RING (4);
+ OUT_RING (rect_format);
+ OUT_RING (value);
+
+ BEGIN_RING(Nv2D, NV50_2D_RECT_X1, 4);
+ OUT_RING (dx);
+ OUT_RING (dy);
+ OUT_RING (dx + w);
+ OUT_RING (dy + h);
+
+ FIRE_RING();
+
+ return 0;
+}
+
+static int
+nv50_surface_data(struct nouveau_context *nv, struct pipe_surface *dst,
+ unsigned dx, unsigned dy, const void *src, unsigned src_pitch,
+ unsigned sx, unsigned sy, unsigned w, unsigned h)
+{
+ NOUVEAU_ERR("unimplemented!!\n");
+ return 0;
+}
+
+int
+nouveau_surface_init_nv50(struct nouveau_context *nv)
+{
+ int ret;
+
+ ret = nouveau_grobj_alloc(nv->channel, nv->next_handle++, NV50_2D,
+ &nv->Nv2D);
+ if (ret)
+ return ret;
+
+ BEGIN_RING(Nv2D, NV50_2D_DMA_NOTIFY, 1);
+ OUT_RING (nv->sync_notifier->handle);
+ BEGIN_RING(Nv2D, NV50_2D_DMA_IN_MEMORY0, 2);
+ OUT_RING (nv->channel->vram->handle);
+ OUT_RING (nv->channel->vram->handle);
+ BEGIN_RING(Nv2D, NV50_2D_OPERATION, 1);
+ OUT_RING (NV50_2D_OPERATION_SRCCOPY);
+
+ nv->surface_copy_prep = nv50_surface_copy_prep;
+ nv->surface_copy = nv50_surface_copy;
+ nv->surface_copy_done = nv50_surface_copy_done;
+ nv->surface_fill = nv50_surface_fill;
+ nv->surface_data = nv50_surface_data;
+ return 0;
+}
+