nvfx: move 2D format selection logic to 2D code
authorLuca Barbieri <luca@luca-barbieri.com>
Sat, 4 Sep 2010 18:16:54 +0000 (20:16 +0200)
committerLuca Barbieri <luca@luca-barbieri.com>
Sat, 4 Sep 2010 20:45:21 +0000 (22:45 +0200)
src/gallium/drivers/nvfx/nv04_2d.c
src/gallium/drivers/nvfx/nv04_2d.h
src/gallium/drivers/nvfx/nvfx_surface.c

index bc6012f013d110c3eeab37e0b587efbcd61dd93e..407f435d0514e2a99cdaf156fc61cb7c0232fb28 100644 (file)
@@ -725,15 +725,58 @@ ms:
        nouveau_bo_unmap(dst->bo);
 }
 
+static inline int
+nv04_region_cs2d_format(struct nv04_region* rgn)
+{
+       switch(rgn->bpps) {
+       case 0:
+               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
+       case 1:
+               if(rgn->one_bits >= 1)
+                       return NV04_CONTEXT_SURFACES_2D_FORMAT_X1R5G5B5_X1R5G5B5;
+               else
+                       return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
+       case 2:
+               if(rgn->one_bits >= 8)
+                       return NV04_CONTEXT_SURFACES_2D_FORMAT_X8R8G8B8_X8R8G8B8;
+               else
+                       return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
+       default:
+               return -1;
+       }
+}
+
+static inline int
+nv04_region_sifm_format(struct nv04_region* rgn)
+{
+       switch(rgn->bpps) {
+       case 0:
+               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8;
+       case 1:
+               if(rgn->one_bits >= 1)
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X1R5G5B5;
+               else
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
+       case 2:
+               if(rgn->one_bits >= 8)
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
+               else
+                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
+       default:
+               return -1;
+       }
+}
 static void
 nv04_region_copy_swizzle(struct nv04_2d_context *ctx,
                          struct nv04_region* dst,
                          struct nv04_region* src,
-                         int w, int h, int cs2d_format, int sifm_format)
+                         int w, int h)
 {
        struct nouveau_channel *chan = ctx->swzsurf->channel;
        struct nouveau_grobj *swzsurf = ctx->swzsurf;
        struct nouveau_grobj *sifm = ctx->sifm;
+       int cs2d_format = nv04_region_cs2d_format(dst);
+       int sifm_format = nv04_region_sifm_format(src);
        /* Max width & height may not be the same on all HW, but must be POT */
        unsigned max_shift = 10;
        unsigned cw = 1 << max_shift;
@@ -951,11 +994,12 @@ nv04_region_copy_m2mf(struct nv04_2d_context *ctx, struct nv04_region *dst, stru
 }
 
 static inline void
-nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src, int w, int h, int format)
+nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src, int w, int h)
 {
        struct nouveau_channel *chan = ctx->surf2d->channel;
        struct nouveau_grobj *surf2d = ctx->surf2d;
        struct nouveau_grobj *blit = ctx->blit;
+       int cs2d_format = nv04_region_cs2d_format(dst);
 
 #ifdef NV04_REGION_DEBUG
        fprintf(stderr, "\tRGN_COPY_BLIT [%i, %i: %i] ", w, h, dst->bpps);
@@ -976,7 +1020,7 @@ nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, stru
        OUT_RELOCo(chan, src->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
        OUT_RELOCo(chan, dst->bo, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
        BEGIN_RING(chan, surf2d, NV04_CONTEXT_SURFACES_2D_FORMAT, 4);
-       OUT_RING  (chan, format);
+       OUT_RING  (chan, cs2d_format);
        OUT_RING  (chan, (dst->pitch << 16) | src->pitch);
        OUT_RELOCl(chan, src->bo, src->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
        OUT_RELOCl(chan, dst->bo, dst->offset, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
@@ -1003,12 +1047,12 @@ nv04_region_copy_blit(struct nv04_2d_context *ctx, struct nv04_region* dst, stru
 // dst and src may be modified, and the possibly modified version should be passed to nv04_region_cpu if necessary
 int
 nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct nv04_region* src,
-               int w, int h, int cs2d_format, int sifm_format, int dst_to_gpu, int src_on_gpu)
+               int w, int h, int dst_to_gpu, int src_on_gpu)
 {
        assert(src->bpps == dst->bpps);
 
 #ifdef NV04_REGION_DEBUG
-       fprintf(stderr, "RGN_COPY%s [%i, %i: %i] ", (cs2d_format >= 0) ? "_2D" : "_NO2D", w, h, dst->bpps);
+       fprintf(stderr, "RGN_COPY [%i, %i: %i] ", w, h, dst->bpps);
        for(int i = 0; i < 2; ++i)
        {
                int gpu = i ? src_on_gpu : dst_to_gpu;
@@ -1061,7 +1105,7 @@ nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct
        {
                if (!dst->pitch)
                {
-                       if(cs2d_format < 0 || sifm_format < 0 || !dst_to_gpu)
+                       if(!dst_to_gpu)
                        {
 #ifdef NV04_REGION_DEBUG
                                fprintf(stderr, "\tCOPY_ENG3D\n");
@@ -1072,7 +1116,7 @@ nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct
                        {
                                assert(!nv04_region_align(dst, w, h, 6));
 
-                               nv04_region_copy_swizzle(ctx, dst, src, w, h, cs2d_format, sifm_format);
+                               nv04_region_copy_swizzle(ctx, dst, src, w, h);
                                return 0;
                        }
                }
@@ -1081,16 +1125,20 @@ nv04_region_copy_2d(struct nv04_2d_context *ctx, struct nv04_region* dst, struct
                        /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
                         * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
                         * TODO: is this also true for the source? possibly not
+                        * TODO: should we just always use m2mf?
+                        * TODO: if not, add support for multiple operations to copy_blit
                         */
 
-                       if ((cs2d_format < 0)
-                               || !dst_to_gpu
+                       if (!dst_to_gpu
+                               || w > 2047
+                               || h > 2047
+                               || (w & 1)
                                || nv04_region_align(src, w, h, 6)
                                || nv04_region_align(dst, w, h, 6)
                                )
                                nv04_region_copy_m2mf(ctx, dst, src, w, h);
                        else
-                               nv04_region_copy_blit(ctx, dst, src, w, h, cs2d_format);
+                               nv04_region_copy_blit(ctx, dst, src, w, h);
 
                        return 0;
                }
@@ -1112,26 +1160,25 @@ nv04_region_fill_gdirect(struct nv04_2d_context *ctx, struct nv04_region* dst, i
        assert(!(dst->pitch & 63) && dst->pitch);
        nv04_region_assert(dst, w, h);
 
-       if(dst->bpps == 0)
+       switch(dst->bpps)
        {
+       case 0:
                gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
                cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
-       }
-       else if(dst->bpps == 1)
-       {
+               break;
+       case 1:
                gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5;
                cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y16;
-       }
-       else if(dst->bpps == 2)
-       {
+               break;
+       case 2:
                gdirect_format = NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8;
                cs2d_format = NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
-       }
-       else
-       {
+               break;
+       default:
                assert(0);
                gdirect_format = 0;
                cs2d_format = 0;
+               break;
        }
 
        MARK_RING (chan, 15, 4);
index e7d872a2be666f87446b003a3d45acfbf50d27f1..00ee5bc0b235e2fdfb5e45a150c92e40760e13eb 100644 (file)
@@ -43,6 +43,7 @@ struct nv04_region {
        int offset;
        unsigned pitch; // 0 -> swizzled
        unsigned bpps; // bpp shift (0, 1, 2; 3, 4 for fp/compressed)
+       unsigned one_bits; // number of high bits read and written as ones (for "no-alpha" optimization)
        unsigned x, y, z;
        unsigned w, h, d;
 };
@@ -95,7 +96,6 @@ int
 nv04_region_copy_2d(struct nv04_2d_context *ctx,
                struct nv04_region* dst, struct nv04_region* src,
                int w, int h,
-               int cs2d_format, int sifm_format,
                int dst_to_gpu, int src_on_gpu);
 
 int
index 0255e3f6306d6232236fb25e28f1cacd79789609..e0c85cc629de61cf4929f996245f4c0c92e755cd 100644 (file)
@@ -48,6 +48,8 @@ nvfx_region_set_format(struct nv04_region* rgn, enum pipe_format format)
 {
        unsigned bits = util_format_get_blocksizebits(format);
        unsigned shift = 0;
+       rgn->one_bits = 0;
+
        switch(bits)
        {
        case 8:
@@ -55,9 +57,13 @@ nvfx_region_set_format(struct nv04_region* rgn, enum pipe_format format)
                break;
        case 16:
                rgn->bpps = 1;
+               if(format == PIPE_FORMAT_B5G5R5X1_UNORM)
+                       rgn->one_bits = 1;
                break;
        case 32:
                rgn->bpps = 2;
+               if(format == PIPE_FORMAT_R8G8B8X8_UNORM || format == PIPE_FORMAT_B8G8R8X8_UNORM)
+                       rgn->one_bits = 8;
                break;
        case 64:
                rgn->bpps = 2;
@@ -149,48 +155,6 @@ nvfx_region_init_for_subresource(struct nv04_region* rgn, struct pipe_resource*
                nv04_region_try_to_linearize(rgn);
 }
 
-// TODO: actually test this for all formats, it's probably wrong for some...
-
-static INLINE int
-nvfx_surface_format(enum pipe_format format)
-{
-       switch(util_format_get_blocksize(format)) {
-       case 1:
-               return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8;
-       case 2:
-               //return NV04_CONTEXT_SURFACES_2D_FORMAT_Y16;
-               return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5;
-       case 4:
-               //if(format == PIPE_FORMAT_B8G8R8X8_UNORM || format == PIPE_FORMAT_B8G8R8A8_UNORM)
-                       return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8;
-               //else
-               //      return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32;
-       default:
-               return -1;
-       }
-}
-
-static INLINE int
-nv04_scaled_image_format(enum pipe_format format)
-{
-       switch(util_format_get_blocksize(format)) {
-       case 1:
-               return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_Y8;
-       case 2:
-               //if(format == PIPE_FORMAT_B5G5R5A1_UNORM)
-               //      return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5;
-               //else
-                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5;
-       case 4:
-               if(format == PIPE_FORMAT_B8G8R8X8_UNORM)
-                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8;
-               else
-                       return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8;
-       default:
-               return -1;
-       }
-}
-
 // don't save index buffer because blitter doesn't setit
 static struct blitter_context*
 nvfx_get_blitter(struct pipe_context* pipe, int copy)
@@ -284,10 +248,7 @@ nvfx_resource_copy_region(struct pipe_context *pipe,
        if((!dst_to_gpu || !src_on_gpu) && small)
                ret = -1; /* use the CPU */
        else
-               ret = nv04_region_copy_2d(ctx, &dst, &src, w, h,
-                       dstr->target == PIPE_BUFFER ? -1 : nvfx_surface_format(dstr->format),
-                       dstr->target == PIPE_BUFFER ? -1 : nv04_scaled_image_format(dstr->format),
-                       dst_to_gpu, src_on_gpu);
+               ret = nv04_region_copy_2d(ctx, &dst, &src, w, h, dst_to_gpu, src_on_gpu);
        if(!ret)
        {}
        else if(ret > 0 && dstr->bind & PIPE_BIND_RENDER_TARGET && srcr->bind & PIPE_BIND_SAMPLER_VIEW)