mesa: Branch 'master' - 7 commits

Ben Skeggs darktama at kemper.freedesktop.org
Wed Dec 27 12:54:38 UTC 2006


 src/mesa/drivers/dri/nouveau/Makefile            |    1 
 src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c |  272 +++++++++++++++++++++++
 src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h |   27 ++
 src/mesa/drivers/dri/nouveau/nouveau_buffers.c   |   77 ++++++
 src/mesa/drivers/dri/nouveau/nouveau_buffers.h   |    7 
 src/mesa/drivers/dri/nouveau/nouveau_context.c   |    7 
 src/mesa/drivers/dri/nouveau/nouveau_context.h   |    4 
 src/mesa/drivers/dri/nouveau/nouveau_object.c    |   10 
 src/mesa/drivers/dri/nouveau/nouveau_object.h    |    2 
 src/mesa/drivers/dri/nouveau/nouveau_shader.h    |    4 
 src/mesa/drivers/dri/nouveau/nouveau_sync.c      |    5 
 src/mesa/drivers/dri/nouveau/nv30_fragprog.c     |   41 +--
 12 files changed, 429 insertions(+), 28 deletions(-)

New commits:
diff-tree 8c180c72d5fed5f26f258759f9649fc647a764ff (from 9a20ae70ecda2e78ea6b52c3fd829d283434c1ad)
Author: Ben Skeggs <darktama at iinet.net.au>
Date:   Wed Dec 27 23:52:40 2006 +1100

    nouveau: Use bufferobj interface for fragment program uploads

diff --git a/src/mesa/drivers/dri/nouveau/nouveau_shader.h b/src/mesa/drivers/dri/nouveau/nouveau_shader.h
index 6e934f2..08cb781 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_shader.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_shader.h
@@ -2,7 +2,7 @@
 #define __SHADER_COMMON_H__
 
 #include "mtypes.h"
-#include "nouveau_buffers.h"
+#include "bufferobj.h"
 
 typedef struct _nvsFunc nvsFunc;
 
