diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7d6bcd2bc4c..60ad7e8fe5f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -42,7 +42,7 @@ jobs: needs: setup strategy: matrix: - runner: [windows-large, macos-12-large] + runner: [windows-large, macos-15-xlarge] configuration: ${{ fromJSON(needs.setup.outputs.configurations) }} runs-on: ${{ matrix.runner }} outputs: @@ -64,7 +64,7 @@ jobs: # autobuild-package.xml. AUTOBUILD_VCS_INFO: "true" AUTOBUILD_VSVER: "170" - DEVELOPER_DIR: "/Applications/Xcode_14.0.1.app/Contents/Developer" + DEVELOPER_DIR: "/Applications/Xcode_16.1.app/Contents/Developer" # Ensure that Linden viewer builds engage Bugsplat. BUGSPLAT_DB: ${{ needs.setup.outputs.bugsplat_db }} build_coverity: false diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml index 013adc9ca8f..7866f943b5a 100644 --- a/.github/workflows/cla.yaml +++ b/.github/workflows/cla.yaml @@ -23,4 +23,4 @@ jobs: path-to-signatures: signatures.json remote-organization-name: secondlife remote-repository-name: cla-signatures - allowlist: callum@mbp.localdomain + allowlist: callum@mbp.localdomain,rye@lindenlab.com diff --git a/.github/workflows/tag-release.yaml b/.github/workflows/tag-release.yaml index 65d1d43a833..24ee2de7949 100644 --- a/.github/workflows/tag-release.yaml +++ b/.github/workflows/tag-release.yaml @@ -37,7 +37,12 @@ jobs: - name: Update Tag uses: actions/github-script@v7.0.1 with: - github-token: ${{ secrets.GITHUB_TOKEN }} + # use a real access token instead of GITHUB_TOKEN default. + # required so that the results of this tag creation can trigger the build workflow + # https://stackoverflow.com/a/71372524 + # https://docs.github.com/en/actions/using-workflows/triggering-a-workflow#triggering-a-workflow-from-a-workflow + # this token will need to be renewed anually in January + github-token: ${{ secrets.LL_TAG_RELEASE_TOKEN }} script: | github.rest.git.createRef({ owner: context.repo.owner, diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 422927704a7..3170dbc180c 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -29,6 +29,11 @@ else() set( USE_AUTOBUILD_3P ON ) endif() +if (NOT DEFINED CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 20) +endif() +set(CMAKE_CXX_STANDARD_REQUIRED ON) + include(Variables) include(BuildVersion) diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index 5f98f2c8c1f..47798844bce 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -300,7 +300,8 @@ EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::strin LLWearableType::EType LLAvatarAppearanceDictionary::getTEWearableType(ETextureIndex index ) const { - return getTexture(index)->mWearableType; + auto* tex = getTexture(index); + return tex ? tex->mWearableType : LLWearableType::WT_INVALID; } // static diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index a7e5292fedb..f30c147b91c 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -652,7 +652,7 @@ void LLWearable::setVisualParamWeight(S32 param_index, F32 value) } else { - LL_ERRS() << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL; + LL_WARNS() << "LLWearable::setVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL; } } @@ -665,7 +665,7 @@ F32 LLWearable::getVisualParamWeight(S32 param_index) const } else { - LL_WARNS() << "LLWerable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL; + LL_WARNS() << "LLWearable::getVisualParam passed invalid parameter index: " << param_index << " for wearable type: " << this->getName() << LL_ENDL; } return (F32)-1.0; } diff --git a/indra/llcommon/fsyspath.h b/indra/llcommon/fsyspath.h index 1b4aec09b47..e9c96edce39 100644 --- a/indra/llcommon/fsyspath.h +++ b/indra/llcommon/fsyspath.h @@ -68,7 +68,11 @@ class fsyspath: public std::filesystem::path } // shadow base-class string() method with UTF-8 aware method - std::string string() const { return super::u8string(); } + std::string string() const + { + auto u8 = super::u8string(); + return std::string(u8.begin(), u8.end()); + } // On Posix systems, where value_type is already char, this operator // std::string() method shadows the base class operator string_type() // method. But on Windows, where value_type is wchar_t, the base class diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 90c6ba309b3..d8340989948 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -1604,11 +1604,11 @@ namespace LLError std::string LLUserWarningMsg::sLocalizedOutOfMemoryWarning; LLUserWarningMsg::Handler LLUserWarningMsg::sHandler; - void LLUserWarningMsg::show(const std::string& message) + void LLUserWarningMsg::show(const std::string& message, S32 error_code) { if (sHandler) { - sHandler(std::string(), message); + sHandler(std::string(), message, error_code); } } @@ -1616,7 +1616,7 @@ namespace LLError { if (sHandler && !sLocalizedOutOfMemoryTitle.empty()) { - sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning); + sHandler(sLocalizedOutOfMemoryTitle, sLocalizedOutOfMemoryWarning, ERROR_BAD_ALLOC); } } @@ -1627,7 +1627,7 @@ namespace LLError "Second Life viewer couldn't access some of the files it needs and will be closed." "\n\nPlease reinstall viewer from https://secondlife.com/support/downloads/ and " "contact https://support.secondlife.com if issue persists after reinstall."; - sHandler("Missing Files", error_string); + sHandler("Missing Files", error_string, ERROR_MISSING_FILES); } void LLUserWarningMsg::setHandler(const LLUserWarningMsg::Handler &handler) diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 8a143ff30a5..41893a35e56 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -308,7 +308,16 @@ namespace LLError class LLUserWarningMsg { public: - typedef std::function Handler; + // error codes, tranlates to last_exec states like LAST_EXEC_OTHER_CRASH + typedef enum + { + ERROR_OTHER = 0, + ERROR_BAD_ALLOC = 1, + ERROR_MISSING_FILES = 2, + } eLastExecEvent; + + // tittle, message and error code to include in error marker file + typedef std::function Handler; static void setHandler(const Handler&); static void setOutOfMemoryStrings(const std::string& title, const std::string& message); @@ -316,7 +325,7 @@ namespace LLError static void showOutOfMemory(); static void showMissingFiles(); // Genering error - static void show(const std::string&); + static void show(const std::string&, S32 error_code = -1); private: // needs to be preallocated before viewer runs out of memory diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 1c4ac5a7bf7..0196a24b183 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -146,7 +146,7 @@ size_t LLQueuedThread::updateQueue(F32 max_time_ms) // schedule a call to threadedUpdate for every call to updateQueue if (!isQuitting()) { - mRequestQueue.post([=]() + mRequestQueue.post([=, this]() { LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qt - update"); mIdleThread = false; @@ -474,7 +474,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req) #else using namespace std::chrono_literals; auto retry_time = LL::WorkQueue::TimePoint::clock::now() + 16ms; - mRequestQueue.post([=] + mRequestQueue.post([=, this] { LL_PROFILE_ZONE_NAMED("processRequest - retry"); if (LL::WorkQueue::TimePoint::clock::now() < retry_time) diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 082d8b2f9f8..075abf95363 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -918,7 +918,7 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const } //sd[INV_FLAGS_LABEL] = (S32)mFlags; sd[INV_FLAGS_LABEL] = ll_sd_from_U32(mFlags); - sd[INV_SALE_INFO_LABEL] = mSaleInfo; + sd[INV_SALE_INFO_LABEL] = mSaleInfo.asLLSD(); sd[INV_NAME_LABEL] = mName; sd[INV_DESC_LABEL] = mDescription; sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate; diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index 98836b178e3..35bbc1dbb18 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -89,8 +89,14 @@ bool LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const LLSD LLSaleInfo::asLLSD() const { - LLSD sd = LLSD(); - sd["sale_type"] = lookup(mSaleType); + LLSD sd; + const char* type = lookup(mSaleType); + if (!type) + { + LL_WARNS_ONCE() << "Unknown sale type: " << mSaleType << LL_ENDL; + type = lookup(LLSaleInfo::FS_NOT); + } + sd["sale_type"] = type; sd["sale_price"] = mSalePrice; return sd; } diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp index 50b458de14e..ff28c305632 100644 --- a/indra/llinventory/llsettingssky.cpp +++ b/indra/llinventory/llsettingssky.cpp @@ -137,7 +137,8 @@ const std::string LLSettingsSky::SETTING_REFLECTION_PROBE_AMBIANCE("reflection_p const LLUUID LLSettingsSky::DEFAULT_ASSET_ID("651510b8-5f4d-8991-1592-e7eeab2a5a06"); -F32 LLSettingsSky::sAutoAdjustProbeAmbiance = 1.f; +const F32 LLSettingsSky::DEFAULT_AUTO_ADJUST_PROBE_AMBIANCE = 1.f; +F32 LLSettingsSky::sAutoAdjustProbeAmbiance = DEFAULT_AUTO_ADJUST_PROBE_AMBIANCE; static const LLUUID DEFAULT_SUN_ID("32bfbcea-24b1-fb9d-1ef9-48a28a63730f"); // dataserver static const LLUUID DEFAULT_MOON_ID("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver @@ -2032,43 +2033,43 @@ F32 LLSettingsSky::getGamma() const return mGamma; } -F32 LLSettingsSky::getHDRMin() const +F32 LLSettingsSky::getHDRMin(bool auto_adjust) const { - if (mCanAutoAdjust) + if (mCanAutoAdjust && !auto_adjust) return 0.f; return mHDRMin; } -F32 LLSettingsSky::getHDRMax() const +F32 LLSettingsSky::getHDRMax(bool auto_adjust) const { - if (mCanAutoAdjust) + if (mCanAutoAdjust && !auto_adjust) return 0.f; return mHDRMax; } -F32 LLSettingsSky::getHDROffset() const +F32 LLSettingsSky::getHDROffset(bool auto_adjust) const { - if (mCanAutoAdjust) + if (mCanAutoAdjust && !auto_adjust) return 1.0f; return mHDROffset; } -F32 LLSettingsSky::getTonemapMix() const +F32 LLSettingsSky::getTonemapMix(bool auto_adjust) const { - if (mCanAutoAdjust) + if (mCanAutoAdjust && !auto_adjust) + { + // legacy settings do not support tonemaping return 0.0f; + } return mTonemapMix; } void LLSettingsSky::setTonemapMix(F32 mix) { - if (mCanAutoAdjust) - return; - mTonemapMix = mix; } diff --git a/indra/llinventory/llsettingssky.h b/indra/llinventory/llsettingssky.h index 4c635fd9467..ff75aea5490 100644 --- a/indra/llinventory/llsettingssky.h +++ b/indra/llinventory/llsettingssky.h @@ -103,6 +103,7 @@ class LLSettingsSky: public LLSettingsBase static const LLUUID DEFAULT_ASSET_ID; + static const F32 DEFAULT_AUTO_ADJUST_PROBE_AMBIANCE; static F32 sAutoAdjustProbeAmbiance; typedef PTR_NAMESPACE::shared_ptr ptr_t; @@ -209,10 +210,10 @@ class LLSettingsSky: public LLSettingsBase F32 getGamma() const; - F32 getHDRMin() const; - F32 getHDRMax() const; - F32 getHDROffset() const; - F32 getTonemapMix() const; + F32 getHDRMin(bool auto_adjust = false) const; + F32 getHDRMax(bool auto_adjust = false) const; + F32 getHDROffset(bool auto_adjust = false) const; + F32 getTonemapMix(bool auto_adjust = false) const; void setTonemapMix(F32 mix); void setGamma(F32 val); diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h index 8ef560dadf4..4004852e065 100644 --- a/indra/llmath/llvector4a.h +++ b/indra/llmath/llvector4a.h @@ -33,6 +33,9 @@ class LLRotation; #include #include "llpreprocessor.h" #include "llmemory.h" +#include "glm/vec3.hpp" +#include "glm/vec4.hpp" +#include "glm/gtc/type_ptr.hpp" /////////////////////////////////// // FIRST TIME USERS PLEASE READ @@ -364,6 +367,16 @@ class alignas(16) LLVector4a inline operator LLQuad() const; + explicit inline operator glm::vec3() const + { + return glm::make_vec3(getF32ptr()); + }; + + explicit inline operator glm::vec4() const + { + return glm::make_vec4(getF32ptr()); + }; + private: LLQuad mQ{}; }; diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index d063b15c74f..a3bfa68060b 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -31,6 +31,11 @@ #include "llmath.h" #include "llsd.h" + +#include "glm/vec3.hpp" +#include "glm/vec4.hpp" +#include "glm/gtc/type_ptr.hpp" + class LLVector2; class LLVector4; class LLVector4a; @@ -66,6 +71,11 @@ class LLVector3 explicit LLVector3(const LLVector4a& vec); // Initializes LLVector4 to (vec[0]. vec[1], vec[2]) explicit LLVector3(const LLSD& sd); + // GLM interop + explicit LLVector3(const glm::vec3& vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) + explicit LLVector3(const glm::vec4& vec); // Initializes LLVector3 to (vec[0]. vec[1], vec[2]) + explicit inline operator glm::vec3() const; // Initializes glm::vec3 to (vec[0]. vec[1], vec[2]) + explicit inline operator glm::vec4() const; // Initializes glm::vec4 to (vec[0]. vec[1], vec[2], 1) LLSD getValue() const; @@ -92,6 +102,8 @@ class LLVector3 inline void set(const F32 *vec); // Sets LLVector3 to vec const LLVector3& set(const LLVector4 &vec); const LLVector3& set(const LLVector3d &vec);// Sets LLVector3 to vec + inline void set(const glm::vec4& vec); // Sets LLVector3 to vec + inline void set(const glm::vec3& vec); // Sets LLVector3 to vec inline void setVec(F32 x, F32 y, F32 z); // deprecated inline void setVec(const LLVector3 &vec); // deprecated @@ -190,6 +202,20 @@ inline LLVector3::LLVector3(const F32 *vec) mV[VZ] = vec[VZ]; } +inline LLVector3::LLVector3(const glm::vec3& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; +} + +inline LLVector3::LLVector3(const glm::vec4& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; +} + /* inline LLVector3::LLVector3(const LLVector3 ©) { @@ -259,6 +285,20 @@ inline void LLVector3::set(const F32 *vec) mV[2] = vec[2]; } +inline void LLVector3::set(const glm::vec4& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; +} + +inline void LLVector3::set(const glm::vec3& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; +} + // deprecated inline void LLVector3::setVec(F32 x, F32 y, F32 z) { @@ -471,6 +511,17 @@ inline LLVector3 operator-(const LLVector3 &a) return LLVector3( -a.mV[0], -a.mV[1], -a.mV[2] ); } +inline LLVector3::operator glm::vec3() const +{ + // Do not use glm::make_vec3 it can result in a buffer overrun on some platforms due to glm::vec3 being a simd vector internally + return glm::vec3(mV[VX], mV[VY], mV[VZ]); +} + +inline LLVector3::operator glm::vec4() const +{ + return glm::vec4(mV[VX], mV[VY], mV[VZ], 1.f); +} + inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b) { F32 x = a.mV[0] - b.mV[0]; diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index a5b6f506d70..a4c9668fdd1 100644 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h @@ -32,6 +32,10 @@ #include "v3math.h" #include "v2math.h" +#include "glm/vec3.hpp" +#include "glm/vec4.hpp" +#include "glm/gtc/type_ptr.hpp" + class LLMatrix3; class LLMatrix4; class LLQuaternion; @@ -73,6 +77,11 @@ class LLVector4 mV[3] = (F32)sd[3].asReal(); } + // GLM interop + explicit LLVector4(const glm::vec3& vec); // Initializes LLVector4 to (vec, 1) + explicit LLVector4(const glm::vec4& vec); // Initializes LLVector4 to vec + explicit operator glm::vec3() const; // Initializes glm::vec3 to (vec[0]. vec[1], vec[2]) + explicit operator glm::vec4() const; // Initializes glm::vec4 to (vec[0]. vec[1], vec[2], vec[3]) inline bool isFinite() const; // checks to see if all values of LLVector3 are finite @@ -85,6 +94,8 @@ class LLVector4 inline void set(const LLVector4 &vec); // Sets LLVector4 to vec inline void set(const LLVector3 &vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec inline void set(const F32 *vec); // Sets LLVector4 to vec + inline void set(const glm::vec4& vec); // Sets LLVector4 to vec + inline void set(const glm::vec3& vec, F32 w = 1.f); // Sets LLVector4 to LLVector3 vec with w defaulted to 1 inline void setVec(F32 x, F32 y, F32 z); // deprecated inline void setVec(F32 x, F32 y, F32 z, F32 w); // deprecated @@ -223,6 +234,21 @@ inline LLVector4::LLVector4(const LLSD &sd) setValue(sd); } +inline LLVector4::LLVector4(const glm::vec3& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; + mV[VW] = 1.f; +} + +inline LLVector4::LLVector4(const glm::vec4& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; + mV[VW] = vec.w; +} inline bool LLVector4::isFinite() const { @@ -297,6 +323,21 @@ inline void LLVector4::set(const F32 *vec) mV[VW] = vec[VW]; } +inline void LLVector4::set(const glm::vec4& vec) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; + mV[VW] = vec.w; +} + +inline void LLVector4::set(const glm::vec3& vec, F32 w) +{ + mV[VX] = vec.x; + mV[VY] = vec.y; + mV[VZ] = vec.z; + mV[VW] = w; +} // deprecated inline void LLVector4::setVec(F32 x, F32 y, F32 z) @@ -466,6 +507,16 @@ inline LLVector4 operator-(const LLVector4 &a) return LLVector4( -a.mV[VX], -a.mV[VY], -a.mV[VZ] ); } +inline LLVector4::operator glm::vec3() const +{ + return glm::vec3(mV[VX], mV[VY], mV[VZ]); +} + +inline LLVector4::operator glm::vec4() const +{ + return glm::make_vec4(mV); +} + inline F32 dist_vec(const LLVector4 &a, const LLVector4 &b) { LLVector4 vec = a - b; diff --git a/indra/llrender/llcubemaparray.cpp b/indra/llrender/llcubemaparray.cpp index 4f5e13765a3..d0a97dc2c61 100644 --- a/indra/llrender/llcubemaparray.cpp +++ b/indra/llrender/llcubemaparray.cpp @@ -109,7 +109,7 @@ LLCubeMapArray::~LLCubeMapArray() { } -void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool use_mips) +void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool use_mips, bool hdr) { U32 texname = 0; mWidth = resolution; @@ -127,7 +127,11 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us bind(0); free_cur_tex_image(); - U32 format = components == 4 ? GL_RGBA16F : GL_RGB16F; + U32 format = components == 4 ? GL_RGBA16F : GL_R11F_G11F_B10F; + if (!hdr) + { + format = components == 4 ? GL_RGBA8 : GL_RGB8; + } U32 mip = 0; U32 mip_resolution = resolution; while (mip_resolution >= 1) diff --git a/indra/llrender/llcubemaparray.h b/indra/llrender/llcubemaparray.h index 675aaaf07c7..bfc72a321d4 100644 --- a/indra/llrender/llcubemaparray.h +++ b/indra/llrender/llcubemaparray.h @@ -52,7 +52,7 @@ class LLCubeMapArray : public LLRefCount // components - number of components per pixel // count - number of cube maps in the array // use_mips - if true, mipmaps will be allocated for this cube map array and anisotropic filtering will be used - void allocate(U32 res, U32 components, U32 count, bool use_mips = true); + void allocate(U32 res, U32 components, U32 count, bool use_mips = true, bool hdr = true); void bind(S32 stage); void unbind(); diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index ee9cfd07198..83f5d31186a 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -107,7 +107,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp mBitmapHeight = image_height; S32 num_components = getNumComponents(bitmap_type); - mImageRawVec[bitmap_idx].push_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components)); + mImageRawVec[bitmap_idx].emplace_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components)); bitmap_num = static_cast(mImageRawVec[bitmap_idx].size()) - 1; LLImageRaw* image_raw = getImageRaw(bitmap_type, bitmap_num); @@ -117,7 +117,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp } // Make corresponding GL image. - mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false, false)); + mImageGLVec[bitmap_idx].emplace_back(new LLImageGL(image_raw, false, false)); LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num); // Start at beginning of the new image. diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 6128e03fa72..38dc23d1dc1 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -552,7 +552,7 @@ LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, l return NULL; llassert(!mIsFallback); - fontp->renderGlyph(requested_glyph_type, glyph_index); + fontp->renderGlyph(requested_glyph_type, glyph_index, wch); EFontGlyphType bitmap_glyph_type = EFontGlyphType::Unspecified; switch (fontp->mFTFace->glyph->bitmap.pixel_mode) @@ -697,7 +697,7 @@ void LLFontFreetype::insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const } } -void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const +void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, llwchar wch) const { if (mFTFace == NULL) return; @@ -712,11 +712,28 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) co FT_Error error = FT_Load_Glyph(mFTFace, glyph_index, load_flags); if (FT_Err_Ok != error) { + if (error == FT_Err_Out_Of_Memory) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Out of memory loading glyph for character " << llformat("U+%xu", U32(wch)) << LL_ENDL; + } + std::string message = llformat( - "Error %d (%s) loading glyph %u: bitmap_type=%u, load_flags=%d", - error, FT_Error_String(error), glyph_index, bitmap_type, load_flags); + "Error %d (%s) loading wchar %u glyph %u/%u: bitmap_type=%u, load_flags=%d", + error, FT_Error_String(error), wch, glyph_index, mFTFace->num_glyphs, bitmap_type, load_flags); LL_WARNS_ONCE() << message << LL_ENDL; error = FT_Load_Glyph(mFTFace, glyph_index, load_flags ^ FT_LOAD_COLOR); + if (FT_Err_Invalid_Outline == error + || FT_Err_Invalid_Composite == error + || (FT_Err_Ok != error && LLStringOps::isEmoji(wch))) + { + glyph_index = FT_Get_Char_Index(mFTFace, '?'); + // if '?' is not present, potentially can use last index, that's supposed to be null glyph + if (glyph_index > 0) + { + error = FT_Load_Glyph(mFTFace, glyph_index, load_flags ^ FT_LOAD_COLOR); + } + } llassert_always_msg(FT_Err_Ok == error, message.c_str()); } diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index eba89f5def4..a2d925c5f67 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -148,6 +148,7 @@ class LLFontFreetype : public LLRefCount void setStyle(U8 style); U8 getStyle() const; + S32 getAddedGlyphs() const { return mAddGlyphCount; } private: void resetBitmapCache(); @@ -156,7 +157,7 @@ class LLFontFreetype : public LLRefCount bool hasGlyph(llwchar wch) const; // Has a glyph for this character LLFontGlyphInfo* addGlyph(llwchar wch, EFontGlyphType glyph_type) const; // Add a new character to the font if necessary LLFontGlyphInfo* addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index, EFontGlyphType bitmap_type) const; // Add a glyph from this font to the other (returns the glyph_index, 0 if not found) - void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index) const; + void renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, llwchar wch) const; void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const; std::string mName; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 4c9a0622469..4037c036e5a 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -58,6 +58,7 @@ F32 LLFontGL::sVertDPI = 96.f; F32 LLFontGL::sHorizDPI = 96.f; F32 LLFontGL::sScaleX = 1.f; F32 LLFontGL::sScaleY = 1.f; +S32 LLFontGL::sResolutionGeneration = 0; bool LLFontGL::sDisplayFont = true ; std::string LLFontGL::sAppDir; @@ -109,6 +110,11 @@ S32 LLFontGL::getNumFaces(const std::string& filename) return mFontFreetype->getNumFaces(filename); } +S32 LLFontGL::getKnownGlyphCount() const +{ + return mFontFreetype ? mFontFreetype->getAddedGlyphs() : 0; +} + S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style, ShadowType shadow, S32 max_chars, F32* right_x, bool use_ellipses, bool use_color) const { @@ -249,6 +255,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); + // This looks wrong, value is dynamic. + // LLFontBitmapCache::nextOpenPos can alter these values when + // new characters get added to cache, which affects whole string. + // Todo: Perhaps value should update after symbols were added? F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth(); F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight(); @@ -270,6 +280,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons const LLFontGlyphInfo* next_glyph = NULL; + // string can have more than one glyph per char (ex: bold or shadow), + // make sure that GLYPH_BATCH_SIZE won't end up with half a symbol. + // See drawGlyph. + // Ex: with shadows it's 6 glyps per char. 30 fits exactly 5 chars. static constexpr S32 GLYPH_BATCH_SIZE = 30; static thread_local LLVector4a vertices[GLYPH_BATCH_SIZE * 6]; static thread_local LLVector2 uvs[GLYPH_BATCH_SIZE * 6]; @@ -282,6 +296,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons std::pair bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1); S32 glyph_count = 0; + llwchar last_char = wstr[begin_offset]; for (i = begin_offset; i < begin_offset + length; i++) { llwchar wch = wstr[i]; @@ -299,7 +314,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons } // Per-glyph bitmap texture. std::pair next_bitmap_entry = fgi->mBitmapEntry; - if (next_bitmap_entry != bitmap_entry) + if (next_bitmap_entry != bitmap_entry || last_char != wch) { // Actually draw the queued glyphs before switching their texture; // otherwise the queued glyphs will be taken from wrong textures. @@ -316,6 +331,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons bitmap_entry = next_bitmap_entry; LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second); gGL.getTexUnit(0)->bind(font_image); + + // For some reason it's not enough to compare by bitmap_entry. + // Issue hits emojis, japenese and chinese glyphs, only on first run. + // Todo: figure it out, there might be a bug with raw image data. + last_char = wch; } if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth)) diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 4bb6c55c65a..73efc6b1eb5 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -90,6 +90,7 @@ class LLFontGL bool loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n); S32 getNumFaces(const std::string& filename); + S32 getKnownGlyphCount() const; S32 render(const LLWString &text, S32 begin_offset, const LLRect& rect, @@ -224,6 +225,7 @@ class LLFontGL static F32 sHorizDPI; static F32 sScaleX; static F32 sScaleY; + static S32 sResolutionGeneration; static bool sDisplayFont ; static std::string sAppDir; // For loading fonts diff --git a/indra/llrender/llfontvertexbuffer.cpp b/indra/llrender/llfontvertexbuffer.cpp index 5bd1ca5eedb..b53a841a870 100644 --- a/indra/llrender/llfontvertexbuffer.cpp +++ b/indra/llrender/llfontvertexbuffer.cpp @@ -146,7 +146,9 @@ S32 LLFontVertexBuffer::render( || mLastScaleY != LLFontGL::sScaleY || mLastVertDPI != LLFontGL::sVertDPI || mLastHorizDPI != LLFontGL::sHorizDPI - || mLastOrigin != LLFontGL::sCurOrigin) + || mLastOrigin != LLFontGL::sCurOrigin + || mLastResGeneration != LLFontGL::sResolutionGeneration + || mLastFontGlyphCount != fontp->getKnownGlyphCount()) { genBuffers(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color); @@ -201,6 +203,8 @@ void LLFontVertexBuffer::genBuffers( mLastVertDPI = LLFontGL::sVertDPI; mLastHorizDPI = LLFontGL::sHorizDPI; mLastOrigin = LLFontGL::sCurOrigin; + mLastResGeneration = LLFontGL::sResolutionGeneration; + mLastFontGlyphCount = fontp->getKnownGlyphCount(); if (right_x) { diff --git a/indra/llrender/llfontvertexbuffer.h b/indra/llrender/llfontvertexbuffer.h index af195dfff92..d5e1280dbf1 100644 --- a/indra/llrender/llfontvertexbuffer.h +++ b/indra/llrender/llfontvertexbuffer.h @@ -117,8 +117,13 @@ class LLFontVertexBuffer F32 mLastScaleY = 1.f; F32 mLastVertDPI = 0.f; F32 mLastHorizDPI = 0.f; + S32 mLastResGeneration = 0; LLCoordGL mLastOrigin; + // Adding new characters to bitmap cache can alter value from getBitmapWidth(); + // which alters whole string. So rerender when new characters were added to cache. + S32 mLastFontGlyphCount = 0; + static bool sEnableBufferCollection; }; diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 58c456f1347..873ab0cff59 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -59,6 +59,7 @@ class LLShaderFeatures bool attachNothing = false; bool hasHeroProbes = false; bool isPBRTerrain = false; + bool hasTonemap = false; }; // ============= Structure for caching shader uniforms =============== diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 3858811a501..3f8903ca093 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -330,6 +330,7 @@ S32 LLImageGL::dataFormatBits(S32 dataformat) case GL_RGB: return 24; case GL_SRGB: return 24; case GL_RGB8: return 24; + case GL_R11F_G11F_B10F: return 32; case GL_RGBA: return 32; case GL_RGBA8: return 32; case GL_RGB10_A2: return 32; @@ -1773,7 +1774,7 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name) ref(); LL::WorkQueue::postMaybe( mMainQueue, - [=]() + [=, this]() { LL_PROFILE_ZONE_NAMED("cglt - delete callback"); syncTexName(new_tex_name); diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 1d53850f74b..1dc87a66cea 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -737,9 +737,8 @@ void LLLightState::setPosition(const LLVector4& position) ++gGL.mLightHash; mPosition = position; //transform position by current modelview matrix - glm::vec4 pos(glm::make_vec4(position.mV)); - const glm::mat4& mat = gGL.getModelviewMatrix(); - pos = mat * pos; + glm::vec4 pos(position); + pos = gGL.getModelviewMatrix() * pos; mPosition.set(glm::value_ptr(pos)); } @@ -794,7 +793,7 @@ void LLLightState::setSpotDirection(const LLVector3& direction) ++gGL.mLightHash; //transform direction by current modelview matrix - glm::vec3 dir(glm::make_vec3(direction.mV)); + glm::vec3 dir(direction); const glm::mat3 mat(gGL.getModelviewMatrix()); dir = mat * dir; @@ -2088,12 +2087,14 @@ void set_last_projection(const glm::mat4& mat) glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec) { - //const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3]; - //return glm::vec3( - // (vec[0] * mat[0][0] + vec[1] * mat[1][0] + vec[2] * mat[2][0] + mat[3][0]) / w, - // (vec[0] * mat[0][1] + vec[1] * mat[1][1] + vec[2] * mat[2][1] + mat[3][1]) / w, - // (vec[0] * mat[0][2] + vec[1] * mat[1][2] + vec[2] * mat[2][2] + mat[3][2]) / w - //); +#if 1 // SIMD path results in strange crashes. Fall back to scalar for now. + const float w = vec[0] * mat[0][3] + vec[1] * mat[1][3] + vec[2] * mat[2][3] + mat[3][3]; + return glm::vec3( + (vec[0] * mat[0][0] + vec[1] * mat[1][0] + vec[2] * mat[2][0] + mat[3][0]) / w, + (vec[0] * mat[0][1] + vec[1] * mat[1][1] + vec[2] * mat[2][1] + mat[3][1]) / w, + (vec[0] * mat[0][2] + vec[1] * mat[1][2] + vec[2] * mat[2][2] + mat[3][2]) / w + ); +#else LLVector4a x, y, z, s, t, p, q; x.splat(vec.x); @@ -2123,4 +2124,5 @@ glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec) res.setAdd(x, z); res.div(q); return glm::make_vec3(res.getF32ptr()); +#endif } diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 0885740934a..4807c122263 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -291,6 +291,14 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) } } + if (features->hasTonemap) + { + if (!shader->attachFragmentObject("deferred/tonemapUtilF.glsl")) + { + return false; + } + } + // NOTE order of shader object attaching is VERY IMPORTANT!!! if (features->hasAtmospherics) { @@ -466,6 +474,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev if (filename.empty()) { + LL_WARNS("ShaderLoading") << "tried loading empty filename" << LL_ENDL; return 0; } @@ -923,6 +932,8 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev } LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL; } + + LL_DEBUGS("ShaderLoading") << "loadShaderFile() completed, ret: " << U32(ret) << LL_ENDL; return ret; } @@ -1389,6 +1400,7 @@ void LLShaderMgr::initAttribsAndUniforms() mReservedUniforms.push_back("screenTex"); mReservedUniforms.push_back("screenDepth"); mReservedUniforms.push_back("refTex"); + mReservedUniforms.push_back("exclusionTex"); mReservedUniforms.push_back("eyeVec"); mReservedUniforms.push_back("time"); mReservedUniforms.push_back("waveDir1"); diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 34bd73a42ef..46788841a5d 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -36,6 +36,8 @@ class LLShaderMgr LLShaderMgr(); virtual ~LLShaderMgr(); + // Note: although you can use statically hashed strings to just bind a random uniform, it's generally preferably that you use this. + // Always document what the actual shader uniform is next to the shader uniform in this struct. // clang-format off typedef enum { // Shader uniform name, set in LLShaderMgr::initAttribsAndUniforms() @@ -234,6 +236,7 @@ class LLShaderMgr WATER_SCREENTEX, // "screenTex" WATER_SCREENDEPTH, // "screenDepth" WATER_REFTEX, // "refTex" + WATER_EXCLUSIONTEX, // "exclusionTex" WATER_EYEVEC, // "eyeVec" WATER_TIME, // "time" WATER_WAVE_DIR1, // "waveDir1" diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 42a9e267d27..b664065532a 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -28,6 +28,7 @@ #include "llfolderview.h" #include "llfolderviewmodel.h" +#include "llcallbacklist.h" #include "llclipboard.h" // *TODO: remove this once hack below gone. #include "llkeyboard.h" #include "lllineeditor.h" @@ -274,7 +275,11 @@ LLFolderView::~LLFolderView( void ) mRenamer = NULL; mStatusTextBox = NULL; - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + if (mPopupMenuHandle.get()) + { + mPopupMenuHandle.get()->die(); + gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this); + } mPopupMenuHandle.markDead(); mAutoOpenItems.removeAllNodes(); @@ -1095,7 +1100,10 @@ bool LLFolderView::handleKeyHere( KEY key, MASK mask ) LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); if (menu && menu->isOpen()) { - LLMenuGL::sMenuContainer->hideMenus(); + if (LLMenuGL::sMenuContainer->hideMenus()) + { + gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this); + } } switch( key ) @@ -1340,7 +1348,10 @@ bool LLFolderView::handleUnicodeCharHere(llwchar uni_char) LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); if (menu && menu->isOpen()) { - LLMenuGL::sMenuContainer->hideMenus(); + if (LLMenuGL::sMenuContainer->hideMenus()) + { + gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this); + } } //do text search @@ -1612,7 +1623,11 @@ void LLFolderView::deleteAllChildren() { LLUI::getInstance()->removePopup(mRenamer); } - if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + if (mPopupMenuHandle.get()) + { + mPopupMenuHandle.get()->die(); + gIdleCallbacks.deleteFunction(onIdleUpdateMenu, this); + } mPopupMenuHandle.markDead(); mScrollContainer = NULL; mRenameItem = NULL; @@ -1979,9 +1994,24 @@ void LLFolderView::updateMenu() LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); if (menu && menu->getVisible()) { - updateMenuOptions(menu); + // When fetching folders in bulk or in parts, each callback + // cause updateMenu individually, so make sure it gets called + // only once per frame, after callbacks are done. + // gIdleCallbacks has built in dupplicate protection. + gIdleCallbacks.addFunction(onIdleUpdateMenu, this); + } +} + +void LLFolderView::onIdleUpdateMenu(void* user_data) +{ + LLFolderView* self = (LLFolderView*)user_data; + LLMenuGL* menu = (LLMenuGL*)self->mPopupMenuHandle.get(); + if (menu) + { + self->updateMenuOptions(menu); menu->needsArrange(); // update menu height if needed } + gIdleCallbacks.deleteFunction(onIdleUpdateMenu, self); } bool LLFolderView::isFolderSelected() diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 62ef2a06260..7ed10d92233 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -266,6 +266,7 @@ class LLFolderView : public LLFolderViewFolder, public LLEditMenuHandler private: void updateMenuOptions(LLMenuGL* menu); void updateRenamerPosition(); + static void onIdleUpdateMenu(void* user_data); protected: LLScrollContainer* mScrollContainer; // NULL if this is not a child of a scroll container. @@ -414,6 +415,7 @@ class LLSaveFolderState : public LLFolderViewFunctor virtual void doItem(LLFolderViewItem* item) {} void setApply(bool apply); void clearOpenFolders() { mOpenFolders.clear(); } + bool hasOpenFolders() { return !mOpenFolders.empty(); } protected: std::set mOpenFolders; bool mApply; diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index cd80e7f63f0..7405413a3df 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1555,7 +1555,7 @@ bool LLNotifications::loadTemplates() gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); if (search_paths.empty()) { - LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"), LLError::LLUserWarningMsg::ERROR_MISSING_FILES); LL_ERRS() << "Problem finding notifications.xml" << LL_ENDL; } @@ -1565,7 +1565,7 @@ bool LLNotifications::loadTemplates() if (!success || root.isNull() || !root->hasName( "notifications" )) { - LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"), LLError::LLUserWarningMsg::ERROR_MISSING_FILES); LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL; return false; } @@ -1576,7 +1576,7 @@ bool LLNotifications::loadTemplates() if(!params.validateBlock()) { - LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"), LLError::LLUserWarningMsg::ERROR_MISSING_FILES); LL_ERRS() << "Problem reading XUI from UI Notifications file: " << base_filename << LL_ENDL; return false; } @@ -1643,7 +1643,7 @@ bool LLNotifications::loadVisibilityRules() if(!params.validateBlock()) { - LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile")); + LLError::LLUserWarningMsg::show(LLTrans::getString("MBMissingFile"), LLError::LLUserWarningMsg::ERROR_MISSING_FILES); LL_ERRS() << "Problem reading UI Notification Visibility Rules file: " << full_filename << LL_ENDL; return false; } diff --git a/indra/llui/llstyle.cpp b/indra/llui/llstyle.cpp index df4b0ef6a02..4714665e8bc 100644 --- a/indra/llui/llstyle.cpp +++ b/indra/llui/llstyle.cpp @@ -39,7 +39,7 @@ LLStyle::Params::Params() readonly_color("readonly_color", LLColor4::black), selected_color("selected_color", LLColor4::black), alpha("alpha", 1.f), - font("font", LLFontGL::getFontMonospace()), + font("font", LLStyle::getDefaultFont()), image("image"), link_href("href"), is_link("is_link") @@ -70,6 +70,11 @@ const LLFontGL* LLStyle::getFont() const return mFont; } +const LLFontGL* LLStyle::getDefaultFont() +{ + return LLFontGL::getFontMonospace(); +} + void LLStyle::setLinkHREF(const std::string& href) { mLink = href; diff --git a/indra/llui/llstyle.h b/indra/llui/llstyle.h index e506895de5c..0c78fe5a9f5 100644 --- a/indra/llui/llstyle.h +++ b/indra/llui/llstyle.h @@ -72,6 +72,7 @@ class LLStyle : public LLRefCount void setFont(const LLFontGL* font); const LLFontGL* getFont() const; + static const LLFontGL* getDefaultFont(); const std::string& getLinkHREF() const { return mLink; } void setLinkHREF(const std::string& href); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index cbbf83d6796..fae22fd2489 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1438,7 +1438,8 @@ void LLTextBase::onVisibilityChange( bool new_visibility ) //virtual void LLTextBase::setValue(const LLSD& value ) { - setText(value.asString()); + static const LLStyle::Params input_params = LLStyle::Params(); + setText(value.asString(), input_params); } //virtual @@ -3880,8 +3881,7 @@ bool LLInlineViewSegment::getDimensionsF32(S32 first_char, S32 num_chars, F32& w if (mForceNewLine) { // Chat, string can't be smaller then font height even if it is empty - LLStyleSP s(new LLStyle(LLStyle::Params().visible(true))); - height = s->getFont()->getLineHeight(); + height = LLStyle::getDefaultFont()->getLineHeight(); return true; // new line } @@ -3945,9 +3945,7 @@ void LLInlineViewSegment::linkToDocument(LLTextBase* editor) LLLineBreakTextSegment::LLLineBreakTextSegment(S32 pos):LLTextSegment(pos,pos+1) { - LLStyleSP s( new LLStyle(LLStyle::Params().visible(true))); - - mFontHeight = s->getFont()->getLineHeight(); + mFontHeight = LLStyle::getDefaultFont()->getLineHeight(); } LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1) { diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp index 05af36b71e1..9f945d37357 100644 --- a/indra/llui/lltextbox.cpp +++ b/indra/llui/lltextbox.cpp @@ -159,7 +159,8 @@ LLSD LLTextBox::getValue() const bool LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text ) { mText.setArg(key, text); - LLTextBase::setText(mText.getString()); + static const LLStyle::Params input_params = LLStyle::Params(); + LLTextBase::setText(mText.getString(), input_params); return true; } diff --git a/indra/llui/lltransutil.cpp b/indra/llui/lltransutil.cpp index 4af5376a8bf..e82af0b96f0 100644 --- a/indra/llui/lltransutil.cpp +++ b/indra/llui/lltransutil.cpp @@ -48,7 +48,7 @@ bool LLTransUtil::parseStrings(const std::string& xml_filename, const std::setdumpCurrentDirectories(LLError::LEVEL_WARN); LL_ERRS() << "Couldn't load string table " << xml_filename << " " << errno << LL_ENDL; return false; diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index c160382c176..195f68e08be 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -194,6 +194,11 @@ bool LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, return false; } +bool LLWindowCallbacks::handleDisplayChanged() +{ + return false; +} + bool LLWindowCallbacks::handleWindowDidChangeScreen(LLWindow *window) { return false; diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index 63b585231f9..d812f935244 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -69,6 +69,7 @@ class LLWindowCallbacks virtual bool handleTimerEvent(LLWindow *window); virtual bool handleDeviceChange(LLWindow *window); virtual bool handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height); + virtual bool handleDisplayChanged(); virtual bool handleWindowDidChangeScreen(LLWindow *window); enum DragNDropAction { diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index f26d6923638..6c3be3eef8d 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -1060,7 +1060,7 @@ F32 LLWindowMacOSX::getGamma() &greenGamma, &blueMin, &blueMax, - &blueGamma) == noErr) + &blueGamma) == kCGErrorSuccess) { // So many choices... // Let's just return the green channel gamma for now. @@ -1111,7 +1111,7 @@ bool LLWindowMacOSX::setGamma(const F32 gamma) &greenGamma, &blueMin, &blueMax, - &blueGamma) != noErr) + &blueGamma) != kCGErrorSuccess) { return false; } @@ -1126,7 +1126,7 @@ bool LLWindowMacOSX::setGamma(const F32 gamma) gamma, blueMin, blueMax, - gamma) != noErr) + gamma) != kCGErrorSuccess) { return false; } @@ -1178,7 +1178,7 @@ bool LLWindowMacOSX::setCursorPosition(const LLCoordWindow position) newPosition.y = screen_pos.mY; CGSetLocalEventsSuppressionInterval(0.0); - if(CGWarpMouseCursorPosition(newPosition) == noErr) + if(CGWarpMouseCursorPosition(newPosition) == kCGErrorSuccess) { result = true; } diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 91437b98d17..832cf254d1b 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -44,6 +44,7 @@ #include "llstring.h" #include "lldir.h" #include "llsdutil.h" +#include "llsys.h" #include "llglslshader.h" #include "llthreadsafequeue.h" #include "stringize.h" @@ -80,10 +81,6 @@ const S32 BITS_PER_PIXEL = 32; const S32 MAX_NUM_RESOLUTIONS = 32; const F32 ICON_FLASH_TIME = 0.5f; -#ifndef WM_DPICHANGED -#define WM_DPICHANGED 0x02E0 -#endif - #ifndef USER_DEFAULT_SCREEN_DPI #define USER_DEFAULT_SCREEN_DPI 96 // Win7 #endif @@ -1317,8 +1314,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo catch (...) { LOG_UNHANDLED_EXCEPTION("ChoosePixelFormat"); - OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"), - mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } @@ -1329,8 +1325,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) { - OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), - mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtDescErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } @@ -1368,8 +1363,7 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo if (!SetPixelFormat(mhDC, pixel_format, &pfd)) { - OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), - mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtSetErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } @@ -1377,16 +1371,14 @@ bool LLWindowWin32::switchContext(bool fullscreen, const LLCoordScreen& size, bo if (!(mhRC = SafeCreateContext(mhDC))) { - OSMessageBox(mCallbacks->translateString("MBGLContextErr"), - mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } if (!wglMakeCurrent(mhDC, mhRC)) { - OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), - mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextActErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } @@ -1592,15 +1584,14 @@ const S32 max_format = (S32)num_formats - 1; if (!mhDC) { - OSMessageBox(mCallbacks->translateString("MBDevContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBDevContextErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } if (!SetPixelFormat(mhDC, pixel_format, &pfd)) { - OSMessageBox(mCallbacks->translateString("MBPixelFmtSetErr"), - mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtSetErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } @@ -1632,7 +1623,7 @@ const S32 max_format = (S32)num_formats - 1; { LL_WARNS("Window") << "No wgl_ARB_pixel_format extension!" << LL_ENDL; // cannot proceed without wgl_ARB_pixel_format extension, shutdown same as any other gGLManager.initGL() failure - OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } @@ -1641,7 +1632,7 @@ const S32 max_format = (S32)num_formats - 1; if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd)) { - OSMessageBox(mCallbacks->translateString("MBPixelFmtDescErr"), mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBPixelFmtDescErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } @@ -1663,14 +1654,14 @@ const S32 max_format = (S32)num_formats - 1; if (!wglMakeCurrent(mhDC, mhRC)) { - OSMessageBox(mCallbacks->translateString("MBGLContextActErr"), mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextActErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } if (!gGLManager.initGL()) { - OSMessageBox(mCallbacks->translateString("MBVideoDrvErr"), mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBVideoDrvErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); close(); return false; } @@ -1875,7 +1866,7 @@ void* LLWindowWin32::createSharedContext() if (!rc && !(rc = wglCreateContext(mhDC))) { close(); - OSMessageBox(mCallbacks->translateString("MBGLContextErr"), mCallbacks->translateString("MBError"), OSMB_OK); + LLError::LLUserWarningMsg::show(mCallbacks->translateString("MBGLContextErr"), 8/*LAST_EXEC_GRAPHICS_INIT*/); } return rc; @@ -2974,6 +2965,11 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ return 0; } + case WM_DISPLAYCHANGE: + { + WINDOW_IMP_POST(window_imp->mCallbacks->handleDisplayChanged()); + } + case WM_SETFOCUS: { LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SETFOCUS"); @@ -4681,6 +4677,23 @@ void LLWindowWin32::LLWindowWin32Thread::checkDXMem() // Alternatively use GetDesc from below to get adapter's memory UINT64 budget_mb = info.Budget / (1024 * 1024); + if (gGLManager.mIsIntel) + { + U32Megabytes phys_mb = gSysMemory.getPhysicalMemoryKB(); + LL_WARNS() << "Physical memory: " << phys_mb << " MB" << LL_ENDL; + + if (phys_mb > 0) + { + // Intel uses 'shared' vram, cap it to 25% of total memory + // Todo: consider caping all adapters at least to 50% ram + budget_mb = llmin(budget_mb, (UINT64)(phys_mb * 0.25)); + } + else + { + // if no data available, cap to 2Gb + budget_mb = llmin(budget_mb, (UINT64)2048); + } + } if (gGLManager.mVRAM < (S32)budget_mb) { gGLManager.mVRAM = (S32)budget_mb; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 5bcfddfe25c..d2736c7c12e 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -156,6 +156,7 @@ set(viewer_SOURCE_FILES lldrawpooltree.cpp lldrawpoolwater.cpp lldrawpoolwlsky.cpp + lldrawpoolwaterexclusion.cpp lldynamictexture.cpp llemote.cpp llenvironment.cpp @@ -823,6 +824,7 @@ set(viewer_HEADER_FILES lldrawpooltree.h lldrawpoolwater.h lldrawpoolwlsky.h + lldrawpoolwaterexclusion.h lldynamictexture.h llemote.h llenvironment.h diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 07298fa9214..4293fa30347 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -12717,7 +12717,7 @@ UpdaterWillingToTest Comment - Whether or not the updater should offer test candidate upgrades. + Whether or not the updater should offer Beta upgrades. Persist 1 Type diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl index fc6d4d7727e..c4610bffac2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredTonemap.glsl @@ -28,138 +28,11 @@ out vec4 frag_color; uniform sampler2D diffuseRect; -uniform sampler2D exposureMap; -uniform vec2 screen_res; in vec2 vary_fragcoord; vec3 linear_to_srgb(vec3 cl); - -//=============================================================== -// tone mapping taken from Khronos sample implementation -//=============================================================== - -// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT -const mat3 ACESInputMat = mat3 -( - 0.59719, 0.07600, 0.02840, - 0.35458, 0.90834, 0.13383, - 0.04823, 0.01566, 0.83777 -); - - -// ODT_SAT => XYZ => D60_2_D65 => sRGB -const mat3 ACESOutputMat = mat3 -( - 1.60475, -0.10208, -0.00327, - -0.53108, 1.10813, -0.07276, - -0.07367, -0.00605, 1.07602 -); - -// ACES tone map (faster approximation) -// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ -vec3 toneMapACES_Narkowicz(vec3 color) -{ - const float A = 2.51; - const float B = 0.03; - const float C = 2.43; - const float D = 0.59; - const float E = 0.14; - return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0); -} - - -// ACES filmic tone map approximation -// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl -vec3 RRTAndODTFit(vec3 color) -{ - vec3 a = color * (color + 0.0245786) - 0.000090537; - vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081; - return a / b; -} - - -// tone mapping -vec3 toneMapACES_Hill(vec3 color) -{ - color = ACESInputMat * color; - - // Apply RRT and ODT - color = RRTAndODTFit(color); - - color = ACESOutputMat * color; - - // Clamp to [0, 1] - color = clamp(color, 0.0, 1.0); - - return color; -} - -// Khronos Neutral tonemapping -// https://github.com/KhronosGroup/ToneMapping/tree/main -// Input color is non-negative and resides in the Linear Rec. 709 color space. -// Output color is also Linear Rec. 709, but in the [0, 1] range. -vec3 PBRNeutralToneMapping( vec3 color ) -{ - const float startCompression = 0.8 - 0.04; - const float desaturation = 0.15; - - float x = min(color.r, min(color.g, color.b)); - float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; - color -= offset; - - float peak = max(color.r, max(color.g, color.b)); - if (peak < startCompression) return color; - - const float d = 1. - startCompression; - float newPeak = 1. - d * d / (peak + d - startCompression); - color *= newPeak / peak; - - float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.); - return mix(color, newPeak * vec3(1, 1, 1), g); -} - -uniform float exposure; -uniform float tonemap_mix; -uniform int tonemap_type; - -vec3 toneMap(vec3 color) -{ -#ifndef NO_POST - float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; - - color *= exposure * exp_scale; - - vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0)); - - switch(tonemap_type) - { - case 0: - color = PBRNeutralToneMapping(color); - break; - case 1: - color = toneMapACES_Hill(color); - break; - } - - // mix tonemapped and linear here to provide adjustment - color = mix(clamped_color, color, tonemap_mix); -#endif - - return color; -} - -//=============================================================== - -void debugExposure(inout vec3 color) -{ - float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; - exp_scale *= 0.5; - if (abs(vary_fragcoord.y-exp_scale) < 0.01 && vary_fragcoord.x < 0.1) - { - color = vec3(1,0,0); - } -} +vec3 toneMap(vec3 color); void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl b/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl new file mode 100644 index 00000000000..a63b8d7c2b5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/tonemapUtilF.glsl @@ -0,0 +1,180 @@ +/** + * @file postDeferredTonemap.glsl + * + * $LicenseInfo:firstyear=2024&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2024, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +/*[EXTRA_CODE_HERE]*/ + +uniform sampler2D exposureMap; +uniform vec2 screen_res; +in vec2 vary_fragcoord; + +//=============================================================== +// tone mapping taken from Khronos sample implementation +//=============================================================== + +// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT +const mat3 ACESInputMat = mat3 +( + 0.59719, 0.07600, 0.02840, + 0.35458, 0.90834, 0.13383, + 0.04823, 0.01566, 0.83777 +); + + +// ODT_SAT => XYZ => D60_2_D65 => sRGB +const mat3 ACESOutputMat = mat3 +( + 1.60475, -0.10208, -0.00327, + -0.53108, 1.10813, -0.07276, + -0.07367, -0.00605, 1.07602 +); + +// ACES tone map (faster approximation) +// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/ +vec3 toneMapACES_Narkowicz(vec3 color) +{ + const float A = 2.51; + const float B = 0.03; + const float C = 2.43; + const float D = 0.59; + const float E = 0.14; + return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0); +} + + +// ACES filmic tone map approximation +// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl +vec3 RRTAndODTFit(vec3 color) +{ + vec3 a = color * (color + 0.0245786) - 0.000090537; + vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081; + return a / b; +} + + +// tone mapping +vec3 toneMapACES_Hill(vec3 color) +{ + color = ACESInputMat * color; + + // Apply RRT and ODT + color = RRTAndODTFit(color); + + color = ACESOutputMat * color; + + // Clamp to [0, 1] + color = clamp(color, 0.0, 1.0); + + return color; +} + +// Khronos Neutral tonemapping +// https://github.com/KhronosGroup/ToneMapping/tree/main +// Input color is non-negative and resides in the Linear Rec. 709 color space. +// Output color is also Linear Rec. 709, but in the [0, 1] range. +vec3 PBRNeutralToneMapping( vec3 color ) +{ + const float startCompression = 0.8 - 0.04; + const float desaturation = 0.15; + + float x = min(color.r, min(color.g, color.b)); + float offset = x < 0.08 ? x - 6.25 * x * x : 0.04; + color -= offset; + + float peak = max(color.r, max(color.g, color.b)); + if (peak < startCompression) return color; + + const float d = 1. - startCompression; + float newPeak = 1. - d * d / (peak + d - startCompression); + color *= newPeak / peak; + + float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.); + return mix(color, newPeak * vec3(1, 1, 1), g); +} + +uniform float exposure; +uniform float tonemap_mix; +uniform int tonemap_type; + +vec3 toneMap(vec3 color) +{ +#ifndef NO_POST + float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; + + color *= exposure * exp_scale; + + vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0)); + + switch(tonemap_type) + { + case 0: + color = PBRNeutralToneMapping(color); + break; + case 1: + color = toneMapACES_Hill(color); + break; + } + + // mix tonemapped and linear here to provide adjustment + color = mix(clamped_color, color, tonemap_mix); +#endif + + return color; +} + + +vec3 toneMapNoExposure(vec3 color) +{ +#ifndef NO_POST + vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0)); + + switch(tonemap_type) + { + case 0: + color = PBRNeutralToneMapping(color); + break; + case 1: + color = toneMapACES_Hill(color); + break; + } + + // mix tonemapped and linear here to provide adjustment + color = mix(clamped_color, color, tonemap_mix); +#endif + + return color; +} + + +//=============================================================== + +void debugExposure(inout vec3 color) +{ + float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r; + exp_scale *= 0.5; + if (abs(vary_fragcoord.y-exp_scale) < 0.01 && vary_fragcoord.x < 0.1) + { + color = vec3(1,0,0); + } +} diff --git a/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl index d7f6d20547b..bf8737615fd 100644 --- a/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/srgbF.glsl @@ -41,6 +41,26 @@ vec3 srgb_to_linear(vec3 cs) } + +vec4 srgb_to_linear4(vec4 cs) +{ + vec4 low_range = cs / vec4(12.92); + vec4 high_range = pow((cs+vec4(0.055))/vec4(1.055), vec4(2.4)); + bvec4 lte = lessThanEqual(cs,vec4(0.04045)); + +#ifdef OLD_SELECT + vec4 result; + result.r = lte.r ? low_range.r : high_range.r; + result.g = lte.g ? low_range.g : high_range.g; + result.b = lte.b ? low_range.b : high_range.b; + result.a = lte.a ? low_range.a : high_range.a; + return result; +#else + return mix(high_range, low_range, lte); +#endif + +} + vec3 linear_to_srgb(vec3 cl) { cl = clamp(cl, vec3(0), vec3(1)); diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl index 20b61e93020..44a979e5651 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl @@ -66,11 +66,11 @@ vec4 getWaterFogViewNoClip(vec3 pos) float t2 = kd + ks * es; float t3 = pow(F, t2*l) - 1.0; - float L = min(t1/t2*t3, 1.0); + float L = pow(min(t1/t2*t3, 1.0), 1.0/1.7); float D = pow(0.98, l*kd); - return vec4(srgb_to_linear(kc.rgb*L), D); + return vec4(srgb_to_linear(kc.rgb)*L, D); } vec4 getWaterFogView(vec3 pos) diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl new file mode 100644 index 00000000000..dea76da5a52 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/simpleColorF.glsl @@ -0,0 +1,57 @@ +/** + * @file simpleColorF.glsl + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +out vec4 frag_color; + +in vec4 vertex_color; +in vec4 vertex_position; + +uniform vec4 waterPlane; +uniform float waterSign; + +void waterClip(vec3 pos) +{ + // TODO: make this less branchy + if (waterSign > 0) + { + if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) < 0.0) + { + discard; + } + } + else + { + if ((dot(pos.xyz, waterPlane.xyz) + waterPlane.w) > 0.0) + { + discard; + } + } +} + +void main() +{ + + frag_color = vertex_color; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl new file mode 100644 index 00000000000..4564e563134 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/simpleNoAtmosV.glsl @@ -0,0 +1,43 @@ +/** + * @file simpleNoAtmosV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +uniform mat4 modelview_matrix; +uniform mat4 modelview_projection_matrix; + +uniform vec4 color; + +in vec3 position; + +out vec4 vertex_color; +out vec4 vertex_position; + +void main() +{ + //transform vertex + vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0)); + vertex_position = modelview_projection_matrix * vec4(position.xyz, 1.0); + gl_Position = vertex_position; + vertex_color = color; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index 3e702f26be5..cc9d72fae61 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -150,7 +150,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec float amb_da = 0.0;//ambiance; if (da > 0) { - lit = max(da * dist_atten,0.0); + lit = clamp(da * dist_atten, 0.0, 1.0); col = lit * light_col * diffuse; amb_da += (da*0.5+0.5) * ambiance; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl index 7f871c0d5e9..5708fc319fa 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/materialF.glsl @@ -140,7 +140,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe float amb_da = ambiance; if (da >= 0) { - lit = max(da * dist_atten, 0.0); + lit = clamp(da * dist_atten, 0.0, 1.0); col = lit * light_col * diffuse; amb_da += (da*0.5 + 0.5) * ambiance; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl index 5dfa196cf6a..136b3dd9668 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/reflectionProbeF.glsl @@ -38,6 +38,8 @@ uniform float max_probe_lod; uniform bool transparent_surface; +uniform int classic_mode; + #define MAX_REFMAP_COUNT 256 // must match LL_MAX_REFLECTION_PROBE_COUNT layout (std140) uniform ReflectionProbes @@ -739,7 +741,10 @@ void doProbeSample(inout vec3 ambenv, inout vec3 glossenv, vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - ambenv = sampleProbeAmbient(pos, norm, amblit); + ambenv = amblit; + + if (classic_mode == 0) + ambenv = sampleProbeAmbient(pos, norm, amblit); float lod = (1.0-glossiness)*reflection_lods; glossenv = sampleProbes(pos, normalize(refnormpersp), lod); @@ -784,9 +789,6 @@ void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv, probeIndex[probeInfluences++] = 0; doProbeSample(ambenv, glossenv, tc, pos, norm, glossiness, false, amblit); - - // fudge factor to get PBR water at a similar luminance ot legacy water - glossenv *= 0.4; } void debugTapRefMap(vec3 pos, vec3 dir, float depth, int i, inout vec4 col) @@ -845,7 +847,10 @@ void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 refnormpersp = reflect(pos.xyz, norm.xyz); - ambenv = sampleProbeAmbient(pos, norm, amblit); + ambenv = amblit; + + if (classic_mode == 0) + ambenv = sampleProbeAmbient(pos, norm, amblit); if (glossiness > 0.0) { diff --git a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl index 2bf785e773b..091c25d15e7 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/waterHazeF.glsl @@ -35,13 +35,25 @@ vec4 getWaterFogView(vec3 pos); uniform int above_water; +uniform sampler2D exclusionTex; + void main() { vec2 tc = vary_fragcoord.xy/vary_fragcoord.w*0.5+0.5; float depth = getDepth(tc.xy); + float mask = texture(exclusionTex, tc.xy).r; if (above_water > 0) { + // Just discard if we're in the exclusion mask. + // The previous invisiprim hack we're replacing would also crank up water fog desntiy. + // But doing that makes exclusion surfaces very slow as we'd need to render even more into the mask. + // - Geenz 2025-02-06 + if (mask < 1) + { + discard; + } + // we want to depth test when the camera is above water, but some GPUs have a hard time // with depth testing against render targets that are bound for sampling in the same shader // so we do it manually here @@ -51,11 +63,13 @@ void main() { discard; } + } vec4 pos = getPositionWithDepth(tc, depth); vec4 fogged = getWaterFogView(pos.xyz); + fogged.a = max(pow(fogged.a, 1.7), 0); frag_color = max(fogged, vec4(0)); //output linear since local lights will be added to this shader's results diff --git a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl index 1c02dc764d7..fa410e9f116 100644 --- a/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/underWaterF.glsl @@ -26,6 +26,7 @@ out vec4 frag_color; uniform sampler2D bumpMap; +uniform sampler2D exclusionTex; #ifdef TRANSPARENT_WATER uniform sampler2D screenTex; @@ -59,6 +60,9 @@ void mirrorClip(vec3 position); void main() { mirrorClip(vary_position); + vec2 screen_tc = (refCoord.xy/refCoord.z) * 0.5 + 0.5; + float water_mask = texture(exclusionTex, screen_tc).r; + vec4 color; //get detail normals @@ -68,8 +72,8 @@ void main() vec3 wavef = normalize(wave1+wave2+wave3); //figure out distortion vector (ripply) - vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; - distort = distort+wavef.xy*refScale; + vec2 distort = screen_tc; + distort = mix(distort, distort+wavef.xy*refScale, water_mask); #ifdef TRANSPARENT_WATER vec4 fb = texture(screenTex, distort); diff --git a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl index 8bf4ec0a7e5..35b2f8bd107 100644 --- a/indra/newview/app_settings/shaders/class3/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -25,6 +25,8 @@ // class3/environment/waterF.glsl +#define WATER_MINIMAL 1 + out vec4 frag_color; #ifdef HAS_SUN_SHADOW @@ -86,23 +88,17 @@ uniform sampler2D screenTex; uniform sampler2D depthMap; #endif -uniform sampler2D refTex; +uniform sampler2D exclusionTex; -uniform float sunAngle; -uniform float sunAngle2; +uniform int classic_mode; uniform vec3 lightDir; uniform vec3 specular; -uniform float lightExp; +uniform float blurMultiplier; uniform float refScale; uniform float kd; -uniform vec2 screenRes; uniform vec3 normScale; uniform float fresnelScale; uniform float fresnelOffset; -uniform float blurMultiplier; -uniform vec4 waterFogColor; -uniform vec3 waterFogColorLinear; - //bigWave is (refCoord.w, view.w); in vec4 refCoord; @@ -122,6 +118,10 @@ vec3 BlendNormal(vec3 bump1, vec3 bump2) vec3 srgb_to_linear(vec3 col); vec3 linear_to_srgb(vec3 col); +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); +vec3 toneMapNoExposure(vec3 color); + vec3 vN, vT, vB; vec3 transform_normal(vec3 vNt) @@ -132,59 +132,107 @@ vec3 transform_normal(vec3 vNt) void sampleReflectionProbesWater(inout vec3 ambenv, inout vec3 glossenv, vec2 tc, vec3 pos, vec3 norm, float glossiness, vec3 amblit_linear); +void sampleReflectionProbes(inout vec3 ambenv, inout vec3 glossenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness, bool transparent, vec3 amblit_linear); + +void sampleReflectionProbesLegacy(inout vec3 ambenv, inout vec3 glossenv, inout vec3 legacyenv, + vec2 tc, vec3 pos, vec3 norm, float glossiness, float envIntensity, bool transparent, vec3 amblit); + + vec3 getPositionWithNDC(vec3 ndc); +void generateWaveNormals(out vec3 wave1, out vec3 wave2, out vec3 wave3) +{ + // Generate all of our wave normals. + // We layer these back and forth. + + vec2 bigwave = vec2(refCoord.w, view.w); + + vec3 wave1_a = texture(bumpMap, bigwave).xyz * 2.0 - 1.0; + vec3 wave2_a = texture(bumpMap, littleWave.xy).xyz * 2.0 - 1.0; + vec3 wave3_a = texture(bumpMap, littleWave.zw).xyz * 2.0 - 1.0; + + vec3 wave1_b = texture(bumpMap2, bigwave).xyz * 2.0 - 1.0; + vec3 wave2_b = texture(bumpMap2, littleWave.xy).xyz * 2.0 - 1.0; + vec3 wave3_b = texture(bumpMap2, littleWave.zw).xyz * 2.0 - 1.0; + + wave1 = BlendNormal(wave1_a, wave1_b); + wave2 = BlendNormal(wave2_a, wave2_b); + wave3 = BlendNormal(wave3_a, wave3_b); +} + +void calculateFresnelFactors(out vec3 df3, out vec2 df2, vec3 viewVec, vec3 wave1, vec3 wave2, vec3 wave3, vec3 wavef) +{ + // We calculate the fresnel here. + // We do this by getting the dot product for each sets of waves, and applying scale and offset. + + df3 = max(vec3(0), vec3( + dot(viewVec, wave1), + dot(viewVec, (wave2 + wave3) * 0.5), + dot(viewVec, wave3) + ) * fresnelScale + fresnelOffset); + + df3 *= df3; + + df2 = max(vec2(0), vec2( + df3.x + df3.y + df3.z, + dot(viewVec, wavef) * fresnelScale + fresnelOffset + )); +} + void main() { mirrorClip(vary_position); + vN = vary_normal; vT = vary_tangent; vB = cross(vN, vT); vec3 pos = vary_position.xyz; + float linear_depth = 1 / -pos.z; float dist = length(pos.xyz); //normalize view vector vec3 viewVec = normalize(pos.xyz); - //get wave normals - vec2 bigwave = vec2(refCoord.w, view.w); - vec3 wave1_a = texture(bumpMap, bigwave, -2 ).xyz*2.0-1.0; - vec3 wave2_a = texture(bumpMap, littleWave.xy).xyz*2.0-1.0; - vec3 wave3_a = texture(bumpMap, littleWave.zw).xyz*2.0-1.0; + // Setup our waves. - vec3 wave1_b = texture(bumpMap2, bigwave ).xyz*2.0-1.0; - vec3 wave2_b = texture(bumpMap2, littleWave.xy).xyz*2.0-1.0; - vec3 wave3_b = texture(bumpMap2, littleWave.zw).xyz*2.0-1.0; + vec3 wave1 = vec3(0, 0, 1); + vec3 wave2 = vec3(0, 0, 1); + vec3 wave3 = vec3(0, 0, 1); - //wave1_a = wave2_a = wave3_a = wave1_b = wave2_b = wave3_b = vec3(0,0,1); - - vec3 wave1 = BlendNormal(wave1_a, wave1_b); - vec3 wave2 = BlendNormal(wave2_a, wave2_b); - vec3 wave3 = BlendNormal(wave3_a, wave3_b); + generateWaveNormals(wave1, wave2, wave3); + float dmod = sqrt(dist); vec2 distort = (refCoord.xy/refCoord.z) * 0.5 + 0.5; - //wave1 = transform_normal(wave1); - //wave2 = transform_normal(wave2); - //wave3 = transform_normal(wave3); - vec3 wavef = (wave1 + wave2 * 0.4 + wave3 * 0.6) * 0.5; + vec3 df3 = vec3(0); + vec2 df2 = vec2(0); + + vec3 sunlit; + vec3 amblit; + vec3 additive; + vec3 atten; + calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten); + + calculateFresnelFactors(df3, df2, normalize(view.xyz), wave1, wave2, wave3, wavef); + vec3 waver = wavef*3; vec3 up = transform_normal(vec3(0,0,1)); float vdu = -dot(viewVec, up)*2; - vec3 wave_ibl = wavef; + vec3 wave_ibl = wavef * normScale; wave_ibl.z *= 2.0; wave_ibl = transform_normal(normalize(wave_ibl)); vec3 norm = transform_normal(normalize(wavef)); vdu = clamp(vdu, 0, 1); - wavef.z *= max(vdu*vdu*vdu, 0.1); + //wavef.z *= max(vdu*vdu*vdu, 0.1); wavef = normalize(wavef); @@ -194,62 +242,66 @@ void main() float dist2 = dist; dist = max(dist, 5.0); - float dmod = sqrt(dist); - //figure out distortion vector (ripply) - vec2 distort2 = distort + waver.xy * refScale / max(dmod, 1.0); + vec2 distort2 = distort + waver.xy * refScale / max(dmod, 1.0) * 2; distort2 = clamp(distort2, vec2(0), vec2(0.999)); - vec3 sunlit; - vec3 amblit; - vec3 additive; - vec3 atten; - float shadow = 1.0f; + float water_mask = texture(exclusionTex, distort).r; + #ifdef HAS_SUN_SHADOW shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, distort); #endif - calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten); - vec3 sunlit_linear = srgb_to_linear(sunlit); - + float fade = 1; #ifdef TRANSPARENT_WATER - vec4 fb = texture(screenTex, distort2); - float depth = texture(depthMap, distort2).r; - vec3 refPos = getPositionWithNDC(vec3(distort2*2.0-vec2(1.0), depth*2.0-1.0)); + float depth = texture(depthMap, distort).r; + + vec3 refPos = getPositionWithNDC(vec3(distort*2.0-vec2(1.0), depth*2.0-1.0)); + + // Calculate some distance fade in the water to better assist with refraction blending and reducing the refraction texture's "disconnect". + fade = max(0,min(1, (pos.z - refPos.z) / 10)) * water_mask; + distort2 = mix(distort, distort2, min(1, fade * 10)); + depth = texture(depthMap, distort2).r; + + refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0)); - if (refPos.z > pos.z-0.05) + if (pos.z < refPos.z - 0.05) { - //we sampled an above water sample, don't distort distort2 = distort; - fb = texture(screenTex, distort2); - depth = texture(depthMap, distort2).r; - refPos = getPositionWithNDC(vec3(distort2 * 2.0 - vec2(1.0), depth * 2.0 - 1.0)); } + vec4 fb = texture(screenTex, distort2); + #else vec4 fb = applyWaterFogViewLinear(viewVec*2048.0, vec4(1.0)); -#endif - // fudge sample on other side of water to be a tad darker - fb.rgb *= 0.75; + if (water_mask < 1) + discard; +#endif - float metallic = 0.0; - float perceptualRoughness = 0.05; - float gloss = 1.0 - perceptualRoughness; + float metallic = 1.0; + float perceptualRoughness = blurMultiplier; + float gloss = 1 - perceptualRoughness; vec3 irradiance = vec3(0); vec3 radiance = vec3(0); - sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, amblit); + vec3 legacyenv = vec3(0); - irradiance = vec3(0); + // TODO: Make this an option. +#ifdef WATER_MINIMAL + sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, amblit); +#elif WATER_MINIMAL_PLUS + sampleReflectionProbes(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, false, amblit); +#endif vec3 diffuseColor = vec3(0); vec3 specularColor = vec3(0); - calcDiffuseSpecular(vec3(1), metallic, diffuseColor, specularColor); + vec3 specular_linear = srgb_to_linear(specular); + calcDiffuseSpecular(specular_linear, metallic, diffuseColor, specularColor); vec3 v = -normalize(pos.xyz); @@ -257,46 +309,36 @@ void main() float ao = 1.0; vec3 light_dir = transform_normal(lightDir); - perceptualRoughness = 0.0; - metallic = 1.0; - float NdotV = clamp(abs(dot(norm, v)), 0.001, 1.0); float nl = 0; vec3 diffPunc = vec3(0); vec3 specPunc = vec3(0); - pbrPunctual(vec3(0), specularColor, 0.1, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir), nl, diffPunc, specPunc); - - vec3 punctual = clamp(nl * (diffPunc + specPunc), vec3(0), vec3(10)); - - vec3 color = punctual * sunlit_linear * 2.75 * shadow; - vec3 iblDiff; - vec3 iblSpec; - pbrIbl(vec3(0), vec3(1), radiance, vec3(0), ao, NdotV, 0.0, iblDiff, iblSpec); - - color += iblDiff + iblSpec; + pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir), nl, diffPunc, specPunc); - float nv = clamp(abs(dot(norm.xyz, v)), 0.001, 1.0); - vec2 brdf = BRDF(clamp(nv, 0, 1), 1.0); - float f = 1.0-brdf.y; //1.0 - (brdf.x+brdf.y); - f *= 0.9; - f *= f; + vec3 punctual = clamp(nl * (diffPunc + specPunc), vec3(0), vec3(10)) * sunlit_linear * shadow; + radiance *= df2.y; + //radiance = toneMapNoExposure(radiance); + vec3 color = vec3(0); + color = mix(fb.rgb, radiance, min(1, df2.x)) + punctual.rgb; - // incoming scale is [0, 1] with 0.5 being default - // shift to 0.5 to 1.5 - f *= (fresnelScale - 0.5)+1.0; + float water_haze_scale = 4; - // incoming offset is [0, 1] with 0.5 being default - // shift from -1 to 1 - f += (fresnelOffset - 0.5) * 2.0; + if (classic_mode > 0) + water_haze_scale = 1; - f = clamp(f, 0, 1); + // This looks super janky, but we do this to restore water haze in the distance. + // These values were finagled in to try and bring back some of the distant brightening on legacy water. Also works reasonably well on PBR skies such as PBR midday. + // color = mix(color, additive * water_haze_scale, (1 - atten)); - color = ((1.0 - f) * color) + fb.rgb; + // We shorten the fade here at the shoreline so it doesn't appear too soft from a distance. + fade *= 60; + fade = min(1, fade); + color = mix(fb.rgb, color, fade); - float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05); + float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0); - frag_color = max(vec4(color, spec), vec4(0)); + frag_color = min(vec4(1),max(vec4(color.rgb, spec * water_mask), vec4(0))); } diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index d894e1b24ef..cb79410d721 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -85,6 +85,7 @@ RenderExposure 1 4 RenderTonemapType 1 1 RenderTonemapMix 1 1 RenderDisableVintageMode 1 1 +RenderMaxTextureResolution 1 2048 // // Low Graphics Settings @@ -126,6 +127,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 +RenderMaxTextureResolution 1 512 // // Medium Low Graphics Settings @@ -167,6 +169,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 +RenderMaxTextureResolution 1 1024 // // Medium Graphics Settings (standard) @@ -207,6 +210,7 @@ RenderCASSharpness 1 0 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // Medium High Graphics Settings @@ -247,6 +251,7 @@ RenderCASSharpness 1 0 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // High Graphics Settings (SSAO + sun shadows) @@ -287,6 +292,7 @@ RenderCASSharpness 1 0.4 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // High Ultra Graphics Settings (deferred + SSAO + all shadows) @@ -327,6 +333,7 @@ RenderCASSharpness 1 0.4 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // Ultra graphics (REALLY PURTY!) @@ -367,6 +374,7 @@ RenderCASSharpness 1 0.4 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // Class Unknown Hardware (unknown) @@ -399,6 +407,7 @@ RenderShadowDetail 0 0 RenderReflectionProbeDetail 0 -1 RenderMirrors 0 0 RenderDisableVintageMode 1 0 +RenderMaxTextureResolution 1 2048 list Intel RenderAnisotropic 1 0 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index cfcd96d6507..dc9473b042b 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -85,6 +85,7 @@ RenderTonemapType 1 1 RenderTonemapMix 1 1 RenderDisableVintageMode 1 1 RenderDownScaleMethod 1 0 +RenderMaxTextureResolution 1 2048 // // Low Graphics Settings @@ -126,6 +127,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 +RenderMaxTextureResolution 1 512 // // Medium Low Graphics Settings @@ -167,6 +169,7 @@ RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 RenderDisableVintageMode 1 0 +RenderMaxTextureResolution 1 1024 // // Medium Graphics Settings (standard) @@ -207,6 +210,7 @@ RenderCASSharpness 1 0 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // Medium High Graphics Settings @@ -247,6 +251,7 @@ RenderCASSharpness 1 0 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // High Graphics Settings (SSAO + sun shadows) @@ -287,6 +292,7 @@ RenderCASSharpness 1 0 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // High Ultra Graphics Settings (SSAO + all shadows) @@ -327,6 +333,7 @@ RenderCASSharpness 1 0.4 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // Ultra graphics (REALLY PURTY!) @@ -367,6 +374,7 @@ RenderCASSharpness 1 0.4 RenderExposure 1 1 RenderTonemapType 1 1 RenderTonemapMix 1 0.7 +RenderMaxTextureResolution 1 2048 // // Class Unknown Hardware (unknown) @@ -398,6 +406,7 @@ RenderDeferredSSAO 0 0 RenderShadowDetail 0 0 RenderMirrors 0 0 RenderDisableVintageMode 1 0 +RenderMaxTextureResolution 1 2048 list TexUnit8orLess RenderDeferredSSAO 0 0 diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp index ed667532678..c33d15228c7 100644 --- a/indra/newview/gltfscenemanager.cpp +++ b/indra/newview/gltfscenemanager.cpp @@ -356,8 +356,9 @@ void GLTFSceneManager::addGLTFObject(LLViewerObject* obj, LLUUID gltf_id) llassert(obj->getVolume()->getParams().getSculptID() == gltf_id); llassert(obj->getVolume()->getParams().getSculptType() == LL_SCULPT_TYPE_GLTF); - if (obj->mGLTFAsset) - { // object already has a GLTF asset, don't reload it + if (obj->mGLTFAsset || obj->mIsGLTFAssetMissing ) + { + // object already has a GLTF asset or load failed, don't reload it // TODO: below assertion fails on dupliate requests for assets -- possibly need to touch up asset loading state machine // llassert(std::find(mObjects.begin(), mObjects.end(), obj) != mObjects.end()); @@ -398,16 +399,19 @@ void GLTFSceneManager::onGLTFBinLoadComplete(const LLUUID& id, LLAssetType::ETyp } else { - LL_WARNS("GLTF") << "Failed to prepare GLTF asset: " << id << LL_ENDL; + LL_WARNS("GLTF") << "Failed to prepare GLTF asset: " << id << ". Marking as missing." << LL_ENDL; + obj->mIsGLTFAssetMissing = true; obj->mGLTFAsset = nullptr; } } } + obj->unref(); // todo: use LLPointer } } else { - LL_WARNS("GLTF") << "Failed to load GLTF asset: " << id << LL_ENDL; + LL_WARNS("GLTF") << "Failed to load GLTF asset: " << id << ". Marking as missing." << LL_ENDL; + obj->mIsGLTFAssetMissing = true; obj->unref(); } }); @@ -446,7 +450,8 @@ void GLTFSceneManager::onGLTFLoadComplete(const LLUUID& id, LLAssetType::EType a } else { - LL_WARNS("GLTF") << "Buffer URI is not a valid UUID: " << buffer.mUri << LL_ENDL; + LL_WARNS("GLTF") << "Buffer URI is not a valid UUID: " << buffer.mUri << " for asset id: " << id << ". Marking as missing." << LL_ENDL; + obj->mIsGLTFAssetMissing = true; obj->unref(); return; } @@ -455,7 +460,8 @@ void GLTFSceneManager::onGLTFLoadComplete(const LLUUID& id, LLAssetType::EType a } else { - LL_WARNS("GLTF") << "Failed to load GLTF asset: " << id << LL_ENDL; + LL_WARNS("GLTF") << "Failed to load GLTF asset: " << id << ". Marking as missing." << LL_ENDL; + obj->mIsGLTFAssetMissing = true; obj->unref(); } } @@ -500,7 +506,7 @@ void GLTFSceneManager::update() LLNewBufferedResourceUploadInfo::uploadFinish_f finish = [this, buffer](LLUUID assetId, LLSD response) { LLAppViewer::instance()->postToMainCoro( - [=]() + [=, this]() { if (mUploadingAsset) { @@ -517,6 +523,7 @@ void GLTFSceneManager::update() if (mUploadingObject) { mUploadingObject->mGLTFAsset = nullptr; + mUploadingObject->mIsGLTFAssetMissing = false; mUploadingObject->setGLTFAsset(assetId); mUploadingObject->markForUpdate(); mUploadingObject = nullptr; @@ -975,9 +982,9 @@ void renderAssetDebug(LLViewerObject* obj, Asset* asset) LLVector4a t; agent_to_asset.affineTransform(gDebugRaycastStart, t); - start = glm::make_vec4(t.getF32ptr()); + start = vec4(t); agent_to_asset.affineTransform(gDebugRaycastEnd, t); - end = glm::make_vec4(t.getF32ptr()); + end = vec4(t); start.w = end.w = 1.0; diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 26c080bf898..8756baa04a8 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -4879,10 +4879,19 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename) LLXMLNodePtr root; bool success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); - if (!success || !root || !root->hasName( "teleport_messages" )) + if (!success) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Problem reading teleport string XML file: " - << xml_filename << LL_ENDL; + << xml_filename << LL_ENDL; + return; + } + + if (!root || !root->hasName("teleport_messages")) + { + LLError::LLUserWarningMsg::showMissingFiles(); + LL_ERRS() << "Invalid teleport string XML file: " + << xml_filename << LL_ENDL; return; } diff --git a/indra/newview/llagentpicksinfo.cpp b/indra/newview/llagentpicksinfo.cpp index e2a2d2d8a98..265e4060ff9 100644 --- a/indra/newview/llagentpicksinfo.cpp +++ b/indra/newview/llagentpicksinfo.cpp @@ -28,6 +28,7 @@ #include "llagentpicksinfo.h" #include "llagent.h" +#include "llagentbenefits.h" #include "llavatarpropertiesprocessor.h" const S32 MAX_AVATAR_PICKS = 10; @@ -85,10 +86,9 @@ class LLAgentPicksInfo::LLAgentPicksObserver : public LLAvatarPropertiesObserver LLAgentPicksInfo::LLAgentPicksInfo() : mAgentPicksObserver(NULL) - , mMaxNumberOfPicks(MAX_AVATAR_PICKS) // Disable Pick creation until we get number of Picks from server - in case // avatar has maximum number of Picks. - , mNumberOfPicks(mMaxNumberOfPicks) + , mNumberOfPicks(S32_MAX) { } @@ -110,7 +110,13 @@ void LLAgentPicksInfo::requestNumberOfPicks() mAgentPicksObserver->sendAgentPicksRequest(); } -bool LLAgentPicksInfo::isPickLimitReached() +// static +S32 LLAgentPicksInfo::getMaxNumberOfPicks() +{ + return LLAgentBenefitsMgr::current().getPicksLimit(); +} + +bool LLAgentPicksInfo::isPickLimitReached() const { return getNumberOfPicks() >= getMaxNumberOfPicks(); } diff --git a/indra/newview/llagentpicksinfo.h b/indra/newview/llagentpicksinfo.h index 9bc105a655f..3514ade65d8 100644 --- a/indra/newview/llagentpicksinfo.h +++ b/indra/newview/llagentpicksinfo.h @@ -52,17 +52,17 @@ class LLAgentPicksInfo : public LLSingleton /** * Returns number of Picks. */ - S32 getNumberOfPicks() { return mNumberOfPicks; } + S32 getNumberOfPicks() const { return mNumberOfPicks; } /** * Returns maximum number of Picks. */ - S32 getMaxNumberOfPicks() { return mMaxNumberOfPicks; } + static S32 getMaxNumberOfPicks(); /** * Returns true if Agent has maximum allowed number of Picks. */ - bool isPickLimitReached(); + bool isPickLimitReached() const; /** * After creating or deleting a Pick we can assume operation on server will be @@ -83,15 +83,9 @@ class LLAgentPicksInfo : public LLSingleton */ void setNumberOfPicks(S32 number) { mNumberOfPicks = number; } - /** - * Sets maximum number of Picks. - */ - void setMaxNumberOfPicks(S32 max_picks) { mMaxNumberOfPicks = max_picks; } - private: LLAgentPicksObserver* mAgentPicksObserver; - S32 mMaxNumberOfPicks; S32 mNumberOfPicks; }; diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 946d674e8be..4e0c5d7df0e 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -537,9 +537,14 @@ LLUpdateAppearanceOnDestroy::~LLUpdateAppearanceOnDestroy() selfStopPhase("update_appearance_on_destroy"); - LLAppearanceMgr::instance().updateAppearanceFromCOF(mEnforceItemRestrictions, - mEnforceOrdering, - mPostUpdateFunc); + //avoid calling an update inside coroutine + bool force_restrictions(mEnforceItemRestrictions); + bool enforce_ordering(mEnforceOrdering); + nullary_func_t post_update_func(mPostUpdateFunc); + doOnIdleOneTime([force_restrictions,enforce_ordering,post_update_func]() + { + LLAppearanceMgr::instance().updateAppearanceFromCOF(force_restrictions, enforce_ordering, post_update_func); + }); } } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c770b7c917a..9889765fffb 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -298,6 +298,7 @@ bool gUseQuickTime = true; eLastExecEvent gLastExecEvent = LAST_EXEC_NORMAL; S32 gLastExecDuration = -1; // (<0 indicates unknown) +LLUUID gLastAgentSessionId; #if LL_WINDOWS # define LL_PLATFORM_KEY "win" @@ -372,7 +373,6 @@ const int MAX_MARKER_LENGTH = 1024; const std::string MARKER_FILE_NAME("SecondLife.exec_marker"); const std::string START_MARKER_FILE_NAME("SecondLife.start_marker"); const std::string ERROR_MARKER_FILE_NAME("SecondLife.error_marker"); -const std::string LLERROR_MARKER_FILE_NAME("SecondLife.llerror_marker"); const std::string LOGOUT_MARKER_FILE_NAME("SecondLife.logout_marker"); static bool gDoDisconnect = false; static std::string gLaunchFileOnQuit; @@ -2219,6 +2219,7 @@ bool LLAppViewer::initThreads() return true; } +// Callback for all LL_ERROR calls void errorCallback(LLError::ELevel level, const std::string &error_string) { if (level == LLError::LEVEL_ERROR) @@ -2234,15 +2235,38 @@ void errorCallback(LLError::ELevel level, const std::string &error_string) // haven't actually trashed anything yet, we can afford to write the whole // static info file. LLAppViewer::instance()->writeDebugInfo(); + + std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); + if (!LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB)) + { + // If marker doesn't exist, create a marker with llerror code for next launch + // otherwise don't override existing file + LLAppViewer::instance()->createErrorMarker(LAST_EXEC_LLERROR_CRASH); + } } } -void errorMSG(const std::string& title_string, const std::string& message_string) +// Callback for LLError::LLUserWarningMsg +void errorHandler(const std::string& title_string, const std::string& message_string, S32 code) { if (!message_string.empty()) { OSMessageBox(message_string, title_string.empty() ? LLTrans::getString("MBFatalError") : title_string, OSMB_OK); } + switch (code) + { + case LLError::LLUserWarningMsg::ERROR_OTHER: + LLAppViewer::instance()->createErrorMarker(LAST_EXEC_OTHER_CRASH); + break; + case LLError::LLUserWarningMsg::ERROR_BAD_ALLOC: + LLAppViewer::instance()->createErrorMarker(LAST_EXEC_BAD_ALLOC); + break; + case LLError::LLUserWarningMsg::ERROR_MISSING_FILES: + LLAppViewer::instance()->createErrorMarker(LAST_EXEC_MISSING_FILES); + break; + default: + break; + } } void LLAppViewer::initLoggingAndGetLastDuration() @@ -2256,7 +2280,7 @@ void LLAppViewer::initLoggingAndGetLastDuration() LLError::addGenericRecorder(&errorCallback); //LLError::setTimeFunction(getRuntime); - LLError::LLUserWarningMsg::setHandler(errorMSG); + LLError::LLUserWarningMsg::setHandler(errorHandler); if (mSecondInstance) @@ -2540,6 +2564,7 @@ bool LLAppViewer::initConfiguration() OSMessageBox( "Unable to load default settings file. The installation may be corrupted.", LLStringUtil::null,OSMB_OK); + LLAppViewer::instance()->createErrorMarker(LAST_EXEC_MISSING_FILES); return false; } @@ -3702,16 +3727,21 @@ bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const bool sameVersion = false; std::string my_version(LLVersionInfo::instance().getChannelAndVersion()); - char marker_version[MAX_MARKER_LENGTH]; + char marker_data[MAX_MARKER_LENGTH]; S32 marker_version_length; LLAPRFile marker_file; marker_file.open(marker_name, LL_APR_RB); if (marker_file.getFileHandle()) { - marker_version_length = marker_file.read(marker_version, sizeof(marker_version)); - std::string marker_string(marker_version, marker_version_length); - if ( 0 == my_version.compare( 0, my_version.length(), marker_version, 0, marker_version_length ) ) + marker_version_length = marker_file.read(marker_data, sizeof(marker_data)); + std::string marker_string(marker_data, marker_version_length); + size_t pos = marker_string.find('\n'); + if (pos != std::string::npos) + { + marker_string = marker_string.substr(0, pos); + } + if ( 0 == my_version.compare( 0, my_version.length(), marker_string, 0, marker_string.length()) ) { sameVersion = true; } @@ -3725,6 +3755,88 @@ bool LLAppViewer::markerIsSameVersion(const std::string& marker_name) const return sameVersion; } +void LLAppViewer::recordSessionToMarker() +{ + std::string marker_version(LLVersionInfo::instance().getChannelAndVersion()); + std::string uuid_str = "\n" + gAgentSessionID.asString(); + if (marker_version.length() + uuid_str.length() > MAX_MARKER_LENGTH) + { + LL_WARNS_ONCE("MarkerFile") << "Version length (" << marker_version.length() << ")" + << " greater than maximum (" << MAX_MARKER_LENGTH << ")" + << ": marker matching may be incorrect" + << LL_ENDL; + } + + mMarkerFile.seek(APR_SET, (S32)marker_version.length()); + mMarkerFile.write(uuid_str.data(), (S32)uuid_str.length()); +} + +LLUUID LLAppViewer::getMarkerSessionId(const std::string& marker_name) const +{ + std::string data; + if (getMarkerData(marker_name, data)) + { + return LLUUID(data); + } + return LLUUID(); +} + +S32 LLAppViewer::getMarkerErrorCode(const std::string& marker_name) const +{ + std::string data; + if (getMarkerData(marker_name, data)) + { + if (data.empty()) + { + return 0; + } + else + { + return std::stoi(data); + } + } + return -1; +} + +bool LLAppViewer::getMarkerData(const std::string& marker_name, std::string& data) const +{ + bool sameVersion = false; + + std::string my_version(LLVersionInfo::instance().getChannelAndVersion()); + char marker_data[MAX_MARKER_LENGTH]; + S32 marker_version_length; + + LLAPRFile marker_file; + marker_file.open(marker_name, LL_APR_RB); + if (marker_file.getFileHandle()) + { + marker_version_length = marker_file.read(marker_data, sizeof(marker_data)); + marker_file.close(); + std::string marker_string(marker_data, marker_version_length); + size_t pos = marker_string.find('\n'); + if (pos != std::string::npos) + { + data = marker_string.substr(pos + 1, marker_version_length - pos - 1); + marker_string = marker_string.substr(0, pos); + } + if (0 == my_version.compare(0, my_version.length(), marker_string, 0, marker_string.length())) + { + sameVersion = true; + } + else + { + return false; + } + LL_DEBUGS("MarkerFile") << "Compare markers for '" << marker_name << "': " + << "\n mine '" << my_version << "'" + << "\n marker '" << marker_string << "'" + << "\n " << (sameVersion ? "same" : "different") << " version" + << LL_ENDL; + return true; + } + return false; +} + void LLAppViewer::processMarkerFiles() { //We've got 4 things to test for here @@ -3743,6 +3855,10 @@ void LLAppViewer::processMarkerFiles() // File exists... // first, read it to see if it was created by the same version (we need this later) marker_is_same_version = markerIsSameVersion(mMarkerFileName); + if (marker_is_same_version) + { + gLastAgentSessionId = getMarkerSessionId(mMarkerFileName); + } // now test to see if this file is locked by a running process (try to open for write) marker_log_stream << "Checking exec marker file for lock..."; @@ -3832,44 +3948,27 @@ void LLAppViewer::processMarkerFiles() } LLAPRFile::remove(logout_marker_file); } - // further refine based on whether or not a marker created during an llerr crash is found - std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME); - if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB)) - { - if (markerIsSameVersion(llerror_marker_file)) - { - if ( gLastExecEvent == LAST_EXEC_LOGOUT_FROZE ) - { - gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; - LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; - } - else - { - gLastExecEvent = LAST_EXEC_LLERROR_CRASH; - LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' crashed, setting LastExecEvent to LLERROR_CRASH" << LL_ENDL; - } - } - else - { - LL_INFOS("MarkerFile") << "LLError marker '"<< llerror_marker_file << "' found, but versions did not match" << LL_ENDL; - } - LLAPRFile::remove(llerror_marker_file); - } // and last refine based on whether or not a marker created during a non-llerr crash is found std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB)) { - if (markerIsSameVersion(error_marker_file)) + S32 marker_code = getMarkerErrorCode(error_marker_file); + if (marker_code >= 0) { if (gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) { gLastExecEvent = LAST_EXEC_LOGOUT_CRASH; LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to LOGOUT_CRASH" << LL_ENDL; } + else if (marker_code > 0 && marker_code < (S32)LAST_EXEC_COUNT) + { + gLastExecEvent = (eLastExecEvent)marker_code; + LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; + } else { gLastExecEvent = LAST_EXEC_OTHER_CRASH; - LL_INFOS("MarkerFile") << "Error marker '"<< error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; + LL_INFOS("MarkerFile") << "Error marker '" << error_marker_file << "' crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL; } } else @@ -5159,6 +5258,24 @@ void LLAppViewer::postToMainCoro(const LL::WorkQueue::Work& work) gMainloopWork.post(work); } +void LLAppViewer::createErrorMarker(eLastExecEvent error_code) const +{ + if (!mSecondInstance) + { + std::string error_marker = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME); + + LLAPRFile file; + file.open(error_marker, LL_APR_WB); + if (file.getFileHandle()) + { + recordMarkerVersion(file); + std::string data = "\n" + std::to_string((S32)error_code); + file.write(data.data(), static_cast(data.length())); + file.close(); + } + } +} + void LLAppViewer::outOfMemorySoftQuit() { if (!mQuitRequested) diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index 4ce4259ed87..b4756eecd68 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -66,6 +66,20 @@ class LLViewerRegion; extern LLTrace::BlockTimerStatHandle FTM_FRAME; +typedef enum +{ + LAST_EXEC_NORMAL = 0, + LAST_EXEC_FROZE, + LAST_EXEC_LLERROR_CRASH, + LAST_EXEC_OTHER_CRASH, + LAST_EXEC_LOGOUT_FROZE, + LAST_EXEC_LOGOUT_CRASH, + LAST_EXEC_BAD_ALLOC, + LAST_EXEC_MISSING_FILES, + LAST_EXEC_GRAPHICS_INIT, + LAST_EXEC_COUNT +} eLastExecEvent; + class LLAppViewer : public LLApp { public: @@ -147,6 +161,7 @@ class LLAppViewer : public LLApp void saveExperienceCache(); void removeMarkerFiles(); + void recordSessionToMarker(); void removeDumpDir(); // LLAppViewer testing helpers. @@ -227,6 +242,9 @@ class LLAppViewer : public LLApp // post given work to the "mainloop" work queue for handling on the main thread void postToMainCoro(const LL::WorkQueue::Work& work); + // Writes an error code into the error_marker file for use on next startup. + void createErrorMarker(eLastExecEvent error_code) const; + // Attempt a 'soft' quit with disconnect and saving of settings/cache. // Intended to be thread safe. // Good chance of viewer crashing either way, but better than alternatives. @@ -272,6 +290,9 @@ class LLAppViewer : public LLApp void processMarkerFiles(); static void recordMarkerVersion(LLAPRFile& marker_file); bool markerIsSameVersion(const std::string& marker_name) const; + LLUUID getMarkerSessionId(const std::string& marker_name) const; + S32 getMarkerErrorCode(const std::string& marker_name) const; + bool getMarkerData(const std::string& marker_name, std::string &data) const; void idle(); void idleShutdown(); @@ -347,18 +368,9 @@ class LLAppViewer : public LLApp extern LLSD gDebugInfo; extern bool gShowObjectUpdates; -typedef enum -{ - LAST_EXEC_NORMAL = 0, - LAST_EXEC_FROZE, - LAST_EXEC_LLERROR_CRASH, - LAST_EXEC_OTHER_CRASH, - LAST_EXEC_LOGOUT_FROZE, - LAST_EXEC_LOGOUT_CRASH -} eLastExecEvent; - extern eLastExecEvent gLastExecEvent; // llstartup extern S32 gLastExecDuration; ///< the duration of the previous run in seconds (<0 indicates unknown) +extern LLUUID gLastAgentSessionId; // will be set if agent logged in extern const char* gPlatform; diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp index 4cd85ac756e..50040556669 100644 --- a/indra/newview/llconversationmodel.cpp +++ b/indra/newview/llconversationmodel.cpp @@ -357,8 +357,9 @@ void LLConversationItemSession::clearParticipants() void LLConversationItemSession::clearAndDeparentModels() { - for (LLFolderViewModelItem* child : mChildren) + for (child_list_t::iterator it = mChildren.begin(); it != mChildren.end();) { + LLFolderViewModelItem* child = *it; if (child->getNumRefs() == 0) { // LLConversationItemParticipant can be created but not assigned to any view, @@ -370,8 +371,8 @@ void LLConversationItemSession::clearAndDeparentModels() // Model is still assigned to some view/widget child->setParent(NULL); } + it = mChildren.erase(it); } - mChildren.clear(); } LLConversationItemParticipant* LLConversationItemSession::findParticipant(const LLUUID& participant_id) diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 7bd5206453e..e60b3eb5dc5 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -42,6 +42,7 @@ #include "lldrawpooltree.h" #include "lldrawpoolterrain.h" #include "lldrawpoolwater.h" +#include "lldrawpoolwaterexclusion.h" #include "llface.h" #include "llviewerobjectlist.h" // For debug listing. #include "pipeline.h" @@ -119,6 +120,9 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerTexture *tex0) case POOL_GLTF_PBR_ALPHA_MASK: poolp = new LLDrawPoolGLTFPBR(LLDrawPool::POOL_GLTF_PBR_ALPHA_MASK); break; + case POOL_WATEREXCLUSION: + poolp = new LLDrawPoolWaterExclusion(); + break; default: LL_ERRS() << "Unknown draw pool type!" << LL_ENDL; return NULL; diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index bc412214c7f..1c8864a9df3 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -55,6 +55,7 @@ class LLDrawPool // based on fill rate and likelihood to occlude future passes (faster, large occluders first). // POOL_SKY = 1, + POOL_WATEREXCLUSION, POOL_WL_SKY, POOL_SIMPLE, POOL_FULLBRIGHT, @@ -140,7 +141,7 @@ class LLRenderPass : public LLDrawPool PASS_GRASS, PASS_FULLBRIGHT, PASS_FULLBRIGHT_RIGGED, - PASS_INVISIBLE, + PASS_INVISIBLE, // Formerly, invisiprims. Now, water exclusion surfaces. PASS_INVISIBLE_RIGGED, PASS_INVISI_SHINY, PASS_INVISI_SHINY_RIGGED, diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 53d6e528b6d..32de0e5ee78 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -176,173 +176,156 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass) light_diffuse *= (1.5f + (6.f * ground_proj_sq)); } - // set up normal maps filtering - for (auto norm_map : mWaterNormp) - { - if (norm_map) norm_map->setFilteringOption(has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT); - } + LLTexUnit::eTextureFilterOptions filter_mode = has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT; LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor()); F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f; LLGLSLShader *shader = nullptr; - // two passes, first with standard water shader bound, second with edge water shader bound - for (int edge = 0; edge < 2; edge++) + // One pass, one of two shaders. Void water and region water share state. + // There isn't a good reason anymore to really have void water run in a separate pass. + // It also just introduced a bunch of weird state consistency stuff that we really don't need. + // Not to mention, re-binding the the same shader and state for that shader is kind of wasteful. + // - Geenz 2025-02-11 + // select shader + if (underwater) { - // select shader - if (underwater) - { - shader = &gUnderWaterProgram; - } - else - { - if (edge) - { - shader = &gWaterEdgeProgram; - } - else - { - shader = &gWaterProgram; - } - } + shader = &gUnderWaterProgram; + } + else + { + shader = &gWaterProgram; + } - gPipeline.bindDeferredShader(*shader, nullptr, &gPipeline.mWaterDis); + gPipeline.bindDeferredShader(*shader, nullptr, &gPipeline.mWaterDis); - //bind normal map - S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); - S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2); + LLViewerTexture* tex_a = mWaterNormp[0]; + LLViewerTexture* tex_b = mWaterNormp[1]; - LLViewerTexture* tex_a = mWaterNormp[0]; - LLViewerTexture* tex_b = mWaterNormp[1]; + F32 blend_factor = (F32)pwater->getBlendFactor(); - F32 blend_factor = (F32)pwater->getBlendFactor(); + if (tex_a && (!tex_b || (tex_a == tex_b))) + { + shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a); + tex_a->setFilteringOption(filter_mode); + blend_factor = 0; // only one tex provided, no blending + } + else if (tex_b && !tex_a) + { + shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_b); + tex_a->setFilteringOption(filter_mode); + blend_factor = 0; // only one tex provided, no blending + } + else if (tex_b != tex_a) + { + shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a); + tex_a->setFilteringOption(filter_mode); + shader->bindTexture(LLViewerShaderMgr::BUMP_MAP2, tex_b); + tex_b->setFilteringOption(filter_mode); + } - gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); + shader->bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &gPipeline.mWaterExclusionMask); - if (tex_a && (!tex_b || (tex_a == tex_b))) - { - gGL.getTexUnit(bumpTex)->bind(tex_a); - blend_factor = 0; // only one tex provided, no blending - } - else if (tex_b && !tex_a) - { - gGL.getTexUnit(bumpTex)->bind(tex_b); - blend_factor = 0; // only one tex provided, no blending - } - else if (tex_b != tex_a) - { - gGL.getTexUnit(bumpTex)->bind(tex_a); - gGL.getTexUnit(bumpTex2)->bind(tex_b); - } + shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); - // bind reflection texture from RenderTarget - S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX); + F32 fog_density = pwater->getModifiedWaterFogDensity(underwater); - F32 screenRes[] = { 1.f / gGLViewport[2], 1.f / gGLViewport[3] }; + shader->bindTexture(LLShaderMgr::WATER_SCREENTEX, &gPipeline.mWaterDis); - shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes); - shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor); + if (mShaderLevel == 1) + { + fog_color.mV[VALPHA] = (F32)(log(fog_density) / log(2)); + } - F32 fog_density = pwater->getModifiedWaterFogDensity(underwater); + F32 water_height = environment.getWaterHeight(); + F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2]; + shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height); + shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time); + shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); - if (screentex > -1) - { - shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density); - gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis); - } + shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); - if (mShaderLevel == 1) - { - fog_color.mV[VALPHA] = (F32)(log(fog_density) / log(2)); - } + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV); + shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV); - F32 water_height = environment.getWaterHeight(); - F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2]; - shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height); - shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time); - shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); + shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); - shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV); - shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV); - shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR_LINEAR, 1, fog_color_linear.mV); + shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale()); + shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset()); + shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, fmaxf(0, pwater->getBlurMultiplier()) * 2); - shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); - shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp); + static LLStaticHashedString s_exposure("exposure"); + static LLStaticHashedString tonemap_mix("tonemap_mix"); + static LLStaticHashedString tonemap_type("tonemap_type"); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV); - shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV); + static LLCachedControl exposure(gSavedSettings, "RenderExposure", 1.f); - shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); + F32 e = llclamp(exposure(), 0.5f, 4.f); - shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale()); - shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset()); - shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier()); + static LLCachedControl should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", false); - F32 sunAngle = llmax(0.f, light_dir.mV[1]); - F32 scaledAngle = 1.f - sunAngle; + shader->uniform1f(s_exposure, e); + static LLCachedControl tonemap_type_setting(gSavedSettings, "RenderTonemapType", 0U); + shader->uniform1i(tonemap_type, tonemap_type_setting); + shader->uniform1f(tonemap_mix, psky->getTonemapMix(should_auto_adjust())); - shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0); - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); - shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); - shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f * sunAngle); - shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0); + F32 sunAngle = llmax(0.f, light_dir.mV[1]); + F32 scaledAngle = 1.f - sunAngle; - // SL-15861 This was changed from getRotatedLightNorm() as it was causing - // lightnorm in shaders\class1\windlight\atmosphericsFuncs.glsl in have inconsistent additive lighting for 180 degrees of the FOV. - LLVector4 rotated_light_direction = LLEnvironment::instance().getClampedLightNorm(); - shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV); + shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0); - shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); + // SL-15861 This was changed from getRotatedLightNorm() as it was causing + // lightnorm in shaders\class1\windlight\atmosphericsFuncs.glsl in have inconsistent additive lighting for 180 degrees of the FOV. + LLVector4 rotated_light_direction = LLEnvironment::instance().getClampedLightNorm(); + shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV); - if (LLViewerCamera::getInstance()->cameraUnderWater()) - { - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); - } - else - { - shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); - } + shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV); - LLGLDisable cullface(GL_CULL_FACE); + if (LLViewerCamera::getInstance()->cameraUnderWater()) + { + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow()); + } + else + { + shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove()); + } - LLVOWater* water = nullptr; - for (LLFace* const& face : mDrawFace) - { - if (!face) continue; - water = static_cast(face->getViewerObject()); - if (!water) continue; - - if ((bool)edge == (bool)water->getIsEdgePatch()) - { - face->renderIndexed(); - - // Note non-void water being drawn, updates required - if (!edge) // SL-16461 remove !LLPipeline::sUseOcclusion check - { - sNeedsReflectionUpdate = true; - sNeedsDistortionUpdate = true; - } - } - } + LLGLDisable cullface(GL_CULL_FACE); - shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); - shader->disableTexture(LLShaderMgr::WATER_SCREENTEX); - shader->disableTexture(LLShaderMgr::BUMP_MAP); - shader->disableTexture(LLShaderMgr::WATER_REFTEX); + // Only push the water planes once. + // Previously we did this twice: once for void water and one for region water. + // However, the void water and region water shaders are the same exact shader. + // They also had the same exact state with the sole exception setting an edge water flag. + // That flag was not actually used anywhere in the shaders. + // - Geenz 2025-02-11 + pushWaterPlanes(0); - // clean up - gPipeline.unbindDeferredShader(*shader); + // clean up + gPipeline.unbindDeferredShader(*shader); - gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE); - } + gGL.setColorMask(true, false); +} - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); +void LLDrawPoolWater::pushWaterPlanes(int pass) +{ + LLVOWater* water = nullptr; + for (LLFace* const& face : mDrawFace) + { + water = static_cast(face->getViewerObject()); - gGL.setColorMask(true, false); + face->renderIndexed(); + + // Note non-void water being drawn, updates required + // Previously we had some logic to determine if this pass was also our water edge pass. + // Now we only have one pass. Check if we're doing a region water plane or void water plane. + // - Geenz 2025-02-11 + if (!water->getIsEdgePatch()) + { + sNeedsReflectionUpdate = true; + sNeedsDistortionUpdate = true; + } + } } LLViewerTexture *LLDrawPoolWater::getDebugTexture() diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h index f64477a059a..7fc9b68bcf3 100644 --- a/indra/newview/lldrawpoolwater.h +++ b/indra/newview/lldrawpoolwater.h @@ -74,6 +74,8 @@ class LLDrawPoolWater final: public LLFacePool void setOpaqueTexture(const LLUUID& opaqueTextureId); void setNormalMaps(const LLUUID& normalMapId, const LLUUID& nextNormalMapId); + void pushWaterPlanes(int pass); + protected: void renderOpaqueLegacyWater(); }; diff --git a/indra/newview/lldrawpoolwaterexclusion.cpp b/indra/newview/lldrawpoolwaterexclusion.cpp new file mode 100644 index 00000000000..d796bf39bf9 --- /dev/null +++ b/indra/newview/lldrawpoolwaterexclusion.cpp @@ -0,0 +1,79 @@ +/** + * @file lldrawpool.cpp + * @brief LLDrawPoolMaterials class implementation + * @author Jonathan "Geenz" Goodman + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "lldrawpoolwaterexclusion.h" +#include "llviewershadermgr.h" +#include "pipeline.h" +#include "llglcommonfunc.h" +#include "llvoavatar.h" +#include "lldrawpoolwater.h" + +LLDrawPoolWaterExclusion::LLDrawPoolWaterExclusion() : LLRenderPass(LLDrawPool::POOL_WATEREXCLUSION) +{ + LL_INFOS("DPInvisible") << "Creating water exclusion draw pool" << LL_ENDL; +} + + +void LLDrawPoolWaterExclusion::render(S32 pass) +{ // render invisiprims + LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; // LL_RECORD_BLOCK_TIME(FTM_RENDER_INVISIBLE); + + if (gPipeline.shadersLoaded()) + { + gDrawColorProgram.bind(); + } + + + LLGLDepthTest depth(GL_TRUE); + gDrawColorProgram.uniform4f(LLShaderMgr::DIFFUSE_COLOR, 1, 1, 1, 1); + + LLDrawPoolWater* pwaterpool = (LLDrawPoolWater*)gPipeline.getPool(LLDrawPool::POOL_WATER); + if (pwaterpool) + { + // Just treat our water planes as double sided for the purposes of generating the exclusion mask. + LLGLDisable cullface(GL_CULL_FACE); + pwaterpool->pushWaterPlanes(0); + + // Take care of the edge water tiles. + pwaterpool->pushWaterPlanes(1); + } + + gDrawColorProgram.uniform4f(LLShaderMgr::DIFFUSE_COLOR, 0, 0, 0, 1); + + static LLStaticHashedString waterSign("waterSign"); + gDrawColorProgram.uniform1f(waterSign, 1.f); + + pushBatches(LLRenderPass::PASS_INVISIBLE, false, false); + + + if (gPipeline.shadersLoaded()) + { + gDrawColorProgram.unbind(); + } +} diff --git a/indra/newview/lldrawpoolwaterexclusion.h b/indra/newview/lldrawpoolwaterexclusion.h new file mode 100644 index 00000000000..e95721a443a --- /dev/null +++ b/indra/newview/lldrawpoolwaterexclusion.h @@ -0,0 +1,61 @@ +/** + * @file lldrawpoolwaterexclusion.h + * @brief LLDrawPoolWaterExclusion class definition + * @author Jonathan "Geenz" Goodman + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLDRAWPOOLWATEREXCLUSION_H +#define LL_LLDRAWPOOLWATEREXCLUSION_H + +#include "v4coloru.h" +#include "v2math.h" +#include "v3math.h" +#include "llvertexbuffer.h" +#include "lldrawpool.h" + +class LLViewerTexture; +class LLDrawInfo; +class LLGLSLShader; + +class LLDrawPoolWaterExclusion : public LLRenderPass +{ +public: + LLDrawPoolWaterExclusion(); + + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX + }; + + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + virtual void prerender() {} + + virtual void render(S32 pass = 0); + virtual void beginRenderPass(S32 pass) {} + virtual void endRenderPass(S32 pass) {} + virtual S32 getNumPasses() { return 1; } +}; + +#endif // LL_LLDRAWPOOLWATEREXCLUSION_H diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 3ccb3633219..811aacb2ed2 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -893,7 +893,7 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, const LLVector4a& po //VECTORIZE THIS // see if we have a non-default mapping - U8 texgen = getTextureEntry()->getTexGen(); + U8 texgen = tep->getTexGen(); if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) { LLVector4a& center = *(mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter); @@ -983,8 +983,17 @@ bool LLFace::calcAlignedPlanarTE(const LLFace* align_to, LLVector2* res_st_offs return false; } const LLTextureEntry *orig_tep = align_to->getTextureEntry(); + if (!orig_tep) + { + return false; + } + const LLTextureEntry* tep = getTextureEntry(); + if (!tep) + { + return false; + } if ((orig_tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR) || - (getTextureEntry()->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR)) + (tep->getTexGen() != LLTextureEntry::TEX_GEN_PLANAR)) { return false; } @@ -1563,7 +1572,8 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); } - U8 texgen = getTextureEntry()->getTexGen(); + const LLTextureEntry* tep = getTextureEntry(); + U8 texgen = tep ? tep->getTexGen() : LLTextureEntry::TEX_GEN_DEFAULT; if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) { //planar texgen needs binormals mVObjp->getVolume()->genTangents(face_index); @@ -2051,7 +2061,12 @@ bool LLFace::getGeometryVolume(const LLVolume& volume, LLStrider emissive; mVertexBuffer->getEmissiveStrider(emissive, mGeomIndex, mGeomCount); - U8 glow = (U8) llclamp((S32) (getTextureEntry()->getGlow()*255), 0, 255); + const LLTextureEntry* tep = getTextureEntry(); + U8 glow = 0; + if (tep) + { + glow = (U8)llclamp((S32)(tep->getGlow() * 255), 0, 255); + } LLVector4a src; diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index af38d696bc7..655674357ff 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -633,7 +633,8 @@ void LLFloaterIMSessionTab::appendMessage(const LLChat& chat, const LLSD& args) chat_args["show_names_for_p2p_conv"] = !mIsP2PChat || gSavedSettings.getBOOL("IMShowNamesForP2PConv"); - mChatHistory->appendMessage(chat, chat_args); + static const LLStyle::Params input_append_params = LLStyle::Params(); + mChatHistory->appendMessage(chat, chat_args, input_append_params); } void LLFloaterIMSessionTab::updateUsedEmojis(LLWStringView text) diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index fb4537f22a7..68b9e758a1c 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -60,6 +60,10 @@ LLPanelSnapshot* LLFloaterSnapshot::Impl::getActivePanel(LLFloaterSnapshotBase* { LLSideTrayPanelContainer* panel_container = floater->getChild("panel_container"); LLPanelSnapshot* active_panel = dynamic_cast(panel_container->getCurrentPanel()); + if (!active_panel) + { + LL_WARNS() << "No snapshot active panel, current panel index: " << panel_container->getCurrentPanelIndex() << LL_ENDL; + } if (!ok_if_not_found) { llassert_always(active_panel != NULL); @@ -643,20 +647,18 @@ void LLFloaterSnapshotBase::ImplBase::setWorking(bool working) working_lbl->setVisible(working); mFloater->getChild("working_indicator")->setVisible(working); - if (working) - { - const std::string panel_name = getActivePanel(mFloater, false)->getName(); - const std::string prefix = panel_name.substr(getSnapshotPanelPrefix().size()); - std::string progress_text = mFloater->getString(prefix + "_" + "progress_str"); - working_lbl->setValue(progress_text); - } - // All controls should be disabled while posting. mFloater->setCtrlsEnabled(!working); - LLPanelSnapshot* active_panel = getActivePanel(mFloater); - if (active_panel) + if (LLPanelSnapshot* active_panel = getActivePanel(mFloater)) { active_panel->enableControls(!working); + if (working) + { + const std::string panel_name = active_panel->getName(); + const std::string prefix = panel_name.substr(getSnapshotPanelPrefix().size()); + std::string progress_text = mFloater->getString(prefix + "_" + "progress_str"); + working_lbl->setValue(progress_text); + } } } diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 112008172e3..5484ce6276b 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -903,6 +903,39 @@ class ShaderBinder }; +F32 shader_timer_benchmark(std::vector & dest, TextureHolder & texHolder, U32 textures_count, LLVertexBuffer * buff, F32 &seconds) +{ + // run GPU timer benchmark + + //number of samples to take + const S32 samples = 64; + + { + ShaderProfileHelper initProfile; + dest[0].bindTarget(); + gBenchmarkProgram.bind(); + for (S32 c = 0; c < samples; ++c) + { + for (U32 i = 0; i < textures_count; ++i) + { + texHolder.bind(i); + buff->setBuffer(); + buff->drawArrays(LLRender::TRIANGLES, 0, 3); + } + } + gBenchmarkProgram.unbind(); + dest[0].flush(); + } + + F32 ms = gBenchmarkProgram.mTimeElapsed / 1000000.f; + seconds = ms / 1000.f; + + F64 samples_drawn = (F64)gBenchmarkProgram.mSamplesDrawn; + F64 gpixels_drawn = samples_drawn / 1000000000.0; + F32 samples_sec = (F32)(gpixels_drawn / seconds); + return samples_sec * 4; // 4 bytes per sample +} + //----------------------------------------------------------------------------- // gpu_benchmark() // returns measured memory bandwidth of GPU in gigabytes per second @@ -944,9 +977,6 @@ F32 gpu_benchmark() //number of textures const U32 count = 32; - //number of samples to take - const S32 samples = 64; - //time limit, allocation operations shouldn't take longer then 30 seconds, same for actual benchmark. const F32 time_limit = 30; @@ -1036,33 +1066,15 @@ F32 gpu_benchmark() LLGLSLShader::unbind(); - // run GPU timer benchmark - { - ShaderProfileHelper initProfile; - dest[0].bindTarget(); - gBenchmarkProgram.bind(); - for (S32 c = 0; c < samples; ++c) - { - for (U32 i = 0; i < count; ++i) - { - texHolder.bind(i); - buff->setBuffer(); - buff->drawArrays(LLRender::TRIANGLES, 0, 3); - } - } - gBenchmarkProgram.unbind(); - dest[0].flush(); - } + // run GPU timer benchmark twice + F32 seconds = 0; + F32 gbps = shader_timer_benchmark(dest, texHolder, count, buff.get(), seconds); - F32 ms = gBenchmarkProgram.mTimeElapsed/1000000.f; - F32 seconds = ms/1000.f; + LL_INFOS("Benchmark") << "Memory bandwidth, 1st run is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL; - F64 samples_drawn = (F64)gBenchmarkProgram.mSamplesDrawn; - F64 gpixels_drawn = samples_drawn / 1000000000.0; - F32 samples_sec = (F32)(gpixels_drawn/seconds); - F32 gbps = samples_sec*4; // 4 bytes per sample + gbps = shader_timer_benchmark(dest, texHolder, count, buff.get(), seconds); - LL_INFOS("Benchmark") << "Memory bandwidth is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL; + LL_INFOS("Benchmark") << "Memory bandwidth, final run is " << llformat("%.3f", gbps) << " GB/sec according to ARB_timer_query, total time " << seconds << " seconds" << LL_ENDL; return gbps; } diff --git a/indra/newview/llgltfmaterialpreviewmgr.cpp b/indra/newview/llgltfmaterialpreviewmgr.cpp index cf6b08797d3..da1f1a466f7 100644 --- a/indra/newview/llgltfmaterialpreviewmgr.cpp +++ b/indra/newview/llgltfmaterialpreviewmgr.cpp @@ -472,9 +472,9 @@ bool LLGLTFPreviewTexture::render() gPipeline.setupHWLights(); glm::mat4 mat = get_current_modelview(); - glm::vec4 transformed_light_dir = glm::make_vec4(light_dir.mV); + glm::vec4 transformed_light_dir(light_dir); transformed_light_dir = mat * transformed_light_dir; - SetTemporarily force_sun_direction_high_graphics(&gPipeline.mTransformedSunDir, LLVector4(glm::value_ptr(transformed_light_dir))); + SetTemporarily force_sun_direction_high_graphics(&gPipeline.mTransformedSunDir, LLVector4(transformed_light_dir)); // Override lights to ensure the sun is always shining from a certain direction (low graphics) // See also force_sun_direction_high_graphics and fixup_shader_constants { diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp index ce419498cf5..e754de2fd14 100644 --- a/indra/newview/llheroprobemanager.cpp +++ b/indra/newview/llheroprobemanager.cpp @@ -89,9 +89,11 @@ void LLHeroProbeManager::update() initReflectionMaps(); + static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); + if (!mRenderTarget.isComplete()) { - U32 color_fmt = GL_RGBA16F; + U32 color_fmt = render_hdr ? GL_RGBA16F : GL_RGBA8; mRenderTarget.allocate(mProbeResolution, mProbeResolution, color_fmt, true); } @@ -103,7 +105,7 @@ void LLHeroProbeManager::update() mMipChain.resize(count); for (U32 i = 0; i < count; ++i) { - mMipChain[i].allocate(res, res, GL_RGBA16F); + mMipChain[i].allocate(res, res, render_hdr ? GL_RGBA16F : GL_RGBA8); res /= 2; } } @@ -220,7 +222,7 @@ void LLHeroProbeManager::renderProbes() static LLCachedControl sUpdateRate(gSavedSettings, "RenderHeroProbeUpdateRate", 0); F32 near_clip = 0.01f; - if (mNearestHero != nullptr && + if (mNearestHero != nullptr && !mNearestHero->isDead() && !gTeleportDisplay && !gDisconnected && !LLAppViewer::instance()->logoutRequestSent()) { LL_PROFILE_ZONE_NAMED_CATEGORY_DISPLAY("hpmu - realtime"); @@ -249,12 +251,13 @@ void LLHeroProbeManager::renderProbes() LL_PROFILE_ZONE_NUM(gFrameCount % rate); LL_PROFILE_ZONE_NUM(rate); + bool dynamic = mNearestHero->getReflectionProbeIsDynamic() && sDetail() > 0; for (U32 i = 0; i < 6; ++i) { if ((gFrameCount % rate) == (i % rate)) { // update 6/rate faces per frame LL_PROFILE_ZONE_NUM(i); - updateProbeFace(mProbes[0], i, mNearestHero->getReflectionProbeIsDynamic() && sDetail > 0, near_clip); + updateProbeFace(mProbes[0], i, dynamic, near_clip); } } generateRadiance(mProbes[0]); @@ -537,8 +540,10 @@ void LLHeroProbeManager::initReflectionMaps() mTexture = new LLCubeMapArray(); + static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); + // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) - mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2); + mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr); if (mDefaultProbe.isNull()) { diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 135fba7897c..6850e57b943 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -106,7 +106,7 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); glm::ivec4 viewport(world_view_rect.mLeft, world_view_rect.mBottom, world_view_rect.getWidth(), world_view_rect.getHeight()); - glm::vec3 win_coord = glm::project(glm::make_vec3(render_pos.mV), get_current_modelview(), get_current_projection(), viewport); + glm::vec3 win_coord = glm::project(glm::vec3(render_pos), get_current_modelview(), get_current_projection(), viewport); //fonts all render orthographically, set up projection`` gGL.matrixMode(LLRender::MM_PROJECTION); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 2e8b1b94fed..e7584018a88 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -4231,14 +4231,9 @@ void LLFolderBridge::staticFolderOptionsMenu() bool LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type) { - LLInventoryModel::cat_array_t cat_array; - LLInventoryModel::item_array_t item_array; - model->collectDescendentsIf(mUUID, - cat_array, - item_array, + return model->hasMatchingDescendents(mUUID, LLInventoryModel::EXCLUDE_TRASH, is_type); - return !item_array.empty(); } void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items, menuentry_vec_t& disabled_items) @@ -4415,21 +4410,26 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items //Added by aura to force inventory pull on right-click to display folder options correctly. 07-17-06 mCallingCards = mWearables = false; - LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); - if (checkFolderForContentsOfType(model, is_callingcard)) + if (gInventory.getRootFolderID() != mUUID) { - mCallingCards=true; - } + LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD); + if (checkFolderForContentsOfType(model, is_callingcard)) + { + mCallingCards = true; + } - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); + const std::vector types = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART, LLAssetType::AT_OBJECT, LLAssetType::AT_GESTURE }; + LLIsOneOfTypes is_wearable(types); - if (checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) + if (checkFolderForContentsOfType(model, is_wearable)) + { + mWearables = true; + } + } + else { - mWearables=true; + // Assume that there are wearables in the root folder + mWearables = true; } } else @@ -4442,13 +4442,10 @@ void LLFolderBridge::buildContextMenuOptions(U32 flags, menuentry_vec_t& items LLFolderType::EType type = category->getPreferredType(); const bool is_system_folder = LLFolderType::lookupIsProtectedType(type); - LLFindWearables is_wearable; - LLIsType is_object(LLAssetType::AT_OBJECT); - LLIsType is_gesture(LLAssetType::AT_GESTURE); + const std::vector types = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART, LLAssetType::AT_OBJECT, LLAssetType::AT_GESTURE }; + LLIsOneOfTypes is_wearable(types); - if (checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture)) + if (checkFolderForContentsOfType(model, is_wearable)) { mWearables = true; } @@ -4571,14 +4568,11 @@ void LLFolderBridge::buildContextMenuFolderOptions(U32 flags, menuentry_vec_t& // wearables related functionality for folders. //is_wearable - LLFindWearables is_wearable; - LLIsType is_object( LLAssetType::AT_OBJECT ); - LLIsType is_gesture( LLAssetType::AT_GESTURE ); + const std::vector types = { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART, LLAssetType::AT_OBJECT, LLAssetType::AT_GESTURE }; + LLIsOneOfTypes is_wearable(types); if (mWearables || - checkFolderForContentsOfType(model, is_wearable) || - checkFolderForContentsOfType(model, is_object) || - checkFolderForContentsOfType(model, is_gesture) ) + checkFolderForContentsOfType(model, is_wearable)) { // Only enable add/replace outfit for non-system folders. if (!is_system_folder) diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index dadd0590a90..1ccefa32123 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -2634,6 +2634,22 @@ bool LLIsType::operator()(LLInventoryCategory* cat, LLInventoryItem* item) return false; } +bool LLIsOneOfTypes::operator()(LLInventoryCategory* cat, LLInventoryItem* item) +{ + for (LLAssetType::EType &type : mTypes) + { + if (type == LLAssetType::AT_CATEGORY) + { + if (cat) return true; + } + if (item) + { + if (item->getType() == type) return true; + } + } + return false; +} + bool LLIsNotType::operator()(LLInventoryCategory* cat, LLInventoryItem* item) { if(mType == LLAssetType::AT_CATEGORY) diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h index a25c0d5ad66..13a64f21dc7 100644 --- a/indra/newview/llinventoryfunctions.h +++ b/indra/newview/llinventoryfunctions.h @@ -245,6 +245,24 @@ class LLIsType : public LLInventoryCollectFunctor LLAssetType::EType mType; }; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Class LLIsOneOfTypes +// +// Implementation of a LLInventoryCollectFunctor which returns true if +// the type is one of the types passed in during construction. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LLIsOneOfTypes : public LLInventoryCollectFunctor +{ +public: + LLIsOneOfTypes(const std::vector &types) : mTypes(types) {} + virtual ~LLIsOneOfTypes() {} + virtual bool operator()(LLInventoryCategory* cat, + LLInventoryItem* item); +protected: + std::vector mTypes; +}; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Class LLIsNotType // diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index d57cb13362f..9fffe6378e8 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1305,6 +1305,47 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id, } } +bool LLInventoryModel::hasMatchingDescendents(const LLUUID& id, + bool include_trash, + LLInventoryCollectFunctor& matches) +{ + if (!include_trash) + { + const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH); + if (trash_id.notNull() && (trash_id == id)) + return false; + } + cat_array_t* cat_array = get_ptr_in_map(mParentChildCategoryTree, id); + if (cat_array) + { + for (auto& cat : *cat_array) + { + if (matches(cat, NULL)) + { + return true; + } + if (hasMatchingDescendents(cat->getUUID(), include_trash, matches)) + { + return true; + } + } + } + + item_array_t* item_array = get_ptr_in_map(mParentChildItemTree, id); + + if (item_array) + { + for (auto& item : *item_array) + { + if (matches(NULL, item)) + { + return true; + } + } + } + return false; +} + void LLInventoryModel::addChangedMaskForLinks(const LLUUID& object_id, U32 mask) { const LLInventoryObject *obj = getObject(object_id); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 1472b705e46..d28743357e2 100644 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -287,6 +287,9 @@ class LLInventoryModel item_array_t& items, bool include_trash, LLInventoryCollectFunctor& add); + bool hasMatchingDescendents(const LLUUID& id, + bool include_trash, + LLInventoryCollectFunctor& add); // Collect all items in inventory that are linked to item_id. // Assumes item_id is itself not a linked item. diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index e4d10102312..5a067ba4542 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -579,7 +579,7 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve { if (model_item && view_item && viewmodel_item) { - const LLUUID& idp = viewmodel_item->getUUID(); + const LLUUID idp = viewmodel_item->getUUID(); view_item->destroyView(); removeItemID(idp); } @@ -1334,6 +1334,8 @@ void LLInventoryPanel::openStartFolderOrMyInventory() LLFolderViewFolder *fchild = dynamic_cast(child); if (fchild && fchild->getViewModelItem() + // Is this right? Name might be localized, + // use FT_ROOT_INVENTORY or gInventory.getRootFolderID()? && fchild->getViewModelItem()->getName() == "My Inventory") { fchild->setOpen(true); diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp index ad04c11cc69..cbc3744aa3f 100644 --- a/indra/newview/lllogininstance.cpp +++ b/indra/newview/lllogininstance.cpp @@ -212,6 +212,7 @@ void LLLoginInstance::constructAuthParams(LLPointer user_credentia request_params["read_critical"] = false; // handleTOSResponse request_params["last_exec_event"] = mLastExecEvent; request_params["last_exec_duration"] = mLastExecDuration; + request_params["last_exec_session_id"] = mLastAgentSessionId.asString(); request_params["mac"] = (char*)hashed_unique_id_string; request_params["version"] = LLVersionInfo::instance().getVersion(); request_params["channel"] = LLVersionInfo::instance().getChannel(); diff --git a/indra/newview/lllogininstance.h b/indra/newview/lllogininstance.h index 624408d46d7..748909c069f 100644 --- a/indra/newview/lllogininstance.h +++ b/indra/newview/lllogininstance.h @@ -64,6 +64,7 @@ class LLLoginInstance : public LLSingleton void setSerialNumber(const std::string& sn) { mSerialNumber = sn; } void setLastExecEvent(int lee) { mLastExecEvent = lee; } void setLastExecDuration(S32 duration) { mLastExecDuration = duration; } + void setLastAgentSessionId(const LLUUID& id) { mLastAgentSessionId = id; } void setPlatformInfo(const std::string platform, const std::string platform_version, const std::string platform_name); void setNotificationsInterface(LLNotificationsInterface* ni) { mNotifications = ni; } @@ -101,6 +102,7 @@ class LLLoginInstance : public LLSingleton std::string mSerialNumber; int mLastExecEvent; S32 mLastExecDuration; + LLUUID mLastAgentSessionId; std::string mPlatform; std::string mPlatformVersion; std::string mPlatformVersionName; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index a5bed1dbe63..93453f507c0 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -548,8 +548,8 @@ LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMate return ppTex ? (*ppTex).get() : NULL; } -volatile S32 LLMeshRepoThread::sActiveHeaderRequests = 0; -volatile S32 LLMeshRepoThread::sActiveLODRequests = 0; +std::atomic LLMeshRepoThread::sActiveHeaderRequests = 0; +std::atomic LLMeshRepoThread::sActiveLODRequests = 0; U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; S32 LLMeshRepoThread::sRequestLowWater = REQUEST2_LOW_WATER_MIN; S32 LLMeshRepoThread::sRequestHighWater = REQUEST2_HIGH_WATER_MIN; @@ -3916,7 +3916,7 @@ void LLMeshRepository::notifyLoadedMeshes() } // erase from background thread - mThread->mWorkQueue.post([=]() + mThread->mWorkQueue.post([=, this]() { mThread->mSkinMap.erase(id); }); diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index b5c2424578e..3d25a4dd789 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -256,8 +256,8 @@ class LLMeshRepoThread : public LLThread { public: - volatile static S32 sActiveHeaderRequests; - volatile static S32 sActiveLODRequests; + static std::atomic sActiveHeaderRequests; + static std::atomic sActiveLODRequests; static U32 sMaxConcurrentRequests; static S32 sRequestLowWater; static S32 sRequestHighWater; diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index dbf56c2b6d7..7910bcb41db 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -139,32 +139,60 @@ void LLPanelContents::getState(LLViewerObject *objectp ) void LLPanelContents::onFilterEdit() { const std::string& filter_substring = mFilterEditor->getText(); - if (filter_substring.empty()) + if (!mPanelInventoryObject->hasInventory()) { - if (mPanelInventoryObject->getFilter().getFilterSubString().empty()) - { - // The current filter and the new filter are empty, nothing to do - return; - } - - mSavedFolderState.setApply(true); - mPanelInventoryObject->getRootFolder()->applyFunctorRecursively(mSavedFolderState); - - // Add a folder with the current item to the list of previously opened folders - LLOpenFoldersWithSelection opener; - mPanelInventoryObject->getRootFolder()->applyFunctorRecursively(opener); - mPanelInventoryObject->getRootFolder()->scrollToShowSelection(); + mDirtyFilter = true; } - else if (mPanelInventoryObject->getFilter().getFilterSubString().empty()) + else { - // The first letter in search term, save existing folder open state - if (!mPanelInventoryObject->getFilter().isNotDefault()) + LLFolderView* root_folder = mPanelInventoryObject->getRootFolder(); + if (filter_substring.empty()) { - mSavedFolderState.setApply(false); - mPanelInventoryObject->getRootFolder()->applyFunctorRecursively(mSavedFolderState); + if (mPanelInventoryObject->getFilter().getFilterSubString().empty()) + { + // The current filter and the new filter are empty, nothing to do + return; + } + + if (mDirtyFilter && !mSavedFolderState.hasOpenFolders()) + { + if (root_folder) + { + root_folder->setOpenArrangeRecursively(true, LLFolderViewFolder::ERecurseType::RECURSE_DOWN); + } + } + else + { + mSavedFolderState.setApply(true); + if (root_folder) + { + root_folder->applyFunctorRecursively(mSavedFolderState); + } + } + mDirtyFilter = false; + + // Add a folder with the current item to the list of previously opened folders + if (root_folder) + { + LLOpenFoldersWithSelection opener; + root_folder->applyFunctorRecursively(opener); + root_folder->scrollToShowSelection(); + } + } + else if (mPanelInventoryObject->getFilter().getFilterSubString().empty()) + { + // The first letter in search term, save existing folder open state + if (!mPanelInventoryObject->getFilter().isNotDefault()) + { + mSavedFolderState.setApply(false); + if (root_folder) + { + root_folder->applyFunctorRecursively(mSavedFolderState); + } + mDirtyFilter = false; + } } } - mPanelInventoryObject->getFilter().setFilterSubString(filter_substring); } diff --git a/indra/newview/llpanelcontents.h b/indra/newview/llpanelcontents.h index bb6308e8b84..6e02b17bab6 100644 --- a/indra/newview/llpanelcontents.h +++ b/indra/newview/llpanelcontents.h @@ -70,6 +70,8 @@ class LLPanelContents : public LLPanel void getState(LLViewerObject *object); void onFilterEdit(); + bool mDirtyFilter { false }; + public: class LLFilterEditor* mFilterEditor; LLSaveFolderState mSavedFolderState; diff --git a/indra/newview/llpanelemojicomplete.cpp b/indra/newview/llpanelemojicomplete.cpp index cb89a5910e3..fc1bf6ca93b 100644 --- a/indra/newview/llpanelemojicomplete.cpp +++ b/indra/newview/llpanelemojicomplete.cpp @@ -438,7 +438,7 @@ void LLPanelEmojiComplete::updateConstraints() { mRenderRect = getLocalRect(); - mEmojiWidth = (U16)(mIconFont->getWidthF32(u8"\U0001F431") + mPadding * 2); + mEmojiWidth = (U16)(mIconFont->getWidthF32(LLWString(1, 0x1F431).c_str()) + mPadding * 2); if (mVertical) { mEmojiHeight = mIconFont->getLineHeight() + mPadding * 2; diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 544b6fbc9c1..c080d725800 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -898,6 +898,10 @@ struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor if (facep->calcAlignedPlanarTE(mCenterFace, &aligned_st_offset, &aligned_st_scale, &aligned_st_rot)) { const LLTextureEntry* tep = facep->getTextureEntry(); + if (!tep) + { + return false; + } LLVector2 st_offset, st_scale; tep->getOffset(&st_offset.mV[VX], &st_offset.mV[VY]); tep->getScale(&st_scale.mV[VX], &st_scale.mV[VY]); diff --git a/indra/newview/llpanelgroupbulk.cpp b/indra/newview/llpanelgroupbulk.cpp index 433db74cda8..8032e207cd5 100644 --- a/indra/newview/llpanelgroupbulk.cpp +++ b/indra/newview/llpanelgroupbulk.cpp @@ -56,6 +56,7 @@ LLPanelGroupBulkImpl::LLPanelGroupBulkImpl(const LLUUID& group_id) : mGroupID(group_id), mBulkAgentList(NULL), mOKButton(NULL), + mAddButton(nullptr), mRemoveButton(NULL), mGroupName(NULL), mLoadingText(), @@ -79,29 +80,18 @@ LLPanelGroupBulkImpl::~LLPanelGroupBulkImpl() } } -// static -void LLPanelGroupBulkImpl::callbackClickAdd(void* userdata) +void LLPanelGroupBulkImpl::callbackClickAdd(LLPanelGroupBulk* panelp) { - if (LLPanelGroupBulk* panelp = (LLPanelGroupBulk*)userdata) - { - // Right now this is hard coded with some knowledge that it is part - // of a floater since the avatar picker needs to be added as a dependent - // floater to the parent floater. - // Soon the avatar picker will be embedded into this panel - // instead of being it's own separate floater. But that is next week. - // This will do for now. -jwolk May 10, 2006 - LLView* button = panelp->findChild("add_button"); - LLFloater* root_floater = gFloaterView->getParentFloater(panelp); - LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( - [&](const uuid_vec_t& agent_ids, const std::vector&) - { - panelp->mImplementation->addUsers(agent_ids); - }, true, false, false, root_floater->getName(), button); - if (picker) + LLFloater* root_floater = gFloaterView->getParentFloater(panelp); + LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show( + [this](const uuid_vec_t& agent_ids, const std::vector&) { - root_floater->addDependentFloater(picker); - LLGroupMgr::getInstance()->sendCapGroupMembersRequest(panelp->mImplementation->mGroupID); - } + addUsers(agent_ids); + }, true, false, false, root_floater->getName(), mAddButton); + if (picker) + { + root_floater->addDependentFloater(picker); + LLGroupMgr::getInstance()->sendCapGroupMembersRequest(mGroupID); } } diff --git a/indra/newview/llpanelgroupbulkban.cpp b/indra/newview/llpanelgroupbulkban.cpp index 3c764887a68..1d3edad0f37 100644 --- a/indra/newview/llpanelgroupbulkban.cpp +++ b/indra/newview/llpanelgroupbulkban.cpp @@ -68,35 +68,26 @@ bool LLPanelGroupBulkBan::postBuild() mImplementation->mBulkAgentList->setCommitCallback(LLPanelGroupBulkImpl::callbackSelect, mImplementation); } - LLButton* button = getChild("add_button", recurse); - if ( button ) + mImplementation->mAddButton = getChild("add_button", recurse); + // default to opening avatarpicker automatically + mImplementation->mAddButton->setClickedCallback( + [this](LLUICtrl* ctrl, const LLSD& param) { - // default to opening avatarpicker automatically - // (*impl::callbackClickAdd)((void*)this); - button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickAdd, this); - } + mImplementation->callbackClickAdd(this); + }); mImplementation->mRemoveButton = getChild("remove_button", recurse); - if ( mImplementation->mRemoveButton ) - { - mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation); - mImplementation->mRemoveButton->setEnabled(false); - } + mImplementation->mRemoveButton->setClickedCallback(LLPanelGroupBulkImpl::callbackClickRemove, mImplementation); + mImplementation->mRemoveButton->setEnabled(false); mImplementation->mOKButton = getChild("ban_button", recurse); - if ( mImplementation->mOKButton ) - { - mImplementation->mOKButton->setClickedCallback(LLPanelGroupBulkBan::callbackClickSubmit, this); - mImplementation->mOKButton->setEnabled(false); - } + mImplementation->mOKButton->setClickedCallback(LLPanelGroupBulkBan::callbackClickSubmit, this); + mImplementation->mOKButton->setEnabled(false); - button = getChild("cancel_button", recurse); - if ( button ) - { - button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickCancel, mImplementation); - } + LLButton* button = getChild("cancel_button", recurse); + button->setClickedCallback(LLPanelGroupBulkImpl::callbackClickCancel, mImplementation); mImplementation->mTooManySelected = getString("ban_selection_too_large"); mImplementation->mBanNotPermitted = getString("ban_not_permitted"); diff --git a/indra/newview/llpanelgroupbulkimpl.h b/indra/newview/llpanelgroupbulkimpl.h index 5a479f81179..5515bd6d9a6 100644 --- a/indra/newview/llpanelgroupbulkimpl.h +++ b/indra/newview/llpanelgroupbulkimpl.h @@ -44,7 +44,7 @@ class LLPanelGroupBulkImpl LLPanelGroupBulkImpl(const LLUUID& group_id); ~LLPanelGroupBulkImpl(); - static void callbackClickAdd(void* userdata); + void callbackClickAdd(LLPanelGroupBulk* panelp); static void callbackClickRemove(void* userdata); static void callbackClickCancel(void* userdata); @@ -70,6 +70,7 @@ class LLPanelGroupBulkImpl LLNameListCtrl* mBulkAgentList; LLButton* mOKButton; + LLButton* mAddButton; LLButton* mRemoveButton; LLTextBox* mGroupName; diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 377af4384aa..a5b4db05803 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -2425,10 +2425,14 @@ void LLPanelMainInventory::updateCombinationVisibility() mCombinationGalleryLayoutPanel->setVisible(!is_gallery_empty); mCombinationListLayoutPanel->setVisible(show_inv_pane); - mCombinationInventoryPanel->getRootFolder()->setForceArrange(!show_inv_pane); - if(mCombinationInventoryPanel->hasVisibleItems()) + LLFolderView* root_folder = mCombinationInventoryPanel->getRootFolder(); + if (root_folder) { - mForceShowInvLayout = false; + root_folder->setForceArrange(!show_inv_pane); + if (mCombinationInventoryPanel->hasVisibleItems()) + { + mForceShowInvLayout = false; + } } if(is_gallery_empty) { diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index abb48dbeed9..154639e4bb5 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -85,6 +85,8 @@ class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener static void idle(void* user_data); + bool hasInventory(){ return mHaveInventory; }; + protected: void reset(); /*virtual*/ void inventoryChanged(LLViewerObject* object, diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 4db0a5b59d5..b8c12ce0b97 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -660,11 +660,11 @@ void LLPanelPrimMediaControls::updateShape() for(; vert_it != vert_end; ++vert_it) { // project silhouette vertices into screen space - glm::vec3 screen_vert(glm::make_vec3(vert_it->mV)); + glm::vec3 screen_vert(*vert_it); screen_vert = mul_mat4_vec3(mat, screen_vert); // add to screenspace bounding box - update_min_max(min, max, LLVector3(glm::value_ptr(screen_vert))); + update_min_max(min, max, LLVector3(screen_vert)); } // convert screenspace bbox to pixels (in screen coords) diff --git a/indra/newview/llprogressview.cpp b/indra/newview/llprogressview.cpp index 80e403dfde3..2c09943b831 100644 --- a/indra/newview/llprogressview.cpp +++ b/indra/newview/llprogressview.cpp @@ -81,10 +81,9 @@ bool LLProgressView::postBuild() { mProgressBar = getChild("login_progress_bar"); - mLogosLabel = getChild("logos_lbl"); - mProgressText = getChild("progress_text"); mMessageText = getChild("message_text"); + mMessageTextRectInitial = mMessageText->getRect(); // auto resizes, save initial size // media control that is used to play intro video mMediaCtrl = getChild("login_media_panel"); @@ -96,6 +95,12 @@ bool LLProgressView::postBuild() mCancelBtn = getChild("cancel_btn"); mCancelBtn->setClickedCallback( LLProgressView::onCancelButtonClicked, NULL ); + mLayoutPanel4 = getChild("panel4"); + mLayoutPanel4RectInitial = mLayoutPanel4->getRect(); + + mLayoutMOTD = getChild("panel_motd"); + mLayoutMOTDRectInitial = mLayoutMOTD->getRect(); + getChild("title_text")->setText(LLStringExplicit(LLAppViewer::instance()->getSecondLifeTitle())); getChild("message_text")->setClickedCallback(onClickMessage, this); @@ -234,33 +239,6 @@ void LLProgressView::drawStartTexture(F32 alpha) gGL.popMatrix(); } -void LLProgressView::drawLogos(F32 alpha) -{ - if (mLogosList.empty()) - { - return; - } - - // logos are tied to label, - // due to potential resizes we have to figure offsets out on draw or resize - S32 offset_x, offset_y; - mLogosLabel->localPointToScreen(0, 0, &offset_x, &offset_y); - std::vector::const_iterator iter = mLogosList.begin(); - std::vector::const_iterator end = mLogosList.end(); - for (; iter != end; iter++) - { - gl_draw_scaled_image_with_border(iter->mDrawRect.mLeft + offset_x, - iter->mDrawRect.mBottom + offset_y, - iter->mDrawRect.getWidth(), - iter->mDrawRect.getHeight(), - iter->mTexturep.get(), - UI_VERTEX_COLOR % alpha, - false, - iter->mClipRect, - iter->mOffsetRect); - } -} - void LLProgressView::draw() { static LLTimer timer; @@ -276,7 +254,6 @@ void LLProgressView::draw() } LLPanel::draw(); - drawLogos(alpha); return; } @@ -289,7 +266,6 @@ void LLProgressView::draw() drawStartTexture(alpha); LLPanel::draw(); - drawLogos(alpha); // faded out completely - remove panel and reveal world if (mFadeToWorldTimer.getElapsedTimeF32() > FADE_TO_WORLD_TIME ) @@ -324,7 +300,6 @@ void LLProgressView::draw() drawStartTexture(1.0f); // draw children LLPanel::draw(); - drawLogos(1.0f); } void LLProgressView::setText(const std::string& text) @@ -341,90 +316,18 @@ void LLProgressView::setMessage(const std::string& msg) { mMessage = msg; mMessageText->setValue(mMessage); -} - -void LLProgressView::loadLogo(const std::string &path, - const U8 image_codec, - const LLRect &pos_rect, - const LLRectf &clip_rect, - const LLRectf &offset_rect) -{ - // We need these images very early, so we have to force-load them, otherwise they might not load in time. - if (!gDirUtilp->fileExists(path)) + S32 height = mMessageText->getTextPixelHeight(); + S32 delta = height - mMessageTextRectInitial.getHeight(); + if (delta > 0) { - return; + mLayoutPanel4->reshape(mLayoutPanel4RectInitial.getWidth(), mLayoutPanel4RectInitial.getHeight() + delta); + mLayoutMOTD->reshape(mLayoutMOTDRectInitial.getWidth(), mLayoutMOTDRectInitial.getHeight() + delta); } - - LLPointer start_image_frmted = LLImageFormatted::createFromType(image_codec); - if (!start_image_frmted->load(path)) - { - LL_WARNS("AppInit") << "Image load failed: " << path << LL_ENDL; - return; - } - - LLPointer raw = new LLImageRaw; - if (!start_image_frmted->decode(raw, 0.0f)) + else { - LL_WARNS("AppInit") << "Image decode failed " << path << LL_ENDL; - return; + mLayoutPanel4->reshape(mLayoutPanel4RectInitial.getWidth(), mLayoutPanel4RectInitial.getHeight()); + mLayoutMOTD->reshape(mLayoutMOTDRectInitial.getWidth(), mLayoutMOTDRectInitial.getHeight()); } - // HACK: getLocalTexture allows only power of two dimentions - raw->expandToPowerOfTwo(); - - TextureData data; - data.mTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), false); - data.mDrawRect = pos_rect; - data.mClipRect = clip_rect; - data.mOffsetRect = offset_rect; - mLogosList.push_back(data); -} - -void LLProgressView::initLogos() -{ - mLogosList.clear(); - - const U8 image_codec = IMG_CODEC_PNG; - const LLRectf default_clip(0.f, 1.f, 1.f, 0.f); - const S32 default_height = 28; - const S32 default_pad = 15; - - S32 icon_width, icon_height; - - // We don't know final screen rect yet, so we can't precalculate position fully - S32 texture_start_x = (S32)mLogosLabel->getFont()->getWidthF32(mLogosLabel->getWText().c_str()) + default_pad; - S32 texture_start_y = -7; - - // Normally we would just preload these textures from textures.xml, - // and display them via icon control, but they are only needed on - // startup and preloaded/UI ones stay forever - // (and this code was done already so simply reused it) - std::string temp_str = gDirUtilp->getExpandedFilename(LL_PATH_DEFAULT_SKIN, "textures", "3p_icons"); - - temp_str += gDirUtilp->getDirDelimiter(); - -#ifdef LL_HAVOK - // original image size is 342x113, central element is on a larger side - // plus internal padding, so it gets slightly more height than desired 32 - icon_width = 88; - icon_height = 29; - S32 pad_havok_y = -1; - loadLogo(temp_str + "havok_logo.png", - image_codec, - LLRect(texture_start_x, texture_start_y + pad_havok_y + icon_height, texture_start_x + icon_width, texture_start_y + pad_havok_y), - default_clip, - default_clip); - - texture_start_x += icon_width + default_pad; -#endif //LL_HAVOK - - // 108x41 - icon_width = 74; - icon_height = default_height; - loadLogo(temp_str + "vivox_logo.png", - image_codec, - LLRect(texture_start_x, texture_start_y + icon_height, texture_start_x + icon_width, texture_start_y), - default_clip, - default_clip); } void LLProgressView::initStartTexture(S32 location_id, bool is_in_production) @@ -505,19 +408,11 @@ void LLProgressView::initStartTexture(S32 location_id, bool is_in_production) void LLProgressView::initTextures(S32 location_id, bool is_in_production) { initStartTexture(location_id, is_in_production); - initLogos(); - - childSetVisible("panel_icons", !mLogosList.empty()); - childSetVisible("panel_top_spacer", mLogosList.empty()); } void LLProgressView::releaseTextures() { gStartTexture = NULL; - mLogosList.clear(); - - childSetVisible("panel_top_spacer", true); - childSetVisible("panel_icons", false); } void LLProgressView::setCancelButtonVisible(bool b, const std::string& label) diff --git a/indra/newview/llprogressview.h b/indra/newview/llprogressview.h index 15b04a8eb95..250ee511d78 100644 --- a/indra/newview/llprogressview.h +++ b/indra/newview/llprogressview.h @@ -53,7 +53,6 @@ class LLProgressView : /*virtual*/ void draw(); void drawStartTexture(F32 alpha); - void drawLogos(F32 alpha); /*virtual*/ bool handleHover(S32 x, S32 y, MASK mask); /*virtual*/ bool handleKeyHere(KEY key, MASK mask); @@ -86,7 +85,6 @@ class LLProgressView : protected: LLProgressBar* mProgressBar; LLMediaCtrl* mMediaCtrl; - LLTextBox* mLogosLabel = nullptr; LLTextBox* mProgressText = nullptr; LLTextBox* mMessageText = nullptr; F32 mPercentDone; @@ -95,6 +93,13 @@ class LLProgressView : LLFrameTimer mFadeToWorldTimer; LLFrameTimer mFadeFromLoginTimer; LLRect mOutlineRect; + LLView* mLayoutPanel4 = nullptr; + LLView* mLayoutMOTD = nullptr; + // Rects for resizing purposes + LLRect mMessageTextRectInitial; + LLRect mLayoutPanel4RectInitial; + LLRect mLayoutMOTDRectInitial; + bool mMouseDownInActiveArea; bool mStartupComplete; @@ -105,25 +110,8 @@ class LLProgressView : bool handleUpdate(const LLSD& event_data); static void onIdle(void* user_data); - void loadLogo(const std::string &path, const U8 image_codec, const LLRect &pos_rect, const LLRectf &clip_rect, const LLRectf &offset_rect); - // logos have unusual location and need to be preloaded to not appear grey, then deleted - void initLogos(); // Loads a bitmap to display during load void initStartTexture(S32 location_id, bool is_in_production); - -private: - // We need to draw textures on login, but only once. - // So this vector gets filled up for textures to render and gets cleaned later - // Some textures have unusual requirements, so we are rendering directly - class TextureData - { - public: - LLPointer mTexturep; - LLRect mDrawRect; - LLRectf mClipRect; - LLRectf mOffsetRect; - }; - std::vector mLogosList; }; #endif // LL_LLPROGRESSVIEW_H diff --git a/indra/newview/llreflectionmap.cpp b/indra/newview/llreflectionmap.cpp index f77d37f821f..f3adb52d5e6 100644 --- a/indra/newview/llreflectionmap.cpp +++ b/indra/newview/llreflectionmap.cpp @@ -65,8 +65,9 @@ void LLReflectionMap::update(U32 resolution, U32 face, bool force_dynamic, F32 n } F32 clip = (near_clip > 0) ? near_clip : getNearClip(); + bool dynamic = force_dynamic || getIsDynamic(); - gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, getIsDynamic() || force_dynamic, useClipPlane, clipPlane); + gViewerWindow->cubeSnapshot(LLVector3(mOrigin), mCubeArray, mCubeIndex, face, clip, dynamic, useClipPlane, clipPlane); } void LLReflectionMap::autoAdjustOrigin() @@ -185,7 +186,7 @@ void LLReflectionMap::autoAdjustOrigin() } } -bool LLReflectionMap::intersects(LLReflectionMap* other) +bool LLReflectionMap::intersects(LLReflectionMap* other) const { LLVector4a delta; delta.setSub(other->mOrigin, mOrigin); @@ -201,24 +202,24 @@ bool LLReflectionMap::intersects(LLReflectionMap* other) extern LLControlGroup gSavedSettings; -F32 LLReflectionMap::getAmbiance() +F32 LLReflectionMap::getAmbiance() const { F32 ret = 0.f; - if (mViewerObject && mViewerObject->getVolume()) + if (mViewerObject && mViewerObject->getVolumeConst()) { - ret = ((LLVOVolume*)mViewerObject)->getReflectionProbeAmbiance(); + ret = mViewerObject->getReflectionProbeAmbiance(); } return ret; } -F32 LLReflectionMap::getNearClip() +F32 LLReflectionMap::getNearClip() const { const F32 MINIMUM_NEAR_CLIP = 0.1f; F32 ret = 0.f; - if (mViewerObject && mViewerObject->getVolume()) + if (mViewerObject && mViewerObject->getVolumeConst()) { ret = mViewerObject->getReflectionProbeNearClip(); } @@ -234,11 +235,13 @@ F32 LLReflectionMap::getNearClip() return llmax(ret, MINIMUM_NEAR_CLIP); } -bool LLReflectionMap::getIsDynamic() +bool LLReflectionMap::getIsDynamic() const { - if (gSavedSettings.getS32("RenderReflectionProbeDetail") > (S32) LLReflectionMapManager::DetailLevel::STATIC_ONLY && + static LLCachedControl detail(gSavedSettings, "RenderReflectionProbeDetail", 1); + if (detail() > (S32)LLReflectionMapManager::DetailLevel::STATIC_ONLY && mViewerObject && - mViewerObject->getVolume()) + !mViewerObject->isDead() && + mViewerObject->getVolumeConst()) { return mViewerObject->getReflectionProbeIsDynamic(); } @@ -256,7 +259,7 @@ bool LLReflectionMap::getBox(LLMatrix4& box) glm::mat4 mv(get_current_modelview()); LLVector3 s = mViewerObject->getScale().scaledVec(LLVector3(0.5f, 0.5f, 0.5f)); mRadius = s.magVec(); - glm::mat4 scale = glm::scale(glm::make_vec3(s.mV)); + glm::mat4 scale = glm::scale(glm::vec3(s)); if (mViewerObject->mDrawable != nullptr) { // object to agent space (no scale) @@ -278,12 +281,12 @@ bool LLReflectionMap::getBox(LLMatrix4& box) return false; } -bool LLReflectionMap::isActive() +bool LLReflectionMap::isActive() const { return mCubeIndex != -1; } -bool LLReflectionMap::isRelevant() +bool LLReflectionMap::isRelevant() const { static LLCachedControl RenderReflectionProbeLevel(gSavedSettings, "RenderReflectionProbeLevel", 3); diff --git a/indra/newview/llreflectionmap.h b/indra/newview/llreflectionmap.h index 117ea4cfa66..d20bba70593 100644 --- a/indra/newview/llreflectionmap.h +++ b/indra/newview/llreflectionmap.h @@ -58,16 +58,16 @@ class alignas(16) LLReflectionMap : public LLRefCount void autoAdjustOrigin(); // return true if given Reflection Map's influence volume intersect's with this one's - bool intersects(LLReflectionMap* other); + bool intersects(LLReflectionMap* other) const; // Get the ambiance value to use for this probe - F32 getAmbiance(); + F32 getAmbiance() const; // Get the near clip plane distance to use for this probe - F32 getNearClip(); + F32 getNearClip() const; // Return true if this probe should include avatars in its reflection map - bool getIsDynamic(); + bool getIsDynamic() const; // get the encoded bounding box of this probe's influence volume // will only return a box if this probe is associated with a VOVolume @@ -76,13 +76,13 @@ class alignas(16) LLReflectionMap : public LLRefCount bool getBox(LLMatrix4& box); // return true if this probe is active for rendering - bool isActive(); + bool isActive() const; // perform occlusion query/readback void doOcclusion(const LLVector4a& eye); // return false if this probe isn't currently relevant (for example, disabled due to graphics preferences) - bool isRelevant(); + bool isRelevant() const; // point at which environment map was last generated from (in agent space) LLVector4a mOrigin; diff --git a/indra/newview/llreflectionmapmanager.cpp b/indra/newview/llreflectionmapmanager.cpp index 8f75b108cc8..9a209776522 100644 --- a/indra/newview/llreflectionmapmanager.cpp +++ b/indra/newview/llreflectionmapmanager.cpp @@ -223,9 +223,11 @@ void LLReflectionMapManager::update() initReflectionMaps(); + static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); + if (!mRenderTarget.isComplete()) { - U32 color_fmt = GL_RGB16F; + U32 color_fmt = render_hdr ? GL_R11F_G11F_B10F : GL_RGB8; U32 targetRes = mProbeResolution * 4; // super sample mRenderTarget.allocate(targetRes, targetRes, color_fmt, true); } @@ -238,7 +240,7 @@ void LLReflectionMapManager::update() mMipChain.resize(count); for (U32 i = 0; i < count; ++i) { - mMipChain[i].allocate(res, res, GL_RGB16F); + mMipChain[i].allocate(res, res, render_hdr ? GL_R11F_G11F_B10F : GL_RGB8); res /= 2; } } @@ -306,7 +308,7 @@ void LLReflectionMapManager::update() LLReflectionMap* probe = mProbes[i]; llassert(probe != nullptr); - if (probe->mCubeIndex != -1 && mUpdatingProbe != probe) + if (probe && probe->mCubeIndex != -1 && mUpdatingProbe != probe) { // free this index mCubeFree.push_back(probe->mCubeIndex); @@ -1415,11 +1417,13 @@ void LLReflectionMapManager::initReflectionMaps() { mTexture = new LLCubeMapArray(); + static LLCachedControl render_hdr(gSavedSettings, "RenderHDREnabled", true); + // store mReflectionProbeCount+2 cube maps, final two cube maps are used for render target and radiance map generation source) - mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2); + mTexture->allocate(mProbeResolution, 3, mReflectionProbeCount + 2, true, render_hdr); mIrradianceMaps = new LLCubeMapArray(); - mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false); + mIrradianceMaps->allocate(LL_IRRADIANCE_MAP_RESOLUTION, 3, mReflectionProbeCount, false, render_hdr); } // reset probe state diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index cf96072ae2a..6023f6885db 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -807,7 +807,7 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) static LLCachedControl tonemap_mix_setting(gSavedSettings, "RenderTonemapMix", 1.f); // sky is a "classic" sky following pre SL 7.0 shading - bool classic_mode = psky->canAutoAdjust(); + bool classic_mode = psky->canAutoAdjust() && !should_auto_adjust(); if (!classic_mode) { @@ -832,6 +832,10 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) { shader->uniform3fv(LLShaderMgr::AMBIENT, LLVector3(ambient.mV)); shader->uniform1f(LLShaderMgr::SKY_HDR_SCALE, sqrtf(g)*2.0f); // use a modifier here so 1.0 maps to the "most desirable" default and the maximum value doesn't go off the rails + + // Low quality setting + if (!LLPipeline::sReflectionProbesEnabled) + probe_ambiance = DEFAULT_AUTO_ADJUST_PROBE_AMBIANCE; } else if (psky->canAutoAdjust() && should_auto_adjust) { // auto-adjust legacy sky to take advantage of probe ambiance @@ -1093,8 +1097,8 @@ void LLSettingsVOWater::applySpecial(void *ptarget, bool force) LLVector4 waterPlane(enorm.x, enorm.y, enorm.z, -glm::dot(ep, enorm)); - norm = glm::make_vec3(gPipeline.mHeroProbeManager.mMirrorNormal.mV); - p = glm::make_vec3(gPipeline.mHeroProbeManager.mMirrorPosition.mV); + norm = glm::vec3(gPipeline.mHeroProbeManager.mMirrorNormal); + p = glm::vec3(gPipeline.mHeroProbeManager.mMirrorPosition); enorm = mul_mat4_vec3(invtrans, norm); enorm = glm::normalize(enorm); ep = mul_mat4_vec3(mat, p); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index a1a67c319cc..f3cfbd9565b 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -2609,12 +2609,8 @@ void renderTexturePriority(LLDrawable* drawable) LLGLDisable blend(GL_BLEND); - //LLViewerTexture* imagep = facep->getTexture(); - //if (imagep) if (facep) { - - //F32 vsize = imagep->mMaxVirtualSize; F32 vsize = facep->getPixelArea(); if (vsize > sCurMaxTexPriority) @@ -2640,18 +2636,6 @@ void renderTexturePriority(LLDrawable* drawable) size.mul(0.5f); size.add(LLVector4a(0.01f)); drawBox(center, size); - - /*S32 boost = imagep->getBoostLevel(); - if (boost>LLGLTexture::BOOST_NONE) - { - F32 t = (F32) boost / (F32) (LLGLTexture::BOOST_MAX_LEVEL-1); - LLVector4 col = lerp(boost_cold, boost_hot, t); - LLGLEnable blend_on(GL_BLEND); - gGL.blendFunc(GL_SRC_ALPHA, GL_ONE); - gGL.diffuseColor4fv(col.mV); - drawBox(center, size); - gGL.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - }*/ } } diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index b32b80331ab..6c3f3849ce2 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1045,6 +1045,7 @@ bool idle_startup() login->setSerialNumber(LLAppViewer::instance()->getSerialNumber()); login->setLastExecEvent(gLastExecEvent); login->setLastExecDuration(gLastExecDuration); + login->setLastAgentSessionId(gLastAgentSessionId); // This call to LLLoginInstance::connect() starts the // authentication process. @@ -1393,7 +1394,7 @@ bool idle_startup() } else if (regionp->capabilitiesError()) { - LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; + LL_WARNS("AppInit") << "Failed to get capabilities. Logging out and backing up to login screen!" << LL_ENDL; if (gRememberPassword) { LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); @@ -1402,6 +1403,15 @@ bool idle_startup() { LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); } + + // Session was created, don't just hang up on server, send a logout request + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_LogoutRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + reset_login(); } else @@ -1409,7 +1419,7 @@ bool idle_startup() U32 num_retries = regionp->getNumSeedCapRetries(); if (num_retries > MAX_SEED_CAP_ATTEMPTS_BEFORE_ABORT) { - LL_WARNS("AppInit") << "Failed to get capabilities. Backing up to login screen!" << LL_ENDL; + LL_WARNS("AppInit") << "Failed to get capabilities. Logging out and backing up to login screen!" << LL_ENDL; if (gRememberPassword) { LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); @@ -1418,6 +1428,15 @@ bool idle_startup() { LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); } + + // Session was created, don't just hang up on server, send a logout request + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_LogoutRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + reset_login(); } else if (num_retries > 0) @@ -1507,7 +1526,7 @@ bool idle_startup() // create a container's instance for start a controlling conversation windows // by the voice's events LLFloaterIMContainer *im_inst = LLFloaterIMContainer::getInstance(); - if(gAgent.isFirstLogin()) + if(gAgent.isFirstLogin() && im_inst) { im_inst->openFloater(im_inst->getKey()); } @@ -1720,7 +1739,7 @@ bool idle_startup() if (!gAgentMovementCompleted && timeout.getElapsedTimeF32() > STATE_AGENT_WAIT_TIMEOUT) { - LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; + LL_WARNS("AppInit") << "Timeout on agent movement. Sending logout and backing up to login screen!" << LL_ENDL; if (gRememberPassword) { LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); @@ -1729,6 +1748,15 @@ bool idle_startup() { LLNotificationsUtil::add("LoginPacketNeverReceivedNoTP", LLSD(), LLSD(), login_alert_status); } + + // Session was created, don't just hang up on server, send a logout request + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_LogoutRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + reset_login(); } return false; @@ -3529,6 +3557,7 @@ bool process_login_success_response() text = response["session_id"].asString(); if(!text.empty()) gAgentSessionID.set(text); gDebugInfo["SessionID"] = text; + LLAppViewer::instance()->recordSessionToMarker(); // Session id needed for parcel info request in LLUrlEntryParcel // to resolve parcel name. diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index bac0c736b11..087761cbd0c 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include "lltexturefetch.h" @@ -2843,7 +2844,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, S3 bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) { LL_PROFILE_ZONE_SCOPED; - mRequestQueue.tryPost([=]() + mRequestQueue.tryPost([=, this]() { LLTextureFetchWorker* worker = getWorker(id); if (worker) @@ -3571,29 +3572,30 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) //if (! gViewerAssetStatsThread1) // return true; - static volatile bool reporting_started(false); - static volatile S32 report_sequence(0); + static std::atomic reporting_started(false); + static std::atomic report_sequence(0); // In mStatsSD, we have a copy we own of the LLSD representation // of the asset stats. Add some additional fields and ship it off. static const S32 metrics_data_version = 2; - bool initial_report = !reporting_started; + bool initial_report = !reporting_started.load(); mStatsSD["session_id"] = mSessionID; mStatsSD["agent_id"] = mAgentID; mStatsSD["message"] = "ViewerAssetMetrics"; - mStatsSD["sequence"] = report_sequence; + mStatsSD["sequence"] = report_sequence.load(); mStatsSD["initial"] = initial_report; mStatsSD["version"] = metrics_data_version; mStatsSD["break"] = static_cast(LLTextureFetch::svMetricsDataBreak); // Update sequence number - if (S32_MAX == ++report_sequence) + if (S32_MAX == report_sequence.fetch_add(1)) { - report_sequence = 0; + report_sequence.store(0); } - reporting_started = true; + + reporting_started.store(true); // Limit the size of the stats report if necessary. diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index aa43b2dbad0..7d777162ed0 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -420,7 +420,7 @@ bool LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); glm::ivec4 viewport(world_view_rect.mLeft, world_view_rect.mBottom, world_view_rect.getWidth(), world_view_rect.getHeight()); - glm::vec3 win_coord = glm::project(glm::make_vec3(pos_agent.mV), get_current_modelview(), get_current_projection(), viewport); + glm::vec3 win_coord = glm::project(glm::vec3(pos_agent), get_current_modelview(), get_current_projection(), viewport); { // convert screen coordinates to virtual UI coordinates @@ -514,7 +514,7 @@ bool LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); glm::ivec4 viewport(world_view_rect.mLeft, world_view_rect.mBottom, world_view_rect.getWidth(), world_view_rect.getHeight()); - glm::vec3 win_coord = glm::project(glm::make_vec3(pos_agent.mV), get_current_modelview(), get_current_projection(), viewport); + glm::vec3 win_coord = glm::project(glm::vec3(pos_agent), get_current_modelview(), get_current_projection(), viewport); { win_coord.x /= gViewerWindow->getDisplayScale().mV[VX]; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 18746e76fc6..598ad89907c 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -261,6 +261,8 @@ static bool handleDisableVintageMode(const LLSD& newvalue) static bool handleEnableHDR(const LLSD& newvalue) { + gPipeline.mReflectionMapManager.reset(); + gPipeline.mHeroProbeManager.reset(); return handleReleaseGLBufferChanged(newvalue) && handleSetShaderChanged(newvalue); } @@ -448,11 +450,11 @@ static bool handleReflectionProbeDetailChanged(const LLSD& newvalue) if (gPipeline.isInit()) { LLPipeline::refreshCachedSettings(); + gPipeline.mReflectionMapManager.reset(); + gPipeline.mHeroProbeManager.reset(); gPipeline.releaseGLBuffers(); gPipeline.createGLBuffers(); LLViewerShaderMgr::instance()->setShaders(); - gPipeline.mReflectionMapManager.reset(); - gPipeline.mHeroProbeManager.reset(); } return true; } @@ -762,9 +764,9 @@ LLPointer setting_get_control(LLControlGroup& group, const st LLPointer cntrl_ptr = group.getControl(setting); if (cntrl_ptr.isNull()) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "Unable to set up setting listener for " << setting - << ". Please reinstall viewer from https ://secondlife.com/support/downloads/ and contact https://support.secondlife.com if issue persists after reinstall." - << LL_ENDL; + << "." << LL_ENDL; } return cntrl_ptr; } diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 4e7416bb63d..d688d5930c0 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -2902,14 +2902,14 @@ void LLViewerMediaImpl::update() media_tex->ref(); main_queue->postTo( mTexUpdateQueue, // Worker thread queue - [=]() // work done on update worker thread + [=, this]() // work done on update worker thread { #if LL_IMAGEGL_THREAD_CHECK media_tex->getGLTexture()->mActiveThread = LLThread::currentID(); #endif doMediaTexUpdate(media_tex, data, data_width, data_height, x_pos, y_pos, width, height, true); }, - [=]() // callback to main thread + [=, this]() // callback to main thread { #if LL_IMAGEGL_THREAD_CHECK media_tex->getGLTexture()->mActiveThread = LLThread::currentID(); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 80c75ec9194..d92faf4d1bf 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -5199,15 +5199,16 @@ void handle_take(bool take_separate) // MAINT-290 // Reason: Showing the confirmation dialog resets object selection, thus there is nothing to derez. // Fix: pass selection to the confirm_take, so that selection doesn't "die" after confirmation dialog is opened - params.functor.function([take_separate](const LLSD ¬ification, const LLSD &response) + LLObjectSelectionHandle obj_selection = LLSelectMgr::instance().getSelection(); + params.functor.function([take_separate, obj_selection](const LLSD ¬ification, const LLSD &response) { if (take_separate) { - confirm_take_separate(notification, response, LLSelectMgr::instance().getSelection()); + confirm_take_separate(notification, response, obj_selection); } else { - confirm_take(notification, response, LLSelectMgr::instance().getSelection()); + confirm_take(notification, response, obj_selection); } }); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index b6846c6716e..119b07b1f59 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -727,6 +727,9 @@ class LLViewerObject // index into LLViewerObjectList::mActiveObjects or -1 if not in list S32 mListIndex; + // last index data for mIndexAndLocalIDToUUID + U32 mRegionIndex; + LLPointer *mTEImages; LLPointer *mTENormalMaps; LLPointer *mTESpecularMaps; @@ -755,6 +758,7 @@ class LLViewerObject // Associated GLTF Asset std::shared_ptr mGLTFAsset; + bool mIsGLTFAssetMissing = false; // Pipeline classes LLPointer mDrawable; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index d667fdbea8c..d72d428c085 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -164,21 +164,14 @@ U64 LLViewerObjectList::getIndex(const U32 local_id, return (((U64)index) << 32) | (U64)local_id; } -bool LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) +bool LLViewerObjectList::removeFromLocalIDTable(LLViewerObject* objectp) { LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; - if(objectp && objectp->getRegion()) + if(objectp && objectp->mRegionIndex != 0) { U32 local_id = objectp->mLocalID; - U32 ip = objectp->getRegion()->getHost().getAddress(); - U32 port = objectp->getRegion()->getHost().getPort(); - U64 ipport = (((U64)ip) << 32) | (U64)port; - U32 index = mIPAndPortToIndex[ipport]; - - // LL_INFOS() << "Removing object from table, local ID " << local_id << ", ip " << ip << ":" << port << LL_ENDL; - - U64 indexid = (((U64)index) << 32) | (U64)local_id; + U64 indexid = (((U64)objectp->mRegionIndex) << 32) | (U64)local_id; std::map::iterator iter = mIndexAndLocalIDToUUID.find(indexid); if (iter == mIndexAndLocalIDToUUID.end()) @@ -190,6 +183,7 @@ bool LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) if (iter->second == objectp->getID()) { // Full UUIDs match, so remove the entry mIndexAndLocalIDToUUID.erase(iter); + objectp->mRegionIndex = 0; return true; } // UUIDs did not match - this would zap a valid entry, so don't erase it @@ -203,7 +197,8 @@ bool LLViewerObjectList::removeFromLocalIDTable(const LLViewerObject* objectp) void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, const U32 local_id, const U32 ip, - const U32 port) + const U32 port, + LLViewerObject* objectp) { U64 ipport = (((U64)ip) << 32) | (U64)port; @@ -215,6 +210,7 @@ void LLViewerObjectList::setUUIDAndLocal(const LLUUID &id, mIPAndPortToIndex[ipport] = index; } + objectp->mRegionIndex = index; // should never be zero, sSimulatorMachineIndex starts from 1 U64 indexid = (((U64)index) << 32) | (U64)local_id; mIndexAndLocalIDToUUID[indexid] = id; @@ -335,7 +331,8 @@ LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* removeFromLocalIDTable(objectp); setUUIDAndLocal(fullid, entry->getLocalID(), regionp->getHost().getAddress(), - regionp->getHost().getPort()); + regionp->getHost().getPort(), + objectp); if (objectp->mLocalID != entry->getLocalID()) { // Update local ID in object with the one sent from the region @@ -582,7 +579,8 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, setUUIDAndLocal(fullid, local_id, gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); + gMessageSystem->getSenderPort(), + objectp); if (objectp->mLocalID != local_id) { // Update local ID in object with the one sent from the region @@ -1381,11 +1379,20 @@ void LLViewerObjectList::killObjects(LLViewerRegion *regionp) void LLViewerObjectList::killAllObjects() { // Used only on global destruction. - LLViewerObject *objectp; + // Mass cleanup to not clear lists one item at a time + mIndexAndLocalIDToUUID.clear(); + mActiveObjects.clear(); + mMapObjects.clear(); + + LLViewerObject *objectp; for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) { objectp = *iter; + objectp->setOnActiveList(false); + objectp->setListIndex(-1); + objectp->mRegionIndex = 0; + objectp->mOnMap = false; killObject(objectp); // Object must be dead, or it's the LLVOAvatarSelf which never dies. llassert((objectp == gAgentAvatarp) || objectp->isDead()); @@ -1398,18 +1405,6 @@ void LLViewerObjectList::killAllObjects() LL_WARNS() << "LLViewerObjectList::killAllObjects still has entries in mObjects: " << mObjects.size() << LL_ENDL; mObjects.clear(); } - - if (!mActiveObjects.empty()) - { - LL_WARNS() << "Some objects still on active object list!" << LL_ENDL; - mActiveObjects.clear(); - } - - if (!mMapObjects.empty()) - { - LL_WARNS() << "Some objects still on map object list!" << LL_ENDL; - mMapObjects.clear(); - } } void LLViewerObjectList::cleanDeadObjects(bool use_timer) @@ -1471,20 +1466,25 @@ void LLViewerObjectList::removeFromActiveList(LLViewerObject* objectp) { S32 idx = objectp->getListIndex(); if (idx != -1) - { //remove by moving last element to this object's position - llassert(mActiveObjects[idx] == objectp); - + { objectp->setListIndex(-1); - S32 last_index = static_cast(mActiveObjects.size()) - 1; - - if (idx != last_index) + S32 size = (S32)mActiveObjects.size(); + if (size > 0) // mActiveObjects could have been cleaned already { - mActiveObjects[idx] = mActiveObjects[last_index]; - mActiveObjects[idx]->setListIndex(idx); - } + // Remove by moving last element to this object's position - mActiveObjects.pop_back(); + llassert(idx < size); // idx should be always within mActiveObjects, unless killAllObjects was called + llassert(mActiveObjects[idx] == objectp); // object should be there + + S32 last_index = size - 1; + if (idx < last_index) + { + mActiveObjects[idx] = mActiveObjects[last_index]; + mActiveObjects[idx]->setListIndex(idx); + } // else assume it's the last element, no need to swap + mActiveObjects.pop_back(); + } } } @@ -1509,9 +1509,9 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) mActiveObjects.push_back(objectp); objectp->setListIndex(static_cast(mActiveObjects.size()) - 1); objectp->setOnActiveList(true); - } - else - { + } + else + { llassert(idx < mActiveObjects.size()); llassert(mActiveObjects[idx] == objectp); @@ -1863,7 +1863,8 @@ LLViewerObject *LLViewerObjectList::createObjectFromCache(const LLPCode pcode, L setUUIDAndLocal(uuid, local_id, regionp->getHost().getAddress(), - regionp->getHost().getPort()); + regionp->getHost().getPort(), + objectp); mObjects.push_back(objectp); updateActive(objectp); @@ -1901,7 +1902,8 @@ LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRe setUUIDAndLocal(fullid, local_id, gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); + gMessageSystem->getSenderPort(), + objectp); mObjects.push_back(objectp); diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index dc31995eb1a..547ef9fb2d4 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -179,9 +179,10 @@ class LLViewerObjectList void setUUIDAndLocal(const LLUUID &id, const U32 local_id, const U32 ip, - const U32 port); // Requires knowledge of message system info! + const U32 port, + LLViewerObject* objectp); // Requires knowledge of message system info! - bool removeFromLocalIDTable(const LLViewerObject* objectp); + bool removeFromLocalIDTable(LLViewerObject* objectp); // Used ONLY by the orphaned object code. U64 getIndex(const U32 local_id, const U32 ip, const U32 port); diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index 8c24b2438bc..8e6657b4b97 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -1824,6 +1824,16 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use S32 bitmap_size = parcel_mgr.mParcelsPerEdge * parcel_mgr.mParcelsPerEdge / 8; + S32 size = msg->getSizeFast(_PREHASH_ParcelData, _PREHASH_Bitmap); + if (size != bitmap_size) + { + // Might be better to ignore bitmap and drop highlights + LL_WARNS("ParcelMgr") << "Parcel Bitmap size expected: " << bitmap_size + << " actual " << size + << ". Bitmap might be corrupted!" << LL_ENDL; + bitmap_size = size; + } + U8* bitmap = new U8[ bitmap_size ]; msg->getBinaryDataFast(_PREHASH_ParcelData, _PREHASH_Bitmap, bitmap, bitmap_size); diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5b4648a0bf7..a0a9906724e 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -101,6 +101,7 @@ LLGLSLShader gReflectionProbeDisplayProgram; LLGLSLShader gCopyProgram; LLGLSLShader gCopyDepthProgram; LLGLSLShader gPBRTerrainBakeProgram; +LLGLSLShader gDrawColorProgram; //object shaders LLGLSLShader gObjectPreviewProgram; @@ -113,7 +114,6 @@ LLGLSLShader gObjectAlphaMaskNoColorProgram; //environment shaders LLGLSLShader gWaterProgram; -LLGLSLShader gWaterEdgeProgram; LLGLSLShader gUnderWaterProgram; //interface shaders @@ -409,7 +409,6 @@ void LLViewerShaderMgr::finalizeShaderList() //ONLY shaders that need WL Param management should be added here mShaderList.push_back(&gAvatarProgram); mShaderList.push_back(&gWaterProgram); - mShaderList.push_back(&gWaterEdgeProgram); mShaderList.push_back(&gAvatarEyeballProgram); mShaderList.push_back(&gImpostorProgram); mShaderList.push_back(&gObjectBumpProgram); @@ -623,6 +622,8 @@ void LLViewerShaderMgr::setShaders() else { // "ShaderLoading" and "Shader" need to be logged + LL_WARNS("Shader") << "Failed loading basic shaders. Retrying with increased log level..." << LL_ENDL; + LLError::ELevel lvl = LLError::getDefaultLevel(); LLError::setDefaultLevel(LLError::LEVEL_DEBUG); loadBasicShaders(); @@ -843,7 +844,7 @@ std::string LLViewerShaderMgr::loadBasicShaders() // Note usage of GL_VERTEX_SHADER if (loadShaderFile(shaders[i].first, shaders[i].second, GL_VERTEX_SHADER, &attribs) == 0) { - LL_WARNS("Shader") << "Failed to load vertex shader " << shaders[i].first << LL_ENDL; + LL_WARNS("Shader") << "Failed to load basic vertex shader " << i << ": " << shaders[i].first << LL_ENDL; return shaders[i].first; } } @@ -874,6 +875,7 @@ std::string LLViewerShaderMgr::loadBasicShaders() index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/pbrterrainUtilF.glsl", 1) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/tonemapUtilF.glsl", 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl", has_reflection_probes ? 3 : 2) ); index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", ssr ? 3 : 1) ); index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) ); @@ -906,7 +908,6 @@ bool LLViewerShaderMgr::loadShadersWater() if (mShaderLevel[SHADER_WATER] == 0) { gWaterProgram.unload(); - gWaterEdgeProgram.unload(); gUnderWaterProgram.unload(); return true; } @@ -920,6 +921,7 @@ bool LLViewerShaderMgr::loadShadersWater() gWaterProgram.mFeatures.hasGamma = true; gWaterProgram.mFeatures.hasSrgb = true; gWaterProgram.mFeatures.hasReflectionProbes = true; + gWaterProgram.mFeatures.hasTonemap = true; gWaterProgram.mFeatures.hasShadows = use_sun_shadow; gWaterProgram.mShaderFiles.clear(); gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER)); @@ -941,36 +943,6 @@ bool LLViewerShaderMgr::loadShadersWater() llassert(success); } - if (success) - { - // load water shader - gWaterEdgeProgram.mName = "Water Edge Shader"; - gWaterEdgeProgram.mFeatures.calculatesAtmospherics = true; - gWaterEdgeProgram.mFeatures.hasAtmospherics = true; - gWaterEdgeProgram.mFeatures.hasGamma = true; - gWaterEdgeProgram.mFeatures.hasSrgb = true; - gWaterEdgeProgram.mFeatures.hasReflectionProbes = true; - gWaterEdgeProgram.mFeatures.hasShadows = use_sun_shadow; - gWaterEdgeProgram.mShaderFiles.clear(); - gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER)); - gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER)); - gWaterEdgeProgram.clearPermutations(); - gWaterEdgeProgram.addPermutation("WATER_EDGE", "1"); - if (LLPipeline::sRenderTransparentWater) - { - gWaterEdgeProgram.addPermutation("TRANSPARENT_WATER", "1"); - } - - if (use_sun_shadow) - { - gWaterEdgeProgram.addPermutation("HAS_SUN_SHADOW", "1"); - } - gWaterEdgeProgram.mShaderGroup = LLGLSLShader::SG_WATER; - gWaterEdgeProgram.mShaderLevel = mShaderLevel[SHADER_WATER]; - success = gWaterEdgeProgram.createShader(); - llassert(success); - } - if (success) { //load under water vertex shader @@ -2481,6 +2453,7 @@ bool LLViewerShaderMgr::loadShadersDeferred() gDeferredPostTonemapProgram.mName = "Deferred Tonemap Post Process"; gDeferredPostTonemapProgram.mFeatures.hasSrgb = true; gDeferredPostTonemapProgram.mFeatures.isDeferred = true; + gDeferredPostTonemapProgram.mFeatures.hasTonemap = true; gDeferredPostTonemapProgram.mShaderFiles.clear(); gDeferredPostTonemapProgram.clearPermutations(); gDeferredPostTonemapProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER)); @@ -2495,6 +2468,7 @@ bool LLViewerShaderMgr::loadShadersDeferred() gNoPostTonemapProgram.mName = "No Post Tonemap Post Process"; gNoPostTonemapProgram.mFeatures.hasSrgb = true; gNoPostTonemapProgram.mFeatures.isDeferred = true; + gNoPostTonemapProgram.mFeatures.hasTonemap = true; gNoPostTonemapProgram.mShaderFiles.clear(); gNoPostTonemapProgram.clearPermutations(); gNoPostTonemapProgram.addPermutation("NO_POST", "1"); @@ -3353,6 +3327,17 @@ bool LLViewerShaderMgr::loadShadersInterface() success = gCopyDepthProgram.createShader(); } + if (success) + { + gDrawColorProgram.mName = "Draw Color Shader"; + gDrawColorProgram.mShaderFiles.clear(); + gDrawColorProgram.mShaderFiles.push_back(make_pair("objects/simpleNoAtmosV.glsl", GL_VERTEX_SHADER)); + gDrawColorProgram.mShaderFiles.push_back(make_pair("objects/simpleColorF.glsl", GL_FRAGMENT_SHADER)); + gDrawColorProgram.clearPermutations(); + gDrawColorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT]; + success = gDrawColorProgram.createShader(); + } + if (gSavedSettings.getBOOL("LocalTerrainPaintEnabled")) { if (success) diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index b08796025a0..7ad2da94640 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -175,6 +175,7 @@ extern LLGLSLShader gReflectionProbeDisplayProgram; extern LLGLSLShader gCopyProgram; extern LLGLSLShader gCopyDepthProgram; extern LLGLSLShader gPBRTerrainBakeProgram; +extern LLGLSLShader gDrawColorProgram; //output tex0[tc0] - tex1[tc1] extern LLGLSLShader gTwoTextureCompareProgram; @@ -191,7 +192,6 @@ extern LLGLSLShader gObjectAlphaMaskNoColorProgram; //environment shaders extern LLGLSLShader gWaterProgram; -extern LLGLSLShader gWaterEdgeProgram; extern LLGLSLShader gUnderWaterProgram; extern LLGLSLShader gGlowProgram; extern LLGLSLShader gGlowExtractProgram; diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 36b6787ace3..609ad38e968 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -87,6 +87,7 @@ S32 LLViewerTexture::sRawCount = 0; S32 LLViewerTexture::sAuxCount = 0; LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; +U32 LLViewerTexture::sBiasTexturesUpdated = 0; S32 LLViewerTexture::sMaxSculptRez = 128; //max sculpt image size constexpr S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64; @@ -107,12 +108,6 @@ LLViewerTexture::EDebugTexels LLViewerTexture::sDebugTexelsMode = LLViewerTextur const F64 log_2 = log(2.0); -#if ADDRESS_SIZE == 32 -const U32 DESIRED_NORMAL_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT / 2; -#else -const U32 DESIRED_NORMAL_TEXTURE_SIZE = (U32)LLViewerFetchedTexture::MAX_IMAGE_SIZE_DEFAULT; -#endif - //---------------------------------------------------------------------------------------------- //namespace: LLViewerTextureAccess //---------------------------------------------------------------------------------------------- @@ -518,6 +513,7 @@ void LLViewerTexture::updateClass() bool is_sys_low = isSystemMemoryLow(); bool is_low = is_sys_low || over_pct > 0.f; + F32 discard_bias = sDesiredDiscardBias; static bool was_low = false; static bool was_sys_low = false; @@ -556,12 +552,13 @@ void LLViewerTexture::updateClass() // don't execute above until the slam to 1.5 has a chance to take effect sEvaluationTimer.reset(); - // lower discard bias over time when free memory is available - if (sDesiredDiscardBias > 1.f && over_pct < 0.f) + // lower discard bias over time when at least 10% of budget is free + const F32 FREE_PERCENTAGE_TRESHOLD = -0.1f; + if (sDesiredDiscardBias > 1.f && over_pct < FREE_PERCENTAGE_TRESHOLD) { static LLCachedControl high_mem_discard_decrement(gSavedSettings, "RenderHighMemMinDiscardDecrement", .1f); - F32 decrement = high_mem_discard_decrement - llmin(over_pct, 0.f); + F32 decrement = high_mem_discard_decrement - llmin(over_pct - FREE_PERCENTAGE_TRESHOLD, 0.f); sDesiredDiscardBias -= decrement * gFrameIntervalSeconds; } } @@ -603,6 +600,12 @@ void LLViewerTexture::updateClass() } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, 1.f, 4.f); + if (discard_bias != sDesiredDiscardBias) + { + // bias changed, reset texture update counter to + // let updates happen at an increased rate. + sBiasTexturesUpdated = 0; + } LLViewerTexture::sFreezeImageUpdates = false; } @@ -1685,6 +1688,16 @@ void LLViewerFetchedTexture::processTextureStats() static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes", false); + U32 max_tex_res = MAX_IMAGE_SIZE_DEFAULT; + if (mBoostLevel < LLGLTexture::BOOST_HIGH) + { + // restrict texture resolution to download based on RenderMaxTextureResolution + static LLCachedControl max_texture_resolution(gSavedSettings, "RenderMaxTextureResolution", 2048); + // sanity clamp debug setting to avoid settings hack shenanigans + max_tex_res = (U32)llclamp((U32)max_texture_resolution, 512, MAX_IMAGE_SIZE_DEFAULT); + mMaxVirtualSize = llmin(mMaxVirtualSize, (F32)(max_tex_res * max_tex_res)); + } + if (textures_fullres) { mDesiredDiscardLevel = 0; @@ -1706,10 +1719,9 @@ void LLViewerFetchedTexture::processTextureStats() } else { - U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 if(!mKnownDrawWidth || !mKnownDrawHeight || (S32)mFullWidth <= mKnownDrawWidth || (S32)mFullHeight <= mKnownDrawHeight) { - if (mFullWidth > desired_size || mFullHeight > desired_size) + if (mFullWidth > max_tex_res || mFullHeight > max_tex_res) { mDesiredDiscardLevel = 1; } @@ -2913,8 +2925,6 @@ LLViewerLODTexture::LLViewerLODTexture(const std::string& url, FTType f_type, co void LLViewerLODTexture::init(bool firstinit) { mTexelsPerImage = 64*64; - mDiscardVirtualSize = 0.f; - mCalculatedDiscardLevel = -1.f; } //virtual @@ -2939,12 +2949,14 @@ void LLViewerLODTexture::processTextureStats() static LLCachedControl textures_fullres(gSavedSettings,"TextureLoadFullRes", false); - { // restrict texture resolution to download based on RenderMaxTextureResolution + F32 max_tex_res = MAX_IMAGE_SIZE_DEFAULT; + if (mBoostLevel < LLGLTexture::BOOST_HIGH) + { + // restrict texture resolution to download based on RenderMaxTextureResolution static LLCachedControl max_texture_resolution(gSavedSettings, "RenderMaxTextureResolution", 2048); // sanity clamp debug setting to avoid settings hack shenanigans - F32 tex_res = (F32)llclamp((S32)max_texture_resolution, 512, 2048); - tex_res *= tex_res; - mMaxVirtualSize = llmin(mMaxVirtualSize, tex_res); + max_tex_res = (F32)llclamp((S32)max_texture_resolution, 512, MAX_IMAGE_SIZE_DEFAULT); + mMaxVirtualSize = llmin(mMaxVirtualSize, max_tex_res * max_tex_res); } if (textures_fullres) @@ -2993,19 +3005,12 @@ void LLViewerLODTexture::processTextureStats() { // Calculate the required scale factor of the image using pixels per texel discard_level = (F32)(log(mTexelsPerImage / mMaxVirtualSize) / log_4); - mDiscardVirtualSize = mMaxVirtualSize; - mCalculatedDiscardLevel = discard_level; } discard_level = floorf(discard_level); F32 min_discard = 0.f; - U32 desired_size = MAX_IMAGE_SIZE_DEFAULT; // MAX_IMAGE_SIZE_DEFAULT = 2048 and max size ever is 4096 - if (mBoostLevel <= LLGLTexture::BOOST_SCULPTED) - { - desired_size = DESIRED_NORMAL_TEXTURE_SIZE; - } - if (mFullWidth > desired_size || mFullHeight > desired_size) + if (mFullWidth > max_tex_res || mFullHeight > max_tex_res) min_discard = 1.f; discard_level = llclamp(discard_level, min_discard, (F32)MAX_DISCARD_LEVEL); @@ -3543,18 +3548,7 @@ void LLViewerMediaTexture::setPlaying(bool playing) for(std::list< LLFace* >::iterator iter = mMediaFaceList.begin(); iter!= mMediaFaceList.end(); ++iter) { LLFace* facep = *iter; - const LLTextureEntry* te = facep->getTextureEntry(); - if (te->getGLTFMaterial()) - { - // PBR material, switch emissive and basecolor - switchTexture(LLRender::EMISSIVE_MAP, *iter); - switchTexture(LLRender::BASECOLOR_MAP, *iter); - } - else - { - // blinn-phong material, switch diffuse map only - switchTexture(LLRender::DIFFUSE_MAP, *iter); - } + switchTexture(LLRender::DIFFUSE_MAP, facep); } } else //stop playing this media diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 4241ef958f9..e1582c74bd9 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -220,6 +220,7 @@ class LLViewerTexture : public LLGLTexture static S32 sAuxCount; static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; + static U32 sBiasTexturesUpdated; static S32 sMaxSculptRez ; static U32 sMinLargeImageSize ; static U32 sMaxSmallImageSize ; @@ -540,10 +541,6 @@ class LLViewerLODTexture : public LLViewerFetchedTexture private: void init(bool firstinit) ; - -private: - F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard - F32 mCalculatedDiscardLevel; // Last calculated discard level }; // diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 0b79c2d8e01..12543089c9c 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -266,7 +266,7 @@ void LLViewerTextureList::doPrefetchImages() S32 pixel_area = imagesd["area"]; S32 texture_type = imagesd["type"]; - if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type) + if((LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type)) { LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, texture_type); if (image) @@ -1081,7 +1081,8 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time) imagep->mCreatePending = false; mCreateTextureList.pop(); - if (imagep->hasGLTexture() && imagep->getDiscardLevel() < imagep->getDesiredDiscardLevel()) + if (imagep->hasGLTexture() && imagep->getDiscardLevel() < imagep->getDesiredDiscardLevel() && + (imagep->getDesiredDiscardLevel() <= MAX_DISCARD_LEVEL)) { // NOTE: this may happen if the desired discard reduces while a decode is in progress and does not // necessarily indicate a problem, but if log occurrences excede that of dsiplay_stats: FPS, @@ -1198,10 +1199,17 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) //update MIN_UPDATE_COUNT or 5% of other textures, whichever is greater update_count = llmax((U32) MIN_UPDATE_COUNT, (U32) mUUIDMap.size()/20); - if (LLViewerTexture::sDesiredDiscardBias > 1.f) + if (LLViewerTexture::sDesiredDiscardBias > 1.f + && LLViewerTexture::sBiasTexturesUpdated < (U32)mUUIDMap.size()) { - // we are over memory target, update more agresively + // We are over memory target. Bias affects discard rates, so update + // existing textures agresively to free memory faster. update_count = (S32)(update_count * LLViewerTexture::sDesiredDiscardBias); + + // This isn't particularly precise and can overshoot, but it doesn't need + // to be, just making sure it did a full circle and doesn't get stuck updating + // at bias = 4 with 4 times the rate permanently. + LLViewerTexture::sBiasTexturesUpdated += update_count; } update_count = llmin(update_count, (U32) mUUIDMap.size()); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 8a5aac9b8b8..1795d62adc9 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1331,7 +1331,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi // Check the whitelist, if there's media (otherwise just show it) if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url)) { - if ( obj != mDragHoveredObject) + if ( obj != mDragHoveredObject.get()) { // Highlight the dragged object LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject); @@ -1746,6 +1746,7 @@ bool LLViewerWindow::handleDeviceChange(LLWindow *window) bool LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height) { + LLFontGL::sResolutionGeneration++; if (ui_scale_factor >= MIN_UI_SCALE && ui_scale_factor <= MAX_UI_SCALE) { LLViewerWindow::reshape(window_width, window_height); @@ -1759,6 +1760,12 @@ bool LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 } } +bool LLViewerWindow::handleDisplayChanged() +{ + LLFontGL::sResolutionGeneration++; + return false; +} + bool LLViewerWindow::handleWindowDidChangeScreen(LLWindow *window) { LLCoordScreen window_rect; @@ -1927,6 +1934,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); mDisplayScale *= ui_scale_factor; LLUI::setScaleFactor(mDisplayScale); + LLFontGL::sResolutionGeneration++; { LLCoordWindow size; @@ -2494,6 +2502,7 @@ void LLViewerWindow::reshape(S32 width, S32 height) bool display_scale_changed = mDisplayScale != LLUI::getScaleFactor(); LLUI::setScaleFactor(mDisplayScale); + LLFontGL::sResolutionGeneration++; // update our window rectangle mWindowRectScaled.mRight = mWindowRectScaled.mLeft + ll_round((F32)width / mDisplayScale.mV[VX]); diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index 1b995ea6501..fbc2c58fbf9 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -225,6 +225,7 @@ class LLViewerWindow : public LLWindowCallbacks /*virtual*/ bool handleTimerEvent(LLWindow *window); /*virtual*/ bool handleDeviceChange(LLWindow *window); /*virtual*/ bool handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height); + /*virtual*/ bool handleDisplayChanged(); /*virtual*/ bool handleWindowDidChangeScreen(LLWindow *window); /*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 7bc9d06f9ab..7bf9c88b998 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -1928,8 +1928,8 @@ bool LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& glm::mat4 inverse = glm::inverse(mat); glm::mat4 norm_mat = glm::transpose(inverse); - glm::vec3 p1(glm::make_vec3(start.getF32ptr())); - glm::vec3 p2(glm::make_vec3(end.getF32ptr())); + glm::vec3 p1(start); + glm::vec3 p2(end); p1 = mul_mat4_vec3(inverse, p1); p2 = mul_mat4_vec3(inverse, p2); @@ -1937,12 +1937,12 @@ bool LLVOAvatar::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& LLVector3 position; LLVector3 norm; - if (linesegment_sphere(LLVector3(glm::value_ptr(p1)), LLVector3(glm::value_ptr(p2)), LLVector3(0,0,0), 1.f, position, norm)) + if (linesegment_sphere(LLVector3(p1), LLVector3(p2), LLVector3(0,0,0), 1.f, position, norm)) { - glm::vec3 res_pos(glm::make_vec3(position.mV)); + glm::vec3 res_pos(position); res_pos = mul_mat4_vec3(mat, res_pos); - glm::vec3 res_norm(glm::make_vec3(norm.mV)); + glm::vec3 res_norm(norm); res_norm = glm::normalize(res_norm); res_norm = glm::mat3(norm_mat) * res_norm; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 623d8deac90..3edd2b473c3 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -285,6 +285,7 @@ void LLVoiceClient::setNonSpatialVoiceModule(const std::string &voice_server_typ void LLVoiceClient::setHidden(bool hidden) { + LL_INFOS("Voice") << "( " << (hidden ? "true" : "false") << " )" << LL_ENDL; LLWebRTCVoiceClient::getInstance()->setHidden(hidden); LLVivoxVoiceClient::getInstance()->setHidden(hidden); } diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 7d6ad743bdf..8792ae3285a 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -2004,7 +2004,7 @@ bool LLVivoxVoiceClient::waitForChannel() { recordingAndPlaybackMode(); } - else if (mProcessChannels && (mNextAudioSession == NULL) && checkParcelChanged()) + else if (mProcessChannels && ((mNextAudioSession == NULL) || checkParcelChanged())) { // the parcel is changed, or we have no pending audio sessions, // so try to request the parcel voice info diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp index b2e5de53719..93c217a7bae 100644 --- a/indra/newview/llvoicewebrtc.cpp +++ b/indra/newview/llvoicewebrtc.cpp @@ -345,6 +345,8 @@ void LLWebRTCVoiceClient::updateSettings() static LLCachedControl sOutputDevice(gSavedSettings, "VoiceOutputAudioDevice"); setRenderDevice(sOutputDevice); + LL_INFOS("Voice") << "Input device: " << std::quoted(sInputDevice()) << ", output device: " << std::quoted(sOutputDevice()) << LL_ENDL; + static LLCachedControl sMicLevel(gSavedSettings, "AudioLevelMic"); setMicGain(sMicLevel); @@ -554,7 +556,7 @@ void LLWebRTCVoiceClient::voiceConnectionCoro() } } LL::WorkQueue::postMaybe(mMainQueue, - [=] { + [=, this] { if (sShuttingDown) { return; @@ -672,7 +674,7 @@ void LLWebRTCVoiceClient::OnDevicesChanged(const llwebrtc::LLWebRTCVoiceDeviceLi { LL::WorkQueue::postMaybe(mMainQueue, - [=] + [=, this] { OnDevicesChangedImpl(render_devices, capture_devices); }); @@ -896,7 +898,7 @@ void LLWebRTCVoiceClient::OnConnectionShutDown(const std::string &channelID, con { if (mSession && mSession->mChannelID == channelID) { - LL_DEBUGS("Voice") << "Main WebRTC Connection Shut Down." << LL_ENDL; + LL_INFOS("Voice") << "Main WebRTC Connection Shut Down." << LL_ENDL; } } mSession->removeAllParticipants(regionID); @@ -1504,6 +1506,11 @@ bool LLWebRTCVoiceClient::compareChannels(const LLSD &channelInfo1, const LLSD & // we're muting the mic, so tell each session such void LLWebRTCVoiceClient::setMuteMic(bool muted) { + if (mMuteMic != muted) + { + LL_INFOS("Voice") << "( " << (muted ? "true" : "false") << " )" << LL_ENDL; + } + mMuteMic = muted; // when you're hidden, your mic is always muted. if (!mHidden) @@ -1552,14 +1559,10 @@ void LLWebRTCVoiceClient::setVoiceEnabled(bool enabled) { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE; - LL_DEBUGS("Voice") - << "( " << (enabled ? "enabled" : "disabled") << " )" - << " was "<< (mVoiceEnabled ? "enabled" : "disabled") - << " coro "<< (mIsCoroutineActive ? "active" : "inactive") - << LL_ENDL; - if (enabled != mVoiceEnabled) { + LL_INFOS("Voice") << "( " << (enabled ? "enabled" : "disabled") << " )" + << ", coro: " << (mIsCoroutineActive ? "active" : "inactive") << LL_ENDL; // TODO: Refactor this so we don't call into LLVoiceChannel, but simply // use the status observer mVoiceEnabled = enabled; @@ -2208,7 +2211,7 @@ LLVoiceWebRTCConnection::~LLVoiceWebRTCConnection() void LLVoiceWebRTCConnection::OnIceGatheringState(llwebrtc::LLWebRTCSignalingObserver::EIceGatheringState state) { LL::WorkQueue::postMaybe(mMainQueue, - [=] { + [=, this] { LL_DEBUGS("Voice") << "Ice Gathering voice account. " << state << LL_ENDL; switch (state) @@ -2231,7 +2234,7 @@ void LLVoiceWebRTCConnection::OnIceGatheringState(llwebrtc::LLWebRTCSignalingObs // callback from llwebrtc void LLVoiceWebRTCConnection::OnIceCandidate(const llwebrtc::LLWebRTCIceCandidate& candidate) { - LL::WorkQueue::postMaybe(mMainQueue, [=] { mIceCandidates.push_back(candidate); }); + LL::WorkQueue::postMaybe(mMainQueue, [=, this] { mIceCandidates.push_back(candidate); }); } void LLVoiceWebRTCConnection::processIceUpdates() @@ -2349,7 +2352,7 @@ void LLVoiceWebRTCConnection::processIceUpdatesCoro(connectionPtr_t connection) void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp) { LL::WorkQueue::postMaybe(mMainQueue, - [=] { + [=, this] { if (mShutDown) { return; @@ -2376,7 +2379,7 @@ void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp) void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface* audio_interface) { LL::WorkQueue::postMaybe(mMainQueue, - [=] { + [=, this] { if (mShutDown) { return; @@ -2398,7 +2401,7 @@ void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterfac void LLVoiceWebRTCConnection::OnRenegotiationNeeded() { LL::WorkQueue::postMaybe(mMainQueue, - [=] { + [=, this] { LL_DEBUGS("Voice") << "Voice channel requires renegotiation." << LL_ENDL; if (!mShutDown) { @@ -2412,7 +2415,7 @@ void LLVoiceWebRTCConnection::OnRenegotiationNeeded() void LLVoiceWebRTCConnection::OnPeerConnectionClosed() { LL::WorkQueue::postMaybe(mMainQueue, - [=] { + [=, this] { LL_DEBUGS("Voice") << "Peer connection has closed." << LL_ENDL; if (mVoiceConnectionState == VOICE_STATE_WAIT_FOR_CLOSE) { @@ -2483,7 +2486,7 @@ void LLVoiceWebRTCConnection::breakVoiceConnectionCoro(connectionPtr_t connectio { LL_PROFILE_ZONE_SCOPED_CATEGORY_VOICE; - LL_DEBUGS("Voice") << "Disconnecting voice." << LL_ENDL; + LL_INFOS("Voice") << "Disconnecting voice." << LL_ENDL; if (connection->mWebRTCDataInterface) { connection->mWebRTCDataInterface->unsetDataObserver(connection.get()); @@ -2591,6 +2594,7 @@ void LLVoiceWebRTCSpatialConnection::requestVoiceConnection() LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + LL_INFOS("Voice") << "Voice connection request: " << (status ? "Success" : status.toString()) << LL_ENDL; if (status) { OnVoiceConnectionRequestSuccess(result); @@ -2884,7 +2888,7 @@ bool LLVoiceWebRTCConnection::connectionStateMachine() // llwebrtc callback void LLVoiceWebRTCConnection::OnDataReceived(const std::string& data, bool binary) { - LL::WorkQueue::postMaybe(mMainQueue, [=] { LLVoiceWebRTCConnection::OnDataReceivedImpl(data, binary); }); + LL::WorkQueue::postMaybe(mMainQueue, [=, this] { LLVoiceWebRTCConnection::OnDataReceivedImpl(data, binary); }); } // @@ -3040,7 +3044,7 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface) { LL::WorkQueue::postMaybe(mMainQueue, - [=] { + [=, this] { if (mShutDown) { return; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 6514db08142..4e8932f9121 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -645,8 +645,12 @@ void LLVOVolume::animateTextures() // LLVOVolume::updateTextureVirtualSize when the // mTextureMatrix is not yet present gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - mDrawable->getSpatialGroup()->dirtyGeom(); - gPipeline.markRebuild(mDrawable->getSpatialGroup()); + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->dirtyGeom(); + gPipeline.markRebuild(group); + } } } @@ -5735,13 +5739,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) continue; } - LLFetchedGLTFMaterial *gltf_mat = (LLFetchedGLTFMaterial*) facep->getTextureEntry()->getGLTFRenderMaterial(); + LLFetchedGLTFMaterial* gltf_mat = nullptr; + const LLTextureEntry* te = facep->getTextureEntry(); + if (te) + { + gltf_mat = (LLFetchedGLTFMaterial*)te->getGLTFRenderMaterial(); + } // if not te, continue? bool is_pbr = gltf_mat != nullptr; if (is_pbr) { // tell texture streaming system to ignore blinn-phong textures - facep->setTexture(LLRender::DIFFUSE_MAP, nullptr); + // except the special case of the diffuse map containing a + // media texture that will be reused for swapping on to the pbr face + if (!facep->hasMedia()) + { + facep->setTexture(LLRender::DIFFUSE_MAP, nullptr); + } facep->setTexture(LLRender::NORMAL_MAP, nullptr); facep->setTexture(LLRender::SPECULAR_MAP, nullptr); @@ -5797,10 +5811,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { cur_total += facep->getGeomCount(); - const LLTextureEntry* te = facep->getTextureEntry(); LLViewerTexture* tex = facep->getTexture(); - if (te->getGlow() > 0.f) + if (te && te->getGlow() > 0.f) { emissive = true; } @@ -5895,6 +5908,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->mLastUpdateTime = gFrameTimeSeconds; } + if (te) { LLGLTFMaterial* gltf_mat = te->getGLTFRenderMaterial(); @@ -5959,6 +5973,11 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) add_face(sFullbrightFaces, fullbright_count, facep); } } + else // no texture entry + { + facep->setState(LLFace::FULLBRIGHT); + add_face(sFullbrightFaces, fullbright_count, facep); + } } } else @@ -6713,8 +6732,11 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { //shiny if (tex->getPrimaryFormat() == GL_ALPHA) { //invisiprim+shiny - registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + if (!facep->getViewerObject()->isAttachment() && !facep->getViewerObject()->isRiggedMesh()) + { + registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } } else if (!hud_group) { //deferred rendering @@ -6750,7 +6772,10 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace { //not alpha and not shiny if (!is_alpha && tex->getPrimaryFormat() == GL_ALPHA) { //invisiprim - registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + if (!facep->getViewerObject()->isAttachment() && !facep->getViewerObject()->isRiggedMesh()) + { + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } } else if (fullbright || bake_sunlight) { //fullbright diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 1ca67dd88ac..18dd694246b 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -431,6 +431,7 @@ void LLPipeline::init() stop_glerror(); //create render pass pools + getPool(LLDrawPool::POOL_WATEREXCLUSION); getPool(LLDrawPool::POOL_ALPHA_PRE_WATER); getPool(LLDrawPool::POOL_ALPHA_POST_WATER); getPool(LLDrawPool::POOL_SIMPLE); @@ -673,6 +674,8 @@ void LLPipeline::cleanup() // don't delete wl sky pool it was handled above in the for loop //delete mWLSkyPool; mWLSkyPool = NULL; + delete mWaterExclusionPool; + mWaterExclusionPool = nullptr; releaseGLBuffers(); @@ -907,6 +910,15 @@ bool LLPipeline::allocateScreenBufferInternal(U32 resX, U32 resY) mPostMap.allocate(resX, resY, screenFormat); + // The water exclusion mask needs its own depth buffer so we can take care of the problem of multiple water planes. + // Should we ever make water not just a plane, it also aids with that as well as the water planes will be rendered into the mask. + // Why do we do this? Because it saves us some janky logic in the exclusion shader when we generate the mask. + // Regardless, this should always only be an R8 texture unless we choose to start having multiple kinds of exclusion that 8 bits can't handle. + // - Geenz 2025-02-06 + bool success = mWaterExclusionMask.allocate(resX, resY, GL_R8, true); + + assert(success); + // used to scale down textures // See LLViwerTextureList::updateImagesCreateTextures and LLImageGL::scaleDown mDownResMap.allocate(1024, 1024, GL_RGBA); @@ -1166,6 +1178,8 @@ void LLPipeline::releaseGLBuffers() mSceneMap.release(); + mWaterExclusionMask.release(); + mPostMap.release(); mFXAAMap.release(); @@ -1676,6 +1690,10 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerTexture *tex0) poolp = mPBRAlphaMaskPool; break; + case LLDrawPool::POOL_WATEREXCLUSION: + poolp = mWaterExclusionPool; + break; + default: llassert(0); LL_ERRS() << "Invalid Pool Type in LLPipeline::findPool() type=" << type << LL_ENDL; @@ -3855,7 +3873,12 @@ void LLPipeline::renderSelectedFaces(const LLColor4& color) for (auto facep : mSelectedFaces) { - if (!facep || facep->getDrawable()->isDead()) + if (!facep || !facep->getViewerObject()) + { + LLSelectMgr::getInstance()->clearSelections(); + return; + } + if (!facep->getDrawable() || facep->getDrawable()->isDead()) { LL_ERRS() << "Bad face on selection" << LL_ENDL; return; @@ -4063,6 +4086,8 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera, bool do_occlusion) } } +// Render all of our geometry that's required after our deferred pass. +// This is gonna be stuff like alpha, water, etc. void LLPipeline::renderGeomPostDeferred(LLCamera& camera) { LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL; @@ -4079,6 +4104,10 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) bool done_atmospherics = LLPipeline::sRenderingHUDs; //skip atmospherics on huds bool done_water_haze = done_atmospherics; + bool done_water_exclusion = false; + + // do water exclusion just before water pass. + U32 water_exclusion_pass = LLDrawPool::POOL_WATEREXCLUSION; // do atmospheric haze just before post water alpha U32 atmospherics_pass = LLDrawPool::POOL_ALPHA_POST_WATER; @@ -4117,6 +4146,12 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) cur_type = poolp->getType(); + if (cur_type >= water_exclusion_pass && !done_water_exclusion) + { // do water exclusion against depth buffer before rendering alpha + doWaterExclusionMask(); + done_water_exclusion = true; + } + if (cur_type >= atmospherics_pass && !done_atmospherics) { // do atmospherics against depth buffer before rendering alpha doAtmospherics(); @@ -5196,6 +5231,17 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) } break; + case LLDrawPool::POOL_WATEREXCLUSION: + if (mWaterExclusionPool) + { + llassert(0); + LL_WARNS() << "LLPipeline::addPool(): Ignoring duplicate Water Exclusion Pool" << LL_ENDL; + } + else + { + mWaterExclusionPool = new_poolp; + } + break; default: llassert(0); @@ -5318,6 +5364,11 @@ void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) mPBRAlphaMaskPool = NULL; break; + case LLDrawPool::POOL_WATEREXCLUSION: + llassert(poolp == mWaterExclusionPool); + mWaterExclusionPool = nullptr; + break; + default: llassert(0); LL_WARNS() << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << LL_ENDL; @@ -7076,7 +7127,7 @@ void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool LLSettingsSky::ptr_t sky = LLEnvironment::instance().getCurrentSky(); - F32 probe_ambiance = LLEnvironment::instance().getCurrentSky()->getReflectionProbeAmbiance(should_auto_adjust); + F32 probe_ambiance = LLEnvironment::instance().getCurrentSky()->getReflectionProbeAmbiance(should_auto_adjust()); F32 exp_min = 1.f; F32 exp_max = 1.f; @@ -7087,13 +7138,13 @@ void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool { if (dynamic_exposure_enabled) { - exp_min = sky->getHDROffset() - sky->getHDRMin(); - exp_max = sky->getHDROffset() + sky->getHDRMax(); + exp_min = sky->getHDROffset(should_auto_adjust()) - sky->getHDRMin(should_auto_adjust()); + exp_max = sky->getHDROffset(should_auto_adjust()) + sky->getHDRMax(should_auto_adjust()); } else { - exp_min = sky->getHDROffset(); - exp_max = sky->getHDROffset(); + exp_min = sky->getHDROffset(should_auto_adjust()); + exp_max = sky->getHDROffset(should_auto_adjust()); } } else if (dynamic_exposure_enabled) @@ -7113,7 +7164,7 @@ void LLPipeline::generateExposure(LLRenderTarget* src, LLRenderTarget* dst, bool shader->uniform1f(dt, gFrameIntervalSeconds); shader->uniform2f(noiseVec, ll_frand() * 2.0f - 1.0f, ll_frand() * 2.0f - 1.0f); shader->uniform4f(dynamic_exposure_params, dynamic_exposure_coefficient, exp_min, exp_max, dynamic_exposure_speed_error); - shader->uniform4f(dynamic_exposure_params2, sky->getHDROffset(), exp_min, exp_max, dynamic_exposure_speed_target); + shader->uniform4f(dynamic_exposure_params2, sky->getHDROffset(should_auto_adjust()), exp_min, exp_max, dynamic_exposure_speed_target); mScreenTriangleVB->setBuffer(); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -7171,7 +7222,7 @@ void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst) static LLCachedControl tonemap_type_setting(gSavedSettings, "RenderTonemapType", 0U); shader.uniform1i(tonemap_type, tonemap_type_setting); - shader.uniform1f(tonemap_mix, psky->getTonemapMix()); + shader.uniform1f(tonemap_mix, psky->getTonemapMix(should_auto_adjust())); mScreenTriangleVB->setBuffer(); mScreenTriangleVB->drawArrays(LLRender::TRIANGLES, 0, 3); @@ -8391,13 +8442,13 @@ void LLPipeline::renderDeferredLighting() setupHWLights(); // to set mSun/MoonDir; - glm::vec4 tc(glm::make_vec4(mSunDir.mV)); + glm::vec4 tc(mSunDir); tc = mat * tc; - mTransformedSunDir.set(glm::value_ptr(tc)); + mTransformedSunDir.set(tc); - glm::vec4 tc_moon(glm::make_vec4(mMoonDir.mV)); + glm::vec4 tc_moon(mMoonDir); tc_moon = mat * tc_moon; - mTransformedMoonDir.set(glm::value_ptr(tc_moon)); + mTransformedMoonDir.set(tc_moon); if ((RenderDeferredSSAO && !gCubeSnapshot) || RenderShadowDetail > 0) { @@ -8650,7 +8701,7 @@ void LLPipeline::renderDeferredLighting() continue; } - glm::vec3 tc(glm::make_vec3(c)); + glm::vec3 tc(center); tc = mul_mat4_vec3(mat, tc); fullscreen_lights.push_back(LLVector4(tc.x, tc.y, tc.z, s)); @@ -8757,13 +8808,12 @@ void LLPipeline::renderDeferredLighting() LLDrawable* drawablep = *iter; LLVOVolume* volume = drawablep->getVOVolume(); LLVector3 center = drawablep->getPositionAgent(); - F32* c = center.mV; F32 light_size_final = volume->getLightRadius() * 1.5f; F32 light_falloff_final = volume->getLightFalloff(DEFERRED_LIGHT_FALLOFF); sVisibleLightCount++; - glm::vec3 tc(glm::make_vec3(c)); + glm::vec3 tc(center); tc = mul_mat4_vec3(mat, tc); setupSpotLight(gDeferredMultiSpotLightProgram, drawablep); @@ -8820,6 +8870,7 @@ void LLPipeline::renderDeferredLighting() LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK, LLPipeline::RENDER_TYPE_TERRAIN, LLPipeline::RENDER_TYPE_WATER, + LLPipeline::RENDER_TYPE_WATEREXCLUSION, END_RENDER_TYPES); renderGeomPostDeferred(*LLViewerCamera::getInstance()); @@ -8958,6 +9009,8 @@ void LLPipeline::doWaterHaze() static LLStaticHashedString above_water_str("above_water"); haze_shader.uniform1i(above_water_str, sUnderWaterRender ? -1 : 1); + haze_shader.bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &mWaterExclusionMask); + if (LLPipeline::sUnderWaterRender) { LLGLDepthTest depth(GL_FALSE); @@ -8988,6 +9041,17 @@ void LLPipeline::doWaterHaze() } } +void LLPipeline::doWaterExclusionMask() +{ + mWaterExclusionMask.bindTarget(); + glClearColor(1, 1, 1, 1); + mWaterExclusionMask.clear(); + mWaterExclusionPool->render(); + + mWaterExclusionMask.flush(); + glClearColor(0, 0, 0, 0); +} + void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) { //construct frustum @@ -9898,10 +9962,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLVector3 lightDir = -caster_dir; lightDir.normVec(); - glm::vec3 light_dir(glm::make_vec3(lightDir.mV)); - //create light space camera matrix - LLVector3 at = lightDir; LLVector3 up = camera.getAtAxis(); @@ -9953,9 +10014,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera) //get good split distances for frustum for (U32 i = 0; i < fp.size(); ++i) { - glm::vec3 v(glm::make_vec3(fp[i].mV)); + glm::vec3 v(fp[i]); v = mul_mat4_vec3(saved_view, v); - fp[i].setVec(glm::value_ptr(v)); + fp[i] = LLVector3(v); } min = fp[0]; @@ -10104,9 +10165,9 @@ void LLPipeline::generateSunShadow(LLCamera& camera) for (U32 i = 0; i < fp.size(); i++) { - glm::vec3 p = glm::make_vec3(fp[i].mV); + glm::vec3 p(fp[i]); p = mul_mat4_vec3(view[j], p); - wpf.push_back(LLVector3(glm::value_ptr(p))); + wpf.push_back(LLVector3(p)); } min = wpf[0]; @@ -10307,19 +10368,19 @@ void LLPipeline::generateSunShadow(LLCamera& camera) view[j] = glm::inverse(view[j]); //llassert(origin.isFinite()); - glm::vec3 origin_agent(glm::make_vec3(origin.mV)); + glm::vec3 origin_agent(origin); //translate view to origin origin_agent = mul_mat4_vec3(view[j], origin_agent); - eye = LLVector3(glm::value_ptr(origin_agent)); + eye = LLVector3(origin_agent); //llassert(eye.isFinite()); if (!hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA) && !gCubeSnapshot) { mShadowFrustOrigin[j] = eye; } - view[j] = look(LLVector3(glm::value_ptr(origin_agent)), lightDir, -up); + view[j] = look(LLVector3(origin_agent), lightDir, -up); F32 fx = 1.f/tanf(fovx); F32 fz = 1.f/tanf(fovz); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 5c9b95ef4aa..315e38ed8c7 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -337,6 +337,9 @@ class LLPipeline // should be called just before rendering pre-water alpha objects void doWaterHaze(); + // Generate the water exclusion surface mask. + void doWaterExclusionMask(); + void postDeferredGammaCorrect(LLRenderTarget* screen_target); void generateSunShadow(LLCamera& camera); @@ -500,6 +503,7 @@ class LLPipeline RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, RENDER_TYPE_CONTROL_AV = LLDrawPool::POOL_CONTROL_AV, // Animesh RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, + RENDER_TYPE_WATEREXCLUSION = LLDrawPool::POOL_WATEREXCLUSION, RENDER_TYPE_VOIDWATER = LLDrawPool::POOL_VOIDWATER, RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, RENDER_TYPE_GLTF_PBR = LLDrawPool::POOL_GLTF_PBR, @@ -714,6 +718,7 @@ class LLPipeline LLRenderTarget mSpotShadow[2]; LLRenderTarget mPbrBrdfLut; + LLRenderTarget mWaterExclusionMask; // copy of the color/depth buffer just before gamma correction // for use by SSR @@ -953,6 +958,7 @@ class LLPipeline LLDrawPool* mWLSkyPool = nullptr; LLDrawPool* mPBROpaquePool = nullptr; LLDrawPool* mPBRAlphaMaskPool = nullptr; + LLDrawPool* mWaterExclusionPool = nullptr; // Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar diff --git a/indra/newview/skins/default/textures/3p_icons/fmod_logo.png b/indra/newview/skins/default/textures/3p_icons/fmod_logo.png deleted file mode 100644 index 5a50e0ad34b..00000000000 Binary files a/indra/newview/skins/default/textures/3p_icons/fmod_logo.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/3p_icons/havok_logo.png b/indra/newview/skins/default/textures/3p_icons/havok_logo.png deleted file mode 100644 index ff1ea3a72e8..00000000000 Binary files a/indra/newview/skins/default/textures/3p_icons/havok_logo.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/3p_icons/vivox_logo.png b/indra/newview/skins/default/textures/3p_icons/vivox_logo.png deleted file mode 100644 index 6f20e87b7ae..00000000000 Binary files a/indra/newview/skins/default/textures/3p_icons/vivox_logo.png and /dev/null differ diff --git a/indra/newview/skins/default/xui/de/panel_progress.xml b/indra/newview/skins/default/xui/de/panel_progress.xml index 8d1abdcac10..c9bed9fd9ba 100644 --- a/indra/newview/skins/default/xui/de/panel_progress.xml +++ b/indra/newview/skins/default/xui/de/panel_progress.xml @@ -1,10 +1,8 @@ - - Second Life verwendet diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml index 65b98c65cf3..96de9e61cb1 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml @@ -1,6 +1,6 @@ + + Maximum LOD resolution: + + + + + + Avatar display: @@ -160,10 +195,10 @@ + width="130"> Antialiasing: + width="130"> Antialiasing Quality: