From 76bf3390eb119a7dfd879bbbc31b4d5e687aac8f Mon Sep 17 00:00:00 2001
From: Cosmic Linden <cosmic@lindenlab.com>
Date: Fri, 13 Oct 2023 09:56:55 -0700
Subject: DRTVWR-592: (WIP) Detect when terrain materials are loaded, use as
 fallback when terrain textures do not load

---
 indra/newview/lldrawpoolterrain.cpp   |  32 +++++++-
 indra/newview/llfetchedgltfmaterial.h |   1 +
 indra/newview/llfloaterregioninfo.cpp |   6 +-
 indra/newview/llviewerregion.cpp      |  16 ++--
 indra/newview/llvlcomposition.cpp     | 135 +++++++++++++++++++++++-----------
 indra/newview/llvlcomposition.h       |  21 ++++--
 6 files changed, 150 insertions(+), 61 deletions(-)

(limited to 'indra')

diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 77189dceae..687ff5f462 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -121,8 +121,36 @@ void LLDrawPoolTerrain::boostTerrainDetailTextures()
 	LLVLComposition *compp = regionp->getComposition();
 	for (S32 i = 0; i < 4; i++)
 	{
-		compp->mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN);
-        compp->mDetailTextures[i]->addTextureStats(1024.f * 1024.f);
+        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>& mat = compp->mDetailMaterials[i];
+        llassert(mat.notNull());
+        if (mat->mBaseColorTexture)
+        {
+            mat->mBaseColorTexture->setBoostLevel(level);
+            mat->mBaseColorTexture->addTextureStats(stats);
+        }
+        if (mat->mNormalTexture)
+        {
+            mat->mNormalTexture->setBoostLevel(level);
+            mat->mNormalTexture->addTextureStats(stats);
+        }
+        if (mat->mMetallicRoughnessTexture)
+        {
+            mat->mMetallicRoughnessTexture->setBoostLevel(level);
+            mat->mMetallicRoughnessTexture->addTextureStats(stats);
+        }
+        if (mat->mEmissiveTexture)
+        {
+            mat->mEmissiveTexture->setBoostLevel(level);
+            mat->mEmissiveTexture->addTextureStats(stats);
+        }
 	}
 }
 
diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h
index 1668657281..ce4d33a213 100644
--- a/indra/newview/llfetchedgltfmaterial.h
+++ b/indra/newview/llfetchedgltfmaterial.h
@@ -49,6 +49,7 @@ public:
     void bind(LLViewerTexture* media_tex = nullptr);
 
     bool isFetching() const { return mFetching; }
+    bool isLoaded() const { return !mFetching; }
 
     // Textures used for fetching/rendering
     LLPointer<LLViewerFetchedTexture> mBaseColorTexture;
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index ff7012efb5..b5698c1d65 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -1541,8 +1541,8 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
 			if(asset_ctrl)
 			{
 				LL_DEBUGS() << "Detail Texture " << i << ": "
-						 << compp->getDetailTextureID(i) << LL_ENDL;
-				LLUUID tmp_id(compp->getDetailTextureID(i));
+						 << compp->getDetailAssetID(i) << LL_ENDL;
+				LLUUID tmp_id(compp->getDetailAssetID(i));
 				asset_ctrl->setImageAssetID(tmp_id);
 			}
 		}
@@ -1552,7 +1552,7 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region)
 			asset_ctrl = getChild<LLTextureCtrl>(buffer);
 			if(asset_ctrl)
 			{
-				LLUUID tmp_id(compp->getDetailTextureID(i));
+				LLUUID tmp_id(compp->getDetailAssetID(i));
 				asset_ctrl->setImageAssetID(tmp_id);
 			}
 		}
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 6b92b16ef4..9d3e63333e 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -2962,20 +2962,20 @@ void LLViewerRegion::unpackRegionHandshake()
 
 		// Get the 4 textures for land
 		msg->getUUID("RegionInfo", "TerrainDetail0", tmp_id);
