From c0a63d8e5e33b7fe3057e32f04c22969ac2adc1d Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 26 Dec 2006 20:59:49 +1100 Subject: nouveau: Add notifier support functions --- src/mesa/drivers/dri/nouveau/Makefile | 1 + src/mesa/drivers/dri/nouveau/nouveau_context.c | 1 + src/mesa/drivers/dri/nouveau/nouveau_context.h | 4 + src/mesa/drivers/dri/nouveau/nouveau_object.c | 14 +-- src/mesa/drivers/dri/nouveau/nouveau_object.h | 16 +++- src/mesa/drivers/dri/nouveau/nouveau_sync.c | 115 +++++++++++++++++++++++++ src/mesa/drivers/dri/nouveau/nouveau_sync.h | 36 ++++++++ 7 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 src/mesa/drivers/dri/nouveau/nouveau_sync.c create mode 100644 src/mesa/drivers/dri/nouveau/nouveau_sync.h (limited to 'src/mesa/drivers') diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile index 1a76169156..962978dc7f 100644 --- a/src/mesa/drivers/dri/nouveau/Makefile +++ b/src/mesa/drivers/dri/nouveau/Makefile @@ -24,6 +24,7 @@ DRIVER_SOURCES = \ nouveau_shader_2.c \ nouveau_tex.c \ nouveau_swtcl.c \ + nouveau_sync.c \ nv10_swtcl.c \ nv10_state.c \ nv20_state.c \ diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index ac940ac595..7aca31d0d3 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -222,6 +222,7 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual, break; } + nouveauSyncInitFuncs(ctx); nmesa->hw_func.InitCard(nmesa); nouveauInitState(ctx); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h index ea28506b74..f54ac9a7c8 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h @@ -40,6 +40,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "nouveau_state_cache.h" #include "nouveau_buffers.h" #include "nouveau_shader.h" +#include "nouveau_sync.h" #include "xmlconfig.h" @@ -101,6 +102,9 @@ typedef struct nouveau_context { uint64_t vram_phys; uint64_t agp_phys; + /* Channel synchronisation */ + nouveau_notifier *syncNotifier; + /* Additional hw-specific functions */ nouveau_hw_func hw_func; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.c b/src/mesa/drivers/dri/nouveau/nouveau_object.c index dda547c916..cf7284d2d5 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_object.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_object.c @@ -4,7 +4,7 @@ #include "nouveau_reg.h" -static GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, int handle, int class, uint32_t flags, uint32_t dma_in, uint32_t dma_out, uint32_t dma_notifier) +GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, int handle, int class, uint32_t flags, uint32_t dma_in, uint32_t dma_out, uint32_t dma_notifier) { drm_nouveau_object_init_t cto; int ret; @@ -20,12 +20,12 @@ static GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, int handle, return ret == 0; } -static GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa, - uint32_t handle, - uint32_t offset, - uint32_t size, - int target, - int access) +GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa, + uint32_t handle, + uint32_t offset, + uint32_t size, + int target, + int access) { drm_nouveau_dma_object_init_t dma; int ret; diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.h b/src/mesa/drivers/dri/nouveau/nouveau_object.h index a49a39719b..87f2dc9ae7 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_object.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_object.h @@ -12,7 +12,8 @@ enum DMAObjects { NvCtxSurf2D = 0x80000020, NvImageBlit = 0x80000021, NvDmaFB = 0xD0FB0001, - NvDmaAGP = 0xD0AA0001 + NvDmaAGP = 0xD0AA0001, + NvSyncNotify = 0xD0000001 }; enum DMASubchannel { @@ -22,4 +23,17 @@ enum DMASubchannel { }; extern void nouveauObjectOnSubchannel(nouveauContextPtr nmesa, int subchannel, int handle); + +extern GLboolean nouveauCreateContextObject(nouveauContextPtr nmesa, + int handle, int class, + uint32_t flags, + uint32_t dma_in, + uint32_t dma_out, + uint32_t dma_notifier); +extern GLboolean nouveauCreateDmaObject(nouveauContextPtr nmesa, + uint32_t handle, + uint32_t offset, + uint32_t size, + int target, + int access); #endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/src/mesa/drivers/dri/nouveau/nouveau_sync.c new file mode 100644 index 0000000000..698f778c4b --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.c @@ -0,0 +1,115 @@ +#include "vblank.h" /* for DO_USLEEP */ + +#include "nouveau_context.h" +#include "nouveau_buffers.h" +#include "nouveau_object.h" +#include "nouveau_fifo.h" +#include "nouveau_reg.h" +#include "nouveau_msg.h" +#include "nouveau_sync.h" + +nouveau_notifier * +nouveau_notifier_new(GLcontext *ctx, GLuint handle) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + nouveau_notifier *notifier; + + notifier = CALLOC_STRUCT(nouveau_notifier_t); + if (!notifier) + return NULL; + + notifier->mem = nouveau_mem_alloc(ctx, NOUVEAU_MEM_FB, 32, 0); + if (!notifier->mem) { + FREE(notifier); + return NULL; + } + + if (!nouveauCreateDmaObject(nmesa, handle, notifier->mem->offset, + notifier->mem->size, + 0 /* NV_DMA_TARGET_FB */, + 0 /* NV_DMA_ACCESS_RW */)) { + nouveau_mem_free(ctx, notifier->mem); + FREE(notifier); + return NULL; + } + + notifier->handle = handle; + return notifier; +} + +void +nouveau_notifier_destroy(GLcontext *ctx, nouveau_notifier *notifier) +{ + /*XXX: free DMA object.. */ + nouveau_mem_free(ctx, notifier->mem); + FREE(notifier); +} + +void +nouveau_notifier_reset(nouveau_notifier *notifier) +{ + volatile GLuint *n = notifier->mem->map; + + n[NV_NOTIFY_TIME_0 /4] = 0x00000000; + n[NV_NOTIFY_TIME_1 /4] = 0x00000000; + n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000; + n[NV_NOTIFY_STATE /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS << + NV_NOTIFY_STATE_STATUS_SHIFT); +} + +GLboolean +nouveau_notifier_wait_status(nouveau_notifier *notifier, GLuint status, + GLuint timeout) +{ + volatile GLuint *n = notifier->mem->map; + unsigned int time = 0; + + while (time <= timeout) { + if (n[NV_NOTIFY_STATE] & NV_NOTIFY_STATE_ERROR_CODE_MASK) { + MESSAGE("Notifier returned error: 0x%04x\n", + n[NV_NOTIFY_STATE] & + NV_NOTIFY_STATE_ERROR_CODE_MASK); + return GL_FALSE; + } + + if (((n[NV_NOTIFY_STATE] & NV_NOTIFY_STATE_STATUS_MASK) >> + NV_NOTIFY_STATE_STATUS_SHIFT) == status) + return GL_TRUE; + + if (timeout) { + DO_USLEEP(1); + time++; + } + } + + MESSAGE("Notifier timed out\n"); + return GL_FALSE; +} + +void +nouveau_notifier_wait_nop(GLcontext *ctx, nouveau_notifier *notifier, + GLuint subc) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + GLboolean ret; + + nouveau_notifier_reset(notifier); + + BEGIN_RING_SIZE(subc, NV_NOTIFY, 1); + OUT_RING (NV_NOTIFY_STYLE_WRITE_ONLY); + BEGIN_RING_SIZE(subc, NV_NOP, 1); + OUT_RING (0); + + ret = nouveau_notifier_wait_status(notifier, + NV_NOTIFY_STATE_STATUS_COMPLETED, + 0 /* no timeout */); + if (ret) MESSAGE("wait on notifier failed\n"); +} + +void nouveauSyncInitFuncs(GLcontext *ctx) +{ + nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); + + nmesa->syncNotifier = nouveau_notifier_new(ctx, NvSyncNotify); +} + diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.h b/src/mesa/drivers/dri/nouveau/nouveau_sync.h new file mode 100644 index 0000000000..b20c2565ca --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.h @@ -0,0 +1,36 @@ +#ifndef __NOUVEAU_SYNC_H__ +#define __NOUVEAU_SYNC_H__ + +#include "nouveau_buffers.h" + +#define NV_NOTIFY_TIME_0 0x00000000 +#define NV_NOTIFY_TIME_1 0x00000004 +#define NV_NOTIFY_RETURN_VALUE 0x00000008 +#define NV_NOTIFY_STATE 0x0000000C +#define NV_NOTIFY_STATE_STATUS_MASK 0xFF000000 +#define NV_NOTIFY_STATE_STATUS_SHIFT 24 +#define NV_NOTIFY_STATE_STATUS_COMPLETED 0x00 +#define NV_NOTIFY_STATE_STATUS_IN_PROCESS 0x01 +#define NV_NOTIFY_STATE_ERROR_CODE_MASK 0x0000FFFF +#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT 0 + +/* Methods that (hopefully) all objects have */ +#define NV_NOP 0x00000100 +#define NV_NOTIFY 0x00000104 +#define NV_NOTIFY_STYLE_WRITE_ONLY 0 + +typedef struct nouveau_notifier_t { + GLuint handle; + nouveau_mem *mem; +} nouveau_notifier; + +extern nouveau_notifier *nouveau_notifier_new(GLcontext *, GLuint handle); +extern void nouveau_notifier_destroy(GLcontext *, nouveau_notifier *); +extern void nouveau_notifier_reset(nouveau_notifier *); +extern GLboolean nouveau_notifier_wait_status(nouveau_notifier *r, + GLuint status, GLuint timeout); +extern void nouveau_notifier_wait_nop(GLcontext *ctx, + nouveau_notifier *, GLuint subc); + +extern void nouveauSyncInitFuncs(GLcontext *ctx); +#endif -- cgit v1.2.3