mesa: Remove target parameter from dd_function_table::MapBufferRange
[mesa.git] / src / mesa / drivers / dri / nouveau / nv04_surface.c
index e8a5409fbde5f2bc28ddb428102ef42ded6eb8ce..c1eda8b7f37042db159084de7c4dfefcc8027018 100644 (file)
  */
 
 #include "nouveau_driver.h"
-#include "nouveau_class.h"
+#include "nv_object.xml.h"
+#include "nv_m2mf.xml.h"
+#include "nv01_2d.xml.h"
+#include "nv04_3d.xml.h"
 #include "nouveau_context.h"
 #include "nouveau_util.h"
 #include "nv04_driver.h"
@@ -191,7 +194,7 @@ sifm_format(gl_format format)
 }
 
 static void
-nv04_surface_copy_swizzle(GLcontext *ctx,
+nv04_surface_copy_swizzle(struct gl_context *ctx,
                          struct nouveau_surface *dst,
                          struct nouveau_surface *src,
                          int dx, int dy, int sx, int sy,
@@ -214,11 +217,6 @@ nv04_surface_copy_swizzle(GLcontext *ctx,
        assert(_mesa_is_pow_two(dst->width) &&
               _mesa_is_pow_two(dst->height));
 
-        /* If area is too large to copy in one shot we must copy it in
-        * POT chunks to meet alignment requirements */
-       assert(sub_w == w || _mesa_is_pow_two(w));
-       assert(sub_h == h || _mesa_is_pow_two(h));
-
        nouveau_bo_marko(bctx, sifm, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE,
                         src->bo, bo_flags | NOUVEAU_BO_RD);
        nouveau_bo_marko(bctx, swzsurf, NV04_SWIZZLED_SURFACE_DMA_IMAGE,
@@ -255,7 +253,7 @@ nv04_surface_copy_swizzle(GLcontext *ctx,
 
                        BEGIN_RING(chan, sifm,
                                   NV03_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
-                       OUT_RING(chan, sub_h << 16 | sub_w);
+                       OUT_RING(chan, align(sub_h, 2) << 16 | align(sub_w, 2));
                        OUT_RING(chan, src->pitch  |
                                 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
                                 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
@@ -274,7 +272,7 @@ nv04_surface_copy_swizzle(GLcontext *ctx,
 }
 
 static void
-nv04_surface_copy_m2mf(GLcontext *ctx,
+nv04_surface_copy_m2mf(struct gl_context *ctx,
                       struct nouveau_surface *dst,
                       struct nouveau_surface *src,
                       int dx, int dy, int sx, int sy,
@@ -288,9 +286,9 @@ nv04_surface_copy_m2mf(GLcontext *ctx,
        unsigned dst_offset = dst->offset + dy * dst->pitch + dx * dst->cpp;
        unsigned src_offset = src->offset + sy * src->pitch + sx * src->cpp;
 
-       nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN,
+       nouveau_bo_marko(bctx, m2mf, NV04_M2MF_DMA_BUFFER_IN,
                         src->bo, bo_flags | NOUVEAU_BO_RD);
-       nouveau_bo_marko(bctx, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_OUT,
+       nouveau_bo_marko(bctx, m2mf, NV04_M2MF_DMA_BUFFER_OUT,
                         dst->bo, bo_flags | NOUVEAU_BO_WR);
 
        while (h) {
@@ -298,7 +296,7 @@ nv04_surface_copy_m2mf(GLcontext *ctx,
 
                MARK_RING(chan, 9, 2);
 
-               BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8);
+               BEGIN_RING(chan, m2mf, NV04_M2MF_OFFSET_IN, 8);
                OUT_RELOCl(chan, src->bo, src_offset,
                           bo_flags | NOUVEAU_BO_RD);
                OUT_RELOCl(chan, dst->bo, dst_offset,
@@ -321,27 +319,109 @@ nv04_surface_copy_m2mf(GLcontext *ctx,
                FIRE_RING(chan);
 }
 
+typedef unsigned (*get_offset_t)(struct nouveau_surface *s,
+                                unsigned x, unsigned y);
+
+static unsigned
+get_linear_offset(struct nouveau_surface *s, unsigned x, unsigned y)
+{
+       return x * s->cpp + y * s->pitch;
+}
+
+static unsigned
+get_swizzled_offset(struct nouveau_surface *s, unsigned x, unsigned y)
+{
+       unsigned k = log2i(MIN2(s->width, s->height));
+
+       unsigned u = (x & 0x001) << 0 |
+               (x & 0x002) << 1 |
+               (x & 0x004) << 2 |
+               (x & 0x008) << 3 |
+               (x & 0x010) << 4 |
+               (x & 0x020) << 5 |
+               (x & 0x040) << 6 |
+               (x & 0x080) << 7 |
+               (x & 0x100) << 8 |
+               (x & 0x200) << 9 |
+               (x & 0x400) << 10 |
+               (x & 0x800) << 11;
+
+       unsigned v = (y & 0x001) << 1 |
+               (y & 0x002) << 2 |
+               (y & 0x004) << 3 |
+               (y & 0x008) << 4 |
+               (y & 0x010) << 5 |
+               (y & 0x020) << 6 |
+               (y & 0x040) << 7 |
+               (y & 0x080) << 8 |
+               (y & 0x100) << 9 |
+               (y & 0x200) << 10 |
+               (y & 0x400) << 11 |
+               (y & 0x800) << 12;
+
+       return s->cpp * (((u | v) & ~(~0 << 2*k)) |
+                        (x & (~0 << k)) << k |
+                        (y & (~0 << k)) << k);
+}
+
+static void
+nv04_surface_copy_cpu(struct gl_context *ctx,
+                     struct nouveau_surface *dst,
+                     struct nouveau_surface *src,
+                     int dx, int dy, int sx, int sy,
+                     int w, int h)
+{
+       int x, y;
+       get_offset_t get_dst = (dst->layout == SWIZZLED ?
+                               get_swizzled_offset : get_linear_offset);
+       get_offset_t get_src = (src->layout == SWIZZLED ?
+                               get_swizzled_offset : get_linear_offset);
+       void *dp, *sp;
+
+       nouveau_bo_map(dst->bo, NOUVEAU_BO_WR);
+       nouveau_bo_map(src->bo, NOUVEAU_BO_RD);
+
+       dp = dst->bo->map + dst->offset;
+       sp = src->bo->map + src->offset;
+
+       for (y = 0; y < h; y++) {
+               for (x = 0; x < w; x++) {
+                       memcpy(dp + get_dst(dst, dx + x, dy + y),
+                              sp + get_src(src, sx + x, sy + y), dst->cpp);
+               }
+       }
+
+       nouveau_bo_unmap(src->bo);
+       nouveau_bo_unmap(dst->bo);
+}
+
 void
-nv04_surface_copy(GLcontext *ctx,
+nv04_surface_copy(struct gl_context *ctx,
                  struct nouveau_surface *dst,
                  struct nouveau_surface *src,
                  int dx, int dy, int sx, int sy,
                  int w, int h)
 {
-       /* Setup transfer to swizzle the texture to vram if needed */
-        if (src->layout != SWIZZLED &&
-           dst->layout == SWIZZLED &&
-           dst->width > 2 && dst->height > 1) {
-               nv04_surface_copy_swizzle(ctx, dst, src,
-                                         dx, dy, sx, sy, w, h);
+       /* Linear texture copy. */
+       if ((src->layout == LINEAR && dst->layout == LINEAR) ||
+           dst->width <= 2 || dst->height <= 1) {
+               nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h);
+               return;
+       }
+
+       /* Swizzle using sifm+swzsurf. */
+        if (src->layout == LINEAR && dst->layout == SWIZZLED &&
+           dst->cpp != 1 && !(dst->offset & 63)) {
+               nv04_surface_copy_swizzle(ctx, dst, src, dx, dy, sx, sy, w, h);
                return;
        }
 
-       nv04_surface_copy_m2mf(ctx, dst, src, dx, dy, sx, sy, w, h);
+       /* Fallback to CPU copy. */
+       nv04_surface_copy_cpu(ctx, dst, src, dx, dy, sx, sy, w, h);
 }
 
 void
-nv04_surface_fill(GLcontext *ctx,
+nv04_surface_fill(struct gl_context *ctx,
                  struct nouveau_surface *dst,
                  unsigned mask, unsigned value,
                  int dx, int dy, int w, int h)
@@ -383,7 +463,7 @@ nv04_surface_fill(GLcontext *ctx,
 }
 
 void
-nv04_surface_takedown(GLcontext *ctx)
+nv04_surface_takedown(struct gl_context *ctx)
 {
        struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
 
@@ -398,7 +478,7 @@ nv04_surface_takedown(GLcontext *ctx)
 }
 
 GLboolean
-nv04_surface_init(GLcontext *ctx)
+nv04_surface_init(struct gl_context *ctx)
 {
        struct nouveau_channel *chan = context_chan(ctx);
        struct nouveau_hw_state *hw = &to_nouveau_context(ctx)->hw;
@@ -411,12 +491,11 @@ nv04_surface_init(GLcontext *ctx)
                goto fail;
 
        /* Memory to memory format. */
-       ret = nouveau_grobj_alloc(chan, handle++, NV04_MEMORY_TO_MEMORY_FORMAT,
-                                 &hw->m2mf);
+       ret = nouveau_grobj_alloc(chan, handle++, NV04_M2MF, &hw->m2mf);
        if (ret)
                goto fail;
 
-       BEGIN_RING(chan, hw->m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
+       BEGIN_RING(chan, hw->m2mf, NV04_M2MF_DMA_NOTIFY, 1);
        OUT_RING  (chan, hw->ntfy->handle);
 
        /* Context surfaces 2D. */