nouveau: Add simple wrapper for NV_MEMORY_TO_MEMORY_FORMAT.
authorBen Skeggs <darktama@iinet.net.au>
Tue, 26 Dec 2006 13:02:38 +0000 (00:02 +1100)
committerBen Skeggs <darktama@iinet.net.au>
Wed, 27 Dec 2006 12:53:25 +0000 (23:53 +1100)
src/mesa/drivers/dri/nouveau/nouveau_buffers.c
src/mesa/drivers/dri/nouveau/nouveau_buffers.h
src/mesa/drivers/dri/nouveau/nouveau_object.c
src/mesa/drivers/dri/nouveau/nouveau_object.h

index f6a03ecd9cf1f10a0ef2019d6ff4bcdfee5da8cf..92329e514f7a10f89540247f174e076736788ae1 100644 (file)
@@ -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)
index bb297ad5587310327f17c6c98087d59b8900dfcf..a8d85b279bff866042f1006e745ff638e8edd06b 100644 (file)
@@ -18,6 +18,11 @@ extern nouveau_mem *nouveau_mem_alloc(GLcontext *ctx, int type,
 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;
index cf7284d2d5496100e417b26ac729adee77dbd337..1558f2963df4724eb31746f23f15ec2c22144eca 100644 (file)
@@ -52,10 +52,13 @@ void nouveauObjectInit(nouveauContextPtr nmesa)
        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 nmesa)
                                   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 nmesa)
        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);
index 87f2dc9ae75cc114cb5dd197fbede73396081af5..d5fcc6df8d2aa24b29a699e4c23cbe1f81decece 100644 (file)
@@ -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,
 };