summaryrefslogtreecommitdiff
path: root/indra/llappearance
diff options
context:
space:
mode:
authorErik Kundiman <erik@megapahit.org>2026-09-01 18:35:23 +0800
committerErik Kundiman <erik@megapahit.org>2026-09-04 21:58:53 +0800
commit00bb3bb6f07660bd914d29a1389342bb3060d254 (patch)
tree431f574922494d2201718f13085f17bc6bd7fb42 /indra/llappearance
parenta8636720129952c10cf49ab80da21bf8b340b96c (diff)
parent4ef9f8f14b35ed388c294d53767a0dca0e890924 (diff)
Merge remote-tracking branch 'secondlife/release/26.4' into 26.4
Diffstat (limited to 'indra/llappearance')
-rw-r--r--indra/llappearance/CMakeLists.txt11
-rw-r--r--indra/llappearance/llavatarappearance.cpp9
-rw-r--r--indra/llappearance/llavatarappearancedefines.cpp4
-rw-r--r--indra/llappearance/llavatarappearancedefines.h4
-rw-r--r--indra/llappearance/llavatarjoint.h6
-rw-r--r--indra/llappearance/llavatarjointmesh.h3
-rw-r--r--indra/llappearance/lldriverparam.h2
-rw-r--r--indra/llappearance/llpolymesh.cpp3
-rw-r--r--indra/llappearance/llpolymorph.h2
-rw-r--r--indra/llappearance/llpolyskeletaldistortion.h4
-rw-r--r--indra/llappearance/lltexlayer.cpp36
-rw-r--r--indra/llappearance/lltexlayer.h2
-rw-r--r--indra/llappearance/lltexlayerparams.h6
-rw-r--r--indra/llappearance/llviewervisualparam.h5
-rw-r--r--indra/llappearance/llwearable.cpp19
15 files changed, 86 insertions, 30 deletions
diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt
index b382e21b3c..9f8fb3217d 100644
--- a/indra/llappearance/CMakeLists.txt
+++ b/indra/llappearance/CMakeLists.txt
@@ -28,7 +28,7 @@ set(llappearance_SOURCE_FILES
llviewervisualparam.cpp
llavatarappearancedefines.cpp
)
-
+
set(llappearance_HEADER_FILES
CMakeLists.txt
@@ -69,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})
@@ -77,6 +81,7 @@ if (BUILD_HEADLESS)
llcharacter
llinventory
llimage
+ llrenderheadless
llfilesystem
llmath
llxml
@@ -84,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 dab18c240d..c8fd2cba70 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -1647,10 +1647,10 @@ 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 (Euler angles rad)
- mat = glm::rotate(mat, mRot[0], glm::vec3(1, 0, 0));
- mat = glm::rotate(mat, mRot[1], glm::vec3(0, 1, 0));
- mat = glm::rotate(mat, mRot[2], glm::vec3(0, 0, 1));
+ // 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;
@@ -1698,6 +1698,7 @@ void LLAvatarSkeletonInfo::getJointMatricesAndHierarhy(
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();
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/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp
index d5323e0b84..b93a232419 100644
--- a/indra/llappearance/llpolymesh.cpp
+++ b/indra/llappearance/llpolymesh.cpp
@@ -280,7 +280,7 @@ 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();
@@ -862,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 2452352097..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 )
@@ -1405,6 +1430,15 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
// We should only be doing this when we believe something has changed with respect to the user's appearance.
{
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)
@@ -1441,6 +1475,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
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;
@@ -1485,6 +1520,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
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;
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.h b/indra/llappearance/lltexlayerparams.h
index 59320cc00d..68374d7283 100644
--- a/indra/llappearance/lltexlayerparams.h
+++ b/indra/llappearance/lltexlayerparams.h
@@ -31,6 +31,7 @@
#include "llpointer.h"
#include "v4color.h"
#include "llviewervisualparam.h"
+#include <atomic>
class LLAvatarAppearance;
class LLImageRaw;
@@ -63,7 +64,6 @@ protected:
// LLTexLayerParamAlpha
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LL_ALIGN_PREFIX(16)
class alignas(16) LLTexLayerParamAlpha : public LLTexLayerParam
{
LL_ALIGN_NEW
@@ -103,7 +103,7 @@ private:
LLPointer<LLImageRaw> mStaticImageRaw;
std::atomic<bool> mNeedsCreateTexture;
bool mStaticImageInvalid;
- LL_ALIGN_16(LLVector4a mAvgDistortionVec);
+ LLVector4a mAvgDistortionVec;
F32 mCachedEffectiveWeight;
public:
@@ -113,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);
}
}