mesa: Branch 'master' - 3 commits
Ben Skeggs
darktama at kemper.freedesktop.org
Tue Dec 26 10:37:13 UTC 2006
src/mesa/drivers/dri/nouveau/Makefile | 1
src/mesa/drivers/dri/nouveau/nouveau_context.c | 2
src/mesa/drivers/dri/nouveau/nouveau_context.h | 4
src/mesa/drivers/dri/nouveau/nouveau_fifo.c | 39 +------
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 | 131 +++++++++++++++++++++++++
src/mesa/drivers/dri/nouveau/nouveau_sync.h | 36 ++++++
8 files changed, 203 insertions(+), 40 deletions(-)
New commits:
diff-tree 3fcb7d388d71c6ab147769d35feab29b7f511521 (from 0b2b2de6cff23bc224f5471cc8d0812661a0d363)
Author: Ben Skeggs <darktama at iinet.net.au>
Date: Tue Dec 26 21:33:58 2006 +1100
nouveau: Make the notifier stuff actually work..
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/src/mesa/drivers/dri/nouveau/nouveau_sync.c
index 5c1c030..e27101d 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, GLu
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_not
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
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)
diff-tree 0b2b2de6cff23bc224f5471cc8d0812661a0d363 (from c0a63d8e5e33b7fe3057e32f04c22969ac2adc1d)
Author: Ben Skeggs <darktama at iinet.net.au>
Date: Tue Dec 26 21:10:38 2006 +1100
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.
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index 7aca31d..d68f4e7 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 __
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 5c2b2c7..7af9f1e 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
}
/*
- * 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 698f778..5c1c030 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
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 b20c256..d9e3d4b 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_s
extern void nouveau_notifier_wait_nop(GLcontext *ctx,
nouveau_notifier *, GLuint subc);
-extern void nouveauSyncInitFuncs(GLcontext *ctx);
+extern GLboolean nouveauSyncInitFuncs(GLcontext *ctx);
#endif
diff-tree c0a63d8e5e33b7fe3057e32f04c22969ac2adc1d (from b8769f318ff9c2e4a74fbb1d4b058eb521e36dda)
Author: Ben Skeggs <darktama at iinet.net.au>
Date: Tue Dec 26 20:59:49 2006 +1100
nouveau: Add notifier support functions
diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile
index 1a76169..962978d 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 ac940ac..7aca31d 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 __
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 ea28506..f54ac9a 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 dda547c..cf7284d 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 nouveauCreateContextObj
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 a49a397..87f2dc9 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 0000000..698f778
--- /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 0000000..b20c256
--- /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
More information about the mesa-commit
mailing list