diff options
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 18456371c0a..9bdc2eabf11 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 ed942fb1658..e4b9c365c97 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 26ffc181031..9959793a332 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 4b01d77322e..3ab7e9e6906 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 283d07f12e4..4a9a54e3aea 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 54b21549ba5..dfb76b3e98c 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 7152c3e8bca..5535f8523a7 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 e33710e71f7..5b3b470cc4e 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 55081beb300..5aa8ef32e65 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 ccdf2cde84b..8dfd4d12a02 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 3175b3bdd40..a932be9b41d 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 9b43cef2737..4948dddae74 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 5c25b2f98b3..4e97f51dbdc 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 b2b7f2e3208..53ee7d31cab 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 6213535a23e..60e0442944b 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 5b00acc7418..2d38ce1a8c4 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 32bcc266a34..7d383924300 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 3eba5b13cae..db51eead16b 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 2042be36bd3..ed1bf26a260 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 8786a036ff4..807453e9974 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. |