-		changed |= (tmp_id != compp->getDetailTextureID(0));		
-		compp->setDetailTextureID(0, tmp_id);
+		changed |= (tmp_id != compp->getDetailAssetID(0));		
+		compp->setDetailAssetID(0, tmp_id);
 
 		msg->getUUID("RegionInfo", "TerrainDetail1", tmp_id);
-		changed |= (tmp_id != compp->getDetailTextureID(1));		
-		compp->setDetailTextureID(1, tmp_id);
+		changed |= (tmp_id != compp->getDetailAssetID(1));		
+		compp->setDetailAssetID(1, tmp_id);
 
 		msg->getUUID("RegionInfo", "TerrainDetail2", tmp_id);
-		changed |= (tmp_id != compp->getDetailTextureID(2));		
-		compp->setDetailTextureID(2, tmp_id);
+		changed |= (tmp_id != compp->getDetailAssetID(2));		
+		compp->setDetailAssetID(2, tmp_id);
 
 		msg->getUUID("RegionInfo", "TerrainDetail3", tmp_id);
-		changed |= (tmp_id != compp->getDetailTextureID(3));		
-		compp->setDetailTextureID(3, tmp_id);
+		changed |= (tmp_id != compp->getDetailAssetID(3));		
+		compp->setDetailAssetID(3, tmp_id);
 
 		// Get the start altitude and range values for land textures
 		F32 tmp_f32;
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index 001fab7755..8480c9ce3d 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -65,10 +65,10 @@ LLVLComposition::LLVLComposition(LLSurface *surfacep, const U32 width, const F32
 	mSurfacep = surfacep;
 
 	// Load Terrain Textures - Original ones
-	setDetailTextureID(0, TERRAIN_DIRT_DETAIL);
-	setDetailTextureID(1, TERRAIN_GRASS_DETAIL);
-	setDetailTextureID(2, TERRAIN_MOUNTAIN_DETAIL);
-	setDetailTextureID(3, TERRAIN_ROCK_DETAIL);
+	setDetailAssetID(0, TERRAIN_DIRT_DETAIL);
+	setDetailAssetID(1, TERRAIN_GRASS_DETAIL);
+	setDetailAssetID(2, TERRAIN_MOUNTAIN_DETAIL);
+	setDetailAssetID(3, TERRAIN_ROCK_DETAIL);
 
 	// Initialize the texture matrix to defaults.
 	for (S32 i = 0; i < CORNER_COUNT; ++i)
@@ -93,7 +93,7 @@ void LLVLComposition::setSurface(LLSurface *surfacep)
 }
 
 
-void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id)
+void LLVLComposition::setDetailAssetID(S32 corner, const LLUUID& id)
 {
 	if(id.isNull())
 	{
@@ -104,6 +104,25 @@ void LLVLComposition::setDetailTextureID(S32 corner, const LLUUID& id)
 	mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id);
 	mDetailTextures[corner]->setNoDelete() ;
 	mRawImages[corner] = NULL;
+    // *TODO: Decide if we have textures or materials. Whichever loads first determines the terrain type.
+    // *TODO: As the material textures are loaded, prevent deletion
+    mDetailMaterials[corner] = LLGLTFMaterialList::getMaterial(id);
+}
+
+void LLVLComposition::setDetailMaterialID(S32 corner, const LLUUID& id)
+{
+	if(id.isNull())
+	{
+		mDetailMaterials[corner] = nullptr;
+	}
+    else
+    {
+        // This is terrain material, but we are not setting it as BOOST_TERRAIN
+        // since we will be manipulating it later as needed.
+        mDetailTextures[corner] = LLViewerTextureManager::getFetchedTexture(id);
+        mDetailTextures[corner]->setNoDelete() ;
+        mRawImages[corner] = NULL;
+    }
 }
 
 BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
