Merge branch 'release/materials_featurette' of https://github.com/secondlife/viewer
commit
6340d7a418
|
|
@ -1916,6 +1916,73 @@ void LLImageRaw::compositeRowScaled4onto3( U8* in, U8* out, S32 in_pixel_len, S3
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void LLImageRaw::addEmissive(LLImageRaw* src)
|
||||
{
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
||||
if (!validateSrcAndDst(__FUNCTION__, src, dst))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
llassert((3 == src->getComponents()) || (4 == src->getComponents()));
|
||||
llassert(3 == dst->getComponents());
|
||||
|
||||
if( 3 == dst->getComponents() )
|
||||
{
|
||||
if( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) )
|
||||
{
|
||||
addEmissiveUnscaled(src);
|
||||
}
|
||||
else
|
||||
{
|
||||
addEmissiveScaled(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageRaw::addEmissiveUnscaled(LLImageRaw* src)
|
||||
{
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
||||
llassert((3 == src->getComponents()) || (4 == src->getComponents()));
|
||||
llassert((3 == dst->getComponents()) || (4 == dst->getComponents()));
|
||||
llassert( (src->getWidth() == dst->getWidth()) && (src->getHeight() == dst->getHeight()) );
|
||||
|
||||
U8* const src_data = src->getData();
|
||||
U8* const dst_data = dst->getData();
|
||||
for(S32 y = 0; y < dst->getHeight(); ++y)
|
||||
{
|
||||
const S32 src_row_offset = src->getComponents() * src->getWidth() * y;
|
||||
const S32 dst_row_offset = dst->getComponents() * dst->getWidth() * y;
|
||||
for (S32 x = 0; x < dst->getWidth(); ++x)
|
||||
{
|
||||
const S32 src_offset = src_row_offset + (x * src->getComponents());
|
||||
const S32 dst_offset = dst_row_offset + (x * dst->getComponents());
|
||||
U8* const src_pixel = src_data + src_offset;
|
||||
U8* const dst_pixel = dst_data + dst_offset;
|
||||
dst_pixel[0] = llmin(255, dst_pixel[0] + src_pixel[0]);
|
||||
dst_pixel[1] = llmin(255, dst_pixel[1] + src_pixel[1]);
|
||||
dst_pixel[2] = llmin(255, dst_pixel[2] + src_pixel[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageRaw::addEmissiveScaled(LLImageRaw* src)
|
||||
{
|
||||
LLImageRaw* dst = this; // Just for clarity.
|
||||
|
||||
llassert( (4 == src->getComponents()) && (3 == dst->getComponents()) );
|
||||
|
||||
LLImageRaw temp(dst->getWidth(), dst->getHeight(), dst->getComponents());
|
||||
llassert_always(temp.getDataSize() > 0);
|
||||
temp.copyScaled(src);
|
||||
|
||||
dst->addEmissiveUnscaled(&temp);
|
||||
}
|
||||
|
||||
|
||||
bool LLImageRaw::validateSrcAndDst(std::string func, LLImageRaw* src, LLImageRaw* dst)
|
||||
{
|
||||
if (!src || !dst || src->isBufferInvalid() || dst->isBufferInvalid())
|
||||
|
|
|
|||
|
|
@ -283,6 +283,12 @@ public:
|
|||
// Src and dst are same size. Src has 4 components. Dst has 3 components.
|
||||
void compositeUnscaled4onto3( LLImageRaw* src );
|
||||
|
||||
// Emissive operations used by minimap
|
||||
// Roughly emulates GLTF emissive texture, but is not GLTF-compliant
|
||||
// *TODO: Remove in favor of shader
|
||||
void addEmissive(LLImageRaw* src);
|
||||
void addEmissiveScaled(LLImageRaw* src);
|
||||
void addEmissiveUnscaled(LLImageRaw* src);
|
||||
protected:
|
||||
// Create an image from a local file (generally used in tools)
|
||||
//bool createFromFile(const std::string& filename, bool j2c_lowest_mip_only = false);
|
||||
|
|
|
|||
|
|
@ -95,7 +95,8 @@ void LLGLTexture::setBoostLevel(S32 level)
|
|||
mBoostLevel = level ;
|
||||
if(mBoostLevel != LLGLTexture::BOOST_NONE
|
||||
&& mBoostLevel != LLGLTexture::BOOST_ICON
|
||||
&& mBoostLevel != LLGLTexture::BOOST_THUMBNAIL)
|
||||
&& mBoostLevel != LLGLTexture::BOOST_THUMBNAIL
|
||||
&& mBoostLevel != LLGLTexture::BOOST_TERRAIN)
|
||||
{
|
||||
setNoDelete() ;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,10 +52,11 @@ public:
|
|||
BOOST_AVATAR ,
|
||||
BOOST_AVATAR_BAKED ,
|
||||
BOOST_SCULPTED ,
|
||||
BOOST_TERRAIN , // Needed for minimap generation for now. Lower than BOOST_HIGH so the texture stats don't get forced, i.e. texture stats are manually managed by minimap/terrain instead.
|
||||
|
||||
BOOST_HIGH = 10,
|
||||
BOOST_BUMP ,
|
||||
BOOST_TERRAIN , // has to be high priority for minimap / low detail
|
||||
BOOST_UNUSED_1 , // Placeholder to avoid disrupting habits around texture debug
|
||||
BOOST_SELECTED ,
|
||||
BOOST_AVATAR_BAKED_SELF ,
|
||||
BOOST_AVATAR_SELF , // needed for baking avatar
|
||||
|
|
|
|||
|
|
@ -129,41 +129,7 @@ void LLDrawPoolTerrain::boostTerrainDetailTextures()
|
|||
// Hack! Get the region that this draw pool is rendering from!
|
||||
LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion();
|
||||
LLVLComposition *compp = regionp->getComposition();
|
||||
for (S32 i = 0; i < 4; i++)
|
||||
{
|
||||
constexpr LLGLTexture::EBoostLevel level = LLGLTexture::BOOST_TERRAIN;
|
||||
constexpr float stats = 1024.f * 1024.f;
|
||||
|
||||
LLPointer<LLViewerFetchedTexture>& tex = compp->mDetailTextures[i];
|
||||
llassert(tex.notNull());
|
||||
tex->setBoostLevel(level);
|
||||
tex->addTextureStats(stats);
|
||||
|
||||
LLPointer<LLFetchedGLTFMaterial>& fetched_material = compp->mDetailMaterials[i];
|
||||
if (fetched_material)
|
||||
{
|
||||
if (fetched_material->mBaseColorTexture)
|
||||
{
|
||||
fetched_material->mBaseColorTexture->setBoostLevel(level);
|
||||
fetched_material->mBaseColorTexture->addTextureStats(stats);
|
||||
}
|
||||
if (fetched_material->mNormalTexture)
|
||||
{
|
||||
fetched_material->mNormalTexture->setBoostLevel(level);
|
||||
fetched_material->mNormalTexture->addTextureStats(stats);
|
||||
}
|
||||
if (fetched_material->mMetallicRoughnessTexture)
|
||||
{
|
||||
fetched_material->mMetallicRoughnessTexture->setBoostLevel(level);
|
||||
fetched_material->mMetallicRoughnessTexture->addTextureStats(stats);
|
||||
}
|
||||
if (fetched_material->mEmissiveTexture)
|
||||
{
|
||||
fetched_material->mEmissiveTexture->setBoostLevel(level);
|
||||
fetched_material->mEmissiveTexture->addTextureStats(stats);
|
||||
}
|
||||
}
|
||||
}
|
||||
compp->boost();
|
||||
}
|
||||
|
||||
void LLDrawPoolTerrain::beginDeferredPass(S32 pass)
|
||||
|
|
|
|||
|
|
@ -244,12 +244,8 @@ void LLGLTFMaterialList::applyOverrideMessage(LLMessageSystem* msg, const std::s
|
|||
}
|
||||
}
|
||||
|
||||
// Workaround for server sending empty overrides.
|
||||
if(cache.mSides.size() > 0)
|
||||
{
|
||||
region->cacheFullUpdateGLTFOverride(cache);
|
||||
LL_DEBUGS("GLTF") << "GLTF Material Override: " << cache.mObjectId << " " << cache.mLocalId << " " << cache.mRegionHandle << " (sides:" << (cache.mSides.size()) << ")" << LL_ENDL;
|
||||
}
|
||||
region->cacheFullUpdateGLTFOverride(cache);
|
||||
LL_DEBUGS("GLTF") << "GLTF Material Override: " << cache.mObjectId << " " << cache.mLocalId << " " << cache.mRegionHandle << " (sides:" << (cache.mSides.size()) << ")" << LL_ENDL;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2610,45 +2610,61 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features)
|
|||
|
||||
setSimulatorFeaturesReceived(true);
|
||||
|
||||
// if region has MaxTextureResolution, set max_texture_dimension settings, otherwise use default
|
||||
if (mSimulatorFeatures.has("MaxTextureResolution"))
|
||||
{
|
||||
S32 max_texture_resolution = mSimulatorFeatures["MaxTextureResolution"].asInteger();
|
||||
gSavedSettings.setS32("max_texture_dimension_X", max_texture_resolution);
|
||||
gSavedSettings.setS32("max_texture_dimension_Y", max_texture_resolution);
|
||||
}
|
||||
else
|
||||
{
|
||||
gSavedSettings.setS32("max_texture_dimension_X", 1024);
|
||||
gSavedSettings.setS32("max_texture_dimension_Y", 1024);
|
||||
}
|
||||
// WARNING: this is called from a coroutine, and flipping saved settings has a LOT of side effects, shuttle
|
||||
// the work below back to the main loop
|
||||
//
|
||||
|
||||
// copy features to lambda in case the region is deleted before the lambda is executed
|
||||
LLSD features = mSimulatorFeatures;
|
||||
|
||||
bool mirrors_enabled = false;
|
||||
if (mSimulatorFeatures.has("MirrorsEnabled"))
|
||||
{
|
||||
mirrors_enabled = mSimulatorFeatures["MirrorsEnabled"].asBoolean();
|
||||
}
|
||||
auto work = [=]()
|
||||
{
|
||||
// if region has MaxTextureResolution, set max_texture_dimension settings, otherwise use default
|
||||
if (features.has("MaxTextureResolution"))
|
||||
{
|
||||
S32 max_texture_resolution = features["MaxTextureResolution"].asInteger();
|
||||
gSavedSettings.setS32("max_texture_dimension_X", max_texture_resolution);
|
||||
gSavedSettings.setS32("max_texture_dimension_Y", max_texture_resolution);
|
||||
}
|
||||
else
|
||||
{
|
||||
gSavedSettings.setS32("max_texture_dimension_X", 1024);
|
||||
gSavedSettings.setS32("max_texture_dimension_Y", 1024);
|
||||
}
|
||||
|
||||
gSavedSettings.setBOOL("RenderMirrors", mirrors_enabled);
|
||||
bool mirrors_enabled = false;
|
||||
if (features.has("MirrorsEnabled"))
|
||||
{
|
||||
mirrors_enabled = features["MirrorsEnabled"].asBoolean();
|
||||
}
|
||||
|
||||
if (mSimulatorFeatures.has("PBRTerrainEnabled"))
|
||||
{
|
||||
bool enabled = mSimulatorFeatures["PBRTerrainEnabled"];
|
||||
gSavedSettings.setBOOL("RenderTerrainPBREnabled", enabled);
|
||||
}
|
||||
else
|
||||
{
|
||||
gSavedSettings.setBOOL("RenderTerrainPBREnabled", false);
|
||||
}
|
||||
gSavedSettings.setBOOL("RenderMirrors", mirrors_enabled);
|
||||
|
||||
if (mSimulatorFeatures.has("PBRMaterialSwatchEnabled"))
|
||||
if (features.has("PBRTerrainEnabled"))
|
||||
{
|
||||
bool enabled = features["PBRTerrainEnabled"];
|
||||
gSavedSettings.setBOOL("RenderTerrainPBREnabled", enabled);
|
||||
}
|
||||
else
|
||||
{
|
||||
gSavedSettings.setBOOL("RenderTerrainPBREnabled", false);
|
||||
}
|
||||
|
||||
if (features.has("PBRMaterialSwatchEnabled"))
|
||||
{
|
||||
bool enabled = features["PBRMaterialSwatchEnabled"];
|
||||
gSavedSettings.setBOOL("UIPreviewMaterial", enabled);
|
||||
}
|
||||
else
|
||||
{
|
||||
gSavedSettings.setBOOL("UIPreviewMaterial", false);
|
||||
}
|
||||
};
|
||||
|
||||
auto workqueue = LL::WorkQueue::getInstance("mainloop");
|
||||
if (workqueue)
|
||||
{
|
||||
bool enabled = mSimulatorFeatures["PBRMaterialSwatchEnabled"];
|
||||
gSavedSettings.setBOOL("UIPreviewMaterial", enabled);
|
||||
}
|
||||
else
|
||||
{
|
||||
gSavedSettings.setBOOL("UIPreviewMaterial", false);
|
||||
LL::WorkQueue::postMaybe(workqueue, work);
|
||||
}
|
||||
|
||||
// <FS:CR> Opensim god names
|
||||
|
|
@ -2956,7 +2972,14 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec
|
|||
void LLViewerRegion::cacheFullUpdateGLTFOverride(const LLGLTFOverrideCacheEntry &override_data)
|
||||
{
|
||||
U32 local_id = override_data.mLocalId;
|
||||
mImpl->mGLTFOverridesLLSD[local_id] = override_data;
|
||||
if (override_data.mSides.size() > 0)
|
||||
{ // empty override means overrides were removed from this object
|
||||
mImpl->mGLTFOverridesLLSD[local_id] = override_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
mImpl->mGLTFOverridesLLSD.erase(local_id);
|
||||
}
|
||||
}
|
||||
|
||||
LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id)
|
||||
|
|
@ -3189,6 +3212,11 @@ void LLViewerRegion::dumpCache()
|
|||
// TODO - add overrides cache too
|
||||
}
|
||||
|
||||
void LLViewerRegion::clearVOCacheFromMemory()
|
||||
{
|
||||
mImpl->mCacheMap.clear();
|
||||
}
|
||||
|
||||
void LLViewerRegion::unpackRegionHandshake()
|
||||
{
|
||||
LLMessageSystem *msg = gMessageSystem;
|
||||
|
|
|
|||
|
|
@ -406,7 +406,8 @@ public:
|
|||
LLViewerObject* updateCacheEntry(U32 local_id, LLViewerObject* objectp);
|
||||
void findOrphans(U32 parent_id);
|
||||
void clearCachedVisibleObjects();
|
||||
void dumpCache();
|
||||
void dumpCache ();
|
||||
void clearVOCacheFromMemory();
|
||||
|
||||
void unpackRegionHandshake();
|
||||
|
||||
|
|
|
|||
|
|
@ -430,7 +430,6 @@ public:
|
|||
BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;}
|
||||
BOOL isRawImageValid()const { return mIsRawImageValid ; }
|
||||
void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
|
||||
void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
|
||||
/*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override;
|
||||
void destroySavedRawImage() ;
|
||||
LLImageRaw* getSavedRawImage() ;
|
||||
|
|
@ -456,6 +455,7 @@ public:
|
|||
protected:
|
||||
/*virtual*/ void switchToCachedImage() override;
|
||||
S32 getCurrentDiscardLevelForFetching() ;
|
||||
void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
|
||||
|
||||
private:
|
||||
void init(bool firstinit) ;
|
||||
|
|
|
|||
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include "llvlcomposition.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "llerror.h"
|
||||
#include "v3math.h"
|
||||
#include "llsurface.h"
|
||||
|
|
@ -45,6 +47,7 @@
|
|||
extern LLColor4U MAX_WATER_COLOR;
|
||||
|
||||
static const U32 BASE_SIZE = 128;
|
||||
static const F32 TERRAIN_DECODE_PRIORITY = 2048.f * 2048.f;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
@ -64,25 +67,38 @@ namespace
|
|||
return result;
|
||||
}
|
||||
|
||||
void unboost_minimap_texture(LLPointer<LLViewerFetchedTexture>& tex)
|
||||
void boost_minimap_texture(LLViewerFetchedTexture* tex, F32 virtual_size)
|
||||
{
|
||||
llassert(tex);
|
||||
if (!tex) { return; }
|
||||
|
||||
tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case the raw image is at low detail
|
||||
tex->addTextureStats(virtual_size); // priority
|
||||
}
|
||||
|
||||
void boost_minimap_material(LLFetchedGLTFMaterial* mat, F32 virtual_size)
|
||||
{
|
||||
if (!mat) { return; }
|
||||
if (mat->mBaseColorTexture) { boost_minimap_texture(mat->mBaseColorTexture, virtual_size); }
|
||||
if (mat->mNormalTexture) { boost_minimap_texture(mat->mNormalTexture, virtual_size); }
|
||||
if (mat->mMetallicRoughnessTexture) { boost_minimap_texture(mat->mMetallicRoughnessTexture, virtual_size); }
|
||||
if (mat->mEmissiveTexture) { boost_minimap_texture(mat->mEmissiveTexture, virtual_size); }
|
||||
}
|
||||
|
||||
void unboost_minimap_texture(LLViewerFetchedTexture* tex)
|
||||
{
|
||||
if (!tex) { return; }
|
||||
tex->setBoostLevel(LLGLTexture::BOOST_NONE);
|
||||
tex->setMinDiscardLevel(MAX_DISCARD_LEVEL + 1);
|
||||
|
||||
if (tex->getTextureState() == LLGLTexture::NO_DELETE)
|
||||
{
|
||||
tex->forceActive();
|
||||
}
|
||||
}
|
||||
|
||||
void unboost_minimap_material(LLPointer<LLFetchedGLTFMaterial>& mat)
|
||||
void unboost_minimap_material(LLFetchedGLTFMaterial* mat)
|
||||
{
|
||||
if (!mat) { return; }
|
||||
unboost_minimap_texture(mat->mBaseColorTexture);
|
||||
unboost_minimap_texture(mat->mNormalTexture);
|
||||
unboost_minimap_texture(mat->mMetallicRoughnessTexture);
|
||||
unboost_minimap_texture(mat->mEmissiveTexture);
|
||||
if (mat->mBaseColorTexture) { unboost_minimap_texture(mat->mBaseColorTexture); }
|
||||
if (mat->mNormalTexture) { unboost_minimap_texture(mat->mNormalTexture); }
|
||||
if (mat->mMetallicRoughnessTexture) { unboost_minimap_texture(mat->mMetallicRoughnessTexture); }
|
||||
if (mat->mEmissiveTexture) { unboost_minimap_texture(mat->mEmissiveTexture); }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -96,11 +112,7 @@ LLTerrainMaterials::LLTerrainMaterials()
|
|||
|
||||
LLTerrainMaterials::~LLTerrainMaterials()
|
||||
{
|
||||
for (S32 i = 0; i < ASSET_COUNT; ++i)
|
||||
{
|
||||
unboost_minimap_texture(mDetailTextures[i]);
|
||||
unboost_minimap_material(mDetailMaterials[i]);
|
||||
}
|
||||
unboost();
|
||||
}
|
||||
|
||||
BOOL LLTerrainMaterials::generateMaterials()
|
||||
|
|
@ -118,6 +130,31 @@ BOOL LLTerrainMaterials::generateMaterials()
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
void LLTerrainMaterials::boost()
|
||||
{
|
||||
for (S32 i = 0; i < ASSET_COUNT; ++i)
|
||||
{
|
||||
LLPointer<LLViewerFetchedTexture>& tex = mDetailTextures[i];
|
||||
llassert(tex.notNull());
|
||||
boost_minimap_texture(tex, TERRAIN_DECODE_PRIORITY);
|
||||
|
||||
LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[i];
|
||||
boost_minimap_material(mat, TERRAIN_DECODE_PRIORITY);
|
||||
}
|
||||
}
|
||||
|
||||
void LLTerrainMaterials::unboost()
|
||||
{
|
||||
for (S32 i = 0; i < ASSET_COUNT; ++i)
|
||||
{
|
||||
LLPointer<LLViewerFetchedTexture>& tex = mDetailTextures[i];
|
||||
unboost_minimap_texture(tex);
|
||||
|
||||
LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[i];
|
||||
unboost_minimap_material(mat);
|
||||
}
|
||||
}
|
||||
|
||||
LLUUID LLTerrainMaterials::getDetailAssetID(S32 asset)
|
||||
{
|
||||
llassert(mDetailTextures[asset] && mDetailMaterials[asset]);
|
||||
|
|
@ -135,7 +172,6 @@ LLPointer<LLViewerFetchedTexture> fetch_terrain_texture(const LLUUID& id)
|
|||
}
|
||||
|
||||
LLPointer<LLViewerFetchedTexture> tex = LLViewerTextureManager::getFetchedTexture(id);
|
||||
tex->setNoDelete();
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
|
@ -240,8 +276,7 @@ bool LLTerrainMaterials::textureReady(LLPointer<LLViewerFetchedTexture>& tex, bo
|
|||
{
|
||||
if (boost)
|
||||
{
|
||||
tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
|
||||
tex->addTextureStats(BASE_SIZE*BASE_SIZE);
|
||||
boost_minimap_texture(tex, BASE_SIZE*BASE_SIZE);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -251,6 +286,8 @@ bool LLTerrainMaterials::textureReady(LLPointer<LLViewerFetchedTexture>& tex, bo
|
|||
{
|
||||
if (boost)
|
||||
{
|
||||
boost_minimap_texture(tex, BASE_SIZE*BASE_SIZE);
|
||||
|
||||
S32 width = tex->getFullWidth();
|
||||
S32 height = tex->getFullHeight();
|
||||
S32 min_dim = llmin(width, height);
|
||||
|
|
@ -260,9 +297,7 @@ bool LLTerrainMaterials::textureReady(LLPointer<LLViewerFetchedTexture>& tex, bo
|
|||
ddiscard++;
|
||||
min_dim /= 2;
|
||||
}
|
||||
tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
|
||||
tex->setMinDiscardLevel(ddiscard);
|
||||
tex->addTextureStats(BASE_SIZE*BASE_SIZE); // priority
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -483,6 +518,108 @@ BOOL LLVLComposition::generateComposition()
|
|||
return LLTerrainMaterials::generateMaterials();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void prepare_fallback_image(LLImageRaw* raw_image)
|
||||
{
|
||||
raw_image->resize(BASE_SIZE, BASE_SIZE, 4);
|
||||
raw_image->fill(LLColor4U::white);
|
||||
}
|
||||
|
||||
// Check if the raw image is loaded for this texture at a discard
|
||||
// level the minimap can use, and if not then try to get it loaded.
|
||||
bool prepare_raw_image(LLPointer<LLImageRaw>& raw_image, bool emissive, LLViewerFetchedTexture* tex, bool& delete_raw_post)
|
||||
{
|
||||
if (!tex)
|
||||
{
|
||||
if (!emissive)
|
||||
{
|
||||
prepare_fallback_image(raw_image);
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(!raw_image);
|
||||
raw_image = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (raw_image)
|
||||
{
|
||||
// Callback already initiated
|
||||
if (raw_image->getDataSize() > 0)
|
||||
{
|
||||
// Callback finished
|
||||
delete_raw_post = true;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
raw_image = new LLImageRaw();
|
||||
|
||||
S32 ddiscard = 0;
|
||||
{
|
||||
S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight());
|
||||
while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
|
||||
{
|
||||
ddiscard++;
|
||||
min_dim /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
struct PendingImage
|
||||
{
|
||||
LLImageRaw* mRawImage;
|
||||
S32 mDesiredDiscard;
|
||||
LLUUID mTextureId;
|
||||
PendingImage(LLImageRaw* raw_image, S32 ddiscard, const LLUUID& texture_id)
|
||||
: mRawImage(raw_image)
|
||||
, mDesiredDiscard(ddiscard)
|
||||
, mTextureId(texture_id)
|
||||
{
|
||||
mRawImage->ref();
|
||||
}
|
||||
~PendingImage()
|
||||
{
|
||||
mRawImage->unref();
|
||||
}
|
||||
};
|
||||
PendingImage* pending_image = new PendingImage(raw_image, ddiscard, tex->getID());
|
||||
|
||||
loaded_callback_func cb = [](BOOL success, LLViewerFetchedTexture * src_vi, LLImageRaw * src, LLImageRaw * src_aux, S32 discard_level, BOOL is_final, void* userdata) {
|
||||
PendingImage* pending = (PendingImage*)userdata;
|
||||
// Owning LLVLComposition still exists
|
||||
|
||||
// Assume mRawImage only used by single LLVLComposition for now
|
||||
const bool in_use_by_composition = pending->mRawImage->getNumRefs() > 1;
|
||||
llassert(pending->mRawImage->getNumRefs());
|
||||
llassert(pending->mRawImage->getNumRefs() <= 2);
|
||||
const bool needs_data = !pending->mRawImage->getDataSize();
|
||||
if (in_use_by_composition && needs_data)
|
||||
{
|
||||
if (success && pending->mDesiredDiscard == discard_level)
|
||||
{
|
||||
pending->mRawImage->resize(BASE_SIZE, BASE_SIZE, src->getComponents());
|
||||
pending->mRawImage->copyScaled(src);
|
||||
}
|
||||
else if (is_final)
|
||||
{
|
||||
prepare_fallback_image(pending->mRawImage);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_final) { delete pending; }
|
||||
};
|
||||
tex->setLoadedCallback(cb, ddiscard, true, false, pending_image, nullptr);
|
||||
tex->forceToSaveRawImage(ddiscard);
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
|
||||
const F32 width, const F32 height)
|
||||
{
|
||||
|
|
@ -550,96 +687,28 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
|
|||
}
|
||||
|
||||
if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; }
|
||||
|
||||
bool delete_raw_post = false;
|
||||
bool delete_raw_post_emissive = false;
|
||||
if (!prepare_raw_image(mRawImagesBaseColor[i], false, tex, delete_raw_post)) { return FALSE; }
|
||||
if (tex_emissive && !prepare_raw_image(mRawImagesEmissive[i], true, tex_emissive, delete_raw_post_emissive)) { return FALSE; }
|
||||
// tex_emissive can be null, and then will be ignored
|
||||
|
||||
S32 ddiscard = 0;
|
||||
{
|
||||
S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight());
|
||||
while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
|
||||
{
|
||||
ddiscard++;
|
||||
min_dim /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
S32 ddiscard_emissive = 0;
|
||||
if (tex_emissive)
|
||||
{
|
||||
S32 min_dim_emissive = llmin(tex_emissive->getFullWidth(), tex_emissive->getFullHeight());
|
||||
while (min_dim_emissive > BASE_SIZE && ddiscard_emissive < MAX_DISCARD_LEVEL)
|
||||
{
|
||||
ddiscard_emissive++;
|
||||
min_dim_emissive /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
// *NOTE: It is probably safe to call destroyRawImage no matter
|
||||
// what, as LLViewerFetchedTexture::mRawImage is managed by
|
||||
// LLPointer and not modified with the rare exception of
|
||||
// icons (see BOOST_ICON). Nevertheless, gate this fix for now, as
|
||||
// it may have unintended consequences on texture loading.
|
||||
// We may want to also set the boost level in setDetailAssetID, but
|
||||
// that is not guaranteed to work if a texture is loaded on an object
|
||||
// before being loaded as terrain, so we will need this fix
|
||||
// regardless.
|
||||
static LLCachedControl<bool> sRenderTerrainPBREnabled(gSavedSettings, "RenderTerrainPBREnabled", false);
|
||||
BOOL delete_raw = (tex->reloadRawImage(ddiscard) != NULL || sRenderTerrainPBREnabled);
|
||||
BOOL delete_raw_emissive = (tex_emissive &&
|
||||
(tex_emissive->reloadRawImage(ddiscard_emissive) != NULL || sRenderTerrainPBREnabled));
|
||||
|
||||
if(tex->getRawImageLevel() != ddiscard)
|
||||
{
|
||||
// Raw image is not ready, will enter here again later.
|
||||
if (tex->getFetchPriority() <= 0.0f && !tex->hasSavedRawImage())
|
||||
{
|
||||
tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
|
||||
tex->forceToRefetchTexture(ddiscard);
|
||||
}
|
||||
|
||||
if(delete_raw)
|
||||
{
|
||||
tex->destroyRawImage() ;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
if (tex_emissive)
|
||||
{
|
||||
if(tex_emissive->getRawImageLevel() != ddiscard_emissive)
|
||||
{
|
||||
// Raw image is not ready, will enter here again later.
|
||||
if (tex_emissive->getFetchPriority() <= 0.0f && !tex_emissive->hasSavedRawImage())
|
||||
{
|
||||
tex_emissive->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
|
||||
tex_emissive->forceToRefetchTexture(ddiscard_emissive);
|
||||
}
|
||||
|
||||
if(delete_raw_emissive)
|
||||
{
|
||||
tex_emissive->destroyRawImage() ;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
mRawImages[i] = tex->getRawImage() ;
|
||||
if(delete_raw)
|
||||
{
|
||||
tex->destroyRawImage() ;
|
||||
}
|
||||
// In the simplest case, the minimap image is just the base color.
|
||||
// This will be replaced if we need to do any tinting/compositing.
|
||||
mRawImages[i] = mRawImagesBaseColor[i];
|
||||
|
||||
// *TODO: This isn't quite right for PBR:
|
||||
// 1) It does not convert the color images from SRGB to linear
|
||||
// before mixing (which will always require copying the image).
|
||||
// 2) It mixes emissive and base color before mixing terrain
|
||||
// materials, but it should be the other way around
|
||||
// 3) The composite function used to put emissive into base color
|
||||
// is not an alpha blend.
|
||||
// Long-term, we should consider a method that is more
|
||||
// maintainable. Shaders, perhaps? Bake shaders to textures?
|
||||
LLPointer<LLImageRaw> raw_emissive;
|
||||
if (tex_emissive)
|
||||
{
|
||||
raw_emissive = tex_emissive->getRawImage();
|
||||
raw_emissive = mRawImagesEmissive[i];
|
||||
if (has_emissive_factor ||
|
||||
tex_emissive->getWidth(tex_emissive->getRawImageLevel()) != BASE_SIZE ||
|
||||
tex_emissive->getHeight(tex_emissive->getRawImageLevel()) != BASE_SIZE ||
|
||||
|
|
@ -647,7 +716,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
|
|||
{
|
||||
LLPointer<LLImageRaw> newraw_emissive = new LLImageRaw(BASE_SIZE, BASE_SIZE, 4);
|
||||
// Copy RGB, leave alpha alone (set to opaque by default)
|
||||
newraw_emissive->copy(mRawImages[i]);
|
||||
newraw_emissive->copy(mRawImagesEmissive[i]);
|
||||
if (has_emissive_factor)
|
||||
{
|
||||
newraw_emissive->tint(emissive_factor);
|
||||
|
|
@ -680,7 +749,7 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
|
|||
MAX_WATER_COLOR.mV[VZ],
|
||||
255);
|
||||
}
|
||||
newraw->composite(mRawImages[i]);
|
||||
newraw->composite(mRawImagesBaseColor[i]);
|
||||
if (has_base_color_factor)
|
||||
{
|
||||
newraw->tint(base_color_factor);
|
||||
|
|
@ -688,16 +757,24 @@ BOOL LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
|
|||
// Apply emissive texture
|
||||
if (raw_emissive)
|
||||
{
|
||||
newraw->composite(raw_emissive);
|
||||
newraw->addEmissive(raw_emissive);
|
||||
}
|
||||
|
||||
mRawImages[i] = newraw; // deletes old
|
||||
}
|
||||
|
||||
if (delete_raw_emissive)
|
||||
if (delete_raw_post)
|
||||
{
|
||||
tex->destroyRawImage();
|
||||
}
|
||||
if (delete_raw_post_emissive)
|
||||
{
|
||||
tex_emissive->destroyRawImage();
|
||||
}
|
||||
|
||||
// Remove intermediary image references
|
||||
mRawImagesBaseColor[i] = nullptr;
|
||||
mRawImagesEmissive[i] = nullptr;
|
||||
}
|
||||
st_data[i] = mRawImages[i]->getData();
|
||||
st_data_size[i] = mRawImages[i]->getDataSize();
|
||||
|
|
@ -871,6 +948,8 @@ void LLVLComposition::setDetailAssetID(S32 asset, const LLUUID& id)
|
|||
}
|
||||
LLTerrainMaterials::setDetailAssetID(asset, id);
|
||||
mRawImages[asset] = NULL;
|
||||
mRawImagesBaseColor[asset] = NULL;
|
||||
mRawImagesEmissive[asset] = NULL;
|
||||
}
|
||||
|
||||
void LLVLComposition::setStartHeight(S32 corner, const F32 start_height)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,8 @@ public:
|
|||
|
||||
BOOL generateMaterials();
|
||||
|
||||
void boost();
|
||||
|
||||
virtual LLUUID getDetailAssetID(S32 asset);
|
||||
virtual void setDetailAssetID(S32 asset, const LLUUID& id);
|
||||
Type getMaterialType();
|
||||
|
|
@ -67,6 +69,7 @@ public:
|
|||
bool materialsReady(bool boost, bool strict);
|
||||
|
||||
protected:
|
||||
void unboost();
|
||||
static bool textureReady(LLPointer<LLViewerFetchedTexture>& tex, bool boost);
|
||||
// strict = true -> all materials must be sufficiently loaded
|
||||
// strict = false -> at least one material must be loaded
|
||||
|
|
@ -127,8 +130,13 @@ protected:
|
|||
BOOL mParamsReady = FALSE;
|
||||
LLSurface *mSurfacep;
|
||||
|
||||
// Final minimap raw images
|
||||
LLPointer<LLImageRaw> mRawImages[LLTerrainMaterials::ASSET_COUNT];
|
||||
|
||||
// Only non-null during minimap tile generation
|
||||
LLPointer<LLImageRaw> mRawImagesBaseColor[LLTerrainMaterials::ASSET_COUNT];
|
||||
LLPointer<LLImageRaw> mRawImagesEmissive[LLTerrainMaterials::ASSET_COUNT];
|
||||
|
||||
F32 mStartHeight[CORNER_COUNT];
|
||||
F32 mHeightRange[CORNER_COUNT];
|
||||
|
||||
|
|
|
|||
|
|
@ -1301,6 +1301,13 @@ void LLVOCache::removeEntry(HeaderEntryInfo* entry)
|
|||
getObjectCacheFilename(entry->mHandle, filename);
|
||||
LL_INFOS() << "Removing entry for region with filename" << filename << LL_ENDL;
|
||||
|
||||
// make sure corresponding LLViewerRegion also clears its in-memory cache
|
||||
LLViewerRegion* regionp = LLWorld::instance().getRegionFromHandle(entry->mHandle);
|
||||
if (regionp)
|
||||
{
|
||||
regionp->clearVOCacheFromMemory();
|
||||
}
|
||||
|
||||
header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry);
|
||||
if(iter != mHeaderEntryQueue.end())
|
||||
{
|
||||
|
|
@ -1369,10 +1376,14 @@ void LLVOCache::removeFromCache(HeaderEntryInfo* entry)
|
|||
|
||||
std::string filename;
|
||||
getObjectCacheFilename(entry->mHandle, filename);
|
||||
LL_WARNS("GLTF", "VOCache") << "Removing object cache for handle " << entry->mHandle << "Filename: " << filename << LL_ENDL;
|
||||
LLAPRFile::remove(filename, mLocalAPRFilePoolp);
|
||||
// Note: `removeFromCache` should take responsibility for cleaning up all cache artefacts specfic to the handle/entry.
|
||||
|
||||
// Note: `removeFromCache` should take responsibility for cleaning up all cache artefacts specfic to the handle/entry.
|
||||
// as such this now includes the generic extras
|
||||
removeGenericExtrasForHandle(entry->mHandle);
|
||||
filename = getObjectCacheExtrasFilename(entry->mHandle);
|
||||
LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << entry->mHandle << "Filename: " << filename << LL_ENDL;
|
||||
LLFile::remove(filename);
|
||||
|
||||
entry->mTime = INVALID_TIME ;
|
||||
updateEntry(entry) ; //update the head file.
|
||||
|
|
@ -1387,7 +1398,7 @@ void LLVOCache::readCacheHeader()
|
|||
}
|
||||
|
||||
//clear stale info.
|
||||
clearCacheInMemory();
|
||||
clearCacheInMemory();
|
||||
|
||||
bool success = true ;
|
||||
if (LLAPRFile::isExist(mHeaderFileName, mLocalAPRFilePoolp))
|
||||
|
|
@ -1636,7 +1647,7 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac
|
|||
}
|
||||
// For future versions we may call a legacy handler here, but realistically we'll just consider this cache out of date.
|
||||
// The important thing is to make sure it gets removed.
|
||||
if(versionNumber != LLGLTFOverrideCacheEntry::VERSION && versionNumber != 0)
|
||||
if(versionNumber != LLGLTFOverrideCacheEntry::VERSION)
|
||||
{
|
||||
LL_WARNS() << "Unexpected version number " << versionNumber << " for extras cache for handle " << handle << LL_ENDL;
|
||||
in.close();
|
||||
|
|
@ -1645,7 +1656,7 @@ void LLVOCache::readGenericExtrasFromCache(U64 handle, const LLUUID& id, LLVOCac
|
|||
}
|
||||
|
||||
LL_DEBUGS("VOCache") << "Reading extras cache for handle " << handle << ", version " << versionNumber << LL_ENDL;
|
||||
|
||||
std::getline(in, line);
|
||||
if(!LLUUID::validate(line))
|
||||
{
|
||||
LL_WARNS() << "Failed reading extras cache for handle" << handle << ". invalid uuid line: '" << line << "'" << LL_ENDL;
|
||||
|
|
@ -1878,8 +1889,19 @@ void LLVOCache::removeGenericExtrasForHandle(U64 handle)
|
|||
LL_WARNS() << "Not removing cache for handle " << handle << ": Cache is currently in read-only mode." << LL_ENDL;
|
||||
return ;
|
||||
}
|
||||
LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << handle << "Filename: " << getObjectCacheExtrasFilename(handle) << LL_ENDL;
|
||||
LLFile::remove(getObjectCacheExtrasFilename(handle));
|
||||
|
||||
// NOTE: when removing the extras, we must also remove the objects so the simulator will send us a full upddate with the valid overrides
|
||||
auto* entry = mHandleEntryMap[handle];
|
||||
if (entry)
|
||||
{
|
||||
removeEntry(entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
//shouldn't happen, but if it does, we should remove the extras file since it's orphaned
|
||||
LL_WARNS("GLTF", "VOCache") << "Removing generic extras for handle " << entry->mHandle << "Filename: " << getObjectCacheExtrasFilename(handle) << LL_ENDL;
|
||||
LLFile::remove(getObjectCacheExtrasFilename(entry->mHandle));
|
||||
}
|
||||
}
|
||||
|
||||
void LLVOCache::writeGenericExtrasToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_gltf_overrides_map_t& cache_extras_entry_map, BOOL dirty_cache, bool removal_enabled)
|
||||
|
|
|
|||
Loading…
Reference in New Issue