diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 85c6f1c44dd..1c725f01008 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -982,6 +982,9 @@ struct gl_texture_object */ GLuint lastLevel; + unsigned Swizzle; + unsigned SwizzleGLSL130; + unsigned int validated_first_level; unsigned int validated_last_level; diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c index 90ba4130770..267738313b9 100644 --- a/src/mesa/main/teximage.c +++ b/src/mesa/main/teximage.c @@ -3288,6 +3288,7 @@ teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, 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_update_texture_object_swizzle(ctx, texObj); } } _mesa_unlock_texture(ctx, texObj); @@ -4547,6 +4548,7 @@ copyteximage(struct gl_context *ctx, GLuint dims, struct gl_texture_object *texO _mesa_update_fbo_texture(ctx, texObj, face, level); _mesa_dirty_texobj(ctx, texObj); + _mesa_update_texture_object_swizzle(ctx, texObj); } } _mesa_unlock_texture(ctx, texObj); @@ -7030,6 +7032,7 @@ texture_image_multisample(struct gl_context *ctx, GLuint dims, _mesa_update_fbo_texture(ctx, texObj, 0, 0); } + _mesa_update_texture_object_swizzle(ctx, texObj); } diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c index 7637acd4add..a59ee386d9d 100644 --- a/src/mesa/main/texobj.c +++ b/src/mesa/main/texobj.c @@ -262,6 +262,57 @@ _mesa_get_texobj_by_target_and_texunit(struct gl_context *ctx, GLenum target, return texUnit->CurrentTex[targetIndex]; } +/** + * Return swizzle1(swizzle2) + */ +static unsigned +swizzle_swizzle(unsigned swizzle1, unsigned swizzle2) +{ + unsigned i, swz[4]; + + if (swizzle1 == SWIZZLE_XYZW) { + /* identity swizzle, no change to swizzle2 */ + return swizzle2; + } + + for (i = 0; i < 4; i++) { + unsigned s = GET_SWZ(swizzle1, i); + switch (s) { + case SWIZZLE_X: + case SWIZZLE_Y: + case SWIZZLE_Z: + case SWIZZLE_W: + swz[i] = GET_SWZ(swizzle2, s); + break; + case SWIZZLE_ZERO: + swz[i] = SWIZZLE_ZERO; + break; + case SWIZZLE_ONE: + swz[i] = SWIZZLE_ONE; + break; + default: + assert(!"Bad swizzle term"); + swz[i] = SWIZZLE_X; + } + } + + return MAKE_SWIZZLE4(swz[0], swz[1], swz[2], swz[3]); +} + +void +_mesa_update_texture_object_swizzle(struct gl_context *ctx, + struct gl_texture_object *texObj) +{ + if (texObj->Attrib.BaseLevel >= MAX_TEXTURE_LEVELS) + return; + const struct gl_texture_image *img = texObj->Image[0][texObj->Attrib.BaseLevel]; + if (!img) + return; + + /* Combine the texture format swizzle with user's swizzle */ + texObj->Swizzle = swizzle_swizzle(texObj->Attrib._Swizzle, img->FormatSwizzle); + texObj->SwizzleGLSL130 = swizzle_swizzle(texObj->Attrib._Swizzle, img->FormatSwizzleGLSL130); +} /** * Initialize a new texture object to default values. @@ -1034,7 +1085,7 @@ _mesa_get_fallback_texture(struct gl_context *ctx, gl_texture_index tex) (dims > 2) ? depth : 1, 0, /* border */ GL_RGBA, texFormat); - + _mesa_update_texture_object_swizzle(ctx, texObj); st_TexImage(ctx, dims, texImage, GL_RGBA, GL_UNSIGNED_BYTE, texel, &ctx->DefaultPacking); diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h index e7d2577de36..2182528ff52 100644 --- a/src/mesa/main/texobj.h +++ b/src/mesa/main/texobj.h @@ -204,7 +204,9 @@ extern struct gl_texture_object * _mesa_lookup_or_create_texture(struct gl_context *ctx, GLenum target, GLuint texName, bool no_error, bool is_ext_dsa, const char *name); - +void +_mesa_update_texture_object_swizzle(struct gl_context *ctx, + struct gl_texture_object *texObj); /*@}*/ #ifdef __cplusplus diff --git a/src/mesa/main/texparam.c b/src/mesa/main/texparam.c index 7799ba9c632..b8918f9500c 100644 --- a/src/mesa/main/texparam.c +++ b/src/mesa/main/texparam.c @@ -415,8 +415,10 @@ 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) + if (texObj->Attrib.BaseLevel < MAX_TEXTURE_LEVELS) { _mesa_update_teximage_format_swizzle(ctx, texObj->Image[0][texObj->Attrib.BaseLevel], texObj->Attrib.DepthMode); + _mesa_update_texture_object_swizzle(ctx, texObj); + } return GL_TRUE; @@ -520,8 +522,10 @@ 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) + if (texObj->Attrib.BaseLevel < MAX_TEXTURE_LEVELS) { _mesa_update_teximage_format_swizzle(ctx, texObj->Image[0][texObj->Attrib.BaseLevel], texObj->Attrib.DepthMode); + _mesa_update_texture_object_swizzle(ctx, texObj); + } return GL_TRUE; } goto invalid_param; @@ -572,6 +576,7 @@ set_tex_parameteri(struct gl_context *ctx, flush(ctx); texObj->Attrib.Swizzle[comp] = params[0]; set_swizzle_component(&texObj->Attrib._Swizzle, comp, swz); + _mesa_update_texture_object_swizzle(ctx, texObj); return GL_TRUE; } goto invalid_pname; @@ -586,6 +591,7 @@ set_tex_parameteri(struct gl_context *ctx, if (swz >= 0) { texObj->Attrib.Swizzle[comp] = params[comp]; set_swizzle_component(&texObj->Attrib._Swizzle, comp, swz); + _mesa_update_texture_object_swizzle(ctx, texObj); } else { _mesa_error(ctx, GL_INVALID_ENUM, diff --git a/src/mesa/main/texstorage.c b/src/mesa/main/texstorage.c index 166e68ea45f..4c82b05e1d3 100644 --- a/src/mesa/main/texstorage.c +++ b/src/mesa/main/texstorage.c @@ -169,6 +169,7 @@ initialize_texture_fields(struct gl_context *ctx, levelWidth, levelHeight, levelDepth, &levelWidth, &levelHeight, &levelDepth); } + _mesa_update_texture_object_swizzle(ctx, texObj); return GL_TRUE; } diff --git a/src/mesa/main/textureview.c b/src/mesa/main/textureview.c index f6c70aebf27..65a132232bc 100644 --- a/src/mesa/main/textureview.c +++ b/src/mesa/main/textureview.c @@ -701,6 +701,7 @@ texture_view(struct gl_context *ctx, struct gl_texture_object *origTexObj, texObj->Target = target; texObj->TargetIndex = _mesa_tex_target_to_index(ctx, target); assert(texObj->TargetIndex < NUM_TEXTURE_TARGETS); + _mesa_update_texture_object_swizzle(ctx, texObj); if (!st_TextureView(ctx, texObj, origTexObj)) { return; /* driver recorded error */ diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c index 03ff48b672f..34a177ad1c8 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.c +++ b/src/mesa/state_tracker/st_cb_eglimage.c @@ -405,6 +405,7 @@ st_bind_egl_image(struct gl_context *ctx, texObj->level_override = stimg->level; texObj->layer_override = stimg->layer; + _mesa_update_texture_object_swizzle(ctx, texObj); _mesa_dirty_texobj(ctx, texObj); } diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index 485a056acfc..2515c54bc3c 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -1041,6 +1041,7 @@ prep_teximage(struct gl_context *ctx, struct gl_texture_image *texImage, texImage->InternalFormat, texFormat); texObj->surface_based = GL_FALSE; + _mesa_update_texture_object_swizzle(ctx, texObj); } } diff --git a/src/mesa/state_tracker/st_manager.c b/src/mesa/state_tracker/st_manager.c index e49ce3ae6f2..8c5dab9bd3f 100644 --- a/src/mesa/state_tracker/st_manager.c +++ b/src/mesa/state_tracker/st_manager.c @@ -900,6 +900,7 @@ st_context_teximage(struct st_context_iface *stctxi, _mesa_clear_texture_image(ctx, texImage); width = height = depth = 0; } + _mesa_update_texture_object_swizzle(ctx, texObj); pipe_resource_reference(&texObj->pt, tex); st_texture_release_all_sampler_views(st, texObj);