summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLuca Barbieri <[email protected]>2009-12-26 07:35:17 +0100
committerYounes Manton <[email protected]>2009-12-28 17:59:01 -0500
commitcb9214f33030e1f482d59049c239f20061d24ad8 (patch)
tree3c9cb08f5e13cf027ec2b89724a39dc7992c1f23 /src
parent3a0c527bd03c0a4e637a1dcde11f0fb6129c07f6 (diff)
nouveau: Fix swizzling for copies to rectangular textures
nVidia hardware seems to swizzle rectangular texture (with width != height) coordinates by swizzling the lower bits and then adding the higher bits from the larger dimension. However, nv04_swizzle_bits ignores width and height and just interleaves everything. This causes problems with rectangular POT textures with height or width 2048 or 4096 (but not 2048x1024 where it works by chance) since the driver swizzles them in 1024x1024 chunks and gets the start position for the non-first chunks wrong. The following patch seems to fix those problems.
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/nv04/nv04_surface_2d.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.c b/src/gallium/drivers/nv04/nv04_surface_2d.c
index 819f45e96ad..40b538fd71b 100644
--- a/src/gallium/drivers/nv04/nv04_surface_2d.c
+++ b/src/gallium/drivers/nv04/nv04_surface_2d.c
@@ -77,7 +77,7 @@ nv04_scaled_image_format(enum pipe_format format)
}
static INLINE unsigned
-nv04_swizzle_bits(unsigned x, unsigned y)
+nv04_swizzle_bits_square(unsigned x, unsigned y)
{
unsigned u = (x & 0x001) << 0 |
(x & 0x002) << 1 |
@@ -107,6 +107,15 @@ nv04_swizzle_bits(unsigned x, unsigned y)
return v | u;
}
+/* rectangular swizzled textures are linear concatenations of swizzled square tiles */
+static INLINE unsigned
+nv04_swizzle_bits(unsigned x, unsigned y, unsigned w, unsigned h)
+{
+ unsigned s = MIN2(w, h);
+ unsigned m = s - 1;
+ return (((x | y) & ~m) * s) | nv04_swizzle_bits_square(x & m, y & m);
+}
+
static int
nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx,
struct pipe_surface *dst, int dx, int dy,
@@ -159,10 +168,10 @@ nv04_surface_copy_swizzle(struct nv04_surface_2d *ctx,
sub_w = MIN2(sub_w, w - x);
/* Must be 64-byte aligned */
- assert(!((dst->offset + nv04_swizzle_bits(dx+x, dy+y) * util_format_get_blocksize(dst->texture->format)) & 63));
+ assert(!((dst->offset + nv04_swizzle_bits(dx+x, dy+y, w, h) * util_format_get_blocksize(dst->texture->format)) & 63));
BEGIN_RING(chan, swzsurf, NV04_SWIZZLED_SURFACE_OFFSET, 1);
- OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(dx+x, dy+y) * util_format_get_blocksize(dst->texture->format),
+ OUT_RELOCl(chan, dst_bo, dst->offset + nv04_swizzle_bits(dx+x, dy+y, w, h) * util_format_get_blocksize(dst->texture->format),
NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
BEGIN_RING(chan, sifm, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION, 9);