@@ -41,7 +41,7 @@ typedef struct _nouveauShader {
    unsigned int program_alloc_size;
    unsigned int program_start_id;
    unsigned int program_current;
-   nouveau_mem *program_buffer;
+   struct gl_buffer_object *program_buffer;
    unsigned int inputs_read;
    unsigned int outputs_written;
    int		inst_count;
diff --git a/src/mesa/drivers/dri/nouveau/nv30_fragprog.c b/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
index b11bc18..cd7c955 100644
--- a/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
+++ b/src/mesa/drivers/dri/nouveau/nv30_fragprog.c
@@ -10,7 +10,7 @@
 #include "nouveau_shader.h"
 #include "nouveau_object.h"
 #include "nouveau_msg.h"
-#include "nouveau_buffers.h"
+#include "nouveau_bufferobj.h"
 #include "nv30_shader.h"
 
 unsigned int NVFP_TX_AOP_COUNT = 64;
@@ -24,29 +24,28 @@ static void
 NV30FPUploadToHW(GLcontext *ctx, nouveauShader *nvs)
 {
    nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+   uint32_t offset;
 
-   if (!nvs->program_buffer) {
-      nouveau_mem *fpbuf;
-
-      fpbuf = nouveau_mem_alloc(ctx, NOUVEAU_MEM_FB|NOUVEAU_MEM_MAPPED,
-	    			nvs->program_size * sizeof(uint32_t), 0);
-      if (!fpbuf) {
-	 fprintf(stderr, "fragprog vram alloc fail!\n");
-	 return;
-      }
-      nvs->program_buffer = fpbuf;
-   }
-
-   /*XXX: should do a DMA.. and not copy over a possibly in-use program.. */
-   /* not using state cache here, updated programs at the same address
-    * seem to not take effect unless ACTIVE_PROGRAM is called again.  hw
-    * caches the program somewhere? so, maybe not so bad to just clobber the
-    * old program in vram..
+   if (!nvs->program_buffer)
+      nvs->program_buffer = ctx->Driver.NewBufferObject(ctx, 0,
+							GL_ARRAY_BUFFER_ARB);
+
+   /* Should use STATIC_DRAW_ARB if shader doesn't use changable params */
+   ctx->Driver.BufferData(ctx, GL_ARRAY_BUFFER_ARB,
+	 		  nvs->program_size * sizeof(uint32_t),
+			  (const GLvoid *)nvs->program,
+			  GL_DYNAMIC_DRAW_ARB,
+			  nvs->program_buffer);
+
+   offset = nouveau_bufferobj_gpu_ref(ctx, GL_READ_ONLY_ARB,
+	 			      nvs->program_buffer);
+
+   /* Not using state cache here, updated programs at the same address don't
+    * seem to take effect unless the ACTIVE_PROGRAM method is called again.
+    * HW caches the program somewhere?
     */
-   memcpy(nvs->program_buffer->map, nvs->program,
-	  nvs->program_size * sizeof(uint32_t));
    BEGIN_RING_SIZE(NvSub3D, NV30_TCL_PRIMITIVE_3D_FP_ACTIVE_PROGRAM, 1);
-   OUT_RING(nouveau_mem_gpu_offset_get(ctx, nvs->program_buffer) | 1);
+   OUT_RING       (offset | 1);
 }
 
 static void
diff-tree 9a20ae70ecda2e78ea6b52c3fd829d283434c1ad (from 1780fd4eeeef2358e929c23cfae2c348cb4a709e)
Author: Ben Skeggs <darktama at iinet.net.au>
Date:   Wed Dec 27 23:30:34 2006 +1100

    nouveau: Initial buffer object support

diff --git a/src/mesa/drivers/dri/nouveau/Makefile b/src/mesa/drivers/dri/nouveau/Makefile
index 962978d..d31b42a 100644
--- a/src/mesa/drivers/dri/nouveau/Makefile
+++ b/src/mesa/drivers/dri/nouveau/Makefile
@@ -8,6 +8,7 @@ LIBNAME = nouveau_dri.so
 MINIGLX_SOURCES = 
 
 DRIVER_SOURCES = \
+	nouveau_bufferobj.c      \
 	nouveau_buffers.c        \
 	nouveau_card.c           \
 	nouveau_context.c        \
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c
new file mode 100644
index 0000000..d36196a
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.c
@@ -0,0 +1,272 @@
+#include "bufferobj.h"
+#include "enums.h"
+
+#include "nouveau_bufferobj.h"
+#include "nouveau_buffers.h"
+#include "nouveau_context.h"
+#include "nouveau_drm.h"
+#include "nouveau_object.h"
+#include "nouveau_msg.h"
+
+#define DEBUG(fmt,args...) do {                \
+	if (NOUVEAU_DEBUG & DEBUG_BUFFEROBJ) { \
+		fprintf(stderr, "%s: "fmt, __func__, ##args);  \
+	}                                      \
+} while(0)
+
+/* Wrapper for nouveau_mem_gpu_offset_get() that marks the bufferobj dirty
+ * if the GPU modifies the data.
+ */
+uint32_t
+nouveau_bufferobj_gpu_ref(GLcontext *ctx, GLenum access,
+			  struct gl_buffer_object *obj)
+{
+	nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+	DEBUG("obj=%p, access=%s\n", obj, _mesa_lookup_enum_by_nr(access));
+
+	if (access == GL_WRITE_ONLY_ARB || access == GL_READ_WRITE_ARB)
+		nbo->gpu_dirty = GL_TRUE;
+
+	return nouveau_mem_gpu_offset_get(ctx, nbo->gpu_mem);
+}
+
+static void
+nouveauBindBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
+{
+}
+
+static struct gl_buffer_object *
+nouveauNewBufferObject(GLcontext *ctx, GLuint buffer, GLenum target)
+{
+	nouveau_buffer_object *nbo;
+
+	nbo = CALLOC_STRUCT(nouveau_buffer_object_t);
+	DEBUG("name=0x%08x, target=%s, obj=%p\n",
+			buffer, _mesa_lookup_enum_by_nr(target), nbo);
+	_mesa_initialize_buffer_object(&nbo->mesa, buffer, target);
+	return &nbo->mesa;
+}
+
+static void
+nouveauDeleteBuffer(GLcontext *ctx, struct gl_buffer_object *obj)
+{
+	nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+	DEBUG("obj=%p\n", obj);
+
+	if (nbo->gpu_mem) {
+		nouveau_mem_free(ctx, nbo->gpu_mem);
+	}
+	_mesa_delete_buffer_object(ctx, obj);
+}
+
+static void
+nouveauBufferData(GLcontext *ctx, GLenum target, GLsizeiptrARB size,
+		  const GLvoid *data, GLenum usage,
+		  struct gl_buffer_object *obj)
+{
+	nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+	DEBUG("obj=%p, target=%s, usage=%s, size=%d, data=%p\n",
+			obj,
+			_mesa_lookup_enum_by_nr(target),
+			_mesa_lookup_enum_by_nr(usage),
+			(unsigned int)size,
+			data);
+
+	if (nbo->gpu_mem && nbo->gpu_mem->size != size)
+		nouveau_mem_free(ctx, nbo->gpu_mem);
+
+	/* Always have the GPU access the data from VRAM if possible.  For
+	 * some "usage" values it may be better from AGP be default?
+	 *
+	 * TODO: At some point we should drop the NOUVEAU_MEM_MAPPED flag.
+	 * TODO: Use the NOUVEAU_MEM_AGP_ACCEPTABLE flag.
+	 * TODO: What about PCI-E and shared system memory?
+	 */
+	if (!nbo->gpu_mem)
+		nbo->gpu_mem = nouveau_mem_alloc(ctx,
+						 NOUVEAU_MEM_FB |
+						 NOUVEAU_MEM_MAPPED,
+						 size,
+						 0);
+
+	if (!nbo->gpu_mem) {
+		MESSAGE("AIII bufferobj malloc failed\n");
+		return;
+	}
+
+	obj->Usage = usage;
+	obj->Size  = size;
+	if (!data)
+		return;
+
+	ctx->Driver.MapBuffer(ctx, target, GL_WRITE_ONLY_ARB, obj);
+	_mesa_memcpy(nbo->cpu_mem->map, data, size);
+	ctx->Driver.UnmapBuffer(ctx, target, obj);
+}
+
+/*TODO: we don't need to DMA the entire buffer like MapBuffer does.. */
+static void
+nouveauBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset,
+		     GLsizeiptrARB size, const GLvoid *data,
+		     struct gl_buffer_object *obj)
+{
+	DEBUG("obj=%p, target=%s, offset=0x%x, size=%d, data=%p\n",
+			obj,
+			_mesa_lookup_enum_by_nr(target),
+			(unsigned int)offset,
+			(unsigned int)size,
+			data);
+
+	ctx->Driver.MapBuffer(ctx, target, GL_WRITE_ONLY_ARB, obj);
+	_mesa_memcpy((GLubyte *)obj->Pointer + offset, data, size);
+	ctx->Driver.UnmapBuffer(ctx, target, obj);
+}
+
+/*TODO: we don't need to DMA the entire buffer like MapBuffer does.. */
+static void
+nouveauGetBufferSubData(GLcontext *ctx, GLenum target, GLintptrARB offset,
+		     GLsizeiptrARB size, GLvoid *data,
+		     struct gl_buffer_object *obj)
+{
+	DEBUG("obj=%p, target=%s, offset=0x%x, size=%d, data=%p\n",
+			obj,
+			_mesa_lookup_enum_by_nr(target),
+			(unsigned int)offset,
+			(unsigned int)size,
+			data);
+
+	ctx->Driver.MapBuffer(ctx, target, GL_READ_ONLY_ARB, obj);
+	_mesa_memcpy(data, (GLubyte *)obj->Pointer + offset, size);
+	ctx->Driver.UnmapBuffer(ctx, target, obj);
+}
+
+static void *
+nouveauMapBuffer(GLcontext *ctx, GLenum target, GLenum access,
+		 struct gl_buffer_object *obj)
+{
+	nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+	nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+	DEBUG("obj=%p, target=%s, access=%s\n",
+			obj,
+			_mesa_lookup_enum_by_nr(target),
+			_mesa_lookup_enum_by_nr(access));
+
+	if (obj->Pointer) {
+		DEBUG("already mapped, return NULL\n");
+		return NULL;
+	}
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+	/* If GPU is accessing the data from VRAM, copy to faster AGP memory
+	 * before CPU access to the buffer.
+	 */
+	if (nbo->gpu_mem->type & NOUVEAU_MEM_FB) {
+		DEBUG("Data in VRAM, copying to AGP for CPU access\n");
+
+		/* This can happen if BufferData grows the GPU-access buffer */
+		if (nbo->cpu_mem && nbo->cpu_mem->size != nbo->gpu_mem->size) {
+			nouveau_mem_free(ctx, nbo->cpu_mem);
+			nbo->cpu_mem = NULL;
+		}
+
+		if (!nbo->cpu_mem) {
+			nbo->cpu_mem = nouveau_mem_alloc(ctx,
+							 NOUVEAU_MEM_AGP |
+							 NOUVEAU_MEM_MAPPED,
+							 nbo->gpu_mem->size,
+							 0);
+
+			/* Mark GPU data as modified, so it gets copied to
+			 * the new buffer */
+			nbo->gpu_dirty = GL_TRUE;
+		}
+
+		if (nbo->cpu_mem && nbo->gpu_dirty) {
+			nouveau_memformat_flat_emit(ctx, nbo->cpu_mem,
+							 nbo->gpu_mem,
+							 0, 0,
+							 nbo->gpu_mem->size);
+
+			nouveau_notifier_wait_nop(ctx,
+						  nmesa->syncNotifier,
+						  NvSubMemFormat);
+			nbo->gpu_dirty = GL_FALSE;
+		}
+
+		/* buffer isn't guaranteed to be up-to-date on the card now */
+		nbo->cpu_dirty = GL_TRUE;
+	}
+#endif
+
+	/* If the copy to AGP failed for some reason, just return a pointer
+	 * directly to vram..
+	 */
+	if (!nbo->cpu_mem) {
+		DEBUG("Returning direct pointer to VRAM\n");
+		nbo->cpu_mem   = nbo->gpu_mem;
+		nbo->cpu_dirty = GL_FALSE;
+	}
+
+	obj->Pointer = nbo->cpu_mem->map;
+	return obj->Pointer;
+}
+
+static GLboolean
+nouveauUnmapBuffer(GLcontext *ctx, GLenum target, struct gl_buffer_object *obj)
+{
+	nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+	nouveau_buffer_object *nbo = (nouveau_buffer_object *)obj;
+
+	DEBUG("obj=%p, target=%s\n", obj, _mesa_lookup_enum_by_nr(target));
+
+#ifdef ALLOW_MULTI_SUBCHANNEL
+	if (nbo->cpu_dirty && nbo->cpu_mem != nbo->gpu_mem) {
+		DEBUG("Copying potentially modified data back to GPU\n");
+
+		/* blit from GPU buffer -> CPU  buffer */
+		nouveau_memformat_flat_emit(ctx, nbo->gpu_mem, nbo->cpu_mem,
+		      			    0, 0, nbo->cpu_mem->size);
+
+		/* buffer is now up-to-date on the hardware (or rather, will
+		 * be by the time any other commands in this channel reference
+		 * the data.)
+		 */
+		nbo->cpu_dirty = GL_FALSE;
+
+		/* we can avoid this wait in some cases.. */
+		nouveau_notifier_wait_nop(ctx,
+					  nmesa->syncNotifier,
+					  NvSubMemFormat);
+
+		/* If it's likely CPU access to the buffer will occur often,
+		 * keep the cpu_mem around to avoid repeated allocs.
+		 */
+		if (obj->Usage != GL_DYNAMIC_DRAW_ARB) {
+
+			nouveau_mem_free(ctx, nbo->cpu_mem);
+			nbo->cpu_mem = NULL;
+		}
+	}
+#endif
+
+	obj->Pointer = NULL;
+	return GL_TRUE;
+}
+	  
+void
+nouveauInitBufferObjects(GLcontext *ctx)
+{
+	ctx->Driver.BindBuffer		= nouveauBindBuffer;
+	ctx->Driver.NewBufferObject	= nouveauNewBufferObject;
+	ctx->Driver.DeleteBuffer	= nouveauDeleteBuffer;
+	ctx->Driver.BufferData		= nouveauBufferData;
+	ctx->Driver.BufferSubData	= nouveauBufferSubData;
+	ctx->Driver.GetBufferSubData	= nouveauGetBufferSubData;
+	ctx->Driver.MapBuffer		= nouveauMapBuffer;
+	ctx->Driver.UnmapBuffer		= nouveauUnmapBuffer;
+}
+
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h
new file mode 100644
index 0000000..fccc349
--- /dev/null
+++ b/src/mesa/drivers/dri/nouveau/nouveau_bufferobj.h
@@ -0,0 +1,27 @@
+#ifndef __NOUVEAU_BUFFEROBJ_H__
+#define __NOUVEAU_BUFFEROBJ_H__
+
+#include "mtypes.h"
+#include "nouveau_buffers.h"
+
+typedef struct nouveau_buffer_object_t {
+	/* Base class, must be first */
+	struct gl_buffer_object mesa;
+
+	/* Memory used for GPU access to the buffer*/
+	nouveau_mem *		gpu_mem;
+	/* Buffer has been dirtied by the GPU */
+	GLboolean		gpu_dirty;
+
+	/* Memory used for CPU access to the buffer */
+	nouveau_mem *		cpu_mem;
+	/* Buffer has possibly been dirtied by the CPU */
+	GLboolean		cpu_dirty;
+} nouveau_buffer_object;
+
+extern uint32_t nouveau_bufferobj_gpu_ref(GLcontext *ctx, GLenum access,
+      					  struct gl_buffer_object *obj);
+
+extern void nouveauInitBufferObjects(GLcontext *ctx);
+
+#endif
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index bb67f72..79da46f 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -65,6 +65,7 @@ static const struct dri_debug_control de
 {
 	{ "shaders"   , DEBUG_SHADERS    },
 	{ "mem"       , DEBUG_MEM        },
+	{ "bufferobj" , DEBUG_BUFFEROBJ  },
 	{ NULL        , 0                }
 };
 
