Module: Mesa Branch: master Commit: 729abfd0f53c27ba58da95882bef985945933c65 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=729abfd0f53c27ba58da95882bef985945933c65
Author: Christoph Bumiller <christoph.bumil...@speed.at> Date: Fri Apr 12 13:42:01 2013 +0200 st/mesa: optionally apply texture swizzle to border color v2 This is the only sane solution for nv50 and nvc0 (really, trust me), but since on other hardware the border colour is tightly coupled with texture state they'd have to undo the swizzle, so I've added a cap. The dependency of update_sampler on the texture updates was introduced to avoid doing the apply_depthmode to the swizzle twice. v2: Moved swizzling helper to u_format.c, extended the CAP to provide more accurate information. --- src/gallium/auxiliary/util/u_format.c | 34 ++++++++++++++++++++++ src/gallium/auxiliary/util/u_format.h | 12 ++++++++ src/gallium/docs/source/cso/sampler.rst | 6 ++- src/gallium/docs/source/screen.rst | 11 +++++++ src/gallium/drivers/freedreno/freedreno_screen.c | 1 + src/gallium/drivers/i915/i915_screen.c | 1 + src/gallium/drivers/llvmpipe/lp_screen.c | 2 + src/gallium/drivers/nv30/nv30_screen.c | 1 + src/gallium/drivers/nv50/nv50_screen.c | 2 + src/gallium/drivers/nvc0/nvc0_screen.c | 2 + src/gallium/drivers/r300/r300_screen.c | 1 + src/gallium/drivers/r600/r600_pipe.c | 3 ++ src/gallium/drivers/radeonsi/radeonsi_pipe.c | 1 + src/gallium/drivers/softpipe/sp_screen.c | 2 + src/gallium/drivers/svga/svga_screen.c | 2 + src/gallium/include/pipe/p_defines.h | 7 ++++- src/mesa/state_tracker/st_atom.c | 2 +- src/mesa/state_tracker/st_atom_sampler.c | 27 +++++++++++++++-- src/mesa/state_tracker/st_context.c | 4 ++ src/mesa/state_tracker/st_context.h | 1 + 20 files changed, 115 insertions(+), 7 deletions(-) diff --git a/src/gallium/auxiliary/util/u_format.c b/src/gallium/auxiliary/util/u_format.c index 1845637..9bdc2ea 100644 --- a/src/gallium/auxiliary/util/u_format.c +++ b/src/gallium/auxiliary/util/u_format.c @@ -632,6 +632,40 @@ void util_format_compose_swizzles(const unsigned char swz1[4], } } +void util_format_apply_color_swizzle(union pipe_color_union *dst, + const union pipe_color_union *src, + const unsigned char swz[4], + const boolean is_integer) +{ + unsigned c; + + if (is_integer) { + for (c = 0; c < 4; ++c) { + switch (swz[c]) { + case PIPE_SWIZZLE_RED: dst->ui[c] = src->ui[0]; break; + case PIPE_SWIZZLE_GREEN: dst->ui[c] = src->ui[1]; break; + case PIPE_SWIZZLE_BLUE: dst->ui[c] = src->ui[2]; break; + case PIPE_SWIZZLE_ALPHA: dst->ui[c] = src->ui[3]; break; + default: + dst->ui[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1 : 0; + break; + } + } + } else { + for (c = 0; c < 4; ++c) { + switch (swz[c]) { + case PIPE_SWIZZLE_RED: dst->f[c] = src->f[0]; break; + case PIPE_SWIZZLE_GREEN: dst->f[c] = src->f[1]; break; + case PIPE_SWIZZLE_BLUE: dst->f[c] = src->f[2]; break; + case PIPE_SWIZZLE_ALPHA: dst->f[c] = src->f[3]; break; + default: + dst->f[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1.0f : 0.0f; + break; + } + } + } +} + void util_format_swizzle_4f(float *dst, const float *src, const unsigned char swz[4]) { diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h index ed942fb..e4b9c36 100644 --- a/src/gallium/auxiliary/util/u_format.h +++ b/src/gallium/auxiliary/util/u_format.h @@ -33,6 +33,9 @@ #include "pipe/p_format.h" #include "util/u_debug.h" +union pipe_color_union; + + #ifdef __cplusplus extern "C" { #endif @@ -1117,6 +1120,15 @@ void util_format_compose_swizzles(const unsigned char swz1[4], const unsigned char swz2[4], unsigned char dst[4]); +/* Apply the swizzle provided in \param swz (which is one of PIPE_SWIZZLE_x) + * to \param src and store the result in \param dst. + * \param is_integer determines the value written for PIPE_SWIZZLE_ONE. + */ +void util_format_apply_color_swizzle(union pipe_color_union *dst, + const union pipe_color_union *src, + const unsigned char swz[4], + const boolean is_integer); + void util_format_swizzle_4f(float *dst, const float *src, const unsigned char swz[4]); diff --git a/src/gallium/docs/source/cso/sampler.rst b/src/gallium/docs/source/cso/sampler.rst index 26ffc18..9959793 100644 --- a/src/gallium/docs/source/cso/sampler.rst +++ b/src/gallium/docs/source/cso/sampler.rst @@ -101,7 +101,9 @@ max_lod border_color Color union used for texel coordinates that are outside the [0,width-1], [0, height-1] or [0, depth-1] ranges. Interpreted according to sampler - view format. + view format, unless the driver reports + PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK, in which case special care has to be + taken (see description of the cap). max_anisotropy Maximum anistropy ratio to use when sampling from textures. For example, if max_anistropy=4, a region of up to 1 by 4 texels will be sampled. @@ -111,4 +113,4 @@ max_anisotropy seamless_cube_map If set, the bilinear filter of a cube map may take samples from adjacent cube map faces when sampled near a texture border to produce a seamless - look. \ No newline at end of file + look. diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst index 4b01d77..3ab7e9e 100644 --- a/src/gallium/docs/source/screen.rst +++ b/src/gallium/docs/source/screen.rst @@ -151,6 +151,17 @@ The integer capabilities: dedicated memory should return 1 and all software rasterizers should return 0. * ``PIPE_CAP_QUERY_PIPELINE_STATISTICS``: Whether PIPE_QUERY_PIPELINE_STATISTICS is supported. +* ``PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK``: Bitmask indicating whether special + considerations have to be given to the interaction between the border color + in the sampler object and the sampler view used with it. + If PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600 is set, the border color + may be affected in undefined ways for any kind of permutational swizzle + (any swizzle XYZW where X/Y/Z/W are not ZERO, ONE, or R/G/B/A respectively) + in the sampler view. + If PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 is set, the border color + state should be swizzled manually according to the swizzle in the sampler + view it is intended to be used with, or herein undefined results may occur + for permutational swizzles. .. _pipe_capf: diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 283d07f..4a9a54e 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -200,6 +200,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_USER_VERTEX_BUFFERS: case PIPE_CAP_USER_INDEX_BUFFERS: case PIPE_CAP_QUERY_PIPELINE_STATISTICS: + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return 0; /* Stream output. */ diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index 54b2154..dfb76b3 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -213,6 +213,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) case PIPE_CAP_QUERY_PIPELINE_STATISTICS: case PIPE_CAP_TEXTURE_MULTISAMPLE: case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT: + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return 0; case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT: diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index 7152c3e..5535f85 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -138,6 +138,8 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) return 1; case PIPE_CAP_TEXTURE_SWIZZLE: return 1; + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: + return 0; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return LP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: diff --git a/src/gallium/drivers/nv30/nv30_screen.c b/src/gallium/drivers/nv30/nv30_screen.c index e33710e..5b3b470 100644 --- a/src/gallium/drivers/nv30/nv30_screen.c +++ b/src/gallium/drivers/nv30/nv30_screen.c @@ -123,6 +123,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_QUERY_PIPELINE_STATISTICS: + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return 0; case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 55081be..5aa8ef3 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -186,6 +186,8 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 1; case PIPE_CAP_QUERY_PIPELINE_STATISTICS: return 0; + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: + return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50; default: NOUVEAU_ERR("unknown PIPE_CAP %d\n", param); return 0; diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index ccdf2cd..8dfd4d1 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -176,6 +176,8 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return (class_3d >= NVE4_3D_CLASS) ? 1 : 0; case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: return 1; + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: + return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50; default: NOUVEAU_ERR("unknown PIPE_CAP %d\n", param); return 0; diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index 3175b3b..a932be9 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -162,6 +162,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_CUBE_MAP_ARRAY: case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return 0; /* SWTCL-only features. */ diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 9b43cef..4948ddd 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -654,6 +654,9 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_MAX_TEXEL_OFFSET: return 7; + + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: + return PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600; } return 0; } diff --git a/src/gallium/drivers/radeonsi/radeonsi_pipe.c b/src/gallium/drivers/radeonsi/radeonsi_pipe.c index 5c25b2f..4e97f51 100644 --- a/src/gallium/drivers/radeonsi/radeonsi_pipe.c +++ b/src/gallium/drivers/radeonsi/radeonsi_pipe.c @@ -380,6 +380,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_CUBE_MAP_ARRAY: case PIPE_CAP_TEXTURE_BUFFER_OBJECTS: case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: return 0; /* Stream output. */ diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index b2b7f2e..53ee7d3 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -94,6 +94,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) return 1; case PIPE_CAP_TEXTURE_SWIZZLE: return 1; + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: + return 0; case PIPE_CAP_MAX_TEXTURE_2D_LEVELS: return SP_MAX_TEXTURE_2D_LEVELS; case PIPE_CAP_MAX_TEXTURE_3D_LEVELS: diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index 6213535..60e0442 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -166,6 +166,8 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param) return 1; case PIPE_CAP_TEXTURE_SWIZZLE: return 1; + case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK: + return 0; case PIPE_CAP_USER_VERTEX_BUFFERS: case PIPE_CAP_USER_INDEX_BUFFERS: return 0; diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 5b00acc..2d38ce1 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -505,9 +505,14 @@ enum pipe_cap { PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT = 78, PIPE_CAP_TGSI_TEXCOORD = 79, PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER = 80, - PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81 + PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81, + PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK = 82 }; +#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0) +#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600 (1 << 1) + + /** * Implementation limits which are queried through * pipe_screen::get_paramf() diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 32bcc26..7d38392 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -55,10 +55,10 @@ static const struct st_tracked_state *atoms[] = &st_update_viewport, &st_update_scissor, &st_update_blend, - &st_update_sampler, &st_update_vertex_texture, &st_update_fragment_texture, &st_update_geometry_texture, + &st_update_sampler, /* depends on update_*_texture for swizzle */ &st_update_framebuffer, &st_update_msaa, &st_update_vs_constants, diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 3eba5b1..db51eea 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -48,6 +48,8 @@ #include "cso_cache/cso_context.h" +#include "util/u_format.h" + /** * Convert GLenum texcoord wrap tokens to pipe tokens. @@ -172,8 +174,10 @@ convert_sampler(struct st_context *st, msamp->BorderColor.ui[1] || msamp->BorderColor.ui[2] || msamp->BorderColor.ui[3]) { + struct st_texture_object *stobj = st_texture_object(texobj); struct gl_texture_image *teximg; GLboolean is_integer = GL_FALSE; + union pipe_color_union border_color; teximg = texobj->Image[0][texobj->BaseLevel]; @@ -181,9 +185,26 @@ convert_sampler(struct st_context *st, is_integer = _mesa_is_enum_format_integer(teximg->InternalFormat); } - st_translate_color(&msamp->BorderColor, - &sampler->border_color, - teximg ? teximg->_BaseFormat : GL_RGBA, is_integer); + if (st->apply_texture_swizzle_to_border_color && stobj->sampler_view) { + const unsigned char swz[4] = + { + stobj->sampler_view->swizzle_r, + stobj->sampler_view->swizzle_g, + stobj->sampler_view->swizzle_b, + stobj->sampler_view->swizzle_a, + }; + + st_translate_color(&msamp->BorderColor, + &border_color, + teximg ? teximg->_BaseFormat : GL_RGBA, is_integer); + + util_format_apply_color_swizzle(&sampler->border_color, + &border_color, swz, is_integer); + } else { + st_translate_color(&msamp->BorderColor, + &sampler->border_color, + teximg ? teximg->_BaseFormat : GL_RGBA, is_integer); + } } sampler->max_anisotropy = (msamp->MaxAnisotropy == 1.0 ? diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c index 2042be3..ed1bf26 100644 --- a/src/mesa/state_tracker/st_context.c +++ b/src/mesa/state_tracker/st_context.c @@ -188,6 +188,10 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe, st->needs_texcoord_semantic = screen->get_param(screen, PIPE_CAP_TGSI_TEXCOORD); + st->apply_texture_swizzle_to_border_color = + !!(screen->get_param(screen, PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK) & + (PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 | + PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600)); /* GL limits and extensions */ st_init_limits(st); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 8786a03..807453e 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -87,6 +87,7 @@ struct st_context boolean prefer_blit_based_texture_transfer; boolean needs_texcoord_semantic; + boolean apply_texture_swizzle_to_border_color; /* On old libGL's for linux we need to invalidate the drawables * on glViewpport calls, this is set via a option. _______________________________________________ mesa-commit mailing list mesa-commit@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-commit