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