@@ -224,6 +225,7 @@ GLboolean nouveauCreateContext( const __
 			break;
 	}
 
+	nouveauInitBufferObjects(ctx);
 	if (!nouveauSyncInitFuncs(ctx))
 	   return GL_FALSE;
 	nmesa->hw_func.InitCard(nmesa);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
index b095207..134e2a4 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -218,6 +218,7 @@ extern int NOUVEAU_DEBUG;
 
 #define DEBUG_SHADERS	0x00000001
 #define DEBUG_MEM	0x00000002
+#define DEBUG_BUFFEROBJ 0x00000004
 
 #endif /* __NOUVEAU_CONTEXT_H__ */
 
diff-tree 1780fd4eeeef2358e929c23cfae2c348cb4a709e (from 885a7cc38d80366396f463a54ef4af00c9fd07ff)
Author: Ben Skeggs <darktama at iinet.net.au>
Date:   Wed Dec 27 15:54:30 2006 +1100

    nouveau: We'll need syncNotifier for NV_MEMORY_TO_MEMORY_FORMAT too.

diff --git a/src/mesa/drivers/dri/nouveau/nouveau_sync.c b/src/mesa/drivers/dri/nouveau/nouveau_sync.c
index e27101d..0bf20e7 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
 	 */
 	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;
 }
