diff --git a/autobuild.xml b/autobuild.xml index 94685ab335..cf1b844d61 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -540,9 +540,9 @@ archive hash - b6357ef3a0ec37877a5831820f25094e + 178b16ee9ff67986c8c14413ee68218e url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80557/759704/apr_suite-1.4.5.558565-darwin64-558565.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107593/938535/apr_suite-1.4.5.576669-darwin64-576669.tar.bz2 name darwin64 @@ -564,9 +564,9 @@ archive hash - cb48ac069440f6dcd564cfa9fd02a4c2 + d2997cad03dbd0d70a060276b5671480 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80556/759710/apr_suite-1.4.5.558565-windows-558565.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107594/938548/apr_suite-1.4.5.576669-windows-576669.tar.bz2 name windows @@ -576,16 +576,16 @@ archive hash - 646dc3828d9c39fb1e77c4eec44ed739 + ec24f5945faa8f13807b83eeaeb994f8 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/80555/759709/apr_suite-1.4.5.558565-windows64-558565.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107592/938547/apr_suite-1.4.5.576669-windows64-576669.tar.bz2 name windows64 version - 1.4.5.558565 + 1.4.5.576669 boost @@ -1892,9 +1892,9 @@ archive hash - c1c9e32e21f3c34d91ed045b2ca91f24 + 7a0059748d0b8733f2f9ce434cf604b8 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87781/805801/libpng-1.6.8.563850-darwin64-563850.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107514/937867/libpng-1.6.38.576621-darwin64-576621.tar.bz2 name darwin64 @@ -1916,9 +1916,9 @@ archive hash - 642e9cf95c8ccd0eb34f6d7a40df585a + 3112013186ad60b0fc270a398d4dd499 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87782/805831/libpng-1.6.8.563850-windows-563850.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107513/937823/libpng-1.6.38.576621-windows-576621.tar.bz2 name windows @@ -1928,16 +1928,16 @@ archive hash - ce46aa0f171d97626c4a3940347cecd7 + 7c6bfcdb0d6162587cdbc436f595dd02 url - https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/87780/805832/libpng-1.6.8.563850-windows64-563850.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/107512/937822/libpng-1.6.38.576621-windows64-576621.tar.bz2 name windows64 version - 1.6.8.563850 + 1.6.38.576621 libuuid @@ -2708,9 +2708,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - 53966a7ba6342395acb7ce15bc3fbe0a + 8114c6a7e499ea20d325db0de08ce30a url - http://3p.firestormviewer.org/openjpeg-2.3.1.203000304-darwin-203000304.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105469/923024/openjpeg-2.5.0.575496-darwin64-575496.tar.bz2 name darwin64 @@ -2732,9 +2732,9 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - ba2034b4a372fd46c3e09f56bede38a7 + edc9388870d951632a6d595792293e05 url - http://3p.firestormviewer.org/openjpeg-2.4.0.211361403-windows-211361403.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105472/923036/openjpeg-2.5.0.575496-windows-575496.tar.bz2 name windows @@ -2744,16 +2744,16 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors archive hash - d7ac606703a9330a2d8a3f7276cb6894 + b95f0732f2388ebb0ddf33d4a30e0ff1 url - http://3p.firestormviewer.org/openjpeg-2.4.0.211361407-windows64-211361407.tar.bz2 + https://automated-builds-secondlife-com.s3.amazonaws.com/ct2/105471/923037/openjpeg-2.5.0.575496-windows64-575496.tar.bz2 name windows64 version - 2.4.0 + 2.5.0.575496 openssl diff --git a/doc/contributions.txt b/doc/contributions.txt index 799882d497..26ccf25c2c 100755 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -285,6 +285,7 @@ Beq Janus SL-15709 SL-16021 SL-16027 + SL-18592 SL-18637 Beth Walcher Bezilon Kasei @@ -376,6 +377,7 @@ Charlie Sazaland Chaser Zaks BUG-225599 BUG-227485 + SL-16874 Cherry Cheevers ChickyBabes Zuzu Chorazin Allen @@ -1396,6 +1398,7 @@ Sovereign Engineer OPEN-343 SL-11625 BUG-229030 + SL-14696 SL-14705 SL-14706 SL-14707 @@ -1403,6 +1406,12 @@ Sovereign Engineer SL-14732 SL-15096 SL-16127 + SL-18249 + SL-18394 + SL-18412 + SL-18497 + SL-18525 + SL-18534 SpacedOut Frye VWR-34 VWR-45 @@ -1665,6 +1674,8 @@ Zi Ree VWR-25588 STORM-1790 STORM-1842 + SL-18348 + SL-18593 Zipherius Turas VWR-76 VWR-77 diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index d0c32504a2..e675ce699c 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -253,7 +253,7 @@ elseif(LINUX) ${EXPAT_COPY} libhunspell-1.3.so.0.0.0 libopenal.so - #libopenjpeg.so + #libopenjp2.so libuuid.so.16 libuuid.so.16.0.22 #libfontconfig.so.1.10.1 # fontconfig and freetype should be taken from the diff --git a/indra/cmake/FindOpenJPEG.cmake b/indra/cmake/FindOpenJPEG.cmake index cdbc6c5841..d77e17764d 100644 --- a/indra/cmake/FindOpenJPEG.cmake +++ b/indra/cmake/FindOpenJPEG.cmake @@ -16,9 +16,10 @@ FIND_PATH(OPENJPEG_INCLUDE_DIR openjpeg.h /usr/include/openjpeg-2.1 /usr/include/openjpeg /usr/include +include/openjpeg ) -SET(OPENJPEG_NAMES ${OPENJPEG_NAMES} openjpeg openjp2) +SET(OPENJPEG_NAMES ${OPENJPEG_NAMES} openjp2) FIND_LIBRARY(OPENJPEG_LIBRARY NAMES ${OPENJPEG_NAMES} PATHS /usr/lib /usr/local/lib diff --git a/indra/cmake/OpenJPEG.cmake b/indra/cmake/OpenJPEG.cmake index f254094df6..a078c97cb8 100644 --- a/indra/cmake/OpenJPEG.cmake +++ b/indra/cmake/OpenJPEG.cmake @@ -8,8 +8,7 @@ if (USESYSTEMLIBS) include(FindOpenJPEG) else (USESYSTEMLIBS) use_prebuilt_binary(openjpeg) - - set(OPENJPEG_LIBRARIES openjp2) + set(OPENJPEG_LIBRARIES openjp2) set(OPENJPEG_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include/openjpeg) endif (USESYSTEMLIBS) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 6d6946d0ff..062a59ed92 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -296,7 +296,12 @@ LLAvatarAppearance::~LLAvatarAppearance() } } - if (mRoot) mRoot->removeAllChildren(); + if (mRoot) + { + mRoot->removeAllChildren(); + delete mRoot; + mRoot = nullptr; + } mJointMap.clear(); clearSkeleton(); diff --git a/indra/llappearance/lllocaltextureobject.cpp b/indra/llappearance/lllocaltextureobject.cpp index defb5018be..ab50db3a5a 100644 --- a/indra/llappearance/lllocaltextureobject.cpp +++ b/indra/llappearance/lllocaltextureobject.cpp @@ -76,7 +76,7 @@ LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject& lto) : LLLocalTextureObject::~LLLocalTextureObject() { - delete_and_clear(mTexLayers); // Mem-leak fix by Drake Arconis + delete_and_clear(mTexLayers); } LLGLTexture* LLLocalTextureObject::getImage() const diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index 2975ce1c5c..f2d7a4bbcd 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1224,7 +1224,7 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8 BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, bool allow_invalid_joints) { BOOL old_version = FALSE; - mJointMotionList = new LLKeyframeMotion::JointMotionList; + std::unique_ptr joint_motion_list(new LLKeyframeMotion::JointMotionList); //------------------------------------------------------------------------- // get base priority @@ -1236,14 +1236,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo if (!dp.unpackU16(version, "version")) { LL_WARNS() << "can't read version number for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } if (!dp.unpackU16(sub_version, "sub_version")) { LL_WARNS() << "can't read sub version number for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1256,7 +1254,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo #if LL_RELEASE LL_WARNS() << "Bad animation version " << version << "." << sub_version << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; #else LL_ERRS() << "Bad animation version " << version << "." << sub_version @@ -1268,89 +1265,80 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read animation base_priority" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - mJointMotionList->mBasePriority = (LLJoint::JointPriority) temp_priority; + joint_motion_list->mBasePriority = (LLJoint::JointPriority) temp_priority; - if (mJointMotionList->mBasePriority >= LLJoint::ADDITIVE_PRIORITY) + if (joint_motion_list->mBasePriority >= LLJoint::ADDITIVE_PRIORITY) { - mJointMotionList->mBasePriority = (LLJoint::JointPriority)((S32)LLJoint::ADDITIVE_PRIORITY-1); - mJointMotionList->mMaxPriority = mJointMotionList->mBasePriority; + joint_motion_list->mBasePriority = (LLJoint::JointPriority)((S32)LLJoint::ADDITIVE_PRIORITY-1); + joint_motion_list->mMaxPriority = joint_motion_list->mBasePriority; } - else if (mJointMotionList->mBasePriority < LLJoint::USE_MOTION_PRIORITY) + else if (joint_motion_list->mBasePriority < LLJoint::USE_MOTION_PRIORITY) { - LL_WARNS() << "bad animation base_priority " << mJointMotionList->mBasePriority + LL_WARNS() << "bad animation base_priority " << joint_motion_list->mBasePriority << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } //------------------------------------------------------------------------- // get duration //------------------------------------------------------------------------- - if (!dp.unpackF32(mJointMotionList->mDuration, "duration")) + if (!dp.unpackF32(joint_motion_list->mDuration, "duration")) { LL_WARNS() << "can't read duration" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - if (mJointMotionList->mDuration > MAX_ANIM_DURATION || - !llfinite(mJointMotionList->mDuration)) + if (joint_motion_list->mDuration > MAX_ANIM_DURATION || + !llfinite(joint_motion_list->mDuration)) { LL_WARNS() << "invalid animation duration" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } //------------------------------------------------------------------------- // get emote (optional) //------------------------------------------------------------------------- - if (!dp.unpackString(mJointMotionList->mEmoteName, "emote_name")) + if (!dp.unpackString(joint_motion_list->mEmoteName, "emote_name")) { LL_WARNS() << "can't read optional_emote_animation" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - if(mJointMotionList->mEmoteName==mID.asString()) + if(joint_motion_list->mEmoteName==mID.asString()) { LL_WARNS() << "Malformed animation mEmoteName==mID" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } //------------------------------------------------------------------------- // get loop //------------------------------------------------------------------------- - if (!dp.unpackF32(mJointMotionList->mLoopInPoint, "loop_in_point") || - !llfinite(mJointMotionList->mLoopInPoint)) + if (!dp.unpackF32(joint_motion_list->mLoopInPoint, "loop_in_point") || + !llfinite(joint_motion_list->mLoopInPoint)) { LL_WARNS() << "can't read loop point" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - if (!dp.unpackF32(mJointMotionList->mLoopOutPoint, "loop_out_point") || - !llfinite(mJointMotionList->mLoopOutPoint)) + if (!dp.unpackF32(joint_motion_list->mLoopOutPoint, "loop_out_point") || + !llfinite(joint_motion_list->mLoopOutPoint)) { LL_WARNS() << "can't read loop point" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - if (!dp.unpackS32(mJointMotionList->mLoop, "loop")) + if (!dp.unpackS32(joint_motion_list->mLoop, "loop")) { LL_WARNS() << "can't read loop" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1360,27 +1348,25 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo if (female_land_anim == asset_id || formal_female_land_anim == asset_id) { LL_WARNS() << "Animation(" << asset_id << ") won't be looped." << LL_ENDL; - mJointMotionList->mLoop = FALSE; + joint_motion_list->mLoop = FALSE; } //------------------------------------------------------------------------- // get easeIn and easeOut //------------------------------------------------------------------------- - if (!dp.unpackF32(mJointMotionList->mEaseInDuration, "ease_in_duration") || - !llfinite(mJointMotionList->mEaseInDuration)) + if (!dp.unpackF32(joint_motion_list->mEaseInDuration, "ease_in_duration") || + !llfinite(joint_motion_list->mEaseInDuration)) { LL_WARNS() << "can't read easeIn" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - if (!dp.unpackF32(mJointMotionList->mEaseOutDuration, "ease_out_duration") || - !llfinite(mJointMotionList->mEaseOutDuration)) + if (!dp.unpackF32(joint_motion_list->mEaseOutDuration, "ease_out_duration") || + !llfinite(joint_motion_list->mEaseOutDuration)) { LL_WARNS() << "can't read easeOut" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1392,7 +1378,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read hand pose" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1400,11 +1385,10 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "invalid LLHandMotion::eHandPose index: " << word << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - mJointMotionList->mHandPose = (LLHandMotion::eHandPose)word; + joint_motion_list->mHandPose = (LLHandMotion::eHandPose)word; //------------------------------------------------------------------------- // get number of joint motions @@ -1414,7 +1398,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read number of joints" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1422,19 +1405,17 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "no joints" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } else if (num_motions > LL_CHARACTER_MAX_ANIMATED_JOINTS) { LL_WARNS() << "too many joints" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - mJointMotionList->mJointMotionArray.clear(); - mJointMotionList->mJointMotionArray.reserve(num_motions); + joint_motion_list->mJointMotionArray.clear(); + joint_motion_list->mJointMotionArray.reserve(num_motions); mJointStates.clear(); mJointStates.reserve(num_motions); @@ -1445,14 +1426,13 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo for(U32 i=0; imJointMotionArray.push_back(joint_motion); + joint_motion_list->mJointMotionArray.push_back(joint_motion); std::string joint_name; if (!dp.unpackString(joint_name, "joint_name")) { LL_WARNS() << "can't read joint name" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1460,7 +1440,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "attempted to animate special " << joint_name << " joint" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1507,7 +1486,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read joint priority." << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1515,15 +1493,14 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "joint priority unknown - too low." << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } joint_motion->mPriority = (LLJoint::JointPriority)joint_priority; if (joint_priority != LLJoint::USE_MOTION_PRIORITY && - joint_priority > mJointMotionList->mMaxPriority) + joint_priority > joint_motion_list->mMaxPriority) { - mJointMotionList->mMaxPriority = (LLJoint::JointPriority)joint_priority; + joint_motion_list->mMaxPriority = (LLJoint::JointPriority)joint_priority; } joint_state->setPriority((LLJoint::JointPriority)joint_priority); @@ -1535,7 +1512,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read number of rotation keys" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1562,7 +1538,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read rotation key (" << k << ")" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1573,17 +1548,15 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read rotation key (" << k << ")" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - time = U16_to_F32(time_short, 0.f, mJointMotionList->mDuration); + time = U16_to_F32(time_short, 0.f, joint_motion_list->mDuration); - if (time < 0 || time > mJointMotionList->mDuration) + if (time < 0 || time > joint_motion_list->mDuration) { LL_WARNS() << "invalid frame time" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } } @@ -1593,40 +1566,58 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo LLVector3 rot_angles; U16 x, y, z; - BOOL success = TRUE; - if (old_version) { - success = dp.unpackVector3(rot_angles, "rot_angles") && rot_angles.isFinite(); + if (!dp.unpackVector3(rot_angles, "rot_angles")) + { + LL_WARNS() << "can't read rot_angles in rotation key (" << k << ")" << LL_ENDL; + return FALSE; + } + if (!rot_angles.isFinite()) + { + LL_WARNS() << "non-finite angle in rotation key (" << k << ")" << LL_ENDL; + return FALSE; + } LLQuaternion::Order ro = StringToOrder("ZYX"); rot_key.mRotation = mayaQ(rot_angles.mV[VX], rot_angles.mV[VY], rot_angles.mV[VZ], ro); } else { - success &= dp.unpackU16(x, "rot_angle_x"); - success &= dp.unpackU16(y, "rot_angle_y"); - success &= dp.unpackU16(z, "rot_angle_z"); + if (!dp.unpackU16(x, "rot_angle_x")) + { + LL_WARNS() << "can't read rot_angle_x in rotation key (" << k << ")" << LL_ENDL; + return FALSE; + } + if (!dp.unpackU16(y, "rot_angle_y")) + { + LL_WARNS() << "can't read rot_angle_y in rotation key (" << k << ")" << LL_ENDL; + return FALSE; + } + if (!dp.unpackU16(z, "rot_angle_z")) + { + LL_WARNS() << "can't read rot_angle_z in rotation key (" << k << ")" << LL_ENDL; + return FALSE; + } LLVector3 rot_vec; rot_vec.mV[VX] = U16_to_F32(x, -1.f, 1.f); rot_vec.mV[VY] = U16_to_F32(y, -1.f, 1.f); rot_vec.mV[VZ] = U16_to_F32(z, -1.f, 1.f); + + if(!rot_vec.isFinite()) + { + LL_WARNS() << "non-finite angle in rotation key (" << k << ")" + << " for animation " << asset_id << LL_ENDL; + return FALSE; + } rot_key.mRotation.unpackFromVector3(rot_vec); } - if( !(rot_key.mRotation.isFinite()) ) + if(!rot_key.mRotation.isFinite()) { - LL_WARNS() << "non-finite angle in rotation key" + LL_WARNS() << "non-finite angle in rotation key (" << k << ")" << " for animation " << asset_id << LL_ENDL; - success = FALSE; - } - - if (!success) - { - LL_WARNS() << "can't read rotation key (" << k << ")" - << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1640,7 +1631,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read number of position keys" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1667,7 +1657,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read position key (" << k << ")" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } } @@ -1677,18 +1666,19 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read position key (" << k << ")" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - pos_key.mTime = U16_to_F32(time_short, 0.f, mJointMotionList->mDuration); + pos_key.mTime = U16_to_F32(time_short, 0.f, joint_motion_list->mDuration); } - BOOL success = TRUE; - if (old_version) { - success = dp.unpackVector3(pos_key.mPosition, "pos"); + if (!dp.unpackVector3(pos_key.mPosition, "pos")) + { + LL_WARNS() << "can't read pos in position key (" << k << ")" << LL_ENDL; + return FALSE; + } //MAINT-6162 pos_key.mPosition.mV[VX] = llclamp( pos_key.mPosition.mV[VX], -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); @@ -1700,27 +1690,31 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { U16 x, y, z; - success &= dp.unpackU16(x, "pos_x"); - success &= dp.unpackU16(y, "pos_y"); - success &= dp.unpackU16(z, "pos_z"); + if (!dp.unpackU16(x, "pos_x")) + { + LL_WARNS() << "can't read pos_x in position key (" << k << ")" << LL_ENDL; + return FALSE; + } + if (!dp.unpackU16(y, "pos_y")) + { + LL_WARNS() << "can't read pos_y in position key (" << k << ")" << LL_ENDL; + return FALSE; + } + if (!dp.unpackU16(z, "pos_z")) + { + LL_WARNS() << "can't read pos_z in position key (" << k << ")" << LL_ENDL; + return FALSE; + } pos_key.mPosition.mV[VX] = U16_to_F32(x, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); pos_key.mPosition.mV[VY] = U16_to_F32(y, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); pos_key.mPosition.mV[VZ] = U16_to_F32(z, -LL_MAX_PELVIS_OFFSET, LL_MAX_PELVIS_OFFSET); } - if( !(pos_key.mPosition.isFinite()) ) + if(!pos_key.mPosition.isFinite()) { LL_WARNS() << "non-finite position in key" << " for animation " << asset_id << LL_ENDL; - success = FALSE; - } - - if (!success) - { - LL_WARNS() << "can't read position key (" << k << ")" - << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1728,7 +1722,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo if (is_pelvis) { - mJointMotionList->mPelvisBBox.addPoint(pos_key.mPosition); + joint_motion_list->mPelvisBBox.addPoint(pos_key.mPosition); } } @@ -1743,7 +1737,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read number of constraints" << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1761,25 +1754,21 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo for(S32 i = 0; i < num_constraints; ++i) { // read in constraint data - JointConstraintSharedData* constraintp = new JointConstraintSharedData; + std::unique_ptr constraintp(new JointConstraintSharedData); U8 byte = 0; if (!dp.unpackU8(byte, "chain_length")) { LL_WARNS() << "can't read constraint chain length" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } constraintp->mChainLength = (S32) byte; - if((U32)constraintp->mChainLength > mJointMotionList->getNumJointMotions()) + if((U32)constraintp->mChainLength > joint_motion_list->getNumJointMotions()) { LL_WARNS() << "invalid constraint chain length" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1787,8 +1776,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read constraint type" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1796,8 +1783,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "invalid constraint type" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } constraintp->mConstraintType = (EConstraintType)byte; @@ -1808,8 +1793,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read source volume name" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1820,8 +1803,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "not a valid source constraint volume " << str << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // avoid mem-leak as per others return FALSE; } @@ -1829,8 +1810,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read constraint source offset" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1838,8 +1817,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "non-finite constraint source offset" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1847,8 +1824,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read target volume name" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1867,8 +1842,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "not a valid target constraint volume " << str << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // avoid mem-leak as per others return FALSE; } } @@ -1877,8 +1850,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read constraint target offset" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1886,8 +1857,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "non-finite constraint target offset" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1895,8 +1864,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read constraint target direction" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1904,8 +1871,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "non-finite constraint target direction" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1919,8 +1884,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read constraint ease in start time" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1928,8 +1891,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read constraint ease in stop time" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1937,8 +1898,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read constraint ease out start time" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1946,36 +1905,31 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "can't read constraint ease out stop time" << " for animation " << asset_id << LL_ENDL; - delete constraintp; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } - mJointMotionList->mConstraints.push_front(constraintp); - - constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte - LLJoint* joint = mCharacter->findCollisionVolume(constraintp->mSourceConstraintVolume); // get joint to which this collision volume is attached if (!joint) { - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } + + constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte + for (S32 i = 0; i < constraintp->mChainLength + 1; i++) { LLJoint* parent = joint->getParent(); if (!parent) { LL_WARNS() << "Joint with no parent: " << joint->getName() - << " Emote: " << mJointMotionList->mEmoteName + << " Emote: " << joint_motion_list->mEmoteName << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } joint = parent; constraintp->mJointStateIndices[i] = -1; - for (U32 j = 0; j < mJointMotionList->getNumJointMotions(); j++) + for (U32 j = 0; j < joint_motion_list->getNumJointMotions(); j++) { LLJoint* constraint_joint = getJoint(j); @@ -1983,7 +1937,6 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "Invalid joint " << j << " for animation " << asset_id << LL_ENDL; - delete mJointMotionList; // Mem-leak fix by Drake Arconis return FALSE; } @@ -1997,17 +1950,16 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp, const LLUUID& asset_id, boo { LL_WARNS() << "No joint index for constraint " << i << " for animation " << asset_id << LL_ENDL; - // Mem-leak fix by Drake Arconis - //delete constraintp; - delete mJointMotionList; - // return FALSE; } } + + joint_motion_list->mConstraints.push_front(constraintp.release()); } } // *FIX: support cleanup of old keyframe data + mJointMotionList = joint_motion_list.release(); // release from unique_ptr to member; LLKeyframeDataCache::addKeyframeData(getID(), mJointMotionList); mAssetStatus = ASSET_LOADED; diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp index e313df704e..f91f17c491 100644 --- a/indra/llcommon/llcoros.cpp +++ b/indra/llcommon/llcoros.cpp @@ -287,25 +287,15 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl return name; } +namespace +{ + #if LL_WINDOWS static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific -U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, const std::string& name) +U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop) { - // C++ exceptions were logged in toplevelTryWrapper, but not SEH - // log SEH exceptions here, to make sure it gets into bugsplat's - // report and because __try won't allow std::string operations - if (code != STATUS_MSC_EXCEPTION) - { - LL_WARNS() << "SEH crash in " << name << ", code: " << code << LL_ENDL; - } - // Handle bugsplat here, since GetExceptionInformation() can only be - // called from within filter for __except(filter), not from __except's {} - // Bugsplat should get all exceptions, C++ and SEH - LLApp::instance()->reportCrashToBugsplat(exception_infop); - - // Only convert non C++ exceptions. if (code == STATUS_MSC_EXCEPTION) { // C++ exception, go on @@ -318,28 +308,38 @@ U32 cpp_exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop, } } -void LLCoros::sehHandle(const std::string& name, const LLCoros::callable_t& callable) +void sehandle(const LLCoros::callable_t& callable) { __try { - LLCoros::toplevelTryWrapper(name, callable); + callable(); } - __except (cpp_exception_filter(GetExceptionCode(), GetExceptionInformation(), name)) + __except (exception_filter(GetExceptionCode(), GetExceptionInformation())) { - // convert to C++ styled exception for handlers other than bugsplat + // convert to C++ styled exception // Note: it might be better to use _se_set_translator // if you want exception to inherit full callstack - // - // in case of bugsplat this will get to exceptionTerminateHandler and - // looks like fiber will terminate application after that char integer_string[512]; - sprintf(integer_string, "SEH crash in %s, code: %lu\n", name.c_str(), GetExceptionCode()); + sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode()); throw std::exception(integer_string); } } -#endif -void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& callable) +#else // ! LL_WINDOWS + +inline void sehandle(const LLCoros::callable_t& callable) +{ + callable(); +} + +#endif // ! LL_WINDOWS + +} // anonymous namespace + +// Top-level wrapper around caller's coroutine callable. +// Normally we like to pass strings and such by const reference -- but in this +// case, we WANT to copy both the name and the callable to our local stack! +void LLCoros::toplevel(std::string name, callable_t callable) { // keep the CoroData on this top-level function's stack frame CoroData corodata(name); @@ -349,12 +349,12 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call // run the code the caller actually wants in the coroutine try { - callable(); + sehandle(callable); } catch (const Stop& exc) { LL_INFOS("LLCoros") << "coroutine " << name << " terminating because " - << exc.what() << LL_ENDL; + << exc.what() << LL_ENDL; } catch (const LLContinueError&) { @@ -365,36 +365,14 @@ void LLCoros::toplevelTryWrapper(const std::string& name, const callable_t& call } catch (...) { -#if LL_WINDOWS - // Any OTHER kind of uncaught exception will cause the viewer to - // crash, SEH handling should catch it and report to bugsplat. - LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name)); - // to not modify callstack - throw; -#else // Stash any OTHER kind of uncaught exception in the rethrow() queue // to be rethrown by the main fiber. LL_WARNS("LLCoros") << "Capturing uncaught exception in coroutine " << name << LL_ENDL; LLCoros::instance().saveException(name, std::current_exception()); -#endif } } -// Top-level wrapper around caller's coroutine callable. -// Normally we like to pass strings and such by const reference -- but in this -// case, we WANT to copy both the name and the callable to our local stack! -void LLCoros::toplevel(std::string name, callable_t callable) -{ -#if LL_WINDOWS - // Because SEH can's have unwinding, need to call a wrapper - // 'try' is inside SEH handling to not catch LLContinue - sehHandle(name, callable); -#else - toplevelTryWrapper(name, callable); -#endif -} - //static void LLCoros::checkStop() { diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h index dbff921f16..966ce03296 100644 --- a/indra/llcommon/llcoros.h +++ b/indra/llcommon/llcoros.h @@ -307,11 +307,7 @@ public: private: std::string generateDistinctName(const std::string& prefix) const; - void toplevelTryWrapper(const std::string& name, const callable_t& callable); -#if LL_WINDOWS - void sehHandle(const std::string& name, const callable_t& callable); // calls toplevelTryWrapper -#endif - void toplevel(std::string name, callable_t callable); // calls sehHandle or toplevelTryWrapper + void toplevel(std::string name, callable_t callable); struct CoroData; static CoroData& get_CoroData(const std::string& caller); void saveException(const std::string& name, std::exception_ptr exc); diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index 687b917303..d0108261fc 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -952,7 +952,7 @@ namespace LLError for (a = sets.beginArray(), end = sets.endArray(); a != end; ++a) { const LLSD& entry = *a; - if (entry.isMap() && !entry.emptyMap()) + if (entry.isMap() && entry.size() != 0) { ELevel level = decodeLevel(entry["level"]); diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 9a735ccadf..c7e69e29cb 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -34,10 +34,9 @@ #include #include "apr_base64.h" -// Add non-allocating variants of unzip_llsd #include #include -// + #ifdef LL_USESYSTEMLIBS # include #else @@ -2132,8 +2131,8 @@ std::string zip_llsd(LLSD& data) { //copy result into output if (strm.avail_out >= CHUNK) { - // free(output); - if( output ) + deflateEnd(&strm); + if(output) free(output); LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; return std::string(); @@ -2157,8 +2156,8 @@ std::string zip_llsd(LLSD& data) } else { - // free(output); - if( output ) + deflateEnd(&strm); + if(output) free(output); LL_WARNS() << "Failed to compress LLSD block." << LL_ENDL; return std::string(); @@ -2170,8 +2169,7 @@ std::string zip_llsd(LLSD& data) std::string result((char*) output, size); deflateEnd(&strm); - // free(output); - if( output ) + if(output) free(output); return result; @@ -2182,148 +2180,8 @@ std::string zip_llsd(LLSD& data) // and deserializes from that copy using LLSDSerialize LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, std::istream& is, S32 size) { - // Add non-allocating variants of unzip_llsd - // U8* result = NULL; - // llssize cur_size = 0; - // z_stream strm; - - // const U32 CHUNK = 65536; - - // U8 *in = new(std::nothrow) U8[size]; - // if (!in) - // { - // return ZR_MEM_ERROR; - // } - // is.read((char*) in, size); - - // U8 out[CHUNK]; - - // strm.zalloc = Z_NULL; - // strm.zfree = Z_NULL; - // strm.opaque = Z_NULL; - // strm.avail_in = size; - // strm.next_in = in; - - // S32 ret = inflateInit(&strm); - - // do - // { - // strm.avail_out = CHUNK; - // strm.next_out = out; - // ret = inflate(&strm, Z_NO_FLUSH); - // if (ret == Z_STREAM_ERROR) - // { - // LL_DEBUGS() << "Unzip error: Z_STREAM_ERROR" << LL_ENDL; // - // inflateEnd(&strm); - // // free(result); - // if( result ) - // free(result); - // delete [] in; - // return ZR_DATA_ERROR; - // } - - // switch (ret) - // { - // case Z_NEED_DICT: - // ret = Z_DATA_ERROR; - // case Z_DATA_ERROR: - // case Z_MEM_ERROR: - // LL_DEBUGS() << "Unzip error: " << ret << LL_ENDL; // - // inflateEnd(&strm); - // // free(result); - // if( result ) - // free(result); - // delete [] in; - // return ZR_MEM_ERROR; - // break; - // } - - // U32 have = CHUNK-strm.avail_out; - - // U8* new_result = (U8*)realloc(result, cur_size + have); - // if (new_result == NULL) - // { - // inflateEnd(&strm); - // if (result) - // { - // free(result); - // } - // delete[] in; - // return ZR_MEM_ERROR; - // } - // result = new_result; - // memcpy(result+cur_size, out, have); - // cur_size += have; - - // } while (ret == Z_OK); - - // inflateEnd(&strm); - // delete [] in; - - // if (ret != Z_STREAM_END) - // { - // LL_DEBUGS() << "Unzip error: !Z_STREAM_END" << LL_ENDL; // - // // free(result); - // if( result ) - // free(result); - // return ZR_DATA_ERROR; - // } - - // //result now points to the decompressed LLSD block - // { - // std::istringstream istr; - // // Since we are using this for meshes, data we are dealing with tend to be large. - // // So string can potentially fail to allocate, make sure this won't cause problems - // try - // { - // std::string res_str((char*)result, cur_size); - - // std::string deprecated_header(""); - - // if (res_str.substr(0, deprecated_header.size()) == deprecated_header) - // { - // res_str = res_str.substr(deprecated_header.size() + 1, cur_size); - // } - // cur_size = res_str.size(); - - // istr.str(res_str); - // } - // #ifdef LL_WINDOWS - // catch (std::length_error) - // { - // // free(result); - // if( result ) - // free(result); - // return ZR_SIZE_ERROR; - // } - // #endif - // catch (std::bad_alloc&) - // { - // // free(result); - // if( result ) - // free(result); - // return ZR_MEM_ERROR; - // } - - // if (!LLSDSerialize::fromBinary(data, istr, cur_size, UNZIP_LLSD_MAX_DEPTH)) - // { - // // free(result); - // if( result ) - // free(result); - // return ZR_PARSE_ERROR; - // } - // } - - // // free(result); - // if( result ) - // free(result); - // return ZR_OK; - std::unique_ptr in; - try - { - in = std::unique_ptr(new U8[size]); - } - catch(const std::bad_alloc&) + std::unique_ptr in = std::unique_ptr(new(std::nothrow) U8[size]); + if (!in) { return ZR_MEM_ERROR; } @@ -2338,19 +2196,12 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 llssize cur_size = 0; z_stream strm; - constexpr U32 CHUNK = 1024 * 256; + constexpr U32 CHUNK = 1024 * 512; static thread_local std::unique_ptr out; if (!out) { - try - { - out = std::unique_ptr(new U8[CHUNK]); - } - catch (const std::bad_alloc&) - { - return ZR_MEM_ERROR; - } + out = std::unique_ptr(new(std::nothrow) U8[CHUNK]); } strm.zalloc = Z_NULL; @@ -2360,16 +2211,7 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 strm.next_in = const_cast(in); S32 ret = inflateInit(&strm); - switch (ret) - { - case Z_STREAM_ERROR: - return ZR_DATA_ERROR; - case Z_VERSION_ERROR: - return ZR_VERSION_ERROR; - case Z_MEM_ERROR: - return ZR_MEM_ERROR; - } - + do { strm.avail_out = CHUNK; @@ -2381,7 +2223,9 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 case Z_DATA_ERROR: { inflateEnd(&strm); - free(result); + // free(result); + if( result ) + free(result); return ZR_DATA_ERROR; } case Z_STREAM_ERROR: @@ -2395,7 +2239,9 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 case Z_MEM_ERROR: { inflateEnd(&strm); - free(result); + // free(result); + if( result ) + free(result); return ZR_MEM_ERROR; } } @@ -2422,7 +2268,9 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 if (ret != Z_STREAM_END) { - free(result); + // free(result); + if( result ) + free(result); return ZR_DATA_ERROR; } @@ -2434,134 +2282,138 @@ LLUZipHelper::EZipRresult LLUZipHelper::unzip_llsd(LLSD& data, const U8* in, S32 if (!LLSDSerialize::fromBinary(data, istrm, cur_size, UNZIP_LLSD_MAX_DEPTH)) { - free(result); + // free(result); + if( result ) + free(result); return ZR_PARSE_ERROR; } } - free(result); + // free(result); + if( result ) + free(result); return ZR_OK; } // //This unzip function will only work with a gzip header and trailer - while the contents //of the actual compressed data is the same for either format (gzip vs zlib ), the headers //and trailers are different for the formats. -U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size ) +U8* unzip_llsdNavMesh(bool& valid, size_t& outsize, std::istream& is, S32 size) { -// Add non-allocating variants of unzip_llsd -// if (size == 0) -// { -// LL_WARNS() << "No data to unzip." << LL_ENDL; -// return NULL; -// } + // Add non-allocating variants of unzip_llsd + // if (size == 0) + // { + // LL_WARNS() << "No data to unzip." << LL_ENDL; + // return NULL; + // } -// U8* result = NULL; -// U32 cur_size = 0; -// z_stream strm; - -// const U32 CHUNK = 0x4000; + // U8* result = NULL; + // U32 cur_size = 0; + // z_stream strm; -// U8 *in = new(std::nothrow) U8[size]; -// if (in == NULL) -// { -// LL_WARNS() << "Memory allocation failure." << LL_ENDL; -// return NULL; -// } -// is.read((char*) in, size); + // const U32 CHUNK = 0x4000; -// U8 out[CHUNK]; - -// strm.zalloc = Z_NULL; -// strm.zfree = Z_NULL; -// strm.opaque = Z_NULL; -// strm.avail_in = size; -// strm.next_in = in; + // U8 *in = new(std::nothrow) U8[size]; + // if (in == NULL) + // { + // LL_WARNS() << "Memory allocation failure." << LL_ENDL; + // return NULL; + // } + // is.read((char*) in, size); -// valid = true; // Default is all okay. -// S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); -// do -// { -// strm.avail_out = CHUNK; -// strm.next_out = out; -// ret = inflate(&strm, Z_NO_FLUSH); -// if (ret == Z_STREAM_ERROR) -// { -// inflateEnd(&strm); -// // free(result); -// if( result ) -// free(result); -// delete [] in; -// in = NULL; result = NULL;// Or we get a double free aftr the while loop ... -// valid = false; -// } - -// switch (ret) -// { -// case Z_NEED_DICT: -// ret = Z_DATA_ERROR; -// case Z_DATA_ERROR: -// case Z_MEM_ERROR: -// inflateEnd(&strm); -// // free(result); -// if( result ) -// free(result); -// delete [] in; -// valid = false; -// in = NULL; result = NULL;// Or we get a double free aftr the while loop ... -// break; -// } + // U8 out[CHUNK]; -// if( valid ) {// in case this stream is invalid, do not pass the already freed buffer to realloc. - -// U32 have = CHUNK-strm.avail_out; + // strm.zalloc = Z_NULL; + // strm.zfree = Z_NULL; + // strm.opaque = Z_NULL; + // strm.avail_in = size; + // strm.next_in = in; -// U8* new_result = (U8*) realloc(result, cur_size + have); -// if (new_result == NULL) -// { -// LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size -// << " bytes; requested " << cur_size + have -// << " bytes; total syze: ." << size << " bytes." -// << LL_ENDL; -// inflateEnd(&strm); -// if (result) -// { -// free(result); -// } -// delete[] in; -// valid = false; -// return NULL; -// } -// result = new_result; -// memcpy(result+cur_size, out, have); -// cur_size += have; + // valid = true; // Default is all okay. + // S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); + // do + // { + // strm.avail_out = CHUNK; + // strm.next_out = out; + // ret = inflate(&strm, Z_NO_FLUSH); + // if (ret == Z_STREAM_ERROR) + // { + // inflateEnd(&strm); + // // free(result); + // if( result ) + // free(result); + // delete [] in; + // in = NULL; result = NULL;// Or we get a double free aftr the while loop ... + // valid = false; + // } -// } // + // switch (ret) + // { + // case Z_NEED_DICT: + // ret = Z_DATA_ERROR; + // case Z_DATA_ERROR: + // case Z_MEM_ERROR: + // inflateEnd(&strm); + // // free(result); + // if( result ) + // free(result); + // delete [] in; + // valid = false; + // in = NULL; result = NULL;// Or we get a double free aftr the while loop ... + // break; + // } -// } while (ret == Z_OK); + // if( valid ) {// in case this stream is invalid, do not pass the already freed buffer to realloc. -// inflateEnd(&strm); -// delete [] in; + // U32 have = CHUNK-strm.avail_out; -// if (ret != Z_STREAM_END) -// { -// // result might have been freed above. And calling free with a null pointer is not defined. -// // free(result); -// if( result ) -// free(result); -// // - -// valid = false; -// return NULL; -// } + // U8* new_result = (U8*) realloc(result, cur_size + have); + // if (new_result == NULL) + // { + // LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size + // << " bytes; requested " << cur_size + have + // << " bytes; total syze: ." << size << " bytes." + // << LL_ENDL; + // inflateEnd(&strm); + // if (result) + // { + // free(result); + // } + // delete[] in; + // valid = false; + // return NULL; + // } + // result = new_result; + // memcpy(result+cur_size, out, have); + // cur_size += have; -// //result now points to the decompressed LLSD block -// { -// outsize= cur_size; -// valid = true; -// } + // } // -// return result; -// } + // } while (ret == Z_OK); + + // inflateEnd(&strm); + // delete [] in; + + // if (ret != Z_STREAM_END) + // { + // // result might have been freed above. And calling free with a null pointer is not defined. + // // free(result); + // if( result ) + // free(result); + // // + + // valid = false; + // return NULL; + // } + + // //result now points to the decompressed LLSD block + // { + // outsize= cur_size; + // valid = true; + // } + + // return result; + // } if (size == 0) { LL_WARNS() << "No data to unzip." << LL_ENDL; @@ -2578,33 +2430,33 @@ U8* unzip_llsdNavMesh( bool& valid, size_t& outsize, std::istream& is, S32 size return nullptr; } - is.read((char*) in.get(), size); + is.read((char*)in.get(), size); return unzip_llsdNavMesh(valid, outsize, in.get(), size); } -U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, const U8* in, S32 size ) +U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, const U8* in, S32 size) { if (size == 0) { LL_WARNS() << "No data to unzip." << LL_ENDL; return nullptr; } - U8* result = NULL; + U8* result = nullptr; U32 cur_size = 0; z_stream strm; - + const U32 CHUNK = 0x4000; U8 out[CHUNK]; - + strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.avail_in = size; strm.next_in = const_cast(in); - - S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP ); + + S32 ret = inflateInit2(&strm, windowBits | ENABLE_ZLIB_GZIP); do { strm.avail_out = CHUNK; @@ -2614,26 +2466,26 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, const U8* in, S32 siz { inflateEnd(&strm); free(result); - return NULL; + return nullptr; } - + switch (ret) { case Z_NEED_DICT: ret = Z_DATA_ERROR; - // [[fallthrough]]; // TODO when we have C++17 compilation. + [[fallthrough]]; case Z_DATA_ERROR: case Z_MEM_ERROR: inflateEnd(&strm); free(result); valid = false; - return NULL; + return nullptr; } - U32 have = CHUNK-strm.avail_out; + U32 have = CHUNK - strm.avail_out; - U8* new_result = (U8*) realloc(result, cur_size + have); - if (new_result == NULL) + U8* new_result = (U8*)realloc(result, cur_size + have); + if (!new_result) { LL_WARNS() << "Failed to unzip LLSD NavMesh block: can't reallocate memory, current size: " << cur_size << " bytes; requested " << cur_size + have @@ -2645,10 +2497,10 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, const U8* in, S32 siz free(result); } valid = false; - return NULL; + return nullptr; } result = new_result; - memcpy(result+cur_size, out, have); + memcpy(result + cur_size, out, have); cur_size += have; } while (ret == Z_OK); @@ -2659,17 +2511,18 @@ U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, const U8* in, S32 siz { free(result); valid = false; - return NULL; + return nullptr; } //result now points to the decompressed LLSD block { - outsize= cur_size; - valid = true; + outsize = cur_size; + valid = true; } return result; } +// char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size) { @@ -2689,4 +2542,4 @@ char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size) return in; } -// \ No newline at end of file + diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 4c0c519a59..49880ec1b5 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -858,14 +858,12 @@ public: ZR_SIZE_ERROR, ZR_DATA_ERROR, ZR_PARSE_ERROR, -// Add non-allocating variants of unzip_llsd - ZR_BUFFER_ERROR, - ZR_VERSION_ERROR -// + ZR_BUFFER_ERROR, + ZR_VERSION_ERROR } EZipRresult; // return OK or reason for failure static EZipRresult unzip_llsd(LLSD& data, std::istream& is, S32 size); - static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size); // Add non-allocating variants of unzip_llsd + static EZipRresult unzip_llsd(LLSD& data, const U8* in, S32 size); }; //dirty little zip functions -- yell at davep @@ -878,5 +876,4 @@ LL_COMMON_API U8* unzip_llsdNavMesh(bool& valid, unsigned int& outsize, const U8 // returns a pointer to the array or past the array if the deprecated header exists LL_COMMON_API char* strip_deprecated_header(char* in, llssize& cur_size, llssize* header_size = nullptr); -// #endif // LL_LLSDSERIALIZE_H diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index 51b324199e..c8d18e32c9 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -1016,44 +1016,6 @@ LLUUID::LLUUID() // } -// Copy constructor - LLUUID::LLUUID(const LLUUID& rhs) -{ - LL_PROFILE_ZONE_SCOPED; - // Fix for misaligned unsigned ints in LLUUID; by Sovereign Engineer / Shyotl Kuhr - //U32 *tmp = (U32 *)mData; - //U32 *rhstmp = (U32 *)rhs.mData; - //tmp[0] = rhstmp[0]; - //tmp[1] = rhstmp[1]; - //tmp[2] = rhstmp[2]; - //tmp[3] = rhstmp[3]; - memcpy(mData, rhs.mData, sizeof(mData)); - // -} - - LLUUID::~LLUUID() -{ -} - -// Assignment - LLUUID& LLUUID::operator=(const LLUUID& rhs) -{ - LL_PROFILE_ZONE_SCOPED; - // Fix for misaligned unsigned ints in LLUUID; by Sovereign Engineer / Shyotl Kuhr - //// No need to check the case where this==&rhs. The branch is slower than the write. - //U32 *tmp = (U32 *)mData; - //U32 *rhstmp = (U32 *)rhs.mData; - //tmp[0] = rhstmp[0]; - //tmp[1] = rhstmp[1]; - //tmp[2] = rhstmp[2]; - //tmp[3] = rhstmp[3]; - - memcpy(mData, rhs.mData, sizeof(mData)); - // - return *this; -} - - LLUUID::LLUUID(const char *in_string) { if (!in_string || in_string[0] == 0) diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index f7215b1dae..5f0d7579f2 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -29,11 +29,10 @@ #include #include #include -#include // for std::memmove #include "stdtypes.h" #include "llpreprocessor.h" #include -#include "llprofiler.h" + class LLMutex; const S32 UUID_BYTES = 16; @@ -56,12 +55,7 @@ public: LLUUID(); explicit LLUUID(const char *in_string); // Convert from string. explicit LLUUID(const std::string& in_string); // Convert from string. - LLUUID(const LLUUID &in); - LLUUID(LLUUID&& rhs) noexcept { LL_PROFILE_ZONE_SCOPED; std::memmove(mData, rhs.mData, sizeof(mData));}; - LLUUID &operator=(const LLUUID &rhs); - LLUUID &operator=(LLUUID &&rhs) noexcept { LL_PROFILE_ZONE_SCOPED; std::memmove(mData, rhs.mData, sizeof(mData));return *this;}; - - ~LLUUID(); + ~LLUUID() = default; // // MANIPULATORS @@ -189,6 +183,9 @@ public: U8 mData[UUID_BYTES]; }; +static_assert(std::is_trivially_copyable::value, "LLUUID must be trivial copy"); +static_assert(std::is_trivially_move_assignable::value, "LLUUID must be trivial move"); +static_assert(std::is_standard_layout::value, "LLUUID must be a standard layout type"); typedef std::vector uuid_vec_t; typedef std::set uuid_set_t; diff --git a/indra/llcommon/threadsafeschedule.h b/indra/llcommon/threadsafeschedule.h index b057b01668..92bc7da940 100644 --- a/indra/llcommon/threadsafeschedule.h +++ b/indra/llcommon/threadsafeschedule.h @@ -248,8 +248,6 @@ namespace LL TimePoint until = TimePoint::clock::now() + std::chrono::hours(24); pop_result popped = tryPopUntil_(lock, until, tt); if (popped == POPPED) - // Prevent RVO elision - //return std::move(tt); return tt; // DONE: throw, just as super::pop() does diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp index b8414ff009..437a380c76 100644 --- a/indra/llfilesystem/lldir_mac.cpp +++ b/indra/llfilesystem/lldir_mac.cpp @@ -66,16 +66,16 @@ LLDir_Mac::LLDir_Mac() const std::string secondLifeString = "Firestorm"; - std::string *executablepathstr = getSystemExecutableFolder(); + std::string executablepathstr = getSystemExecutableFolder(); //NOTE: LLINFOS/LLERRS will not output to log here. The streams are not initialized. - if (executablepathstr) + if (!executablepathstr.empty()) { // mExecutablePathAndName - mExecutablePathAndName = *executablepathstr; + mExecutablePathAndName = executablepathstr; - boost::filesystem::path executablepath(*executablepathstr); + boost::filesystem::path executablepath(executablepathstr); # ifndef BOOST_SYSTEM_NO_DEPRECATED #endif @@ -83,8 +83,8 @@ LLDir_Mac::LLDir_Mac() mExecutableDir = executablepath.parent_path().string(); // mAppRODataDir - std::string *resourcepath = getSystemResourceFolder(); - mAppRODataDir = *resourcepath; + std::string resourcepath = getSystemResourceFolder(); + mAppRODataDir = resourcepath; // *NOTE: When running in a dev tree, use the copy of // skins in indra/newview/ rather than in the application bundle. This @@ -110,11 +110,11 @@ LLDir_Mac::LLDir_Mac() } // mOSUserDir - std::string *appdir = getSystemApplicationSupportFolder(); + std::string appdir = getSystemApplicationSupportFolder(); std::string rootdir; //Create root directory - if (CreateDirectory(*appdir, secondLifeString, &rootdir)) + if (CreateDirectory(appdir, secondLifeString, &rootdir)) { // Save the full path to the folder @@ -128,12 +128,10 @@ LLDir_Mac::LLDir_Mac() } //mOSCacheDir - std::string *cachedir = getSystemCacheFolder(); - - if (cachedir) - + std::string cachedir = getSystemCacheFolder(); + if (!cachedir.empty()) { - mOSCacheDir = *cachedir; + mOSCacheDir = cachedir; //TODO: This changes from ~/Library/Cache/Secondlife to ~/Library/Cache/com.app.secondlife/Secondlife. Last dir level could go away. // Adjust the cache directory to match what's expected in lldir. //CreateDirectory(mOSCacheDir, secondLifeString, NULL); @@ -159,12 +157,10 @@ LLDir_Mac::LLDir_Mac() // mTempDir //Aura 120920 boost::filesystem::temp_directory_path() not yet implemented on mac. :( - std::string *tmpdir = getSystemTempFolder(); - if (tmpdir) + std::string tmpdir = getSystemTempFolder(); + if (!tmpdir.empty()) { - - CreateDirectory(*tmpdir, secondLifeString, &mTempDir); - if (tmpdir) delete tmpdir; + CreateDirectory(tmpdir, secondLifeString, &mTempDir); } mWorkingDir = getCurPath(); diff --git a/indra/llfilesystem/lldir_utils_objc.h b/indra/llfilesystem/lldir_utils_objc.h index 12019c4284..59dbeb4aec 100644 --- a/indra/llfilesystem/lldir_utils_objc.h +++ b/indra/llfilesystem/lldir_utils_objc.h @@ -33,11 +33,11 @@ #include -std::string* getSystemTempFolder(); -std::string* getSystemCacheFolder(); -std::string* getSystemApplicationSupportFolder(); -std::string* getSystemResourceFolder(); -std::string* getSystemExecutableFolder(); +std::string getSystemTempFolder(); +std::string getSystemCacheFolder(); +std::string getSystemApplicationSupportFolder(); +std::string getSystemResourceFolder(); +std::string getSystemExecutableFolder(); #endif // LL_LLDIR_UTILS_OBJC_H diff --git a/indra/llfilesystem/lldir_utils_objc.mm b/indra/llfilesystem/lldir_utils_objc.mm index da55a2f897..20540fb93c 100644 --- a/indra/llfilesystem/lldir_utils_objc.mm +++ b/indra/llfilesystem/lldir_utils_objc.mm @@ -30,75 +30,75 @@ #include "lldir_utils_objc.h" #import -std::string* getSystemTempFolder() +std::string getSystemTempFolder() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSString * tempDir = NSTemporaryDirectory(); - if (tempDir == nil) - tempDir = @"/tmp"; - std::string *result = ( new std::string([tempDir UTF8String]) ); - [pool release]; + std::string result; + @autoreleasepool { + NSString * tempDir = NSTemporaryDirectory(); + if (tempDir == nil) + tempDir = @"/tmp"; + result = std::string([tempDir UTF8String]); + } return result; } //findSystemDirectory scoped exclusively to this file. -std::string* findSystemDirectory(NSSearchPathDirectory searchPathDirectory, +std::string findSystemDirectory(NSSearchPathDirectory searchPathDirectory, NSSearchPathDomainMask domainMask) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - std::string *result = nil; - NSString *path = nil; - - // Search for the path - NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory, - domainMask, - YES); - if ([paths count]) - { - path = [paths objectAtIndex:0]; - //HACK: Always attempt to create directory, ignore errors. - NSError *error = nil; - - [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]; - + std::string result; + @autoreleasepool { + NSString *path = nil; - result = new std::string([path UTF8String]); + // Search for the path + NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory, + domainMask, + YES); + if ([paths count]) + { + path = [paths objectAtIndex:0]; + //HACK: Always attempt to create directory, ignore errors. + NSError *error = nil; + + [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error]; + + + result = std::string([path UTF8String]); + } } - [pool release]; return result; } -std::string* getSystemExecutableFolder() +std::string getSystemExecutableFolder() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *bundlePath = [[NSBundle mainBundle] executablePath]; - std::string *result = (new std::string([bundlePath UTF8String])); - [pool release]; + std::string result; + @autoreleasepool { + NSString *bundlePath = [[NSBundle mainBundle] executablePath]; + result = std::string([bundlePath UTF8String]); + } return result; } -std::string* getSystemResourceFolder() +std::string getSystemResourceFolder() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - NSString *bundlePath = [[NSBundle mainBundle] resourcePath]; - std::string *result = (new std::string([bundlePath UTF8String])); - [pool release]; + std::string result; + @autoreleasepool { + NSString *bundlePath = [[NSBundle mainBundle] resourcePath]; + result = std::string([bundlePath UTF8String]); + } return result; } -std::string* getSystemCacheFolder() +std::string getSystemCacheFolder() { return findSystemDirectory (NSCachesDirectory, NSUserDomainMask); } -std::string* getSystemApplicationSupportFolder() +std::string getSystemApplicationSupportFolder() { return findSystemDirectory (NSApplicationSupportDirectory, NSUserDomainMask); diff --git a/indra/llimage/llpngwrapper.cpp b/indra/llimage/llpngwrapper.cpp index f7dc6272cf..cad7c00042 100644 --- a/indra/llimage/llpngwrapper.cpp +++ b/indra/llimage/llpngwrapper.cpp @@ -257,12 +257,7 @@ void LLPngWrapper::normalizeImage() png_set_strip_16(mReadPngPtr); } -#if LL_DARWIN - const F64 SCREEN_GAMMA = 1.8; -#else const F64 SCREEN_GAMMA = 2.2; -#endif - if (png_get_gAMA(mReadPngPtr, mReadInfoPtr, &mGamma)) { png_set_gamma(mReadPngPtr, SCREEN_GAMMA, mGamma); diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index 08f03c7bdb..4f8aa59c1a 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -25,184 +25,48 @@ */ #include "linden_common.h" -// #include "fstelemetry.h" // instrument image decodes #include "llimagej2coj.h" -#define OPENJPEG2 // this is defined so that we get static linking. #include "openjpeg.h" -#ifndef OPENJPEG2 -#include "cio.h" -#endif #include "event.h" +#include "cio.h" -#include "lltimer.h" - -// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3 -#ifdef OPENJPEG2 -class LLJp2StreamReader { -public: - LLJp2StreamReader(LLImageJ2C* pImage) : m_pImage(pImage), m_Position(0) { } - - static OPJ_SIZE_T readStream(void* pBufferOut, OPJ_SIZE_T szBufferOut, void* pUserData) - { - LLJp2StreamReader* pStream = (LLJp2StreamReader*)pUserData; - if ( (!pBufferOut) || (!pStream) || (!pStream->m_pImage) ) - return (OPJ_SIZE_T)-1; - - OPJ_SIZE_T szBufferRead = llmin(szBufferOut, pStream->m_pImage->getDataSize() - pStream->m_Position); - if (!szBufferRead) - return (OPJ_SIZE_T)-1; - - memcpy(pBufferOut, pStream->m_pImage->getData() + pStream->m_Position, szBufferRead); - pStream->m_Position += szBufferRead; - return szBufferRead; - } - - static OPJ_OFF_T skipStream(OPJ_OFF_T bufferOffset, void* pUserData) - { - LLJp2StreamReader* pStream = (LLJp2StreamReader*)pUserData; - if ( (!pStream) || (!pStream->m_pImage) ) - return (OPJ_SIZE_T)-1; - - if (bufferOffset < 0) - { - // Skipping backward - if (pStream->m_Position == 0) - return (OPJ_SIZE_T)-1; // Already at the start of the stream - else if (pStream->m_Position + bufferOffset < 0) - bufferOffset = -(OPJ_OFF_T)pStream->m_Position; // Don't underflow - } - else - { - // Skipping forward - OPJ_SIZE_T szRemaining = pStream->m_pImage->getDataSize() - pStream->m_Position; - if (!szRemaining) - return (OPJ_SIZE_T)-1; // Already at the end of the stream - else if (bufferOffset > szRemaining) - bufferOffset = szRemaining; // Don't overflow - } - pStream->m_Position += bufferOffset; - - return bufferOffset; - } - - static OPJ_BOOL seekStream(OPJ_OFF_T bufferOffset, void* pUserData) - { - LLJp2StreamReader* pStream = (LLJp2StreamReader*)pUserData; - if ( (!pStream) || (!pStream->m_pImage) ) - return OPJ_FALSE; - - if ( (bufferOffset < 0) || (bufferOffset > pStream->m_pImage->getDataSize()) ) - return OPJ_FALSE; - - pStream->m_Position = bufferOffset; - return OPJ_TRUE; - } -protected: - LLImageJ2C* m_pImage = nullptr; - OPJ_SIZE_T m_Position = 0; -}; - -class LLJp2StreamWriter { -public: - LLJp2StreamWriter(LLImageJ2C* pImage) : m_pImage(pImage), m_Position(0) { } - - static OPJ_SIZE_T writeStream(void* pBufferIn, OPJ_SIZE_T szBufferIn, void* pUserData) - { - LLJp2StreamWriter* pStream = (LLJp2StreamWriter*)pUserData; - if ( (!pBufferIn) || (!pStream) || (!pStream->m_pImage) ) - return (OPJ_SIZE_T)-1; - - if (pStream->m_Position + szBufferIn > pStream->m_pImage->getDataSize()) - pStream->m_pImage->reallocateData(pStream->m_Position + szBufferIn); - - memcpy(pStream->m_pImage->getData() + pStream->m_Position, pBufferIn, szBufferIn); - pStream->m_Position += szBufferIn; - return szBufferIn; - } - - static OPJ_OFF_T skipStream(OPJ_OFF_T bufferOffset, void* pUserData) - { - LLJp2StreamWriter* pStream = (LLJp2StreamWriter*)pUserData; - if ( (!pStream) || (!pStream->m_pImage) ) - return -1; - - if (bufferOffset < 0) - { - // Skipping backward - if (pStream->m_Position == 0) - return -1; // Already at the start of the stream - else if (pStream->m_Position + bufferOffset < 0) - bufferOffset = -pStream->m_Position; // Don't underflow - } - else - { - // Skipping forward - if (pStream->m_Position + bufferOffset > pStream->m_pImage->getDataSize()) - return -1; // Don't allow skipping past the end of the stream - } - - pStream->m_Position += bufferOffset; - return bufferOffset; - } - - static OPJ_BOOL seekStream(OPJ_OFF_T bufferOffset, void* pUserData) - { - LLJp2StreamWriter* pStream = (LLJp2StreamWriter*)pUserData; - if ( (!pStream) || (!pStream->m_pImage) ) - return OPJ_FALSE; - - if ( (bufferOffset < 0) || (bufferOffset > pStream->m_pImage->getDataSize()) ) - return OPJ_FALSE; - - pStream->m_Position = bufferOffset; - return OPJ_TRUE; - } - -protected: - LLImageJ2C* m_pImage = nullptr; - OPJ_OFF_T m_Position = 0; -}; -#endif -// [/SL:KB] +#define MAX_ENCODED_DISCARD_LEVELS 5 // Factory function: see declaration in llimagej2c.cpp LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl() { - return new LLImageJ2COJ(); + return new LLImageJ2COJ(); } std::string LLImageJ2COJ::getEngineInfo() const { -#ifdef OPENJPEG_VERSION - return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ") - + opj_version(); -#elif defined OPJ_PACKAGE_VERSION - return std::string("OpenJPEG: " OPJ_PACKAGE_VERSION ", Runtime: ") + opj_version(); -#else -#ifdef OPENJPEG2 - return llformat("OpenJPEG: %i.%i.%i, Runtime: %s", OPJ_VERSION_MAJOR, OPJ_VERSION_MINOR, OPJ_VERSION_BUILD, opj_version()); -#else - return std::string("OpenJPEG Runtime: ") + opj_version(); -#endif -#endif +// OpenJpeg fixes +//#ifdef OPENJPEG_VERSION +// return std::string("OpenJPEG: " OPENJPEG_VERSION ", Runtime: ") +// + opj_version(); +//#else +// return std::string("OpenJPEG runtime: ") + opj_version(); +//#endif + return llformat("OpenJPEG: %i.%i.%i, Runtime: %s", OPJ_VERSION_MAJOR, OPJ_VERSION_MINOR, OPJ_VERSION_BUILD, opj_version()); +// } // Return string from message, eliminating final \n if present static std::string chomp(const char* msg) { - // stomp trailing \n - std::string message = msg; - if (!message.empty()) - { - size_t last = message.size() - 1; - if (message[last] == '\n') - { - message.resize( last ); - } - } - return message; + // stomp trailing \n + std::string message = msg; + if (!message.empty()) + { + size_t last = message.size() - 1; + if (message[last] == '\n') + { + message.resize(last); + } +} + return message; } /** @@ -210,29 +74,642 @@ sample error callback expecting a LLFILE* client object */ void error_callback(const char* msg, void*) { - LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL; + LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL; } /** sample warning callback expecting a LLFILE* client object */ void warning_callback(const char* msg, void*) { - LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL; + LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL; } /** sample debug callback expecting no client object */ void info_callback(const char* msg, void*) { - LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL; + LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL; } // Divide a by 2 to the power of b and round upwards int ceildivpow2(int a, int b) { - return (a + (1 << b) - 1) >> b; + return (a + (1 << b) - 1) >> b; } +class JPEG2KBase +{ +public: + JPEG2KBase() {} + + U8* buffer = nullptr; + OPJ_SIZE_T size = 0; + OPJ_OFF_T offset = 0; +}; + +#define WANT_VERBOSE_OPJ_SPAM LL_DEBUG + +static void opj_info(const char* msg, void* user_data) +{ + llassert(user_data); +#if WANT_VERBOSE_OPJ_SPAM + LL_INFOS("OpenJPEG") << msg << LL_ENDL; +#endif +} + +static void opj_warn(const char* msg, void* user_data) +{ + llassert(user_data); +#if WANT_VERBOSE_OPJ_SPAM + LL_WARNS("OpenJPEG") << msg << LL_ENDL; +#endif +} + +static void opj_error(const char* msg, void* user_data) +{ + llassert(user_data); +#if WANT_VERBOSE_OPJ_SPAM + LL_WARNS("OpenJPEG") << msg << LL_ENDL; +#endif +} + +static OPJ_SIZE_T opj_read(void * buffer, OPJ_SIZE_T bytes, void* user_data) +{ + llassert(user_data); + JPEG2KBase* jpeg_codec = static_cast(user_data); + OPJ_SIZE_T remainder = (jpeg_codec->size - jpeg_codec->offset); + if (remainder <= 0) + { + jpeg_codec->offset = jpeg_codec->size; + // Indicate end of stream (hacky?) + return (OPJ_OFF_T)-1; + } + OPJ_SIZE_T to_read = llclamp(U32(bytes), U32(0), U32(remainder)); + memcpy(buffer, jpeg_codec->buffer + jpeg_codec->offset, to_read); + jpeg_codec->offset += to_read; + return to_read; +} + +static OPJ_SIZE_T opj_write(void * buffer, OPJ_SIZE_T bytes, void* user_data) +{ + llassert(user_data); + JPEG2KBase* jpeg_codec = static_cast(user_data); + OPJ_SIZE_T remainder = jpeg_codec->size - jpeg_codec->offset; + if (remainder < bytes) + { + OPJ_SIZE_T new_size = jpeg_codec->size + (bytes - remainder); + U8* new_buffer = (U8*)ll_aligned_malloc_16(new_size); + memcpy(new_buffer, jpeg_codec->buffer, jpeg_codec->offset); + U8* old_buffer = jpeg_codec->buffer; + jpeg_codec->buffer = new_buffer; + ll_aligned_free_16(old_buffer); + jpeg_codec->size = new_size; + } + memcpy(jpeg_codec->buffer + jpeg_codec->offset, buffer, bytes); + jpeg_codec->offset += bytes; + return bytes; +} + +static OPJ_OFF_T opj_skip(OPJ_OFF_T bytes, void* user_data) +{ + JPEG2KBase* jpeg_codec = static_cast(user_data); + jpeg_codec->offset += bytes; + + if (jpeg_codec->offset > jpeg_codec->size) + { + jpeg_codec->offset = jpeg_codec->size; + // Indicate end of stream + return (OPJ_OFF_T)-1; + } + + if (jpeg_codec->offset < 0) + { + // Shouldn't be possible? + jpeg_codec->offset = 0; + return (OPJ_OFF_T)-1; + } + + return bytes; +} + +static OPJ_BOOL opj_seek(OPJ_OFF_T bytes, void * user_data) +{ + JPEG2KBase* jpeg_codec = static_cast(user_data); + jpeg_codec->offset = bytes; + jpeg_codec->offset = llclamp(U32(jpeg_codec->offset), U32(0), U32(jpeg_codec->size)); + return OPJ_TRUE; +} + +static void opj_free_user_data(void * user_data) +{ + JPEG2KBase* jpeg_codec = static_cast(user_data); + // Don't free, data is managed externally + jpeg_codec->buffer = nullptr; + jpeg_codec->size = 0; + jpeg_codec->offset = 0; +} + +static void opj_free_user_data_write(void * user_data) +{ + JPEG2KBase* jpeg_codec = static_cast(user_data); + // Free, data was allocated here + ll_aligned_free_16(jpeg_codec->buffer); + jpeg_codec->buffer = nullptr; + jpeg_codec->size = 0; + jpeg_codec->offset = 0; +} + +class JPEG2KDecode : public JPEG2KBase +{ +public: + + JPEG2KDecode(S8 discardLevel) + { + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + memset(¶meters, 0, sizeof(opj_dparameters_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + opj_set_default_decoder_parameters(¶meters); + parameters.cp_reduce = discardLevel; + } + + ~JPEG2KDecode() + { + if (decoder) + { + opj_destroy_codec(decoder); + } + decoder = nullptr; + + if (image) + { + opj_image_destroy(image); + } + image = nullptr; + + if (stream) + { + opj_stream_destroy(stream); + } + stream = nullptr; + + if (codestream_info) + { + opj_destroy_cstr_info(&codestream_info); + } + codestream_info = nullptr; + } + + bool readHeader( + U8* data, + U32 dataSize, + S32& widthOut, + S32& heightOut, + S32& components, + S32& discard_level) + { + parameters.flags |= OPJ_DPARAMETERS_DUMP_FLAG; + + decoder = opj_create_decompress(OPJ_CODEC_J2K); + + if (!opj_setup_decoder(decoder, ¶meters)) + { + return false; + } + + if (stream) + { + opj_stream_destroy(stream); + } + + stream = opj_stream_create(dataSize, true); + if (!stream) + { + return false; + } + + opj_stream_set_user_data(stream, this, opj_free_user_data); + opj_stream_set_user_data_length(stream, dataSize); + opj_stream_set_read_function(stream, opj_read); + opj_stream_set_write_function(stream, opj_write); + opj_stream_set_skip_function(stream, opj_skip); + opj_stream_set_seek_function(stream, opj_seek); + + buffer = data; + size = dataSize; + offset = 0; + + // enable decoding partially loaded images + opj_decoder_set_strict_mode(decoder, OPJ_FALSE); + + /* Read the main header of the codestream and if necessary the JP2 boxes*/ + if (!opj_read_header((opj_stream_t*)stream, decoder, &image)) + { + return false; + } + + codestream_info = opj_get_cstr_info(decoder); + + if (!codestream_info) + { + return false; + } + + U32 tileDimX = codestream_info->tdx; + U32 tileDimY = codestream_info->tdy; + U32 tilesW = codestream_info->tw; + U32 tilesH = codestream_info->th; + + widthOut = S32(tilesW * tileDimX); + heightOut = S32(tilesH * tileDimY); + components = codestream_info->nbcomps; + + discard_level = 0; + while (tilesW > 1 && tilesH > 1 && discard_level < MAX_DISCARD_LEVEL) + { + discard_level++; + tilesW >>= 1; + tilesH >>= 1; + } + + return true; + } + + bool decode(U8* data, U32 dataSize, U32* channels, U8 discard_level) + { + parameters.flags &= ~OPJ_DPARAMETERS_DUMP_FLAG; + + decoder = opj_create_decompress(OPJ_CODEC_J2K); + opj_setup_decoder(decoder, ¶meters); + + opj_set_info_handler(decoder, opj_info, this); + opj_set_warning_handler(decoder, opj_warn, this); + opj_set_error_handler(decoder, opj_error, this); + + if (stream) + { + opj_stream_destroy(stream); + } + + stream = opj_stream_create(dataSize, true); + if (!stream) + { + return false; + } + + opj_stream_set_user_data(stream, this, opj_free_user_data); + opj_stream_set_user_data_length(stream, dataSize); + opj_stream_set_read_function(stream, opj_read); + opj_stream_set_write_function(stream, opj_write); + opj_stream_set_skip_function(stream, opj_skip); + opj_stream_set_seek_function(stream, opj_seek); + + buffer = data; + size = dataSize; + offset = 0; + + if (image) + { + opj_image_destroy(image); + image = nullptr; + } + + // needs to happen before opj_read_header and opj_decode... + opj_set_decoded_resolution_factor(decoder, discard_level); + + // enable decoding partially loaded images + opj_decoder_set_strict_mode(decoder, OPJ_FALSE); + + if (!opj_read_header(stream, decoder, &image)) + { + return false; + } + + // needs to happen before decode which may fail + if (channels) + { + *channels = image->numcomps; + } + + OPJ_BOOL decoded = opj_decode(decoder, stream, image); + + // count was zero. The latter is just a sanity check before we + // dereference the array. + if (!decoded || !image || !image->numcomps) + { + opj_end_decompress(decoder, stream); + return false; + } + + opj_end_decompress(decoder, stream); + + return true; + } + + opj_image_t* getImage() { return image; } + +private: + opj_dparameters_t parameters; + opj_event_mgr_t event_mgr; + opj_image_t* image = nullptr; + opj_codec_t* decoder = nullptr; + opj_stream_t* stream = nullptr; + opj_codestream_info_v2_t* codestream_info = nullptr; +}; + +class JPEG2KEncode : public JPEG2KBase +{ +public: + const OPJ_UINT32 TILE_SIZE = 64 * 64 * 3; + + JPEG2KEncode(const char* comment_text_in, bool reversible) + { + memset(¶meters, 0, sizeof(opj_cparameters_t)); + memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); + event_mgr.error_handler = error_callback; + event_mgr.warning_handler = warning_callback; + event_mgr.info_handler = info_callback; + + opj_set_default_encoder_parameters(¶meters); + parameters.cod_format = OPJ_CODEC_J2K; + parameters.cp_disto_alloc = 1; + parameters.max_cs_size = (1 << 15); + + if (reversible) + { + parameters.tcp_numlayers = 1; + parameters.tcp_rates[0] = 1.0f; + } + else + { + parameters.tcp_numlayers = 5; + parameters.tcp_rates[0] = 1920.0f; + parameters.tcp_rates[1] = 960.0f; + parameters.tcp_rates[2] = 480.0f; + parameters.tcp_rates[3] = 120.0f; + parameters.tcp_rates[4] = 30.0f; + parameters.irreversible = 1; + parameters.tcp_mct = 1; + } + + if (comment_text) + { + free(comment_text); + } + comment_text = comment_text_in ? strdup(comment_text_in) : nullptr; + + parameters.cp_comment = comment_text ? comment_text : (char*)"no comment"; + llassert(parameters.cp_comment); + } + + ~JPEG2KEncode() + { + if (encoder) + { + opj_destroy_codec(encoder); + } + encoder = nullptr; + + if (image) + { + opj_image_destroy(image); + } + image = nullptr; + + if (stream) + { + opj_stream_destroy(stream); + } + stream = nullptr; + + if (comment_text) + { + free(comment_text); + } + comment_text = nullptr; + } + + bool encode(const LLImageRaw& rawImageIn, LLImageJ2C &compressedImageOut) + { + setImage(rawImageIn); + + encoder = opj_create_compress(OPJ_CODEC_J2K); + + parameters.tcp_mct = (image->numcomps >= 3) ? 1 : 0; + parameters.cod_format = OPJ_CODEC_J2K; + parameters.prog_order = OPJ_RLCP; + parameters.cp_disto_alloc = 1; + + if (!opj_setup_encoder(encoder, ¶meters, image)) + { + return false; + } + + opj_set_info_handler(encoder, opj_info, this); + opj_set_warning_handler(encoder, opj_warn, this); + opj_set_error_handler(encoder, opj_error, this); + + U32 tile_count = (rawImageIn.getWidth() >> 6) * (rawImageIn.getHeight() >> 6); + U32 data_size_guess = tile_count * TILE_SIZE; + + // will be freed in opj_free_user_data_write + buffer = (U8*)ll_aligned_malloc_16(data_size_guess); + size = data_size_guess; + offset = 0; + + memset(buffer, 0, data_size_guess); + + if (stream) + { + opj_stream_destroy(stream); + } + + stream = opj_stream_create(data_size_guess, false); + if (!stream) + { + return false; + } + + opj_stream_set_user_data(stream, this, opj_free_user_data_write); + opj_stream_set_user_data_length(stream, data_size_guess); + opj_stream_set_read_function(stream, opj_read); + opj_stream_set_write_function(stream, opj_write); + opj_stream_set_skip_function(stream, opj_skip); + opj_stream_set_seek_function(stream, opj_seek); + + OPJ_BOOL started = opj_start_compress(encoder, image, stream); + + if (!started) + { + return false; + } + + if (!opj_encode(encoder, stream)) + { + return false; + } + + OPJ_BOOL encoded = opj_end_compress(encoder, stream); + + // if we successfully encoded, then stream out the compressed data... + if (encoded) + { + // "append" (set) the data we "streamed" (memcopied) for writing to the formatted image + // with side-effect of setting the actually encoded size to same + compressedImageOut.allocateData(offset); + memcpy(compressedImageOut.getData(), buffer, offset); + compressedImageOut.updateData(); // update width, height etc from header + } + return encoded; + } + + void setImage(const LLImageRaw& raw) + { + opj_image_cmptparm_t cmptparm[MAX_ENCODED_DISCARD_LEVELS]; + memset(&cmptparm[0], 0, MAX_ENCODED_DISCARD_LEVELS * sizeof(opj_image_cmptparm_t)); + + S32 numcomps = raw.getComponents(); + S32 width = raw.getWidth(); + S32 height = raw.getHeight(); + + for (S32 c = 0; c < numcomps; c++) + { + cmptparm[c].prec = 8; + cmptparm[c].bpp = 8; + cmptparm[c].sgnd = 0; + cmptparm[c].dx = parameters.subsampling_dx; + cmptparm[c].dy = parameters.subsampling_dy; + cmptparm[c].w = width; + cmptparm[c].h = height; + } + + image = opj_image_create(numcomps, &cmptparm[0], OPJ_CLRSPC_SRGB); + + image->x1 = width; + image->y1 = height; + + const U8 *src_datap = raw.getData(); + + S32 i = 0; + for (S32 y = height - 1; y >= 0; y--) + { + for (S32 x = 0; x < width; x++) + { + const U8 *pixel = src_datap + (y*width + x) * numcomps; + for (S32 c = 0; c < numcomps; c++) + { + image->comps[c].data[i] = *pixel; + pixel++; + } + i++; + } + } + + // This likely works, but there seems to be an issue openjpeg side + // check over after gixing that. + + // De-interleave to component plane data + /* + switch (numcomps) + { + case 0: + default: + break; + + case 1: + { + U32 rBitDepth = image->comps[0].bpp; + U32 bytesPerPixel = rBitDepth >> 3; + memcpy(image->comps[0].data, src, width * height * bytesPerPixel); + } + break; + + case 2: + { + U32 rBitDepth = image->comps[0].bpp; + U32 gBitDepth = image->comps[1].bpp; + U32 totalBitDepth = rBitDepth + gBitDepth; + U32 bytesPerPixel = totalBitDepth >> 3; + U32 stride = width * bytesPerPixel; + U32 offset = 0; + for (S32 y = height - 1; y >= 0; y--) + { + const U8* component = src + (y * stride); + for (S32 x = 0; x < width; x++) + { + image->comps[0].data[offset] = *component++; + image->comps[1].data[offset] = *component++; + offset++; + } + } + } + break; + + case 3: + { + U32 rBitDepth = image->comps[0].bpp; + U32 gBitDepth = image->comps[1].bpp; + U32 bBitDepth = image->comps[2].bpp; + U32 totalBitDepth = rBitDepth + gBitDepth + bBitDepth; + U32 bytesPerPixel = totalBitDepth >> 3; + U32 stride = width * bytesPerPixel; + U32 offset = 0; + for (S32 y = height - 1; y >= 0; y--) + { + const U8* component = src + (y * stride); + for (S32 x = 0; x < width; x++) + { + image->comps[0].data[offset] = *component++; + image->comps[1].data[offset] = *component++; + image->comps[2].data[offset] = *component++; + offset++; + } + } + } + break; + + + case 4: + { + U32 rBitDepth = image->comps[0].bpp; + U32 gBitDepth = image->comps[1].bpp; + U32 bBitDepth = image->comps[2].bpp; + U32 aBitDepth = image->comps[3].bpp; + + U32 totalBitDepth = rBitDepth + gBitDepth + bBitDepth + aBitDepth; + U32 bytesPerPixel = totalBitDepth >> 3; + + U32 stride = width * bytesPerPixel; + U32 offset = 0; + for (S32 y = height - 1; y >= 0; y--) + { + const U8* component = src + (y * stride); + for (S32 x = 0; x < width; x++) + { + image->comps[0].data[offset] = *component++; + image->comps[1].data[offset] = *component++; + image->comps[2].data[offset] = *component++; + image->comps[3].data[offset] = *component++; + offset++; + } + } + } + break; + }*/ + } + + opj_image_t* getImage() { return image; } + +private: + opj_cparameters_t parameters; + opj_event_mgr_t event_mgr; + opj_image_t* image = nullptr; + opj_codec_t* encoder = nullptr; + opj_stream_t* stream = nullptr; + char* comment_text = nullptr; +}; + LLImageJ2COJ::LLImageJ2COJ() : LLImageJ2CImpl() @@ -246,7 +723,7 @@ LLImageJ2COJ::~LLImageJ2COJ() bool LLImageJ2COJ::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, int discard_level, int* region) { - // No specific implementation for this method in the OpenJpeg case + base.mDiscardLevel = discard_level; return false; } @@ -258,656 +735,165 @@ bool LLImageJ2COJ::initEncode(LLImageJ2C &base, LLImageRaw &raw_image, int block bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decode_time, S32 first_channel, S32 max_channel_count) { - // texture comment metadata reader - LL_PROFILE_ZONE_SCOPED; // instrument image decodes - U8* c_data = base.getData(); - S32 c_size = base.getDataSize(); - S32 position = 0; - - while (position < 1024 && position < (c_size - 7)) // the comment field should be in the first 1024 bytes. - { - if (c_data[position] == 0xff && c_data[position + 1] == 0x64) - { - U8 high_byte = c_data[position + 2]; - U8 low_byte = c_data[position + 3]; - S32 c_length = (high_byte * 256) + low_byte; // This size also counts the markers, 00 01 and itself - if (c_length > 200) // sanity check - { - // While comments can be very long, anything longer then 200 is suspect. - break; - } + JPEG2KDecode decoder(0); - if (position + 2 + c_length > c_size) - { - // comment extends past end of data, corruption, or all data not retrived yet. - break; - } + // texture comment metadata reader + LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE; // instrument image decodes + U8* c_data = base.getData(); + S32 c_size = base.getDataSize(); + S32 position = 0; - // if the comment block does not end at the end of data, check to see if the next - // block starts with 0xFF - if (position + 2 + c_length < c_size && c_data[position + 2 + c_length] != 0xff) - { - // invalied comment block - break; - } + while (position < 1024 && position < (c_size - 7)) // the comment field should be in the first 1024 bytes. + { + if (c_data[position] == 0xff && c_data[position + 1] == 0x64) + { + U8 high_byte = c_data[position + 2]; + U8 low_byte = c_data[position + 3]; + S32 c_length = (high_byte * 256) + low_byte; // This size also counts the markers, 00 01 and itself + if (c_length > 200) // sanity check + { + // While comments can be very long, anything longer then 200 is suspect. + break; + } - // extract the comment minus the markers, 00 01 - raw_image.mComment.assign((char*)(c_data + position + 6), c_length - 4); - break; - } - position++; - } - // + if (position + 2 + c_length > c_size) + { + // comment extends past end of data, corruption, or all data not retrived yet. + break; + } - LLTimer decode_timer; + // if the comment block does not end at the end of data, check to see if the next + // block starts with 0xFF + if (position + 2 + c_length < c_size && c_data[position + 2 + c_length] != 0xff) + { + // invalied comment block + break; + } - opj_dparameters_t parameters; /* decompression parameters */ - opj_event_mgr_t event_mgr; /* event manager */ - opj_image_t *image = NULL; + // extract the comment minus the markers, 00 01 + raw_image.mComment.assign((char*)(c_data + position + 6), c_length - 4); + break; + } + position++; + } + // -#ifndef OPENJPEG2 - opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ - opj_cio_t *cio = NULL; -#endif + U32 image_channels = 0; + S32 data_size = base.getDataSize(); + S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size); + bool decoded = decoder.decode(base.getData(), max_bytes, &image_channels, base.mDiscardLevel); - /* configure the event callbacks (not required) */ - memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); - event_mgr.error_handler = error_callback; - event_mgr.warning_handler = warning_callback; - event_mgr.info_handler = info_callback; + // set correct channel count early so failed decodes don't miss it... + S32 channels = (S32)image_channels - first_channel; + channels = llmin(channels, max_channel_count); - /* set decoding parameters to default values */ - opj_set_default_decoder_parameters(¶meters); + if (!decoded) + { + // reset the channel count if necessary + if (raw_image.getComponents() != channels) + { + raw_image.resize(raw_image.getWidth(), raw_image.getHeight(), S8(channels)); + } - parameters.cp_reduce = base.getRawDiscardLevel(); + LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; + // [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3 + base.decodeFailed(); + // [SL:KB] + return true; // done + } - /* decode the code-stream */ - /* ---------------------- */ + opj_image_t *image = decoder.getImage(); - /* JPEG-2000 codestream */ + // Component buffers are allocated in an image width by height buffer. + // The image placed in that buffer is ceil(width/2^factor) by + // ceil(height/2^factor) and if the factor isn't zero it will be at the + // top left of the buffer with black filled in the rest of the pixels. + // It is integer math so the formula is written in ceildivpo2. + // (Assuming all the components have the same width, height and + // factor.) + U32 comp_width = image->comps[0].w; // leave this unshifted by 'f' discard factor, the strides are always for the full buffer width + U32 f = image->comps[0].factor; -#ifdef OPENJPEG2 -// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3 - /* get a decoder handle */ - opj_codec_t* opj_decoder_p = opj_create_decompress(OPJ_CODEC_J2K); + // do size the texture to the mem we'll acrually use... + U32 width = image->comps[0].w; + U32 height = image->comps[0].h; - /* catch events using our callbacks and give a local context */ - opj_set_error_handler(opj_decoder_p, error_callback, 0); - opj_set_warning_handler(opj_decoder_p, warning_callback, 0); - opj_set_info_handler(opj_decoder_p, info_callback, 0); + raw_image.resize(U16(width), U16(height), S8(channels)); - /* setup the decoder decoding parameters using user parameters */ - opj_setup_decoder(opj_decoder_p, ¶meters); + U8 *rawp = raw_image.getData(); - /* allow multi-threading */ - if (opj_has_thread_support()) - { - opj_codec_set_threads(opj_decoder_p, opj_get_num_cpus()); - } + // Port fix for MAINT-4327/MAINT-6584 to OpenJPEG decoder + if (!rawp) + { + base.setLastError("Memory error"); + base.decodeFailed(); + return true; // done + } + // - /* open a byte stream */ - LLJp2StreamReader streamReader(&base); - opj_stream_t* opj_stream_p = opj_stream_default_create(OPJ_STREAM_READ); - opj_stream_set_read_function(opj_stream_p, LLJp2StreamReader::readStream); - opj_stream_set_skip_function(opj_stream_p, LLJp2StreamReader::skipStream); - opj_stream_set_seek_function(opj_stream_p, LLJp2StreamReader::seekStream); - opj_stream_set_user_data(opj_stream_p, &streamReader, nullptr); - opj_stream_set_user_data_length(opj_stream_p, base.getDataSize()); + // first_channel is what channel to start copying from + // dest is what channel to copy to. first_channel comes from the + // argument, dest always starts writing at channel zero. + for (S32 comp = first_channel, dest = 0; comp < first_channel + channels; comp++, dest++) + { + llassert(image->comps[comp].data); + if (image->comps[comp].data) + { + S32 offset = dest; + for (S32 y = (height - 1); y >= 0; y--) + { + for (S32 x = 0; x < width; x++) + { + rawp[offset] = image->comps[comp].data[y*comp_width + x]; + offset += channels; + } + } + } + else // Some rare OpenJPEG versions have this bug. + { + LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed! (OpenJPEG bug)" << LL_ENDL; + // [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3 + base.decodeFailed(); + // [SL:KB] + } + } - /* decode the stream and fill the image structure */ - bool fSuccess = opj_read_header(opj_stream_p, opj_decoder_p, &image) && - opj_decode(opj_decoder_p, opj_stream_p, image) && - opj_end_decompress(opj_decoder_p, opj_stream_p); + base.setDiscardLevel(f); - /* close the byte stream */ - opj_stream_destroy(opj_stream_p); - - /* free remaining structures */ - opj_destroy_codec(opj_decoder_p); -#else - /* get a decoder handle */ - dinfo = opj_create_decompress(CODEC_J2K); - - /* catch events using our callbacks and give a local context */ - opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); - - /* setup the decoder decoding parameters using user parameters */ - opj_setup_decoder(dinfo, ¶meters); - - /* open a byte stream */ - cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); - - /* decode the stream and fill the image structure */ - image = opj_decode(dinfo, cio); - - /* close the byte stream */ - opj_cio_close(cio); - - /* free remaining structures */ - if(dinfo) - { - opj_destroy_decompress(dinfo); - } -#endif -// [/SL:KB] - - // The image decode failed if the return was NULL or the component - // count was zero. The latter is just a sanity check before we - // dereference the array. -// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3 -#ifdef OPENJPEG2 - if ( (!fSuccess) || (!image) || (!image->numcomps) ) -#else - if(!image || !image->numcomps) -#endif -// [/SL:KB] - { - LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image!" << LL_ENDL; - if (image) - { - opj_image_destroy(image); - } - -// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3 - base.decodeFailed(); -// [SL:KB] - return true; // done - } - - // sometimes we get bad data out of the cache - check to see if the decode succeeded -// for (S32 i = 0; i < image->numcomps; i++) -// { -// if (image->comps[i].factor != base.getRawDiscardLevel()) -// { -// // if we didn't get the discard level we're expecting, fail -// -//// [SN:SG] - Patch: Import-MiscOpenJPEG -// LL_WARNS("Texture") << "Expected discard level not reached!" << LL_ENDL; -// base.decodeFailed(); -//// [SN:SG] -//// base.mDecoding = false; -// return true; -// } -// } - - if(image->numcomps <= first_channel) - { - LL_WARNS() << "trying to decode more channels than are present in image: numcomps: " << image->numcomps << " first_channel: " << first_channel << LL_ENDL; - if (image) - { - opj_image_destroy(image); - } - -// [SN:SG] - Patch: Import-MiscOpenJPEG - base.decodeFailed(); -// [SN:SG] - - return true; - } - - // Copy image data into our raw image format (instead of the separate channel format - - S32 img_components = image->numcomps; - S32 channels = img_components - first_channel; - if( channels > max_channel_count ) - channels = max_channel_count; - - // Component buffers are allocated in an image width by height buffer. - // The image placed in that buffer is ceil(width/2^factor) by - // ceil(height/2^factor) and if the factor isn't zero it will be at the - // top left of the buffer with black filled in the rest of the pixels. - // It is integer math so the formula is written in ceildivpo2. - // (Assuming all the components have the same width, height and - // factor.) - S32 comp_width = image->comps[0].w; - S32 f=image->comps[0].factor; - S32 width = ceildivpow2(image->x1 - image->x0, f); - S32 height = ceildivpow2(image->y1 - image->y0, f); - raw_image.resize(width, height, channels); - U8 *rawp = raw_image.getData(); - - // Port fix for MAINT-4327/MAINT-6584 to OpenJPEG decoder - if (!rawp) - { - base.setLastError("Memory error"); - base.decodeFailed(); - opj_image_destroy(image); - return true; // done - } - // - - // first_channel is what channel to start copying from - // dest is what channel to copy to. first_channel comes from the - // argument, dest always starts writing at channel zero. - for (S32 comp = first_channel, dest=0; comp < first_channel + channels; - comp++, dest++) - { - if (image->comps[comp].data) - { - S32 offset = dest; - for (S32 y = (height - 1); y >= 0; y--) - { - for (S32 x = 0; x < width; x++) - { - rawp[offset] = image->comps[comp].data[y*comp_width + x]; - offset += channels; - } - } - } - else // Some rare OpenJPEG versions have this bug. - { - LL_DEBUGS("Texture") << "ERROR -> decodeImpl: failed to decode image! (NULL comp data - OpenJPEG bug)" << LL_ENDL; - opj_image_destroy(image); - -// [SN:SG] - Patch: Import-MiscOpenJPEG - base.decodeFailed(); -// [SN:SG] - return true; // done - } - } - - /* free image data structure */ - opj_image_destroy(image); - - return true; // done + return true; // done } bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible) { - const S32 MAX_COMPS = 5; - opj_cparameters_t parameters; /* compression parameters */ - opj_event_mgr_t event_mgr; /* event manager */ - - - /* - configure the event callbacks (not required) - setting of each callback is optional - */ - memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); - event_mgr.error_handler = error_callback; - event_mgr.warning_handler = warning_callback; - event_mgr.info_handler = info_callback; - - /* set encoding parameters to default values */ - opj_set_default_encoder_parameters(¶meters); - parameters.cod_format = 0; - parameters.cp_disto_alloc = 1; - - if (reversible) - { - parameters.tcp_numlayers = 1; - parameters.tcp_rates[0] = 0.0f; - } - else - { - parameters.tcp_numlayers = 5; - parameters.tcp_rates[0] = 1920.0f; - parameters.tcp_rates[1] = 480.0f; - parameters.tcp_rates[2] = 120.0f; - parameters.tcp_rates[3] = 30.0f; - parameters.tcp_rates[4] = 10.0f; - parameters.irreversible = 1; - if (raw_image.getComponents() >= 3) - { - parameters.tcp_mct = 1; - } - } - - if (!comment_text) - { - parameters.cp_comment = (char *) ""; - } - else - { - // Awful hacky cast, too lazy to copy right now. - parameters.cp_comment = (char *) comment_text; - } - - // - // Fill in the source image from our raw image - // -// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3 -#ifdef OPENJPEG2 - OPJ_COLOR_SPACE color_space = OPJ_CLRSPC_SRGB; -#else - OPJ_COLOR_SPACE color_space = CLRSPC_SRGB; -#endif -// [/SL:KB] - opj_image_cmptparm_t cmptparm[MAX_COMPS]; - opj_image_t * image = NULL; - S32 numcomps = raw_image.getComponents(); - S32 width = raw_image.getWidth(); - S32 height = raw_image.getHeight(); - - memset(&cmptparm[0], 0, MAX_COMPS * sizeof(opj_image_cmptparm_t)); - for(S32 c = 0; c < numcomps; c++) { - cmptparm[c].prec = 8; - cmptparm[c].bpp = 8; - cmptparm[c].sgnd = 0; - cmptparm[c].dx = parameters.subsampling_dx; - cmptparm[c].dy = parameters.subsampling_dy; - cmptparm[c].w = width; - cmptparm[c].h = height; - } - - /* create the image */ - image = opj_image_create(numcomps, &cmptparm[0], color_space); - - image->x1 = width; - image->y1 = height; - - S32 i = 0; - const U8 *src_datap = raw_image.getData(); - for (S32 y = height - 1; y >= 0; y--) - { - for (S32 x = 0; x < width; x++) - { - const U8 *pixel = src_datap + (y*width + x) * numcomps; - for (S32 c = 0; c < numcomps; c++) - { - image->comps[c].data[i] = *pixel; - pixel++; - } - i++; - } - } - - - - /* encode the destination image */ - /* ---------------------------- */ - -// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3 -#ifdef OPENJPEG2 - /* get a J2K compressor handle */ - opj_codec_t* opj_encoder_p = opj_create_compress(OPJ_CODEC_J2K); - - /* catch events using our callbacks and give a local context */ - opj_set_error_handler(opj_encoder_p, error_callback, 0); - opj_set_warning_handler(opj_encoder_p, warning_callback, 0); - opj_set_info_handler(opj_encoder_p, info_callback, 0); - - /* setup the encoder parameters using the current image and using user parameters */ - bool fSuccess = opj_setup_encoder(opj_encoder_p, ¶meters, image); - if (!fSuccess) - { - opj_destroy_codec(opj_encoder_p); - opj_image_destroy(image); - LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL; - return false; - } - - /* open a byte stream for writing */ - /* allocate memory for all tiles */ - LLJp2StreamWriter streamWriter(&base); - opj_stream_t* opj_stream_p = opj_stream_default_create(OPJ_STREAM_WRITE); - opj_stream_set_write_function(opj_stream_p, LLJp2StreamWriter::writeStream); - opj_stream_set_skip_function(opj_stream_p, LLJp2StreamWriter::skipStream); - opj_stream_set_seek_function(opj_stream_p, LLJp2StreamWriter::seekStream); - opj_stream_set_user_data(opj_stream_p, &streamWriter, nullptr); - opj_stream_set_user_data_length(opj_stream_p, raw_image.getDataSize()); - - /* encode the image */ - fSuccess = opj_start_compress(opj_encoder_p, image, opj_stream_p) && - opj_encode(opj_encoder_p, opj_stream_p) && - opj_end_compress(opj_encoder_p, opj_stream_p); - if (!fSuccess) - { - opj_stream_destroy(opj_stream_p); - opj_destroy_codec(opj_encoder_p); - opj_image_destroy(image); - LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL; - return false; - } - - base.updateData(); // set width, height - - /* close and free the byte stream */ - opj_stream_destroy(opj_stream_p); - - /* free remaining compression structures */ - opj_destroy_codec(opj_encoder_p); -#else - int codestream_length; - opj_cio_t *cio = NULL; - - /* get a J2K compressor handle */ - opj_cinfo_t* cinfo = opj_create_compress(CODEC_J2K); - - /* catch events using our callbacks and give a local context */ - opj_set_event_mgr((opj_common_ptr)cinfo, &event_mgr, stderr); - - /* setup the encoder parameters using the current image and using user parameters */ - opj_setup_encoder(cinfo, ¶meters, image); - - /* open a byte stream for writing */ - /* allocate memory for all tiles */ - cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); - - /* encode the image */ - bool bSuccess = opj_encode(cinfo, cio, image, NULL); - if (!bSuccess) - { - opj_cio_close(cio); - LL_DEBUGS("Texture") << "Failed to encode image." << LL_ENDL; - return false; - } - codestream_length = cio_tell(cio); - - base.copyData(cio->buffer, codestream_length); - base.updateData(); // set width, height - - /* close and free the byte stream */ - opj_cio_close(cio); - - /* free remaining compression structures */ - opj_destroy_compress(cinfo); - - - /* free user parameters structure */ - if(parameters.cp_matrice) free(parameters.cp_matrice); -#endif - // [/SL:KB] - - /* free image data */ - opj_image_destroy(image); - return true; -} - -inline S32 extractLong4( U8 const *aBuffer, int nOffset ) -{ - S32 ret = aBuffer[ nOffset ] << 24; - ret += aBuffer[ nOffset + 1 ] << 16; - ret += aBuffer[ nOffset + 2 ] << 8; - ret += aBuffer[ nOffset + 3 ]; - return ret; -} - -inline S32 extractShort2( U8 const *aBuffer, int nOffset ) -{ - S32 ret = aBuffer[ nOffset ] << 8; - ret += aBuffer[ nOffset + 1 ]; - - return ret; -} - -inline bool isSOC( U8 const *aBuffer ) -{ - return aBuffer[ 0 ] == 0xFF && aBuffer[ 1 ] == 0x4F; -} - -inline bool isSIZ( U8 const *aBuffer ) -{ - return aBuffer[ 0 ] == 0xFF && aBuffer[ 1 ] == 0x51; -} - -bool getMetadataFast( LLImageJ2C &aImage, S32 &aW, S32 &aH, S32 &aComps ) -{ - const int J2K_HDR_LEN( 42 ); - const int J2K_HDR_X1( 8 ); - const int J2K_HDR_Y1( 12 ); - const int J2K_HDR_X0( 16 ); - const int J2K_HDR_Y0( 20 ); - const int J2K_HDR_NUMCOMPS( 40 ); - - if( aImage.getDataSize() < J2K_HDR_LEN ) - return false; - - U8 const* pBuffer = aImage.getData(); - - if( !isSOC( pBuffer ) || !isSIZ( pBuffer+2 ) ) - return false; - - S32 x1 = extractLong4( pBuffer, J2K_HDR_X1 ); - S32 y1 = extractLong4( pBuffer, J2K_HDR_Y1 ); - S32 x0 = extractLong4( pBuffer, J2K_HDR_X0 ); - S32 y0 = extractLong4( pBuffer, J2K_HDR_Y0 ); - S32 numComps = extractShort2( pBuffer, J2K_HDR_NUMCOMPS ); - - aComps = numComps; - aW = x1 - x0; - aH = y1 - y0; - - return true; + JPEG2KEncode encode(comment_text, reversible); + bool encoded = encode.encode(raw_image, base); + if (encoded) + { + LL_WARNS() << "Openjpeg encoding implementation isn't complete, returning false" << LL_ENDL; + } + return encoded; + //return false; } bool LLImageJ2COJ::getMetadata(LLImageJ2C &base) { - // - // FIXME: We get metadata by decoding the ENTIRE image. - // + JPEG2KDecode decode(0); - // Update the raw discard level - base.updateRawDiscardLevel(); + S32 width = 0; + S32 height = 0; + S32 components = 0; + S32 discard_level = 0; - S32 width(0); - S32 height(0); - S32 img_components(0); + U32 dataSize = base.getDataSize(); + U8* data = base.getData(); + bool header_read = decode.readHeader(data, dataSize, width, height, components, discard_level); + if (!header_read) + { + return false; + } - if ( getMetadataFast( base, width, height, img_components ) ) - { - base.setSize(width, height, img_components); - return true; - } - - // Do it the old and slow way, decode the image with openjpeg - - opj_dparameters_t parameters; /* decompression parameters */ - opj_event_mgr_t event_mgr; /* event manager */ - opj_image_t *image = NULL; - -#ifndef OPENJPEG2 - opj_dinfo_t* dinfo = NULL; /* handle to a decompressor */ - opj_cio_t *cio = NULL; -#endif - - /* configure the event callbacks (not required) */ - memset(&event_mgr, 0, sizeof(opj_event_mgr_t)); - event_mgr.error_handler = error_callback; - event_mgr.warning_handler = warning_callback; - event_mgr.info_handler = info_callback; - - /* set decoding parameters to default values */ - opj_set_default_decoder_parameters(¶meters); - - // Only decode what's required to get the size data. -#ifndef OPENJPEG2 - parameters.cp_limit_decoding=LIMIT_TO_MAIN_HEADER; -#endif - - //parameters.cp_reduce = mRawDiscardLevel; - - /* decode the code-stream */ - /* ---------------------- */ - - /* JPEG-2000 codestream */ - -// [SL:KB] - Patch: Viewer-OpenJPEG2 | Checked: Catznip-5.3 -#ifdef OPENJPEG2 - /* get a decoder handle */ - opj_codec_t* opj_decoder_p = opj_create_decompress(OPJ_CODEC_J2K); - - /* catch events using our callbacks and give a local context */ - opj_set_error_handler(opj_decoder_p, error_callback, 0); - opj_set_warning_handler(opj_decoder_p, warning_callback, 0); - opj_set_info_handler(opj_decoder_p, info_callback, 0); - - /* setup the decoder decoding parameters using user parameters */ - bool fSuccess = opj_setup_decoder(opj_decoder_p, ¶meters); - if (!fSuccess) - { - opj_destroy_codec(opj_decoder_p); - LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL; - return false; - } - - /* open a byte stream */ - LLJp2StreamReader streamReader(&base); - opj_stream_t* opj_stream_p = opj_stream_default_create(OPJ_STREAM_READ); - opj_stream_set_read_function(opj_stream_p, LLJp2StreamReader::readStream); - opj_stream_set_skip_function(opj_stream_p, LLJp2StreamReader::skipStream); - opj_stream_set_seek_function(opj_stream_p, LLJp2StreamReader::seekStream); - opj_stream_set_user_data(opj_stream_p, &streamReader, nullptr); - opj_stream_set_user_data_length(opj_stream_p, base.getDataSize()); - - /* decode the stream and fill the image structure */ - fSuccess = opj_read_header(opj_stream_p, opj_decoder_p, &image); - if (!fSuccess) - { - opj_stream_destroy(opj_stream_p); - opj_destroy_codec(opj_decoder_p); - LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL; - return false; - } - - /* close the byte stream */ - opj_stream_destroy(opj_stream_p); - - /* free remaining structures */ - opj_destroy_codec(opj_decoder_p); -#else - /* get a decoder handle */ - dinfo = opj_create_decompress(CODEC_J2K); - - /* catch events using our callbacks and give a local context */ - opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr); - - /* setup the decoder decoding parameters using user parameters */ - opj_setup_decoder(dinfo, ¶meters); - - /* open a byte stream */ - cio = opj_cio_open((opj_common_ptr)dinfo, base.getData(), base.getDataSize()); - - /* decode the stream and fill the image structure */ - image = opj_decode(dinfo, cio); - - /* close the byte stream */ - opj_cio_close(cio); - - /* free remaining structures */ - if(dinfo) - { - opj_destroy_decompress(dinfo); - } -#endif -// [/SL:KB] - - if(!image) - { - LL_WARNS() << "ERROR -> getMetadata: failed to decode image!" << LL_ENDL; - return false; - } - - // Copy image data into our raw image format (instead of the separate channel format - - img_components = image->numcomps; - width = image->x1 - image->x0; - height = image->y1 - image->y0; - - base.setSize(width, height, img_components); - - /* free image data structure */ - opj_image_destroy(image); - return true; + base.mDiscardLevel = discard_level; + base.setSize(width, height, components); + return true; } diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 975f837857..07939a027e 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2406,13 +2406,12 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD with code " << uzip_result << " , will probably fetch from sim again." << LL_ENDL; return false; } -// Add non-allocating variants of of unpackVolumeFaces return unpackVolumeFacesInternal(mdl); } bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size) { - //input stream is now pointing at a zlib compressed block of LLSD + //input data is now pointing at a zlib compressed block of LLSD //decompress block LLSD mdl; U32 uzip_result = LLUZipHelper::unzip_llsd(mdl, in_data, size); @@ -2426,7 +2425,6 @@ bool LLVolume::unpackVolumeFaces(U8* in_data, S32 size) bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl) { -// { U32 face_count = mdl.size(); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 079ca8ac72..e832c86cf2 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -1113,14 +1113,12 @@ protected: BOOL generate(); void createVolumeFaces(); public: - virtual bool unpackVolumeFaces(std::istream& is, S32 size); -// Add non-allocating variants of of unpackVolumeFaces + bool unpackVolumeFaces(std::istream& is, S32 size); bool unpackVolumeFaces(U8* in_data, S32 size); private: bool unpackVolumeFacesInternal(const LLSD& mdl); public: -// virtual void setMeshAssetLoaded(BOOL loaded); virtual BOOL isMeshAssetLoaded(); diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp index 64cd1c2ad0..9f7768f78e 100644 --- a/indra/llmessage/lldatapacker.cpp +++ b/indra/llmessage/lldatapacker.cpp @@ -754,14 +754,13 @@ BOOL LLDataPackerAsciiBuffer::packString(const std::string& value, const char *n BOOL LLDataPackerAsciiBuffer::unpackString(std::string& value, const char *name) { - BOOL success = TRUE; char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore*/ if (!getValueStr(name, valuestr, DP_BUFSIZE)) // NULL terminated { return FALSE; } value = valuestr; - return success; + return TRUE; } diff --git a/indra/llmessage/tests/llcoproceduremanager_test.cpp b/indra/llmessage/tests/llcoproceduremanager_test.cpp index 6424117ef3..a1a4ce0520 100644 --- a/indra/llmessage/tests/llcoproceduremanager_test.cpp +++ b/indra/llmessage/tests/llcoproceduremanager_test.cpp @@ -92,7 +92,7 @@ namespace tut Sync sync; int foo = 0; LLCoprocedureManager::instance().initializePool("PoolName"); - LLUUID queueId = LLCoprocedureManager::instance().enqueueCoprocedure("PoolName", "ProcName", + LLCoprocedureManager::instance().enqueueCoprocedure("PoolName", "ProcName", [&foo, &sync] (LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t & ptr, const LLUUID & id) { sync.bump(); foo = 1; diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index ae09251aa3..67c9ea64c4 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -1429,6 +1429,16 @@ LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin): fromLLSD(skin); } +LLMeshSkinInfo::LLMeshSkinInfo(const LLUUID& mesh_id, LLSD& skin) : + mMeshID(mesh_id), + mPelvisOffset(0.0), + mLockScaleIfJointPosition(false), + mInvalidJointsScrubbed(false), + mJointNumsInitialized(false) +{ + fromLLSD(skin); +} + void LLMeshSkinInfo::fromLLSD(LLSD& skin) { if (skin.has("joint_names")) diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 7461a38ac9..689172dda3 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -43,12 +43,13 @@ class domMesh; #define MAX_MODEL_FACES 8 LL_ALIGN_PREFIX(16) -class LLMeshSkinInfo +class LLMeshSkinInfo : public LLRefCount { LL_ALIGN_NEW public: LLMeshSkinInfo(); LLMeshSkinInfo(LLSD& data); + LLMeshSkinInfo(const LLUUID& mesh_id, LLSD& data); void fromLLSD(LLSD& data); LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const; void updateHash(); diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp index 15a9c8bb0a..5a68c00c33 100644 --- a/indra/llui/llflatlistview.cpp +++ b/indra/llui/llflatlistview.cpp @@ -515,6 +515,17 @@ LLFlatListView::LLFlatListView(const LLFlatListView::Params& p) } }; +LLFlatListView::~LLFlatListView() +{ + for (pairs_iterator_t it = mItemPairs.begin(); it != mItemPairs.end(); ++it) + { + mItemsPanel->removeChild((*it)->first); + (*it)->first->die(); + delete *it; + } + mItemPairs.clear(); +} + // virtual void LLFlatListView::draw() { diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h index c2ba8f2f02..7fe5d90876 100644 --- a/indra/llui/llflatlistview.h +++ b/indra/llui/llflatlistview.h @@ -307,6 +307,7 @@ public: virtual S32 notify(const LLSD& info) ; + virtual ~LLFlatListView(); protected: /** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */ diff --git a/indra/llui/llfolderview.cpp b/indra/llui/llfolderview.cpp index 89735c86b1..32538ab3fa 100644 --- a/indra/llui/llfolderview.cpp +++ b/indra/llui/llfolderview.cpp @@ -163,6 +163,7 @@ LLFolderView::LLFolderView(const Params& p) : LLFolderViewFolder(p), mScrollContainer( NULL ), mPopupMenuHandle(), + mMenuFileName(p.options_menu), mAllowMultiSelect(p.allow_multiselect), mAllowDrag(p.allow_drag), mShowEmptyMessage(p.show_empty_message), @@ -186,6 +187,7 @@ LLFolderView::LLFolderView(const Params& p) mDragStartY(0), // [/SL:KB] mCallbackRegistrar(NULL), + mEnableRegistrar(NULL), mUseEllipses(p.use_ellipses), mDraggingOverItem(NULL), mStatusTextBox(NULL), @@ -248,17 +250,6 @@ LLFolderView::LLFolderView(const Params& p) mStatusTextBox->setFollowsTop(); addChild(mStatusTextBox); - - // make the popup menu available - llassert(LLMenuGL::sMenuContainer != NULL); - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile(p.options_menu, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (!menu) - { - menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); - } - menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); - mPopupMenuHandle = menu->getHandle(); - mViewModelItem->openItem(); mAreChildrenInited = true; // root folder is a special case due to not being loaded normally, assume that it's inited. @@ -280,6 +271,7 @@ LLFolderView::~LLFolderView( void ) mStatusTextBox = NULL; if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); + mPopupMenuHandle.markDead(); mAutoOpenItems.removeAllNodes(); clearSelection(); @@ -1534,22 +1526,56 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) BOOL handled = childrenHandleRightMouseDown(x, y, mask) != NULL; S32 count = mSelectedItems.size(); - LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get(); + LLMenuGL* menu = static_cast(mPopupMenuHandle.get()); + if (!menu) + { + if (mCallbackRegistrar) + { + mCallbackRegistrar->pushScope(); + } + if (mEnableRegistrar) + { + mEnableRegistrar->pushScope(); + } + llassert(LLMenuGL::sMenuContainer != NULL); + menu = LLUICtrlFactory::getInstance()->createFromFile(mMenuFileName, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (!menu) + { + menu = LLUICtrlFactory::getDefaultWidget("inventory_menu"); + } + menu->setBackgroundColor(LLUIColorTable::instance().getColor("MenuPopupBgColor")); + mPopupMenuHandle = menu->getHandle(); + if (mEnableRegistrar) + { + mEnableRegistrar->popScope(); + } + if (mCallbackRegistrar) + { + mCallbackRegistrar->popScope(); + } + } bool hide_folder_menu = mSuppressFolderMenu && isFolderSelected(); - if ((handled - && ( count > 0 && (hasVisibleChildren()) ) // show menu only if selected items are visible - && menu ) && + if (menu && (handled + && ( count > 0 && (hasVisibleChildren()) )) && // show menu only if selected items are visible !hide_folder_menu) { if (mCallbackRegistrar) { mCallbackRegistrar->pushScope(); } + if (mEnableRegistrar) + { + mEnableRegistrar->pushScope(); + } updateMenuOptions(menu); menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, menu, x, y); + if (mEnableRegistrar) + { + mEnableRegistrar->popScope(); + } if (mCallbackRegistrar) { mCallbackRegistrar->popScope(); @@ -1627,7 +1653,7 @@ void LLFolderView::deleteAllChildren() { closeRenamer(); if (mPopupMenuHandle.get()) mPopupMenuHandle.get()->die(); - mPopupMenuHandle = LLHandle(); + mPopupMenuHandle.markDead(); mScrollContainer = NULL; mRenameItem = NULL; mRenamer = NULL; diff --git a/indra/llui/llfolderview.h b/indra/llui/llfolderview.h index 491028556c..e6d6d76ad9 100644 --- a/indra/llui/llfolderview.h +++ b/indra/llui/llfolderview.h @@ -240,6 +240,7 @@ public: bool showItemLinkOverlays() { return mShowItemLinkOverlays; } void setCallbackRegistrar(LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* registrar) { mCallbackRegistrar = registrar; } + void setEnableRegistrar(LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* registrar) { mEnableRegistrar = registrar; } LLPanel* getParentPanel() { return mParentPanel.get(); } // DEBUG only @@ -277,6 +278,7 @@ protected: protected: LLHandle mPopupMenuHandle; + std::string mMenuFileName; selected_items_t mSelectedItems; bool mKeyboardSelection, @@ -336,6 +338,7 @@ protected: LLFolderViewItem* mDraggingOverItem; // See EXT-719 LLUICtrl::CommitCallbackRegistry::ScopedRegistrar* mCallbackRegistrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar* mEnableRegistrar; public: static F32 sAutoOpenTime; diff --git a/indra/llui/llfolderviewmodel.h b/indra/llui/llfolderviewmodel.h index 4b8a31a07e..31d28a5257 100644 --- a/indra/llui/llfolderviewmodel.h +++ b/indra/llui/llfolderviewmodel.h @@ -432,21 +432,15 @@ public: mFilter(filter) {} - virtual ~LLFolderViewModel() - { - delete mSorter; - mSorter = NULL; - delete mFilter; - mFilter = NULL; - } + virtual ~LLFolderViewModel() {} virtual SortType& getSorter() { return *mSorter; } virtual const SortType& getSorter() const { return *mSorter; } - virtual void setSorter(const SortType& sorter) { mSorter = new SortType(sorter); requestSortAll(); } + virtual void setSorter(const SortType& sorter) { mSorter.reset(new SortType(sorter)); requestSortAll(); } virtual FilterType& getFilter() { return *mFilter; } virtual const FilterType& getFilter() const { return *mFilter; } - virtual void setFilter(const FilterType& filter) { mFilter = new FilterType(filter); } + virtual void setFilter(const FilterType& filter) { mFilter.reset(new FilterType(filter)); } // By default, we assume the content is available. If a network fetch mechanism is implemented for the model, // this method needs to be overloaded and return the relevant fetch status. @@ -484,8 +478,8 @@ public: } protected: - SortType* mSorter; - FilterType* mFilter; + std::unique_ptr mSorter; + std::unique_ptr mFilter; }; #endif // LLFOLDERVIEWMODEL_H diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 63482df996..86a26df6ad 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -164,8 +164,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) mHighlightColor(p.highlight_color()), mPreeditBgColor(p.preedit_bg_color()), mGLFont(p.font), - // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL - mDelayedInit(false), mContextMenuHandle(), mAutoreplaceCallback() { @@ -212,24 +210,6 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p) setPrevalidateInput(p.prevalidate_input_callback()); setPrevalidate(p.prevalidate_callback()); - - // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL - if (LLMenuGL::sMenuContainer) - { - // - llassert(LLMenuGL::sMenuContainer != NULL); - LLContextMenu* menu = LLUICtrlFactory::instance().createFromFile - ("menu_text_editor.xml", - LLMenuGL::sMenuContainer, - LLMenuHolderGL::child_registry_t::instance()); - setContextMenu(menu); - // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL - } - else - { - mDelayedInit = true; - } - // } LLLineEditor::~LLLineEditor() @@ -244,9 +224,6 @@ LLLineEditor::~LLLineEditor() } setContextMenu(NULL); - // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL - mDelayedInit = false; - // calls onCommit() while LLLineEditor still valid gFocusMgr.releaseFocusIfNeeded( this ); } @@ -1660,10 +1637,7 @@ BOOL LLLineEditor::handleKeyHere(KEY key, MASK mask ) KEY_SHIFT != key && KEY_CONTROL != key && KEY_ALT != key && - // Capslock deselecting text - //KEY_CAPSLOCK ) KEY_CAPSLOCK != key) - // { deselect(); } @@ -2759,24 +2733,16 @@ LLWString LLLineEditor::getConvertedText() const void LLLineEditor::showContextMenu(S32 x, S32 y, bool set_cursor_pos) // { - //LLContextMenu* menu = static_cast(mContextMenuHandle.get()); - // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL - LLContextMenu* menu = NULL; - if (mDelayedInit && !mContextMenuHandle.get()) + LLContextMenu* menu = static_cast(mContextMenuHandle.get()); + if (!menu) { llassert(LLMenuGL::sMenuContainer != NULL); - menu = LLUICtrlFactory::instance().createFromFile + menu = LLUICtrlFactory::createFromFile ("menu_text_editor.xml", - LLMenuGL::sMenuContainer, - LLMenuHolderGL::child_registry_t::instance()); + LLMenuGL::sMenuContainer, + LLMenuHolderGL::child_registry_t::instance()); setContextMenu(menu); } - else - { - menu = static_cast(mContextMenuHandle.get()); - } - mDelayedInit = false; - // if (menu) { @@ -2827,8 +2793,6 @@ void LLLineEditor::setContextMenu(LLContextMenu* new_context_menu) { menu->die(); mContextMenuHandle.markDead(); - // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL - mDelayedInit = false; } if (new_context_menu) diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 2387cc1478..a7b4029d32 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -422,9 +422,6 @@ protected: LLHandle mContextMenuHandle; - // Delay context menu initialization if LLMenuGL::sMenuContainer is still NULL - bool mDelayedInit; - private: // Instances that by default point to the statics but can be overidden in XML. LLPointer mBgImage; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index d0d1db88dd..18b789da24 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -4125,12 +4125,7 @@ void LLTearOffMenu::closeTearOff() LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p) : LLMenuItemGL(p) - //mBranch( p.branch()->getHandle() ) // Context menu memory leak fix by Rye Mutt { - // Context menu memory leak fix by Rye Mutt - //mBranch.get()->hide(); - //mBranch.get()->setParentMenuItem(this); - // LLContextMenu* branch = static_cast(p.branch); if (branch) { @@ -4140,7 +4135,6 @@ LLContextMenuBranch::LLContextMenuBranch(const LLContextMenuBranch::Params& p) } } -// Context menu memory leak fix by Rye Mutt LLContextMenuBranch::~LLContextMenuBranch() { if (mBranch.get()) @@ -4148,30 +4142,21 @@ LLContextMenuBranch::~LLContextMenuBranch() mBranch.get()->die(); } } -// // called to rebuild the draw label void LLContextMenuBranch::buildDrawLabel( void ) { - // Context menu memory leak fix by Rye Mutt auto menu = getBranch(); if (menu) - // { // default enablement is this -- if any of the subitems are // enabled, this item is enabled. JC - // Context menu memory leak fix by Rye Mutt - //U32 sub_count = mBranch.get()->getItemCount(); U32 sub_count = menu->getItemCount(); - // U32 i; BOOL any_enabled = FALSE; for (i = 0; i < sub_count; i++) { - // Context menu memory leak fix by Rye Mutt - //LLMenuItemGL* item = mBranch.get()->getItem(i); LLMenuItemGL* item = menu->getItem(i); - // item->buildDrawLabel(); if (item->getEnabled() && !item->getDrawTextDisabled() ) { @@ -4193,28 +4178,18 @@ void LLContextMenuBranch::buildDrawLabel( void ) void LLContextMenuBranch::showSubMenu() { - // Context menu memory leak fix by Rye Mutt - //LLMenuItemGL* menu_item = mBranch.get()->getParentMenuItem(); - //if (menu_item != NULL && menu_item->getVisible()) - //{ - // S32 center_x; - // S32 center_y; - // localPointToScreen(getRect().getWidth(), getRect().getHeight() , ¢er_x, ¢er_y); - // mBranch.get()->show(center_x, center_y); - //} auto menu = getBranch(); - if (menu) + if(menu) { LLMenuItemGL* menu_item = menu->getParentMenuItem(); if (menu_item != NULL && menu_item->getVisible()) { S32 center_x; S32 center_y; - localPointToScreen(getRect().getWidth(), getRect().getHeight() , ¢er_x, ¢er_y); + localPointToScreen(getRect().getWidth(), getRect().getHeight(), ¢er_x, ¢er_y); menu->show(center_x, center_y); } } - // } // onCommit() - do the primary funcationality of the menu item. @@ -4227,15 +4202,6 @@ void LLContextMenuBranch::setHighlight( BOOL highlight ) { if (highlight == getHighlight()) return; LLMenuItemGL::setHighlight(highlight); - // Context menu memory leak fix by Rye Mutt - //if( highlight ) - //{ - // showSubMenu(); - //} - //else - //{ - // mBranch.get()->hide(); - //} auto menu = getBranch(); if (menu) { @@ -4248,7 +4214,6 @@ void LLContextMenuBranch::setHighlight( BOOL highlight ) menu->hide(); } } - // } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 73600f01f3..760d3eff6c 100644 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -754,11 +754,7 @@ public: LLContextMenuBranch(const Params&); - // Context menu memory leak fix by Rye Mutt - //virtual ~LLContextMenuBranch() - //{} virtual ~LLContextMenuBranch(); - // // called to rebuild the draw label virtual void buildDrawLabel( void ); diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index f89064d59a..604d246f12 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -92,7 +92,7 @@ LLMultiSlider::LLMultiSlider(const LLMultiSlider::Params& p) mMouseDownSignal(NULL), mMouseUpSignal(NULL) { - mValue.emptyMap(); + mValue = LLSD::emptyMap(); mCurSlider = LLStringUtil::null; if (mOrientation == HORIZONTAL) diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index bc1aa24d25..35d5c44f9b 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -201,7 +201,6 @@ LLScrollListCtrl::LLScrollListCtrl(const LLScrollListCtrl::Params& p) mHighlightedItem(-1), mBorder(NULL), mSortCallback(NULL), - mPopupMenu(NULL), mCommentTextView(NULL), mNumDynamicWidthColumns(0), mTotalStaticColumnWidth(0), @@ -412,6 +411,13 @@ LLScrollListCtrl::~LLScrollListCtrl() mItemList.clear(); clearColumns(); //clears columns and deletes headers delete mIsFriendSignal; + + auto menu = mPopupMenuHandle.get(); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } } @@ -1423,20 +1429,20 @@ LLScrollListItem* LLScrollListCtrl::getItemByLabel(const std::string& label, BOO } -BOOL LLScrollListCtrl::selectItemByPrefix(const std::string& target, BOOL case_sensitive) +BOOL LLScrollListCtrl::selectItemByPrefix(const std::string& target, BOOL case_sensitive, S32 column) { - return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive); + return selectItemByPrefix(utf8str_to_wstring(target), case_sensitive, column); } // Selects first enabled item that has a name where the name's first part matched the target string. // Returns false if item not found. -BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive) +BOOL LLScrollListCtrl::selectItemByPrefix(const LLWString& target, BOOL case_sensitive, S32 column) // Allow selection by substring match { return selectItemByStringMatch(target, true, case_sensitive); } -BOOL LLScrollListCtrl::selectItemByStringMatch(const LLWString& target, bool prefix_match, BOOL case_sensitive) +BOOL LLScrollListCtrl::selectItemByStringMatch(const LLWString& target, bool prefix_match, BOOL case_sensitive, S32 column) // { BOOL found = FALSE; @@ -1452,7 +1458,7 @@ BOOL LLScrollListCtrl::selectItemByStringMatch(const LLWString& target, bool pre { LLScrollListItem* item = *iter; // Only select enabled items with matching names - LLScrollListCell* cellp = item->getColumn(getSearchColumn()); + LLScrollListCell* cellp = item->getColumn(column == -1 ? getSearchColumn() : column); BOOL select = cellp ? item->getEnabled() && ('\0' == cellp->getValue().asString()[0]) : FALSE; if (select) { @@ -1475,7 +1481,7 @@ BOOL LLScrollListCtrl::selectItemByStringMatch(const LLWString& target, bool pre LLScrollListItem* item = *iter; // Only select enabled items with matching names - LLScrollListCell* cellp = item->getColumn(getSearchColumn()); + LLScrollListCell* cellp = item->getColumn(column == -1 ? getSearchColumn() : column); if (!cellp) { continue; @@ -2252,17 +2258,23 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) // create the context menu from the XUI file and display it std::string menu_name = is_group ? "menu_url_group.xml" : "menu_url_agent.xml"; - delete mPopupMenu; - llassert(LLMenuGL::sMenuContainer != NULL); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile( - menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - if (mPopupMenu) + auto menu = mPopupMenuHandle.get(); + if (menu) { + menu->die(); + mPopupMenuHandle.markDead(); + } + llassert(LLMenuGL::sMenuContainer != NULL); + menu = LLUICtrlFactory::getInstance()->createFromFile( + menu_name, LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandle = menu->getHandle(); if (mIsFriendSignal) { bool isFriend = *(*mIsFriendSignal)(uuid); - LLView* addFriendButton = mPopupMenu->getChild("add_friend"); - LLView* removeFriendButton = mPopupMenu->getChild("remove_friend"); + LLView* addFriendButton = menu->getChild("add_friend"); + LLView* removeFriendButton = menu->getChild("remove_friend"); if (addFriendButton && removeFriendButton) { @@ -2271,8 +2283,8 @@ BOOL LLScrollListCtrl::handleRightMouseDown(S32 x, S32 y, MASK mask) } } - mPopupMenu->show(x, y); - LLMenuGL::showPopup(this, mPopupMenu, x, y); + menu->show(x, y); + LLMenuGL::showPopup(this, menu, x, y); return TRUE; } } diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 55d30ad422..30d7e54f82 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -270,12 +270,12 @@ public: virtual LLScrollListItem* addSimpleElement(const std::string& value, EAddPosition pos = ADD_BOTTOM, const LLSD& id = LLSD()); BOOL selectItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); // FALSE if item not found - BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE); - BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE); + BOOL selectItemByPrefix(const std::string& target, BOOL case_sensitive = TRUE, S32 column = -1); + BOOL selectItemByPrefix(const LLWString& target, BOOL case_sensitive = TRUE, S32 column = -1); // Allow selection by substring match BOOL selectItemBySubstring(const std::string& target, BOOL case_sensitive = TRUE); BOOL selectItemBySubstring(const LLWString& target, BOOL case_sensitive = TRUE); - BOOL selectItemByStringMatch(const LLWString& target, bool prefix_match, BOOL case_sensitive = TRUE); + BOOL selectItemByStringMatch(const LLWString& target, bool prefix_match, BOOL case_sensitive = TRUE, S32 column = -1); // LLScrollListItem* getItemByLabel( const std::string& item, BOOL case_sensitive = TRUE, S32 column = 0 ); const std::string getSelectedItemLabel(S32 column = 0) const; @@ -565,7 +565,7 @@ private: S32 mHighlightedItem; class LLViewBorder* mBorder; - LLContextMenu *mPopupMenu; + LLHandle mPopupMenuHandle; LLView *mCommentTextView; diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 0a04ae36ac..ea965c83ee 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -1583,12 +1583,10 @@ void LLTabContainer::selectLastTab() void LLTabContainer::selectNextTab() { - // FIRE-15580: Crash fix (division by 0) - if (mTabList.size() == 0) - { - return; - } - // + if (mTabList.size() == 0) + { + return; + } BOOL tab_has_focus = FALSE; if (mCurrentTabIdx >= 0 && mTabList[mCurrentTabIdx]->mButton->hasFocus()) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 498dbc4a3a..aa8822a00e 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -303,6 +303,12 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) LLTextBase::~LLTextBase() { mSegments.clear(); + LLContextMenu* menu = static_cast(mPopupMenuHandle.get()); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } delete mURLClickSignal; delete mIsFriendSignal; delete mIsObjectBlockedSignal; diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 942af90fd8..c208c0006b 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -258,7 +258,6 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) : mMouseDownY(0), mTabsToNextField(p.ignore_tab), mPrevalidateFunc(p.prevalidate_callback()), - mContextMenu(NULL), mShowContextMenu(p.show_context_menu), mEnableTooltipPaste(p.enable_tooltip_paste), mPassDelete(FALSE), @@ -303,8 +302,13 @@ LLTextEditor::~LLTextEditor() // Scrollbar is deleted by LLView std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer()); mUndoStack.clear(); - // context menu is owned by menu holder, not us - //delete mContextMenu; + // Mark the menu as dead or its retained in memory till shutdown. + LLContextMenu* menu = static_cast(mContextMenuHandle.get()); + if(menu) + { + menu->die(); + mContextMenuHandle.markDead(); + } } //////////////////////////////////////////////////////////// @@ -2236,19 +2240,19 @@ void LLTextEditor::setEnabled(BOOL enabled) void LLTextEditor::showContextMenu(S32 x, S32 y, bool set_cursor_pos) // { - if (!mContextMenu) + LLContextMenu* menu = static_cast(mContextMenuHandle.get()); + if (!menu) { llassert(LLMenuGL::sMenuContainer != NULL); - mContextMenu = LLUICtrlFactory::instance().createFromFile("menu_text_editor.xml", + menu = LLUICtrlFactory::createFromFile("menu_text_editor.xml", LLMenuGL::sMenuContainer, LLMenuHolderGL::child_registry_t::instance()); - // FIRE-31081 defend against null this prt exception in setItemVisible found in BugSplat - if(!mContextMenu) - { - LL_WARNS() << "Failed to create context menu 'menu_text_editor'" << LL_ENDL; - return; - } - // + if(!menu) + { + LL_WARNS() << "Failed to create menu for LLTextEditor: " << getName() << LL_ENDL; + return; + } + mContextMenuHandle = menu->getHandle(); } // Route menu to this class @@ -2295,11 +2299,11 @@ void LLTextEditor::showContextMenu(S32 x, S32 y, bool set_cursor_pos) } } - mContextMenu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty())); - mContextMenu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled)); - mContextMenu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled)); - mContextMenu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled)); - mContextMenu->show(screen_x, screen_y, this); + menu->setItemVisible("Suggestion Separator", (use_spellcheck) && (!mSuggestionList.empty())); + menu->setItemVisible("Add to Dictionary", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Add to Ignore", (use_spellcheck) && (is_misspelled)); + menu->setItemVisible("Spellcheck Separator", (use_spellcheck) && (is_misspelled)); + menu->show(screen_x, screen_y, this); } diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h index 714247c1c6..4fc837c439 100644 --- a/indra/llui/lltexteditor.h +++ b/indra/llui/lltexteditor.h @@ -345,7 +345,7 @@ private: keystroke_signal_t mKeystrokeSignal; LLTextValidate::validate_func_t mPrevalidateFunc; - LLContextMenu* mContextMenu; + LLHandle mContextMenuHandle; }; // end class LLTextEditor // Build time optimization, generate once in .cpp file diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index dcce2aa1fd..bf8c3f51e5 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -162,7 +162,12 @@ LLToolBar::LLToolBar(const LLToolBar::Params& p) LLToolBar::~LLToolBar() { - delete mPopupMenuHandle.get(); + auto menu = mPopupMenuHandle.get(); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } delete mButtonAddSignal; delete mButtonEnterSignal; delete mButtonLeaveSignal; diff --git a/indra/llwindow/lldxhardware.cpp b/indra/llwindow/lldxhardware.cpp index e13cfc4aa9..c0614811e7 100644 --- a/indra/llwindow/lldxhardware.cpp +++ b/indra/llwindow/lldxhardware.cpp @@ -1108,7 +1108,7 @@ LLSD LLDXHardware::getDisplayInfo() } LCleanup: - if (ret.emptyMap()) + if (!ret.isMap() || (ret.size() == 0)) { LL_INFOS() << "Failed to get data, cleaning up" << LL_ENDL; } diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h index a9ebffc09a..0c6da56cd3 100644 --- a/indra/llwindow/llwindowmacosx-objc.h +++ b/indra/llwindow/llwindowmacosx-objc.h @@ -83,7 +83,7 @@ int createNSApp(int argc, const char **argv); void setupCocoa(); bool pasteBoardAvailable(); bool copyToPBoard(const unsigned short *str, unsigned int len); -const unsigned short *copyFromPBoard(); +unsigned short *copyFromPBoard(); CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY); short releaseImageCursor(CursorRef ref); short setImageCursor(CursorRef ref); diff --git a/indra/llwindow/llwindowmacosx-objc.mm b/indra/llwindow/llwindowmacosx-objc.mm index 2a88049c5c..37baad1324 100644 --- a/indra/llwindow/llwindowmacosx-objc.mm +++ b/indra/llwindow/llwindowmacosx-objc.mm @@ -49,14 +49,12 @@ void setupCocoa() if(!inited) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents. - // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr' - // when init'ing the Cocoa App window. - [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; - - [pool release]; + @autoreleasepool { + // The following prevents the Cocoa command line parser from trying to open 'unknown' arguements as documents. + // ie. running './secondlife -set Language fr' would cause a pop-up saying can't open document 'fr' + // when init'ing the Cocoa App window. + [[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"]; + } inited = true; } @@ -64,13 +62,13 @@ void setupCocoa() bool copyToPBoard(const unsigned short *str, unsigned int len) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; - NSPasteboard *pboard = [NSPasteboard generalPasteboard]; - [pboard clearContents]; - - NSArray *contentsToPaste = [[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil]; - [pool release]; - return [pboard writeObjects:contentsToPaste]; + @autoreleasepool { + NSPasteboard *pboard = [NSPasteboard generalPasteboard]; + [pboard clearContents]; + + NSArray *contentsToPaste = [[[NSArray alloc] initWithObjects:[NSString stringWithCharacters:str length:len], nil] autorelease]; + return [pboard writeObjects:contentsToPaste]; + } } bool pasteBoardAvailable() @@ -79,45 +77,39 @@ bool pasteBoardAvailable() return [[NSPasteboard generalPasteboard] canReadObjectForClasses:classArray options:[NSDictionary dictionary]]; } -const unsigned short *copyFromPBoard() +unsigned short *copyFromPBoard() { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init]; - NSPasteboard *pboard = [NSPasteboard generalPasteboard]; - NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; - NSString *str = NULL; - BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]]; - if (ok) - { - NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]]; - str = [objToPaste objectAtIndex:0]; - } - NSUInteger len = [str length]; - - // add+1 for 0-terminator. - // unichar* temp = (unichar*)calloc([str length]+1, sizeof(unichar)); - unichar* buffer = (unichar*)calloc(len+1, sizeof(unichar)); - // - - [str getCharacters:buffer range:NSMakeRange(0, len)]; - [pool release]; - return buffer; + @autoreleasepool { + NSPasteboard *pboard = [NSPasteboard generalPasteboard]; + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + NSString *str = NULL; + BOOL ok = [pboard canReadObjectForClasses:classArray options:[NSDictionary dictionary]]; + if (ok) + { + NSArray *objToPaste = [pboard readObjectsForClasses:classArray options:[NSDictionary dictionary]]; + str = [objToPaste objectAtIndex:0]; + } + NSUInteger str_len = [str length]; + unichar* temp = (unichar*)calloc(str_len+1, sizeof(unichar)); + [str getCharacters:temp range:NSMakeRange(0, str_len)]; + return temp; + } } CursorRef createImageCursor(const char *fullpath, int hotspotX, int hotspotY) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - - // extra retain on the NSCursor since we want it to live for the lifetime of the app. - NSCursor *cursor = - [[[NSCursor alloc] - initWithImage: - [[[NSImage alloc] initWithContentsOfFile: - [NSString stringWithUTF8String:fullpath] - ]autorelease] - hotSpot:NSMakePoint(hotspotX, hotspotY) - ]retain]; - - [pool release]; + NSCursor *cursor = nil; + @autoreleasepool { + // extra retain on the NSCursor since we want it to live for the lifetime of the app. + cursor = + [[[NSCursor alloc] + initWithImage: + [[[NSImage alloc] initWithContentsOfFile: + [NSString stringWithUTF8String:fullpath] + ] autorelease] + hotSpot:NSMakePoint(hotspotX, hotspotY) + ] retain]; + } return (CursorRef)cursor; } @@ -184,10 +176,10 @@ OSErr releaseImageCursor(CursorRef ref) { if( ref != NULL ) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSCursor *cursor = (NSCursor*)ref; - [cursor release]; - [pool release]; + @autoreleasepool { + NSCursor *cursor = (NSCursor*)ref; + [cursor autorelease]; + } } else { @@ -201,10 +193,10 @@ OSErr setImageCursor(CursorRef ref) { if( ref != NULL ) { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - NSCursor *cursor = (NSCursor*)ref; - [cursor set]; - [pool release]; + @autoreleasepool { + NSCursor *cursor = (NSCursor*)ref; + [cursor set]; + } } else { @@ -425,24 +417,26 @@ void requestUserAttention() long showAlert(std::string text, std::string title, int type) { - NSAlert *alert = [[NSAlert alloc] init]; - - [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]]; - [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]]; - if (type == 0) - { - [alert addButtonWithTitle:@"Okay"]; - } else if (type == 1) - { - [alert addButtonWithTitle:@"Okay"]; - [alert addButtonWithTitle:@"Cancel"]; - } else if (type == 2) - { - [alert addButtonWithTitle:@"Yes"]; - [alert addButtonWithTitle:@"No"]; + long ret = 0; + @autoreleasepool { + NSAlert *alert = [[[NSAlert alloc] init] autorelease]; + + [alert setMessageText:[NSString stringWithCString:title.c_str() encoding:[NSString defaultCStringEncoding]]]; + [alert setInformativeText:[NSString stringWithCString:text.c_str() encoding:[NSString defaultCStringEncoding]]]; + if (type == 0) + { + [alert addButtonWithTitle:@"Okay"]; + } else if (type == 1) + { + [alert addButtonWithTitle:@"Okay"]; + [alert addButtonWithTitle:@"Cancel"]; + } else if (type == 2) + { + [alert addButtonWithTitle:@"Yes"]; + [alert addButtonWithTitle:@"No"]; + } + ret = [alert runModal]; } - long ret = [alert runModal]; - [alert dealloc]; if (ret == NSAlertFirstButtonReturn) { diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 7580e66ad7..8286ecab4c 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -678,11 +678,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits if (cgl_err != kCGLNoError ) { - LL_DEBUGS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL; + LL_INFOS("GLInit") << "Multi-threaded OpenGL not available." << LL_ENDL; } else { - LL_DEBUGS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL; + LL_INFOS("GLInit") << "Multi-threaded OpenGL enabled." << LL_ENDL; } } makeFirstResponder(mWindow, mGLView); @@ -1256,10 +1256,13 @@ BOOL LLWindowMacOSX::isClipboardTextAvailable() } BOOL LLWindowMacOSX::pasteTextFromClipboard(LLWString &dst) -{ - //llutf16string str(copyFromPBoard()); - dst = utf16str_to_wstring(copyFromPBoard()); - LLWStringUtil::removeCRLF(dst); // +{ + unsigned short* pboard_data = copyFromPBoard(); // must free returned data + llutf16string str(pboard_data); + free(pboard_data); + + dst = utf16str_to_wstring(str) + LLWStringUtil::removeCRLF(dst); // ; if (dst != L"") { return true; @@ -1291,7 +1294,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r { if (!mSupportedResolutions) { - CFArrayRef modes = CGDisplayAvailableModes(mDisplay); + CFArrayRef modes = CGDisplayCopyAllDisplayModes(mDisplay, nullptr); if(modes != NULL) { @@ -1330,6 +1333,7 @@ LLWindow::LLWindowResolution* LLWindowMacOSX::getSupportedResolutions(S32 &num_r } } } + CFRelease(modes); } } diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 892d61e938..babe6f66cc 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -232,6 +232,7 @@ protected: BOOL mLanguageTextInputAllowed; LLPreeditor* mPreeditor; +public: static BOOL sUseMultGL; friend class LLWindowManager; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index f146b71b6e..3e89c320f5 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -3472,24 +3472,45 @@ BOOL LLWindowWin32::getClientRectInScreenSpace( RECT* rectp ) void LLWindowWin32::flashIcon(F32 seconds) { - if (mWindowHandle && (GetFocus() != mWindowHandle || GetForegroundWindow() != mWindowHandle)) - { - mWindowThread->post([=]() - { - FLASHWINFO flash_info; + // FIRE-32105: Application icon flashes also while viewer has focus + //if (mWindowHandle && (GetFocus() != mWindowHandle || GetForegroundWindow() != mWindowHandle)) + //{ + // mWindowThread->post([=]() + // { + // FLASHWINFO flash_info; - flash_info.cbSize = sizeof(FLASHWINFO); - flash_info.hwnd = mWindowHandle; - flash_info.dwFlags = FLASHW_TRAY; - // FIRE-23498: Tray icon flash functions randomly - //flash_info.uCount = UINT(seconds / ICON_FLASH_TIME); - //flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds - flash_info.uCount = UINT(ll_round(seconds / ICON_FLASH_TIME)); - flash_info.dwTimeout = DWORD(ll_round(1000.f * ICON_FLASH_TIME)); // milliseconds - // - FlashWindowEx(&flash_info); - }); - } + // flash_info.cbSize = sizeof(FLASHWINFO); + // flash_info.hwnd = mWindowHandle; + // flash_info.dwFlags = FLASHW_TRAY; + // // FIRE-23498: Tray icon flash functions randomly + // //flash_info.uCount = UINT(seconds / ICON_FLASH_TIME); + // //flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds + // flash_info.uCount = UINT(ll_round(seconds / ICON_FLASH_TIME)); + // flash_info.dwTimeout = DWORD(ll_round(1000.f * ICON_FLASH_TIME)); // milliseconds + // // + // FlashWindowEx(&flash_info); + // }); + //} + + mWindowThread->post([=]() + { + if (mWindowHandle && (GetFocus() != mWindowHandle || GetForegroundWindow() != mWindowHandle)) + { + FLASHWINFO flash_info; + + flash_info.cbSize = sizeof(FLASHWINFO); + flash_info.hwnd = mWindowHandle; + flash_info.dwFlags = FLASHW_TRAY; + // FIRE-23498: Tray icon flash functions randomly + //flash_info.uCount = UINT(seconds / ICON_FLASH_TIME); + //flash_info.dwTimeout = DWORD(1000.f * ICON_FLASH_TIME); // milliseconds + flash_info.uCount = UINT(ll_round(seconds / ICON_FLASH_TIME)); + flash_info.dwTimeout = DWORD(ll_round(1000.f * ICON_FLASH_TIME)); // milliseconds + // + FlashWindowEx(&flash_info); + } + }); + // } F32 LLWindowWin32::getGamma() diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 3231305da1..9aff39addd 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -2238,9 +2238,9 @@ if (WINDOWS) set_target_properties(${VIEWER_BINARY_NAME} PROPERTIES # *TODO -reenable this once we get server usage sorted out - LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /LARGEADDRESSAWARE" - LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO /LARGEADDRESSAWARE" - LINK_FLAGS_RELEASE "/FORCE:MULTIPLE /MAP\"secondlife-bin.MAP\" /OPT:REF /LARGEADDRESSAWARE" + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT /SUBSYSTEM:WINDOWS /LARGEADDRESSAWARE /LTCG" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\" /INCREMENTAL:NO /LARGEADDRESSAWARE /LTCG" + LINK_FLAGS_RELEASE "/FORCE:MULTIPLE /MAP\"secondlife-bin.MAP\" /OPT:REF /LARGEADDRESSAWARE /LTCG" ) if(USE_PRECOMPILED_HEADERS) diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt index f5199477c5..0673dfa857 100644 --- a/indra/newview/VIEWER_VERSION.txt +++ b/indra/newview/VIEWER_VERSION.txt @@ -1 +1 @@ -6.6.9 +6.6.10 diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 0ebe2c9c2b..94b6e727e1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -23427,6 +23427,17 @@ Change of this parameter will affect the layout of buttons in notification toast Value 0 + DebugSettingsHideDefault + + Comment + Show non-default settings only in Debug Settings list + Persist + 0 + Type + Boolean + Value + 0 + FSNetMapPhantomOpacity Comment diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl index 331249dc33..de22312d3c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -25,6 +25,17 @@ /*[EXTRA_CODE_HERE]*/ +// Inputs +VARYING vec4 vary_HazeColor; +VARYING float vary_LightNormPosDot; + +uniform sampler2D rainbow_map; +uniform sampler2D halo_map; + +uniform float moisture_level; +uniform float droplet_radius; +uniform float ice_level; + #ifdef DEFINE_GL_FRAGCOLOR out vec4 frag_data[3]; #else @@ -35,11 +46,34 @@ out vec4 frag_data[3]; // The fragment shader for the sky ///////////////////////////////////////////////////////////////////////// -VARYING vec4 vary_HazeColor; +vec3 rainbow(float d) +{ + // 'Interesting' values of d are -0.75 .. -0.825, i.e. when view vec nearly opposite of sun vec + // Rainbox tex is mapped with REPEAT, so -.75 as tex coord is same as 0.25. -0.825 -> 0.175. etc. + // SL-13629 + // Unfortunately the texture is inverted, so we need to invert the y coord, but keep the 'interesting' + // part within the same 0.175..0.250 range, i.e. d = (1 - d) - 1.575 + d = clamp(-0.575 - d, 0.0, 1.0); + + // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible. + // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate + // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857 + float interior_coord = max(0.0, d - 0.25) * 4.2857; + d = clamp(d, 0.0, 0.25) + interior_coord; + + float rad = (droplet_radius - 5.0f) / 1024.0f; + return pow(texture2D(rainbow_map, vec2(rad+0.5, d)).rgb, vec3(1.8)) * moisture_level; +} + +vec3 halo22(float d) +{ + d = clamp(d, 0.1, 1.0); + float v = sqrt(clamp(1 - (d * d), 0, 1)); + return texture2D(halo_map, vec2(0, v)).rgb * ice_level; +} /// Soft clips the light with a gamma correction vec3 scaleSoftClip(vec3 light); -vec3 srgb_to_linear(vec3 c); void main() { @@ -48,14 +82,18 @@ void main() // the fragment) if the sky wouldn't show up because the clouds // are fully opaque. - vec4 color; - color = vary_HazeColor; + vec4 color = vary_HazeColor; + float rel_pos_lightnorm = vary_LightNormPosDot; + float optic_d = rel_pos_lightnorm; + vec3 halo_22 = halo22(optic_d); + color.rgb += rainbow(optic_d); + color.rgb += halo_22; color.rgb *= 2.; color.rgb = scaleSoftClip(color.rgb); - /// Gamma correct for WL (soft clip effect). - frag_data[0] = vec4(color.rgb, 0.0); + // Gamma correct for WL (soft clip effect). + frag_data[0] = vec4(color.rgb, 1.0); frag_data[1] = vec4(0.0,0.0,0.0,0.0); frag_data[2] = vec4(0.0,0.0,0.0,1.0); //1.0 in norm.w masks off fog diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index 28a1faf24f..6db4690bff 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -33,6 +33,7 @@ ATTRIBUTE vec3 position; // Output parameters VARYING vec4 vary_HazeColor; +VARYING float vary_LightNormPosDot; // Inputs uniform vec3 camPosLocal; @@ -72,27 +73,29 @@ void main() vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0); // Adj position vector to clamp altitude - if (rel_pos.y > 0) + if (rel_pos.y > 0.) { rel_pos *= (max_y / rel_pos.y); } - if (rel_pos.y < 0) + if (rel_pos.y < 0.) { rel_pos *= (-32000. / rel_pos.y); } - // Can normalize then - vec3 rel_pos_norm = normalize(rel_pos); + // Normalized + vec3 rel_pos_norm = normalize(rel_pos); + float rel_pos_len = length(rel_pos); - float rel_pos_len = length(rel_pos); + // Grab this value and pass to frag shader for rainbows + float rel_pos_lightnorm_dot = dot(rel_pos_norm, lightnorm.xyz); + vary_LightNormPosDot = rel_pos_lightnorm_dot; // Initialize temp variables vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color; - vec4 light_atten; // Sunlight attenuation effect (hue and brightness) due to atmosphere // this is used later for sunlight modulation at various altitudes - light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); + vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); // Calculate relative weights vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density)); @@ -112,7 +115,7 @@ void main() combined_haze = exp(-combined_haze * density_dist); // Compute haze glow - float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz); + float haze_glow = 1.0 - rel_pos_lightnorm_dot; // haze_glow is 0 at the sun and increases away from sun haze_glow = max(haze_glow, .001); // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) @@ -123,30 +126,30 @@ void main() // Add "minimum anti-solar illumination" // For sun, add to glow. For moon, remove glow entirely. SL-13768 - haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25); + haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25)); - vec4 color = - (blue_horizon * blue_weight * (sunlight + ambient_color) + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color)); + // Haze color above cloud + vec4 color = (blue_horizon * blue_weight * (sunlight + ambient_color) + + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient_color)); // Final atmosphere additive color *= (1. - combined_haze); // Increase ambient when there are more clouds - vec4 tmpAmbient = ambient_color; - tmpAmbient += max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; + vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; // Dim sunlight by cloud shadow percentage sunlight *= max(0.0, (1. - cloud_shadow)); // Haze color below cloud - vec4 additiveColorBelowCloud = - (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient)); + vec4 add_below_cloud = (blue_horizon * blue_weight * (sunlight + ambient) + + (haze_horizon * haze_weight) * (sunlight * haze_glow + ambient)); // Attenuate cloud color by atmosphere combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds // At horizon, blend high altitude sky color towards the darker color below the clouds - color += (additiveColorBelowCloud - color) * (1. - sqrt(combined_haze)); + color += (add_below_cloud - color) * (1. - sqrt(combined_haze)); // Haze color above cloud vary_HazeColor = color; diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl deleted file mode 100644 index 6841a8194f..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl +++ /dev/null @@ -1,199 +0,0 @@ -/** - * @file class2/deferred/skyF.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, 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_projection_matrix; - -// SKY //////////////////////////////////////////////////////////////////////// -// The vertex shader for creating the atmospheric sky -/////////////////////////////////////////////////////////////////////////////// - -// Inputs -uniform vec3 camPosLocal; - -uniform vec4 lightnorm; -uniform vec4 sunlight_color; -uniform vec4 moonlight_color; -uniform int sun_up_factor; -uniform vec4 ambient_color; -uniform vec4 blue_horizon; -uniform vec4 blue_density; -uniform float haze_horizon; -uniform float haze_density; - -uniform float cloud_shadow; -uniform float density_multiplier; -uniform float distance_multiplier; -uniform float max_y; - -uniform vec4 glow; -uniform float sun_moon_glow_factor; - -uniform vec4 cloud_color; - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_data[3]; -#else -#define frag_data gl_FragData -#endif - -VARYING vec3 pos; - -///////////////////////////////////////////////////////////////////////// -// The fragment shader for the sky -///////////////////////////////////////////////////////////////////////// - -uniform sampler2D rainbow_map; -uniform sampler2D halo_map; - -uniform float moisture_level; -uniform float droplet_radius; -uniform float ice_level; - -vec3 rainbow(float d) -{ - // d is the dot product of view and sun directions, so ranging -1.0..1.0 - // 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec - // Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175. - - // SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted. - // Rather than replace the texture, we mirror and translate the y tc to keep the colors within the - // interesting range, but in reversed order: i.e. d = (1 - d) - 1.575 - d = clamp(-0.575 - d, 0.0, 1.0); - - // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible. - // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate - // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857 - float interior_coord = max(0.0, d - 0.25) * 4.2857; - d = clamp(d, 0.0, 0.25) + interior_coord; - - float rad = (droplet_radius - 5.0f) / 1024.0f; - return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level; -} - -vec3 halo22(float d) -{ - d = clamp(d, 0.1, 1.0); - float v = sqrt(clamp(1 - (d * d), 0, 1)); - return texture2D(halo_map, vec2(0, v)).rgb * ice_level; -} - -/// Soft clips the light with a gamma correction -vec3 scaleSoftClip(vec3 light); - -void main() -{ - // World / view / projection - // Get relative position (offset why?) - vec3 rel_pos = pos.xyz - camPosLocal.xyz + vec3(0, 50, 0); - - // Adj position vector to clamp altitude - if (rel_pos.y > 0.) - { - rel_pos *= (max_y / rel_pos.y); - } - if (rel_pos.y < 0.) - { - rel_pos *= (-32000. / rel_pos.y); - } - - // Normalized - vec3 rel_pos_norm = normalize(rel_pos); - float rel_pos_len = length(rel_pos); - - // Initialize temp variables - vec4 sunlight = (sun_up_factor == 1) ? sunlight_color : moonlight_color; - - // Sunlight attenuation effect (hue and brightness) due to atmosphere - // this is used later for sunlight modulation at various altitudes - vec4 light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y); - - // Calculate relative weights - vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density)); - vec4 blue_weight = blue_density / combined_haze; - vec4 haze_weight = haze_density / combined_haze; - - // Compute sunlight from rel_pos & lightnorm (for long rays like sky) - float off_axis = 1.0 / max(1e-6, max(0, rel_pos_norm.y) + lightnorm.y); - sunlight *= exp(-light_atten * off_axis); - - // Distance - float density_dist = rel_pos_len * density_multiplier; - - // Transparency (-> combined_haze) - // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati - // compiler gets confused. - combined_haze = exp(-combined_haze * density_dist); - - // Compute haze glow - float haze_glow = dot(rel_pos_norm, lightnorm.xyz); - haze_glow = 1. - haze_glow; - // haze_glow is 0 at the sun and increases away from sun - haze_glow = max(haze_glow, .001); - // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) - haze_glow *= glow.x; - // Higher glow.x gives dimmer glow (because next step is 1 / "angle") - haze_glow = pow(haze_glow, glow.z); - // glow.z should be negative, so we're doing a sort of (1 / "angle") function - - // Add "minimum anti-solar illumination" - // For sun, add to glow. For moon, remove glow entirely. SL-13768 - haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (sun_moon_glow_factor * (haze_glow + 0.25)); - - // Haze color above cloud - vec4 color = blue_horizon * blue_weight * (sunlight + ambient_color) - + haze_horizon * haze_weight * (sunlight * haze_glow + ambient_color); - - // Final atmosphere additive - color *= (1. - combined_haze); - - // Increase ambient when there are more clouds - // TODO 9/20: DJH what does this do? max(0,(1-ambient)) will change the color - vec4 ambient = ambient_color + max(vec4(0), (1. - ambient_color)) * cloud_shadow * 0.5; - - // Dim sunlight by cloud shadow percentage - sunlight *= max(0.0, (1. - cloud_shadow)); - - // Haze color below cloud - vec4 add_below_cloud = blue_horizon * blue_weight * (sunlight + ambient) - + haze_horizon * haze_weight * (sunlight * haze_glow + ambient); - - // Attenuate cloud color by atmosphere - combined_haze = sqrt(combined_haze); // less atmos opacity (more transparency) below clouds - - // At horizon, blend high altitude sky color towards the darker color below the clouds - color += (add_below_cloud - color) * (1. - sqrt(combined_haze)); - - float optic_d = dot(rel_pos_norm, lightnorm.xyz); - vec3 halo_22 = halo22(optic_d); - color.rgb += rainbow(optic_d); - color.rgb += halo_22; - color.rgb *= 2.; - color.rgb = scaleSoftClip(color.rgb); - - // Gamma correct for WL (soft clip effect). - frag_data[0] = vec4(color.rgb, 1.0); - frag_data[1] = vec4(0.0, 0.0, 0.0, 0.0); - frag_data[2] = vec4(0.0, 0.0, 0.0, 1.0); // 1.0 in norm.w masks off fog -} diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl deleted file mode 100644 index bcf775577a..0000000000 --- a/indra/newview/app_settings/shaders/class2/deferred/skyV.glsl +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file WLSkyV.glsl - * - * $LicenseInfo:firstyear=2005&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2005, 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_projection_matrix; - -ATTRIBUTE vec3 position; - -// SKY //////////////////////////////////////////////////////////////////////// -// The vertex shader for creating the atmospheric sky -/////////////////////////////////////////////////////////////////////////////// - -VARYING vec3 pos; - -void main() -{ - - // World / view / projection - pos = position.xyz; - gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); -} diff --git a/indra/newview/fschathistory.cpp b/indra/newview/fschathistory.cpp index 51d151b5e2..46ed261d15 100644 --- a/indra/newview/fschathistory.cpp +++ b/indra/newview/fschathistory.cpp @@ -1263,9 +1263,7 @@ FSChatHistory::FSChatHistory(const FSChatHistory::Params& p) LLSD FSChatHistory::getValue() const { - LLSD* text=new LLSD(); - text->assign(getText()); - return *text; + return LLSD(getText()); } FSChatHistory::~FSChatHistory() diff --git a/indra/newview/fscontactsfriendsmenu.cpp b/indra/newview/fscontactsfriendsmenu.cpp index 06cac87333..54016424dd 100644 --- a/indra/newview/fscontactsfriendsmenu.cpp +++ b/indra/newview/fscontactsfriendsmenu.cpp @@ -106,7 +106,7 @@ bool FSContactsFriendsMenu::enableContextMenuItem(const LLSD& userdata) { if (mUUIDs.size() == 1) { - return (FSRadar::getInstance()->getEntry(mUUIDs.front()) != NULL); + return FSRadar::getInstance()->getEntry(mUUIDs.front()) != nullptr; } return false; } @@ -126,7 +126,7 @@ bool FSContactsFriendsMenu::enableContextMenuItem(const LLSD& userdata) { if (mUUIDs.size() == 1) { - return (FSRadar::getInstance()->getEntry(mUUIDs.front()) != NULL); + return FSRadar::getInstance()->getEntry(mUUIDs.front()) != nullptr; } return false; } diff --git a/indra/newview/fslslpreproc.cpp b/indra/newview/fslslpreproc.cpp index 12f46fa2eb..12d7d3ff7b 100644 --- a/indra/newview/fslslpreproc.cpp +++ b/indra/newview/fslslpreproc.cpp @@ -38,12 +38,12 @@ #include "fslslpreprocviewer.h" #include "llagent.h" #include "llappviewer.h" -#include "llinventoryfunctions.h" -#include "lltrans.h" -#include "llfilesystem.h" -#include "llviewercontrol.h" #include "llcompilequeue.h" +#include "llfilesystem.h" +#include "llinventoryfunctions.h" #include "llnotificationsutil.h" +#include "lltrans.h" +#include "llviewercontrol.h" #ifdef __GNUC__ // There is a sprintf( ... "%d", size_t_value) buried inside boost::wave. In order to not mess with system header, I rather disable that warning here. @@ -53,7 +53,7 @@ class ScriptMatches : public LLInventoryCollectFunctor { public: - ScriptMatches(const std::string& name) + ScriptMatches(std::string_view name) { mName = name; } @@ -70,7 +70,7 @@ private: std::string mName; }; -LLUUID FSLSLPreprocessor::findInventoryByName(std::string name) +std::optional FSLSLPreprocessor::findInventoryByName(std::string_view name) { LLInventoryModel::cat_array_t cats; LLInventoryModel::item_array_t items; @@ -81,17 +81,11 @@ LLUUID FSLSLPreprocessor::findInventoryByName(std::string name) { return items.front()->getUUID(); } - return LLUUID::null; + return std::nullopt; } -std::map FSLSLPreprocessor::cached_assetids; - -#if !defined(LL_DARWIN) || defined(DARWINPREPROC) - -//apparently LL #defined this function which happens to precisely match -//a boost::wave function name, destroying the internet, silly grey furries -#undef equivalent +std::map FSLSLPreprocessor::cached_assetids; // Work around stupid Microsoft STL warning #ifdef LL_WINDOWS @@ -131,20 +125,14 @@ using namespace boost::regex_constants; std::string FSLSLPreprocessor::encode(const std::string& script) { std::string otext = FSLSLPreprocessor::decode(script); - - bool mono = mono_directive(script); - + otext = boost::regex_replace(otext, boost::regex("([/*])(?=[/*|])", boost::regex::perl), "$1|"); - - //otext = curl_escape(otext.c_str(), otext.size()); - otext = encode_start + otext + encode_end; - otext += "\n//nfo_preprocessor_version 0"; - + //otext += "\n//^ = determine what featureset is supported"; otext += llformat("\n//program_version %s", LLAppViewer::instance()->getWindowTitle().c_str()); - + time_t utc_time = time_corrected(); std::string timeStr ="["+LLTrans::getString ("TimeMonth")+"]/[" +LLTrans::getString ("TimeDay")+"]/[" @@ -156,10 +144,9 @@ std::string FSLSLPreprocessor::encode(const std::string& script) substitution["datetime"] = (S32) utc_time; LLStringUtil::format (timeStr, substitution); otext += "\n//last_compiled " + timeStr; - otext += "\n"; - - if (mono) + + if (mono_directive(script)) { otext += "//mono\n"; } @@ -173,19 +160,19 @@ std::string FSLSLPreprocessor::encode(const std::string& script) std::string FSLSLPreprocessor::decode(const std::string& script) { - static S32 startpoint = encode_start.length(); - + static const S32 startpoint = encode_start.length(); + std::string tip = script.substr(0, startpoint); - + if (tip != encode_start) { LL_DEBUGS("FSLSLPreprocessor") << "No start" << LL_ENDL; //if(sp != -1)trigger warningg/error? return script; } - + S32 end = script.find(encode_end); - + if (end == -1) { LL_DEBUGS("FSLSLPreprocessor") << "No end" << LL_ENDL; @@ -196,11 +183,8 @@ std::string FSLSLPreprocessor::decode(const std::string& script) LL_DEBUGS("FSLSLPreprocessor") << "data = " << data << LL_ENDL; std::string otext = data; - otext = boost::regex_replace(otext, boost::regex("([/*])\\|", boost::regex::perl), "$1"); - //otext = curl_unescape(otext.c_str(),otext.length()); - return otext; } @@ -211,13 +195,13 @@ static std::string scopeript2(std::string& top, S32 fstart, char left = '{', cha { return "begin out of bounds"; } - + S32 cursor = fstart; bool noscoped = true; bool in_literal = false; S32 count = 0; char ltoken = ' '; - + do { char token = top.at(cursor); @@ -253,7 +237,7 @@ static std::string scopeript2(std::string& top, S32 fstart, char left = '{', cha return "end out of bounds"; } - return top.substr(fstart,(cursor-fstart)); + return top.substr(fstart, (cursor - fstart)); } static inline S32 const_iterator_to_pos(std::string::const_iterator begin, std::string::const_iterator cursor) @@ -317,7 +301,6 @@ static void shredder(std::string& text) std::string FSLSLPreprocessor::lslopt(std::string script) { - try { std::string bottom; @@ -409,17 +392,12 @@ std::string FSLSLPreprocessor::lslopt(std::string script) do { repass = false; - std::map::iterator func_it; - for (func_it = functions.begin(); func_it != functions.end(); func_it++) + for (const auto& [funcname, function] : functions) { - - std::string funcname = func_it->first; - if (kept_functions.find(funcname) == kept_functions.end()) { - boost::smatch calls; - //funcname has to be [a-zA-Z0-9_]+, so we know it's safe + //funcname has to be [a-zA-Z0-9_]+, so we know it's safe boost::regex findcalls(std::string() + rDOT_MATCHES_NEWLINE "(?second; kept_functions.insert(funcname); bottom = function + bottom; repass = true; @@ -456,11 +433,9 @@ std::string FSLSLPreprocessor::lslopt(std::string script) while (repass); // Find variable invocations and add the declarations back if used. - std::vector >::reverse_iterator var_it; for (var_it = gvars.rbegin(); var_it != gvars.rend(); var_it++) { - std::string varname = var_it->first; boost::regex findvcalls(std::string() + rDOT_MATCHES_NEWLINE "(?mMainScriptName); } - template bool found_include_directive(ContextT const& ctx, std::string const &filename, bool include_next) { std::string cfilename = filename.substr(1, filename.length() - 2); LL_DEBUGS("FSLSLPreprocessor") << cfilename << ":found_include_directive" << LL_ENDL; - LLUUID item_id = FSLSLPreprocessor::findInventoryByName(cfilename); - if (item_id.notNull()) + std::optional item_id = FSLSLPreprocessor::findInventoryByName(cfilename); + if (item_id.has_value()) { - LLViewerInventoryItem* item = gInventory.getItem(item_id); + LLViewerInventoryItem* item = gInventory.getItem(item_id.value()); if (item) { std::map::iterator it = mProc->cached_assetids.find(cfilename); @@ -605,8 +580,8 @@ public: info->self = mProc; LLPermissions perm(((LLInventoryItem*)item)->getPermissions()); gAssetStorage->getInvItemAsset(LLHost(), - gAgent.getID(), - gAgent.getSessionID(), + gAgentID, + gAgentSessionID, perm.getOwner(), LLUUID::null, item->getUUID(), @@ -624,7 +599,6 @@ public: { //todo check on HDD in user defined dir for file in question } - //++include_depth; return false; } @@ -633,11 +607,10 @@ public: std::string const &relname, std::string const& absname, bool is_system_include) { - ContextT& usefulctx = const_cast(ctx); std::string id; - std::string filename = shortfile(relname);//boost::filesystem::path(std::string(relname)).filename(); - std::map::iterator it = mProc->cached_assetids.find(filename); + std::string filename = shortfile(relname); + std::map::iterator it = mProc->cached_assetids.find(filename); if (it != mProc->cached_assetids.end()) { id = mProc->cached_assetids[filename].asString(); @@ -707,7 +680,6 @@ private: void cache_script(std::string name, std::string content) { - content += "\n";/*hack!*/ LL_DEBUGS("FSLSLPreprocessor") << "writing " << name << " to cache" << LL_ENDL; std::string path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "lslpreproc", name); @@ -752,15 +724,16 @@ void FSLSLPreprocessor::FSProcCacheCallback(const LLUUID& iuuid, LLAssetType::ET args["[FILENAME]"] = name; self->display_message(LLTrans::getString("fs_preprocessor_cache_completed", args)); cache_script(name, content); - std::set::iterator loc = self->caching_files.find(name); - if (loc != self->caching_files.end()) + if (std::set::iterator loc = self->caching_files.find(name); loc != self->caching_files.end()) { LL_DEBUGS("FSLSLPreprocessor") << "finalizing cache" << LL_ENDL; self->caching_files.erase(loc); - //self->cached_files.insert(name); - if(uuid.isNull())uuid.generate(); + if (uuid.isNull()) + { + uuid.generate(); + } item->setAssetUUID(uuid); - self->cached_assetids[name] = uuid;//.insert(uuid.asString()); + self->cached_assetids[name] = uuid; self->start_process(); } else @@ -797,12 +770,11 @@ void FSLSLPreprocessor::preprocess_script(BOOL close, bool sync, bool defcache) caching_files.clear(); LLStringUtil::format_map_t args; display_message(LLTrans::getString("fs_preprocessor_starting")); - - LLFile::mkdir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"") + gDirUtilp->getDirDelimiter() + "lslpreproc"); - std::string script = mCore->mEditor->getText(); + + LLFile::mkdir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "lslpreproc")); if (mMainScriptName.empty())//more sanity { - const LLInventoryItem* item = NULL; + const LLInventoryItem* item = nullptr; LLPreview* preview = (LLPreview*)mCore->mUserdata; if (preview) { @@ -818,34 +790,33 @@ void FSLSLPreprocessor::preprocess_script(BOOL close, bool sync, bool defcache) mMainScriptName = "(Unknown)"; } } - std::string name = mMainScriptName; - cached_assetids[name] = LLUUID::null; - cache_script(name, script); + cached_assetids[mMainScriptName] = LLUUID::null; + cache_script(mMainScriptName, mCore->mEditor->getText()); //start the party start_process(); } void FSLSLPreprocessor::preprocess_script(const LLUUID& asset_id, LLScriptQueueData* data, LLAssetType::EType type, const std::string& script_data) { - if(!data) + if (!data) { return; } - + std::string script = FSLSLPreprocessor::decode(script_data); - + mScript = script; mAssetID = asset_id; mData = data; mType = type; - + mDefinitionCaching = false; caching_files.clear(); LLStringUtil::format_map_t args; display_message(LLTrans::getString("fs_preprocessor_starting")); - - LLFile::mkdir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"") + gDirUtilp->getDirDelimiter() + "lslpreproc"); - + + LLFile::mkdir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "lslpreproc")); + if (mData->mItem) { mMainScriptName = mData->mItem->getName(); @@ -854,10 +825,9 @@ void FSLSLPreprocessor::preprocess_script(const LLUUID& asset_id, LLScriptQueueD { mMainScriptName = "(Unknown)"; } - - std::string name = mMainScriptName; - cached_assetids[name] = LLUUID::null; - cache_script(name, script); + + cached_assetids[mMainScriptName] = LLUUID::null; + cache_script(mMainScriptName, script); //start the party start_process(); } @@ -974,13 +944,6 @@ static inline std::string quicklabel() return std::string("c") + randstr(5, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"); } -/* unused: -static std::string minimalize_whitespace(std::string in) -{ - return boost::regex_replace(in, boost::regex("\\s*",boost::regex::perl), "\n"); -} -*/ - static std::string reformat_switch_statements(std::string script, bool &lackDefault) { std::string buffer = script; @@ -1274,11 +1237,11 @@ void FSLSLPreprocessor::start_process() } input = oaux.str(); } - + //Make sure wave does not complain about missing newline at end of script. input += "\n"; std::string output; - + std::string name = mMainScriptName; bool lazy_lists = gSavedSettings.getBOOL("_NACL_PreProcLSLLazyLists"); bool use_switch = gSavedSettings.getBOOL("_NACL_PreProcLSLSwitch"); @@ -1327,7 +1290,7 @@ void FSLSLPreprocessor::start_process() ctx.set_language(boost::wave::enable_long_long(ctx.get_language())); ctx.set_language(boost::wave::enable_prefer_pp_numbers(ctx.get_language())); ctx.set_language(boost::wave::enable_variadics(ctx.get_language())); - + std::string path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"") + gDirUtilp->getDirDelimiter() + "lslpreproc" + gDirUtilp->getDirDelimiter(); ctx.add_include_path(path.c_str()); if (enable_hdd_include) @@ -1447,7 +1410,7 @@ void FSLSLPreprocessor::start_process() display_error(err); } } - + if (preprocessor_enabled && !errored) { FAILDEBUG @@ -1534,7 +1497,7 @@ void FSLSLPreprocessor::start_process() output = lslopt(output); } catch(...) - { + { errored = true; display_error(LLTrans::getString("fs_preprocessor_optimizer_unexpected_exception")); } @@ -1584,7 +1547,7 @@ void FSLSLPreprocessor::start_process() if (mStandalone) { - LLFloaterCompileQueue::scriptPreprocComplete(mAssetID, mData, mType, output); + LLFloaterCompileQueue::scriptPreprocComplete(mData, mType, output); } else { @@ -1605,66 +1568,20 @@ void FSLSLPreprocessor::start_process() mWaving = false; } -#else -std::string FSLSLPreprocessor::encode(const std::string& script) -{ - LLStringUtil::format_map_t args; - args["[WHERE]"] = "encode"; - display_error(LLTrans::getString("fs_preprocessor_not_supported", args)); - return script; -} - -std::string FSLSLPreprocessor::decode(const std::string& script) -{ - LLStringUtil::format_map_t args; - args["[WHERE]"] = "decode"; - display_error(LLTrans::getString("fs_preprocessor_not_supported", args)); - return script; -} - -std::string FSLSLPreprocessor::lslopt(std::string script) -{ - LLStringUtil::format_map_t args; - args["[WHERE]"] = "lslopt"; - display_error(LLTrans::getString("fs_preprocessor_not_supported", args)); - return script; -} - -void FSLSLPreprocessor::FSProcCacheCallback(LLVFS *vfs, const LLUUID& uuid, LLAssetType::EType type, void *userdata, S32 result, LLExtStat extstat) -{ -} - -void FSLSLPreprocessor::preprocess_script(BOOL close, bool sync, bool defcache) -{ - FSLSLPreProcViewer* outfield = mCore->mPostEditor; - if (outfield) - { - outfield->setText(LLStringExplicit(mCore->mEditor->getText())); - } - mCore->doSaveComplete((void*)mCore, close, sync); -} - -void FSLSLPreprocessor::preprocess_script(const LLUUID& asset_id, LLScriptQueueData* data, LLAssetType::EType type, const std::string& script_data) -{ - LLFloaterCompileQueue::scriptPreprocComplete(asset_id, data, type, script_data); -} - -#endif - -void FSLSLPreprocessor::display_message(const std::string& err) +void FSLSLPreprocessor::display_message(std::string_view msg) { if (mStandalone) { - LLFloaterCompileQueue::scriptLogMessage(mData, err); + LLFloaterCompileQueue::scriptLogMessage(mData, msg); } else { - mCore->mErrorList->addCommentText(err); + mCore->mErrorList->addCommentText(msg.data()); } } -void FSLSLPreprocessor::display_error(const std::string& err) +void FSLSLPreprocessor::display_error(std::string_view err) { if (mStandalone) { @@ -1673,14 +1590,13 @@ void FSLSLPreprocessor::display_error(const std::string& err) else { LLSD row; - row["columns"][0]["value"] = err; + row["columns"][0]["value"] = err.data(); row["columns"][0]["font"] = "SANSSERIF_SMALL"; mCore->mErrorList->addElement(row); } } - -bool FSLSLPreprocessor::mono_directive(std::string const& text, bool agent_inv) +bool FSLSLPreprocessor::mono_directive(std::string_view text, bool agent_inv) { bool domono = agent_inv; diff --git a/indra/newview/fslslpreproc.h b/indra/newview/fslslpreproc.h index 4c94d1f131..9959dc1133 100644 --- a/indra/newview/fslslpreproc.h +++ b/indra/newview/fslslpreproc.h @@ -37,16 +37,13 @@ #include "llviewerprecompiledheaders.h" #include "llpreviewscript.h" -#define DARWINPREPROC -//force preproc on mac - struct LLScriptQueueData; class FSLSLPreprocessor { LOG_CLASS(FSLSLPreprocessor); -public: +public: FSLSLPreprocessor(LLScriptEdCore* corep) : mCore(corep), mWaving(false), mClose(FALSE), mSync(false), mStandalone(false) {} @@ -55,23 +52,21 @@ public: : mWaving(false), mClose(FALSE), mSync(false), mStandalone(true) {} - static bool mono_directive(std::string const& text, bool agent_inv = true); + static bool mono_directive(std::string_view text, bool agent_inv = true); std::string encode(const std::string& script); std::string decode(const std::string& script); std::string lslopt(std::string script); std::string lslcomp(std::string script); - static LLUUID findInventoryByName(std::string name); + static std::optional findInventoryByName(std::string_view name); static void FSProcCacheCallback(const LLUUID& uuid, LLAssetType::EType type, void *userdata, S32 result, LLExtStat extstat); void preprocess_script(BOOL close = FALSE, bool sync = false, bool defcache = false); void preprocess_script(const LLUUID& asset_id, LLScriptQueueData* data, LLAssetType::EType type, const std::string& script_data); void start_process(); - void display_message(const std::string& err); - void display_error(const std::string& err); - - std::string uncollide_string_literals(std::string script); + void display_message(std::string_view msg); + void display_error(std::string_view err); //dual function, determines if files have been modified this session and if we have cached them //also assetids exposed in-preprocessing as a predefined macro for use in include once style include files, e.g. #define THISFILE file_ ## __ASSETIDRAW__ @@ -85,8 +80,6 @@ public: //(it seems rather dumb that readable scripts don't show the asset id without a DL, but thats beside the point.) static std::map cached_assetids; - static std::map decollided_literals; - std::set caching_files; std::set defcached_files; bool mDefinitionCaching; @@ -96,7 +89,7 @@ public: BOOL mClose; bool mSync; std::string mMainScriptName; - + // Compile queue bool mStandalone; std::string mScript; diff --git a/indra/newview/fsnamelistavatarmenu.cpp b/indra/newview/fsnamelistavatarmenu.cpp index 1f3f51ca47..49c7bd91f3 100644 --- a/indra/newview/fsnamelistavatarmenu.cpp +++ b/indra/newview/fsnamelistavatarmenu.cpp @@ -85,15 +85,15 @@ LLContextMenu* FSNameListAvatarMenu::createMenu() bool FSNameListAvatarMenu::enableContextMenuItem(const LLSD& userdata) { std::string item = userdata.asString(); - bool isSelf = mUUIDs.size() > 0 && mUUIDs.front() == gAgentID; + bool isSelf = !mUUIDs.empty() && mUUIDs.front() == gAgentID; if (item == "remove_friend") { - bool result = (mUUIDs.size() > 0); + bool result = !mUUIDs.empty(); - for (uuid_vec_t::const_iterator it = mUUIDs.begin(); it != mUUIDs.end(); ++it) + for (const auto& avid : mUUIDs) { - if (!LLAvatarActions::isFriend(*it)) + if (!LLAvatarActions::isFriend(avid)) { result = false; break; @@ -127,14 +127,14 @@ bool FSNameListAvatarMenu::enableContextMenuItem(const LLSD& userdata) else if (mUUIDs.size() > 1) { // Prevent starting a conference if IMs are blocked for a member - for (uuid_vec_t::const_iterator it = mUUIDs.begin(); it != mUUIDs.end(); ++it) + for (const auto& avid : mUUIDs) { - if ((*it) == gAgentID) + if (avid == gAgentID) { continue; } - if (!RlvActions::canStartIM(*it)) + if (!RlvActions::canStartIM(avid)) { return false; } @@ -147,7 +147,7 @@ bool FSNameListAvatarMenu::enableContextMenuItem(const LLSD& userdata) { if (mUUIDs.size() == 1) { - return (!isSelf && FSRadar::getInstance()->getEntry(mUUIDs.front()) != NULL); + return (!isSelf && FSRadar::getInstance()->getEntry(mUUIDs.front()) != nullptr); } return false; } @@ -167,7 +167,7 @@ bool FSNameListAvatarMenu::enableContextMenuItem(const LLSD& userdata) { if (mUUIDs.size() == 1) { - return (!isSelf && FSRadar::getInstance()->getEntry(mUUIDs.front()) != NULL); + return (!isSelf && FSRadar::getInstance()->getEntry(mUUIDs.front()) != nullptr); } return false; } @@ -191,14 +191,14 @@ bool FSNameListAvatarMenu::enableContextMenuItem(const LLSD& userdata) void FSNameListAvatarMenu::offerTeleport() { - uuid_vec_t uuids; + uuid_vec_t uuids{}; uuids.reserve(mUUIDs.size()); - for (uuid_vec_t::const_iterator it = mUUIDs.begin(); it != mUUIDs.end(); ++it) + for (const auto& avid : mUUIDs) { // Skip ourself if sending a TP to more than one agent - if ((*it) != gAgentID) + if (avid != gAgentID) { - uuids.push_back(*it); + uuids.emplace_back(avid); } } LLAvatarActions::offerTeleport(uuids); @@ -216,14 +216,14 @@ void FSNameListAvatarMenu::onTrackAvatarMenuItemClick() void FSNameListAvatarMenu::addToContactSet() { - uuid_vec_t uuids; + uuid_vec_t uuids{}; uuids.reserve(mUUIDs.size()); - for (uuid_vec_t::const_iterator it = mUUIDs.begin(); it != mUUIDs.end(); ++it) + for (const auto& avid : mUUIDs) { // Skip ourself if adding more than one agent - if ((*it) != gAgentID) + if (avid != gAgentID) { - uuids.push_back(*it); + uuids.emplace_back(avid); } } LLAvatarActions::addToContactSet(uuids); diff --git a/indra/newview/fspanelradar.cpp b/indra/newview/fspanelradar.cpp index e6e0d7c5d5..b0eb1e168d 100644 --- a/indra/newview/fspanelradar.cpp +++ b/indra/newview/fspanelradar.cpp @@ -78,13 +78,13 @@ static LLPanelInjector t_fs_panel_radar("fs_panel_radar"); FSPanelRadar::FSPanelRadar() : LLPanel(), - mRadarGearButton(NULL), - mOptionsButton(NULL), - mMiniMap(NULL), + mRadarGearButton(nullptr), + mOptionsButton(nullptr), + mMiniMap(nullptr), mFilterSubString(LLStringUtil::null), mFilterSubStringOrig(LLStringUtil::null), - mRadarList(NULL), - mVisibleCheckFunction(NULL), + mRadarList(nullptr), + mVisibleCheckFunction(), mUpdateSignalConnection(), mFSRadarColumnConfigConnection(), mLastResizeDelta(0) @@ -215,10 +215,9 @@ LLUUID FSPanelRadar::getCurrentItemID() const void FSPanelRadar::getCurrentItemIDs(uuid_vec_t& selected_uuids) const { - std::vector selected_items = mRadarList->getAllSelected(); - for (std::vector::iterator it = selected_items.begin(); it != selected_items.end(); ++it) + for (auto selected_item : mRadarList->getAllSelected()) { - selected_uuids.push_back((*it)->getUUID()); + selected_uuids.emplace_back(selected_item->getUUID()); } } @@ -314,7 +313,7 @@ void FSPanelRadar::requestUpdate() void FSPanelRadar::updateList(const std::vector& entries, const LLSD& stats) { - if (mVisibleCheckFunction && !mVisibleCheckFunction()) + if (!mVisibleCheckFunction.empty() && !mVisibleCheckFunction()) { return; } @@ -331,11 +330,10 @@ void FSPanelRadar::updateList(const std::vector& entries, const LLSD& stat { last_selected_id = mRadarList->getLastSelectedItem()->getUUID(); } - std::vector selected_items = mRadarList->getAllSelected(); uuid_vec_t selected_ids; - for (std::vector::iterator it = selected_items.begin(); it != selected_items.end(); ++it) + for (auto selected_item : mRadarList->getAllSelected()) { - selected_ids.push_back((*it)->getUUID()); + selected_ids.emplace_back(selected_item->getUUID()); } S32 lastScroll = mRadarList->getScrollPos(); @@ -346,11 +344,10 @@ void FSPanelRadar::updateList(const std::vector& entries, const LLSD& stat mRadarList->setNeedsSort(false); mRadarList->clearRows(); - const std::vector::const_iterator it_end = entries.end(); - for (std::vector::const_iterator it = entries.begin(); it != it_end; ++it) + for (const auto& avdata : entries) { - LLSD entry = (*it)["entry"]; - LLSD options = (*it)["options"]; + LLSD entry = avdata["entry"]; + LLSD options = avdata["options"]; LLSD row_data; row_data["value"] = entry["id"]; @@ -480,7 +477,7 @@ void FSPanelRadar::onColumnDisplayModeChanged() std::vector column_params = mRadarList->getColumnInitParams(); S32 column_padding = mRadarList->getColumnPadding(); - LLFloater* parent_floater = NULL; + LLFloater* parent_floater = nullptr; LLView* parent = getParent(); while (parent) { @@ -508,10 +505,8 @@ void FSPanelRadar::onColumnDisplayModeChanged() mRadarList->clearColumns(); mRadarList->updateLayout(); - std::vector::iterator param_it; - for (param_it = column_params.begin(); param_it != column_params.end(); ++param_it) + for (const auto& p : column_params) { - LLScrollListColumn::Params p = *param_it; default_width += (p.width.pixel_width.getValue() + column_padding); LLScrollListColumn::Params params; diff --git a/indra/newview/fsradar.cpp b/indra/newview/fsradar.cpp index 0277474047..ebf3d659d1 100644 --- a/indra/newview/fsradar.cpp +++ b/indra/newview/fsradar.cpp @@ -112,10 +112,9 @@ FSRadar::~FSRadar() { delete mRadarListUpdater; - entry_map_t::iterator em_it_end = mEntryList.end(); - for (entry_map_t::iterator em_it = mEntryList.begin(); em_it != em_it_end; ++em_it) + for (const auto& [av_id, entry] : mEntryList) { - delete em_it->second; + delete entry; } if (mShowUsernamesCallbackConnection.connected()) @@ -134,7 +133,7 @@ FSRadar::~FSRadar() } } -void FSRadar::radarAlertMsg(const LLUUID& agent_id, const LLAvatarName& av_name, const std::string& postMsg) +void FSRadar::radarAlertMsg(const LLUUID& agent_id, const LLAvatarName& av_name, std::string_view postMsg) { // Milkshake-style radar alerts static LLCachedControl sFSMilkshakeRadarToasts(gSavedSettings, "FSMilkshakeRadarToasts", false); @@ -144,7 +143,7 @@ void FSRadar::radarAlertMsg(const LLUUID& agent_id, const LLAvatarName& av_name, LLSD payload = agent_id; LLSD args; args["NAME"] = FSRadarEntry::getRadarName(av_name); - args["MESSAGE"] = postMsg; + args["MESSAGE"] = static_cast(postMsg); LLNotificationsUtil::add("RadarAlert", args, payload.with("respond_on_mousedown", TRUE), @@ -250,20 +249,16 @@ void FSRadar::updateRadarList() // Determine lists of new added and removed avatars uuid_vec_t current_vec, added_vec, removed_vec; - uuid_vec_t::iterator vec_it_end; - entry_map_t::iterator em_it_end = mEntryList.end(); current_vec.reserve(mEntryList.size()); - for (entry_map_t::iterator em_it = mEntryList.begin(); em_it != em_it_end; ++em_it) + for (const auto& [av_id, entry] : mEntryList) { - current_vec.push_back(em_it->first); + current_vec.emplace_back(av_id); } LLCommonUtils::computeDifference(avatar_ids, current_vec, added_vec, removed_vec); // Remove old avatars from our list - vec_it_end = removed_vec.end(); - for (uuid_vec_t::iterator it = removed_vec.begin(); it != vec_it_end; ++it) + for (const auto& avid : removed_vec) { - LLUUID avid = *it; entry_map_t::iterator found = mEntryList.find(avid); if (found != mEntryList.end()) { @@ -273,10 +268,8 @@ void FSRadar::updateRadarList() } // Add new avatars - vec_it_end = added_vec.end(); - for (uuid_vec_t::iterator it = added_vec.begin(); it != vec_it_end; ++it) + for (const auto& avid : added_vec) { - LLUUID avid = *it; mEntryList[avid] = new FSRadarEntry(avid); } @@ -695,11 +688,8 @@ void FSRadar::updateRadarList() // if (RlvActions::canShowNearbyAgents()) { - radarfields_map_t::iterator rf_it_end = mLastRadarSweep.end(); - for (radarfields_map_t::iterator i = mLastRadarSweep.begin(); i != rf_it_end; ++i) + for (const auto& [prevId, rf] : mLastRadarSweep) { - LLUUID prevId = i->first; - RadarFields rf = i->second; if ((sFSRadarShowMutedAndDerendered || !rf.lastIgnore) && mEntryList.find(prevId) == mEntryList.end()) { if (sRadarReportChatRangeLeave && (rf.lastDistance <= chat_range_say) && rf.lastDistance > AVATAR_UNKNOWN_RANGE) @@ -797,24 +787,22 @@ void FSRadar::updateRadarList() // mLastRadarSweep.clear(); - em_it_end = mEntryList.end(); - for (entry_map_t::iterator em_it = mEntryList.begin(); em_it != em_it_end; ++em_it) + for (const auto& [avid, entry] : mEntryList) { - FSRadarEntry* ent = em_it->second; RadarFields rf; - rf.lastDistance = ent->mRange; - rf.lastIgnore = ent->mIgnore; + rf.lastDistance = entry->mRange; + rf.lastIgnore = entry->mIgnore; rf.lastRegion = LLUUID::null; - if (ent->mGlobalPos != LLVector3d(0.0, 0.0, 0.0)) + if (entry->mGlobalPos != LLVector3d(0.0, 0.0, 0.0)) { - LLViewerRegion* lastRegion = world->getRegionFromPosGlobal(ent->mGlobalPos); + LLViewerRegion* lastRegion = world->getRegionFromPosGlobal(entry->mGlobalPos); if (lastRegion) { rf.lastRegion = lastRegion->getRegionID(); } } - mLastRadarSweep[ent->mID] = rf; + mLastRadarSweep[entry->mID] = rf; } // @@ -857,7 +845,7 @@ FSRadarEntry* FSRadar::getEntry(const LLUUID& avatar_id) entry_map_t::iterator found = mEntryList.find(avatar_id); if (found == mEntryList.end()) { - return NULL; + return nullptr; } return found->second; } @@ -1026,7 +1014,7 @@ void FSRadar::updateTracking() } } -void FSRadar::zoomAvatar(const LLUUID& avatar_id, const std::string& name) +void FSRadar::zoomAvatar(const LLUUID& avatar_id, std::string_view name) { if (LLAvatarActions::canZoomIn(avatar_id)) { @@ -1035,7 +1023,7 @@ void FSRadar::zoomAvatar(const LLUUID& avatar_id, const std::string& name) else { LLStringUtil::format_map_t args; - args["AVATARNAME"] = name.c_str(); + args["AVATARNAME"] = static_cast(name); report_to_nearby_chat(LLTrans::getString("camera_no_focus", args)); } } @@ -1060,9 +1048,17 @@ void FSRadar::updateName(const LLUUID& avatar_id) void FSRadar::updateAgeAlertCheck() { - const entry_map_t::iterator it_end = mEntryList.end(); - for (entry_map_t::iterator it = mEntryList.begin(); it != it_end; ++it) + for (auto& [av_id, entry] : mEntryList) { - it->second->checkAge(); + entry->checkAge(); + } +} + +void FSRadar::updateNotes(const LLUUID& avatar_id, std::string_view notes) +{ + FSRadarEntry* entry = getEntry(avatar_id); + if (entry) + { + entry->setNotes(notes); } } diff --git a/indra/newview/fsradar.h b/indra/newview/fsradar.h index 44356924e8..90ccdcd676 100644 --- a/indra/newview/fsradar.h +++ b/indra/newview/fsradar.h @@ -67,11 +67,12 @@ public: entry_map_t getRadarList() { return mEntryList; } void startTracking(const LLUUID& avatar_id); - void zoomAvatar(const LLUUID& avatar_id, const std::string& name); + void zoomAvatar(const LLUUID& avatar_id, std::string_view name); void teleportToAvatar(const LLUUID& targetAv); void requestRadarChannelAlertSync(); void updateNames(); void updateName(const LLUUID& avatar_id); + void updateNotes(const LLUUID& avatar_id, std::string_view notes); static void onRadarNameFmtClicked(const LLSD& userdata); static bool radarNameFmtCheck(const LLSD& userdata); @@ -112,7 +113,7 @@ private: void updateRadarList(); void updateTracking(); void checkTracking(); - void radarAlertMsg(const LLUUID& agent_id, const LLAvatarName& av_name, const std::string& postMsg); + void radarAlertMsg(const LLUUID& agent_id, const LLAvatarName& av_name, std::string_view postMsg); void updateAgeAlertCheck(); Updater* mRadarListUpdater; diff --git a/indra/newview/fsradarentry.cpp b/indra/newview/fsradarentry.cpp index ef911faa58..9382b85e64 100644 --- a/indra/newview/fsradarentry.cpp +++ b/indra/newview/fsradarentry.cpp @@ -39,12 +39,12 @@ FSRadarEntry::FSRadarEntry(const LLUUID& avid) mUserName(LLStringUtil::null), mDisplayName(LLStringUtil::null), mRange(0.f), - mFirstSeen(time(NULL)), + mFirstSeen(time(nullptr)), mGlobalPos(LLVector3d(0.0, 0.0, 0.0)), mRegion(LLUUID::null), mStatus(0), mZOffset(0.f), - mLastZOffsetTime(time(NULL)), + mLastZOffsetTime(time(nullptr)), mAge(-1), mIsLinden(false), mIgnore(false), @@ -126,8 +126,7 @@ void FSRadarEntry::processProperties(void* data, EAvatarProcessorType type) LLAvatarNotes* avatar_notes = static_cast(data); if (avatar_notes && avatar_notes->agent_id == gAgentID && avatar_notes->target_id == mID && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) { - mNotes = avatar_notes->notes; - LLStringUtil::trim(mNotes); + setNotes(avatar_notes->notes); } } } @@ -191,3 +190,9 @@ void FSRadarEntry::checkAge() mAgeAlertPerformed = true; } } + +void FSRadarEntry::setNotes(std::string_view notes) +{ + mNotes = notes; + LLStringUtil::trim(mNotes); +} diff --git a/indra/newview/fsradarentry.h b/indra/newview/fsradarentry.h index 30c1599378..5248803c75 100644 --- a/indra/newview/fsradarentry.h +++ b/indra/newview/fsradarentry.h @@ -63,6 +63,8 @@ public: static std::string getRadarName(const LLAvatarName& av_name); + void setNotes(std::string_view notes); + private: void updateName(); void onAvatarNameCache(const LLUUID& av_id, const LLAvatarName& av_name); diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp index e09527a34b..d3f988d715 100644 --- a/indra/newview/llaccountingcostmanager.cpp +++ b/indra/newview/llaccountingcostmanager.cpp @@ -96,11 +96,7 @@ void LLAccountingCostManager::accountingCostCoro(std::string url, LLSD dataToPost = LLSD::emptyMap(); dataToPost[keystr.c_str()] = objectList; - LLAccountingCostObserver* observer = observerHandle.get(); - LLUUID transactionId = observer->getTransactionID(); - observer = NULL; - - + LLAccountingCostObserver* observer = NULL; LLSD results = httpAdapter->postAndSuspend(httpRequest, url, dataToPost); diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm index aa801d6ae6..55e35c8ef7 100644 --- a/indra/newview/llappdelegate-objc.mm +++ b/indra/newview/llappdelegate-objc.mm @@ -46,6 +46,7 @@ - (void)dealloc { + [currentInputLanguage release]; [super dealloc]; } @@ -199,17 +200,17 @@ - (bool) romanScript { - // How to add support for new languages with the input window: - // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.) - NSArray *nonRomanScript = [[NSArray alloc] initWithObjects:@"ja", @"ko", @"zh-Hant", @"zh-Hans", nil]; - bool ret = true; - if ([nonRomanScript containsObject:currentInputLanguage]) - { - ret = false; + @autoreleasepool { + // How to add support for new languages with the input window: + // Simply append this array with the language code (ja for japanese, ko for korean, zh for chinese, etc.) + NSArray* nonRomanScript = @[@"ja", @"ko", @"zh-Hant", @"zh-Hans"]; + if ([nonRomanScript containsObject:currentInputLanguage]) + { + return false; + } } - [nonRomanScript release]; - return ret; + return true; } #if defined(LL_BUGSPLAT) diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp index 5a77e44399..771d7398da 100644 --- a/indra/newview/llappearancemgr.cpp +++ b/indra/newview/llappearancemgr.cpp @@ -4504,7 +4504,7 @@ void LLAppearanceMgr::makeNewOutfitLinks(const std::string& new_folder_name, boo // existence of AIS as an indicator the fix is present. Does // not actually use AIS to create the category. inventory_func_type func = boost::bind(&LLAppearanceMgr::onOutfitFolderCreated,this,_1,show_panel); - LLUUID folder_id = gInventory.createNewCategory( + gInventory.createNewCategory( parent_id, LLFolderType::FT_OUTFIT, new_folder_name, diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 691589d39d..2a6ccd1149 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -150,6 +150,10 @@ #include "vlc/libvlc_version.h" #endif // LL_LINUX +#if LL_DARWIN +#include "llwindowmacosx.h" +#endif + // Third party library includes #include #include @@ -638,6 +642,7 @@ static void settings_to_globals() LLWorldMapView::setScaleSetting(gSavedSettings.getF32("MapScale")); #if LL_DARWIN + LLWindowMacOSX::sUseMultGL = gSavedSettings.getBOOL("RenderAppleUseMultGL"); gHiDPISupport = gSavedSettings.getBOOL("RenderHiDPI"); #endif } @@ -2025,7 +2030,8 @@ bool LLAppViewer::cleanup() { if (!isSecondInstance()) { - LLSceneMonitor::instance().dumpToFile(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv")); + std::string dump_path = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv"); + LLSceneMonitor::instance().dumpToFile(dump_path); } LLSceneMonitor::deleteSingleton(); } diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp index 275f17b02a..293c9d60a1 100644 --- a/indra/newview/llavatarrenderinfoaccountant.cpp +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -364,11 +364,10 @@ void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regi } } -// static // Called every frame - send render weight requests to every region void LLAvatarRenderInfoAccountant::idle() { - if (mRenderInfoScanTimer.hasExpired()) + if (mRenderInfoScanTimer.hasExpired() && !LLApp::isExiting()) { LL_DEBUGS("AvatarRenderInfo") << "Scanning regions for render info updates" << LL_ENDL; diff --git a/indra/newview/llbuycurrencyhtml.cpp b/indra/newview/llbuycurrencyhtml.cpp index c1099ffa23..d2f191036a 100644 --- a/indra/newview/llbuycurrencyhtml.cpp +++ b/indra/newview/llbuycurrencyhtml.cpp @@ -43,7 +43,7 @@ class LLBuyCurrencyHTMLHandler : { public: // requests will be throttled from a non-trusted browser - LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_ALLOW ) {} + LLBuyCurrencyHTMLHandler() : LLCommandHandler( "buycurrencyhtml", UNTRUSTED_THROTTLE) {} bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 51d4e94430..ad9ae12ced 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -723,8 +723,7 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) { if(mBuddyInfo.find(agent_id) != mBuddyInfo.end()) { - if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS) - && !gAgent.isDoNotDisturb()) + if (((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS)) { LLSD args; // Always show complete name in rights dialogs @@ -803,19 +802,18 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) // we were tracking someone who went offline deleteTrackingData(); } - // } [FIRE-32324] least invasive change move this brace after the if. LL fix should follow sometime soon - //[FIX FIRE-3522 : SJ] Notify Online/Offline to Nearby Chat even if chat_notify isnt true - - // Attempt to speed up things a little - // if(chat_notify||LGGContactSets::getInstance()->notifyForFriend(agent_id)||gSavedSettings.getBOOL("OnlineOfflinetoNearbyChat")) - static LLCachedControl OnlineOfflinetoNearbyChat(gSavedSettings, "OnlineOfflinetoNearbyChat"); - if(chat_notify || LGGContactSets::getInstance()->notifyForFriend(agent_id) || OnlineOfflinetoNearbyChat) - // - { - // Look up the name of this agent for the notification - LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload)); + + //[FIX FIRE-3522 : SJ] Notify Online/Offline to Nearby Chat even if chat_notify isnt true + // Attempt to speed up things a little + // if(chat_notify||LGGContactSets::getInstance()->notifyForFriend(agent_id)||gSavedSettings.getBOOL("OnlineOfflinetoNearbyChat")) + static LLCachedControl OnlineOfflinetoNearbyChat(gSavedSettings, "OnlineOfflinetoNearbyChat"); + if(chat_notify || LGGContactSets::getInstance()->notifyForFriend(agent_id) || OnlineOfflinetoNearbyChat) + // + { + // Look up the name of this agent for the notification + LLAvatarNameCache::get(agent_id,boost::bind(&on_avatar_name_cache_notify,_1, _2, online, payload)); + } } - } // [FIRE-32324] least invasive change move this brace after the if mModifyMask |= LLFriendObserver::ONLINE; instance().notifyObservers(); diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 293c92cc49..6cd03db6f7 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -155,6 +155,18 @@ public: { mAvatarNameCacheConnection.disconnect(); } + auto menu = mPopupMenuHandleAvatar.get(); + if (menu) + { + menu->die(); + mPopupMenuHandleAvatar.markDead(); + } + menu = mPopupMenuHandleObject.get(); + if (menu) + { + menu->die(); + mPopupMenuHandleObject.markDead(); + } } BOOL handleMouseUp(S32 x, S32 y, MASK mask) @@ -587,36 +599,6 @@ public: BOOL postBuild() { - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; - LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable; - - registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); - registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2)); - registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2)); - registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2)); - registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); - registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); - - LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if (menu) - { - mPopupMenuHandleAvatar = menu->getHandle(); - } - else - { - LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL; - } - - menu = LLUICtrlFactory::getInstance()->createFromFile("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - if (menu) - { - mPopupMenuHandleObject = menu->getHandle(); - } - else - { - LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL; - } - setDoubleClickCallback(boost::bind(&LLChatHistoryHeader::showInspector, this)); setMouseEnterCallback(boost::bind(&LLChatHistoryHeader::showInfoCtrl, this)); @@ -937,13 +919,53 @@ protected: void showObjectContextMenu(S32 x,S32 y) { LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleObject.get(); - if(menu) + if (!menu) + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable; + registrar.add("ObjectIcon.Action", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemClicked, this, _2)); + registrar_enable.add("ObjectIcon.Visible", boost::bind(&LLChatHistoryHeader::onObjectIconContextMenuItemVisible, this, _2)); + + menu = LLUICtrlFactory::getInstance()->createFromFile("menu_object_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandleObject = menu->getHandle(); + menu->updateParent(LLMenuGL::sMenuContainer); + LLMenuGL::showPopup(this, menu, x, y); + } + else + { + LL_WARNS() << " Failed to create menu_object_icon.xml" << LL_ENDL; + } + } + else + { LLMenuGL::showPopup(this, menu, x, y); + } } void showAvatarContextMenu(S32 x,S32 y) { LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandleAvatar.get(); + if (!menu) + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; + LLUICtrl::EnableCallbackRegistry::ScopedRegistrar registrar_enable; + registrar.add("AvatarIcon.Action", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemClicked, this, _2)); + registrar_enable.add("AvatarIcon.Check", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemChecked, this, _2)); + registrar_enable.add("AvatarIcon.Enable", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemEnabled, this, _2)); + registrar_enable.add("AvatarIcon.Visible", boost::bind(&LLChatHistoryHeader::onAvatarIconContextMenuItemVisible, this, _2)); + + menu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_icon.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandleAvatar = menu->getHandle(); + } + else + { + LL_WARNS() << " Failed to create menu_avatar_icon.xml" << LL_ENDL; + } + } if(menu) { @@ -1142,10 +1164,7 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) LLSD LLChatHistory::getValue() const { - LLSD* text=new LLSD(); - text->assign(mEditor->getText()); - return *text; - + return LLSD(mEditor->getText()); } LLChatHistory::~LLChatHistory() diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp index ae54043cba..9d3ad0effc 100644 --- a/indra/newview/llchiclet.cpp +++ b/indra/newview/llchiclet.cpp @@ -98,7 +98,6 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p) , mMaxDisplayedCount(p.max_displayed_count) , mIsNewMessagesState(false) , mFlashToLitTimer(NULL) - , mContextMenu(NULL) { LLButton::Params button_params = p.button; mButton = LLUICtrlFactory::create(button_params); @@ -110,6 +109,12 @@ LLSysWellChiclet::LLSysWellChiclet(const Params& p) LLSysWellChiclet::~LLSysWellChiclet() { mFlashToLitTimer->unset(); + LLContextMenu* menu = static_cast(mContextMenuHandle.get()); + if (menu) + { + menu->die(); + mContextMenuHandle.markDead(); + } } void LLSysWellChiclet::setCounter(S32 counter) @@ -176,14 +181,16 @@ void LLSysWellChiclet::updateWidget(bool is_window_empty) // virtual BOOL LLSysWellChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if(!mContextMenu) + LLContextMenu* menu_avatar = mContextMenuHandle.get(); + if(!menu_avatar) { createMenu(); + menu_avatar = mContextMenuHandle.get(); } - if (mContextMenu) + if (menu_avatar) { - mContextMenu->show(x, y); - LLMenuGL::showPopup(this, mContextMenu, x, y); + menu_avatar->show(x, y); + LLMenuGL::showPopup(this, menu_avatar, x, y); } return TRUE; } @@ -207,6 +214,13 @@ LLIMWellChiclet::LLIMWellChiclet(const Params& p) LLIMWellChiclet::~LLIMWellChiclet() { + LLContextMenu* menu = static_cast(mContextMenuHandle.get()); + if (menu) + { + menu->die(); + mContextMenuHandle.markDead(); + } + LLIMWellWindow* im_well_window = LLIMWellWindow::findInstance(); if (im_well_window) { @@ -237,7 +251,7 @@ bool LLIMWellChiclet::enableMenuItem(const LLSD& user_data) void LLIMWellChiclet::createMenu() { - if(mContextMenu) + if(mContextMenuHandle.get()) { LL_WARNS() << "Menu already exists" << LL_ENDL; return; @@ -251,10 +265,14 @@ void LLIMWellChiclet::createMenu() enable_registrar.add("IMWellChicletMenu.EnableItem", boost::bind(&LLIMWellChiclet::enableMenuItem, this, _2)); - mContextMenu = LLUICtrlFactory::getInstance()->createFromFile + LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile ("menu_fs_im_well_button.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mContextMenuHandle = menu->getHandle(); + } } void LLIMWellChiclet::messageCountChanged(const LLSD& session_data) @@ -358,7 +376,7 @@ bool LLNotificationChiclet::enableMenuItem(const LLSD& user_data) void LLNotificationChiclet::createMenu() { - if(mContextMenu) + if(mContextMenuHandle.get()) { LL_WARNS() << "Menu already exists" << LL_ENDL; return; @@ -373,10 +391,14 @@ void LLNotificationChiclet::createMenu() boost::bind(&LLNotificationChiclet::enableMenuItem, this, _2)); llassert(LLMenuGL::sMenuContainer != NULL); - mContextMenu = LLUICtrlFactory::getInstance()->createFromFile + LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile ("menu_notification_well_button.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mContextMenuHandle = menu->getHandle(); + } } /*virtual*/ @@ -492,12 +514,21 @@ LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p) , mCounterCtrl(NULL) // [FS communication UI] , mChicletButton(NULL) -, mPopupMenu(NULL) { // [FS communication UI] enableCounterControl(p.enable_counter); } +LLIMChiclet::~LLIMChiclet() +{ + auto menu = mPopupMenuHandle.get(); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } +} + /* virtual*/ BOOL LLIMChiclet::postBuild() { @@ -688,16 +719,18 @@ LLIMChiclet::EType LLIMChiclet::getIMSessionType(const LLUUID& session_id) BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if(!mPopupMenu) + auto menu = static_cast(mPopupMenuHandle.get()); + if(!menu) { createPopupMenu(); + menu = static_cast(mPopupMenuHandle.get()); } - if (mPopupMenu) + if (menu) { updateMenuItems(); - mPopupMenu->arrangeAndClear(); - LLMenuGL::showPopup(this, mPopupMenu, x, y); + menu->arrangeAndClear(); + LLMenuGL::showPopup(this, menu, x, y); } return TRUE; @@ -705,15 +738,16 @@ BOOL LLIMChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask) void LLIMChiclet::hidePopupMenu() { - if (mPopupMenu) + auto menu = mPopupMenuHandle.get(); + if (menu) { - mPopupMenu->setVisible(FALSE); + menu->setVisible(FALSE); } } bool LLIMChiclet::canCreateMenu() { - if(mPopupMenu) + if(mPopupMenuHandle.get()) { LL_WARNS() << "Menu already exists" << LL_ENDL; return false; @@ -784,17 +818,17 @@ void LLIMP2PChiclet::setOtherParticipantId(const LLUUID& other_participant_id) void LLIMP2PChiclet::updateMenuItems() { - if(!mPopupMenu) + if(!mPopupMenuHandle.get()) return; if(getSessionId().isNull()) return; FSFloaterIM* open_im_floater = FSFloaterIM::findInstance(getSessionId()); bool open_window_exists = open_im_floater && open_im_floater->getVisible(); - mPopupMenu->getChild("Send IM")->setEnabled(!open_window_exists); + mPopupMenuHandle.get()->getChild("Send IM")->setEnabled(!open_window_exists); bool is_friend = LLAvatarActions::isFriend(getOtherParticipantId()); - mPopupMenu->getChild("Add Friend")->setEnabled(!is_friend); + mPopupMenuHandle.get()->getChild("Add Friend")->setEnabled(!is_friend); } void LLIMP2PChiclet::createPopupMenu() @@ -805,8 +839,12 @@ void LLIMP2PChiclet::createPopupMenu() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("IMChicletMenu.Action", boost::bind(&LLIMP2PChiclet::onMenuItemClicked, this, _2)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile ("menu_fs_imchiclet_p2p.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandle = menu->getHandle(); + } } void LLIMP2PChiclet::onMenuItemClicked(const LLSD& user_data) @@ -925,8 +963,12 @@ void LLAdHocChiclet::createPopupMenu() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("IMChicletMenu.Action", boost::bind(&LLAdHocChiclet::onMenuItemClicked, this, _2)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile + auto menu = LLUICtrlFactory::getInstance()->createFromFile ("menu_fs_imchiclet_adhoc.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandle = menu->getHandle(); + } } void LLAdHocChiclet::onMenuItemClicked(const LLSD& user_data) @@ -1060,14 +1102,14 @@ void LLIMGroupChiclet::changed(LLGroupChange gc) void LLIMGroupChiclet::updateMenuItems() { - if(!mPopupMenu) + if(!mPopupMenuHandle.get()) return; if(getSessionId().isNull()) return; FSFloaterIM* open_im_floater = FSFloaterIM::findInstance(getSessionId()); bool open_window_exists = open_im_floater && open_im_floater->getVisible(); - mPopupMenu->getChild("Chat")->setEnabled(!open_window_exists); + mPopupMenuHandle.get()->getChild("Chat")->setEnabled(!open_window_exists); } void LLIMGroupChiclet::createPopupMenu() @@ -1078,8 +1120,12 @@ void LLIMGroupChiclet::createPopupMenu() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("IMChicletMenu.Action", boost::bind(&LLIMGroupChiclet::onMenuItemClicked, this, _2)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile + auto menu = LLUICtrlFactory::getInstance()->createFromFile ("menu_fs_imchiclet_group.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandle = menu->getHandle(); + } } void LLIMGroupChiclet::onMenuItemClicked(const LLSD& user_data) @@ -2010,8 +2056,13 @@ void LLScriptChiclet::createPopupMenu() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("ScriptChiclet.Action", boost::bind(&LLScriptChiclet::onMenuItemClicked, this, _2)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile ("menu_script_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandle = menu->getHandle(); + } + } ////////////////////////////////////////////////////////////////////////// @@ -2095,8 +2146,12 @@ void LLInvOfferChiclet::createPopupMenu() LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; registrar.add("InvOfferChiclet.Action", boost::bind(&LLInvOfferChiclet::onMenuItemClicked, this, _2)); - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile ("menu_inv_offer_chiclet.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mPopupMenuHandle = menu->getHandle(); + } } // EOF diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h index 598678f6ea..478e02a1ef 100644 --- a/indra/newview/llchiclet.h +++ b/indra/newview/llchiclet.h @@ -325,7 +325,7 @@ public: {}; - virtual ~LLIMChiclet() {}; + virtual ~LLIMChiclet(); /** * It is used for default setting up of chicklet:click handler, etc. @@ -456,7 +456,7 @@ protected: bool canCreateMenu(); - LLMenuGL* mPopupMenu; + LLHandle mPopupMenuHandle; bool mShowSpeaker; bool mCounterEnabled; @@ -633,6 +633,8 @@ public: */ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } + /*virtual*/ ~LLIMP2PChiclet() {}; + protected: LLIMP2PChiclet(const Params& p); friend class LLUICtrlFactory; @@ -705,6 +707,8 @@ public: */ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); } + /*virtual*/ ~LLAdHocChiclet() {}; + protected: LLAdHocChiclet(const Params& p); friend class LLUICtrlFactory; @@ -884,7 +888,7 @@ protected: bool mIsNewMessagesState; LLFlashTimer* mFlashToLitTimer; - LLContextMenu* mContextMenu; + LLHandle mContextMenuHandle; }; class LLNotificationChiclet : public LLSysWellChiclet diff --git a/indra/newview/llcommandhandler.cpp b/indra/newview/llcommandhandler.cpp index 23e2271eae..74f37961c7 100644 --- a/indra/newview/llcommandhandler.cpp +++ b/indra/newview/llcommandhandler.cpp @@ -39,6 +39,7 @@ #define THROTTLE_PERIOD 5 // required seconds between throttled commands static LLCommandDispatcherListener sCommandDispatcherListener; +const std::string LLCommandHandler::NAV_TYPE_CLICKED = "clicked"; //--------------------------------------------------------------------------- // Underlying registry for command handlers, not directly accessible. @@ -64,6 +65,9 @@ public: bool trusted_browser); private: + void notifySlurlBlocked(); + void notifySlurlThrottled(); + friend LLSD LLCommandDispatcher::enumerate(); std::map mMap; }; @@ -96,8 +100,6 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, const std::string& nav_type, bool trusted_browser) { - static bool slurl_blocked = false; - static bool slurl_throttled = false; static F64 last_throttle_time = 0.0; F64 cur_time = 0.0; std::map::iterator it = mMap.find(cmd); @@ -115,44 +117,45 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, // block request from external browser, but report as // "handled" because it was well formatted. LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; - if (! slurl_blocked) - { - if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) - { - // Note: commands can arrive before we initialize everything we need for Notification. - LLNotificationsUtil::add("BlockedSLURL"); - } - slurl_blocked = true; - } + notifySlurlBlocked(); return true; + case LLCommandHandler::UNTRUSTED_CLICK_ONLY: + if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED + && info.mHandler->canHandleUntrusted(params, query_map, web, nav_type)) + { + break; + } + LL_WARNS_ONCE("SLURL") << "Blocked SLURL click-only command " << cmd << " from untrusted browser" << LL_ENDL; + notifySlurlBlocked(); + return true; + case LLCommandHandler::UNTRUSTED_THROTTLE: - // if users actually click on a link, we don't need to throttle it - // (throttling mechanism is used to prevent an avalanche of clicks via - // javascript - if ( nav_type == "clicked" ) - { - break; - } //skip initial request from external browser before STATE_BROWSER_INIT if (LLStartUp::getStartupState() == STATE_FIRST) { return true; } + if (!info.mHandler->canHandleUntrusted(params, query_map, web, nav_type)) + { + LL_WARNS_ONCE("SLURL") << "Blocked SLURL command from untrusted browser" << LL_ENDL; + notifySlurlBlocked(); + return true; + } + // if users actually click on a link, we don't need to throttle it + // (throttling mechanism is used to prevent an avalanche of clicks via + // javascript + if (nav_type == LLCommandHandler::NAV_TYPE_CLICKED) + { + break; + } cur_time = LLTimer::getElapsedSeconds(); if (cur_time < last_throttle_time + THROTTLE_PERIOD) { // block request from external browser if it happened // within THROTTLE_PERIOD seconds of the last command LL_WARNS_ONCE("SLURL") << "Throttled SLURL command from untrusted browser" << LL_ENDL; - if (! slurl_throttled) - { - if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) - { - LLNotificationsUtil::add("ThrottledSLURL"); - } - slurl_throttled = true; - } + notifySlurlThrottled(); return true; } last_throttle_time = cur_time; @@ -163,6 +166,34 @@ bool LLCommandHandlerRegistry::dispatch(const std::string& cmd, return info.mHandler->handle(params, query_map, web); } +void LLCommandHandlerRegistry::notifySlurlBlocked() +{ + static bool slurl_blocked = false; + if (!slurl_blocked) + { + if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) + { + // Note: commands can arrive before we initialize everything we need for Notification. + LLNotificationsUtil::add("BlockedSLURL"); + } + slurl_blocked = true; + } +} + +void LLCommandHandlerRegistry::notifySlurlThrottled() +{ + static bool slurl_throttled = false; + if (!slurl_throttled) + { + if (LLStartUp::getStartupState() >= STATE_BROWSER_INIT) + { + // Note: commands can arrive before we initialize everything we need for Notification. + LLNotificationsUtil::add("ThrottledSLURL"); + } + slurl_throttled = true; + } +} + //--------------------------------------------------------------------------- // Automatic registration of commands, runs before main() //--------------------------------------------------------------------------- @@ -230,6 +261,7 @@ symbol_info symbols[] = { ent(LLCommandHandler::UNTRUSTED_ALLOW), // allow commands from untrusted browsers ent(LLCommandHandler::UNTRUSTED_BLOCK), // ignore commands from untrusted browsers + ent(LLCommandHandler::UNTRUSTED_CLICK_ONLY), // allow untrusted, but only if clicked ent(LLCommandHandler::UNTRUSTED_THROTTLE) // allow untrusted, but only a few per min. }; diff --git a/indra/newview/llcommandhandler.h b/indra/newview/llcommandhandler.h index 1e0895565a..763e3ee51f 100644 --- a/indra/newview/llcommandhandler.h +++ b/indra/newview/llcommandhandler.h @@ -65,9 +65,12 @@ public: { UNTRUSTED_ALLOW, // allow commands from untrusted browsers UNTRUSTED_BLOCK, // ignore commands from untrusted browsers + UNTRUSTED_CLICK_ONLY, // allow untrusted, but only if clicked UNTRUSTED_THROTTLE // allow untrusted, but only a few per min. }; + static const std::string NAV_TYPE_CLICKED; + LLCommandHandler(const char* command, EUntrustedAccess untrusted_access); // Automatically registers object to get called when // command is executed. All commands can be processed @@ -76,6 +79,13 @@ public: virtual ~LLCommandHandler(); + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { return true; } + virtual bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) = 0; diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 07cdecf920..4bf35003d2 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -1114,28 +1114,23 @@ void LLFloaterCompileQueue::finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID // This is the callback after the script has been processed by preproc // static -void LLFloaterCompileQueue::scriptPreprocComplete(const LLUUID& asset_id, LLScriptQueueData* data, LLAssetType::EType type, const std::string& script_text) +void LLFloaterCompileQueue::scriptPreprocComplete(LLScriptQueueData* data, LLAssetType::EType type, const std::string& script_text) { LL_INFOS() << "LLFloaterCompileQueue::scriptPreprocComplete()" << LL_ENDL; if (!data) { return; } + LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance("compile_queue", data->mQueueID); - if (queue) { - std::string filename; - std::string uuid_str; - asset_id.toString(uuid_str); - filename = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str) + llformat(".%s",LLAssetType::lookup(type)); - - const bool is_running = true; + constexpr bool is_running{ true }; LLViewerObject* object = gObjectList.findObject(data->mTaskId); if (object) { - std::string scriptName = data->mItem->getName(); - std::string url = object->getRegion()->getCapability("UpdateScriptTask"); + const std::string scriptName = data->mItem->getName(); + const std::string url = object->getRegion() ? object->getRegion()->getCapability("UpdateScriptTask") : std::string(); if (!url.empty()) { queue->addProcessingMessage("CompileQueuePreprocessingComplete", LLSD().with("SCRIPT", scriptName)); @@ -1166,7 +1161,7 @@ void LLFloaterCompileQueue::scriptPreprocComplete(const LLUUID& asset_id, LLScri } // static -void LLFloaterCompileQueue::scriptLogMessage(LLScriptQueueData* data, std::string message) +void LLFloaterCompileQueue::scriptLogMessage(LLScriptQueueData* data, std::string_view message) { if (!data) { @@ -1175,7 +1170,7 @@ void LLFloaterCompileQueue::scriptLogMessage(LLScriptQueueData* data, std::strin LLFloaterCompileQueue* queue = LLFloaterReg::findTypedInstance("compile_queue", data->mQueueID); if (queue) { - queue->addStringMessage(message); + queue->addStringMessage(static_cast(message)); } } // diff --git a/indra/newview/llcompilequeue.h b/indra/newview/llcompilequeue.h index edd7900ec4..416f316fc3 100644 --- a/indra/newview/llcompilequeue.h +++ b/indra/newview/llcompilequeue.h @@ -150,8 +150,8 @@ public: // [LSL PreProc] static void finishLSLUpload(LLUUID itemId, LLUUID taskId, LLUUID newAssetId, LLSD response, std::string scriptName, LLUUID queueId); - static void scriptPreprocComplete(const LLUUID& asset_id, LLScriptQueueData* data, LLAssetType::EType type, const std::string& script_text); - static void scriptLogMessage(LLScriptQueueData* data, std::string message); + static void scriptPreprocComplete(LLScriptQueueData* data, LLAssetType::EType type, const std::string& script_text); + static void scriptLogMessage(LLScriptQueueData* data, std::string_view message); protected: LLFloaterCompileQueue(const LLSD& key); virtual ~LLFloaterCompileQueue(); diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp index 2e287bf8b5..3505dce54f 100644 --- a/indra/newview/llenvironment.cpp +++ b/indra/newview/llenvironment.cpp @@ -691,7 +691,6 @@ namespace if (!injection->mBlendIn) mix = 1.0 - mix; stringset_t dummy; - LLUUID cloud_noise_id = getCloudNoiseTextureId(); F64 value = this->mSettings[injection->mKeyName].asReal(); if (this->getCloudNoiseTextureId().isNull()) { @@ -3231,7 +3230,7 @@ bool LLEnvironment::loadFromSettings() LL_INFOS("ENVIRONMENT") << "Unable to open previous session environment file " << user_filepath << LL_ENDL; } - if (!env_data.isMap() || env_data.emptyMap()) + if (!env_data.isMap() || (env_data.size() == 0)) { LL_DEBUGS("ENVIRONMENT") << "Empty map loaded from: " << user_filepath << LL_ENDL; return false; diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index f90606e7e2..7f69a15b0a 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -671,9 +671,9 @@ BOOL LLFilePicker::getSaveFileModeless(ESaveFilter filter, #elif LL_DARWIN -std::vector* LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) +std::unique_ptr> LLFilePicker::navOpenFilterProc(ELoadFilter filter) //(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode) { - std::vector *allowedv = new std::vector< std::string >; + std::unique_ptr> allowedv(new std::vector< std::string >); switch(filter) { case FFLOAD_ALL: @@ -758,9 +758,9 @@ bool LLFilePicker::doNavChooseDialog(ELoadFilter filter) gViewerWindow->getWindow()->beforeDialog(); - std::vector *allowed_types=navOpenFilterProc(filter); + std::unique_ptr> allowed_types = navOpenFilterProc(filter); - std::vector *filev = doLoadDialog(allowed_types, + std::unique_ptr> filev = doLoadDialog(allowed_types.get(), mPickOptions); gViewerWindow->getWindow()->afterDialog(); @@ -922,7 +922,7 @@ bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filena gViewerWindow->getWindow()->beforeDialog(); // Run the dialog - std::string* filev = doSaveDialog(&namestring, + std::unique_ptr filev = doSaveDialog(&namestring, &type, &creator, &extension, diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index a302be1851..2ae409f8ee 100644 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -193,7 +193,7 @@ private: void (*callback)(bool, std::vector&, void*), void *userdata); bool doNavSaveDialog(ESaveFilter filter, const std::string& filename); - std::vector* navOpenFilterProc(ELoadFilter filter); + std::unique_ptr> navOpenFilterProc(ELoadFilter filter); bool doNavSaveDialogModeless(ESaveFilter filter, const std::string& filename, void (*callback)(bool, std::string&, void*), diff --git a/indra/newview/llfilepicker_mac.h b/indra/newview/llfilepicker_mac.h index 2ec9d0c4e6..367c792969 100644 --- a/indra/newview/llfilepicker_mac.h +++ b/indra/newview/llfilepicker_mac.h @@ -39,7 +39,7 @@ #include //void modelessPicker(); -std::vector* doLoadDialog(const std::vector* allowed_types, +std::unique_ptr> doLoadDialog(const std::vector* allowed_types, unsigned int flags); void doLoadDialogModeless(const std::vector* allowed_types, @@ -47,7 +47,7 @@ void doLoadDialogModeless(const std::vector* allowed_types, void (*callback)(bool, std::vector&, void*), void *userdata); -std::string* doSaveDialog(const std::string* file, +std::unique_ptr doSaveDialog(const std::string* file, const std::string* type, const std::string* creator, const std::string* extension, diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm index aaa3df17af..4537235204 100644 --- a/indra/newview/llfilepicker_mac.mm +++ b/indra/newview/llfilepicker_mac.mm @@ -72,17 +72,17 @@ NSOpenPanel *init_panel(const std::vector* allowed_types, unsigned return panel; } -std::vector* doLoadDialog(const std::vector* allowed_types, +std::unique_ptr> doLoadDialog(const std::vector* allowed_types, unsigned int flags) { + std::unique_ptr> outfiles; + int result; NSOpenPanel *panel = init_panel(allowed_types,flags); result = [panel runModal]; - std::vector* outfiles = NULL; - if (result == NSOKButton) { NSArray *filesToOpen = [panel URLs]; @@ -90,7 +90,7 @@ std::vector* doLoadDialog(const std::vector* allowed_t if (count > 0) { - outfiles = new std::vector; + outfiles.reset(new std::vector); } for (i=0; i* allowed_types, }]; } -std::string* doSaveDialog(const std::string* file, +std::unique_ptr doSaveDialog(const std::string* file, const std::string* type, const std::string* creator, const std::string* extension, unsigned int flags) { + std::unique_ptr outfile; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Fix mem leak by Cinder Roxley NSSavePanel *panel = [NSSavePanel savePanel]; @@ -161,17 +163,16 @@ std::string* doSaveDialog(const std::string* file, [panel setAllowedFileTypes:fileType]; NSString *fileName = [NSString stringWithCString:file->c_str() encoding:[NSString defaultCStringEncoding]]; - std::string *outfile = NULL; NSURL* url = [NSURL fileURLWithPath:fileName]; [panel setNameFieldStringValue: fileName]; [panel setDirectoryURL: url]; - [panel setNameFieldStringValue: fileName]; // Populate filename in the save panel + [panel setNameFieldStringValue: fileName]; // Populate filename in the save panel if([panel runModal] == NSFileHandlingPanelOKButton) { NSURL* url = [panel URL]; NSString* p = [url path]; - outfile = new std::string( [p UTF8String] ); + outfile.reset(new std::string([p UTF8String])); // write the file } [pool release]; // Fix mem leak by Cinder Roxley diff --git a/indra/newview/llfloater360capture.cpp b/indra/newview/llfloater360capture.cpp index 8c92bc643a..cfa742cd38 100644 --- a/indra/newview/llfloater360capture.cpp +++ b/indra/newview/llfloater360capture.cpp @@ -553,7 +553,8 @@ void LLFloater360Capture::capture360Images() // We need to convert from the angle getYaw() gives us into something // the XMP data field wants (N=0, E=90, S=180, W= 270 etc.) mInitialHeadingDeg = (360 + 90 - (int)(camera->getYaw() * RAD_TO_DEG)) % 360; - LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg) << LL_ENDL; + LL_INFOS("360Capture") << "Recording a heading of " << (int)(mInitialHeadingDeg) + << " Image size: " << (S32)mSourceImageSize << LL_ENDL; // camera constants for the square, cube map capture image camera->setAspect(1.0); // must set aspect ratio first to avoid undesirable clamping of vertical FoV @@ -603,6 +604,9 @@ void LLFloater360Capture::capture360Images() // for each of the 6 directions we shoot... for (int i = 0; i < 6; i++) { + LLAppViewer::instance()->pauseMainloopTimeout(); + LLViewerStats::instance().getRecording().stop(); + // these buffers are where the raw, captured pixels are stored and // the first time we use them, we have to make a new one if (mRawImages[i] == nullptr) @@ -640,8 +644,10 @@ void LLFloater360Capture::capture360Images() auto duration = std::chrono::duration_cast>(t_end - t_start); encode_time_total += duration.count(); - // ping the main loop in case the snapshot process takes a really long - // time and we get disconnected + LLViewerStats::instance().getRecording().resume(); + LLAppViewer::instance()->resumeMainloopTimeout(); + + // update main loop timeout state LLAppViewer::instance()->pingMainloopTimeout("LLFloater360Capture::capture360Images"); } diff --git a/indra/newview/llfloateravatar.cpp b/indra/newview/llfloateravatar.cpp index d5f341e705..e91371b762 100644 --- a/indra/newview/llfloateravatar.cpp +++ b/indra/newview/llfloateravatar.cpp @@ -48,12 +48,11 @@ LLFloaterAvatar::LLFloaterAvatar(const LLSD& key) LLFloaterAvatar::~LLFloaterAvatar() { - LLMediaCtrl* avatar_picker = findChild("avatar_picker_contents"); - if (avatar_picker) + if (mAvatarPicker) { - avatar_picker->navigateStop(); - avatar_picker->clearCache(); //images are reloading each time already - avatar_picker->unloadMediaSource(); + mAvatarPicker->navigateStop(); + mAvatarPicker->clearCache(); //images are reloading each time already + mAvatarPicker->unloadMediaSource(); } // Avatar chooser does not change between OpenSim grids @@ -66,6 +65,11 @@ LLFloaterAvatar::~LLFloaterAvatar() BOOL LLFloaterAvatar::postBuild() { + mAvatarPicker = findChild("avatar_picker_contents"); + if (mAvatarPicker) + { + mAvatarPicker->clearCache(); + } enableResizeCtrls(true, true, false); return TRUE; } diff --git a/indra/newview/llfloateravatar.h b/indra/newview/llfloateravatar.h index 331a6b5ade..1f898e08a1 100644 --- a/indra/newview/llfloateravatar.h +++ b/indra/newview/llfloateravatar.h @@ -29,6 +29,7 @@ #define LL_FLOATER_AVATAR_H #include "llfloater.h" +class LLMediaCtrl; class LLFloaterAvatar: public LLFloater @@ -39,6 +40,8 @@ private: /*virtual*/ ~LLFloaterAvatar(); /*virtual*/ BOOL postBuild(); + LLMediaCtrl* mAvatarPicker; + // Avatar chooser does not change between OpenSim grids /*virtual*/ void onOpen(const LLSD& key); void handleUrlChanged(const std::string& url); diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp index 7d15480091..71c0d8d57b 100644 --- a/indra/newview/llfloaterbump.cpp +++ b/indra/newview/llfloaterbump.cpp @@ -81,6 +81,14 @@ LLFloaterBump::LLFloaterBump(const LLSD& key) // Destroys the object LLFloaterBump::~LLFloaterBump() { + // Improved bump list + //auto menu = mPopupMenuHandle.get(); + //if (menu) + //{ + // menu->die(); + // mPopupMenuHandle.markDead(); + //} + // } BOOL LLFloaterBump::postBuild() @@ -90,11 +98,15 @@ BOOL LLFloaterBump::postBuild() //mList->setAllowMultipleSelection(false); //mList->setRightMouseDownCallback(boost::bind(&LLFloaterBump::onScrollListRightClicked, this, _1, _2, _3)); - //mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - //mPopupMenu->setItemVisible(std::string("Normal"), false); - //mPopupMenu->setItemVisible(std::string("Always use impostor"), false); - //mPopupMenu->setItemVisible(std::string("Never use impostor"), false); - //mPopupMenu->setItemVisible(std::string("Impostor seperator"), false); + //LLContextMenu* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_avatar_other.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + //if (menu) + //{ + // mPopupMenuHandle = menu->getHandle(); + // menu->setItemVisible(std::string("Normal"), false); + // menu->setItemVisible(std::string("Always use impostor"), false); + // menu->setItemVisible(std::string("Never use impostor"), false); + // menu->setItemVisible(std::string("Impostor seperator"), false); + //} //return TRUE; mList = getChild("bump_list"); @@ -227,18 +239,19 @@ void LLFloaterBump::onScrollListRightClicked(LLUICtrl* ctrl, S32 x, S32 y) if (!gMeanCollisionList.empty()) { LLScrollListItem* item = mList->hitItem(x, y); - if (item && mPopupMenu) + auto menu = mPopupMenuHandle.get(); + if (item && menu) { mItemUUID = item->getUUID(); - mPopupMenu->buildDrawLabels(); - mPopupMenu->updateParent(LLMenuGL::sMenuContainer); + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); std::string mute_msg = (LLMuteList::getInstance()->isMuted(mItemUUID, mNames[mItemUUID])) ? "UnmuteAvatar" : "MuteAvatar"; - mPopupMenu->getChild("Avatar Mute")->setValue(LLTrans::getString(mute_msg)); - mPopupMenu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID))); + menu->getChild("Avatar Mute")->setValue(LLTrans::getString(mute_msg)); + menu->setItemEnabled(std::string("Zoom In"), bool(gObjectList.findObject(mItemUUID))); - ((LLContextMenu*)mPopupMenu)->show(x, y); - LLMenuGL::showPopup(ctrl, mPopupMenu, x, y); + menu->show(x, y); + LLMenuGL::showPopup(ctrl, menu, x, y); } } } diff --git a/indra/newview/llfloaterbump.h b/indra/newview/llfloaterbump.h index a951d53fdc..66414dd7d0 100644 --- a/indra/newview/llfloaterbump.h +++ b/indra/newview/llfloaterbump.h @@ -76,7 +76,7 @@ private: // Improved bump list //LLScrollListCtrl* mList; - //LLMenuGL* mPopupMenu; + //LLHandle mPopupMenuHandle; //LLUUID mItemUUID; //typedef std::map uuid_map_t; diff --git a/indra/newview/llfloatercreatelandmark.cpp b/indra/newview/llfloatercreatelandmark.cpp index da22c5ff6e..6a21486f7f 100644 --- a/indra/newview/llfloatercreatelandmark.cpp +++ b/indra/newview/llfloatercreatelandmark.cpp @@ -324,7 +324,6 @@ void LLFloaterCreateLandmark::onSaveClicked() LLStringUtil::trim(current_title_value); LLStringUtil::trim(current_notes_value); - LLUUID item_id = mItem->getUUID(); LLUUID folder_id = mFolderCombo->getValue().asUUID(); bool change_parent = folder_id != mItem->getParentUUID(); diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp index af96c3ce22..c9d549dc6d 100644 --- a/indra/newview/llfloaterimcontainer.cpp +++ b/indra/newview/llfloaterimcontainer.cpp @@ -215,6 +215,7 @@ BOOL LLFloaterIMContainer::postBuild() p.options_menu = "menu_conversation.xml"; mConversationsRoot = LLUICtrlFactory::create(p); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar); // Add listener to conversation model events mConversationsEventStream.listen("ConversationsRefresh", boost::bind(&LLFloaterIMContainer::onConversationModelEvent, this, _1)); diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp index 0bda09c1a2..11fb8d5931 100644 --- a/indra/newview/llfloaterimsessiontab.cpp +++ b/indra/newview/llfloaterimsessiontab.cpp @@ -318,6 +318,7 @@ BOOL LLFloaterIMSessionTab::postBuild() p.name = "root"; mConversationsRoot = LLUICtrlFactory::create(p); mConversationsRoot->setCallbackRegistrar(&mCommitCallbackRegistrar); + mConversationsRoot->setEnableRegistrar(&mEnableCallbackRegistrar); // Attach that root to the scroller mScroller->addChild(mConversationsRoot); mConversationsRoot->setScrollContainer(mScroller); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 9aee06e600..1161fbaa21 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1938,7 +1938,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible) childSetTextArg("download_weight", "[ST]", tbd); childSetTextArg("server_weight", "[SIM]", tbd); childSetTextArg("physics_weight", "[PH]", tbd); - if (!mModelPhysicsFee.isMap() || mModelPhysicsFee.emptyMap()) + if (!mModelPhysicsFee.isMap() || (mModelPhysicsFee.size() == 0)) { childSetTextArg("upload_fee", "[FEE]", tbd); } diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 361f54c2f1..980bdf530e 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -59,8 +59,6 @@ LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key) { // Cinder's fly-out button //mCommitCallbackRegistrar.add("OpenObject.MoveToInventory", boost::bind(&LLFloaterOpenObject::onClickMoveToInventory, this)); - //mCommitCallbackRegistrar.add("OpenObject.MoveAndWear", boost::bind(&LLFloaterOpenObject::onClickMoveAndWear, this)); - //mCommitCallbackRegistrar.add("OpenObject.ReplaceOutfit", boost::bind(&LLFloaterOpenObject::onClickReplace, this)); mCommitCallbackRegistrar.add("OpenObject.CopyAction", boost::bind(&LLFloaterOpenObject::onClickCopy, this, _2)); // mCommitCallbackRegistrar.add("OpenObject.Cancel", boost::bind(&LLFloaterOpenObject::onClickCancel, this)); @@ -260,18 +258,6 @@ void LLFloaterOpenObject::callbackMoveInventory(S32 result, void* data) // moveToInventory(false); // closeFloater(); //} -// -//void LLFloaterOpenObject::onClickMoveAndWear() -//{ -// moveToInventory(true, false); -// closeFloater(); -//} -// -//void LLFloaterOpenObject::onClickReplace() -//{ -// moveToInventory(true, true); -// closeFloater(); -//} // void LLFloaterOpenObject::onClickCancel() diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h index 3c0e6c1ddc..7dc4255b5e 100644 --- a/indra/newview/llfloateropenobject.h +++ b/indra/newview/llfloateropenobject.h @@ -64,8 +64,6 @@ protected: // Cinder's fly-out button //void onClickMoveToInventory(); - //void onClickMoveAndWear(); - //void onClickReplace(); void onClickCopy(const LLSD& value); // void onClickCancel(); diff --git a/indra/newview/llfloateroutfitphotopreview.cpp b/indra/newview/llfloateroutfitphotopreview.cpp index 6c39db730c..ade258aef7 100644 --- a/indra/newview/llfloateroutfitphotopreview.cpp +++ b/indra/newview/llfloateroutfitphotopreview.cpp @@ -234,7 +234,6 @@ void LLFloaterOutfitPhotoPreview::updateImageID() if(item) { mImageID = item->getAssetUUID(); - LLPermissions perm(item->getPermissions()); } else { diff --git a/indra/newview/llfloaterpathfindinglinksets.cpp b/indra/newview/llfloaterpathfindinglinksets.cpp index 1e46d7a402..03aede94c6 100644 --- a/indra/newview/llfloaterpathfindinglinksets.cpp +++ b/indra/newview/llfloaterpathfindinglinksets.cpp @@ -44,6 +44,7 @@ #include "llpathfindinglinkset.h" #include "llpathfindinglinksetlist.h" #include "llpathfindingmanager.h" +#include "llsearcheditor.h" #include "llscrolllistitem.h" #include "llsd.h" #include "lltextbase.h" @@ -114,17 +115,13 @@ BOOL LLFloaterPathfindingLinksets::postBuild() { mBeaconColor = LLUIColorTable::getInstance()->getColor("PathfindingLinksetBeaconColor"); - mFilterByName = findChild("filter_by_name"); - llassert(mFilterByName != NULL); - mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); - mFilterByName->setSelectAllonFocusReceived(true); - mFilterByName->setCommitOnFocusLost(true); + mFilterByName = getChild("filter_by_name"); + mFilterByName->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + mFilterByName->setCommitOnFocusLost(true); - mFilterByDescription = findChild("filter_by_description"); - llassert(mFilterByDescription != NULL); - mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); - mFilterByDescription->setSelectAllonFocusReceived(true); - mFilterByDescription->setCommitOnFocusLost(true); + mFilterByDescription = getChild("filter_by_description"); + mFilterByDescription->setCommitCallback(boost::bind(&LLFloaterPathfindingLinksets::onApplyAllFilters, this)); + mFilterByDescription->setCommitOnFocusLost(true); mFilterByLinksetUse = findChild("filter_by_linkset_use"); llassert(mFilterByLinksetUse != NULL); diff --git a/indra/newview/llfloaterpathfindinglinksets.h b/indra/newview/llfloaterpathfindinglinksets.h index 7149da9215..a954d8a8ec 100644 --- a/indra/newview/llfloaterpathfindinglinksets.h +++ b/indra/newview/llfloaterpathfindinglinksets.h @@ -42,6 +42,7 @@ class LLSD; class LLTextBase; class LLUICtrl; class LLVector3; +class LLSearchEditor; class LLFloaterPathfindingLinksets : public LLFloaterPathfindingObjects { @@ -105,8 +106,8 @@ private: LLPathfindingLinkset::ELinksetUse convertToLinksetUse(LLSD pXuiValue) const; LLSD convertToXuiValue(LLPathfindingLinkset::ELinksetUse pLinksetUse) const; - LLLineEditor *mFilterByName; - LLLineEditor *mFilterByDescription; + LLSearchEditor *mFilterByName; + LLSearchEditor *mFilterByDescription; LLComboBox *mFilterByLinksetUse; LLComboBox *mEditLinksetUse; LLScrollListItem *mEditLinksetUseUnset; diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp index 1b97794c5a..db997c4a54 100644 --- a/indra/newview/llfloaterscriptlimits.cpp +++ b/indra/newview/llfloaterscriptlimits.cpp @@ -421,7 +421,6 @@ void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content) for(S32 i = 0; i < number_parcels; i++) { std::string parcel_name = content["parcels"][i]["name"].asString(); - LLUUID parcel_id = content["parcels"][i]["id"].asUUID(); S32 number_objects = content["parcels"][i]["objects"].size(); S32 local_id = 0; diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp index 77ed07f057..a9b802f5c3 100644 --- a/indra/newview/llfloatersearch.cpp +++ b/indra/newview/llfloatersearch.cpp @@ -48,7 +48,7 @@ class LLSearchHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_THROTTLE) { } + LLSearchHandler() : LLCommandHandler("search", UNTRUSTED_CLICK_ONLY) { } bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { if (!LLUI::getInstance()->mSettingGroups["config"]->getBOOL("EnableSearch")) diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index e44c5b5ad2..dcd67c2fb3 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -130,7 +130,7 @@ class LLWorldMapHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_THROTTLE ) { } + LLWorldMapHandler() : LLCommandHandler("worldmap", UNTRUSTED_CLICK_ONLY ) { } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) @@ -174,7 +174,7 @@ class LLMapTrackAvatarHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_THROTTLE) + LLMapTrackAvatarHandler() : LLCommandHandler("maptrackavatar", UNTRUSTED_CLICK_ONLY) { } diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp index dac8a034e5..2e53c5048e 100644 --- a/indra/newview/llgroupactions.cpp +++ b/indra/newview/llgroupactions.cpp @@ -68,7 +68,32 @@ class LLGroupHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_THROTTLE) { } + LLGroupHandler() : LLCommandHandler("group", UNTRUSTED_CLICK_ONLY) { } + + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 1) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED) + { + return true; + } + + const std::string verb = params[0].asString(); + if (verb == "create") + { + return false; + } + return true; + } + bool handle(const LLSD& tokens, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp index bef574e9e5..3b68ee7326 100644 --- a/indra/newview/llimprocessing.cpp +++ b/indra/newview/llimprocessing.cpp @@ -2309,7 +2309,7 @@ void LLIMProcessing::requestOfflineMessagesCoro(std::string url) return; } - if (messages.emptyArray()) + if (messages.size() == 0) { // Nothing to process return; diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 4c380d320e..b4c773fbb9 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2396,8 +2396,6 @@ void LLOutgoingCallDialog::show(const LLSD& key) std::string callee_name = mPayload["session_name"].asString(); - LLUUID session_id = mPayload["session_id"].asUUID(); - if (callee_name == "anonymous") // obsolete? Likely was part of avaline support { callee_name = getString("anonymous"); @@ -2784,7 +2782,7 @@ void LLIncomingCallDialog::processCallResponse(S32 response, const LLSD &payload } } - LLUUID new_session_id = gIMMgr->addSession(correct_session_name, type, session_id, true); + gIMMgr->addSession(correct_session_name, type, session_id, true); std::string url = gAgent.getRegion()->getCapability( "ChatSessionRequest"); @@ -2870,7 +2868,7 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response) } else { - LLUUID new_session_id = gIMMgr->addSession( + gIMMgr->addSession( payload["session_name"].asString(), type, session_id, true); diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 0dfadb63db..d5570cd6f7 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -894,6 +894,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id, { disabled_items.push_back(std::string("Find Original")); } + + items.push_back(std::string("Cut")); + if (!isItemMovable() || !isItemRemovable()) + { + disabled_items.push_back(std::string("Cut")); + } } else { @@ -2382,6 +2388,7 @@ bool LLItemBridge::isItemCopyable(bool can_copy_as_link) const // [/SL:KB] // static LLCachedControl inventory_linking(gSavedSettings, "InventoryLinking", true); // return (can_copy_as_link && inventory_linking) +// || (mIsLink && inventory_linking) // || item->getPermissions().allowCopyBy(gAgent.getID()); } @@ -2632,6 +2639,12 @@ BOOL LLFolderBridge::isUpToDate() const bool LLFolderBridge::isItemCopyable(bool can_copy_as_link) const { + if (can_copy_as_link && !LLFolderType::lookupIsProtectedType(getPreferredType())) + { + // Can copy and paste unprotected folders as links + return true; + } + // Folders are copyable if items in them are, recursively, copyable. // Get the content of the folder diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index dc0902e52d..843ab0650c 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -497,7 +497,6 @@ bool LLInventoryFilter::checkAgainstFilterType(const LLFolderViewModelItemInvent bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const { LLInventoryType::EType object_type = item->getInventoryType(); - const LLUUID object_id = item->getUUID(); const U32 filterTypes = mFilterOps.mFilterTypes; diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index 9526bb7048..4c0b285193 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -1533,9 +1533,6 @@ bool move_item_to_marketplacelistings(LLInventoryItem* inv_item, LLUUID dest_fol LLNotificationsUtil::add("MerchantPasteFailed", subs); return false; } - - // Get the parent folder of the moved item : we may have to update it - LLUUID src_folder = viewer_inv_item->getParentUUID(); if (copy) { diff --git a/indra/newview/llinventorylistitem.h b/indra/newview/llinventorylistitem.h index 3d07116651..bb751927c5 100644 --- a/indra/newview/llinventorylistitem.h +++ b/indra/newview/llinventorylistitem.h @@ -201,6 +201,7 @@ protected: virtual const LLPanelInventoryListItemBase::Params& getDefaultParams() const; // Better attachment list const LLUUID mInventoryItemUUID; + bool mHovered; private: @@ -225,7 +226,6 @@ private: LLUIImagePtr mSelectedImage; LLUIImagePtr mSeparatorImage; - bool mHovered; bool mSelected; bool mSeparatorVisible; diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp index 1094d925bf..8ad8f2dd6d 100644 --- a/indra/newview/llinventorymodel.cpp +++ b/indra/newview/llinventorymodel.cpp @@ -1869,11 +1869,11 @@ void LLInventoryModel::deleteObject(const LLUUID& id, bool fix_broken_links, boo // Can't have links to links, so there's no need for this update // if the item removed is a link. Can also skip if source of the // update is getting broken link info separately. - obj = NULL; // delete obj if (fix_broken_links && !is_link_type) { updateLinkedObjectsFromPurge(id); } + obj = nullptr; // delete obj if (do_notify_observers) { notifyObservers(); @@ -2961,7 +2961,6 @@ void LLInventoryModel::buildParentChildMap() // some accounts has pbroken inventory root folders std::string name = "My Inventory"; - LLUUID prev_root_id = mRootFolderID; for (parent_cat_map_t::const_iterator it = mParentChildCategoryTree.begin(), it_end = mParentChildCategoryTree.end(); it != it_end; ++it) { diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index ac84c4d5c5..49c41d0d4e 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -233,7 +233,11 @@ LLFolderView * LLInventoryPanel::createFolderRoot(LLUUID root_id ) p.item_top_pad = default_params.item_top_pad - (default_params.item_height - fsFolderViewItemHeight) / 2 - 1; // - return LLUICtrlFactory::create(p); + LLFolderView* fv = LLUICtrlFactory::create(p); + fv->setCallbackRegistrar(&mCommitCallbackRegistrar); + fv->setEnableRegistrar(&mEnableCallbackRegistrar); + + return fv; } void LLInventoryPanel::clearFolderRoot() @@ -286,6 +290,7 @@ void LLInventoryPanel::initFromParams(const LLInventoryPanel::Params& params) } mCommitCallbackRegistrar.popScope(); mFolderRoot.get()->setCallbackRegistrar(&mCommitCallbackRegistrar); + mFolderRoot.get()->setEnableRegistrar(&mEnableCallbackRegistrar); // Scroller LLRect scroller_view_rect = getRect(); diff --git a/indra/newview/llkeyconflict.cpp b/indra/newview/llkeyconflict.cpp index d3ba18525b..60f8aca94c 100644 --- a/indra/newview/llkeyconflict.cpp +++ b/indra/newview/llkeyconflict.cpp @@ -171,8 +171,9 @@ bool LLKeyConflictHandler::isReservedByMenu(const KEY &key, const MASK &mask) { return false; } - return (gMenuBarView && gMenuBarView->hasAccelerator(key, mask)) - || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(key, mask)); + // At the moment controls are only applicable inworld, + // ignore gLoginMenuBarView + return gMenuBarView && gMenuBarView->hasAccelerator(key, mask); } // static @@ -182,8 +183,7 @@ bool LLKeyConflictHandler::isReservedByMenu(const LLKeyData &data) { return false; } - return (gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask)) - || (gLoginMenuBarView && gLoginMenuBarView->hasAccelerator(data.mKey, data.mMask)); + return gMenuBarView && gMenuBarView->hasAccelerator(data.mKey, data.mMask); } bool LLKeyConflictHandler::registerControl(const std::string &control_name, U32 index, EMouseClickType mouse, KEY key, MASK mask, bool ignore_mask) diff --git a/indra/newview/lllistcontextmenu.cpp b/indra/newview/lllistcontextmenu.cpp index 6bda8b1d0d..77185411c5 100644 --- a/indra/newview/lllistcontextmenu.cpp +++ b/indra/newview/lllistcontextmenu.cpp @@ -51,6 +51,7 @@ LLListContextMenu::~LLListContextMenu() if (!mMenuHandle.isDead()) { mMenuHandle.get()->die(); + mMenuHandle.markDead(); } } @@ -59,13 +60,8 @@ void LLListContextMenu::show(LLView* spawning_view, const uuid_vec_t& uuids, S32 LLContextMenu* menup = mMenuHandle.get(); if (menup) { - //preventing parent (menu holder) from deleting already "dead" context menus on exit - LLView* parent = menup->getParent(); - if (parent) - { - parent->removeChild(menup); - } - delete menup; + menup->die(); + mMenuHandle.markDead(); mUUIDs.clear(); } diff --git a/indra/newview/llmaterialmgr.cpp b/indra/newview/llmaterialmgr.cpp index dd3bf13296..a52f7244f3 100644 --- a/indra/newview/llmaterialmgr.cpp +++ b/indra/newview/llmaterialmgr.cpp @@ -429,12 +429,10 @@ void LLMaterialMgr::onGetResponse(bool success, const LLSD& content, const LLUUI llassert(content.has(MATERIALS_CAP_ZIP_FIELD)); llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); - LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); - std::string content_string(reinterpret_cast(content_binary.data()), content_binary.size()); - std::istringstream content_stream(content_string); + const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); LLSD response_data; - U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); + U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size()); if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; @@ -472,15 +470,10 @@ void LLMaterialMgr::onGetAllResponse(bool success, const LLSD& content, const LL llassert(content.has(MATERIALS_CAP_ZIP_FIELD)); llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); - LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); - std::string content_string(reinterpret_cast(content_binary.data()), content_binary.size()); - std::istringstream content_stream(content_string); + const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); LLSD response_data; - // Use new variant unzip_llsd - // U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size()); - // if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; @@ -544,12 +537,10 @@ void LLMaterialMgr::onPutResponse(bool success, const LLSD& content) llassert(content.has(MATERIALS_CAP_ZIP_FIELD)); llassert(content[MATERIALS_CAP_ZIP_FIELD].isBinary()); - LLSD::Binary content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); - std::string content_string(reinterpret_cast(content_binary.data()), content_binary.size()); - std::istringstream content_stream(content_string); + const LLSD::Binary& content_binary = content[MATERIALS_CAP_ZIP_FIELD].asBinary(); LLSD response_data; - U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_stream, content_binary.size()); + U32 uzip_result = LLUZipHelper::unzip_llsd(response_data, content_binary.data(), content_binary.size()); if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS("Materials") << "Cannot unzip LLSD binary content: " << uzip_result << LL_ENDL; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 5bba2f9e54..6e728b7f6d 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -112,7 +112,6 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : mTrusted(p.trusted_content), mWindowShade(NULL), mHoverTextChanged(false), - mContextMenu(NULL), mAllowFileDownload(false) { { @@ -157,6 +156,13 @@ LLMediaCtrl::LLMediaCtrl( const Params& p) : LLMediaCtrl::~LLMediaCtrl() { + auto menu = mContextMenuHandle.get(); + if (menu) + { + menu->die(); + mContextMenuHandle.markDead(); + } + if (mMediaSource) { mMediaSource->remObserver( this ); @@ -342,15 +348,33 @@ BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) setFocus( TRUE ); } - if (mContextMenu) + auto menu = mContextMenuHandle.get(); + if (!menu) + { + LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; + registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); + + // stinson 05/05/2014 : use this as the parent of the context menu if the static menu + // container has yet to be created + LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast(LLMenuGL::sMenuContainer) : dynamic_cast(this); + llassert(menuParent != NULL); + menu = LLUICtrlFactory::getInstance()->createFromFile( + "menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance()); + if (menu) + { + mContextMenuHandle = menu->getHandle(); + } + } + + if (menu) { // hide/show debugging options bool media_plugin_debugging_enabled = gSavedSettings.getBOOL("MediaPluginDebugging"); - mContextMenu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); - mContextMenu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); + menu->setItemVisible("open_webinspector", media_plugin_debugging_enabled ); + menu->setItemVisible("debug_separator", media_plugin_debugging_enabled ); - mContextMenu->show(x, y); - LLMenuGL::showPopup(this, mContextMenu, x, y); + menu->show(x, y); + LLMenuGL::showPopup(this, menu, x, y); } return TRUE; @@ -460,15 +484,6 @@ void LLMediaCtrl::setFocus(BOOL b) // BOOL LLMediaCtrl::postBuild () { - LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registar; - registar.add("Open.WebInspector", boost::bind(&LLMediaCtrl::onOpenWebInspector, this)); - - // stinson 05/05/2014 : use this as the parent of the context menu if the static menu - // container has yet to be created - LLPanel* menuParent = (LLMenuGL::sMenuContainer != NULL) ? dynamic_cast(LLMenuGL::sMenuContainer) : dynamic_cast(this); - llassert(menuParent != NULL); - mContextMenu = LLUICtrlFactory::getInstance()->createFromFile( - "menu_media_ctrl.xml", menuParent, LLViewerMenuHolderGL::child_registry_t::instance()); setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2)); return TRUE; @@ -1300,11 +1315,6 @@ void LLMediaCtrl::setTrustedContent(bool trusted) } } -void LLMediaCtrl::updateContextMenuParent(LLView* pNewParent) -{ - mContextMenu->updateParent(pNewParent); -} - bool LLMediaCtrl::wantsKeyUpKeyDown() const { return true; diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 2372e3d7b0..0f1bcb6f75 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -175,8 +175,6 @@ public: LLUUID getTextureID() {return mMediaTextureID;} - void updateContextMenuParent(LLView* pNewParent); - // The Browser windows want keyup and keydown events. Overridden from LLFocusableElement to return true. virtual bool wantsKeyUpKeyDown() const; virtual bool wantsReturnKey() const; @@ -221,7 +219,7 @@ public: mTextureHeight; class LLWindowShade* mWindowShade; - LLContextMenu* mContextMenu; + LLHandle mContextMenuHandle; }; #endif // LL_LLMediaCtrl_H diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 9a85724ffc..970dd60539 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -77,6 +77,8 @@ #include "lluploaddialog.h" #include "llfloaterreg.h" +#include "boost/iostreams/device/array.hpp" +#include "boost/iostreams/stream.hpp" #include "boost/lexical_cast.hpp" // Reduce temporaries and copes in decoding mesh headers #include @@ -143,7 +145,7 @@ // data copied // headerReceived() invoked // LLSD parsed -// mMeshHeader, mMeshHeaderSize updated +// mMeshHeader updated // scan mPendingLOD for LOD request // push LODRequest to mLODReqQ // ... @@ -251,7 +253,6 @@ // sActiveLODRequests mMutex rw.any.mMutex, ro.repo.none [1] // sMaxConcurrentRequests mMutex wo.main.none, ro.repo.none, ro.main.mMutex // mMeshHeader mHeaderMutex rw.repo.mHeaderMutex, ro.main.mHeaderMutex, ro.main.none [0] -// mMeshHeaderSize mHeaderMutex rw.repo.mHeaderMutex // mSkinRequests mMutex rw.repo.mMutex, ro.repo.none [5] // mSkinInfoQ mMutex rw.repo.mMutex, rw.main.mMutex [5] (was: [0]) // mDecompositionRequests mMutex rw.repo.mMutex, ro.repo.none [5] @@ -888,6 +889,12 @@ LLMeshRepoThread::~LLMeshRepoThread() mHttpRequestSet.clear(); mHttpHeaders.reset(); + while (!mSkinInfoQ.empty()) + { + delete mSkinInfoQ.front(); + mSkinInfoQ.pop_front(); + } + while (!mDecompositionQ.empty()) { delete mDecompositionQ.front(); @@ -977,7 +984,8 @@ void LLMeshRepoThread::run() else { // too many fails - mUnavailableQ.push(req); + LLMutexLock lock(mMutex); + mUnavailableQ.push_back(req); LL_WARNS() << "Failed to load " << req.mMeshParams << " , skip" << LL_ENDL; } } @@ -1053,37 +1061,42 @@ void LLMeshRepoThread::run() if (!mSkinRequests.empty()) { - std::set incomplete; - while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater) - { - mMutex->lock(); - std::set::iterator iter = mSkinRequests.begin(); - UUIDBasedRequest req = *iter; - mSkinRequests.erase(iter); - mMutex->unlock(); - if (req.isDelayed()) - { - incomplete.insert(req); - } - else if (!fetchMeshSkinInfo(req.mId)) - { - if (req.canRetry()) - { - req.updateTime(); - incomplete.insert(req); - } - else - { - LL_DEBUGS() << "mSkinRequests failed: " << req.mId << LL_ENDL; - } - } - } + std::list incomplete; + while (!mSkinRequests.empty() && mHttpRequestSet.size() < sRequestHighWater) + { - if (!incomplete.empty()) - { - LLMutexLock locker(mMutex); - mSkinRequests.insert(incomplete.begin(), incomplete.end()); - } + mMutex->lock(); + auto req = mSkinRequests.front(); + mSkinRequests.pop_front(); + mMutex->unlock(); + if (req.isDelayed()) + { + incomplete.emplace_back(req); + } + else if (!fetchMeshSkinInfo(req.mId, req.canRetry())) + { + if (req.canRetry()) + { + req.updateTime(); + incomplete.emplace_back(req); + } + else + { + LLMutexLock locker(mMutex); + mSkinUnavailableQ.push_back(req); + LL_DEBUGS() << "mSkinReqQ failed: " << req.mId << LL_ENDL; + } + } + } + + if (!incomplete.empty()) + { + LLMutexLock locker(mMutex); + for (const auto& req : incomplete) + { + mSkinRequests.push_back(req); + } + } } // holding lock, try next list @@ -1182,7 +1195,7 @@ void LLMeshRepoThread::run() // Mutex: LLMeshRepoThread::mMutex must be held on entry void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id) { - mSkinRequests.insert(UUIDBasedRequest(mesh_id)); + mSkinRequests.push_back(UUIDBasedRequest(mesh_id)); } // Mutex: LLMeshRepoThread::mMutex must be held on entry @@ -1208,10 +1221,13 @@ void LLMeshRepoThread::lockAndLoadMeshLOD(const LLVolumeParams& mesh_params, S32 void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) { //could be called from any thread + const LLUUID& mesh_id = mesh_params.getSculptID(); LLMutexLock lock(mMutex); - mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); + LLMutexLock header_lock(mHeaderMutex); + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); if (iter != mMeshHeader.end()) { //if we have the header, request LOD byte range + LODRequest req(mesh_params, lod); { mLODReqQ.push(req); @@ -1221,8 +1237,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) else { HeaderRequest req(mesh_params); - - pending_lod_map::iterator pending = mPendingLOD.find(mesh_params); + pending_lod_map::iterator pending = mPendingLOD.find(mesh_id); if (pending != mPendingLOD.end()) { //append this lod request to existing header request @@ -1232,7 +1247,7 @@ void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) else { //if no header request is pending, fetch header mHeaderReqQ.push(req); - mPendingLOD[mesh_params].push_back(lod); + mPendingLOD[mesh_id].push_back(lod); } } } @@ -1377,7 +1392,7 @@ LLCore::HttpHandle LLMeshRepoThread::getByteRange(const std::string & url, int l } -bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) +bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry) { if (!mHeaderMutex) @@ -1387,7 +1402,8 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) mHeaderMutex->lock(); - if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) { //we have no header info for this mesh, do nothing mHeaderMutex->unlock(); return false; @@ -1395,13 +1411,14 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) ++LLMeshRepository::sMeshRequestCount; bool ret = true; - U32 header_size = mMeshHeaderSize[mesh_id]; + U32 header_size = header_it->second.first; if (header_size > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id]["skin"]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id]["skin"]["size"].asInteger(); + const LLSD& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header["skin"]["offset"].asInteger(); + S32 size = header["skin"]["size"].asInteger(); mHeaderMutex->unlock(); @@ -1464,12 +1481,27 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) << LL_ENDL; ret = false; } - else + else if(can_retry) { handler->mHttpHandle = handle; mHttpRequestSet.insert(handler); } + else + { + LLMutexLock locker(mMutex); + mSkinUnavailableQ.emplace_back(mesh_id); + } } + else + { + LLMutexLock locker(mMutex); + mSkinUnavailableQ.emplace_back(mesh_id); + } + } + else + { + LLMutexLock locker(mMutex); + mSkinUnavailableQ.emplace_back(mesh_id); } } else @@ -1490,21 +1522,23 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) mHeaderMutex->lock(); - if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) { //we have no header info for this mesh, do nothing mHeaderMutex->unlock(); return false; } ++LLMeshRepository::sMeshRequestCount; - U32 header_size = mMeshHeaderSize[mesh_id]; + U32 header_size = header_it->second.first; bool ret = true; if (header_size > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id]["physics_convex"]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id]["physics_convex"]["size"].asInteger(); + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header["physics_convex"]["offset"].asInteger(); + S32 size = header["physics_convex"]["size"].asInteger(); mHeaderMutex->unlock(); @@ -1594,21 +1628,23 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) mHeaderMutex->lock(); - if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) { //we have no header info for this mesh, do nothing mHeaderMutex->unlock(); return false; } ++LLMeshRepository::sMeshRequestCount; - U32 header_size = mMeshHeaderSize[mesh_id]; + U32 header_size = header_it->second.first; bool ret = true; if (header_size > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id]["physics_mesh"]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id]["physics_mesh"]["size"].asInteger(); + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header["physics_mesh"]["offset"].asInteger(); + S32 size = header["physics_mesh"]["size"].asInteger(); mHeaderMutex->unlock(); @@ -1802,20 +1838,25 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, return false; } - mHeaderMutex->lock(); + const LLUUID& mesh_id = mesh_params.getSculptID(); + mHeaderMutex->lock(); + auto header_it = mMeshHeader.find(mesh_id); + if (header_it == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } ++LLMeshRepository::sMeshRequestCount; bool retval = true; - - LLUUID mesh_id = mesh_params.getSculptID(); - U32 header_size = mMeshHeaderSize[mesh_id]; - + U32 header_size = header_it->second.first; if (header_size > 0) { - S32 version = mMeshHeader[mesh_id]["version"].asInteger(); - S32 offset = header_size + mMeshHeader[mesh_id][header_lod[lod]]["offset"].asInteger(); - S32 size = mMeshHeader[mesh_id][header_lod[lod]]["size"].asInteger(); + const auto& header = header_it->second.second; + S32 version = header["version"].asInteger(); + S32 offset = header_size + header[header_lod[lod]]["offset"].asInteger(); + S32 size = header[header_lod[lod]]["size"].asInteger(); mHeaderMutex->unlock(); if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) @@ -1897,17 +1938,20 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod, } else { - mUnavailableQ.push(LODRequest(mesh_params, lod)); + LLMutexLock lock(mMutex); + mUnavailableQ.push_back(LODRequest(mesh_params, lod)); } } else { - mUnavailableQ.push(LODRequest(mesh_params, lod)); + LLMutexLock lock(mMutex); + mUnavailableQ.push_back(LODRequest(mesh_params, lod)); } } else { - mUnavailableQ.push(LODRequest(mesh_params, lod)); + LLMutexLock lock(mMutex); + mUnavailableQ.push_back(LODRequest(mesh_params, lod)); } } else @@ -1926,28 +1970,6 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes U32 header_size = 0; if (data_size > 0) { - // Reduce temporaries and copes in decoding mesh headers - // std::istringstream stream; - // try - // { - // std::string res_str((char*)data, data_size); - - // std::string deprecated_header(""); - - // if (res_str.substr(0, deprecated_header.size()) == deprecated_header) - // { - // res_str = res_str.substr(deprecated_header.size() + 1, data_size); - // header_size = deprecated_header.size() + 1; - // } - // data_size = res_str.size(); - - // stream.str(res_str); - // } - // catch (std::bad_alloc&) - // { - // // out of memory, we won't be able to process this mesh - // return MESH_OUT_OF_MEMORY; - // } llssize dsize = data_size; llssize header_size_tmp{}; char* result_ptr = strip_deprecated_header((char*)data, dsize, &header_size_tmp); @@ -1956,7 +1978,6 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes data_size = static_cast(dsize); boost::iostreams::stream stream(result_ptr, data_size); - // if (!LLSDSerialize::fromBinary(header, stream, data_size)) { @@ -1993,8 +2014,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes { LLMutexLock lock(mHeaderMutex); - mMeshHeaderSize[mesh_id] = header_size; - mMeshHeader[mesh_id] = header; + mMeshHeader[mesh_id] = { header_size, header }; LLMeshRepository::sCacheBytesHeaders += header_size; } @@ -2002,7 +2022,7 @@ EMeshProcessingResult LLMeshRepoThread::headerReceived(const LLVolumeParams& mes LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time. //check for pending requests - pending_lod_map::iterator iter = mPendingLOD.find(mesh_params); + pending_lod_map::iterator iter = mPendingLOD.find(mesh_id); if (iter != mPendingLOD.end()) { for (U32 i = 0; i < iter->second.size(); ++i) @@ -2026,29 +2046,14 @@ EMeshProcessingResult LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_p } LLPointer volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); - // Reduce temporaries and copes in decoding mesh headers - // std::istringstream stream; - // try - // { - // std::string mesh_string((char*)data, data_size); - // stream.str(mesh_string); - // } - // catch (std::bad_alloc&) - // { - // // out of memory, we won't be able to process this mesh - // return MESH_OUT_OF_MEMORY; - // } - - // if (volume->unpackVolumeFaces(stream, data_size)) if (volume->unpackVolumeFaces(data, data_size)) - // { if (volume->getNumFaces() > 0) { LoadedMesh mesh(volume, mesh_params, lod); { LLMutexLock lock(mMutex); - mLoadedQ.push(mesh); + mLoadedQ.push_back(mesh); // LLPointer is not thread safe, since we added this pointer into // threaded list, make sure counter gets decreased inside mutex lock // and won't affect mLoadedQ processing @@ -2071,13 +2076,7 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat { try { - // Reduce temporaries and copes in decoding mesh headers - // std::string res_str((char*)data, data_size); - // std::istringstream stream(res_str); - - // U32 uzip_result = LLUZipHelper::unzip_llsd(skin, stream, data_size); U32 uzip_result = LLUZipHelper::unzip_llsd(skin, data, data_size); - // if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS(LOG_MESH) << "Mesh skin info parse error. Not a valid mesh asset! ID: " << mesh_id @@ -2094,8 +2093,16 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat } { - LLMeshSkinInfo info(skin); - info.mMeshID = mesh_id; + LLMeshSkinInfo* info = nullptr; + try + { + info = new LLMeshSkinInfo(mesh_id, skin); + } + catch (const std::bad_alloc& ex) + { + LL_WARNS() << "Failed to allocate skin info with exception: " << ex.what() << LL_ENDL; + return false; + } // LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL; { @@ -2115,13 +2122,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3 { try { - // Reduce temporaries and copes in decoding mesh headers - // std::string res_str((char*)data, data_size); - // std::istringstream stream(res_str); - - // U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, stream, data_size); U32 uzip_result = LLUZipHelper::unzip_llsd(decomp, data, data_size); - // if (uzip_result != LLUZipHelper::ZR_OK) { LL_WARNS(LOG_MESH) << "Mesh decomposition parse error. Not a valid mesh asset! ID: " << mesh_id @@ -2130,7 +2131,7 @@ bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S3 return false; } } - catch (const std::bad_alloc&) // const cos const! + catch (const std::bad_alloc&) { LL_WARNS(LOG_MESH) << "Out of memory for mesh ID " << mesh_id << " of size: " << data_size << LL_ENDL; return false; @@ -2167,21 +2168,6 @@ EMeshProcessingResult LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_ volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH); LLPointer volume = new LLVolume(volume_params,0); - // Reduce temporaries and copes in decoding mesh headers - // std::istringstream stream; - // try - // { - // std::string mesh_string((char*)data, data_size); - // stream.str(mesh_string); - // } - // catch (std::bad_alloc&) - // { - // // out of memory, we won't be able to process this mesh - // delete d; - // return MESH_OUT_OF_MEMORY; - // } - - // if (volume->unpackVolumeFaces(stream, data_size)) if (volume->unpackVolumeFaces(data, data_size)) { d->mPhysicsShapeMesh.clear(); @@ -2996,58 +2982,72 @@ void LLMeshRepoThread::notifyLoadedMeshes() return; } - while (!mLoadedQ.empty()) + if (!mLoadedQ.empty()) { + std::deque loaded_queue; + mMutex->lock(); - if (mLoadedQ.empty()) + if (!mLoadedQ.empty()) { + loaded_queue.swap(mLoadedQ); mMutex->unlock(); - break; - } - LoadedMesh mesh = mLoadedQ.front(); // make sure nothing else owns volume pointer by this point - mLoadedQ.pop(); - mMutex->unlock(); - - update_metrics = true; - if (mesh.mVolume->getNumVolumeFaces() > 0) - { - gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); - } - else - { - gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams, - LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail())); + + update_metrics = true; + + // Process the elements free of the lock + for (const auto& mesh : loaded_queue) + { + if (mesh.mVolume->getNumVolumeFaces() > 0) + { + gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); + } + else + { + gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams, + LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail())); + } + } } } - while (!mUnavailableQ.empty()) + if (!mUnavailableQ.empty()) { - mMutex->lock(); - if (mUnavailableQ.empty()) - { - mMutex->unlock(); - break; - } - - LODRequest req = mUnavailableQ.front(); - mUnavailableQ.pop(); - mMutex->unlock(); + std::deque unavil_queue; - update_metrics = true; - gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD); + mMutex->lock(); + if (!mUnavailableQ.empty()) + { + unavil_queue.swap(mUnavailableQ); + mMutex->unlock(); + + update_metrics = true; + + // Process the elements free of the lock + for (const auto& req : unavil_queue) + { + gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD); + } + } } - if (! mSkinInfoQ.empty() || ! mDecompositionQ.empty()) + if (!mSkinInfoQ.empty() || !mSkinUnavailableQ.empty() || ! mDecompositionQ.empty()) { if (mMutex->trylock()) { - std::list skin_info_q; + std::deque skin_info_q; + std::deque skin_info_unavail_q; std::list decomp_q; if (! mSkinInfoQ.empty()) { skin_info_q.swap(mSkinInfoQ); } + + if (! mSkinUnavailableQ.empty()) + { + skin_info_unavail_q.swap(mSkinUnavailableQ); + } + if (! mDecompositionQ.empty()) { decomp_q.swap(mDecompositionQ); @@ -3061,6 +3061,11 @@ void LLMeshRepoThread::notifyLoadedMeshes() gMeshRepo.notifySkinInfoReceived(skin_info_q.front()); skin_info_q.pop_front(); } + while (! skin_info_unavail_q.empty()) + { + gMeshRepo.notifySkinInfoUnavailable(skin_info_unavail_q.front().mId); + skin_info_unavail_q.pop_front(); + } while (! decomp_q.empty()) { @@ -3085,7 +3090,7 @@ S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo if (iter != mMeshHeader.end()) { - LLSD& header = iter->second; + LLSD& header = iter->second.second; return LLMeshRepository::getActualMeshLOD(header, lod); } @@ -3291,7 +3296,7 @@ void LLMeshHeaderHandler::processFailure(LLCore::HttpStatus status) LLMutexLock lock(gMeshRepo.mThread->mMutex); for (int i(0); i < 4; ++i) { - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i)); } } @@ -3320,7 +3325,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b LLMutexLock lock(gMeshRepo.mThread->mMutex); for (int i(0); i < 4; ++i) { - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i)); } } else if (data && data_size > 0) @@ -3333,8 +3338,8 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b LLMeshRepoThread::mesh_header_map::iterator iter = gMeshRepo.mThread->mMeshHeader.find(mesh_id); if (iter != gMeshRepo.mThread->mMeshHeader.end()) { - header_bytes = (S32)gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; - header = iter->second; + header_bytes = (S32)iter->second.first; + header = iter->second.second; } if (header_bytes > 0 @@ -3402,7 +3407,7 @@ void LLMeshHeaderHandler::processData(LLCore::BufferArray * /* body */, S32 /* b LLMutexLock lock(gMeshRepo.mThread->mMutex); for (int i(0); i < 4; ++i) { - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, i)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, i)); } } } @@ -3429,7 +3434,7 @@ void LLMeshLODHandler::processFailure(LLCore::HttpStatus status) << LL_ENDL; LLMutexLock lock(gMeshRepo.mThread->mMutex); - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); } void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, @@ -3466,7 +3471,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body << " Not retrying." << LL_ENDL; LLMutexLock lock(gMeshRepo.mThread->mMutex); - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); } } else @@ -3477,7 +3482,7 @@ void LLMeshLODHandler::processData(LLCore::BufferArray * /* body */, S32 /* body << " Data size: " << data_size << LL_ENDL; LLMutexLock lock(gMeshRepo.mThread->mMutex); - gMeshRepo.mThread->mUnavailableQ.push(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); + gMeshRepo.mThread->mUnavailableQ.push_back(LLMeshRepoThread::LODRequest(mMeshParams, mLOD)); } } @@ -3495,9 +3500,8 @@ void LLMeshSkinInfoHandler::processFailure(LLCore::HttpStatus status) << ", Reason: " << status.toString() << " (" << status.toTerseString() << "). Not retrying." << LL_ENDL; - - // *TODO: Mark mesh unavailable on error. For now, simply leave - // request unfulfilled rather than retry forever. + LLMutexLock lock(gMeshRepo.mThread->mMutex); + gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID); } void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* body_offset */, @@ -3528,7 +3532,8 @@ void LLMeshSkinInfoHandler::processData(LLCore::BufferArray * /* body */, S32 /* LL_WARNS(LOG_MESH) << "Error during mesh skin info processing. ID: " << mMeshID << ", Unknown reason. Not retrying." << LL_ENDL; - // *TODO: Mark mesh unavailable on error + LLMutexLock lock(gMeshRepo.mThread->mMutex); + gMeshRepo.mThread->mSkinUnavailableQ.emplace_back(mMeshID); } } @@ -3638,7 +3643,7 @@ LLMeshRepository::LLMeshRepository() mLegacyGetMeshVersion(0), // [UDP Assets] mThread(NULL) { - + mSkinInfoCullTimer.resetWithExpiry(10.f); } void LLMeshRepository::init() @@ -3739,6 +3744,22 @@ S32 LLMeshRepository::update() return size ; } +void LLMeshRepository::unregisterMesh(LLVOVolume* vobj) +{ + for (auto& lod : mLoadingMeshes) + { + for (auto& param : lod) + { + vector_replace_with_last(param.second, vobj); + } + } + + for (auto& skin_pair : mLoadingSkins) + { + vector_replace_with_last(skin_pair.second, vobj); + } +} + S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail, S32 last_lod) { LL_PROFILE_ZONE_SCOPED_CATEGORY_NETWORK; //LL_LL_RECORD_BLOCK_TIME(FTM_MESH_FETCH); @@ -3754,15 +3775,19 @@ S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_para { LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes - mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_params); + const auto& mesh_id = mesh_params.getSculptID(); + mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_id); if (iter != mLoadingMeshes[detail].end()) { //request pending for this mesh, append volume id to list - iter->second.insert(vobj->getID()); + auto it = std::find(iter->second.begin(), iter->second.end(), vobj); + if (it == iter->second.end()) { + iter->second.push_back(vobj); + } } else { //first request for this mesh - mLoadingMeshes[detail][mesh_params].insert(vobj->getID()); + mLoadingMeshes[detail][mesh_id].push_back(vobj); mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail)); LLMeshRepository::sLODPending++; } @@ -3975,6 +4000,28 @@ void LLMeshRepository::notifyLoadedMeshes() //call completed callbacks on finished decompositions mDecompThread->notifyCompleted(); + if (mSkinInfoCullTimer.checkExpirationAndReset(10.f)) + { + //// Clean up dead skin info + //U64Bytes skinbytes(0); + for (auto iter = mSkinMap.begin(), ender = mSkinMap.end(); iter != ender;) + { + auto copy_iter = iter++; + + //skinbytes += U64Bytes(sizeof(LLMeshSkinInfo)); + //skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(std::string)); + //skinbytes += U64Bytes(copy_iter->second->mJointNums.size() * sizeof(S32)); + //skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4a)); + //skinbytes += U64Bytes(copy_iter->second->mJointNames.size() * sizeof(LLMatrix4)); + + if (copy_iter->second->getNumRefs() == 1) + { + mSkinMap.erase(copy_iter); + } + } + //LL_INFOS() << "Skin info cache elements:" << mSkinMap.size() << " Memory: " << U64Kilobytes(skinbytes) << LL_ENDL; + } + // For major operations, attempt to get the required locks // without blocking and punt if they're not available. The // longest run of holdoffs is kept in sMaxLockHoldoffs just @@ -4059,10 +4106,9 @@ void LLMeshRepository::notifyLoadedMeshes() for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) { F32 max_score = 0.f; - for (std::set::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) + for (auto obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) { - LLViewerObject* object = gObjectList.findObject(*obj_iter); - + LLVOVolume* object = *obj_iter; if (object) { LLDrawable* drawable = object->mDrawable; @@ -4074,7 +4120,7 @@ void LLMeshRepository::notifyLoadedMeshes() } } - score_map[iter->first.getSculptID()] = max_score; + score_map[iter->first] = max_score; } } @@ -4126,24 +4172,39 @@ void LLMeshRepository::notifyLoadedMeshes() mThread->mSignal->signal(); } -void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) +void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo* info) { - mSkinMap[info.mMeshID] = info; + mSkinMap[info->mMeshID] = info; // Cache into LLPointer // Alternative: We can get skin size from header - sCacheBytesSkins += info.sizeBytes(); + sCacheBytesSkins += info->sizeBytes(); - skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID); + skin_load_map::iterator iter = mLoadingSkins.find(info->mMeshID); if (iter != mLoadingSkins.end()) { - for (std::set::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id) + for (LLVOVolume* vobj : iter->second) { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id); if (vobj) { - vobj->notifyMeshLoaded(); + vobj->notifySkinInfoLoaded(info); } } - mLoadingSkins.erase(info.mMeshID); + mLoadingSkins.erase(iter); + } +} + +void LLMeshRepository::notifySkinInfoUnavailable(const LLUUID& mesh_id) +{ + skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); + if (iter != mLoadingSkins.end()) + { + for (LLVOVolume* vobj : iter->second) + { + if (vobj) + { + vobj->notifySkinInfoUnavailable(); + } + } + mLoadingSkins.erase(iter); } } @@ -4172,14 +4233,15 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail()); //get list of objects waiting to be notified this mesh is loaded - mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_params); + const auto& mesh_id = mesh_params.getSculptID(); + mesh_load_map::iterator obj_iter = mLoadingMeshes[detail].find(mesh_id); if (volume && obj_iter != mLoadingMeshes[detail].end()) { //make sure target volume is still valid if (volume->getNumVolumeFaces() <= 0) { - LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_params.getSculptID() + LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_id << LL_ENDL; } @@ -4193,37 +4255,35 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol } else { - LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_params.getSculptID() + LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_id << LL_ENDL; } } //notify waiting LLVOVolume instances that their requested mesh is available - for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + for (LLVOVolume* vobj : obj_iter->second) { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); if (vobj) { vobj->notifyMeshLoaded(); } } - mLoadingMeshes[detail].erase(mesh_params); + mLoadingMeshes[detail].erase(obj_iter); } } void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod) { //called from main thread //get list of objects waiting to be notified this mesh is loaded - mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_params); - - F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod); - + const auto& mesh_id = mesh_params.getSculptID(); + mesh_load_map::iterator obj_iter = mLoadingMeshes[lod].find(mesh_id); if (obj_iter != mLoadingMeshes[lod].end()) { - for (std::set::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + F32 detail = LLVolumeLODGroup::getVolumeScaleFromDetail(lod); + + for (LLVOVolume* vobj : obj_iter->second) { - LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); if (vobj) { LLVolume* obj_volume = vobj->getVolume(); @@ -4237,7 +4297,7 @@ void LLMeshRepository::notifyMeshUnavailable(const LLVolumeParams& mesh_params, } } - mLoadingMeshes[lod].erase(mesh_params); + mLoadingMeshes[lod].erase(obj_iter); } } @@ -4246,7 +4306,7 @@ S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lo return mThread->getActualMeshLOD(mesh_params, lod); } -const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj) +const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj) { LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; if (mesh_id.notNull()) @@ -4254,7 +4314,7 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const skin_map::iterator iter = mSkinMap.find(mesh_id); if (iter != mSkinMap.end()) { - return &(iter->second); + return iter->second; } //no skin info known about given mesh, try to fetch it @@ -4263,14 +4323,22 @@ const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLMutexLock lock(mMeshMutex); //add volume to list of loading meshes skin_load_map::iterator iter = mLoadingSkins.find(mesh_id); - if (iter == mLoadingSkins.end()) - { //no request pending for this skin info + if (iter != mLoadingSkins.end()) + { //request pending for this mesh, append volume id to list + auto it = std::find(iter->second.begin(), iter->second.end(), requesting_obj); + if (it == iter->second.end()) { + iter->second.push_back(requesting_obj); + } + } + else + { + //first request for this mesh + mLoadingSkins[mesh_id].push_back(requesting_obj); mPendingSkinRequests.push(mesh_id); } - mLoadingSkins[mesh_id].insert(requesting_obj->getID()); } } - return NULL; + return nullptr; } void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id) @@ -4373,16 +4441,13 @@ bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id) bool LLMeshRepoThread::hasPhysicsShapeInHeader(const LLUUID& mesh_id) { LLMutexLock lock(mHeaderMutex); - if (mMeshHeaderSize[mesh_id] > 0) + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); + if (iter != mMeshHeader.end() && iter->second.first > 0) { - mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); - if (iter != mMeshHeader.end()) + LLSD &mesh = iter->second.second; + if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) { - LLSD &mesh = iter->second; - if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) - { - return true; - } + return true; } } @@ -4403,16 +4468,13 @@ LLUUID LLMeshRepository::getCreatorFromHeader(const LLUUID& mesh_id) LLUUID LLMeshRepoThread::getCreatorFromHeader(const LLUUID& mesh_id) { LLMutexLock lock(mHeaderMutex); - if (mMeshHeaderSize[mesh_id] > 0) + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); + if (iter != mMeshHeader.end() && iter->second.first > 0) { - mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); - if (iter != mMeshHeader.end()) + LLSD& mesh = iter->second.second; + if (mesh.has("creator") && mesh["creator"].isUUID()) { - LLSD& mesh = iter->second; - if (mesh.has("creator") && mesh["creator"].isUUID()) - { - return mesh["creator"].asUUID(); - } + return mesh["creator"].asUUID(); } } @@ -4437,9 +4499,9 @@ S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod) { LLMutexLock lock(mThread->mHeaderMutex); LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); - if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) + if (iter != mThread->mMeshHeader.end() && iter->second.first > 0) { - LLSD& header = iter->second; + const LLSD& header = iter->second.second; if (header.has("404")) { @@ -4543,9 +4605,9 @@ F32 LLMeshRepository::getStreamingCostLegacy(LLUUID mesh_id, F32 radius, S32* by { LLMutexLock lock(mThread->mHeaderMutex); LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); - if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) + if (iter != mThread->mMeshHeader.end() && iter->second.first > 0) { - result = getStreamingCostLegacy(iter->second, radius, bytes, bytes_visible, lod, unscaled_value); + result = getStreamingCostLegacy(iter->second.second, radius, bytes, bytes_visible, lod, unscaled_value); } } if (result > 0.f) @@ -4867,10 +4929,9 @@ bool LLMeshRepository::getCostData(LLUUID mesh_id, LLMeshCostData& data) { LLMutexLock lock(mThread->mHeaderMutex); LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); - if (iter != mThread->mMeshHeader.end() && mThread->mMeshHeaderSize[mesh_id] > 0) + if (iter != mThread->mMeshHeader.end() && iter->second.first > 0) { - // TODO - come to this back later. From all known so far it's not a simply race condition but LLSD being not multi thread safe at all. (which in fact it isn't). - LLSD& header = iter->second; + LLSD& header = iter->second.second; bool header_invalid = (header.has("404") || !header.has("lowest_lod") diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index 4e86dcd1cc..5932f8453d 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -210,10 +210,8 @@ public: LLCondition* mSignal; //map of known mesh headers - typedef std::map mesh_header_map; + typedef boost::unordered_map> mesh_header_map; // pair is header_size and data mesh_header_map mMeshHeader; - - std::map mMeshHeaderSize; class HeaderRequest : public RequestStats { @@ -283,10 +281,13 @@ public: }; //set of requested skin info - std::set mSkinRequests; + std::deque mSkinRequests; // list of completed skin info requests - std::list mSkinInfoQ; + std::deque mSkinInfoQ; + + // list of skin info requests that have failed or are unavailaibe + std::deque mSkinUnavailableQ; //set of requested decompositions std::set mDecompositionRequests; @@ -304,13 +305,13 @@ public: std::queue mLODReqQ; //queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD) - std::queue mUnavailableQ; + std::deque mUnavailableQ; //queue of successfully loaded meshes - std::queue mLoadedQ; + std::deque mLoadedQ; //map of pending header requests and currently desired LODs - typedef std::map > pending_lod_map; + typedef boost::unordered_map > pending_lod_map; pending_lod_map mPendingLOD; // llcorehttp library interface objects. @@ -360,7 +361,7 @@ public: //send request for skin info, returns true if header info exists // (should hold onto mesh_id and try again later if header info does not exist) - bool fetchMeshSkinInfo(const LLUUID& mesh_id); + bool fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry = true); //send request for decomposition, returns true if header info exists // (should hold onto mesh_id and try again later if header info does not exist) @@ -599,18 +600,20 @@ public: void shutdown(); S32 update(); + void unregisterMesh(LLVOVolume* volume); //mesh management functions S32 loadMesh(LLVOVolume* volume, const LLVolumeParams& mesh_params, S32 detail = 0, S32 last_lod = -1); void notifyLoadedMeshes(); void notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume); void notifyMeshUnavailable(const LLVolumeParams& mesh_params, S32 lod); - void notifySkinInfoReceived(LLMeshSkinInfo& info); + void notifySkinInfoReceived(LLMeshSkinInfo* info); + void notifySkinInfoUnavailable(const LLUUID& info); void notifyDecompositionReceived(LLModel::Decomposition* info); S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); static S32 getActualMeshLOD(LLSD& header, S32 lod); - const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj = nullptr); + const LLMeshSkinInfo* getSkinInfo(const LLUUID& mesh_id, LLVOVolume* requesting_obj = nullptr); LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id); void fetchPhysicsShape(const LLUUID& mesh_id); bool hasPhysicsShape(const LLUUID& mesh_id); @@ -635,13 +638,13 @@ public: static void metricsProgress(unsigned int count); static void metricsUpdate(); - typedef std::map > mesh_load_map; + typedef boost::unordered_map > mesh_load_map; mesh_load_map mLoadingMeshes[4]; // DAE export LLUUID getCreatorFromHeader(const LLUUID& mesh_id); - typedef std::unordered_map skin_map; + typedef std::unordered_map> skin_map; skin_map mSkinMap; typedef std::map decomposition_map; @@ -652,7 +655,7 @@ public: std::vector mPendingRequests; //list of mesh ids awaiting skin info - typedef std::map > skin_load_map; + typedef boost::unordered_map > skin_load_map; skin_load_map mLoadingSkins; //list of mesh ids that need to send skin info fetch requests @@ -677,6 +680,8 @@ public: std::vector mUploadWaitList; LLPhysicsDecomp* mDecompThread; + + LLFrameTimer mSkinInfoCullTimer; class inventory_data { diff --git a/indra/newview/llmodelpreview.cpp b/indra/newview/llmodelpreview.cpp index 3e64e7577e..1f75e1b590 100644 --- a/indra/newview/llmodelpreview.cpp +++ b/indra/newview/llmodelpreview.cpp @@ -2746,38 +2746,16 @@ void LLModelPreview::genMeshOptimizerLODs(S32 which_lod, S32 meshopt_mode, U32 d if (sloppy_ratio < 0) { // Sloppy method didn't work, try with smaller decimation values - S32 size_vertices = 0; - - for (U32 face_idx = 0; face_idx < base->getNumVolumeFaces(); ++face_idx) - { - const LLVolumeFace &face = base->getVolumeFace(face_idx); - size_vertices += face.mNumVertices; - } - - // Complex models aren't supposed to get here, they are supposed - // to work on a first try of sloppy due to having more viggle room. - // If they didn't, something is likely wrong, no point locking the - // thread in a long calculation that will fail. - const U32 too_many_vertices = 65535; - if (size_vertices > too_many_vertices) - { - // log this properly. - // LL_WARNS() << "Sloppy optimization method failed for a complex model " << target_model->getName() << LL_ENDL; - std::ostringstream out; - out << "Sloppy optimization method failed for a complex model " << target_model->getName(); - LL_WARNS() << out.str() << LL_ENDL; - LLFloaterModelPreview::addStringToLog(out, true); - // - } - else { // Find a decimator that does work F32 sloppy_decimation_step = sqrt((F32)decimation); // example: 27->15->9->5->3 F32 sloppy_decimator = indices_decimator / sloppy_decimation_step; + U64Microseconds end_time = LLTimer::getTotalTime() + U64Seconds(5); while (sloppy_ratio < 0 && sloppy_decimator > precise_ratio - && sloppy_decimator > 1)// precise_ratio isn't supposed to be below 1, but check just in case + && sloppy_decimator > 1 // precise_ratio isn't supposed to be below 1, but check just in case + && end_time > LLTimer::getTotalTime()) { sloppy_ratio = genMeshOptimizerPerModel(base, target_model, sloppy_decimator, lod_error_threshold, MESH_OPTIMIZER_NO_TOPOLOGY); sloppy_decimator = sloppy_decimator / sloppy_decimation_step; diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index c0d59dbfed..9ef304d08e 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -140,8 +140,7 @@ LLNetMap::LLNetMap (const Params & p) // [/SL:KB] mClosestAgentToCursor(), // mClosestAgentAtLastRightClick(), - mToolTipMsg(), - mPopupMenu(NULL) + mToolTipMsg() { // Fixing borked minimap zoom level persistance //mScale = gSavedSettings.getF32("MiniMapScale"); @@ -160,6 +159,13 @@ LLNetMap::LLNetMap (const Params & p) LLNetMap::~LLNetMap() { + auto menu = static_cast(mPopupMenuHandle.get()); + if (menu) + { + menu->die(); + mPopupMenuHandle.markDead(); + } + // Protect avatar name lookup callbacks for (avatar_name_cache_connection_map_t::iterator it = mAvatarNameCacheConnections.begin(); it != mAvatarNameCacheConnections.end(); ++it) { @@ -252,10 +258,9 @@ BOOL LLNetMap::postBuild() mParcelOverlayConn = LLViewerParcelOverlay::setUpdateCallback(boost::bind(&LLNetMap::refreshParcelOverlay, this)); // [/SL:KB] - mPopupMenu = LLUICtrlFactory::getInstance()->createFromFile("menu_mini_map.xml", gMenuHolder, - LLViewerMenuHolderGL::child_registry_t::instance()); - mPopupMenu->setItemEnabled("Re-center map", false); - + LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_mini_map.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); + mPopupMenuHandle = menu->getHandle(); + menu->setItemEnabled("Re-center map", false); return TRUE; } @@ -358,8 +363,12 @@ void LLNetMap::draw() mCentering = false; } - bool can_recenter_map = !(centered || mCentering || auto_centering); - mPopupMenu->setItemEnabled("Re-center map", can_recenter_map); + auto menu = static_cast(mPopupMenuHandle.get()); + if (menu) + { + bool can_recenter_map = !(centered || mCentering || auto_centering); + menu->setItemEnabled("Re-center map", can_recenter_map); + } updateAboutLandPopupButton(); // Prepare a scissor region @@ -1045,14 +1054,15 @@ void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color, bool LLNetMap::isMouseOnPopupMenu() { - if (!mPopupMenu->isOpen()) + auto menu = static_cast(mPopupMenuHandle.get()); + if (!menu || !menu->isOpen()) { return false; } S32 popup_x; S32 popup_y; - LLUI::getInstance()->getMousePositionLocal(mPopupMenu, &popup_x, &popup_y); + LLUI::getInstance()->getMousePositionLocal(menu, &popup_x, &popup_y); // *NOTE: Tolerance is larger than it needs to be because the context menu is offset from the mouse when the menu is opened from certain // directions. This may be a quirk of LLMenuGL::showPopup. -Cosmic,2022-03-22 constexpr S32 tolerance = 10; @@ -1063,7 +1073,7 @@ bool LLNetMap::isMouseOnPopupMenu() { for (S32 sign_y = -1; sign_y <= 1; sign_y += 2) { - if (mPopupMenu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance))) + if (menu->pointInView(popup_x + (sign_x * tolerance), popup_y + (sign_y * tolerance))) { return true; } @@ -1074,7 +1084,8 @@ bool LLNetMap::isMouseOnPopupMenu() void LLNetMap::updateAboutLandPopupButton() { - if (!mPopupMenu->isOpen()) + auto menu = static_cast(mPopupMenuHandle.get()); + if (!menu || !menu->isOpen()) { return; } @@ -1082,7 +1093,7 @@ void LLNetMap::updateAboutLandPopupButton() LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal(mPopupWorldPos); if (!region) { - mPopupMenu->setItemEnabled("About Land", false); + menu->setItemEnabled("About Land", false); } else { @@ -1097,7 +1108,7 @@ void LLNetMap::updateAboutLandPopupButton() { valid_parcel = hover_parcel->getOwnerID().notNull(); } - mPopupMenu->setItemEnabled("About Land", valid_parcel); + menu->setItemEnabled("About Land", valid_parcel); } } } @@ -1744,11 +1755,15 @@ void LLNetMap::setAvatarProfileLabel(const LLUUID& av_id, const LLAvatarName& av mAvatarNameCacheConnections.erase(it); } - LLMenuItemGL* pItem = mPopupMenu->findChild(item_name, TRUE /*recurse*/); - if (pItem) + auto menu = static_cast(mPopupMenuHandle.get()); + if (menu) { - pItem->setLabel(avName.getCompleteName()); - pItem->getMenu()->arrange(); + LLMenuItemGL* pItem = menu->findChild(item_name, TRUE /*recurse*/); + if (pItem) + { + pItem->setLabel(avName.getCompleteName()); + pItem->getMenu()->arrange(); + } } } @@ -1802,23 +1817,24 @@ void LLNetMap::handleTextureType(const LLSD& sdParam) const BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask) { - if (mPopupMenu) + auto menu = static_cast(mPopupMenuHandle.get()); + if (menu) { mPopupWorldPos = viewPosToGlobal(x, y); // [SL:KB] - Patch: World-MiniMap | Checked: 2012-07-08 (Catznip-3.3) mClosestAgentRightClick = mClosestAgentToCursor; mClosestAgentsRightClick = mClosestAgentsToCursor; - mPopupMenu->setItemVisible("Add to Set Multiple", mClosestAgentsToCursor.size() > 1); - mPopupMenu->setItemVisible("More Options", mClosestAgentsToCursor.size() == 1); - mPopupMenu->setItemVisible("View Profile", mClosestAgentsToCursor.size() == 1); + menu->setItemVisible("Add to Set Multiple", mClosestAgentsToCursor.size() > 1); + menu->setItemVisible("More Options", mClosestAgentsToCursor.size() == 1); + menu->setItemVisible("View Profile", mClosestAgentsToCursor.size() == 1); bool can_show_names = !RlvActions::hasBehaviour(RLV_BHVR_SHOWNAMES); - mPopupMenu->setItemEnabled("Add to Set Multiple", can_show_names); - mPopupMenu->setItemEnabled("More Options", can_show_names); - mPopupMenu->setItemEnabled("View Profile", can_show_names); + menu->setItemEnabled("Add to Set Multiple", can_show_names); + menu->setItemEnabled("More Options", can_show_names); + menu->setItemEnabled("View Profile", can_show_names); - LLMenuItemBranchGL* pProfilesMenu = mPopupMenu->getChild("View Profiles"); + LLMenuItemBranchGL* pProfilesMenu = menu->getChild("View Profiles"); if (pProfilesMenu) { pProfilesMenu->setVisible(mClosestAgentsToCursor.size() > 1); @@ -1857,22 +1873,22 @@ BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask) pProfilesMenu->getBranch()->addChild(pMenuItem); } } - mPopupMenu->setItemVisible("Cam", LLAvatarActions::canZoomIn(mClosestAgentToCursor)); - mPopupMenu->setItemVisible("MarkAvatar", mClosestAgentToCursor.notNull()); - mPopupMenu->setItemVisible("Start Tracking", mClosestAgentToCursor.notNull()); - mPopupMenu->setItemVisible("Profile Separator", (mClosestAgentsToCursor.size() >= 1 || mClosestAgentToCursor.notNull())); - mPopupMenu->setItemEnabled("Place Profile", RlvActions::canShowLocation()); - mPopupMenu->setItemEnabled("World Map", !RlvActions::hasBehaviour(RLV_BHVR_SHOWWORLDMAP)); + menu->setItemVisible("Cam", LLAvatarActions::canZoomIn(mClosestAgentToCursor)); + menu->setItemVisible("MarkAvatar", mClosestAgentToCursor.notNull()); + menu->setItemVisible("Start Tracking", mClosestAgentToCursor.notNull()); + menu->setItemVisible("Profile Separator", (mClosestAgentsToCursor.size() >= 1 || mClosestAgentToCursor.notNull())); + menu->setItemEnabled("Place Profile", RlvActions::canShowLocation()); + menu->setItemEnabled("World Map", !RlvActions::hasBehaviour(RLV_BHVR_SHOWWORLDMAP)); // [/SL:KB] - mPopupMenu->buildDrawLabels(); - mPopupMenu->updateParent(LLMenuGL::sMenuContainer); + menu->buildDrawLabels(); + menu->updateParent(LLMenuGL::sMenuContainer); // [SL:KB] - Patch: World-MiniMap | Checked: 2012-07-08 (Catznip-3.3) - mPopupMenu->setItemVisible("Stop Tracking", LLTracker::isTracking(0)); - mPopupMenu->setItemVisible("Stop Tracking Separator", LLTracker::isTracking(0)); + menu->setItemVisible("Stop Tracking", LLTracker::isTracking(0)); + menu->setItemVisible("Stop Tracking Separator", LLTracker::isTracking(0)); // [/SL:KB] -// mPopupMenu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0)); - LLMenuGL::showPopup(this, mPopupMenu, x, y); +// menu->setItemEnabled("Stop Tracking", LLTracker::isTracking(0)); + LLMenuGL::showPopup(this, menu, x, y); } return TRUE; } @@ -2127,11 +2143,12 @@ void LLNetMap::handleStartTracking() void LLNetMap::handleStopTracking (const LLSD& userdata) { - if (mPopupMenu) + auto menu = static_cast(mPopupMenuHandle.get()); + if (menu) { // Hide tracking option instead of disabling - //mPopupMenu->setItemEnabled ("Stop Tracking", false); - mPopupMenu->setItemVisible ("Stop Tracking", false); + //menu->setItemEnabled ("Stop Tracking", false); + menu->setItemVisible ("Stop Tracking", false); // LLTracker::stopTracking (LLTracker::isTracking(NULL)); } diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index f2de5a91fe..957cd43716 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -266,7 +266,7 @@ private: void handleEstateBan(); void handleDerender(bool permanent); - LLMenuGL* mPopupMenu; + LLHandle mPopupMenuHandle; uuid_vec_t gmSelected; }; diff --git a/indra/newview/llnotificationlistitem.cpp b/indra/newview/llnotificationlistitem.cpp index cbfd3fcc2d..871e8228da 100644 --- a/indra/newview/llnotificationlistitem.cpp +++ b/indra/newview/llnotificationlistitem.cpp @@ -556,8 +556,6 @@ void LLGroupNoticeNotificationListItem::close() void LLGroupNoticeNotificationListItem::onClickAttachment() { if (mInventoryOffer != NULL) { - mInventoryOffer->forceResponse(IOR_ACCEPT); - static const LLUIColor textColor = LLUIColorTable::instance().getColor( "GroupNotifyDimmedTextColor"); mAttachmentTextBox->setColor(textColor); @@ -567,7 +565,7 @@ void LLGroupNoticeNotificationListItem::onClickAttachment() if (!isAttachmentOpenable(mInventoryOffer->mType)) { LLNotifications::instance().add("AttachmentSaved", LLSD(), LLSD()); } - + mInventoryOffer->forceResponse(IOR_ACCEPT); mInventoryOffer = NULL; } } diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp index 4b9f177eca..14eebf40f3 100644 --- a/indra/newview/lloutfitgallery.cpp +++ b/indra/newview/lloutfitgallery.cpp @@ -1226,7 +1226,7 @@ void LLOutfitGallery::uploadOutfitImage(const std::vector& filename checkRemovePhoto(outfit_id); std::string upload_pending_name = outfit_id.asString(); std::string upload_pending_desc = ""; - LLUUID photo_id = upload_new_resource(filename, // file + upload_new_resource(filename, // file upload_pending_name, upload_pending_desc, 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE, diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp index e0c79b58eb..c0074fd2f9 100644 --- a/indra/newview/lloutfitslist.cpp +++ b/indra/newview/lloutfitslist.cpp @@ -894,8 +894,7 @@ void LLOutfitListBase::onOpen(const LLSD& info) mCategoriesObserver->addCategory(outfits, boost::bind(&LLOutfitListBase::refreshList, this, outfits)); - const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); - + //const LLUUID cof = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT); // Start observing changes in Current Outfit category. //mCategoriesObserver->addCategory(cof, boost::bind(&LLOutfitsList::onCOFChanged, this)); diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index 4ec757a9c2..d384de1123 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -1892,7 +1892,7 @@ void LLPanelEditWearable::onClickedImportBtnCallback(const std::vectorsetEnabled( can_change_media && allow_resize ); - LLUUID tmp = parcel->getMediaID(); mMediaTextureCtrl->setImageAssetID ( parcel->getMediaID() ); mMediaTextureCtrl->setEnabled( can_change_media ); diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index c047e0430a..0fb500f7e2 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -424,6 +424,13 @@ LLPanelMainInventory::~LLPanelMainInventory( void ) gInventory.removeObserver(this); delete mSavedFolderState; + + auto menu = mMenuAddHandle.get(); + if(menu) + { + menu->die(); + mMenuAddHandle.markDead(); + } } LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel() @@ -1629,13 +1636,12 @@ void LLPanelMainInventory::initListCommandsHandlers() mEnableCallbackRegistrar.add("Inventory.GearDefault.Check", boost::bind(&LLPanelMainInventory::isActionChecked, this, _2)); mEnableCallbackRegistrar.add("Inventory.GearDefault.Enable", boost::bind(&LLPanelMainInventory::isActionEnabled, this, _2)); mMenuGearDefault = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_gear_default.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mGearMenuButton->setMenu(mMenuGearDefault); + mGearMenuButton->setMenu(mMenuGearDefault, LLMenuButton::MP_TOP_LEFT, true); LLMenuGL* menu = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_add.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); mMenuAddHandle = menu->getHandle(); mMenuVisibility = LLUICtrlFactory::getInstance()->createFromFile("menu_inventory_search_visibility.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance()); - mVisibilityMenuButton->setMenu(mMenuVisibility); - mVisibilityMenuButton->setMenuPosition(LLMenuButton::MP_BOTTOM_LEFT); + mVisibilityMenuButton->setMenu(mMenuVisibility, LLMenuButton::MP_BOTTOM_LEFT, true); // Update the trash button when selected item(s) get worn or taken off. LLOutfitObserver::instance().addCOFChangedCallback(boost::bind(&LLPanelMainInventory::updateListCommands, this)); diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 1bb133734b..8f9bb63522 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -2783,7 +2783,7 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) // } // else if (command == "params_paste") // { -// return mHasClipboardParams; +// return mClipboardParams.isMap() && (mClipboardParams.size() != 0); // } // // copy options // else if (command == "psr_copy") diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp index d4dea894b7..01eda70ef4 100644 --- a/indra/newview/llpanelobjectinventory.cpp +++ b/indra/newview/llpanelobjectinventory.cpp @@ -1438,7 +1438,8 @@ LLPanelObjectInventory::LLPanelObjectInventory(const LLPanelObjectInventory::Par mHaveInventory(FALSE), mIsInventoryEmpty(TRUE), mInventoryNeedsUpdate(FALSE), - mInventoryViewModel(p.name) + mInventoryViewModel(p.name), + mShowRootFolder(p.show_root_folder) { // Setup context menu callbacks mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLPanelObjectInventory::doToSelected, this, _2)); @@ -1535,6 +1536,7 @@ void LLPanelObjectInventory::reset() mFolders = LLUICtrlFactory::create(p); mFolders->setCallbackRegistrar(&mCommitCallbackRegistrar); + mFolders->setEnableRegistrar(&mEnableCallbackRegistrar); if (hasFocus()) { @@ -1710,15 +1712,23 @@ void LLPanelObjectInventory::createFolderViews(LLInventoryObject* inventory_root // LLFolderViewFolder* new_folder = LLUICtrlFactory::create(p); - new_folder->addToFolder(mFolders); - new_folder->toggleOpen(); + + if (mShowRootFolder) + { + new_folder->addToFolder(mFolders); + new_folder->toggleOpen(); + } if (!contents.empty()) { - createViewsForCategory(&contents, inventory_root, new_folder); + createViewsForCategory(&contents, inventory_root, mShowRootFolder ? new_folder : mFolders); } - // Refresh for label to add item count - new_folder->refresh(); + + if (mShowRootFolder) + { + // Refresh for label to add item count + new_folder->refresh(); + } } } diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h index 22dadeee7c..bcf5c567f9 100644 --- a/indra/newview/llpanelobjectinventory.h +++ b/indra/newview/llpanelobjectinventory.h @@ -48,8 +48,14 @@ class LLViewerObject; class LLPanelObjectInventory : public LLPanel, public LLVOInventoryListener { public: - // dummy param block for template registration purposes - struct Params : public LLPanel::Params {}; + struct Params : public LLInitParam::Block + { + Optional show_root_folder; + + Params() + : show_root_folder("show_root_folder", true) + {} + }; LLPanelObjectInventory(const Params&); virtual ~LLPanelObjectInventory(); @@ -113,6 +119,7 @@ private: BOOL mIsInventoryEmpty; // 'Empty' label BOOL mInventoryNeedsUpdate; // for idle, set on changed callback LLFolderViewModelInventory mInventoryViewModel; + bool mShowRootFolder; }; #endif // LL_LLPANELOBJECTINVENTORY_H diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index ec953552f2..dd33202980 100644 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -853,7 +853,6 @@ void LLPanelPlaces::onSaveButtonClicked() LLStringUtil::trim(current_title_value); LLStringUtil::trim(current_notes_value); - LLUUID item_id = mItem->getUUID(); LLUUID folder_id = mLandmarkInfo->getLandmarkFolder(); bool change_parent = folder_id != mItem->getParentUUID(); diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 48dc4f547f..d213e8e535 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -81,6 +81,7 @@ #include "llviewernetwork.h" // For LLGridManager #include "fsdata.h" +#include "fsradar.h" // Update notes in radar when edited #include "llviewermenu.h" static LLPanelInjector t_panel_profile_secondlife("panel_profile_secondlife"); @@ -496,6 +497,30 @@ public: // requires trusted browser to trigger LLAgentHandler() : LLCommandHandler("agent", UNTRUSTED_THROTTLE) { } + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 2) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED) + { + return true; + } + + const std::string verb = params[1].asString(); + if (verb == "about" || verb == "inspect" || verb == "reportAbuse") + { + return true; + } + return false; + } + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { @@ -1237,7 +1262,6 @@ void LLPanelProfileSecondLife::resetData() void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) { - LLUUID avatar_id = getAvatarId(); const LLRelationship* relationship = LLAvatarTracker::instance().getBuddyInfo(getAvatarId()); if ((relationship != NULL || gAgent.isGodlike()) && !getSelfProfile()) { @@ -1267,7 +1291,7 @@ void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avat #ifdef OPENSIM if (LLGridManager::instance().isInOpenSim()) { - LLFloater* floater_profile = LLFloaterReg::findInstance("profile", LLSD().with("id", avatar_id)); + LLFloater* floater_profile = LLFloaterReg::findInstance("profile", LLSD().with("id", getAvatarId())); if (!floater_profile) { // floater is dead, so panels are dead as well @@ -1592,6 +1616,8 @@ void LLPanelProfileSecondLife::fillRightsData() void LLPanelProfileSecondLife::fillAgeData(const LLDate &born_on) { // Fix LL UI/UX design accident + //// Date from server comes already converted to stl timezone, + //// so display it as an UTC + 0 //std::string name_and_date = getString("date_format"); //LLSD args_name; //args_name["datetime"] = (S32)born_on.secondsSinceEpoch(); @@ -3145,6 +3171,8 @@ void LLPanelProfileNotes::onSaveNotesChanges() LL_WARNS("AvatarProperties") << "Failed to update profile data, no cap found" << LL_ENDL; } + FSRadar::getInstance()->updateNotes(getAvatarId(), mCurrentNotes); // Update notes in radar when edited + mSaveChanges->setEnabled(FALSE); mDiscardChanges->setEnabled(FALSE); mHasUnsavedChanges = false; diff --git a/indra/newview/llpanelprofileclassifieds.cpp b/indra/newview/llpanelprofileclassifieds.cpp index e05bf6993e..2be077de0b 100644 --- a/indra/newview/llpanelprofileclassifieds.cpp +++ b/indra/newview/llpanelprofileclassifieds.cpp @@ -83,6 +83,30 @@ public: std::set mClassifiedIds; std::string mRequestVerb; + + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 1) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED) + { + return true; + } + + const std::string verb = params[0].asString(); + if (verb == "create") + { + return false; + } + return true; + } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llpanelprofilepicks.cpp b/indra/newview/llpanelprofilepicks.cpp index f5ef2ca7a0..386bd5a3e8 100644 --- a/indra/newview/llpanelprofilepicks.cpp +++ b/indra/newview/llpanelprofilepicks.cpp @@ -65,6 +65,30 @@ public: // requires trusted browser to trigger LLPickHandler() : LLCommandHandler("pick", UNTRUSTED_THROTTLE) { } + virtual bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) + { + if (params.size() < 1) + { + return true; // don't block, will fail later + } + + if (nav_type == NAV_TYPE_CLICKED) + { + return true; + } + + const std::string verb = params[0].asString(); + if (verb == "create") + { + return false; + } + return true; + } + bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) { diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index b3a947c5fe..1c4f1f646b 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -317,7 +317,7 @@ void LLPreviewNotecard::loadAsset() else { LLHost source_sim = LLHost(); - LLSD* user_data = new LLSD(); + LLSD* user_data = nullptr; if (mObjectUUID.notNull()) { LLViewerObject *objectp = gObjectList.findObject(mObjectUUID); @@ -336,6 +336,7 @@ void LLPreviewNotecard::loadAsset() mAssetStatus = PREVIEW_ASSET_LOADED; return; } + user_data = new LLSD(); user_data->with("taskid", mObjectUUID).with("itemid", mItemUUID); } else diff --git a/indra/newview/llpreviewscript.h b/indra/newview/llpreviewscript.h index 659a603440..3a0689c3d8 100644 --- a/indra/newview/llpreviewscript.h +++ b/indra/newview/llpreviewscript.h @@ -177,7 +177,9 @@ private: bool enableAction(const std::string& action); // NaCl End void onBtnHelp(); // Keep help links +public: // Show keyword help on F1 void onBtnDynamicHelp(); +private: // Show keyword help on F1 void onBtnUndoChanges(); bool hasChanged(); diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp index 815f5e5d82..8eb734cc0a 100644 --- a/indra/newview/llscenemonitor.cpp +++ b/indra/newview/llscenemonitor.cpp @@ -515,7 +515,7 @@ void LLSceneMonitor::fetchQueryResult() } //dump results to a file _scene_xmonitor_results.csv -void LLSceneMonitor::dumpToFile(std::string file_name) +void LLSceneMonitor::dumpToFile(const std::string &file_name) { if (!hasResults()) return; diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h index fcfd5ccc64..82db9dc552 100644 --- a/indra/newview/llscenemonitor.h +++ b/indra/newview/llscenemonitor.h @@ -61,7 +61,7 @@ public: bool needsUpdate() const; const LLTrace::ExtendablePeriodicRecording* getRecording() const {return &mSceneLoadRecording;} - void dumpToFile(std::string file_name); + void dumpToFile(const std::string &file_name); bool hasResults() const { return mSceneLoadRecording.getResults().getDuration() != S32Seconds(0);} void reset(); diff --git a/indra/newview/llscripteditor.cpp b/indra/newview/llscripteditor.cpp index 4b71be92d9..9730c1f7a0 100644 --- a/indra/newview/llscripteditor.cpp +++ b/indra/newview/llscripteditor.cpp @@ -31,6 +31,8 @@ #include "llsyntaxid.h" #include "lllocalcliprect.h" +#include "llpreviewscript.h" + // FIRE-23047: Increase width of line number column //const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 32; const S32 UI_TEXTEDITOR_LINE_NUMBER_MARGIN = 40; @@ -283,3 +285,19 @@ void LLScriptEditor::startOfLine() } } // + +// Show keyword help on F1 +BOOL LLScriptEditor::handleKeyHere(KEY key, MASK mask) +{ + if (key == KEY_F1 && mask == MASK_NONE) + { + if (LLScriptEdCore* parent = getParentByType(); parent != nullptr) + { + parent->onBtnDynamicHelp(); + return TRUE; + } + } + + return LLTextEditor::handleKeyHere(key, mask); +} +// diff --git a/indra/newview/llscripteditor.h b/indra/newview/llscripteditor.h index 795871ca45..088d9e7f10 100644 --- a/indra/newview/llscripteditor.h +++ b/indra/newview/llscripteditor.h @@ -74,6 +74,9 @@ private: // Doesn't exist //void loadKeywords(const std::string& filename_keywords, // const std::string& filename_colors); + + // Show keyword help on F1 + /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); LLKeywords mKeywords; bool mShowLineNumbers; diff --git a/indra/newview/llscriptfloater.cpp b/indra/newview/llscriptfloater.cpp index 16b52a2d0b..812ec015f5 100644 --- a/indra/newview/llscriptfloater.cpp +++ b/indra/newview/llscriptfloater.cpp @@ -559,11 +559,11 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) if(it != mNotifications.end()) { - auto old_id = it->first; // store UUID to prevent use after free - Rye + LLUUID old_id = it->first; // copy LLUUID to prevent use after free when it is erased below LLChicletPanel * chiclet_panelp = LLChicletBar::getInstance()->getChicletPanel(); if (NULL != chiclet_panelp) { - LLIMChiclet * chicletp = chiclet_panelp->findChiclet(old_id); // avoid use after free - Rye + LLIMChiclet * chicletp = chiclet_panelp->findChiclet(old_id); if (NULL != chicletp) { // Pass the new_message icon state further. @@ -572,7 +572,7 @@ void LLScriptFloaterManager::onAddNotification(const LLUUID& notification_id) } } - LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", old_id); // avoid use after free - Rye + LLScriptFloater* floater = LLFloaterReg::findTypedInstance("script_floater", old_id); if (floater) { // Generate chiclet with a "new message" indicator if a docked window was opened but not in focus. See EXT-3142. diff --git a/indra/newview/llsettingsvo.cpp b/indra/newview/llsettingsvo.cpp index 0c1f6b49d8..b1eed81476 100644 --- a/indra/newview/llsettingsvo.cpp +++ b/indra/newview/llsettingsvo.cpp @@ -694,12 +694,8 @@ void LLSettingsVOSky::applySpecial(void *ptarget, bool force) LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - // Fix array out of bounds on assigning LLColor3() to llVector4() - // LLVector4 sunDiffuse = LLVector4(psky->getSunlightColor().mV); - // LLVector4 moonDiffuse = LLVector4(psky->getMoonlightColor().mV); LLVector4 sunDiffuse = LLVector4(LLVector3(psky->getSunlightColor().mV)); LLVector4 moonDiffuse = LLVector4(LLVector3(psky->getMoonlightColor().mV)); - // shader->uniform4fv(LLShaderMgr::SUNLIGHT_COLOR, sunDiffuse); shader->uniform4fv(LLShaderMgr::MOONLIGHT_COLOR, moonDiffuse); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index 3daabfe0c7..935afbf86b 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -995,7 +995,6 @@ void LLActiveSpeakerMgr::updateSpeakerList() // clean up text only speakers for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) { - LLUUID speaker_id = speaker_it->first; LLSpeaker* speakerp = speaker_it->second; if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) { diff --git a/indra/newview/llspeakingindicatormanager.cpp b/indra/newview/llspeakingindicatormanager.cpp index 5ca1d4b4a5..0111d8869c 100644 --- a/indra/newview/llspeakingindicatormanager.cpp +++ b/indra/newview/llspeakingindicatormanager.cpp @@ -51,6 +51,10 @@ class SpeakingIndicatorManager : public LLSingleton, L LLSINGLETON(SpeakingIndicatorManager); ~SpeakingIndicatorManager(); LOG_CLASS(SpeakingIndicatorManager); + +protected: + void cleanupSingleton(); + public: /** @@ -183,12 +187,16 @@ SpeakingIndicatorManager::SpeakingIndicatorManager() SpeakingIndicatorManager::~SpeakingIndicatorManager() { - // Don't use LLVoiceClient::getInstance() here without check - // singleton MAY have already been destroyed. - if(LLVoiceClient::instanceExists()) - { - LLVoiceClient::getInstance()->removeObserver(this); - } +} + +void SpeakingIndicatorManager::cleanupSingleton() +{ + // Don't use LLVoiceClient::getInstance() here without a check, + // singleton MAY have already been destroyed. + if (LLVoiceClient::instanceExists()) + { + LLVoiceClient::getInstance()->removeObserver(this); + } } void SpeakingIndicatorManager::sOnCurrentChannelChanged(const LLUUID& /*session_id*/) diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 3812fcc8fd..08f91eede6 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -319,12 +319,10 @@ void show_release_notes_if_required(); bool first_run_dialog_callback(const LLSD& notification, const LLSD& response); void set_startup_status(const F32 frac, const std::string& string, const std::string& msg); bool login_alert_status(const LLSD& notification, const LLSD& response); -void login_packet_failed(void**, S32 result); void use_circuit_callback(void**, S32 result); void register_viewer_callbacks(LLMessageSystem* msg); void asset_callback_nothing(const LLUUID&, LLAssetType::EType, void*, S32); bool callback_choose_gender(const LLSD& notification, const LLSD& response); -void init_start_screen(S32 location_id); void release_start_screen(); void reset_login(); LLSD transform_cert_args(LLPointer cert); diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index e509b94c71..be1bcb3e43 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -93,6 +93,7 @@ LLButton* LLToastNotifyPanel::createButton(const LLSD& form_element, BOOL is_opt const LLFontGL* font = make_small_btn ? sFontSmall: sFont; // for block and ignore buttons in script dialog p.name = form_element["name"].asString(); p.label = form_element["text"].asString(); + p.tool_tip = form_element["text"].asString(); p.font = font; p.rect.height = BTN_HEIGHT; p.click_callback.function(boost::bind(&LLToastNotifyPanel::onClickButton, userdata)); diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index 010b9d128a..3c73ed7857 100644 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -44,7 +44,6 @@ #include "llagent.h" // HACK for destinations guide on startup #include "llfloaterreg.h" // HACK for destinations guide on startup #include "llviewercontrol.h" // HACK for destinations guide on startup -#include "llinventorymodel.h" // HACK to disable starter avatars button for NUX #include @@ -383,22 +382,6 @@ bool LLToolBarView::loadToolbars(bool force_default) } } } - - // SL-18581: Don't show the starter avatar toolbar button for NUX users - LLViewerInventoryCategory* my_outfits_cat = gInventory.getCategory(gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS)); - if (gAgent.isFirstLogin() - && my_outfits_cat != NULL - && my_outfits_cat->getDescendentCount() > 0) - { - for (S32 i = LLToolBarEnums::TOOLBAR_FIRST; i <= LLToolBarEnums::TOOLBAR_LAST; i++) - { - if (mToolbars[i]) - { - mToolbars[i]->removeCommand(LLCommandId("avatar")); - } - } - } - mToolbarsLoaded = true; return true; } diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp index 2930c46bcc..5e231a8698 100644 --- a/indra/newview/llurldispatcher.cpp +++ b/indra/newview/llurldispatcher.cpp @@ -328,7 +328,7 @@ public: // inside the app, otherwise a malicious web page could // cause a constant teleport loop. JC LLTeleportHandler() : - LLCommandHandler("teleport", UNTRUSTED_THROTTLE), + LLCommandHandler("teleport", UNTRUSTED_CLICK_ONLY), LLEventAPI("LLTeleportHandler", "Low-level teleport API") { LLEventAPI::add("teleport", diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index 5bfaac1bfc..86ed25b744 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -230,11 +230,103 @@ const std::string FLOATER_PROFILE("profile"); class LLFloaterOpenHandler : public LLCommandHandler { public: - // requires trusted browser to trigger + // requires trusted browser to trigger or an explicit click LLFloaterOpenHandler() : LLCommandHandler("openfloater", UNTRUSTED_THROTTLE) { } - bool handle(const LLSD& params, const LLSD& query_map, - LLMediaCtrl* web) + bool canHandleUntrusted( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web, + const std::string& nav_type) override + { + if (params.size() != 1) + { + return true; // will fail silently + } + + std::string fl_name = params[0].asString(); + + if (nav_type == NAV_TYPE_CLICKED) + { + const std::list blacklist_clicked = { + "camera_presets", + "delete_pref_preset", + "forget_username", + "god_tools", + "group_picker", + "hud", + "incoming_call", + "linkreplace", + "message_critical", // Modal!!! Login specific. + "message_tos", // Modal!!! Login specific. + "save_pref_preset", + "save_camera_preset", + "region_restarting", + "outfit_snapshot", + "upload_anim_bvh", + "upload_anim_anim", + "upload_image", + "upload_model", + "upload_script", + "upload_sound" + }; + return std::find(blacklist_clicked.begin(), blacklist_clicked.end(), fl_name) == blacklist_clicked.end(); + } + else + { + const std::list blacklist_untrusted = { + "360capture", + "block_timers", + "add_payment_method", + "appearance", + "associate_listing", + "avatar_picker", + "camera", + "camera_presets", + "classified", + "add_landmark", + "delete_pref_preset", + "env_fixed_environmentent_water", + "env_fixed_environmentent_sky", + "env_edit_extdaycycle", + "font_test", + "forget_username", + "god_tools", + "group_picker", + "hud", + "incoming_call", + "linkreplace", + "mem_leaking", + "marketplace_validation", + "message_critical", // Modal!!! Login specific. If this is in use elsewhere, better to create a non modal variant + "message_tos", // Modal!!! Login specific. + "mute_object_by_name", + "publish_classified", + "save_pref_preset", + "save_camera_preset", + "region_restarting", + "script_debug", + "script_debug_output", + "sell_land", + "outfit_snapshot", + "upload_anim_bvh", + "upload_anim_anim", + "upload_image", + "upload_model", + "upload_script", + "upload_sound" + }; + return std::find(blacklist_untrusted.begin(), blacklist_untrusted.end(), fl_name) == blacklist_untrusted.end(); + } + + + return true; + } + + bool handle( + const LLSD& params, + const LLSD& query_map, + LLMediaCtrl* web) override { if (params.size() != 1) { diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp index 881a7df71a..df68909ffc 100644 --- a/indra/newview/llviewerinput.cpp +++ b/indra/newview/llviewerinput.cpp @@ -1707,12 +1707,22 @@ BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask, clicktype = CLICK_DOUBLELEFT; } + // If the first LMB click is handled by the menu, skip the following double click + static bool skip_double_click = false; + if (clicktype == CLICK_LEFT && down ) + { + skip_double_click = handled; + } if (double_click_sp && down) { // Consume click. // Due to handling, double click that is not handled will be immediately followed by LMB click } + else if (clicktype == CLICK_DOUBLELEFT && skip_double_click) + { + handled = true; + } // If UI handled 'down', it should handle 'up' as well // If we handle 'down' not by UI, then we should handle 'up'/'level' regardless of UI else if (handled) diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 3cdf8bb86d..04b2b1de68 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -235,7 +235,7 @@ class LLInventoryHandler : public LLCommandHandler { public: // requires trusted browser to trigger - LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_THROTTLE) { } + LLInventoryHandler() : LLCommandHandler("inventory", UNTRUSTED_CLICK_ONLY) { } bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 3e74e96692..ce44acab71 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3460,14 +3460,15 @@ bool enable_object_show_original() } // -static void init_default_item_label(const std::string& item_name) +static void init_default_item_label(LLUICtrl* ctrl) { + const std::string& item_name = ctrl->getName(); boost::unordered_map::iterator it = sDefaultItemLabels.find(item_name); if (it == sDefaultItemLabels.end()) { // *NOTE: This will not work for items of type LLMenuItemCheckGL because they return boolean value // (doesn't seem to matter much ATM). - LLStringExplicit default_label = gMenuHolder->childGetValue(item_name).asString(); + LLStringExplicit default_label = ctrl->getValue().asString(); if (!default_label.empty()) { sDefaultItemLabels.insert(std::pair(item_name, default_label)); @@ -3506,18 +3507,17 @@ bool enable_object_touch(LLUICtrl* ctrl) } // [/RLVa:KB] - std::string item_name = ctrl->getName(); - init_default_item_label(item_name); + init_default_item_label(ctrl); // Update label based on the node touch name if available. LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if (node && node->mValid && !node->mTouchName.empty()) { - gMenuHolder->childSetValue(item_name, node->mTouchName); + ctrl->setValue(node->mTouchName); } else { - gMenuHolder->childSetValue(item_name, get_default_item_label(item_name)); + ctrl->setValue(get_default_item_label(ctrl->getName())); } return new_value; @@ -6922,9 +6922,6 @@ class LLToolsSelectNextPartFace : public view_listener_t } } LLSelectMgr::getInstance()->selectObjectOnly(to_select, new_te); - - // Add this back in additionally to selectObjectOnly() to get the lastOperadedTE() - // function back working to properly shift+cycle through faces LLSelectMgr::getInstance()->addAsIndividual(to_select, new_te, false); } else @@ -8162,20 +8159,18 @@ bool enable_object_sit(LLUICtrl* ctrl) bool sitting_on_sel = sitting_on_selection(); if (!sitting_on_sel) { - std::string item_name = ctrl->getName(); - // init default labels - init_default_item_label(item_name); + init_default_item_label(ctrl); // Update label LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstRootNode(); if (node && node->mValid && !node->mSitName.empty()) { - gMenuHolder->childSetValue(item_name, node->mSitName); + ctrl->setValue(node->mSitName); } else { - gMenuHolder->childSetValue(item_name, get_default_item_label(item_name)); + ctrl->setValue(get_default_item_label(ctrl->getName())); } } @@ -9538,7 +9533,6 @@ void handle_selected_texture_info(void*) map_t::iterator it; for (it = faces_per_texture.begin(); it != faces_per_texture.end(); ++it) { - LLUUID image_id = it->first; U8 te = it->second[0]; LLViewerTexture* img = node->getObject()->getTEImage(te); S32 height = img->getHeight(); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index aa94093717..724280469a 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -3366,36 +3366,39 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) return; } - LLFilenameAndTask* ft = new LLFilenameAndTask; - ft->mTaskID = task_id; // we can receive multiple task updates simultaneously, make sure we will not rewrite newer with older update - msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, ft->mSerial); + S16 serial = 0; + msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, serial); - if (ft->mSerial == object->mInventorySerialNum - && ft->mSerial < object->mExpectedInventorySerialNum) + if (serial == object->mInventorySerialNum + && serial < object->mExpectedInventorySerialNum) { // Loop Protection. // We received same serial twice. // Viewer did some changes to inventory that couldn't be saved server side // or something went wrong to cause serial to be out of sync. // Drop xfer and restart after some time, assign server's value as expected - LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << ft->mSerial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL; - object->mExpectedInventorySerialNum = ft->mSerial; + LL_WARNS() << "Task inventory serial might be out of sync, server serial: " << serial << " client expected serial: " << object->mExpectedInventorySerialNum << LL_ENDL; + object->mExpectedInventorySerialNum = serial; object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_DESYNC); } - else if (ft->mSerial < object->mExpectedInventorySerialNum) + else if (serial < object->mExpectedInventorySerialNum) { // Out of date message, record to current serial for loop protection, but do not load it // Drop xfer and restart after some time - if (ft->mSerial < object->mInventorySerialNum) + if (serial < object->mInventorySerialNum) { LL_WARNS() << "Task serial decreased. Potentially out of order packet or desync." << LL_ENDL; } - object->mInventorySerialNum = ft->mSerial; + object->mInventorySerialNum = serial; object->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_OUTDATED); } - else if (ft->mSerial >= object->mExpectedInventorySerialNum) + else if (serial >= object->mExpectedInventorySerialNum) { + LLFilenameAndTask* ft = new LLFilenameAndTask; + ft->mTaskID = task_id; + ft->mSerial = serial; + // We received version we expected or newer. Load it. object->mInventorySerialNum = ft->mSerial; object->mExpectedInventorySerialNum = ft->mSerial; @@ -3430,7 +3433,7 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) object->mRegionp->getHost(), TRUE, &LLViewerObject::processTaskInvFile, - (void**)ft, + (void**)ft, // This takes ownership of ft LLXferManager::HIGH_PRIORITY); if (object->mInvRequestState == INVENTORY_XFER) { diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index f042040e98..1751ee1ebb 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -793,7 +793,7 @@ void LLViewerPartSourceBeam::update(const F32 dt) } LLViewerPart* part = new LLViewerPart(); - part->init(this, mImagep, NULL); + part->init(this, mImagep, updatePart); part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index bfe83fe944..d5e04767f6 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -1341,7 +1341,6 @@ bool LLViewerTextEditor::onCopyToInvDialog(const LLSD& notification, const LLSD& S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if( 0 == option ) { - LLUUID item_id = notification["payload"]["item_id"].asUUID(); llwchar wc = llwchar(notification["payload"]["item_wc"].asInteger()); LLInventoryItem* itemp = LLEmbeddedItems::getEmbeddedItemPtr(wc); if (itemp) diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index b8f91d2dff..7c82bfd23b 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1409,7 +1409,6 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi TRUE /* pick_transparent */, FALSE /* pick_rigged */); - LLUUID object_id = pick_info.getObjectID(); S32 object_face = pick_info.mObjectFace; std::string url = data; @@ -3921,6 +3920,59 @@ void LLViewerWindow::updateUI() root_view = mRootView; } + static LLCachedControl dump_menu_holder(gSavedSettings, "DumpMenuHolderSize", false); + if (dump_menu_holder) + { + static bool init = false; + static LLFrameTimer child_count_timer; + static std::vector child_vec; + if (!init) + { + child_count_timer.resetWithExpiry(5.f); + init = true; + } + if (child_count_timer.hasExpired()) + { + LL_INFOS() << "gMenuHolder child count: " << gMenuHolder->getChildCount() << LL_ENDL; + std::vector local_child_vec; + LLView::child_list_t child_list = *gMenuHolder->getChildList(); + for (auto child : child_list) + { + local_child_vec.emplace_back(child->getName()); + } + if (!local_child_vec.empty() && local_child_vec != child_vec) + { + std::vector out_vec; + std::sort(local_child_vec.begin(), local_child_vec.end()); + std::sort(child_vec.begin(), child_vec.end()); + std::set_difference(child_vec.begin(), child_vec.end(), local_child_vec.begin(), local_child_vec.end(), std::inserter(out_vec, out_vec.begin())); + if (!out_vec.empty()) + { + LL_INFOS() << "gMenuHolder removal diff size: '"<singletoneInstanceExists()) mVoiceModule->removeObserver(observer); + if (mVoiceModule) + { + mVoiceModule->removeObserver(observer); + } } void LLVoiceClient::addObserver(LLFriendObserver* observer) @@ -865,7 +868,10 @@ void LLVoiceClient::addObserver(LLFriendObserver* observer) void LLVoiceClient::removeObserver(LLFriendObserver* observer) { - if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer); + if (mVoiceModule) + { + mVoiceModule->removeObserver(observer); + } } void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer) @@ -875,7 +881,10 @@ void LLVoiceClient::addObserver(LLVoiceClientParticipantObserver* observer) void LLVoiceClient::removeObserver(LLVoiceClientParticipantObserver* observer) { - if (mVoiceModule && mVoiceModule->singletoneInstanceExists()) mVoiceModule->removeObserver(observer); + if (mVoiceModule) + { + mVoiceModule->removeObserver(observer); + } } std::string LLVoiceClient::sipURIFromID(const LLUUID &id) diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 50fc6d1da5..b4896aba8b 100644 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -125,8 +125,6 @@ public: virtual const LLVoiceVersionInfo& getVersion()=0; - virtual bool singletoneInstanceExists()=0; - ///////////////////// /// @name Tuning //@{ diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp index 384c416c0f..a86ec254c4 100644 --- a/indra/newview/llvoicevivox.cpp +++ b/indra/newview/llvoicevivox.cpp @@ -5377,11 +5377,6 @@ void LLVivoxVoiceClient::declineInvite(std::string &sessionHandle) } } -bool LLVivoxVoiceClient::singletoneInstanceExists() -{ - return LLVivoxVoiceClient::instanceExists(); -} - void LLVivoxVoiceClient::leaveNonSpatialChannel() { LL_DEBUGS("Voice") << "Request to leave spacial channel." << LL_ENDL; diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h index 343bd2f8c8..2097b71192 100644 --- a/indra/newview/llvoicevivox.h +++ b/indra/newview/llvoicevivox.h @@ -73,8 +73,6 @@ public: // Returns true if vivox has successfully logged in and is not in error state virtual bool isVoiceWorking() const; - - virtual bool singletoneInstanceExists(); ///////////////////// /// @name Tuning diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 25168cc495..bc9b091e93 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -100,12 +100,8 @@ LLSkyTex::LLSkyTex() : void LLSkyTex::init(bool isShiny) { mIsShiny = isShiny; - // Compiler fix - make sure the array size is an integer value - // mSkyData = new LLColor4[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION]; - // mSkyDirs = new LLVector3[SKYTEX_RESOLUTION * SKYTEX_RESOLUTION]; mSkyData = new LLColor4[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)]; mSkyDirs = new LLVector3[(U32)(SKYTEX_RESOLUTION * SKYTEX_RESOLUTION)]; - // for (S32 i = 0; i < 2; ++i) { diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 29a83bc64b..ebf8746368 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -245,6 +245,9 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re mColorChanged = FALSE; mSpotLightPriority = 0.f; + mSkinInfoFailed = false; + mSkinInfo = NULL; + mMediaImplList.resize(getNumTEs()); mLastFetchedMediaVersion = -1; mServerDrawableUpdateCount = 0; @@ -263,6 +266,8 @@ LLVOVolume::~LLVOVolume() delete mVolumeImpl; mVolumeImpl = NULL; + gMeshRepo.unregisterMesh(this); + if(!mMediaImplList.empty()) { for(U32 i = 0 ; i < mMediaImplList.size() ; i++) @@ -981,10 +986,7 @@ void LLVOVolume::updateTextureVirtualSize(bool forced) if (isSculpted()) { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - - updateSculptTexture(); + updateSculptTexture(); @@ -1254,10 +1256,15 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo // if it's a mesh if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { + if (mSkinInfo && mSkinInfo->mMeshID != volume_params.getSculptID()) + { + mSkinInfo = NULL; + mSkinInfoFailed = false; + } + if (!getVolume()->isMeshAssetLoaded()) { //load request not yet issued, request pipeline load this mesh - LLUUID asset_id = volume_params.getSculptID(); S32 available_lod = gMeshRepo.loadMesh(this, volume_params, lod, last_lod); if (available_lod != lod) { @@ -1265,6 +1272,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo } } + if (!mSkinInfo && !mSkinInfoFailed) + { + const LLMeshSkinInfo* skin_info = gMeshRepo.getSkinInfo(volume_params.getSculptID(), this); + if (skin_info) + { + notifySkinInfoLoaded(skin_info); + } + } } else // otherwise is sculptie { @@ -1317,6 +1332,9 @@ void LLVOVolume::updateSculptTexture() { mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } + + mSkinInfoFailed = false; + mSkinInfo = NULL; } else { @@ -1371,6 +1389,20 @@ void LLVOVolume::notifyMeshLoaded() updateVisualComplexity(); } +void LLVOVolume::notifySkinInfoLoaded(const LLMeshSkinInfo* skin) +{ + mSkinInfoFailed = false; + mSkinInfo = skin; + + notifyMeshLoaded(); +} + +void LLVOVolume::notifySkinInfoUnavailable() +{ + mSkinInfoFailed = true; + mSkinInfo = nullptr; +} + // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() { @@ -3847,7 +3879,7 @@ const LLMeshSkinInfo* LLVOVolume::getSkinInfo() const { if (getVolume()) { - return gMeshRepo.getSkinInfo(getMeshID(), this); + return mSkinInfo; } else { diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 46b38ba68a..4114a87b96 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -360,6 +360,8 @@ public: void updateVisualComplexity(); void notifyMeshLoaded(); + void notifySkinInfoLoaded(const LLMeshSkinInfo* skin); + void notifySkinInfoUnavailable(); // Returns 'true' iff the media data for this object is in flight bool isMediaDataBeingFetched() const; @@ -449,6 +451,8 @@ private: LLPointer mRiggedVolume; + bool mSkinInfoFailed; + LLConstPointer mSkinInfo; // statics public: static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp index 26c071b66e..4b8a8a690f 100644 --- a/indra/newview/llwearableitemslist.cpp +++ b/indra/newview/llwearableitemslist.cpp @@ -98,17 +98,82 @@ LLPanelWearableListItem::LLPanelWearableListItem(LLViewerInventoryItem* item, co ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// +static LLWidgetNameRegistry::StaticRegistrar sRegisterPanelWearableOutfitItem(&typeid(LLPanelWearableOutfitItem::Params), "wearable_outfit_list_item"); + +LLPanelWearableOutfitItem::Params::Params() +: add_btn("add_btn"), + remove_btn("remove_btn") +{ +} + +BOOL LLPanelWearableOutfitItem::postBuild() +{ + LLPanelWearableListItem::postBuild(); + + LLViewerInventoryItem* inv_item = getItem(); + mShowWidgets &= (inv_item->getType() != LLAssetType::AT_BODYPART); + //if(mShowWidgets) // Make Add/Remove buttons work + { + // Make Add/Remove buttons work + //addWidgetToRightSide("add_wearable"); + //addWidgetToRightSide("remove_wearable"); + addWidgetToRightSide("add_wearable", mShowWidgets); + addWidgetToRightSide("remove_wearable", mShowWidgets); + // + + childSetAction("add_wearable", boost::bind(&LLPanelWearableOutfitItem::onAddWearable, this)); + childSetAction("remove_wearable", boost::bind(&LLPanelWearableOutfitItem::onRemoveWearable, this)); + + setWidgetsVisible(false); + reshapeWidgets(); + } + + return TRUE; +} + +BOOL LLPanelWearableOutfitItem::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + if(!mShowWidgets) + { + return LLPanelWearableListItem::handleDoubleClick(x, y, mask); + } + + if(LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID)) + { + onRemoveWearable(); + } + else + { + onAddWearable(); + } + return TRUE; +} + +void LLPanelWearableOutfitItem::onAddWearable() +{ + setWidgetsVisible(false); + reshapeWidgets(); + LLAppearanceMgr::instance().wearItemOnAvatar(mInventoryItemUUID, true, false); +} + +void LLPanelWearableOutfitItem::onRemoveWearable() +{ + setWidgetsVisible(false); + reshapeWidgets(); + LLAppearanceMgr::instance().removeItemFromAvatar(mInventoryItemUUID); +} // static LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryItem* item, - bool worn_indication_enabled) + bool worn_indication_enabled, + bool show_widgets) { LLPanelWearableOutfitItem* list_item = NULL; if (item) { - const LLPanelInventoryListItemBase::Params& params = LLUICtrlFactory::getDefaultParams(); + const LLPanelWearableOutfitItem::Params& params = LLUICtrlFactory::getDefaultParams(); - list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params); + list_item = new LLPanelWearableOutfitItem(item, worn_indication_enabled, params, show_widgets); list_item->initFromParams(params); list_item->postBuild(); } @@ -116,11 +181,24 @@ LLPanelWearableOutfitItem* LLPanelWearableOutfitItem::create(LLViewerInventoryIt } LLPanelWearableOutfitItem::LLPanelWearableOutfitItem(LLViewerInventoryItem* item, - bool worn_indication_enabled, - const LLPanelWearableOutfitItem::Params& params) -: LLPanelInventoryListItemBase(item, params) + bool worn_indication_enabled, + const LLPanelWearableOutfitItem::Params& params, + bool show_widgets) +: LLPanelWearableListItem(item, params) , mWornIndicationEnabled(worn_indication_enabled) +, mShowWidgets(show_widgets) +, mIsWorn(false) // Make Add/Remove buttons work { + if(mShowWidgets) + { + LLButton::Params button_params = params.add_btn; + applyXUILayout(button_params, this); + addChild(LLUICtrlFactory::create(button_params)); + + button_params = params.remove_btn; + applyXUILayout(button_params, this); + addChild(LLUICtrlFactory::create(button_params)); + } } // virtual @@ -133,8 +211,11 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name, // We don't use get_is_item_worn() here because this update is triggered by // an inventory observer upon link in COF beind added or removed so actual // worn status of a linked item may still remain unchanged. + bool is_worn = LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID); + // Make Add/Remove buttons work + mIsWorn = is_worn; // Better attachment list - //if (mWornIndicationEnabled && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID)) + //if (mWornIndicationEnabled && is_worn) //{ // search_label += LLTrans::getString("worn"); // item_state = IS_WORN; @@ -161,9 +242,9 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name, search_label += LLTrans::getString("AttachmentErrorMessage", args); } - item_state = LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID) ? IS_WORN : IS_MISMATCH; + item_state = is_worn ? IS_WORN : IS_MISMATCH; } - else if (getType() != LLAssetType::AT_OBJECT && LLAppearanceMgr::instance().isLinkedInCOF(mInventoryItemUUID)) + else if (getType() != LLAssetType::AT_OBJECT && is_worn) { search_label += LLTrans::getString("worn"); item_state = IS_WORN; @@ -171,6 +252,17 @@ void LLPanelWearableOutfitItem::updateItem(const std::string& name, } // + if(mShowWidgets) + { + setShowWidget("add_wearable", !is_worn); + setShowWidget("remove_wearable", is_worn); + if(mHovered) + { + setWidgetsVisible(true); + reshapeWidgets(); + } + } + LLPanelInventoryListItemBase::updateItem(search_label, item_state); } @@ -430,13 +522,13 @@ FSPanelCOFWearableOutfitListItem::Params::Params() // static FSPanelCOFWearableOutfitListItem* FSPanelCOFWearableOutfitListItem::create(LLViewerInventoryItem* item, - bool worn_indication_enabled, U32 weight) + bool worn_indication_enabled, bool show_widgets, U32 weight) { FSPanelCOFWearableOutfitListItem* list_item = NULL; if(item) { const Params& params = LLUICtrlFactory::getDefaultParams(); - list_item = new FSPanelCOFWearableOutfitListItem(item, worn_indication_enabled, params); + list_item = new FSPanelCOFWearableOutfitListItem(item, worn_indication_enabled, show_widgets, params); list_item->initFromParams(params); list_item->postBuild(); list_item->updateItemWeight(weight); @@ -447,8 +539,9 @@ FSPanelCOFWearableOutfitListItem* FSPanelCOFWearableOutfitListItem::create(LLVie FSPanelCOFWearableOutfitListItem::FSPanelCOFWearableOutfitListItem(LLViewerInventoryItem* item, bool worn_indication_enabled, + bool show_widgets, const FSPanelCOFWearableOutfitListItem::Params& params) -: LLPanelWearableOutfitItem(item, worn_indication_enabled, params) +: LLPanelWearableOutfitItem(item, worn_indication_enabled, params, show_widgets) , mWeightCtrl(NULL) { LLTextBox::Params weight_params = params.item_weight; @@ -460,13 +553,17 @@ BOOL FSPanelCOFWearableOutfitListItem::postBuild() { mWeightCtrl = getChild("item_weight"); - LLPanelWearableOutfitItem::postBuild(); + if (!LLPanelWearableOutfitItem::postBuild()) + { + return FALSE; + } - addWidgetToRightSide("item_weight"); + addWidgetToRightSide(mWeightCtrl); // Reserve space for 'delete' button event if it is invisible. setRightWidgetsWidth(mWeightCtrl->getRect().getWidth() + 5); + setWidgetsVisible(true); reshapeWidgets(); return TRUE; @@ -483,6 +580,35 @@ void FSPanelCOFWearableOutfitListItem::updateItemWeight(U32 item_weight) mWeightCtrl->setText(complexity_string); } +//virtual +void FSPanelCOFWearableOutfitListItem::updateItem(const std::string& name, EItemState item_state) +{ + LLPanelWearableOutfitItem::updateItem(name, item_state); + + setShowWidget("add_wearable", false); + setShowWidget("remove_wearable", mShowWidgets && mIsWorn && mHovered); + setWidgetsVisible(true); + reshapeWidgets(); +} + +//virtual +void FSPanelCOFWearableOutfitListItem::onMouseEnter(S32 x, S32 y, MASK mask) +{ + LLPanelInventoryListItemBase::onMouseEnter(x, y, mask); + setShowWidget("remove_wearable", mShowWidgets && mIsWorn); + setWidgetsVisible(true); + reshapeWidgets(); +} + +//virtual +void FSPanelCOFWearableOutfitListItem::onMouseLeave(S32 x, S32 y, MASK mask) +{ + LLPanelInventoryListItemBase::onMouseLeave(x, y, mask); + setShowWidget("remove_wearable", false); + setWidgetsVisible(true); + reshapeWidgets(); +} + //virtual const LLPanelInventoryListItemBase::Params& FSPanelCOFWearableOutfitListItem::getDefaultParams() const { @@ -745,6 +871,7 @@ static const LLDefaultChildRegistry::Register r("wearable_i LLWearableItemsList::Params::Params() : standalone("standalone", true) , worn_indication_enabled("worn_indication_enabled", true) +, show_item_widgets("show_item_widgets", false) , show_create_new("show_create_new", true) // Optional "Create new" menu item , show_complexity("show_complexity", false) // Show per-item complexity in COF {} @@ -763,6 +890,7 @@ LLWearableItemsList::LLWearableItemsList(const LLWearableItemsList::Params& p) } mWornIndicationEnabled = p.worn_indication_enabled; setNoItemsCommentText(LLTrans::getString("LoadingData")); + mShowItemWidgets = p.show_item_widgets; mShowCreateNew = p.show_create_new; // Optional "Create new" menu item // Show per-item complexity in COF mShowComplexity = p.show_complexity; @@ -795,10 +923,10 @@ LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item) } // Show per-item complexity in COF - //return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled); + //return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled, mShowItemWidgets); if (!mShowComplexity) { - return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled); + return LLPanelWearableOutfitItem::create(item, mWornIndicationEnabled, mShowItemWidgets); } else { @@ -813,7 +941,7 @@ LLPanel* LLWearableItemsList::createNewItem(LLViewerInventoryItem* item) mLinkedItemsMap[linked_item_id] = item->getUUID(); weight = mItemComplexityMap[linked_item_id]; } - return FSPanelCOFWearableOutfitListItem::create(item, mWornIndicationEnabled, weight); + return FSPanelCOFWearableOutfitListItem::create(item, mWornIndicationEnabled, mShowItemWidgets, weight); } // } diff --git a/indra/newview/llwearableitemslist.h b/indra/newview/llwearableitemslist.h index 4b0a70f252..3a27f23519 100644 --- a/indra/newview/llwearableitemslist.h +++ b/indra/newview/llwearableitemslist.h @@ -72,12 +72,23 @@ protected: * Extends LLPanelInventoryListItemBase with handling * double click to wear the item. */ -class LLPanelWearableOutfitItem : public LLPanelInventoryListItemBase +class LLPanelWearableOutfitItem : public LLPanelWearableListItem { LOG_CLASS(LLPanelWearableOutfitItem); public: + struct Params : public LLInitParam::Block + { + Optional add_btn, remove_btn; + + Params(); + }; + + BOOL postBuild(); + BOOL handleDoubleClick(S32 x, S32 y, MASK mask); + static LLPanelWearableOutfitItem* create(LLViewerInventoryItem* item, - bool worn_indication_enabled); + bool worn_indication_enabled, + bool show_widgets); /** * Updates item name and (worn) suffix. @@ -85,12 +96,20 @@ public: /*virtual*/ void updateItem(const std::string& name, EItemState item_state = IS_DEFAULT); + void onAddWearable(); + void onRemoveWearable(); + protected: LLPanelWearableOutfitItem(LLViewerInventoryItem* item, - bool worn_indication_enabled, const Params& params); + bool worn_indication_enabled, const Params& params, bool show_widgets = false); private: bool mWornIndicationEnabled; + // Make Add/Remove buttons work +protected: + bool mShowWidgets; + bool mIsWorn; + // }; class LLPanelDeletableWearableListItem : public LLPanelWearableListItem @@ -222,7 +241,7 @@ class FSPanelCOFWearableOutfitListItem : public LLPanelWearableOutfitItem { LOG_CLASS(FSPanelCOFWearableOutfitListItem); public: - struct Params : public LLInitParam::Block + struct Params : public LLInitParam::Block { Optional item_weight; @@ -230,15 +249,20 @@ public: }; static FSPanelCOFWearableOutfitListItem* create(LLViewerInventoryItem* item, - bool worn_indication_enabled, U32 weight); + bool worn_indication_enabled, bool show_widgets, U32 weight); /*virtual*/ BOOL postBuild(); void updateItemWeight(U32 item_weight); + /*virtual*/ void updateItem(const std::string& name, EItemState item_state = IS_DEFAULT); + + /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); + /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); + protected: FSPanelCOFWearableOutfitListItem(LLViewerInventoryItem* item, - bool worn_indication_enabled, const Params& params); + bool worn_indication_enabled, bool show_widgets, const Params& params); virtual const LLPanelInventoryListItemBase::Params& getDefaultParams() const; private: @@ -479,6 +503,7 @@ public: { Optional standalone; Optional worn_indication_enabled; + Optional show_item_widgets; Optional show_create_new; // Optional "Create new" menu item Optional show_complexity; // Show per-item complexity in COF @@ -528,6 +553,7 @@ protected: bool mIsStandalone; bool mWornIndicationEnabled; + bool mShowItemWidgets; bool mShowCreateNew; // Optional "Create new" menu item bool mShowComplexity; // Show per-item complexity in COF diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 89ed211d3c..2d16018c05 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -719,13 +719,13 @@ void LLWorld::removeRegion(const LLHost &host) mRegionRemovedSignal(regionp); - delete regionp; - updateWaterObjects(); //double check all objects of this region are removed. gObjectList.clearAllMapObjectsInRegion(regionp) ; //llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ; + + delete regionp; // Delete last to prevent use after free } diff --git a/indra/newview/skins/ansastorm/xui/en/panel_outfits_wearing.xml b/indra/newview/skins/ansastorm/xui/en/panel_outfits_wearing.xml index f87e6f4d30..c32ae40a0a 100644 --- a/indra/newview/skins/ansastorm/xui/en/panel_outfits_wearing.xml +++ b/indra/newview/skins/ansastorm/xui/en/panel_outfits_wearing.xml @@ -32,6 +32,7 @@ left="3" multi_select="true" name="cof_items_list" + show_item_widgets="true" standalone="false" top="0" width="309" diff --git a/indra/newview/skins/ansastorm/xui/en/widgets/filter_editor.xml b/indra/newview/skins/ansastorm/xui/en/widgets/filter_editor.xml index 5b8a659f95..895226ef00 100644 --- a/indra/newview/skins/ansastorm/xui/en/widgets/filter_editor.xml +++ b/indra/newview/skins/ansastorm/xui/en/widgets/filter_editor.xml @@ -6,7 +6,7 @@ text_pad_left="4" select_on_focus="true" text_tentative_color="TextFgTentativeColor" - highlight_text_field="false" + highlight_text_field="true" background_image="TextField_Off" background_image_disabled="TextField_Disabled" background_image_focused="TextField_Active" diff --git a/indra/newview/skins/ansastorm/xui/en/widgets/search_editor.xml b/indra/newview/skins/ansastorm/xui/en/widgets/search_editor.xml index 4c582f29ef..97848020dc 100644 --- a/indra/newview/skins/ansastorm/xui/en/widgets/search_editor.xml +++ b/indra/newview/skins/ansastorm/xui/en/widgets/search_editor.xml @@ -7,7 +7,7 @@ text_pad_right="2" select_on_focus="true" text_tentative_color="TextFgTentativeColor" - highlight_text_field="false" + highlight_text_field="true" background_image="TextField_Off" background_image_disabled="TextField_Disabled" background_image_focused="TextField_Active" diff --git a/indra/newview/skins/default/textures/icons/add_icon.png b/indra/newview/skins/default/textures/icons/add_icon.png new file mode 100644 index 0000000000..cb68ee8e16 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/add_icon.png differ diff --git a/indra/newview/skins/default/textures/icons/remove_icon.png b/indra/newview/skins/default/textures/icons/remove_icon.png new file mode 100644 index 0000000000..6e62ee33f4 Binary files /dev/null and b/indra/newview/skins/default/textures/icons/remove_icon.png differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 074b0aa285..14eac8c4d2 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -917,6 +917,9 @@ with the same filename but different name + + + diff --git a/indra/newview/skins/default/xui/de/floater_pathfinding_linksets.xml b/indra/newview/skins/default/xui/de/floater_pathfinding_linksets.xml index 61ce6185dc..c777dfeef0 100644 --- a/indra/newview/skins/default/xui/de/floater_pathfinding_linksets.xml +++ b/indra/newview/skins/default/xui/de/floater_pathfinding_linksets.xml @@ -97,9 +97,11 @@ Name + Beschreibung + diff --git a/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml index 30d996468d..a7fc26560c 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml @@ -15,7 +15,7 @@ Anmelden, um Änderungen vorzunehmen -