nouveau: upload and swizzle each mipmap level in turn
authorPatrice Mandin <patmandin@gmail.com>
Sun, 8 Feb 2009 15:42:56 +0000 (16:42 +0100)
committerPatrice Mandin <patmandin@gmail.com>
Sun, 8 Feb 2009 16:04:09 +0000 (17:04 +0100)
src/gallium/drivers/nv04/nv04_surface_2d.c

index b507e993f1efd6829c0d2cc8c1bde3716bb9c565..1892055418b00b78dee772f8c5ca1fa84e5a1739 100644 (file)
@@ -107,6 +107,7 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx,
        const unsigned sub_h = h > max_h ? max_h : h;
        unsigned cx = 0;
        unsigned cy = 0;
+       int i, offset = 0;
 
        /* POT or GTFO */
        assert(!(w & (w - 1)) && !(h & (h - 1)));
@@ -125,34 +126,43 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx,
        BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE, 1);
        OUT_RING  (chan, swzsurf->handle);
 
-       for (cy = 0; cy < h; cy += sub_h) {
-         for (cx = 0; cx < w; cx += sub_w) {
-           BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1);
-           OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(cx, cy) *
-                            dst->block.size, NOUVEAU_BO_GART |
-                            NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
-
-           BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
-           OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
-           OUT_RING  (chan, nv04_scaled_image_format(src->format));
-           OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
-           OUT_RING  (chan, 0);
-           OUT_RING  (chan, sub_h << 16 | sub_w);
-           OUT_RING  (chan, 0);
-           OUT_RING  (chan, sub_h << 16 | sub_w);
-           OUT_RING  (chan, 1 << 20);
-           OUT_RING  (chan, 1 << 20);
-
-           BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
-           OUT_RING  (chan, sub_h << 16 | sub_w);
-           OUT_RING  (chan, src->stride |
-                            NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
-                            NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
-           OUT_RELOCl(chan, src_bo, src->offset + cy * src->stride +
-                            cx * src->block.size, NOUVEAU_BO_GART |
-                            NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
-           OUT_RING  (chan, 0);
-         }
+       /* Upload, then swizzle each mipmap level in turn */
+       for (i=0; i<src->texture->last_level; i++) {
+
+               for (cy = 0; cy < h; cy += sub_h) {
+                 for (cx = 0; cx < w; cx += sub_w) {
+                   BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1);
+                   OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(cx, cy) *
+                                    dst->block.size + offset, NOUVEAU_BO_GART |
+                                    NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
+
+                   BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);
+                   OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE);
+                   OUT_RING  (chan, nv04_scaled_image_format(src->format));
+                   OUT_RING  (chan, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY);
+                   OUT_RING  (chan, 0);
+                   OUT_RING  (chan, sub_h << 16 | sub_w);
+                   OUT_RING  (chan, 0);
+                   OUT_RING  (chan, sub_h << 16 | sub_w);
+                   OUT_RING  (chan, 1 << 20);
+                   OUT_RING  (chan, 1 << 20);
+
+                   BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE, 4);
+                   OUT_RING  (chan, sub_h << 16 | sub_w);
+                   OUT_RING  (chan, src->stride |
+                                    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER |
+                                    NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE);
+                   OUT_RELOCl(chan, src_bo, src->offset + cy * src->stride +
+                                    cx * src->block.size + offset, NOUVEAU_BO_GART |
+                                    NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
+                   OUT_RING  (chan, 0);
+                 }
+               }
+
+               w >>= 1;
+               h >>= 1;
+               /* FIXME: need to know how many bytes per pixel */
+               offset += align(w * h * 2, 64);
        }
 
        return 0;