diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/drivers/nvfx/nv04_2d.c | 87 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nv04_2d.h | 2 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_surface.c | 53 |
3 files changed, 75 insertions, 67 deletions
diff --git a/src/gallium/drivers/nvfx/nv04_2d.c b/src/gallium/drivers/nvfx/nv04_2d.c index bc6012f013..407f435d05 100644 --- a/src/gallium/drivers/nvfx/nv04_2d.c +++ b/src/gallium/drivers/nvfx/nv04_2d.c @@ -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); diff --git a/src/gallium/drivers/nvfx/nv04_2d.h b/src/gallium/drivers/nvfx/nv04_2d.h index e7d872a2be..00ee5bc0b2 100644 --- a/src/gallium/drivers/nvfx/nv04_2d.h +++ b/src/gallium/drivers/nvfx/nv04_2d.h @@ -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 diff --git a/src/gallium/drivers/nvfx/nvfx_surface.c b/src/gallium/drivers/nvfx/nvfx_surface.c index 0255e3f630..e0c85cc629 100644 --- a/src/gallium/drivers/nvfx/nvfx_surface.c +++ b/src/gallium/drivers/nvfx/nvfx_surface.c @@ -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) |