diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index eea350fbd72..85c6f1c44dd 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -789,6 +789,9 @@ struct gl_texture_image /** Cube map face: index into gl_texture_object::Image[] array */ GLuint Face; + unsigned FormatSwizzle; + unsigned FormatSwizzleGLSL130; //for depth formats + /** GL_ARB_texture_multisample */ GLuint NumSamples; /**< Sample count, or 0 for non-multisample */ GLboolean FixedSampleLocations; /**< Same sample locations for all pixels? */ diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index b9f2e88e032..90ba4130770 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -60,6 +60,8 @@ #include "util/u_memory.h" +#include "program/prog_instruction.h" + #include "state_tracker/st_cb_texture.h" #include "state_tracker/st_context.h" #include "state_tracker/st_format.h" @@ -803,6 +805,100 @@ clear_teximage_fields(struct gl_texture_image *img) img->FixedSampleLocations = GL_TRUE; } +/** + * Given a user-specified texture base format, the actual gallium texture + * format and the current GL_DEPTH_MODE, return a texture swizzle. + * + * 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 unsigned +compute_texture_format_swizzle(GLenum baseFormat, GLenum depthMode, + bool glsl130_or_later) +{ + switch (baseFormat) { + case GL_RGBA: + return SWIZZLE_XYZW; + case GL_RGB: + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_ONE); + case GL_RG: + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_ZERO, SWIZZLE_ONE); + case GL_RED: + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_ONE); + case GL_ALPHA: + return MAKE_SWIZZLE4(SWIZZLE_ZERO, SWIZZLE_ZERO, + SWIZZLE_ZERO, SWIZZLE_W); + case GL_LUMINANCE: + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_ONE); + case GL_LUMINANCE_ALPHA: + return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_X, SWIZZLE_X, SWIZZLE_W); + case GL_INTENSITY: + return SWIZZLE_XXXX; + case GL_STENCIL_INDEX: + case GL_DEPTH_STENCIL: + 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: + /* The texture(sampler*Shadow) functions from GLSL 1.30 ignore + * the depth mode and return float, while older shadow* functions + * and ARB_fp instructions return vec4 according to the depth mode. + * + * The problem with the GLSL 1.30 functions is that GL_ALPHA forces + * them to return 0, breaking them completely. + * + * A proper fix would increase code complexity and that's not worth + * it for a rarely used feature such as the GL_ALPHA depth mode + * in GL3. Therefore, change GL_ALPHA to GL_INTENSITY for all + * shaders that use GLSL 1.30 or later. + * + * BTW, it's required that sampler views are updated when + * shaders change (check_sampler_swizzle takes care of that). + */ + if (glsl130_or_later) + return SWIZZLE_XXXX; + else + 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; + } +} + +void +_mesa_update_teximage_format_swizzle(struct gl_context *ctx, + struct gl_texture_image *img, + GLenum depth_mode) +{ + if (!img) + return; + img->FormatSwizzle = compute_texture_format_swizzle(img->_BaseFormat, depth_mode, false); + img->FormatSwizzleGLSL130 = compute_texture_format_swizzle(img->_BaseFormat, depth_mode, true); +} /** * Initialize basic fields of the gl_texture_image struct. @@ -845,6 +941,22 @@ _mesa_init_teximage_fields_ms(struct gl_context *ctx, img->Height = height; img->Depth = depth; + GLenum depth_mode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE; + + /* In ES 3.0, DEPTH_TEXTURE_MODE is expected to be GL_RED for textures + * with depth component data specified with a sized internal format. + */ + if (_mesa_is_gles3(ctx) && + (base_format == GL_DEPTH_COMPONENT || + base_format == GL_DEPTH_STENCIL || + base_format == GL_STENCIL_INDEX)) { + if (internalFormat != GL_DEPTH_COMPONENT && + internalFormat != GL_DEPTH_STENCIL && + internalFormat != GL_STENCIL_INDEX) + depth_mode = GL_RED; + } + _mesa_update_teximage_format_swizzle(ctx, img, depth_mode); + img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ img->WidthLog2 = util_logbase2(img->Width2); @@ -3172,6 +3284,10 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, _mesa_update_fbo_texture(ctx, texObj, face, level); _mesa_dirty_texobj(ctx, texObj); + /* only apply depthMode swizzle if it was explicitly changed */ + GLenum depth_mode = ctx->API == API_OPENGL_CORE ? GL_RED : GL_LUMINANCE; + if (texObj->Attrib.DepthMode != depth_mode) + _mesa_update_teximage_format_swizzle(ctx, texObj->Image[0][texObj->Attrib.BaseLevel], texObj->Attrib.DepthMode); } } _mesa_unlock_texture(ctx, texObj); diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h index da8721ddc81..12ba82a4997 100644 --- a/src/mesa/main/teximage.h +++ b/src/mesa/main/teximage.h @@ -139,7 +139,10 @@ _mesa_init_teximage_fields_ms(struct gl_context *ctx, GLuint numSamples, GLboolean fixedSampleLocations); - +void +_mesa_update_teximage_format_swizzle(struct gl_context *ctx, + struct gl_texture_image *img, + GLenum depth_mode); extern mesa_format _mesa_choose_texture_format(struct gl_context *ctx, struct gl_texture_object *texObj, diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index fd84515d2b0..7799ba9c632 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -415,6 +415,8 @@ set_tex_parameteri(struct gl_context *ctx, texObj->Attrib.BaseLevel = MIN2(texObj->Attrib.ImmutableLevels - 1, params[0]); else texObj->Attrib.BaseLevel = params[0]; + if (texObj->Attrib.BaseLevel < MAX_TEXTURE_LEVELS) + _mesa_update_teximage_format_swizzle(ctx, texObj->Image[0][texObj->Attrib.BaseLevel], texObj->Attrib.DepthMode); return GL_TRUE; @@ -518,6 +520,8 @@ set_tex_parameteri(struct gl_context *ctx, (ctx->Extensions.ARB_texture_rg && params[0] == GL_RED)) { flush(ctx); texObj->Attrib.DepthMode = params[0]; + if (texObj->Attrib.BaseLevel < MAX_TEXTURE_LEVELS) + _mesa_update_teximage_format_swizzle(ctx, texObj->Image[0][texObj->Attrib.BaseLevel], texObj->Attrib.DepthMode); return GL_TRUE; } goto invalid_param;