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/nouveau_sync.c | 115 ++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/mesa/drivers/dri/nouveau/nouveau_sync.c (limited to 'src/mesa/drivers/dri/nouveau/nouveau_sync.c') 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); +} + -- cgit v1.2.3 From 0b2b2de6cff23bc224f5471cc8d0812661a0d363 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 26 Dec 2006 21:10:38 +1100 Subject: nouveau: Wait on notifier to check for completion of previous commands. We can't wait on NV_PGRAPH_STATUS. We don't have the regs mapped, and there's no guarantee that we'll catch PGRAPH idle when multiple channels are active. --- src/mesa/drivers/dri/nouveau/nouveau_context.c | 3 +- src/mesa/drivers/dri/nouveau/nouveau_fifo.c | 39 +++++--------------------- src/mesa/drivers/dri/nouveau/nouveau_sync.c | 14 ++++++++- src/mesa/drivers/dri/nouveau/nouveau_sync.h | 2 +- 4 files changed, 23 insertions(+), 35 deletions(-) (limited to 'src/mesa/drivers/dri/nouveau/nouveau_sync.c') diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c index 7aca31d0d3..d68f4e77e7 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_context.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c @@ -222,7 +222,8 @@ GLboolean nouveauCreateContext( const __GLcontextModes *glVisual, break; } - nouveauSyncInitFuncs(ctx); + if (!nouveauSyncInitFuncs(ctx)) + return GL_FALSE; nmesa->hw_func.InitCard(nmesa); nouveauInitState(ctx); diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fifo.c b/src/mesa/drivers/dri/nouveau/nouveau_fifo.c index 5c2b2c7552..7af9f1e3c2 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_fifo.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_fifo.c @@ -35,6 +35,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #include "nouveau_msg.h" #include "nouveau_fifo.h" #include "nouveau_lock.h" +#include "nouveau_object.h" +#include "nouveau_sync.h" #define RING_SKIPS 8 @@ -68,45 +70,18 @@ void WAIT_RING(nouveauContextPtr nmesa,u_int32_t size) } /* - * Wait for the card to be idle + * Wait for the channel to be idle */ void nouveauWaitForIdleLocked(nouveauContextPtr nmesa) { - int i,status; - + /* Wait for FIFO idle */ FIRE_RING(); while(RING_AHEAD()>0); - /* We can't wait on PGRAPH going idle.. - * 1) We don't have the regs mapped - * 2) PGRAPH may not go idle with multiple channels active - * Look into replacing this with a NOTIFY/NOP + wait notifier sequence. + /* Wait on notifier to indicate all commands in the channel have + * been completed. */ -#if 0 - for(i=0;i<1000000;i++) /* 1 second */ - { - switch(nmesa->screen->card->type) - { - case NV_03: - status=NV_READ(NV03_STATUS); - break; - case NV_04: - case NV_05: - case NV_10: - case NV_20: - case NV_30: - case NV_40: - case NV_44: - case NV_50: - default: - status=NV_READ(NV04_STATUS); - break; - } - if (status) - return; - DO_USLEEP(1); - } -#endif + nouveau_notifier_wait_nop(nmesa->glCtx, nmesa->syncNotifier, NvSub3D); } void nouveauWaitForIdle(nouveauContextPtr nmesa) diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/src/mesa/drivers/dri/nouveau/nouveau_sync.c index 698f778c4b..5c1c030913 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_sync.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.c @@ -106,10 +106,22 @@ nouveau_notifier_wait_nop(GLcontext *ctx, nouveau_notifier *notifier, if (ret) MESSAGE("wait on notifier failed\n"); } -void nouveauSyncInitFuncs(GLcontext *ctx) +GLboolean nouveauSyncInitFuncs(GLcontext *ctx) { nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); nmesa->syncNotifier = nouveau_notifier_new(ctx, NvSyncNotify); + if (!nmesa->syncNotifier) { + MESSAGE("Failed to create channel sync notifier\n"); + return GL_FALSE; + } + + /* 0x180 is SET_DMA_NOTIFY, should be correct for all supported 3D + * object classes + */ + BEGIN_RING_CACHE(NvSub3D, 0x180, 1); + OUT_RING_CACHE (NvSyncNotify); + + return GL_TRUE; } diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.h b/src/mesa/drivers/dri/nouveau/nouveau_sync.h index b20c2565ca..d9e3d4b80c 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_sync.h +++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.h @@ -32,5 +32,5 @@ extern GLboolean nouveau_notifier_wait_status(nouveau_notifier *r, extern void nouveau_notifier_wait_nop(GLcontext *ctx, nouveau_notifier *, GLuint subc); -extern void nouveauSyncInitFuncs(GLcontext *ctx); +extern GLboolean nouveauSyncInitFuncs(GLcontext *ctx); #endif -- cgit v1.2.3 From 3fcb7d388d71c6ab147769d35feab29b7f511521 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 26 Dec 2006 21:33:58 +1100 Subject: nouveau: Make the notifier stuff actually work.. --- src/mesa/drivers/dri/nouveau/nouveau_sync.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/mesa/drivers/dri/nouveau/nouveau_sync.c') diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/src/mesa/drivers/dri/nouveau/nouveau_sync.c index 5c1c030913..e27101d868 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_sync.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.c @@ -18,7 +18,10 @@ nouveau_notifier_new(GLcontext *ctx, GLuint handle) if (!notifier) return NULL; - notifier->mem = nouveau_mem_alloc(ctx, NOUVEAU_MEM_FB, 32, 0); + notifier->mem = nouveau_mem_alloc(ctx, + NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED, + 32, + 0); if (!notifier->mem) { FREE(notifier); return NULL; @@ -65,14 +68,14 @@ nouveau_notifier_wait_status(nouveau_notifier *notifier, GLuint status, unsigned int time = 0; while (time <= timeout) { - if (n[NV_NOTIFY_STATE] & NV_NOTIFY_STATE_ERROR_CODE_MASK) { + if (n[NV_NOTIFY_STATE/4] & 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) >> + if (((n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_STATUS_MASK) >> NV_NOTIFY_STATE_STATUS_SHIFT) == status) return GL_TRUE; @@ -99,11 +102,12 @@ nouveau_notifier_wait_nop(GLcontext *ctx, nouveau_notifier *notifier, OUT_RING (NV_NOTIFY_STYLE_WRITE_ONLY); BEGIN_RING_SIZE(subc, NV_NOP, 1); OUT_RING (0); + FIRE_RING(); ret = nouveau_notifier_wait_status(notifier, NV_NOTIFY_STATE_STATUS_COMPLETED, 0 /* no timeout */); - if (ret) MESSAGE("wait on notifier failed\n"); + if (ret == GL_FALSE) MESSAGE("wait on notifier failed\n"); } GLboolean nouveauSyncInitFuncs(GLcontext *ctx) -- cgit v1.2.3 From 1780fd4eeeef2358e929c23cfae2c348cb4a709e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Wed, 27 Dec 2006 15:54:30 +1100 Subject: nouveau: We'll need syncNotifier for NV_MEMORY_TO_MEMORY_FORMAT too. --- src/mesa/drivers/dri/nouveau/nouveau_sync.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/mesa/drivers/dri/nouveau/nouveau_sync.c') diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/src/mesa/drivers/dri/nouveau/nouveau_sync.c index e27101d868..0bf20e723b 100644 --- a/src/mesa/drivers/dri/nouveau/nouveau_sync.c +++ b/src/mesa/drivers/dri/nouveau/nouveau_sync.c @@ -125,6 +125,11 @@ GLboolean nouveauSyncInitFuncs(GLcontext *ctx) */ BEGIN_RING_CACHE(NvSub3D, 0x180, 1); OUT_RING_CACHE (NvSyncNotify); +#ifdef ALLOW_MULTI_SUBCHANNEL + BEGIN_RING_SIZE(NvSubMemFormat, + NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1); + OUT_RING (NvSyncNotify); +#endif return GL_TRUE; } -- cgit v1.2.3