diff-tree 885a7cc38d80366396f463a54ef4af00c9fd07ff (from 2dd37534506e85351fb114c79fd6c994a9c355c0)
Author: Ben Skeggs <darktama at iinet.net.au>
Date:   Wed Dec 27 15:50:59 2006 +1100

    nouveau: add nouveau_mem_alloc/free debugging

diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
index e628dd5..b54f68f 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
@@ -71,6 +71,11 @@ nouveau_mem_free(GLcontext *ctx, nouveau
    nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
    drm_nouveau_mem_free_t memf;
 
+   if (NOUVEAU_DEBUG & DEBUG_MEM)  {
+      fprintf(stderr, "%s: type=0x%x, offset=0x%x, size=0x%x\n",
+	    __func__, mem->type, (GLuint)mem->offset, (GLuint)mem->size);
+   }
+
    if (mem->map)
       drmUnmap(mem->map, mem->size);
    memf.flags         = mem->type;
@@ -87,6 +92,11 @@ nouveau_mem_alloc(GLcontext *ctx, int ty
    nouveau_mem *mem;
    int ret;
 
+   if (NOUVEAU_DEBUG & DEBUG_MEM)  {
+      fprintf(stderr, "%s: requested: type=0x%x, size=0x%x, align=0x%x\n",
+	    __func__, type, (GLuint)size, align);
+   }
+
    mem = CALLOC(sizeof(nouveau_mem));
    if (!mem)
       return NULL;
@@ -104,6 +114,11 @@ nouveau_mem_alloc(GLcontext *ctx, int ty
    mem->offset = mema.region_offset;
    mem->type   = mema.flags;
 
+   if (NOUVEAU_DEBUG & DEBUG_MEM)  {
+      fprintf(stderr, "%s: actual: type=0x%x, offset=0x%x, size=0x%x\n",
+	    __func__, mem->type, (GLuint)mem->offset, (GLuint)mem->size);
+   }
+
    if (type & NOUVEAU_MEM_MAPPED)
       ret = drmMap(nmesa->driFd, mem->offset, mem->size, &mem->map);
    if (ret) {
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.c b/src/mesa/drivers/dri/nouveau/nouveau_context.c
index 3718900..bb67f72 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.c
@@ -63,8 +63,9 @@ int NOUVEAU_DEBUG = 0;
 
 static const struct dri_debug_control debug_control[] =
 {
-	{ "shaders", DEBUG_SHADERS },
-	{ NULL,    0 }
+	{ "shaders"   , DEBUG_SHADERS    },
+	{ "mem"       , DEBUG_MEM        },
+	{ NULL        , 0                }
 };
 
 #define need_GL_ARB_vertex_program
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h
index 0efbcce..b095207 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_context.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h
@@ -216,7 +216,8 @@ extern void nouveauCopySubBuffer(__DRIdr
 /* Debugging utils: */
 extern int NOUVEAU_DEBUG;
 
-#define DEBUG_SHADERS 0x00000001
+#define DEBUG_SHADERS	0x00000001
+#define DEBUG_MEM	0x00000002
 
 #endif /* __NOUVEAU_CONTEXT_H__ */
 
diff-tree 2dd37534506e85351fb114c79fd6c994a9c355c0 (from 7b59a424b519c37b7c94e4ea8c420794c6a0eb4c)
Author: Ben Skeggs <darktama at iinet.net.au>
Date:   Wed Dec 27 15:39:52 2006 +1100

    nouveau: record *actual* type of memory that was alloc'd, not the requested types.

diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
index 6d73e9f..e628dd5 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
@@ -91,7 +91,7 @@ nouveau_mem_alloc(GLcontext *ctx, int ty
    if (!mem)
       return NULL;
 
-   mema.flags     = mem->type = type;
+   mema.flags     = type;
    mema.size      = mem->size = size;
    mema.alignment = align;
    mem->map       = NULL;
@@ -102,6 +102,7 @@ nouveau_mem_alloc(GLcontext *ctx, int ty
       return NULL;
    }
    mem->offset = mema.region_offset;
+   mem->type   = mema.flags;
 
    if (type & NOUVEAU_MEM_MAPPED)
       ret = drmMap(nmesa->driFd, mem->offset, mem->size, &mem->map);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.h b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
index a8d85b2..d864551 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
@@ -19,8 +19,10 @@ extern void nouveau_mem_free(GLcontext *
 extern uint32_t nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem);
 
 extern GLboolean nouveau_memformat_flat_emit(GLcontext *ctx,
-      					     nouveau_mem *dst, nouveau_mem *src,
-					     GLuint dst_offset, GLuint src_offset,
+      					     nouveau_mem *dst,
+					     nouveau_mem *src,
+					     GLuint dst_offset,
+					     GLuint src_offset,
 					     GLuint size);
 
 typedef struct nouveau_renderbuffer_t {
diff-tree 7b59a424b519c37b7c94e4ea8c420794c6a0eb4c (from 297a35eb69382193a4cc9ba4b51619984a8969db)
Author: Ben Skeggs <darktama at iinet.net.au>
Date:   Wed Dec 27 15:38:09 2006 +1100

    nouveau: Typo

diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
index 92329e5..6d73e9f 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
@@ -33,7 +33,7 @@ nouveau_memformat_flat_emit(GLcontext *c
    }
 
    src_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaAGP;
-   dst_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaAGP;
+   dst_handle = (dst->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaAGP;
    src_offset += nouveau_mem_gpu_offset_get(ctx, src);
    dst_offset += nouveau_mem_gpu_offset_get(ctx, dst);
 
diff-tree 297a35eb69382193a4cc9ba4b51619984a8969db (from 2dccca57e4325e77d7b2f0a08835eeccc11892cb)
Author: Ben Skeggs <darktama at iinet.net.au>
Date:   Wed Dec 27 00:02:38 2006 +1100

    nouveau: Add simple wrapper for NV_MEMORY_TO_MEMORY_FORMAT.

diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
index f6a03ec..92329e5 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.c
@@ -5,6 +5,65 @@
 
 #include "nouveau_context.h"
 #include "nouveau_buffers.h"
+#include "nouveau_object.h"
+#include "nouveau_fifo.h"
+#include "nouveau_reg.h"
+#include "nouveau_msg.h"
+
+#define MAX_MEMFMT_LENGTH 32768
+
+/* Unstrided blit using NV_MEMORY_TO_MEMORY_FORMAT */
+GLboolean
+nouveau_memformat_flat_emit(GLcontext *ctx,
+      			    nouveau_mem *dst, nouveau_mem *src,
+			    GLuint dst_offset, GLuint src_offset,
+			    GLuint size)
+{
+   nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
+   uint32_t src_handle, dst_handle;
+   GLuint count;
+
+   if (src_offset + size > src->size) {
+      MESSAGE("src out of nouveau_mem bounds\n");
+      return GL_FALSE;
+   }
+   if (dst_offset + size > dst->size) {
+      MESSAGE("dst out of nouveau_mem bounds\n");
+      return GL_FALSE;
+   }
+
+   src_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaAGP;
+   dst_handle = (src->type & NOUVEAU_MEM_FB) ? NvDmaFB : NvDmaAGP;
+   src_offset += nouveau_mem_gpu_offset_get(ctx, src);
+   dst_offset += nouveau_mem_gpu_offset_get(ctx, dst);
+
+   BEGIN_RING_SIZE(NvSubMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_OBJECT_IN, 2);
+   OUT_RING       (src_handle);
+   OUT_RING       (dst_handle);
+
+   count = (size / MAX_MEMFMT_LENGTH) + ((size % MAX_MEMFMT_LENGTH) ? 1 : 0);
+
+   while (count--) {
+      GLuint length = (size > MAX_MEMFMT_LENGTH) ? MAX_MEMFMT_LENGTH : size;
+
+      BEGIN_RING_SIZE(NvSubMemFormat, NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+      OUT_RING       (src_offset);
+      OUT_RING       (dst_offset);
+      OUT_RING       (0); /* pitch in */
+      OUT_RING       (0); /* pitch out */
+      OUT_RING       (length); /* line length */
+      OUT_RING       (1); /* number of lines */
+      OUT_RING       ((1 << 8) /* dst_inc */ | (1 << 0) /* src_inc */);
+      OUT_RING       (0); /* buffer notify? */
+      FIRE_RING();
+
+      src_offset += length;
+      dst_offset += length;
+      size       -= length;
+   }
+
+   return GL_TRUE;
+}
 
 void
 nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem)
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_buffers.h b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
index bb297ad..a8d85b2 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_buffers.h
@@ -18,6 +18,11 @@ extern nouveau_mem *nouveau_mem_alloc(GL
 extern void nouveau_mem_free(GLcontext *ctx, nouveau_mem *mem);
 extern uint32_t nouveau_mem_gpu_offset_get(GLcontext *ctx, nouveau_mem *mem);
 
+extern GLboolean nouveau_memformat_flat_emit(GLcontext *ctx,
+      					     nouveau_mem *dst, nouveau_mem *src,
+					     GLuint dst_offset, GLuint src_offset,
+					     GLuint size);
+
 typedef struct nouveau_renderbuffer_t {
    struct gl_renderbuffer mesa; /* must be first! */
    __DRIdrawablePrivate  *dPriv;
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.c b/src/mesa/drivers/dri/nouveau/nouveau_object.c
index cf7284d..1558f29 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_object.c
+++ b/src/mesa/drivers/dri/nouveau/nouveau_object.c
@@ -52,10 +52,13 @@ void nouveauObjectInit(nouveauContextPtr
 	return;
 #endif
 
-/* We need to know vram size.. */
+/* We need to know vram size.. and AGP size (and even if the card is AGP..) */
 	nouveauCreateDmaObject( nmesa, NvDmaFB,
 				0, (256*1024*1024),
 				0 /*NV_DMA_TARGET_FB*/, 0 /*NV_DMA_ACCESS_RW*/);
+	nouveauCreateDmaObject( nmesa, NvDmaAGP,
+	      			nmesa->agp_phys, (128*1024*1024),
+				3 /* AGP */, 0 /* RW */);
 
 	nouveauCreateContextObject(nmesa, Nv3D, nmesa->screen->card->class_3d,
 	      			   0, 0, 0, 0);
@@ -63,6 +66,9 @@ void nouveauObjectInit(nouveauContextPtr
 	      			   0, 0, 0, 0);
 	nouveauCreateContextObject(nmesa, NvImageBlit, NV10_IMAGE_BLIT,
 	      			   NV_DMA_CONTEXT_FLAGS_PATCH_SRCCOPY, 0, 0, 0);
+	nouveauCreateContextObject(nmesa, NvMemFormat,
+	      			   NV_MEMORY_TO_MEMORY_FORMAT,
+	      			   0, 0, 0, 0);
 
 #ifdef ALLOW_MULTI_SUBCHANNEL
 	nouveauObjectOnSubchannel(nmesa, NvSubCtxSurf2D, NvCtxSurf2D);
@@ -75,6 +81,8 @@ void nouveauObjectInit(nouveauContextPtr
 	OUT_RING(NvCtxSurf2D);
 	BEGIN_RING_SIZE(NvSubImageBlit, NV10_IMAGE_BLIT_SET_OPERATION, 1);
 	OUT_RING(3); /* SRCCOPY */
+
+	nouveauObjectOnSubchannel(nmesa, NvSubMemFormat, NvMemFormat);
 #endif
 
 	nouveauObjectOnSubchannel(nmesa, NvSub3D, Nv3D);
diff --git a/src/mesa/drivers/dri/nouveau/nouveau_object.h b/src/mesa/drivers/dri/nouveau/nouveau_object.h
index 87f2dc9..d5fcc6d 100644
--- a/src/mesa/drivers/dri/nouveau/nouveau_object.h
+++ b/src/mesa/drivers/dri/nouveau/nouveau_object.h
@@ -11,6 +11,7 @@ enum DMAObjects {
 	Nv3D                    = 0x80000019,
 	NvCtxSurf2D		= 0x80000020,
 	NvImageBlit		= 0x80000021,
+	NvMemFormat		= 0x80000022,
 	NvDmaFB			= 0xD0FB0001,
 	NvDmaAGP		= 0xD0AA0001,
 	NvSyncNotify		= 0xD0000001
@@ -19,6 +20,7 @@ enum DMAObjects {
 enum DMASubchannel {
 	NvSubCtxSurf2D	= 0,
 	NvSubImageBlit	= 1,
+	NvSubMemFormat	= 2,
 	NvSub3D		= 7,
 };
 



More information about the mesa-commit mailing list