diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index d859c9cfac..b1ba3b54c5 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -641,6 +641,11 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve if(discard_level > 0) { mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)discard_level); + // [FIRE-35361] RenderMaxTextureResolution caps texture resolution lower than intended + // 2K textures could set the mMaxDiscardLevel above MAX_DISCARD_LEVEL, which would + // cause them to not be down-scaled so they would get stuck at 0 discard all the time. + mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)MAX_DISCARD_LEVEL); + // [FIRE-35361] } } else diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 014e9311ac..80a9e73f96 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -2095,6 +2095,30 @@ LLPointer LLTextureCache::readFromFastCache(const LLUUID& id, S32& d } LLPointer raw = new LLImageRaw(data, head[0], head[1], head[2], true); + // + // This fixes the invalid discard values from being created which cause the decoder code to fail when trying to handle 6 and 7's which are above the MAX_DISCARD_LEVEL of 5 + // especially on load + // We will expand the 16x16 texture to the actual MAX_DISCARD_LEVEL texture size, it may be blurry until the user gets closer but 5 discard value should be objects far from the camera. + // So a 1024x1024 texture with a dicard of 6 will become 32x32 and a 2048x2048 texture with a discard of 7 will become a 64x64 texture. + if (discardlevel > MAX_DISCARD_LEVEL) + { + LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("FixBadDiscardLevel"); + + S32 w = head[0]; // Get the current width from the header (16) + S32 h = head[1]; // Get the current height from the header (16) + + // Expand the width and height by teh difference between the discard and MAX_DISCARD_LEVEL bit shifted to the left. (Expand power of 2 textures) + w <<= discardlevel - MAX_DISCARD_LEVEL; + h <<= discardlevel - MAX_DISCARD_LEVEL; + + // Set the discard level to the MAX_DISCARD_LEVEL + discardlevel = MAX_DISCARD_LEVEL; + + // Scale up the texture and scale the actual data, as we just created it above, it should be fine. + raw->scale(w, h, true); + } + // + return raw; }