diff options
Diffstat (limited to 'indra/llappearance')
| -rw-r--r-- | indra/llappearance/CMakeLists.txt | 12 | ||||
| -rw-r--r-- | indra/llappearance/llavatarappearance.cpp | 67 | ||||
| -rw-r--r-- | indra/llappearance/llavatarappearance.h | 10 | ||||
| -rw-r--r-- | indra/llappearance/llavatarappearancedefines.cpp | 4 | ||||
| -rw-r--r-- | indra/llappearance/llavatarappearancedefines.h | 4 | ||||
| -rw-r--r-- | indra/llappearance/llavatarjoint.h | 6 | ||||
| -rw-r--r-- | indra/llappearance/llavatarjointmesh.h | 3 | ||||
| -rw-r--r-- | indra/llappearance/lldriverparam.h | 2 | ||||
| -rw-r--r-- | indra/llappearance/lljointdata.h | 66 | ||||
| -rw-r--r-- | indra/llappearance/llpolymesh.cpp | 4 | ||||
| -rw-r--r-- | indra/llappearance/llpolymorph.h | 2 | ||||
| -rw-r--r-- | indra/llappearance/llpolyskeletaldistortion.h | 4 | ||||
| -rw-r--r-- | indra/llappearance/lltexlayer.cpp | 88 | ||||
| -rw-r--r-- | indra/llappearance/lltexlayer.h | 2 | ||||
| -rw-r--r-- | indra/llappearance/lltexlayerparams.cpp | 5 | ||||
| -rw-r--r-- | indra/llappearance/lltexlayerparams.h | 7 | ||||
| -rw-r--r-- | indra/llappearance/llviewervisualparam.h | 5 | ||||
| -rw-r--r-- | indra/llappearance/llwearable.cpp | 19 |
18 files changed, 266 insertions, 44 deletions
diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt index f3f822f61c..9f8fb3217d 100644 --- a/indra/llappearance/CMakeLists.txt +++ b/indra/llappearance/CMakeLists.txt @@ -14,6 +14,7 @@ set(llappearance_SOURCE_FILES llavatarjoint.cpp llavatarjointmesh.cpp lldriverparam.cpp + lljointdata.h lllocaltextureobject.cpp llpolyskeletaldistortion.cpp llpolymesh.cpp @@ -27,7 +28,7 @@ set(llappearance_SOURCE_FILES llviewervisualparam.cpp llavatarappearancedefines.cpp ) - + set(llappearance_HEADER_FILES CMakeLists.txt @@ -68,6 +69,10 @@ target_link_libraries(llappearance ) target_include_directories( llappearance INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +if (USE_PRECOMPILED_HEADERS) + target_precompile_headers(llappearance REUSE_FROM llprecompiled) +endif () + if (BUILD_HEADLESS) add_library (llappearanceheadless ${llappearance_SOURCE_FILES}) target_include_directories( llappearanceheadless INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) @@ -76,6 +81,7 @@ if (BUILD_HEADLESS) llcharacter llinventory llimage + llrenderheadless llfilesystem llmath llxml @@ -83,6 +89,10 @@ if (BUILD_HEADLESS) llcorehttp llcommon ) + + if (USE_PRECOMPILED_HEADERS) + target_precompile_headers(llappearanceheadless REUSE_FROM llprecompiled) + endif () endif (BUILD_HEADLESS) include(LibraryInstall) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 3d66809ed6..c8fd2cba70 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -29,16 +29,17 @@ #include "llavatarappearance.h" #include "llavatarappearancedefines.h" #include "llavatarjointmesh.h" +#include "lljointdata.h" #include "llstl.h" #include "lldir.h" #include "llpolymorph.h" #include "llpolymesh.h" #include "llpolyskeletaldistortion.h" -#include "llstl.h" #include "lltexglobalcolor.h" #include "llwearabledata.h" #include "boost/bind.hpp" #include "boost/tokenizer.hpp" +#include "v4math.h" using namespace LLAvatarAppearanceDefines; @@ -71,11 +72,13 @@ public: mChildren.clear(); } bool parseXml(LLXmlTreeNode* node); + glm::mat4 getJointMatrix(); private: std::string mName; std::string mSupport; std::string mAliases; + std::string mGroup; bool mIsJoint; LLVector3 mPos; LLVector3 mEnd; @@ -106,10 +109,16 @@ public: S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; } private: + typedef std::vector<LLAvatarBoneInfo*> bone_info_list_t; + static void getJointMatricesAndHierarhy( + LLAvatarBoneInfo* bone_info, + LLJointData& data, + const glm::mat4& parent_mat); + +private: S32 mNumBones; S32 mNumCollisionVolumes; LLAvatarAppearance::joint_alias_map_t mJointAliasMap; - typedef std::vector<LLAvatarBoneInfo*> bone_info_list_t; bone_info_list_t mBoneInfoList; }; @@ -1598,6 +1607,15 @@ bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) mSupport = "base"; } + // Skeleton has 133 bones, but shader only allows 110 (LL_MAX_JOINTS_PER_MESH_OBJECT) + // Groups can be used by importer to cut out unused groups of joints + static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group"); + if (!node->getFastAttributeString(group_string, mGroup)) + { + LL_WARNS() << "Bone without group " << mName << LL_ENDL; + mGroup = "global"; + } + if (mIsJoint) { static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot"); @@ -1623,6 +1641,21 @@ bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node) return true; } + +glm::mat4 LLAvatarBoneInfo::getJointMatrix() +{ + glm::mat4 mat(1.0f); + // 1. Scaling + mat = glm::scale(mat, glm::vec3(mScale[0], mScale[1], mScale[2])); + // 2. Rotation (avatar_skeleton.xml stores Euler angles in degrees) + mat = glm::rotate(mat, glm::radians(mRot[0]), glm::vec3(1, 0, 0)); + mat = glm::rotate(mat, glm::radians(mRot[1]), glm::vec3(0, 1, 0)); + mat = glm::rotate(mat, glm::radians(mRot[2]), glm::vec3(0, 0, 1)); + // 3. Position + mat = glm::translate(mat, glm::vec3(mPos[0], mPos[1], mPos[2])); + return mat; +} + //----------------------------------------------------------------------------- // LLAvatarSkeletonInfo::parseXml() //----------------------------------------------------------------------------- @@ -1653,6 +1686,26 @@ bool LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) return true; } +void LLAvatarSkeletonInfo::getJointMatricesAndHierarhy( + LLAvatarBoneInfo* bone_info, + LLJointData& data, + const glm::mat4& parent_mat) +{ + data.mName = bone_info->mName; + data.mJointMatrix = bone_info->getJointMatrix(); + data.mScale = glm::vec3(bone_info->mScale[0], bone_info->mScale[1], bone_info->mScale[2]); + data.mRotation = bone_info->mRot; + data.mRestMatrix = parent_mat * data.mJointMatrix; + data.mIsJoint = bone_info->mIsJoint; + data.mGroup = bone_info->mGroup; + data.setSupport(bone_info->mSupport); + for (LLAvatarBoneInfo* child_info : bone_info->mChildren) + { + LLJointData& child_data = data.mChildren.emplace_back(); + getJointMatricesAndHierarhy(child_info, child_data, data.mRestMatrix); + } +} + //Make aliases for joint and push to map. void LLAvatarAppearance::makeJointAliases(LLAvatarBoneInfo *bone_info) { @@ -1714,6 +1767,16 @@ const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases return mJointAliasMap; } +void LLAvatarAppearance::getJointMatricesAndHierarhy(std::vector<LLJointData> &data) const +{ + glm::mat4 identity(1.f); + for (LLAvatarBoneInfo* bone_info : sAvatarSkeletonInfo->mBoneInfoList) + { + LLJointData& child_data = data.emplace_back(); + LLAvatarSkeletonInfo::getJointMatricesAndHierarhy(bone_info, child_data, identity); + } +} + //----------------------------------------------------------------------------- // parseXmlSkeletonNode(): parses <skeleton> nodes from XML tree diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index 13e504e639..84cb42056a 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -34,6 +34,7 @@ #include "lltexlayer.h" #include "llviewervisualparam.h" #include "llxmltree.h" +#include "v4math.h" class LLTexLayerSet; class LLTexGlobalColor; @@ -41,6 +42,7 @@ class LLTexGlobalColorInfo; class LLWearableData; class LLAvatarBoneInfo; class LLAvatarSkeletonInfo; +class LLJointData; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLAvatarAppearance @@ -138,7 +140,7 @@ public: LLVector3 mHeadOffset{}; // current head position LLAvatarJoint* mRoot{ nullptr }; - typedef std::map<std::string, LLJoint*> joint_map_t; + typedef std::map<std::string, LLJoint*, std::less<>> joint_map_t; joint_map_t mJointMap; typedef std::map<std::string, LLVector3> joint_state_map_t; @@ -151,9 +153,11 @@ public: public: typedef std::vector<LLAvatarJoint*> avatar_joint_list_t; const avatar_joint_list_t& getSkeleton() { return mSkeleton; } - typedef std::map<std::string, std::string> joint_alias_map_t; + typedef std::map<std::string, std::string, std::less<>> joint_alias_map_t; const joint_alias_map_t& getJointAliases(); - + typedef std::map<std::string, std::string> joint_parent_map_t; // matrix plus parent + typedef std::map<std::string, glm::mat4> joint_rest_map_t; + void getJointMatricesAndHierarhy(std::vector<LLJointData> &data) const; protected: static bool parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree); diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index 47798844bc..f26795123f 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -260,7 +260,7 @@ ETextureIndex LLAvatarAppearanceDictionary::bakedToLocalTextureIndex(EBakedTextu return getBakedTexture(index)->mTextureIndex; } -EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::string name) +EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(const std::string& name) const { U8 index = 0; while (index < BAKED_NUM_INDICES) @@ -277,7 +277,7 @@ EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByRegionName(std::stri return BAKED_NUM_INDICES; } -EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(std::string name) +EBakedTextureIndex LLAvatarAppearanceDictionary::findBakedByImageName(const std::string& name) const { U8 index = 0; while (index < BAKED_NUM_INDICES) diff --git a/indra/llappearance/llavatarappearancedefines.h b/indra/llappearance/llavatarappearancedefines.h index 50a72a45a5..0f9edc1ca0 100644 --- a/indra/llappearance/llavatarappearancedefines.h +++ b/indra/llappearance/llavatarappearancedefines.h @@ -238,8 +238,8 @@ public: ETextureIndex bakedToLocalTextureIndex(EBakedTextureIndex t) const; // find a baked texture index based on its name - EBakedTextureIndex findBakedByRegionName(std::string name); - EBakedTextureIndex findBakedByImageName(std::string name); + EBakedTextureIndex findBakedByRegionName(const std::string& name) const; + EBakedTextureIndex findBakedByImageName(const std::string& name) const; // Given a texture entry, determine which wearable type owns it. LLWearableType::EType getTEWearableType(ETextureIndex index) const; diff --git a/indra/llappearance/llavatarjoint.h b/indra/llappearance/llavatarjoint.h index 13f025fd5f..71fe4b61b6 100644 --- a/indra/llappearance/llavatarjoint.h +++ b/indra/llappearance/llavatarjoint.h @@ -41,9 +41,10 @@ extern const F32 DEFAULT_AVATAR_JOINT_LOD; //----------------------------------------------------------------------------- // class LLViewerJoint //----------------------------------------------------------------------------- -class LLAvatarJoint : +class alignas(16) LLAvatarJoint : public LLJoint { + LL_ALIGN_NEW public: LLAvatarJoint(); LLAvatarJoint(S32 joint_num); @@ -121,8 +122,9 @@ protected: S32 mMeshID; }; -class LLAvatarJointCollisionVolume : public LLAvatarJoint +class alignas(16) LLAvatarJointCollisionVolume : public LLAvatarJoint { + LL_ALIGN_NEW public: LLAvatarJointCollisionVolume(); virtual ~LLAvatarJointCollisionVolume() {}; diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h index 33f50fce00..153a2b88fe 100644 --- a/indra/llappearance/llavatarjointmesh.h +++ b/indra/llappearance/llavatarjointmesh.h @@ -59,8 +59,9 @@ public: //----------------------------------------------------------------------------- // class LLViewerJointMesh //----------------------------------------------------------------------------- -class LLAvatarJointMesh : public virtual LLAvatarJoint +class alignas(16) LLAvatarJointMesh : public virtual LLAvatarJoint { + LL_ALIGN_NEW protected: LLColor4 mColor; // color value // LLColor4 mSpecular; // specular color (always white for now) diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index 59092988dd..df8733dde7 100644 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -128,7 +128,7 @@ protected: void setDrivenWeight(LLDrivenEntry* driven, F32 driven_weight); - LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder + LLVector4a mDefaultVec; // temp holder entry_list_t mDriven; LLViewerVisualParam* mCurrentDistortionParam{ nullptr }; // Backlink only; don't make this an LLPointer. diff --git a/indra/llappearance/lljointdata.h b/indra/llappearance/lljointdata.h new file mode 100644 index 0000000000..2fc26198ee --- /dev/null +++ b/indra/llappearance/lljointdata.h @@ -0,0 +1,66 @@ +/** + * @file lljointdata.h + * @brief LLJointData class for holding individual joint data and skeleton + * + * $LicenseInfo:firstyear=2025&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2025, 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_LLJOINTDATA_H +#define LL_LLJOINTDATA_H + +#include "v4math.h" + +// may be just move LLAvatarBoneInfo +class LLJointData +{ +public: + std::string mName; + std::string mGroup; + glm::mat4 mJointMatrix; + glm::mat4 mRestMatrix; + glm::vec3 mScale; + LLVector3 mRotation; + + typedef std::vector<LLJointData> bones_t; + bones_t mChildren; + + bool mIsJoint; // if not, collision_volume + enum SupportCategory + { + SUPPORT_BASE, + SUPPORT_EXTENDED + }; + SupportCategory mSupport; + void setSupport(const std::string& support) + { + if (support == "extended") + { + mSupport = SUPPORT_EXTENDED; + } + else + { + mSupport = SUPPORT_BASE; + } + } +}; + +#endif //LL_LLJOINTDATA_H diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp index 719381b4fc..b93a232419 100644 --- a/indra/llappearance/llpolymesh.cpp +++ b/indra/llappearance/llpolymesh.cpp @@ -280,9 +280,10 @@ bool LLPolyMeshSharedData::loadMesh( const std::string& fileName ) LL_ERRS() << "Filename is Empty!" << LL_ENDL; return false; } - LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ + LLFILE* fp = LLFile::fopen(fileName, LLFILE_MODE("rb")); /*Flawfinder: ignore*/ if (!fp) { + LLError::LLUserWarningMsg::showMissingFiles(); LL_ERRS() << "can't open: " << fileName << LL_ENDL; return false; } @@ -861,6 +862,7 @@ LLPolyMesh *LLPolyMesh::getMesh(const std::string &name, LLPolyMesh* reference_m //----------------------------------------------------------------------------- void LLPolyMesh::freeAllMeshes() { + LL_PROFILE_ZONE_SCOPED; // delete each item in the global lists for_each(sGlobalSharedMeshList.begin(), sGlobalSharedMeshList.end(), DeletePairedPointer()); sGlobalSharedMeshList.clear(); diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index 8c76689f2c..64434bd5d9 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -71,7 +71,7 @@ public: private: void freeData(); -} LL_ALIGN_POSTFIX(16); +}; //----------------------------------------------------------------------------- diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h index 9ba4cf66e9..37f35d50ba 100644 --- a/indra/llappearance/llpolyskeletaldistortion.h +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -111,13 +111,13 @@ public: protected: LLPolySkeletalDistortion(const LLPolySkeletalDistortion& pOther); - LL_ALIGN_16(LLVector4a mDefaultVec); + LLVector4a mDefaultVec; typedef std::map<LLJoint*, LLVector3> joint_vec_map_t; joint_vec_map_t mJointScales; joint_vec_map_t mJointOffsets; // Backlink only; don't make this an LLPointer. LLAvatarAppearance *mAvatar; -} LL_ALIGN_POSTFIX(16); +}; #endif // LL_LLPOLYSKELETALDISTORTION_H diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index e368ace35e..7b5ff21bc4 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -435,6 +435,31 @@ const std::string LLTexLayerSet::getBodyRegionName() const return mInfo->mBodyRegion; } +// virtual +void LLTexLayerSet::asLLSD(LLSD& sd) const +{ + sd["visible"] = LLSD::Boolean(isVisible()); + LLSD layer_list_sd; + layer_list_t::const_iterator layer_iter = mLayerList.begin(); + layer_list_t::const_iterator layer_end = mLayerList.end(); + for(; layer_iter != layer_end; ++layer_iter) + { + LLSD layer_sd; + LLTexLayerInterface* layer = (*layer_iter); + if (layer) + { + layer->asLLSD(layer_sd); + } + layer_list_sd.append(layer_sd); + } + LLSD mask_list_sd; + LLSD info_sd; + sd["layers"] = layer_list_sd; + sd["masks"] = mask_list_sd; + sd["info"] = info_sd; +} + + void LLTexLayerSet::destroyComposite() { if( mComposite ) @@ -1293,7 +1318,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { if (!force_render && !hasMorph()) { - LL_DEBUGS() << "skipping renderMorphMasks for " << getUUID() << LL_ENDL; + LL_DEBUGS("Morph") << "skipping renderMorphMasks for " << getUUID() << LL_ENDL; return; } LL_PROFILE_ZONE_SCOPED; @@ -1325,7 +1350,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC success &= param->render( x, y, width, height ); if (!success && !force_render) { - LL_DEBUGS() << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL; + LL_DEBUGS("Morph") << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL; return; } } @@ -1365,7 +1390,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC } else { - LL_WARNS() << "Skipping rendering of " << getInfo()->mStaticImageFileName + LL_WARNS("Morph") << "Skipping rendering of " << getInfo()->mStaticImageFileName << "; expected 1 or 4 components." << LL_ENDL; } } @@ -1404,8 +1429,17 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // We can get bad morph masks during login, on minimize, and occasional gl errors. // We should only be doing this when we believe something has changed with respect to the user's appearance. { - LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL; - // clear out a slot if we have filled our cache + LL_DEBUGS("Morph") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL; + + // Replace the cached mask without leaking its old allocation. + alpha_cache_t::iterator cached = mAlphaCache.find(cache_index); + if (cached != mAlphaCache.end()) + { + ll_aligned_free_32(cached->second); + mAlphaCache.erase(cached); + } + + // clear out a slot if we have filled our cache S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1; while ((S32)mAlphaCache.size() >= max_cache_entries) { @@ -1424,6 +1458,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC size_t mem_size = pixels * bytes_per_pixel; alpha_data = (U8*)ll_aligned_malloc_32(mem_size); + if (!alpha_data) + { + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate memory for morph texture: " << (S32)(mem_size) << LL_ENDL; + return; + } bool skip_readback = LLRender::sNsightDebugSupport; // nSight doesn't support use of glReadPixels @@ -1433,6 +1473,13 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC { // work-around for broken intel drivers which cannot do glReadPixels on an RGBA FBO // returning only the alpha portion without locking up downstream U8* temp = (U8*)ll_aligned_malloc_32(mem_size << 2); // allocate same size, but RGBA + if (!temp) + { + ll_aligned_free_32(alpha_data); + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate temporary memory for morph texture readback: " << (S32)(mem_size << 2) << LL_ENDL; + return; + } if (bound_target) { @@ -1446,13 +1493,20 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC #if GL_VERSION_1_1 glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); #endif - - U8* alpha_cursor = alpha_data; - U8* pixel = temp; - for (int i = 0; i < pixels; i++) + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { - *alpha_cursor++ = pixel[3]; - pixel += 4; + LL_INFOS("Morph") << "GL Error while reading back morph texture. Error code: " << error << LL_ENDL; + } + else + { + U8* alpha_cursor = alpha_data; + U8* pixel = temp; + for (int i = 0; i < pixels; i++) + { + *alpha_cursor++ = pixel[3]; + pixel += 4; + } } gGL.getTexUnit(0)->disable(); @@ -1464,6 +1518,13 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC // We just want GL_ALPHA, but that isn't supported in OGL core profile 4. static const size_t TEMP_BYTES_PER_PIXEL = 4; U8* temp_data = (U8*)ll_aligned_malloc_32(mem_size * TEMP_BYTES_PER_PIXEL); + if (!temp_data) + { + ll_aligned_free_32(alpha_data); + LLError::LLUserWarningMsg::showOutOfMemory(); + LL_ERRS() << "Failed to allocate temporary memory for morph texture: " << (S32)(mem_size * TEMP_BYTES_PER_PIXEL) << LL_ENDL; + return; + } glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, temp_data); for (size_t pixel = 0; pixel < pixels; pixel++) { alpha_data[pixel] = temp_data[(pixel * TEMP_BYTES_PER_PIXEL) + 3]; @@ -1885,7 +1946,10 @@ LLGLTexture* LLTexLayerStaticImageList::getTexture(const std::string& file_name, image_raw->copyUnscaledAlphaMask(alpha_image_raw, LLColor4U::black); } - tex->createGLTexture(0, image_raw, 0, true, LLGLTexture::LOCAL); + if (!tex->createGLTexture(0, image_raw, 0, true, LLGLTexture::LOCAL)) + { + LL_WARNS() << "Failed to create GL texture for image: " << file_name << LL_ENDL; + } gGL.getTexUnit(0)->bind(tex); tex->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/llappearance/lltexlayer.h b/indra/llappearance/lltexlayer.h index 876ea6f600..6b501474d6 100644 --- a/indra/llappearance/lltexlayer.h +++ b/indra/llappearance/lltexlayer.h @@ -220,6 +220,8 @@ public: static bool sHasCaches; + virtual void asLLSD(LLSD& sd) const; + protected: typedef std::vector<LLTexLayerInterface *> layer_list_t; layer_list_t mLayerList; diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 30551c115d..dd2499cf37 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -338,7 +338,10 @@ bool LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height) // Create the GL texture, and then hang onto it for future use. if (mNeedsCreateTexture) { - mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw); + if (!mCachedProcessedTexture->createGLTexture(0, mStaticImageRaw)) + { + LL_WARNS() << "Failed to create GL texture for image: " << mCachedProcessedTexture->getID() << LL_ENDL; + } mNeedsCreateTexture = false; gGL.getTexUnit(0)->bind(mCachedProcessedTexture); mCachedProcessedTexture->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index 5e785e4f3e..68374d7283 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -27,9 +27,11 @@ #ifndef LL_LLTEXLAYERPARAMS_H #define LL_LLTEXLAYERPARAMS_H +#include <atomic> #include "llpointer.h" #include "v4color.h" #include "llviewervisualparam.h" +#include <atomic> class LLAvatarAppearance; class LLImageRaw; @@ -62,7 +64,6 @@ protected: // LLTexLayerParamAlpha // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -LL_ALIGN_PREFIX(16) class alignas(16) LLTexLayerParamAlpha : public LLTexLayerParam { LL_ALIGN_NEW @@ -102,7 +103,7 @@ private: LLPointer<LLImageRaw> mStaticImageRaw; std::atomic<bool> mNeedsCreateTexture; bool mStaticImageInvalid; - LL_ALIGN_16(LLVector4a mAvgDistortionVec); + LLVector4a mAvgDistortionVec; F32 mCachedEffectiveWeight; public: @@ -112,7 +113,7 @@ public: typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t; static param_alpha_ptr_list_t sInstances; -} LL_ALIGN_POSTFIX(16); +}; class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo { friend class LLTexLayerParamAlpha; diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h index b79983df8e..37771cc8d3 100644 --- a/indra/llappearance/llviewervisualparam.h +++ b/indra/llappearance/llviewervisualparam.h @@ -65,8 +65,7 @@ protected: // VIRTUAL CLASS // a viewer side interface class for a generalized parametric modification of the avatar mesh //----------------------------------------------------------------------------- -LL_ALIGN_PREFIX(16) -class LLViewerVisualParam : public LLVisualParam +class alignas(16) LLViewerVisualParam : public LLVisualParam { public: LLViewerVisualParam(); @@ -107,6 +106,6 @@ public: protected: LLViewerVisualParam(const LLViewerVisualParam& pOther); -} LL_ALIGN_POSTFIX(16); +}; #endif // LL_LLViewerVisualParam_H diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp index 4acb0ef3d4..5758f79791 100644 --- a/indra/llappearance/llwearable.cpp +++ b/indra/llappearance/llwearable.cpp @@ -727,17 +727,22 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp) if (!avatarp) return; // Pull params - for( const LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() ) + // Iterate over wearable's params first since they should be fewer than avatar params. + // Wearables are cloned from avatar params by mType, so they should be always be a + // subset of the avatar's params and a situation where mType param doesn't exist in + // a wearable yet exist in the avatar should not happen. + for (const visual_param_index_map_t::value_type& vp_pair : mVisualParamIndexMap) { + LLVisualParam* wearable_param = vp_pair.second; + // cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the // avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way. - if( (((LLViewerVisualParam*)param)->getWearableType() == mType) && (!((LLViewerVisualParam*)param)->getCrossWearable()) ) - { - S32 param_id = param->getID(); - F32 weight = getVisualParamWeight(param_id); + if (((LLViewerVisualParam*)wearable_param)->getCrossWearable()) + continue; - avatarp->setVisualParamWeight( param_id, weight); - } + F32 weight = wearable_param->getWeight(); + // Silently fails if param was not found + avatarp->setVisualParamWeight(vp_pair.first, mType, weight); } } |