@@ -149,10 +168,6 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
 	const F32 noise_magnitude = 2.f;		//  Degree to which noise modulates composition layer (versus
 											//  simple height)
 
-	// Heights map into textures as 0-1 = first, 1-2 = second, etc.
-	// So we need to compress heights into this range.
-	const S32 NUM_TEXTURES = 4;
-
 	const F32 xyScaleInv = (1.f / xyScale);
 	const F32 zScaleInv = (1.f / zScale);
 
@@ -199,7 +214,7 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
 			twiddle += turbulence2(vec, 2)*slope_squared;	//  High frequency component
 			twiddle *= noise_magnitude;
 
-			F32 scaled_noisy_height = (height + twiddle - start_height) * F32(NUM_TEXTURES) / height_range;
+			F32 scaled_noisy_height = (height + twiddle - start_height) * F32(ASSET_COUNT) / height_range;
 
 			scaled_noisy_height = llmax(0.f, scaled_noisy_height);
 			scaled_noisy_height = llmin(3.f, scaled_noisy_height);
@@ -211,6 +226,37 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y,
 
 static const U32 BASE_SIZE = 128;
 
+// Boost the texture loading priority
+// Return true when ready to use (i.e. texture is sufficiently loaded)
+bool boost_texture_until_ready(LLPointer<LLViewerFetchedTexture>& tex)
+{
+    if (tex->getDiscardLevel() < 0)
+    {
+        tex->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
+        tex->addTextureStats(BASE_SIZE*BASE_SIZE);
+        return false;
+    }
+    if ((tex->getDiscardLevel() != 0 &&
+         (tex->getWidth() < BASE_SIZE ||
+          tex->getHeight() < BASE_SIZE)))
+    {
+        S32 width = tex->getFullWidth();
+        S32 height = tex->getFullHeight();
+        S32 min_dim = llmin(width, height);
+        S32 ddiscard = 0;
+        while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
+        {
+            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;
+    }
+    return true;
+}
+
 BOOL LLVLComposition::generateComposition()
 {
 
@@ -220,35 +266,44 @@ BOOL LLVLComposition::generateComposition()
 		return FALSE;
 	}
 
-	for (S32 i = 0; i < 4; i++)
+    bool textures_ready = true;
+	for (S32 i = 0; i < ASSET_COUNT; i++)
 	{
-		if (mDetailTextures[i]->getDiscardLevel() < 0)
-		{
-			mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
-			mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE);
-			return FALSE;
-		}
-		if ((mDetailTextures[i]->getDiscardLevel() != 0 &&
-			 (mDetailTextures[i]->getWidth() < BASE_SIZE ||
-			  mDetailTextures[i]->getHeight() < BASE_SIZE)))
-		{
-			S32 width = mDetailTextures[i]->getFullWidth();
-			S32 height = mDetailTextures[i]->getFullHeight();
-			S32 min_dim = llmin(width, height);
-			S32 ddiscard = 0;
-			while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
-			{
-				ddiscard++;
-				min_dim /= 2;
-			}
-			mDetailTextures[i]->setBoostLevel(LLGLTexture::BOOST_TERRAIN); // in case we are at low detail
-			mDetailTextures[i]->setMinDiscardLevel(ddiscard);
-			mDetailTextures[i]->addTextureStats(BASE_SIZE*BASE_SIZE); // priority
-			return FALSE;
-		}
+        if (!boost_texture_until_ready(mDetailTextures[i]))
+        {
+            textures_ready = false;
+            break;
+        }
 	}
+
+    if (textures_ready)
+    {
+        return TRUE;
+    }
 	
