diff options
author | Luca Barbieri <[email protected]> | 2010-08-07 03:47:25 +0200 |
---|---|---|
committer | Luca Barbieri <[email protected]> | 2010-08-21 20:42:14 +0200 |
commit | 73b7c6fb336ad3e717f8e961f4e2df761e94cd2f (patch) | |
tree | 32c08325837d6441c1b6a33ce0fea1d386312c85 | |
parent | 4e2080a86e0cbb93c72bbf4acace53867fac8276 (diff) |
nvfx: refactor sampling code, add support for swizzles and depth tex
This is a significant refactoring of the sampling code that:
- Moves all generic functions in nvfx_fragtex.c
- Adds a driver-specific sampler view structure and uses it to
precompute texture setup as it should be done
- Unifies a bit more of code between nv30 and nv40
- Adds support for sampler view swizzles
- Support for specifying as sampler view format different from the
resource one (only trivially)
- Support for sampler view specification of first and last level
- Support for depth textures on nv30, both for reading depth and
for compare
- Support for sRGB textures
- Unifies the format table between nv30 and nv40
- Expands the format table to include essentially all supportable formats
except mixed sign and "autonormal" formats
- Fixes the "is format supported" logic, which was quite broken, and
makes it use the format table
Only tested on nv30 currently.
-rw-r--r-- | src/gallium/drivers/nouveau/nouveau_class.h | 4 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nv30_fragtex.c | 174 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nv40_fragtex.c | 166 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_context.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_context.h | 12 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_fragtex.c | 295 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_screen.c | 64 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_state.c | 112 | ||||
-rw-r--r-- | src/gallium/drivers/nvfx/nvfx_tex.h | 90 |
9 files changed, 525 insertions, 393 deletions
diff --git a/src/gallium/drivers/nouveau/nouveau_class.h b/src/gallium/drivers/nouveau/nouveau_class.h index adfdd37b1b6..685fa00b455 100644 --- a/src/gallium/drivers/nouveau/nouveau_class.h +++ b/src/gallium/drivers/nouveau/nouveau_class.h @@ -6328,6 +6328,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NV34TCL_TX_FORMAT_FORMAT_R8G8B8_RECT 0x00001e00 #define NV34TCL_TX_FORMAT_FORMAT_A8L8_RECT 0x00002000 #define NV34TCL_TX_FORMAT_FORMAT_DSDT8 0x00002800 +#define NV34TCL_TX_FORMAT_FORMAT_Z24 0x2a00 +#define NV34TCL_TX_FORMAT_FORMAT_Z24_RECT 0x2b00 /* XXX: guess! */ +#define NV34TCL_TX_FORMAT_FORMAT_Z16 0x2c00 +#define NV34TCL_TX_FORMAT_FORMAT_Z16_RECT 0x2d00 /* XXX: guess! */ #define NV34TCL_TX_FORMAT_FORMAT_HILO16 0x00003300 #define NV34TCL_TX_FORMAT_FORMAT_HILO16_RECT 0x00003600 #define NV34TCL_TX_FORMAT_FORMAT_HILO8 0x00004400 diff --git a/src/gallium/drivers/nvfx/nv30_fragtex.c b/src/gallium/drivers/nvfx/nv30_fragtex.c index fbc69cf44ac..63c578a0ce1 100644 --- a/src/gallium/drivers/nvfx/nv30_fragtex.c +++ b/src/gallium/drivers/nvfx/nv30_fragtex.c @@ -10,88 +10,75 @@ nv30_sampler_state_init(struct pipe_context *pipe, struct nvfx_sampler_state *ps, const struct pipe_sampler_state *cso) { - if (cso->max_anisotropy >= 8) { - ps->en |= NV34TCL_TX_ENABLE_ANISO_8X; - } else - if (cso->max_anisotropy >= 4) { - ps->en |= NV34TCL_TX_ENABLE_ANISO_4X; - } else - if (cso->max_anisotropy >= 2) { - ps->en |= NV34TCL_TX_ENABLE_ANISO_2X; - } + float limit; + if (cso->max_anisotropy >= 2) { - float limit; + if (cso->max_anisotropy >= 8) + ps->en |= NV34TCL_TX_ENABLE_ANISO_8X; + else if (cso->max_anisotropy >= 4) + ps->en |= NV34TCL_TX_ENABLE_ANISO_4X; + else if (cso->max_anisotropy >= 2) + ps->en |= NV34TCL_TX_ENABLE_ANISO_2X; + } - limit = CLAMP(cso->lod_bias, -16.0, 15.0); - ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; + limit = CLAMP(cso->lod_bias, -16.0, 15.0); + ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; - limit = CLAMP(cso->max_lod, 0.0, 15.0); - ps->en |= (int)(limit) << 14 /*NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT*/; + ps->max_lod = (int)CLAMP(cso->max_lod, 0.0, 15.0); + ps->min_lod = (int)CLAMP(cso->min_lod, 0.0, 15.0); - limit = CLAMP(cso->min_lod, 0.0, 15.0); - ps->en |= (int)(limit) << 26 /*NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT*/; - } + ps->en |= NV34TCL_TX_ENABLE_ENABLE; } -#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w) \ -[PIPE_FORMAT_##m] = { \ - NV34TCL_TX_FORMAT_FORMAT_##tf, \ - NV34TCL_TX_FORMAT_FORMAT_##tf##_RECT, \ - (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \ - NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \ - NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \ - NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w) \ -} +void +nv30_sampler_view_init(struct pipe_context *pipe, + struct nvfx_sampler_view *sv) +{ + struct pipe_resource* pt = sv->base.texture; + struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format]; + unsigned txf; + unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level; + + assert(tf->fmt[0] >= 0); + + txf = sv->u.init_fmt; + txf |= (level != sv->base.last_level ? NV34TCL_TX_FORMAT_MIPMAP : 0); + txf |= log2i(u_minify(pt->width0, level)) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT; + txf |= log2i(u_minify(pt->height0, level)) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT; + txf |= log2i(u_minify(pt->depth0, level)) << NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT; + txf |= 0x10000; + + sv->u.nv30.fmt[0] = tf->fmt[0] | txf; + sv->u.nv30.fmt[1] = tf->fmt[1] | txf; + sv->u.nv30.fmt[2] = tf->fmt[2] | txf; + sv->u.nv30.fmt[3] = tf->fmt[3] | txf; -struct nv30_texture_format { - int format; - int rect_format; - int swizzle; -}; - -#define NV34TCL_TX_FORMAT_FORMAT_DXT1_RECT NV34TCL_TX_FORMAT_FORMAT_DXT1 -#define NV34TCL_TX_FORMAT_FORMAT_DXT3_RECT NV34TCL_TX_FORMAT_FORMAT_DXT3 -#define NV34TCL_TX_FORMAT_FORMAT_DXT5_RECT NV34TCL_TX_FORMAT_FORMAT_DXT5 - -static struct nv30_texture_format -nv30_texture_formats[PIPE_FORMAT_COUNT] = { - [0 ... PIPE_FORMAT_COUNT - 1] = {-1, 0, 0}, - _(B8G8R8X8_UNORM, A8R8G8B8, S1, S1, S1, ONE, X, Y, Z, W), - _(B8G8R8A8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W), - _(B5G5R5A1_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W), - _(B4G4R4A4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W), - _(B5G6R5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W), - _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X), - _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X), - _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X), - _(L8A8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y), - _(Z16_UNORM , R5G6B5 , S1, S1, S1, ONE, X, X, X, X), - _(S8_USCALED_Z24_UNORM , A8R8G8B8, S1, S1, S1, ONE, X, X, X, X), - _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W), - _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W), - _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W), - _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W), - {}, -}; + sv->swizzle |= (nvfx_subresource_pitch(pt, 0) << NV34TCL_TX_SWIZZLE_RECT_PITCH_SHIFT); + + if(pt->height0 <= 1 || util_format_is_compressed(sv->base.format)) + sv->u.nv30.rect = -1; + else + sv->u.nv30.rect = !!(pt->flags & NVFX_RESOURCE_FLAG_LINEAR); + + sv->lod_offset = sv->base.first_level - level; + sv->max_lod_limit = sv->base.last_level - level; +} void nv30_fragtex_set(struct nvfx_context *nvfx, int unit) { struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; - struct nvfx_miptree *mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture; - struct pipe_resource *pt = &mt->base.base; - struct nouveau_bo *bo = mt->base.bo; - struct nv30_texture_format *tf; + struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit]; + struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo; struct nouveau_channel* chan = nvfx->screen->base.channel; - uint32_t txf, txs; + unsigned txf; unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; unsigned use_rect; + unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit); + unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod) ; - tf = &nv30_texture_formats[pt->format]; - assert(tf->format >= 0); - - if(pt->height0 <= 1 || util_format_is_compressed(pt->format)) + if(sv->u.nv30.rect < 0) { /* in the case of compressed or 1D textures, we can get away with this, * since the layout is the same @@ -100,9 +87,9 @@ nv30_fragtex_set(struct nvfx_context *nvfx, int unit) } else { - static int warned = 0; - if(!warned && !ps->fmt != !(pt->flags & NVFX_RESOURCE_FLAG_LINEAR)) { - warned = 1; + static boolean warned = FALSE; + if( !!ps->fmt != sv->u.nv30.rect && !warned) { + warned = TRUE; fprintf(stderr, "Unimplemented: coordinate normalization mismatch. Possible reasons:\n" "1. ARB_texture_non_power_of_two is being used despite the fact it isn't supported\n" @@ -110,51 +97,22 @@ nv30_fragtex_set(struct nvfx_context *nvfx, int unit) "3. The state tracker is not supported\n"); } - use_rect = pt->flags & NVFX_RESOURCE_FLAG_LINEAR; - } - - txf = use_rect ? tf->rect_format : tf->format; - txf |= ((pt->last_level>0) ? NV34TCL_TX_FORMAT_MIPMAP : 0); - txf |= log2i(pt->width0) << NV34TCL_TX_FORMAT_BASE_SIZE_U_SHIFT; - txf |= log2i(pt->height0) << NV34TCL_TX_FORMAT_BASE_SIZE_V_SHIFT; - txf |= log2i(pt->depth0) << NV34TCL_TX_FORMAT_BASE_SIZE_W_SHIFT; - txf |= NV34TCL_TX_FORMAT_NO_BORDER | 0x10000; - - switch (pt->target) { - case PIPE_TEXTURE_CUBE: - txf |= NV34TCL_TX_FORMAT_CUBIC; - /* fall-through */ - case PIPE_TEXTURE_2D: - case PIPE_TEXTURE_RECT: - txf |= NV34TCL_TX_FORMAT_DIMS_2D; - break; - case PIPE_TEXTURE_3D: - txf |= NV34TCL_TX_FORMAT_DIMS_3D; - break; - case PIPE_TEXTURE_1D: - txf |= NV34TCL_TX_FORMAT_DIMS_1D; - break; - default: - NOUVEAU_ERR("Unknown target %d\n", pt->target); - return; + use_rect = sv->u.nv30.rect; } - txs = tf->swizzle; - - if(use_rect) - txs |= nvfx_subresource_pitch(&mt->base, 0) << NV34TCL_TX_SWIZZLE_RECT_PITCH_SHIFT; + txf = sv->u.nv30.fmt[ps->compare + (use_rect ? 2 : 0)]; MARK_RING(chan, 9, 2); OUT_RING(chan, RING_3D(NV34TCL_TX_OFFSET(unit), 8)); - OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); - OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR, - NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); - OUT_RING(chan, ps->wrap); - OUT_RING(chan, NV34TCL_TX_ENABLE_ENABLE | ps->en); - OUT_RING(chan, txs); - OUT_RING(chan, ps->filt | 0x2000 /*voodoo*/); - OUT_RING(chan, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | - pt->height0); + OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0); + OUT_RELOC(chan, bo, txf, + tex_flags | NOUVEAU_BO_OR, + NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); + OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap); + OUT_RING(chan, ps->en | (min_lod << NV34TCL_TX_ENABLE_MIPMAP_MIN_LOD_SHIFT) | (max_lod << NV34TCL_TX_ENABLE_MIPMAP_MAX_LOD_SHIFT)); + OUT_RING(chan, sv->swizzle); + OUT_RING(chan, ps->filt | sv->filt); + OUT_RING(chan, sv->npot_size); OUT_RING(chan, ps->bcol); nvfx->hw_txf[unit] = txf; diff --git a/src/gallium/drivers/nvfx/nv40_fragtex.c b/src/gallium/drivers/nvfx/nv40_fragtex.c index 87aa7eb1a20..5fe742f260c 100644 --- a/src/gallium/drivers/nvfx/nv40_fragtex.c +++ b/src/gallium/drivers/nvfx/nv40_fragtex.c @@ -8,149 +8,97 @@ nv40_sampler_state_init(struct pipe_context *pipe, struct nvfx_sampler_state *ps, const struct pipe_sampler_state *cso) { + float limit; if (cso->max_anisotropy >= 2) { /* no idea, binary driver sets it, works without it.. meh.. */ ps->wrap |= (1 << 5); - if (cso->max_anisotropy >= 16) { + if (cso->max_anisotropy >= 16) ps->en |= NV40TCL_TEX_ENABLE_ANISO_16X; - } else - if (cso->max_anisotropy >= 12) { + else if (cso->max_anisotropy >= 12) ps->en |= NV40TCL_TEX_ENABLE_ANISO_12X; - } else - if (cso->max_anisotropy >= 10) { + else if (cso->max_anisotropy >= 10) ps->en |= NV40TCL_TEX_ENABLE_ANISO_10X; - } else - if (cso->max_anisotropy >= 8) { + else if (cso->max_anisotropy >= 8) ps->en |= NV40TCL_TEX_ENABLE_ANISO_8X; - } else - if (cso->max_anisotropy >= 6) { + else if (cso->max_anisotropy >= 6) ps->en |= NV40TCL_TEX_ENABLE_ANISO_6X; - } else - if (cso->max_anisotropy >= 4) { + else if (cso->max_anisotropy >= 4) ps->en |= NV40TCL_TEX_ENABLE_ANISO_4X; - } else { + else ps->en |= NV40TCL_TEX_ENABLE_ANISO_2X; - } } - { - float limit; + limit = CLAMP(cso->lod_bias, -16.0, 15.0); + ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; - limit = CLAMP(cso->lod_bias, -16.0, 15.0); - ps->filt |= (int)(cso->lod_bias * 256.0) & 0x1fff; + ps->max_lod = (int)(CLAMP(cso->max_lod, 0.0, 15.0) * 256.0); + ps->min_lod = (int)(CLAMP(cso->min_lod, 0.0, 15.0) * 256.0); - limit = CLAMP(cso->max_lod, 0.0, 15.0); - ps->en |= (int)(limit * 256.0) << 7; + ps->en |= NV40TCL_TEX_ENABLE_ENABLE; +} + +void +nv40_sampler_view_init(struct pipe_context *pipe, + struct nvfx_sampler_view *sv) +{ + struct pipe_resource* pt = sv->base.texture; + struct nvfx_miptree* mt = (struct nvfx_miptree*)pt; + struct nvfx_texture_format *tf = &nvfx_texture_formats[sv->base.format]; + unsigned txf; + unsigned level = pt->target == PIPE_TEXTURE_CUBE ? 0 : sv->base.first_level; + assert(tf->fmt[4] >= 0); + + txf = sv->u.init_fmt; + txf |= 0x8000; + if(pt->target == PIPE_TEXTURE_CUBE) + txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT); + else + txf |= (((sv->base.last_level - sv->base.first_level) + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT); - limit = CLAMP(cso->min_lod, 0.0, 15.0); - ps->en |= (int)(limit * 256.0) << 19; + if (!mt->linear_pitch) + sv->u.nv40.npot_size2 = 0; + else { + sv->u.nv40.npot_size2 = mt->linear_pitch; + txf |= NV40TCL_TEX_FORMAT_LINEAR; } -} -#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sx,sy,sz,sw) \ -[PIPE_FORMAT_##m] = { \ - NV40TCL_TEX_FORMAT_FORMAT_##tf, \ - (NV34TCL_TX_SWIZZLE_S0_X_##ts0x | NV34TCL_TX_SWIZZLE_S0_Y_##ts0y | \ - NV34TCL_TX_SWIZZLE_S0_Z_##ts0z | NV34TCL_TX_SWIZZLE_S0_W_##ts0w | \ - NV34TCL_TX_SWIZZLE_S1_X_##ts1x | NV34TCL_TX_SWIZZLE_S1_Y_##ts1y | \ - NV34TCL_TX_SWIZZLE_S1_Z_##ts1z | NV34TCL_TX_SWIZZLE_S1_W_##ts1w), \ - ((NV34TCL_TX_FILTER_SIGNED_RED*sx) | (NV34TCL_TX_FILTER_SIGNED_GREEN*sy) | \ - (NV34TCL_TX_FILTER_SIGNED_BLUE*sz) | (NV34TCL_TX_FILTER_SIGNED_ALPHA*sw)) \ -} + sv->u.nv40.fmt[0] = tf->fmt[4] | txf; + sv->u.nv40.fmt[1] = tf->fmt[5] | txf; -struct nv40_texture_format { - int format; - int swizzle; - int sign; -}; + sv->u.nv40.npot_size2 |= (u_minify(pt->depth0, level) << NV40TCL_TEX_SIZE1_DEPTH_SHIFT); -static struct nv40_texture_format -nv40_texture_formats[PIPE_FORMAT_COUNT] = { - [0 ... PIPE_FORMAT_COUNT - 1] = {-1, 0, 0}, - _(B8G8R8X8_UNORM, A8R8G8B8, S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0), - _(B8G8R8A8_UNORM, A8R8G8B8, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0), - _(B5G5R5A1_UNORM, A1R5G5B5, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0), - _(B4G4R4A4_UNORM, A4R4G4B4, S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0), - _(B5G6R5_UNORM , R5G6B5 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0), - _(L8_UNORM , L8 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0), - _(A8_UNORM , L8 , ZERO, ZERO, ZERO, S1, X, X, X, X, 0, 0, 0, 0), - _(R16_SNORM , A16 , ZERO, ZERO, S1, ONE, X, X, X, Y, 1, 1, 1, 1), - _(I8_UNORM , L8 , S1, S1, S1, S1, X, X, X, X, 0, 0, 0, 0), - _(L8A8_UNORM , A8L8 , S1, S1, S1, S1, X, X, X, Y, 0, 0, 0, 0), - _(Z16_UNORM , Z16 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0), - _(S8_USCALED_Z24_UNORM , Z24 , S1, S1, S1, ONE, X, X, X, X, 0, 0, 0, 0), - _(DXT1_RGB , DXT1 , S1, S1, S1, ONE, X, Y, Z, W, 0, 0, 0, 0), - _(DXT1_RGBA , DXT1 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0), - _(DXT3_RGBA , DXT3 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0), - _(DXT5_RGBA , DXT5 , S1, S1, S1, S1, X, Y, Z, W, 0, 0, 0, 0), - {}, -}; + sv->lod_offset = (sv->base.first_level - level) * 256; + sv->max_lod_limit = (sv->base.last_level - level) * 256; +} void nv40_fragtex_set(struct nvfx_context *nvfx, int unit) { struct nouveau_channel* chan = nvfx->screen->base.channel; struct nvfx_sampler_state *ps = nvfx->tex_sampler[unit]; - struct nvfx_miptree *mt = (struct nvfx_miptree *)nvfx->fragment_sampler_views[unit]->texture; - struct nouveau_bo *bo = mt->base.bo; - struct pipe_resource *pt = &mt->base.base; - struct nv40_texture_format *tf; - - uint32_t txf, txs, txp; + struct nvfx_sampler_view* sv = (struct nvfx_sampler_view*)nvfx->fragment_sampler_views[unit]; + struct nouveau_bo *bo = ((struct nvfx_miptree *)sv->base.texture)->base.bo; unsigned tex_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD; + unsigned txf; + unsigned max_lod = MIN2(ps->max_lod + sv->lod_offset, sv->max_lod_limit); + unsigned min_lod = MIN2(ps->min_lod + sv->lod_offset, max_lod); - tf = &nv40_texture_formats[pt->format]; - assert(tf->format >= 0); - - txf = ps->fmt; - txf |= tf->format | 0x8000; - txf |= ((pt->last_level + 1) << NV40TCL_TEX_FORMAT_MIPMAP_COUNT_SHIFT); - - if (1) /* XXX */ - txf |= NV34TCL_TX_FORMAT_NO_BORDER; - - switch (pt->target) { - case PIPE_TEXTURE_CUBE: - txf |= NV34TCL_TX_FORMAT_CUBIC; - /* fall-through */ - case PIPE_TEXTURE_2D: - case PIPE_TEXTURE_RECT: - txf |= NV34TCL_TX_FORMAT_DIMS_2D; - break; - case PIPE_TEXTURE_3D: - txf |= NV34TCL_TX_FORMAT_DIMS_3D; - break; - case PIPE_TEXTURE_1D: - txf |= NV34TCL_TX_FORMAT_DIMS_1D; - break; - default: - NOUVEAU_ERR("Unknown target %d\n", pt->target); - return; - } - - if (!mt->linear_pitch) - txp = 0; - else { - txp = mt->linear_pitch; - txf |= NV40TCL_TEX_FORMAT_LINEAR; - } - - txs = tf->swizzle; + txf = sv->u.nv40.fmt[ps->compare] | ps->fmt; - MARK_RING(chan, 11 + 2 * !unit, 2); + MARK_RING(chan, 11, 2); OUT_RING(chan, RING_3D(NV34TCL_TX_OFFSET(unit), 8)); - OUT_RELOC(chan, bo, 0, tex_flags | NOUVEAU_BO_LOW, 0, 0); + OUT_RELOC(chan, bo, sv->offset, tex_flags | NOUVEAU_BO_LOW, 0, 0); OUT_RELOC(chan, bo, txf, tex_flags | NOUVEAU_BO_OR, NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); - OUT_RING(chan, ps->wrap); - OUT_RING(chan, NV40TCL_TEX_ENABLE_ENABLE | ps->en); - OUT_RING(chan, txs); - OUT_RING(chan, ps->filt | tf->sign | 0x2000 /*voodoo*/); - OUT_RING(chan, (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | pt->height0); + OUT_RING(chan, (ps->wrap & sv->wrap_mask) | sv->wrap); + OUT_RING(chan, ps->en | (min_lod << 19) | (max_lod << 7)); + OUT_RING(chan, sv->swizzle); + OUT_RING(chan, ps->filt | sv->filt); + OUT_RING(chan, sv->npot_size); OUT_RING(chan, ps->bcol); OUT_RING(chan, RING_3D(NV40TCL_TEX_SIZE1(unit), 1)); - OUT_RING(chan, (pt->depth0 << NV40TCL_TEX_SIZE1_DEPTH_SHIFT) | txp); + OUT_RING(chan, sv->u.nv40.npot_size2); nvfx->hw_txf[unit] = txf; nvfx->hw_samplers |= (1 << unit); diff --git a/src/gallium/drivers/nvfx/nvfx_context.c b/src/gallium/drivers/nvfx/nvfx_context.c index 7ab81de7dd5..1980176b23e 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.c +++ b/src/gallium/drivers/nvfx/nvfx_context.c @@ -75,6 +75,7 @@ nvfx_create(struct pipe_screen *pscreen, void *priv) nvfx_init_query_functions(nvfx); nvfx_init_surface_functions(nvfx); nvfx_init_state_functions(nvfx); + nvfx_init_sampling_functions(nvfx); nvfx_init_resource_functions(&nvfx->pipe); /* Create, configure, and install fallback swtnl path */ diff --git a/src/gallium/drivers/nvfx/nvfx_context.h b/src/gallium/drivers/nvfx/nvfx_context.h index a6ea9139675..bce19df044d 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.h +++ b/src/gallium/drivers/nvfx/nvfx_context.h @@ -201,15 +201,20 @@ extern void nvfx_fragprog_relocate(struct nvfx_context *nvfx); /* nvfx_fragtex.c */ +extern void nvfx_init_sampling_functions(struct nvfx_context *nvfx); extern void nvfx_fragtex_validate(struct nvfx_context *nvfx); -extern void -nvfx_fragtex_relocate(struct nvfx_context *nvfx); +extern void nvfx_fragtex_relocate(struct nvfx_context *nvfx); + +struct nvfx_sampler_view; /* nv30_fragtex.c */ extern void nv30_sampler_state_init(struct pipe_context *pipe, struct nvfx_sampler_state *ps, const struct pipe_sampler_state *cso); +extern void +nv30_sampler_view_init(struct pipe_context *pipe, + struct nvfx_sampler_view *sv); extern void nv30_fragtex_set(struct nvfx_context *nvfx, int unit); /* nv40_fragtex.c */ @@ -217,6 +222,9 @@ extern void nv40_sampler_state_init(struct pipe_context *pipe, struct nvfx_sampler_state *ps, const struct pipe_sampler_state *cso); +extern void +nv40_sampler_view_init(struct pipe_context *pipe, + struct nvfx_sampler_view *sv); extern void nv40_fragtex_set(struct nvfx_context *nvfx, int unit); /* nvfx_state.c */ diff --git a/src/gallium/drivers/nvfx/nvfx_fragtex.c b/src/gallium/drivers/nvfx/nvfx_fragtex.c index 66057454337..00c47be76ab 100644 --- a/src/gallium/drivers/nvfx/nvfx_fragtex.c +++ b/src/gallium/drivers/nvfx/nvfx_fragtex.c @@ -1,5 +1,177 @@ #include "nvfx_context.h" #include "nvfx_resource.h" +#include "nvfx_tex.h" + +static void * +nvfx_sampler_state_create(struct pipe_context *pipe, + const struct pipe_sampler_state *cso) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_sampler_state *ps; + + ps = MALLOC(sizeof(struct nvfx_sampler_state)); + + /* on nv30, we use this as an internal flag */ + ps->fmt = cso->normalized_coords ? 0 : NV40TCL_TEX_FORMAT_RECT; + ps->en = 0; + ps->filt = nvfx_tex_filter(cso) | 0x2000; /*voodoo*/ + ps->wrap = (nvfx_tex_wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) | + (nvfx_tex_wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) | + (nvfx_tex_wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT); + ps->compare = FALSE; + + if(cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) + { + ps->wrap |= nvfx_tex_wrap_compare_mode(cso->compare_func); + ps->compare = TRUE; + } + ps->bcol = nvfx_tex_border_color(cso->border_color); + + if(nvfx->is_nv4x) + nv40_sampler_state_init(pipe, ps, cso); + else + nv30_sampler_state_init(pipe, ps, cso); + + return (void *)ps; +} + +static void +nvfx_sampler_state_delete(struct pipe_context *pipe, void *hwcso) +{ + FREE(hwcso); +} + +static void +nvfx_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + unsigned unit; + + for (unit = 0; unit < nr; unit++) { + nvfx->tex_sampler[unit] = sampler[unit]; + nvfx->dirty_samplers |= (1 << unit); + } + + for (unit = nr; unit < nvfx->nr_samplers; unit++) { + nvfx->tex_sampler[unit] = NULL; + nvfx->dirty_samplers |= (1 << unit); + } + + nvfx->nr_samplers = nr; + nvfx->dirty |= NVFX_NEW_SAMPLER; +} + +static struct pipe_sampler_view * +nvfx_create_sampler_view(struct pipe_context *pipe, + struct pipe_resource *pt, + const struct pipe_sampler_view *templ) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + struct nvfx_sampler_view *sv = CALLOC_STRUCT(nvfx_sampler_view); + struct nvfx_texture_format *tf = &nvfx_texture_formats[templ->format]; + unsigned txf; + + if (!sv) + return NULL; + + sv->base = *templ; + sv->base.reference.count = 1; + sv->base.texture = NULL; + pipe_resource_reference(&sv->base.texture, pt); + sv->base.context = pipe; + + txf = NV34TCL_TX_FORMAT_NO_BORDER; + + switch (pt->target) { + case PIPE_TEXTURE_CUBE: + txf |= NV34TCL_TX_FORMAT_CUBIC; + /* fall-through */ + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_RECT: + txf |= NV34TCL_TX_FORMAT_DIMS_2D; + break; + case PIPE_TEXTURE_3D: + txf |= NV34TCL_TX_FORMAT_DIMS_3D; + break; + case PIPE_TEXTURE_1D: + txf |= NV34TCL_TX_FORMAT_DIMS_1D; + break; + default: + assert(0); + } + sv->u.init_fmt = txf; + + sv->swizzle = 0 + | (tf->src[sv->base.swizzle_r] << NV34TCL_TX_SWIZZLE_S0_Z_SHIFT) + | (tf->src[sv->base.swizzle_g] << NV34TCL_TX_SWIZZLE_S0_Y_SHIFT) + | (tf->src[sv->base.swizzle_b] << NV34TCL_TX_SWIZZLE_S0_X_SHIFT) + | (tf->src[sv->base.swizzle_a] << NV34TCL_TX_SWIZZLE_S0_W_SHIFT) + | (tf->comp[sv->base.swizzle_r] << NV34TCL_TX_SWIZZLE_S1_Z_SHIFT) + | (tf->comp[sv->base.swizzle_g] << NV34TCL_TX_SWIZZLE_S1_Y_SHIFT) + | (tf->comp[sv->base.swizzle_b] << NV34TCL_TX_SWIZZLE_S1_X_SHIFT) + | (tf->comp[sv->base.swizzle_a] << NV34TCL_TX_SWIZZLE_S1_W_SHIFT); + + sv->filt = tf->sign; + sv->wrap = tf->wrap; + sv->wrap_mask = ~0; + + if (pt->target == PIPE_TEXTURE_CUBE) + { + sv->offset = 0; + sv->npot_size = (pt->width0 << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | pt->height0; + } + else + { + sv->offset = nvfx_subresource_offset(pt, 0, sv->base.first_level, 0); + sv->npot_size = (u_minify(pt->width0, sv->base.first_level) << NV34TCL_TX_NPOT_SIZE_W_SHIFT) | u_minify(pt->height0, sv->base.first_level); + + /* apparently, we need to ignore the t coordinate for 1D textures to fix piglit tex1d-2dborder */ + if(pt->target == PIPE_TEXTURE_1D) + { + sv->wrap_mask &=~ NV34TCL_TX_WRAP_T_MASK; + sv->wrap |= NV34TCL_TX_WRAP_T_REPEAT; + } + } + + if(nvfx->is_nv4x) + nv40_sampler_view_init(pipe, sv); + else + nv30_sampler_view_init(pipe, sv); + + return &sv->base; +} + +static void +nvfx_sampler_view_destroy(struct pipe_context *pipe, + struct pipe_sampler_view *view) +{ + pipe_resource_reference(&view->texture, NULL); + FREE(view); +} + +static void +nvfx_set_fragment_sampler_views(struct pipe_context *pipe, + unsigned nr, + struct pipe_sampler_view **views) +{ + struct nvfx_context *nvfx = nvfx_context(pipe); + unsigned unit; + + for (unit = 0; unit < nr; unit++) { + pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], + views[unit]); + nvfx->dirty_samplers |= (1 << unit); + } + + for (unit = nr; unit < nvfx->nr_textures; unit++) { + pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], + NULL); + nvfx->dirty_samplers |= (1 << unit); + } + + nvfx->nr_textures = nr; + nvfx->dirty |= NVFX_NEW_SAMPLER; +} void nvfx_fragtex_validate(struct nvfx_context *nvfx) @@ -60,3 +232,126 @@ nvfx_fragtex_relocate(struct nvfx_context *nvfx) NV34TCL_TX_FORMAT_DMA0, NV34TCL_TX_FORMAT_DMA1); } } + +void +nvfx_init_sampling_functions(struct nvfx_context *nvfx) +{ + nvfx->pipe.create_sampler_state = nvfx_sampler_state_create; + nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind; + nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete; + nvfx->pipe.set_fragment_sampler_views = nvfx_set_fragment_sampler_views; + nvfx->pipe.create_sampler_view = nvfx_create_sampler_view; + nvfx->pipe.sampler_view_destroy = nvfx_sampler_view_destroy; +} + +#define NV34TCL_TX_FORMAT_FORMAT_DXT1_RECT NV34TCL_TX_FORMAT_FORMAT_DXT1 +#define NV34TCL_TX_FORMAT_FORMAT_DXT3_RECT NV34TCL_TX_FORMAT_FORMAT_DXT3 +#define NV34TCL_TX_FORMAT_FORMAT_DXT5_RECT NV34TCL_TX_FORMAT_FORMAT_DXT5 + +#define NV40TCL_TEX_FORMAT_FORMAT_HILO16 NV40TCL_TEX_FORMAT_FORMAT_A16L16 + +#define NV34TCL_TX_FORMAT_FORMAT_RGBA16F 0x00004a00 +#define NV34TCL_TX_FORMAT_FORMAT_RGBA16F_RECT NV34TCL_TX_FORMAT_FORMAT_RGBA16F +#define NV34TCL_TX_FORMAT_FORMAT_RGBA32F 0x00004b00 +#define NV34TCL_TX_FORMAT_FORMAT_RGBA32F_RECT NV34TCL_TX_FORMAT_FORMAT_RGBA32F +#define NV34TCL_TX_FORMAT_FORMAT_R32F 0x00004c00 +#define NV34TCL_TX_FORMAT_FORMAT_R32F_RECT NV34TCL_TX_FORMAT_FORMAT_R32F + +// TODO: guess! +#define NV40TCL_TEX_FORMAT_FORMAT_R32F 0x00001c00 + +#define SRGB 0x00700000 + +#define __(m,tf,tfc,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign,wrap) \ +[PIPE_FORMAT_##m] = { \ + {NV34TCL_TX_FORMAT_FORMAT_##tf, \ + NV34TCL_TX_FORMAT_FORMAT_##tfc, \ + NV34TCL_TX_FORMAT_FORMAT_##tf##_RECT, \ + NV34TCL_TX_FORMAT_FORMAT_##tfc##_RECT, \ + NV40TCL_TEX_FORMAT_FORMAT_##tf, \ + NV40TCL_TEX_FORMAT_FORMAT_##tfc}, \ + sign, wrap, \ + {ts0z, ts0y, ts0x, ts0w, 0, 1}, {ts1z, ts1y, ts1x, ts1w, 0, 0} \ +} + +#define _(m,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign, wrap) \ + __(m,tf,tf,ts0x,ts0y,ts0z,ts0w,ts1x,ts1y,ts1z,ts1w,sign, wrap) + +/* Depth formats works by reading the depth value most significant 8/16 bits. + * We are losing precision, but nVidia loses even more by using A8R8G8B8 instead of HILO16 + * There is no 32-bit integer texture support, so other things are infeasible. + * + * TODO: is it possible to read 16 bits for Z16? A16 doesn't seem to work, either due to normalization or endianness issues + */ + +#define T 2 + +#define X 3 +#define Y 2 +#define Z 1 +#define W 0 + +#define SNORM ((NV34TCL_TX_FILTER_SIGNED_RED) | (NV34TCL_TX_FILTER_SIGNED_GREEN) | (NV34TCL_TX_FILTER_SIGNED_BLUE) | (NV34TCL_TX_FILTER_SIGNED_ALPHA)) +#define UNORM 0 + +struct nvfx_texture_format +nvfx_texture_formats[PIPE_FORMAT_COUNT] = { + [0 ... PIPE_FORMAT_COUNT - 1] = {{-1, -1, -1, -1, -1, -1}}, + _(B8G8R8X8_UNORM, A8R8G8B8, T, T, T, 1, X, Y, Z, W, UNORM, 0), + _(B8G8R8X8_SRGB, A8R8G8B8, T, T, T, 1, X, Y, Z, W, UNORM, SRGB), + _(B8G8R8A8_UNORM, A8R8G8B8, T, T, T, T, X, Y, Z, W, UNORM, 0), + _(B8G8R8A8_SRGB, A8R8G8B8, T, T, T, T, X, Y, Z, W, UNORM, SRGB), + + _(R8G8B8A8_UNORM, A8R8G8B8, T, T, T, T, Z, Y, X, W, UNORM, 0), + _(R8G8B8A8_SRGB, A8R8G8B8, T, T, T, T, Z, Y, X, W, UNORM, SRGB), + _(R8G8B8X8_UNORM, A8R8G8B8, T, T, T, 1, Z, Y, X, W, UNORM, 0), + + _(A8R8G8B8_UNORM, A8R8G8B8, T, T, T, T, W, Z, Y, X, UNORM, 0), + _(A8R8G8B8_SRGB, A8R8G8B8, T, T, T, T, W, Z, Y, X, UNORM, SRGB), + _(A8B8G8R8_UNORM, A8R8G8B8, T, T, T, T, W, X, Y, Z, UNORM, 0), + _(A8B8G8R8_SRGB, A8R8G8B8, T, T, T, T, W, X, Y, Z, UNORM, SRGB), + _(X8R8G8B8_UNORM, A8R8G8B8, T, T, T, 1, W, Z, Y, X, UNORM, 0), + _(X8R8G8B8_SRGB, A8R8G8B8, T, T, T, 1, W, Z, Y, X, UNORM, SRGB), + + _(B5G5R5A1_UNORM, A1R5G5B5, T, T, T, T, X, Y, Z, W, UNORM, 0), + _(B5G5R5X1_UNORM, A1R5G5B5, T, T, T, 1, X, Y, Z, W, UNORM, 0), + + _(B4G4R4A4_UNORM, A4R4G4B4, T, T, T, T, X, Y, Z, W, UNORM, 0), + _(B4G4R4X4_UNORM, A4R4G4B4, T, T, T, 1, X, Y, Z, W, UNORM, 0), + + _(B5G6R5_UNORM, R5G6B5, T, T, T, 1, X, Y, Z, W, UNORM, 0), + + _(R8_UNORM, L8, T, 0, 0, 1, X, X, X, X, UNORM, 0), + _(R8_SNORM, L8, T, 0, 0, 1, X, X, X, X, SNORM, 0), + _(L8_UNORM, L8, T, T, T, 1, X, X, X, X, UNORM, 0), + _(L8_SRGB, L8, T, T, T, 1, X, X, X, X, UNORM, SRGB), + _(A8_UNORM, L8, 0, 0, 0, T, X, X, X, X, UNORM, 0), + _(I8_UNORM, L8, T, T, T, T, X, X, X, X, UNORM, 0), + + _(R8G8_UNORM, A8L8, T, T, T, T, X, X, X, W, UNORM, 0), + _(R8G8_SNORM, A8L8, T, T, T, T, X, X, X, W, SNORM, 0), + _(L8A8_UNORM, A8L8, T, T, T, T, X, X, X, W, UNORM, 0), + _(L8A8_SRGB, A8L8, T, T, T, T, X, X, X, W, UNORM, SRGB), + + _(DXT1_RGB, DXT1, T, T, T, 1, X, Y, Z, W, UNORM, 0), + _(DXT1_SRGB, DXT1, T, T, T, 1, X, Y, Z, W, UNORM, SRGB), + _(DXT1_RGBA, DXT1, T, T, T, T, X, Y, Z, W, UNORM, 0), + _(DXT1_SRGBA, DXT1, T, T, T, T, X, Y, Z, W, UNORM, SRGB), + _(DXT3_RGBA, DXT3, T, T, T, T, X, Y, Z, W, UNORM, 0), + _(DXT3_SRGBA, DXT3, T, T, T, T, X, Y, Z, W, UNORM, SRGB), + _(DXT5_RGBA, DXT5, T, T, T, T, X, Y, Z, W, UNORM, 0), + _(DXT5_SRGBA, DXT5, T, T, T, T, X, Y, Z, W, UNORM, SRGB), + + __(Z16_UNORM, A8L8, Z16, T, T, T, 1, W, W, W, W, UNORM, 0), + __(S8_USCALED_Z24_UNORM,HILO16,Z24, T, T, T, 1, W, W, W, W, UNORM, 0), + __(X8Z24_UNORM, HILO16,Z24, T, T, T, 1, W, W, W, W, UNORM, 0), + + _(R16_UNORM, A16, T, 0, 0, 1, X, X, X, X, UNORM, 0), + _(R16_SNORM, A16, T, 0, 0, 1, X, X, X, X, SNORM, 0), + _(R16G16_UNORM, HILO16, T, T, 0, 1, X, Y, X, X, UNORM, 0), + _(R16G16_SNORM, HILO16, T, T, 0, 1, X, Y, X, X, SNORM, 0), + + _(R16G16B16A16_FLOAT, RGBA16F, T, T, T, T, X, Y, Z, W, UNORM, 0), + _(R32G32B32A32_FLOAT, RGBA32F, T, T, T, T, X, Y, Z, W, UNORM, 0), + _(R32_FLOAT, R32F, T, 0, 0, 1, X, X, X, X, UNORM, 0) +}; diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index a1b7c218f11..a1b8361a9a4 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -8,6 +8,7 @@ #include "nvfx_context.h" #include "nvfx_screen.h" #include "nvfx_resource.h" +#include "nvfx_tex.h" #define NV30TCL_CHIPSET_3X_MASK 0x00000003 #define NV34TCL_CHIPSET_3X_MASK 0x00000010 @@ -179,58 +180,45 @@ nvfx_screen_surface_format_supported(struct pipe_screen *pscreen, case PIPE_FORMAT_B8G8R8A8_UNORM: case PIPE_FORMAT_B8G8R8X8_UNORM: case PIPE_FORMAT_B5G6R5_UNORM: - return TRUE; - default: break; + default: + return FALSE; } - } else + } + if (tex_usage & PIPE_BIND_DEPTH_STENCIL) { switch (format) { case PIPE_FORMAT_S8_USCALED_Z24_UNORM: case PIPE_FORMAT_X8Z24_UNORM: - return TRUE; + break; case PIPE_FORMAT_Z16_UNORM: /* TODO: this nv30 limitation probably does not exist */ - if (!screen->is_nv4x && front) - return (front->format == PIPE_FORMAT_B5G6R5_UNORM); - return TRUE; - default: + if (!screen->is_nv4x && front && front->format != PIPE_FORMAT_B5G6R5_UNORM) + return FALSE; break; + default: + return FALSE; } - } else { - if (tex_usage & PIPE_BIND_SAMPLER_VIEW) { - switch (format) { - case PIPE_FORMAT_DXT1_RGB: - case PIPE_FORMAT_DXT1_RGBA: - case PIPE_FORMAT_DXT3_RGBA: - case PIPE_FORMAT_DXT5_RGBA: - return util_format_s3tc_enabled; - default: - break; - } + } + + if (tex_usage & PIPE_BIND_SAMPLER_VIEW) { + struct nvfx_texture_format* tf = &nvfx_texture_formats[format]; + if(util_format_is_s3tc(format) && !util_format_s3tc_enabled) + return FALSE; + + if(screen->is_nv4x) + { + if(tf->fmt[4] < 0) + return FALSE; } - switch (format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - case PIPE_FORMAT_B8G8R8X8_UNORM: - case PIPE_FORMAT_B5G5R5A1_UNORM: - case PIPE_FORMAT_B4G4R4A4_UNORM: - case PIPE_FORMAT_B5G6R5_UNORM: - case PIPE_FORMAT_L8_UNORM: - case PIPE_FORMAT_A8_UNORM: - case PIPE_FORMAT_I8_UNORM: - case PIPE_FORMAT_L8A8_UNORM: - case PIPE_FORMAT_Z16_UNORM: - case PIPE_FORMAT_S8_USCALED_Z24_UNORM: - return TRUE; - /* TODO: does nv30 support this? */ - case PIPE_FORMAT_R16_SNORM: - return !!screen->is_nv4x; - default: - break; + else + { + if(tf->fmt[0] < 0) + return FALSE; } } - return FALSE; + return TRUE; } static void diff --git a/src/gallium/drivers/nvfx/nvfx_state.c b/src/gallium/drivers/nvfx/nvfx_state.c index ab7bed0f938..d459f9a8801 100644 --- a/src/gallium/drivers/nvfx/nvfx_state.c +++ b/src/gallium/drivers/nvfx/nvfx_state.c @@ -82,111 +82,6 @@ nvfx_blend_state_delete(struct pipe_context *pipe, void *hwcso) } static void * -nvfx_sampler_state_create(struct pipe_context *pipe, - const struct pipe_sampler_state *cso) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - struct nvfx_sampler_state *ps; - - ps = MALLOC(sizeof(struct nvfx_sampler_state)); - - /* on nv30, we use this as an internal flag */ - ps->fmt = cso->normalized_coords ? 0 : NV40TCL_TEX_FORMAT_RECT; - ps->en = 0; - ps->filt = nvfx_tex_filter(cso); - ps->wrap = (nvfx_tex_wrap_mode(cso->wrap_s) << NV34TCL_TX_WRAP_S_SHIFT) | - (nvfx_tex_wrap_mode(cso->wrap_t) << NV34TCL_TX_WRAP_T_SHIFT) | - (nvfx_tex_wrap_mode(cso->wrap_r) << NV34TCL_TX_WRAP_R_SHIFT) | - nvfx_tex_wrap_compare_mode(cso); - ps->bcol = nvfx_tex_border_color(cso->border_color); - - if(nvfx->is_nv4x) - nv40_sampler_state_init(pipe, ps, cso); - else - nv30_sampler_state_init(pipe, ps, cso); - - return (void *)ps; -} - -static void -nvfx_sampler_state_bind(struct pipe_context *pipe, unsigned nr, void **sampler) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - nvfx->tex_sampler[unit] = sampler[unit]; - nvfx->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nvfx->nr_samplers; unit++) { - nvfx->tex_sampler[unit] = NULL; - nvfx->dirty_samplers |= (1 << unit); - } - - nvfx->nr_samplers = nr; - nvfx->dirty |= NVFX_NEW_SAMPLER; -} - -static void -nvfx_sampler_state_delete(struct pipe_context *pipe, void *hwcso) -{ - FREE(hwcso); -} - -static void -nvfx_set_fragment_sampler_views(struct pipe_context *pipe, - unsigned nr, - struct pipe_sampler_view **views) -{ - struct nvfx_context *nvfx = nvfx_context(pipe); - unsigned unit; - - for (unit = 0; unit < nr; unit++) { - pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], - views[unit]); - nvfx->dirty_samplers |= (1 << unit); - } - - for (unit = nr; unit < nvfx->nr_textures; unit++) { - pipe_sampler_view_reference(&nvfx->fragment_sampler_views[unit], - NULL); - nvfx->dirty_samplers |= (1 << unit); - } - - nvfx->nr_textures = nr; - nvfx->dirty |= NVFX_NEW_SAMPLER; -} - - -static struct pipe_sampler_view * -nvfx_create_sampler_view(struct pipe_context *pipe, - struct pipe_resource *texture, - const struct pipe_sampler_view *templ) -{ - struct pipe_sampler_view *view = CALLOC_STRUCT(pipe_sampler_view); - - if (view) { - *view = *templ; - view->reference.count = 1; - view->texture = NULL; - pipe_resource_reference(&view->texture, texture); - view->context = pipe; - } - - return view; -} - - -static void -nvfx_sampler_view_destroy(struct pipe_context *pipe, - struct pipe_sampler_view *view) -{ - pipe_resource_reference(&view->texture, NULL); - FREE(view); -} - -static void * nvfx_rasterizer_state_create(struct pipe_context *pipe, const struct pipe_rasterizer_state *cso) { @@ -630,13 +525,6 @@ nvfx_init_state_functions(struct nvfx_context *nvfx) nvfx->pipe.bind_blend_state = nvfx_blend_state_bind; nvfx->pipe.delete_blend_state = nvfx_blend_state_delete; - nvfx->pipe.create_sampler_state = nvfx_sampler_state_create; - nvfx->pipe.bind_fragment_sampler_states = nvfx_sampler_state_bind; - nvfx->pipe.delete_sampler_state = nvfx_sampler_state_delete; - nvfx->pipe.set_fragment_sampler_views = nvfx_set_fragment_sampler_views; - nvfx->pipe.create_sampler_view = nvfx_create_sampler_view; - nvfx->pipe.sampler_view_destroy = nvfx_sampler_view_destroy; - nvfx->pipe.create_rasterizer_state = nvfx_rasterizer_state_create; nvfx->pipe.bind_rasterizer_state = nvfx_rasterizer_state_bind; nvfx->pipe.delete_rasterizer_state = nvfx_rasterizer_state_delete; diff --git a/src/gallium/drivers/nvfx/nvfx_tex.h b/src/gallium/drivers/nvfx/nvfx_tex.h index 69187a79e79..34be936a891 100644 --- a/src/gallium/drivers/nvfx/nvfx_tex.h +++ b/src/gallium/drivers/nvfx/nvfx_tex.h @@ -1,6 +1,11 @@ #ifndef NVFX_TEX_H_ #define NVFX_TEX_H_ +#include "util/u_math.h" +#include "pipe/p_defines.h" +#include "pipe/p_state.h" +#include <nouveau/nouveau_class.h> + static inline unsigned nvfx_tex_wrap_mode(unsigned wrap) { unsigned ret; @@ -31,7 +36,7 @@ nvfx_tex_wrap_mode(unsigned wrap) { ret = NV40TCL_TEX_WRAP_S_MIRROR_CLAMP; break; default: - NOUVEAU_ERR("unknown wrap mode: %d\n", wrap); + assert(0); ret = NV34TCL_TX_WRAP_S_REPEAT; break; } @@ -40,31 +45,29 @@ nvfx_tex_wrap_mode(unsigned wrap) { } static inline unsigned -nvfx_tex_wrap_compare_mode(const struct pipe_sampler_state* cso) +nvfx_tex_wrap_compare_mode(unsigned func) { - if (cso->compare_mode == PIPE_TEX_COMPARE_R_TO_TEXTURE) { - switch (cso->compare_func) { - case PIPE_FUNC_NEVER: - return NV34TCL_TX_WRAP_RCOMP_NEVER; - case PIPE_FUNC_GREATER: - return NV34TCL_TX_WRAP_RCOMP_GREATER; - case PIPE_FUNC_EQUAL: - return NV34TCL_TX_WRAP_RCOMP_EQUAL; - case PIPE_FUNC_GEQUAL: - return NV34TCL_TX_WRAP_RCOMP_GEQUAL; - case PIPE_FUNC_LESS: - return NV34TCL_TX_WRAP_RCOMP_LESS; - case PIPE_FUNC_NOTEQUAL: - return NV34TCL_TX_WRAP_RCOMP_NOTEQUAL; - case PIPE_FUNC_LEQUAL: - return NV34TCL_TX_WRAP_RCOMP_LEQUAL; - case PIPE_FUNC_ALWAYS: - return NV34TCL_TX_WRAP_RCOMP_ALWAYS; - default: - break; - } + switch (func) { + case PIPE_FUNC_NEVER: + return NV34TCL_TX_WRAP_RCOMP_NEVER; + case PIPE_FUNC_GREATER: + return NV34TCL_TX_WRAP_RCOMP_GREATER; + case PIPE_FUNC_EQUAL: + return NV34TCL_TX_WRAP_RCOMP_EQUAL; + case PIPE_FUNC_GEQUAL: + return NV34TCL_TX_WRAP_RCOMP_GEQUAL; + case PIPE_FUNC_LESS: + return NV34TCL_TX_WRAP_RCOMP_LESS; + case PIPE_FUNC_NOTEQUAL: + return NV34TCL_TX_WRAP_RCOMP_NOTEQUAL; + case PIPE_FUNC_LEQUAL: + return NV34TCL_TX_WRAP_RCOMP_LEQUAL; + case PIPE_FUNC_ALWAYS: + return NV34TCL_TX_WRAP_RCOMP_ALWAYS; + default: + assert(0); + return 0; } - return 0; } static inline unsigned nvfx_tex_filter(const struct pipe_sampler_state* cso) @@ -128,6 +131,45 @@ struct nvfx_sampler_state { uint32_t en; uint32_t filt; uint32_t bcol; + uint32_t min_lod; + uint32_t max_lod; + boolean compare; +}; + +struct nvfx_sampler_view { + struct pipe_sampler_view base; + int offset; + uint32_t swizzle; + uint32_t npot_size; + uint32_t filt; + uint32_t wrap_mask; + uint32_t wrap; + uint32_t lod_offset; + uint32_t max_lod_limit; + union + { + struct + { + uint32_t fmt[4]; /* nv30 has 4 entries, nv40 one */ + int rect; + } nv30; + struct + { + uint32_t fmt[2]; /* nv30 has 4 entries, nv40 one */ + uint32_t npot_size2; /* nv40 only */ + } nv40; + uint32_t init_fmt; + } u; }; +struct nvfx_texture_format { + int fmt[6]; + unsigned sign; + unsigned wrap; + unsigned char src[6]; + unsigned char comp[6]; +}; + +extern struct nvfx_texture_format nvfx_texture_formats[PIPE_FORMAT_COUNT]; + #endif /* NVFX_TEX_H_ */ |