From 12b959c351d81a35139ad0e504f6f6896077dbd0 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 25 Mar 2014 11:04:40 -0600 Subject: [PATCH] st/mesa: overhaul texture / sample swizzle code MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Previously we only examined the GL_DEPTH_MODE state to determine the sampler view swizzle for depth textures. Now we also consider the texture base format for color textures too. The basic idea is if we're sampling from a RGB texture we always want to get A=1, even if the actual hardware format might be RGBA. We had assumed that the texture's A values were always one since that's what Mesa's texstore code does. But if we render to the RGBA texture, the A values might not be 1. Subsequent sampling didn't return the right values. Now we examine the user-specified texture base format vs. the actual gallium format to determine the right swizzle. Fixes several fbo-blending-formats, fbo-clear-formats and fbo-tex-rgbx failures with VMware/svga driver (and possibly other drivers). No other piglit regressions with softpipe or VMware/svga. Reviewed-by: Marek Olšák --- src/mesa/state_tracker/st_atom_texture.c | 167 ++++++++++++++++------- 1 file changed, 114 insertions(+), 53 deletions(-) diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index c4452134a22..c9bffce4f7e 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -83,67 +83,132 @@ swizzle_swizzle(unsigned swizzle1, unsigned swizzle2) /** - * Combine depth texture mode with "swizzle" so that depth mode swizzling - * takes place before texture swizzling, and return the resulting swizzle. - * If the format is not a depth format, return "swizzle" unchanged. + * Given a user-specified texture base format, the actual gallium texture + * format and the current GL_DEPTH_MODE, return a texture swizzle. * - * \param format PIPE_FORMAT_*. - * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. - * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED. + * Consider the case where the user requests a GL_RGB internal texture + * format the driver actually uses an RGBA format. The A component should + * be ignored and sampling from the texture should always return (r,g,b,1). + * But if we rendered to the texture we might have written A values != 1. + * By sampling the texture with a ".xyz1" swizzle we'll get the expected A=1. + * This function computes the texture swizzle needed to get the expected + * values. + * + * In the case of depth textures, the GL_DEPTH_MODE state determines the + * texture swizzle. + * + * This result must be composed with the user-specified swizzle to get + * the final swizzle. */ -static GLuint -apply_depthmode(enum pipe_format format, GLuint swizzle, GLenum depthmode) +static unsigned +compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode, + enum pipe_format actualFormat) { - const struct util_format_description *desc = - util_format_description(format); - unsigned swz; - - if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS || - desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) { - /* Not a depth format. */ - return swizzle; - } - - switch (depthmode) { + switch (baseFormat) { + case GL_RGBA: + return SWIZZLE_XYZW; + case GL_RGB: + if (util_format_has_alpha(actualFormat)) + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE); + else + return SWIZZLE_XYZW; + case GL_RG: + if (util_format_get_nr_components(actualFormat) > 2) + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE); + else + return SWIZZLE_XYZW; + case GL_RED: + if (util_format_get_nr_components(actualFormat) > 1) + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ONE); + else + return SWIZZLE_XYZW; + case GL_ALPHA: + if (util_format_get_nr_components(actualFormat) > 1) + return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_W); + else + return SWIZZLE_XYZW; case GL_LUMINANCE: - swz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); - break; + if (util_format_get_nr_components(actualFormat) > 1) + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); + else + return SWIZZLE_XYZW; + case GL_LUMINANCE_ALPHA: + if (util_format_get_nr_components(actualFormat) > 2) + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W); + else + return SWIZZLE_XYZW; case GL_INTENSITY: - swz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); - break; - case GL_ALPHA: - swz = MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_X); - break; - case GL_RED: - swz = MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, SWIZZLE_ZERO, SWIZZLE_ONE); - break; + if (util_format_get_nr_components(actualFormat) > 1) + return SWIZZLE_XXXX; + else + return SWIZZLE_XYZW; + case GL_STENCIL_INDEX: + return SWIZZLE_XYZW; + case GL_DEPTH_STENCIL: + /* fall-through */ + case GL_DEPTH_COMPONENT: + /* Now examine the depth mode */ + switch (depthMode) { + case GL_LUMINANCE: + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); + case GL_INTENSITY: + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_X); + case GL_ALPHA: + return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_X); + case GL_RED: + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ONE); + default: + assert(!"Unexpected depthMode"); + return SWIZZLE_XYZW; + } + default: + assert(!"Unexpected baseFormat"); + return SWIZZLE_XYZW; } - - return swizzle_swizzle(swizzle, swz); } +static unsigned +get_texture_format_swizzle(const struct st_texture_object *stObj) +{ + const struct gl_texture_image *texImage = + stObj->base.Image[0][stObj->base.BaseLevel]; + unsigned tex_swizzle; + + if (texImage) { + tex_swizzle = compute_texture_format_swizzle(texImage->_BaseFormat, + stObj->base.DepthMode, + stObj->pt->format); + } + else { + tex_swizzle = SWIZZLE_XYZW; + } + + /* Combine the texture format swizzle with user's swizzle */ + return swizzle_swizzle(stObj->base._Swizzle, tex_swizzle); +} + + /** - * Return TRUE if the swizzling described by "swizzle" and - * "depthmode" (for depth textures only) is different from the swizzling - * set in the given sampler view. + * Return TRUE if the texture's sampler view swizzle is equal to + * the texture's swizzle. * - * \param sv A sampler view. - * \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4. - * \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA. + * \param stObj the st texture object, */ static boolean -check_sampler_swizzle(struct pipe_sampler_view *sv, - GLuint swizzle, GLenum depthmode) +check_sampler_swizzle(const struct st_texture_object *stObj) { - swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode); - - if ((sv->swizzle_r != GET_SWZ(swizzle, 0)) || - (sv->swizzle_g != GET_SWZ(swizzle, 1)) || - (sv->swizzle_b != GET_SWZ(swizzle, 2)) || - (sv->swizzle_a != GET_SWZ(swizzle, 3))) - return TRUE; - return FALSE; + const struct pipe_sampler_view *sv = stObj->sampler_view; + unsigned swizzle = get_texture_format_swizzle(stObj); + + return ((sv->swizzle_r != GET_SWZ(swizzle, 0)) || + (sv->swizzle_g != GET_SWZ(swizzle, 1)) || + (sv->swizzle_b != GET_SWZ(swizzle, 2)) || + (sv->swizzle_a != GET_SWZ(swizzle, 3))); } @@ -154,9 +219,7 @@ st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe, enum pipe_format format) { struct pipe_sampler_view templ; - GLuint swizzle = apply_depthmode(stObj->pt->format, - stObj->base._Swizzle, - stObj->base.DepthMode); + unsigned swizzle = get_texture_format_swizzle(stObj); u_sampler_view_default_template(&templ, stObj->pt, @@ -269,9 +332,7 @@ update_single_texture(struct st_context *st, /* if sampler view has changed dereference it */ if (stObj->sampler_view) { - if (check_sampler_swizzle(stObj->sampler_view, - stObj->base._Swizzle, - stObj->base.DepthMode) || + if (check_sampler_swizzle(stObj) || (view_format != stObj->sampler_view->format) || stObj->base.BaseLevel != stObj->sampler_view->u.tex.first_level) { pipe_sampler_view_release(pipe, &stObj->sampler_view); -- 2.30.2