-	return TRUE;
+    bool materials_ready = true;
+	for (S32 i = 0; i < ASSET_COUNT; i++)
+	{
+        const LLPointer<LLFetchedGLTFMaterial>& mat = mDetailMaterials[i];
+        if (!mat.isLoaded() ||
+            (mat->mBaseColorTexture && !boost_texture_until_ready(mat->mBaseColorTexture)) ||
+            (mat->mNormalTexture && !boost_texture_until_ready(mat->mNormalTexture)) ||
+            (mat->mMetallicRoughnessTexture && !boost_texture_until_ready(mat->mMetallicRoughnessTexture)) ||
+            (mat->mEmissiveTexture && !boost_texture_until_ready(mat->mEmissiveTexture)))
+        {
+            materials_ready = false;
+            break;
+        }
+    }
+
+    if (materials_ready)
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
 }
 
 BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
@@ -469,16 +524,12 @@ BOOL LLVLComposition::generateTexture(const F32 x, const F32 y,
 	return TRUE;
 }
 
-LLUUID LLVLComposition::getDetailTextureID(S32 corner)
+LLUUID LLVLComposition::getDetailAssetID(S32 corner)
 {
+    llassert(mDetailTextures[corner] && mDetailMaterials[corner] && mDetailTextures[corner]->getID() == mDetailMaterials[corner].getID());
 	return mDetailTextures[corner]->getID();
 }
 
-LLViewerFetchedTexture* LLVLComposition::getDetailTexture(S32 corner)
-{
-	return mDetailTextures[corner];
-}
-
 F32 LLVLComposition::getStartHeight(S32 corner)
 {
 	return mStartHeight[corner];
diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h
index 2dd04ac5a5..3e465efc95 100644
--- a/indra/newview/llvlcomposition.h
+++ b/indra/newview/llvlcomposition.h
@@ -28,10 +28,13 @@
 #define LL_LLVLCOMPOSITION_H
 
 #include "llviewerlayer.h"
-#include "llviewertexture.h"
+#include "llpointer.h"
 
 class LLSurface;
 
+class LLViewerFetchedTexture;
+class LLFetchedGLTFMaterial;
+
 class LLVLComposition : public LLViewerLayer
 {
 public:
@@ -46,6 +49,10 @@ public:
 	// Generate texture from composition values.
 	BOOL generateTexture(const F32 x, const F32 y, const F32 width, const F32 height);		
 
+	// Heights map into textures (or materials) as 0-1 = first, 1-2 = second, etc.
+	// So we need to compress heights into this range.
+    static const S32 ASSET_COUNT = 4;
+
 	// Use these as indeces ito the get/setters below that use 'corner'
 	enum ECorner
 	{
@@ -55,12 +62,12 @@ public:
 		NORTHEAST = 3,
 		CORNER_COUNT = 4
 	};
-	LLUUID getDetailTextureID(S32 corner);
-	LLViewerFetchedTexture* getDetailTexture(S32 corner);
+
+	LLUUID getDetailAssetID(S32 asset);
 	F32 getStartHeight(S32 corner);
 	F32 getHeightRange(S32 corner);
 
-	void setDetailTextureID(S32 corner, const LLUUID& id);
+	void setDetailAssetID(S32 asset, const LLUUID& id);
 	void setStartHeight(S32 corner, F32 start_height);
 	void setHeightRange(S32 corner, F32 range);
 
@@ -73,8 +80,10 @@ protected:
 	LLSurface *mSurfacep;
 	BOOL mTexturesLoaded;
 
-	LLPointer<LLViewerFetchedTexture> mDetailTextures[CORNER_COUNT];
-	LLPointer<LLImageRaw> mRawImages[CORNER_COUNT];
+    // TODO: Set flag to indicate whether the textures or materials loaded first
+	LLPointer<LLViewerFetchedTexture> mDetailTextures[ASSET_COUNT];
+	LLPointer<LLImageRaw> mRawImages[ASSET_COUNT];
+	LLPointer<LLFetchedGLTFMaterial> mDetailMaterials[ASSET_COUNT];
 
 	F32 mStartHeight[CORNER_COUNT];
 	F32 mHeightRange[CORNER_COUNT];
-- 
cgit v1.2.3