From 1ee3bcfff08599961c69549a1ad699c02df49bec Mon Sep 17 00:00:00 2001 From: Patrice Mandin Date: Mon, 27 Jul 2009 10:57:53 +0200 Subject: nouveau: swizzle a single row or column, doing it one pixel at a time --- src/gallium/drivers/nv04/nv04_surface_2d.c | 108 +++++++++++++++++++++-------- 1 file changed, 80 insertions(+), 28 deletions(-) (limited to 'src/gallium') diff --git a/src/gallium/drivers/nv04/nv04_surface_2d.c b/src/gallium/drivers/nv04/nv04_surface_2d.c index aba40cfaff..bbbcb54c46 100644 --- a/src/gallium/drivers/nv04/nv04_surface_2d.c +++ b/src/gallium/drivers/nv04/nv04_surface_2d.c @@ -209,6 +209,43 @@ nv04_surface_copy_m2mf(struct nv04_surface_2d *ctx, return 0; } +static int +nv04_surface_copy_m2mf_swizzle(struct nv04_surface_2d *ctx, + struct pipe_surface *dst, int dx, int dy, + struct pipe_surface *src, int sx, int sy) +{ + struct nouveau_channel *chan = ctx->m2mf->channel; + struct nouveau_grobj *m2mf = ctx->m2mf; + struct nouveau_bo *src_bo = nouveau_bo(ctx->buf(src)); + struct nouveau_bo *dst_bo = nouveau_bo(ctx->buf(dst)); + unsigned src_pitch = ((struct nv04_surface *)src)->pitch; + unsigned dst_pitch = ((struct nv04_surface *)dst)->pitch; + unsigned dst_offset = dst->offset + nv04_swizzle_bits(dx, dy) * + dst->texture->block.size; + unsigned src_offset = src->offset + sy * src_pitch + + sx * src->texture->block.size; + + BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN, 2); + OUT_RELOCo(chan, src_bo, + NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_RD); + OUT_RELOCo(chan, dst_bo, + NOUVEAU_BO_GART | NOUVEAU_BO_VRAM | NOUVEAU_BO_WR); + + BEGIN_RING(chan, m2mf, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + OUT_RELOCl(chan, src_bo, src_offset, + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD); + OUT_RELOCl(chan, dst_bo, dst_offset, + NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_WR); + OUT_RING (chan, src_pitch); + OUT_RING (chan, dst_pitch); + OUT_RING (chan, 1 * src->texture->block.size); + OUT_RING (chan, 1); + OUT_RING (chan, 0x0101); + OUT_RING (chan, 0); + + return 0; +} + static int nv04_surface_copy_blit(struct nv04_surface_2d *ctx, struct pipe_surface *dst, int dx, int dy, struct pipe_surface *src, int sx, int sy, @@ -258,42 +295,57 @@ nv04_surface_copy(struct nv04_surface_2d *ctx, struct pipe_surface *dst, assert(src->format == dst->format); /* Setup transfer to swizzle the texture to vram if needed */ - if (src_linear && !dst_linear && w > 1 && h > 1) { - int potWidth = 1<potHeight ? potHeight : potWidth); + if (src_linear && !dst_linear) { int x,y; - /* top left is always POT, but we can only swizzle squares */ - for (y=0; y1) && (h>1)) { + int potWidth = 1<potHeight ? potHeight : potWidth); + + /* top left is always POT, but we can only swizzle squares */ + for (y=0; y0) { + /* top right */ + if (remainWidth>0) { nv04_surface_copy(ctx, dst, dx+potWidth, dy, - src, sx+potWidth, sy, - remainWidth, potHeight); - } + src, sx+potWidth, sy, + remainWidth, potHeight); + } - /* bottom left */ - if (remainHeight>0) { - nv04_surface_copy(ctx, dst, dx, dy+potHeight, + /* bottom left */ + if (remainHeight>0) { + nv04_surface_copy(ctx, dst, dx, dy+potHeight, src, sx, sy+potHeight, - potWidth, remainHeight); - } + potWidth, remainHeight); + } - /* bottom right */ - if ((remainWidth>0) && (remainHeight>0)) { - nv04_surface_copy(ctx, dst, dx+potWidth, dy+potHeight, - src, sx+potWidth, sy+potHeight, - remainWidth, remainHeight); + /* bottom right */ + if ((remainWidth>0) && (remainHeight>0)) { + nv04_surface_copy(ctx, dst, dx+potWidth, dy+potHeight, + src, sx+potWidth, sy+potHeight, + remainWidth, remainHeight); + } + } else if (w==1) { + /* We have a column to copy to a swizzled texture */ + for (y=0; y