diff options
Diffstat (limited to 'src/mesa/drivers')
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, ®ion->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; +} + |
