diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index c0e8dc408..3b1c1e467 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -88,7 +88,7 @@ if (VIEWER) add_subdirectory(${VIEWER_PREFIX}linux_crash_logger) add_dependencies(viewer linux-crash-logger-strip-target) elseif (DARWIN) - add_subdirectory(${VIEWER_PREFIX}mac_crash_logger) + #add_subdirectory(${VIEWER_PREFIX}mac_crash_logger) #add_subdirectory(${VIEWER_PREFIX}mac_updater) add_dependencies(viewer mac-crash-logger) #add_dependencies(viewer mac-updater) diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index ef5b14b80..916878ec3 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -31,10 +31,10 @@ if (WINDOWS) # Don't build DLLs. set(BUILD_SHARED_LIBS OFF) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd" + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Od /Zi /MDd /arch:SSE2" CACHE STRING "C++ compiler debug options" FORCE) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO - "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP" + "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Od /Zi /MD /MP /arch:SSE2" CACHE STRING "C++ compiler release-with-debug options" FORCE) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /O2 /Zi /MD /MP /arch:SSE /fp:fast" @@ -220,14 +220,17 @@ if (LINUX) set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers") else (${ARCH} STREQUAL "x86_64") - set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS}) - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS}) + if (NOT STANDALONE) + set(MARCH_FLAG " -march=pentium4") + endif (NOT STANDALONE) + set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2}${MARCH_FLAG} -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS}) + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}${MARCH_FLAG} -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS}) endif (${ARCH} STREQUAL "x86_64") endif (VIEWER) - set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG} -msse2") set(CMAKE_CXX_FLAGS_RELEASE "-O3 ${CMAKE_CXX_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_RELEASE "-O3 ${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_CXX_FLAGS_RELEASESSE2 "-O3 ${CMAKE_CXX_FLAGS_RELEASESSE2}") @@ -245,8 +248,8 @@ if (DARWIN) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mlong-branch") # NOTE: it's critical that the optimization flag is put in front. # NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered. - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") - set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O0 ${CMAKE_C_FLAGS_RELWITHDEBINFO}") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") + set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -03 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -03 -msse3 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -O3 -msse2 -mtune=generic -mfpmath=sse ${GCC_EXTRA_OPTIMIZATIONS}") @@ -278,11 +281,6 @@ endif (LINUX OR DARWIN) if (STANDALONE) add_definitions(-DLL_STANDALONE=1) - - if (LINUX AND ${ARCH} STREQUAL "i686") - add_definitions(-march=pentiumpro) - endif (LINUX AND ${ARCH} STREQUAL "i686") - else (STANDALONE) set(${ARCH}_linux_INCLUDES ELFIO @@ -297,6 +295,7 @@ endif (STANDALONE) if(1 EQUAL 1) add_definitions(-DOPENSIM_RULES=1) + add_definitions(-DMESH_ENABLED=1) endif(1 EQUAL 1) if(SERVER) diff --git a/indra/cmake/FMOD.cmake b/indra/cmake/FMOD.cmake index 759b8f134..df9b5b18e 100644 --- a/indra/cmake/FMOD.cmake +++ b/indra/cmake/FMOD.cmake @@ -43,6 +43,7 @@ endif (NOT FMOD_LIBRARY) find_path(FMOD_INCLUDE_DIR fmod.h ${LIBS_PREBUILT_DIR}/include + ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include ${FMOD_SDK_DIR}/api/inc ${FMOD_SDK_DIR}/inc ${FMOD_SDK_DIR} diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index 1a12339a7..fc5b40d42 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -24,11 +24,11 @@ else (STANDALONE) endif (LINUX) endif (STANDALONE) -if (GOOGLE_PERFTOOLS_FOUND) +if (GOOGLE_PERFTOOLS_FOUND AND STANDALONE) set(USE_GOOGLE_PERFTOOLS ON CACHE BOOL "Build with Google PerfTools support.") -else (GOOGLE_PERFTOOLS_FOUND) +else () set(USE_GOOGLE_PERFTOOLS OFF) -endif (GOOGLE_PERFTOOLS_FOUND) +endif () # XXX Disable temporarily, until we have compilation issues on 64-bit # Etch sorted. diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake index efb3d004c..beac1d012 100644 --- a/indra/cmake/LLCommon.cmake +++ b/indra/cmake/LLCommon.cmake @@ -5,6 +5,12 @@ include(Boost) include(EXPAT) include(ZLIB) +if (DARWIN) + include(CMakeFindFrameworks) + find_library(CORESERVICES_LIBRARY CoreServices) +endif (DARWIN) + + set(LLCOMMON_INCLUDE_DIRS ${LIBS_OPEN_DIR}/cwdebug ${LIBS_OPEN_DIR}/llcommon @@ -13,3 +19,8 @@ set(LLCOMMON_INCLUDE_DIRS ) set(LLCOMMON_LIBRARIES llcommon) + +set(LLCOMMON_LINK_SHARED ON CACHE BOOL "Build the llcommon target as a shared library.") +if(LLCOMMON_LINK_SHARED) + add_definitions(-DLL_COMMON_LINK_SHARED=1) +endif(LLCOMMON_LINK_SHARED) diff --git a/indra/cmake/OpenGL.cmake b/indra/cmake/OpenGL.cmake index 3dcd396c5..f8a113f65 100644 --- a/indra/cmake/OpenGL.cmake +++ b/indra/cmake/OpenGL.cmake @@ -2,9 +2,9 @@ include(Prebuilt) if (NOT STANDALONE) - use_prebuilt_binary(GL) + use_prebuilt_binary(glext) # possible glh_linear should have its own .cmake file instead #use_prebuilt_binary(glh_linear) # actually... not any longer, it's now in git -SG - set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include) + set(GLEXT_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/include) endif (NOT STANDALONE) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index adfa08429..67cbd5b25 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -30,7 +30,7 @@ set(LIBS_SERVER_DIR ${CMAKE_SOURCE_DIR}/${LIBS_SERVER_PREFIX}) set(SCRIPTS_DIR ${CMAKE_SOURCE_DIR}/${SCRIPTS_PREFIX}) set(SERVER_DIR ${CMAKE_SOURCE_DIR}/${SERVER_PREFIX}) set(VIEWER_DIR ${CMAKE_SOURCE_DIR}/${VIEWER_PREFIX}) -set(LL_TESTS ON CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation)") +set(LL_TESTS OFF CACHE BOOL "Build and run unit and integration tests (disable for build timing runs to reduce variation)") set(VISTA_ICON OFF CACHE BOOL "Allow vista icon with pre 2008 Visual Studio IDEs. (Assumes replacement old rcdll.dll with new rcdll.dll from win sdk 7.0 or later)") set(LIBS_PREBUILT_DIR ${CMAKE_SOURCE_DIR}/../libraries CACHE PATH diff --git a/indra/fmodfilestructure.zip b/indra/fmodfilestructure.zip deleted file mode 100644 index 1dcaffdd7..000000000 Binary files a/indra/fmodfilestructure.zip and /dev/null differ diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp index 443b57698..2fcaf97a8 100644 --- a/indra/llaudio/llvorbisencode.cpp +++ b/indra/llaudio/llvorbisencode.cpp @@ -89,7 +89,7 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro //******************************** LLAPRFile infile ; - infile.open(in_fname,LL_APR_RB, LLAPRFile::global); + infile.open(in_fname,LL_APR_RB); //******************************** if (!infile.getFileHandle()) { @@ -240,7 +240,7 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname S32 data_left = 0; LLAPRFile infile ; - infile.open(in_fname,LL_APR_RB, LLAPRFile::global); + infile.open(in_fname,LL_APR_RB); if (!infile.getFileHandle()) { llwarns << "Couldn't open temporary ogg file for writing: " << in_fname @@ -249,7 +249,7 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname } LLAPRFile outfile ; - outfile.open(out_fname,LL_APR_WPB, LLAPRFile::global); + outfile.open(out_fname,LL_APR_WPB); if (!outfile.getFileHandle()) { llwarns << "Couldn't open upload sound file for reading: " << in_fname diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 12bcffac2..8c7878936 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -226,7 +226,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName); LLAPRFile infile ; - infile.open(path, LL_APR_R, LLAPRFile::global); + infile.open(path, LL_APR_R); apr_file_t *fp = infile.getFileHandle(); if (!fp) return E_ST_NO_XLT_FILE; diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 89a55658f..288bf1ff5 100644 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -45,7 +45,7 @@ LLStringTable LLCharacter::sVisualParamNames(1024); std::vector< LLCharacter* > LLCharacter::sInstances; - +BOOL LLCharacter::sAllowInstancesChange = TRUE ; //----------------------------------------------------------------------------- // LLCharacter() @@ -59,8 +59,10 @@ LLCharacter::LLCharacter() mSkeletonSerialNum( 0 ), mInAppearance( false ) { - mMotionController.setCharacter( this ); + llassert_always(sAllowInstancesChange) ; sInstances.push_back(this); + + mMotionController.setCharacter( this ); mPauseRequest = new LLPauseRequestHandle(); } @@ -77,11 +79,22 @@ LLCharacter::~LLCharacter() { delete param; } - std::vector::iterator iter = std::find(sInstances.begin(), sInstances.end(), this); - if (iter != sInstances.end()) + + U32 i ; + U32 size = sInstances.size() ; + for(i = 0 ; i < size ; i++) { - sInstances.erase(iter); + if(sInstances[i] == this) + { + break ; + } } + + llassert_always(i < size) ; + + llassert_always(sAllowInstancesChange) ; + sInstances[i] = sInstances[size - 1] ; + sInstances.pop_back() ; } diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index f7206f750..d435a4cca 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -42,7 +42,7 @@ #include "llmotioncontroller.h" #include "llvisualparam.h" #include "string_table.h" -#include "llmemory.h" +#include "llpointer.h" #include "llthread.h" class LLPolyMesh; @@ -279,6 +279,7 @@ public: void setSkeletonSerialNum( U32 num ) { mSkeletonSerialNum = num; } static std::vector< LLCharacter* > sInstances; + static BOOL sAllowInstancesChange ; //debug use protected: LLMotionController mMotionController; diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 25fbc03fa..16600a227 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -56,6 +56,9 @@ LLJoint::LLJoint() mUpdateXform = TRUE; mJointNum = -1; touch(); +#if MESH_ENABLED + mResetAfterRestoreOldXform = false; +#endif //MESH_ENABLED } @@ -239,6 +242,43 @@ void LLJoint::setPosition( const LLVector3& pos ) } } +#if MESH_ENABLED +//-------------------------------------------------------------------- +// setPosition() +//-------------------------------------------------------------------- +void LLJoint::setDefaultFromCurrentXform( void ) +{ + mDefaultXform = mXform; + touch(MATRIX_DIRTY | POSITION_DIRTY); + +} + +//-------------------------------------------------------------------- +// storeCurrentXform() +//-------------------------------------------------------------------- +void LLJoint::storeCurrentXform( const LLVector3& pos ) +{ + mOldXform = mXform; + mResetAfterRestoreOldXform = true; + setPosition( pos ); +} +//-------------------------------------------------------------------- +// restoreOldXform() +//-------------------------------------------------------------------- +void LLJoint::restoreOldXform( void ) +{ + mResetAfterRestoreOldXform = false; + mXform = mOldXform; +} +//-------------------------------------------------------------------- +// restoreOldXform() +//-------------------------------------------------------------------- +void LLJoint::restoreToDefaultXform( void ) +{ + mXform = mDefaultXform; + setPosition( mXform.getPosition() ); +} +#endif //MESH_ENABLED //-------------------------------------------------------------------- // getWorldPosition() diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 37ae44998..852f04e05 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -86,10 +86,19 @@ protected: // explicit transformation members LLXformMatrix mXform; +#if MESH_ENABLED + LLXformMatrix mOldXform; + LLXformMatrix mDefaultXform; + LLUUID mId; +#endif //MESH_ENABLED public: U32 mDirtyFlags; BOOL mUpdateXform; + +#if MESH_ENABLED + BOOL mResetAfterRestoreOldXform; +#endif //MESH_ENABLED // describes the skin binding pose LLVector3 mSkinOffset; @@ -179,6 +188,24 @@ public: S32 getJointNum() const { return mJointNum; } void setJointNum(S32 joint_num) { mJointNum = joint_num; } +#if MESH_ENABLED + + void restoreOldXform( void ); + void restoreToDefaultXform( void ); + void setDefaultFromCurrentXform( void ); + void storeCurrentXform( const LLVector3& pos ); + + //Accessor for the joint id + LLUUID getId( void ) { return mId; } + //Setter for the joints id + void setId( const LLUUID& id ) { mId = id;} + + //If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it + const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; } + //Setter for joint reset flag + void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; } +#endif //MESH_ENABLED + // std::string exportString(U32 tabs = 0); // diff --git a/indra/llcharacter/lljointstate.h b/indra/llcharacter/lljointstate.h index 16ad0e120..e40cf2673 100644 --- a/indra/llcharacter/lljointstate.h +++ b/indra/llcharacter/lljointstate.h @@ -37,7 +37,7 @@ // Header Files //----------------------------------------------------------------------------- #include "lljoint.h" -#include "llmemory.h" +#include "llrefcount.h" //----------------------------------------------------------------------------- // class LLJointState diff --git a/indra/llcharacter/llpose.cpp b/indra/llcharacter/llpose.cpp index 8c7cba0a1..7f08f3e58 100644 --- a/indra/llcharacter/llpose.cpp +++ b/indra/llcharacter/llpose.cpp @@ -89,6 +89,7 @@ LLJointState *LLPose::getNextJointState() //----------------------------------------------------------------------------- BOOL LLPose::addJointState(const LLPointer& jointState) { + llassert_always(jointState.notNull()); if (mJointMap.find(jointState->getJoint()->getName()) == mJointMap.end()) { mJointMap[jointState->getJoint()->getName()] = jointState; @@ -161,6 +162,7 @@ void LLPose::setWeight(F32 weight) // // there was a crash here // + llassert_always(iter->second.notNull()); iter->second->setWeight(weight); } mWeight = weight; diff --git a/indra/llcharacter/llpose.h b/indra/llcharacter/llpose.h index 80487bd12..2b976b219 100644 --- a/indra/llcharacter/llpose.h +++ b/indra/llcharacter/llpose.h @@ -40,6 +40,8 @@ #include "lljointstate.h" #include "lljoint.h" #include "llmap.h" +#include "llpointer.h" + #include #include diff --git a/indra/llcharacter/llstatemachine.cpp b/indra/llcharacter/llstatemachine.cpp index cc74d9ccf..e6fa4d798 100644 --- a/indra/llcharacter/llstatemachine.cpp +++ b/indra/llcharacter/llstatemachine.cpp @@ -211,7 +211,7 @@ LLFSMState* LLStateDiagram::getState(U32 state_id) BOOL LLStateDiagram::saveDotFile(const std::string& filename) { LLAPRFile outfile ; - outfile.open(filename, LL_APR_W, LLAPRFile::global); + outfile.open(filename, LL_APR_W); apr_file_t* dot_file = outfile.getFileHandle() ; if (!dot_file) diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 19fc67588..99f00a2c5 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -58,12 +58,14 @@ set(llcommon_SOURCE_FILES llprocessor.cpp llqueuedthread.cpp llrand.cpp + llrefcount.cpp llrun.cpp llsd.cpp llsdserialize.cpp llsdserialize_xml.cpp llsdutil.cpp llsecondlifeurls.cpp + llsingleton.cpp llstat.cpp llstacktrace.cpp llstreamtools.cpp @@ -94,6 +96,7 @@ set(llcommon_HEADER_FILES indra_constants.h linden_common.h linked_lists.h + llaccountingcost.h llagentconstants.h llavatarname.h llapp.h @@ -159,6 +162,7 @@ set(llcommon_HEADER_FILES llmortician.h llnametable.h lloptioninterface.h + llpointer.h llpreprocessor.h llpriqueuemap.h llprocesslauncher.h @@ -168,6 +172,8 @@ set(llcommon_HEADER_FILES llqueuedthread.h llrand.h llrun.h + llrefcount.h + llsafehandle.h llscopedvolatileaprpool.h llsd.h llsdserialize.h @@ -175,6 +181,7 @@ set(llcommon_HEADER_FILES llsdutil.h llsecondlifeurls.h llsimplehash.h + llsingleton.h llskiplist.h llskipmap.h llstack.h @@ -189,6 +196,7 @@ set(llcommon_HEADER_FILES llsys.h llthread.h lltimer.h + lltreeiterators.h lluri.h lluuid.h lluuidhashmap.h @@ -205,6 +213,7 @@ set(llcommon_HEADER_FILES stdenums.h stdtypes.h string_table.h + stringize.h timer.h timing.h u64.h @@ -224,7 +233,9 @@ target_link_libraries( ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} ${WINDOWS_LIBRARIES} + ${BOOST_REGEX_LIBRARY} ${CWDEBUG_LIBRARIES} + ${CORESERVICES_LIBRARY} ) if (LINUX) diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h index 815145ac8..089f8ed38 100644 --- a/indra/llcommon/indra_constants.h +++ b/indra/llcommon/indra_constants.h @@ -153,6 +153,11 @@ const char LAND_LAYER_CODE = 'L'; const char WATER_LAYER_CODE = 'W'; const char WIND_LAYER_CODE = '7'; const char CLOUD_LAYER_CODE = '8'; +// Extended land layer for Aurora Sim +const char AURORA_LAND_LAYER_CODE = 'M'; +const char AURORA_WATER_LAYER_CODE = 'X'; +const char AURORA_WIND_LAYER_CODE = '9'; +const char AURORA_CLOUD_LAYER_CODE = ':'; // keys // Bit masks for various keyboard modifier keys. diff --git a/indra/llcommon/llaccountingcost.h b/indra/llcommon/llaccountingcost.h new file mode 100644 index 000000000..0ef3b50c6 --- /dev/null +++ b/indra/llcommon/llaccountingcost.h @@ -0,0 +1,86 @@ +/** + * @file llaccountingcost.h + * @ + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_ACCOUNTINGQUOTA_H +#define LL_ACCOUNTINGQUOTA_H + +struct ParcelQuota +{ + ParcelQuota( F32 ownerRenderCost, F32 ownerPhysicsCost, F32 ownerNetworkCost, F32 ownerSimulationCost, + F32 groupRenderCost, F32 groupPhysicsCost, F32 groupNetworkCost, F32 groupSimulationCost, + F32 otherRenderCost, F32 otherPhysicsCost, F32 otherNetworkCost, F32 otherSimulationCost, + F32 tempRenderCost, F32 tempPhysicsCost, F32 tempNetworkCost, F32 tempSimulationCost, + F32 selectedRenderCost, F32 selectedPhysicsCost, F32 selectedNetworkCost, F32 selectedSimulationCost, + F32 parcelCapacity ) + : mOwnerRenderCost( ownerRenderCost ), mOwnerPhysicsCost( ownerPhysicsCost ) + , mOwnerNetworkCost( ownerNetworkCost ), mOwnerSimulationCost( ownerSimulationCost ) + , mGroupRenderCost( groupRenderCost ), mGroupPhysicsCost( groupPhysicsCost ) + , mGroupNetworkCost( groupNetworkCost ), mGroupSimulationCost( groupSimulationCost ) + , mOtherRenderCost( otherRenderCost ), mOtherPhysicsCost( otherPhysicsCost ) + , mOtherNetworkCost( otherNetworkCost ), mOtherSimulationCost( otherSimulationCost ) + , mTempRenderCost( tempRenderCost ), mTempPhysicsCost( tempPhysicsCost ) + , mTempNetworkCost( tempNetworkCost ), mTempSimulationCost( tempSimulationCost ) + , mSelectedRenderCost( tempRenderCost ), mSelectedPhysicsCost( tempPhysicsCost ) + , mSelectedNetworkCost( tempNetworkCost ), mSelectedSimulationCost( selectedSimulationCost ) + , mParcelCapacity( parcelCapacity ) + { + } + + ParcelQuota(){} + F32 mOwnerRenderCost, mOwnerPhysicsCost, mOwnerNetworkCost, mOwnerSimulationCost; + F32 mGroupRenderCost, mGroupPhysicsCost, mGroupNetworkCost, mGroupSimulationCost; + F32 mOtherRenderCost, mOtherPhysicsCost, mOtherNetworkCost, mOtherSimulationCost; + F32 mTempRenderCost, mTempPhysicsCost, mTempNetworkCost, mTempSimulationCost; + F32 mSelectedRenderCost, mSelectedPhysicsCost, mSelectedNetworkCost, mSelectedSimulationCost; + F32 mParcelCapacity; +}; + +//SelectionQuota atm does not require a id +struct SelectionCost +{ + SelectionCost( /*LLTransactionID transactionId, */ F32 physicsCost, F32 networkCost, F32 simulationCost ) + //: mTransactionId( transactionId) + : mPhysicsCost( physicsCost ) + , mNetworkCost( networkCost ) + , mSimulationCost( simulationCost ) + { + } + SelectionCost() + : mPhysicsCost( 0.0f ) + , mNetworkCost( 0.0f ) + , mSimulationCost( 0.0f ) + {} + + F32 mPhysicsCost, mNetworkCost, mSimulationCost; + //LLTransactionID mTransactionId; +}; + +typedef enum { Roots = 0 , Prims } eSelectionType; + +#endif + + + diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index c35a84255..75c85a105 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -249,15 +249,6 @@ LLSD LLApp::getOptionData(OptionPriority level) return mOptions[level]; } -void LLApp::stepFrame() -{ - LLFrameTimer::updateFrameTime(); - LLFrameTimer::updateFrameCount(); - LLEventTimer::updateClass(); - mRunner.run(); -} - - void LLApp::setupErrorHandling() { // Error handling is done by starting up an error handling thread, which just sleeps and @@ -297,10 +288,13 @@ void LLApp::startErrorThread() // Start the error handling thread, which is responsible for taking action // when the app goes into the APP_STATUS_ERROR state // - llinfos << "Starting error thread" << llendl; - mThreadErrorp = new LLErrorThread(); - mThreadErrorp->setUserData((void *) this); - mThreadErrorp->start(); + if(!mThreadErrorp) + { + llinfos << "Starting error thread" << llendl; + mThreadErrorp = new LLErrorThread(); + mThreadErrorp->setUserData((void *) this); + mThreadErrorp->start(); + } } void LLApp::setErrorHandler(LLAppErrorHandler handler) diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 05e2bccaf..09e88b326 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -236,17 +236,6 @@ public: pid_t fork(); #endif - /** - * @brief Get a reference to the application runner - * - * Please use the runner with caution. Since the Runner usage - * pattern is not yet clear, this method just gives access to it - * to add and remove runnables. - * @return Returns the application runner. Do not save the - * pointer past the caller's stack frame. - */ - LLRunner& getRunner() { return mRunner; } - public: typedef std::map string_map; string_map mOptionMap; // Contains all command-line options and arguments in a map @@ -264,11 +253,6 @@ protected: static LLAppChildCallback sDefaultChildCallback; #endif - /** - * @brief This method is called once a frame to do once a frame tasks. - */ - void stepFrame(); - /** * @ brief This method is called once as soon as logging is initialized. */ @@ -289,9 +273,6 @@ private: // Default application threads LLErrorThread* mThreadErrorp; // Waits for app to go to status ERROR, then runs the error callback - // This is the application level runnable scheduler. - LLRunner mRunner; - /** @name Runtime option implementation */ //@{ diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index d2169d65e..fb07621cb 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -191,6 +191,10 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc return status; } +apr_status_t LLAPRFile::open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool) +{ + return open(filename, flags, use_global_pool ? LLAPRFile::global : LLAPRFile::local); +} // File I/O S32 LLAPRFile::read(void *buf, S32 nbytes) { diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index ded15f531..a9c0543c2 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -150,10 +150,11 @@ public: }; LLAPRFile() ; - LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type); + LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type = LLAPRFile::global); ~LLAPRFile() ; - apr_status_t open(const std::string& filename, apr_int32_t flags, access_t access_type, S32* sizep = NULL); + apr_status_t open(const std::string& filename, apr_int32_t flags, access_t access_type = LLAPRFile::global, S32* sizep = NULL); + apr_status_t open(const std::string& filename, apr_int32_t flags, BOOL use_global_pool); //use global pool. apr_status_t close() ; // Returns actual offset, -1 if seek fails diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index d88013fc4..6aea07fd0 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -35,6 +35,7 @@ #include "llassettype.h" #include "lldictionary.h" #include "llmemory.h" +#include "llsingleton.h" ///---------------------------------------------------------------------------- /// Class LLAssetType @@ -105,6 +106,9 @@ LLAssetDictionary::LLAssetDictionary() //addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("FOLDER_LINK", "current", "current outfit", false, false, false)); //addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", false, false, false)); //addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", false, false, false)); +#if MESH_ENABLED + addEntry(LLAssetType::AT_MESH, new AssetEntry("MESH", "mesh", "mesh", false, false, false)); +#endif //MESH_ENABLED addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, false, false, false)); }; diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 554fc0c02..4590fc831 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -138,13 +138,19 @@ public: // Inventory folder link AT_LINK_FOLDER = 25, - + //AT_CURRENT_OUTFIT = 46, //AT_OUTFIT = 47, //AT_MY_OUTFITS = 48, +#if MESH_ENABLED + AT_MESH = 49, + // Mesh data in our proprietary SLM format + + AT_COUNT = 50, +#endif //MESH_ENABLED // +*********************************************+ // | TO ADD AN ELEMENT TO THIS ENUM: | // +*********************************************+ @@ -155,8 +161,9 @@ public: // +*********************************************+ //AT_COUNT = 49, - +#if !MESH_ENABLED AT_COUNT = 26, +#endif //!MESH_ENABLED AT_NONE = -1 }; diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index e116e9cdf..7e8ae6368 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -38,6 +38,8 @@ #include #include +#include "llpreprocessor.h" + #include "stdtypes.h" /** diff --git a/indra/llcommon/lleventtimer.cpp b/indra/llcommon/lleventtimer.cpp index 2720b93ab..a29a837a8 100644 --- a/indra/llcommon/lleventtimer.cpp +++ b/indra/llcommon/lleventtimer.cpp @@ -44,63 +44,40 @@ // ////////////////////////////////////////////////////////////////////////////// -//std::list LLEventTimer::sActiveList; - LLEventTimer::LLEventTimer(F32 period) : mEventTimer() { mPeriod = period; - //sActiveList.push_back(this); } LLEventTimer::LLEventTimer(const LLDate& time) : mEventTimer() { mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch()); - //sActiveList.push_back(this); } -LLEventTimer::~LLEventTimer() +LLEventTimer::~LLEventTimer() { - //sActiveList.remove(this); } //static void LLEventTimer::updateClass() { std::list completed_timers; - - /*{ - for (std::list::iterator iter = sActiveList.begin(); iter != sActiveList.end(); ) - { - LLEventTimer* timer = *iter++; - F32 et = timer->mEventTimer.getElapsedTimeF32(); - if (timer->mEventTimer.getStarted() && et > timer->mPeriod) { - timer->mEventTimer.reset(); - if ( timer->tick() ) - { - completed_timers.push_back( timer ); - } - } - } - }*/ + for (instance_iter iter = beginInstances(); iter != endInstances(); ) { - LLInstanceTrackerScopedGuard guard; - for (instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ) - { - LLEventTimer& timer = *iter++; - F32 et = timer.mEventTimer.getElapsedTimeF32(); - if (timer.mEventTimer.getStarted() && et > timer.mPeriod) { - timer.mEventTimer.reset(); - if ( timer.tick() ) - { - completed_timers.push_back( &timer ); - } + LLEventTimer& timer = *iter++; + F32 et = timer.mEventTimer.getElapsedTimeF32(); + if (timer.mEventTimer.getStarted() && et > timer.mPeriod) { + timer.mEventTimer.reset(); + if ( timer.tick() ) + { + completed_timers.push_back( &timer ); } } } - + if ( completed_timers.size() > 0 ) { for (std::list::iterator completed_iter = completed_timers.begin(); diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h index 1521b507a..9e003119d 100644 --- a/indra/llcommon/lleventtimer.h +++ b/indra/llcommon/lleventtimer.h @@ -56,11 +56,6 @@ public: protected: LLTimer mEventTimer; F32 mPeriod; - -//private: - //list of active timers -// static std::list sActiveList; // TODO should this be a vector }; - #endif //LL_EVENTTIMER_H diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index d3783c582..f1d7eb305 100644 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -29,33 +29,22 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ + #include "linden_common.h" #include "llfasttimer.h" - #include "llmemory.h" #include "llprocessor.h" - #if LL_WINDOWS #define WIN32_LEAN_AND_MEAN #include -#include "lltimer.h" -#elif LL_LINUX || LL_SOLARIS -#include -#include -#include "lltimer.h" -#elif LL_DARWIN -#include -#include "lltimer.h" // get_clock_count() -#else -#error "architecture not supported" #endif +#include "lltimer.h" ////////////////////////////////////////////////////////////////////////////// // statics - LLFastTimer::EFastTimerType LLFastTimer::sCurType = LLFastTimer::FTM_OTHER; int LLFastTimer::sCurDepth = 0; U64 LLFastTimer::sStart[LLFastTimer::FTM_MAX_DEPTH]; @@ -70,44 +59,12 @@ S32 LLFastTimer::sLastFrameIndex = -1; int LLFastTimer::sPauseHistory = 0; int LLFastTimer::sResetHistory = 0; -#define USE_RDTSC 0 +U64 LLFastTimer::sClockResolution = calc_clock_frequency(50U); // Resolution of get_clock_count() -#if LL_LINUX || LL_SOLARIS -U64 LLFastTimer::sClockResolution = 1000000000; // 1e9, Nanosecond resolution -#else -U64 LLFastTimer::sClockResolution = 1000000; // 1e6, Microsecond resolution -#endif - - -//static -#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer { return sClockResolution >> 8; } -#else // windows or x86-mac or x86-linux or x86-solaris -U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer -{ -#if USE_RDTSC || !LL_WINDOWS - //getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz - static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0); - - // we drop the low-order byte in our timers, so report a lower frequency -#else - // If we're not using RDTSC, each fasttimer tick is just a performance counter tick. - // Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency()) - // since that would change displayed MHz stats for CPUs - static bool firstcall = true; - static U64 sCPUClockFrequency; - if (firstcall) - { - QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency); - firstcall = false; - } -#endif - return sCPUClockFrequency >> 8; -} -#endif void LLFastTimer::reset() { @@ -162,139 +119,17 @@ void LLFastTimer::reset() // Important note: These implementations must be FAST! // - -#if LL_WINDOWS -// -// Windows implementation of CPU clock -// - -// -// NOTE: put back in when we aren't using platform sdk anymore -// -// because MS has different signatures for these functions in winnt.h -// need to rename them to avoid conflicts -//#define _interlockedbittestandset _renamed_interlockedbittestandset -//#define _interlockedbittestandreset _renamed_interlockedbittestandreset -//#include -//#undef _interlockedbittestandset -//#undef _interlockedbittestandreset - -//inline U32 LLFastTimer::getCPUClockCount32() -//{ -// U64 time_stamp = __rdtsc(); -// return (U32)(time_stamp >> 8); -//} -// -//// return full timer value, *not* shifted by 8 bits -//inline U64 LLFastTimer::getCPUClockCount64() -//{ -// return __rdtsc(); -//} - // shift off lower 8 bits for lower resolution but longer term timing // on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing -#if USE_RDTSC -U32 LLFastTimer::getCPUClockCount32() -{ - U32 ret_val; - __asm - { - _emit 0x0f - _emit 0x31 - shr eax,8 - shl edx,24 - or eax, edx - mov dword ptr [ret_val], eax - } - return ret_val; -} -// return full timer value, *not* shifted by 8 bits -U64 LLFastTimer::getCPUClockCount64() -{ - U64 ret_val; - __asm - { - _emit 0x0f - _emit 0x31 - mov eax,eax - mov edx,edx - mov dword ptr [ret_val+4], edx - mov dword ptr [ret_val], eax - } - return ret_val; -} - -std::string LLFastTimer::sClockType = "rdtsc"; - -#else //LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp -// These use QueryPerformanceCounter, which is arguably fine and also works on amd architectures. +// On windows these use QueryPerformanceCounter, which is arguably fine and also works on amd architectures. U32 LLFastTimer::getCPUClockCount32() { - return (U32)(get_clock_count()>>8); + return get_clock_count() >> 8; } U64 LLFastTimer::getCPUClockCount64() { return get_clock_count(); } - -std::string LLFastTimer::sClockType = "QueryPerformanceCounter"; -#endif - -#endif - - -#if (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) -// -// Linux and Solaris implementation of CPU clock - non-x86. -// This is accurate but SLOW! Only use out of desperation. -// -// Try to use the MONOTONIC clock if available, this is a constant time counter -// with nanosecond resolution (but not necessarily accuracy) and attempts are -// made to synchronize this value between cores at kernel start. It should not -// be affected by CPU frequency. If not available use the REALTIME clock, but -// this may be affected by NTP adjustments or other user activity affecting -// the system time. -U64 LLFastTimer::getCPUClockCount64() -{ - struct timespec tp; - -#ifdef CLOCK_MONOTONIC // MONOTONIC supported at build-time? - if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime then ouch, try REALTIME -#endif - clock_gettime(CLOCK_REALTIME,&tp); - - return (tp.tv_sec*LLFastTimer::sClockResolution)+tp.tv_nsec; -} - -U32 LLFastTimer::getCPUClockCount32() -{ - return (U32)(LLFastTimer::getCPUClockCount64() >> 8); -} - -std::string LLFastTimer::sClockType = "clock_gettime"; - -#endif // (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) - - -#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) -// -// Mac+Linux+Solaris FAST x86 implementation of CPU clock -U32 LLFastTimer::getCPUClockCount32() -{ - U64 x; - __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); - return (U32)(x >> 8); -} - -U64 LLFastTimer::getCPUClockCount64() -{ - U64 x; - __asm__ volatile (".byte 0x0f, 0x31": "=A"(x)); - return x; -} - -std::string LLFastTimer::sClockType = "rdtsc"; -#endif \ No newline at end of file diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 3a7f30511..ddb2c1d3e 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -72,7 +72,12 @@ public: FTM_UPDATE_GRASS, FTM_UPDATE_TREE, FTM_UPDATE_AVATAR, - +#if MESH_ENABLED + FTM_UPDATE_RIGGED_VOLUME, + FTM_SKIN_RIGGED, + FTM_RIGGED_OCTREE, +#endif //MESH_ENABLED + // common render components FTM_SHADOW_GEOMETRY, FTM_SHADOW_RENDER, @@ -131,6 +136,12 @@ public: FTM_STATESORT, FTM_STATESORT_DRAWABLE, FTM_STATESORT_POSTSORT, +#if MESH_ENABLED + FTM_MESH_UPDATE, + FTM_MESH_LOCK1, + FTM_MESH_LOCK2, + FTM_LOAD_MESH_LOD, +#endif //MESH_ENABLED FTM_REBUILD_VBO, FTM_REBUILD_VOLUME_VB, FTM_REBUILD_BRIDGE_VB, @@ -256,7 +267,6 @@ public: static void reset(); static U64 countsPerSecond(); - static std::string sClockType; public: static int sCurDepth; static U64 sStart[FTM_MAX_DEPTH]; diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp index 76e0d2bc9..280606b4f 100644 --- a/indra/llcommon/llfoldertype.cpp +++ b/indra/llcommon/llfoldertype.cpp @@ -36,6 +36,7 @@ #include "llfoldertype.h" #include "lldictionary.h" #include "llmemory.h" +#include "llsingleton.h" ///---------------------------------------------------------------------------- /// Class LLFolderType @@ -95,7 +96,12 @@ LLFolderDictionary::LLFolderDictionary() addEntry(LLFolderType::FT_CURRENT_OUTFIT, new FolderEntry("current", TRUE)); addEntry(LLFolderType::FT_OUTFIT, new FolderEntry("outfit", FALSE)); addEntry(LLFolderType::FT_MY_OUTFITS, new FolderEntry("my_otfts", TRUE)); + + addEntry(LLFolderType::FT_MESH, new FolderEntry("mesh", TRUE)); + addEntry(LLFolderType::FT_INBOX, new FolderEntry("inbox", TRUE)); + addEntry(LLFolderType::FT_OUTBOX, new FolderEntry("outbox", TRUE)); + addEntry(LLFolderType::FT_BASIC_ROOT, new FolderEntry("basic_rt", TRUE)); addEntry(LLFolderType::FT_NONE, new FolderEntry("-1", FALSE)); }; diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h index e0ce9fa3f..7e7cfa2b9 100644 --- a/indra/llcommon/llfoldertype.h +++ b/indra/llcommon/llfoldertype.h @@ -87,9 +87,14 @@ public: FT_OUTFIT = 47, FT_MY_OUTFITS = 48, - FT_INBOX = 49, + FT_MESH = 49, - FT_COUNT = 50, + FT_INBOX = 50, + FT_OUTBOX = 51, + + FT_BASIC_ROOT = 52, + + FT_COUNT, FT_NONE = -1 }; diff --git a/indra/llcommon/llframetimer.cpp b/indra/llcommon/llframetimer.cpp index 138c67a36..d05b9875c 100644 --- a/indra/llcommon/llframetimer.cpp +++ b/indra/llcommon/llframetimer.cpp @@ -4,6 +4,7 @@ * $LicenseInfo:firstyear=2002&license=viewergpl$ * * Copyright (c) 2002-2009, Linden Research, Inc. + * Copyright (c) 2011, Aleric Inglewood. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -35,48 +36,55 @@ #include "llframetimer.h" +// Local constants. +static F64 const USEC_PER_SECOND = 1000000.0; +static F64 const USEC_TO_SEC_F64 = 0.000001; + // Static members -//LLTimer LLFrameTimer::sInternalTimer; -U64 LLFrameTimer::sStartTotalTime = totalTime(); -F64 LLFrameTimer::sFrameTime = 0.0; -U64 LLFrameTimer::sTotalTime = 0; -F64 LLFrameTimer::sTotalSeconds = 0.0; -S32 LLFrameTimer::sFrameCount = 0; -U64 LLFrameTimer::sFrameDeltaTime = 0; -const F64 USEC_PER_SECOND = 1000000.0; -const F64 USEC_TO_SEC_F64 = 0.000001; +U64 const LLFrameTimer::sStartTotalTime = totalTime(); // Application start in microseconds since epoch. +U64 LLFrameTimer::sTotalTime = LLFrameTimer::sStartTotalTime; // Current time in microseconds since epoch, updated at least once per frame. +F64 LLFrameTimer::sTotalSeconds = // Current time in seconds since epoch, updated together with LLFrameTimer::sTotalTime. + U64_to_F64(LLFrameTimer::sTotalTime) * USEC_TO_SEC_F64; +F64 LLFrameTimer::sFrameTime = 0.0; // Current time in seconds since application start, updated together with LLFrameTimer::sTotalTime. +// Updated exactly once per frame: +S32 LLFrameTimer::sFrameCount = 0; // Current frame number (number of frames since application start). +U64 LLFrameTimer::sPrevTotalTime = LLFrameTimer::sStartTotalTime; // Previous (frame) time in microseconds since epoch, updated once per frame. +U64 LLFrameTimer::sFrameDeltaTime = 0; // Microseconds between last two calls to LLFrameTimer::updateFrameTimeAndCount. // static void LLFrameTimer::updateFrameTime() { - U64 total_time = totalTime(); - sFrameDeltaTime = total_time - sTotalTime; - sTotalTime = total_time; + sTotalTime = totalTime(); sTotalSeconds = U64_to_F64(sTotalTime) * USEC_TO_SEC_F64; sFrameTime = U64_to_F64(sTotalTime - sStartTotalTime) * USEC_TO_SEC_F64; } -void LLFrameTimer::start() +// static +void LLFrameTimer::updateFrameTimeAndCount() { - reset(); - mStarted = TRUE; + updateFrameTime(); + sFrameDeltaTime = sTotalTime - sPrevTotalTime; + sPrevTotalTime = sTotalTime; + ++sFrameCount; +} + +void LLFrameTimer::reset(F32 expiration) +{ + llassert(!mPaused); + mStartTime = sFrameTime; + mExpiry = sFrameTime + expiration; +} + +void LLFrameTimer::start(F32 expiration) +{ + reset(expiration); + mRunning = true; // Start, if not already started. } void LLFrameTimer::stop() { - mStarted = FALSE; -} - -void LLFrameTimer::reset() -{ - mStartTime = sFrameTime; - mExpiry = sFrameTime; -} - -void LLFrameTimer::resetWithExpiry(F32 expiration) -{ - reset(); - setTimerExpirySec(expiration); + llassert(!mPaused); + mRunning = false; } // Don't combine pause/unpause with start/stop @@ -89,25 +97,31 @@ void LLFrameTimer::resetWithExpiry(F32 expiration) // Note: elapsed would also be valid with no unpause() call (= time run until pause() called) void LLFrameTimer::pause() { - if (mStarted) - mStartTime = sFrameTime - mStartTime; // save dtime - mStarted = FALSE; + if (!mPaused) + { + mStartTime = sFrameTime - mStartTime; // Abuse mStartTime to store the elapsed time so far. + } + mPaused = true; } void LLFrameTimer::unpause() { - if (!mStarted) - mStartTime = sFrameTime - mStartTime; // restore dtime - mStarted = TRUE; + if (mPaused) + { + mStartTime = sFrameTime - mStartTime; // Set mStartTime consistent with the elapsed time so far. + } + mPaused = false; } void LLFrameTimer::setTimerExpirySec(F32 expiration) { - mExpiry = expiration + mStartTime; + llassert(!mPaused); + mExpiry = mStartTime + expiration; } void LLFrameTimer::setExpiryAt(F64 seconds_since_epoch) { + llassert(!mPaused); mStartTime = sFrameTime; mExpiry = seconds_since_epoch - (USEC_TO_SEC_F64 * sStartTotalTime); } @@ -119,20 +133,14 @@ F64 LLFrameTimer::expiresAt() const return expires_at; } -BOOL LLFrameTimer::checkExpirationAndReset(F32 expiration) +bool LLFrameTimer::checkExpirationAndReset(F32 expiration) { - //llinfos << "LLFrameTimer::checkExpirationAndReset()" << llendl; - //llinfos << " mStartTime:" << mStartTime << llendl; - //llinfos << " sFrameTime:" << sFrameTime << llendl; - //llinfos << " mExpiry: " << mExpiry << llendl; - - if(hasExpired()) + if (hasExpired()) { - reset(); - setTimerExpirySec(expiration); - return TRUE; + reset(expiration); + return true; } - return FALSE; + return false; } // static diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h index f4775a992..e737a884e 100644 --- a/indra/llcommon/llframetimer.h +++ b/indra/llcommon/llframetimer.h @@ -6,6 +6,7 @@ * $LicenseInfo:firstyear=2002&license=viewergpl$ * * Copyright (c) 2002-2009, Linden Research, Inc. + * Copyright (c) 2011, Aleric Inglewood. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -37,7 +38,7 @@ /** * *NOTE: Because of limitations on linux which we do not really have * time to explore, the total time is derived from the frame time - * and is recsynchronized on every frame. + * and is resynchronized on every frame. */ #include "lltimer.h" @@ -46,61 +47,64 @@ class LL_COMMON_API LLFrameTimer { public: - LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(TRUE) {} + // Create an LLFrameTimer and start it. After creation it is running and in the state expired (hasExpired will return true). + LLFrameTimer(void) : mStartTime(sFrameTime), mExpiry(0), mRunning(true), mPaused(false) { } - // Return the number of seconds since the start of this - // application instance. + // Return the number of seconds since the start of the application. static F64 getElapsedSeconds() { // Loses msec precision after ~4.5 hours... return sFrameTime; } - // Return a low precision usec since epoch + // Return a low precision usec since epoch. static U64 getTotalTime() { - return sTotalTime ? sTotalTime : totalTime(); + llassert(sTotalTime); + return sTotalTime; } - // Return a low precision seconds since epoch + // Return a low precision seconds since epoch. static F64 getTotalSeconds() { return sTotalSeconds; } - // Call this method once per frame to update the current frame time. This is actually called - // at some other times as well + // Call this method once per frame to update the current frame time. + // This is actually called at some other times as well. static void updateFrameTime(); - // Call this method once, and only once, per frame to update the current frame count. - static void updateFrameCount() { sFrameCount++; } + // Call this method once, and only once, per frame to update the current frame count and sFrameDeltaTime. + static void updateFrameTimeAndCount(); - static U32 getFrameCount() { return sFrameCount; } + // Return current frame number (the number of frames since application start). + static U32 getFrameCount() { return sFrameCount; } - static F32 getFrameDeltaTimeF32(); + // Return duration of last frame in seconds. + static F32 getFrameDeltaTimeF32(); // Return seconds since the current frame started - static F32 getCurrentFrameTime(); + static F32 getCurrentFrameTime(); // MANIPULATORS - void start(); - void stop(); - void reset(); - void resetWithExpiry(F32 expiration); - void pause(); - void unpause(); + + void reset(F32 expiration = 0.f); // Same as start() but leaves mRunning off when called after stop(). + void start(F32 expiration = 0.f); // Reset and (re)start with expiration. + void stop(); // Stop running. + + void pause(); // Mark elapsed time so far. + void unpause(); // Move 'start' time in order to decrement time between pause and unpause from ElapsedTime. + void setTimerExpirySec(F32 expiration); void setExpiryAt(F64 seconds_since_epoch); - BOOL checkExpirationAndReset(F32 expiration); - F32 getElapsedTimeAndResetF32() { F32 t = F32(sFrameTime - mStartTime); reset(); return t; } - - void setAge(const F64 age) { mStartTime = sFrameTime - age; } + bool checkExpirationAndReset(F32 expiration); // Returns true when expired. Only resets if expired. + F32 getElapsedTimeAndResetF32() { F32 t = getElapsedTimeF32(); reset(); return t; } + void setAge(const F64 age) { llassert(!mPaused); mStartTime = sFrameTime - age; } // ACCESSORS - BOOL hasExpired() const { return (sFrameTime >= mExpiry); } - F32 getTimeToExpireF32() const { return (F32)(mExpiry - sFrameTime); } - F32 getElapsedTimeF32() const { return mStarted ? (F32)(sFrameTime - mStartTime) : (F32)mStartTime; } - BOOL getStarted() const { return mStarted; } + bool hasExpired() const { return sFrameTime >= mExpiry; } + F32 getElapsedTimeF32() const { llassert(mRunning); return mPaused ? (F32)mStartTime : (F32)(sFrameTime - mStartTime); } + bool getStarted() const { return mRunning; } // return the seconds since epoch when this timer will expire. F64 expiresAt() const; @@ -114,45 +118,52 @@ protected: // Aplication constants // - // Start time of opp in usec since epoch - static U64 sStartTotalTime; + // Application start in microseconds since epoch. + static U64 const sStartTotalTime; // // Data updated per frame // - // Seconds since application start + // Current time in seconds since application start, updated together with sTotalTime. static F64 sFrameTime; - // Time that has elapsed since last call to updateFrameTime() + // Microseconds between last two calls to updateFrameTimeAndCount (time between last two frames). static U64 sFrameDeltaTime; - // Total microseconds since epoch. + // Current time in microseconds since epoch, updated at least once per frame. static U64 sTotalTime; - // Seconds since epoch. + // Previous (frame) time in microseconds since epoch, updated once per frame. + static U64 sPrevTotalTime; + + // Current time in seconds since epoch, updated together with sTotalTime. static F64 sTotalSeconds; - // Total number of frames elapsed in application + // Current frame number (number of frames since application start). static S32 sFrameCount; // // Member data // - // Number of seconds after application start when this timer was - // started. Set equal to sFrameTime when reset. + // When not paused (mPaused is false): number of seconds since application start, + // otherwise this value is equal to the accumulated run time (ElapsedTime). + // Set equal to sFrameTime when reset. F64 mStartTime; - // Timer expires this many seconds after application start time. + // Timer expires when sFrameTime reaches this value (in seconds since application start). F64 mExpiry; - // Useful bit of state usually associated with timers, but does - // not affect actual functionality - BOOL mStarted; + // True when running, merely a boolean return by getStarted(). The timer always runs. + bool mRunning; + + // True when accumulating ElapsedTime. If false mStartTime has a different meaning + // and really unpause() should be called before anything else. + bool mPaused; }; // Glue code for Havok (or anything else that doesn't want the full .h files) -extern F32 getCurrentFrameTime(); +extern F32 getCurrentFrameTime(); #endif // LL_LLFRAMETIMER_H diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index e4e535222..46c72455a 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -49,6 +49,7 @@ class LL_COMMON_API LLInstanceTrackerBase : public boost::noncopyable protected: static void * & getInstances(std::type_info const & info); }; + /// This mix-in class adds support for tracking all instances of the specified class parameter T /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup /// If KEY is not provided, then instances are stored in a simple set @@ -58,13 +59,80 @@ class LLInstanceTracker : public LLInstanceTrackerBase { typedef typename std::map InstanceMap; typedef LLInstanceTracker MyT; - typedef boost::function KeyGetter; - typedef boost::function InstancePtrGetter; public: - /// Dereferencing key_iter gives you a const KEY& - typedef boost::transform_iterator key_iter; - /// Dereferencing instance_iter gives you a T& - typedef boost::indirect_iterator< boost::transform_iterator > instance_iter; + class instance_iter : public boost::iterator_facade + { + public: + typedef boost::iterator_facade super_t; + + instance_iter(const typename InstanceMap::iterator& it) + : mIterator(it) + { + ++sIterationNestDepth; + } + + ~instance_iter() + { + --sIterationNestDepth; + } + + + private: + friend class boost::iterator_core_access; + + void increment() { mIterator++; } + bool equal(instance_iter const& other) const + { + return mIterator == other.mIterator; + } + + T& dereference() const + { + return *(mIterator->second); + } + + typename InstanceMap::iterator mIterator; + }; + + class key_iter : public boost::iterator_facade + { + public: + typedef boost::iterator_facade super_t; + + key_iter(typename InstanceMap::iterator it) + : mIterator(it) + { + ++sIterationNestDepth; + } + + key_iter(const key_iter& other) + : mIterator(other.mIterator) + { + ++sIterationNestDepth; + } + + ~key_iter() + { + --sIterationNestDepth; + } + + + private: + friend class boost::iterator_core_access; + + void increment() { mIterator++; } + bool equal(key_iter const& other) const + { + return mIterator == other.mIterator; + } + + KEY& dereference() const + { + return const_cast(mIterator->first); + } + + typename InstanceMap::iterator mIterator; + }; static T* getInstance(const KEY& k) { @@ -72,42 +140,47 @@ public: return (found == getMap_().end()) ? NULL : found->second; } + static instance_iter beginInstances() + { + return instance_iter(getMap_().begin()); + } + + static instance_iter endInstances() + { + return instance_iter(getMap_().end()); + } + + static S32 instanceCount() { return getMap_().size(); } + static key_iter beginKeys() { - return boost::make_transform_iterator(getMap_().begin(), - boost::bind(&InstanceMap::value_type::first, _1)); + return key_iter(getMap_().begin()); } static key_iter endKeys() { - return boost::make_transform_iterator(getMap_().end(), - boost::bind(&InstanceMap::value_type::first, _1)); + return key_iter(getMap_().end()); } - static instance_iter beginInstances() - { - return instance_iter(boost::make_transform_iterator(getMap_().begin(), - boost::bind(&InstanceMap::value_type::second, _1))); - } - static instance_iter endInstances() - { - return instance_iter(boost::make_transform_iterator(getMap_().end(), - boost::bind(&InstanceMap::value_type::second, _1))); - } - static S32 instanceCount() { return getMap_().size(); } + protected: LLInstanceTracker(KEY key) { add_(key); } - virtual ~LLInstanceTracker() { remove_(); } + virtual ~LLInstanceTracker() + { + // it's unsafe to delete instances of this type while all instances are being iterated over. + llassert(sIterationNestDepth == 0); + remove_(); + } virtual void setKey(KEY key) { remove_(); add_(key); } - virtual const KEY& getKey() const { return mKey; } + virtual const KEY& getKey() const { return mInstanceKey; } private: void add_(KEY key) { - mKey = key; + mInstanceKey = key; getMap_()[key] = static_cast(this); } void remove_() { - getMap_().erase(mKey); + getMap_().erase(mInstanceKey); } static InstanceMap& getMap_() @@ -122,9 +195,12 @@ private: private: - KEY mKey; + KEY mInstanceKey; + static S32 sIterationNestDepth; }; +template S32 LLInstanceTracker::sIterationNestDepth = 0; + /// explicit specialization for default case where KEY is T* /// use a simple std::set template @@ -133,42 +209,55 @@ class LLInstanceTracker : public LLInstanceTrackerBase typedef typename std::set InstanceSet; typedef LLInstanceTracker MyT; public: - /// Dereferencing key_iter gives you a T* (since T* is the key) - typedef typename InstanceSet::iterator key_iter; - /// Dereferencing instance_iter gives you a T& - typedef boost::indirect_iterator instance_iter; /// for completeness of analogy with the generic implementation static T* getInstance(T* k) { return k; } static S32 instanceCount() { return getSet_().size(); } - // Instantiate this to get access to iterators for this type. It's a 'guard' in the sense - // that it treats deletes of this type as errors as long as there is an instance of - // this class alive in scope somewhere (i.e. deleting while iterating is bad). - class LLInstanceTrackerScopedGuard + class instance_iter : public boost::iterator_facade { public: - LLInstanceTrackerScopedGuard() + instance_iter(const typename InstanceSet::iterator& it) + : mIterator(it) { ++sIterationNestDepth; } - ~LLInstanceTrackerScopedGuard() + instance_iter(const instance_iter& other) + : mIterator(other.mIterator) + { + ++sIterationNestDepth; + } + + ~instance_iter() { --sIterationNestDepth; } - static instance_iter beginInstances() { return instance_iter(getSet_().begin()); } - static instance_iter endInstances() { return instance_iter(getSet_().end()); } - static key_iter beginKeys() { return getSet_().begin(); } - static key_iter endKeys() { return getSet_().end(); } + private: + friend class boost::iterator_core_access; + + void increment() { mIterator++; } + bool equal(instance_iter const& other) const + { + return mIterator == other.mIterator; + } + + T& dereference() const + { + return **mIterator; + } + + typename InstanceSet::iterator mIterator; }; + static instance_iter beginInstances() { return instance_iter(getSet_().begin()); } + static instance_iter endInstances() { return instance_iter(getSet_().end()); } + protected: LLInstanceTracker() { // it's safe but unpredictable to create instances of this type while all instances are being iterated over. I hate unpredictable. This assert will probably be turned on early in the next development cycle. - //llassert(sIterationNestDepth == 0); getSet_().insert(static_cast(this)); } virtual ~LLInstanceTracker() @@ -180,7 +269,6 @@ protected: LLInstanceTracker(const LLInstanceTracker& other) { - //llassert(sIterationNestDepth == 0); getSet_().insert(static_cast(this)); } diff --git a/indra/llcommon/llkeythrottle.h b/indra/llcommon/llkeythrottle.h index 873f50a65..4ac689163 100644 --- a/indra/llcommon/llkeythrottle.h +++ b/indra/llcommon/llkeythrottle.h @@ -118,6 +118,62 @@ public: THROTTLE_BLOCKED, // rate exceed, block key }; + F64 getActionCount(const T& id) + { + U64 now = 0; + if ( mIsRealtime ) + { + now = LLKeyThrottleImpl::getTime(); + } + else + { + now = LLKeyThrottleImpl::getFrame(); + } + + if (now >= (m.startTime + m.intervalLength)) + { + if (now < (m.startTime + 2 * m.intervalLength)) + { + // prune old data + delete m.prevMap; + m.prevMap = m.currMap; + m.currMap = new typename LLKeyThrottleImpl::EntryMap; + + m.startTime += m.intervalLength; + } + else + { + // lots of time has passed, all data is stale + delete m.prevMap; + delete m.currMap; + m.prevMap = new typename LLKeyThrottleImpl::EntryMap; + m.currMap = new typename LLKeyThrottleImpl::EntryMap; + + m.startTime = now; + } + } + + U32 prevCount = 0; + + typename LLKeyThrottleImpl::EntryMap::const_iterator prev = m.prevMap->find(id); + if (prev != m.prevMap->end()) + { + prevCount = prev->second.count; + } + + typename LLKeyThrottleImpl::Entry& curr = (*m.currMap)[id]; + + // curr.count is the number of keys in + // this current 'time slice' from the beginning of it until now + // prevCount is the number of keys in the previous + // time slice scaled to be one full time slice back from the current + // (now) time. + + // compute current, windowed rate + F64 timeInCurrent = ((F64)(now - m.startTime) / m.intervalLength); + F64 averageCount = curr.count + prevCount * (1.0 - timeInCurrent); + return averageCount; + } // call each time the key wants use State noteAction(const T& id, S32 weight = 1) { diff --git a/indra/llcommon/lllslconstants.h b/indra/llcommon/lllslconstants.h index b7c8356ee..06af6dd29 100644 --- a/indra/llcommon/lllslconstants.h +++ b/indra/llcommon/lllslconstants.h @@ -48,6 +48,7 @@ const U32 AGENT_TYPING = 0x0200; const U32 AGENT_CROUCHING = 0x0400; const U32 AGENT_BUSY = 0x0800; const U32 AGENT_ALWAYS_RUN = 0x1000; +const U32 AGENT_AUTOPILOT = 0x2000; const S32 LSL_REMOTE_DATA_CHANNEL = 1; const S32 LSL_REMOTE_DATA_REQUEST = 2; @@ -184,6 +185,10 @@ const S32 OBJECT_VELOCITY = 5; const S32 OBJECT_OWNER = 6; const S32 OBJECT_GROUP = 7; const S32 OBJECT_CREATOR = 8; +const S32 OBJECT_RUNNING_SCRIPT_COUNT = 9; +const S32 OBJECT_TOTAL_SCRIPT_COUNT = 10; +const S32 OBJECT_SCRIPT_MEMORY = 11; +const S32 OBJECT_SCRIPT_TIME = 12; // changed() event flags const U32 CHANGED_NONE = 0x0; @@ -198,5 +203,17 @@ const U32 CHANGED_OWNER = 0x80; const U32 CHANGED_REGION = 0x100; const U32 CHANGED_TELEPORT = 0x200; const U32 CHANGED_REGION_START = 0x400; +const U32 CHANGED_MEDIA = 0x800; +// Possible error results +const U32 LSL_STATUS_OK = 0; +const U32 LSL_STATUS_MALFORMED_PARAMS = 1000; +const U32 LSL_STATUS_TYPE_MISMATCH = 1001; +const U32 LSL_STATUS_BOUNDS_ERROR = 1002; +const U32 LSL_STATUS_NOT_FOUND = 1003; +const U32 LSL_STATUS_NOT_SUPPORTED = 1004; +const U32 LSL_STATUS_INTERNAL_ERROR = 1999; + +// Start per-function errors below, starting at 2000: +const U32 LSL_STATUS_WHITELIST_FAILED = 2001; #endif diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 39abd14ed..87be91c0c 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -276,37 +276,12 @@ void operator delete[] (void *p) #endif -//---------------------------------------------------------------------------- - -LLRefCount::LLRefCount() : - mRef(0) -{ -} - -LLRefCount::LLRefCount(const LLRefCount& other) -: mRef(0) -{ -} - -LLRefCount::~LLRefCount() -{ - if (mRef != 0) - { - llerrs << "deleting non-zero reference" << llendl; - } -} - -LLRefCount& LLRefCount::operator=(const LLRefCount&) -{ - // do nothing, since ref count is specific to *this* reference - return *this; -} //---------------------------------------------------------------------------- #if defined(LL_WINDOWS) -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { HANDLE self = GetCurrentProcess(); PROCESS_MEMORY_COUNTERS counters; @@ -320,6 +295,20 @@ U64 getCurrentRSS() return counters.WorkingSetSize; } +//static +U32 LLMemory::getWorkingSetSize() +{ + PROCESS_MEMORY_COUNTERS pmc ; + U32 ret = 0 ; + + if (GetProcessMemoryInfo( GetCurrentProcess(), &pmc, sizeof(pmc)) ) + { + ret = pmc.WorkingSetSize ; + } + + return ret ; +} + #elif defined(LL_DARWIN) /* @@ -344,7 +333,7 @@ U64 getCurrentRSS() // } // } -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { U64 residentSize = 0; task_basic_info_data_t basicInfo; @@ -366,9 +355,14 @@ U64 getCurrentRSS() return residentSize; } +U32 LLMemory::getWorkingSetSize() +{ + return 0 ; +} + #elif defined(LL_LINUX) -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { static const char statPath[] = "/proc/self/stat"; LLFILE *fp = LLFile::fopen(statPath, "r"); @@ -400,6 +394,10 @@ bail: return rss; } +U32 LLMemory::getWorkingSetSize() +{ + return 0 ; +} #elif LL_SOLARIS #include #include @@ -407,7 +405,7 @@ bail: #define _STRUCTURED_PROC 1 #include -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { char path [LL_MAX_PATH]; /* Flawfinder: ignore */ @@ -428,11 +426,22 @@ U64 getCurrentRSS() return((U64)proc_psinfo.pr_rssize * 1024); } + +U32 LLMemory::getWorkingSetSize() +{ + return 0 ; +} + #else -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { return 0; } +U32 LLMemory::getWorkingSetSize() +{ + return 0 ; +} + #endif diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 780ed9830..99aec9997 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -29,453 +29,115 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ -#ifndef LL_MEMORY_H -#define LL_MEMORY_H +#ifndef LLMEMORY_H +#define LLMEMORY_H + #include #include +#if !LL_WINDOWS +#include // uintptr_t +#endif #include "llerror.h" -extern S32 gTotalDAlloc; -extern S32 gTotalDAUse; -extern S32 gDACount; - -const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA; - //---------------------------------------------------------------------------- +#if LL_DEBUG +inline void* ll_aligned_malloc( size_t size, int align ) +{ + void* mem = malloc( size + (align - 1) + sizeof(void*) ); + char* aligned = ((char*)mem) + sizeof(void*); + aligned += align - ((uintptr_t)aligned & (align - 1)); + + ((void**)aligned)[-1] = mem; + return aligned; +} + +inline void ll_aligned_free( void* ptr ) +{ + free( ((void**)ptr)[-1] ); +} + +inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16(). +{ +#if defined(LL_WINDOWS) + return _mm_malloc(size, 16); +#elif defined(LL_DARWIN) + return malloc(size); // default osx malloc is 16 byte aligned. +#else + void *rtn; + if (LL_LIKELY(0 == posix_memalign(&rtn, 16, size))) + return rtn; + else // bad alignment requested, or out of memory + return NULL; +#endif +} + +inline void ll_aligned_free_16(void *p) +{ +#if defined(LL_WINDOWS) + _mm_free(p); +#elif defined(LL_DARWIN) + return free(p); +#else + free(p); // posix_memalign() is compatible with heap deallocator +#endif +} + +inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed with ll_aligned_free_32(). +{ +#if defined(LL_WINDOWS) + return _mm_malloc(size, 32); +#elif defined(LL_DARWIN) + return ll_aligned_malloc( size, 32 ); +#else + void *rtn; + if (LL_LIKELY(0 == posix_memalign(&rtn, 32, size))) + return rtn; + else // bad alignment requested, or out of memory + return NULL; +#endif +} + +inline void ll_aligned_free_32(void *p) +{ +#if defined(LL_WINDOWS) + _mm_free(p); +#elif defined(LL_DARWIN) + ll_aligned_free( p ); +#else + free(p); // posix_memalign() is compatible with heap deallocator +#endif +} +#else // LL_DEBUG +// ll_aligned_foo are noops now that we use tcmalloc everywhere (tcmalloc aligns automatically at appropriate intervals) +#define ll_aligned_malloc( size, align ) malloc(size) +#define ll_aligned_free( ptr ) free(ptr) +#define ll_aligned_malloc_16 malloc +#define ll_aligned_free_16 free +#define ll_aligned_malloc_32 malloc +#define ll_aligned_free_32 free +#endif // LL_DEBUG + class LL_COMMON_API LLMemory { public: static void initClass(); static void cleanupClass(); static void freeReserve(); + // Return the resident set size of the current process, in bytes. + // Return value is zero if not known. + static U64 getCurrentRSS(); + static U32 getWorkingSetSize(); private: static char* reserveMem; }; -//---------------------------------------------------------------------------- -// RefCount objects should generally only be accessed by way of LLPointer<>'s -// NOTE: LLPointer x = new LLFoo(); MAY NOT BE THREAD SAFE -// if LLFoo::LLFoo() does anything like put itself in an update queue. -// The queue may get accessed before it gets assigned to x. -// The correct implementation is: -// LLPointer x = new LLFoo; // constructor does not do anything interesting -// x->instantiate(); // does stuff like place x into an update queue - -// see llthread.h for LLThreadSafeRefCount - -//---------------------------------------------------------------------------- - -class LL_COMMON_API LLRefCount -{ -protected: - LLRefCount(const LLRefCount&); -private: - LLRefCount&operator=(const LLRefCount&); - -protected: - virtual ~LLRefCount(); // use unref() - -public: - LLRefCount(); - - void ref() - { - mRef++; - } - - S32 unref() - { - llassert(mRef >= 1); - if (0 == --mRef) - { - delete this; - return 0; - } - return mRef; - } - - S32 getNumRefs() const - { - return mRef; - } - -private: - S32 mRef; -}; - -//---------------------------------------------------------------------------- - -// Note: relies on Type having ref() and unref() methods -template class LLPointer -{ -public: - - LLPointer() : - mPointer(NULL) - { - } - - LLPointer(Type* ptr) : - mPointer(ptr) - { - ref(); - } - - LLPointer(const LLPointer& ptr) : - mPointer(ptr.mPointer) - { - ref(); - } - - // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLPointer(const LLPointer& ptr) : - mPointer(ptr.get()) - { - ref(); - } - - ~LLPointer() - { - unref(); - } - - Type* get() const { return mPointer; } - const Type* operator->() const { return mPointer; } - Type* operator->() { return mPointer; } - const Type& operator*() const { return *mPointer; } - Type& operator*() { return *mPointer; } - - operator BOOL() const { return (mPointer != NULL); } - operator bool() const { return (mPointer != NULL); } - bool operator!() const { return (mPointer == NULL); } - bool isNull() const { return (mPointer == NULL); } - bool notNull() const { return (mPointer != NULL); } - - operator Type*() const { return mPointer; } - operator const Type*() const { return mPointer; } - bool operator !=(Type* ptr) const { return (mPointer != ptr); } - bool operator ==(Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLPointer& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLPointer& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLPointer& ptr) const { return (mPointer > ptr.mPointer); } - - LLPointer& operator =(Type* ptr) - { - if( mPointer != ptr ) - { - unref(); - mPointer = ptr; - ref(); - } - - return *this; - } - - LLPointer& operator =(const LLPointer& ptr) - { - if( mPointer != ptr.mPointer ) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } - return *this; - } - - // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLPointer& operator =(const LLPointer& ptr) - { - if( mPointer != ptr.get() ) - { - unref(); - mPointer = ptr.get(); - ref(); - } - return *this; - } - - // Just exchange the pointers, which will not change the reference counts. - static void swap(LLPointer& a, LLPointer& b) - { - Type* temp = a.mPointer; - a.mPointer = b.mPointer; - b.mPointer = temp; - } - -protected: - void ref() - { - if (mPointer) - { - mPointer->ref(); - } - } - - void unref() - { - if (mPointer) - { - Type *tempp = mPointer; - mPointer = NULL; - tempp->unref(); - if (mPointer != NULL) - { - llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; - unref(); - } - } - } - -protected: - Type* mPointer; -}; - -//template -//class LLPointerTraits -//{ -// static Type* null(); -//}; -// -// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL. -// This is useful in instances where operations on NULL pointers are semantically safe and/or -// when error checking occurs at a different granularity or in a different part of the code -// than when referencing an object via a LLSafeHandle. -// - -template -class LLSafeHandle -{ -public: - LLSafeHandle() : - mPointer(NULL) - { - } - - LLSafeHandle(Type* ptr) : - mPointer(NULL) - { - assign(ptr); - } - - LLSafeHandle(const LLSafeHandle& ptr) : - mPointer(NULL) - { - assign(ptr.mPointer); - } - - // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLSafeHandle(const LLSafeHandle& ptr) : - mPointer(NULL) - { - assign(ptr.get()); - } - - ~LLSafeHandle() - { - unref(); - } - - const Type* operator->() const { return nonNull(mPointer); } - Type* operator->() { return nonNull(mPointer); } - - Type* get() const { return mPointer; } - // we disallow these operations as they expose our null objects to direct manipulation - // and bypass the reference counting semantics - //const Type& operator*() const { return *nonNull(mPointer); } - //Type& operator*() { return *nonNull(mPointer); } - - operator BOOL() const { return mPointer != NULL; } - operator bool() const { return mPointer != NULL; } - bool operator!() const { return mPointer == NULL; } - bool isNull() const { return mPointer == NULL; } - bool notNull() const { return mPointer != NULL; } - - - operator Type*() const { return mPointer; } - operator const Type*() const { return mPointer; } - bool operator !=(Type* ptr) const { return (mPointer != ptr); } - bool operator ==(Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLSafeHandle& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLSafeHandle& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLSafeHandle& ptr) const { return (mPointer > ptr.mPointer); } - - LLSafeHandle& operator =(Type* ptr) - { - assign(ptr); - return *this; - } - - LLSafeHandle& operator =(const LLSafeHandle& ptr) - { - assign(ptr.mPointer); - return *this; - } - - // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLSafeHandle& operator =(const LLSafeHandle& ptr) - { - assign(ptr.get()); - return *this; - } - -public: - typedef Type* (*NullFunc)(); - static const NullFunc sNullFunc; - -protected: - void ref() - { - if (mPointer) - { - mPointer->ref(); - } - } - - void unref() - { - if (mPointer) - { - Type *tempp = mPointer; - mPointer = NULL; - tempp->unref(); - if (mPointer != NULL) - { - llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; - unref(); - } - } - } - - void assign(Type* ptr) - { - if( mPointer != ptr ) - { - unref(); - mPointer = ptr; - ref(); - } - } - - static Type* nonNull(Type* ptr) - { - return ptr == NULL ? sNullFunc() : ptr; - } - -protected: - Type* mPointer; -}; - -// LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL -// NOT a smart pointer like LLPointer<> -// Useful for example in std::map > -// (std::map uses the default constructor for creating new entries) -template class LLInitializedPointer -{ -public: - LLInitializedPointer() : mPointer(NULL) {} - ~LLInitializedPointer() { delete mPointer; } - - const T* operator->() const { return mPointer; } - T* operator->() { return mPointer; } - const T& operator*() const { return *mPointer; } - T& operator*() { return *mPointer; } - operator const T*() const { return mPointer; } - operator T*() { return mPointer; } - T* operator=(T* x) { return (mPointer = x); } - operator bool() const { return mPointer != NULL; } - bool operator!() const { return mPointer == NULL; } - bool operator==(T* rhs) { return mPointer == rhs; } - bool operator==(const LLInitializedPointer* rhs) { return mPointer == rhs.mPointer; } - -protected: - T* mPointer; -}; - -//---------------------------------------------------------------------------- - -// LLSingleton implements the getInstance() method part of the Singleton -// pattern. It can't make the derived class constructors protected, though, so -// you have to do that yourself. -// -// There are two ways to use LLSingleton. The first way is to inherit from it -// while using the typename that you'd like to be static as the template -// parameter, like so: -// -// class Foo: public LLSingleton{}; -// -// Foo& instance = Foo::instance(); -// -// The second way is to use the singleton class directly, without inheritance: -// -// typedef LLSingleton FooSingleton; -// -// Foo& instance = FooSingleton::instance(); -// -// In this case, the class being managed as a singleton needs to provide an -// initSingleton() method since the LLSingleton virtual method won't be -// available -// -// As currently written, it is not thread-safe. -template -class LLSingleton -{ - static bool &needsInit() - { - static bool needs_init = true; - return needs_init; - } -public: - static bool instanceExists() - { - return !needsInit(); - } - virtual ~LLSingleton() {} -#ifdef LL_MSVC7 -// workaround for VC7 compiler bug -// adapted from http://www.codeproject.com/KB/tips/VC2003MeyersSingletonBug.aspx -// our version doesn't introduce a nested struct so that you can still declare LLSingleton -// a friend and hide your constructor - static T* getInstance() - { - LLSingleton singleton; - return singleton.vsHack(); - } - - T* vsHack() -#else - static T* getInstance() -#endif - { - static T instance; - bool &needs_init = needsInit(); - if (needs_init) - { - needs_init = false; - instance.initSingleton(); - } - return &instance; - } - - static T& instance() - { - return *getInstance(); - } - -private: - virtual void initSingleton() {} -}; - -//---------------------------------------------------------------------------- - -// Return the resident set size of the current process, in bytes. -// Return value is zero if not known. -LL_COMMON_API U64 getCurrentRSS(); +//EVENTUALLY REMOVE THESE: +#include "llpointer.h" +#include "llrefcount.h" +#include "llsingleton.h" +#include "llsafehandle.h" #endif diff --git a/indra/llcommon/llmortician.cpp b/indra/llcommon/llmortician.cpp index 2909f4514..c800b654b 100644 --- a/indra/llcommon/llmortician.cpp +++ b/indra/llcommon/llmortician.cpp @@ -74,9 +74,3 @@ void LLMortician::setZealous(BOOL b) { sDestroyImmediate = b; } - -// static -BOOL LLMortician::getZealous() -{ - return sDestroyImmediate; -} diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h index 55a101a97..59d284182 100644 --- a/indra/llcommon/llmortician.h +++ b/indra/llcommon/llmortician.h @@ -46,7 +46,6 @@ public: // sets destroy immediate true static void setZealous(BOOL b); - static BOOL getZealous(); private: static BOOL sDestroyImmediate; diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h new file mode 100644 index 000000000..affa04060 --- /dev/null +++ b/indra/llcommon/llpointer.h @@ -0,0 +1,170 @@ +/** + * @file llpointer.h + * @brief A reference-counted pointer for objects derived from LLRefCount + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLPOINTER_H +#define LLPOINTER_H + +#include "llerror.h" // *TODO: consider eliminating this + +//---------------------------------------------------------------------------- +// RefCount objects should generally only be accessed by way of LLPointer<>'s +// NOTE: LLPointer x = new LLFoo(); MAY NOT BE THREAD SAFE +// if LLFoo::LLFoo() does anything like put itself in an update queue. +// The queue may get accessed before it gets assigned to x. +// The correct implementation is: +// LLPointer x = new LLFoo; // constructor does not do anything interesting +// x->instantiate(); // does stuff like place x into an update queue + +// see llthread.h for LLThreadSafeRefCount + +//---------------------------------------------------------------------------- + +// Note: relies on Type having ref() and unref() methods +template class LLPointer +{ +public: + + LLPointer() : + mPointer(NULL) + { + } + + LLPointer(Type* ptr) : + mPointer(ptr) + { + ref(); + } + + LLPointer(const LLPointer& ptr) : + mPointer(ptr.mPointer) + { + ref(); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLPointer(const LLPointer& ptr) : + mPointer(ptr.get()) + { + ref(); + } + + ~LLPointer() + { + unref(); + } + + Type* get() const { return mPointer; } + const Type* operator->() const { return mPointer; } + Type* operator->() { return mPointer; } + const Type& operator*() const { return *mPointer; } + Type& operator*() { return *mPointer; } + + operator BOOL() const { return (mPointer != NULL); } + operator bool() const { return (mPointer != NULL); } + bool operator!() const { return (mPointer == NULL); } + bool isNull() const { return (mPointer == NULL); } + bool notNull() const { return (mPointer != NULL); } + + operator Type*() const { return mPointer; } + bool operator !=(Type* ptr) const { return (mPointer != ptr); } + bool operator ==(Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLPointer& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLPointer& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLPointer& ptr) const { return (mPointer > ptr.mPointer); } + + LLPointer& operator =(Type* ptr) + { + if( mPointer != ptr ) + { + unref(); + mPointer = ptr; + ref(); + } + + return *this; + } + + LLPointer& operator =(const LLPointer& ptr) + { + if( mPointer != ptr.mPointer ) + { + unref(); + mPointer = ptr.mPointer; + ref(); + } + return *this; + } + + // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLPointer& operator =(const LLPointer& ptr) + { + if( mPointer != ptr.get() ) + { + unref(); + mPointer = ptr.get(); + ref(); + } + return *this; + } + + // Just exchange the pointers, which will not change the reference counts. + static void swap(LLPointer& a, LLPointer& b) + { + Type* temp = a.mPointer; + a.mPointer = b.mPointer; + b.mPointer = temp; + } + +protected: + void ref() + { + if (mPointer) + { + mPointer->ref(); + } + } + + void unref() + { + if (mPointer) + { + Type *tempp = mPointer; + mPointer = NULL; + tempp->unref(); + if (mPointer != NULL) + { + llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; + unref(); + } + } + } + +protected: + Type* mPointer; +}; + +#endif diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index df49757a6..a956718e6 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -107,7 +107,17 @@ #endif -// Deal with the differences on Windows + +// Static linking with apr on windows needs to be declared. +#if LL_WINDOWS && !LL_COMMON_LINK_SHARED +#ifndef APR_DECLARE_STATIC +#define APR_DECLARE_STATIC // For APR on Windows +#endif +#ifndef APU_DECLARE_STATIC +#define APU_DECLARE_STATIC // For APR util on Windows +#endif +#endif + #if defined(LL_WINDOWS) #define BOOST_REGEX_NO_LIB 1 #define CURL_STATICLIB 1 @@ -159,12 +169,19 @@ #define LL_DLLIMPORT #endif // LL_WINDOWS -#ifdef llcommon_EXPORTS -// Compiling llcommon (shared) -#define LL_COMMON_API LL_DLLEXPORT -#else // llcommon_EXPORTS -// Using llcommon (shared) -#define LL_COMMON_API LL_DLLIMPORT -#endif // llcommon_EXPORTS +#if LL_COMMON_LINK_SHARED +// CMake automagically defines llcommon_EXPORTS only when building llcommon +// sources, and only when llcommon is a shared library (i.e. when +// LL_COMMON_LINK_SHARED). We must still test LL_COMMON_LINK_SHARED because +// otherwise we can't distinguish between (non-llcommon source) and (llcommon +// not shared). +# if defined(llcommon_EXPORTS) +# define LL_COMMON_API LL_DLLEXPORT +# else //llcommon_EXPORTS +# define LL_COMMON_API LL_DLLIMPORT +# endif //llcommon_EXPORTS +#else // LL_COMMON_LINK_SHARED +# define LL_COMMON_API +#endif // LL_COMMON_LINK_SHARED #endif // not LL_LINDEN_PREPROCESSOR_H diff --git a/indra/llcommon/llprocesslauncher.cpp b/indra/llcommon/llprocesslauncher.cpp index 45bd98e20..6a6854aa6 100644 --- a/indra/llcommon/llprocesslauncher.cpp +++ b/indra/llcommon/llprocesslauncher.cpp @@ -102,7 +102,7 @@ int LLProcessLauncher::launch(void) STARTUPINFOA sinfo; memset(&sinfo, 0, sizeof(sinfo)); - std::string args = "\"" + mExecutable + "\""; + std::string args = mExecutable; for(int i = 0; i < (int)mLaunchArguments.size(); i++) { args += " "; @@ -114,10 +114,30 @@ int LLProcessLauncher::launch(void) char *args2 = new char[args.size() + 1]; strcpy(args2, args.c_str()); - if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo ) ) + const char * working_directory = 0; + if(!mWorkingDir.empty()) working_directory = mWorkingDir.c_str(); + if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, working_directory, &sinfo, &pinfo ) ) { - // TODO: do better than returning the OS-specific error code on failure... result = GetLastError(); + + LPTSTR error_str = 0; + if( + FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + result, + 0, + (LPTSTR)&error_str, + 0, + NULL) + != 0) + { + char message[256]; + wcstombs(message, error_str, 256); + message[255] = 0; + llwarns << "CreateProcessA failed: " << message << llendl; + LocalFree(error_str); + } + if(result == 0) { // Make absolutely certain we return a non-zero value on failure. @@ -328,7 +348,11 @@ int LLProcessLauncher::launch(void) apr_file_t* out; AIAPRPool pool; pool.create(); +#if(APR_VERSION_MAJOR==1 && APR_VERSION_MINOR>=3 || APR_VERSION_MAJOR>1) apr_status_t status = apr_file_pipe_create_ex(&in, &out, APR_FULL_BLOCK, pool()); +#else + apr_status_t status = apr_file_pipe_create(&in, &out, pool()); +#endif assert(status == APR_SUCCESS); bool success = (status == APR_SUCCESS); if (success) diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 5be0414f9..2325efc38 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -31,8 +31,9 @@ #include "linden_common.h" #include "llqueuedthread.h" + #include "llstl.h" -#include "lltimer.h" +#include "lltimer.h" // ms_sleep() //============================================================================ @@ -41,7 +42,8 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : LLThread(name), mThreaded(threaded), mIdleThread(TRUE), - mNextHandle(0) + mNextHandle(0), + mStarted(FALSE) { if (mThreaded) { @@ -52,6 +54,10 @@ LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded) : // MAIN THREAD LLQueuedThread::~LLQueuedThread() { + if (!mThreaded) + { + endThread(); + } shutdown(); // ~LLThread() will be called here } @@ -90,6 +96,7 @@ void LLQueuedThread::shutdown() if (req->getStatus() == STATUS_QUEUED || req->getStatus() == STATUS_INPROGRESS) { ++active_count; + req->setStatus(STATUS_ABORTED); // avoid assert in deleteRequest } req->deleteRequest(); } @@ -105,6 +112,14 @@ void LLQueuedThread::shutdown() // virtual S32 LLQueuedThread::update(U32 max_time_ms) { + if (!mStarted) + { + if (!mThreaded) + { + startThread(); + mStarted = TRUE; + } + } return updateQueue(max_time_ms); } @@ -118,8 +133,11 @@ S32 LLQueuedThread::updateQueue(U32 max_time_ms) if (mThreaded) { pending = getPending(); + if(pending > 0) + { unpause(); } + } else { while (pending > 0) @@ -349,9 +367,9 @@ bool LLQueuedThread::completeRequest(handle_t handle) #if _DEBUG // llinfos << llformat("LLQueuedThread::Completed req [%08d]",handle) << llendl; #endif - //re insert to the queue to schedule for a delete later - req->setStatus(STATUS_DELETE); - mRequestQueue.insert(req); + mRequestHash.erase(handle); + req->deleteRequest(); +// check(); res = true; } unlockData(); @@ -395,19 +413,11 @@ S32 LLQueuedThread::processNextRequest() } req = *mRequestQueue.begin(); mRequestQueue.erase(mRequestQueue.begin()); - - if(req->getStatus() == STATUS_DELETE) - { - mRequestHash.erase(req); - req->deleteRequest(); - continue; - } - if ((req->getFlags() & FLAG_ABORT) || (mStatus == QUITTING)) { req->setStatus(STATUS_ABORTED); req->finishRequest(false); - if ((req->getFlags() & FLAG_AUTO_COMPLETE)) + if (req->getFlags() & FLAG_AUTO_COMPLETE) { mRequestHash.erase(req); req->deleteRequest(); @@ -418,9 +428,11 @@ S32 LLQueuedThread::processNextRequest() llassert_always(req->getStatus() == STATUS_QUEUED); break; } + U32 start_priority = 0 ; if (req) { req->setStatus(STATUS_INPROGRESS); + start_priority = req->getPriority(); } unlockData(); @@ -436,13 +448,12 @@ S32 LLQueuedThread::processNextRequest() { lockData(); req->setStatus(STATUS_COMPLETE); - req->finishRequest(true); - - if ((req->getFlags() & FLAG_AUTO_COMPLETE)) + if (req->getFlags() & FLAG_AUTO_COMPLETE) { mRequestHash.erase(req); req->deleteRequest(); +// check(); } unlockData(); } @@ -451,9 +462,8 @@ S32 LLQueuedThread::processNextRequest() lockData(); req->setStatus(STATUS_QUEUED); mRequestQueue.insert(req); - U32 priority = req->getPriority(); unlockData(); - if (priority < PRIORITY_NORMAL) + if (mThreaded && start_priority < PRIORITY_NORMAL) { ms_sleep(1); // sleep the thread a little } @@ -481,6 +491,7 @@ void LLQueuedThread::run() // call checPause() immediately so we don't try to do anything before the class is fully constructed checkPause(); startThread(); + mStarted = TRUE; while (1) { diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index e0e0f1bfe..f0c36896c 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -184,7 +184,7 @@ public: void waitOnPending(); void printQueueStats(); - S32 getPending(); + virtual S32 getPending(); bool getThreaded() { return mThreaded ? true : false; } // Request accessors @@ -202,6 +202,7 @@ public: protected: BOOL mThreaded; // if false, run on main thread and do updates during update() + BOOL mStarted; // required when mThreaded is false to call startThread() from update() LLAtomic32 mIdleThread; // request queue is empty (or we are quitting) and the thread is idle typedef std::set request_queue_t; diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp new file mode 100644 index 000000000..e1876599f --- /dev/null +++ b/indra/llcommon/llrefcount.cpp @@ -0,0 +1,164 @@ +/** + * @file llrefcount.cpp + * @brief Base class for reference counted objects for use with LLPointer + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llrefcount.h" + +#include "llerror.h" + +#if LL_REF_COUNT_DEBUG +#include "llthread.h" +#include "llapr.h" +#endif + +LLRefCount::LLRefCount(const LLRefCount& other) +: mRef(0) +{ +#if LL_REF_COUNT_DEBUG + if(gAPRPoolp) + { + mMutexp = new LLMutex(gAPRPoolp) ; + } + else + { + mMutexp = NULL ; + } + mCrashAtUnlock = FALSE ; +#endif +} + +LLRefCount& LLRefCount::operator=(const LLRefCount&) +{ + // do nothing, since ref count is specific to *this* reference + return *this; +} + +LLRefCount::LLRefCount() : + mRef(0) +{ +#if LL_REF_COUNT_DEBUG + if(gAPRPoolp) + { + mMutexp = new LLMutex(gAPRPoolp) ; + } + else + { + mMutexp = NULL ; + } + mCrashAtUnlock = FALSE ; +#endif +} + +LLRefCount::~LLRefCount() +{ + if (mRef != 0) + { + llerrs << "deleting non-zero reference" << llendl; + } + +#if LL_REF_COUNT_DEBUG + if(gAPRPoolp) + { + delete mMutexp ; + } +#endif +} + +#if LL_REF_COUNT_DEBUG +void LLRefCount::ref() const +{ + if(mMutexp) + { + if(mMutexp->isLocked()) + { + mCrashAtUnlock = TRUE ; + llerrs << "the mutex is locked by the thread: " << mLockedThreadID + << " Current thread: " << LLThread::currentID() << llendl ; + } + + mMutexp->lock() ; + mLockedThreadID = LLThread::currentID() ; + + mRef++; + + if(mCrashAtUnlock) + { + while(1); //crash here. + } + mMutexp->unlock() ; + } + else + { + mRef++; + } +} + +S32 LLRefCount::unref() const +{ + if(mMutexp) + { + if(mMutexp->isLocked()) + { + mCrashAtUnlock = TRUE ; + llerrs << "the mutex is locked by the thread: " << mLockedThreadID + << " Current thread: " << LLThread::currentID() << llendl ; + } + + mMutexp->lock() ; + mLockedThreadID = LLThread::currentID() ; + + llassert(mRef >= 1); + if (0 == --mRef) + { + if(mCrashAtUnlock) + { + while(1); //crash here. + } + mMutexp->unlock() ; + + delete this; + return 0; + } + + if(mCrashAtUnlock) + { + while(1); //crash here. + } + mMutexp->unlock() ; + return mRef; + } + else + { + llassert(mRef >= 1); + if (0 == --mRef) + { + delete this; + return 0; + } + return mRef; + } +} +#endif diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h new file mode 100644 index 000000000..8eb5d53f3 --- /dev/null +++ b/indra/llcommon/llrefcount.h @@ -0,0 +1,89 @@ +/** + * @file llrefcount.h + * @brief Base class for reference counted objects for use with LLPointer + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLREFCOUNT_H +#define LLREFCOUNT_H + +#include + +#define LL_REF_COUNT_DEBUG 0 +#if LL_REF_COUNT_DEBUG +class LLMutex ; +#endif + +//---------------------------------------------------------------------------- +// RefCount objects should generally only be accessed by way of LLPointer<>'s +// see llthread.h for LLThreadSafeRefCount +//---------------------------------------------------------------------------- + +class LL_COMMON_API LLRefCount +{ +protected: + LLRefCount(const LLRefCount& other); + LLRefCount& operator=(const LLRefCount&); + virtual ~LLRefCount(); // use unref() + +public: + LLRefCount(); + +#if LL_REF_COUNT_DEBUG + void ref() const ; + S32 unref() const ; +#else + inline void ref() const + { + mRef++; + } + + inline S32 unref() const + { + llassert(mRef >= 1); + if (0 == --mRef) + { + delete this; + return 0; + } + return mRef; + } +#endif + + //NOTE: when passing around a const LLRefCount object, this can return different results + // at different types, since mRef is mutable + S32 getNumRefs() const + { + return mRef; + } + +private: + mutable S32 mRef; + +#if LL_REF_COUNT_DEBUG + LLMutex* mMutexp ; + mutable U32 mLockedThreadID ; + mutable BOOL mCrashAtUnlock ; +#endif +}; + +#endif diff --git a/indra/llcommon/llsafehandle.h b/indra/llcommon/llsafehandle.h new file mode 100644 index 000000000..8d52d9bb1 --- /dev/null +++ b/indra/llcommon/llsafehandle.h @@ -0,0 +1,162 @@ +/** + * @file llsafehandle.h + * @brief Reference-counted object where Object() is valid, not NULL. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLSAFEHANDLE_H +#define LLSAFEHANDLE_H + +#include "llerror.h" // *TODO: consider eliminating this + +// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL. +// This is useful in instances where operations on NULL pointers are semantically safe and/or +// when error checking occurs at a different granularity or in a different part of the code +// than when referencing an object via a LLSafeHandle. + +template +class LLSafeHandle +{ +public: + LLSafeHandle() : + mPointer(NULL) + { + } + + LLSafeHandle(Type* ptr) : + mPointer(NULL) + { + assign(ptr); + } + + LLSafeHandle(const LLSafeHandle& ptr) : + mPointer(NULL) + { + assign(ptr.mPointer); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLSafeHandle(const LLSafeHandle& ptr) : + mPointer(NULL) + { + assign(ptr.get()); + } + + ~LLSafeHandle() + { + unref(); + } + + const Type* operator->() const { return nonNull(mPointer); } + Type* operator->() { return nonNull(mPointer); } + + Type* get() const { return mPointer; } + void clear() { assign(NULL); } + // we disallow these operations as they expose our null objects to direct manipulation + // and bypass the reference counting semantics + //const Type& operator*() const { return *nonNull(mPointer); } + //Type& operator*() { return *nonNull(mPointer); } + + operator BOOL() const { return mPointer != NULL; } + operator bool() const { return mPointer != NULL; } + bool operator!() const { return mPointer == NULL; } + bool isNull() const { return mPointer == NULL; } + bool notNull() const { return mPointer != NULL; } + + + operator Type*() const { return mPointer; } + operator const Type*() const { return mPointer; } + bool operator !=(Type* ptr) const { return (mPointer != ptr); } + bool operator ==(Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLSafeHandle& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLSafeHandle& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLSafeHandle& ptr) const { return (mPointer > ptr.mPointer); } + + LLSafeHandle& operator =(Type* ptr) + { + assign(ptr); + return *this; + } + + LLSafeHandle& operator =(const LLSafeHandle& ptr) + { + assign(ptr.mPointer); + return *this; + } + + // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLSafeHandle& operator =(const LLSafeHandle& ptr) + { + assign(ptr.get()); + return *this; + } + +public: + typedef Type* (*NullFunc)(); + static const NullFunc sNullFunc; + +protected: + void ref() + { + if (mPointer) + { + mPointer->ref(); + } + } + + void unref() + { + if (mPointer) + { + Type *tempp = mPointer; + mPointer = NULL; + tempp->unref(); + if (mPointer != NULL) + { + llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; + unref(); + } + } + } + + void assign(Type* ptr) + { + if( mPointer != ptr ) + { + unref(); + mPointer = ptr; + ref(); + } + } + + static Type* nonNull(Type* ptr) + { + return ptr == NULL ? sNullFunc() : ptr; + } + +protected: + Type* mPointer; +}; + +#endif diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp index ba7901cdb..7086e4248 100644 --- a/indra/llcommon/llsd.cpp +++ b/indra/llcommon/llsd.cpp @@ -754,11 +754,7 @@ void LLSD::insert(const String& k, const LLSD& v) { makeMap(impl).insert(k, v); LLSD& LLSD::with(const String& k, const LLSD& v) { makeMap(impl).insert(k, v); - #ifdef LL_MSVC7 - return *dynamic_cast(this); - #else - return *this; - #endif + return *this; } void LLSD::erase(const String& k) { makeMap(impl).erase(k); } @@ -784,11 +780,7 @@ void LLSD::insert(Integer i, const LLSD& v) { makeArray(impl).insert(i, v); } LLSD& LLSD::with(Integer i, const LLSD& v) { makeArray(impl).insert(i, v); - #ifdef LL_MSVC7 - return *dynamic_cast(this); - #else - return *this; - #endif + return *this; } void LLSD::append(const LLSD& v) { makeArray(impl).append(v); } void LLSD::erase(Integer i) { makeArray(impl).erase(i); } diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index b7f28d365..28700faae 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -34,11 +34,18 @@ #include "linden_common.h" #include "llsdserialize.h" -#include "llmemory.h" +#include "llpointer.h" #include "llstreamtools.h" // for fullread #include #include "apr_base64.h" +#if MESH_ENABLED +#ifdef LL_STANDALONE +# include +#else +# include "zlib/zlib.h" // for davep's dirty little zip functions +#endif +#endif //MESH_ENABLED #if !LL_WINDOWS #include // htonl & ntohl @@ -1990,3 +1997,181 @@ std::ostream& operator<<(std::ostream& s, const LLSD& llsd) return s; } +#if MESH_ENABLED + +//dirty little zippers -- yell at davep if these are horrid + +//return a string containing gzipped bytes of binary serialized LLSD +// VERY inefficient -- creates several copies of LLSD block in memory +std::string zip_llsd(LLSD& data) +{ + std::stringstream llsd_strm; + + LLSDSerialize::toBinary(data, llsd_strm); + + const U32 CHUNK = 65536; + + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + + S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION); + if (ret != Z_OK) + { + llwarns << "Failed to compress LLSD block." << llendl; + return std::string(); + } + + std::string source = llsd_strm.str(); + + U8 out[CHUNK]; + + strm.avail_in = source.size(); + strm.next_in = (U8*) source.data(); + U8* output = NULL; + + U32 cur_size = 0; + + U32 have = 0; + + do + { + strm.avail_out = CHUNK; + strm.next_out = out; + + ret = deflate(&strm, Z_FINISH); + if (ret == Z_OK || ret == Z_STREAM_END) + { //copy result into output + if (strm.avail_out >= CHUNK) + { + free(output); + llwarns << "Failed to compress LLSD block." << llendl; + return std::string(); + } + + have = CHUNK-strm.avail_out; + output = (U8*) realloc(output, cur_size+have); + memcpy(output+cur_size, out, have); + cur_size += have; + } + else + { + free(output); + llwarns << "Failed to compress LLSD block." << llendl; + return std::string(); + } + } + while (ret == Z_OK); + + std::string::size_type size = cur_size; + + std::string result((char*) output, size); + deflateEnd(&strm); + free(output); + +#if 0 //verify results work with unzip_llsd + std::istringstream test(result); + LLSD test_sd; + if (!unzip_llsd(test_sd, test, result.size())) + { + llerrs << "Invalid compression result!" << llendl; + } +#endif + + return result; +} + +//decompress a block of LLSD from provided istream +// not very efficient -- creats a copy of decompressed LLSD block in memory +// and deserializes from that copy using LLSDSerialize +bool unzip_llsd(LLSD& data, std::istream& is, S32 size) +{ + U8* result = NULL; + U32 cur_size = 0; + z_stream strm; + + const U32 CHUNK = 65536; + + U8 *in = new U8[size]; + 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) + { + inflateEnd(&strm); + free(result); + delete [] in; + return false; + } + + switch (ret) + { + case Z_NEED_DICT: + ret = Z_DATA_ERROR; + case Z_DATA_ERROR: + case Z_MEM_ERROR: + inflateEnd(&strm); + free(result); + delete [] in; + return false; + break; + } + + U32 have = CHUNK-strm.avail_out; + + result = (U8*) realloc(result, cur_size + have); + memcpy(result+cur_size, out, have); + cur_size += have; + + } while (ret == Z_OK); + + inflateEnd(&strm); + delete [] in; + + if (ret != Z_STREAM_END) + { + free(result); + return false; + } + + //result now points to the decompressed LLSD block + { + 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(); + + std::istringstream istr(res_str); + + if (!LLSDSerialize::fromBinary(data, istr, cur_size)) + { + llwarns << "Failed to unzip LLSD block" << llendl; + free(result); + return false; + } + } + + free(result); + return true; +} +#endif //MESH_ENABLED \ No newline at end of file diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index 7dd2603eb..6f657b464 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -36,8 +36,9 @@ #define LL_LLSDSERIALIZE_H #include +#include "llpointer.h" +#include "llrefcount.h" #include "llsd.h" -#include "llmemory.h" /** * @class LLSDParser @@ -787,4 +788,9 @@ public: } }; +#if MESH_ENABLED +//dirty little zip functions -- yell at davep +LL_COMMON_API std::string zip_llsd(LLSD& data); +LL_COMMON_API bool unzip_llsd(LLSD& data, std::istream& is, S32 size); +#endif //MESH_ENABLED #endif // LL_LLSDSERIALIZE_H diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 33206b46d..9bc17e0aa 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -37,6 +37,7 @@ #include #include "apr_base64.h" +#include extern "C" { @@ -734,6 +735,7 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) case ELEMENT_INTEGER: { S32 i; + // sscanf okay here with different locales - ints don't change for different locale settings like floats do. if ( sscanf(mCurrentContent.c_str(), "%d", &i ) == 1 ) { // See if sscanf works - it's faster value = i; @@ -747,15 +749,19 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) case ELEMENT_REAL: { - F64 r; - if ( sscanf(mCurrentContent.c_str(), "%lf", &r ) == 1 ) - { // See if sscanf works - it's faster - value = r; - } - else - { - value = LLSD(mCurrentContent).asReal(); - } + value = LLSD(mCurrentContent).asReal(); + // removed since this breaks when locale has decimal separator that isn't '.' + // investigated changing local to something compatible each time but deemed higher + // risk that just using LLSD.asReal() each time. + //F64 r; + //if ( sscanf(mCurrentContent.c_str(), "%lf", &r ) == 1 ) + //{ // See if sscanf works - it's faster + // value = r; + //} + //else + //{ + // value = LLSD(mCurrentContent).asReal(); + //} } break; @@ -777,10 +783,17 @@ void LLSDXMLParser::Impl::endElementHandler(const XML_Char* name) case ELEMENT_BINARY: { - S32 len = apr_base64_decode_len(mCurrentContent.c_str()); + // Regex is expensive, but only fix for whitespace in base64, + // created by python and other non-linden systems - DEV-39358 + // Fortunately we have very little binary passing now, + // so performance impact shold be negligible. + poppy 2009-09-04 + boost::regex r; + r.assign("\\s"); + std::string stripped = boost::regex_replace(mCurrentContent, r, ""); + S32 len = apr_base64_decode_len(stripped.c_str()); std::vector data; data.resize(len); - len = apr_base64_decode_binary(&data[0], mCurrentContent.c_str()); + len = apr_base64_decode_binary(&data[0], stripped.c_str()); data.resize(len); value = data; break; diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index aa0e0f369..2c91b68ef 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -46,6 +46,12 @@ #endif #include "llsdserialize.h" +#include "stringize.h" +#include "is_approx_equal_fraction.h" + +#include +#include +#include // U32 LLSD ll_sd_from_U32(const U32 val) @@ -171,6 +177,15 @@ char* ll_print_sd(const LLSD& sd) return buffer; } +char* ll_pretty_print_sd_ptr(const LLSD* sd) +{ + if (sd) + { + return ll_pretty_print_sd(*sd); + } + return NULL; +} + char* ll_pretty_print_sd(const LLSD& sd) { const U32 bufferSize = 10 * 1024; @@ -304,3 +319,363 @@ BOOL compare_llsd_with_template( return TRUE; } + +/***************************************************************************** +* Helpers for llsd_matches() +*****************************************************************************/ +// raw data used for LLSD::Type lookup +struct Data +{ + LLSD::Type type; + const char* name; +} typedata[] = +{ +#define def(type) { LLSD::type, #type + 4 } + def(TypeUndefined), + def(TypeBoolean), + def(TypeInteger), + def(TypeReal), + def(TypeString), + def(TypeUUID), + def(TypeDate), + def(TypeURI), + def(TypeBinary), + def(TypeMap), + def(TypeArray) +#undef def +}; + +// LLSD::Type lookup class into which we load the above static data +class TypeLookup +{ + typedef std::map MapType; + +public: + TypeLookup() + { + for (const Data *di(boost::begin(typedata)), *dend(boost::end(typedata)); di != dend; ++di) + { + mMap[di->type] = di->name; + } + } + + std::string lookup(LLSD::Type type) const + { + MapType::const_iterator found = mMap.find(type); + if (found != mMap.end()) + { + return found->second; + } + return STRINGIZE(""); + } + +private: + MapType mMap; +}; + +// static instance of the lookup class +static const TypeLookup sTypes; + +// describe a mismatch; phrasing may want tweaking +const std::string op(" required instead of "); + +// llsd_matches() wants to identify specifically where in a complex prototype +// structure the mismatch occurred. This entails passing a prefix string, +// empty for the top-level call. If the prototype contains an array of maps, +// and the mismatch occurs in the second map in a key 'foo', we want to +// decorate the returned string with: "[1]['foo']: etc." On the other hand, we +// want to omit the entire prefix -- including colon -- if the mismatch is at +// top level. This helper accepts the (possibly empty) recursively-accumulated +// prefix string, returning either empty or the original string with colon +// appended. +static std::string colon(const std::string& pfx) +{ + if (pfx.empty()) + return pfx; + return pfx + ": "; +} + +// param type for match_types +typedef std::vector TypeVector; + +// The scalar cases in llsd_matches() use this helper. In most cases, we can +// accept not only the exact type specified in the prototype, but also other +// types convertible to the expected type. That implies looping over an array +// of such types. If the actual type doesn't match any of them, we want to +// provide a list of acceptable conversions as well as the exact type, e.g.: +// "Integer (or Boolean, Real, String) required instead of UUID". Both the +// implementation and the calling logic are simplified by separating out the +// expected type from the convertible types. +static std::string match_types(LLSD::Type expect, // prototype.type() + const TypeVector& accept, // types convertible to that type + LLSD::Type actual, // type we're checking + const std::string& pfx) // as for llsd_matches +{ + // Trivial case: if the actual type is exactly what we expect, we're good. + if (actual == expect) + return ""; + + // For the rest of the logic, build up a suitable error string as we go so + // we only have to make a single pass over the list of acceptable types. + // If we detect success along the way, we'll simply discard the partial + // error string. + std::ostringstream out; + out << colon(pfx) << sTypes.lookup(expect); + + // If there are any convertible types, append that list. + if (! accept.empty()) + { + out << " ("; + const char* sep = "or "; + for (TypeVector::const_iterator ai(accept.begin()), aend(accept.end()); + ai != aend; ++ai, sep = ", ") + { + // Don't forget to return success if we match any of those types... + if (actual == *ai) + return ""; + out << sep << sTypes.lookup(*ai); + } + out << ')'; + } + // If we got this far, it's because 'actual' was not one of the acceptable + // types, so we must return an error. 'out' already contains colon(pfx) + // and the formatted list of acceptable types, so just append the mismatch + // phrase and the actual type. + out << op << sTypes.lookup(actual); + return out.str(); +} + +// see docstring in .h file +std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx) +{ + // An undefined prototype means that any data is valid. + // An undefined slot in an array or map prototype means that any data + // may fill that slot. + if (prototype.isUndefined()) + return ""; + // A prototype array must match a data array with at least as many + // entries. Moreover, every prototype entry must match the + // corresponding data entry. + if (prototype.isArray()) + { + if (! data.isArray()) + { + return STRINGIZE(colon(pfx) << "Array" << op << sTypes.lookup(data.type())); + } + if (data.size() < prototype.size()) + { + return STRINGIZE(colon(pfx) << "Array size " << prototype.size() << op + << "Array size " << data.size()); + } + for (LLSD::Integer i = 0; i < prototype.size(); ++i) + { + std::string match(llsd_matches(prototype[i], data[i], STRINGIZE('[' << i << ']'))); + if (! match.empty()) + { + return match; + } + } + return ""; + } + // A prototype map must match a data map. Every key in the prototype + // must have a corresponding key in the data map; every value in the + // prototype must match the corresponding key's value in the data. + if (prototype.isMap()) + { + if (! data.isMap()) + { + return STRINGIZE(colon(pfx) << "Map" << op << sTypes.lookup(data.type())); + } + // If there are a number of keys missing from the data, it would be + // frustrating to a coder to discover them one at a time, with a big + // build each time. Enumerate all missing keys. + std::ostringstream out; + out << colon(pfx); + const char* init = "Map missing keys: "; + const char* sep = init; + for (LLSD::map_const_iterator mi = prototype.beginMap(); mi != prototype.endMap(); ++mi) + { + if (! data.has(mi->first)) + { + out << sep << mi->first; + sep = ", "; + } + } + // So... are we missing any keys? + if (sep != init) + { + return out.str(); + } + // Good, the data block contains all the keys required by the + // prototype. Now match the prototype entries. + for (LLSD::map_const_iterator mi2 = prototype.beginMap(); mi2 != prototype.endMap(); ++mi2) + { + std::string match(llsd_matches(mi2->second, data[mi2->first], + STRINGIZE("['" << mi2->first << "']"))); + if (! match.empty()) + { + return match; + } + } + return ""; + } + // A String prototype can match String, Boolean, Integer, Real, UUID, + // Date and URI, because any of these can be converted to String. + if (prototype.isString()) + { + static LLSD::Type accept[] = + { + LLSD::TypeBoolean, + LLSD::TypeInteger, + LLSD::TypeReal, + LLSD::TypeUUID, + LLSD::TypeDate, + LLSD::TypeURI + }; + return match_types(prototype.type(), + TypeVector(boost::begin(accept), boost::end(accept)), + data.type(), + pfx); + } + // Boolean, Integer, Real match each other or String. TBD: ensure that + // a String value is numeric. + if (prototype.isBoolean() || prototype.isInteger() || prototype.isReal()) + { + static LLSD::Type all[] = + { + LLSD::TypeBoolean, + LLSD::TypeInteger, + LLSD::TypeReal, + LLSD::TypeString + }; + // Funny business: shuffle the set of acceptable types to include all + // but the prototype's type. Get the acceptable types in a set. + std::set rest(boost::begin(all), boost::end(all)); + // Remove the prototype's type because we pass that separately. + rest.erase(prototype.type()); + return match_types(prototype.type(), + TypeVector(rest.begin(), rest.end()), + data.type(), + pfx); + } + // UUID, Date and URI match themselves or String. + if (prototype.isUUID() || prototype.isDate() || prototype.isURI()) + { + static LLSD::Type accept[] = + { + LLSD::TypeString + }; + return match_types(prototype.type(), + TypeVector(boost::begin(accept), boost::end(accept)), + data.type(), + pfx); + } + // We don't yet know the conversion semantics associated with any new LLSD + // data type that might be added, so until we've been extended to handle + // them, assume it's strict: the new type matches only itself. (This is + // true of Binary, which is why we don't handle that case separately.) Too + // bad LLSD doesn't define isConvertible(Type to, Type from). + return match_types(prototype.type(), TypeVector(), data.type(), pfx); +} + +bool llsd_equals(const LLSD& lhs, const LLSD& rhs, unsigned bits) +{ + // We're comparing strict equality of LLSD representation rather than + // performing any conversions. So if the types aren't equal, the LLSD + // values aren't equal. + if (lhs.type() != rhs.type()) + { + return false; + } + + // Here we know both types are equal. Now compare values. + switch (lhs.type()) + { + case LLSD::TypeUndefined: + // Both are TypeUndefined. There's nothing more to know. + return true; + + case LLSD::TypeReal: + // This is where the 'bits' argument comes in handy. If passed + // explicitly, it means to use is_approx_equal_fraction() to compare. + if (bits >= 0) + { + return is_approx_equal_fraction(lhs.asReal(), rhs.asReal(), bits); + } + // Otherwise we compare bit representations, and the usual caveats + // about comparing floating-point numbers apply. Omitting 'bits' when + // comparing Real values is only useful when we expect identical bit + // representation for a given Real value, e.g. for integer-valued + // Reals. + return (lhs.asReal() == rhs.asReal()); + +#define COMPARE_SCALAR(type) \ + case LLSD::Type##type: \ + /* LLSD::URI has operator!=() but not operator==() */ \ + /* rely on the optimizer for all others */ \ + return (! (lhs.as##type() != rhs.as##type())) + + COMPARE_SCALAR(Boolean); + COMPARE_SCALAR(Integer); + COMPARE_SCALAR(String); + COMPARE_SCALAR(UUID); + COMPARE_SCALAR(Date); + COMPARE_SCALAR(URI); + COMPARE_SCALAR(Binary); + +#undef COMPARE_SCALAR + + case LLSD::TypeArray: + { + LLSD::array_const_iterator + lai(lhs.beginArray()), laend(lhs.endArray()), + rai(rhs.beginArray()), raend(rhs.endArray()); + // Compare array elements, walking the two arrays in parallel. + for ( ; lai != laend && rai != raend; ++lai, ++rai) + { + // If any one array element is unequal, the arrays are unequal. + if (! llsd_equals(*lai, *rai, bits)) + return false; + } + // Here we've reached the end of one or the other array. They're equal + // only if they're BOTH at end: that is, if they have equal length too. + return (lai == laend && rai == raend); + } + + case LLSD::TypeMap: + { + // Build a set of all rhs keys. + std::set rhskeys; + for (LLSD::map_const_iterator rmi(rhs.beginMap()), rmend(rhs.endMap()); + rmi != rmend; ++rmi) + { + rhskeys.insert(rmi->first); + } + // Now walk all the lhs keys. + for (LLSD::map_const_iterator lmi(lhs.beginMap()), lmend(lhs.endMap()); + lmi != lmend; ++lmi) + { + // Try to erase this lhs key from the set of rhs keys. If rhs has + // no such key, the maps are unequal. erase(key) returns count of + // items erased. + if (rhskeys.erase(lmi->first) != 1) + return false; + // Both maps have the current key. Compare values. + if (! llsd_equals(lmi->second, rhs[lmi->first], bits)) + return false; + } + // We've now established that all the lhs keys have equal values in + // both maps. The maps are equal unless rhs contains a superset of + // those keys. + return rhskeys.empty(); + } + + default: + // We expect that every possible type() value is specifically handled + // above. Failing to extend this switch to support a new LLSD type is + // an error that must be brought to the coder's attention. + LL_ERRS("llsd_equals") << "llsd_equals(" << lhs << ", " << rhs << ", " << bits << "): " + "unknown type " << lhs.type() << LL_ENDL; + return false; // pacify the compiler + } +} diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index bb5765539..f57cab3e0 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -35,7 +35,7 @@ #ifndef LL_LLSDUTIL_H #define LL_LLSDUTIL_H -#include "llsd.h" +class LLSD; // U32 LL_COMMON_API LLSD ll_sd_from_U32(const U32); @@ -59,6 +59,7 @@ LL_COMMON_API LLSD ll_binary_from_string(const LLSD& sd); LL_COMMON_API char* ll_print_sd(const LLSD& sd); // Serializes sd to static buffer and returns pointer, using "pretty printing" mode. +LL_COMMON_API char* ll_pretty_print_sd_ptr(const LLSD* sd); LL_COMMON_API char* ll_pretty_print_sd(const LLSD& sd); //compares the structure of an LLSD to a template LLSD and stores the @@ -73,6 +74,66 @@ LL_COMMON_API BOOL compare_llsd_with_template( const LLSD& template_llsd, LLSD& resultant_llsd); +/** + * Recursively determine whether a given LLSD data block "matches" another + * LLSD prototype. The returned string is empty() on success, non-empty() on + * mismatch. + * + * This function tests structure (types) rather than data values. It is + * intended for when a consumer expects an LLSD block with a particular + * structure, and must succinctly detect whether the arriving block is + * well-formed. For instance, a test of the form: + * @code + * if (! (data.has("request") && data.has("target") && data.has("modifier") ...)) + * @endcode + * could instead be expressed by initializing a prototype LLSD map with the + * required keys and writing: + * @code + * if (! llsd_matches(prototype, data).empty()) + * @endcode + * + * A non-empty return value is an error-message fragment intended to indicate + * to (English-speaking) developers where in the prototype structure the + * mismatch occurred. + * + * * If a slot in the prototype isUndefined(), then anything is valid at that + * place in the real object. (Passing prototype == LLSD() matches anything + * at all.) + * * An array in the prototype must match a data array at least that large. + * (Additional entries in the data array are ignored.) Every isDefined() + * entry in the prototype array must match the corresponding entry in the + * data array. + * * A map in the prototype must match a map in the data. Every key in the + * prototype map must match a corresponding key in the data map. (Additional + * keys in the data map are ignored.) Every isDefined() value in the + * prototype map must match the corresponding key's value in the data map. + * * Scalar values in the prototype are tested for @em type rather than value. + * For instance, a String in the prototype matches any String at all. In + * effect, storing an Integer at a particular place in the prototype asserts + * that the caller intends to apply asInteger() to the corresponding slot in + * the data. + * * A String in the prototype matches String, Boolean, Integer, Real, UUID, + * Date and URI, because asString() applied to any of these produces a + * meaningful result. + * * Similarly, a Boolean, Integer or Real in the prototype can match any of + * Boolean, Integer or Real in the data -- or even String. + * * UUID matches UUID or String. + * * Date matches Date or String. + * * URI matches URI or String. + * * Binary in the prototype matches only Binary in the data. + * + * @TODO: when a Boolean, Integer or Real in the prototype matches a String in + * the data, we should examine the String @em value to ensure it can be + * meaningfully converted to the requested type. The same goes for UUID, Date + * and URI. + */ +LL_COMMON_API std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx=""); + +/// Deep equality. If you want to compare LLSD::Real values for approximate +/// equality rather than bitwise equality, pass @a bits as for +/// is_approx_equal_fraction(). +LL_COMMON_API bool llsd_equals(const LLSD& lhs, const LLSD& rhs, unsigned bits=-1); + // Simple function to copy data out of input & output iterators if // there is no need for casting. template LLSD llsd_copy_array(Input iter, Input end) @@ -85,4 +146,283 @@ template LLSD llsd_copy_array(Input iter, Input end) return dest; } +/***************************************************************************** +* LLSDArray +*****************************************************************************/ +/** + * Construct an LLSD::Array inline, with implicit conversion to LLSD. Usage: + * + * @code + * void somefunc(const LLSD&); + * ... + * somefunc(LLSDArray("text")(17)(3.14)); + * @endcode + * + * For completeness, LLSDArray() with no args constructs an empty array, so + * LLSDArray()("text")(17)(3.14) produces an array equivalent to the + * above. But for most purposes, LLSD() is already equivalent to an empty + * array, and if you explicitly want an empty isArray(), there's + * LLSD::emptyArray(). However, supporting a no-args LLSDArray() constructor + * follows the principle of least astonishment. + */ +class LLSDArray +{ +public: + LLSDArray(): + _data(LLSD::emptyArray()) + {} + + /** + * Need an explicit copy constructor. Consider the following: + * + * @code + * LLSD array_of_arrays(LLSDArray(LLSDArray(17)(34)) + * (LLSDArray("x")("y"))); + * @endcode + * + * The coder intends to construct [[17, 34], ["x", "y"]]. + * + * With the compiler's implicit copy constructor, s/he gets instead + * [17, 34, ["x", "y"]]. + * + * The expression LLSDArray(17)(34) constructs an LLSDArray with those two + * values. The reader assumes it should be converted to LLSD, as we always + * want with LLSDArray, before passing it to the @em outer LLSDArray + * constructor! This copy constructor makes that happen. + */ + LLSDArray(const LLSDArray& inner): + _data(LLSD::emptyArray()) + { + _data.append(inner); + } + + LLSDArray(const LLSD& value): + _data(LLSD::emptyArray()) + { + _data.append(value); + } + + LLSDArray& operator()(const LLSD& value) + { + _data.append(value); + return *this; + } + + operator LLSD() const { return _data; } + LLSD get() const { return _data; } + +private: + LLSD _data; +}; + +/***************************************************************************** +* LLSDMap +*****************************************************************************/ +/** + * Construct an LLSD::Map inline, with implicit conversion to LLSD. Usage: + * + * @code + * void somefunc(const LLSD&); + * ... + * somefunc(LLSDMap("alpha", "abc")("number", 17)("pi", 3.14)); + * @endcode + * + * For completeness, LLSDMap() with no args constructs an empty map, so + * LLSDMap()("alpha", "abc")("number", 17)("pi", 3.14) produces a map + * equivalent to the above. But for most purposes, LLSD() is already + * equivalent to an empty map, and if you explicitly want an empty isMap(), + * there's LLSD::emptyMap(). However, supporting a no-args LLSDMap() + * constructor follows the principle of least astonishment. + */ +class LLSDMap +{ +public: + LLSDMap(): + _data(LLSD::emptyMap()) + {} + LLSDMap(const LLSD::String& key, const LLSD& value): + _data(LLSD::emptyMap()) + { + _data[key] = value; + } + + LLSDMap& operator()(const LLSD::String& key, const LLSD& value) + { + _data[key] = value; + return *this; + } + + operator LLSD() const { return _data; } + LLSD get() const { return _data; } + +private: + LLSD _data; +}; + +/***************************************************************************** +* LLSDParam +*****************************************************************************/ +/** + * LLSDParam is a customization point for passing LLSD values to function + * parameters of more or less arbitrary type. LLSD provides a small set of + * native conversions; but if a generic algorithm explicitly constructs an + * LLSDParam object in the function's argument list, a consumer can provide + * LLSDParam specializations to support more different parameter types than + * LLSD's native conversions. + * + * Usage: + * + * @code + * void somefunc(const paramtype&); + * ... + * somefunc(..., LLSDParam(someLLSD), ...); + * @endcode + */ +template +class LLSDParam +{ +public: + /** + * Default implementation converts to T on construction, saves converted + * value for later retrieval + */ + LLSDParam(const LLSD& value): + _value(value) + {} + + operator T() const { return _value; } + +private: + T _value; +}; + +/** + * Turns out that several target types could accept an LLSD param using any of + * a few different conversions, e.g. LLUUID's constructor can accept LLUUID or + * std::string. Therefore, the compiler can't decide which LLSD conversion + * operator to choose, even though to us it seems obvious. But that's okay, we + * can specialize LLSDParam for such target types, explicitly specifying the + * desired conversion -- that's part of what LLSDParam is all about. Turns out + * we have to do that enough to make it worthwhile generalizing. Use a macro + * because I need to specify one of the asReal, etc., explicit conversion + * methods as well as a type. If I'm overlooking a clever way to implement + * that using a template instead, feel free to reimplement. + */ +#define LLSDParam_for(T, AS) \ +template <> \ +class LLSDParam \ +{ \ +public: \ + LLSDParam(const LLSD& value): \ + _value(value.AS()) \ + {} \ + \ + operator T() const { return _value; } \ + \ +private: \ + T _value; \ +} + +LLSDParam_for(float, asReal); +LLSDParam_for(LLUUID, asUUID); +LLSDParam_for(LLDate, asDate); +LLSDParam_for(LLURI, asURI); +LLSDParam_for(LLSD::Binary, asBinary); + +/** + * LLSDParam is an example of the kind of conversion you can + * support with LLSDParam beyond native LLSD conversions. Normally you can't + * pass an LLSD object to a function accepting const char* -- but you can + * safely pass an LLSDParam(yourLLSD). + */ +template <> +class LLSDParam +{ +private: + // The difference here is that we store a std::string rather than a const + // char*. It's important that the LLSDParam object own the std::string. + std::string _value; + // We don't bother storing the incoming LLSD object, but we do have to + // distinguish whether _value is an empty string because the LLSD object + // contains an empty string or because it's isUndefined(). + bool _undefined; + +public: + LLSDParam(const LLSD& value): + _value(value), + _undefined(value.isUndefined()) + {} + + // The const char* we retrieve is for storage owned by our _value member. + // That's how we guarantee that the const char* is valid for the lifetime + // of this LLSDParam object. Constructing your LLSDParam in the argument + // list should ensure that the LLSDParam object will persist for the + // duration of the function call. + operator const char*() const + { + if (_undefined) + { + // By default, an isUndefined() LLSD object's asString() method + // will produce an empty string. But for a function accepting + // const char*, it's often important to be able to pass NULL, and + // isUndefined() seems like the best way. If you want to pass an + // empty string, you can still pass LLSD(""). Without this special + // case, though, no LLSD value could pass NULL. + return NULL; + } + return _value.c_str(); + } +}; + +namespace llsd +{ + +/***************************************************************************** +* BOOST_FOREACH() helpers for LLSD +*****************************************************************************/ +/// Usage: BOOST_FOREACH(LLSD item, inArray(someLLSDarray)) { ... } +class inArray +{ +public: + inArray(const LLSD& array): + _array(array) + {} + + typedef LLSD::array_const_iterator const_iterator; + typedef LLSD::array_iterator iterator; + + iterator begin() { return _array.beginArray(); } + iterator end() { return _array.endArray(); } + const_iterator begin() const { return _array.beginArray(); } + const_iterator end() const { return _array.endArray(); } + +private: + LLSD _array; +}; + +/// MapEntry is what you get from dereferencing an LLSD::map_[const_]iterator. +typedef std::map::value_type MapEntry; + +/// Usage: BOOST_FOREACH([const] MapEntry& e, inMap(someLLSDmap)) { ... } +class inMap +{ +public: + inMap(const LLSD& map): + _map(map) + {} + + typedef LLSD::map_const_iterator const_iterator; + typedef LLSD::map_iterator iterator; + + iterator begin() { return _map.beginMap(); } + iterator end() { return _map.endMap(); } + const_iterator begin() const { return _map.beginMap(); } + const_iterator end() const { return _map.endMap(); } + +private: + LLSD _map; +}; + +} // namespace llsd + #endif // LL_LLSDUTIL_H diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp new file mode 100644 index 000000000..eb8e2c945 --- /dev/null +++ b/indra/llcommon/llsingleton.cpp @@ -0,0 +1,32 @@ +/** + * @file llsingleton.cpp + * @author Brad Kittenbrink + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llsingleton.h" + +std::map * LLSingletonRegistry::sSingletonMap = NULL; + diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h new file mode 100644 index 000000000..00757be27 --- /dev/null +++ b/indra/llcommon/llsingleton.h @@ -0,0 +1,207 @@ +/** + * @file llsingleton.h + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLSINGLETON_H +#define LLSINGLETON_H + +#include "llerror.h" // *TODO: eliminate this + +#include +#include + +/// @brief A global registry of all singletons to prevent duplicate allocations +/// across shared library boundaries +class LL_COMMON_API LLSingletonRegistry { + private: + typedef std::map TypeMap; + static TypeMap * sSingletonMap; + + static void checkInit() + { + if(sSingletonMap == NULL) + { + sSingletonMap = new TypeMap(); + } + } + + public: + template static void * & get() + { + std::string name(typeid(T).name()); + + checkInit(); + + // the first entry of the pair returned by insert will be either the existing + // iterator matching our key, or the newly inserted NULL initialized entry + // see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html + TypeMap::iterator result = + sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first; + + return result->second; + } +}; + +// LLSingleton implements the getInstance() method part of the Singleton +// pattern. It can't make the derived class constructors protected, though, so +// you have to do that yourself. +// +// There are two ways to use LLSingleton. The first way is to inherit from it +// while using the typename that you'd like to be static as the template +// parameter, like so: +// +// class Foo: public LLSingleton{}; +// +// Foo& instance = Foo::instance(); +// +// The second way is to use the singleton class directly, without inheritance: +// +// typedef LLSingleton FooSingleton; +// +// Foo& instance = FooSingleton::instance(); +// +// In this case, the class being managed as a singleton needs to provide an +// initSingleton() method since the LLSingleton virtual method won't be +// available +// +// As currently written, it is not thread-safe. + +template +class LLSingleton : private boost::noncopyable +{ + +private: + typedef enum e_init_state + { + UNINITIALIZED, + CONSTRUCTING, + INITIALIZING, + INITIALIZED, + DELETED + } EInitState; + + // stores pointer to singleton instance + // and tracks initialization state of singleton + struct SingletonInstanceData + { + EInitState mInitState; + DERIVED_TYPE* mSingletonInstance; + + SingletonInstanceData() + : mSingletonInstance(NULL), + mInitState(UNINITIALIZED) + {} + + ~SingletonInstanceData() + { + SingletonInstanceData& data = getData(); + if (data.mInitState != DELETED) + { + deleteSingleton(); + } + } + }; + +public: + virtual ~LLSingleton() + { + SingletonInstanceData& data = getData(); + data.mSingletonInstance = NULL; + data.mInitState = DELETED; + } + + // Can be used to control when the singleton is deleted. Not normally needed. + static void deleteSingleton() + { + delete getData().mSingletonInstance; + getData().mSingletonInstance = NULL; + getData().mInitState = DELETED; + } + + static SingletonInstanceData& getData() + { + // this is static to cache the lookup results + static void * & registry = LLSingletonRegistry::get(); + + // *TODO - look into making this threadsafe + if(NULL == registry) + { + static SingletonInstanceData data; + registry = &data; + } + + return *static_cast(registry); + } + + static DERIVED_TYPE* getInstance() + { + SingletonInstanceData& data = getData(); + + if (data.mInitState == CONSTRUCTING) + { + llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl; + } + + if (data.mInitState == DELETED) + { + llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl; + } + + if (!data.mSingletonInstance) + { + data.mInitState = CONSTRUCTING; + data.mSingletonInstance = new DERIVED_TYPE(); + data.mInitState = INITIALIZING; + data.mSingletonInstance->initSingleton(); + data.mInitState = INITIALIZED; + } + + return data.mSingletonInstance; + } + + // Reference version of getInstance() + // Preferred over getInstance() as it disallows checking for NULL + static DERIVED_TYPE& instance() + { + return *getInstance(); + } + + // Has this singleton been created uet? + // Use this to avoid accessing singletons before the can safely be constructed + static bool instanceExists() + { + return getData().mInitState == INITIALIZED; + } + + // Has this singleton already been deleted? + // Use this to avoid accessing singletons from a static object's destructor + static bool destroyed() + { + return getData().mInitState == DELETED; + } + +private: + virtual void initSingleton() {} +}; + +#endif diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index 0583a0539..40ae67c51 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -43,9 +43,10 @@ // statics -BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information +S32 LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS; // Control what is being recorded LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step" +LLStat::stat_map_t LLStat::sStatList; //------------------------------------------------------------------------ // Live config file to trigger stats logging @@ -129,6 +130,7 @@ bool LLStatsConfigFile::loadFile() F32 duration = 0.f; F32 interval = 0.f; + S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS; const char * w = "duration"; if (stats_config.has(w)) @@ -140,8 +142,18 @@ bool LLStatsConfigFile::loadFile() { interval = (F32)stats_config[w].asReal(); } + w = "flags"; + if (stats_config.has(w)) + { + flags = (S32)stats_config[w].asInteger(); + if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS && + duration > 0) + { // No flags passed in, but have a duration, so reset to basic stats + flags = LLPerfBlock::LLSTATS_BASIC_STATS; + } + } - mStatsp->setReportPerformanceDuration( duration ); + mStatsp->setReportPerformanceDuration( duration, flags ); mStatsp->setReportPerformanceInterval( interval ); if ( duration > 0 ) @@ -253,13 +265,14 @@ void LLPerfStats::dumpIntervalPerformanceStats() } } -// Set length of performance stat recording -void LLPerfStats::setReportPerformanceDuration( F32 seconds ) +// Set length of performance stat recording. +// If turning stats on, caller must provide flags +void LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ ) { if ( seconds <= 0.f ) { mReportPerformanceStatEnd = 0.0; - LLPerfBlock::setStatsEnabled( FALSE ); + LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS); // Make sure all recording is off mFrameStatsFile.close(); LLPerfBlock::clearDynamicStats(); } @@ -268,8 +281,8 @@ void LLPerfStats::setReportPerformanceDuration( F32 seconds ) mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds); // Clear failure flag to try and create the log file once mFrameStatsFileFailure = FALSE; - LLPerfBlock::setStatsEnabled( TRUE ); mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame) + LLPerfBlock::setStatsFlags(flags); } } @@ -611,11 +624,26 @@ LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicSta } } -// Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key. -// These are also turned on or off via the switch passed in -LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat(NULL), mDynamicStat(NULL) +// Use this constructor for normal, optional LLPerfBlock time slices +LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL) { - if (!sStatsEnabled) return; + if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0) + { // These are off unless the base set is enabled + return; + } + + initDynamicStat(key); +} + + +// Use this constructor for dynamically created LLPerfBlock time slices +// that are only enabled by specific control flags +LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL) +{ + if ((sStatsFlags & flags) == 0) + { + return; + } if (NULL == key2 || strlen(key2) == 0) { @@ -629,10 +657,12 @@ LLPerfBlock::LLPerfBlock( const char* key1, const char* key2 ) : mPredefinedStat } } +// Set up the result data map if dynamic stats are enabled void LLPerfBlock::initDynamicStat(const std::string& key) { // Early exit if dynamic stats aren't enabled. - if (!sStatsEnabled) return; + if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS) + return; mLastPath = sCurrentStatPath; // Save and restore current path sCurrentStatPath += "/" + key; // Add key to current path @@ -713,7 +743,7 @@ void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats, } } else - { // WTF? Shouldn't have a NULL pointer in the map. + { // Shouldn't have a NULL pointer in the map. llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl; } } @@ -725,14 +755,12 @@ void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats, LLTimer LLStat::sTimer; LLFrameTimer LLStat::sFrameTimer; -LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) +void LLStat::init() { - llassert(num_bins > 0); - mUseFrameTimer = use_frame_timer; + llassert(mNumBins > 0); mNumValues = 0; mLastValue = 0.f; mLastTime = 0.f; - mNumBins = num_bins; mCurBin = (mNumBins-1); mNextBin = 0; mBins = new F32[mNumBins]; @@ -746,6 +774,29 @@ LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) mTime[i] = 0.0; mDT[i] = 0.f; } + + if (!mName.empty()) + { + stat_map_t::iterator iter = sStatList.find(mName); + if (iter != sStatList.end()) + llwarns << "LLStat with duplicate name: " << mName << llendl; + sStatList.insert(std::make_pair(mName, this)); + } +} + +LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) + : mUseFrameTimer(use_frame_timer), + mNumBins(num_bins) +{ + init(); +} + +LLStat::LLStat(std::string name, U32 num_bins, BOOL use_frame_timer) + : mUseFrameTimer(use_frame_timer), + mNumBins(num_bins), + mName(name) +{ + init(); } LLStat::~LLStat() @@ -754,6 +805,15 @@ LLStat::~LLStat() delete[] mBeginTime; delete[] mTime; delete[] mDT; + + if (!mName.empty()) + { + // handle multiple entries with the same name + stat_map_t::iterator iter = sStatList.find(mName); + while (iter != sStatList.end() && iter->second != this) + ++iter; + sStatList.erase(iter); + } } void LLStat::reset() diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h index 797e82b9e..bd73c9a6b 100644 --- a/indra/llcommon/llstat.h +++ b/indra/llcommon/llstat.h @@ -192,14 +192,23 @@ public: // Use this constructor for pre-defined LLStatTime objects LLPerfBlock(LLStatTime* stat); - // Use this constructor for dynamically created LLStatTime objects (not pre-defined) with a multi-part key - LLPerfBlock( const char* key1, const char* key2 = NULL); + // Use this constructor for normal, optional LLPerfBlock time slices + LLPerfBlock( const char* key ); + // Use this constructor for dynamically created LLPerfBlock time slices + // that are only enabled by specific control flags + LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS ); ~LLPerfBlock(); - static void setStatsEnabled( BOOL enable ) { sStatsEnabled = enable; }; - static S32 getStatsEnabled() { return sStatsEnabled; }; + enum + { // Stats bitfield flags + LLSTATS_NO_OPTIONAL_STATS = 0x00, // No optional stats gathering, just pre-defined LLStatTime objects + LLSTATS_BASIC_STATS = 0x01, // Gather basic optional runtime stats + LLSTATS_SCRIPT_FUNCTIONS = 0x02, // Include LSL function calls + }; + static void setStatsFlags( S32 flags ) { sStatsFlags = flags; }; + static S32 getStatsFlags() { return sStatsFlags; }; static void clearDynamicStats(); // Reset maps to clear out dynamic objects static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin @@ -213,7 +222,7 @@ private: LLStatTime * mPredefinedStat; // LLStatTime object to get data StatEntry * mDynamicStat; // StatEntryobject to get data - static BOOL sStatsEnabled; // Normally FALSE + static S32 sStatsFlags; // Control what is being recorded static stat_map_t sStatMap; // Map full path string to LLStatTime objects static std::string sCurrentStatPath; // Something like "frame/physics/physics step" }; @@ -236,7 +245,7 @@ public: BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); }; F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; }; void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; }; - void setReportPerformanceDuration( F32 seconds ); + void setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS ); void setProcessName(const std::string& process_name) { mProcessName = process_name; } void setProcessPID(S32 process_pid) { mProcessPID = process_pid; } @@ -258,8 +267,15 @@ private: // ---------------------------------------------------------------------------- class LL_COMMON_API LLStat { +private: + typedef std::multimap stat_map_t; + static stat_map_t sStatList; + + void init(); + public: - LLStat(const U32 num_bins = 32, BOOL use_frame_timer = FALSE); + LLStat(U32 num_bins = 32, BOOL use_frame_timer = FALSE); + LLStat(std::string name, U32 num_bins = 32, BOOL use_frame_timer = FALSE); ~LLStat(); void reset(); @@ -322,8 +338,22 @@ private: F32 *mDT; S32 mCurBin; S32 mNextBin; + + std::string mName; + static LLTimer sTimer; static LLFrameTimer sFrameTimer; + +public: + static LLStat* getStat(const std::string& name) + { + // return the first stat that matches 'name' + stat_map_t::iterator iter = sStatList.find(name); + if (iter != sStatList.end()) + return iter->second; + else + return NULL; + } }; - + #endif // LL_STAT_ diff --git a/indra/llcommon/llstreamtools.cpp b/indra/llcommon/llstreamtools.cpp index b60220830..4ed2df58e 100644 --- a/indra/llcommon/llstreamtools.cpp +++ b/indra/llcommon/llstreamtools.cpp @@ -45,7 +45,7 @@ // skips spaces and tabs bool skip_whitespace(std::istream& input_stream) { - char c = input_stream.peek(); + int c = input_stream.peek(); while (('\t' == c || ' ' == c) && input_stream.good()) { input_stream.get(); @@ -57,7 +57,7 @@ bool skip_whitespace(std::istream& input_stream) // skips whitespace, newlines, and carriage returns bool skip_emptyspace(std::istream& input_stream) { - char c = input_stream.peek(); + int c = input_stream.peek(); while ( input_stream.good() && ('\t' == c || ' ' == c || '\n' == c || '\r' == c) ) { @@ -72,7 +72,7 @@ bool skip_comments_and_emptyspace(std::istream& input_stream) { while (skip_emptyspace(input_stream)) { - char c = input_stream.peek(); + int c = input_stream.peek(); if ('#' == c ) { while ('\n' != c && input_stream.good()) @@ -90,7 +90,7 @@ bool skip_comments_and_emptyspace(std::istream& input_stream) bool skip_line(std::istream& input_stream) { - char c; + int c; do { c = input_stream.get(); @@ -100,7 +100,7 @@ bool skip_line(std::istream& input_stream) bool skip_to_next_word(std::istream& input_stream) { - char c = input_stream.peek(); + int c = input_stream.peek(); while ( input_stream.good() && ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') @@ -132,7 +132,7 @@ bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream while (input_stream.good()) { skip_emptyspace(input_stream); - char c = input_stream.get(); + int c = input_stream.get(); if (keyword[0] != c) { skip_line(input_stream); @@ -181,7 +181,7 @@ bool skip_to_start_of_next_keyword(const char* keyword, std::istream& input_stre while (input_stream.good()) { skip_emptyspace(input_stream); - char c = input_stream.get(); + int c = input_stream.get(); if (keyword[0] != c) { skip_line(input_stream); @@ -229,7 +229,7 @@ bool skip_to_start_of_next_keyword(const char* keyword, std::istream& input_stre bool get_word(std::string& output_string, std::istream& input_stream) { skip_emptyspace(input_stream); - char c = input_stream.peek(); + int c = input_stream.peek(); while ( !isspace(c) && '\n' != c && '\r' != c @@ -246,7 +246,7 @@ bool get_word(std::string& output_string, std::istream& input_stream, int n) { skip_emptyspace(input_stream); int char_count = 0; - char c = input_stream.peek(); + int c = input_stream.peek(); while (!isspace(c) && '\n' != c && '\r' != c @@ -265,7 +265,7 @@ bool get_word(std::string& output_string, std::istream& input_stream, int n) bool get_line(std::string& output_string, std::istream& input_stream) { output_string.clear(); - char c = input_stream.get(); + int c = input_stream.get(); while (input_stream.good()) { output_string += c; @@ -285,7 +285,7 @@ bool get_line(std::string& output_string, std::istream& input_stream, int n) { output_string.clear(); int char_count = 0; - char c = input_stream.get(); + int c = input_stream.get(); while (input_stream.good() && char_count < n) { char_count++; diff --git a/indra/llcommon/llstrider.h b/indra/llcommon/llstrider.h index 44ea80a36..b9f0da206 100644 --- a/indra/llcommon/llstrider.h +++ b/indra/llcommon/llstrider.h @@ -42,14 +42,17 @@ template class LLStrider U8* mBytep; }; U32 mSkip; + U32 mTypeSize; public: - LLStrider() { mObjectp = NULL; mSkip = sizeof(Object); } + LLStrider() { mObjectp = NULL; mTypeSize = mSkip = sizeof(Object); } ~LLStrider() { } const LLStrider& operator = (Object *first) { mObjectp = first; return *this;} void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));} + void setTypeSize (S32 typeBytes){ mTypeSize = (typeBytes ? typeBytes : sizeof(Object)); } + bool isStrided() const { return mTypeSize != mSkip; } void skip(const U32 index) { mBytep += mSkip*index;} U32 getSkip() const { return mSkip; } Object* get() { return mObjectp; } @@ -58,6 +61,71 @@ public: Object* operator ++(int) { Object* old = mObjectp; mBytep += mSkip; return old; } Object* operator +=(int i) { mBytep += mSkip*i; return mObjectp; } Object& operator[](U32 index) { return *(Object*)(mBytep + (mSkip * index)); } + void assignArray(U8* __restrict source, const size_t elem_size, const size_t elem_count) + { + llassert_always(sizeof(Object) <= elem_size); + + U8* __restrict dest = mBytep; //refer to dest instead of mBytep to benefit from __restrict hint + const U32 bytes = elem_size * elem_count; //total bytes to copy from source to dest + + //stride == sizeof(element) implies entire buffer is unstrided and thus memcpy-able, provided source buffer elements match in size. + //Because LLStrider is often passed an LLVector3 even if the reprensentation is LLVector4 in the vertex buffer, mTypeSize is set to + //the TRUE vbo datatype size via VertexBufferStrider::get + if(!isStrided() && mTypeSize == elem_size) + { + if(bytes >= sizeof(LLVector4) * 4) //Should be able to pull at least 3 16byte blocks from this. Smaller isn't really beneficial. + { + U8* __restrict aligned_source = LL_NEXT_ALIGNED_ADDRESS(source); + U8* __restrict aligned_dest = LL_NEXT_ALIGNED_ADDRESS(dest); + const U32 source_offset = aligned_source - source; //Offset to first aligned location in source buffer. + const U32 dest_offset = aligned_dest - dest; //Offset to first aligned location in dest buffer. + llassert_always(source_offset < 16); + llassert_always(dest_offset < 16); + if(source_offset == dest_offset) //delta to aligned location matches between source and destination! _mm_*_ps should be viable. + { + const U32 end_offset = (bytes - source_offset) % sizeof(LLVector4); //buffers may not neatly end on a 16byte alignment boundary. + const U32 aligned_bytes = bytes - source_offset - end_offset; //how many bytes to copy from aligned start to aligned end. + + llassert_always(aligned_bytes > 0); + + if(source_offset) //memcpy up to the aligned location if needed + memcpy(dest,source,source_offset); + LLVector4a::memcpyNonAliased16((F32*) aligned_dest, (F32*) aligned_source, aligned_bytes); + if(end_offset) //memcpy to the very end if needed. + memcpy(aligned_dest+aligned_bytes,aligned_source+aligned_bytes,end_offset); + } + else //buffers non-uniformly offset from aligned location. Using _mm_*u_ps. + { + U32 end = bytes/sizeof(LLVector4); //sizeof(LLVector4) = 16 bytes = 128 bits + + llassert_always(end > 0); + + __m128* dst = (__m128*) dest; + __m128* src = (__m128*) source; + + for (U32 i = 0; i < end; i++) //copy 128bit chunks + { + __m128 res = _mm_loadu_ps((F32*)&src[i]); + _mm_storeu_ps((F32*)&dst[i], res); + } + end*=16;//Convert to real byte offset + if(end < bytes) //just memcopy the rest + memcpy(dest+end,source+end,bytes-end); + } + } + else //Too small. just do a simple memcpy. + memcpy(dest,source,bytes); + } + else + { + for(U32 i=0;i # include # include -//# include May be needed? +# include #elif LL_LINUX # include # include diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 8bd341457..f81b53ae2 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -62,6 +62,21 @@ // //---------------------------------------------------------------------------- +#if !LL_DARWIN +U32 ll_thread_local sThreadID = 0; +#endif + +U32 LLThread::sIDIter = 0; + +LL_COMMON_API void assert_main_thread() +{ + static U32 s_thread_id = LLThread::currentID(); + if (LLThread::currentID() != s_thread_id) + { + llerrs << "Illegal execution outside main thread." << llendl; + } +} + // // Handed to the APR thread creation function // @@ -73,8 +88,10 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap LLThread *threadp = (LLThread *)datap; - // Set thread state to running - threadp->mStatus = RUNNING; +#if !LL_DARWIN + sThreadID = threadp->mID; +#endif + // Create a thread local data. AIThreadLocalData::create(threadp); @@ -82,11 +99,21 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap // Run the user supplied function threadp->run(); - llinfos << "LLThread::staticRun() Exiting: " << threadp->mName << llendl; + // Setting mStatus to STOPPED is done non-thread-safe, so it's + // possible that the thread is deleted by another thread at + // the moment it happens... therefore make a copy here. + char const* volatile name = threadp->mName.c_str(); // We're done with the run function, this thread is done executing now. threadp->mStatus = STOPPED; + // Only now print this info [doing that before setting mStatus + // to STOPPED makes it much more likely that another thread runs + // after the LLCurl::Multi::run() function exits and we actually + // change this variable (which really SHOULD have been inside + // the critical area of the mSignal lock)]. + llinfos << "LLThread::staticRun() Exiting: " << name << llendl; + return NULL; } @@ -98,6 +125,7 @@ LLThread::LLThread(std::string const& name) : mStatus(STOPPED), mThreadLocalData(NULL) { + mID = ++sIDIter; mRunCondition = new LLCondition; } @@ -119,7 +147,7 @@ void LLThread::shutdown() // First, set the flag that indicates that we're ready to die setQuitting(); - llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl; + llinfos << "LLThread::shutdown() Killing thread " << mName << " Status: " << mStatus << llendl; // Now wait a bit for the thread to exit // It's unclear whether I should even bother doing this - this destructor // should netver get called unless we're already stopped, really... @@ -142,20 +170,38 @@ void LLThread::shutdown() { // This thread just wouldn't stop, even though we gave it time llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl; + // Put a stake in its heart. + apr_thread_exit(mAPRThreadp, -1); return; } mAPRThreadp = NULL; } delete mRunCondition; + mRunCondition = 0; } void LLThread::start() { - apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool()); + llassert(isStopped()); + + // Set thread state to running + mStatus = RUNNING; - // We won't bother joining - apr_thread_detach(mAPRThreadp); + apr_status_t status = + apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool()); + + if(status == APR_SUCCESS) + { + // We won't bother joining + apr_thread_detach(mAPRThreadp); + } + else + { + mStatus = STOPPED; + llwarns << "failed to start thread " << mName << llendl; + ll_apr_warn_status(status); + } } //============================================================================ @@ -318,6 +364,55 @@ AIThreadLocalData& AIThreadLocalData::tldata(void) //============================================================================ +void LLMutexBase::lock() +{ +#if LL_DARWIN + if (mLockingThread == LLThread::currentID()) +#else + if (mLockingThread == sThreadID) +#endif + { //redundant lock + mCount++; + return; + } + + apr_thread_mutex_lock(mAPRMutexp); + +#if MUTEX_DEBUG + // Have to have the lock before we can access the debug info + U32 id = LLThread::currentID(); + if (mIsLocked[id] != FALSE) + llerrs << "Already locked in Thread: " << id << llendl; + mIsLocked[id] = TRUE; +#endif + +#if LL_DARWIN + mLockingThread = LLThread::currentID(); +#else + mLockingThread = sThreadID; +#endif +} + +void LLMutexBase::unlock() +{ + if (mCount > 0) + { //not the root unlock + mCount--; + return; + } + +#if MUTEX_DEBUG + // Access the debug info while we have the lock + U32 id = LLThread::currentID(); + if (mIsLocked[id] != TRUE) + llerrs << "Not locked in Thread: " << id << llendl; + mIsLocked[id] = FALSE; +#endif + + mLockingThread = NO_THREAD; + apr_thread_mutex_unlock(mAPRMutexp); +} + bool LLMutexBase::isLocked() { if (!tryLock()) @@ -328,6 +423,11 @@ bool LLMutexBase::isLocked() return false; } +U32 LLMutexBase::lockingThread() const +{ + return mLockingThread; +} + //============================================================================ LLCondition::LLCondition(AIAPRPool& parent) : LLMutex(parent) @@ -335,6 +435,7 @@ LLCondition::LLCondition(AIAPRPool& parent) : LLMutex(parent) apr_thread_cond_create(&mAPRCondp, mPool()); } + LLCondition::~LLCondition() { apr_thread_cond_destroy(mAPRCondp); diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 97dac455e..c5c30a904 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -48,6 +48,12 @@ class LLThread; class LLMutex; class LLCondition; +#if LL_WINDOWS +#define ll_thread_local __declspec(thread) +#else +#define ll_thread_local __thread +#endif + class LL_COMMON_API AIThreadLocalData { private: @@ -66,6 +72,9 @@ public: class LL_COMMON_API LLThread { +private: + static U32 sIDIter; + public: typedef enum e_thread_status { @@ -106,6 +115,8 @@ public: // Return thread-local data for the current thread. static AIThreadLocalData& tldata(void) { return AIThreadLocalData::tldata(); } + U32 getID() const { return mID; } + private: BOOL mPaused; @@ -117,7 +128,8 @@ protected: LLCondition* mRunCondition; apr_thread_t *mAPRThreadp; - EThreadStatus mStatus; + volatile EThreadStatus mStatus; + U32 mID; friend void AIThreadLocalData::create(LLThread* threadp); AIThreadLocalData* mThreadLocalData; @@ -151,16 +163,26 @@ protected: class LL_COMMON_API LLMutexBase { public: - void lock() { apr_thread_mutex_lock(mAPRMutexp); } - void unlock() { apr_thread_mutex_unlock(mAPRMutexp); } + typedef enum + { + NO_THREAD = 0xFFFFFFFF + } e_locking_thread; + + LLMutexBase() : mLockingThread(NO_THREAD), mCount(0) {} + + void lock(); //blocks + void unlock(); // Returns true if lock was obtained successfully. bool tryLock() { return !APR_STATUS_IS_EBUSY(apr_thread_mutex_trylock(mAPRMutexp)); } bool isLocked(); // non-blocking, but does do a lock/unlock so not free + U32 lockingThread() const; //get ID of locking thread protected: // mAPRMutexp is initialized and uninitialized in the derived class. apr_thread_mutex_t* mAPRMutexp; + mutable U32 mCount; + mutable U32 mLockingThread; }; class LL_COMMON_API LLMutex : public LLMutexBase @@ -350,6 +372,7 @@ void LLThread::unlockData() mRunCondition->unlock(); } + //============================================================================ // see llmemory.h for LLPointer<> definition diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 34e19f83f..1762b3b00 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -36,6 +36,8 @@ #include "u64.h" +#include "lldate.h" + #if LL_WINDOWS # define WIN32_LEAN_AND_MEAN # include diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 68f06fdce..478585e54 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -39,8 +39,6 @@ #include #include "stdtypes.h" -#include "llpreprocessor.h" -#include "lldate.h" #include #include @@ -55,8 +53,6 @@ const U32 USEC_PER_HOUR = USEC_PER_MIN * MIN_PER_HOUR; const U32 SEC_PER_HOUR = SEC_PER_MIN * MIN_PER_HOUR; const F64 SEC_PER_USEC = 1.0 / (F64) USEC_PER_SEC; -LL_COMMON_API U64 totalTime(); // Returns current system time in microseconds - class LL_COMMON_API LLTimer { public: @@ -175,4 +171,5 @@ LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstri LL_COMMON_API void timeToFormattedString(time_t time, std::string format, std::string ×tr); LL_COMMON_API void timeStructToFormattedString(struct tm * time, std::string format, std::string ×tr); +U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds #endif diff --git a/indra/llcommon/lltreeiterators.h b/indra/llcommon/lltreeiterators.h new file mode 100644 index 000000000..ba861ae70 --- /dev/null +++ b/indra/llcommon/lltreeiterators.h @@ -0,0 +1,705 @@ +/** + * @file lltreeiterators.h + * @author Nat Goodspeed + * @date 2008-08-19 + * @brief This file defines iterators useful for traversing arbitrary node + * classes, potentially polymorphic, linked into strict tree + * structures. + * + * Dereferencing any one of these iterators actually yields a @em + * pointer to the node in question. For example, given an + * LLLinkedIter li, *li gets you a pointer + * to MyNode, and **li gets you the MyNode instance itself. + * More commonly, instead of writing li->member, you write + * (*li)->member -- as you would if you were traversing an + * STL container of MyNode pointers. + * + * It would certainly be possible to build these iterators so that + * *iterator would return a reference to the node itself + * rather than a pointer to the node, and for many purposes it would + * even be more convenient. However, that would be insufficiently + * flexible. If you want to use an iterator range to (e.g.) initialize + * a std::vector collecting results -- you rarely want to actually @em + * copy the nodes in question. You're much more likely to want to copy + * pointers to the traversed nodes. Hence these iterators + * produce pointers. + * + * Though you specify the actual NODE class as the template parameter, + * these iterators internally use LLPtrTo<> to discover whether to + * store and return an LLPointer or a simple NODE*. + * + * By strict tree structures, we mean that each child must have + * exactly one parent. This forbids a child claiming any ancestor as a + * child of its own. Child nodes with multiple parents will be visited + * once for each parent. Cycles in the graph will result in either an + * infinite loop or an out-of-memory crash. You Have Been Warned. + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#if ! defined(LL_LLTREEITERATORS_H) +#define LL_LLTREEITERATORS_H + +#include "llptrto.h" +#include +#include +#include +#include +#include + +namespace LLTreeIter +{ + /// Discriminator between LLTreeUpIter and LLTreeDownIter + enum RootIter { UP, DOWN }; + /// Discriminator between LLTreeDFSIter, LLTreeDFSPostIter and LLTreeBFSIter + enum WalkIter { DFS_PRE, DFS_POST, BFS }; +} + +/** + * LLBaseIter defines some machinery common to all these iterators. We use + * boost::iterator_facade to define the iterator boilerplate: the conventional + * operators and methods necessary to implement a standards-conforming + * iterator. That allows us to specify the actual iterator semantics in terms + * of equal(), dereference() and increment() methods. + */ +template +class LLBaseIter: public boost::iterator_facade::type, + boost::forward_traversal_tag> +{ +protected: + /// LLPtrTo::type is either NODE* or LLPointer, as appropriate + typedef typename LLPtrTo::type ptr_type; + /// function that advances from this node to next accepts a node pointer + /// and returns another + typedef boost::function func_type; + typedef SELFTYPE self_type; +}; + +/// Functor returning NULL, suitable for an end-iterator's 'next' functor +template +typename LLPtrTo::type LLNullNextFunctor(const typename LLPtrTo::type&) +{ + return typename LLPtrTo::type(); +} + +/** + * LLLinkedIter is an iterator over an intrusive singly-linked list. The + * beginning of the list is represented by LLLinkedIter(list head); the end is + * represented by LLLinkedIter(). + * + * The begin LLLinkedIter must be instantiated with a functor to extract the + * 'next' pointer from the current node. Supposing that the link pointer is @c + * public, something like: + * + * @code + * NODE* mNext; + * @endcode + * + * you can use (e.g.) boost::bind(&NODE::mNext, _1) for the purpose. + * Alternatively, you can bind whatever accessor method is normally used to + * advance to the next node, e.g. for: + * + * @code + * NODE* next() const; + * @endcode + * + * you can use boost::bind(&NODE::next, _1). + */ +template +class LLLinkedIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; +protected: + /// some methods need to return a reference to self + typedef typename super::self_type self_type; + typedef typename super::ptr_type ptr_type; + typedef typename super::func_type func_type; +public: + /// Instantiate an LLLinkedIter to start a range, or to end a range before + /// a particular list entry. Pass a functor to extract the 'next' pointer + /// from the current node. + LLLinkedIter(const ptr_type& entry, const func_type& nextfunc): + mCurrent(entry), + mNextFunc(nextfunc) + {} + /// Instantiate an LLLinkedIter to end a range at the end of the list + LLLinkedIter(): + mCurrent(), + mNextFunc(LLNullNextFunctor) + {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + void increment() + { + mCurrent = mNextFunc(mCurrent); + } + /// equality + bool equal(const self_type& that) const { return this->mCurrent == that.mCurrent; } + /// dereference + ptr_type& dereference() const { return const_cast(mCurrent); } + + ptr_type mCurrent; + func_type mNextFunc; +}; + +/** + * LLTreeUpIter walks from the node in hand to the root of the tree. The term + * "up" is applied to a tree visualized with the root at the top. + * + * LLTreeUpIter is an alias for LLLinkedIter, since any linked tree that you + * can navigate that way at all contains parent pointers. + */ +template +class LLTreeUpIter: public LLLinkedIter +{ + typedef LLLinkedIter super; +public: + /// Instantiate an LLTreeUpIter to start from a particular tree node, or + /// to end a parent traversal before reaching a particular ancestor. Pass + /// a functor to extract the 'parent' pointer from the current node. + LLTreeUpIter(const typename super::ptr_type& node, + const typename super::func_type& parentfunc): + super(node, parentfunc) + {} + /// Instantiate an LLTreeUpIter to end a range at the root of the tree + LLTreeUpIter(): + super() + {} +}; + +/** + * LLTreeDownIter walks from the root of the tree to the node in hand. The + * term "down" is applied to a tree visualized with the root at the top. + * + * Though you instantiate the begin() LLTreeDownIter with a pointer to some + * node at an arbitrary location in the tree, the root will be the first node + * you dereference and the passed node will be the last node you dereference. + * + * On construction, LLTreeDownIter walks from the current node to the root, + * capturing the path. Then in use, it replays that walk in reverse. As with + * all traversals of interesting data structures, it is actively dangerous to + * modify the tree during an LLTreeDownIter walk. + */ +template +class LLTreeDownIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + typedef typename super::func_type func_type; +private: + typedef std::vector list_type; +public: + /// Instantiate an LLTreeDownIter to end at a particular tree node. Pass a + /// functor to extract the 'parent' pointer from the current node. + LLTreeDownIter(const ptr_type& node, + const func_type& parentfunc) + { + for (ptr_type n = node; n; n = parentfunc(n)) + mParents.push_back(n); + } + /// Instantiate an LLTreeDownIter representing "here", the end of the loop + LLTreeDownIter() {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + void increment() + { + mParents.pop_back(); + } + /// equality + bool equal(const self_type& that) const { return this->mParents == that.mParents; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mParents.back()); } + + list_type mParents; +}; + +/** + * When you want to select between LLTreeUpIter and LLTreeDownIter with a + * compile-time discriminator, use LLTreeRootIter with an LLTreeIter::RootIter + * template arg. + */ +template +class LLTreeRootIter +{ + enum { use_a_valid_LLTreeIter_RootIter_value = false }; +public: + /// Bogus constructors for default (unrecognized discriminator) case + template + LLTreeRootIter(TYPE1, TYPE2) + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value); + } + LLTreeRootIter() + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value); + } +}; + +/// Specialize for LLTreeIter::UP +template +class LLTreeRootIter: public LLTreeUpIter +{ + typedef LLTreeUpIter super; +public: + /// forward begin ctor + LLTreeRootIter(const typename super::ptr_type& node, + const typename super::func_type& parentfunc): + super(node, parentfunc) + {} + /// forward end ctor + LLTreeRootIter(): + super() + {} +}; + +/// Specialize for LLTreeIter::DOWN +template +class LLTreeRootIter: public LLTreeDownIter +{ + typedef LLTreeDownIter super; +public: + /// forward begin ctor + LLTreeRootIter(const typename super::ptr_type& node, + const typename super::func_type& parentfunc): + super(node, parentfunc) + {} + /// forward end ctor + LLTreeRootIter(): + super() + {} +}; + +/** + * Instantiated with a tree node, typically the root, LLTreeDFSIter "flattens" + * a depth-first tree walk through that node and all its descendants. + * + * The begin() LLTreeDFSIter must be instantiated with functors to obtain from + * a given node begin() and end() iterators for that node's children. For this + * reason, you must specify the type of the node's child iterator as an + * additional template parameter. + * + * Specifically, the begin functor must return an iterator whose dereferenced + * value is a @em pointer to a child tree node. For instance, if each node + * tracks its children in an STL container of node* pointers, you can simply + * return that container's begin() iterator. + * + * Alternatively, if a node tracks its children with a classic linked list, + * write a functor returning LLLinkedIter. + * + * The end() LLTreeDFSIter must, of course, match the begin() iterator's + * template parameters, but is constructed without runtime parameters. + */ +template +class LLTreeDFSIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + // The func_type is different for this: from a NODE pointer, we must + // obtain a CHILDITER. + typedef boost::function func_type; +private: + typedef std::vector list_type; +public: + /// Instantiate an LLTreeDFSIter to start a depth-first walk. Pass + /// functors to extract the 'child begin' and 'child end' iterators from + /// each node. + LLTreeDFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc) + : mBeginFunc(beginfunc), + mEndFunc(endfunc), + mSkipChildren(false) + { + // Only push back this node if it's non-NULL! + if (node) + mPending.push_back(node); + } + /// Instantiate an LLTreeDFSIter to mark the end of the walk + LLTreeDFSIter() : mSkipChildren(false) {} + + /// flags iterator logic to skip traversing children of current node on next increment + void skipDescendants(bool skip = true) { mSkipChildren = skip; } + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search + void increment() + { + // Capture the node we were just looking at + ptr_type current = mPending.back(); + // Remove it from mPending so we don't process it again later + mPending.pop_back(); + if (!mSkipChildren) + { + // Add all its children to mPending + addChildren(current); + } + // reset flag after each step + mSkipChildren = false; + } + /// equality + bool equal(const self_type& that) const { return this->mPending == that.mPending; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mPending.back()); } + + /// Add the direct children of the specified node to mPending + void addChildren(const ptr_type& node) + { + // If we just use push_back() for each child in turn, we'll end up + // processing children in reverse order. We don't want to assume + // CHILDITER is reversible: some of the linked trees we'll be + // processing manage their children using singly-linked lists. So + // figure out how many children there are, grow mPending by that size + // and reverse-copy the children into the new space. + CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node); + // grow mPending by the number of children + mPending.resize(mPending.size() + std::distance(chi, chend)); + // reverse-copy the children into the newly-expanded space + std::copy(chi, chend, mPending.rbegin()); + } + + /// list of the nodes yet to be processed + list_type mPending; + /// functor to extract begin() child iterator + func_type mBeginFunc; + /// functor to extract end() child iterator + func_type mEndFunc; + /// flag which controls traversal of children (skip children of current node if true) + bool mSkipChildren; +}; + +/** + * Instantiated with a tree node, typically the root, LLTreeDFSPostIter + * "flattens" a depth-first tree walk through that node and all its + * descendants. Whereas LLTreeDFSIter visits each node before visiting any of + * its children, LLTreeDFSPostIter visits all of a node's children before + * visiting the node itself. + * + * The begin() LLTreeDFSPostIter must be instantiated with functors to obtain + * from a given node begin() and end() iterators for that node's children. For + * this reason, you must specify the type of the node's child iterator as an + * additional template parameter. + * + * Specifically, the begin functor must return an iterator whose dereferenced + * value is a @em pointer to a child tree node. For instance, if each node + * tracks its children in an STL container of node* pointers, you can simply + * return that container's begin() iterator. + * + * Alternatively, if a node tracks its children with a classic linked list, + * write a functor returning LLLinkedIter. + * + * The end() LLTreeDFSPostIter must, of course, match the begin() iterator's + * template parameters, but is constructed without runtime parameters. + */ +template +class LLTreeDFSPostIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + // The func_type is different for this: from a NODE pointer, we must + // obtain a CHILDITER. + typedef boost::function func_type; +private: + // Upon reaching a given node in our pending list, we need to know whether + // we've already pushed that node's children, so we must associate a bool + // with each node pointer. + typedef std::vector< std::pair > list_type; +public: + /// Instantiate an LLTreeDFSPostIter to start a depth-first walk. Pass + /// functors to extract the 'child begin' and 'child end' iterators from + /// each node. + LLTreeDFSPostIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc) + : mBeginFunc(beginfunc), + mEndFunc(endfunc), + mSkipAncestors(false) + { + if (! node) + return; + mPending.push_back(typename list_type::value_type(node, false)); + makeCurrent(); + } + /// Instantiate an LLTreeDFSPostIter to mark the end of the walk + LLTreeDFSPostIter() : mSkipAncestors(false) {} + + /// flags iterator logic to skip traversing ancestors of current node on next increment + void skipAncestors(bool skip = true) { mSkipAncestors = skip; } + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search + void increment() + { + // Pop the previous current node + mPending.pop_back(); + makeCurrent(); + } + /// equality + bool equal(const self_type& that) const { return this->mPending == that.mPending; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mPending.back().first); } + + struct isOpen + { + bool operator()(const typename list_type::value_type& item) + { + return item.second; + } + }; + + /// Call this each time we change mPending.back() -- that is, every time + /// we're about to change the value returned by dereference(). If we + /// haven't yet pushed the new node's children, do so now. + void makeCurrent() + { + if (mSkipAncestors) + { + mPending.erase(std::remove_if(mPending.begin(), mPending.end(), isOpen()), mPending.end()); + mSkipAncestors = false; + } + + // Once we've popped the last node, this becomes a no-op. + if (mPending.empty()) + return; + // Here mPending.back() holds the node pointer we're proposing to + // dereference next. Have we pushed that node's children yet? + if (mPending.back().second) + return; // if so, it's okay to visit this node now + // We haven't yet pushed this node's children. Do so now. Remember + // that we did -- while the node in question is still back(). + mPending.back().second = true; + addChildren(mPending.back().first); + // Now, because we've just changed mPending.back(), make that new node + // current. + makeCurrent(); + } + + /// Add the direct children of the specified node to mPending + void addChildren(const ptr_type& node) + { + // If we just use push_back() for each child in turn, we'll end up + // processing children in reverse order. We don't want to assume + // CHILDITER is reversible: some of the linked trees we'll be + // processing manage their children using singly-linked lists. So + // figure out how many children there are, grow mPending by that size + // and reverse-copy the children into the new space. + CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node); + // grow mPending by the number of children + mPending.resize(mPending.size() + std::distance(chi, chend)); + // Reverse-copy the children into the newly-expanded space. We can't + // just use std::copy() because the source is a ptr_type, whereas the + // dest is a pair of (ptr_type, bool). + for (typename list_type::reverse_iterator pi = mPending.rbegin(); chi != chend; ++chi, ++pi) + { + pi->first = *chi; // copy the child pointer + pi->second = false; // we haven't yet pushed this child's chldren + } + } + + /// list of the nodes yet to be processed + list_type mPending; + /// functor to extract begin() child iterator + func_type mBeginFunc; + /// functor to extract end() child iterator + func_type mEndFunc; + /// flags logic to skip traversal of ancestors of current node + bool mSkipAncestors; +}; + +/** + * Instantiated with a tree node, typically the root, LLTreeBFSIter "flattens" + * a breadth-first tree walk through that node and all its descendants. + * + * The begin() LLTreeBFSIter must be instantiated with functors to obtain from + * a given node the begin() and end() iterators of that node's children. For + * this reason, you must specify the type of the node's child iterator as an + * additional template parameter. + * + * Specifically, the begin functor must return an iterator whose dereferenced + * value is a @em pointer to a child tree node. For instance, if each node + * tracks its children in an STL container of node* pointers, you can simply + * return that container's begin() iterator. + * + * Alternatively, if a node tracks its children with a classic linked list, + * write a functor returning LLLinkedIter. + * + * The end() LLTreeBFSIter must, of course, match the begin() iterator's + * template parameters, but is constructed without runtime parameters. + */ +template +class LLTreeBFSIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + // The func_type is different for this: from a NODE pointer, we must + // obtain a CHILDITER. + typedef boost::function func_type; +private: + // We need a FIFO queue rather than a LIFO stack. Use a deque rather than + // a vector, since vector can't implement pop_front() efficiently. + typedef std::deque list_type; +public: + /// Instantiate an LLTreeBFSIter to start a depth-first walk. Pass + /// functors to extract the 'child begin' and 'child end' iterators from + /// each node. + LLTreeBFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc): + mBeginFunc(beginfunc), + mEndFunc(endfunc) + { + if (node) + mPending.push_back(node); + } + /// Instantiate an LLTreeBFSIter to mark the end of the walk + LLTreeBFSIter() {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + /// This implementation is due to http://en.wikipedia.org/wiki/Breadth-first_search + void increment() + { + // Capture the node we were just looking at + ptr_type current = mPending.front(); + // Remove it from mPending so we don't process it again later + mPending.pop_front(); + // Add all its children to mPending + CHILDITER chend = mEndFunc(current); + for (CHILDITER chi = mBeginFunc(current); chi != chend; ++chi) + mPending.push_back(*chi); + } + /// equality + bool equal(const self_type& that) const { return this->mPending == that.mPending; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mPending.front()); } + + /// list of the nodes yet to be processed + list_type mPending; + /// functor to extract begin() child iterator + func_type mBeginFunc; + /// functor to extract end() child iterator + func_type mEndFunc; +}; + +/** + * When you want to select between LLTreeDFSIter, LLTreeDFSPostIter and + * LLTreeBFSIter with a compile-time discriminator, use LLTreeWalkIter with an + * LLTreeIter::WalkIter template arg. + */ +template +class LLTreeWalkIter +{ + enum { use_a_valid_LLTreeIter_WalkIter_value = false }; +public: + /// Bogus constructors for default (unrecognized discriminator) case + template + LLTreeWalkIter(TYPE1, TYPE2) + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value); + } + LLTreeWalkIter() + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value); + } +}; + +/// Specialize for LLTreeIter::DFS_PRE +template +class LLTreeWalkIter: + public LLTreeDFSIter +{ + typedef LLTreeDFSIter super; +public: + /// forward begin ctor + LLTreeWalkIter(const typename super::ptr_type& node, + const typename super::func_type& beginfunc, + const typename super::func_type& endfunc): + super(node, beginfunc, endfunc) + {} + /// forward end ctor + LLTreeWalkIter(): + super() + {} +}; + +/// Specialize for LLTreeIter::DFS_POST +template +class LLTreeWalkIter: + public LLTreeDFSPostIter +{ + typedef LLTreeDFSPostIter super; +public: + /// forward begin ctor + LLTreeWalkIter(const typename super::ptr_type& node, + const typename super::func_type& beginfunc, + const typename super::func_type& endfunc): + super(node, beginfunc, endfunc) + {} + /// forward end ctor + LLTreeWalkIter(): + super() + {} +}; + +/// Specialize for LLTreeIter::BFS +template +class LLTreeWalkIter: + public LLTreeBFSIter +{ + typedef LLTreeBFSIter super; +public: + /// forward begin ctor + LLTreeWalkIter(const typename super::ptr_type& node, + const typename super::func_type& beginfunc, + const typename super::func_type& endfunc): + super(node, beginfunc, endfunc) + {} + /// forward end ctor + LLTreeWalkIter(): + super() + {} +}; + +#endif /* ! defined(LL_LLTREEITERATORS_H) */ diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index ae2e852c3..ba2e3f542 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -35,7 +35,7 @@ const S32 LL_VERSION_MAJOR = 1; const S32 LL_VERSION_MINOR = 5; -const S32 LL_VERSION_PATCH = 9; +const S32 LL_VERSION_PATCH = 10; const S32 LL_VERSION_BUILD = 1; const char * const LL_CHANNEL = "Singularity"; diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 00ed4e469..73b4b7b90 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -245,7 +245,7 @@ U8* LLImageBase::allocateDataSize(S32 width, S32 height, S32 ncomponents, S32 si // LLImageRaw //--------------------------------------------------------------------------- -S32 LLImageRaw::sGlobalRawMemory = 0; +AITHREADSAFESIMPLE(S32, LLImageRaw::sGlobalRawMemory, ); S32 LLImageRaw::sRawImageCount = 0; S32 LLImageRaw::sRawImageCachedCount = 0; @@ -295,23 +295,25 @@ LLImageRaw::~LLImageRaw() U8* LLImageRaw::allocateData(S32 size) { U8* res = LLImageBase::allocateData(size); - sGlobalRawMemory += getDataSize(); + *AIAccess(sGlobalRawMemory) += getDataSize(); return res; } // virtual U8* LLImageRaw::reallocateData(S32 size) { - sGlobalRawMemory -= getDataSize(); + S32 old_data_size = getDataSize(); U8* res = LLImageBase::reallocateData(size); - sGlobalRawMemory += getDataSize(); + *AIAccess(sGlobalRawMemory) += getDataSize() - old_data_size; return res; } // virtual void LLImageRaw::deleteData() { - sGlobalRawMemory -= getDataSize(); + { + *AIAccess(sGlobalRawMemory) -= getDataSize(); + } LLImageBase::deleteData(); } @@ -327,7 +329,7 @@ void LLImageRaw::setDataAndSize(U8 *data, S32 width, S32 height, S8 components) LLImageBase::setSize(width, height, components) ; LLImageBase::setDataAndSize(data, width * height * components) ; - sGlobalRawMemory += getDataSize(); + *AIAccess(sGlobalRawMemory) += getDataSize(); } BOOL LLImageRaw::resize(U16 width, U16 height, S8 components) diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 9f0cfa87d..99b07be84 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -37,6 +37,7 @@ #include "llstring.h" #include "llmemory.h" #include "llthread.h" +#include "aithreadsafe.h" const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 const S32 MAX_IMAGE_MIP = 11; // 2048x2048 @@ -241,7 +242,7 @@ protected: void setDataAndSize(U8 *data, S32 width, S32 height, S8 components) ; public: - static S32 sGlobalRawMemory; + static AIThreadSafeSimple sGlobalRawMemory; static S32 sRawImageCount; static S32 sRawImageCachedCount; diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h index 2e2adc4d4..e48008545 100644 --- a/indra/llinventory/lleconomy.h +++ b/indra/llinventory/lleconomy.h @@ -32,7 +32,7 @@ #ifndef LL_LLECONOMY_H #define LL_LLECONOMY_H -#include "llmemory.h" +#include "llsingleton.h" class LLMessageSystem; class LLVector3; diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index e28c046bf..479c7d397 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -36,10 +36,9 @@ #include "lldarray.h" #include "llfoldertype.h" #include "llinventorytype.h" -#include "llinventorydefines.h" #include "llmemtype.h" #include "llpermissions.h" -#include "llmemory.h" +#include "llrefcount.h" #include "llsaleinfo.h" #include "llsd.h" #include "lluuid.h" @@ -304,84 +303,11 @@ protected: //----------------------------------------------------------------------------- -// Useful bits +// Convertors +// +// These functions convert between structured data and an inventory +// item, appropriate for serialization. //----------------------------------------------------------------------------- - -// This functor tests if an item is transferrable and returns true if -// it is. Derived from unary_function<> so that the object can be used -// in stl-compliant adaptable predicates (eg, not1<>). You might want -// to use this in std::partition() or similar logic. -struct IsItemTransferable : public std::unary_function -{ - LLUUID mDestID; - IsItemTransferable(const LLUUID& dest_id) : mDestID(dest_id) {} - bool operator()(const LLInventoryItem* item) const - { - return (item->getPermissions().allowTransferTo(mDestID)) ? true:false; - } -}; - -// This functor is used to set the owner and group of inventory items, -// for example, in a simple std::for_each() loop. Note that the call -// to setOwnerAndGroup can fail if authority_id != LLUUID::null. -struct SetItemOwnerAndGroup -{ - LLUUID mAuthorityID; - LLUUID mOwnerID; - LLUUID mGroupID; - SetItemOwnerAndGroup(const LLUUID& authority_id, - const LLUUID& owner_id, - const LLUUID& group_id) : - mAuthorityID(authority_id), mOwnerID(owner_id), mGroupID(group_id) {} - void operator()(LLInventoryItem* item) const - { - LLPermissions perm = item->getPermissions(); - bool is_atomic = (LLAssetType::AT_OBJECT == item->getType()) ? false : true; - perm.setOwnerAndGroup(mAuthorityID, mOwnerID, mGroupID, is_atomic); - // If no owner id is set, this is equivalent to a deed action. - // Clear 'share with group'. - if (mOwnerID.isNull()) - { - perm.setMaskGroup(PERM_NONE); - } - item->setPermissions(perm); - } -}; - -// This functor is used to unset the share with group, everyone perms, and -// for sale info for objects being sold through contents. -struct SetNotForSale -{ - LLUUID mAgentID; - LLUUID mGroupID; - SetNotForSale(const LLUUID& agent_id, - const LLUUID& group_id) : - mAgentID(agent_id), mGroupID(group_id) {} - void operator()(LLInventoryItem* item) const - { - // Clear group & everyone permissions. - LLPermissions perm = item->getPermissions(); - perm.setGroupBits(mAgentID, mGroupID, FALSE, PERM_MODIFY | PERM_MOVE | PERM_COPY); - perm.setEveryoneBits(mAgentID, mGroupID, FALSE, PERM_MOVE | PERM_COPY); - item->setPermissions(perm); - - // Mark group & everyone permissions for overwrite on the next - // rez if it is an object. - if(LLAssetType::AT_OBJECT == item->getType()) - { - U32 flags = item->getFlags(); - flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP; - flags |= LLInventoryItemFlags::II_FLAGS_OBJECT_PERM_OVERWRITE_EVERYONE; - item->setFlags(flags); - } - - // Clear for sale info. - item->setSaleInfo(LLSaleInfo::DEFAULT); - } -}; - -// These functions convert between structured data and an inventroy -// item, appropriate for serialization. LLSD ll_create_sd_from_inventory_item(LLPointer item); LLPointer ll_create_item_from_sd(const LLSD& sd_item); LLSD ll_create_sd_from_inventory_category(LLPointer cat); diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index 35b5bde05..1dc7a7f2c 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -35,6 +35,7 @@ #include "llinventorytype.h" #include "lldictionary.h" #include "llmemory.h" +#include "llsingleton.h" static const std::string empty_string; diff --git a/indra/llinventory/llnotecard.h b/indra/llinventory/llnotecard.h index b903f1fdb..092ab2ce3 100644 --- a/indra/llinventory/llnotecard.h +++ b/indra/llinventory/llnotecard.h @@ -33,7 +33,7 @@ #ifndef LL_NOTECARD_H #define LL_NOTECARD_H -#include "llmemory.h" +#include "llpointer.h" #include "llinventory.h" class LLNotecard diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index c167ef194..070437ee4 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -177,7 +177,7 @@ void LLParcel::init(const LLUUID &owner_id, mSaleTimerExpires.stop(); mGraceExtension = 0; //mExpireAction = STEA_REVERT; - mRecordTransaction = FALSE; + //mRecordTransaction = FALSE; mAuctionID = 0; mInEscrow = false; diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 2d74495b6..401fb0040 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -38,8 +38,8 @@ #include "lluuid.h" #include "llparcelflags.h" #include "llpermissions.h" -#include "v3math.h" #include "lltimer.h" +#include "v3math.h" // Grid out of which parcels taken is stepped every 4 meters. const F32 PARCEL_GRID_STEP_METERS = 4.f; @@ -67,6 +67,7 @@ const F32 PARCEL_PASS_HOURS_DEFAULT = 1.f; // Number of "chunks" in which parcel overlay data is sent // Chunk 0 = southern rows, entire width +// NOTE: NOT USABLE FOR VAR SIZED REGIONS! const S32 PARCEL_OVERLAY_CHUNKS = 4; // Bottom three bits are a color index for the land overlay @@ -432,13 +433,10 @@ public: void completeSale(U32& type, U8& flags, LLUUID& to_id); void clearSale(); - // this function returns TRUE if the parcel needs conversion to a - // lease from a non-owned-status state. - BOOL getRecordTransaction() const { return mRecordTransaction; } - void setRecordTransaction(BOOL record) { mRecordTransaction = record; } BOOL isMediaResetTimerExpired(const U64& time); + // more accessors U32 getParcelFlags() const { return mParcelFlags; } @@ -473,7 +471,9 @@ public: { return (mParcelFlags & PF_ALLOW_FLY) ? TRUE : FALSE; } BOOL getAllowLandmark() const - { return (mParcelFlags & PF_ALLOW_LANDMARK) ? TRUE : FALSE; } + { return TRUE; } + //Perhaps revert for opensim? + //{ return (mParcelFlags & PF_ALLOW_LANDMARK) ? TRUE : FALSE; } BOOL getAllowGroupScripts() const { return (mParcelFlags & PF_ALLOW_GROUP_SCRIPTS) ? TRUE : FALSE; } @@ -599,6 +599,7 @@ public: BOOL getPreviouslyGroupOwned() const { return mPreviouslyGroupOwned; } BOOL getSellWithObjects() const { return (mParcelFlags & PF_SELL_PARCEL_OBJECTS) ? TRUE : FALSE; } + protected: LLUUID mID; LLUUID mOwnerID; @@ -618,8 +619,6 @@ protected: LLTimer mMediaResetTimer; S32 mGraceExtension; - BOOL mRecordTransaction; - // This value is non-zero if there is an auction associated with // the parcel. @@ -672,7 +671,6 @@ protected: BOOL mRegionDenyAnonymousOverride; BOOL mRegionDenyAgeUnverifiedOverride; - public: // HACK, make private S32 mLocalID; diff --git a/indra/llinventory/llparcelflags.h b/indra/llinventory/llparcelflags.h index a1bd85f50..122468e91 100644 --- a/indra/llinventory/llparcelflags.h +++ b/indra/llinventory/llparcelflags.h @@ -132,5 +132,7 @@ const S32 PARCEL_DETAILS_DESC = 1; const S32 PARCEL_DETAILS_OWNER = 2; const S32 PARCEL_DETAILS_GROUP = 3; const S32 PARCEL_DETAILS_AREA = 4; +const S32 PARCEL_DETAILS_ID = 5; +const S32 PARCEL_DETAILS_SEE_AVATARS = 6; #endif diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index e51e35e6e..b7afb28ad 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -30,8 +30,8 @@ * $/LicenseInfo$ */ -#include "linden_common.h" #include +#include "linden_common.h" #include "llsaleinfo.h" diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt index b1560c461..fbed12a81 100644 --- a/indra/llmath/CMakeLists.txt +++ b/indra/llmath/CMakeLists.txt @@ -17,13 +17,16 @@ set(llmath_SOURCE_FILES llcamera.cpp llcoordframe.cpp llline.cpp + llmatrix3a.cpp llmodularmath.cpp llperlin.cpp llquaternion.cpp llrect.cpp llsphere.cpp + llvector4a.cpp llvolume.cpp llvolumemgr.cpp + llvolumeoctree.cpp llsdutil_math.cpp m3math.cpp m4math.cpp @@ -53,21 +56,32 @@ set(llmath_HEADER_FILES llinterp.h llline.h llmath.h + llmatrix3a.h + llmatrix3a.inl llmodularmath.h lloctree.h llperlin.h llplane.h llquantize.h llquaternion.h + llquaternion2.h + llquaternion2.inl llrect.h + llsimdmath.h + llsimdtypes.h + llsimdtypes.inl llsphere.h lltreenode.h + llvector4a.h + llvector4a.inl + llvector4logical.h llv4math.h llv4matrix3.h llv4matrix4.h llv4vector3.h llvolume.h llvolumemgr.h + llvolumeoctree.h llsdutil_math.h m3math.h m4math.h diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp index 6f127c916..597d0815f 100644 --- a/indra/llmath/llcalc.cpp +++ b/indra/llmath/llcalc.cpp @@ -54,28 +54,20 @@ LLCalc* LLCalc::sInstance = NULL; LLCalc::LLCalc() : mLastErrorPos(0) { -// mUserVariables = new calc_map_t; - mVariables = new calc_map_t; - mConstants = new calc_map_t; - // Init table of constants - (*mConstants)["PI"] = F_PI; - (*mConstants)["TWO_PI"] = F_TWO_PI; - (*mConstants)["PI_BY_TWO"] = F_PI_BY_TWO; - (*mConstants)["SQRT2"] = F_SQRT2; - (*mConstants)["DEG_TO_RAD"] = DEG_TO_RAD; - (*mConstants)["RAD_TO_DEG"] = RAD_TO_DEG; - (*mConstants)["GRAVITY"] = GRAVITY; - (*mConstants)["ALMOST_ZERO"] = F_ALMOST_ZERO; - (*mConstants)["ALMOST_ONE"] = F_ALMOST_ONE; - (*mConstants)["THE_ANSWER"] = 42; + mConstants["PI"] = F_PI; + mConstants["TWO_PI"] = F_TWO_PI; + mConstants["PI_BY_TWO"] = F_PI_BY_TWO; + mConstants["SQRT_TWO_PI"] = F_SQRT_TWO_PI; + mConstants["SQRT2"] = F_SQRT2; + mConstants["SQRT3"] = F_SQRT3; + mConstants["DEG_TO_RAD"] = DEG_TO_RAD; + mConstants["RAD_TO_DEG"] = RAD_TO_DEG; + mConstants["GRAVITY"] = GRAVITY; } LLCalc::~LLCalc() { - delete mConstants; - delete mVariables; -// delete mUserVariables; } //static @@ -94,17 +86,17 @@ LLCalc* LLCalc::getInstance() void LLCalc::setVar(const std::string& name, const F32& value) { - (*mVariables)[name] = value; + mVariables[name] = value; } void LLCalc::clearVar(const std::string& name) { - mVariables->erase(name); + mVariables.erase(name); } void LLCalc::clearAllVariables() { - mVariables->clear(); + mVariables.clear(); } /* @@ -123,7 +115,7 @@ bool LLCalc::evalString(const std::string& expression, F32& result) std::string expr_upper = expression; LLStringUtil::toUpper(expr_upper); - LLCalcParser calc(result, mConstants, mVariables); + LLCalcParser calc(result, &mConstants, &mVariables); mLastErrorPos = 0; std::string::iterator start = expr_upper.begin(); diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h index 23c83f623..886e0bc8f 100644 --- a/indra/llmath/llcalc.h +++ b/indra/llmath/llcalc.h @@ -69,8 +69,8 @@ public: private: std::string::size_type mLastErrorPos; - calc_map_t* mConstants; - calc_map_t* mVariables; + calc_map_t mConstants; + calc_map_t mVariables; // *TODO: Add support for storing user defined variables, and stored functions. // Will need UI work, and a means to save them between sessions. diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h index a759a3571..600e17366 100644 --- a/indra/llmath/llcalcparser.h +++ b/indra/llmath/llcalcparser.h @@ -73,7 +73,9 @@ struct LLCalcParser : grammar (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) | (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) | (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) | - (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) + (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)]) | + (str_p("FLR") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_floor)(self,arg1)]) | + (str_p("CEIL") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_ceil)(self,arg1)]) ) >> assert_syntax(ch_p(')')) ; @@ -118,7 +120,8 @@ struct LLCalcParser : grammar term = power[term.value = arg1] >> *(('*' >> assert_syntax(power[term.value *= arg1])) | - ('/' >> assert_syntax(power[term.value /= arg1])) + ('/' >> assert_syntax(power[term.value /= arg1])) | + ('%' >> assert_syntax(power[term.value = bind(&fmodf)(term.value, arg1)])) ) ; @@ -153,7 +156,9 @@ private: F32 _sqrt(const F32& a) const { return sqrt(a); } F32 _log(const F32& a) const { return log(a); } F32 _exp(const F32& a) const { return exp(a); } - F32 _fabs(const F32& a) const { return fabs(a) * RAD_TO_DEG; } + F32 _fabs(const F32& a) const { return fabs(a); } + F32 _floor(const F32& a) const { return llfloor(a); } + F32 _ceil(const F32& a) const { return llceil(a); } F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index 263803930..7ab6cdd5f 100644 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -92,7 +92,7 @@ F32 LLCamera::getMaxView() const // ---------------- LLCamera::setFoo() member functions ---------------- -void LLCamera::setUserClipPlane(LLPlane const& plane) +void LLCamera::setUserClipPlane(const LLPlane& plane) { mPlaneCount = 7; mAgentPlanes[6] = plane; @@ -168,166 +168,91 @@ size_t LLCamera::readFrustumFromBuffer(const char *buffer) // ---------------- test methods ---------------- -S32 LLCamera::AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius) +S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius) { - static const LLVector3 scaler[] = { - LLVector3(-1,-1,-1), - LLVector3( 1,-1,-1), - LLVector3(-1, 1,-1), - LLVector3( 1, 1,-1), - LLVector3(-1,-1, 1), - LLVector3( 1,-1, 1), - LLVector3(-1, 1, 1), - LLVector3( 1, 1, 1) + static const LLVector4a scaler[] = { + LLVector4a(-1,-1,-1), + LLVector4a( 1,-1,-1), + LLVector4a(-1, 1,-1), + LLVector4a( 1, 1,-1), + LLVector4a(-1,-1, 1), + LLVector4a( 1,-1, 1), + LLVector4a(-1, 1, 1), + LLVector4a( 1, 1, 1) }; U8 mask = 0; - S32 result = 2; - - /*if (radius.magVecSquared() > mFrustumCornerDist * mFrustumCornerDist) - { //box is larger than frustum, check frustum quads against box planes - - static const LLVector3 dir[] = - { - LLVector3(1, 0, 0), - LLVector3(-1, 0, 0), - LLVector3(0, 1, 0), - LLVector3(0, -1, 0), - LLVector3(0, 0, 1), - LLVector3(0, 0, -1) - }; - - U32 quads[] = - { - 0, 1, 2, 3, - 0, 1, 5, 4, - 2, 3, 7, 6, - 3, 0, 7, 4, - 1, 2, 6, 4, - 4, 5, 6, 7 - }; - - result = 0; - - BOOL total_inside = TRUE; - for (U32 i = 0; i < 6; i++) - { - LLVector3 p = center + radius.scaledVec(dir[i]); - F32 d = -p*dir[i]; - - for (U32 j = 0; j < 6; j++) - { //for each quad - F32 dist = mAgentFrustum[quads[j*4+0]]*dir[i] + d; - if (dist > 0) - { //at least one frustum point is outside the AABB - total_inside = FALSE; - for (U32 k = 1; k < 4; k++) - { //for each other point on quad - if ( mAgentFrustum[quads[j*4+k]]*dir[i]+d <= 0.f) - { //quad is straddling some plane of AABB - return 1; - } - } - } - else - { - for (U32 k = 1; k < 4; k++) - { - if (mAgentFrustum[quads[j*4+k]]*dir[i]+d > 0.f) - { - return 1; - } - } - } - } - } - - if (total_inside) - { - result = 1; - } - } - else*/ + bool result = false; + LLVector4a rscale, maxp, minp; + LLSimdScalar d; + for (U32 i = 0; i < mPlaneCount; i++) { - for (U32 i = 0; i < mPlaneCount; i++) + mask = mPlaneMask[i]; + if (mask != 0xff) { - mask = mPlaneMask[i]; - if (mask == 0xff) - { - continue; - } - LLPlane p = mAgentPlanes[i]; - LLVector3 n = LLVector3(p); - float d = p.mV[3]; - LLVector3 rscale = radius.scaledVec(scaler[mask]); - - LLVector3 minp = center - rscale; - LLVector3 maxp = center + rscale; - - if (n * minp > -d) + const LLPlane& p(mAgentPlanes[i]); + p.getAt<3>(d); + rscale.setMul(radius, scaler[mask]); + minp.setSub(center, rscale); + d = -d; + if (p.dot3(minp).getF32() > d) { return 0; } - - if (n * maxp > -d) + + if(!result) { - result = 1; + maxp.setAdd(center, rscale); + result = (p.dot3(maxp).getF32() > d); } } } - - return result; + return result?1:2; } -S32 LLCamera::AABBInFrustumNoFarClip(const LLVector3 ¢er, const LLVector3& radius) + +S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius) { - static const LLVector3 scaler[] = { - LLVector3(-1,-1,-1), - LLVector3( 1,-1,-1), - LLVector3(-1, 1,-1), - LLVector3( 1, 1,-1), - LLVector3(-1,-1, 1), - LLVector3( 1,-1, 1), - LLVector3(-1, 1, 1), - LLVector3( 1, 1, 1) + static const LLVector4a scaler[] = { + LLVector4a(-1,-1,-1), + LLVector4a( 1,-1,-1), + LLVector4a(-1, 1,-1), + LLVector4a( 1, 1,-1), + LLVector4a(-1,-1, 1), + LLVector4a( 1,-1, 1), + LLVector4a(-1, 1, 1), + LLVector4a( 1, 1, 1) }; U8 mask = 0; - S32 result = 2; - + bool result = false; + LLVector4a rscale, maxp, minp; + LLSimdScalar d; for (U32 i = 0; i < mPlaneCount; i++) { - if (i == 5) - { - continue; - } - mask = mPlaneMask[i]; - if (mask == 0xff) + if ((i != 5) && (mask != 0xff)) { - continue; - } - LLPlane p = mAgentPlanes[i]; - LLVector3 n = LLVector3(p); - float d = p.mV[3]; - LLVector3 rscale = radius.scaledVec(scaler[mask]); - - LLVector3 minp = center - rscale; - LLVector3 maxp = center + rscale; - - if (n * minp > -d) - { - return 0; - } - - if (n * maxp > -d) - { - result = 1; + const LLPlane& p(mAgentPlanes[i]); + p.getAt<3>(d); + rscale.setMul(radius, scaler[mask]); + minp.setSub(center, rscale); + d = -d; + if (p.dot3(minp).getF32() > d) + { + return 0; + } + + if(!result) + { + maxp.setAdd(center, rscale); + result = (p.dot3(maxp).getF32() > d); + } } } - return result; + return result?1:2; } int LLCamera::sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius) @@ -715,9 +640,10 @@ void LLCamera::calculateWorldFrustumPlanes() F32 d; LLVector3 center = mOrigin - mXAxis*mNearPlane; mWorldPlanePos = center; + LLVector3 pnorm; for (int p=0; p<4; p++) { - LLVector3 pnorm = LLVector3(mLocalPlanes[p]); + mLocalPlanes[p].getVector3(pnorm); LLVector3 norm = rotateToAbsolute(pnorm); norm.normVec(); d = -(center * norm); @@ -727,13 +653,15 @@ void LLCamera::calculateWorldFrustumPlanes() LLVector3 zaxis(0, 0, 1.0f); F32 yaw = getYaw(); { - LLVector3 tnorm = LLVector3(mLocalPlanes[PLANE_LEFT]); + LLVector3 tnorm; + mLocalPlanes[PLANE_LEFT].getVector3(tnorm); tnorm.rotVec(yaw, zaxis); d = -(mOrigin * tnorm); mHorizPlanes[HORIZ_PLANE_LEFT] = LLPlane(tnorm, d); } { - LLVector3 tnorm = LLVector3(mLocalPlanes[PLANE_RIGHT]); + LLVector3 tnorm; + mLocalPlanes[PLANE_RIGHT].getVector3(tnorm); tnorm.rotVec(yaw, zaxis); d = -(mOrigin * tnorm); mHorizPlanes[HORIZ_PLANE_RIGHT] = LLPlane(tnorm, d); diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index 56afca025..0459f797c 100644 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -37,6 +37,7 @@ #include "llmath.h" #include "llcoordframe.h" #include "llplane.h" +#include "llvector4a.h" const F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD; const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f; @@ -143,7 +144,7 @@ public: virtual ~LLCamera(); - void setUserClipPlane(LLPlane const& plane); + void setUserClipPlane(const LLPlane& plane); void disableUserClipPlane(); virtual void setView(F32 vertical_fov_rads); void setViewHeightInPixels(S32 height); @@ -191,8 +192,8 @@ public: S32 sphereInFrustum(const LLVector3 ¢er, const F32 radius) const; S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); } S32 sphereInFrustumFull(const LLVector3 ¢er, const F32 radius) const { return sphereInFrustum(center, radius); } - S32 AABBInFrustum(const LLVector3 ¢er, const LLVector3& radius); - S32 AABBInFrustumNoFarClip(const LLVector3 ¢er, const LLVector3& radius); + S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius); + S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius); //does a quick 'n dirty sphere-sphere check S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius); diff --git a/indra/llmath/llinterp.h b/indra/llmath/llinterp.h index 62891d198..485c7a3a6 100644 --- a/indra/llmath/llinterp.h +++ b/indra/llmath/llinterp.h @@ -38,6 +38,7 @@ // So, let's define _USE_MATH_DEFINES before including math.h #define _USE_MATH_DEFINES #endif + #include "math.h" // Class from which different types of interpolators can be derived diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index cbc8388a7..89ef7d616 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -35,10 +35,10 @@ #include #include -#include +#include #include "lldefs.h" -#include "llstl.h" // *TODO: Remove when LLString is gone -#include "llstring.h" // *TODO: Remove when LLString is gone +//#include "llstl.h" // *TODO: Remove when LLString is gone +//#include "llstring.h" // *TODO: Remove when LLString is gone // lltut.h uses is_approx_equal_fraction(). This was moved to its own header // file in llcommon so we can use lltut.h for llcommon tests without making // llcommon depend on llmath. @@ -61,32 +61,11 @@ #endif // Single Precision Floating Point Routines -#ifndef sqrtf -#define sqrtf(x) ((F32)sqrt((F64)(x))) -#endif -#ifndef fsqrtf -#define fsqrtf(x) sqrtf(x) -#endif - -#ifndef cosf -#define cosf(x) ((F32)cos((F64)(x))) -#endif -#ifndef sinf -#define sinf(x) ((F32)sin((F64)(x))) -#endif -#ifndef tanf +// (There used to be more defined here, but they appeared to be redundant and +// were breaking some other includes. Removed by Falcon, reviewed by Andrew, 11/25/09) +/*#ifndef tanf #define tanf(x) ((F32)tan((F64)(x))) -#endif -#ifndef acosf -#define acosf(x) ((F32)acos((F64)(x))) -#endif - -#ifndef powf -#define powf(x,y) ((F32)pow((F64)(x),(F64)(y))) -#endif -#ifndef expf -#define expf(x) ((F32)exp((F64)(x))) -#endif +#endif*/ const F32 GRAVITY = -9.8f; @@ -206,7 +185,7 @@ inline S32 llfloor( F32 f ) } return result; #else - return (S32)floorf(f); + return (S32)floor(f); #endif } @@ -537,6 +516,12 @@ inline void ll_remove_outliers(std::vector& data, F32 k) VEC_TYPE Q1 = data[data.size()/4]; VEC_TYPE Q3 = data[data.size()-data.size()/4-1]; + if ((F32)(Q3-Q1) < 1.f) + { + // not enough variation to detect outliers + return; + } + VEC_TYPE min = (VEC_TYPE) ((F32) Q1-k * (F32) (Q3-Q1)); VEC_TYPE max = (VEC_TYPE) ((F32) Q3+k * (F32) (Q3-Q1)); @@ -562,4 +547,7 @@ inline void ll_remove_outliers(std::vector& data, F32 k) data.erase(data.begin(), data.begin()+i); } } + +// Include simd math header +#include "llsimdmath.h" #endif diff --git a/indra/llmath/llmatrix3a.cpp b/indra/llmath/llmatrix3a.cpp new file mode 100644 index 000000000..ab077abcb --- /dev/null +++ b/indra/llmath/llmatrix3a.cpp @@ -0,0 +1,134 @@ +/** + * @file llvector4a.cpp + * @brief SIMD vector implementation + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llmath.h" + +static LL_ALIGN_16(const F32 M_IDENT_3A[12]) = + { 1.f, 0.f, 0.f, 0.f, // Column 1 + 0.f, 1.f, 0.f, 0.f, // Column 2 + 0.f, 0.f, 1.f, 0.f }; // Column 3 + +extern const LLMatrix3a LL_M3A_IDENTITY = *reinterpret_cast (M_IDENT_3A); + +void LLMatrix3a::setMul( const LLMatrix3a& lhs, const LLMatrix3a& rhs ) +{ + const LLVector4a col0 = lhs.getColumn(0); + const LLVector4a col1 = lhs.getColumn(1); + const LLVector4a col2 = lhs.getColumn(2); + + for ( int i = 0; i < 3; i++ ) + { + LLVector4a xxxx = _mm_load_ss( rhs.mColumns[i].getF32ptr() ); + xxxx.splat<0>( xxxx ); + xxxx.mul( col0 ); + + { + LLVector4a yyyy = _mm_load_ss( rhs.mColumns[i].getF32ptr() + 1 ); + yyyy.splat<0>( yyyy ); + yyyy.mul( col1 ); + xxxx.add( yyyy ); + } + + { + LLVector4a zzzz = _mm_load_ss( rhs.mColumns[i].getF32ptr() + 2 ); + zzzz.splat<0>( zzzz ); + zzzz.mul( col2 ); + xxxx.add( zzzz ); + } + + xxxx.store4a( mColumns[i].getF32ptr() ); + } + +} + +/*static */void LLMatrix3a::batchTransform( const LLMatrix3a& xform, const LLVector4a* src, int numVectors, LLVector4a* dst ) +{ + const LLVector4a col0 = xform.getColumn(0); + const LLVector4a col1 = xform.getColumn(1); + const LLVector4a col2 = xform.getColumn(2); + const LLVector4a* maxAddr = src + numVectors; + + if ( numVectors & 0x1 ) + { + LLVector4a xxxx = _mm_load_ss( (const F32*)src ); + LLVector4a yyyy = _mm_load_ss( (const F32*)src + 1 ); + LLVector4a zzzz = _mm_load_ss( (const F32*)src + 2 ); + xxxx.splat<0>( xxxx ); + yyyy.splat<0>( yyyy ); + zzzz.splat<0>( zzzz ); + xxxx.mul( col0 ); + yyyy.mul( col1 ); + zzzz.mul( col2 ); + xxxx.add( yyyy ); + xxxx.add( zzzz ); + xxxx.store4a( (F32*)dst ); + src++; + dst++; + } + + + numVectors >>= 1; + while ( src < maxAddr ) + { + _mm_prefetch( (const char*)(src + 32 ), _MM_HINT_NTA ); + _mm_prefetch( (const char*)(dst + 32), _MM_HINT_NTA ); + LLVector4a xxxx = _mm_load_ss( (const F32*)src ); + LLVector4a xxxx1= _mm_load_ss( (const F32*)(src + 1) ); + + xxxx.splat<0>( xxxx ); + xxxx1.splat<0>( xxxx1 ); + xxxx.mul( col0 ); + xxxx1.mul( col0 ); + + { + LLVector4a yyyy = _mm_load_ss( (const F32*)src + 1 ); + LLVector4a yyyy1 = _mm_load_ss( (const F32*)(src + 1) + 1); + yyyy.splat<0>( yyyy ); + yyyy1.splat<0>( yyyy1 ); + yyyy.mul( col1 ); + yyyy1.mul( col1 ); + xxxx.add( yyyy ); + xxxx1.add( yyyy1 ); + } + + { + LLVector4a zzzz = _mm_load_ss( (const F32*)(src) + 2 ); + LLVector4a zzzz1 = _mm_load_ss( (const F32*)(++src) + 2 ); + zzzz.splat<0>( zzzz ); + zzzz1.splat<0>( zzzz1 ); + zzzz.mul( col2 ); + zzzz1.mul( col2 ); + xxxx.add( zzzz ); + xxxx1.add( zzzz1 ); + } + + xxxx.store4a(dst->getF32ptr()); + src++; + dst++; + + xxxx1.store4a((F32*)dst++); + } +} diff --git a/indra/llmath/llmatrix3a.h b/indra/llmath/llmatrix3a.h new file mode 100644 index 000000000..adb7e3389 --- /dev/null +++ b/indra/llmath/llmatrix3a.h @@ -0,0 +1,128 @@ +/** + * @file llmatrix3a.h + * @brief LLMatrix3a class header file - memory aligned and vectorized 3x3 matrix + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLMATRIX3A_H +#define LL_LLMATRIX3A_H + +///////////////////////////// +// LLMatrix3a, LLRotation +///////////////////////////// +// This class stores a 3x3 (technically 4x3) matrix in column-major order +///////////////////////////// +///////////////////////////// +// These classes are intentionally minimal right now. If you need additional +// functionality, please contact someone with SSE experience (e.g., Falcon or +// Huseby). +///////////////////////////// + +// LLMatrix3a is the base class for LLRotation, which should be used instead any time you're dealing with a +// rotation matrix. +class LLMatrix3a +{ +public: + + // Utility function for quickly transforming an array of LLVector4a's + // For transforming a single LLVector4a, see LLVector4a::setRotated + static void batchTransform( const LLMatrix3a& xform, const LLVector4a* src, int numVectors, LLVector4a* dst ); + + // Utility function to obtain the identity matrix + static inline const LLMatrix3a& getIdentity(); + + ////////////////////////// + // Ctors + ////////////////////////// + + // Ctor + LLMatrix3a() {} + + // Ctor for setting by columns + inline LLMatrix3a( const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2 ); + + ////////////////////////// + // Get/Set + ////////////////////////// + + // Loads from an LLMatrix3 + inline void loadu(const LLMatrix3& src); + + // Set rows + inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2); + + // Set columns + inline void setColumns(const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2); + + // Get the read-only access to a specified column. Valid columns are 0-2, but the + // function is unchecked. You've been warned. + inline const LLVector4a& getColumn(const U32 column) const; + + ///////////////////////// + // Matrix modification + ///////////////////////// + + // Set this matrix to the product of lhs and rhs ( this = lhs * rhs ) + void setMul( const LLMatrix3a& lhs, const LLMatrix3a& rhs ); + + // Set this matrix to the transpose of src + inline void setTranspose(const LLMatrix3a& src); + + // Set this matrix to a*w + b*(1-w) + inline void setLerp(const LLMatrix3a& a, const LLMatrix3a& b, F32 w); + + ///////////////////////// + // Matrix inspection + ///////////////////////// + + // Sets all 4 elements in 'dest' to the determinant of this matrix. + // If you will be using the determinant in subsequent ops with LLVector4a, use this version + inline void getDeterminant( LLVector4a& dest ) const; + + // Returns the determinant as an LLSimdScalar. Use this if you will be using the determinant + // primary for scalar operations. + inline LLSimdScalar getDeterminant() const; + + // Returns nonzero if rows 0-2 and colums 0-2 contain no NaN or INF values. Row 3 is ignored + inline LLBool32 isFinite() const; + + // Returns true if this matrix is equal to 'rhs' up to 'tolerance' + inline bool isApproximatelyEqual( const LLMatrix3a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + +protected: + + LLVector4a mColumns[3]; + +}; + +class LLRotation : public LLMatrix3a +{ +public: + + LLRotation() {} + + // Returns true if this rotation is orthonormal with det ~= 1 + inline bool isOkRotation() const; +}; + +#endif diff --git a/indra/llmath/llmatrix3a.inl b/indra/llmath/llmatrix3a.inl new file mode 100644 index 000000000..37819fea3 --- /dev/null +++ b/indra/llmath/llmatrix3a.inl @@ -0,0 +1,119 @@ +/** + * @file llmatrix3a.inl + * @brief LLMatrix3a inline definitions + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llmatrix3a.h" +#include "m3math.h" + +inline LLMatrix3a::LLMatrix3a( const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2 ) +{ + setColumns( c0, c1, c2 ); +} + +inline void LLMatrix3a::loadu(const LLMatrix3& src) +{ + mColumns[0].load3(src.mMatrix[0]); + mColumns[1].load3(src.mMatrix[1]); + mColumns[2].load3(src.mMatrix[2]); +} + +inline void LLMatrix3a::setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2) +{ + mColumns[0] = r0; + mColumns[1] = r1; + mColumns[2] = r2; + setTranspose( *this ); +} + +inline void LLMatrix3a::setColumns(const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2) +{ + mColumns[0] = c0; + mColumns[1] = c1; + mColumns[2] = c2; +} + +inline void LLMatrix3a::setTranspose(const LLMatrix3a& src) +{ + const LLQuad srcCol0 = src.mColumns[0]; + const LLQuad srcCol1 = src.mColumns[1]; + const LLQuad unpacklo = _mm_unpacklo_ps( srcCol0, srcCol1 ); + mColumns[0] = _mm_movelh_ps( unpacklo, src.mColumns[2] ); + mColumns[1] = _mm_shuffle_ps( _mm_movehl_ps( srcCol0, unpacklo ), src.mColumns[2], _MM_SHUFFLE(0, 1, 1, 0) ); + mColumns[2] = _mm_shuffle_ps( _mm_unpackhi_ps( srcCol0, srcCol1 ), src.mColumns[2], _MM_SHUFFLE(0, 2, 1, 0) ); +} + +inline const LLVector4a& LLMatrix3a::getColumn(const U32 column) const +{ + llassert( column < 3 ); + return mColumns[column]; +} + +inline void LLMatrix3a::setLerp(const LLMatrix3a& a, const LLMatrix3a& b, F32 w) +{ + mColumns[0].setLerp( a.mColumns[0], b.mColumns[0], w ); + mColumns[1].setLerp( a.mColumns[1], b.mColumns[1], w ); + mColumns[2].setLerp( a.mColumns[2], b.mColumns[2], w ); +} + +inline LLBool32 LLMatrix3a::isFinite() const +{ + return mColumns[0].isFinite3() && mColumns[1].isFinite3() && mColumns[2].isFinite3(); +} + +inline void LLMatrix3a::getDeterminant( LLVector4a& dest ) const +{ + LLVector4a col1xcol2; col1xcol2.setCross3( mColumns[1], mColumns[2] ); + dest.setAllDot3( col1xcol2, mColumns[0] ); +} + +inline LLSimdScalar LLMatrix3a::getDeterminant() const +{ + LLVector4a col1xcol2; col1xcol2.setCross3( mColumns[1], mColumns[2] ); + return col1xcol2.dot3( mColumns[0] ); +} + +inline bool LLMatrix3a::isApproximatelyEqual( const LLMatrix3a& rhs, F32 tolerance /*= F_APPROXIMATELY_ZERO*/ ) const +{ + return rhs.getColumn(0).equals3(mColumns[0], tolerance) + && rhs.getColumn(1).equals3(mColumns[1], tolerance) + && rhs.getColumn(2).equals3(mColumns[2], tolerance); +} + +inline const LLMatrix3a& LLMatrix3a::getIdentity() +{ + extern const LLMatrix3a LL_M3A_IDENTITY; + return LL_M3A_IDENTITY; +} + +inline bool LLRotation::isOkRotation() const +{ + LLMatrix3a transpose; transpose.setTranspose( *this ); + LLMatrix3a product; product.setMul( *this, transpose ); + + LLSimdScalar detMinusOne = getDeterminant() - 1.f; + + return product.isApproximatelyEqual( LLMatrix3a::getIdentity() ) && (detMinusOne.getAbs() < F_APPROXIMATELY_ZERO); +} + diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h new file mode 100644 index 000000000..27cf5b79f --- /dev/null +++ b/indra/llmath/llmatrix4a.h @@ -0,0 +1,143 @@ +/** + * @file llmatrix4a.h + * @brief LLMatrix4a class header file - memory aligned and vectorized 4x4 matrix + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLMATRIX4A_H +#define LL_LLMATRIX4A_H + +#include "llvector4a.h" +#include "m4math.h" +#include "m3math.h" + +class LLMatrix4a +{ +public: + LLVector4a mMatrix[4]; + + inline void clear() + { + mMatrix[0].clear(); + mMatrix[1].clear(); + mMatrix[2].clear(); + mMatrix[3].clear(); + } + + inline void loadu(const LLMatrix4& src) + { + mMatrix[0] = _mm_loadu_ps(src.mMatrix[0]); + mMatrix[1] = _mm_loadu_ps(src.mMatrix[1]); + mMatrix[2] = _mm_loadu_ps(src.mMatrix[2]); + mMatrix[3] = _mm_loadu_ps(src.mMatrix[3]); + + } + + inline void loadu(const LLMatrix3& src) + { + mMatrix[0].load3(src.mMatrix[0]); + mMatrix[1].load3(src.mMatrix[1]); + mMatrix[2].load3(src.mMatrix[2]); + mMatrix[3].set(0,0,0,1.f); + } + + inline void add(const LLMatrix4a& rhs) + { + mMatrix[0].add(rhs.mMatrix[0]); + mMatrix[1].add(rhs.mMatrix[1]); + mMatrix[2].add(rhs.mMatrix[2]); + mMatrix[3].add(rhs.mMatrix[3]); + } + + inline void setRows(const LLVector4a& r0, const LLVector4a& r1, const LLVector4a& r2) + { + mMatrix[0] = r0; + mMatrix[1] = r1; + mMatrix[2] = r2; + } + + inline void setMul(const LLMatrix4a& m, const F32 s) + { + mMatrix[0].setMul(m.mMatrix[0], s); + mMatrix[1].setMul(m.mMatrix[1], s); + mMatrix[2].setMul(m.mMatrix[2], s); + mMatrix[3].setMul(m.mMatrix[3], s); + } + + inline void setLerp(const LLMatrix4a& a, const LLMatrix4a& b, F32 w) + { + LLVector4a d0,d1,d2,d3; + d0.setSub(b.mMatrix[0], a.mMatrix[0]); + d1.setSub(b.mMatrix[1], a.mMatrix[1]); + d2.setSub(b.mMatrix[2], a.mMatrix[2]); + d3.setSub(b.mMatrix[3], a.mMatrix[3]); + + // this = a + d*w + + d0.mul(w); + d1.mul(w); + d2.mul(w); + d3.mul(w); + + mMatrix[0].setAdd(a.mMatrix[0],d0); + mMatrix[1].setAdd(a.mMatrix[1],d1); + mMatrix[2].setAdd(a.mMatrix[2],d2); + mMatrix[3].setAdd(a.mMatrix[3],d3); + } + + inline void rotate(const LLVector4a& v, LLVector4a& res) + { + res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + res.mul(mMatrix[0]); + + LLVector4a y; + y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + y.mul(mMatrix[1]); + + LLVector4a z; + z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + z.mul(mMatrix[2]); + + res.add(y); + res.add(z); + } + + inline void affineTransform(const LLVector4a& v, LLVector4a& res) + { + LLVector4a x,y,z; + + x = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + + x.mul(mMatrix[0]); + y.mul(mMatrix[1]); + z.mul(mMatrix[2]); + + x.add(y); + z.add(mMatrix[3]); + res.setAdd(x,z); + } +}; + +#endif diff --git a/indra/llmath/lloctree.h b/indra/llmath/lloctree.h index eda350e93..f49c657c0 100644 --- a/indra/llmath/lloctree.h +++ b/indra/llmath/lloctree.h @@ -35,6 +35,7 @@ #include "lltreenode.h" #include "v3math.h" +#include "llvector4a.h" #include #include @@ -85,6 +86,7 @@ template class LLOctreeNode : public LLTreeNode { public: + typedef LLOctreeTraveler oct_traveler; typedef LLTreeTraveler tree_traveler; typedef typename std::set > element_list; @@ -96,23 +98,30 @@ public: typedef LLOctreeNode oct_node; typedef LLOctreeListener oct_listener; - static const U8 OCTANT_POSITIVE_X = 0x01; - static const U8 OCTANT_POSITIVE_Y = 0x02; - static const U8 OCTANT_POSITIVE_Z = 0x04; - - LLOctreeNode( LLVector3d center, - LLVector3d size, + /*void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + }*/ + + LLOctreeNode( const LLVector4a& center, + const LLVector4a& size, BaseType* parent, U8 octant = 255) : mParent((oct_node*)parent), - mCenter(center), - mSize(size), mOctant(octant) { + mCenter = center; + mSize = size; + updateMinMax(); if ((mOctant == 255) && mParent) { - mOctant = ((oct_node*) mParent)->getOctant(mCenter.mdV); + mOctant = ((oct_node*) mParent)->getOctant(mCenter); } clearChildren(); @@ -129,39 +138,24 @@ public: } inline const BaseType* getParent() const { return mParent; } - inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; } - inline const LLVector3d& getCenter() const { return mCenter; } - inline const LLVector3d& getSize() const { return mSize; } - inline void setCenter(const LLVector3d center) { mCenter = center; } - inline void setSize(const LLVector3d size) { mSize = size; } + inline void setParent(BaseType* parent) { mParent = (oct_node*) parent; } + inline const LLVector4a& getCenter() const { return mCenter; } + inline const LLVector4a& getSize() const { return mSize; } + inline void setCenter(const LLVector4a& center) { mCenter = center; } + inline void setSize(const LLVector4a& size) { mSize = size; } inline oct_node* getNodeAt(T* data) { return getNodeAt(data->getPositionGroup(), data->getBinRadius()); } inline U8 getOctant() const { return mOctant; } inline const oct_node* getOctParent() const { return (const oct_node*) getParent(); } inline oct_node* getOctParent() { return (oct_node*) getParent(); } - U8 getOctant(const F64 pos[]) const //get the octant pos is in + U8 getOctant(const LLVector4a& pos) const //get the octant pos is in { - U8 ret = 0; - - if (pos[0] > mCenter.mdV[0]) - { - ret |= OCTANT_POSITIVE_X; - } - if (pos[1] > mCenter.mdV[1]) - { - ret |= OCTANT_POSITIVE_Y; - } - if (pos[2] > mCenter.mdV[2]) - { - ret |= OCTANT_POSITIVE_Z; - } - - return ret; + return (U8) (pos.greaterThan(mCenter).getGatheredBits() & 0x7); } - inline bool isInside(const LLVector3d& pos, const F64& rad) const + inline bool isInside(const LLVector4a& pos, const F32& rad) const { - return rad <= mSize.mdV[0]*2.0 && isInside(pos); + return rad <= mSize[0]*2.f && isInside(pos); } inline bool isInside(T* data) const @@ -169,29 +163,27 @@ public: return isInside(data->getPositionGroup(), data->getBinRadius()); } - bool isInside(const LLVector3d& pos) const + bool isInside(const LLVector4a& pos) const { - const F64& x = pos.mdV[0]; - const F64& y = pos.mdV[1]; - const F64& z = pos.mdV[2]; - - if (x > mMax.mdV[0] || x <= mMin.mdV[0] || - y > mMax.mdV[1] || y <= mMin.mdV[1] || - z > mMax.mdV[2] || z <= mMin.mdV[2]) + S32 gt = pos.greaterThan(mMax).getGatheredBits() & 0x7; + if (gt) { return false; } - + + S32 lt = pos.lessEqual(mMin).getGatheredBits() & 0x7; + if (lt) + { + return false; + } + return true; } void updateMinMax() { - for (U32 i = 0; i < 3; i++) - { - mMax.mdV[i] = mCenter.mdV[i] + mSize.mdV[i]; - mMin.mdV[i] = mCenter.mdV[i] - mSize.mdV[i]; - } + mMax.setAdd(mCenter, mSize); + mMin.setSub(mCenter, mSize); } inline oct_listener* getOctListener(U32 index) @@ -218,20 +210,20 @@ public: (radius <= p_size && radius > size); } - static void pushCenter(LLVector3d ¢er, const LLVector3d &size, const T* data) + static void pushCenter(LLVector4a ¢er, const LLVector4a &size, const T* data) { - const LLVector3d& pos = data->getPositionGroup(); - for (U32 i = 0; i < 3; i++) - { - if (pos.mdV[i] > center.mdV[i]) - { - center.mdV[i] += size.mdV[i]; - } - else - { - center.mdV[i] -= size.mdV[i]; - } - } + const LLVector4a& pos = data->getPositionGroup(); + + LLVector4Logical gt = pos.greaterThan(center); + + LLVector4a up; + up = _mm_and_ps(size, gt); + + LLVector4a down; + down = _mm_andnot_ps(gt, size); + + center.add(up); + center.sub(down); } void accept(oct_traveler* visitor) { visitor->visit(this); } @@ -273,14 +265,14 @@ public: } - oct_node* getNodeAt(const LLVector3d& pos, const F32& rad) + oct_node* getNodeAt(const LLVector4a& pos, const F32& rad) { LLOctreeNode* node = this; if (node->isInside(pos, rad)) { //do a quick search by octant - U8 octant = node->getOctant(pos.mdV); + U8 octant = node->getOctant(pos); //traverse the tree until we find a node that has no node //at the appropriate octant or is smaller than the object. @@ -291,7 +283,7 @@ public: while (next_node != 255 && node->getSize()[0] >= rad) { node = node->getChild(next_node); - octant = node->getOctant(pos.mdV); + octant = node->getOctant(pos); next_node = node->mChildMap[octant]; } } @@ -307,7 +299,7 @@ public: { if (data == NULL) { - //OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl; + OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE BRANCH !!!" << llendl; return false; } LLOctreeNode* parent = getOctParent(); @@ -347,16 +339,21 @@ public: } //it's here, but no kids are in the right place, make a new kid - LLVector3d center(getCenter()); - LLVector3d size(getSize()*0.5); + LLVector4a center = getCenter(); + LLVector4a size = getSize(); + size.mul(0.5f); //push center in direction of data LLOctreeNode::pushCenter(center, size, data); // handle case where floating point number gets too small - if( llabs(center.mdV[0] - getCenter().mdV[0]) < F_APPROXIMATELY_ZERO && - llabs(center.mdV[1] - getCenter().mdV[1]) < F_APPROXIMATELY_ZERO && - llabs(center.mdV[2] - getCenter().mdV[2]) < F_APPROXIMATELY_ZERO) + LLVector4a val; + val.setSub(center, getCenter()); + val.setAbs(val); + + S32 lt = val.lessThan(LLVector4a::getEpsilon()).getGatheredBits() & 0x7; + + if( lt == 0x7 ) { mData.insert(data); BaseType::insert(data); @@ -374,7 +371,7 @@ public: //make sure no existing node matches this position for (U32 i = 0; i < getChildCount(); i++) { - if (mChild[i]->getCenter() == center) + if (mChild[i]->getCenter().equals3(center)) { OCT_ERRS << "Octree detected duplicate child center and gave up." << llendl; return false; @@ -392,7 +389,7 @@ public: else { //it's not in here, give it to the root - //OCT_ERRS << "Octree insertion failed, starting over from root!" << llendl; + OCT_ERRS << "Octree insertion failed, starting over from root!" << llendl; oct_node* node = this; @@ -503,18 +500,18 @@ public: { #if LL_OCTREE_PARANOIA_CHECK - if (child->getSize() == getSize()) + if (child->getSize().equals3(getSize())) { OCT_ERRS << "Child size is same as parent size!" << llendl; } for (U32 i = 0; i < getChildCount(); i++) { - if(mChild[i]->getSize() != child->getSize()) + if(!mChild[i]->getSize().equals3(child->getSize())) { OCT_ERRS <<"Invalid octree child size." << llendl; } - if (mChild[i]->getCenter() == child->getCenter()) + if (mChild[i]->getCenter().equals3(child->getCenter())) { OCT_ERRS <<"Duplicate octree child position." << llendl; } @@ -593,7 +590,7 @@ public: } } - //OCT_ERRS << "Octree failed to delete requested child." << llendl; + OCT_ERRS << "Octree failed to delete requested child." << llendl; } protected: @@ -605,11 +602,11 @@ protected: MIN = 3 } eDName; - LLVector3d mCenter; - LLVector3d mSize; - LLVector3d mMax; - LLVector3d mMin; - + LLVector4a mCenter; + LLVector4a mSize; + LLVector4a mMax; + LLVector4a mMin; + oct_node* mParent; U8 mOctant; @@ -628,9 +625,9 @@ public: typedef LLOctreeNode BaseType; typedef LLOctreeNode oct_node; - LLOctreeRoot( const LLVector3d ¢er, - const LLVector3d &size, - BaseType* parent) + LLOctreeRoot(const LLVector4a& center, + const LLVector4a& size, + BaseType* parent) : BaseType(center, size, parent) { } @@ -673,28 +670,33 @@ public: { if (data == NULL) { - //OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl; + OCT_ERRS << "!!! INVALID ELEMENT ADDED TO OCTREE ROOT !!!" << llendl; return false; } if (data->getBinRadius() > 4096.0) { - //OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl; + OCT_ERRS << "!!! ELEMENT EXCEEDS MAXIMUM SIZE IN OCTREE ROOT !!!" << llendl; return false; } - const F64 MAX_MAG = 1024.0*1024.0; + LLVector4a MAX_MAG; + MAX_MAG.splat(1024.f*1024.f); - const LLVector3d& v = data->getPositionGroup(); - if (!(fabs(v.mdV[0]-this->mCenter.mdV[0]) < MAX_MAG && - fabs(v.mdV[1]-this->mCenter.mdV[1]) < MAX_MAG && - fabs(v.mdV[2]-this->mCenter.mdV[2]) < MAX_MAG)) + const LLVector4a& v = data->getPositionGroup(); + + LLVector4a val; + val.setSub(v, BaseType::mCenter); + val.setAbs(val); + S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; + + if (lt != 0x7) { - //OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl; + OCT_ERRS << "!!! ELEMENT EXCEEDS RANGE OF SPATIAL PARTITION !!!" << llendl; return false; } - if (this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup())) + if (this->getSize()[0] > data->getBinRadius() && isInside(data->getPositionGroup())) { //we got it, just act like a branch oct_node* node = getNodeAt(data); @@ -710,31 +712,34 @@ public: else if (this->getChildCount() == 0) { //first object being added, just wrap it up - while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup()))) + while (!(this->getSize()[0] > data->getBinRadius() && isInside(data->getPositionGroup()))) { - LLVector3d center, size; + LLVector4a center, size; center = this->getCenter(); size = this->getSize(); LLOctreeNode::pushCenter(center, size, data); this->setCenter(center); - this->setSize(size*2); + size.mul(2.f); + this->setSize(size); this->updateMinMax(); } LLOctreeNode::insert(data); } else { - while (!(this->getSize().mdV[0] > data->getBinRadius() && isInside(data->getPositionGroup()))) + while (!(this->getSize()[0] > data->getBinRadius() && isInside(data->getPositionGroup()))) { //the data is outside the root node, we need to grow - LLVector3d center(this->getCenter()); - LLVector3d size(this->getSize()); + LLVector4a center(this->getCenter()); + LLVector4a size(this->getSize()); //expand this node - LLVector3d newcenter(center); + LLVector4a newcenter(center); LLOctreeNode::pushCenter(newcenter, size, data); this->setCenter(newcenter); - this->setSize(size*2); + LLVector4a size2 = size; + size2.mul(2.f); + this->setSize(size2); this->updateMinMax(); //copy our children to a new branch diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h index 8803d0774..a18f63a0d 100644 --- a/indra/llmath/llplane.h +++ b/indra/llmath/llplane.h @@ -42,13 +42,17 @@ // The plane normal = [A, B, C] // The closest approach = D / sqrt(A*A + B*B + C*C) -class LLPlane : public LLVector4 +class LLPlane { public: + + // Constructors LLPlane() {}; // no default constructor LLPlane(const LLVector3 &p0, F32 d) { setVec(p0, d); } LLPlane(const LLVector3 &p0, const LLVector3 &n) { setVec(p0, n); } - inline void setVec(const LLVector3 &p0, F32 d) { LLVector4::setVec(p0[0], p0[1], p0[2], d); } + inline void setVec(const LLVector3 &p0, F32 d) { mV.set(p0[0], p0[1], p0[2], d); } + + // Set inline void setVec(const LLVector3 &p0, const LLVector3 &n) { F32 d = -(p0 * n); @@ -64,39 +68,38 @@ public: F32 d = -(w * p0); setVec(w, d); } - - inline LLPlane& operator=(const LLVector4& v2) { LLVector4::setVec(v2[0],v2[1],v2[2],v2[3]); return *this;} - - inline void set(const LLPlane& p2) { LLVector4::setVec(p2); } + + inline LLPlane& operator=(const LLVector4& v2) { mV.set(v2[0],v2[1],v2[2],v2[3]); return *this;} + + inline LLPlane& operator=(const LLVector4a& v2) { mV.set(v2[0],v2[1],v2[2],v2[3]); return *this;} + + inline void set(const LLPlane& p2) { mV = p2.mV; } // F32 dist(const LLVector3 &v2) const { return mV[0]*v2[0] + mV[1]*v2[1] + mV[2]*v2[2] + mV[3]; } + inline LLSimdScalar dot3(const LLVector4a& b) const { return mV.dot3(b); } + + // Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates + // the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead + inline F32 operator[](const S32 idx) const { return mV[idx]; } + + // preferable when index is known at compile time + template LL_FORCE_INLINE void getAt(LLSimdScalar& v) const { v = mV.getScalarAt(); } + // reset the vector to 0, 0, 0, 1 - inline void clear() { LLVector4::setVec(0, 0, 0, 1); } + inline void clear() { mV.set(0, 0, 0, 1); } inline void getVector3(LLVector3& vec) const { vec.set(mV[0], mV[1], mV[2]); } - + // Retrieve the mask indicating which of the x, y, or z axis are greater or equal to zero. inline U8 calcPlaneMask() const - { - U8 mask = 0; - - if (mV[0] >= 0) - { - mask |= 1; - } - if (mV[1] >= 0) - { - mask |= 2; - } - if (mV[2] >= 0) - { - mask |= 4; - } - - return mask; + { + return mV.greaterEqual(LLVector4a::getZero()).getGatheredBits() & LLVector4Logical::MASK_XYZ; } + +private: + LLVector4a mV; }; diff --git a/indra/llmath/llquantize.h b/indra/llmath/llquantize.h index 2192427f0..c043f7f75 100644 --- a/indra/llmath/llquantize.h +++ b/indra/llmath/llquantize.h @@ -35,10 +35,16 @@ #define LL_LLQUANTIZE_H const U16 U16MAX = 65535; +LL_ALIGN_16( const F32 F_U16MAX_4A[4] ) = { 65535.f, 65535.f, 65535.f, 65535.f }; + const F32 OOU16MAX = 1.f/(F32)(U16MAX); +LL_ALIGN_16( const F32 F_OOU16MAX_4A[4] ) = { OOU16MAX, OOU16MAX, OOU16MAX, OOU16MAX }; const U8 U8MAX = 255; +LL_ALIGN_16( const F32 F_U8MAX_4A[4] ) = { 255.f, 255.f, 255.f, 255.f }; + const F32 OOU8MAX = 1.f/(F32)(U8MAX); +LL_ALIGN_16( const F32 F_OOU8MAX_4A[4] ) = { OOU8MAX, OOU8MAX, OOU8MAX, OOU8MAX }; const U8 FIRSTVALIDCHAR = 54; const U8 MAXSTRINGVAL = U8MAX - FIRSTVALIDCHAR; //we don't allow newline or null diff --git a/indra/llmath/llquaternion2.h b/indra/llmath/llquaternion2.h new file mode 100644 index 000000000..fd9c0cf3a --- /dev/null +++ b/indra/llmath/llquaternion2.h @@ -0,0 +1,105 @@ +/** + * @file llquaternion2.h + * @brief LLQuaternion2 class header file - SIMD-enabled quaternion class + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_QUATERNION2_H +#define LL_QUATERNION2_H + +///////////////////////////// +// LLQuaternion2 +///////////////////////////// +// This class stores a quaternion x*i + y*j + z*k + w in order +// (i.e., w in high order element of vector) +///////////////////////////// +///////////////////////////// +// These classes are intentionally minimal right now. If you need additional +// functionality, please contact someone with SSE experience (e.g., Falcon or +// Huseby). +///////////////////////////// +#include "llquaternion.h" + +class LLQuaternion2 +{ +public: + + ////////////////////////// + // Ctors + ////////////////////////// + + // Ctor + LLQuaternion2() {} + + // Ctor from LLQuaternion + explicit LLQuaternion2( const class LLQuaternion& quat ); + + ////////////////////////// + // Get/Set + ////////////////////////// + + // Load from an LLQuaternion + inline void operator=( const LLQuaternion& quat ) + { + mQ.loadua( quat.mQ ); + } + + // Return the internal LLVector4a representation of the quaternion + inline const LLVector4a& getVector4a() const; + inline LLVector4a& getVector4aRw(); + + ///////////////////////// + // Quaternion modification + ///////////////////////// + + // Set this quaternion to the conjugate of src + inline void setConjugate(const LLQuaternion2& src); + + // Renormalizes the quaternion. Assumes it has nonzero length. + inline void normalize(); + + // Quantize this quaternion to 8 bit precision + inline void quantize8(); + + // Quantize this quaternion to 16 bit precision + inline void quantize16(); + + ///////////////////////// + // Quaternion inspection + ///////////////////////// + + // Return true if this quaternion is equal to 'rhs'. + // Note! Quaternions exhibit "double-cover", so any rotation has two equally valid + // quaternion representations and they will NOT compare equal. + inline bool equals(const LLQuaternion2& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + + // Return true if all components are finite and the quaternion is normalized + inline bool isOkRotation() const; + +protected: + + LLVector4a mQ; + +}; + +#endif diff --git a/indra/llmath/llquaternion2.inl b/indra/llmath/llquaternion2.inl new file mode 100644 index 000000000..2a6987552 --- /dev/null +++ b/indra/llmath/llquaternion2.inl @@ -0,0 +1,102 @@ +/** + * @file llquaternion2.inl + * @brief LLQuaternion2 inline definitions + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llquaternion2.h" + +static const LLQuad LL_V4A_PLUS_ONE = {1.f, 1.f, 1.f, 1.f}; +static const LLQuad LL_V4A_MINUS_ONE = {-1.f, -1.f, -1.f, -1.f}; + +// Ctor from LLQuaternion +inline LLQuaternion2::LLQuaternion2( const LLQuaternion& quat ) +{ + mQ.set(quat.mQ[VX], quat.mQ[VY], quat.mQ[VZ], quat.mQ[VW]); +} + +////////////////////////// +// Get/Set +////////////////////////// + +// Return the internal LLVector4a representation of the quaternion +inline const LLVector4a& LLQuaternion2::getVector4a() const +{ + return mQ; +} + +inline LLVector4a& LLQuaternion2::getVector4aRw() +{ + return mQ; +} + +///////////////////////// +// Quaternion modification +///////////////////////// + +// Set this quaternion to the conjugate of src +inline void LLQuaternion2::setConjugate(const LLQuaternion2& src) +{ + static LL_ALIGN_16( const U32 F_QUAT_INV_MASK_4A[4] ) = { 0x80000000, 0x80000000, 0x80000000, 0x00000000 }; + mQ = _mm_xor_ps(src.mQ, *reinterpret_cast(&F_QUAT_INV_MASK_4A)); +} + +// Renormalizes the quaternion. Assumes it has nonzero length. +inline void LLQuaternion2::normalize() +{ + mQ.normalize4(); +} + +// Quantize this quaternion to 8 bit precision +inline void LLQuaternion2::quantize8() +{ + mQ.quantize8( LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE ); + normalize(); +} + +// Quantize this quaternion to 16 bit precision +inline void LLQuaternion2::quantize16() +{ + mQ.quantize16( LL_V4A_MINUS_ONE, LL_V4A_PLUS_ONE ); + normalize(); +} + + +///////////////////////// +// Quaternion inspection +///////////////////////// + +// Return true if this quaternion is equal to 'rhs'. +// Note! Quaternions exhibit "double-cover", so any rotation has two equally valid +// quaternion representations and they will NOT compare equal. +inline bool LLQuaternion2::equals(const LLQuaternion2 &rhs, F32 tolerance/* = F_APPROXIMATELY_ZERO*/) const +{ + return mQ.equals4(rhs.mQ, tolerance); +} + +// Return true if all components are finite and the quaternion is normalized +inline bool LLQuaternion2::isOkRotation() const +{ + return mQ.isFinite4() && mQ.isNormalized4(); +} + diff --git a/indra/llmath/llrect.cpp b/indra/llmath/llrect.cpp index cba76dd21..0db74f20f 100644 --- a/indra/llmath/llrect.cpp +++ b/indra/llmath/llrect.cpp @@ -31,4 +31,5 @@ #include "linden_common.h" +// implementation is all in the header, this include dep ensures the unit test is rerun if the implementation changes. #include "llrect.h" diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h new file mode 100644 index 000000000..c7cdf7b32 --- /dev/null +++ b/indra/llmath/llsimdmath.h @@ -0,0 +1,93 @@ +/** + * @file llsimdmath.h + * @brief Common header for SIMD-based math library (llvector4a, llmatrix3a, etc.) + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_SIMD_MATH_H +#define LL_SIMD_MATH_H + +#ifndef LLMATH_H +#error "Please include llmath.h before this file." +#endif + +#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 ) ) +#error SSE2 not enabled. LLVector4a and related class will not compile. +#endif + +#if !LL_WINDOWS +#include +#endif + +template T* LL_NEXT_ALIGNED_ADDRESS(T* address) +{ + return reinterpret_cast( + (reinterpret_cast(address) + 0xF) & ~0xF); +} + +template T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) +{ + return reinterpret_cast( + (reinterpret_cast(address) + 0x3F) & ~0x3F); +} + +#if LL_LINUX || LL_DARWIN + +#define LL_ALIGN_PREFIX(x) +#define LL_ALIGN_POSTFIX(x) __attribute__((aligned(x))) + +#elif LL_WINDOWS + +#define LL_ALIGN_PREFIX(x) __declspec(align(x)) +#define LL_ALIGN_POSTFIX(x) + +#else +#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined" +#endif + +#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) + + + +#include +#include + +#include "llsimdtypes.h" +#include "llsimdtypes.inl" + +class LLMatrix3a; +class LLRotation; +class LLMatrix3; + +#include "llquaternion.h" + +#include "llvector4logical.h" +#include "llvector4a.h" +#include "llmatrix3a.h" +#include "llquaternion2.h" +#include "llvector4a.inl" +#include "llmatrix3a.inl" +#include "llquaternion2.inl" + + +#endif //LL_SIMD_MATH_H diff --git a/indra/llmath/llsimdtypes.h b/indra/llmath/llsimdtypes.h new file mode 100644 index 000000000..bd991d0e7 --- /dev/null +++ b/indra/llmath/llsimdtypes.h @@ -0,0 +1,124 @@ +/** + * @file llsimdtypes.h + * @brief Declaration of basic SIMD math related types + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_SIMD_TYPES_H +#define LL_SIMD_TYPES_H + +#ifndef LL_SIMD_MATH_H +#error "Please include llmath.h before this file." +#endif + +typedef __m128 LLQuad; + + +#if LL_WINDOWS +#pragma warning(push) +#pragma warning( disable : 4800 3 ) // Disable warning about casting int to bool for this class. +#if defined(_MSC_VER) && (_MSC_VER < 1500) +// VC++ 2005 is missing these intrinsics +// __forceinline is MSVC specific and attempts to override compiler inlining judgment. This is so +// even in debug builds this call is a NOP. +__forceinline const __m128 _mm_castsi128_ps( const __m128i a ) { return reinterpret_cast(a); } +__forceinline const __m128i _mm_castps_si128( const __m128 a ) { return reinterpret_cast(a); } +#endif // _MSC_VER + +#endif // LL_WINDOWS + +class LLBool32 +{ +public: + inline LLBool32() {} + inline LLBool32(int rhs) : m_bool(rhs) {} + inline LLBool32(unsigned int rhs) : m_bool(rhs) {} + inline LLBool32(bool rhs) { m_bool = static_cast(rhs); } + inline LLBool32& operator= (bool rhs) { m_bool = (int)rhs; return *this; } + inline bool operator== (bool rhs) const { return static_cast(m_bool) == rhs; } + inline bool operator!= (bool rhs) const { return !operator==(rhs); } + inline operator bool() const { return static_cast(m_bool); } + +private: + int m_bool; +}; + +#if LL_WINDOWS +#pragma warning(pop) +#endif + +class LLSimdScalar +{ +public: + inline LLSimdScalar() {} + inline LLSimdScalar(LLQuad q) + { + mQ = q; + } + + inline LLSimdScalar(F32 f) + { + mQ = _mm_set_ss(f); + } + + static inline const LLSimdScalar& getZero() + { + extern const LLQuad F_ZERO_4A; + return reinterpret_cast(F_ZERO_4A); + } + + inline F32 getF32() const; + + inline LLBool32 isApproximatelyEqual(const LLSimdScalar& rhs, F32 tolerance = F_APPROXIMATELY_ZERO) const; + + inline LLSimdScalar getAbs() const; + + inline void setMax( const LLSimdScalar& a, const LLSimdScalar& b ); + + inline void setMin( const LLSimdScalar& a, const LLSimdScalar& b ); + + inline LLSimdScalar& operator=(F32 rhs); + + inline LLSimdScalar& operator+=(const LLSimdScalar& rhs); + + inline LLSimdScalar& operator-=(const LLSimdScalar& rhs); + + inline LLSimdScalar& operator*=(const LLSimdScalar& rhs); + + inline LLSimdScalar& operator/=(const LLSimdScalar& rhs); + + inline operator LLQuad() const + { + return mQ; + } + + inline const LLQuad& getQuad() const + { + return mQ; + } + +private: + LLQuad mQ; +}; + +#endif //LL_SIMD_TYPES_H diff --git a/indra/llmath/llsimdtypes.inl b/indra/llmath/llsimdtypes.inl new file mode 100644 index 000000000..712239e42 --- /dev/null +++ b/indra/llmath/llsimdtypes.inl @@ -0,0 +1,157 @@ +/** + * @file llsimdtypes.inl + * @brief Inlined definitions of basic SIMD math related types + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + + + + +////////////////// +// LLSimdScalar +////////////////// + +inline LLSimdScalar operator+(const LLSimdScalar& a, const LLSimdScalar& b) +{ + LLSimdScalar t(a); + t += b; + return t; +} + +inline LLSimdScalar operator-(const LLSimdScalar& a, const LLSimdScalar& b) +{ + LLSimdScalar t(a); + t -= b; + return t; +} + +inline LLSimdScalar operator*(const LLSimdScalar& a, const LLSimdScalar& b) +{ + LLSimdScalar t(a); + t *= b; + return t; +} + +inline LLSimdScalar operator/(const LLSimdScalar& a, const LLSimdScalar& b) +{ + LLSimdScalar t(a); + t /= b; + return t; +} + +inline LLSimdScalar operator-(const LLSimdScalar& a) +{ + static LL_ALIGN_16(const U32 signMask[4]) = {0x80000000, 0x80000000, 0x80000000, 0x80000000 }; + return _mm_xor_ps(*reinterpret_cast(signMask), a); +} + +inline LLBool32 operator==(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comieq_ss(a, b); +} + +inline LLBool32 operator!=(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comineq_ss(a, b); +} + +inline LLBool32 operator<(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comilt_ss(a, b); +} + +inline LLBool32 operator<=(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comile_ss(a, b); +} + +inline LLBool32 operator>(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comigt_ss(a, b); +} + +inline LLBool32 operator>=(const LLSimdScalar& a, const LLSimdScalar& b) +{ + return _mm_comige_ss(a, b); +} + +inline LLBool32 LLSimdScalar::isApproximatelyEqual(const LLSimdScalar& rhs, F32 tolerance /* = F_APPROXIMATELY_ZERO */) const +{ + const LLSimdScalar tol( tolerance ); + const LLSimdScalar diff = _mm_sub_ss( mQ, rhs.mQ ); + const LLSimdScalar absDiff = diff.getAbs(); + return absDiff <= tol; +} + +inline void LLSimdScalar::setMax( const LLSimdScalar& a, const LLSimdScalar& b ) +{ + mQ = _mm_max_ss( a, b ); +} + +inline void LLSimdScalar::setMin( const LLSimdScalar& a, const LLSimdScalar& b ) +{ + mQ = _mm_min_ss( a, b ); +} + +inline LLSimdScalar& LLSimdScalar::operator=(F32 rhs) +{ + mQ = _mm_set_ss(rhs); + return *this; +} + +inline LLSimdScalar& LLSimdScalar::operator+=(const LLSimdScalar& rhs) +{ + mQ = _mm_add_ss( mQ, rhs ); + return *this; +} + +inline LLSimdScalar& LLSimdScalar::operator-=(const LLSimdScalar& rhs) +{ + mQ = _mm_sub_ss( mQ, rhs ); + return *this; +} + +inline LLSimdScalar& LLSimdScalar::operator*=(const LLSimdScalar& rhs) +{ + mQ = _mm_mul_ss( mQ, rhs ); + return *this; +} + +inline LLSimdScalar& LLSimdScalar::operator/=(const LLSimdScalar& rhs) +{ + mQ = _mm_div_ss( mQ, rhs ); + return *this; +} + +inline LLSimdScalar LLSimdScalar::getAbs() const +{ + static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; + return _mm_and_ps( mQ, *reinterpret_cast(F_ABS_MASK_4A)); +} + +inline F32 LLSimdScalar::getF32() const +{ + F32 ret; + _mm_store_ss(&ret, mQ); + return ret; +} diff --git a/indra/llmath/lltreenode.h b/indra/llmath/lltreenode.h index ee9836241..ada1f0075 100644 --- a/indra/llmath/lltreenode.h +++ b/indra/llmath/lltreenode.h @@ -34,6 +34,8 @@ #include "stdtypes.h" #include "xform.h" +#include "llpointer.h" +#include "llrefcount.h" #include template class LLTreeNode; diff --git a/indra/llmath/llv4math.h b/indra/llmath/llv4math.h index 9a493b267..5b180b3d7 100644 --- a/indra/llmath/llv4math.h +++ b/indra/llmath/llv4math.h @@ -52,8 +52,6 @@ // // Sorry the code is such a mess. JC -#include "llpreprocessor.h" - //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // LLV4MATH - GNUC diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp new file mode 100644 index 000000000..b66b7a707 --- /dev/null +++ b/indra/llmath/llvector4a.cpp @@ -0,0 +1,222 @@ +/** + * @file llvector4a.cpp + * @brief SIMD vector implementation + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llmath.h" +#include "llquantize.h" + +extern const LLQuad F_ZERO_4A = { 0, 0, 0, 0 }; +extern const LLQuad F_APPROXIMATELY_ZERO_4A = { + F_APPROXIMATELY_ZERO, + F_APPROXIMATELY_ZERO, + F_APPROXIMATELY_ZERO, + F_APPROXIMATELY_ZERO +}; + +extern const LLVector4a LL_V4A_ZERO = reinterpret_cast ( F_ZERO_4A ); +extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast ( F_APPROXIMATELY_ZERO_4A ); + +/*static */void LLVector4a::memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes) +{ + assert(src != NULL); + assert(dst != NULL); + assert(bytes > 0); + assert((bytes % sizeof(F32))== 0); + + F32* end = dst + (bytes / sizeof(F32) ); + + if (bytes > 64) + { + F32* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst); + + //at least 64 (16*4) bytes before the end of the destination, switch to 16 byte copies + F32* end_64 = end-16; + + _mm_prefetch((char*)begin_64, _MM_HINT_NTA); + _mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA); + _mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA); + _mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA); + + while (dst < begin_64) + { + copy4a(dst, src); + dst += 4; + src += 4; + } + + while (dst < end_64) + { + _mm_prefetch((char*)src + 512, _MM_HINT_NTA); + _mm_prefetch((char*)dst + 512, _MM_HINT_NTA); + copy4a(dst, src); + copy4a(dst+4, src+4); + copy4a(dst+8, src+8); + copy4a(dst+12, src+12); + + dst += 16; + src += 16; + } + } + + while (dst < end) + { + copy4a(dst, src); + dst += 4; + src += 4; + } +} + +void LLVector4a::setRotated( const LLRotation& rot, const LLVector4a& vec ) +{ + const LLVector4a col0 = rot.getColumn(0); + const LLVector4a col1 = rot.getColumn(1); + const LLVector4a col2 = rot.getColumn(2); + + LLVector4a result = _mm_load_ss( vec.getF32ptr() ); + result.splat<0>( result ); + result.mul( col0 ); + + { + LLVector4a yyyy = _mm_load_ss( vec.getF32ptr() + 1 ); + yyyy.splat<0>( yyyy ); + yyyy.mul( col1 ); + result.add( yyyy ); + } + + { + LLVector4a zzzz = _mm_load_ss( vec.getF32ptr() + 2 ); + zzzz.splat<0>( zzzz ); + zzzz.mul( col2 ); + result.add( zzzz ); + } + + *this = result; +} + +void LLVector4a::setRotated( const LLQuaternion2& quat, const LLVector4a& vec ) +{ + const LLVector4a& quatVec = quat.getVector4a(); + LLVector4a temp; temp.setCross3(quatVec, vec); + temp.add( temp ); + + const LLVector4a realPart( quatVec.getScalarAt<3>() ); + LLVector4a tempTimesReal; tempTimesReal.setMul( temp, realPart ); + + mQ = vec; + add( tempTimesReal ); + + LLVector4a imagCrossTemp; imagCrossTemp.setCross3( quatVec, temp ); + add(imagCrossTemp); +} + +void LLVector4a::quantize8( const LLVector4a& low, const LLVector4a& high ) +{ + LLVector4a val(mQ); + LLVector4a delta; delta.setSub( high, low ); + + { + val.clamp(low, high); + val.sub(low); + + // 8-bit quantization means we can do with just 12 bits of reciprocal accuracy + const LLVector4a oneOverDelta = _mm_rcp_ps(delta.mQ); +// { +// static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; +// LLVector4a two; two.load4a( F_TWO_4A ); +// +// // Here we use _mm_rcp_ps plus one round of newton-raphson +// // We wish to find 'x' such that x = 1/delta +// // As a first approximation, we take x0 = _mm_rcp_ps(delta) +// // Then x1 = 2 * x0 - a * x0^2 or x1 = x0 * ( 2 - a * x0 ) +// // See Intel AP-803 http://ompf.org/!/Intel_application_note_AP-803.pdf +// const LLVector4a recipApprox = _mm_rcp_ps(delta.mQ); +// oneOverDelta.setMul( delta, recipApprox ); +// oneOverDelta.setSub( two, oneOverDelta ); +// oneOverDelta.mul( recipApprox ); +// } + + val.mul(oneOverDelta); + val.mul(*reinterpret_cast(F_U8MAX_4A)); + } + + val = _mm_cvtepi32_ps(_mm_cvtps_epi32( val.mQ )); + + { + val.mul(*reinterpret_cast(F_OOU8MAX_4A)); + val.mul(delta); + val.add(low); + } + + { + LLVector4a maxError; maxError.setMul(delta, *reinterpret_cast(F_OOU8MAX_4A)); + LLVector4a absVal; absVal.setAbs( val ); + setSelectWithMask( absVal.lessThan( maxError ), F_ZERO_4A, val ); + } +} + +void LLVector4a::quantize16( const LLVector4a& low, const LLVector4a& high ) +{ + LLVector4a val(mQ); + LLVector4a delta; delta.setSub( high, low ); + + { + val.clamp(low, high); + val.sub(low); + + // 16-bit quantization means we need a round of Newton-Raphson + LLVector4a oneOverDelta; + { + static LL_ALIGN_16( const F32 F_TWO_4A[4] ) = { 2.f, 2.f, 2.f, 2.f }; + LLVector4a two; two.load4a( F_TWO_4A ); + + // Here we use _mm_rcp_ps plus one round of newton-raphson + // We wish to find 'x' such that x = 1/delta + // As a first approximation, we take x0 = _mm_rcp_ps(delta) + // Then x1 = 2 * x0 - a * x0^2 or x1 = x0 * ( 2 - a * x0 ) + // See Intel AP-803 http://ompf.org/!/Intel_application_note_AP-803.pdf + const LLVector4a recipApprox = _mm_rcp_ps(delta.mQ); + oneOverDelta.setMul( delta, recipApprox ); + oneOverDelta.setSub( two, oneOverDelta ); + oneOverDelta.mul( recipApprox ); + } + + val.mul(oneOverDelta); + val.mul(*reinterpret_cast(F_U16MAX_4A)); + } + + val = _mm_cvtepi32_ps(_mm_cvtps_epi32( val.mQ )); + + { + val.mul(*reinterpret_cast(F_OOU16MAX_4A)); + val.mul(delta); + val.add(low); + } + + { + LLVector4a maxError; maxError.setMul(delta, *reinterpret_cast(F_OOU16MAX_4A)); + LLVector4a absVal; absVal.setAbs( val ); + setSelectWithMask( absVal.lessThan( maxError ), F_ZERO_4A, val ); + } +} diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h new file mode 100644 index 000000000..596082509 --- /dev/null +++ b/indra/llmath/llvector4a.h @@ -0,0 +1,324 @@ +/** + * @file llvector4a.h + * @brief LLVector4a class header file - memory aligned and vectorized 4 component vector + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLVECTOR4A_H +#define LL_LLVECTOR4A_H + + +class LLRotation; + +#include +#include "llpreprocessor.h" + +/////////////////////////////////// +// FIRST TIME USERS PLEASE READ +////////////////////////////////// +// This is just the beginning of LLVector4a. There are many more useful functions +// yet to be implemented. For example, setNeg to negate a vector, rotate() to apply +// a matrix rotation, various functions to manipulate only the X, Y, and Z elements +// and many others (including a whole variety of accessors). So if you don't see a +// function here that you need, please contact Falcon or someone else with SSE +// experience (Richard, I think, has some and davep has a little as of the time +// of this writing, July 08, 2010) about getting it implemented before you resort to +// LLVector3/LLVector4. +///////////////////////////////// + +class LLVector4a +{ +public: + + /////////////////////////////////// + // STATIC METHODS + /////////////////////////////////// + + // Call initClass() at startup to avoid 15,000+ cycle penalties from denormalized numbers + static void initClass() + { + _MM_SET_FLUSH_ZERO_MODE(_MM_FLUSH_ZERO_ON); + _MM_SET_ROUNDING_MODE(_MM_ROUND_NEAREST); + } + + // Return a vector of all zeros + static inline const LLVector4a& getZero() + { + extern const LLVector4a LL_V4A_ZERO; + return LL_V4A_ZERO; + } + + // Return a vector of all epsilon, where epsilon is a small float suitable for approximate equality checks + static inline const LLVector4a& getEpsilon() + { + extern const LLVector4a LL_V4A_EPSILON; + return LL_V4A_EPSILON; + } + + // Copy 16 bytes from src to dst. Source and destination must be 16-byte aligned + static inline void copy4a(F32* dst, const F32* src) + { + _mm_store_ps(dst, _mm_load_ps(src)); + } + + // Copy words 16-byte blocks from src to dst. Source and destination must not overlap. + static void memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes); + + //////////////////////////////////// + // CONSTRUCTORS + //////////////////////////////////// + + LLVector4a() + { //DO NOT INITIALIZE -- The overhead is completely unnecessary + } + + LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f) + { + set(x,y,z,w); + } + + LLVector4a(F32 x) + { + splat(x); + } + + LLVector4a(const LLSimdScalar& x) + { + splat(x); + } + + LLVector4a(LLQuad q) + { + mQ = q; + } + + //////////////////////////////////// + // LOAD/STORE + //////////////////////////////////// + + // Load from 16-byte aligned src array (preferred method of loading) + inline void load4a(const F32* src); + + // Load from unaligned src array (NB: Significantly slower than load4a) + inline void loadua(const F32* src); + + // Load only three floats beginning at address 'src'. Slowest method. + inline void load3(const F32* src); + + // Store to a 16-byte aligned memory address + inline void store4a(F32* dst) const; + + //////////////////////////////////// + // BASIC GET/SET + //////////////////////////////////// + + // Return a "this" as an F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) + inline F32* getF32ptr(); + + // Return a "this" as a const F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) + inline const F32* const getF32ptr() const; + + // Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates + // the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead + inline F32 operator[](const S32 idx) const; + + // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. + inline LLSimdScalar getScalarAt(const S32 idx) const; + + // Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. + template LL_FORCE_INLINE LLSimdScalar getScalarAt() const; + + // Set to an x, y, z and optional w provided + inline void set(F32 x, F32 y, F32 z, F32 w = 0.f); + + // Set to all zeros. This is preferred to using ::getZero() + inline void clear(); + + // Set all elements to 'x' + inline void splat(const F32 x); + + // Set all elements to 'x' + inline void splat(const LLSimdScalar& x); + + // Set all 4 elements to element N of src, with N known at compile time + template void splat(const LLVector4a& src); + + // Set all 4 elements to element i of v, with i NOT known at compile time + inline void splat(const LLVector4a& v, U32 i); + + // Select bits from sourceIfTrue and sourceIfFalse according to bits in mask + inline void setSelectWithMask( const LLVector4Logical& mask, const LLVector4a& sourceIfTrue, const LLVector4a& sourceIfFalse ); + + //////////////////////////////////// + // ALGEBRAIC + //////////////////////////////////// + + // Set this to the element-wise (a + b) + inline void setAdd(const LLVector4a& a, const LLVector4a& b); + + // Set this to element-wise (a - b) + inline void setSub(const LLVector4a& a, const LLVector4a& b); + + // Set this to element-wise multiply (a * b) + inline void setMul(const LLVector4a& a, const LLVector4a& b); + + // Set this to element-wise quotient (a / b) + inline void setDiv(const LLVector4a& a, const LLVector4a& b); + + // Set this to the element-wise absolute value of src + inline void setAbs(const LLVector4a& src); + + // Add to each component in this vector the corresponding component in rhs + inline void add(const LLVector4a& rhs); + + // Subtract from each component in this vector the corresponding component in rhs + inline void sub(const LLVector4a& rhs); + + // Multiply each component in this vector by the corresponding component in rhs + inline void mul(const LLVector4a& rhs); + + // Divide each component in this vector by the corresponding component in rhs + inline void div(const LLVector4a& rhs); + + // Multiply this vector by x in a scalar fashion + inline void mul(const F32 x); + + // Set this to (a x b) (geometric cross-product) + inline void setCross3(const LLVector4a& a, const LLVector4a& b); + + // Set all elements to the dot product of the x, y, and z elements in a and b + inline void setAllDot3(const LLVector4a& a, const LLVector4a& b); + + // Set all elements to the dot product of the x, y, z, and w elements in a and b + inline void setAllDot4(const LLVector4a& a, const LLVector4a& b); + + // Return the 3D dot product of this vector and b + inline LLSimdScalar dot3(const LLVector4a& b) const; + + // Return the 4D dot product of this vector and b + inline LLSimdScalar dot4(const LLVector4a& b) const; + + // Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed + // Note that this does not consider zero length vectors! + inline void normalize3(); + + // Same as normalize3() but with respect to all 4 components + inline void normalize4(); + + // Same as normalize3(), but returns length as a SIMD scalar + inline LLSimdScalar normalize3withLength(); + + // Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed + // Note that this does not consider zero length vectors! + inline void normalize3fast(); + + // Return true if this vector is normalized with respect to x,y,z up to tolerance + inline LLBool32 isNormalized3( F32 tolerance = 1e-3 ) const; + + // Return true if this vector is normalized with respect to all components up to tolerance + inline LLBool32 isNormalized4( F32 tolerance = 1e-3 ) const; + + // Set all elements to the length of vector 'v' + inline void setAllLength3( const LLVector4a& v ); + + // Get this vector's length + inline LLSimdScalar getLength3() const; + + // Set the components of this vector to the minimum of the corresponding components of lhs and rhs + inline void setMin(const LLVector4a& lhs, const LLVector4a& rhs); + + // Set the components of this vector to the maximum of the corresponding components of lhs and rhs + inline void setMax(const LLVector4a& lhs, const LLVector4a& rhs); + + // Clamps this vector to be within the component-wise range low to high (inclusive) + inline void clamp( const LLVector4a& low, const LLVector4a& high ); + + // Set this to (c * lhs) + rhs * ( 1 - c) + inline void setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c); + + // Return true (nonzero) if x, y, z (and w for Finite4) are all finite floats + inline LLBool32 isFinite3() const; + inline LLBool32 isFinite4() const; + + // Set this vector to 'vec' rotated by the LLRotation or LLQuaternion2 provided + void setRotated( const LLRotation& rot, const LLVector4a& vec ); + void setRotated( const class LLQuaternion2& quat, const LLVector4a& vec ); + + // Set this vector to 'vec' rotated by the INVERSE of the LLRotation or LLQuaternion2 provided + inline void setRotatedInv( const LLRotation& rot, const LLVector4a& vec ); + inline void setRotatedInv( const class LLQuaternion2& quat, const LLVector4a& vec ); + + // Quantize this vector to 8 or 16 bit precision + void quantize8( const LLVector4a& low, const LLVector4a& high ); + void quantize16( const LLVector4a& low, const LLVector4a& high ); + + //////////////////////////////////// + // LOGICAL + //////////////////////////////////// + // The functions in this section will compare the elements in this vector + // to those in rhs and return an LLVector4Logical with all bits set in elements + // where the comparison was true and all bits unset in elements where the comparison + // was false. See llvector4logica.h + //////////////////////////////////// + // WARNING: Other than equals3 and equals4, these functions do NOT account + // for floating point tolerance. You should include the appropriate tolerance + // in the inputs. + //////////////////////////////////// + + inline LLVector4Logical greaterThan(const LLVector4a& rhs) const; + + inline LLVector4Logical lessThan(const LLVector4a& rhs) const; + + inline LLVector4Logical greaterEqual(const LLVector4a& rhs) const; + + inline LLVector4Logical lessEqual(const LLVector4a& rhs) const; + + inline LLVector4Logical equal(const LLVector4a& rhs) const; + + // Returns true if this and rhs are componentwise equal up to the specified absolute tolerance + inline bool equals4(const LLVector4a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + + inline bool equals3(const LLVector4a& rhs, F32 tolerance = F_APPROXIMATELY_ZERO ) const; + + //////////////////////////////////// + // OPERATORS + //////////////////////////////////// + + // Do NOT add aditional operators without consulting someone with SSE experience + inline const LLVector4a& operator= ( const LLVector4a& rhs ); + + inline const LLVector4a& operator= ( const LLQuad& rhs ); + + inline operator LLQuad() const; + +private: + LLQuad mQ; +}; + +inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p) +{ + min.setMin(min, p); + max.setMax(max, p); +} + +#endif diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl new file mode 100644 index 000000000..7ad22a563 --- /dev/null +++ b/indra/llmath/llvector4a.inl @@ -0,0 +1,593 @@ +/** + * @file llvector4a.inl + * @brief LLVector4a inline function implementations + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +//////////////////////////////////// +// LOAD/STORE +//////////////////////////////////// + +// Load from 16-byte aligned src array (preferred method of loading) +inline void LLVector4a::load4a(const F32* src) +{ + mQ = _mm_load_ps(src); +} + +// Load from unaligned src array (NB: Significantly slower than load4a) +inline void LLVector4a::loadua(const F32* src) +{ + mQ = _mm_loadu_ps(src); +} + +// Load only three floats beginning at address 'src'. Slowest method. +inline void LLVector4a::load3(const F32* src) +{ + // mQ = { 0.f, src[2], src[1], src[0] } = { W, Z, Y, X } + // NB: This differs from the convention of { Z, Y, X, W } + mQ = _mm_set_ps(0.f, src[2], src[1], src[0]); +} + +// Store to a 16-byte aligned memory address +inline void LLVector4a::store4a(F32* dst) const +{ + _mm_store_ps(dst, mQ); +} + +//////////////////////////////////// +// BASIC GET/SET +//////////////////////////////////// + +// Return a "this" as an F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) +F32* LLVector4a::getF32ptr() +{ + return (F32*) &mQ; +} + +// Return a "this" as a const F32 pointer. Do not use unless you have a very good reason. (Not sure? Ask Falcon) +const F32* const LLVector4a::getF32ptr() const +{ + return (const F32* const) &mQ; +} + +// Read-only access a single float in this vector. Do not use in proximity to any function call that manipulates +// the data at the whole vector level or you will incur a substantial penalty. Consider using the splat functions instead +inline F32 LLVector4a::operator[](const S32 idx) const +{ + return ((F32*)&mQ)[idx]; +} + +// Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. +inline LLSimdScalar LLVector4a::getScalarAt(const S32 idx) const +{ + // Return appropriate LLQuad. It will be cast to LLSimdScalar automatically (should be effectively a nop) + switch (idx) + { + case 0: + return mQ; + case 1: + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(1, 1, 1, 1)); + case 2: + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(2, 2, 2, 2)); + case 3: + default: + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(3, 3, 3, 3)); + } +} + +// Prefer this method for read-only access to a single element. Prefer the templated version if the elem is known at compile time. +template LL_FORCE_INLINE LLSimdScalar LLVector4a::getScalarAt() const +{ + return _mm_shuffle_ps(mQ, mQ, _MM_SHUFFLE(N, N, N, N)); +} + +template<> LL_FORCE_INLINE LLSimdScalar LLVector4a::getScalarAt<0>() const +{ + return mQ; +} + +// Set to an x, y, z and optional w provided +inline void LLVector4a::set(F32 x, F32 y, F32 z, F32 w) +{ + mQ = _mm_set_ps(w, z, y, x); +} + +// Set to all zeros +inline void LLVector4a::clear() +{ + mQ = LLVector4a::getZero().mQ; +} + +inline void LLVector4a::splat(const F32 x) +{ + mQ = _mm_set1_ps(x); +} + +inline void LLVector4a::splat(const LLSimdScalar& x) +{ + mQ = _mm_shuffle_ps( x.getQuad(), x.getQuad(), _MM_SHUFFLE(0,0,0,0) ); +} + +// Set all 4 elements to element N of src, with N known at compile time +template void LLVector4a::splat(const LLVector4a& src) +{ + mQ = _mm_shuffle_ps(src.mQ, src.mQ, _MM_SHUFFLE(N, N, N, N) ); +} + +// Set all 4 elements to element i of v, with i NOT known at compile time +inline void LLVector4a::splat(const LLVector4a& v, U32 i) +{ + switch (i) + { + case 0: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(0, 0, 0, 0)); + break; + case 1: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(1, 1, 1, 1)); + break; + case 2: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(2, 2, 2, 2)); + break; + case 3: + mQ = _mm_shuffle_ps(v.mQ, v.mQ, _MM_SHUFFLE(3, 3, 3, 3)); + break; + } +} + +// Select bits from sourceIfTrue and sourceIfFalse according to bits in mask +inline void LLVector4a::setSelectWithMask( const LLVector4Logical& mask, const LLVector4a& sourceIfTrue, const LLVector4a& sourceIfFalse ) +{ + // ((( sourceIfTrue ^ sourceIfFalse ) & mask) ^ sourceIfFalse ) + // E.g., sourceIfFalse = 1010b, sourceIfTrue = 0101b, mask = 1100b + // (sourceIfTrue ^ sourceIfFalse) = 1111b --> & mask = 1100b --> ^ sourceIfFalse = 0110b, + // as expected (01 from sourceIfTrue, 10 from sourceIfFalse) + // Courtesy of Mark++, http://markplusplus.wordpress.com/2007/03/14/fast-sse-select-operation/ + mQ = _mm_xor_ps( sourceIfFalse, _mm_and_ps( mask, _mm_xor_ps( sourceIfTrue, sourceIfFalse ) ) ); +} + +//////////////////////////////////// +// ALGEBRAIC +//////////////////////////////////// + +// Set this to the element-wise (a + b) +inline void LLVector4a::setAdd(const LLVector4a& a, const LLVector4a& b) +{ + mQ = _mm_add_ps(a.mQ, b.mQ); +} + +// Set this to element-wise (a - b) +inline void LLVector4a::setSub(const LLVector4a& a, const LLVector4a& b) +{ + mQ = _mm_sub_ps(a.mQ, b.mQ); +} + +// Set this to element-wise multiply (a * b) +inline void LLVector4a::setMul(const LLVector4a& a, const LLVector4a& b) +{ + mQ = _mm_mul_ps(a.mQ, b.mQ); +} + +// Set this to element-wise quotient (a / b) +inline void LLVector4a::setDiv(const LLVector4a& a, const LLVector4a& b) +{ + mQ = _mm_div_ps( a.mQ, b.mQ ); +} + +// Set this to the element-wise absolute value of src +inline void LLVector4a::setAbs(const LLVector4a& src) +{ + static const LL_ALIGN_16(U32 F_ABS_MASK_4A[4]) = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; + mQ = _mm_and_ps(src.mQ, *reinterpret_cast(F_ABS_MASK_4A)); +} + +// Add to each component in this vector the corresponding component in rhs +inline void LLVector4a::add(const LLVector4a& rhs) +{ + mQ = _mm_add_ps(mQ, rhs.mQ); +} + +// Subtract from each component in this vector the corresponding component in rhs +inline void LLVector4a::sub(const LLVector4a& rhs) +{ + mQ = _mm_sub_ps(mQ, rhs.mQ); +} + +// Multiply each component in this vector by the corresponding component in rhs +inline void LLVector4a::mul(const LLVector4a& rhs) +{ + mQ = _mm_mul_ps(mQ, rhs.mQ); +} + +// Divide each component in this vector by the corresponding component in rhs +inline void LLVector4a::div(const LLVector4a& rhs) +{ + // TODO: Check accuracy, maybe add divFast + mQ = _mm_div_ps(mQ, rhs.mQ); +} + +// Multiply this vector by x in a scalar fashion +inline void LLVector4a::mul(const F32 x) +{ + LLVector4a t; + t.splat(x); + + mQ = _mm_mul_ps(mQ, t.mQ); +} + +// Set this to (a x b) (geometric cross-product) +inline void LLVector4a::setCross3(const LLVector4a& a, const LLVector4a& b) +{ + // Vectors are stored in memory in w, z, y, x order from high to low + // Set vector1 = { a[W], a[X], a[Z], a[Y] } + const LLQuad vector1 = _mm_shuffle_ps( a.mQ, a.mQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // Set vector2 = { b[W], b[Y], b[X], b[Z] } + const LLQuad vector2 = _mm_shuffle_ps( b.mQ, b.mQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } + mQ = _mm_mul_ps( vector1, vector2 ); + // vector3 = { a[W], a[Y], a[X], a[Z] } + const LLQuad vector3 = _mm_shuffle_ps( a.mQ, a.mQ, _MM_SHUFFLE( 3, 1, 0, 2 )); + // vector4 = { b[W], b[X], b[Z], b[Y] } + const LLQuad vector4 = _mm_shuffle_ps( b.mQ, b.mQ, _MM_SHUFFLE( 3, 0, 2, 1 )); + // mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } + mQ = _mm_sub_ps( mQ, _mm_mul_ps( vector3, vector4 )); +} + +/* This function works, but may be slightly slower than the one below on older machines + inline void LLVector4a::setAllDot3(const LLVector4a& a, const LLVector4a& b) + { + // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } + const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); + // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } + const LLQuad wzxy = _mm_shuffle_ps( ab, ab, _MM_SHUFFLE(3, 2, 0, 1 )); + // xPlusY = { 2*a[W]*b[W], 2 * a[Z] * b[Z], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusY = _mm_add_ps(ab, wzxy); + // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusYSplat = _mm_movelh_ps(xPlusY, xPlusY); + // zSplat = { a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z] } + const LLQuad zSplat = _mm_shuffle_ps( ab, ab, _MM_SHUFFLE( 2, 2, 2, 2 )); + // mQ = { a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } + mQ = _mm_add_ps(zSplat, xPlusYSplat); + }*/ + +// Set all elements to the dot product of the x, y, and z elements in a and b +inline void LLVector4a::setAllDot3(const LLVector4a& a, const LLVector4a& b) +{ + // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } + const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); + // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } + const __m128i wzxy = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE(3, 2, 0, 1 )); + // xPlusY = { 2*a[W]*b[W], 2 * a[Z] * b[Z], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusY = _mm_add_ps(ab, _mm_castsi128_ps(wzxy)); + // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusYSplat = _mm_movelh_ps(xPlusY, xPlusY); + // zSplat = { a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z], a[Z]*b[Z] } + const __m128i zSplat = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE( 2, 2, 2, 2 )); + // mQ = { a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } + mQ = _mm_add_ps(_mm_castsi128_ps(zSplat), xPlusYSplat); +} + +// Set all elements to the dot product of the x, y, z, and w elements in a and b +inline void LLVector4a::setAllDot4(const LLVector4a& a, const LLVector4a& b) +{ + // ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] } + const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ ); + // yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] } + const __m128i zwxy = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE(2, 3, 0, 1 )); + // zPlusWandXplusY = { a[W]*b[W] + a[Z]*b[Z], a[Z] * b[Z] + a[W]*b[W], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad zPlusWandXplusY = _mm_add_ps(ab, _mm_castsi128_ps(zwxy)); + // xPlusYSplat = { a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y], a[Y]*b[Y] + a[X] * b[X], a[X] * b[X] + a[Y] * b[Y] } + const LLQuad xPlusYSplat = _mm_movelh_ps(zPlusWandXplusY, zPlusWandXplusY); + const LLQuad zPlusWSplat = _mm_movehl_ps(zPlusWandXplusY, zPlusWandXplusY); + + // mQ = { a[W]*b[W] + a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same } + mQ = _mm_add_ps(xPlusYSplat, zPlusWSplat); +} + +// Return the 3D dot product of this vector and b +inline LLSimdScalar LLVector4a::dot3(const LLVector4a& b) const +{ + const LLQuad ab = _mm_mul_ps( mQ, b.mQ ); + const LLQuad splatY = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(1, 1, 1, 1) ) ); + const LLQuad splatZ = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(2, 2, 2, 2) ) ); + const LLQuad xPlusY = _mm_add_ps( ab, splatY ); + return _mm_add_ps( xPlusY, splatZ ); +} + +// Return the 4D dot product of this vector and b +inline LLSimdScalar LLVector4a::dot4(const LLVector4a& b) const +{ + // ab = { w, z, y, x } + const LLQuad ab = _mm_mul_ps( mQ, b.mQ ); + // upperProdsInLowerElems = { y, x, y, x } + const LLQuad upperProdsInLowerElems = _mm_movehl_ps( ab, ab ); + // sumOfPairs = { w+y, z+x, 2y, 2x } + const LLQuad sumOfPairs = _mm_add_ps( upperProdsInLowerElems, ab ); + // shuffled = { z+x, z+x, z+x, z+x } + const LLQuad shuffled = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( sumOfPairs ), _MM_SHUFFLE(1, 1, 1, 1) ) ); + return _mm_add_ss( sumOfPairs, shuffled ); +} + +// Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed +// Note that this does not consider zero length vectors! +inline void LLVector4a::normalize3() +{ + // lenSqrd = a dot a + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } + const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; + static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; + // Now we do one round of Newton-Raphson approximation to get full accuracy + // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) + // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) + // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 + // = 0.5 * w * (3 - a*w^2) + // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula + // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] + const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); + const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); + const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); + const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); + mQ = _mm_mul_ps( mQ, nrApprox ); +} + +// Normalize this vector with respect to all components. Accurate to 22 bites of precision. +// Note that this does not consider zero length vectors! +inline void LLVector4a::normalize4() +{ + // lenSqrd = a dot a + LLVector4a lenSqrd; lenSqrd.setAllDot4( *this, *this ); + // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } + const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; + static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; + // Now we do one round of Newton-Raphson approximation to get full accuracy + // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) + // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) + // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 + // = 0.5 * w * (3 - a*w^2) + // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula + // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] + const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); + const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); + const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); + const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); + mQ = _mm_mul_ps( mQ, nrApprox ); +} + +// Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed +// Note that this does not consider zero length vectors! +inline LLSimdScalar LLVector4a::normalize3withLength() +{ + // lenSqrd = a dot a + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + // rsqrt = approximate reciprocal square (i.e., { ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2, ~1/len(a)^2 } + const LLQuad rsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + static const LLQuad half = { 0.5f, 0.5f, 0.5f, 0.5f }; + static const LLQuad three = {3.f, 3.f, 3.f, 3.f }; + // Now we do one round of Newton-Raphson approximation to get full accuracy + // According to the Newton-Raphson method, given a first 'w' for the root of f(x) = 1/x^2 - a (i.e., x = 1/sqrt(a)) + // the next better approximation w[i+1] = w - f(w)/f'(w) = w - (1/w^2 - a)/(-2*w^(-3)) + // w[i+1] = w + 0.5 * (1/w^2 - a) * w^3 = w + 0.5 * (w - a*w^3) = 1.5 * w - 0.5 * a * w^3 + // = 0.5 * w * (3 - a*w^2) + // Our first approx is w = rsqrt. We need out = a * w[i+1] (this is the input vector 'a', not the 'a' from the above formula + // which is actually lenSqrd). So out = a * [0.5*rsqrt * (3 - lenSqrd*rsqrt*rsqrt)] + const LLQuad AtimesRsqrt = _mm_mul_ps( lenSqrd.mQ, rsqrt ); + const LLQuad AtimesRsqrtTimesRsqrt = _mm_mul_ps( AtimesRsqrt, rsqrt ); + const LLQuad threeMinusAtimesRsqrtTimesRsqrt = _mm_sub_ps(three, AtimesRsqrtTimesRsqrt ); + const LLQuad nrApprox = _mm_mul_ps(half, _mm_mul_ps(rsqrt, threeMinusAtimesRsqrtTimesRsqrt)); + mQ = _mm_mul_ps( mQ, nrApprox ); + return _mm_sqrt_ss(lenSqrd); +} + +// Normalize this vector with respect to the x, y, and z components only. Accurate only to 10-12 bits of precision. W component is destroyed +// Note that this does not consider zero length vectors! +inline void LLVector4a::normalize3fast() +{ + LLVector4a lenSqrd; lenSqrd.setAllDot3( *this, *this ); + const LLQuad approxRsqrt = _mm_rsqrt_ps(lenSqrd.mQ); + mQ = _mm_mul_ps( mQ, approxRsqrt ); +} + +// Return true if this vector is normalized with respect to x,y,z up to tolerance +inline LLBool32 LLVector4a::isNormalized3( F32 tolerance ) const +{ + static LL_ALIGN_16(const U32 ones[4]) = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; + LLSimdScalar tol = _mm_load_ss( &tolerance ); + tol = _mm_mul_ss( tol, tol ); + LLVector4a lenSquared; lenSquared.setAllDot3( *this, *this ); + lenSquared.sub( *reinterpret_cast(ones) ); + lenSquared.setAbs(lenSquared); + return _mm_comile_ss( lenSquared, tol ); +} + +// Return true if this vector is normalized with respect to all components up to tolerance +inline LLBool32 LLVector4a::isNormalized4( F32 tolerance ) const +{ + static LL_ALIGN_16(const U32 ones[4]) = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 }; + LLSimdScalar tol = _mm_load_ss( &tolerance ); + tol = _mm_mul_ss( tol, tol ); + LLVector4a lenSquared; lenSquared.setAllDot4( *this, *this ); + lenSquared.sub( *reinterpret_cast(ones) ); + lenSquared.setAbs(lenSquared); + return _mm_comile_ss( lenSquared, tol ); +} + +// Set all elements to the length of vector 'v' +inline void LLVector4a::setAllLength3( const LLVector4a& v ) +{ + LLVector4a lenSqrd; + lenSqrd.setAllDot3(v, v); + + mQ = _mm_sqrt_ps(lenSqrd.mQ); +} + +// Get this vector's length +inline LLSimdScalar LLVector4a::getLength3() const +{ + return _mm_sqrt_ss( dot3( (const LLVector4a)mQ ) ); +} + +// Set the components of this vector to the minimum of the corresponding components of lhs and rhs +inline void LLVector4a::setMin(const LLVector4a& lhs, const LLVector4a& rhs) +{ + mQ = _mm_min_ps(lhs.mQ, rhs.mQ); +} + +// Set the components of this vector to the maximum of the corresponding components of lhs and rhs +inline void LLVector4a::setMax(const LLVector4a& lhs, const LLVector4a& rhs) +{ + mQ = _mm_max_ps(lhs.mQ, rhs.mQ); +} + +// Set this to (c * lhs) + rhs * ( 1 - c) +inline void LLVector4a::setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c) +{ + LLVector4a a = lhs; + a.mul(c); + + LLVector4a b = rhs; + b.mul(1.f-c); + + setAdd(a, b); +} + +inline LLBool32 LLVector4a::isFinite3() const +{ + static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; + const __m128i nanOrInfMaskV = *reinterpret_cast (nanOrInfMask); + const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); + const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); + return !equalityCheck.areAnySet( LLVector4Logical::MASK_XYZ ); +} + +inline LLBool32 LLVector4a::isFinite4() const +{ + static LL_ALIGN_16(const U32 nanOrInfMask[4]) = { 0x7f800000, 0x7f800000, 0x7f800000, 0x7f800000 }; + const __m128i nanOrInfMaskV = *reinterpret_cast (nanOrInfMask); + const __m128i maskResult = _mm_and_si128( _mm_castps_si128(mQ), nanOrInfMaskV ); + const LLVector4Logical equalityCheck = _mm_castsi128_ps(_mm_cmpeq_epi32( maskResult, nanOrInfMaskV )); + return !equalityCheck.areAnySet( LLVector4Logical::MASK_XYZW ); +} + +inline void LLVector4a::setRotatedInv( const LLRotation& rot, const LLVector4a& vec ) +{ + LLRotation inv; inv.setTranspose( rot ); + setRotated( inv, vec ); +} + +inline void LLVector4a::setRotatedInv( const LLQuaternion2& quat, const LLVector4a& vec ) +{ + LLQuaternion2 invRot; invRot.setConjugate( quat ); + setRotated(invRot, vec); +} + +inline void LLVector4a::clamp( const LLVector4a& low, const LLVector4a& high ) +{ + const LLVector4Logical highMask = greaterThan( high ); + const LLVector4Logical lowMask = lessThan( low ); + + setSelectWithMask( highMask, high, *this ); + setSelectWithMask( lowMask, low, *this ); +} + + +//////////////////////////////////// +// LOGICAL +//////////////////////////////////// +// The functions in this section will compare the elements in this vector +// to those in rhs and return an LLVector4Logical with all bits set in elements +// where the comparison was true and all bits unset in elements where the comparison +// was false. See llvector4logica.h +//////////////////////////////////// +// WARNING: Other than equals3 and equals4, these functions do NOT account +// for floating point tolerance. You should include the appropriate tolerance +// in the inputs. +//////////////////////////////////// + +inline LLVector4Logical LLVector4a::greaterThan(const LLVector4a& rhs) const +{ + return _mm_cmpgt_ps(mQ, rhs.mQ); +} + +inline LLVector4Logical LLVector4a::lessThan(const LLVector4a& rhs) const +{ + return _mm_cmplt_ps(mQ, rhs.mQ); +} + +inline LLVector4Logical LLVector4a::greaterEqual(const LLVector4a& rhs) const +{ + return _mm_cmpge_ps(mQ, rhs.mQ); +} + +inline LLVector4Logical LLVector4a::lessEqual(const LLVector4a& rhs) const +{ + return _mm_cmple_ps(mQ, rhs.mQ); +} + +inline LLVector4Logical LLVector4a::equal(const LLVector4a& rhs) const +{ + return _mm_cmpeq_ps(mQ, rhs.mQ); +} + +// Returns true if this and rhs are componentwise equal up to the specified absolute tolerance +inline bool LLVector4a::equals4(const LLVector4a& rhs, F32 tolerance ) const +{ + LLVector4a diff; diff.setSub( *this, rhs ); + diff.setAbs( diff ); + const LLQuad tol = _mm_set1_ps( tolerance ); + const LLQuad cmp = _mm_cmplt_ps( diff, tol ); + return (_mm_movemask_ps( cmp ) & LLVector4Logical::MASK_XYZW) == LLVector4Logical::MASK_XYZW; +} + +inline bool LLVector4a::equals3(const LLVector4a& rhs, F32 tolerance ) const +{ + LLVector4a diff; diff.setSub( *this, rhs ); + diff.setAbs( diff ); + const LLQuad tol = _mm_set1_ps( tolerance ); + const LLQuad t = _mm_cmplt_ps( diff, tol ); + return (_mm_movemask_ps( t ) & LLVector4Logical::MASK_XYZ) == LLVector4Logical::MASK_XYZ; + +} + +//////////////////////////////////// +// OPERATORS +//////////////////////////////////// + +// Do NOT add aditional operators without consulting someone with SSE experience +inline const LLVector4a& LLVector4a::operator= ( const LLVector4a& rhs ) +{ + mQ = rhs.mQ; + return *this; +} + +inline const LLVector4a& LLVector4a::operator= ( const LLQuad& rhs ) +{ + mQ = rhs; + return *this; +} + +inline LLVector4a::operator LLQuad() const +{ + return mQ; +} diff --git a/indra/llmath/llvector4logical.h b/indra/llmath/llvector4logical.h new file mode 100644 index 000000000..dd66b09d4 --- /dev/null +++ b/indra/llmath/llvector4logical.h @@ -0,0 +1,124 @@ +/** + * @file llvector4logical.h + * @brief LLVector4Logical class header file - Companion class to LLVector4a for logical and bit-twiddling operations + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_VECTOR4LOGICAL_H +#define LL_VECTOR4LOGICAL_H + + +//////////////////////////// +// LLVector4Logical +//////////////////////////// +// This class is incomplete. If you need additional functionality, +// for example setting/unsetting particular elements or performing +// other boolean operations, feel free to implement. If you need +// assistance in determining the most optimal implementation, +// contact someone with SSE experience (Falcon, Richard, Davep, e.g.) +//////////////////////////// + +static LL_ALIGN_16(const U32 S_V4LOGICAL_MASK_TABLE[4*4]) = +{ + 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0xFFFFFFFF, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF +}; + +class LLVector4Logical +{ +public: + + enum { + MASK_X = 1, + MASK_Y = 1 << 1, + MASK_Z = 1 << 2, + MASK_W = 1 << 3, + MASK_XYZ = MASK_X | MASK_Y | MASK_Z, + MASK_XYZW = MASK_XYZ | MASK_W + }; + + // Empty default ctor + LLVector4Logical() {} + + LLVector4Logical( const LLQuad& quad ) + { + mQ = quad; + } + + // Create and return a mask consisting of the lowest order bit of each element + inline U32 getGatheredBits() const + { + return _mm_movemask_ps(mQ); + }; + + // Invert this mask + inline LLVector4Logical& invert() + { + static const LL_ALIGN_16(U32 allOnes[4]) = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; + mQ = _mm_andnot_ps( mQ, *(LLQuad*)(allOnes) ); + return *this; + } + + inline LLBool32 areAllSet( U32 mask ) const + { + return ( getGatheredBits() & mask) == mask; + } + + inline LLBool32 areAllSet() const + { + return areAllSet( MASK_XYZW ); + } + + inline LLBool32 areAnySet( U32 mask ) const + { + return getGatheredBits() & mask; + } + + inline LLBool32 areAnySet() const + { + return areAnySet( MASK_XYZW ); + } + + inline operator LLQuad() const + { + return mQ; + } + + inline void clear() + { + mQ = _mm_setzero_ps(); + } + + template void setElement() + { + mQ = _mm_or_ps( mQ, *reinterpret_cast(S_V4LOGICAL_MASK_TABLE + 4*N) ); + } + +private: + + LLQuad mQ; +}; + +#endif //LL_VECTOR4ALOGICAL_H diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 8285a8175..abe1cd402 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -30,6 +30,7 @@ */ #include "linden_common.h" +#include "llmemory.h" #include "llmath.h" #include @@ -43,9 +44,16 @@ #include "v4math.h" #include "m4math.h" #include "m3math.h" +#include "llmatrix3a.h" +#include "lloctree.h" #include "lldarray.h" #include "llvolume.h" +#include "llvolumeoctree.h" #include "llstl.h" +#include "llsdserialize.h" +#include "llvector4a.h" +#include "llmatrix4a.h" +#include "lltimer.h" #define DEBUG_SILHOUETTE_BINORMALS 0 #define DEBUG_SILHOUETTE_NORMALS 0 // TomY: Use this to display normals using the silhouette @@ -86,6 +94,19 @@ const F32 SKEW_MAX = 0.95f; const F32 SCULPT_MIN_AREA = 0.002f; const S32 SCULPT_MIN_AREA_DETAIL = 1; +extern BOOL gDebugGL; + +void assert_aligned(void* ptr, uintptr_t alignment) +{ +#if 0 + uintptr_t t = (uintptr_t) ptr; + if (t%alignment != 0) + { + llerrs << "Alignment check failed." << llendl; + } +#endif +} + BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm) { LLVector3 test = (pt2-pt1)%(pt3-pt2); @@ -135,102 +156,230 @@ BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* cent // and returns the intersection point along dir in intersection_t. // Moller-Trumbore algorithm -BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, - F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided) +BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t) +{ + + /* find vectors for two edges sharing vert0 */ + LLVector4a edge1; + edge1.setSub(vert1, vert0); + + LLVector4a edge2; + edge2.setSub(vert2, vert0); + + /* begin calculating determinant - also used to calculate U parameter */ + LLVector4a pvec; + pvec.setCross3(dir, edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + LLVector4a det; + det.setAllDot3(edge1, pvec); + + if (det.greaterEqual(LLVector4a::getEpsilon()).getGatheredBits() & 0x7) + { + /* calculate distance from vert0 to ray origin */ + LLVector4a tvec; + tvec.setSub(orig, vert0); + + /* calculate U parameter and test bounds */ + LLVector4a u; + u.setAllDot3(tvec,pvec); + + if ((u.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7) && + (u.lessEqual(det).getGatheredBits() & 0x7)) + { + /* prepare to test V parameter */ + LLVector4a qvec; + qvec.setCross3(tvec, edge1); + + /* calculate V parameter and test bounds */ + LLVector4a v; + v.setAllDot3(dir, qvec); + + + //if (!(v < 0.f || u + v > det)) + + LLVector4a sum_uv; + sum_uv.setAdd(u, v); + + S32 v_gequal = v.greaterEqual(LLVector4a::getZero()).getGatheredBits() & 0x7; + S32 sum_lequal = sum_uv.lessEqual(det).getGatheredBits() & 0x7; + + if (v_gequal && sum_lequal) + { + /* calculate t, scale parameters, ray intersects triangle */ + LLVector4a t; + t.setAllDot3(edge2,qvec); + + t.div(det); + u.div(det); + v.div(det); + + intersection_a = u[0]; + intersection_b = v[0]; + intersection_t = t[0]; + return TRUE; + } + } + } + + return FALSE; +} + +BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t) { F32 u, v, t; /* find vectors for two edges sharing vert0 */ - LLVector3 edge1 = vert1 - vert0; + LLVector4a edge1; + edge1.setSub(vert1, vert0); - LLVector3 edge2 = vert2 - vert0;; + + LLVector4a edge2; + edge2.setSub(vert2, vert0); /* begin calculating determinant - also used to calculate U parameter */ - LLVector3 pvec = dir % edge2; - + LLVector4a pvec; + pvec.setCross3(dir, edge2); + /* if determinant is near zero, ray lies in plane of triangle */ - F32 det = edge1 * pvec; + F32 det = edge1.dot3(pvec).getF32(); - if (!two_sided) + + if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) { - if (det < F_APPROXIMATELY_ZERO) - { - return FALSE; - } - - /* calculate distance from vert0 to ray origin */ - LLVector3 tvec = orig - vert0; - - /* calculate U parameter and test bounds */ - u = tvec * pvec; - - if (u < 0.f || u > det) - { - return FALSE; - } - - /* prepare to test V parameter */ - LLVector3 qvec = tvec % edge1; - - /* calculate V parameter and test bounds */ - v = dir * qvec; - if (v < 0.f || u + v > det) - { - return FALSE; - } - - /* calculate t, scale parameters, ray intersects triangle */ - t = edge2 * qvec; - F32 inv_det = 1.0 / det; - t *= inv_det; - u *= inv_det; - v *= inv_det; + return FALSE; } + + F32 inv_det = 1.f / det; + + /* calculate distance from vert0 to ray origin */ + LLVector4a tvec; + tvec.setSub(orig, vert0); - else // two sided - { - if (det > -F_APPROXIMATELY_ZERO && det < F_APPROXIMATELY_ZERO) - { - return FALSE; - } - F32 inv_det = 1.0 / det; - - /* calculate distance from vert0 to ray origin */ - LLVector3 tvec = orig - vert0; - - /* calculate U parameter and test bounds */ - u = (tvec * pvec) * inv_det; - if (u < 0.f || u > 1.f) - { - return FALSE; - } - - /* prepare to test V parameter */ - LLVector3 qvec = tvec - edge1; - - /* calculate V parameter and test bounds */ - v = (dir * qvec) * inv_det; - - if (v < 0.f || u + v > 1.f) - { - return FALSE; - } - - /* calculate t, ray intersects triangle */ - t = (edge2 * qvec) * inv_det; + /* calculate U parameter and test bounds */ + u = (tvec.dot3(pvec).getF32()) * inv_det; + if (u < 0.f || u > 1.f) + { + return FALSE; } + + /* prepare to test V parameter */ + tvec.sub(edge1); + + /* calculate V parameter and test bounds */ + v = (dir.dot3(tvec).getF32()) * inv_det; - if (intersection_a != NULL) - *intersection_a = u; - if (intersection_b != NULL) - *intersection_b = v; - if (intersection_t != NULL) - *intersection_t = t; + if (v < 0.f || u + v > 1.f) + { + return FALSE; + } + + /* calculate t, ray intersects triangle */ + t = (edge2.dot3(tvec).getF32()) * inv_det; + + intersection_a = u; + intersection_b = v; + intersection_t = t; return TRUE; } +//helper for non-aligned vectors +BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided) +{ + LLVector4a vert0a, vert1a, vert2a, origa, dira; + vert0a.load3(vert0.mV); + vert1a.load3(vert1.mV); + vert2a.load3(vert2.mV); + origa.load3(orig.mV); + dira.load3(dir.mV); + + if (two_sided) + { + return LLTriangleRayIntersectTwoSided(vert0a, vert1a, vert2a, origa, dira, + intersection_a, intersection_b, intersection_t); + } + else + { + return LLTriangleRayIntersect(vert0a, vert1a, vert2a, origa, dira, + intersection_a, intersection_b, intersection_t); + } +} + +class LLVolumeOctreeRebound : public LLOctreeTravelerDepthFirst +{ +public: + const LLVolumeFace* mFace; + + LLVolumeOctreeRebound(const LLVolumeFace* face) + { + mFace = face; + } + + virtual void visit(const LLOctreeNode* branch) + { //this is a depth first traversal, so it's safe to assum all children have complete + //bounding data + + LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); + + LLVector4a& min = node->mExtents[0]; + LLVector4a& max = node->mExtents[1]; + + if (!branch->getData().empty()) + { //node has data, find AABB that binds data set + const LLVolumeTriangle* tri = *(branch->getData().begin()); + + //initialize min/max to first available vertex + min = *(tri->mV[0]); + max = *(tri->mV[0]); + + for (LLOctreeNode::const_element_iter iter = + branch->getData().begin(); iter != branch->getData().end(); ++iter) + { //for each triangle in node + + //stretch by triangles in node + tri = *iter; + + min.setMin(min, *tri->mV[0]); + min.setMin(min, *tri->mV[1]); + min.setMin(min, *tri->mV[2]); + + max.setMax(max, *tri->mV[0]); + max.setMax(max, *tri->mV[1]); + max.setMax(max, *tri->mV[2]); + } + } + else if (!branch->getChildren().empty()) + { //no data, but child nodes exist + LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(0)->getListener(0); + + //initialize min/max to extents of first child + min = child->mExtents[0]; + max = child->mExtents[1]; + } + else + { + llerrs << "Empty leaf" << llendl; + } + + for (U32 i = 0; i < branch->getChildCount(); ++i) + { //stretch by child extents + LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); + min.setMin(min, child->mExtents[0]); + max.setMax(max, child->mExtents[1]); + } + + node->mBounds[0].setAdd(min, max); + node->mBounds[0].mul(0.5f); + + node->mBounds[1].setSub(max,min); + node->mBounds[1].mul(0.5f); + } +}; //------------------------------------------------------------------- // statics @@ -269,6 +418,70 @@ LLProfile::Face* LLProfile::addFace(S32 i, S32 count, F32 scaleU, S16 faceID, BO return face; } +//static +S32 LLProfile::getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset, F32 bevel, F32 ang_scale, S32 split) +{ // this is basically LLProfile::genNGon stripped down to only the operations that influence the number of points + LLMemType m1(LLMemType::MTYPE_VOLUME); + S32 np = 0; + + // Generate an n-sided "circular" path. + // 0 is (1,0), and we go counter-clockwise along a circular path from there. + F32 t, t_step, t_first, t_fraction; + + F32 begin = params.getBegin(); + F32 end = params.getEnd(); + + t_step = 1.0f / sides; + + t_first = floor(begin * sides) / (F32)sides; + + // pt1 is the first point on the fractional face. + // Starting t and ang values for the first face + t = t_first; + + // Increment to the next point. + // pt2 is the end point on the fractional face + t += t_step; + + t_fraction = (begin - t_first)*sides; + + // Only use if it's not almost exactly on an edge. + if (t_fraction < 0.9999f) + { + np++; + } + + // There's lots of potential here for floating point error to generate unneeded extra points - DJS 04/05/02 + while (t < end) + { + // Iterate through all the integer steps of t. + np++; + + t += t_step; + } + + t_fraction = (end - (t - t_step))*sides; + + // Find the fraction that we need to add to the end point. + t_fraction = (end - (t - t_step))*sides; + if (t_fraction > 0.0001f) + { + np++; + } + + // If we're sliced, the profile is open. + if ((end - begin)*ang_scale < 0.99f) + { + if (params.getHollow() <= 0) + { + // put center point if not hollow. + np++; + } + } + + return np; +} + // What is the bevel parameter used for? - DJS 04/05/02 // Bevel parameter is currently unused but presumedly would support // filleted and chamfered corners @@ -525,6 +738,117 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3 return face; } +//static +S32 LLProfile::getNumPoints(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, + BOOL is_sculpted, S32 sculpt_size) +{ // this is basically LLProfile::generate stripped down to only operations that influence the number of points + LLMemType m1(LLMemType::MTYPE_VOLUME); + + if (detail < MIN_LOD) + { + detail = MIN_LOD; + } + + // Generate the face data + F32 hollow = params.getHollow(); + + S32 np = 0; + + switch (params.getCurveType() & LL_PCODE_PROFILE_MASK) + { + case LL_PCODE_PROFILE_SQUARE: + { + np = getNumNGonPoints(params, 4,-0.375, 0, 1, split); + + if (hollow) + { + np *= 2; + } + } + break; + case LL_PCODE_PROFILE_ISOTRI: + case LL_PCODE_PROFILE_RIGHTTRI: + case LL_PCODE_PROFILE_EQUALTRI: + { + np = getNumNGonPoints(params, 3,0, 0, 1, split); + + if (hollow) + { + np *= 2; + } + } + break; + case LL_PCODE_PROFILE_CIRCLE: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + F32 circle_detail = MIN_DETAIL_FACES * detail; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides, + // so that corners line up. + circle_detail = llceil(circle_detail / 4.0f) * 4.0f; + } + } + + S32 sides = (S32)circle_detail; + + if (is_sculpted) + sides = sculpt_size; + + np = getNumNGonPoints(params, sides); + + if (hollow) + { + np *= 2; + } + } + break; + case LL_PCODE_PROFILE_CIRCLE_HALF: + { + // If this has a square hollow, we should adjust the + // number of faces a bit so that the geometry lines up. + U8 hole_type=0; + // Number of faces is cut in half because it's only a half-circle. + F32 circle_detail = MIN_DETAIL_FACES * detail * 0.5f; + if (hollow) + { + hole_type = params.getCurveType() & LL_PCODE_HOLE_MASK; + if (hole_type == LL_PCODE_HOLE_SQUARE) + { + // Snap to the next multiple of four sides (div 2), + // so that corners line up. + circle_detail = llceil(circle_detail / 2.0f) * 2.0f; + } + } + np = getNumNGonPoints(params, llfloor(circle_detail), 0.5f, 0.f, 0.5f); + + if (hollow) + { + np *= 2; + } + + // Special case for openness of sphere + if ((params.getEnd() - params.getBegin()) < 1.f) + { + } + else if (!hollow) + { + np++; + } + } + break; + default: + break; + }; + + + return np; +} BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detail, S32 split, @@ -986,6 +1310,32 @@ LLPath::~LLPath() { } +S32 LLPath::getNumNGonPoints(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) +{ //this is basically LLPath::genNGon stripped down to only operations that influence the number of points added + S32 ret = 0; + + F32 step= 1.0f / sides; + F32 t = params.getBegin(); + ret = 1; + + t+=step; + + // Snap to a quantized parameter, so that cut does not + // affect most sample points. + t = ((S32)(t * sides)) / (F32)sides; + + // Run through the non-cut dependent points. + while (t < params.getEnd()) + { + ret++; + t+=step; + } + + ret++; + + return ret; +} + void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 end_scale, F32 twist_scale) { // Generates a circular path, starting at (1, 0, 0), counterclockwise along the xz plane. @@ -1163,6 +1513,56 @@ const LLVector2 LLPathParams::getEndScale() const return end_scale; } +S32 LLPath::getNumPoints(const LLPathParams& params, F32 detail) +{ // this is basically LLPath::generate stripped down to only the operations that influence the number of points + LLMemType m1(LLMemType::MTYPE_VOLUME); + + if (detail < MIN_LOD) + { + detail = MIN_LOD; + } + + S32 np = 2; // hardcode for line + + // Is this 0xf0 mask really necessary? DK 03/02/05 + + switch (params.getCurveType() & 0xf0) + { + default: + case LL_PCODE_PATH_LINE: + { + // Take the begin/end twist into account for detail. + np = llfloor(fabs(params.getTwistBegin() - params.getTwist()) * 3.5f * (detail-0.5f)) + 2; + } + break; + + case LL_PCODE_PATH_CIRCLE: + { + // Increase the detail as the revolutions and twist increase. + F32 twist_mag = fabs(params.getTwistBegin() - params.getTwist()); + + S32 sides = (S32)llfloor(llfloor((MIN_DETAIL_FACES * detail + twist_mag * 3.5f * (detail-0.5f))) * params.getRevolutions()); + + np = sides; + } + break; + + case LL_PCODE_PATH_CIRCLE2: + { + //genNGon(params, llfloor(MIN_DETAIL_FACES * detail), 4.f, 0.f); + np = getNumNGonPoints(params, llfloor(MIN_DETAIL_FACES * detail)); + } + break; + + case LL_PCODE_PATH_TEST: + + np = 5; + break; + }; + + return np; +} + BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split, BOOL is_sculpted, S32 sculpt_size) { @@ -1679,6 +2079,14 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge mFaceMask = 0x0; mDetail = detail; mSculptLevel = -2; +#if MESH_ENABLED + mIsMeshAssetLoaded = FALSE; + mLODScaleBias.setVec(1,1,1); + mHullPoints = NULL; + mHullIndices = NULL; + mNumHullPoints = 0; + mNumHullIndices = 0; +#endif //MESH_ENABLED // set defaults if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) @@ -1695,7 +2103,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge generate(); - if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE) + if (mParams.getSculptID().isNull() && mParams.getSculptType() == LL_SCULPT_TYPE_NONE || mParams.getSculptType() == LL_SCULPT_TYPE_MESH) { createVolumeFaces(); } @@ -1730,6 +2138,13 @@ LLVolume::~LLVolume() mPathp = NULL; mProfilep = NULL; mVolumeFaces.clear(); + +#if MESH_ENABLED + ll_aligned_free_16(mHullPoints); + mHullPoints = NULL; + ll_aligned_free_16(mHullIndices); + mHullIndices = NULL; +#endif //MESH_ENABLED } BOOL LLVolume::generate() @@ -1846,6 +2261,488 @@ BOOL LLVolume::generate() return FALSE; } +void LLVolumeFace::VertexData::init() +{ + if (!mData) + { + mData = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*2); + } +} + +LLVolumeFace::VertexData::VertexData() +{ + mData = NULL; + init(); +} + +LLVolumeFace::VertexData::VertexData(const VertexData& rhs) +{ + mData = NULL; + *this = rhs; +} + +const LLVolumeFace::VertexData& LLVolumeFace::VertexData::operator=(const LLVolumeFace::VertexData& rhs) +{ + if (this != &rhs) + { + init(); + LLVector4a::memcpyNonAliased16((F32*) mData, (F32*) rhs.mData, 2*sizeof(LLVector4a)); + mTexCoord = rhs.mTexCoord; + } + return *this; +} + +LLVolumeFace::VertexData::~VertexData() +{ + ll_aligned_free_16(mData); + mData = NULL; +} + +LLVector4a& LLVolumeFace::VertexData::getPosition() +{ + return mData[POSITION]; +} + +LLVector4a& LLVolumeFace::VertexData::getNormal() +{ + return mData[NORMAL]; +} + +const LLVector4a& LLVolumeFace::VertexData::getPosition() const +{ + return mData[POSITION]; +} + +const LLVector4a& LLVolumeFace::VertexData::getNormal() const +{ + return mData[NORMAL]; +} + + +void LLVolumeFace::VertexData::setPosition(const LLVector4a& pos) +{ + mData[POSITION] = pos; +} + +void LLVolumeFace::VertexData::setNormal(const LLVector4a& norm) +{ + mData[NORMAL] = norm; +} + +bool LLVolumeFace::VertexData::operator<(const LLVolumeFace::VertexData& rhs)const +{ + const F32* lp = this->getPosition().getF32ptr(); + const F32* rp = rhs.getPosition().getF32ptr(); + + if (lp[0] != rp[0]) + { + return lp[0] < rp[0]; + } + + if (rp[1] != lp[1]) + { + return lp[1] < rp[1]; + } + + if (rp[2] != lp[2]) + { + return lp[2] < rp[2]; + } + + lp = getNormal().getF32ptr(); + rp = rhs.getNormal().getF32ptr(); + + if (lp[0] != rp[0]) + { + return lp[0] < rp[0]; + } + + if (rp[1] != lp[1]) + { + return lp[1] < rp[1]; + } + + if (rp[2] != lp[2]) + { + return lp[2] < rp[2]; + } + + if (mTexCoord.mV[0] != rhs.mTexCoord.mV[0]) + { + return mTexCoord.mV[0] < rhs.mTexCoord.mV[0]; + } + + return mTexCoord.mV[1] < rhs.mTexCoord.mV[1]; +} + +bool LLVolumeFace::VertexData::operator==(const LLVolumeFace::VertexData& rhs)const +{ + return mData[POSITION].equals3(rhs.getPosition()) && + mData[NORMAL].equals3(rhs.getNormal()) && + mTexCoord == rhs.mTexCoord; +} + +bool LLVolumeFace::VertexData::compareNormal(const LLVolumeFace::VertexData& rhs, F32 angle_cutoff) const +{ + bool retval = false; + + const F32 epsilon = 0.00001f; + + if (rhs.mData[POSITION].equals3(mData[POSITION], epsilon) && + fabs(rhs.mTexCoord[0]-mTexCoord[0]) < epsilon && + fabs(rhs.mTexCoord[1]-mTexCoord[1]) < epsilon) + { + if (angle_cutoff > 1.f) + { + retval = (mData[NORMAL].equals3(rhs.mData[NORMAL], epsilon)); + } + else + { + F32 cur_angle = rhs.mData[NORMAL].dot3(mData[NORMAL]).getF32(); + retval = cur_angle > angle_cutoff; + } + } + + return retval; +} + +#if MESH_ENABLED +bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size) +{ + //input stream is now pointing at a zlib compressed block of LLSD + //decompress block + LLSD mdl; + if (!unzip_llsd(mdl, is, size)) + { + LL_DEBUGS("MeshStreaming") << "Failed to unzip LLSD blob for LoD, will probably fetch from sim again." << llendl; + return false; + } + + { + U32 face_count = mdl.size(); + + if (face_count == 0) + { //no faces unpacked, treat as failed decode + llwarns << "found no faces!" << llendl; + return false; + } + + mVolumeFaces.resize(face_count); + + for (U32 i = 0; i < face_count; ++i) + { + LLVolumeFace& face = mVolumeFaces[i]; + + if (mdl[i].has("NoGeometry")) + { //face has no geometry, continue + face.resizeIndices(3); + face.resizeVertices(1); + memset(face.mPositions, 0, sizeof(LLVector4a)); + memset(face.mNormals, 0, sizeof(LLVector4a)); + memset(face.mTexCoords, 0, sizeof(LLVector2)); + memset(face.mIndices, 0, sizeof(U16)*3); + continue; + } + + LLSD::Binary pos = mdl[i]["Position"]; + LLSD::Binary norm = mdl[i]["Normal"]; + LLSD::Binary tc = mdl[i]["TexCoord0"]; + LLSD::Binary idx = mdl[i]["TriangleList"]; + + + + //copy out indices + face.resizeIndices(idx.size()/2); + + if (idx.empty() || face.mNumIndices < 3) + { //why is there an empty index list? + llwarns <<"Empty face present!" << llendl; + continue; + } + + U16* indices = (U16*) &(idx[0]); + U32 count = idx.size()/2; + for (U32 j = 0; j < count; ++j) + { + face.mIndices[j] = indices[j]; + } + + //copy out vertices + U32 num_verts = pos.size()/(3*2); + face.resizeVertices(num_verts); + + LLVector3 minp; + LLVector3 maxp; + LLVector2 min_tc; + LLVector2 max_tc; + + minp.setValue(mdl[i]["PositionDomain"]["Min"]); + maxp.setValue(mdl[i]["PositionDomain"]["Max"]); + LLVector4a min_pos, max_pos; + min_pos.load3(minp.mV); + max_pos.load3(maxp.mV); + + min_tc.setValue(mdl[i]["TexCoord0Domain"]["Min"]); + max_tc.setValue(mdl[i]["TexCoord0Domain"]["Max"]); + + LLVector4a pos_range; + pos_range.setSub(max_pos, min_pos); + LLVector2 tc_range2 = max_tc - min_tc; + LLVector4a tc_range; + tc_range.set(tc_range2[0], tc_range2[1], tc_range2[0], tc_range2[1]); + LLVector4a min_tc4(min_tc[0], min_tc[1], min_tc[0], min_tc[1]); + + LLVector4a* pos_out = face.mPositions; + LLVector4a* norm_out = face.mNormals; + LLVector4a* tc_out = (LLVector4a*) face.mTexCoords; + + { + U16* v = (U16*) &(pos[0]); + for (U32 j = 0; j < num_verts; ++j) + { + pos_out->set((F32) v[0], (F32) v[1], (F32) v[2]); + pos_out->div(65535.f); + pos_out->mul(pos_range); + pos_out->add(min_pos); + pos_out++; + v += 3; + } + + } + + { + if (!norm.empty()) + { + U16* n = (U16*) &(norm[0]); + for (U32 j = 0; j < num_verts; ++j) + { + norm_out->set((F32) n[0], (F32) n[1], (F32) n[2]); + norm_out->div(65535.f); + norm_out->mul(2.f); + norm_out->sub(1.f); + norm_out++; + n += 3; + } + } + else + { + memset(norm_out, 0, sizeof(LLVector4a)*num_verts); + } + } + + { + if (!tc.empty()) + { + U16* t = (U16*) &(tc[0]); + for (U32 j = 0; j < num_verts; j+=2) + { + if (j < num_verts-1) + { + tc_out->set((F32) t[0], (F32) t[1], (F32) t[2], (F32) t[3]); + } + else + { + tc_out->set((F32) t[0], (F32) t[1], 0.f, 0.f); + } + + t += 4; + + tc_out->div(65535.f); + tc_out->mul(tc_range); + tc_out->add(min_tc4); + + tc_out++; + } + } + else + { + memset(tc_out, 0, sizeof(LLVector2)*num_verts); + } + } + + if (mdl[i].has("Weights")) + { + face.allocateWeights(num_verts); + + LLSD::Binary weights = mdl[i]["Weights"]; + + U32 idx = 0; + + U32 cur_vertex = 0; + while (idx < weights.size() && cur_vertex < num_verts) + { + const U8 END_INFLUENCES = 0xFF; + U8 joint = weights[idx++]; + + U32 cur_influence = 0; + LLVector4 wght(0,0,0,0); + + while (joint != END_INFLUENCES && idx < weights.size()) + { + U16 influence = weights[idx++]; + influence |= ((U16) weights[idx++] << 8); + + F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f); + wght.mV[cur_influence++] = (F32) joint + w; + + if (cur_influence >= 4) + { + joint = END_INFLUENCES; + } + else + { + joint = weights[idx++]; + } + } + + face.mWeights[cur_vertex].loadua(wght.mV); + + cur_vertex++; + } + + if (cur_vertex != num_verts || idx != weights.size()) + { + llwarns << "Vertex weight count does not match vertex count!" << llendl; + } + + } + + // modifier flags? + bool do_mirror = (mParams.getSculptType() & LL_SCULPT_FLAG_MIRROR); + bool do_invert = (mParams.getSculptType() &LL_SCULPT_FLAG_INVERT); + + + // translate to actions: + bool do_reflect_x = false; + bool do_reverse_triangles = false; + bool do_invert_normals = false; + + if (do_mirror) + { + do_reflect_x = true; + do_reverse_triangles = !do_reverse_triangles; + } + + if (do_invert) + { + do_invert_normals = true; + do_reverse_triangles = !do_reverse_triangles; + } + + // now do the work + + if (do_reflect_x) + { + LLVector4a* p = (LLVector4a*) face.mPositions; + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (S32 i = 0; i < face.mNumVertices; i++) + { + p[i].mul(-1.0f); + n[i].mul(-1.0f); + } + } + + if (do_invert_normals) + { + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (S32 i = 0; i < face.mNumVertices; i++) + { + n[i].mul(-1.0f); + } + } + + if (do_reverse_triangles) + { + for (U32 j = 0; j < (U32)face.mNumIndices; j += 3) + { + // swap the 2nd and 3rd index + S32 swap = face.mIndices[j+1]; + face.mIndices[j+1] = face.mIndices[j+2]; + face.mIndices[j+2] = swap; + } + } + + //calculate bounding box + LLVector4a& min = face.mExtents[0]; + LLVector4a& max = face.mExtents[1]; + + if (face.mNumVertices < 3) + { //empty face, use a dummy 1cm (at 1m scale) bounding box + min.splat(-0.005f); + max.splat(0.005f); + } + else + { + min = max = face.mPositions[0]; + + for (S32 i = 1; i < face.mNumVertices; ++i) + { + min.setMin(min, face.mPositions[i]); + max.setMax(max, face.mPositions[i]); + } + + if (face.mTexCoords) + { + LLVector2& min_tc = face.mTexCoordExtents[0]; + LLVector2& max_tc = face.mTexCoordExtents[1]; + + min_tc = face.mTexCoords[0]; + max_tc = face.mTexCoords[0]; + + for (U32 j = 1; j < (U32)face.mNumVertices; ++j) + { + update_min_max(min_tc, max_tc, face.mTexCoords[j]); + } + } + else + { + face.mTexCoordExtents[0].set(0,0); + face.mTexCoordExtents[1].set(1,1); + } + } + } + } + + mSculptLevel = 0; // success! + + cacheOptimize(); + + return true; +} + + +BOOL LLVolume::isMeshAssetLoaded() +{ + return mIsMeshAssetLoaded; +} + +void LLVolume::setMeshAssetLoaded(BOOL loaded) +{ + mIsMeshAssetLoaded = loaded; +} + +void LLVolume::copyVolumeFaces(const LLVolume* volume) +{ + mVolumeFaces = volume->mVolumeFaces; + mSculptLevel = 0; +} + +void LLVolume::cacheOptimize() +{ + for (S32 i = 0; i < (S32)mVolumeFaces.size(); ++i) + { + mVolumeFaces[i].cacheOptimize(); + } +} +#endif //MESH_ENABLED + +S32 LLVolume::getNumFaces() const +{ + return mIsMeshAssetLoaded ? getNumVolumeFaces() : (S32)mProfilep->mFaces.size(); +} + void LLVolume::createVolumeFaces() { @@ -2199,7 +3096,7 @@ void sculpt_calc_mesh_resolution(U16 width, U16 height, U8 type, F32 detail, S32 ratio = (F32) width / (F32) height; - s = (S32)fsqrtf(((F32)vertices / ratio)); + s = (S32)(F32) sqrt(((F32)vertices / ratio)); s = llmax(s, 4); // no degenerate sizes, please t = vertices / s; @@ -2258,7 +3155,11 @@ void LLVolume::sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, // don't test lowest LOD to support legacy content DEV-33670 if (mDetail > SCULPT_MIN_AREA_DETAIL) { - if (sculptGetSurfaceArea() < SCULPT_MIN_AREA) + F32 area = sculptGetSurfaceArea(); + + const F32 SCULPT_MAX_AREA = 384.f; + + if (area < SCULPT_MIN_AREA || area > SCULPT_MAX_AREA) { data_is_empty = TRUE; } @@ -2299,6 +3200,18 @@ BOOL LLVolume::isFlat(S32 face) } +bool LLVolumeParams::isSculpt() const +{ + return mSculptID.notNull(); +} + +#if MESH_ENABLED +bool LLVolumeParams::isMeshSculpt() const +{ + return isSculpt() && ((mSculptType & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH); +} +#endif //MESH_ENABLED + bool LLVolumeParams::operator==(const LLVolumeParams ¶ms) const { return ( (getPathParams() == params.getPathParams()) && @@ -2332,7 +3245,6 @@ bool LLVolumeParams::operator<(const LLVolumeParams ¶ms) const return mSculptID < params.mSculptID; } - return mSculptType < params.mSculptType; @@ -3333,6 +4245,23 @@ S32 *LLVolume::getTriangleIndices(U32 &num_indices) const return index; } +void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts) +{ //attempt to approximate the number of triangles that will result from generating a volume LoD set for the + //supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost + F32 detail[] = {1.f, 1.5f, 2.5f, 4.f}; + for (S32 i = 0; i < 4; i++) + { + S32 count = 0; + S32 path_points = LLPath::getNumPoints(params.getPathParams(), detail[i]); + S32 profile_points = LLProfile::getNumPoints(params.getProfileParams(), false, detail[i]); + + count = (profile_points-1)*2*(path_points-1); + count += profile_points*2; + + counts[i] = count; + } +} + S32 LLVolume::getNumTriangleIndices() const { BOOL profile_open = getProfile().isOpen(); @@ -3390,22 +4319,50 @@ S32 LLVolume::getNumTriangleIndices() const return count; } + +S32 LLVolume::getNumTriangles() const +{ + U32 triangle_count = 0; + + for (S32 i = 0; i < getNumVolumeFaces(); ++i) + { + triangle_count += getVolumeFace(i).mNumIndices/3; + } + + return triangle_count; +} + + //----------------------------------------------------------------------------- // generateSilhouetteVertices() //----------------------------------------------------------------------------- void LLVolume::generateSilhouetteVertices(std::vector &vertices, std::vector &normals, - std::vector &segments, - const LLVector3& obj_cam_vec, - const LLMatrix4& mat, - const LLMatrix3& norm_mat, + const LLVector3& obj_cam_vec_in, + const LLMatrix4& mat_in, + const LLMatrix3& norm_mat_in, S32 face_mask) { LLMemType m1(LLMemType::MTYPE_VOLUME); - + + LLMatrix4a mat; + mat.loadu(mat_in); + + LLMatrix4a norm_mat; + norm_mat.loadu(norm_mat_in); + + LLVector4a obj_cam_vec; + obj_cam_vec.load3(obj_cam_vec_in.mV); + vertices.clear(); normals.clear(); - segments.clear(); + +#if MESH_ENABLED + if ((mParams.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { + return; + } +#endif //MESH_ENABLED S32 cur_index = 0; //for each face @@ -3414,10 +4371,12 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, { const LLVolumeFace& face = *iter; - if (!(face_mask & (0x1 << cur_index++))) + if (!(face_mask & (0x1 << cur_index++)) || + face.mNumIndices == 0 || face.mEdge.empty()) { continue; } + if (face.mTypeMask & (LLVolumeFace::CAP_MASK)) { } @@ -3430,7 +4389,7 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, #if DEBUG_SILHOUETTE_EDGE_MAP //for each triangle - U32 count = face.mIndices.size(); + U32 count = face.mNumIndices; for (U32 j = 0; j < count/3; j++) { //get vertices S32 v1 = face.mIndices[j*3+0]; @@ -3438,9 +4397,9 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, S32 v3 = face.mIndices[j*3+2]; //get current face center - LLVector3 cCenter = (face.mVertices[v1].mPosition + - face.mVertices[v2].mPosition + - face.mVertices[v3].mPosition) / 3.0f; + LLVector3 cCenter = (face.mVertices[v1].getPosition() + + face.mVertices[v2].getPosition() + + face.mVertices[v3].getPosition()) / 3.0f; //for each edge for (S32 k = 0; k < 3; k++) { @@ -3458,9 +4417,9 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, v3 = face.mIndices[nIndex*3+2]; //get neighbor face center - LLVector3 nCenter = (face.mVertices[v1].mPosition + - face.mVertices[v2].mPosition + - face.mVertices[v3].mPosition) / 3.0f; + LLVector3 nCenter = (face.mVertices[v1].getPosition() + + face.mVertices[v2].getPosition() + + face.mVertices[v3].getPosition()) / 3.0f; //draw line vertices.push_back(cCenter); @@ -3483,18 +4442,16 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, #elif DEBUG_SILHOUETTE_NORMALS //for each vertex - for (U32 j = 0; j < face.mVertices.size(); j++) { - vertices.push_back(face.mVertices[j].mPosition); - vertices.push_back(face.mVertices[j].mPosition + face.mVertices[j].mNormal*0.1f); + for (U32 j = 0; j < face.mNumVertices; j++) { + vertices.push_back(face.mVertices[j].getPosition()); + vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].getNormal()*0.1f); normals.push_back(LLVector3(0,0,1)); normals.push_back(LLVector3(0,0,1)); - segments.push_back(vertices.size()); #if DEBUG_SILHOUETTE_BINORMALS - vertices.push_back(face.mVertices[j].mPosition); - vertices.push_back(face.mVertices[j].mPosition + face.mVertices[j].mBinormal*0.1f); + vertices.push_back(face.mVertices[j].getPosition()); + vertices.push_back(face.mVertices[j].getPosition() + face.mVertices[j].mBinormal*0.1f); normals.push_back(LLVector3(0,0,1)); normals.push_back(LLVector3(0,0,1)); - segments.push_back(vertices.size()); #endif } @@ -3509,26 +4466,36 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, //for each triangle std::vector fFacing; - vector_append(fFacing, face.mIndices.size()/3); - for (U32 j = 0; j < face.mIndices.size()/3; j++) + vector_append(fFacing, face.mNumIndices/3); + + LLVector4a* v = (LLVector4a*) face.mPositions; + LLVector4a* n = (LLVector4a*) face.mNormals; + + for (U32 j = 0; j < (U32)face.mNumIndices/3; j++) { //approximate normal S32 v1 = face.mIndices[j*3+0]; S32 v2 = face.mIndices[j*3+1]; S32 v3 = face.mIndices[j*3+2]; - LLVector3 norm = (face.mVertices[v1].mPosition - face.mVertices[v2].mPosition) % - (face.mVertices[v2].mPosition - face.mVertices[v3].mPosition); - - if (norm.magVecSquared() < 0.00000001f) + LLVector4a c1,c2; + c1.setSub(v[v1], v[v2]); + c2.setSub(v[v2], v[v3]); + + LLVector4a norm; + + norm.setCross3(c1, c2); + + if (norm.dot3(norm) < 0.00000001f) { fFacing[j] = AWAY | TOWARDS; } else { //get view vector - LLVector3 view = (obj_cam_vec-face.mVertices[v1].mPosition); - bool away = view * norm > 0.0f; + LLVector4a view; + view.setSub(obj_cam_vec, v[v1]); + bool away = view.dot3(norm) > 0.0f; if (away) { fFacing[j] = AWAY; @@ -3541,7 +4508,7 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, } //for each triangle - for (U32 j = 0; j < face.mIndices.size()/3; j++) + for (U32 j = 0; j < (U32)face.mNumIndices/3; j++) { if (fFacing[j] == (AWAY | TOWARDS)) { //this is a degenerate triangle @@ -3574,17 +4541,21 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, S32 v1 = face.mIndices[j*3+k]; S32 v2 = face.mIndices[j*3+((k+1)%3)]; - vertices.push_back(face.mVertices[v1].mPosition*mat); - LLVector3 norm1 = face.mVertices[v1].mNormal * norm_mat; - norm1.normVec(); - normals.push_back(norm1); + LLVector4a t; + mat.affineTransform(v[v1], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); - vertices.push_back(face.mVertices[v2].mPosition*mat); - LLVector3 norm2 = face.mVertices[v2].mNormal * norm_mat; - norm2.normVec(); - normals.push_back(norm2); + norm_mat.rotate(n[v1], t); - segments.push_back(vertices.size()); + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); + + mat.affineTransform(v[v2], t); + vertices.push_back(LLVector3(t[0], t[1], t[2])); + + norm_mat.rotate(n[v2], t); + t.normalize3fast(); + normals.push_back(LLVector3(t[0], t[1], t[2])); } } } @@ -3596,6 +4567,19 @@ void LLVolume::generateSilhouetteVertices(std::vector &vertices, S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) +{ + LLVector4a starta, enda; + starta.load3(start.mV); + enda.load3(end.mV); + + return lineSegmentIntersect(starta, enda, face, intersection, tex_coord, normal, bi_normal); + +} + + +S32 LLVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + S32 face, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) { S32 hit_face = -1; @@ -3613,16 +4597,23 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, end_face = face; } - LLVector3 dir = end - start; + LLVector4a dir; + dir.setSub(end, start); F32 closest_t = 2.f; // must be larger than 1 + end_face = llmin(end_face, getNumVolumeFaces()-1); + for (S32 i = start_face; i <= end_face; i++) { - const LLVolumeFace &face = getVolumeFace((U32)i); + LLVolumeFace &face = mVolumeFaces[i]; - LLVector3 box_center = (face.mExtents[0] + face.mExtents[1]) / 2.f; - LLVector3 box_size = face.mExtents[1] - face.mExtents[0]; + LLVector4a box_center; + box_center.setAdd(face.mExtents[0], face.mExtents[1]); + box_center.mul(0.5f); + + LLVector4a box_size; + box_size.setSub(face.mExtents[1], face.mExtents[0]); if (LLLineSegmentBoxIntersect(start, end, box_center, box_size)) { @@ -3630,56 +4621,19 @@ S32 LLVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, { genBinormals(i); } - - for (U32 tri = 0; tri < face.mIndices.size()/3; tri++) + + if (!face.mOctree) { - S32 index1 = face.mIndices[tri*3+0]; - S32 index2 = face.mIndices[tri*3+1]; - S32 index3 = face.mIndices[tri*3+2]; - - F32 a, b, t; + face.createOctree(); + } - if (LLTriangleRayIntersect(face.mVertices[index1].mPosition, - face.mVertices[index2].mPosition, - face.mVertices[index3].mPosition, - start, dir, &a, &b, &t, FALSE)) - { - if ((t >= 0.f) && // if hit is after start - (t <= 1.f) && // and before end - (t < closest_t)) // and this hit is closer - { - closest_t = t; - hit_face = i; + //LLVector4a* p = (LLVector4a*) face.mPositions; - if (intersection != NULL) - { - *intersection = start + dir * closest_t; - } - - if (tex_coord != NULL) + LLOctreeTriangleRayIntersect intersect(start, dir, &face, &closest_t, intersection, tex_coord, normal, bi_normal); + intersect.traverse(face.mOctree); + if (intersect.mHitFace) { - *tex_coord = ((1.f - a - b) * face.mVertices[index1].mTexCoord + - a * face.mVertices[index2].mTexCoord + - b * face.mVertices[index3].mTexCoord); - - } - - if (normal != NULL) - { - *normal = ((1.f - a - b) * face.mVertices[index1].mNormal + - a * face.mVertices[index2].mNormal + - b * face.mVertices[index3].mNormal); - } - - if (bi_normal != NULL) - { - *bi_normal = ((1.f - a - b) * face.mVertices[index1].mBinormal + - a * face.mVertices[index2].mBinormal + - b * face.mVertices[index3].mBinormal); - } - - } - } + hit_face = i; } } } @@ -4127,11 +5081,28 @@ BOOL LLVolumeParams::exportLegacyStream(std::ostream& output_stream) const return TRUE; } +LLSD LLVolumeParams::sculptAsLLSD() const +{ + LLSD sd = LLSD(); + sd["id"] = getSculptID(); + sd["type"] = getSculptType(); + + return sd; +} + +bool LLVolumeParams::sculptFromLLSD(LLSD& sd) +{ + setSculptID(sd["id"].asUUID(), (U8)sd["type"].asInteger()); + return true; +} + LLSD LLVolumeParams::asLLSD() const { LLSD sd = LLSD(); sd["path"] = mPathParams; sd["profile"] = mProfileParams; + sd["sculpt"] = sculptAsLLSD(); + return sd; } @@ -4139,6 +5110,8 @@ bool LLVolumeParams::fromLLSD(LLSD& sd) { mPathParams.fromLLSD(sd["path"]); mProfileParams.fromLLSD(sd["profile"]); + sculptFromLLSD(sd["sculpt"]); + return true; } @@ -4181,6 +5154,12 @@ const F32 MIN_CONCAVE_PATH_WEDGE = 0.111111f; // 1/9 unity // for collison purposes BOOL LLVolumeParams::isConvex() const { + if (!getSculptID().isNull()) + { + // can't determine, be safe and say no: + return FALSE; + } + F32 path_length = mPathParams.getEnd() - mPathParams.getBegin(); F32 hollow = mProfileParams.getHollow(); @@ -4421,9 +5400,172 @@ std::ostream& operator<<(std::ostream &s, const LLVolume *volumep) return s; } +LLVolumeFace::LLVolumeFace() : + mID(0), + mTypeMask(0), + mBeginS(0), + mBeginT(0), + mNumS(0), + mNumT(0), + mNumVertices(0), + mNumIndices(0), + mPositions(NULL), + mNormals(NULL), + mBinormals(NULL), + mTexCoords(NULL), + mIndices(NULL), +#if MESH_ENABLED + mWeights(NULL), +#endif //MESH_ENABLED + mOctree(NULL) +{ + mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); + mExtents[0].splat(-0.5f); + mExtents[1].splat(0.5f); + mCenter = mExtents+2; +} + +LLVolumeFace::LLVolumeFace(const LLVolumeFace& src) +: mID(0), + mTypeMask(0), + mBeginS(0), + mBeginT(0), + mNumS(0), + mNumT(0), + mNumVertices(0), + mNumIndices(0), + mPositions(NULL), + mNormals(NULL), + mBinormals(NULL), + mTexCoords(NULL), + mIndices(NULL), +#if MESH_ENABLED + mWeights(NULL), +#endif //MESH_ENABLED + mOctree(NULL) +{ + mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3); + mCenter = mExtents+2; + *this = src; +} + +LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src) +{ + if (&src == this) + { //self assignment, do nothing + return *this; + } + + mID = src.mID; + mTypeMask = src.mTypeMask; + mBeginS = src.mBeginS; + mBeginT = src.mBeginT; + mNumS = src.mNumS; + mNumT = src.mNumT; + + mExtents[0] = src.mExtents[0]; + mExtents[1] = src.mExtents[1]; + *mCenter = *src.mCenter; + + mNumVertices = 0; + mNumIndices = 0; + + freeData(); + + LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 3*sizeof(LLVector4a)); + + resizeVertices(src.mNumVertices); + resizeIndices(src.mNumIndices); + + if (mNumVertices) + { + S32 vert_size = mNumVertices*sizeof(LLVector4a); + S32 tc_size = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF; + + LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size); + LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size); + + if(src.mTexCoords) + { + LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size); + } + else + { + ll_aligned_free_16(mTexCoords) ; + mTexCoords = NULL ; + } + + + if (src.mBinormals) + { + allocateBinormals(src.mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) src.mBinormals, vert_size); + } + else + { + ll_aligned_free_16(mBinormals); + mBinormals = NULL; + } + +#if MESH_ENABLED + if (src.mWeights) + { + allocateWeights(src.mNumVertices); + LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size); + } + else + { + ll_aligned_free_16(mWeights); + mWeights = NULL; + } +#endif //MESH_ENABLED + } + if (mNumIndices) + { + S32 idx_size = (mNumIndices*sizeof(U16)+0xF) & ~0xF; + + LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size); + } + + //delete + return *this; +} + +LLVolumeFace::~LLVolumeFace() +{ + ll_aligned_free_16(mExtents); + mExtents = NULL; + + freeData(); +} + +void LLVolumeFace::freeData() +{ + ll_aligned_free_16(mPositions); + mPositions = NULL; + ll_aligned_free_16( mNormals); + mNormals = NULL; + ll_aligned_free_16(mTexCoords); + mTexCoords = NULL; + ll_aligned_free_16(mIndices); + mIndices = NULL; + ll_aligned_free_16(mBinormals); + mBinormals = NULL; +#if MESH_ENABLED + ll_aligned_free_16(mWeights); + mWeights = NULL; +#endif //MESH_ENABLED + + delete mOctree; + mOctree = NULL; +} BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) { + //tree for this face is no longer valid + delete mOctree; + mOctree = NULL; + BOOL ret = FALSE ; if (mTypeMask & CAP_MASK) { @@ -4444,25 +5586,24 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) mTexCoordExtents[0].setVec(1.f, 1.f) ; mTexCoordExtents[1].setVec(0.f, 0.f) ; - U32 end = mVertices.size() ; - for(U32 i = 0 ; i < end ; i++) + for(U32 i = 0 ; i < (U32)mNumVertices ; i++) { - if(mTexCoordExtents[0].mV[0] > mVertices[i].mTexCoord.mV[0]) + if(mTexCoordExtents[0].mV[0] > mTexCoords[i].mV[0]) { - mTexCoordExtents[0].mV[0] = mVertices[i].mTexCoord.mV[0] ; + mTexCoordExtents[0].mV[0] = mTexCoords[i].mV[0] ; } - if(mTexCoordExtents[1].mV[0] < mVertices[i].mTexCoord.mV[0]) + if(mTexCoordExtents[1].mV[0] < mTexCoords[i].mV[0]) { - mTexCoordExtents[1].mV[0] = mVertices[i].mTexCoord.mV[0] ; + mTexCoordExtents[1].mV[0] = mTexCoords[i].mV[0] ; } - if(mTexCoordExtents[0].mV[1] > mVertices[i].mTexCoord.mV[1]) + if(mTexCoordExtents[0].mV[1] > mTexCoords[i].mV[1]) { - mTexCoordExtents[0].mV[1] = mVertices[i].mTexCoord.mV[1] ; + mTexCoordExtents[0].mV[1] = mTexCoords[i].mV[1] ; } - if(mTexCoordExtents[1].mV[1] < mVertices[i].mTexCoord.mV[1]) + if(mTexCoordExtents[1].mV[1] < mTexCoords[i].mV[1]) { - mTexCoordExtents[1].mV[1] = mVertices[i].mTexCoord.mV[1] ; + mTexCoordExtents[1].mV[1] = mTexCoords[i].mV[1] ; } } mTexCoordExtents[0].mV[0] = llmax(0.f, mTexCoordExtents[0].mV[0]) ; @@ -4474,6 +5615,667 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build) return ret ; } +void LLVolumeFace::getVertexData(U16 index, LLVolumeFace::VertexData& cv) +{ + cv.setPosition(mPositions[index]); + if (mNormals) + { + cv.setNormal(mNormals[index]); + } + else + { + cv.getNormal().clear(); + } + + if (mTexCoords) + { + cv.mTexCoord = mTexCoords[index]; + } + else + { + cv.mTexCoord.clear(); + } +} + +bool LLVolumeFace::VertexMapData::operator==(const LLVolumeFace::VertexData& rhs) const +{ + return getPosition().equals3(rhs.getPosition()) && + mTexCoord == rhs.mTexCoord && + getNormal().equals3(rhs.getNormal()); +} + +bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a, const LLVector3& b) const +{ + if (a.mV[0] != b.mV[0]) + { + return a.mV[0] < b.mV[0]; + } + + if (a.mV[1] != b.mV[1]) + { + return a.mV[1] < b.mV[1]; + } + + return a.mV[2] < b.mV[2]; +} + +void LLVolumeFace::optimize(F32 angle_cutoff) +{ + LLVolumeFace new_face; + + //map of points to vector of vertices at that point + std::map > point_map; + + LLVector4a range; + range.setSub(mExtents[1],mExtents[0]); + + //remove redundant vertices + for (U32 i = 0; i < (U32)mNumIndices; ++i) + { + U16 index = mIndices[i]; + + LLVolumeFace::VertexData cv; + getVertexData(index, cv); + + BOOL found = FALSE; + + LLVector4a pos; + pos.setSub(mPositions[index], mExtents[0]); + pos.div(range); + + U64 pos64 = 0; + + pos64 = (U16) (pos[0]*65535); + pos64 = pos64 | (((U64) (pos[1]*65535)) << 16); + pos64 = pos64 | (((U64) (pos[2]*65535)) << 32); + + std::map >::iterator point_iter = point_map.find(pos64); + + if (point_iter != point_map.end()) + { //duplicate point might exist + for (U32 j = 0; j < point_iter->second.size(); ++j) + { + LLVolumeFace::VertexData& tv = (point_iter->second)[j]; + if (tv.compareNormal(cv, angle_cutoff)) + { + found = TRUE; + new_face.pushIndex((point_iter->second)[j].mIndex); + break; + } + } + } + + if (!found) + { + new_face.pushVertex(cv); + U16 index = (U16) new_face.mNumVertices-1; + new_face.pushIndex(index); + + VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[pos64].push_back(d); + } + } + } + + llassert(new_face.mNumIndices == mNumIndices); + llassert(new_face.mNumVertices <= mNumVertices); + + if (angle_cutoff > 1.f && !mNormals) + { + ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!mTexCoords) + { + ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + swapData(new_face); +} + +class LLVCacheTriangleData; + +class LLVCacheVertexData +{ +public: + S32 mIdx; + S32 mCacheTag; + F32 mScore; + U32 mActiveTriangles; + std::vector mTriangles; + + LLVCacheVertexData() + { + mCacheTag = -1; + mScore = 0.f; + mActiveTriangles = 0; + mIdx = -1; + } +}; + +class LLVCacheTriangleData +{ +public: + bool mActive; + F32 mScore; + LLVCacheVertexData* mVertex[3]; + + LLVCacheTriangleData() + { + mActive = true; + mScore = 0.f; + mVertex[0] = mVertex[1] = mVertex[2] = NULL; + } + + void complete() + { + mActive = false; + for (S32 i = 0; i < 3; ++i) + { + if (mVertex[i]) + { + llassert_always(mVertex[i]->mActiveTriangles > 0); + mVertex[i]->mActiveTriangles--; + } + } + } + + bool operator<(const LLVCacheTriangleData& rhs) const + { //highest score first + return rhs.mScore < mScore; + } +}; + +const F32 FindVertexScore_CacheDecayPower = 1.5f; +const F32 FindVertexScore_LastTriScore = 0.75f; +const F32 FindVertexScore_ValenceBoostScale = 2.0f; +const F32 FindVertexScore_ValenceBoostPower = 0.5f; +const U32 MaxSizeVertexCache = 32; + +F32 find_vertex_score(LLVCacheVertexData& data) +{ + if (data.mActiveTriangles == 0) + { //no triangle references this vertex + return -1.f; + } + + F32 score = 0.f; + + S32 cache_idx = data.mCacheTag; + + if (cache_idx < 0) + { + //not in cache + } + else + { + if (cache_idx < 3) + { //vertex was in the last triangle + score = FindVertexScore_LastTriScore; + } + else + { //more points for being higher in the cache + F32 scaler = 1.f/(MaxSizeVertexCache-3); + score = 1.f-((cache_idx-3)*scaler); + score = powf(score, FindVertexScore_CacheDecayPower); + } + } + + //bonus points for having low valence + F32 valence_boost = powf(data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); + score += FindVertexScore_ValenceBoostScale * valence_boost; + + return score; +} + +class LLVCacheFIFO +{ +public: + LLVCacheVertexData* mCache[MaxSizeVertexCache]; + U32 mMisses; + + LLVCacheFIFO() + { + mMisses = 0; + for (U32 i = 0; i < MaxSizeVertexCache; ++i) + { + mCache[i] = NULL; + } + } + + void addVertex(LLVCacheVertexData* data) + { + if (data->mCacheTag == -1) + { + mMisses++; + + S32 end = MaxSizeVertexCache-1; + + if (mCache[end]) + { + mCache[end]->mCacheTag = -1; + } + + for (S32 i = end; i > 0; --i) + { + mCache[i] = mCache[i-1]; + if (mCache[i]) + { + mCache[i]->mCacheTag = i; + } + } + + mCache[0] = data; + data->mCacheTag = 0; + } + } +}; + +class LLVCacheLRU +{ +public: + LLVCacheVertexData* mCache[MaxSizeVertexCache+3]; + + LLVCacheTriangleData* mBestTriangle; + + U32 mMisses; + + LLVCacheLRU() + { + for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) + { + mCache[i] = NULL; + } + + mBestTriangle = NULL; + mMisses = 0; + } + + void addVertex(LLVCacheVertexData* data) + { + S32 end = MaxSizeVertexCache+2; + if (data->mCacheTag != -1) + { //just moving a vertex to the front of the cache + end = data->mCacheTag; + } + else + { + mMisses++; + if (mCache[end]) + { //adding a new vertex, vertex at end of cache falls off + mCache[end]->mCacheTag = -1; + } + } + + for (S32 i = end; i > 0; --i) + { //adjust cache pointers and tags + mCache[i] = mCache[i-1]; + + if (mCache[i]) + { + mCache[i]->mCacheTag = i; + } + } + + mCache[0] = data; + mCache[0]->mCacheTag = 0; + } + + void addTriangle(LLVCacheTriangleData* data) + { + addVertex(data->mVertex[0]); + addVertex(data->mVertex[1]); + addVertex(data->mVertex[2]); + } + + void updateScores() + { + for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i) + { //trailing 3 vertices aren't actually in the cache for scoring purposes + if (mCache[i]) + { + mCache[i]->mCacheTag = -1; + } + } + + for (U32 i = 0; i < MaxSizeVertexCache; ++i) + { //update scores of vertices in cache + if (mCache[i]) + { + mCache[i]->mScore = find_vertex_score(*(mCache[i])); + llassert_always(mCache[i]->mCacheTag == i); + } + } + + mBestTriangle = NULL; + //update triangle scores + for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) + { + if (mCache[i]) + { + for (U32 j = 0; j < mCache[i]->mTriangles.size(); ++j) + { + LLVCacheTriangleData* tri = mCache[i]->mTriangles[j]; + if (tri->mActive) + { + tri->mScore = tri->mVertex[0]->mScore; + tri->mScore += tri->mVertex[1]->mScore; + tri->mScore += tri->mVertex[2]->mScore; + + if (!mBestTriangle || mBestTriangle->mScore < tri->mScore) + { + mBestTriangle = tri; + } + } + } + } + } + + //knock trailing 3 vertices off the cache + for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i) + { + if (mCache[i]) + { + llassert_always(mCache[i]->mCacheTag == -1); + mCache[i] = NULL; + } + } + } +}; + + +void LLVolumeFace::cacheOptimize() +{ //optimize for vertex cache according to Forsyth method: + // http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html + + LLVCacheLRU cache; + + if (mNumVertices < 3) + { //nothing to do + return; + } + + //mapping of vertices to triangles and indices + std::vector vertex_data; + + //mapping of triangles do vertices + std::vector triangle_data; + + triangle_data.resize(mNumIndices/3); + vertex_data.resize(mNumVertices); + + for (U32 i = 0; i < (U32)mNumIndices; i++) + { //populate vertex data and triangle data arrays + U16 idx = mIndices[i]; + U32 tri_idx = i/3; + + vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx])); + vertex_data[idx].mIdx = idx; + triangle_data[tri_idx].mVertex[i%3] = &(vertex_data[idx]); + } + + /*F32 pre_acmr = 1.f; + //measure cache misses from before rebuild + { + LLVCacheFIFO test_cache; + for (U32 i = 0; i < mNumIndices; ++i) + { + test_cache.addVertex(&vertex_data[mIndices[i]]); + } + + for (U32 i = 0; i < mNumVertices; i++) + { + vertex_data[i].mCacheTag = -1; + } + + pre_acmr = (F32) test_cache.mMisses/(mNumIndices/3); + }*/ + + for (U32 i = 0; i < (U32)mNumVertices; i++) + { //initialize score values (no cache -- might try a fifo cache here) + vertex_data[i].mScore = find_vertex_score(vertex_data[i]); + vertex_data[i].mActiveTriangles = vertex_data[i].mTriangles.size(); + + for (U32 j = 0; j < vertex_data[i].mTriangles.size(); ++j) + { + vertex_data[i].mTriangles[j]->mScore += vertex_data[i].mScore; + } + } + + //sort triangle data by score + std::sort(triangle_data.begin(), triangle_data.end()); + + std::vector new_indices; + + LLVCacheTriangleData* tri; + + //prime pump by adding first triangle to cache; + tri = &(triangle_data[0]); + cache.addTriangle(tri); + new_indices.push_back(tri->mVertex[0]->mIdx); + new_indices.push_back(tri->mVertex[1]->mIdx); + new_indices.push_back(tri->mVertex[2]->mIdx); + tri->complete(); + + U32 breaks = 0; + for (U32 i = 1; i < (U32)mNumIndices/3; ++i) + { + cache.updateScores(); + tri = cache.mBestTriangle; + if (!tri) + { + breaks++; + for (U32 j = 0; j < triangle_data.size(); ++j) + { + if (triangle_data[j].mActive) + { + tri = &(triangle_data[j]); + break; + } + } + } + + cache.addTriangle(tri); + new_indices.push_back(tri->mVertex[0]->mIdx); + new_indices.push_back(tri->mVertex[1]->mIdx); + new_indices.push_back(tri->mVertex[2]->mIdx); + tri->complete(); + } + + for (U32 i = 0; i < (U32)mNumIndices; ++i) + { + mIndices[i] = new_indices[i]; + } + + /*F32 post_acmr = 1.f; + //measure cache misses from after rebuild + { + LLVCacheFIFO test_cache; + for (U32 i = 0; i < mNumVertices; i++) + { + vertex_data[i].mCacheTag = -1; + } + + for (U32 i = 0; i < mNumIndices; ++i) + { + test_cache.addVertex(&vertex_data[mIndices[i]]); + } + + post_acmr = (F32) test_cache.mMisses/(mNumIndices/3); + }*/ + + //optimize for pre-TnL cache + + //allocate space for new buffer + S32 num_verts = mNumVertices; + LLVector4a* pos = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + LLVector4a* norm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; + LLVector2* tc = (LLVector2*) ll_aligned_malloc_16(size); + +#if MESH_ENABLED + LLVector4a* wght = NULL; + if (mWeights) + { + wght = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + } +#endif //MESH_ENABLED + + LLVector4a* binorm = NULL; + if (mBinormals) + { + binorm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + } + + //allocate mapping of old indices to new indices + std::vector new_idx; + new_idx.resize(mNumVertices, -1); + + S32 cur_idx = 0; + for (U32 i = 0; i < (U32)mNumIndices; ++i) + { + U16 idx = mIndices[i]; + if (new_idx[idx] == -1) + { //this vertex hasn't been added yet + new_idx[idx] = cur_idx; + + //copy vertex data + pos[cur_idx] = mPositions[idx]; + norm[cur_idx] = mNormals[idx]; + tc[cur_idx] = mTexCoords[idx]; +#if MESH_ENABLED + if (mWeights) + { + wght[cur_idx] = mWeights[idx]; + } +#endif //MESH_ENABLED + if (mBinormals) + { + binorm[cur_idx] = mBinormals[idx]; + } + + cur_idx++; + } + } + + for (U32 i = 0; i < (U32)mNumIndices; ++i) + { + mIndices[i] = new_idx[mIndices[i]]; + } + + ll_aligned_free_16(mPositions); + ll_aligned_free_16(mNormals); + ll_aligned_free_16(mTexCoords); +#if MESH_ENABLED + ll_aligned_free_16(mWeights); +#endif //MESH_ENABLED + ll_aligned_free_16(mBinormals); + + mPositions = pos; + mNormals = norm; + mTexCoords = tc; +#if MESH_ENABLED + mWeights = wght; +#endif //MESH_ENABLED + mBinormals = binorm; + + //std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks); + //llinfos << result << llendl; + +} + +void LLVolumeFace::createOctree(F32 scaler, const LLVector4a& center, const LLVector4a& size) +{ + if (mOctree) + { + return; + } + + mOctree = new LLOctreeRoot(center, size, NULL); + new LLVolumeOctreeListener(mOctree); + + for (U32 i = 0; i < (U32)mNumIndices; i+= 3) + { //for each triangle + LLPointer tri = new LLVolumeTriangle(); + + const LLVector4a& v0 = mPositions[mIndices[i]]; + const LLVector4a& v1 = mPositions[mIndices[i+1]]; + const LLVector4a& v2 = mPositions[mIndices[i+2]]; + + //store pointers to vertex data + tri->mV[0] = &v0; + tri->mV[1] = &v1; + tri->mV[2] = &v2; + + //store indices + tri->mIndex[0] = mIndices[i]; + tri->mIndex[1] = mIndices[i+1]; + tri->mIndex[2] = mIndices[i+2]; + + //get minimum point + LLVector4a min = v0; + min.setMin(min, v1); + min.setMin(min, v2); + + //get maximum point + LLVector4a max = v0; + max.setMax(max, v1); + max.setMax(max, v2); + + //compute center + LLVector4a center; + center.setAdd(min, max); + center.mul(0.5f); + + tri->mPositionGroup = center; + + //compute "radius" + LLVector4a size; + size.setSub(max,min); + + tri->mRadius = size.getLength3().getF32() * scaler; + + //insert + mOctree->insert(tri); + } + + //remove unneeded octree layers + while (!mOctree->balance()) { } + + //calculate AABB for each node + LLVolumeOctreeRebound rebound(this); + rebound.traverse(mOctree); + + if (gDebugGL) + { + LLVolumeOctreeValidate validate; + validate.traverse(mOctree); + } +} + + +void LLVolumeFace::swapData(LLVolumeFace& rhs) +{ + llswap(rhs.mPositions, mPositions); + llswap(rhs.mNormals, mNormals); + llswap(rhs.mBinormals, mBinormals); + llswap(rhs.mTexCoords, mTexCoords); + llswap(rhs.mIndices,mIndices); + llswap(rhs.mNumVertices, mNumVertices); + llswap(rhs.mNumIndices, mNumIndices); +} void LerpPlanarVertex(LLVolumeFace::VertexData& v0, LLVolumeFace::VertexData& v1, LLVolumeFace::VertexData& v2, @@ -4481,10 +6283,21 @@ void LerpPlanarVertex(LLVolumeFace::VertexData& v0, F32 coef01, F32 coef02) { - vout.mPosition = v0.mPosition + ((v1.mPosition-v0.mPosition)*coef01)+((v2.mPosition-v0.mPosition)*coef02); + + LLVector4a lhs; + lhs.setSub(v1.getPosition(), v0.getPosition()); + lhs.mul(coef01); + LLVector4a rhs; + rhs.setSub(v2.getPosition(), v0.getPosition()); + rhs.mul(coef02); + + rhs.add(lhs); + rhs.add(v0.getPosition()); + + vout.setPosition(rhs); + vout.mTexCoord = v0.mTexCoord + ((v1.mTexCoord-v0.mTexCoord)*coef01)+((v2.mTexCoord-v0.mTexCoord)*coef02); - vout.mNormal = v0.mNormal; - vout.mBinormal = v0.mBinormal; + vout.setNormal(v0.getNormal()); } BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) @@ -4504,81 +6317,113 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build) num_vertices = (grid_size+1)*(grid_size+1); num_indices = quad_count * 4; - LLVector3& min = mExtents[0]; - LLVector3& max = mExtents[1]; + LLVector4a& min = mExtents[0]; + LLVector4a& max = mExtents[1]; S32 offset = 0; if (mTypeMask & TOP_MASK) - offset = (max_t-1) * max_s; - else - offset = mBeginS; - - VertexData corners[4]; - VertexData baseVert; - for(int t = 0; t < 4; t++){ - corners[t].mPosition = mesh[offset + (grid_size*t)].mPos; - corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f; - corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1]; - } - baseVert.mNormal = - ((corners[1].mPosition-corners[0].mPosition) % - (corners[2].mPosition-corners[1].mPosition)); - baseVert.mNormal.normVec(); - if(!(mTypeMask & TOP_MASK)){ - baseVert.mNormal *= -1.0f; - }else{ - //Swap the UVs on the U(X) axis for top face - LLVector2 swap; - swap = corners[0].mTexCoord; - corners[0].mTexCoord=corners[3].mTexCoord; - corners[3].mTexCoord=swap; - swap = corners[1].mTexCoord; - corners[1].mTexCoord=corners[2].mTexCoord; - corners[2].mTexCoord=swap; - } - baseVert.mBinormal = calc_binormal_from_triangle( - corners[0].mPosition, corners[0].mTexCoord, - corners[1].mPosition, corners[1].mTexCoord, - corners[2].mPosition, corners[2].mTexCoord); - for(int t = 0; t < 4; t++){ - corners[t].mBinormal = baseVert.mBinormal; - corners[t].mNormal = baseVert.mNormal; - } - mHasBinormals = TRUE; - - if (partial_build) { - mVertices.clear(); + offset = (max_t-1) * max_s; + } + else + { + offset = mBeginS; } - S32 vtop = mVertices.size(); - for(int gx = 0;gxsetAdd(min, max); + mCenter->mul(0.5f); + } if (!partial_build) { + resizeIndices(grid_size*grid_size*6); + + U16* out = mIndices; + S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0}; for(S32 gx = 0;gx=0;i--) { - mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); - } + *out++ = ((gy*(grid_size+1))+gx+idxs[i]); + } } else { for(S32 i=0;i<6;i++) { - mIndices.push_back(vtop+(gy*(grid_size+1))+gx+idxs[i]); + *out++ = ((gy*(grid_size+1))+gx+idxs[i]); } } } @@ -4630,17 +6475,31 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) num_vertices = profile.size(); num_indices = (profile.size() - 2)*3; - mVertices.resize(num_vertices); - - if (!partial_build) + if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) { - mIndices.resize(num_indices); + resizeVertices(num_vertices+1); + allocateBinormals(num_vertices+1); + + if (!partial_build) + { + resizeIndices(num_indices+3); + } + } + else + { + resizeVertices(num_vertices); + allocateBinormals(num_vertices); + + if (!partial_build) + { + resizeIndices(num_indices); + } } S32 max_s = volume->getProfile().getTotal(); S32 max_t = volume->getPath().mPath.size(); - mCenter.clearVec(); + mCenter->clear(); S32 offset = 0; if (mTypeMask & TOP_MASK) @@ -4658,82 +6517,91 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) LLVector2 cuv; LLVector2 min_uv, max_uv; - LLVector3& min = mExtents[0]; - LLVector3& max = mExtents[1]; + LLVector4a& min = mExtents[0]; + LLVector4a& max = mExtents[1]; + + LLVector2* tc = (LLVector2*) mTexCoords; + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector4a* binorm = (LLVector4a*) mBinormals; // Copy the vertices into the array for (S32 i = 0; i < num_vertices; i++) { if (mTypeMask & TOP_MASK) { - mVertices[i].mTexCoord.mV[0] = profile[i].mV[0]+0.5f; - mVertices[i].mTexCoord.mV[1] = profile[i].mV[1]+0.5f; + tc[i].mV[0] = profile[i].mV[0]+0.5f; + tc[i].mV[1] = profile[i].mV[1]+0.5f; } else { // Mirror for underside. - mVertices[i].mTexCoord.mV[0] = profile[i].mV[0]+0.5f; - mVertices[i].mTexCoord.mV[1] = 0.5f - profile[i].mV[1]; + tc[i].mV[0] = profile[i].mV[0]+0.5f; + tc[i].mV[1] = 0.5f - profile[i].mV[1]; } - mVertices[i].mPosition = mesh[i + offset].mPos; + pos[i].load3(mesh[i + offset].mPos.mV); if (i == 0) { - min = max = mVertices[i].mPosition; - min_uv = max_uv = mVertices[i].mTexCoord; + max = pos[i]; + min = max; + min_uv = max_uv = tc[i]; } else { - update_min_max(min,max, mVertices[i].mPosition); - update_min_max(min_uv, max_uv, mVertices[i].mTexCoord); + update_min_max(min,max,pos[i]); + update_min_max(min_uv, max_uv, tc[i]); } } - mCenter = (min+max)*0.5f; + mCenter->setAdd(min, max); + mCenter->mul(0.5f); + cuv = (min_uv + max_uv)*0.5f; - LLVector3 binormal = calc_binormal_from_triangle( - mCenter, cuv, - mVertices[0].mPosition, mVertices[0].mTexCoord, - mVertices[1].mPosition, mVertices[1].mTexCoord); - binormal.normVec(); + LLVector4a binormal; + calc_binormal_from_triangle(binormal, + *mCenter, cuv, + pos[0], tc[0], + pos[1], tc[1]); + binormal.normalize3fast(); - LLVector3 d0; - LLVector3 d1; - LLVector3 normal; + LLVector4a normal; + LLVector4a d0, d1; + - d0 = mCenter-mVertices[0].mPosition; - d1 = mCenter-mVertices[1].mPosition; + d0.setSub(*mCenter, pos[0]); + d1.setSub(*mCenter, pos[1]); - normal = (mTypeMask & TOP_MASK) ? (d0%d1) : (d1%d0); - normal.normVec(); + if (mTypeMask & TOP_MASK) + { + normal.setCross3(d0, d1); + } + else + { + normal.setCross3(d1, d0); + } + + normal.normalize3fast(); VertexData vd; - vd.mPosition = mCenter; - vd.mNormal = normal; - vd.mBinormal = binormal; + vd.setPosition(*mCenter); vd.mTexCoord = cuv; if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK)) { - mVertices.push_back(vd); + pos[num_vertices] = *mCenter; + tc[num_vertices] = cuv; num_vertices++; - if (!partial_build) - { - vector_append(mIndices, 3); - } } - for (S32 i = 0; i < num_vertices; i++) { - mVertices[i].mBinormal = binormal; - mVertices[i].mNormal = normal; + binorm[i].load4a(binormal.getF32ptr()); + norm[i].load4a(normal.getF32ptr()); } - mHasBinormals = TRUE; - if (partial_build) { return TRUE; @@ -4965,7 +6833,10 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build) mIndices[3*i+v1] = i; mIndices[3*i+v2] = i + 1; } + + } + return TRUE; } @@ -4973,44 +6844,270 @@ void LLVolumeFace::createBinormals() { LLMemType m1(LLMemType::MTYPE_VOLUME); - if (!mHasBinormals) + if (!mBinormals) { + allocateBinormals(mNumVertices); + //generate binormals - for (U32 i = 0; i < mIndices.size()/3; i++) + LLVector4a* pos = mPositions; + LLVector2* tc = (LLVector2*) mTexCoords; + LLVector4a* binorm = (LLVector4a*) mBinormals; + + LLVector4a* end = mBinormals+mNumVertices; + while (binorm < end) + { + (*binorm++).clear(); + } + + binorm = mBinormals; + + for (U32 i = 0; i < (U32)mNumIndices/3; i++) { //for each triangle - const VertexData& v0 = mVertices[mIndices[i*3+0]]; - const VertexData& v1 = mVertices[mIndices[i*3+1]]; - const VertexData& v2 = mVertices[mIndices[i*3+2]]; + const U16& i0 = mIndices[i*3+0]; + const U16& i1 = mIndices[i*3+1]; + const U16& i2 = mIndices[i*3+2]; //calculate binormal - LLVector3 binorm = calc_binormal_from_triangle(v0.mPosition, v0.mTexCoord, - v1.mPosition, v1.mTexCoord, - v2.mPosition, v2.mTexCoord); + LLVector4a binormal; + calc_binormal_from_triangle(binormal, + pos[i0], tc[i0], + pos[i1], tc[i1], + pos[i2], tc[i2]); - for (U32 j = 0; j < 3; j++) - { //add triangle normal to vertices - mVertices[mIndices[i*3+j]].mBinormal += binorm; // * (weight_sum - d[j])/weight_sum; - } + + //add triangle normal to vertices + binorm[i0].add(binormal); + binorm[i1].add(binormal); + binorm[i2].add(binormal); //even out quad contributions if (i % 2 == 0) { - mVertices[mIndices[i*3+2]].mBinormal += binorm; + binorm[i2].add(binormal); } else { - mVertices[mIndices[i*3+1]].mBinormal += binorm; + binorm[i1].add(binormal); } } //normalize binormals - for (U32 i = 0; i < mVertices.size(); i++) + for (U32 i = 0; i < (U32)mNumVertices; i++) { - mVertices[i].mBinormal.normVec(); - mVertices[i].mNormal.normVec(); + binorm[i].normalize3fast(); + //bump map/planar projection code requires normals to be normalized + mNormals[i].normalize3fast(); } + } +} - mHasBinormals = TRUE; +void LLVolumeFace::resizeVertices(S32 num_verts) +{ + ll_aligned_free_16(mPositions); + ll_aligned_free_16(mNormals); + ll_aligned_free_16(mBinormals); + ll_aligned_free_16(mTexCoords); + + mBinormals = NULL; + + if (num_verts) + { + mPositions = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + assert_aligned(mPositions, 16); + mNormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); + assert_aligned(mNormals, 16); + + //pad texture coordinate block end to allow for QWORD reads + S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; + mTexCoords = (LLVector2*) ll_aligned_malloc_16(size); + assert_aligned(mTexCoords, 16); + } + else + { + mPositions = NULL; + mNormals = NULL; + mTexCoords = NULL; + } + + mNumVertices = num_verts; +} + +void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv) +{ + pushVertex(cv.getPosition(), cv.getNormal(), cv.mTexCoord); +} + +void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc) +{ + S32 new_verts = mNumVertices+1; + S32 new_size = new_verts*16; +// S32 old_size = mNumVertices*16; + + //positions + mPositions = (LLVector4a*) realloc(mPositions, new_size); + + //normals + mNormals = (LLVector4a*) realloc(mNormals, new_size); + + //tex coords + new_size = ((new_verts*8)+0xF) & ~0xF; + mTexCoords = (LLVector2*) realloc(mTexCoords, new_size); + + + //just clear binormals + ll_aligned_free_16(mBinormals); + mBinormals = NULL; + + mPositions[mNumVertices] = pos; + mNormals[mNumVertices] = norm; + mTexCoords[mNumVertices] = tc; + + mNumVertices++; +} + +void LLVolumeFace::allocateBinormals(S32 num_verts) +{ + ll_aligned_free_16(mBinormals); + mBinormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); +} + +#if MESH_ENABLED +void LLVolumeFace::allocateWeights(S32 num_verts) +{ + + ll_aligned_free_16(mWeights); + mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); +} +#endif //MESH_ENABLED + +void LLVolumeFace::resizeIndices(S32 num_indices) +{ + ll_aligned_free_16(mIndices); + + if (num_indices) + { + //pad index block end to allow for QWORD reads + S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF; + + mIndices = (U16*) ll_aligned_malloc_16(size); + } + else + { + mIndices = NULL; + } + + mNumIndices = num_indices; +} + +void LLVolumeFace::pushIndex(const U16& idx) +{ + S32 new_count = mNumIndices + 1; + S32 new_size = ((new_count*2)+0xF) & ~0xF; + + S32 old_size = ((mNumIndices*2)+0xF) & ~0xF; + if (new_size != old_size) + { + mIndices = (U16*) realloc(mIndices, new_size); + } + + mIndices[mNumIndices++] = idx; +} + +void LLVolumeFace::fillFromLegacyData(std::vector& v, std::vector& idx) +{ + resizeVertices(v.size()); + resizeIndices(idx.size()); + + for (U32 i = 0; i < v.size(); ++i) + { + mPositions[i] = v[i].getPosition(); + mNormals[i] = v[i].getNormal(); + mTexCoords[i] = v[i].mTexCoord; + } + + for (U32 i = 0; i < idx.size(); ++i) + { + mIndices[i] = idx[i]; + } +} + +void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMatrix4& norm_mat_in) +{ + U16 offset = mNumVertices; + + S32 new_count = face.mNumVertices + mNumVertices; + + if (new_count > 65536) + { + llerrs << "Cannot append face -- 16-bit overflow will occur." << llendl; + } + + if (face.mNumVertices == 0) + { + llerrs << "Cannot append empty face." << llendl; + } + + //allocate new buffer space + mPositions = (LLVector4a*) realloc(mPositions, new_count*sizeof(LLVector4a)); + assert_aligned(mPositions, 16); + mNormals = (LLVector4a*) realloc(mNormals, new_count*sizeof(LLVector4a)); + assert_aligned(mNormals, 16); + mTexCoords = (LLVector2*) realloc(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF); + assert_aligned(mTexCoords, 16); + + mNumVertices = new_count; + + //get destination address of appended face + LLVector4a* dst_pos = mPositions+offset; + LLVector2* dst_tc = mTexCoords+offset; + LLVector4a* dst_norm = mNormals+offset; + + //get source addresses of appended face + const LLVector4a* src_pos = face.mPositions; + const LLVector2* src_tc = face.mTexCoords; + const LLVector4a* src_norm = face.mNormals; + + //load aligned matrices + LLMatrix4a mat, norm_mat; + mat.loadu(mat_in); + norm_mat.loadu(norm_mat_in); + + for (U32 i = 0; i < (U32)face.mNumVertices; ++i) + { + //transform appended face position and store + mat.affineTransform(src_pos[i], dst_pos[i]); + + //transform appended face normal and store + norm_mat.rotate(src_norm[i], dst_norm[i]); + dst_norm[i].normalize3fast(); + + //copy appended face texture coordinate + dst_tc[i] = src_tc[i]; + + if (offset == 0 && i == 0) + { //initialize bounding box + mExtents[0] = mExtents[1] = dst_pos[i]; + } + else + { + //stretch bounding box + update_min_max(mExtents[0], mExtents[1], dst_pos[i]); + } + } + + + new_count = mNumIndices + face.mNumIndices; + + //allocate new index buffer + mIndices = (U16*) realloc(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF); + + //get destination address into new index buffer + U16* dst_idx = mIndices+mNumIndices; + mNumIndices = new_count; + + for (U32 i = 0; i < (U32)face.mNumIndices; ++i) + { //copy indices, offsetting by old vertex count + dst_idx[i] = face.mIndices[i]+offset; } } @@ -5040,18 +7137,21 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) num_vertices = mNumS*mNumT; num_indices = (mNumS-1)*(mNumT-1)*6; - mVertices.resize(num_vertices); - if (!partial_build) { - mIndices.resize(num_indices); - mEdge.resize(num_indices); - } - else - { - mHasBinormals = FALSE; + resizeVertices(num_vertices); + resizeIndices(num_indices); +#if MESH_ENABLED + if (!volume->isMeshAssetLoaded()) +#endif //MESH_ENABLED + { + mEdge.resize(num_indices); + } } + LLVector4a* pos = (LLVector4a*) mPositions; + LLVector4a* norm = (LLVector4a*) mNormals; + LLVector2* tc = (LLVector2*) mTexCoords; S32 begin_stex = llfloor( profile[mBeginS].mV[2] ); S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS; @@ -5102,21 +7202,20 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) i = mBeginS + s + max_s*t; } - mVertices[cur_vertex].mPosition = mesh[i].mPos; - mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt); + pos[cur_vertex].load3(mesh[i].mPos.mV); + tc[cur_vertex] = LLVector2(ss,tt); - mVertices[cur_vertex].mNormal = LLVector3(0,0,0); - mVertices[cur_vertex].mBinormal = LLVector3(0,0,0); - + norm[cur_vertex].clear(); cur_vertex++; if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2 && s > 0) { - mVertices[cur_vertex].mPosition = mesh[i].mPos; - mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt); + + pos[cur_vertex].load3(mesh[i].mPos.mV); + tc[cur_vertex] = LLVector2(ss,tt); - mVertices[cur_vertex].mNormal = LLVector3(0,0,0); - mVertices[cur_vertex].mBinormal = LLVector3(0,0,0); + norm[cur_vertex].clear(); + cur_vertex++; } } @@ -5134,29 +7233,29 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) i = mBeginS + s + max_s*t; ss = profile[mBeginS + s].mV[2] - begin_stex; - mVertices[cur_vertex].mPosition = mesh[i].mPos; - mVertices[cur_vertex].mTexCoord = LLVector2(ss,tt); - - mVertices[cur_vertex].mNormal = LLVector3(0,0,0); - mVertices[cur_vertex].mBinormal = LLVector3(0,0,0); - + pos[cur_vertex].load3(mesh[i].mPos.mV); + tc[cur_vertex] = LLVector2(ss,tt); + norm[cur_vertex].clear(); + cur_vertex++; } } //get bounding box for this side - LLVector3& face_min = mExtents[0]; - LLVector3& face_max = mExtents[1]; - mCenter.clearVec(); + LLVector4a& face_min = mExtents[0]; + LLVector4a& face_max = mExtents[1]; + mCenter->clear(); - face_min = face_max = mVertices[0].mPosition; - for (U32 i = 1; i < mVertices.size(); ++i) + face_min = face_max = pos[0]; + + for (U32 i = 1; i < (U32)mNumVertices; ++i) { - update_min_max(face_min, face_max, mVertices[i].mPosition); + update_min_max(face_min, face_max, pos[i]); } - mCenter = (face_min + face_max) * 0.5f; + mCenter->setAdd(face_min, face_max); + mCenter->mul(0.5f); S32 cur_index = 0; S32 cur_edge = 0; @@ -5219,38 +7318,58 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) } } + //clear normals + for (U32 i = 0; i < (U32)mNumVertices; i++) + { + mNormals[i].clear(); + } + //generate normals - for (U32 i = 0; i < mIndices.size()/3; i++) //for each triangle + for (U32 i = 0; i < (U32)mNumIndices/3; i++) //for each triangle { const U16* idx = &(mIndices[i*3]); - - VertexData* v[] = - { &mVertices[idx[0]], &mVertices[idx[1]], &mVertices[idx[2]] }; - + + + LLVector4a* v[] = + { pos+idx[0], pos+idx[1], pos+idx[2] }; + + LLVector4a* n[] = + { norm+idx[0], norm+idx[1], norm+idx[2] }; + //calculate triangle normal - LLVector3 norm = (v[0]->mPosition-v[1]->mPosition) % (v[0]->mPosition-v[2]->mPosition); - - v[0]->mNormal += norm; - v[1]->mNormal += norm; - v[2]->mNormal += norm; + LLVector4a a, b, c; + + a.setSub(*v[0], *v[1]); + b.setSub(*v[0], *v[2]); + c.setCross3(a,b); + n[0]->add(c); + n[1]->add(c); + n[2]->add(c); + //even out quad contributions - v[i%2+1]->mNormal += norm; + n[i%2+1]->add(c); } // adjust normals based on wrapping and stitching - BOOL s_bottom_converges = ((mVertices[0].mPosition - mVertices[mNumS*(mNumT-2)].mPosition).magVecSquared() < 0.000001f); - BOOL s_top_converges = ((mVertices[mNumS-1].mPosition - mVertices[mNumS*(mNumT-2)+mNumS-1].mPosition).magVecSquared() < 0.000001f); + LLVector4a top; + top.setSub(pos[0], pos[mNumS*(mNumT-2)]); + BOOL s_bottom_converges = (top.dot3(top) < 0.000001f); + + top.setSub(pos[mNumS-1], pos[mNumS*(mNumT-2)+mNumS-1]); + BOOL s_top_converges = (top.dot3(top) < 0.000001f); + if (sculpt_stitching == LL_SCULPT_TYPE_NONE) // logic for non-sculpt volumes { if (volume->getPath().isOpen() == FALSE) { //wrap normals on T for (S32 i = 0; i < mNumS; i++) { - LLVector3 norm = mVertices[i].mNormal + mVertices[mNumS*(mNumT-1)+i].mNormal; - mVertices[i].mNormal = norm; - mVertices[mNumS*(mNumT-1)+i].mNormal = norm; + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; } } @@ -5258,9 +7377,10 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { //wrap normals on S for (S32 i = 0; i < mNumT; i++) { - LLVector3 norm = mVertices[mNumS*i].mNormal + mVertices[mNumS*i+mNumS-1].mNormal; - mVertices[mNumS * i].mNormal = norm; - mVertices[mNumS * i+mNumS-1].mNormal = norm; + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; } } @@ -5271,7 +7391,7 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { //all lower S have same normal for (S32 i = 0; i < mNumT; i++) { - mVertices[mNumS*i].mNormal = LLVector3(1,0,0); + norm[mNumS*i].set(1,0,0); } } @@ -5279,12 +7399,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { //all upper S have same normal for (S32 i = 0; i < mNumT; i++) { - mVertices[mNumS*i+mNumS-1].mNormal = LLVector3(-1,0,0); + norm[mNumS*i+mNumS-1].set(-1,0,0); } } } } - else // logic for sculpt volumes { BOOL average_poles = FALSE; @@ -5307,30 +7426,33 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { // average normals for north pole - LLVector3 average(0.0, 0.0, 0.0); + LLVector4a average; + average.clear(); + for (S32 i = 0; i < mNumS; i++) { - average += mVertices[i].mNormal; + average.add(norm[i]); } // set average for (S32 i = 0; i < mNumS; i++) { - mVertices[i].mNormal = average; + norm[i] = average; } // average normals for south pole - average = LLVector3(0.0, 0.0, 0.0); + average.clear(); + for (S32 i = 0; i < mNumS; i++) { - average += mVertices[i + mNumS * (mNumT - 1)].mNormal; + average.add(norm[i + mNumS * (mNumT - 1)]); } // set average for (S32 i = 0; i < mNumS; i++) { - mVertices[i + mNumS * (mNumT - 1)].mNormal = average; + norm[i + mNumS * (mNumT - 1)] = average; } } @@ -5340,23 +7462,22 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) { for (S32 i = 0; i < mNumT; i++) { - LLVector3 norm = mVertices[mNumS*i].mNormal + mVertices[mNumS*i+mNumS-1].mNormal; - mVertices[mNumS * i].mNormal = norm; - mVertices[mNumS * i+mNumS-1].mNormal = norm; + LLVector4a n; + n.setAdd(norm[mNumS*i], norm[mNumS*i+mNumS-1]); + norm[mNumS * i] = n; + norm[mNumS * i+mNumS-1] = n; } } - - if (wrap_t) { for (S32 i = 0; i < mNumS; i++) { - LLVector3 norm = mVertices[i].mNormal + mVertices[mNumS*(mNumT-1)+i].mNormal; - mVertices[i].mNormal = norm; - mVertices[mNumS*(mNumT-1)+i].mNormal = norm; + LLVector4a n; + n.setAdd(norm[i], norm[mNumS*(mNumT-1)+i]); + norm[i] = n; + norm[mNumS*(mNumT-1)+i] = n; } - } } @@ -5366,41 +7487,51 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build) // Finds binormal based on three vertices with texture coordinates. // Fills in dummy values if the triangle has degenerate texture coordinates. -LLVector3 calc_binormal_from_triangle( - const LLVector3& pos0, +void calc_binormal_from_triangle(LLVector4a& binormal, + + const LLVector4a& pos0, const LLVector2& tex0, - const LLVector3& pos1, + const LLVector4a& pos1, const LLVector2& tex1, - const LLVector3& pos2, + const LLVector4a& pos2, const LLVector2& tex2) { - LLVector3 rx0( pos0.mV[VX], tex0.mV[VX], tex0.mV[VY] ); - LLVector3 rx1( pos1.mV[VX], tex1.mV[VX], tex1.mV[VY] ); - LLVector3 rx2( pos2.mV[VX], tex2.mV[VX], tex2.mV[VY] ); + LLVector4a rx0( pos0[VX], tex0.mV[VX], tex0.mV[VY] ); + LLVector4a rx1( pos1[VX], tex1.mV[VX], tex1.mV[VY] ); + LLVector4a rx2( pos2[VX], tex2.mV[VX], tex2.mV[VY] ); - LLVector3 ry0( pos0.mV[VY], tex0.mV[VX], tex0.mV[VY] ); - LLVector3 ry1( pos1.mV[VY], tex1.mV[VX], tex1.mV[VY] ); - LLVector3 ry2( pos2.mV[VY], tex2.mV[VX], tex2.mV[VY] ); + LLVector4a ry0( pos0[VY], tex0.mV[VX], tex0.mV[VY] ); + LLVector4a ry1( pos1[VY], tex1.mV[VX], tex1.mV[VY] ); + LLVector4a ry2( pos2[VY], tex2.mV[VX], tex2.mV[VY] ); - LLVector3 rz0( pos0.mV[VZ], tex0.mV[VX], tex0.mV[VY] ); - LLVector3 rz1( pos1.mV[VZ], tex1.mV[VX], tex1.mV[VY] ); - LLVector3 rz2( pos2.mV[VZ], tex2.mV[VX], tex2.mV[VY] ); + LLVector4a rz0( pos0[VZ], tex0.mV[VX], tex0.mV[VY] ); + LLVector4a rz1( pos1[VZ], tex1.mV[VX], tex1.mV[VY] ); + LLVector4a rz2( pos2[VZ], tex2.mV[VX], tex2.mV[VY] ); - LLVector3 r0 = (rx0 - rx1) % (rx0 - rx2); - LLVector3 r1 = (ry0 - ry1) % (ry0 - ry2); - LLVector3 r2 = (rz0 - rz1) % (rz0 - rz2); + LLVector4a lhs, rhs; - if( r0.mV[VX] && r1.mV[VX] && r2.mV[VX] ) + LLVector4a r0; + lhs.setSub(rx0, rx1); rhs.setSub(rx0, rx2); + r0.setCross3(lhs, rhs); + + LLVector4a r1; + lhs.setSub(ry0, ry1); rhs.setSub(ry0, ry2); + r1.setCross3(lhs, rhs); + + LLVector4a r2; + lhs.setSub(rz0, rz1); rhs.setSub(rz0, rz2); + r2.setCross3(lhs, rhs); + + if( r0[VX] && r1[VX] && r2[VX] ) { - LLVector3 binormal( - -r0.mV[VZ] / r0.mV[VX], - -r1.mV[VZ] / r1.mV[VX], - -r2.mV[VZ] / r2.mV[VX]); + binormal.set( + -r0[VZ] / r0[VX], + -r1[VZ] / r1[VX], + -r2[VZ] / r2[VX]); // binormal.normVec(); - return binormal; } else { - return LLVector3( 0, 1 , 0 ); + binormal.set( 0, 1 , 0 ); } } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 7bae2749e..a20e9a5c9 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -40,8 +40,13 @@ class LLPathParams; class LLVolumeParams; class LLProfile; class LLPath; + +template class LLOctreeNode; + +class LLVector4a; class LLVolumeFace; class LLVolume; +class LLVolumeTriangle; #include "lldarray.h" #include "lluuid.h" @@ -49,10 +54,12 @@ class LLVolume; //#include "vmath.h" #include "v2math.h" #include "v3math.h" +#include "v3dmath.h" +#include "v4math.h" #include "llquaternion.h" #include "llstrider.h" #include "v4coloru.h" -#include "llmemory.h" +#include "llrefcount.h" #include "llfile.h" //============================================================================ @@ -184,12 +191,21 @@ const U8 LL_SCULPT_TYPE_SPHERE = 1; const U8 LL_SCULPT_TYPE_TORUS = 2; const U8 LL_SCULPT_TYPE_PLANE = 3; const U8 LL_SCULPT_TYPE_CYLINDER = 4; - +#if MESH_ENABLED +const U8 LL_SCULPT_TYPE_MESH = 5; +const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | + LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH; +#endif //MESH_ENABLED +#if !MESH_ENABLED const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE | LL_SCULPT_TYPE_CYLINDER; +#endif //!MESH_ENABLED const U8 LL_SCULPT_FLAG_INVERT = 64; const U8 LL_SCULPT_FLAG_MIRROR = 128; +#if MESH_ENABLED +const S32 LL_SCULPT_MESH_MAX_FACES = 8; +#endif //MESH_ENABLED class LLProfileParams { @@ -576,6 +592,9 @@ public: BOOL importLegacyStream(std::istream& input_stream); BOOL exportLegacyStream(std::ostream& output_stream) const; + LLSD sculptAsLLSD() const; + bool sculptFromLLSD(LLSD& sd); + LLSD asLLSD() const; operator LLSD() const { return asLLSD(); } bool fromLLSD(LLSD& sd); @@ -635,7 +654,10 @@ public: const F32& getSkew() const { return mPathParams.getSkew(); } const LLUUID& getSculptID() const { return mSculptID; } const U8& getSculptType() const { return mSculptType; } - + bool isSculpt() const; + #if MESH_ENABLED + bool isMeshSculpt() const; + #endif //MESH_ENABLED BOOL isConvex() const; // 'begin' and 'end' should be in range [0, 1] (they will be clamped) @@ -684,6 +706,9 @@ public: BOOL isFlat(S32 face) const { return (mFaces[face].mCount == 2); } BOOL isOpen() const { return mOpen; } void setDirty() { mDirty = TRUE; } + + static S32 getNumPoints(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0, + BOOL is_sculpted = FALSE, S32 sculpt_size = 0); BOOL generate(const LLProfileParams& params, BOOL path_open, F32 detail = 1.0f, S32 split = 0, BOOL is_sculpted = FALSE, S32 sculpt_size = 0); BOOL isConcave() const { return mConcave; } @@ -708,6 +733,7 @@ public: protected: void genNormals(const LLProfileParams& params); + static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); Face* addHole(const LLProfileParams& params, BOOL flat, F32 sides, F32 offset, F32 box_hollow, F32 ang_scale, S32 split = 0); @@ -750,6 +776,9 @@ public: virtual ~LLPath(); + static S32 getNumPoints(const LLPathParams& params, F32 detail); + static S32 getNumNGonPoints(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); + void genNGon(const LLPathParams& params, S32 sides, F32 offset=0.0f, F32 end_scale = 1.f, F32 twist_scale = 1.f); virtual BOOL generate(const LLPathParams& params, F32 detail=1.0f, S32 split = 0, BOOL is_sculpted = FALSE, S32 sculpt_size = 0); @@ -786,29 +815,90 @@ public: class LLVolumeFace { public: - LLVolumeFace() : - mID(0), - mTypeMask(0), - mHasBinormals(FALSE), - mBeginS(0), - mBeginT(0), - mNumS(0), - mNumT(0) + class VertexData { - } + enum + { + POSITION = 0, + NORMAL = 1 + }; + + private: + void init(); + public: + VertexData(); + VertexData(const VertexData& rhs); + const VertexData& operator=(const VertexData& rhs); + + ~VertexData(); + LLVector4a& getPosition(); + LLVector4a& getNormal(); + const LLVector4a& getPosition() const; + const LLVector4a& getNormal() const; + void setPosition(const LLVector4a& pos); + void setNormal(const LLVector4a& norm); + + + LLVector2 mTexCoord; + + bool operator<(const VertexData& rhs) const; + bool operator==(const VertexData& rhs) const; + bool compareNormal(const VertexData& rhs, F32 angle_cutoff) const; + + private: + LLVector4a* mData; + }; + + LLVolumeFace(); + LLVolumeFace(const LLVolumeFace& src); + LLVolumeFace& operator=(const LLVolumeFace& rhs); + + ~LLVolumeFace(); +private: + void freeData(); +public: BOOL create(LLVolume* volume, BOOL partial_build = FALSE); void createBinormals(); + + void appendFace(const LLVolumeFace& face, LLMatrix4& transform, LLMatrix4& normal_tranform); - class VertexData + void resizeVertices(S32 num_verts); + void allocateBinormals(S32 num_verts); + #if MESH_ENABLED + void allocateWeights(S32 num_verts); + #endif //MESH_ENABLED + void resizeIndices(S32 num_indices); + void fillFromLegacyData(std::vector& v, std::vector& idx); + + void pushVertex(const VertexData& cv); + void pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc); + void pushIndex(const U16& idx); + + void swapData(LLVolumeFace& rhs); + + void getVertexData(U16 indx, LLVolumeFace::VertexData& cv); + + class VertexMapData : public LLVolumeFace::VertexData { public: - LLVector3 mPosition; - LLVector3 mNormal; - LLVector3 mBinormal; - LLVector2 mTexCoord; + U16 mIndex; + + bool operator==(const LLVolumeFace::VertexData& rhs) const; + + struct ComparePosition + { + bool operator()(const LLVector3& a, const LLVector3& b) const; + }; + + typedef std::map, VertexMapData::ComparePosition > PointMap; }; + void optimize(F32 angle_cutoff = 2.f); + void cacheOptimize(); + + void createOctree(F32 scaler = 0.25f, const LLVector4a& center = LLVector4a(0,0,0), const LLVector4a& size = LLVector4a(0.5f,0.5f,0.5f)); + enum { SINGLE_MASK = 0x0001, @@ -827,8 +917,6 @@ public: public: S32 mID; U32 mTypeMask; - LLVector3 mCenter; - BOOL mHasBinormals; // Only used for INNER/OUTER faces S32 mBeginS; @@ -836,13 +924,30 @@ public: S32 mNumS; S32 mNumT; - LLVector3 mExtents[2]; //minimum and maximum point of face - LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face. + LLVector4a* mExtents; //minimum and maximum point of face + LLVector4a* mCenter; + LLVector2 mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face. + + S32 mNumVertices; + S32 mNumIndices; + + LLVector4a* mPositions; + LLVector4a* mNormals; + LLVector4a* mBinormals; + LLVector2* mTexCoords; + U16* mIndices; - std::vector mVertices; - std::vector mIndices; std::vector mEdge; + #if MESH_ENABLED + //list of skin weights for rigged volumes + // format is mWeights[vertex_index].mV[influence] = . + // mWeights.size() should be empty or match mVertices.size() + LLVector4a* mWeights; + #endif //MESH_ENABLED + + LLOctreeNode* mOctree; + private: BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE); BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE); @@ -853,7 +958,12 @@ class LLVolume : public LLRefCount { friend class LLVolumeLODGroup; +#if MESH_ENABLED +protected: +#endif //MESH_ENABLED +#if !MESH_ENABLED private: +#endif //!MESH_ENABLED LLVolume(const LLVolume&); // Don't implement ~LLVolume(); // use unref @@ -876,7 +986,7 @@ public: U8 getProfileType() const { return mParams.getProfileParams().getCurveType(); } U8 getPathType() const { return mParams.getPathParams().getCurveType(); } - S32 getNumFaces() const { return (S32)mProfilep->mFaces.size(); } + S32 getNumFaces() const; S32 getNumVolumeFaces() const { return mVolumeFaces.size(); } F32 getDetail() const { return mDetail; } const LLVolumeParams& getParams() const { return mParams; } @@ -898,15 +1008,18 @@ public: BOOL isUnique() const { return mUnique; } S32 getSculptLevel() const { return mSculptLevel; } - + void setSculptLevel(S32 level) { mSculptLevel = level; } + S32 *getTriangleIndices(U32 &num_indices) const; // returns number of triangle indeces required for path/profile mesh S32 getNumTriangleIndices() const; + static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts); + + S32 getNumTriangles() const; void generateSilhouetteVertices(std::vector &vertices, std::vector &normals, - std::vector &segments, const LLVector3& view_vec, const LLMatrix4& mat, const LLMatrix3& norm_mat, @@ -922,6 +1035,13 @@ public: LLVector3* normal = NULL, // return the surface normal at the intersection point LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point ); + + S32 lineSegmentIntersect(const LLVector4a& start, const LLVector4a& end, + S32 face = 1, + LLVector3* intersection = NULL, + LLVector2* tex_coord = NULL, + LLVector3* normal = NULL, + LLVector3* bi_normal = NULL); // The following cleans up vertices and triangles, // getting rid of degenerate triangles and duplicate vertices, @@ -948,6 +1068,9 @@ public: LLVector3 mLODScaleBias; // vector for biasing LOD based on scale void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level); + void copyVolumeFaces(const LLVolume* volume); + void cacheOptimize(); + private: void sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, U8 sculpt_type); F32 sculptGetSurfaceArea(); @@ -958,11 +1081,20 @@ private: protected: BOOL generate(); void createVolumeFaces(); +#if MESH_ENABLED +public: + virtual bool unpackVolumeFaces(std::istream& is, S32 size); + virtual void setMeshAssetLoaded(BOOL loaded); + virtual BOOL isMeshAssetLoaded(); +#endif //MESH_ENABLED protected: BOOL mUnique; F32 mDetail; S32 mSculptLevel; +#if MESH_ENABLED + BOOL mIsMeshAssetLoaded; +#endif //MESH_ENABLED LLVolumeParams mParams; LLPath *mPathp; @@ -972,22 +1104,38 @@ protected: BOOL mGenerateSingleFace; typedef std::vector face_list_t; face_list_t mVolumeFaces; + +#if MESH_ENABLED +public: + LLVector4a* mHullPoints; + U16* mHullIndices; + S32 mNumHullPoints; + S32 mNumHullIndices; +#endif //MESH_ENABLED }; std::ostream& operator<<(std::ostream &s, const LLVolumeParams &volume_params); -LLVector3 calc_binormal_from_triangle( - const LLVector3& pos0, +void calc_binormal_from_triangle( + LLVector4a& binormal, + const LLVector4a& pos0, const LLVector2& tex0, - const LLVector3& pos1, + const LLVector4a& pos1, const LLVector2& tex1, - const LLVector3& pos2, + const LLVector4a& pos2, const LLVector2& tex2); BOOL LLLineSegmentBoxIntersect(const F32* start, const F32* end, const F32* center, const F32* size); BOOL LLLineSegmentBoxIntersect(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size); +BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size); + BOOL LLTriangleRayIntersect(const LLVector3& vert0, const LLVector3& vert1, const LLVector3& vert2, const LLVector3& orig, const LLVector3& dir, - F32* intersection_a, F32* intersection_b, F32* intersection_t, BOOL two_sided); + F32& intersection_a, F32& intersection_b, F32& intersection_t, BOOL two_sided); + +BOOL LLTriangleRayIntersect(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t); +BOOL LLTriangleRayIntersectTwoSided(const LLVector4a& vert0, const LLVector4a& vert1, const LLVector4a& vert2, const LLVector4a& orig, const LLVector4a& dir, + F32& intersection_a, F32& intersection_b, F32& intersection_t); diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 8bfebcb42..c6c68e3a6 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -154,7 +154,7 @@ void LLVolumeMgr::unrefVolume(LLVolume *volumep) volume_lod_group_map_t::iterator iter = mVolumeLODGroups.find(params); if( iter == mVolumeLODGroups.end() ) { - llerrs << "Warning! Tried to cleanup unknown volume type! " << *params << llendl; + llwarns << "Warning! Tried to cleanup unknown volume type! " << *params << llendl; if (mDataMutex) { mDataMutex->unlock(); @@ -320,7 +320,7 @@ BOOL LLVolumeLODGroup::derefLOD(LLVolume *volumep) { llassert_always(mLODRefs[i] > 0); mLODRefs[i]--; -#if 1 // SJB: Possible opt: keep other lods around +#if 0 // SJB: Possible opt: keep other lods around if (!mLODRefs[i]) { mVolumeLODs[i] = NULL; @@ -375,6 +375,19 @@ F32 LLVolumeLODGroup::getVolumeScaleFromDetail(const S32 detail) return mDetailScales[detail]; } +S32 LLVolumeLODGroup::getVolumeDetailFromScale(const F32 detail) +{ + for (S32 i = 1; i < 4; i++) + { + if (mDetailScales[i] > detail) + { + return i-1; + } + } + + return 3; +} + F32 LLVolumeLODGroup::dump() { F32 usage = 0.f; diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h index e10ad94db..f5dc4cd74 100644 --- a/indra/llmath/llvolumemgr.h +++ b/indra/llmath/llvolumemgr.h @@ -36,7 +36,7 @@ #include #include "llvolume.h" -#include "llmemory.h" +#include "llpointer.h" #include "llthread.h" class LLVolumeParams; @@ -59,6 +59,7 @@ public: static S32 getDetailFromTan(const F32 tan_angle); static void getDetailProximity(const F32 tan_angle, F32 &to_lower, F32& to_higher); static F32 getVolumeScaleFromDetail(const S32 detail); + static S32 getVolumeDetailFromScale(F32 scale); LLVolume* refLOD(const S32 detail); BOOL derefLOD(LLVolume *volumep); @@ -92,8 +93,8 @@ public: // whatever calls getVolume() never owns the LLVolume* and // cannot keep references for long since it may be deleted // later. For best results hold it in an LLPointer. - LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail); - void unrefVolume(LLVolume *volumep); + virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail); + virtual void unrefVolume(LLVolume *volumep); void dump(); diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp new file mode 100644 index 000000000..a420c8e51 --- /dev/null +++ b/indra/llmath/llvolumeoctree.cpp @@ -0,0 +1,255 @@ +/** + + * @file llvolumeoctree.cpp + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llvolumeoctree.h" +#include "llvector4a.h" + +BOOL LLLineSegmentBoxIntersect(const LLVector4a& start, const LLVector4a& end, const LLVector4a& center, const LLVector4a& size) +{ + LLVector4a fAWdU; + LLVector4a dir; + LLVector4a diff; + + dir.setSub(end, start); + dir.mul(0.5f); + + diff.setAdd(end,start); + diff.mul(0.5f); + diff.sub(center); + fAWdU.setAbs(dir); + + LLVector4a rhs; + rhs.setAdd(size, fAWdU); + + LLVector4a lhs; + lhs.setAbs(diff); + + U32 grt = lhs.greaterThan(rhs).getGatheredBits(); + + if (grt & 0x7) + { + return false; + } + + LLVector4a f; + f.setCross3(dir, diff); + f.setAbs(f); + + LLVector4a v0, v1; + + v0 = _mm_shuffle_ps(size, size,_MM_SHUFFLE(3,0,0,1)); + v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,1,2,2)); + lhs.setMul(v0, v1); + + v0 = _mm_shuffle_ps(size, size, _MM_SHUFFLE(3,1,2,2)); + v1 = _mm_shuffle_ps(fAWdU, fAWdU, _MM_SHUFFLE(3,0,0,1)); + rhs.setMul(v0, v1); + rhs.add(lhs); + + grt = f.greaterThan(rhs).getGatheredBits(); + + return (grt & 0x7) ? false : true; +} + +LLVolumeOctreeListener::LLVolumeOctreeListener(LLOctreeNode* node) +{ + node->addListener(this); +} + +LLVolumeOctreeListener::~LLVolumeOctreeListener() +{ + +} + +void LLVolumeOctreeListener::handleChildAddition(const LLOctreeNode* parent, + LLOctreeNode* child) +{ + new LLVolumeOctreeListener(child); +} + + +LLOctreeTriangleRayIntersect::LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, + const LLVolumeFace* face, F32* closest_t, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal) + : mFace(face), + mStart(start), + mDir(dir), + mIntersection(intersection), + mTexCoord(tex_coord), + mNormal(normal), + mBinormal(bi_normal), + mClosestT(closest_t), + mHitFace(false) +{ + mEnd.setAdd(mStart, mDir); +} + +void LLOctreeTriangleRayIntersect::traverse(const LLOctreeNode* node) +{ + LLVolumeOctreeListener* vl = (LLVolumeOctreeListener*) node->getListener(0); + + /*const F32* start = mStart.getF32(); + const F32* end = mEnd.getF32(); + const F32* center = vl->mBounds[0].getF32(); + const F32* size = vl->mBounds[1].getF32();*/ + + //if (LLLineSegmentBoxIntersect(mStart, mEnd, vl->mBounds[0], vl->mBounds[1])) + if (LLLineSegmentBoxIntersect(mStart.getF32ptr(), mEnd.getF32ptr(), vl->mBounds[0].getF32ptr(), vl->mBounds[1].getF32ptr())) + { + node->accept(this); + for (U32 i = 0; i < node->getChildCount(); ++i) + { + traverse(node->getChild(i)); + } + } +} + +void LLOctreeTriangleRayIntersect::visit(const LLOctreeNode* node) +{ + for (LLOctreeNode::const_element_iter iter = + node->getData().begin(); iter != node->getData().end(); ++iter) + { + const LLVolumeTriangle* tri = *iter; + + F32 a, b, t; + + if (LLTriangleRayIntersect(*tri->mV[0], *tri->mV[1], *tri->mV[2], + mStart, mDir, a, b, t)) + { + if ((t >= 0.f) && // if hit is after start + (t <= 1.f) && // and before end + (t < *mClosestT)) // and this hit is closer + { + *mClosestT = t; + mHitFace = true; + + if (mIntersection != NULL) + { + LLVector4a intersect = mDir; + intersect.mul(*mClosestT); + intersect.add(mStart); + mIntersection->set(intersect.getF32ptr()); + } + + + if (mTexCoord != NULL) + { + LLVector2* tc = (LLVector2*) mFace->mTexCoords; + *mTexCoord = ((1.f - a - b) * tc[tri->mIndex[0]] + + a * tc[tri->mIndex[1]] + + b * tc[tri->mIndex[2]]); + + } + + if (mNormal != NULL) + { + LLVector4* norm = (LLVector4*) mFace->mNormals; + + *mNormal = ((1.f - a - b) * LLVector3(norm[tri->mIndex[0]]) + + a * LLVector3(norm[tri->mIndex[1]]) + + b * LLVector3(norm[tri->mIndex[2]])); + } + + if (mBinormal != NULL) + { + LLVector4* binormal = (LLVector4*) mFace->mBinormals; + *mBinormal = ((1.f - a - b) * LLVector3(binormal[tri->mIndex[0]]) + + a * LLVector3(binormal[tri->mIndex[1]]) + + b * LLVector3(binormal[tri->mIndex[2]])); + } + } + } + } +} + +const LLVector4a& LLVolumeTriangle::getPositionGroup() const +{ + return mPositionGroup; +} + +const F32& LLVolumeTriangle::getBinRadius() const +{ + return mRadius; +} + + +//TEST CODE + +void LLVolumeOctreeValidate::visit(const LLOctreeNode* branch) +{ + LLVolumeOctreeListener* node = (LLVolumeOctreeListener*) branch->getListener(0); + + //make sure bounds matches extents + LLVector4a& min = node->mExtents[0]; + LLVector4a& max = node->mExtents[1]; + + LLVector4a& center = node->mBounds[0]; + LLVector4a& size = node->mBounds[1]; + + LLVector4a test_min, test_max; + test_min.setSub(center, size); + test_max.setAdd(center, size); + + if (!test_min.equals3(min, 0.001f) || + !test_max.equals3(max, 0.001f)) + { + llerrs << "Bad bounding box data found." << llendl; + } + + test_min.sub(LLVector4a(0.001f)); + test_max.add(LLVector4a(0.001f)); + + for (U32 i = 0; i < branch->getChildCount(); ++i) + { + LLVolumeOctreeListener* child = (LLVolumeOctreeListener*) branch->getChild(i)->getListener(0); + + //make sure all children fit inside this node + if (child->mExtents[0].lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ) || + child->mExtents[1].greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ)) + { + llerrs << "Child protrudes from bounding box." << llendl; + } + } + + //children fit, check data + for (LLOctreeNode::const_element_iter iter = branch->getData().begin(); + iter != branch->getData().end(); ++iter) + { + const LLVolumeTriangle* tri = *iter; + + //validate triangle + for (U32 i = 0; i < 3; i++) + { + if (tri->mV[i]->greaterThan(test_max).areAnySet(LLVector4Logical::MASK_XYZ) || + tri->mV[i]->lessThan(test_min).areAnySet(LLVector4Logical::MASK_XYZ)) + { + llerrs << "Triangle protrudes from node." << llendl; + } + } + } +} + + diff --git a/indra/llmath/llvolumeoctree.h b/indra/llmath/llvolumeoctree.h new file mode 100644 index 000000000..688d91dc4 --- /dev/null +++ b/indra/llmath/llvolumeoctree.h @@ -0,0 +1,134 @@ +/** + * @file llvolumeoctree.h + * @brief LLVolume octree classes. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLVOLUME_OCTREE_H +#define LL_LLVOLUME_OCTREE_H + +#include "linden_common.h" +#include "llmemory.h" + +#include "lloctree.h" +#include "llvolume.h" +#include "llvector4a.h" + +class LLVolumeTriangle : public LLRefCount +{ +public: + LLVolumeTriangle() + { + + } + + LLVolumeTriangle(const LLVolumeTriangle& rhs) + { + *this = rhs; + } + + const LLVolumeTriangle& operator=(const LLVolumeTriangle& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + + ~LLVolumeTriangle() + { + + } + + LLVector4a mPositionGroup; + + const LLVector4a* mV[3]; + U16 mIndex[3]; + + F32 mRadius; + + virtual const LLVector4a& getPositionGroup() const; + virtual const F32& getBinRadius() const; +}; + +class LLVolumeOctreeListener : public LLOctreeListener +{ +public: + + LLVolumeOctreeListener(LLOctreeNode* node); + ~LLVolumeOctreeListener(); + + LLVolumeOctreeListener(const LLVolumeOctreeListener& rhs) + { + *this = rhs; + } + + const LLVolumeOctreeListener& operator=(const LLVolumeOctreeListener& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + + //LISTENER FUNCTIONS + virtual void handleChildAddition(const LLOctreeNode* parent, + LLOctreeNode* child); + virtual void handleStateChange(const LLTreeNode* node) { } + virtual void handleChildRemoval(const LLOctreeNode* parent, + const LLOctreeNode* child) { } + virtual void handleInsertion(const LLTreeNode* node, LLVolumeTriangle* tri) { } + virtual void handleRemoval(const LLTreeNode* node, LLVolumeTriangle* tri) { } + virtual void handleDestruction(const LLTreeNode* node) { } + + +public: + LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) + LLVector4a mExtents[2]; // extents (min, max) of this node and all its children +}; + +class LLOctreeTriangleRayIntersect : public LLOctreeTraveler +{ +public: + const LLVolumeFace* mFace; + LLVector4a mStart; + LLVector4a mDir; + LLVector4a mEnd; + LLVector3* mIntersection; + LLVector2* mTexCoord; + LLVector3* mNormal; + LLVector3* mBinormal; + F32* mClosestT; + bool mHitFace; + + LLOctreeTriangleRayIntersect(const LLVector4a& start, const LLVector4a& dir, + const LLVolumeFace* face, F32* closest_t, + LLVector3* intersection,LLVector2* tex_coord, LLVector3* normal, LLVector3* bi_normal); + + void traverse(const LLOctreeNode* node); + + virtual void visit(const LLOctreeNode* node); +}; + +class LLVolumeOctreeValidate : public LLOctreeTraveler +{ + virtual void visit(const LLOctreeNode* branch); +}; + +#endif diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp index 220336e0c..2603127f7 100644 --- a/indra/llmath/v2math.cpp +++ b/indra/llmath/v2math.cpp @@ -92,7 +92,7 @@ F32 dist_vec(const LLVector2 &a, const LLVector2 &b) { F32 x = a.mV[0] - b.mV[0]; F32 y = a.mV[1] - b.mV[1]; - return fsqrtf( x*x + y*y ); + return (F32) sqrt( x*x + y*y ); } F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b) diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h index ae26c85ce..35fd1b604 100644 --- a/indra/llmath/v2math.h +++ b/indra/llmath/v2math.h @@ -225,7 +225,7 @@ inline void LLVector2::setVec(const F32 *vec) inline F32 LLVector2::length(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); } inline F32 LLVector2::lengthSquared(void) const @@ -235,7 +235,7 @@ inline F32 LLVector2::lengthSquared(void) const inline F32 LLVector2::normalize(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -262,7 +262,7 @@ inline bool LLVector2::isFinite() const // deprecated inline F32 LLVector2::magVec(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); } // deprecated @@ -274,7 +274,7 @@ inline F32 LLVector2::magVecSquared(void) const // deprecated inline F32 LLVector2::normVec(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]); F32 oomag; if (mag > FP_MAG_THRESHOLD) diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h index 1915d8050..95a3de8b6 100644 --- a/indra/llmath/v3color.h +++ b/indra/llmath/v3color.h @@ -284,7 +284,7 @@ inline F32 LLColor3::brightness(void) const inline F32 LLColor3::length(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } inline F32 LLColor3::lengthSquared(void) const @@ -294,7 +294,7 @@ inline F32 LLColor3::lengthSquared(void) const inline F32 LLColor3::normalize(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); F32 oomag; if (mag) @@ -310,7 +310,7 @@ inline F32 LLColor3::normalize(void) // deprecated inline F32 LLColor3::magVec(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } // deprecated @@ -322,7 +322,7 @@ inline F32 LLColor3::magVecSquared(void) const // deprecated inline F32 LLColor3::normVec(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); F32 oomag; if (mag) @@ -444,7 +444,7 @@ inline F32 distVec(const LLColor3 &a, const LLColor3 &b) F32 x = a.mV[0] - b.mV[0]; F32 y = a.mV[1] - b.mV[1]; F32 z = a.mV[2] - b.mV[2]; - return fsqrtf( x*x + y*y + z*z ); + return (F32) sqrt( x*x + y*y + z*z ); } inline F32 distVec_squared(const LLColor3 &a, const LLColor3 &b) diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h index 96ae27a52..211b0b91a 100644 --- a/indra/llmath/v3dmath.h +++ b/indra/llmath/v3dmath.h @@ -240,7 +240,7 @@ inline const LLVector3d& LLVector3d::setVec(const F64 *vec) inline F64 LLVector3d::normVec(void) { - F64 mag = fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); F64 oomag; if (mag > FP_MAG_THRESHOLD) @@ -262,7 +262,7 @@ inline F64 LLVector3d::normVec(void) inline F64 LLVector3d::normalize(void) { - F64 mag = fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); F64 oomag; if (mag > FP_MAG_THRESHOLD) @@ -286,7 +286,7 @@ inline F64 LLVector3d::normalize(void) inline F64 LLVector3d::magVec(void) const { - return fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); } inline F64 LLVector3d::magVecSquared(void) const @@ -296,7 +296,7 @@ inline F64 LLVector3d::magVecSquared(void) const inline F64 LLVector3d::length(void) const { - return fsqrtf(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); + return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]); } inline F64 LLVector3d::lengthSquared(void) const @@ -406,7 +406,7 @@ inline F64 dist_vec(const LLVector3d &a, const LLVector3d &b) F64 x = a.mdV[0] - b.mdV[0]; F64 y = a.mdV[1] - b.mdV[1]; F64 z = a.mdV[2] - b.mdV[2]; - return fsqrtf( x*x + y*y + z*z ); + return (F32) sqrt( x*x + y*y + z*z ); } inline F64 dist_vec_squared(const LLVector3d &a, const LLVector3d &b) diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h index 1cfa1edaa..b87db741b 100644 --- a/indra/llmath/v3math.h +++ b/indra/llmath/v3math.h @@ -285,7 +285,7 @@ inline void LLVector3::setVec(const F32 *vec) inline F32 LLVector3::normalize(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -308,7 +308,7 @@ inline F32 LLVector3::normalize(void) // deprecated inline F32 LLVector3::normVec(void) { - F32 mag = fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -332,7 +332,7 @@ inline F32 LLVector3::normVec(void) inline F32 LLVector3::length(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } inline F32 LLVector3::lengthSquared(void) const @@ -342,7 +342,7 @@ inline F32 LLVector3::lengthSquared(void) const inline F32 LLVector3::magVec(void) const { - return fsqrtf(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); + return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]); } inline F32 LLVector3::magVecSquared(void) const @@ -476,7 +476,7 @@ inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b) F32 x = a.mV[0] - b.mV[0]; F32 y = a.mV[1] - b.mV[1]; F32 z = a.mV[2] - b.mV[2]; - return fsqrtf( x*x + y*y + z*z ); + return (F32) sqrt( x*x + y*y + z*z ); } inline F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b) diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index f5a9adcfc..3a4f8475c 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -392,7 +392,7 @@ inline const LLColor4& LLColor4::setAlpha(F32 a) inline F32 LLColor4::length(void) const { - return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } inline F32 LLColor4::lengthSquared(void) const @@ -402,7 +402,7 @@ inline F32 LLColor4::lengthSquared(void) const inline F32 LLColor4::normalize(void) { - F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag) @@ -418,7 +418,7 @@ inline F32 LLColor4::normalize(void) // deprecated inline F32 LLColor4::magVec(void) const { - return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } // deprecated @@ -430,7 +430,7 @@ inline F32 LLColor4::magVecSquared(void) const // deprecated inline F32 LLColor4::normVec(void) { - F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag) diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h index ae0d707f9..8b7df774e 100644 --- a/indra/llmath/v4coloru.h +++ b/indra/llmath/v4coloru.h @@ -300,7 +300,7 @@ inline const LLColor4U& LLColor4U::setAlpha(U8 a) inline F32 LLColor4U::length(void) const { - return fsqrtf( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); + return (F32) sqrt( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); } inline F32 LLColor4U::lengthSquared(void) const @@ -311,7 +311,7 @@ inline F32 LLColor4U::lengthSquared(void) const // deprecated inline F32 LLColor4U::magVec(void) const { - return fsqrtf( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); + return (F32) sqrt( ((F32)mV[VX]) * mV[VX] + ((F32)mV[VY]) * mV[VY] + ((F32)mV[VZ]) * mV[VZ] ); } // deprecated diff --git a/indra/llmath/v4math.h b/indra/llmath/v4math.h index 4c82e6b62..72a477ed2 100644 --- a/indra/llmath/v4math.h +++ b/indra/llmath/v4math.h @@ -321,7 +321,7 @@ inline void LLVector4::setVec(const F32 *vec) inline F32 LLVector4::length(void) const { - return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } inline F32 LLVector4::lengthSquared(void) const @@ -331,7 +331,7 @@ inline F32 LLVector4::lengthSquared(void) const inline F32 LLVector4::magVec(void) const { - return fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + return (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); } inline F32 LLVector4::magVecSquared(void) const @@ -463,7 +463,7 @@ inline LLVector4 lerp(const LLVector4 &a, const LLVector4 &b, F32 u) inline F32 LLVector4::normalize(void) { - F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag > FP_MAG_THRESHOLD) @@ -486,7 +486,7 @@ inline F32 LLVector4::normalize(void) // deprecated inline F32 LLVector4::normVec(void) { - F32 mag = fsqrtf(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); + F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]); F32 oomag; if (mag > FP_MAG_THRESHOLD) diff --git a/indra/llmath/xform.h b/indra/llmath/xform.h index 05ee8b9ce..70b2a8375 100644 --- a/indra/llmath/xform.h +++ b/indra/llmath/xform.h @@ -39,6 +39,9 @@ const F32 MAX_OBJECT_Z = 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f const F32 MIN_OBJECT_Z = -256.f; const F32 DEFAULT_MAX_PRIM_SCALE = 256.f; +#if MESH_ENABLED +const F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = DEFAULT_MAX_PRIM_SCALE; +#endif //MESH_ENABLED const F32 MIN_PRIM_SCALE = 0.01f; const F32 MAX_PRIM_SCALE = 65536.f; // something very high but not near FLT_MAX diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 6b8e86b94..16ddce622 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -92,6 +92,9 @@ std::vector LLCurl::sSSLMutex; std::string LLCurl::sCAPath; std::string LLCurl::sCAFile; +bool LLCurl::sMultiThreaded = false; +static U32 sMainThreadID = 0; + void check_curl_code(CURLcode code) { if (code != CURLE_OK) @@ -250,7 +253,7 @@ public: U32 report(CURLcode); void getTransferInfo(LLCurl::TransferInfo* info); - void prepRequest(const std::string& url, const std::vector& headers, ResponderPtr, bool post = false); + void prepRequest(const std::string& url, const std::vector& headers, ResponderPtr, S32 time_out = 0, bool post = false); const char* getErrorBuffer(); @@ -549,7 +552,7 @@ size_t curlHeaderCallback(void* data, size_t size, size_t nmemb, void* user_data void LLCurl::Easy::prepRequest(const std::string& url, const std::vector& headers, - ResponderPtr responder, bool post) + ResponderPtr responder, S32 time_out, bool post) { resetState(); @@ -599,7 +602,7 @@ void LLCurl::Easy::prepRequest(const std::string& url, //don't verify host name so urls with scrubbed host names will work (improves DNS performance) setopt(CURLOPT_SSL_VERIFYHOST, 0); - setopt(CURLOPT_TIMEOUT, CURL_REQUEST_TIMEOUT); + setopt(CURLOPT_TIMEOUT, llmax(time_out, CURL_REQUEST_TIMEOUT)); setoptString(CURLOPT_URL, url); @@ -620,11 +623,18 @@ void LLCurl::Easy::prepRequest(const std::string& url, //////////////////////////////////////////////////////////////////////////// -class LLCurl::Multi +class LLCurl::Multi : public LLThread { LOG_CLASS(Multi); public: - + + typedef enum + { + PERFORM_STATE_READY=0, + PERFORM_STATE_PERFORMING=1, + PERFORM_STATE_COMPLETED=2 + } ePerformState; + Multi(); ~Multi(); @@ -634,13 +644,22 @@ public: void removeEasy(Easy* easy); S32 process(); - S32 perform(); + void perform(); + void doPerform(); + virtual void run(); + CURLMsg* info_read(S32* msgs_in_queue); S32 mQueued; S32 mErrorCount; + S32 mPerformState; + + LLCondition* mSignal; + bool mQuitting; + bool mThreaded; + private: void easyFree(Easy*); @@ -655,21 +674,41 @@ private: }; LLCurl::Multi::Multi() - : mQueued(0), - mErrorCount(0) + : LLThread("Curl Multi"), + mQueued(0), + mErrorCount(0), + mPerformState(PERFORM_STATE_READY) { + mQuitting = false; + + mThreaded = LLCurl::sMultiThreaded && LLThread::currentID() == sMainThreadID; + if (mThreaded) + { + mSignal = new LLCondition; + } + else + { + mSignal = NULL; + } + mCurlMultiHandle = curl_multi_init(); if (!mCurlMultiHandle) { llwarns << "curl_multi_init() returned NULL! Easy handles: " << gCurlEasyCount << " Multi handles: " << gCurlMultiCount << llendl; mCurlMultiHandle = curl_multi_init(); } + llassert_always(mCurlMultiHandle); ++gCurlMultiCount; } LLCurl::Multi::~Multi() { + llassert(isStopped()); + + delete mSignal; + mSignal = NULL; + // Clean up active for(easy_active_list_t::iterator iter = mEasyActiveList.begin(); iter != mEasyActiveList.end(); ++iter) @@ -695,13 +734,48 @@ CURLMsg* LLCurl::Multi::info_read(S32* msgs_in_queue) return curlmsg; } +void LLCurl::Multi::perform() +{ + if (mThreaded) + { + mSignal->lock(); + if (mPerformState == PERFORM_STATE_READY) + { + mSignal->signal(); + } + mSignal->unlock(); + } + else + { + doPerform(); + } +} -S32 LLCurl::Multi::perform() +void LLCurl::Multi::run() +{ + llassert(mThreaded); + + mSignal->lock(); + while (!mQuitting) + { + mSignal->wait(); + mPerformState = PERFORM_STATE_PERFORMING; + if (!mQuitting) + { + doPerform(); + } + } + mSignal->unlock(); +} + +void LLCurl::Multi::doPerform() { S32 q = 0; + if (mThreaded) + mSignal->unlock(); for (S32 call_count = 0; - call_count < MULTI_PERFORM_CALL_REPEAT; - call_count += 1) + call_count < MULTI_PERFORM_CALL_REPEAT; + call_count += 1) { CURLMcode code = curl_multi_perform(mCurlMultiHandle, &q); if (CURLM_CALL_MULTI_PERFORM != code || q == 0) @@ -711,14 +785,21 @@ S32 LLCurl::Multi::perform() } } + if (mThreaded) + mSignal->lock(); mQueued = q; - return q; + mPerformState = PERFORM_STATE_COMPLETED; } S32 LLCurl::Multi::process() { perform(); - + + if (mPerformState != PERFORM_STATE_COMPLETED) + { + return 0; + } + CURLMsg* msg; int msgs_in_queue; @@ -749,6 +830,8 @@ S32 LLCurl::Multi::process() } } } + + mPerformState = PERFORM_STATE_READY; return processed; } @@ -827,6 +910,27 @@ LLCurlRequest::LLCurlRequest() : LLCurlRequest::~LLCurlRequest() { llassert_always(mThreadID == LLThread::currentID()); + + //stop all Multi handle background threads + for (curlmulti_set_t::iterator iter = mMultiSet.begin(); iter != mMultiSet.end(); ++iter) + { + LLCurl::Multi* multi = *iter; + if (multi->mThreaded) + multi->mSignal->lock(); + multi->mQuitting = true; + if (multi->mThreaded) + { + while (!multi->isStopped()) + { + multi->mSignal->signal(); + multi->mSignal->unlock(); + apr_sleep(1000); + multi->mSignal->lock(); + } + } + if (multi->mThreaded) + multi->mSignal->unlock(); + } for_each(mMultiSet.begin(), mMultiSet.end(), DeletePointer()); } @@ -834,6 +938,10 @@ void LLCurlRequest::addMulti() { llassert_always(mThreadID == LLThread::currentID()); LLCurl::Multi* multi = new LLCurl::Multi(); + if (multi->mThreaded) + { + multi->start(); + } mMultiSet.insert(multi); mActiveMulti = multi; mActiveRequestCount = 0; @@ -895,14 +1003,14 @@ bool LLCurlRequest::getByteRange(const std::string& url, bool LLCurlRequest::post(const std::string& url, const headers_t& headers, const LLSD& data, - LLCurl::ResponderPtr responder) + LLCurl::ResponderPtr responder, S32 time_out) { LLCurl::Easy* easy = allocEasy(); if (!easy) { return false; } - easy->prepRequest(url, headers, responder); + easy->prepRequest(url, headers, responder, time_out); LLSDSerialize::toXML(data, easy->getInput()); S32 bytes = easy->getInput().str().length(); @@ -922,14 +1030,14 @@ bool LLCurlRequest::post(const std::string& url, bool LLCurlRequest::post(const std::string& url, const headers_t& headers, const std::string& data, - LLCurl::ResponderPtr responder) + LLCurl::ResponderPtr responder, S32 time_out) { LLCurl::Easy* easy = allocEasy(); if (!easy) { return false; } - easy->prepRequest(url, headers, responder); + easy->prepRequest(url, headers, responder, time_out); easy->getInput().write(data.data(), data.size()); S32 bytes = easy->getInput().str().length(); @@ -963,6 +1071,22 @@ S32 LLCurlRequest::process() if (multi != mActiveMulti && tres == 0 && multi->mQueued == 0) { mMultiSet.erase(curiter); + if (multi->mThreaded) + multi->mSignal->lock(); + multi->mQuitting = true; + if (multi->mThreaded) + { + while (!multi->isStopped()) + { + multi->mSignal->signal(); + multi->mSignal->unlock(); + apr_sleep(1000); + multi->mSignal->unlock(); + } + } + if (multi->mThreaded) + multi->mSignal->unlock(); + delete multi; } } @@ -980,6 +1104,10 @@ S32 LLCurlRequest::getQueued() curlmulti_set_t::iterator curiter = iter++; LLCurl::Multi* multi = *curiter; queued += multi->mQueued; + if (multi->mPerformState != LLCurl::Multi::PERFORM_STATE_READY) + { + ++queued; + } } return queued; } @@ -993,6 +1121,10 @@ LLCurlEasyRequest::LLCurlEasyRequest() mResultReturned(false) { mMulti = new LLCurl::Multi(); + if (mMulti->mThreaded) + { + mMulti->start(); + } mEasy = mMulti->allocEasy(); if (mEasy) { @@ -1003,6 +1135,21 @@ LLCurlEasyRequest::LLCurlEasyRequest() LLCurlEasyRequest::~LLCurlEasyRequest() { + if (mMulti->mThreaded) + mMulti->mSignal->lock(); + mMulti->mQuitting = true; + if (mMulti->mThreaded) + { + while (!mMulti->isStopped()) + { + mMulti->mSignal->signal(); + mMulti->mSignal->unlock(); + apr_sleep(1000); + mMulti->mSignal->lock(); + } + } + if (mMulti->mThreaded) + mMulti->mSignal->unlock(); delete mMulti; } @@ -1099,14 +1246,20 @@ void LLCurlEasyRequest::requestComplete() } } -S32 LLCurlEasyRequest::perform() +void LLCurlEasyRequest::perform() { - return mMulti->perform(); + mMulti->perform(); } // Usage: Call getRestult until it returns false (no more messages) bool LLCurlEasyRequest::getResult(CURLcode* result, LLCurl::TransferInfo* info) { + if (mMulti->mPerformState != LLCurl::Multi::PERFORM_STATE_COMPLETED) + { //we're busy, try again later + return false; + } + mMulti->mPerformState = LLCurl::Multi::PERFORM_STATE_READY; + if (!mEasy) { // Special case - we failed to initialize a curl_easy (can happen if too many open files) @@ -1191,8 +1344,10 @@ unsigned long LLCurl::ssl_thread_id(void) } #endif -void LLCurl::initClass() +void LLCurl::initClass(bool multi_threaded) { + sMainThreadID = LLThread::currentID(); + sMultiThreaded = multi_threaded; // Do not change this "unless you are familiar with and mean to control // internal operations of libcurl" // - http://curl.haxx.se/libcurl/c/curl_global_init.html diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 084408c70..73516803f 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -47,6 +47,7 @@ #include "llbuffer.h" #include "lliopipe.h" #include "llsd.h" +#include "llthread.h" class LLMutex; @@ -61,6 +62,8 @@ public: class Easy; class Multi; + static bool sMultiThreaded; + struct TransferInfo { TransferInfo() : mSizeDownload(0.0), mTotalTime(0.0), mSpeedDownload(0.0) {} @@ -164,7 +167,7 @@ public: /** * @ brief Initialize LLCurl class */ - static void initClass(); + static void initClass(bool multi_threaded = false); /** * @ brief Cleanup LLCurl class @@ -206,8 +209,8 @@ public: void get(const std::string& url, LLCurl::ResponderPtr responder); bool getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, LLCurl::ResponderPtr responder); - bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder); - bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder); + bool post(const std::string& url, const headers_t& headers, const LLSD& data, LLCurl::ResponderPtr responder, S32 time_out = 0); + bool post(const std::string& url, const headers_t& headers, const std::string& data, LLCurl::ResponderPtr responder, S32 time_out = 0); S32 process(); S32 getQueued(); @@ -241,7 +244,7 @@ public: void slist_append(const char* str); void sendRequest(const std::string& url); void requestComplete(); - S32 perform(); + void perform(); bool getResult(CURLcode* result, LLCurl::TransferInfo* info = NULL); std::string getErrorString(); diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h index 7b7e18762..2c0fe8655 100644 --- a/indra/llmessage/llhttpnode.h +++ b/indra/llmessage/llhttpnode.h @@ -33,7 +33,8 @@ #ifndef LL_LLHTTPNODE_H #define LL_LLHTTPNODE_H -#include "llmemory.h" +#include "llpointer.h" +#include "llrefcount.h" #include "llsd.h" class LLChainIOFactory; diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index 018b649a6..57e8a2254 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -41,7 +41,7 @@ #include "llsd.h" #include "llsdserialize.h" #include "llsdutil_math.h" -#include "llmemory.h" +#include "llpointer.h" #include "message.h" #include "message.h" diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index df8e0bebf..dfc193301 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -36,7 +36,8 @@ #include "llhost.h" #include "lluuid.h" #include "llsd.h" -#include "llmemory.h" +#include "llrefcount.h" +#include "llpointer.h" #include "v3math.h" class LLMessageSystem; diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index c50dcc876..7a10c0fa6 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -1147,9 +1147,7 @@ void LLPumpIO::LLChainInfo::setTimeoutSeconds(F32 timeout) LLMemType m1(LLMemType::MTYPE_IO_PUMP); if(timeout > 0.0f) { - mTimer.start(); - mTimer.reset(); - mTimer.setTimerExpirySec(timeout); + mTimer.start(timeout); } else { diff --git a/indra/llmessage/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp index 93de1b13d..3bcbb070e 100644 --- a/indra/llmessage/lltemplatemessagereader.cpp +++ b/indra/llmessage/lltemplatemessagereader.cpp @@ -434,10 +434,9 @@ inline void LLTemplateMessageReader::getString(const char *block, const char *va inline void LLTemplateMessageReader::getString(const char *block, const char *var, std::string& outstr, S32 blocknum ) { - char s[MTUBYTES]; - s[0] = '\0'; + char s[MTUBYTES + 1]= {0}; // every element is initialized with 0 getData(block, var, s, 0, blocknum, MTUBYTES); - s[MTUBYTES - 1] = '\0'; + s[MTUBYTES] = '\0'; outstr = s; } diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 892547cab..855d1cccf 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -588,6 +588,8 @@ char* _PREHASH_LastName = LLMessageStringTable::getInstance()->getString("LastNa char* _PREHASH_From = LLMessageStringTable::getInstance()->getString("From"); char* _PREHASH_RoleChange = LLMessageStringTable::getInstance()->getString("RoleChange"); char* _PREHASH_Port = LLMessageStringTable::getInstance()->getString("Port"); +char* _PREHASH_RegionSizeX = LLMessageStringTable::getInstance()->getString("RegionSizeX"); +char* _PREHASH_RegionSizeY = LLMessageStringTable::getInstance()->getString("RegionSizeY"); char* _PREHASH_MemberTitle = LLMessageStringTable::getInstance()->getString("MemberTitle"); char* _PREHASH_LogParcelChanges = LLMessageStringTable::getInstance()->getString("LogParcelChanges"); char* _PREHASH_AgentCachedTextureResponse = LLMessageStringTable::getInstance()->getString("AgentCachedTextureResponse"); diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h index 4bf89e513..77cfe710a 100644 --- a/indra/llmessage/message_prehash.h +++ b/indra/llmessage/message_prehash.h @@ -588,6 +588,8 @@ extern char * _PREHASH_LastName; extern char * _PREHASH_From; extern char * _PREHASH_RoleChange; extern char * _PREHASH_Port; +extern char * _PREHASH_RegionSizeX; +extern char * _PREHASH_RegionSizeY; extern char * _PREHASH_MemberTitle; extern char * _PREHASH_LogParcelChanges; extern char * _PREHASH_AgentCachedTextureResponse; diff --git a/indra/llmessage/patch_code.cpp b/indra/llmessage/patch_code.cpp index 90fb23634..12ed19ea4 100644 --- a/indra/llmessage/patch_code.cpp +++ b/indra/llmessage/patch_code.cpp @@ -235,7 +235,7 @@ void decode_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp) gPatchSize = gopp->patch_size; } -void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph) +void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph, BOOL b_large_patch) { U8 retvalu8; @@ -274,15 +274,18 @@ void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph) #endif ph->range = retvalu16; - retvalu16 = 0; + retvalu32 = 0; #ifdef LL_BIG_ENDIAN ret = (U8 *)&retvalu16; bitpack.bitUnpack(&(ret[1]), 8); bitpack.bitUnpack(&(ret[0]), 2); #else - bitpack.bitUnpack((U8 *)&retvalu16, 10); + if (b_large_patch) + bitpack.bitUnpack((U8 *)&retvalu32, 32); + else + bitpack.bitUnpack((U8 *)&retvalu32, 10); #endif - ph->patchids = retvalu16; + ph->patchids = retvalu32; gWordBits = (ph->quant_wbits & 0xf) + 2; } diff --git a/indra/llmessage/patch_code.h b/indra/llmessage/patch_code.h index 82fa6bb62..dbfdf7059 100644 --- a/indra/llmessage/patch_code.h +++ b/indra/llmessage/patch_code.h @@ -46,7 +46,7 @@ void end_patch_coding(LLBitPack &bitpack); void init_patch_decoding(LLBitPack &bitpack); void decode_patch_group_header(LLBitPack &bitpack, LLGroupHeader *gopp); -void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph); +void decode_patch_header(LLBitPack &bitpack, LLPatchHeader *ph, BOOL b_large_patch); void decode_patch(LLBitPack &bitpack, S32 *patches); #endif diff --git a/indra/llmessage/patch_dct.h b/indra/llmessage/patch_dct.h index 663e146a8..ba21be711 100644 --- a/indra/llmessage/patch_dct.h +++ b/indra/llmessage/patch_dct.h @@ -79,7 +79,7 @@ public: F32 dc_offset; // 4 bytes U16 range; // 2 = 7 ((S16) FP range (breaks if we need > 32K meters in 1 patch) U8 quant_wbits; // 1 = 8 (upper 4 bits is quant - 2, lower 4 bits is word bits - 2) - U16 patchids; // 2 = 10 (actually only uses 10 bits, 5 for each) + U32 patchids; // 2 = 10 (actually only uses 10 bits, 5 for each) }; // Compression routines diff --git a/indra/llmessage/sound_ids.cpp b/indra/llmessage/sound_ids.cpp index 9262a33b3..7e0fec493 100644 --- a/indra/llmessage/sound_ids.cpp +++ b/indra/llmessage/sound_ids.cpp @@ -29,6 +29,7 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ +#include "linden_common.h" #include "sound_ids.h" diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp index c8b903e58..de208cb44 100644 --- a/indra/llplugin/llpluginclassmedia.cpp +++ b/indra/llplugin/llpluginclassmedia.cpp @@ -122,7 +122,10 @@ void LLPluginClassMedia::reset_impl(void) mStatusText.clear(); mProgressPercent = 0; mClickURL.clear(); + mClickNavType.clear(); mClickTarget.clear(); + mClickUUID.clear(); + mStatusCode = 0; // media_time class mCurrentTime = 0.0f; @@ -393,6 +396,94 @@ std::string LLPluginClassMedia::translateModifiers(MASK modifiers) return result; } +void LLPluginClassMedia::jsEnableObject( bool enable ) +{ + if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) + { + return; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_enable_object"); + message.setValueBoolean( "enable", enable ); + sendMessage( message ); +} + +void LLPluginClassMedia::jsAgentLocationEvent( double x, double y, double z ) +{ + if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) + { + return; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_location"); + message.setValueReal( "x", x ); + message.setValueReal( "y", y ); + message.setValueReal( "z", z ); + sendMessage( message ); +} + +void LLPluginClassMedia::jsAgentGlobalLocationEvent( double x, double y, double z ) +{ + if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) + { + return; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_global_location"); + message.setValueReal( "x", x ); + message.setValueReal( "y", y ); + message.setValueReal( "z", z ); + sendMessage( message ); +} + +void LLPluginClassMedia::jsAgentOrientationEvent( double angle ) +{ + if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) + { + return; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_orientation"); + message.setValueReal( "angle", angle ); + + sendMessage( message ); +} + +void LLPluginClassMedia::jsAgentLanguageEvent( const std::string& language ) +{ + if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) + { + return; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_language"); + message.setValue( "language", language ); + sendMessage( message ); +} + +void LLPluginClassMedia::jsAgentRegionEvent( const std::string& region ) +{ + if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) + { + return; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_region"); + message.setValue( "region", region ); + sendMessage( message ); +} + +void LLPluginClassMedia::jsAgentMaturityEvent( const std::string& maturity ) +{ + if( ! mPlugin || !mPlugin->isRunning() || mPlugin->isBlocked() ) + { + return; + } + + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "js_agent_maturity"); + message.setValue( "maturity", maturity ); + sendMessage( message ); +} void LLPluginClassMedia::mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers) { if(type == MOUSE_EVENT_MOVE) @@ -568,6 +659,32 @@ F64 LLPluginClassMedia::getCPUUsage() return result; } +void LLPluginClassMedia::sendPickFileResponse(const std::string &file) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "pick_file_response"); + message.setValue("file", file); + if(mPlugin && mPlugin->isBlocked()) + { + // If the plugin sent a blocking pick-file request, the response should unblock it. + message.setValueBoolean("blocking_response", true); + } + sendMessage(message); +} + +void LLPluginClassMedia::sendAuthResponse(bool ok, const std::string &username, const std::string &password) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "auth_response"); + message.setValueBoolean("ok", ok); + message.setValue("username", username); + message.setValue("password", password); + if(mPlugin && mPlugin->isBlocked()) + { + // If the plugin sent a blocking pick-file request, the response should unblock it. + message.setValueBoolean("blocking_response", true); + } + sendMessage(message); +} + void LLPluginClassMedia::cut() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "edit_cut"); @@ -614,6 +731,10 @@ void LLPluginClassMedia::setJavascriptEnabled(const bool enabled) sendMessage(message); } +void LLPluginClassMedia::setTarget(const std::string &target) +{ + mTarget = target; +} /* virtual */ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { @@ -828,6 +949,16 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mMediaName = message.getValue("name"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAME_CHANGED); } + else if(message_name == "pick_file") + { + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PICK_FILE_REQUEST); + } + else if(message_name == "auth_request") + { + mAuthURL = message.getValue("url"); + mAuthRealm = message.getValue("realm"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_AUTH_REQUEST); + } else { LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; @@ -870,14 +1001,21 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) { mClickURL = message.getValue("uri"); mClickTarget = message.getValue("target"); + mClickUUID = message.getValue("uuid"); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_HREF); } else if(message_name == "click_nofollow") { mClickURL = message.getValue("uri"); + mClickNavType = message.getValue("nav_type"); mClickTarget.clear(); mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLICK_LINK_NOFOLLOW); } + else if(message_name == "navigate_error_page") + { + mStatusCode = message.getValueS32("status_code"); + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_NAVIGATE_ERROR_PAGE); + } else if(message_name == "cookie_set") { if(mOwner) @@ -885,6 +1023,29 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message) mOwner->handleCookieSet(this, message.getValue("cookie")); } } + else if(message_name == "close_request") + { + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_CLOSE_REQUEST); + } + else if(message_name == "geometry_change") + { + mClickUUID = message.getValue("uuid"); + mGeometryX = message.getValueS32("x"); + mGeometryY = message.getValueS32("y"); + mGeometryWidth = message.getValueS32("width"); + mGeometryHeight = message.getValueS32("height"); + + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_GEOMETRY_CHANGE); + } + else if(message_name == "link_hovered") + { + // text is not currently used -- the tooltip hover text is taken from the "title". + mHoverLink = message.getValue("link"); + mHoverText = message.getValue("title"); + // message.getValue("text"); + + mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_LINK_HOVERED); + } else { LL_WARNS("Plugin") << "Unknown " << message_name << " class message: " << message_name << LL_ENDL; @@ -1025,6 +1186,39 @@ void LLPluginClassMedia::setBrowserUserAgent(const std::string& user_agent) sendMessage(message); } +void LLPluginClassMedia::proxyWindowOpened(const std::string &target, const std::string &uuid) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_opened"); + + message.setValue("target", target); + message.setValue("uuid", uuid); + + sendMessage(message); +} + +void LLPluginClassMedia::proxyWindowClosed(const std::string &uuid) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "proxy_window_closed"); + + message.setValue("uuid", uuid); + + sendMessage(message); +} + +void LLPluginClassMedia::ignore_ssl_cert_errors(bool ignore) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "ignore_ssl_cert_errors"); + message.setValueBoolean("ignore", ignore); + sendMessage(message); +} + +void LLPluginClassMedia::addCertificateFilePath(const std::string& path) +{ + LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER, "add_certificate_file_path"); + message.setValue("path", path); + sendMessage(message); +} + void LLPluginClassMedia::crashPlugin() { LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_INTERNAL, "crash"); diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h index 2882de180..8136e9cb7 100644 --- a/indra/llplugin/llpluginclassmedia.h +++ b/indra/llplugin/llpluginclassmedia.h @@ -36,6 +36,7 @@ #ifndef LL_LLPLUGINCLASSMEDIA_H #define LL_LLPLUGINCLASSMEDIA_H +#include "llgltypes.h" #include "llpluginclassbasic.h" #include "llrect.h" #include "v4color.h" @@ -79,6 +80,8 @@ public: void setBackgroundColor(LLColor4 color) { mBackgroundColor = color; }; + void setOwner(LLPluginClassMediaOwner *owner) { mOwner = owner; }; + // Returns true if all of the texture parameters (depth, format, size, and texture size) are set up and consistent. // This will initially be false, and will also be false for some time after setSize while the resize is processed. // Note that if this returns true, it is safe to use all the get() functions above without checking for invalid return values @@ -88,27 +91,36 @@ public: bool getDirty(LLRect *dirty_rect = NULL); void resetDirty(void); - enum EMouseEventType + typedef enum { MOUSE_EVENT_DOWN, MOUSE_EVENT_UP, MOUSE_EVENT_MOVE, MOUSE_EVENT_DOUBLE_CLICK - }; + }EMouseEventType; void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers); - enum EKeyEventType + typedef enum { KEY_EVENT_DOWN, KEY_EVENT_UP, KEY_EVENT_REPEAT - }; + }EKeyEventType; bool keyEvent(EKeyEventType type, int key_code, MASK modifiers, LLSD native_key_data); void scrollEvent(int x, int y, MASK modifiers); - + + // Javascript <-> viewer events + void jsEnableObject( bool enable ); + void jsAgentLocationEvent( double x, double y, double z ); + void jsAgentGlobalLocationEvent( double x, double y, double z ); + void jsAgentOrientationEvent( double angle ); + void jsAgentLanguageEvent( const std::string& language ); + void jsAgentRegionEvent( const std::string& region_name ); + void jsAgentMaturityEvent( const std::string& maturity ); + // Text may be unicode (utf8 encoded) bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data); @@ -124,6 +136,10 @@ public: void setLowPrioritySizeLimit(int size); F64 getCPUUsage(); + + void sendPickFileResponse(const std::string &file); + + void sendAuthResponse(bool ok, const std::string &username, const std::string &password); // Valid after a MEDIA_EVENT_CURSOR_CHANGED event std::string getCursorName() const { return mCursorName; }; @@ -144,7 +160,8 @@ public: void setLanguageCode(const std::string &language_code); void setPluginsEnabled(const bool enabled); void setJavascriptEnabled(const bool enabled); - + void setTarget(const std::string &target); + /////////////////////////////////// // media browser class functions bool pluginSupportsMediaBrowser(void); @@ -161,6 +178,10 @@ public: void browse_back(); void set_status_redirect(int code, const std::string &url); void setBrowserUserAgent(const std::string& user_agent); + void proxyWindowOpened(const std::string &target, const std::string &uuid); + void proxyWindowClosed(const std::string &uuid); + void ignore_ssl_cert_errors(bool ignore); + void addCertificateFilePath(const std::string& path); // This is valid after MEDIA_EVENT_NAVIGATE_BEGIN or MEDIA_EVENT_NAVIGATE_COMPLETE std::string getNavigateURI() const { return mNavigateURI; }; @@ -183,10 +204,32 @@ public: // This is valid after MEDIA_EVENT_CLICK_LINK_HREF or MEDIA_EVENT_CLICK_LINK_NOFOLLOW std::string getClickURL() const { return mClickURL; }; + // This is valid after MEDIA_EVENT_CLICK_LINK_NOFOLLOW + std::string getClickNavType() const { return mClickNavType; }; + // This is valid after MEDIA_EVENT_CLICK_LINK_HREF std::string getClickTarget() const { return mClickTarget; }; + // This is valid during MEDIA_EVENT_CLICK_LINK_HREF and MEDIA_EVENT_GEOMETRY_CHANGE + std::string getClickUUID() const { return mClickUUID; }; + // This is valid after MEDIA_EVENT_NAVIGATE_ERROR_PAGE + S32 getStatusCode() const { return mStatusCode; }; + + // These are valid during MEDIA_EVENT_GEOMETRY_CHANGE + S32 getGeometryX() const { return mGeometryX; }; + S32 getGeometryY() const { return mGeometryY; }; + S32 getGeometryWidth() const { return mGeometryWidth; }; + S32 getGeometryHeight() const { return mGeometryHeight; }; + + // These are valid during MEDIA_EVENT_AUTH_REQUEST + std::string getAuthURL() const { return mAuthURL; }; + std::string getAuthRealm() const { return mAuthRealm; }; + + // These are valid during MEDIA_EVENT_LINK_HOVERED + std::string getHoverText() const { return mHoverText; }; + std::string getHoverLink() const { return mHoverLink; }; + std::string getMediaName() const { return mMediaName; }; std::string getMediaDescription() const { return mMediaDescription; }; @@ -228,12 +271,12 @@ protected: protected: LLPluginClassMediaOwner *mOwner; - + bool mTextureParamsReceived; // the mRequestedTexture* fields are only valid when this is true S32 mRequestedTextureDepth; - U32 mRequestedTextureInternalFormat; - U32 mRequestedTextureFormat; - U32 mRequestedTextureType; + LLGLenum mRequestedTextureInternalFormat; + LLGLenum mRequestedTextureFormat; + LLGLenum mRequestedTextureType; bool mRequestedTextureSwapBytes; bool mRequestedTextureCoordsOpenGL; @@ -299,6 +342,8 @@ protected: LLColor4 mBackgroundColor; + std::string mTarget; + ///////////////////////////////////////// // media_browser class std::string mNavigateURI; @@ -310,7 +355,18 @@ protected: int mProgressPercent; std::string mLocation; std::string mClickURL; + std::string mClickNavType; std::string mClickTarget; + std::string mClickUUID; + S32 mGeometryX; + S32 mGeometryY; + S32 mGeometryWidth; + S32 mGeometryHeight; + S32 mStatusCode; + std::string mAuthURL; + std::string mAuthRealm; + std::string mHoverText; + std::string mHoverLink; ///////////////////////////////////////// // media_time class diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h index 9d1f35220..0083e0c41 100644 --- a/indra/llplugin/llpluginclassmediaowner.h +++ b/indra/llplugin/llpluginclassmediaowner.h @@ -59,11 +59,19 @@ public: MEDIA_EVENT_STATUS_TEXT_CHANGED, // browser has updated the status text MEDIA_EVENT_NAME_CHANGED, // browser has updated the name of the media (typically tag) MEDIA_EVENT_LOCATION_CHANGED, // browser location (URL) has changed (maybe due to internal navagation/frames/etc) + MEDIA_EVENT_NAVIGATE_ERROR_PAGE, // browser navigated to a page that resulted in an HTTP error MEDIA_EVENT_CLICK_LINK_HREF, // I'm not entirely sure what the semantics of these two are MEDIA_EVENT_CLICK_LINK_NOFOLLOW, - + MEDIA_EVENT_CLOSE_REQUEST, // The plugin requested its window be closed (currently hooked up to javascript window.close in webkit) + MEDIA_EVENT_PICK_FILE_REQUEST, // The plugin wants the user to pick a file + MEDIA_EVENT_GEOMETRY_CHANGE, // The plugin requested its window geometry be changed (per the javascript window interface) + MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch - MEDIA_EVENT_PLUGIN_FAILED // The plugin died unexpectedly + MEDIA_EVENT_PLUGIN_FAILED, // The plugin died unexpectedly + + MEDIA_EVENT_AUTH_REQUEST, // The plugin wants to display an auth dialog + + MEDIA_EVENT_LINK_HOVERED // Got a "link hovered" event from the plugin } EMediaEvent; diff --git a/indra/llplugin/llpluginprocesschild.cpp b/indra/llplugin/llpluginprocesschild.cpp index fdcb4f6a8..d014cf9bb 100644 --- a/indra/llplugin/llpluginprocesschild.cpp +++ b/indra/llplugin/llpluginprocesschild.cpp @@ -433,7 +433,7 @@ void LLPluginProcessChild::receiveMessageRaw(const std::string &message) } else if(message_name == "sleep_time") { - mSleepTime = parsed.getValueReal("time"); + mSleepTime = llmax(parsed.getValueReal("time"), 1.0 / 100.0); // clamp to maximum of 100Hz } else if(message_name == "crash") { diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp index 0d361324e..dd10d73f2 100644 --- a/indra/llplugin/llpluginprocessparent.cpp +++ b/indra/llplugin/llpluginprocessparent.cpp @@ -993,6 +993,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message) } // Send initial sleep time + llassert_always(mSleepTime != 0.f); setSleepTime(mSleepTime, true); setState(STATE_RUNNING); diff --git a/indra/llplugin/slplugin/slplugin.cpp b/indra/llplugin/slplugin/slplugin.cpp index febcfea84..90ca3fea7 100644 --- a/indra/llplugin/slplugin/slplugin.cpp +++ b/indra/llplugin/slplugin/slplugin.cpp @@ -293,7 +293,7 @@ int main(int argc, char **argv) } // Check for a change in this process's frontmost window. - if(FrontWindow() != front_window) + if(FrontNonFloatingWindow() != front_window) { ProcessSerialNumber self = { 0, kCurrentProcess }; ProcessSerialNumber parent = { 0, kNoProcess }; @@ -319,7 +319,7 @@ int main(int argc, char **argv) } } - if((FrontWindow() != NULL) && (front_window == NULL)) + if((FrontNonFloatingWindow() != NULL) && (front_window == NULL)) { // Opening the first window @@ -331,7 +331,7 @@ int main(int argc, char **argv) if(layer_group) { - SetWindowGroup(FrontWindow(), layer_group); + SetWindowGroup(FrontNonFloatingWindow(), layer_group); } if(parent_is_front_process) @@ -340,9 +340,9 @@ int main(int argc, char **argv) (void) SetFrontProcess( &self ); } - ActivateWindow(FrontWindow(), true); + ActivateWindow(FrontNonFloatingWindow(), true); } - else if((FrontWindow() == NULL) && (front_window != NULL)) + else if((FrontNonFloatingWindow() == NULL) && (front_window != NULL)) { // Closing the last window @@ -362,7 +362,7 @@ int main(int argc, char **argv) window_hack_state = 2; } - front_window = FrontWindow(); + front_window = FrontNonFloatingWindow(); } } diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index 572bc4328..52171c6bc 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -17,6 +17,7 @@ include_directories( set(llprimitive_SOURCE_FILES llmaterialtable.cpp + llmodel.cpp llprimitive.cpp llprimtexturelist.cpp lltextureanim.cpp @@ -32,6 +33,8 @@ set(llprimitive_HEADER_FILES legacy_object_types.h llmaterialtable.h + llmediaentry.h + llmodel.h llprimitive.h llprimtexturelist.h lltextureanim.h diff --git a/indra/llprimitive/llmediaentry.h b/indra/llprimitive/llmediaentry.h new file mode 100644 index 000000000..33855b3fb --- /dev/null +++ b/indra/llprimitive/llmediaentry.h @@ -0,0 +1,222 @@ +/** + * @file llmediaentry.h + * @brief This is a single instance of media data related to the face of a prim + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLMEDIAENTRY_H +#define LL_LLMEDIAENTRY_H + +#include "llsd.h" +#include "llstring.h" + +// For return values of set* +#include "lllslconstants.h" + +class LLMediaEntry +{ +public: + enum MediaControls { + STANDARD = 0, + MINI + }; + + // Constructors + LLMediaEntry(); + LLMediaEntry(const LLMediaEntry &rhs); + + LLMediaEntry &operator=(const LLMediaEntry &rhs); + virtual ~LLMediaEntry(); + + bool operator==(const LLMediaEntry &rhs) const; + bool operator!=(const LLMediaEntry &rhs) const; + + // Render as LLSD + LLSD asLLSD() const; + void asLLSD(LLSD& sd) const; + operator LLSD() const { return asLLSD(); } + // Returns false iff the given LLSD contains fields that violate any bounds + // limits. + static bool checkLLSD(const LLSD& sd); + // This doesn't merge, it overwrites the data, so will use + // LLSD defaults if need be. Note: does not check limits! + // Use checkLLSD() above first to ensure the LLSD is valid. + void fromLLSD(const LLSD& sd); + // This merges data from the incoming LLSD into our fields. + // Note that it also does NOT check limits! Use checkLLSD() above first. + void mergeFromLLSD(const LLSD& sd); + + // "general" fields + bool getAltImageEnable() const { return mAltImageEnable; } + MediaControls getControls() const { return mControls; } + std::string getCurrentURL() const { return mCurrentURL; } + std::string getHomeURL() const { return mHomeURL; } + bool getAutoLoop() const { return mAutoLoop; } + bool getAutoPlay() const { return mAutoPlay; } + bool getAutoScale() const { return mAutoScale; } + bool getAutoZoom() const { return mAutoZoom; } + bool getFirstClickInteract() const { return mFirstClickInteract; } + U16 getWidthPixels() const { return mWidthPixels; } + U16 getHeightPixels() const { return mHeightPixels; } + + // "security" fields + bool getWhiteListEnable() const { return mWhiteListEnable; } + const std::vector<std::string> &getWhiteList() const { return mWhiteList; } + + // "permissions" fields + U8 getPermsInteract() const { return mPermsInteract; } + U8 getPermsControl() const { return mPermsControl; } + + // Setters. Those that return a U32 return a status error code + // See lllslconstants.h + + // "general" fields + U32 setAltImageEnable(bool alt_image_enable) { mAltImageEnable = alt_image_enable; return LSL_STATUS_OK; } + U32 setControls(MediaControls controls); + U32 setCurrentURL(const std::string& current_url); + U32 setHomeURL(const std::string& home_url); + U32 setAutoLoop(bool auto_loop) { mAutoLoop = auto_loop; return LSL_STATUS_OK; } + U32 setAutoPlay(bool auto_play) { mAutoPlay = auto_play; return LSL_STATUS_OK; } + U32 setAutoScale(bool auto_scale) { mAutoScale = auto_scale; return LSL_STATUS_OK; } + U32 setAutoZoom(bool auto_zoom) { mAutoZoom = auto_zoom; return LSL_STATUS_OK; } + U32 setFirstClickInteract(bool first_click) { mFirstClickInteract = first_click; return LSL_STATUS_OK; } + U32 setWidthPixels(U16 width); + U32 setHeightPixels(U16 height); + + // "security" fields + U32 setWhiteListEnable( bool whitelist_enable ) { mWhiteListEnable = whitelist_enable; return LSL_STATUS_OK; } + U32 setWhiteList( const std::vector<std::string> &whitelist ); + U32 setWhiteList( const LLSD &whitelist ); // takes an LLSD array + + // "permissions" fields + U32 setPermsInteract( U8 val ); + U32 setPermsControl( U8 val ); + + const LLUUID& getMediaID() const; + + // Helper function to check a candidate URL against the whitelist + // Returns true iff candidate URL passes (or if there is no whitelist), false otherwise + bool checkCandidateUrl(const std::string& url) const; + +public: + // Static function to check a URL against a whitelist + // Returns true iff url passes the given whitelist + static bool checkUrlAgainstWhitelist(const std::string &url, + const std::vector<std::string> &whitelist); + +public: + // LLSD key defines + // "general" fields + static const char* ALT_IMAGE_ENABLE_KEY; + static const char* CONTROLS_KEY; + static const char* CURRENT_URL_KEY; + static const char* HOME_URL_KEY; + static const char* AUTO_LOOP_KEY; + static const char* AUTO_PLAY_KEY; + static const char* AUTO_SCALE_KEY; + static const char* AUTO_ZOOM_KEY; + static const char* FIRST_CLICK_INTERACT_KEY; + static const char* WIDTH_PIXELS_KEY; + static const char* HEIGHT_PIXELS_KEY; + + // "security" fields + static const char* WHITELIST_ENABLE_KEY; + static const char* WHITELIST_KEY; + + // "permissions" fields + static const char* PERMS_INTERACT_KEY; + static const char* PERMS_CONTROL_KEY; + + // Field enumerations & constants + + // *NOTE: DO NOT change the order of these, and do not insert values + // in the middle! + // Add values to the end, and make sure to change PARAM_MAX_ID! + enum Fields { + ALT_IMAGE_ENABLE_ID = 0, + CONTROLS_ID = 1, + CURRENT_URL_ID = 2, + HOME_URL_ID = 3, + AUTO_LOOP_ID = 4, + AUTO_PLAY_ID = 5, + AUTO_SCALE_ID = 6, + AUTO_ZOOM_ID = 7, + FIRST_CLICK_INTERACT_ID = 8, + WIDTH_PIXELS_ID = 9, + HEIGHT_PIXELS_ID = 10, + WHITELIST_ENABLE_ID = 11, + WHITELIST_ID = 12, + PERMS_INTERACT_ID = 13, + PERMS_CONTROL_ID = 14, + PARAM_MAX_ID = PERMS_CONTROL_ID + }; + + // "permissions" values + // (e.g. (PERM_OWNER | PERM_GROUP) sets permissions on for OWNER and GROUP + static const U8 PERM_NONE = 0x0; + static const U8 PERM_OWNER = 0x1; + static const U8 PERM_GROUP = 0x2; + static const U8 PERM_ANYONE = 0x4; + static const U8 PERM_ALL = PERM_OWNER|PERM_GROUP|PERM_ANYONE; + static const U8 PERM_MASK = PERM_OWNER|PERM_GROUP|PERM_ANYONE; + + // Limits (in bytes) + static const U32 MAX_URL_LENGTH = 1024; + static const U32 MAX_WHITELIST_SIZE = 1024; + static const U32 MAX_WHITELIST_COUNT = 64; + static const U16 MAX_WIDTH_PIXELS = 2048; + static const U16 MAX_HEIGHT_PIXELS = 2048; + +private: + + U32 setStringFieldWithLimit( std::string &field, const std::string &value, U32 limit ); + U32 setCurrentURLInternal( const std::string &url, bool check_whitelist); + bool fromLLSDInternal(const LLSD &sd, bool overwrite); + +private: + // "general" fields + bool mAltImageEnable; + MediaControls mControls; + std::string mCurrentURL; + std::string mHomeURL; + bool mAutoLoop; + bool mAutoPlay; + bool mAutoScale; + bool mAutoZoom; + bool mFirstClickInteract; + U16 mWidthPixels; + U16 mHeightPixels; + + // "security" fields + bool mWhiteListEnable; + std::vector<std::string> mWhiteList; + + // "permissions" fields + U8 mPermsInteract; + U8 mPermsControl; + + mutable LLUUID *mMediaIDp; // temporary id assigned to media on the viewer +}; + +#endif + diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp new file mode 100644 index 000000000..37b3d27d1 --- /dev/null +++ b/indra/llprimitive/llmodel.cpp @@ -0,0 +1,2417 @@ +/** + * @file llmodel.cpp + * @brief Model handling implementation + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#if MESH_ENABLED +#include "llmodel.h" +#include "llmemory.h" +#if MESH_IMPORT +#include "llconvexdecomposition.h" +#endif //MESH_IMPORT +#include "llsdserialize.h" +#include "llvector4a.h" + +#if MESH_IMPORT +#include "dae.h" +#include "dae/daeErrorHandler.h" +#include "dom/domConstants.h" +#include "dom/domMesh.h" +#endif //MESH_IMPORT + +#ifdef LL_STANDALONE +# include <zlib.h> +#else +# include "zlib/zlib.h" +#endif + + + +std::string model_names[] = +{ + "lowest_lod", + "low_lod", + "medium_lod", + "high_lod", + "physics_mesh" +}; + +const int MODEL_NAMES_LENGTH = sizeof(model_names) / sizeof(std::string); + +LLModel::LLModel(LLVolumeParams& params, F32 detail) + : LLVolume(params, detail), mNormalizedScale(1,1,1), mNormalizedTranslation(0,0,0) + , mPelvisOffset( 0.0f ), mStatus(NO_ERRORS) +{ + mDecompID = -1; + mLocalID = -1; +} + +LLModel::~LLModel() +{ + if (mDecompID >= 0) + { +#if MESH_IMPORT + LLConvexDecomposition::getInstance()->deleteDecomposition(mDecompID); +#endif //MESH_IMPORT + } +} + +#if MESH_IMPORT + +bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride, + domSource* &pos_source, domSource* &tc_source, domSource* &norm_source) +{ + + idx_stride = 0; + + for (U32 j = 0; j < inputs.getCount(); ++j) + { + idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride); + + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) + { //found vertex array + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + domVertices* vertices = (domVertices*) elem.cast(); + if ( !vertices ) + { + return false; + } + + domInputLocal_Array& v_inp = vertices->getInput_array(); + + + for (U32 k = 0; k < v_inp.getCount(); ++k) + { + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) + { + pos_offset = inputs[j]->getOffset(); + + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + pos_source = (domSource*) elem.cast(); + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0) + { + norm_offset = inputs[j]->getOffset(); + + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + norm_source = (domSource*) elem.cast(); + } + } + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) + { + //found normal array for this triangle list + norm_offset = inputs[j]->getOffset(); + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + norm_source = (domSource*) elem.cast(); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) + { //found texCoords + tc_offset = inputs[j]->getOffset(); + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + tc_source = (domSource*) elem.cast(); + } + } + + idx_stride += 1; + + return true; +} + +LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domTrianglesRef& tri) +{ + LLVolumeFace face; + std::vector<LLVolumeFace::VertexData> verts; + std::vector<U16> indices; + + const domInputLocalOffset_Array& inputs = tri->getInput_array(); + + S32 pos_offset = -1; + S32 tc_offset = -1; + S32 norm_offset = -1; + + domSource* pos_source = NULL; + domSource* tc_source = NULL; + domSource* norm_source = NULL; + + S32 idx_stride = 0; + + if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source ) + { + return LLModel::BAD_ELEMENT; + } + + + domPRef p = tri->getP(); + domListOfUInts& idx = p->getValue(); + + domListOfFloats dummy ; + domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy ; + domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy ; + domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy ; + + if (pos_source) + { + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + } + + LLVolumeFace::VertexMapData::PointMap point_map; + + for (U32 i = 0; i < idx.getCount(); i += idx_stride) + { + LLVolumeFace::VertexData cv; + if (pos_source) + { + cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0], + v[idx[i+pos_offset]*3+1], + v[idx[i+pos_offset]*3+2])); + } + + if (tc_source) + { + cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0], + tc[idx[i+tc_offset]*2+1]); + } + + if (norm_source) + { + cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0], + n[idx[i+norm_offset]*3+1], + n[idx[i+norm_offset]*3+2])); + } + + + BOOL found = FALSE; + + LLVolumeFace::VertexMapData::PointMap::iterator point_iter; + point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); + + if (point_iter != point_map.end()) + { + for (U32 j = 0; j < point_iter->second.size(); ++j) + { + if ((point_iter->second)[j] == cv) + { + found = TRUE; + indices.push_back((point_iter->second)[j].mIndex); + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 65535) + { + //llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << llendl; + return LLModel::VERTEX_NUMBER_OVERFLOW ; + } + U16 index = (U16) (verts.size()-1); + indices.push_back(index); + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); + } + } + + if (indices.size()%3 == 0 && verts.size() >= 65532) + { + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + face = LLVolumeFace(); + point_map.clear(); + } + + } + + if (!verts.empty()) + { + std::string material; + + if (tri->getMaterial()) + { + material = std::string(tri->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + + face_list.rbegin()->fillFromLegacyData(verts, indices); + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS ; +} + +LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolylistRef& poly) +{ + domPRef p = poly->getP(); + domListOfUInts& idx = p->getValue(); + + if (idx.getCount() == 0) + { + return LLModel::NO_ERRORS ; + } + + const domInputLocalOffset_Array& inputs = poly->getInput_array(); + + + domListOfUInts& vcount = poly->getVcount()->getValue(); + + S32 pos_offset = -1; + S32 tc_offset = -1; + S32 norm_offset = -1; + + domSource* pos_source = NULL; + domSource* tc_source = NULL; + domSource* norm_source = NULL; + + S32 idx_stride = 0; + + if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source)) + { + return LLModel::BAD_ELEMENT; + } + + LLVolumeFace face; + + std::vector<U16> indices; + std::vector<LLVolumeFace::VertexData> verts; + + domListOfFloats v; + domListOfFloats tc; + domListOfFloats n; + + if (pos_source) + { + v = pos_source->getFloat_array()->getValue(); + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + } + + if (tc_source) + { + tc = tc_source->getFloat_array()->getValue(); + } + + if (norm_source) + { + n = norm_source->getFloat_array()->getValue(); + } + + LLVolumeFace::VertexMapData::PointMap point_map; + + U32 cur_idx = 0; + for (U32 i = 0; i < vcount.getCount(); ++i) + { //for each polygon + U32 first_index = 0; + U32 last_index = 0; + for (U32 j = 0; j < vcount[i]; ++j) + { //for each vertex + + LLVolumeFace::VertexData cv; + + if (pos_source) + { + cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0], + v[idx[cur_idx+pos_offset]*3+1], + v[idx[cur_idx+pos_offset]*3+2]); + } + + if (tc_source) + { + cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0], + tc[idx[cur_idx+tc_offset]*2+1]); + } + + if (norm_source) + { + cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0], + n[idx[cur_idx+norm_offset]*3+1], + n[idx[cur_idx+norm_offset]*3+2]); + } + + cur_idx += idx_stride; + + BOOL found = FALSE; + + LLVolumeFace::VertexMapData::PointMap::iterator point_iter; + LLVector3 pos3(cv.getPosition().getF32ptr()); + point_iter = point_map.find(pos3); + + if (point_iter != point_map.end()) + { + for (U32 k = 0; k < point_iter->second.size(); ++k) + { + if ((point_iter->second)[k] == cv) + { + found = TRUE; + U32 index = (point_iter->second)[k].mIndex; + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 65535) + { + //llerrs << "Attempted to write model exceeding 16-bit index buffer limitation." << llendl; + return LLModel::VERTEX_NUMBER_OVERFLOW ; + } + U16 index = (U16) (verts.size()-1); + + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[pos3].push_back(d); + } + } + + if (indices.size()%3 == 0 && indices.size() >= 65532) + { + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + face = LLVolumeFace(); + verts.clear(); + indices.clear(); + point_map.clear(); + } + } + } + + if (!verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS ; +} + +LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& face_list, std::vector<std::string>& materials, domPolygonsRef& poly) +{ + LLVolumeFace face; + std::vector<U16> indices; + std::vector<LLVolumeFace::VertexData> verts; + + const domInputLocalOffset_Array& inputs = poly->getInput_array(); + + + S32 v_offset = -1; + S32 n_offset = -1; + S32 t_offset = -1; + + domListOfFloats* v = NULL; + domListOfFloats* n = NULL; + domListOfFloats* t = NULL; + + U32 stride = 0; + for (U32 i = 0; i < inputs.getCount(); ++i) + { + stride = llmax((U32) inputs[i]->getOffset()+1, stride); + + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0) + { //found vertex array + v_offset = inputs[i]->getOffset(); + + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domVertices* vertices = (domVertices*) elem.cast(); + if (!vertices) + { + return LLModel::BAD_ELEMENT; + } + domInputLocal_Array& v_inp = vertices->getInput_array(); + + for (U32 k = 0; k < v_inp.getCount(); ++k) + { + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) + { + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + if (!src) + { + return LLModel::BAD_ELEMENT; + } + v = &(src->getFloat_array()->getValue()); + } + } + } + else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0) + { + n_offset = inputs[i]->getOffset(); + //found normal array for this triangle list + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + if (!src) + { + return LLModel::BAD_ELEMENT; + } + n = &(src->getFloat_array()->getValue()); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0) + { //found texCoords + t_offset = inputs[i]->getOffset(); + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + if (!src) + { + return LLModel::BAD_ELEMENT; + } + t = &(src->getFloat_array()->getValue()); + } + } + + domP_Array& ps = poly->getP_array(); + + //make a triangle list in <verts> + for (U32 i = 0; i < ps.getCount(); ++i) + { //for each polygon + domListOfUInts& idx = ps[i]->getValue(); + for (U32 j = 0; j < idx.getCount()/stride; ++j) + { //for each vertex + if (j > 2) + { + U32 size = verts.size(); + LLVolumeFace::VertexData v0 = verts[size-3]; + LLVolumeFace::VertexData v1 = verts[size-1]; + + verts.push_back(v0); + verts.push_back(v1); + } + + LLVolumeFace::VertexData vert; + + + if (v) + { + U32 v_idx = idx[j*stride+v_offset]*3; + vert.getPosition().set(v->get(v_idx), + v->get(v_idx+1), + v->get(v_idx+2)); + } + + if (n) + { + U32 n_idx = idx[j*stride+n_offset]*3; + vert.getNormal().set(n->get(n_idx), + n->get(n_idx+1), + n->get(n_idx+2)); + } + + if (t) + { + U32 t_idx = idx[j*stride+t_offset]*2; + vert.mTexCoord.setVec(t->get(t_idx), + t->get(t_idx+1)); + } + + + verts.push_back(vert); + } + } + + if (verts.empty()) + { + return LLModel::NO_ERRORS; + } + + face.mExtents[0] = verts[0].getPosition(); + face.mExtents[1] = verts[0].getPosition(); + + //create a map of unique vertices to indices + std::map<LLVolumeFace::VertexData, U32> vert_idx; + + U32 cur_idx = 0; + for (U32 i = 0; i < verts.size(); ++i) + { + std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.find(verts[i]); + if (iter == vert_idx.end()) + { + vert_idx[verts[i]] = cur_idx++; + } + } + + //build vertex array from map + std::vector<LLVolumeFace::VertexData> new_verts; + new_verts.resize(vert_idx.size()); + + for (std::map<LLVolumeFace::VertexData, U32>::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter) + { + new_verts[iter->second] = iter->first; + update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition()); + } + + //build index array from map + indices.resize(verts.size()); + + for (U32 i = 0; i < verts.size(); ++i) + { + indices[i] = vert_idx[verts[i]]; + } + + // DEBUG just build an expanded triangle list + /*for (U32 i = 0; i < verts.size(); ++i) + { + indices.push_back((U16) i); + update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition()); + }*/ + + if (!new_verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(new_verts, indices); + + LLVolumeFace& new_face = *face_list.rbegin(); + if (!n) + { + ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!t) + { + ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS ; +} + +//static +std::string LLModel::getStatusString(U32 status) +{ + const static std::string status_strings[(S32)INVALID_STATUS] = {"status_no_error", "status_vertex_number_overflow","bad_element"}; + + if(status < INVALID_STATUS) + { + if(status_strings[status] == std::string()) + { + llerrs << "No valid status string for this status: " << (U32)status << llendl ; + } + return status_strings[status] ; + } + + llerrs << "Invalid model status: " << (U32)status << llendl ; + + return std::string() ; +} + +void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh) +{ + domTriangles_Array& tris = mesh->getTriangles_array(); + + for (U32 i = 0; i < tris.getCount(); ++i) + { + domTrianglesRef& tri = tris.get(i); + + mStatus = load_face_from_dom_triangles(mVolumeFaces, mMaterialList, tri); + + if(mStatus != NO_ERRORS) + { + mVolumeFaces.clear() ; + mMaterialList.clear() ; + return ; //abort + } + } + + domPolylist_Array& polys = mesh->getPolylist_array(); + for (U32 i = 0; i < polys.getCount(); ++i) + { + domPolylistRef& poly = polys.get(i); + mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly); + + if(mStatus != NO_ERRORS) + { + mVolumeFaces.clear() ; + mMaterialList.clear() ; + return ; //abort + } + } + + domPolygons_Array& polygons = mesh->getPolygons_array(); + + for (U32 i = 0; i < polygons.getCount(); ++i) + { + domPolygonsRef& poly = polygons.get(i); + mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly); + + if(mStatus != NO_ERRORS) + { + mVolumeFaces.clear() ; + mMaterialList.clear() ; + return ; //abort + } + } + +} + +BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh) +{ + if (mesh) + { + mVolumeFaces.clear(); + mMaterialList.clear(); + + addVolumeFacesFromDomMesh(mesh); + + if (getNumVolumeFaces() > 0) + { + normalizeVolumeFaces(); + optimizeVolumeFaces(); + + if (getNumVolumeFaces() > 0) + { + return TRUE; + } + } + } + else + { + llwarns << "no mesh found" << llendl; + } + + return FALSE; +} +#endif //MESH_IMPORT + +void LLModel::offsetMesh( const LLVector3& pivotPoint ) +{ + LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); + + for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); ) + { + std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++; + LLVolumeFace& face = *currentFaceIt; + LLVector4a *pos = (LLVector4a*) face.mPositions; + + for (U32 i=0; i< (U32)face.mNumVertices; ++i ) + { + pos[i].add( pivot ); + } + } +} + +void LLModel::optimizeVolumeFaces() +{ + for (U32 i = 0; i < (U32)getNumVolumeFaces(); ++i) + { + mVolumeFaces[i].optimize(); + } +} + +// Shrink the model to fit +// on a 1x1x1 cube centered at the origin. +// The positions and extents +// multiplied by mNormalizedScale +// and offset by mNormalizedTranslation +// to be the "original" extents and position. +// Also, the positions will fit +// within the unit cube. +void LLModel::normalizeVolumeFaces() +{ + + // ensure we don't have too many faces + if (mVolumeFaces.size() > LL_SCULPT_MESH_MAX_FACES) + mVolumeFaces.resize(LL_SCULPT_MESH_MAX_FACES); + + if (!mVolumeFaces.empty()) + { + LLVector4a min, max; + + // For all of the volume faces + // in the model, loop over + // them and see what the extents + // of the volume along each axis. + min = mVolumeFaces[0].mExtents[0]; + max = mVolumeFaces[0].mExtents[1]; + + for (U32 i = 1; i < mVolumeFaces.size(); ++i) + { + LLVolumeFace& face = mVolumeFaces[i]; + + update_min_max(min, max, face.mExtents[0]); + update_min_max(min, max, face.mExtents[1]); + + if (face.mTexCoords) + { + LLVector2& min_tc = face.mTexCoordExtents[0]; + LLVector2& max_tc = face.mTexCoordExtents[1]; + + min_tc = face.mTexCoords[0]; + max_tc = face.mTexCoords[0]; + + for (U32 j = 1; j < (U32)face.mNumVertices; ++j) + { + update_min_max(min_tc, max_tc, face.mTexCoords[j]); + } + } + else + { + face.mTexCoordExtents[0].set(0,0); + face.mTexCoordExtents[1].set(1,1); + } + } + + // Now that we have the extents of the model + // we can compute the offset needed to center + // the model at the origin. + + // Compute center of the model + // and make it negative to get translation + // needed to center at origin. + LLVector4a trans; + trans.setAdd(min, max); + trans.mul(-0.5f); + + // Compute the total size along all + // axes of the model. + LLVector4a size; + size.setSub(max, min); + + // Prevent division by zero. + F32 x = size[0]; + F32 y = size[1]; + F32 z = size[2]; + F32 w = size[3]; + if (fabs(x)<F_APPROXIMATELY_ZERO) + { + x = 1.0; + } + if (fabs(y)<F_APPROXIMATELY_ZERO) + { + y = 1.0; + } + if (fabs(z)<F_APPROXIMATELY_ZERO) + { + z = 1.0; + } + size.set(x,y,z,w); + + // Compute scale as reciprocal of size + LLVector4a scale; + scale.splat(1.f); + scale.div(size); + + LLVector4a inv_scale(1.f); + inv_scale.div(scale); + + for (U32 i = 0; i < mVolumeFaces.size(); ++i) + { + LLVolumeFace& face = mVolumeFaces[i]; + + // We shrink the extents so + // that they fall within + // the unit cube. + face.mExtents[0].add(trans); + face.mExtents[0].mul(scale); + + face.mExtents[1].add(trans); + face.mExtents[1].mul(scale); + + // For all the positions, we scale + // the positions to fit within the unit cube. + LLVector4a* pos = (LLVector4a*) face.mPositions; + LLVector4a* norm = (LLVector4a*) face.mNormals; + + for (U32 j = 0; j < (U32)face.mNumVertices; ++j) + { + pos[j].add(trans); + pos[j].mul(scale); + if (norm && !norm[j].equals3(LLVector4a::getZero())) + { + norm[j].mul(inv_scale); + norm[j].normalize3(); + } + } + } + + // mNormalizedScale is the scale at which + // we would need to multiply the model + // by to get the original size of the + // model instead of the normalized size. + LLVector4a normalized_scale; + normalized_scale.splat(1.f); + normalized_scale.div(scale); + mNormalizedScale.set(normalized_scale.getF32ptr()); + mNormalizedTranslation.set(trans.getF32ptr()); + mNormalizedTranslation *= -1.f; + } +} + +void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) +{ + scale_out = mNormalizedScale; + translation_out = mNormalizedTranslation; +} + +void LLModel::setNumVolumeFaces(S32 count) +{ + mVolumeFaces.resize(count); +} + +void LLModel::setVolumeFaceData( + S32 f, + LLStrider<LLVector3> pos, + LLStrider<LLVector3> norm, + LLStrider<LLVector2> tc, + LLStrider<U16> ind, + U32 num_verts, + U32 num_indices) +{ + LLVolumeFace& face = mVolumeFaces[f]; + + face.resizeVertices(num_verts); + face.resizeIndices(num_indices); + + if(!pos.isStrided()) + LLVector4a::memcpyNonAliased16((F32*) face.mPositions, (F32*) pos.get(), num_verts*4*sizeof(F32)); + else + for(U32 i=0;i<num_verts;++i) face.mPositions[i].load3(pos[i].mV); + if (norm.get()) + { + if(!norm.isStrided()) + LLVector4a::memcpyNonAliased16((F32*) face.mNormals, (F32*) norm.get(), num_verts*4*sizeof(F32)); + else + for(U32 i=0;i<num_verts;++i) face.mNormals[i].load3(norm[i].mV); + } + else + { + ll_aligned_free_16(face.mNormals); + face.mNormals = NULL; + } + + if (tc.get()) + { + if(!tc.isStrided()) + LLVector4a::memcpyNonAliased16((F32*) face.mTexCoords, (F32*) tc.get(), num_verts*2*sizeof(F32)); + else + for(U32 i=0;i<num_verts;++i) face.mTexCoords[i] = tc[i].mV; + } + else + { + ll_aligned_free_16(face.mTexCoords); + face.mTexCoords = NULL; + } + + U32 size = (num_indices*2+0xF)&~0xF; + LLVector4a::memcpyNonAliased16((F32*) face.mIndices, (F32*) ind.get(), size); +} + +void LLModel::appendFaces(LLModel *model, LLMatrix4 &transform, LLMatrix4& norm_mat) +{ + if (mVolumeFaces.empty()) + { + setNumVolumeFaces(1); + } + + LLVolumeFace& face = mVolumeFaces[mVolumeFaces.size()-1]; + + + for (S32 i = 0; i < model->getNumFaces(); ++i) + { + face.appendFace(model->getVolumeFace(i), transform, norm_mat); + } + +} + +void LLModel::appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat) +{ + S32 rindex = getNumVolumeFaces()-1; + if (rindex == -1 || + mVolumeFaces[rindex].mNumVertices + src_face.mNumVertices >= 65536) + { //empty or overflow will occur, append new face + LLVolumeFace cur_face; + cur_face.appendFace(src_face, mat, norm_mat); + addFace(cur_face); + mMaterialList.push_back(src_material); + } + else + { //append to existing end face + mVolumeFaces.rbegin()->appendFace(src_face, mat, norm_mat); + } +} + +void LLModel::addFace(const LLVolumeFace& face) +{ + if (face.mNumVertices == 0) + { + llerrs << "Cannot add empty face." << llendl; + } + + mVolumeFaces.push_back(face); + + if (mVolumeFaces.size() > MAX_MODEL_FACES) + { + llerrs << "Model prims cannot have more than " << MAX_MODEL_FACES << " faces!" << llendl; + } +} + + +void LLModel::generateNormals(F32 angle_cutoff) +{ + //generate normals for all faces by: + // 1 - Create faceted copy of face with no texture coordinates + // 2 - Weld vertices in faceted copy that are shared between triangles with less than "angle_cutoff" difference between normals + // 3 - Generate smoothed set of normals based on welding results + // 4 - Create faceted copy of face with texture coordinates + // 5 - Copy smoothed normals to faceted copy, using closest normal to triangle normal where more than one normal exists for a given position + // 6 - Remove redundant vertices from new faceted (now smooth) copy + + angle_cutoff = cosf(angle_cutoff); + for (U32 j = 0; j < mVolumeFaces.size(); ++j) + { + LLVolumeFace& vol_face = mVolumeFaces[j]; + + if (vol_face.mNumIndices > 65535) + { + llwarns << "Too many vertices for normal generation to work." << llendl; + continue; + } + + //create faceted copy of current face with no texture coordinates (step 1) + LLVolumeFace faceted; + + LLVector4a* src_pos = (LLVector4a*) vol_face.mPositions; + //LLVector4a* src_norm = (LLVector4a*) vol_face.mNormals; + + + faceted.resizeVertices(vol_face.mNumIndices); + faceted.resizeIndices(vol_face.mNumIndices); + //bake out triangles into temporary face, clearing texture coordinates + for (U32 i = 0; i < (U32)vol_face.mNumIndices; ++i) + { + U32 idx = vol_face.mIndices[i]; + + faceted.mPositions[i] = src_pos[idx]; + faceted.mTexCoords[i] = LLVector2(0,0); + faceted.mIndices[i] = i; + } + + //generate normals for temporary face + for (U32 i = 0; i < (U32)faceted.mNumIndices; i += 3) + { //for each triangle + U16 i0 = faceted.mIndices[i+0]; + U16 i1 = faceted.mIndices[i+1]; + U16 i2 = faceted.mIndices[i+2]; + + LLVector4a& p0 = faceted.mPositions[i0]; + LLVector4a& p1 = faceted.mPositions[i1]; + LLVector4a& p2 = faceted.mPositions[i2]; + + LLVector4a& n0 = faceted.mNormals[i0]; + LLVector4a& n1 = faceted.mNormals[i1]; + LLVector4a& n2 = faceted.mNormals[i2]; + + LLVector4a lhs, rhs; + lhs.setSub(p1, p0); + rhs.setSub(p2, p0); + + n0.setCross3(lhs, rhs); + n0.normalize3(); + n1 = n0; + n2 = n0; + } + + //weld vertices in temporary face, respecting angle_cutoff (step 2) + faceted.optimize(angle_cutoff); + + //generate normals for welded face based on new topology (step 3) + + for (U32 i = 0; i < (U32)faceted.mNumVertices; i++) + { + faceted.mNormals[i].clear(); + } + + for (U32 i = 0; i < (U32)faceted.mNumIndices; i += 3) + { //for each triangle + U16 i0 = faceted.mIndices[i+0]; + U16 i1 = faceted.mIndices[i+1]; + U16 i2 = faceted.mIndices[i+2]; + + LLVector4a& p0 = faceted.mPositions[i0]; + LLVector4a& p1 = faceted.mPositions[i1]; + LLVector4a& p2 = faceted.mPositions[i2]; + + LLVector4a& n0 = faceted.mNormals[i0]; + LLVector4a& n1 = faceted.mNormals[i1]; + LLVector4a& n2 = faceted.mNormals[i2]; + + LLVector4a lhs, rhs; + lhs.setSub(p1, p0); + rhs.setSub(p2, p0); + + LLVector4a n; + n.setCross3(lhs, rhs); + + n0.add(n); + n1.add(n); + n2.add(n); + } + + //normalize normals and build point map + LLVolumeFace::VertexMapData::PointMap point_map; + + for (U32 i = 0; i < (U32)faceted.mNumVertices; ++i) + { + faceted.mNormals[i].normalize3(); + + LLVolumeFace::VertexMapData v; + v.setPosition(faceted.mPositions[i]); + v.setNormal(faceted.mNormals[i]); + + point_map[LLVector3(v.getPosition().getF32ptr())].push_back(v); + } + + //create faceted copy of current face with texture coordinates (step 4) + LLVolumeFace new_face; + + //bake out triangles into new face + new_face.resizeIndices(vol_face.mNumIndices); + new_face.resizeVertices(vol_face.mNumIndices); + + for (U32 i = 0; i < (U32)vol_face.mNumIndices; ++i) + { + U32 idx = vol_face.mIndices[i]; + LLVolumeFace::VertexData v; + new_face.mPositions[i] = vol_face.mPositions[idx]; + new_face.mNormals[i].clear(); + new_face.mIndices[i] = i; + } + + if (vol_face.mTexCoords) + { + for (U32 i = 0; i < (U32)vol_face.mNumIndices; i++) + { + U32 idx = vol_face.mIndices[i]; + new_face.mTexCoords[i] = vol_face.mTexCoords[idx]; + } + } + else + { + ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + //generate normals for new face + for (U32 i = 0; i < (U32)new_face.mNumIndices; i += 3) + { //for each triangle + U16 i0 = new_face.mIndices[i+0]; + U16 i1 = new_face.mIndices[i+1]; + U16 i2 = new_face.mIndices[i+2]; + + LLVector4a& p0 = new_face.mPositions[i0]; + LLVector4a& p1 = new_face.mPositions[i1]; + LLVector4a& p2 = new_face.mPositions[i2]; + + LLVector4a& n0 = new_face.mNormals[i0]; + LLVector4a& n1 = new_face.mNormals[i1]; + LLVector4a& n2 = new_face.mNormals[i2]; + + LLVector4a lhs, rhs; + lhs.setSub(p1, p0); + rhs.setSub(p2, p0); + + n0.setCross3(lhs, rhs); + n0.normalize3(); + n1 = n0; + n2 = n0; + } + + //swap out normals in new_face with best match from point map (step 5) + for (U32 i = 0; i < (U32)new_face.mNumVertices; ++i) + { + //LLVolumeFace::VertexData v = new_face.mVertices[i]; + + LLVector4a ref_norm = new_face.mNormals[i]; + + LLVolumeFace::VertexMapData::PointMap::iterator iter = point_map.find(LLVector3(new_face.mPositions[i].getF32ptr())); + + if (iter != point_map.end()) + { + F32 best = -2.f; + for (U32 k = 0; k < iter->second.size(); ++k) + { + LLVector4a& n = iter->second[k].getNormal(); + + F32 cur = n.dot3(ref_norm).getF32(); + + if (cur > best) + { + best = cur; + new_face.mNormals[i] = n; + } + } + } + } + + //remove redundant vertices from new face (step 6) + new_face.optimize(); + + mVolumeFaces[j] = new_face; + } +} + +#if MESH_IMPORT + +//static +std::string LLModel::getElementLabel(daeElement *element) +{ // try to get a decent label for this element + // if we have a name attribute, use it + std::string name = element->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if we have an ID attribute, use it + if (element->getID()) + { + return std::string(element->getID()); + } + + // if we have a parent, use it + daeElement* parent = element->getParent(); + if (parent) + { + // if parent has a name, use it + std::string name = parent->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if parent has an ID, use it + if (parent->getID()) + { + return std::string(parent->getID()); + } + } + + // try to use our type + daeString element_name = element->getElementName(); + if (element_name) + { + return std::string(element_name); + } + + // if all else fails, use "object" + return std::string("object"); +} + +//static +LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh) +{ + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + LLModel* ret = new LLModel(volume_params, 0.f); + ret->createVolumeFacesFromDomMesh(mesh); + ret->mLabel = getElementLabel(mesh); + return ret; +} +#endif //MESH_IMPORT + +std::string LLModel::getName() const +{ + if (!mRequestedLabel.empty()) + return mRequestedLabel; + else + return mLabel; +} + +//static +LLSD LLModel::writeModel( + std::ostream& ostr, + LLModel* physics, + LLModel* high, + LLModel* medium, + LLModel* low, + LLModel* impostor, + const LLModel::Decomposition& decomp, + BOOL upload_skin, + BOOL upload_joints, + BOOL nowrite, + BOOL as_slm) +{ + LLSD mdl; + + LLModel* model[] = + { + impostor, + low, + medium, + high, + physics + }; + + bool skinning = upload_skin && high && !high->mSkinWeights.empty(); + + if (skinning) + { //write skinning block + mdl["skin"] = high->mSkinInfo.asLLSD(upload_joints); + } + + if (!decomp.mBaseHull.empty() || + !decomp.mHull.empty()) + { + mdl["physics_convex"] = decomp.asLLSD(); + if (!decomp.mHull.empty() && !as_slm) + { //convex decomposition exists, physics mesh will not be used (unless this is an slm file) + model[LLModel::LOD_PHYSICS] = NULL; + } + } + + if (as_slm) + { //save material list names + for (U32 i = 0; i < high->mMaterialList.size(); ++i) + { + mdl["material_list"][i] = high->mMaterialList[i]; + } + } + + for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx) + { + if (model[idx] && model[idx]->getNumVolumeFaces() > 0) + { + LLVector3 min_pos = LLVector3(model[idx]->getVolumeFace(0).mPositions[0].getF32ptr()); + LLVector3 max_pos = min_pos; + + //find position domain + for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i) + { //for each face + const LLVolumeFace& face = model[idx]->getVolumeFace(i); + for (U32 j = 0; j < (U32)face.mNumVertices; ++j) + { + update_min_max(min_pos, max_pos, face.mPositions[j].getF32ptr()); + } + } + + LLVector3 pos_range = max_pos - min_pos; + + for (S32 i = 0; i < model[idx]->getNumVolumeFaces(); ++i) + { //for each face + const LLVolumeFace& face = model[idx]->getVolumeFace(i); + if (face.mNumVertices < 3) + { //don't export an empty face + mdl[model_names[idx]][i]["NoGeometry"] = true; + continue; + } + LLSD::Binary verts(face.mNumVertices*3*2); + LLSD::Binary tc(face.mNumVertices*2*2); + LLSD::Binary normals(face.mNumVertices*3*2); + LLSD::Binary indices(face.mNumIndices*2); + + U32 vert_idx = 0; + U32 norm_idx = 0; + U32 tc_idx = 0; + + LLVector2* ftc = (LLVector2*) face.mTexCoords; + LLVector2 min_tc; + LLVector2 max_tc; + + if (ftc) + { + min_tc = ftc[0]; + max_tc = min_tc; + + //get texture coordinate domain + for (U32 j = 0; j < (U32)face.mNumVertices; ++j) + { + update_min_max(min_tc, max_tc, ftc[j]); + } + } + + + LLVector2 tc_range = max_tc - min_tc; + + for (U32 j = 0; j < (U32)face.mNumVertices; ++j) + { //for each vert + + F32* pos = face.mPositions[j].getF32ptr(); + + //position + for (U32 k = 0; k < 3; ++k) + { //for each component + //convert to 16-bit normalized across domain + U16 val = (U16) (((pos[k]-min_pos.mV[k])/pos_range.mV[k])*65535); + + U8* buff = (U8*) &val; + //write to binary buffer + verts[vert_idx++] = buff[0]; + verts[vert_idx++] = buff[1]; + } + + if (face.mNormals) + { //normals + F32* norm = face.mNormals[j].getF32ptr(); + + for (U32 k = 0; k < 3; ++k) + { //for each component + //convert to 16-bit normalized + U16 val = (U16) ((norm[k]+1.f)*0.5f*65535); + U8* buff = (U8*) &val; + + //write to binary buffer + normals[norm_idx++] = buff[0]; + normals[norm_idx++] = buff[1]; + } + } + + F32* src_tc = (F32*) face.mTexCoords[j].mV; + + //texcoord + if (face.mTexCoords) + { + for (U32 k = 0; k < 2; ++k) + { //for each component + //convert to 16-bit normalized + U16 val = (U16) ((src_tc[k]-min_tc.mV[k])/tc_range.mV[k]*65535); + + U8* buff = (U8*) &val; + //write to binary buffer + tc[tc_idx++] = buff[0]; + tc[tc_idx++] = buff[1]; + } + } + } + + U32 idx_idx = 0; + for (U32 j = 0; j < (U32)face.mNumIndices; ++j) + { + U8* buff = (U8*) &(face.mIndices[j]); + indices[idx_idx++] = buff[0]; + indices[idx_idx++] = buff[1]; + } + + //write out face data + mdl[model_names[idx]][i]["PositionDomain"]["Min"] = min_pos.getValue(); + mdl[model_names[idx]][i]["PositionDomain"]["Max"] = max_pos.getValue(); + mdl[model_names[idx]][i]["Position"] = verts; + + if (face.mNormals) + { + mdl[model_names[idx]][i]["Normal"] = normals; + } + + if (face.mTexCoords) + { + mdl[model_names[idx]][i]["TexCoord0Domain"]["Min"] = min_tc.getValue(); + mdl[model_names[idx]][i]["TexCoord0Domain"]["Max"] = max_tc.getValue(); + mdl[model_names[idx]][i]["TexCoord0"] = tc; + } + mdl[model_names[idx]][i]["TriangleList"] = indices; + + if (skinning) + { + //write out skin weights + + //each influence list entry is up to 4 24-bit values + // first 8 bits is bone index + // last 16 bits is bone influence weight + // a bone index of 0xFF signifies no more influences for this vertex + + std::stringstream ostr; + + for (U32 j = 0; j < (U32)face.mNumVertices; ++j) + { + LLVector3 pos(face.mPositions[j].getF32ptr()); + + weight_list& weights = high->getJointInfluences(pos); + + S32 count = 0; + for (weight_list::iterator iter = weights.begin(); iter != weights.end(); ++iter) + { + if (iter->mJointIdx < 255 && iter->mJointIdx >= 0) + { + U8 idx = (U8) iter->mJointIdx; + ostr.write((const char*) &idx, 1); + + U16 influence = (U16) (iter->mWeight*65535); + ostr.write((const char*) &influence, 2); + + ++count; + } + } + U8 end_list = 0xFF; + if (count < 4) + { + ostr.write((const char*) &end_list, 1); + } + } + + //copy ostr to binary buffer + std::string data = ostr.str(); + const U8* buff = (U8*) data.data(); + U32 bytes = data.size(); + + LLSD::Binary w(bytes); + for (U32 j = 0; j < bytes; ++j) + { + w[j] = buff[j]; + } + + mdl[model_names[idx]][i]["Weights"] = w; + } + } + } + } + + return writeModelToStream(ostr, mdl, nowrite, as_slm); +} + +LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BOOL as_slm) +{ + U32 bytes = 0; + + std::string::size_type cur_offset = 0; + + LLSD header; + + if (as_slm && mdl.has("material_list")) + { //save material binding names to header + header["material_list"] = mdl["material_list"]; + } + + std::string skin; + + if (mdl.has("skin")) + { //write out skin block + skin = zip_llsd(mdl["skin"]); + + U32 size = skin.size(); + if (size > 0) + { + header["skin"]["offset"] = (LLSD::Integer) cur_offset; + header["skin"]["size"] = (LLSD::Integer) size; + cur_offset += size; + bytes += size; + } + } + + std::string decomposition; + + if (mdl.has("physics_convex")) + { //write out convex decomposition + decomposition = zip_llsd(mdl["physics_convex"]); + + U32 size = decomposition.size(); + if (size > 0) + { + header["physics_convex"]["offset"] = (LLSD::Integer) cur_offset; + header["physics_convex"]["size"] = (LLSD::Integer) size; + cur_offset += size; + bytes += size; + } + } + + std::string out[MODEL_NAMES_LENGTH]; + + for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++) + { + if (mdl.has(model_names[i])) + { + out[i] = zip_llsd(mdl[model_names[i]]); + + U32 size = out[i].size(); + + header[model_names[i]]["offset"] = (LLSD::Integer) cur_offset; + header[model_names[i]]["size"] = (LLSD::Integer) size; + cur_offset += size; + bytes += size; + } + } + + if (!nowrite) + { + LLSDSerialize::toBinary(header, ostr); + + if (!skin.empty()) + { //write skin block + ostr.write((const char*) skin.data(), header["skin"]["size"].asInteger()); + } + + if (!decomposition.empty()) + { //write decomposition block + ostr.write((const char*) decomposition.data(), header["physics_convex"]["size"].asInteger()); + } + + for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++) + { + if (!out[i].empty()) + { + ostr.write((const char*) out[i].data(), header[model_names[i]]["size"].asInteger()); + } + } + } + + return header; +} + +LLModel::weight_list& LLModel::getJointInfluences(const LLVector3& pos) +{ + //1. If a vertex has been weighted then we'll find it via pos and return it's weight list + weight_map::iterator iterPos = mSkinWeights.begin(); + weight_map::iterator iterEnd = mSkinWeights.end(); + + for ( ; iterPos!=iterEnd; ++iterPos ) + { + if ( jointPositionalLookup( iterPos->first, pos ) ) + { + return iterPos->second; + } + } + + //2. Otherwise we'll use the older implementation + weight_map::iterator iter = mSkinWeights.find(pos); + + if (iter != mSkinWeights.end()) + { + if ((iter->first - pos).magVec() > 0.1f) + { + llerrs << "Couldn't find weight list." << llendl; + } + + return iter->second; + } + else + { //no exact match found, get closest point + const F32 epsilon = 1e-5f; + weight_map::iterator iter_up = mSkinWeights.lower_bound(pos); + weight_map::iterator iter_down = ++iter_up; + + weight_map::iterator best = iter_up; + + F32 min_dist = (iter->first - pos).magVec(); + + bool done = false; + while (!done) + { //search up and down mSkinWeights from lower bound of pos until a + //match is found within epsilon. If no match is found within epsilon, + //return closest match + done = true; + if (iter_up != mSkinWeights.end() && ++iter_up != mSkinWeights.end()) + { + done = false; + F32 dist = (iter_up->first - pos).magVec(); + + if (dist < epsilon) + { + return iter_up->second; + } + + if (dist < min_dist) + { + best = iter_up; + min_dist = dist; + } + } + + if (iter_down != mSkinWeights.begin() && --iter_down != mSkinWeights.begin()) + { + done = false; + + F32 dist = (iter_down->first - pos).magVec(); + + if (dist < epsilon) + { + return iter_down->second; + } + + if (dist < min_dist) + { + best = iter_down; + min_dist = dist; + } + + } + } + + return best->second; + } +} + +void LLModel::setConvexHullDecomposition( + const LLModel::convex_hull_decomposition& decomp) +{ + mPhysics.mHull = decomp; + mPhysics.mMesh.clear(); + updateHullCenters(); +} + +void LLModel::updateHullCenters() +{ + mHullCenter.resize(mPhysics.mHull.size()); + mHullPoints = 0; + mCenterOfHullCenters.clear(); + + for (U32 i = 0; i < mPhysics.mHull.size(); ++i) + { + LLVector3 cur_center; + + for (U32 j = 0; j < mPhysics.mHull[i].size(); ++j) + { + cur_center += mPhysics.mHull[i][j]; + } + mCenterOfHullCenters += cur_center; + cur_center *= 1.f/mPhysics.mHull[i].size(); + mHullCenter[i] = cur_center; + mHullPoints += mPhysics.mHull[i].size(); + } + + if (mHullPoints > 0) + { + mCenterOfHullCenters *= 1.f / mHullPoints; + llassert(mPhysics.hasHullList()); + } +} + +bool LLModel::loadModel(std::istream& is) +{ + mSculptLevel = -1; // default is an error occured + + LLSD header; + { + if (!LLSDSerialize::fromBinary(header, is, 1024*1024*1024)) + { + llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl; + return false; + } + } + + if (header.has("material_list")) + { //load material list names + mMaterialList.clear(); + for (U32 i = 0; i < (U32)header["material_list"].size(); ++i) + { + mMaterialList.push_back(header["material_list"][i].asString()); + } + } + + std::string nm[] = + { + "lowest_lod", + "low_lod", + "medium_lod", + "high_lod", + "physics_mesh", + }; + + const S32 MODEL_LODS = 5; + + S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS); + + if (header[nm[lod]]["offset"].asInteger() == -1 || + header[nm[lod]]["size"].asInteger() == 0 ) + { //cannot load requested LOD + llwarns << "LoD data is invalid!" << llendl; + return false; + } + + bool has_skin = header["skin"]["offset"].asInteger() >=0 && + header["skin"]["size"].asInteger() > 0; + + if (lod == LLModel::LOD_HIGH) + { //try to load skin info and decomp info + std::ios::pos_type cur_pos = is.tellg(); + loadSkinInfo(header, is); + is.seekg(cur_pos); + } + + if (lod == LLModel::LOD_HIGH || lod == LLModel::LOD_PHYSICS) + { + std::ios::pos_type cur_pos = is.tellg(); + loadDecomposition(header, is); + is.seekg(cur_pos); + } + + is.seekg(header[nm[lod]]["offset"].asInteger(), std::ios_base::cur); + + if (unpackVolumeFaces(is, header[nm[lod]]["size"].asInteger())) + { + if (has_skin) + { + //build out mSkinWeight from face info + for (S32 i = 0; i < getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = getVolumeFace(i); + + if (face.mWeights) + { + for (S32 j = 0; j < face.mNumVertices; ++j) + { + LLVector4a& w = face.mWeights[j]; + + std::vector<JointWeight> wght; + + for (S32 k = 0; k < 4; ++k) + { + S32 idx = (S32) w[k]; + F32 f = w[k] - idx; + if (f > 0.f) + { + wght.push_back(JointWeight(idx, f)); + } + } + + if (!wght.empty()) + { + LLVector3 pos(face.mPositions[j].getF32ptr()); + mSkinWeights[pos] = wght; + } + } + } + } + } + return true; + } + else + { + llwarns << "unpackVolumeFaces failed!" << llendl; + } + + return false; + +} + +void LLModel::matchMaterialOrder(LLModel* ref) +{ + llassert(ref->mMaterialList.size() == mMaterialList.size()); + + std::map<std::string, U32> index_map; + + //build a map of material slot names to face indexes + bool reorder = false; + std::set<std::string> base_mat; + std::set<std::string> cur_mat; + + for (U32 i = 0; i < mMaterialList.size(); i++) + { + index_map[ref->mMaterialList[i]] = i; + if (!reorder) + { //if any material name does not match reference, we need to reorder + reorder = ref->mMaterialList[i] != mMaterialList[i]; + } + base_mat.insert(ref->mMaterialList[i]); + cur_mat.insert(mMaterialList[i]); + } + + + if (reorder && + base_mat == cur_mat) //don't reorder if material name sets don't match + { + std::vector<LLVolumeFace> new_face_list; + new_face_list.resize(mVolumeFaces.size()); + + std::vector<std::string> new_material_list; + new_material_list.resize(mVolumeFaces.size()); + + //rebuild face list so materials have the same order + //as the reference model + for (U32 i = 0; i < mMaterialList.size(); ++i) + { + U32 ref_idx = index_map[mMaterialList[i]]; + new_face_list[ref_idx] = mVolumeFaces[i]; + + new_material_list[ref_idx] = mMaterialList[i]; + } + + llassert(new_material_list == ref->mMaterialList); + + mVolumeFaces = new_face_list; + } + + //override material list with reference model ordering + mMaterialList = ref->mMaterialList; +} + + +bool LLModel::loadSkinInfo(LLSD& header, std::istream &is) +{ + S32 offset = header["skin"]["offset"].asInteger(); + S32 size = header["skin"]["size"].asInteger(); + + if (offset >= 0 && size > 0) + { + is.seekg(offset, std::ios_base::cur); + + LLSD skin_data; + + if (unzip_llsd(skin_data, is, size)) + { + mSkinInfo.fromLLSD(skin_data); + return true; + } + } + + return false; +} + +bool LLModel::loadDecomposition(LLSD& header, std::istream& is) +{ + S32 offset = header["physics_convex"]["offset"].asInteger(); + S32 size = header["physics_convex"]["size"].asInteger(); + + if (offset >= 0 && size > 0) + { + is.seekg(offset, std::ios_base::cur); + + LLSD data; + + if (unzip_llsd(data, is, size)) + { + mPhysics.fromLLSD(data); + updateHullCenters(); + } + } + + return true; +} + + +LLMeshSkinInfo::LLMeshSkinInfo(LLSD& skin) +{ + fromLLSD(skin); +} + +void LLMeshSkinInfo::fromLLSD(LLSD& skin) +{ + if (skin.has("joint_names")) + { + for (U32 i = 0; i < (U32)skin["joint_names"].size(); ++i) + { + mJointNames.push_back(skin["joint_names"][i]); + } + } + + if (skin.has("inverse_bind_matrix")) + { + for (U32 i = 0; i < (U32)skin["inverse_bind_matrix"].size(); ++i) + { + LLMatrix4 mat; + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + mat.mMatrix[j][k] = skin["inverse_bind_matrix"][i][j*4+k].asReal(); + } + } + + mInvBindMatrix.push_back(mat); + } + } + + if (skin.has("bind_shape_matrix")) + { + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + mBindShapeMatrix.mMatrix[j][k] = skin["bind_shape_matrix"][j*4+k].asReal(); + } + } + } + + if (skin.has("alt_inverse_bind_matrix")) + { + for (U32 i = 0; i < (U32)skin["alt_inverse_bind_matrix"].size(); ++i) + { + LLMatrix4 mat; + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + mat.mMatrix[j][k] = skin["alt_inverse_bind_matrix"][i][j*4+k].asReal(); + } + } + + mAlternateBindMatrix.push_back(mat); + } + } + + if (skin.has("pelvis_offset")) + { + mPelvisOffset = skin["pelvis_offset"].asReal(); + } +} + +LLSD LLMeshSkinInfo::asLLSD(bool include_joints) const +{ + LLSD ret; + + for (U32 i = 0; i < mJointNames.size(); ++i) + { + ret["joint_names"][i] = mJointNames[i]; + + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + ret["inverse_bind_matrix"][i][j*4+k] = mInvBindMatrix[i].mMatrix[j][k]; + } + } + } + + for (U32 i = 0; i < 4; i++) + { + for (U32 j = 0; j < 4; j++) + { + ret["bind_shape_matrix"][i*4+j] = mBindShapeMatrix.mMatrix[i][j]; + } + } + + if ( include_joints && mAlternateBindMatrix.size() > 0 ) + { + for (U32 i = 0; i < mJointNames.size(); ++i) + { + for (U32 j = 0; j < 4; j++) + { + for (U32 k = 0; k < 4; k++) + { + ret["alt_inverse_bind_matrix"][i][j*4+k] = mAlternateBindMatrix[i].mMatrix[j][k]; + } + } + } + + ret["pelvis_offset"] = mPelvisOffset; + } + + return ret; +} + +LLModel::Decomposition::Decomposition(LLSD& data) +{ + fromLLSD(data); +} + +void LLModel::Decomposition::fromLLSD(LLSD& decomp) +{ + if (decomp.has("HullList") && decomp.has("Positions")) + { + // updated for const-correctness. gcc is picky about this type of thing - Nyx + const LLSD::Binary& hulls = decomp["HullList"].asBinary(); + const LLSD::Binary& position = decomp["Positions"].asBinary(); + + U16* p = (U16*) &position[0]; + + mHull.resize(hulls.size()); + + LLVector3 min; + LLVector3 max; + LLVector3 range; + + if (decomp.has("Min")) + { + min.setValue(decomp["Min"]); + max.setValue(decomp["Max"]); + } + else + { + min.set(-0.5f, -0.5f, -0.5f); + max.set(0.5f, 0.5f, 0.5f); + } + + range = max-min; + + for (U32 i = 0; i < hulls.size(); ++i) + { + U16 count = (hulls[i] == 0) ? 256 : hulls[i]; + + std::set<U64> valid; + + //must have at least 4 points + //llassert(count > 3); + + for (U32 j = 0; j < count; ++j) + { + U64 test = (U64) p[0] | ((U64) p[1] << 16) | ((U64) p[2] << 32); + //point must be unique + //llassert(valid.find(test) == valid.end()); + valid.insert(test); + + mHull[i].push_back(LLVector3( + (F32) p[0]/65535.f*range.mV[0]+min.mV[0], + (F32) p[1]/65535.f*range.mV[1]+min.mV[1], + (F32) p[2]/65535.f*range.mV[2]+min.mV[2])); + p += 3; + + + } + + //each hull must contain at least 4 unique points + //llassert(valid.size() > 3); + } + } + + if (decomp.has("BoundingVerts")) + { + const LLSD::Binary& position = decomp["BoundingVerts"].asBinary(); + + U16* p = (U16*) &position[0]; + + LLVector3 min; + LLVector3 max; + LLVector3 range; + + if (decomp.has("Min")) + { + min.setValue(decomp["Min"]); + max.setValue(decomp["Max"]); + } + else + { + min.set(-0.5f, -0.5f, -0.5f); + max.set(0.5f, 0.5f, 0.5f); + } + + range = max-min; + + U16 count = position.size()/6; + + for (U32 j = 0; j < count; ++j) + { + mBaseHull.push_back(LLVector3( + (F32) p[0]/65535.f*range.mV[0]+min.mV[0], + (F32) p[1]/65535.f*range.mV[1]+min.mV[1], + (F32) p[2]/65535.f*range.mV[2]+min.mV[2])); + p += 3; + } + } + else + { + //empty base hull mesh to indicate decomposition has been loaded + //but contains no base hull + mBaseHullMesh.clear(); + } +} + +bool LLModel::Decomposition::hasHullList() const +{ + return !mHull.empty() ; +} + +LLSD LLModel::Decomposition::asLLSD() const +{ + LLSD ret; + + if (mBaseHull.empty() && mHull.empty()) + { //nothing to write + return ret; + } + + //write decomposition block + // ["physics_convex"]["HullList"] -- list of 8 bit integers, each entry represents a hull with specified number of points + // ["physics_convex"]["Position"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points + // ["physics_convex"]["BoundingVerts"] -- list of 16-bit integers to be decoded to given domain, encoded 3D points representing a single hull approximation of given shape + + //get minimum and maximum + LLVector3 min; + + if (mHull.empty()) + { + min = mBaseHull[0]; + } + else + { + min = mHull[0][0]; + } + + LLVector3 max = min; + + LLSD::Binary hulls(mHull.size()); + + U32 total = 0; + + for (U32 i = 0; i < mHull.size(); ++i) + { + U32 size = mHull[i].size(); + total += size; + hulls[i] = (U8) (size); + + for (U32 j = 0; j < mHull[i].size(); ++j) + { + update_min_max(min, max, mHull[i][j]); + } + } + + for (U32 i = 0; i < mBaseHull.size(); ++i) + { + update_min_max(min, max, mBaseHull[i]); + } + + ret["Min"] = min.getValue(); + ret["Max"] = max.getValue(); + + LLVector3 range = max-min; + + if (!hulls.empty()) + { + ret["HullList"] = hulls; + } + + if (total > 0) + { + LLSD::Binary p(total*3*2); + + U32 vert_idx = 0; + + for (U32 i = 0; i < mHull.size(); ++i) + { + std::set<U64> valid; + + llassert(!mHull[i].empty()); + + for (U32 j = 0; j < mHull[i].size(); ++j) + { + U64 test = 0; + const F32* src = mHull[i][j].mV; + + for (U32 k = 0; k < 3; k++) + { + //convert to 16-bit normalized across domain + U16 val = (U16) (((src[k]-min.mV[k])/range.mV[k])*65535); + + if(valid.size() < 3) + { + switch (k) + { + case 0: test = test | (U64) val; break; + case 1: test = test | ((U64) val << 16); break; + case 2: test = test | ((U64) val << 32); break; + }; + + valid.insert(test); + } + + U8* buff = (U8*) &val; + //write to binary buffer + p[vert_idx++] = buff[0]; + p[vert_idx++] = buff[1]; + + //makes sure we haven't run off the end of the array + llassert(vert_idx <= p.size()); + } + } + + //must have at least 3 unique points + llassert(valid.size() > 2); + } + + ret["Positions"] = p; + } + + //llassert(!mBaseHull.empty()); + + if (!mBaseHull.empty()) + { + LLSD::Binary p(mBaseHull.size()*3*2); + + U32 vert_idx = 0; + for (U32 j = 0; j < mBaseHull.size(); ++j) + { + const F32* v = mBaseHull[j].mV; + + for (U32 k = 0; k < 3; k++) + { + //convert to 16-bit normalized across domain + U16 val = (U16) (((v[k]-min.mV[k])/range.mV[k])*65535); + + U8* buff = (U8*) &val; + //write to binary buffer + p[vert_idx++] = buff[0]; + p[vert_idx++] = buff[1]; + + if (vert_idx > p.size()) + { + llerrs << "Index out of bounds" << llendl; + } + } + } + + ret["BoundingVerts"] = p; + } + + return ret; +} + +void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs) +{ + if (!rhs) + { + return; + } + + if (mMeshID != rhs->mMeshID) + { + llerrs << "Attempted to merge with decomposition of some other mesh." << llendl; + } + + if (mBaseHull.empty()) + { //take base hull and decomposition from rhs + mHull = rhs->mHull; + mBaseHull = rhs->mBaseHull; + mMesh = rhs->mMesh; + mBaseHullMesh = rhs->mBaseHullMesh; + } + + if (mPhysicsShapeMesh.empty()) + { //take physics shape mesh from rhs + mPhysicsShapeMesh = rhs->mPhysicsShapeMesh; + } +} +#endif //MESH_ENABLED diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h new file mode 100644 index 000000000..58975e55b --- /dev/null +++ b/indra/llprimitive/llmodel.h @@ -0,0 +1,285 @@ +/** + * @file llmodel.h + * @brief Model handling class definitions + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLMODEL_H +#define LL_LLMODEL_H + +#include "llpointer.h" +#include "llvolume.h" +#include "v4math.h" +#include "m4math.h" + +#if MESH_IMPORT +class daeElement; +class domMesh; +#endif //MESH_IMPORT + +#define MAX_MODEL_FACES 8 + + +class LLMeshSkinInfo +{ +public: + LLUUID mMeshID; + std::vector<std::string> mJointNames; + std::vector<LLMatrix4> mInvBindMatrix; + std::vector<LLMatrix4> mAlternateBindMatrix; + std::map<std::string, U32> mJointMap; + + LLMeshSkinInfo() { } + LLMeshSkinInfo(LLSD& data); + void fromLLSD(LLSD& data); + LLSD asLLSD(bool include_joints) const; + LLMatrix4 mBindShapeMatrix; + float mPelvisOffset; +}; + +class LLModel : public LLVolume +{ +public: + + enum + { + LOD_IMPOSTOR = 0, + LOD_LOW, + LOD_MEDIUM, + LOD_HIGH, + LOD_PHYSICS, + NUM_LODS + }; + + enum EModelStatus + { + NO_ERRORS = 0, + VERTEX_NUMBER_OVERFLOW, //vertex number is >= 65535. + BAD_ELEMENT, + INVALID_STATUS + } ; + + //convex_hull_decomposition is a vector of convex hulls + //each convex hull is a set of points + typedef std::vector<std::vector<LLVector3> > convex_hull_decomposition; + typedef std::vector<LLVector3> hull; + + class PhysicsMesh + { + public: + std::vector<LLVector3> mPositions; + std::vector<LLVector3> mNormals; + + void clear() + { + mPositions.clear(); + mNormals.clear(); + } + + bool empty() const + { + return mPositions.empty(); + } + }; + + class Decomposition + { + public: + Decomposition() { } + Decomposition(LLSD& data); + void fromLLSD(LLSD& data); + LLSD asLLSD() const; + bool hasHullList() const; + + void merge(const Decomposition* rhs); + + LLUUID mMeshID; + LLModel::convex_hull_decomposition mHull; + LLModel::hull mBaseHull; + + std::vector<LLModel::PhysicsMesh> mMesh; + LLModel::PhysicsMesh mBaseHullMesh; + LLModel::PhysicsMesh mPhysicsShapeMesh; + }; + + LLModel(LLVolumeParams& params, F32 detail); + ~LLModel(); + + bool loadModel(std::istream& is); + bool loadSkinInfo(LLSD& header, std::istream& is); + bool loadDecomposition(LLSD& header, std::istream& is); + + static LLSD writeModel( + std::ostream& ostr, + LLModel* physics, + LLModel* high, + LLModel* medium, + LLModel* low, + LLModel* imposotr, + const LLModel::Decomposition& decomp, + BOOL upload_skin, + BOOL upload_joints, + BOOL nowrite = FALSE, + BOOL as_slm = FALSE); + + static LLSD writeModelToStream( + std::ostream& ostr, + LLSD& mdl, + BOOL nowrite = FALSE, BOOL as_slm = FALSE); + +#if MESH_IMPORT + static LLModel* loadModelFromDomMesh(domMesh* mesh); + static std::string getElementLabel(daeElement* element); +#endif //MESH_IMPORT + std::string getName() const; + std::string getMetric() const {return mMetric;} + EModelStatus getStatus() const {return mStatus;} + static std::string getStatusString(U32 status) ; + + void appendFaces(LLModel* model, LLMatrix4& transform, LLMatrix4& normal_transform); + void appendFace(const LLVolumeFace& src_face, std::string src_material, LLMatrix4& mat, LLMatrix4& norm_mat); + + void setNumVolumeFaces(S32 count); + void setVolumeFaceData( + S32 f, + LLStrider<LLVector3> pos, + LLStrider<LLVector3> norm, + LLStrider<LLVector2> tc, + LLStrider<U16> ind, + U32 num_verts, + U32 num_indices); + + void generateNormals(F32 angle_cutoff); + + void addFace(const LLVolumeFace& face); + + void normalizeVolumeFaces(); + void optimizeVolumeFaces(); + void offsetMesh( const LLVector3& pivotPoint ); + void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out); + + //reorder face list based on mMaterialList in this and reference so + //order matches that of reference (material ordering touchup) + void matchMaterialOrder(LLModel* reference); + + std::vector<std::string> mMaterialList; + + //data used for skin weights + class JointWeight + { + public: + S32 mJointIdx; + F32 mWeight; + + JointWeight() + { + mJointIdx = 0; + mWeight = 0.f; + } + + JointWeight(S32 idx, F32 weight) + : mJointIdx(idx), mWeight(weight) + { + } + + bool operator<(const JointWeight& rhs) const + { + if (mWeight == rhs.mWeight) + { + return mJointIdx < rhs.mJointIdx; + } + + return mWeight < rhs.mWeight; + } + + }; + + struct CompareWeightGreater + { + bool operator()(const JointWeight& lhs, const JointWeight& rhs) + { + return rhs < lhs; // strongest = first + } + }; + + + //Are the doubles the same w/in epsilon specified tolerance + bool areEqual( double a, double b ) + { + const float epsilon = 1e-5f; + return (fabs((a - b)) < epsilon) ? true : false ; + } + //Make sure that we return false for any values that are within the tolerance for equivalence + bool jointPositionalLookup( const LLVector3& a, const LLVector3& b ) + { + return ( areEqual( a[0],b[0]) && areEqual( a[1],b[1] ) && areEqual( a[2],b[2]) ) ? true : false; + } + + //copy of position array for this model -- mPosition[idx].mV[X,Y,Z] + std::vector<LLVector3> mPosition; + + //map of positions to skin weights --- mSkinWeights[pos].mV[0..4] == <joint_index>.<weight> + //joint_index corresponds to mJointList + typedef std::vector<JointWeight> weight_list; + typedef std::map<LLVector3, weight_list > weight_map; + weight_map mSkinWeights; + + //get list of weight influences closest to given position + weight_list& getJointInfluences(const LLVector3& pos); + + LLMeshSkinInfo mSkinInfo; + + std::string mRequestedLabel; // name requested in UI, if any. + std::string mLabel; // name computed from dae. + + std::string mMetric; // user-supplied metric data for upload + + LLVector3 mNormalizedScale; + LLVector3 mNormalizedTranslation; + + float mPelvisOffset; + // convex hull decomposition + S32 mDecompID; + + void setConvexHullDecomposition( + const convex_hull_decomposition& decomp); + void updateHullCenters(); + + LLVector3 mCenterOfHullCenters; + std::vector<LLVector3> mHullCenter; + U32 mHullPoints; + + //ID for storing this model in a .slm file + S32 mLocalID; + + Decomposition mPhysics; + + EModelStatus mStatus ; +protected: +#if MESH_IMPORT + void addVolumeFacesFromDomMesh(domMesh* mesh); + virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh); +#endif //MESH_IMPORT +}; + +#endif //LL_LLMODEL_H diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index c9b035db3..6c60e507d 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -109,6 +109,10 @@ public: PARAMS_LIGHT = 0x20, PARAMS_SCULPT = 0x30, PARAMS_LIGHT_IMAGE = 0x40, +#if MESH_ENABLED + PARAMS_RESERVED = 0x50, // Used on server-side + PARAMS_MESH = 0x60, +#endif //MESH_ENABLED }; public: diff --git a/indra/llrender/llcubemap.cpp b/indra/llrender/llcubemap.cpp index 036714e5c..0086ef9bb 100644 --- a/indra/llrender/llcubemap.cpp +++ b/indra/llrender/llcubemap.cpp @@ -265,7 +265,7 @@ void LLCubeMap::setMatrix(S32 stage) if (mMatrixStage < 0) return; - if (stage > 0) + //if (stage > 0) { gGL.getTexUnit(stage)->activate(); } @@ -284,17 +284,17 @@ void LLCubeMap::setMatrix(S32 stage) glLoadMatrixf((F32 *)trans.mMatrix); glMatrixMode(GL_MODELVIEW); - if (stage > 0) + /*if (stage > 0) { gGL.getTexUnit(0)->activate(); - } + }*/ } void LLCubeMap::restoreMatrix() { if (mMatrixStage < 0) return; - if (mMatrixStage > 0) + //if (mMatrixStage > 0) { gGL.getTexUnit(mMatrixStage)->activate(); } @@ -302,10 +302,10 @@ void LLCubeMap::restoreMatrix() glPopMatrix(); glMatrixMode(GL_MODELVIEW); - if (mMatrixStage > 0) + /*if (mMatrixStage > 0) { gGL.getTexUnit(0)->activate(); - } + }*/ } void LLCubeMap::setReflection (void) diff --git a/indra/llrender/llfont.cpp b/indra/llrender/llfont.cpp index 80f938ec6..69daf389c 100644 --- a/indra/llrender/llfont.cpp +++ b/indra/llrender/llfont.cpp @@ -246,9 +246,9 @@ BOOL LLFont::loadFace(const std::string& filename, const F32 point_size, const F FT_Set_Charmap(mFTFace, mFTFace->charmaps[0]); } - if (!mIsFallback) + if (!mIsFallback || !sOpenGLcrashOnRestart) // because this often crashes under Linux... { - // Add the default glyph + // Add the empty glyph`5 addGlyph(0, 0); } @@ -362,7 +362,7 @@ BOOL LLFont::addGlyphFromFont(const LLFont *fontp, const llwchar wch, const U32 if (mFTFace == NULL) return FALSE; - llassert(!mIsFallback); + //llassert(!mIsFallback); fontp->renderGlyph(glyph_index); S32 width = fontp->mFTFace->glyph->bitmap.width; S32 height = fontp->mFTFace->glyph->bitmap.rows; @@ -581,7 +581,7 @@ void LLFont::setSubImageLuminanceAlpha(const U32 x, { LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); - llassert(!mIsFallback); + //llassert(!mIsFallback); llassert(image_raw && (image_raw->getComponents() == 2)); diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index f597d7c70..ea2da1150 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -275,7 +275,7 @@ void LLFontGL::destroyAllGL() else { sFontRegistry->destroyGL(); - } + } } } diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index d5560b5eb..40baf7b33 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -53,6 +53,7 @@ #include "llstacktrace.h" #include "llglheaders.h" +#include "llglslshader.h" #ifdef _DEBUG //#define GL_STATE_VERIFY @@ -127,6 +128,23 @@ PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL; PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL; PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL; +// GL_ARB_map_buffer_range +PFNGLMAPBUFFERRANGEPROC glMapBufferRange = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange = NULL; + +// GL_ARB_sync +PFNGLFENCESYNCPROC glFenceSync = NULL; +PFNGLISSYNCPROC glIsSync = NULL; +PFNGLDELETESYNCPROC glDeleteSync = NULL; +PFNGLCLIENTWAITSYNCPROC glClientWaitSync = NULL; +PFNGLWAITSYNCPROC glWaitSync = NULL; +PFNGLGETINTEGER64VPROC glGetInteger64v = NULL; +PFNGLGETSYNCIVPROC glGetSynciv = NULL; + +// GL_APPLE_flush_buffer_range +PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE = NULL; + // vertex object prototypes PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI = NULL; PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI = NULL; @@ -156,27 +174,33 @@ PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL; PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB = NULL; PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB = NULL; -// GL_EXT_framebuffer_object -PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL; -PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL; -PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL; -PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL; -PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL; -PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT = NULL; -PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL; -PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL; -PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL; -PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL; -PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL; -PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL; -PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL; -PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL; -PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL; -PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL; -PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL; -PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL; -PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL; -PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT = NULL; +// GL_ARB_framebuffer_object +PFNGLISRENDERBUFFERPROC glIsRenderbuffer = NULL; +PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = NULL; +PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = NULL; +PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = NULL; +PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv = NULL; +PFNGLISFRAMEBUFFERPROC glIsFramebuffer = NULL; +PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = NULL; +PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = NULL; +PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = NULL; +PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D = NULL; +PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = NULL; +PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D = NULL; +PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv = NULL; +PFNGLGENERATEMIPMAPPROC glGenerateMipmap = NULL; +PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample = NULL; +PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = NULL; + +//GL_ARB_texture_multisample +PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample; +PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; +PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; +PFNGLSAMPLEMASKIPROC glSampleMaski; // GL_EXT_blend_func_separate PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL; @@ -321,10 +345,13 @@ LLGLManager::LLGLManager() : mHasMipMapGeneration(FALSE), mHasCompressedTextures(FALSE), mHasFramebufferObject(FALSE), + mMaxSamples(0), mHasFramebufferMultisample(FALSE), mHasBlendFuncSeparate(FALSE), - + mHasSync(FALSE), mHasVertexBufferObject(FALSE), + mHasMapBufferRange(FALSE), + mHasFlushBufferRange(FALSE), mHasPBuffer(FALSE), mHasShaderObjects(FALSE), mHasVertexShader(FALSE), @@ -335,6 +362,11 @@ LLGLManager::LLGLManager() : mHasPointParameters(FALSE), mHasDrawBuffers(FALSE), mHasTextureRectangle(FALSE), + mHasTextureMultisample(FALSE), + mMaxSampleMaskWords(0), + mMaxColorTextureSamples(0), + mMaxDepthTextureSamples(0), + mMaxIntegerSamples(0), mHasAnisotropic(FALSE), mHasARBEnvCombine(FALSE), @@ -353,6 +385,8 @@ LLGLManager::LLGLManager() : mHasSeparateSpecularColor(FALSE), + mDebugGPU(FALSE), + mDriverVersionMajor(1), mDriverVersionMinor(0), mDriverVersionRelease(0), @@ -538,13 +572,46 @@ bool LLGLManager::initGL() { GLint num_tex_image_units; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units); - mNumTextureImageUnits = num_tex_image_units; + mNumTextureImageUnits = llmin(num_tex_image_units, 32); } + if (mHasTextureMultisample) + { + glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &mMaxColorTextureSamples); + glGetIntegerv(GL_MAX_DEPTH_TEXTURE_SAMPLES, &mMaxDepthTextureSamples); + glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples); + glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords); + } + +#if LL_WINDOWS + if (mIsATI) + { //using multisample textures on ATI results in black screen for some reason + mHasTextureMultisample = FALSE; + } +#endif + + if (mHasFramebufferObject) + { + glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples); + } + + setToDebugGPU(); + initGLStates(); return true; } +void LLGLManager::setToDebugGPU() +{ + //"MOBILE INTEL(R) 965 EXPRESS CHIP", + if (mGLRenderer.find("INTEL") != std::string::npos && mGLRenderer.find("965") != std::string::npos) + { + mDebugGPU = TRUE ; + } + + return ; +} + void LLGLManager::getGLInfo(LLSD& info) { info["GLInfo"]["GLVendor"] = std::string((const char *)glGetString(GL_VENDOR)); @@ -601,6 +668,14 @@ std::string LLGLManager::getRawGLString() return gl_string; } +U32 LLGLManager::getNumFBOFSAASamples(U32 samples) +{ + samples = llmin(samples, (U32) mMaxColorTextureSamples); + samples = llmin(samples, (U32) mMaxDepthTextureSamples); + samples = llmin(samples, (U32) 4); + return samples; +} + void LLGLManager::shutdownGL() { if (mInited) @@ -686,6 +761,9 @@ void LLGLManager::initExtensions() mHasOcclusionQuery = ExtensionExists("GL_ARB_occlusion_query", gGLHExts.mSysExts); mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts); mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts); + mHasSync = ExtensionExists("GL_ARB_sync", gGLHExts.mSysExts); + mHasMapBufferRange = ExtensionExists("GL_ARB_map_buffer_range", gGLHExts.mSysExts); + mHasFlushBufferRange = ExtensionExists("GL_APPLE_flush_buffer_range", gGLHExts.mSysExts); mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts); // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad #ifdef GL_ARB_framebuffer_object @@ -700,7 +778,10 @@ void LLGLManager::initExtensions() mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts); mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts); + mHasTextureMultisample = ExtensionExists("GL_ARB_texture_multisample", gGLHExts.mSysExts); +#if !LL_DARWIN mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); +#endif mHasShaderObjects = ExtensionExists("GL_ARB_shader_objects", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts); mHasVertexShader = ExtensionExists("GL_ARB_vertex_program", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_vertex_shader", gGLHExts.mSysExts) && ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts); @@ -879,29 +960,44 @@ void LLGLManager::initExtensions() mHasVertexBufferObject = FALSE; } } + if (mHasSync) + { + glFenceSync = (PFNGLFENCESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glFenceSync"); + glIsSync = (PFNGLISSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glIsSync"); + glDeleteSync = (PFNGLDELETESYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteSync"); + glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glClientWaitSync"); + glWaitSync = (PFNGLWAITSYNCPROC) GLH_EXT_GET_PROC_ADDRESS("glWaitSync"); + glGetInteger64v = (PFNGLGETINTEGER64VPROC) GLH_EXT_GET_PROC_ADDRESS("glGetInteger64v"); + glGetSynciv = (PFNGLGETSYNCIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetSynciv"); + } + if (mHasMapBufferRange) + { + glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glMapBufferRange"); + glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glFlushMappedBufferRange"); + } if (mHasFramebufferObject) { llinfos << "initExtensions() FramebufferObject-related procs..." << llendl; - glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glIsRenderbufferEXT"); - glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBindRenderbufferEXT"); - glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffersEXT"); - glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenRenderbuffersEXT"); - glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageEXT"); - glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetRenderbufferParameterivEXT"); - glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glIsFramebufferEXT"); - glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBindFramebufferEXT"); - glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteFramebuffersEXT"); - glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenFramebuffersEXT"); - glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glCheckFramebufferStatusEXT"); - glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture1DEXT"); - glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture2DEXT"); - glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture3DEXT"); - glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbufferEXT"); - glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameterivEXT"); - glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmapEXT"); - glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebufferEXT"); - glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisampleEXT"); - glFramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayerEXT"); + glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glIsRenderbuffer"); + glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBindRenderbuffer"); + glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteRenderbuffers"); + glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenRenderbuffers"); + glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorage"); + glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetRenderbufferParameteriv"); + glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glIsFramebuffer"); + glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBindFramebuffer"); + glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glDeleteFramebuffers"); + glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) GLH_EXT_GET_PROC_ADDRESS("glGenFramebuffers"); + glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) GLH_EXT_GET_PROC_ADDRESS("glCheckFramebufferStatus"); + glFramebufferTexture1D = (PFNGLFRAMEBUFFERTEXTURE1DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture1D"); + glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture2D"); + glFramebufferTexture3D = (PFNGLFRAMEBUFFERTEXTURE3DPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTexture3D"); + glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbuffer"); + glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameteriv"); + glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmap"); + glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebuffer"); + glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisample"); + glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayer"); } if (mHasDrawBuffers) { @@ -911,6 +1007,13 @@ void LLGLManager::initExtensions() { glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlendFuncSeparateEXT"); } + if (mHasTextureMultisample) + { + glTexImage2DMultisample = (PFNGLTEXIMAGE2DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage2DMultisample"); + glTexImage3DMultisample = (PFNGLTEXIMAGE3DMULTISAMPLEPROC) GLH_EXT_GET_PROC_ADDRESS("glTexImage3DMultisample"); + glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) GLH_EXT_GET_PROC_ADDRESS("glGetMultisamplefv"); + glSampleMaski = (PFNGLSAMPLEMASKIPROC) GLH_EXT_GET_PROC_ADDRESS("glSampleMaski"); + } #if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS // This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements"); @@ -1299,6 +1402,7 @@ void LLGLState::checkStates(const std::string& msg) void LLGLState::checkTextureChannels(const std::string& msg) { +#if 0 if (!gDebugGL) { return; @@ -1458,11 +1562,12 @@ void LLGLState::checkTextureChannels(const std::string& msg) LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; } } +#endif } void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { - if (!gDebugGL) + if (!gDebugGL || LLGLSLShader::sNoFixedFunction) { return; } @@ -1574,7 +1679,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) } } - if (glIsEnabled(GL_TEXTURE_2D)) + /*if (glIsEnabled(GL_TEXTURE_2D)) { if (!(data_mask & 0x0008)) { @@ -1597,7 +1702,7 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl; } } - } + }*/ glClientActiveTextureARB(GL_TEXTURE0_ARB); gGL.getTexUnit(0)->activate(); @@ -1640,6 +1745,16 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) LLGLState::LLGLState(LLGLenum state, S32 enabled) : mState(state), mWasEnabled(FALSE), mIsEnabled(FALSE) { + if (LLGLSLShader::sNoFixedFunction) + { //always disable state that's deprecated post GL 3.0 + switch (state) + { + case GL_ALPHA_TEST: + enabled = 0; + break; + } + } + stop_glerror(); if (state) { @@ -1998,8 +2113,7 @@ void LLGLNamePool::release(GLuint name) //static void LLGLNamePool::upkeepPools() { - tracker_t::LLInstanceTrackerScopedGuard guard; - for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ++iter) + for (tracker_t::instance_iter iter = beginInstances(); iter != endInstances(); ++iter) { LLGLNamePool & pool = *iter; pool.upkeep(); @@ -2009,8 +2123,7 @@ void LLGLNamePool::upkeepPools() //static void LLGLNamePool::cleanupPools() { - tracker_t::LLInstanceTrackerScopedGuard guard; - for (tracker_t::instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); ++iter) + for (tracker_t::instance_iter iter = beginInstances(); iter != endInstances(); ++iter) { LLGLNamePool & pool = *iter; pool.cleanup(); diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 2e0ca22e5..736cc1b0d 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -89,11 +89,15 @@ public: BOOL mHasMipMapGeneration; BOOL mHasCompressedTextures; BOOL mHasFramebufferObject; + S32 mMaxSamples; BOOL mHasFramebufferMultisample; BOOL mHasBlendFuncSeparate; // ARB Extensions BOOL mHasVertexBufferObject; + BOOL mHasSync; + BOOL mHasMapBufferRange; + BOOL mHasFlushBufferRange; BOOL mHasPBuffer; BOOL mHasShaderObjects; BOOL mHasVertexShader; @@ -105,6 +109,11 @@ public: BOOL mHasDrawBuffers; BOOL mHasDepthClamp; BOOL mHasTextureRectangle; + BOOL mHasTextureMultisample; + S32 mMaxSampleMaskWords; + S32 mMaxColorTextureSamples; + S32 mMaxDepthTextureSamples; + S32 mMaxIntegerSamples; // Other extensions. BOOL mHasAnisotropic; @@ -126,6 +135,9 @@ public: // Misc extensions BOOL mHasSeparateSpecularColor; + + //whether this GPU is in the debug list. + BOOL mDebugGPU; S32 mDriverVersionMajor; S32 mDriverVersionMinor; @@ -143,6 +155,7 @@ public: void printGLInfoString(); void getGLInfo(LLSD& info); + U32 getNumFBOFSAASamples(U32 desired_samples = 32); // In ALL CAPS std::string mGLVendor; std::string mGLVendorShort; @@ -154,6 +167,7 @@ private: void initExtensions(); void initGLStates(); void initGLImages(); + void setToDebugGPU(); }; extern LLGLManager gGLManager; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 9efe16432..f18c6dbb3 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -76,6 +76,23 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; +// GL_ARB_sync +extern PFNGLFENCESYNCPROC glFenceSync; +extern PFNGLISSYNCPROC glIsSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLWAITSYNCPROC glWaitSync; +extern PFNGLGETINTEGER64VPROC glGetInteger64v; +extern PFNGLGETSYNCIVPROC glGetSynciv; + +// GL_APPLE_flush_buffer_range +extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; +extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; + +// GL_ARB_map_buffer_range +extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; +extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; + // GL_ATI_vertex_array_object extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; @@ -312,6 +329,23 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; +// GL_ARB_sync +extern PFNGLFENCESYNCPROC glFenceSync; +extern PFNGLISSYNCPROC glIsSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLWAITSYNCPROC glWaitSync; +extern PFNGLGETINTEGER64VPROC glGetInteger64v; +extern PFNGLGETSYNCIVPROC glGetSynciv; + +// GL_APPLE_flush_buffer_range +extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; +extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; + +// GL_ARB_map_buffer_range +extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; +extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; + // GL_ATI_vertex_array_object extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; @@ -455,31 +489,36 @@ extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB; //GL_EXT_blend_func_separate extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; -//GL_EXT_framebuffer_object -extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; -extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; -extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; -extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; -extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; -extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; -extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; -extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; -extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; -extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; -extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; -extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; -extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; -extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; -extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; -extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; -extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; -extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; -extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; -extern PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT; +//GL_ARB_framebuffer_object +extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer; +extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; +extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; +extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; +extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; +extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv; +extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer; +extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; +extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; +extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; +extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; +extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D; +extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; +extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D; +extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; +extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv; +extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap; +extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample; +extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; +//GL_ARB_texture_multisample +extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample; +extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; +extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; +extern PFNGLSAMPLEMASKIPROC glSampleMaski; #elif LL_WINDOWS //---------------------------------------------------------------------------- @@ -512,6 +551,23 @@ extern PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB; extern PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB; extern PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB; +// GL_ARB_sync +extern PFNGLFENCESYNCPROC glFenceSync; +extern PFNGLISSYNCPROC glIsSync; +extern PFNGLDELETESYNCPROC glDeleteSync; +extern PFNGLCLIENTWAITSYNCPROC glClientWaitSync; +extern PFNGLWAITSYNCPROC glWaitSync; +extern PFNGLGETINTEGER64VPROC glGetInteger64v; +extern PFNGLGETSYNCIVPROC glGetSynciv; + +// GL_APPLE_flush_buffer_range +extern PFNGLBUFFERPARAMETERIAPPLEPROC glBufferParameteriAPPLE; +extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE; + +// GL_ARB_map_buffer_range +extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; +extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC glFlushMappedBufferRange; + // GL_ATI_vertex_array_object extern PFNGLNEWOBJECTBUFFERATIPROC glNewObjectBufferATI; extern PFNGLISOBJECTBUFFERATIPROC glIsObjectBufferATI; @@ -654,31 +710,37 @@ extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB; //GL_EXT_blend_func_separate extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT; -//GL_EXT_framebuffer_object -extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT; -extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT; -extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT; -extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT; -extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT; -extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT; -extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT; -extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; -extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; -extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT; -extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; -extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT; -extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; -extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT; -extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; -extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT; -extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT; -extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; -extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; -extern PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT; +//GL_ARB_framebuffer_object +extern PFNGLISRENDERBUFFERPROC glIsRenderbuffer; +extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; +extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; +extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; +extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; +extern PFNGLGETRENDERBUFFERPARAMETERIVPROC glGetRenderbufferParameteriv; +extern PFNGLISFRAMEBUFFERPROC glIsFramebuffer; +extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; +extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; +extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; +extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; +extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D; +extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; +extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D; +extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; +extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glGetFramebufferAttachmentParameteriv; +extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap; +extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glRenderbufferStorageMultisample; +extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer; //GL_ARB_draw_buffers extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; +//GL_ARB_texture_multisample +extern PFNGLTEXIMAGE2DMULTISAMPLEPROC glTexImage2DMultisample; +extern PFNGLTEXIMAGE3DMULTISAMPLEPROC glTexImage3DMultisample; +extern PFNGLGETMULTISAMPLEFVPROC glGetMultisamplefv; +extern PFNGLSAMPLEMASKIPROC glSampleMaski; + #elif LL_DARWIN //---------------------------------------------------------------------------- // LL_DARWIN @@ -696,7 +758,7 @@ extern PFNGLDRAWBUFFERSARBPROC glDrawBuffersARB; #include <AvailabilityMacros.h> //GL_EXT_blend_func_separate -extern void glBlendFuncSeparateEXT(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; +extern void glBlendFuncSeparateEXT(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) ; // GL_EXT_framebuffer_object extern GLboolean glIsRenderbufferEXT(GLuint renderbuffer) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; @@ -719,6 +781,7 @@ extern void glGenerateMipmapEXT(GLenum target) AVAILABLE_MAC_OS_X_VERSION_10_4_A #ifndef GL_ARB_framebuffer_object #define glGenerateMipmap glGenerateMipmapEXT +#define GL_MAX_SAMPLES 0x8D57 #endif // GL_ARB_draw_buffers extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER; @@ -726,6 +789,46 @@ extern void glDrawBuffersARB(GLsizei n, const GLenum* bufs) AVAILABLE_MAC_OS_X_V #ifdef __cplusplus extern "C" { #endif + +// +// Define map buffer range headers on Mac +// +#ifndef GL_ARB_map_buffer_range +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#endif + +// +// Define multisample headers on Mac +// +#ifndef GL_ARB_texture_multisample +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE 0x9101 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9103 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#endif + // // Define vertex buffer object headers on Mac // diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 5eb5ffd10..d84158342 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -37,6 +37,7 @@ #include "llshadermgr.h" #include "llfile.h" #include "llrender.h" +#include "llcontrol.h" #if LL_DARWIN #include "OpenGL/OpenGL.h" @@ -54,6 +55,16 @@ using std::pair; using std::make_pair; using std::string; +GLhandleARB LLGLSLShader::sCurBoundShader = 0; +LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; +bool LLGLSLShader::sNoFixedFunction = false; + +//UI shader -- declared here so llui_libtest will link properly +//Singu note: Not using llui_libtest... and LLViewerShaderMgr is a part of newview. So, +// these are declared in newview/llviewershadermanager.cpp just like every other shader. +//LLGLSLShader gUIProgram(LLViewerShaderMgr::SHADER_INTERFACE); +//LLGLSLShader gSolidColorProgram(LLViewerShaderMgr::SHADER_INTERFACE); + BOOL shouldChange(const LLVector4& v1, const LLVector4& v2) { return v1 != v2; @@ -63,6 +74,10 @@ LLShaderFeatures::LLShaderFeatures() : calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), hasTransport(false), hasSkinning(false), hasAtmospherics(false), isSpecular(false), hasGamma(false), hasLighting(false), calculatesAtmospherics(false) +, mIndexedTextureChannels(0), disableTextureIndex(false), hasAlphaMask(false) +#if MESH_ENABLED +, hasObjectSkinning(false) +#endif //MESH_ENABLED { } @@ -116,6 +131,28 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, glDeleteObjectARB(mProgramObject); // Create program mProgramObject = glCreateProgramObjectARB(); + + static const LLCachedControl<bool> no_texture_indexing("ShyotlUseLegacyTextureBatching",false); + if (gGLManager.mGLVersion < 3.1f || no_texture_indexing) + { //force indexed texture channels to 1 if GL version is old (performance improvement for drivers with poor branching shader model support) + mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); + } + + //compile new source + vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin(); + for ( ; fileIter != mShaderFiles.end(); fileIter++ ) + { + GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second, mFeatures.mIndexedTextureChannels); + LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; + if (shaderhandle > 0) + { + attachObject(shaderhandle); + } + else + { + success = FALSE; + } + } // Attach existing objects if (!LLShaderMgr::instance()->attachShaderFeatures(this)) @@ -126,19 +163,9 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, return FALSE; } - vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin(); - for ( ; fileIter != mShaderFiles.end(); fileIter++ ) - { - GLhandleARB shaderhandle = LLShaderMgr::instance()->loadShaderFile((*fileIter).first, mShaderLevel, (*fileIter).second); - LL_DEBUGS("ShaderLoading") << "SHADER FILE: " << (*fileIter).first << " mShaderLevel=" << mShaderLevel << LL_ENDL; - if (mShaderLevel > 0) - { - attachObject(shaderhandle); - } - else - { - success = FALSE; - } + if (gGLManager.mGLVersion < 3.1f || no_texture_indexing) + { //attachShaderFeatures may have set the number of indexed texture channels, so set to 1 again + mFeatures.mIndexedTextureChannels = llmin(mFeatures.mIndexedTextureChannels, 1); } // Map attributes and uniforms @@ -166,6 +193,28 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes, return createShader(attributes,uniforms); } } + else if (mFeatures.mIndexedTextureChannels > 0) + { //override texture channels for indexed texture rendering + bind(); + S32 channel_count = mFeatures.mIndexedTextureChannels; + + for (S32 i = 0; i < channel_count; i++) + { + uniform1i(llformat("tex%d", i), i); + } + + S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten + for (U32 i = 0; i < mTexture.size(); i++) + { + if (mTexture[i] > -1 && mTexture[i] < channel_count) + { + llassert(cur_tex < gGLManager.mNumTextureImageUnits); + uniform1i(i, cur_tex); + mTexture[i] = cur_tex++; + } + } + unbind(); + } return success; } @@ -311,7 +360,8 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms) GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type) { - if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB) + if (type >= GL_SAMPLER_1D_ARB && type <= GL_SAMPLER_2D_RECT_SHADOW_ARB /*|| + type == GL_SAMPLER_2D_MULTISAMPLE*/) { //this here is a texture glUniform1iARB(location, mActiveTextureChannels); LL_DEBUGS("ShaderLoading") << "Assigned to texture channel " << mActiveTextureChannels << LL_ENDL; @@ -357,10 +407,12 @@ BOOL LLGLSLShader::link(BOOL suppress_errors) void LLGLSLShader::bind() { + gGL.flush(); if (gGLManager.mHasShaderObjects) { glUseProgramObjectARB(mProgramObject); - + sCurBoundShader = mProgramObject; + sCurBoundShaderPtr = this; if (mUniformsDirty) { LLShaderMgr::instance()->updateShaderUniforms(this); @@ -371,6 +423,7 @@ void LLGLSLShader::bind() void LLGLSLShader::unbind() { + gGL.flush(); if (gGLManager.mHasShaderObjects) { stop_glerror(); @@ -383,6 +436,8 @@ void LLGLSLShader::unbind() } } glUseProgramObjectARB(0); + sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; stop_glerror(); } } @@ -390,6 +445,8 @@ void LLGLSLShader::unbind() void LLGLSLShader::bindNoShader(void) { glUseProgramObjectARB(0); + sCurBoundShader = 0; + sCurBoundShaderPtr = NULL; } S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode) @@ -935,6 +992,12 @@ void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean } } + +void LLGLSLShader::setAlphaRange(F32 minimum, F32 maximum) +{ + uniform1f("minimum_alpha", minimum); + uniform1f("maximum_alpha", maximum); +} void LLGLSLShader::vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 3c47e7504..f05176fd5 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -48,8 +48,14 @@ public: bool hasWaterFog; // implies no gamma bool hasTransport; // implies no lighting (it's possible to have neither though) bool hasSkinning; +#if MESH_ENABLED + bool hasObjectSkinning; +#endif //MESH_ENABLED bool hasAtmospherics; bool hasGamma; + S32 mIndexedTextureChannels; + bool disableTextureIndex; + bool hasAlphaMask; // char numLights; @@ -69,6 +75,10 @@ public: LLGLSLShader(S32 shader_class); + static GLhandleARB sCurBoundShader; + static LLGLSLShader* sCurBoundShaderPtr; + static bool sNoFixedFunction; + void unload(); BOOL createShader(std::vector<std::string> * attributes, std::vector<std::string> * uniforms); @@ -105,6 +115,8 @@ public: void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); + void setAlphaRange(F32 minimum, F32 maximum); + void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); void vertexAttrib4fv(U32 index, GLfloat* v); @@ -143,4 +155,9 @@ public: std::string mName; }; +//UI shader (declared here so llui_libtest will link properly) +extern LLGLSLShader gUIProgram; +//output vec4(color.rgb,color.a*tex0[tc0].a) +extern LLGLSLShader gSolidColorProgram; + #endif diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index a439d954c..e5a782f3f 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -1400,22 +1400,36 @@ BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compre void LLImageGL::deleteDeadTextures() { + bool reset = false; + while (!sDeadTextureList.empty()) { GLuint tex = sDeadTextureList.front(); sDeadTextureList.pop_front(); - for (int i = 0; i < gGLManager.mNumTextureUnits; i++) + for (int i = 0; i < gGLManager.mNumTextureImageUnits; i++) { - if (sCurrentBoundTextures[i] == tex) + LLTexUnit* tex_unit = gGL.getTexUnit(i); + + if (tex_unit->getCurrTexture() == tex) { - gGL.getTexUnit(i)->unbind(LLTexUnit::TT_TEXTURE); + tex_unit->unbind(tex_unit->getCurrType()); stop_glerror(); + + if (i > 0) + { + reset = true; + } } } glDeleteTextures(1, &tex); stop_glerror(); } + + if (reset) + { + gGL.getTexUnit(0)->activate(); + } } void LLImageGL::destroyGLTexture() diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 60e2682a9..a88d1dca6 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -37,7 +37,8 @@ #include "llimage.h" #include "llgltypes.h" -#include "llmemory.h" +#include "llpointer.h" +#include "llrefcount.h" #include "v2math.h" #include "llrender.h" diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 552814c7e..5cd77af36 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -36,6 +36,7 @@ #include "llvertexbuffer.h" #include "llcubemap.h" +#include "llglslshader.h" #include "llimagegl.h" #include "llrendertarget.h" #include "lltexture.h" @@ -49,7 +50,9 @@ F64 gGLLastProjection[16]; F64 gGLProjection[16]; S32 gGLViewport[4]; -static const U32 LL_NUM_TEXTURE_LAYERS = 8; +U32 LLTexUnit::sWhiteTexture = 0; + +static const U32 LL_NUM_TEXTURE_LAYERS = 32; static const U32 LL_NUM_LIGHT_UNITS = 8; static GLenum sGLTextureType[] = @@ -57,6 +60,7 @@ static GLenum sGLTextureType[] = GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_CUBE_MAP_ARB + //,GL_TEXTURE_2D_MULTISAMPLE Don't use. }; static GLint sGLAddressMode[] = @@ -119,13 +123,16 @@ void LLTexUnit::refreshState(void) // We set dirty to true so that the tex unit knows to ignore caching // and we reset the cached tex unit state + gGL.flush(); + glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); // // Per apple spec, don't call glEnable/glDisable when index exceeds max texture units // http://www.mailinglistarchive.com/html/mac-opengl@lists.apple.com/2008-07/msg00653.html // - bool enableDisable = (mIndex < gGLManager.mNumTextureUnits); + bool enableDisable = !LLGLSLShader::sNoFixedFunction && + (mIndex < gGLManager.mNumTextureUnits) /*&& mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE*/; if (mCurrTexType != TT_NONE) { @@ -163,6 +170,7 @@ void LLTexUnit::activate(void) if ((S32)gGL.mCurrTextureUnitIndex != mIndex || gGL.mDirty) { + gGL.flush(); glActiveTextureARB(GL_TEXTURE0_ARB + mIndex); gGL.mCurrTextureUnitIndex = mIndex; } @@ -180,7 +188,11 @@ void LLTexUnit::enable(eTextureType type) disable(); // Force a disable of a previous texture type if it's enabled. } mCurrTexType = type; - if (mIndex < gGLManager.mNumTextureUnits) + + gGL.flush(); + if (!LLGLSLShader::sNoFixedFunction && + //type != LLTexUnit::TT_MULTISAMPLE_TEXTURE && + mIndex < gGLManager.mNumTextureUnits) { glEnable(sGLTextureType[type]); } @@ -195,7 +207,10 @@ void LLTexUnit::disable(void) { activate(); unbind(mCurrTexType); - if (mIndex < gGLManager.mNumTextureUnits) + gGL.flush(); + if (!LLGLSLShader::sNoFixedFunction && + //mCurrTexType != LLTexUnit::TT_MULTISAMPLE_TEXTURE && + mIndex < gGLManager.mNumTextureUnits) { glDisable(sGLTextureType[mCurrTexType]); } @@ -279,6 +294,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool for_rendering, bool forceBind) } if ((mCurrTexture != texture->getTexName()) || forceBind) { + gGL.flush(); activate(); enable(texture->getTarget()); mCurrTexture = texture->getTexName(); @@ -398,7 +414,15 @@ void LLTexUnit::unbind(eTextureType type) activate(); mCurrTexture = 0; - glBindTexture(sGLTextureType[type], 0); + if (LLGLSLShader::sNoFixedFunction && type == LLTexUnit::TT_TEXTURE) + { + glBindTexture(sGLTextureType[type], sWhiteTexture); + } + else + { + glBindTexture(sGLTextureType[type], 0); + } + stop_glerror(); } } @@ -406,6 +430,8 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) { if (mIndex < 0 || mCurrTexture == 0) return; + gGL.flush(); + activate(); glTexParameteri (sGLTextureType[mCurrTexType], GL_TEXTURE_WRAP_S, sGLAddressMode[mode]); @@ -418,7 +444,9 @@ void LLTexUnit::setTextureAddressMode(eTextureAddressMode mode) void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions option) { - if (mIndex < 0 || mCurrTexture == 0) return; + if (mIndex < 0 || mCurrTexture == 0 /*|| mCurrTexType == LLTexUnit::TT_MULTISAMPLE_TEXTURE*/) return; + + gGL.flush(); if (option == TFO_POINT) { @@ -464,6 +492,11 @@ void LLTexUnit::setTextureFilteringOption(LLTexUnit::eTextureFilterOptions optio void LLTexUnit::setTextureBlendType(eTextureBlendType type) { + if (LLGLSLShader::sNoFixedFunction) + { //texture blend type means nothing when using shaders + return; + } + if (mIndex < 0) return; // Do nothing if it's already correctly set. @@ -472,6 +505,8 @@ void LLTexUnit::setTextureBlendType(eTextureBlendType type) return; } + gGL.flush(); + activate(); mCurrBlendType = type; S32 scale_amount = 1; @@ -582,12 +617,18 @@ GLint LLTexUnit::getTextureSourceType(eTextureBlendSrc src, bool isAlpha) void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eTextureBlendSrc src2, bool isAlpha) { + if (LLGLSLShader::sNoFixedFunction) + { //register combiners do nothing when not using fixed function + return; + } + if (mIndex < 0) return; activate(); if (mCurrBlendType != TB_COMBINE || gGL.mDirty) { mCurrBlendType = TB_COMBINE; + gGL.flush(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); } @@ -598,6 +639,8 @@ void LLTexUnit::setTextureCombiner(eTextureBlendOp op, eTextureBlendSrc src1, eT return; } + gGL.flush(); + // Get the gl source enums according to the eTextureBlendSrc sources passed in GLint source1 = getTextureSource(src1); GLint source2 = getTextureSource(src2); @@ -730,6 +773,7 @@ void LLTexUnit::setColorScale(S32 scale) if (mCurrColorScale != scale || gGL.mDirty) { mCurrColorScale = scale; + gGL.flush(); glTexEnvi( GL_TEXTURE_ENV, GL_RGB_SCALE, scale ); } } @@ -739,6 +783,7 @@ void LLTexUnit::setAlphaScale(S32 scale) if (mCurrAlphaScale != scale || gGL.mDirty) { mCurrAlphaScale = scale; + gGL.flush(); glTexEnvi( GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale ); } } @@ -1047,6 +1092,10 @@ void LLRender::setSceneBlendType(eBlendType type) void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) { flush(); + if (LLGLSLShader::sNoFixedFunction) + { //glAlphaFunc is deprecated in OpenGL 3.3 + return; + } if (mCurrAlphaFunc != func || mCurrAlphaFuncVal != value) @@ -1062,6 +1111,30 @@ void LLRender::setAlphaRejectSettings(eCompareFunc func, F32 value) glAlphaFunc(sGLCompareFunc[func], value); } } + + if (gDebugGL) + { //make sure cached state is correct + GLint cur_func = 0; + glGetIntegerv(GL_ALPHA_TEST_FUNC, &cur_func); + + if (func == CF_DEFAULT) + { + func = CF_GREATER; + } + + if (cur_func != sGLCompareFunc[func]) + { + llerrs << "Alpha test function corrupted!" << llendl; + } + + F32 ref = 0.f; + glGetFloatv(GL_ALPHA_TEST_REF, &ref); + + if (ref != value) + { + llerrs << "Alpha test value corrupted!" << llendl; + } + } } void LLRender::blendFunc(eBlendFactor sfactor, eBlendFactor dfactor) diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 6dd4db9e5..0c6cc4589 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -58,11 +58,13 @@ class LLTexUnit { friend class LLRender; public: + static U32 sWhiteTexture; typedef enum { TT_TEXTURE = 0, // Standard 2D Texture TT_RECT_TEXTURE, // Non power of 2 texture TT_CUBE_MAP, // 6-sided cube map texture + //TT_MULTISAMPLE_TEXTURE, // see GL_ARB_texture_multisample Do not use TT_NONE // No texture type is currently enabled } eTextureType; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 4b9a897bb..145b02631 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -44,13 +44,14 @@ void check_framebuffer_status() { if (gDebugGL) { - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); switch (status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: + case GL_FRAMEBUFFER_COMPLETE: break; default: - llerrs <<"check_framebuffer_status failed" << llendl; + llwarns << "check_framebuffer_status failed -- " << std::hex << status << llendl; + ll_fail("check_framebuffer_status failed"); break; } } @@ -84,9 +85,12 @@ void LLRenderTarget::setSampleBuffer(LLMultisampleBuffer* buffer) mSampleBuffer = buffer; } -void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo) +bool LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo) { stop_glerror(); + release(); + stop_glerror(); + mResX = resx; mResY = resy; @@ -94,48 +98,49 @@ void LLRenderTarget::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, boo mUsage = usage; mUseDepth = depth; - release(); if ((sUseFBO || use_fbo) && gGLManager.mHasFramebufferObject) { if (depth) { - stop_glerror(); - allocateDepth(); - stop_glerror(); + if (!allocateDepth()) + { + llwarns << "Failed to allocate depth buffer for render target." << llendl; + return false; + } } - glGenFramebuffersEXT(1, (GLuint *) &mFBO); + glGenFramebuffers(1, (GLuint *) &mFBO); if (mDepth) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); if (mStencil) { - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); } else { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } stop_glerror(); } - addColorAttachment(color_fmt); + return addColorAttachment(color_fmt); } -void LLRenderTarget::addColorAttachment(U32 color_fmt) +bool LLRenderTarget::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { - return; + return true; } U32 offset = mTex.size(); @@ -151,52 +156,78 @@ void LLRenderTarget::addColorAttachment(U32 color_fmt) stop_glerror(); - LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + { + clear_glerror(); + LLImageGL::setManualImage(LLTexUnit::getInternalType(mUsage), 0, color_fmt, mResX, mResY, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Could not allocate color buffer for render target." << llendl; + return false; + } + } stop_glerror(); - if (offset == 0) { - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); - } - else - { //don't filter data attachments - gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - if (mUsage != LLTexUnit::TT_RECT_TEXTURE) - { - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); - } - else - { - // ATI doesn't support mirrored repeat for rectangular textures. - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + if (offset == 0) + { //use bilinear filtering on single texture render targets that aren't multisampled + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); + stop_glerror(); + } + else + { //don't filter data attachments + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + stop_glerror(); + } + + if (mUsage != LLTexUnit::TT_RECT_TEXTURE) + { + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_MIRROR); + stop_glerror(); + } + else + { + // ATI doesn't support mirrored repeat for rectangular textures. + gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + stop_glerror(); + } } + if (mFBO) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, + stop_glerror(); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, LLTexUnit::getInternalType(mUsage), tex, 0); stop_glerror(); check_framebuffer_status(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } mTex.push_back(tex); + if (gDebugGL) + { //bind and unbind to validate target + bindTarget(); + flush(); + } + + return true; } -void LLRenderTarget::allocateDepth() +bool LLRenderTarget::allocateDepth() { if (mStencil) { //use render buffers where stencil buffers are in play - glGenRenderbuffersEXT(1, (GLuint *) &mDepth); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, mResX, mResY); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); + glGenRenderbuffers(1, (GLuint *) &mDepth); + glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + stop_glerror(); + clear_glerror(); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mResX, mResY); + glBindRenderbuffer(GL_RENDERBUFFER, 0); } else { @@ -204,8 +235,18 @@ void LLRenderTarget::allocateDepth() gGL.getTexUnit(0)->bindManual(mUsage, mDepth); U32 internal_type = LLTexUnit::getInternalType(mUsage); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32_ARB, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); + stop_glerror(); + clear_glerror(); + LLImageGL::setManualImage(internal_type, 0, GL_DEPTH_COMPONENT32, mResX, mResY, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL); } + + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Unable to allocate depth buffer for render target." << llendl; + return false; + } + + return true; } void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) @@ -228,25 +269,28 @@ void LLRenderTarget::shareDepthBuffer(LLRenderTarget& target) if (mDepth) { stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, target.mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, target.mFBO); stop_glerror(); if (mStencil) { - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); stop_glerror(); target.mStencil = true; } else { - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), mDepth, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), mDepth, 0); stop_glerror(); } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - target.mUseDepth = TRUE; + check_framebuffer_status(); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + target.mUseDepth = true; } } @@ -256,7 +300,7 @@ void LLRenderTarget::release() { if (mStencil) { - glDeleteRenderbuffersEXT(1, (GLuint*) &mDepth); + glDeleteRenderbuffers(1, (GLuint*) &mDepth); stop_glerror(); } else @@ -268,23 +312,23 @@ void LLRenderTarget::release() } else if (mUseDepth && mFBO) { //detach shared depth buffer - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); if (mStencil) { //attached as a renderbuffer - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); mStencil = false; } else { //attached as a texture - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, LLTexUnit::getInternalType(mUsage), 0, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0); } mUseDepth = false; } if (mFBO) { - glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); + glDeleteFramebuffers(1, (GLuint *) &mFBO); mFBO = 0; } @@ -294,6 +338,8 @@ void LLRenderTarget::release() mTex.clear(); } + mResX = mResY = 0; + mSampleBuffer = NULL; sBoundTarget = NULL; } @@ -310,14 +356,14 @@ void LLRenderTarget::bindTarget() } else { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); stop_glerror(); if (gGLManager.mHasDrawBuffers) { //setup multiple render targets - GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, - GL_COLOR_ATTACHMENT1_EXT, - GL_COLOR_ATTACHMENT2_EXT, - GL_COLOR_ATTACHMENT3_EXT}; + GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3}; glDrawBuffersARB(mTex.size(), drawbuffers); } @@ -342,7 +388,7 @@ void LLRenderTarget::unbindTarget() { if (gGLManager.mHasFramebufferObject) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } sBoundTarget = NULL; } @@ -404,7 +450,7 @@ void LLRenderTarget::flush(bool fetch_depth) } gGL.getTexUnit(0)->bind(this); - glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8_EXT, 0, 0, mResX, mResY, 0); + glCopyTexImage2D(LLTexUnit::getInternalType(mUsage), 0, GL_DEPTH24_STENCIL8, 0, 0, mResX, mResY, 0); } gGL.getTexUnit(0)->disable(); @@ -412,56 +458,55 @@ void LLRenderTarget::flush(bool fetch_depth) else { stop_glerror(); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - + glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); if (mSampleBuffer) { - LLGLEnable multisample(GL_MULTISAMPLE_ARB); + LLGLEnable multisample(GL_MULTISAMPLE); stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); stop_glerror(); check_framebuffer_status(); - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, mSampleBuffer->mFBO); + glBindFramebuffer(GL_READ_FRAMEBUFFER, mSampleBuffer->mFBO); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI) { - glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); - glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_STENCIL_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_STENCIL_BUFFER_BIT, GL_NEAREST); } else - glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + { + glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST); + } stop_glerror(); if (mTex.size() > 1) { for (U32 i = 1; i < mTex.size(); ++i) { - glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); - glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); + glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mSampleBuffer->mTex[i]); stop_glerror(); - glBlitFramebufferEXT(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer(0, 0, mResX, mResY, 0, 0, mResX, mResY, GL_COLOR_BUFFER_BIT, GL_NEAREST); stop_glerror(); } for (U32 i = 0; i < mTex.size(); ++i) { - glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, LLTexUnit::getInternalType(mUsage), mTex[i], 0); stop_glerror(); - glFramebufferRenderbufferEXT(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+i, GL_RENDERBUFFER_EXT, mSampleBuffer->mTex[i]); + glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+i, GL_RENDERBUFFER, mSampleBuffer->mTex[i]); stop_glerror(); } } + glBindFramebuffer(GL_FRAMEBUFFER, 0); } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } } @@ -488,31 +533,36 @@ void LLRenderTarget::copyContents(LLRenderTarget& source, S32 srcX0, S32 srcY0, { stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, source.mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, source.mFBO); + check_framebuffer_status(); gGL.getTexUnit(0)->bind(this, true); stop_glerror(); glCopyTexSubImage2D(LLTexUnit::getInternalType(mUsage), 0, srcX0, srcY0, dstX0, dstY0, dstX1, dstY1); stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } else { - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mFBO); + glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mFBO); stop_glerror(); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, mFBO); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFBO); stop_glerror(); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI && mask & GL_STENCIL_BUFFER_BIT) { mask &= ~GL_STENCIL_BUFFER_BIT; - glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter); + glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter); } if(mask) - glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + stop_glerror(); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + stop_glerror(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } } @@ -531,21 +581,21 @@ void LLRenderTarget::copyContentsToFramebuffer(LLRenderTarget& source, S32 srcX0 LLGLDepthTest depth(write_depth, write_depth); - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, source.mSampleBuffer ? source.mSampleBuffer->mFBO : source.mFBO); + glBindFramebuffer(GL_READ_FRAMEBUFFER, source.mSampleBuffer ? source.mSampleBuffer->mFBO : source.mFBO); stop_glerror(); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); stop_glerror(); check_framebuffer_status(); stop_glerror(); if(gGLManager.mIsATI && mask & GL_STENCIL_BUFFER_BIT) { mask &= ~GL_STENCIL_BUFFER_BIT; - glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter); + glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_STENCIL_BUFFER_BIT, filter); } if(mask) - glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } } @@ -580,19 +630,19 @@ void LLMultisampleBuffer::release() { if (mFBO) { - glDeleteFramebuffersEXT(1, (GLuint *) &mFBO); + glDeleteFramebuffers(1, (GLuint *) &mFBO); mFBO = 0; } if (mTex.size() > 0) { - glDeleteRenderbuffersEXT(mTex.size(), (GLuint *) &mTex[0]); + glDeleteRenderbuffers(mTex.size(), (GLuint *) &mTex[0]); mTex.clear(); } if (mDepth) { - glDeleteRenderbuffersEXT(1, (GLuint *) &mDepth); + glDeleteRenderbuffers(1, (GLuint *) &mDepth); mDepth = 0; } } @@ -609,13 +659,13 @@ void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) ref = this; } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); if (gGLManager.mHasDrawBuffers) { //setup multiple render targets - GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0_EXT, - GL_COLOR_ATTACHMENT1_EXT, - GL_COLOR_ATTACHMENT2_EXT, - GL_COLOR_ATTACHMENT3_EXT}; + GLenum drawbuffers[] = {GL_COLOR_ATTACHMENT0, + GL_COLOR_ATTACHMENT1, + GL_COLOR_ATTACHMENT2, + GL_COLOR_ATTACHMENT3}; glDrawBuffersARB(ref->mTex.size(), drawbuffers); } @@ -626,14 +676,16 @@ void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) sBoundTarget = this; } -void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo ) +bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo ) { - allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2); + return allocate(resx,resy,color_fmt,depth,stencil,usage,use_fbo,2); } -void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples ) +bool LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples ) { + release(); stop_glerror(); + mResX = resx; mResY = resy; @@ -641,18 +693,18 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth mUseDepth = depth; mStencil = stencil; - release(); - if (!gGLManager.mHasFramebufferMultisample) { llerrs << "Attempting to allocate unsupported render target type!" << llendl; + return false; } - mSamples = samples; + mSamples = gGLManager.getNumFBOFSAASamples(samples); if (mSamples <= 1) { llerrs << "Cannot create a multisample buffer with less than 2 samples." << llendl; + return false; } stop_glerror(); @@ -663,36 +715,37 @@ void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, bool depth if (depth) { stop_glerror(); - allocateDepth(); + if(!allocateDepth()) + return false; stop_glerror(); } - - glGenFramebuffersEXT(1, (GLuint *) &mFBO); - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); - + glGenFramebuffers(1, (GLuint *) &mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + stop_glerror(); + clear_glerror(); if (mDepth) { - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mDepth); if (mStencil) { - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, mDepth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mDepth); } + check_framebuffer_status(); } stop_glerror(); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); stop_glerror(); } - addColorAttachment(color_fmt); + return addColorAttachment(color_fmt); } -void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) +bool LLMultisampleBuffer::addColorAttachment(U32 color_fmt) { if (color_fmt == 0) { - return; + return true; } U32 offset = mTex.size(); @@ -703,44 +756,47 @@ void LLMultisampleBuffer::addColorAttachment(U32 color_fmt) } U32 tex; - glGenRenderbuffersEXT(1, &tex); - - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tex); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, color_fmt, mResX, mResY); + glGenRenderbuffers(1, &tex); + glBindRenderbuffer(GL_RENDERBUFFER, tex); stop_glerror(); - + clear_glerror(); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, color_fmt, mResX, mResY); + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Unable to allocate color buffer for multisample render target." << llendl; + return false; + } if (mFBO) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, mFBO); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT+offset, GL_RENDERBUFFER_EXT, tex); - stop_glerror(); - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - switch (status) - { - case GL_FRAMEBUFFER_COMPLETE_EXT: - break; - default: - llerrs << "WTF? " << std::hex << status << llendl; - break; - } - - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+offset, GL_RENDERBUFFER, tex); + check_framebuffer_status(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } mTex.push_back(tex); + return true; } -void LLMultisampleBuffer::allocateDepth() +bool LLMultisampleBuffer::allocateDepth() { - glGenRenderbuffersEXT(1, (GLuint* ) &mDepth); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, mDepth); + glGenRenderbuffers(1, (GLuint* ) &mDepth); + glBindRenderbuffer(GL_RENDERBUFFER, mDepth); + stop_glerror(); + clear_glerror(); if (mStencil) { - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH24_STENCIL8_EXT, mResX, mResY); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH24_STENCIL8, mResX, mResY); } else { - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, mSamples, GL_DEPTH_COMPONENT16_ARB, mResX, mResY); } + if (glGetError() != GL_NO_ERROR) + { + llwarns << "Unable to allocate depth buffer for multisample render target." << llendl; + return false; + } + return true; } diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index fe5cf9072..685da79a6 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -77,17 +77,17 @@ public: //allocate resources for rendering //must be called before use //multiple calls will release previously allocated resources - void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE); + bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage = LLTexUnit::TT_TEXTURE, bool use_fbo = FALSE); //provide this render target with a multisample resource. void setSampleBuffer(LLMultisampleBuffer* buffer); //add color buffer attachment //limit of 4 color attachments per render target - virtual void addColorAttachment(U32 color_fmt); + virtual bool addColorAttachment(U32 color_fmt); //allocate a depth texture - virtual void allocateDepth(); + virtual bool allocateDepth(); //share depth buffer with provided render target virtual void shareDepthBuffer(LLRenderTarget& target); @@ -174,10 +174,10 @@ public: virtual void bindTarget(); void bindTarget(LLRenderTarget* ref); - virtual void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo); - void allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples); - virtual void addColorAttachment(U32 color_fmt); - virtual void allocateDepth(); + virtual bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo); + bool allocate(U32 resx, U32 resy, U32 color_fmt, bool depth, bool stencil, LLTexUnit::eTextureType usage, bool use_fbo, U32 samples); + virtual bool addColorAttachment(U32 color_fmt); + virtual bool allocateDepth(); }; #endif //!LL_MESA_HEADLESS diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 2dc3dae91..dc81d8e85 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -152,6 +152,16 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) return FALSE; } } + +#if MESH_ENABLED + if (features->hasObjectSkinning) + { + if (!shader->attachObject("avatar/objectSkinV.glsl")) + { + return FALSE; + } + } +#endif //MESH_ENABLED /////////////////////////////////////// // Attach Fragment Shader Features Next @@ -207,17 +217,79 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->hasWaterFog) { - if (!shader->attachObject("lighting/lightWaterF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightWaterAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightWaterF.glsl")) + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } else { - if (!shader->attachObject("lighting/lightF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightAlphaMaskNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightNonIndexedF.glsl")) + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightF.glsl")) + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } } @@ -228,32 +300,111 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->isShiny && features->hasWaterFog) { - if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (!shader->attachObject("lighting/lightFullbrightShinyWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightShinyWaterF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } else if (features->hasWaterFog) { - if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightWaterAlphaMaskF.glsl")) + { + return FALSE; + } + } + else if (!shader->attachObject("lighting/lightFullbrightWaterF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } else if (features->isShiny) { - if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (!shader->attachObject("lighting/lightFullbrightShinyNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightShinyF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } else { - if (!shader->attachObject("lighting/lightFullbrightF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightNonIndexedAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightNonIndexedF.glsl")) + { + return FALSE; + } + } + } + else + { + if (features->hasAlphaMask) + { + if (!shader->attachObject("lighting/lightFullbrightAlphaMaskF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightFullbrightF.glsl")) + { + return FALSE; + } + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } } @@ -264,17 +415,39 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) if (features->hasWaterFog) { - if (!shader->attachObject("lighting/lightShinyWaterF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (!shader->attachObject("lighting/lightShinyWaterNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightShinyWaterF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } else { - if (!shader->attachObject("lighting/lightShinyF.glsl")) + if (features->disableTextureIndex) { - return FALSE; + if (!shader->attachObject("lighting/lightShinyNonIndexedF.glsl")) + { + return FALSE; + } + } + else + { + if (!shader->attachObject("lighting/lightShinyF.glsl")) + { + return FALSE; + } + shader->mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits-1; } } } @@ -318,13 +491,16 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns) } } -GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type) +GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels) { - GLenum error; - error = glGetError(); - if (error != GL_NO_ERROR) + GLenum error = GL_NO_ERROR; + if (gDebugGL) { - LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL; + } } LL_DEBUGS("ShaderLoading") << "Loading shader file: " << filename << " class " << shader_level << LL_ENDL; @@ -365,11 +541,121 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade //we can't have any lines longer than 1024 characters //or any shaders longer than 1024 lines... deal - DaveP - GLcharARB buff[1024]; - GLcharARB* text[1024]; + GLcharARB buff[1024] = {0}; + GLcharARB* text[1024] = {0}; GLuint count = 0; + if (gGLManager.mGLVersion < 2.1f) + { + text[count++] = strdup("#version 110\n"); + } + else if (gGLManager.mGLVersion < 3.f) + { + //set version to 1.20 + text[count++] = strdup("#version 120\n"); + } + else + { //set version to 1.30 + text[count++] = strdup("#version 130\n"); + } + //copy preprocessor definitions into buffer + for (std::map<std::string,std::string>::iterator iter = mDefinitions.begin(); iter != mDefinitions.end(); ++iter) + { + std::string define = "#define " + iter->first + " " + iter->second + "\n"; + text[count++] = (GLcharARB *) strdup(define.c_str()); + } + + if (texture_index_channels > 0 && type == GL_FRAGMENT_SHADER_ARB) + { + //use specified number of texture channels for indexed texture rendering + + /* prepend shader code that looks like this: + + uniform sampler2D tex0; + uniform sampler2D tex1; + uniform sampler2D tex2; + . + . + . + uniform sampler2D texN; + + varying float vary_texture_index; + + vec4 diffuseLookup(vec2 texcoord) + { + switch (int(vary_texture_index+0.25)) + { + case 0: return texture2D(tex0, texcoord); + case 1: return texture2D(tex1, texcoord); + case 2: return texture2D(tex2, texcoord); + . + . + . + case N: return texture2D(texN, texcoord); + } + + return vec4(0,0,0,0); + } + */ + + //uniform declartion + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string decl = llformat("uniform sampler2D tex%d;\n", i); + text[count++] = strdup(decl.c_str()); + } + + text[count++] = strdup("varying float vary_texture_index;\n"); + text[count++] = strdup("vec4 diffuseLookup(vec2 texcoord)\n"); + text[count++] = strdup("{\n"); + + + if (texture_index_channels == 1) + { //don't use flow control, that's silly + text[count++] = strdup("return texture2D(tex0, texcoord);\n"); + text[count++] = strdup("}\n"); + } + else if (gGLManager.mGLVersion >= 3.f) + { + text[count++] = strdup("\tswitch (int(vary_texture_index+0.25))\n"); + text[count++] = strdup("\t{\n"); + + //switch body + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string case_str = llformat("\t\tcase %d: return texture2D(tex%d, texcoord);\n", i, i); + text[count++] = strdup(case_str.c_str()); + } + + text[count++] = strdup("\t}\n"); + text[count++] = strdup("\treturn vec4(0,0,0,0);\n"); + text[count++] = strdup("}\n"); + } + else + { + //switches aren't supported, make block that looks like: + /* + int ti = int(vary_texture_index+0.25); + if (ti == 0) return texture2D(tex0, texcoord); + if (ti == 1) return texture2D(tex1, texcoord); + . + . + . + if (ti == N) return texture2D(texN, texcoord); + */ + + text[count++] = strdup("int ti = int(vary_texture_index+0.25);\n"); + for (S32 i = 0; i < texture_index_channels; ++i) + { + std::string if_str = llformat("if (ti == %d) return texture2D(tex%d, texcoord);\n", i, i); + text[count++] = strdup(if_str.c_str()); + } + + text[count++] = strdup("\treturn vec4(0,0,0,0);\n"); + text[count++] = strdup("}\n"); + } + } //copy file into memory while( fgets((char *)buff, 1024, file) != NULL && count < LL_ARRAY_SIZE(buff) ) { @@ -379,51 +665,67 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade //create shader object GLhandleARB ret = glCreateShaderObjectARB(type); - error = glGetError(); - if (error != GL_NO_ERROR) + if (gDebugGL) { - LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; + error = glGetError(); + if (error != GL_NO_ERROR) + { + LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL; + glDeleteObjectARB(ret); //no longer need handle + } } - else + + //load source + glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL); + + if (gDebugGL) { - //load source - glShaderSourceARB(ret, count, (const GLcharARB**) text, NULL); error = glGetError(); if (error != GL_NO_ERROR) { LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL; glDeleteObjectARB(ret); //no longer need handle } - else + } + + //compile source + glCompileShaderARB(ret); + + if (gDebugGL) + { + error = glGetError(); + if (error != GL_NO_ERROR) { - //compile source - glCompileShaderARB(ret); - error = glGetError(); - if (error != GL_NO_ERROR) - { - LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; - glDeleteObjectARB(ret); //no longer need handle - } + LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL; + glDeleteObjectARB(ret); //no longer need handle } } - //free memory - for (GLuint i = 0; i < count; i++) - { - free(text[i]); - } + if (error == GL_NO_ERROR) { //check for errors GLint success = GL_TRUE; glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success); - error = glGetError(); - if (error != GL_NO_ERROR || success == GL_FALSE) + if (gDebugGL || success == GL_FALSE) { - //an error occured, print log - LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; - dumpObjectLog(ret); - glDeleteObjectARB(ret); //no longer need handle - ret = 0; + error = glGetError(); + if (error != GL_NO_ERROR || success == GL_FALSE) + { + //an error occured, print log + LL_WARNS("ShaderLoading") << "GLSL Compilation Error: (" << error << ") in " << filename << LL_ENDL; + dumpObjectLog(ret); + + std::stringstream ostr; + //dump shader source for debugging + for (GLuint i = 0; i < count; i++) + { + ostr << i << ": " << text[i]; + } + + LL_WARNS("ShaderLoading") << "\n" << ostr.str() << llendl; + glDeleteObjectARB(ret); //no longer need handle + ret = 0; + } } } else @@ -432,6 +734,12 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade } stop_glerror(); + //free memory + for (GLuint i = 0; i < count; i++) + { + free(text[i]); + } + //successfully loaded, save results if (ret) { @@ -444,7 +752,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade if (shader_level > 1) { shader_level--; - return loadShaderFile(filename,shader_level,type); + return loadShaderFile(filename,shader_level,type,texture_index_channels); } LL_WARNS("ShaderLoading") << "Failed to load " << filename << LL_ENDL; } diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 02f5842a1..fdc13043f 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -49,7 +49,7 @@ public: void dumpObjectLog(GLhandleARB ret, BOOL warns = TRUE); BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE); BOOL validateProgramObject(GLhandleARB obj); - GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type); + GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, S32 texture_index_channels = -1); // Implemented in the application to actually point to the shader directory. virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual @@ -66,6 +66,9 @@ public: std::vector<std::string> mReservedUniforms; + //preprocessor definitions (name/value) + std::map<std::string, std::string> mDefinitions; + protected: // our parameter manager singleton instance diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h index 8745b5059..6a08c5b2a 100644 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -39,7 +39,7 @@ #ifndef LL_TEXTURE_H #define LL_TEXTURE_H -#include "llmemory.h" +#include "llrefcount.h" class LLImageGL ; class LLTexUnit ; class LLFontGL ; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index d697b95dd..aa632b094 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -40,8 +40,9 @@ #include "llglheaders.h" #include "llmemtype.h" #include "llrender.h" - +#include "llvector4a.h" #include "llcontrol.h" +#include "llglslshader.h" //============================================================================ @@ -66,6 +67,7 @@ BOOL LLVertexBuffer::sIBOActive = FALSE; U32 LLVertexBuffer::sAllocatedBytes = 0; BOOL LLVertexBuffer::sMapped = FALSE; BOOL LLVertexBuffer::sUseStreamDraw = TRUE; +U32 LLVertexBuffer::sForceStrideMode = 0; BOOL LLVertexBuffer::sOmitBlank = FALSE; BOOL LLVertexBuffer::sPreferStreamDraw = FALSE; S32 LLVertexBuffer::sWeight4Loc = -1; @@ -87,8 +89,61 @@ void LLVBOPool::releaseName(GLuint name) LLVertexBuffer::sGLCount--; } +const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000; //1 ms -S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = +class LLGLSyncFence : public LLGLFence +{ +public: +#ifdef GL_ARB_sync + GLsync mSync; +#endif + + LLGLSyncFence() + { +#ifdef GL_ARB_sync + mSync = 0; +#endif + } + + virtual ~LLGLSyncFence() + { +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } +#endif + } + + void placeFence() + { +#ifdef GL_ARB_sync + if (mSync) + { + glDeleteSync(mSync); + } + mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); +#endif + } + + void wait() + { +#ifdef GL_ARB_sync + if (mSync) + { + while (glClientWaitSync(mSync, 0, FENCE_WAIT_TIME_NANOSECONDS) == GL_TIMEOUT_EXPIRED) + { //track the number of times we've waited here + static S32 waits = 0; + waits++; + } + } +#endif + } + + +}; + +S32 LLVertexBuffer::sTypeSize[LLVertexBuffer::TYPE_MAX] = { sizeof(LLVector4), // TYPE_VERTEX, sizeof(LLVector4), // TYPE_NORMAL, @@ -263,7 +318,8 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm) { U32 count = pos.size(); - llassert(norm.size() >= pos.size()); + llassert_always(norm.size() >= pos.size()); + llassert_always(count > 0) ; unbind(); @@ -332,6 +388,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, idx); stop_glerror(); + placeFence(); } void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const @@ -363,6 +420,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const glDrawElements(sGLMode[mode], count, GL_UNSIGNED_SHORT, ((U16*) getIndicesPointer()) + indices_offset); stop_glerror(); + placeFence(); } void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const @@ -388,6 +446,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const stop_glerror(); glDrawArrays(sGLMode[mode], first, count); stop_glerror(); + placeFence(); } //static @@ -448,7 +507,7 @@ void LLVertexBuffer::clientCopy(F64 max_time) //---------------------------------------------------------------------------- -LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : +LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage, bool strided) : LLRefCount(), mNumVerts(0), @@ -466,7 +525,10 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mFilthy(FALSE), mEmpty(TRUE), mResized(FALSE), - mDynamicSize(FALSE) + mDynamicSize(FALSE), + mIsStrided(strided), + mStride(0), + mFence(NULL) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (!sEnableVBOs) @@ -483,18 +545,27 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : { mUsage = GL_STREAM_DRAW_ARB; } - - S32 stride = calcStride(typemask, mOffsets); + + //zero out offsets + for (U32 i = 0; i < TYPE_MAX; i++) + { + mOffsets[i] = 0; + } mTypeMask = typemask; - mStride = stride; + mSize = 0; + mAlignedOffset = 0; + mAlignedIndexOffset = 0; + + if(sForceStrideMode) + mIsStrided = sForceStrideMode == 1; + sCount++; } -//static -S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets) +S32 LLVertexBuffer::calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices) { - S32 stride = 0; + S32 offset = 0; for (S32 i=0; i<TYPE_MAX; i++) { U32 mask = 1<<i; @@ -502,13 +573,50 @@ S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets) { if (offsets) { - offsets[i] = stride; + offsets[i] = offset; } - stride += sTypeOffsets[i]; + if(mIsStrided) + { + offset += sTypeSize[i]; + } + else + { + offset += LLVertexBuffer::sTypeSize[i]*num_vertices; + offset = (offset + 0xF) & ~0xF; + } + } + } + if(mIsStrided) + { + mStride = offset; + return mStride * num_vertices + 16; + } + else + { + mStride = -1; //Stride is invalid with unstrided arrays. + return offset + 16; + } +} + +//static +S32 LLVertexBuffer::calcVertexSize(const U32& typemask) +{ + S32 size = 0; + for (S32 i = 0; i < TYPE_MAX; i++) + { + U32 mask = 1<<i; + if (typemask & mask) + { + size += LLVertexBuffer::sTypeSize[i]; } } - return stride; + return size; +} + +S32 LLVertexBuffer::getSize() const +{ + return mSize; } // protected, use unref() @@ -520,9 +628,40 @@ LLVertexBuffer::~LLVertexBuffer() destroyGLIndices(); sCount--; + if (mFence) + { + delete mFence; + } + + mFence = NULL; + llassert_always(!mMappedData && !mMappedIndexData) ; }; +void LLVertexBuffer::placeFence() const +{ + /*if (!mFence && useVBOs()) + { + if (gGLManager.mHasSync) + { + mFence = new LLGLSyncFence(); + } + } + + if (mFence) + { + mFence->placeFence(); + }*/ +} + +void LLVertexBuffer::waitFence() const +{ + /*if (mFence) + { + mFence->wait(); + }*/ +} + //---------------------------------------------------------------------------- void LLVertexBuffer::genBuffer() @@ -619,8 +758,8 @@ void LLVertexBuffer::createGLBuffer() else { static int gl_buffer_idx = 0; - mGLBuffer = ++gl_buffer_idx; - mMappedData = new U8[size]; + mGLBuffer = ++gl_buffer_idx; + mMappedData = (U8*) ll_aligned_malloc_16(size); if(!sOmitBlank) memset((void*)mMappedData, 0, size); } } @@ -642,15 +781,20 @@ void LLVertexBuffer::createGLIndices() mEmpty = TRUE; + //pad by 16 bytes for aligned copies + size += 16; + if (useVBOs()) { + //pad by another 16 bytes for VBO pointer adjustment + size += 16; mMappedIndexData = NULL; genIndices(); mResized = TRUE; } else { - mMappedIndexData = new U8[size]; + mMappedIndexData = (U8*) ll_aligned_malloc_16(size); if(!sOmitBlank) memset((void*)mMappedIndexData, 0, size); static int gl_buffer_idx = 0; mGLIndices = ++gl_buffer_idx; @@ -674,7 +818,7 @@ void LLVertexBuffer::destroyGLBuffer() } else { - delete [] mMappedData; + ll_aligned_free_16((void*)mMappedData); mMappedData = NULL; mEmpty = TRUE; } @@ -683,7 +827,7 @@ void LLVertexBuffer::destroyGLBuffer() } mGLBuffer = 0; - unbind(); + //unbind(); } void LLVertexBuffer::destroyGLIndices() @@ -703,7 +847,7 @@ void LLVertexBuffer::destroyGLIndices() } else { - delete [] mMappedIndexData; + ll_aligned_free_16((void*)mMappedIndexData); mMappedIndexData = NULL; mEmpty = TRUE; } @@ -712,7 +856,7 @@ void LLVertexBuffer::destroyGLIndices() } mGLIndices = 0; - unbind(); + //unbind(); } void LLVertexBuffer::updateNumVerts(S32 nverts) @@ -728,7 +872,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) } mRequestedNumVerts = nverts; - + if (!mDynamicSize) { mNumVerts = nverts; @@ -743,7 +887,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) } mNumVerts = nverts; } - + mSize = calcOffsets(mTypeMask, mOffsets, mNumVerts); } void LLVertexBuffer::updateNumIndices(S32 nindices) @@ -779,6 +923,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) { llerrs << "Bad vertex buffer allocation: " << nverts << " : " << nindices << llendl; } + updateNumVerts(nverts); updateNumIndices(nindices); @@ -840,7 +985,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) if (!useVBOs()) { volatile U8* old = mMappedData; - mMappedData = new U8[newsize]; + mMappedData = (U8*) ll_aligned_malloc_16(newsize); if (old) { memcpy((void*)mMappedData, (void*)old, llmin(newsize, oldsize)); @@ -849,7 +994,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) memset((void*)(mMappedData+oldsize), 0, newsize-oldsize); } - delete [] old; + ll_aligned_free_16((void*)old); } else { @@ -877,7 +1022,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { //delete old buffer, keep GL buffer for now volatile U8* old = mMappedIndexData; - mMappedIndexData = new U8[new_index_size]; + mMappedIndexData = (U8*) ll_aligned_malloc_16(new_index_size); if (old) { @@ -886,7 +1031,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) { memset((void*)(mMappedIndexData+old_index_size), 0, new_index_size - old_index_size); } - delete [] old; + ll_aligned_free_16((void*)old); } else { @@ -924,8 +1069,8 @@ void LLVertexBuffer::freeClientBuffer() { if(useVBOs() && sDisableVBOMapping && (mMappedData || mMappedIndexData)) { - delete[] mMappedData ; - delete[] mMappedIndexData ; + ll_aligned_free_16((void*)mMappedData) ; + ll_aligned_free_16((void*)mMappedIndexData) ; mMappedData = NULL ; mMappedIndexData = NULL ; } @@ -935,9 +1080,8 @@ void LLVertexBuffer::allocateClientVertexBuffer() { if(!mMappedData) { - U32 size = getSize() ; - mMappedData = new U8[size]; - memset((void*)mMappedData, 0, size); + mMappedData = (U8*)ll_aligned_malloc_16(getSize()); + if (!sOmitBlank) memset((void*)mMappedData, 0, getSize()); } } @@ -945,14 +1089,13 @@ void LLVertexBuffer::allocateClientIndexBuffer() { if(!mMappedIndexData) { - U32 size = getIndicesSize(); - mMappedIndexData = new U8[size]; - memset((void*)mMappedIndexData, 0, size); + mMappedIndexData = (U8*)ll_aligned_malloc_16(getIndicesSize()); + if (!sOmitBlank) memset((void*)mMappedIndexData, 0, getIndicesSize()); } } // Map for data access -volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access) +volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mFinal) @@ -977,7 +1120,12 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access) } else { - mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + U8* src = NULL; + { + src = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src); + mAlignedOffset = mMappedData - src; } stop_glerror(); } @@ -1020,10 +1168,10 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 access) sMappedCount++; } - return mMappedData; + return mMappedData+mOffsets[type]+ (mIsStrided ? mStride : sTypeSize[type])*index; } -volatile U8* LLVertexBuffer::mapIndexBuffer(S32 access) +volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); if (mFinal) @@ -1049,7 +1197,16 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 access) } else { - mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + U8* src = NULL; + { + src = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + } + + llassert(src != NULL); + + + mMappedIndexData = src; //LL_NEXT_ALIGNED_ADDRESS<U8>(src); + mAlignedIndexOffset = mMappedIndexData - src; stop_glerror(); } } @@ -1078,13 +1235,13 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 access) sMappedCount++; } - return mMappedIndexData ; + return mMappedIndexData + sizeof(U16)*index; } void LLVertexBuffer::unmapBuffer(S32 type) { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); - if (!useVBOs()) + if (!useVBOs() || type == -2) { return ; //nothing to unmap } @@ -1165,30 +1322,36 @@ template <class T,S32 type> struct VertexBufferStrider { if (type == LLVertexBuffer::TYPE_INDEX) { - S32 stride = sizeof(T); + volatile U8* ptr = vbo.mapIndexBuffer(index); - if (vbo.mapIndexBuffer() == NULL) + if (ptr == NULL) { llwarns << "mapIndexBuffer failed!" << llendl; return FALSE; } - strider = (T*)(vbo.getMappedIndices() + index*stride); + strider = (T*)ptr; strider.setStride(0); + strider.setTypeSize(0); return TRUE; } else if (vbo.hasDataType(type)) { - S32 stride = vbo.getStride(); + S32 stride = vbo.getStride(type); + + volatile U8* ptr = vbo.mapVertexBuffer(type,index); - if (vbo.mapVertexBuffer(type) == NULL) + if (ptr == NULL) { llwarns << "mapVertexBuffer failed!" << llendl; return FALSE; } - strider = (T*)(vbo.getMappedData() + vbo.getOffset(type) + index*stride); + + strider = (T*)ptr; + strider.setStride(stride); + strider.setTypeSize(LLVertexBuffer::sTypeSize[type]); return TRUE; } else @@ -1251,25 +1414,6 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4>& strider, S32 in return VertexBufferStrider<LLVector4,TYPE_CLOTHWEIGHT>::get(*this, strider, index); } -void LLVertexBuffer::setStride(S32 type, S32 new_stride) -{ - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); - if (mNumVerts) - { - llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl; - } - // This code assumes that setStride() will only be called once per VBO per type. - S32 delta = new_stride - sTypeOffsets[type]; - for (S32 i=type+1; i<TYPE_MAX; i++) - { - if (mTypeMask & (1<<i)) - { - mOffsets[i] += delta; - } - } - mStride += delta; -} - //---------------------------------------------------------------------------- // Set for rendering @@ -1466,8 +1610,7 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const { LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); stop_glerror(); - volatile U8* base = useVBOs() ? NULL : mMappedData; - S32 stride = mStride; + volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; if ((data_mask & mTypeMask) != data_mask) { @@ -1500,68 +1643,67 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const if (data_mask & MAP_NORMAL) { - glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); + glNormalPointer(GL_FLOAT, getStride(TYPE_NORMAL), (void*)(base + mOffsets[TYPE_NORMAL])); } if (data_mask & MAP_TEXCOORD3) { glClientActiveTextureARB(GL_TEXTURE3_ARB); - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD3])); + glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD3), (void*)(base + mOffsets[TYPE_TEXCOORD3])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD2) { glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD2), (void*)(base + mOffsets[TYPE_TEXCOORD2])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD1) { glClientActiveTextureARB(GL_TEXTURE1_ARB); - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD1])); + glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD1), (void*)(base + mOffsets[TYPE_TEXCOORD1])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_BINORMAL) { glClientActiveTextureARB(GL_TEXTURE2_ARB); - glTexCoordPointer(3,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_BINORMAL])); + glTexCoordPointer(3,GL_FLOAT, getStride(TYPE_BINORMAL), (void*)(base + mOffsets[TYPE_BINORMAL])); glClientActiveTextureARB(GL_TEXTURE0_ARB); } if (data_mask & MAP_TEXCOORD0) { - glTexCoordPointer(2,GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD0), (void*)(base + mOffsets[TYPE_TEXCOORD0])); } if (data_mask & MAP_COLOR) { - glColorPointer(4, GL_UNSIGNED_BYTE, stride, (void*)(base + mOffsets[TYPE_COLOR])); + glColorPointer(4, GL_UNSIGNED_BYTE, getStride(TYPE_COLOR), (void*)(base + mOffsets[TYPE_COLOR])); } if (data_mask & MAP_WEIGHT) { - glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, stride, (void*)(base + mOffsets[TYPE_WEIGHT])); + glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, getStride(TYPE_WEIGHT), (void*)(base + mOffsets[TYPE_WEIGHT])); } if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1) { - glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, stride, (void*)(base+mOffsets[TYPE_WEIGHT4])); + glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, getStride(TYPE_WEIGHT4), (void*)(base+mOffsets[TYPE_WEIGHT4])); } if (data_mask & MAP_CLOTHWEIGHT) { - glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, getStride(TYPE_CLOTHWEIGHT), (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } if (data_mask & MAP_VERTEX) { - glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0)); + if (data_mask & MAP_TEXTURE_INDEX) + { + glVertexPointer(4,GL_FLOAT, getStride(TYPE_VERTEX), (void*)(base + 0)); + } + else + { + glVertexPointer(3,GL_FLOAT, getStride(TYPE_VERTEX), (void*)(base + 0)); + } } llglassertok(); } -void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count) -{ - // TODO: use GL_APPLE_flush_buffer_range here - /*if (useVBOs() && !mFilthy) - { - - }*/ -} diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 76080558c..2aa8f5313 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -64,6 +64,12 @@ protected: virtual void releaseName(GLuint name); }; +class LLGLFence +{ +public: + virtual void placeFence() = 0; + virtual void wait() = 0; +}; //============================================================================ // base class @@ -81,6 +87,7 @@ public: llerrs << "Illegal operation!" << llendl; return *this; } + static LLVBOPool sStreamVBOPool; static LLVBOPool sDynamicVBOPool; static LLVBOPool sStreamIBOPool; @@ -89,22 +96,28 @@ public: static S32 sWeight4Loc; static BOOL sUseStreamDraw; + static U32 sForceStrideMode; static BOOL sOmitBlank; static BOOL sPreferStreamDraw; - + static void initClass(bool use_vbo, bool no_vbo_mapping); static void cleanupClass(); static void setupClientArrays(U32 data_mask); static void drawArrays(U32 mode, const std::vector<LLVector3>& pos, const std::vector<LLVector3>& norm); + static void clientCopy(F64 max_time = 0.005); //copy data from client to GL static void unbind(); //unbind any bound vertex buffer //get the size of a vertex with the given typemask - //if offsets is not NULL, its contents will be filled - //with the offset of each vertex component in the buffer, - // indexed by the following enum - static S32 calcStride(const U32& typemask, S32* offsets = NULL); + static S32 calcVertexSize(const U32& typemask); + //get the size of a buffer with the given typemask and vertex count + //fill offsets with the offset of each vertex component array into the buffer + // indexed by the following enum + //If strided, num_vertices will be ignored. + S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices); + + enum { TYPE_VERTEX, TYPE_NORMAL, @@ -120,6 +133,9 @@ public: TYPE_CLOTHWEIGHT, TYPE_MAX, TYPE_INDEX, + + //no actual additional data, but indicates position.w is texture index + TYPE_TEXTURE_INDEX, }; enum { MAP_VERTEX = (1<<TYPE_VERTEX), @@ -134,6 +150,7 @@ public: MAP_WEIGHT = (1<<TYPE_WEIGHT), MAP_WEIGHT4 = (1<<TYPE_WEIGHT4), MAP_CLOTHWEIGHT = (1<<TYPE_CLOTHWEIGHT), + MAP_TEXTURE_INDEX = (1<<TYPE_TEXTURE_INDEX), }; protected: @@ -160,11 +177,11 @@ protected: void allocateClientIndexBuffer() ; public: - LLVertexBuffer(U32 typemask, S32 usage); + LLVertexBuffer(U32 typemask, S32 usage, bool strided=true); // map for data access - volatile U8* mapVertexBuffer(S32 type = -1, S32 access = -1); - volatile U8* mapIndexBuffer(S32 access = -1); + volatile U8* mapVertexBuffer(S32 type, S32 index); + volatile U8* mapIndexBuffer(S32 index); // set for rendering virtual void setBuffer(U32 data_mask, S32 type = -1); // calls setupVertexBuffer() if data_mask is not 0 @@ -197,22 +214,18 @@ public: S32 getRequestedVerts() const { return mRequestedNumVerts; } S32 getRequestedIndices() const { return mRequestedNumIndices; } - volatile U8* getIndicesPointer() const { return useVBOs() ? NULL : mMappedIndexData; } - volatile U8* getVerticesPointer() const { return useVBOs() ? NULL : mMappedData; } - S32 getStride() const { return mStride; } - S32 getTypeMask() const { return mTypeMask; } - BOOL hasDataType(S32 type) const { return ((1 << type) & getTypeMask()) ? TRUE : FALSE; } - S32 getSize() const { return mNumVerts*mStride; } + volatile U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; } + volatile U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; } + S32 getStride(S32 type) const { return mIsStrided ? mStride : sTypeSize[type]; } + U32 getTypeMask() const { return mTypeMask; } + bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); } + S32 getSize() const; S32 getIndicesSize() const { return mNumIndices * sizeof(U16); } volatile U8* getMappedData() const { return mMappedData; } volatile U8* getMappedIndices() const { return mMappedIndexData; } S32 getOffset(S32 type) const { return mOffsets[type]; } S32 getUsage() const { return mUsage; } - - void setStride(S32 type, S32 new_stride); - void markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count); - void draw(U32 mode, U32 count, U32 indices_offset) const; void drawArrays(U32 mode, U32 offset, U32 count) const; void drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const; @@ -228,7 +241,11 @@ protected: S32 mRequestedNumVerts; // Number of vertices requested S32 mRequestedNumIndices; // Number of indices requested - S32 mStride; + ptrdiff_t mAlignedOffset; + ptrdiff_t mAlignedIndexOffset; + bool mIsStrided; + S32 mStride; // Vertex size. + S32 mSize; // Full array size U32 mTypeMask; S32 mUsage; // GL usage U32 mGLBuffer; // GL VBO handle @@ -244,20 +261,11 @@ protected: BOOL mDynamicSize; // if TRUE, buffer has been resized at least once (and should be padded) S32 mOffsets[TYPE_MAX]; - class DirtyRegion - { - public: - U32 mIndex; - U32 mCount; - U32 mIndicesIndex; - U32 mIndicesCount; + mutable LLGLFence* mFence; - DirtyRegion(U32 vi, U32 vc, U32 ii, U32 ic) - : mIndex(vi), mCount(vc), mIndicesIndex(ii), mIndicesCount(ic) - { } - }; + void placeFence() const; + void waitFence() const; - std::vector<DirtyRegion> mDirtyRegions; //vector of dirty regions to rebuild public: static S32 sCount; @@ -269,10 +277,10 @@ public: static BOOL sDisableVBOMapping; //disable glMapBufferARB static BOOL sEnableVBOs; - static S32 sTypeOffsets[TYPE_MAX]; + static S32 sTypeSize[TYPE_MAX]; static U32 sGLMode[LLRender::NUM_MODES]; static U32 sGLRenderBuffer; - static U32 sGLRenderIndices; + static U32 sGLRenderIndices; static BOOL sVBOActive; static BOOL sIBOActive; static U32 sLastMask; diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 1dbc3de7e..ae2cfbc28 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -44,6 +44,7 @@ set(llui_SOURCE_FILES llmultislider.cpp llmultisliderctrl.cpp llnotifications.cpp + llnotificationsutil.cpp llpanel.cpp llprogressbar.cpp llradiogroup.cpp @@ -100,7 +101,9 @@ set(llui_HEADER_FILES llmodaldialog.h llmultisliderctrl.h llmultislider.h + llnotificationptr.h llnotifications.h + llnotificationsutil.h llpanel.h llprogressbar.h llradiogroup.h diff --git a/indra/llui/llalertdialog.cpp b/indra/llui/llalertdialog.cpp index f708e220e..27700ca20 100644 --- a/indra/llui/llalertdialog.cpp +++ b/indra/llui/llalertdialog.cpp @@ -349,8 +349,7 @@ bool LLAlertDialog::show() if(mDefaultOption >= 0) { // delay before enabling default button - mDefaultBtnTimer.start(); - mDefaultBtnTimer.setTimerExpirySec(DEFAULT_BUTTON_DELAY); + mDefaultBtnTimer.start(DEFAULT_BUTTON_DELAY); } // attach to floater if necessary diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 8699a5039..315ca14de 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -297,7 +297,9 @@ private: bool mDragOnLeft; BOOL mButtonsEnabled[BUTTON_COUNT]; +protected: LLButton* mButtons[BUTTON_COUNT]; +private: F32 mButtonScale; BOOL mAutoFocus; LLHandle<LLFloater> mSnappedTo; diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index 7c03f2f69..31d48084b 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -40,7 +40,7 @@ #include <boost/function.hpp> #include "llsd.h" -#include "llmemory.h" +#include "llsingleton.h" /** * @class LLFunctorRegistry diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index fe4190a2b..328e62051 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -858,8 +858,7 @@ BOOL LLLineEditor::handleHover(S32 x, S32 y, MASK mask) if (mScrollTimer.hasExpired()) { S32 increment = llround(mScrollTimer.getElapsedTimeF32() / AUTO_SCROLL_TIME); - mScrollTimer.reset(); - mScrollTimer.setTimerExpirySec(AUTO_SCROLL_TIME); + mScrollTimer.reset(AUTO_SCROLL_TIME); if( (x < mMinHPixels) && (mScrollHPos > 0 ) ) { // Scroll to the left diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h index 2272c450b..8c8229050 100644 --- a/indra/llui/lllineeditor.h +++ b/indra/llui/lllineeditor.h @@ -431,7 +431,8 @@ public: void setText(const LLStringExplicit &new_text) { mSearchEdit->setText(new_text); } - void setSearchCallback(void (*search_callback)(const std::string& search_string, void* user_data), void* data) { mSearchCallback = search_callback; mCallbackUserData = data; } + typedef boost::function<void (const std::string&, void *)> search_callback_t; + void setSearchCallback(search_callback_t cb,void *user_data) { mSearchCallback = boost::bind(cb,_1,user_data); } // LLUICtrl interface virtual void setValue(const LLSD& value ); @@ -446,7 +447,8 @@ private: LLLineEditor* mSearchEdit; class LLButton* mClearSearchButton; - void (*mSearchCallback)(const std::string& search_string, void* user_data); + + search_callback_t mSearchCallback; }; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 21c216c8c..cf9af9b32 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -77,11 +77,6 @@ S32 MENU_BAR_WIDTH = 0; /// Local function declarations, constants, enums, and typedefs ///============================================================================ -const std::string SEPARATOR_NAME("separator"); -const std::string TEAROFF_SEPARATOR_LABEL( "~~~~~~~~~~~" ); -const std::string SEPARATOR_LABEL( "-----------" ); -const std::string VERTICAL_SEPARATOR_LABEL( "|" ); - const S32 LABEL_BOTTOM_PAD_PIXELS = 2; const U32 LEFT_PAD_PIXELS = 3; @@ -101,7 +96,12 @@ const U32 SEPARATOR_HEIGHT_PIXELS = 8; const S32 TEAROFF_SEPARATOR_HEIGHT_PIXELS = 10; const S32 MENU_ITEM_PADDING = 4; -const std::string BOOLEAN_TRUE_PREFIX( "\xe2\x9c\x93" ); // U+2714 -- MC +const std::string SEPARATOR_NAME("separator"); +const std::string SEPARATOR_LABEL( "-----------" ); +const std::string VERTICAL_SEPARATOR_LABEL( "|" ); +const std::string TEAROFF_SEPARATOR_LABEL( "~~~~~~~~~~~" ); + +const std::string BOOLEAN_TRUE_PREFIX( "\xE2\x9C\x94" ); // U+2714 HEAVY CHECK MARK const std::string BRANCH_SUFFIX( "\xE2\x96\xB6" ); // U+25B6 BLACK RIGHT-POINTING TRIANGLE const std::string ARROW_UP ("^^^^^^^"); const std::string ARROW_DOWN("vvvvvvv"); diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index 06903d742..810cb0a25 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -88,8 +88,9 @@ LLMultiSlider::LLMultiSlider( mThumbCenterSelectedColor( LLUI::sColorsGroup->getColor( "MultiSliderThumbCenterSelectedColor" ) ), mDisabledThumbColor(LLUI::sColorsGroup->getColor( "MultiSliderDisabledThumbColor" ) ), mTriangleColor(LLUI::sColorsGroup->getColor( "MultiSliderTriangleColor" ) ), - mMouseDownCallback( NULL ), - mMouseUpCallback( NULL ) + mMouseDownSignal( NULL ), + mMouseUpSignal( NULL ), + mThumbWidth(MULTI_THUMB_WIDTH) { mValue.emptyMap(); mCurSlider = LLStringUtil::null; @@ -101,6 +102,13 @@ LLMultiSlider::LLMultiSlider( setValue(getValue()); } +LLMultiSlider::~LLMultiSlider() +{ + delete mMouseDownSignal; + delete mMouseUpSignal; +} + + void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from_event) { // exit if not there @@ -152,12 +160,12 @@ void LLMultiSlider::setSliderValue(const std::string& name, F32 value, BOOL from F32 t = (newValue - mMinValue) / (mMaxValue - mMinValue); - S32 left_edge = MULTI_THUMB_WIDTH/2; - S32 right_edge = getRect().getWidth() - (MULTI_THUMB_WIDTH/2); + S32 left_edge = mThumbWidth/2; + S32 right_edge = getRect().getWidth() - (mThumbWidth/2); S32 x = left_edge + S32( t * (right_edge - left_edge) ); - mThumbRects[name].mLeft = x - (MULTI_THUMB_WIDTH/2); - mThumbRects[name].mRight = x + (MULTI_THUMB_WIDTH/2); + mThumbRects[name].mLeft = x - (mThumbWidth/2); + mThumbRects[name].mRight = x + (mThumbWidth/2); } void LLMultiSlider::setValue(const LLSD& value) @@ -211,7 +219,7 @@ const std::string& LLMultiSlider::addSlider(F32 val) } // add a new thumb rect - mThumbRects[newName.str()] = LLRect( 0, getRect().getHeight(), MULTI_THUMB_WIDTH, 0 ); + mThumbRects[newName.str()] = LLRect( 0, getRect().getHeight(), mThumbWidth, 0 ); // add the value and set the current slider to this one mValue.insert(newName.str(), initVal); @@ -223,6 +231,30 @@ const std::string& LLMultiSlider::addSlider(F32 val) return mCurSlider; } +void LLMultiSlider::addSlider(F32 val, const std::string& name) +{ + F32 initVal = val; + + if(mValue.size() >= mMaxNumSliders) { + return; + } + + bool foundOne = findUnusedValue(initVal); + if(!foundOne) { + return; + } + + // add a new thumb rect + mThumbRects[name] = LLRect( 0, getRect().getHeight(), mThumbWidth, 0 ); + + // add the value and set the current slider to this one + mValue.insert(name, initVal); + mCurSlider = name; + + // move the slider + setSliderValue(mCurSlider, initVal, TRUE); +} + bool LLMultiSlider::findUnusedValue(F32& initVal) { bool firstTry = true; @@ -302,8 +334,8 @@ BOOL LLMultiSlider::handleHover(S32 x, S32 y, MASK mask) { if( gFocusMgr.getMouseCapture() == this ) { - S32 left_edge = MULTI_THUMB_WIDTH/2; - S32 right_edge = getRect().getWidth() - (MULTI_THUMB_WIDTH/2); + S32 left_edge = mThumbWidth/2; + S32 right_edge = getRect().getWidth() - (mThumbWidth/2); x += mMouseOffset; x = llclamp( x, left_edge, right_edge ); @@ -331,10 +363,9 @@ BOOL LLMultiSlider::handleMouseUp(S32 x, S32 y, MASK mask) { gFocusMgr.setMouseCapture( NULL ); - if( mMouseUpCallback ) - { - mMouseUpCallback( this, mCallbackUserData ); - } + if (mMouseUpSignal) + (*mMouseUpSignal)( this, LLSD() ); + handled = TRUE; make_ui_sound("UISndClickRelease"); } @@ -353,10 +384,8 @@ BOOL LLMultiSlider::handleMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); } - if( mMouseDownCallback ) - { - mMouseDownCallback( this, mCallbackUserData ); - } + if (mMouseDownSignal) + (*mMouseDownSignal)( this, LLSD() ); if (MASK_CONTROL & mask) // if CTRL is modifying { @@ -379,7 +408,7 @@ BOOL LLMultiSlider::handleMouseDown(S32 x, S32 y, MASK mask) // Find the offset of the actual mouse location from the center of the thumb. if (mThumbRects[mCurSlider].pointInRect(x,y)) { - mMouseOffset = (mThumbRects[mCurSlider].mLeft + MULTI_THUMB_WIDTH/2) - x; + mMouseOffset = (mThumbRects[mCurSlider].mLeft + mThumbWidth/2) - x; } else { @@ -566,6 +595,18 @@ void LLMultiSlider::draw() LLUICtrl::draw(); } +boost::signals2::connection LLMultiSlider::setMouseDownCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); + return mMouseDownSignal->connect(cb); +} + +boost::signals2::connection LLMultiSlider::setMouseUpCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t(); + return mMouseUpSignal->connect(cb); +} + // virtual LLXMLNodePtr LLMultiSlider::getXML(bool save_children) const { diff --git a/indra/llui/llmultislider.h b/indra/llui/llmultislider.h index cdbdb597f..f8363fd97 100644 --- a/indra/llui/llmultislider.h +++ b/indra/llui/llmultislider.h @@ -59,6 +59,7 @@ public: virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + virtual ~LLMultiSlider(); void setSliderValue(const std::string& name, F32 value, BOOL from_event = FALSE); F32 getSliderValue(const std::string& name) const; @@ -80,15 +81,17 @@ public: void setMinValue(F32 min_value) { mMinValue = min_value; } void setMaxValue(F32 max_value) { mMaxValue = max_value; } void setIncrement(F32 increment) { mIncrement = increment; } - void setMouseDownCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseDownCallback = cb; } - void setMouseUpCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseUpCallback = cb; } + + boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); bool findUnusedValue(F32& initVal); const std::string& addSlider(); const std::string& addSlider(F32 val); - void deleteSlider(const std::string& name); - void deleteCurSlider() { deleteSlider(mCurSlider); } - void clear(); + void addSlider(F32 val, const std::string& name); + void deleteSlider(const std::string& name); + void deleteCurSlider() { deleteSlider(mCurSlider); } + void clear(); virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -112,6 +115,7 @@ protected: S32 mMouseOffset; LLRect mDragStartThumbRect; + S32 mThumbWidth; std::map<std::string, LLRect> mThumbRects; LLColor4 mTrackColor; @@ -121,8 +125,8 @@ protected: LLColor4 mDisabledThumbColor; LLColor4 mTriangleColor; - void (*mMouseDownCallback)(LLUICtrl* ctrl, void* userdata); - void (*mMouseUpCallback)(LLUICtrl* ctrl, void* userdata); + commit_signal_t* mMouseDownSignal; + commit_signal_t* mMouseUpSignal; }; #endif // LL_LLSLIDER_H diff --git a/indra/llui/llmultisliderctrl.cpp b/indra/llui/llmultisliderctrl.cpp index f9ec6d5ee..f4970b792 100644 --- a/indra/llui/llmultisliderctrl.cpp +++ b/indra/llui/llmultisliderctrl.cpp @@ -78,9 +78,7 @@ LLMultiSliderCtrl::LLMultiSliderCtrl(const std::string& name, const LLRect& rect mEditor( NULL ), mTextBox( NULL ), mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ), - mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ), - mSliderMouseUpCallback( NULL ), - mSliderMouseDownCallback( NULL ) + mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ) { S32 top = getRect().getHeight(); S32 bottom = 0; @@ -307,17 +305,10 @@ void LLMultiSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata ) val = (F32) atof( text.c_str() ); if( self->mMultiSlider->getMinValue() <= val && val <= self->mMultiSlider->getMaxValue() ) { - if( self->mValidateCallback ) + self->setCurSliderValue( val ); + if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) && + (!self->mValidateSignal || (*(self->mValidateSignal))(self, val))) { - self->setCurSliderValue( val ); // set the value temporarily so that the callback can retrieve it. - if( self->mValidateCallback( self, self->mCallbackUserData ) ) - { - success = TRUE; - } - } - else - { - self->setCurSliderValue( val ); success = TRUE; } } @@ -348,18 +339,11 @@ void LLMultiSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata ) F32 saved_val = self->mCurValue; F32 new_val = self->mMultiSlider->getCurSliderValue(); - if( self->mValidateCallback ) + self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it. + if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) && + (!self->mValidateSignal || (*(self->mValidateSignal))(self, new_val ))) { - self->mCurValue = new_val; // set the value temporarily so that the callback can retrieve it. - if( self->mValidateCallback( self, self->mCallbackUserData ) ) - { success = TRUE; - } - } - else - { - self->mCurValue = new_val; - success = TRUE; } if( success ) @@ -435,37 +419,14 @@ void LLMultiSliderCtrl::setPrecision(S32 precision) updateText(); } -void LLMultiSliderCtrl::setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) ) +boost::signals2::connection LLMultiSliderCtrl::setSliderMouseDownCallback( const commit_signal_t::slot_type& cb ) { - mSliderMouseDownCallback = slider_mousedown_callback; - mMultiSlider->setMouseDownCallback( LLMultiSliderCtrl::onSliderMouseDown ); + return mMultiSlider->setMouseDownCallback( cb ); } -// static -void LLMultiSliderCtrl::onSliderMouseDown(LLUICtrl* caller, void* userdata) +boost::signals2::connection LLMultiSliderCtrl::setSliderMouseUpCallback( const commit_signal_t::slot_type& cb ) { - LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata; - if( self->mSliderMouseDownCallback ) - { - self->mSliderMouseDownCallback( self, self->mCallbackUserData ); - } -} - - -void LLMultiSliderCtrl::setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) ) -{ - mSliderMouseUpCallback = slider_mouseup_callback; - mMultiSlider->setMouseUpCallback( LLMultiSliderCtrl::onSliderMouseUp ); -} - -// static -void LLMultiSliderCtrl::onSliderMouseUp(LLUICtrl* caller, void* userdata) -{ - LLMultiSliderCtrl* self = (LLMultiSliderCtrl*) userdata; - if( self->mSliderMouseUpCallback ) - { - self->mSliderMouseUpCallback( self, self->mCallbackUserData ); - } + return mMultiSlider->setMouseUpCallback( cb ); } void LLMultiSliderCtrl::onTabInto() diff --git a/indra/llui/llmultisliderctrl.h b/indra/llui/llmultisliderctrl.h index b62b5ec32..47b1d1fb1 100644 --- a/indra/llui/llmultisliderctrl.h +++ b/indra/llui/llmultisliderctrl.h @@ -112,8 +112,8 @@ public: void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; } void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; } - void setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) ); - void setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) ); + boost::signals2::connection setSliderMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setSliderMouseUpCallback( const commit_signal_t::slot_type& cb ); virtual void onTabInto(); @@ -124,10 +124,8 @@ public: virtual std::string getControlName() const; static void onSliderCommit(LLUICtrl* caller, void* userdata); - static void onSliderMouseDown(LLUICtrl* caller,void* userdata); - static void onSliderMouseUp(LLUICtrl* caller,void* userdata); - - static void onEditorCommit(LLUICtrl* caller, void* userdata); + + static void onEditorCommit(LLUICtrl* ctrl, void* userdata); static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); static void onEditorChangeFocus(LLUICtrl* caller, S32 direction, void *userdata); @@ -151,9 +149,6 @@ private: LLColor4 mTextEnabledColor; LLColor4 mTextDisabledColor; - - void (*mSliderMouseUpCallback)( LLUICtrl* ctrl, void* userdata ); - void (*mSliderMouseDownCallback)( LLUICtrl* ctrl, void* userdata ); }; #endif // LL_MULTI_SLIDERCTRL_H diff --git a/indra/llui/llnotificationptr.h b/indra/llui/llnotificationptr.h new file mode 100644 index 000000000..acc047527 --- /dev/null +++ b/indra/llui/llnotificationptr.h @@ -0,0 +1,35 @@ +/** + * @file llnotificationptr.h + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLNOTIFICATIONPTR_H +#define LLNOTIFICATIONPTR_H + +// Many classes just store a single LLNotificationPtr +// and llnotifications.h is very large, so define this ligher header. +#include <boost/shared_ptr.hpp> + +class LLNotification; +typedef boost::shared_ptr<LLNotification> LLNotificationPtr; + +#endif diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 509a443e5..999f664a0 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -91,8 +91,9 @@ #include <boost/utility.hpp> #include <boost/shared_ptr.hpp> -#include <boost/type_traits.hpp> #include <boost/enable_shared_from_this.hpp> +#include <boost/type_traits.hpp> +#include <boost/signals2.hpp> // we want to minimize external dependencies, but this one is important #include "llsd.h" @@ -101,9 +102,9 @@ // and we need this to manage the notification callbacks #include "llfunctorregistry.h" #include "llui.h" +#include "llxmlnode.h" +#include "llnotificationptr.h" -class LLNotification; -typedef boost::shared_ptr<LLNotification> LLNotificationPtr; /***************************************************************************** * Signal and handler declarations diff --git a/indra/llui/llnotificationsutil.cpp b/indra/llui/llnotificationsutil.cpp new file mode 100644 index 000000000..4abc9ca69 --- /dev/null +++ b/indra/llui/llnotificationsutil.cpp @@ -0,0 +1,85 @@ +/** + * @file llnotificationsutil.cpp + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llnotificationsutil.h" + +#include "llnotifications.h" +#include "llsd.h" +#include "llxmlnode.h" // apparently needed to call LLNotifications::instance() + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name) +{ + return LLNotifications::instance().add( + LLNotification::Params(name).substitutions(LLSD()).payload(LLSD())); +} + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions) +{ + return LLNotifications::instance().add( + LLNotification::Params(name).substitutions(substitutions).payload(LLSD())); +} + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload) +{ + return LLNotifications::instance().add( + LLNotification::Params(name).substitutions(substitutions).payload(payload)); +} + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + const std::string& functor_name) +{ + return LLNotifications::instance().add( + LLNotification::Params(name).substitutions(substitutions).payload(payload).functor_name(functor_name)); +} + +LLNotificationPtr LLNotificationsUtil::add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + boost::function<void (const LLSD&, const LLSD&)> functor) +{ + return LLNotifications::instance().add( + LLNotification::Params(name).substitutions(substitutions).payload(payload).functor(functor)); +} + +S32 LLNotificationsUtil::getSelectedOption(const LLSD& notification, const LLSD& response) +{ + return LLNotification::getSelectedOption(notification, response); +} + +void LLNotificationsUtil::cancel(LLNotificationPtr pNotif) +{ + LLNotifications::instance().cancel(pNotif); +} + +LLNotificationPtr LLNotificationsUtil::find(LLUUID uuid) +{ + return LLNotifications::instance().find(uuid); +} diff --git a/indra/llui/llnotificationsutil.h b/indra/llui/llnotificationsutil.h new file mode 100644 index 000000000..4093324d0 --- /dev/null +++ b/indra/llui/llnotificationsutil.h @@ -0,0 +1,66 @@ +/** + * @file llnotificationsutil.h + * + * $LicenseInfo:firstyear=2008&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLNOTIFICATIONSUTIL_H +#define LLNOTIFICATIONSUTIL_H + +// The vast majority of clients of the notifications system just want to add +// a notification to the screen, so define this lightweight public interface +// to avoid including the heavyweight llnotifications.h + +#include "llnotificationptr.h" + +#include <boost/function.hpp> + +class LLSD; + +namespace LLNotificationsUtil +{ + LLNotificationPtr add(const std::string& name); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + const std::string& functor_name); + + LLNotificationPtr add(const std::string& name, + const LLSD& substitutions, + const LLSD& payload, + boost::function<void (const LLSD&, const LLSD&)> functor); + + S32 getSelectedOption(const LLSD& notification, const LLSD& response); + + void cancel(LLNotificationPtr pNotif); + + LLNotificationPtr find(LLUUID uuid); +} + +#endif diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 9edc6451a..cc7f7bdcc 100644 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -54,6 +54,7 @@ #include "lluictrlfactory.h" #include "llviewborder.h" #include "llbutton.h" +#include "llnotificationsutil.h" // LLLayoutStack #include "llresizebar.h" @@ -1049,7 +1050,7 @@ void LLPanel::childDisplayNotFound() mNewExpectedMembers.clear(); LLSD args; args["CONTROLS"] = msg; - LLNotifications::instance().add("FloaterNotFound", args); + LLNotificationsUtil::add("FloaterNotFound", args); } void LLPanel::storeRectControl() diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp index 68fd08921..07649adfa 100644 --- a/indra/llui/llresmgr.cpp +++ b/indra/llui/llresmgr.cpp @@ -453,15 +453,17 @@ const std::string LLLocale::USER_LOCALE("en_US.utf8"); const std::string LLLocale::SYSTEM_LOCALE("C"); #endif +static std::string PrevFailedLocaleString = ""; LLLocale::LLLocale(const std::string& locale_string) { mPrevLocaleString = setlocale( LC_ALL, NULL ); char* new_locale_string = setlocale( LC_ALL, locale_string.c_str()); - if ( new_locale_string == NULL) + if ( new_locale_string == NULL && PrevFailedLocaleString != locale_string ) { llwarns << "Failed to set locale " << locale_string.c_str() << llendl; setlocale(LC_ALL, SYSTEM_LOCALE.c_str()); + PrevFailedLocaleString = locale_string; } //else //{ diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp index 28b30cccb..145901681 100644 --- a/indra/llui/llslider.cpp +++ b/indra/llui/llslider.cpp @@ -70,8 +70,8 @@ LLSlider::LLSlider( mTrackColor( LLUI::sColorsGroup->getColor( "SliderTrackColor" ) ), mThumbOutlineColor( LLUI::sColorsGroup->getColor( "SliderThumbOutlineColor" ) ), mThumbCenterColor( LLUI::sColorsGroup->getColor( "SliderThumbCenterColor" ) ), - mMouseDownCallback( NULL ), - mMouseUpCallback( NULL ) + mMouseDownSignal( NULL ), + mMouseUpSignal( NULL ) { mThumbImage = LLUI::getUIImage("icn_slide-thumb_dark.tga"); mTrackImage = LLUI::getUIImage("icn_slide-groove_dark.tga"); @@ -87,6 +87,11 @@ LLSlider::LLSlider( mDragStartThumbRect = mThumbRect; } +LLSlider::~LLSlider() +{ + delete mMouseDownSignal; + delete mMouseUpSignal; +} void LLSlider::setValue(F32 value, BOOL from_event) { @@ -109,10 +114,11 @@ void LLSlider::setValue(F32 value, BOOL from_event) void LLSlider::updateThumbRect() { + const S32 DEFAULT_THUMB_SIZE = 16; F32 t = (mValue - mMinValue) / (mMaxValue - mMinValue); - S32 thumb_width = mThumbImage->getWidth(); - S32 thumb_height = mThumbImage->getHeight(); + S32 thumb_width = mThumbImage ? mThumbImage->getWidth() : DEFAULT_THUMB_SIZE; + S32 thumb_height = mThumbImage ? mThumbImage->getHeight() : DEFAULT_THUMB_SIZE; S32 left_edge = (thumb_width / 2); S32 right_edge = getRect().getWidth() - (thumb_width / 2); @@ -169,10 +175,9 @@ BOOL LLSlider::handleMouseUp(S32 x, S32 y, MASK mask) { gFocusMgr.setMouseCapture( NULL ); - if( mMouseUpCallback ) - { - mMouseUpCallback( this, mCallbackUserData ); - } + if (mMouseUpSignal) + (*mMouseUpSignal)( this, getValueF32() ); + handled = TRUE; make_ui_sound("UISndClickRelease"); } @@ -191,10 +196,8 @@ BOOL LLSlider::handleMouseDown(S32 x, S32 y, MASK mask) { setFocus(TRUE); } - if( mMouseDownCallback ) - { - mMouseDownCallback( this, mCallbackUserData ); - } + if (mMouseDownSignal) + (*mMouseDownSignal)( this, getValueF32() ); if (MASK_CONTROL & mask) // if CTRL is modifying { @@ -309,6 +312,17 @@ LLXMLNodePtr LLSlider::getXML(bool save_children) const return node; } +boost::signals2::connection LLSlider::setMouseDownCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mMouseDownSignal) mMouseDownSignal = new commit_signal_t(); + return mMouseDownSignal->connect(cb); +} + +boost::signals2::connection LLSlider::setMouseUpCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mMouseUpSignal) mMouseUpSignal = new commit_signal_t(); + return mMouseUpSignal->connect(cb); +} //static LLView* LLSlider::fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory) diff --git a/indra/llui/llslider.h b/indra/llui/llslider.h index 253b72803..e09f537dd 100644 --- a/indra/llui/llslider.h +++ b/indra/llui/llslider.h @@ -55,6 +55,7 @@ public: virtual LLXMLNodePtr getXML(bool save_children = true) const; static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory); + virtual ~LLSlider(); void setValue( F32 value, BOOL from_event = FALSE ); F32 getValueF32() const { return mValue; } @@ -71,8 +72,10 @@ public: void setMinValue(F32 min_value) {mMinValue = min_value; updateThumbRect(); } void setMaxValue(F32 max_value) {mMaxValue = max_value; updateThumbRect(); } void setIncrement(F32 increment) {mIncrement = increment;} - void setMouseDownCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseDownCallback = cb; } - void setMouseUpCallback( void (*cb)(LLUICtrl* ctrl, void* userdata) ) { mMouseUpCallback = cb; } + + boost::signals2::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); + virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -103,8 +106,8 @@ private: LLColor4 mThumbOutlineColor; LLColor4 mThumbCenterColor; - void (*mMouseDownCallback)(LLUICtrl* ctrl, void* userdata); - void (*mMouseUpCallback)(LLUICtrl* ctrl, void* userdata); + commit_signal_t* mMouseDownSignal; + commit_signal_t* mMouseUpSignal; }; #endif // LL_LLSLIDER_H diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp index 51d43fbb7..ad6382729 100644 --- a/indra/llui/llsliderctrl.cpp +++ b/indra/llui/llsliderctrl.cpp @@ -76,9 +76,7 @@ LLSliderCtrl::LLSliderCtrl(const std::string& name, const LLRect& rect, mEditor( NULL ), mTextBox( NULL ), mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ), - mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ), - mSliderMouseUpCallback( NULL ), - mSliderMouseDownCallback( NULL ) + mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ) { S32 top = getRect().getHeight(); S32 bottom = 0; @@ -238,17 +236,10 @@ void LLSliderCtrl::onEditorCommit( LLUICtrl* caller, void *userdata ) val = (F32) atof( text.c_str() ); if( self->mSlider->getMinValue() <= val && val <= self->mSlider->getMaxValue() ) { - if( self->mValidateCallback ) + self->setValue( val ); + if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) && + (!self->mValidateSignal || (*(self->mValidateSignal))( self, val ))) { - self->setValue( val ); // set the value temporarily so that the callback can retrieve it. - if( self->mValidateCallback( self, self->mCallbackUserData ) ) - { - success = TRUE; - } - } - else - { - self->setValue( val ); success = TRUE; } } @@ -279,17 +270,10 @@ void LLSliderCtrl::onSliderCommit( LLUICtrl* caller, void *userdata ) F32 saved_val = self->mValue; F32 new_val = self->mSlider->getValueF32(); - if( self->mValidateCallback ) + self->mValue = new_val; // set the value temporarily so that the callback can retrieve it. + if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) && + (!self->mValidateSignal || (*(self->mValidateSignal))( self, new_val ))) { - self->mValue = new_val; // set the value temporarily so that the callback can retrieve it. - if( self->mValidateCallback( self, self->mCallbackUserData ) ) - { - success = TRUE; - } - } - else - { - self->mValue = new_val; success = TRUE; } @@ -366,37 +350,14 @@ void LLSliderCtrl::setPrecision(S32 precision) updateText(); } -void LLSliderCtrl::setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) ) +boost::signals2::connection LLSliderCtrl::setSliderMouseDownCallback( const commit_signal_t::slot_type& cb ) { - mSliderMouseDownCallback = slider_mousedown_callback; - mSlider->setMouseDownCallback( LLSliderCtrl::onSliderMouseDown ); + return mSlider->setMouseDownCallback( cb ); } -// static -void LLSliderCtrl::onSliderMouseDown(LLUICtrl* caller, void* userdata) +boost::signals2::connection LLSliderCtrl::setSliderMouseUpCallback( const commit_signal_t::slot_type& cb ) { - LLSliderCtrl* self = (LLSliderCtrl*) userdata; - if( self->mSliderMouseDownCallback ) - { - self->mSliderMouseDownCallback( self, self->mCallbackUserData ); - } -} - - -void LLSliderCtrl::setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) ) -{ - mSliderMouseUpCallback = slider_mouseup_callback; - mSlider->setMouseUpCallback( LLSliderCtrl::onSliderMouseUp ); -} - -// static -void LLSliderCtrl::onSliderMouseUp(LLUICtrl* caller, void* userdata) -{ - LLSliderCtrl* self = (LLSliderCtrl*) userdata; - if( self->mSliderMouseUpCallback ) - { - self->mSliderMouseUpCallback( self, self->mCallbackUserData ); - } + return mSlider->setMouseUpCallback( cb ); } void LLSliderCtrl::onTabInto() diff --git a/indra/llui/llsliderctrl.h b/indra/llui/llsliderctrl.h index 272dd7ffd..68748eb4d 100644 --- a/indra/llui/llsliderctrl.h +++ b/indra/llui/llsliderctrl.h @@ -75,14 +75,18 @@ public: virtual LLSD getValue() const { return LLSD(getValueF32()); } virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); } - virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); } + BOOL isMouseHeldDown() const { return mSlider->hasMouseCapture(); } + + virtual void setPrecision(S32 precision); + virtual void setEnabled( BOOL b ); virtual void clear(); - virtual void setPrecision(S32 precision); + + virtual void setMinValue(LLSD min_value) { setMinValue((F32)min_value.asReal()); } + virtual void setMaxValue(LLSD max_value) { setMaxValue((F32)max_value.asReal()); } void setMinValue(F32 min_value) { mSlider->setMinValue(min_value); updateText(); } void setMaxValue(F32 max_value) { mSlider->setMaxValue(max_value); updateText(); } void setIncrement(F32 increment) { mSlider->setIncrement(increment);} @@ -94,8 +98,8 @@ public: void setLabelColor(const LLColor4& c) { mTextEnabledColor = c; } void setDisabledLabelColor(const LLColor4& c) { mTextDisabledColor = c; } - void setSliderMouseDownCallback( void (*slider_mousedown_callback)(LLUICtrl* caller, void* userdata) ); - void setSliderMouseUpCallback( void (*slider_mouseup_callback)(LLUICtrl* caller, void* userdata) ); + boost::signals2::connection setSliderMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setSliderMouseUpCallback( const commit_signal_t::slot_type& cb ); virtual void onTabInto(); @@ -111,8 +115,6 @@ public: virtual std::string getControlName() const { return mSlider->getControlName(); } static void onSliderCommit(LLUICtrl* caller, void* userdata); - static void onSliderMouseDown(LLUICtrl* caller,void* userdata); - static void onSliderMouseUp(LLUICtrl* caller,void* userdata); static void onEditorCommit(LLUICtrl* caller, void* userdata); static void onEditorGainFocus(LLFocusableElement* caller, void *userdata); @@ -138,9 +140,6 @@ private: LLColor4 mTextEnabledColor; LLColor4 mTextDisabledColor; - - void (*mSliderMouseUpCallback)( LLUICtrl* ctrl, void* userdata ); - void (*mSliderMouseDownCallback)( LLUICtrl* ctrl, void* userdata ); }; #endif // LL_LLSLIDERCTRL_H diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp index 717604670..f833dac6c 100644 --- a/indra/llui/llspinctrl.cpp +++ b/indra/llui/llspinctrl.cpp @@ -168,21 +168,15 @@ void LLSpinCtrl::onUpBtn( void *userdata ) val = clamp_precision(val, self->mPrecision); val = llmin( val, self->mMaxValue ); - if( self->mValidateCallback ) + F32 saved_val = (F32)self->getValue().asReal(); + self->setValue(val); + if( (self->mValidateCallback && !self->mValidateCallback( self, self->mCallbackUserData ) ) || + (self->mValidateSignal && !(*(self->mValidateSignal))( self, val ) )) { - F32 saved_val = (F32)self->getValue().asReal(); - self->setValue(val); - if( !self->mValidateCallback( self, self->mCallbackUserData ) ) - { - self->setValue( saved_val ); - self->reportInvalidData(); - self->updateEditor(); - return; - } - } - else - { - self->setValue(val); + self->setValue( saved_val ); + self->reportInvalidData(); + self->updateEditor(); + return; } self->updateEditor(); @@ -201,21 +195,19 @@ void LLSpinCtrl::onDownBtn( void *userdata ) val = clamp_precision(val, self->mPrecision); val = llmax( val, self->mMinValue ); - if( self->mValidateCallback ) + + if (val < self->mMinValue) val = self->mMinValue; + if (val > self->mMaxValue) val = self->mMaxValue; + + F32 saved_val = (F32)self->getValue().asReal(); + self->setValue(val); + if( (self->mValidateCallback && !self->mValidateCallback( self, self->mCallbackUserData ) ) || + (self->mValidateSignal && !(*(self->mValidateSignal))( self, val ) )) { - F32 saved_val = (F32)self->getValue().asReal(); - self->setValue(val); - if( !self->mValidateCallback( self, self->mCallbackUserData ) ) - { - self->setValue( saved_val ); - self->reportInvalidData(); - self->updateEditor(); - return; - } - } - else - { - self->setValue(val); + self->setValue( saved_val ); + self->reportInvalidData(); + self->updateEditor(); + return; } self->updateEditor(); @@ -303,32 +295,20 @@ void LLSpinCtrl::onEditorCommit( LLUICtrl* caller, void *userdata ) if (val < self->mMinValue) val = self->mMinValue; if (val > self->mMaxValue) val = self->mMaxValue; - if( self->mValidateCallback ) + F32 saved_val = self->mValue; + self->mValue = val; + + if( (!self->mValidateCallback || self->mValidateCallback( self, self->mCallbackUserData )) && + (!self->mValidateSignal || (*(self->mValidateSignal))(self, val))) { - F32 saved_val = self->mValue; - self->mValue = val; - if( self->mValidateCallback( self, self->mCallbackUserData ) ) - { - success = TRUE; - self->onCommit(); - } - else - { - self->mValue = saved_val; - } + success = TRUE; + self->onCommit(); } else { - self->mValue = val; - self->onCommit(); - success = TRUE; + self->mValue = saved_val; } } - else - { - // We want to update the editor in case it fails while blanking -- MC - success = TRUE; - } if( success ) { diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index 1f94191d2..e1bf4d4aa 100644 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -630,49 +630,59 @@ LLXMLNodePtr LLTabContainer::getXML(bool save_children) const // virtual BOOL LLTabContainer::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, EDragAndDropType type, void* cargo_data, EAcceptance *accept, std::string &tooltip) { - BOOL has_scroll_arrows = (getMaxScrollPos() > 0); + bool const has_scroll_arrows = (getMaxScrollPos() > 0); - if( mDragAndDropDelayTimer.getElapsedTimeF32() > SCROLL_DELAY_TIME ) + LLButton* button = NULL; + if (has_scroll_arrows) { - if (has_scroll_arrows) + // We're dragging an inventory item. Check if we're hovering over scroll arrows of this tab container. + if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y)) { - if (mJumpPrevArrowBtn && mJumpPrevArrowBtn->getRect().pointInRect(x, y)) + button = mJumpPrevArrowBtn; + } + else if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y)) + { + button = mJumpNextArrowBtn; + } + else if (mPrevArrowBtn->getRect().pointInRect(x, y)) + { + button = mPrevArrowBtn; + } + else if (mNextArrowBtn->getRect().pointInRect(x, y)) + { + button = mNextArrowBtn; + } + if (button) + { + if (mDragAndDropDelayTimer.getStarted() && mDragAndDropDelayTimer.hasExpired()) { - S32 local_x = x - mJumpPrevArrowBtn->getRect().mLeft; - S32 local_y = y - mJumpPrevArrowBtn->getRect().mBottom; - mJumpPrevArrowBtn->handleHover(local_x, local_y, mask); + // We've been hovering (another) SCROLL_DELAY_TIME seconds. Emulate a button press. + button->onCommit(); + // Reset the timer. + mDragAndDropDelayTimer.start(SCROLL_DELAY_TIME); } - if (mJumpNextArrowBtn && mJumpNextArrowBtn->getRect().pointInRect(x, y)) + else if (!mDragAndDropDelayTimer.getStarted()) { - S32 local_x = x - mJumpNextArrowBtn->getRect().mLeft; - S32 local_y = y - mJumpNextArrowBtn->getRect().mBottom; - mJumpNextArrowBtn->handleHover(local_x, local_y, mask); - } - if (mPrevArrowBtn->getRect().pointInRect(x, y)) - { - S32 local_x = x - mPrevArrowBtn->getRect().mLeft; - S32 local_y = y - mPrevArrowBtn->getRect().mBottom; - mPrevArrowBtn->handleHover(local_x, local_y, mask); - } - else if (mNextArrowBtn->getRect().pointInRect(x, y)) - { - S32 local_x = x - mNextArrowBtn->getRect().mLeft; - S32 local_y = y - mNextArrowBtn->getRect().mBottom; - mNextArrowBtn->handleHover(local_x, local_y, mask); + // We just entered the arrow. Start the timer. + mDragAndDropDelayTimer.start(SCROLL_DELAY_TIME); } } - - for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + else { - LLTabTuple* tuple = *iter; - tuple->mButton->setVisible( TRUE ); - S32 local_x = x - tuple->mButton->getRect().mLeft; - S32 local_y = y - tuple->mButton->getRect().mBottom; - if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible()) - { - tuple->mButton->onCommit(); - mDragAndDropDelayTimer.stop(); - } + // We're not on an arrow or just left it. Stop the time (in case it was running). + mDragAndDropDelayTimer.stop(); + } + } + + for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter) + { + LLTabTuple* tuple = *iter; + tuple->mButton->setVisible( TRUE ); + S32 local_x = x - tuple->mButton->getRect().mLeft; + S32 local_y = y - tuple->mButton->getRect().mBottom; + if (tuple->mButton->pointInView(local_x, local_y) && tuple->mButton->getEnabled() && !tuple->mTabPanel->getVisible()) + { + tuple->mButton->onCommit(); } } @@ -1849,5 +1859,3 @@ void LLTabContainer::commitHoveredButton(S32 x, S32 y) } } - - diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3326524cb..0a951e7e9 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -4095,7 +4095,7 @@ void LLTextEditor::appendHighlightedText(const std::string &new_text, if (highlight && stylep) { - LLSD pieces = highlight->parsePartialLineHighlights(new_text, stylep->getColor(), highlight_part); + LLSD pieces = highlight->parsePartialLineHighlights(new_text, stylep->getColor(), (LLTextParser::EHighlightPosition)highlight_part); bool lprepend=prepend_newline; for (S32 i=0;i<pieces.size();i++) { diff --git a/indra/llui/lltextparser.cpp b/indra/llui/lltextparser.cpp index 707dd0afd..c8a85dd86 100644 --- a/indra/llui/lltextparser.cpp +++ b/indra/llui/lltextparser.cpp @@ -43,29 +43,14 @@ #include "v4color.h" #include "lldir.h" -// Routines used for parsing text for TextParsers and html - -LLTextParser* LLTextParser::sInstance = NULL; - // // Member Functions // -LLTextParser::~LLTextParser() -{ - sInstance=NULL; -} +LLTextParser::LLTextParser() +: mLoaded(false) +{} -// static -LLTextParser* LLTextParser::getInstance() -{ - if (!sInstance) - { - sInstance = new LLTextParser(); - sInstance->loadFromDisk(); - } - return sInstance; -} // Moved triggerAlerts() to llfloaterchat.cpp to break llui/llaudio library dependency. @@ -103,8 +88,10 @@ S32 LLTextParser::findPattern(const std::string &text, LLSD highlight) return found; } -LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, S32 part, S32 index) +LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, EHighlightPosition part, S32 index) { + loadKeywords(); + //evil recursive string atomizer. LLSD ret_llsd, start_llsd, middle_llsd, end_llsd; @@ -122,7 +109,7 @@ LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLC { S32 end = std::string(mHighlights[i]["pattern"]).length(); S32 len = text.length(); - S32 newpart; + EHighlightPosition newpart; if (start==0) { start_llsd[0]["text"] =text.substr(0,end); @@ -195,6 +182,8 @@ LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLC bool LLTextParser::parseFullLineHighlights(const std::string &text, LLColor4 *color) { + loadKeywords(); + for (S32 i=0;i<mHighlights.size();i++) { if ((S32)mHighlights[i]["highlight"]==ALL || (S32)mHighlights[i]["condition"]==MATCHES) @@ -221,14 +210,14 @@ std::string LLTextParser::getFileName() return path; } -LLSD LLTextParser::loadFromDisk() +void LLTextParser::loadKeywords() { - std::string filename=getFileName(); - if (filename.empty()) - { - llwarns << "LLTextParser::loadFromDisk() no valid user directory." << llendl; + if (mLoaded) + {// keywords already loaded + return; } - else + std::string filename=getFileName(); + if (!filename.empty()) { llifstream file; file.open(filename.c_str()); @@ -237,23 +226,21 @@ LLSD LLTextParser::loadFromDisk() LLSDSerialize::fromXML(mHighlights, file); } file.close(); + mLoaded = true; } - - return mHighlights; } bool LLTextParser::saveToDisk(LLSD highlights) { mHighlights=highlights; - std::string filename=getFileName(); - if (filename.empty()) + if (gDirUtilp->getLindenUserDir(true).empty()) { - llwarns << "LLTextParser::saveToDisk() no valid user directory." << llendl; - return FALSE; + // User didn't login, so nothing to save. + return false; } llofstream file; - file.open(filename.c_str()); + file.open(getFileName().c_str()); LLSDSerialize::toPrettyXML(mHighlights, file); file.close(); - return TRUE; + return true; } diff --git a/indra/llui/lltextparser.h b/indra/llui/lltextparser.h index 32343a2da..f1a1b10ed 100644 --- a/indra/llui/lltextparser.h +++ b/indra/llui/lltextparser.h @@ -35,34 +35,34 @@ #define LL_LLTEXTPARSER_H #include "llsd.h" +#include "llsingleton.h" class LLUUID; class LLVector3d; class LLColor4; -class LLTextParser +class LLTextParser : public LLSingleton<LLTextParser> { public: - enum ConditionType { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH }; - enum HighlightType { PART, ALL }; - enum HighlightPosition { WHOLE, START, MIDDLE, END }; - enum DialogAction { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE }; + typedef enum e_condition_type { CONTAINS, MATCHES, STARTS_WITH, ENDS_WITH } EConditionType; + typedef enum e_highlight_type { PART, ALL } EHighlightType; + typedef enum e_highlight_position { WHOLE, START, MIDDLE, END } EHighlightPosition; + typedef enum e_dialog_action { ACTION_NONE, ACTION_CLOSE, ACTION_ADD, ACTION_COPY, ACTION_UPDATE } EDialogAction; - static LLTextParser* getInstance(); - LLTextParser(){}; - ~LLTextParser(); + LLTextParser(); - S32 findPattern(const std::string &text, LLSD highlight); - LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color,S32 part=WHOLE, S32 index=0); + LLSD parsePartialLineHighlights(const std::string &text,const LLColor4 &color, EHighlightPosition part=WHOLE, S32 index=0); bool parseFullLineHighlights(const std::string &text, LLColor4 *color); - std::string getFileName(); - LLSD loadFromDisk(); - bool saveToDisk(LLSD highlights); -public: - LLSD mHighlights; + S32 findPattern(const std::string &text, LLSD highlight); private: - static LLTextParser* sInstance; + std::string getFileName(); + void loadKeywords(); + bool saveToDisk(LLSD highlights); + +public: + LLSD mHighlights; + bool mLoaded; }; #endif diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index a947c434d..dae598e8c 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -487,8 +487,15 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex if (solid_color) { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); + if (LLGLSLShader::sNoFixedFunction) + { + gSolidColorProgram.bind(); + } + else + { + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); + } } gGL.pushMatrix(); @@ -624,7 +631,14 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex if (solid_color) { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + else + { + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } } } diff --git a/indra/llui/llui.h b/indra/llui/llui.h index a77ffa32e..541811852 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -39,6 +39,7 @@ #include "llcontrol.h" #include "llrect.h" #include "llcoord.h" +#include "llglslshader.h" //#include "llhtmlhelp.h" #include "llgl.h" // *TODO: break this dependency #include <stack> diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index 3f4ab5e45..49767a547 100644 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -42,6 +42,8 @@ static LLRegisterWidget<LLUICtrl> r("ui_ctrl"); // NOTE: the LLFocusableElement implementation has been moved to llfocusmgr.cpp, to mirror the header where the class is defined. LLUICtrl::LLUICtrl() : + mCommitSignal(NULL), + mValidateSignal(NULL), mCommitCallback(NULL), mLostTopCallback(NULL), mValidateCallback(NULL), @@ -59,7 +61,9 @@ LLUICtrl::LLUICtrl(const std::string& name, const LLRect& rect, BOOL mouse_opaqu : // can't make this automatically follow top and left, breaks lots // of buttons in the UI. JC 7/20/2002 LLView( name, rect, mouse_opaque, reshape ), - mCommitCallback( on_commit_callback) , + mCommitSignal(NULL), + mValidateSignal(NULL), + mCommitCallback( on_commit_callback), mLostTopCallback( NULL ), mValidateCallback( NULL ), mCallbackUserData( callback_userdata ), @@ -78,6 +82,9 @@ LLUICtrl::~LLUICtrl() llwarns << "UI Control holding top ctrl deleted: " << getName() << ". Top view removed." << llendl; gFocusMgr.removeTopCtrlWithoutCallback( this ); } + + delete mCommitSignal; + delete mValidateSignal; } void LLUICtrl::onCommit() @@ -86,6 +93,8 @@ void LLUICtrl::onCommit() { mCommitCallback( this, mCallbackUserData ); } + if (mCommitSignal) + (*mCommitSignal)(this, getValue()); } //virtual @@ -555,3 +564,15 @@ void LLUICtrl::setMinValue(LLSD min_value) // virtual void LLUICtrl::setMaxValue(LLSD max_value) { } + +boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb ) +{ + if (!mCommitSignal) mCommitSignal = new commit_signal_t(); + return mCommitSignal->connect(cb); +} + +boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t::slot_type& cb ) +{ + if (!mValidateSignal) mValidateSignal = new enable_signal_t(); + return mValidateSignal->connect(cb); +} diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h index be8e86336..519b45c0b 100644 --- a/indra/llui/lluictrl.h +++ b/indra/llui/lluictrl.h @@ -43,6 +43,9 @@ class LLUICtrl : public LLView { public: + typedef boost::signals2::signal<void (LLUICtrl* ctrl, const LLSD& param)> commit_signal_t; + typedef boost::signals2::signal<bool (LLUICtrl* ctrl, const LLSD& param), boost_boolean_combiner> enable_signal_t; + typedef void (*LLUICtrlCallback)(LLUICtrl* ctrl, void* userdata); typedef BOOL (*LLUICtrlValidate)(LLUICtrl* ctrl, void* userdata); @@ -111,6 +114,12 @@ public: LLUICtrl* getParentUICtrl() const; + //Start using these! + boost::signals2::connection setCommitCallback( const commit_signal_t::slot_type& cb ); + boost::signals2::connection setValidateCallback( const enable_signal_t::slot_type& cb ); + + // *TODO: Deprecate; for backwards compatability only: + //Keeping userdata around with legacy setCommitCallback because it's used ALL OVER THE PLACE. void* getCallbackUserData() const { return mCallbackUserData; } void setCallbackUserData( void* data ) { mCallbackUserData = data; } @@ -132,6 +141,8 @@ public: protected: + commit_signal_t* mCommitSignal; + enable_signal_t* mValidateSignal; void (*mCommitCallback)( LLUICtrl* ctrl, void* userdata ); void (*mLostTopCallback)( LLUICtrl* ctrl, void* userdata ); BOOL (*mValidateCallback)( LLUICtrl* ctrl, void* userdata ); diff --git a/indra/llui/lluitrans.cpp b/indra/llui/lluitrans.cpp index 920fe6ad0..a60ff370d 100644 --- a/indra/llui/lluitrans.cpp +++ b/indra/llui/lluitrans.cpp @@ -36,6 +36,7 @@ #include "llxmlnode.h" #include "lluictrlfactory.h" #include "llalertdialog.h" +#include "llnotificationsutil.h" #include <map> @@ -93,7 +94,7 @@ std::string LLUITrans::getString(const std::string &xml_desc, const LLStringUtil LLSD args; args["STRING_NAME"] = xml_desc; LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; - LLNotifications::instance().add("MissingString", args); + LLNotificationsUtil::add("MissingString", args); return xml_desc; } diff --git a/indra/llui/llviewquery.h b/indra/llui/llviewquery.h index e87795f9a..98d9bf879 100644 --- a/indra/llui/llviewquery.h +++ b/indra/llui/llviewquery.h @@ -35,7 +35,7 @@ #include <list> -#include "llmemory.h" +#include "llsingleton.h" #include "llui.h" class LLView; diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp index 59c1d6fd2..a0f319a90 100644 --- a/indra/llvfs/lldiriterator.cpp +++ b/indra/llvfs/lldiriterator.cpp @@ -51,8 +51,24 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) { fs::path dir_path(dirname); - // Check if path exists. - if (!fs::exists(dir_path)) + bool is_dir = false; + + // Check if path is a directory. + try + { + is_dir = fs::is_directory(dir_path); + } +#if BOOST_FILESYSTEM_VERSION >= 3 + catch (fs::filesystem_error& e) +#else + catch (fs::basic_filesystem_error<fs::path>& e) +#endif + { + llwarns << e.what() << llendl; + return; + } + + if (!is_dir) { llwarns << "Invalid path: \"" << dir_path.string() << "\"" << llendl; return; @@ -63,10 +79,10 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) { mIter = fs::directory_iterator(dir_path); } -#if BOOST_FILESYSTEM_VERSION == 2 - catch (fs::basic_filesystem_error<fs::path>& e) -#else +#if BOOST_FILESYSTEM_VERSION >= 3 catch (fs::filesystem_error& e) +#else + catch (fs::basic_filesystem_error<fs::path>& e) #endif { llerrs << e.what() << llendl; @@ -112,10 +128,10 @@ bool LLDirIterator::Impl::next(std::string &fname) while (mIter != end_itr && !found) { boost::smatch match; -#if BOOST_FILESYSTEM_VERSION == 2 - std::string name = mIter->path().filename(); -#else +#if BOOST_FILESYSTEM_VERSION >= 3 std::string name = mIter->path().filename().string(); +#else + std::string name = mIter->path().filename(); #endif if (found = boost::regex_match(name, match, mFilterExp)) { diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp index 28cee2940..5df5eadbe 100644 --- a/indra/llvfs/llpidlock.cpp +++ b/indra/llvfs/llpidlock.cpp @@ -167,7 +167,7 @@ bool LLPidLockFile::requestLock(LLNameTable<void *> *name_table, bool autosave, if (!mWaiting) //Not presently waiting to save. Queue up. { - mTimer.resetWithExpiry(timeout); + mTimer.reset(timeout); mWaiting=TRUE; } diff --git a/indra/llwindow/CMakeLists.txt b/indra/llwindow/CMakeLists.txt index 710789fc4..8d927f7e9 100644 --- a/indra/llwindow/CMakeLists.txt +++ b/indra/llwindow/CMakeLists.txt @@ -33,14 +33,18 @@ include_directories( set(llwindow_SOURCE_FILES llkeyboard.cpp + llkeyboardheadless.cpp llwindowheadless.cpp + llwindowcallbacks.cpp ) -set(llwindows_HEADER_FILES +set(llwindow_HEADER_FILES CMakeLists.txt llkeyboard.h + llkeyboardheadless.h llwindowheadless.h + llwindowcallbacks.h ) set(viewer_SOURCE_FILES @@ -55,10 +59,13 @@ set(viewer_HEADER_FILES # Libraries on which this library depends, needed for Linux builds # Sort by high-level to low-level -set(llwindow_LINK_LIBRARIES - ${UI_LIBRARIES} # for GTK - ${SDL_LIBRARY} - ) +if (LINUX AND VIEWER) + set(llwindow_LINK_LIBRARIES + ${UI_LIBRARIES} # for GTK + ${SDL_LIBRARY} + fontconfig # For FCInit and other FC* functions. + ) +endif (LINUX AND VIEWER) if (DARWIN) list(APPEND llwindow_SOURCE_FILES @@ -81,7 +88,7 @@ if (DARWIN) ) endif (DARWIN) -if (LINUX) +if (LINUX AND VIEWER) list(APPEND viewer_SOURCE_FILES llkeyboardsdl.cpp llwindowsdl.cpp @@ -90,21 +97,24 @@ if (LINUX) llkeyboardsdl.h llwindowsdl.h ) -endif (LINUX) +endif (LINUX AND VIEWER) if (WINDOWS) list(APPEND llwindow_SOURCE_FILES llwindowwin32.cpp lldxhardware.cpp llkeyboardwin32.cpp + lldragdropwin32.cpp ) list(APPEND llwindow_HEADER_FILES llwindowwin32.h lldxhardware.h llkeyboardwin32.h + lldragdropwin32.h ) list(APPEND llwindow_LINK_LIBRARIES comdlg32 # Common Dialogs for ChooseColor + ole32 ) endif (WINDOWS) @@ -141,8 +151,7 @@ if (SERVER AND NOT WINDOWS AND NOT DARWIN) ${llwindow_SOURCE_FILES} ${server_SOURCE_FILES} ) - add_dependencies(llwindowheadless prepare) - # *TODO: This should probably have target_link_libraries + target_link_libraries (llwindowheadless ${llwindow_LINK_LIBRARIES}) endif (SERVER AND NOT WINDOWS AND NOT DARWIN) if (llwindow_HEADER_FILES) diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp new file mode 100644 index 000000000..d4d444eb2 --- /dev/null +++ b/indra/llwindow/lldragdropwin32.cpp @@ -0,0 +1,365 @@ +/** + * @file lldragdrop32.cpp + * @brief Handler for Windows specific drag and drop (OS to client) code + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#if LL_WINDOWS + +#if LL_OS_DRAGDROP_ENABLED + +#include "linden_common.h" + +#include "llwindowwin32.h" +#include "llkeyboardwin32.h" +#include "llwindowcallbacks.h" +#include "lldragdropwin32.h" + +class LLDragDropWin32Target: + public IDropTarget +{ + public: + //////////////////////////////////////////////////////////////////////////////// + // + LLDragDropWin32Target( HWND hWnd ) : + mRefCount( 1 ), + mAppWindowHandle( hWnd ), + mAllowDrop(false), + mIsSlurl(false) + { + }; + + virtual ~LLDragDropWin32Target() + { + }; + + //////////////////////////////////////////////////////////////////////////////// + // + ULONG __stdcall AddRef( void ) + { + return InterlockedIncrement( &mRefCount ); + }; + + //////////////////////////////////////////////////////////////////////////////// + // + ULONG __stdcall Release( void ) + { + LONG count = InterlockedDecrement( &mRefCount ); + + if ( count == 0 ) + { + delete this; + return 0; + } + else + { + return count; + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall QueryInterface( REFIID iid, void** ppvObject ) + { + if ( iid == IID_IUnknown || iid == IID_IDropTarget ) + { + AddRef(); + *ppvObject = this; + return S_OK; + } + else + { + *ppvObject = 0; + return E_NOINTERFACE; + }; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragEnter( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) + { + FORMATETC fmtetc = { CF_TEXT, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + + // support CF_TEXT using a HGLOBAL? + if ( S_OK == pDataObject->QueryGetData( &fmtetc ) ) + { + mAllowDrop = true; + mDropUrl = std::string(); + mIsSlurl = false; + + STGMEDIUM stgmed; + if( S_OK == pDataObject->GetData( &fmtetc, &stgmed ) ) + { + PVOID data = GlobalLock( stgmed.hGlobal ); + mDropUrl = std::string( (char*)data ); + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + MASK mask = gKeyboard->currentMask(TRUE); + + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; + + GlobalUnlock( stgmed.hGlobal ); + ReleaseStgMedium( &stgmed ); + }; + SetFocus( mAppWindowHandle ); + } + else + { + mAllowDrop = false; + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragOver( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) + { + if ( mAllowDrop ) + { + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt2; + pt2.x = pt.x; + pt2.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt2 ); + + LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + MASK mask = gKeyboard->currentMask(TRUE); + + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_TRACK, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; + } + else + { + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall DragLeave( void ) + { + // XXX MAJOR MAJOR HACK! + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong(mAppWindowHandle, GWL_USERDATA); + if (NULL != window_imp) + { + LLCoordGL gl_coord( 0, 0 ); + MASK mask = gKeyboard->currentMask(TRUE); + window_imp->completeDragNDropRequest( gl_coord, mask, LLWindowCallbacks::DNDA_STOP_TRACKING, mDropUrl ); + }; + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + HRESULT __stdcall Drop( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) + { + if ( mAllowDrop ) + { + // window impl stored in Window data (neat!) + LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA ); + if ( NULL != window_imp ) + { + LLCoordGL gl_coord( 0, 0 ); + + POINT pt_client; + pt_client.x = pt.x; + pt_client.y = pt.y; + ScreenToClient( mAppWindowHandle, &pt_client ); + + LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); + window_imp->convertCoords(cursor_coord_window, &gl_coord); + llinfos << "### (Drop) URL is: " << mDropUrl << llendl; + llinfos << "### raw coords are: " << pt.x << " x " << pt.y << llendl; + llinfos << "### client coords are: " << pt_client.x << " x " << pt_client.y << llendl; + llinfos << "### GL coords are: " << gl_coord.mX << " x " << gl_coord.mY << llendl; + llinfos << llendl; + + // no keyboard modifier option yet but we could one day + MASK mask = gKeyboard->currentMask( TRUE ); + + // actually do the drop + LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask, + LLWindowCallbacks::DNDA_DROPPED, mDropUrl ); + + switch (result) + { + case LLWindowCallbacks::DND_COPY: + *pdwEffect = DROPEFFECT_COPY; + break; + case LLWindowCallbacks::DND_LINK: + *pdwEffect = DROPEFFECT_LINK; + break; + case LLWindowCallbacks::DND_MOVE: + *pdwEffect = DROPEFFECT_MOVE; + break; + case LLWindowCallbacks::DND_NONE: + default: + *pdwEffect = DROPEFFECT_NONE; + break; + } + }; + } + else + { + *pdwEffect = DROPEFFECT_NONE; + }; + + return S_OK; + }; + + //////////////////////////////////////////////////////////////////////////////// + // + private: + LONG mRefCount; + HWND mAppWindowHandle; + bool mAllowDrop; + std::string mDropUrl; + bool mIsSlurl; + friend class LLWindowWin32; +}; + +//////////////////////////////////////////////////////////////////////////////// +// +LLDragDropWin32::LLDragDropWin32() : + mDropTarget( NULL ), + mDropWindowHandle( NULL ) + +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +LLDragDropWin32::~LLDragDropWin32() +{ +} + +//////////////////////////////////////////////////////////////////////////////// +// +bool LLDragDropWin32::init( HWND hWnd ) +{ + if ( NOERROR != OleInitialize( NULL ) ) + return FALSE; + + mDropTarget = new LLDragDropWin32Target( hWnd ); + if ( mDropTarget ) + { + HRESULT result = CoLockObjectExternal( mDropTarget, TRUE, FALSE ); + if ( S_OK == result ) + { + result = RegisterDragDrop( hWnd, mDropTarget ); + if ( S_OK != result ) + { + // RegisterDragDrop failed + return false; + }; + + // all ok + mDropWindowHandle = hWnd; + } + else + { + // Unable to lock OLE object + return false; + }; + }; + + // success + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLDragDropWin32::reset() +{ + if ( mDropTarget ) + { + RevokeDragDrop( mDropWindowHandle ); + CoLockObjectExternal( mDropTarget, FALSE, TRUE ); + mDropTarget->Release(); + }; + + OleUninitialize(); +} + +#endif // LL_OS_DRAGDROP_ENABLED + +#endif // LL_WINDOWS + diff --git a/indra/llwindow/lldragdropwin32.h b/indra/llwindow/lldragdropwin32.h new file mode 100644 index 000000000..929e7f9e3 --- /dev/null +++ b/indra/llwindow/lldragdropwin32.h @@ -0,0 +1,74 @@ +/** + * @file lldragdrop32.cpp + * @brief Handler for Windows specific drag and drop (OS to client) code + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, 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$ + */ + +#if LL_WINDOWS + +#if LL_OS_DRAGDROP_ENABLED + +#ifndef LL_LLDRAGDROP32_H +#define LL_LLDRAGDROP32_H + +#include <windows.h> +#include <ole2.h> + +class LLDragDropWin32 +{ + public: + LLDragDropWin32(); + ~LLDragDropWin32(); + + bool init( HWND hWnd ); + void reset(); + + private: + IDropTarget* mDropTarget; + HWND mDropWindowHandle; +}; +#endif // LL_LLDRAGDROP32_H + +#else // LL_OS_DRAGDROP_ENABLED + +#ifndef LL_LLDRAGDROP32_H +#define LL_LLDRAGDROP32_H + +#include <windows.h> +#include <ole2.h> + +// imposter class that does nothing +class LLDragDropWin32 +{ + public: + LLDragDropWin32() {}; + ~LLDragDropWin32() {}; + + bool init( HWND hWnd ) { return false; }; + void reset() { }; +}; +#endif // LL_LLDRAGDROP32_H + +#endif // LL_OS_DRAGDROP_ENABLED + +#endif // LL_WINDOWS diff --git a/indra/llwindow/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp index 02b4ed17c..f0f618aef 100644 --- a/indra/llwindow/llkeyboard.cpp +++ b/indra/llwindow/llkeyboard.cpp @@ -34,7 +34,7 @@ #include "indra_constants.h" #include "llkeyboard.h" -#include "llwindow.h" +#include "llwindowcallbacks.h" // diff --git a/indra/llwindow/llkeyboardheadless.cpp b/indra/llwindow/llkeyboardheadless.cpp new file mode 100644 index 000000000..c87617c9f --- /dev/null +++ b/indra/llwindow/llkeyboardheadless.cpp @@ -0,0 +1,73 @@ +/** + * @file llkeyboardheadless.cpp + * @brief Handler for assignable key bindings + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llkeyboardheadless.h" +#include "llwindowcallbacks.h" + +LLKeyboardHeadless::LLKeyboardHeadless() +{ } + +void LLKeyboardHeadless::resetMaskKeys() +{ } + + +BOOL LLKeyboardHeadless::handleKeyDown(const U16 key, const U32 mask) +{ return FALSE; } + + +BOOL LLKeyboardHeadless::handleKeyUp(const U16 key, const U32 mask) +{ return FALSE; } + +MASK LLKeyboardHeadless::currentMask(BOOL for_mouse_event) +{ return MASK_NONE; } + +void LLKeyboardHeadless::scanKeyboard() +{ + for (S32 key = 0; key < KEY_COUNT; key++) + { + // Generate callback if any event has occurred on this key this frame. + // Can't just test mKeyLevel, because this could be a slow frame and + // key might have gone down then up. JC + if (mKeyLevel[key] || mKeyDown[key] || mKeyUp[key]) + { + mCurScanKey = key; + mCallbacks->handleScanKey(key, mKeyDown[key], mKeyUp[key], mKeyLevel[key]); + } + } + + // Reset edges for next frame + for (S32 key = 0; key < KEY_COUNT; key++) + { + mKeyUp[key] = FALSE; + mKeyDown[key] = FALSE; + if (mKeyLevel[key]) + { + mKeyLevelFrameCount[key]++; + } + } +} + diff --git a/indra/llwindow/llkeyboardheadless.h b/indra/llwindow/llkeyboardheadless.h new file mode 100644 index 000000000..4e666f8ce --- /dev/null +++ b/indra/llwindow/llkeyboardheadless.h @@ -0,0 +1,45 @@ +/** + * @file llkeyboardheadless.h + * @brief Handler for assignable key bindings + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLKEYBOARDHEADLESS_H +#define LL_LLKEYBOARDHEADLESS_H + +#include "llkeyboard.h" + +class LLKeyboardHeadless : public LLKeyboard +{ +public: + LLKeyboardHeadless(); + /*virtual*/ ~LLKeyboardHeadless() {}; + + /*virtual*/ BOOL handleKeyUp(const U16 key, MASK mask); + /*virtual*/ BOOL handleKeyDown(const U16 key, MASK mask); + /*virtual*/ void resetMaskKeys(); + /*virtual*/ MASK currentMask(BOOL for_mouse_event); + /*virtual*/ void scanKeyboard(); +}; + +#endif diff --git a/indra/llwindow/llkeyboardmacosx.cpp b/indra/llwindow/llkeyboardmacosx.cpp index ec8203216..f53773c39 100644 --- a/indra/llwindow/llkeyboardmacosx.cpp +++ b/indra/llwindow/llkeyboardmacosx.cpp @@ -34,7 +34,7 @@ #include "linden_common.h" #include "llkeyboardmacosx.h" -#include "llwindow.h" +#include "llwindowcallbacks.h" #include <Carbon/Carbon.h> diff --git a/indra/llwindow/llkeyboardsdl.cpp b/indra/llwindow/llkeyboardsdl.cpp index 8a6b6d629..8a0b1de98 100644 --- a/indra/llwindow/llkeyboardsdl.cpp +++ b/indra/llwindow/llkeyboardsdl.cpp @@ -34,7 +34,7 @@ #include "linden_common.h" #include "llkeyboardsdl.h" -#include "llwindow.h" +#include "llwindowcallbacks.h" #include "SDL/SDL.h" LLKeyboardSDL::LLKeyboardSDL() diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp index a06f19149..1d3fa0fc6 100644 --- a/indra/llwindow/llkeyboardwin32.cpp +++ b/indra/llwindow/llkeyboardwin32.cpp @@ -34,14 +34,15 @@ #include "linden_common.h" -#include "llkeyboardwin32.h" - -#include "llwindow.h" - #define WIN32_LEAN_AND_MEAN #include <winsock2.h> #include <windows.h> +#include "llkeyboardwin32.h" + +#include "llwindowcallbacks.h" + + LLKeyboardWin32::LLKeyboardWin32() { // Set up key mapping for windows - eventually can read this from a file? @@ -63,7 +64,7 @@ LLKeyboardWin32::LLKeyboardWin32() // numpad number keys for (cur_char = 0x60; cur_char <= 0x69; cur_char++) { - mTranslateKeyMap[cur_char] = (KEY)('0' + (0x60 - cur_char)); + mTranslateKeyMap[cur_char] = (KEY)('0' + (cur_char - 0x60)); } @@ -78,7 +79,7 @@ LLKeyboardWin32::LLKeyboardWin32() mTranslateKeyMap[VK_OEM_COMMA] = ','; mTranslateKeyMap[VK_OEM_MINUS] = '-'; mTranslateKeyMap[VK_OEM_PERIOD] = '.'; - mTranslateKeyMap[VK_OEM_2] = KEY_PAD_DIVIDE; + mTranslateKeyMap[VK_OEM_2] = '/';//This used to be KEY_PAD_DIVIDE, but that breaks typing into text fields in media prims mTranslateKeyMap[VK_OEM_3] = '`'; mTranslateKeyMap[VK_OEM_4] = '['; mTranslateKeyMap[VK_OEM_5] = '\\'; diff --git a/indra/llwindow/llpreeditor.h b/indra/llwindow/llpreeditor.h index 370f76cb8..623406f30 100644 --- a/indra/llwindow/llpreeditor.h +++ b/indra/llwindow/llpreeditor.h @@ -95,7 +95,7 @@ public: // the returned LLWString contains it. virtual const LLWString & getWText() const = 0; - + const LLWString & getPreeditString() const {return getWText();} // Handle a UTF-32 char on this preeditor, i.e., add the character // to the contents. // This is a back door of the method of same name of LLWindowCallback. diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 7e412a14d..615247893 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -46,14 +46,11 @@ #include "llerror.h" #include "llkeyboard.h" #include "linked_lists.h" - -//static instance for default callbacks -LLWindowCallbacks LLWindow::sDefaultCallbacks; +#include "llwindowcallbacks.h" // // LLWindowCallbacks // - LLSplashScreen *gSplashScreenp = NULL; BOOL gDebugClicks = FALSE; BOOL gDebugWindowProc = FALSE; @@ -67,158 +64,6 @@ const std::string gURLProtocolWhitelist[] = { "file:", "http:", "https:" }; // Important - these lists should match - protocol to handler const std::string gURLProtocolWhitelistHandler[] = { "http", "http", "https" }; -BOOL LLWindowCallbacks::handleTranslatedKeyDown(const KEY key, const MASK mask, BOOL repeated) -{ - return FALSE; -} - - -BOOL LLWindowCallbacks::handleTranslatedKeyUp(const KEY key, const MASK mask) -{ - return FALSE; -} - -void LLWindowCallbacks::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) -{ -} - -BOOL LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask) -{ - return FALSE; -} - - -BOOL LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask) -{ - return FALSE; -} - -BOOL LLWindowCallbacks::handleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask) -{ - return FALSE; -} - -void LLWindowCallbacks::handleMouseLeave(LLWindow *window) -{ - return; -} - -BOOL LLWindowCallbacks::handleCloseRequest(LLWindow *window) -{ - //allow the window to close - return TRUE; -} - -void LLWindowCallbacks::handleQuit(LLWindow *window) -{ - if(LLWindowManager::destroyWindow(window) == FALSE) - { - llerrs << "LLWindowCallbacks::handleQuit() : Couldn't destroy window" << llendl; - } -} - -BOOL LLWindowCallbacks::handleRightMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask) -{ - return FALSE; -} - -BOOL LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask) -{ - return FALSE; -} - -BOOL LLWindowCallbacks::handleMiddleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask) -{ - return FALSE; -} - -BOOL LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask) -{ - return FALSE; -} - -BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated) -{ - return FALSE; -} - -BOOL LLWindowCallbacks::handleActivateApp(LLWindow *window, BOOL activating) -{ - return FALSE; -} - -void LLWindowCallbacks::handleMouseMove(LLWindow *window, const LLCoordGL pos, MASK mask) -{ -} - -void LLWindowCallbacks::handleScrollWheel(LLWindow *window, S32 clicks) -{ -} - -void LLWindowCallbacks::handleResize(LLWindow *window, const S32 width, const S32 height) -{ -} - -void LLWindowCallbacks::handleFocus(LLWindow *window) -{ -} - -void LLWindowCallbacks::handleFocusLost(LLWindow *window) -{ -} - -void LLWindowCallbacks::handleMenuSelect(LLWindow *window, const S32 menu_item) -{ -} - -BOOL LLWindowCallbacks::handlePaint(LLWindow *window, const S32 x, const S32 y, - const S32 width, const S32 height) -{ - return FALSE; -} - -BOOL LLWindowCallbacks::handleDoubleClick(LLWindow *window, const LLCoordGL pos, MASK mask) -{ - return FALSE; -} - -void LLWindowCallbacks::handleWindowBlock(LLWindow *window) -{ -} - -void LLWindowCallbacks::handleWindowUnblock(LLWindow *window) -{ -} - -void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *data) -{ -} - -BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window) -{ - return FALSE; -} - -BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window) -{ - return FALSE; -} - -void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg) -{ - -} - -void LLWindowCallbacks::handlePauseWatchdog(LLWindow *window) -{ - -} - -void LLWindowCallbacks::handleResumeWatchdog(LLWindow *window) -{ - -} - S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type) { @@ -257,8 +102,8 @@ S32 OSMessageBox(const std::string& text, const std::string& caption, U32 type) // LLWindow // -LLWindow::LLWindow(BOOL fullscreen, U32 flags) - : mCallbacks(&sDefaultCallbacks), +LLWindow::LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags) + : mCallbacks(callbacks), mPostQuit(TRUE), mFullscreen(fullscreen), mFullscreenWidth(0), @@ -277,7 +122,23 @@ LLWindow::LLWindow(BOOL fullscreen, U32 flags) mHighSurrogate(0) { } - + +LLWindow::~LLWindow() +{ + +} + +//virtual +BOOL LLWindow::isValid() +{ + return TRUE; +} + +//virtual +BOOL LLWindow::canDelete() +{ + return TRUE; +} // virtual void LLWindow::incBusyCount() { @@ -293,13 +154,28 @@ void LLWindow::decBusyCount() } } -void LLWindow::setCallbacks(LLWindowCallbacks *callbacks) +//virtual +void LLWindow::resetBusyCount() { - mCallbacks = callbacks; - if (gKeyboard) - { - gKeyboard->setCallbacks(callbacks); - } + mBusyCount = 0; +} + +//virtual +S32 LLWindow::getBusyCount() const +{ + return mBusyCount; +} + +//virtual +ECursorType LLWindow::getCursor() const +{ + return mCurrentCursor; +} + +//virtual +BOOL LLWindow::dialogColorPicker(F32 *r, F32 *g, F32 *b) +{ + return FALSE; } void *LLWindow::getMediaWindow() @@ -462,23 +338,7 @@ void LLSplashScreen::hide() static std::set<LLWindow*> sWindowList; LLWindow* LLWindowManager::createWindow( - const std::string& title, - const std::string& name, - LLCoordScreen upper_left, - LLCoordScreen size, - U32 flags, - BOOL fullscreen, - BOOL clearBg, - BOOL disable_vsync, - BOOL use_gl, - BOOL ignore_pixel_depth) -{ - return createWindow( - title, name, upper_left.mX, upper_left.mY, size.mX, size.mY, flags, - fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth); -} - -LLWindow* LLWindowManager::createWindow( + LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, @@ -492,26 +352,26 @@ LLWindow* LLWindowManager::createWindow( if (use_gl) { #if LL_MESA_HEADLESS - new_window = new LLWindowMesaHeadless( + new_window = new LLWindowMesaHeadless(callbacks, title, name, x, y, width, height, flags, fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth); #elif LL_SDL - new_window = new LLWindowSDL( + new_window = new LLWindowSDL(callbacks, title, x, y, width, height, flags, fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); #elif LL_WINDOWS - new_window = new LLWindowWin32( + new_window = new LLWindowWin32(callbacks, title, name, x, y, width, height, flags, fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); #elif LL_DARWIN - new_window = new LLWindowMacOSX( + new_window = new LLWindowMacOSX(callbacks, title, name, x, y, width, height, flags, fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth, fsaa_samples); #endif } else { - new_window = new LLWindowHeadless( + new_window = new LLWindowHeadless(callbacks, title, name, x, y, width, height, flags, fullscreen, clearBg, disable_vsync, use_gl, ignore_pixel_depth); } diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index 4d1d4a808..a15332e2f 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -37,54 +37,15 @@ #include "llcoord.h" #include "llstring.h" #include "llcursortypes.h" +#include "llsd.h" class LLSplashScreen; class LLWindow; class LLPreeditor; +class LLWindowCallbacks; -class LLWindowCallbacks -{ -public: - virtual ~LLWindowCallbacks() {} - virtual BOOL handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated); - virtual BOOL handleTranslatedKeyUp(KEY key, MASK mask); - virtual void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level); - virtual BOOL handleUnicodeChar(llwchar uni_char, MASK mask); - - virtual BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); - virtual BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); - virtual void handleMouseLeave(LLWindow *window); - // return TRUE to allow window to close, which will then cause handleQuit to be called - virtual BOOL handleCloseRequest(LLWindow *window); - // window is about to be destroyed, clean up your business - virtual void handleQuit(LLWindow *window); - virtual BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); - virtual BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); - virtual BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); - virtual BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); - virtual BOOL handleActivate(LLWindow *window, BOOL activated); - virtual BOOL handleActivateApp(LLWindow *window, BOOL activating); - virtual void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask); - virtual void handleScrollWheel(LLWindow *window, S32 clicks); - virtual void handleResize(LLWindow *window, S32 width, S32 height); - virtual void handleFocus(LLWindow *window); - virtual void handleFocusLost(LLWindow *window); - virtual void handleMenuSelect(LLWindow *window, S32 menu_item); - virtual BOOL handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height); - virtual BOOL handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask); // double-click of left mouse button - virtual void handleWindowBlock(LLWindow *window); // window is taking over CPU for a while - virtual void handleWindowUnblock(LLWindow *window); // window coming back after taking over CPU for a while - virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data); - virtual BOOL handleTimerEvent(LLWindow *window); - virtual BOOL handleDeviceChange(LLWindow *window); - - virtual void handlePingWatchdog(LLWindow *window, const char * msg); - virtual void handlePauseWatchdog(LLWindow *window); - virtual void handleResumeWatchdog(LLWindow *window); - -}; // Refer to llwindow_test in test/common/llwindow for usage example @@ -114,6 +75,8 @@ public: virtual BOOL getMinimized() = 0; virtual BOOL getMaximized() = 0; virtual BOOL maximize() = 0; + virtual void minimize() = 0; + virtual void restore() = 0; BOOL getFullscreen() { return mFullscreen; }; virtual BOOL getPosition(LLCoordScreen *position) = 0; virtual BOOL getSize(LLCoordScreen *size) = 0; @@ -134,12 +97,12 @@ public: // arrow/hour if busycount > 0. virtual void incBusyCount(); virtual void decBusyCount(); - virtual void resetBusyCount() { mBusyCount = 0; } - virtual S32 getBusyCount() const { return mBusyCount; } + virtual void resetBusyCount(); + virtual S32 getBusyCount() const; // Sets cursor, may set to arrow+hourglass virtual void setCursor(ECursorType cursor) = 0; - virtual ECursorType getCursor() const { return mCurrentCursor; } + virtual ECursorType getCursor() const; virtual void captureMouse() = 0; virtual void releaseMouse() = 0; @@ -182,13 +145,12 @@ public: virtual F32 getPixelAspectRatio() = 0; virtual void setNativeAspectRatio(F32 aspect) = 0; - void setCallbacks(LLWindowCallbacks *callbacks); - virtual void beforeDialog() {}; // prepare to put up an OS dialog (if special measures are required, such as in fullscreen mode) virtual void afterDialog() {}; // undo whatever was done in beforeDialog() -// opens system default color picker - virtual BOOL dialog_color_picker (F32 *r, F32 *g, F32 *b) { return FALSE; }; + // opens system default color picker, modally + // Returns TRUE if valid color selected + virtual BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b); // return a platform-specific window reference (HWND on Windows, WindowRef on the Mac, Gtk window on Linux) virtual void *getPlatformWindow() = 0; @@ -201,18 +163,21 @@ public: virtual void setLanguageTextInput( const LLCoordGL & pos ) {}; virtual void updateLanguageTextInputArea() {} virtual void interruptLanguageTextInput() {} - virtual void spawnWebBrowser(const std::string& escaped_url) {}; + virtual void spawnWebBrowser(const std::string& escaped_url, bool async) {}; virtual void ShellEx(const std::string& command) {}; static std::vector<std::string> getDynamicFallbackFontList(); + + // Provide native key event data + virtual LLSD getNativeKeyData() { return LLSD::emptyMap(); } protected: - LLWindow(BOOL fullscreen, U32 flags); - virtual ~LLWindow() {} - virtual BOOL isValid() {return TRUE;} - virtual BOOL canDelete() {return TRUE;} -protected: - static LLWindowCallbacks sDefaultCallbacks; +LLWindow(LLWindowCallbacks* callbacks, BOOL fullscreen, U32 flags); + virtual ~LLWindow(); + // Defaults to true + virtual BOOL isValid(); + // Defaults to true + virtual BOOL canDelete(); protected: LLWindowCallbacks* mCallbacks; @@ -294,18 +259,8 @@ const S32 OSBTN_CANCEL = 3; class LLWindowManager { public: - static LLWindow* createWindow( - const std::string& title, - const std::string& name, - LLCoordScreen upper_left = LLCoordScreen(10, 10), - LLCoordScreen size = LLCoordScreen(320, 240), - U32 flags = 0, - BOOL fullscreen = FALSE, - BOOL clearBg = FALSE, - BOOL disable_vsync = TRUE, - BOOL use_gl = TRUE, - BOOL ignore_pixel_depth = FALSE); static LLWindow *createWindow( + LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags = 0, BOOL fullscreen = FALSE, diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp new file mode 100644 index 000000000..09689d087 --- /dev/null +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -0,0 +1,189 @@ +/** + * @file llwindowcallbacks.cpp + * @brief OS event callback class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llwindowcallbacks.h" + +#include "llcoord.h" + +// +// LLWindowCallbacks +// + +BOOL LLWindowCallbacks::handleTranslatedKeyDown(const KEY key, const MASK mask, BOOL repeated) +{ + return FALSE; +} + + +BOOL LLWindowCallbacks::handleTranslatedKeyUp(const KEY key, const MASK mask) +{ + return FALSE; +} + +void LLWindowCallbacks::handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level) +{ +} + +BOOL LLWindowCallbacks::handleUnicodeChar(llwchar uni_char, MASK mask) +{ + return FALSE; +} + + +BOOL LLWindowCallbacks::handleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask) +{ + return FALSE; +} + +BOOL LLWindowCallbacks::handleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask) +{ + return FALSE; +} + +void LLWindowCallbacks::handleMouseLeave(LLWindow *window) +{ + return; +} + +BOOL LLWindowCallbacks::handleCloseRequest(LLWindow *window) +{ + //allow the window to close + return TRUE; +} + +void LLWindowCallbacks::handleQuit(LLWindow *window) +{ +} + +BOOL LLWindowCallbacks::handleRightMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask) +{ + return FALSE; +} + +BOOL LLWindowCallbacks::handleRightMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask) +{ + return FALSE; +} + +BOOL LLWindowCallbacks::handleMiddleMouseDown(LLWindow *window, const LLCoordGL pos, MASK mask) +{ + return FALSE; +} + +BOOL LLWindowCallbacks::handleMiddleMouseUp(LLWindow *window, const LLCoordGL pos, MASK mask) +{ + return FALSE; +} + +BOOL LLWindowCallbacks::handleActivate(LLWindow *window, BOOL activated) +{ + return FALSE; +} + +BOOL LLWindowCallbacks::handleActivateApp(LLWindow *window, BOOL activating) +{ + return FALSE; +} + +void LLWindowCallbacks::handleMouseMove(LLWindow *window, const LLCoordGL pos, MASK mask) +{ +} + +void LLWindowCallbacks::handleScrollWheel(LLWindow *window, S32 clicks) +{ +} + +void LLWindowCallbacks::handleResize(LLWindow *window, const S32 width, const S32 height) +{ +} + +void LLWindowCallbacks::handleFocus(LLWindow *window) +{ +} + +void LLWindowCallbacks::handleFocusLost(LLWindow *window) +{ +} + +void LLWindowCallbacks::handleMenuSelect(LLWindow *window, const S32 menu_item) +{ +} + +BOOL LLWindowCallbacks::handlePaint(LLWindow *window, const S32 x, const S32 y, + const S32 width, const S32 height) +{ + return FALSE; +} + +BOOL LLWindowCallbacks::handleDoubleClick(LLWindow *window, const LLCoordGL pos, MASK mask) +{ + return FALSE; +} + +void LLWindowCallbacks::handleWindowBlock(LLWindow *window) +{ +} + +void LLWindowCallbacks::handleWindowUnblock(LLWindow *window) +{ +} + +void LLWindowCallbacks::handleDataCopy(LLWindow *window, S32 data_type, void *data) +{ +} + +LLWindowCallbacks::DragNDropResult LLWindowCallbacks::handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data ) +{ + return LLWindowCallbacks::DND_NONE; +} + +BOOL LLWindowCallbacks::handleTimerEvent(LLWindow *window) +{ + return FALSE; +} + +BOOL LLWindowCallbacks::handleDeviceChange(LLWindow *window) +{ + return FALSE; +} + +void LLWindowCallbacks::handlePingWatchdog(LLWindow *window, const char * msg) +{ + +} + +void LLWindowCallbacks::handlePauseWatchdog(LLWindow *window) +{ + +} + +void LLWindowCallbacks::handleResumeWatchdog(LLWindow *window) +{ + +} + diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h new file mode 100644 index 000000000..5ba442ed4 --- /dev/null +++ b/indra/llwindow/llwindowcallbacks.h @@ -0,0 +1,91 @@ +/** + * @file llwindowcallbacks.h + * @brief OS event callback class + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ +#ifndef LLWINDOWCALLBACKS_H +#define LLWINDOWCALLBACKS_H + +class LLCoordGL; +class LLWindow; + +class LLWindowCallbacks +{ +public: + virtual ~LLWindowCallbacks() {} + virtual BOOL handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated); + virtual BOOL handleTranslatedKeyUp(KEY key, MASK mask); + virtual void handleScanKey(KEY key, BOOL key_down, BOOL key_up, BOOL key_level); + virtual BOOL handleUnicodeChar(llwchar uni_char, MASK mask); + + virtual BOOL handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); + virtual BOOL handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); + virtual void handleMouseLeave(LLWindow *window); + // return TRUE to allow window to close, which will then cause handleQuit to be called + virtual BOOL handleCloseRequest(LLWindow *window); + // window is about to be destroyed, clean up your business + virtual void handleQuit(LLWindow *window); + virtual BOOL handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); + virtual BOOL handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); + virtual BOOL handleMiddleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask); + virtual BOOL handleMiddleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask); + virtual BOOL handleActivate(LLWindow *window, BOOL activated); + virtual BOOL handleActivateApp(LLWindow *window, BOOL activating); + virtual void handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask); + virtual void handleScrollWheel(LLWindow *window, S32 clicks); + virtual void handleResize(LLWindow *window, S32 width, S32 height); + virtual void handleFocus(LLWindow *window); + virtual void handleFocusLost(LLWindow *window); + virtual void handleMenuSelect(LLWindow *window, S32 menu_item); + virtual BOOL handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S32 height); + virtual BOOL handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK mask); // double-click of left mouse button + virtual void handleWindowBlock(LLWindow *window); // window is taking over CPU for a while + virtual void handleWindowUnblock(LLWindow *window); // window coming back after taking over CPU for a while + virtual void handleDataCopy(LLWindow *window, S32 data_type, void *data); + virtual BOOL handleTimerEvent(LLWindow *window); + virtual BOOL handleDeviceChange(LLWindow *window); + + enum DragNDropAction { + DNDA_START_TRACKING = 0,// Start tracking an incoming drag + DNDA_TRACK, // User is dragging an incoming drag around the window + DNDA_STOP_TRACKING, // User is no longer dragging an incoming drag around the window (may have either cancelled or dropped on the window) + DNDA_DROPPED // User dropped an incoming drag on the window (this is the "commit" event) + }; + + enum DragNDropResult { + DND_NONE = 0, // No drop allowed + DND_MOVE, // Drop accepted would result in a "move" operation + DND_COPY, // Drop accepted would result in a "copy" operation + DND_LINK // Drop accepted would result in a "link" operation + }; + virtual DragNDropResult handleDragNDrop(LLWindow *window, LLCoordGL pos, MASK mask, DragNDropAction action, std::string data); + + virtual void handlePingWatchdog(LLWindow *window, const char * msg); + virtual void handlePauseWatchdog(LLWindow *window); + virtual void handleResumeWatchdog(LLWindow *window); + +}; + + + +#endif diff --git a/indra/llwindow/llwindowheadless.cpp b/indra/llwindow/llwindowheadless.cpp index 374284644..6486b0a36 100644 --- a/indra/llwindow/llwindowheadless.cpp +++ b/indra/llwindow/llwindowheadless.cpp @@ -34,15 +34,19 @@ #include "indra_constants.h" #include "llwindowheadless.h" +#include "llkeyboardheadless.h" // // LLWindowHeadless // -LLWindowHeadless::LLWindowHeadless(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, - U32 flags, BOOL fullscreen, BOOL clearBg, +LLWindowHeadless::LLWindowHeadless(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, + U32 flags, BOOL fullscreen, BOOL clear_background, BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth) - : LLWindow(fullscreen, flags) + : LLWindow(callbacks, fullscreen, flags) { + // Initialize a headless keyboard. + gKeyboard = new LLKeyboardHeadless(); + gKeyboard->setCallbacks(callbacks); } diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h index 4353d157b..59fc2ec65 100644 --- a/indra/llwindow/llwindowheadless.h +++ b/indra/llwindow/llwindowheadless.h @@ -45,6 +45,8 @@ public: /*virtual*/ BOOL getMinimized() {return FALSE;}; /*virtual*/ BOOL getMaximized() {return FALSE;}; /*virtual*/ BOOL maximize() {return FALSE;}; + /*virtual*/ void minimize() {}; + /*virtual*/ void restore() {}; /*virtual*/ BOOL getFullscreen() {return FALSE;}; /*virtual*/ BOOL getPosition(LLCoordScreen *position) {return FALSE;}; /*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;}; @@ -94,9 +96,12 @@ public: /*virtual*/ void *getPlatformWindow() { return 0; }; /*virtual*/ void bringToFront() {}; - LLWindowHeadless(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, - U32 flags, BOOL fullscreen, BOOL clearBg, - BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth); + LLWindowHeadless(LLWindowCallbacks* callbacks, + const std::string& title, const std::string& name, + S32 x, S32 y, + S32 width, S32 height, + U32 flags, BOOL fullscreen, BOOL clear_background, + BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth); virtual ~LLWindowHeadless(); private: diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp index 21921057f..5020b65b7 100644 --- a/indra/llwindow/llwindowmacosx.cpp +++ b/indra/llwindow/llwindowmacosx.cpp @@ -32,19 +32,21 @@ #include "linden_common.h" -#include <Carbon/Carbon.h> -#include <OpenGL/OpenGL.h> - #include "llwindowmacosx.h" + #include "llkeyboardmacosx.h" +#include "llwindowcallbacks.h" +#include "llwindowmacosx-objc.h" +#include "llpreeditor.h" + #include "llerror.h" #include "llgl.h" #include "llstring.h" #include "lldir.h" #include "indra_constants.h" -#include "llwindowmacosx-objc.h" -#include "llpreeditor.h" +#include <Carbon/Carbon.h> +#include <OpenGL/OpenGL.h> extern BOOL gDebugWindowProc; @@ -112,9 +114,6 @@ static long getDictLong (CFDictionaryRef refDict, CFStringRef key); static EventTypeSpec WindowHandlerEventList[] = { // Window-related events - // { kEventClassWindow, kEventWindowCollapsing }, - // { kEventClassWindow, kEventWindowCollapsed }, - // { kEventClassWindow, kEventWindowShown }, { kEventClassWindow, kEventWindowActivated }, { kEventClassWindow, kEventWindowDeactivated }, { kEventClassWindow, kEventWindowShown }, @@ -125,8 +124,7 @@ static EventTypeSpec WindowHandlerEventList[] = { kEventClassWindow, kEventWindowClose }, { kEventClassWindow, kEventWindowBoundsChanging }, { kEventClassWindow, kEventWindowBoundsChanged }, - // { kEventClassWindow, kEventWindowZoomed }, - // { kEventClassWindow, kEventWindowDrawContent }, + { kEventClassWindow, kEventWindowGetIdealSize }, // Mouse events { kEventClassMouse, kEventMouseDown }, @@ -214,19 +212,27 @@ static LLWindowMacOSX *gWindowImplementation = NULL; -LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, +LLWindowMacOSX::LLWindowMacOSX(LLWindowCallbacks* callbacks, + const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples) - : LLWindow(fullscreen, flags) + : LLWindow(NULL, fullscreen, flags) { + // *HACK: During window construction we get lots of OS events for window + // reshape, activate, etc. that the viewer isn't ready to handle. + // Route them to a dummy callback structure until the end of constructor. + LLWindowCallbacks null_callbacks; + mCallbacks = &null_callbacks; + // Voodoo for calling cocoa from carbon (see llwindowmacosx-objc.mm). setupCocoa(); // Initialize the keyboard gKeyboard = new LLKeyboardMacOSX(); + gKeyboard->setCallbacks(callbacks); // Ignore use_gl for now, only used for drones on PC mWindow = NULL; @@ -244,12 +250,14 @@ LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name mCursorIgnoreNextDelta = FALSE; mNeedsResize = FALSE; mOverrideAspectRatio = 0.f; + mMaximized = FALSE; mMinimized = FALSE; mTSMDocument = NULL; // Just in case. mLanguageTextInputAllowed = FALSE; mTSMScriptCode = 0; mTSMLangCode = 0; mPreeditor = NULL; + mRawKeyEvent = NULL; mFSAASamples = fsaa_samples; mForceRebuild = FALSE; @@ -268,6 +276,8 @@ LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name mMoveEventCampartorUPP = NewEventComparatorUPP(staticMoveEventComparator); mGlobalHandlerRef = NULL; mWindowHandlerRef = NULL; + + mDragOverrideCursor = -1; // We're not clipping yet SetRect( &mOldMouseClip, 0, 0, 0, 0 ); @@ -315,6 +325,7 @@ LLWindowMacOSX::LLWindowMacOSX(const std::string& title, const std::string& name setCursor( UI_CURSOR_ARROW ); } + mCallbacks = callbacks; stop_glerror(); } @@ -447,24 +458,23 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits if(!mFullscreen && (mWindow == NULL)) { - Rect window_rect; //int displayWidth = CGDisplayPixelsWide(mDisplay); //int displayHeight = CGDisplayPixelsHigh(mDisplay); //const int menuBarPlusTitleBar = 44; // Ugly magic number. LL_DEBUGS("Window") << "createContext: creating window" << LL_ENDL; - window_rect.left = (long) x; - window_rect.right = (long) x + width; - window_rect.top = (long) y; - window_rect.bottom = (long) y + height; + mPreviousWindowRect.left = (long) x; + mPreviousWindowRect.right = (long) x + width; + mPreviousWindowRect.top = (long) y; + mPreviousWindowRect.bottom = (long) y + height; //----------------------------------------------------------------------- // Create the window //----------------------------------------------------------------------- mWindow = NewCWindow( NULL, - &window_rect, + &mPreviousWindowRect, mWindowTitle, false, // Create the window invisible. Whoever calls createContext() should show it after any moving/resizing. // noGrowDocProc, // Window with no grow box and no zoom box @@ -488,8 +498,11 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits // Set up window event handlers (some window-related events ONLY go to window handlers.) InstallStandardEventHandler(GetWindowEventTarget(mWindow)); - InstallWindowEventHandler (mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler - + InstallWindowEventHandler(mWindow, mEventHandlerUPP, GetEventTypeCount (WindowHandlerEventList), WindowHandlerEventList, (void*)this, &mWindowHandlerRef); // add event handler +#if LL_OS_DRAGDROP_ENABLED + InstallTrackingHandler( dragTrackingHandler, mWindow, (void*)this ); + InstallReceiveHandler( dragReceiveHandler, mWindow, (void*)this ); +#endif // LL_OS_DRAGDROP_ENABLED } { @@ -511,7 +524,6 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits if (mTSMDocument) { ActivateTSMDocument(mTSMDocument); - UseInputWindow(mTSMDocument, FALSE); allowLanguageTextInput(NULL, FALSE); } } @@ -531,20 +543,20 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits GLint fullscreenAttrib[] = { AGL_RGBA, - AGL_FULLSCREEN, - // AGL_NO_RECOVERY, // MBW -- XXX -- Not sure if we want this attribute - AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, - AGL_SAMPLES_ARB, mFSAASamples, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, - AGL_ACCELERATED, - AGL_RED_SIZE, 8, - AGL_GREEN_SIZE, 8, - AGL_BLUE_SIZE, 8, - AGL_ALPHA_SIZE, 8, - AGL_DEPTH_SIZE, 24, - AGL_STENCIL_SIZE, 8, - AGL_NONE + AGL_FULLSCREEN, + AGL_NO_RECOVERY, + AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, + AGL_SAMPLES_ARB, mFSAASamples, + AGL_DOUBLEBUFFER, + AGL_CLOSEST_POLICY, + AGL_ACCELERATED, + AGL_RED_SIZE, 8, + AGL_GREEN_SIZE, 8, + AGL_BLUE_SIZE, 8, + AGL_ALPHA_SIZE, 8, + AGL_DEPTH_SIZE, 24, + AGL_STENCIL_SIZE, 8, + AGL_NONE }; LL_DEBUGS("Window") << "createContext: creating fullscreen pixelformat" << LL_ENDL; @@ -557,11 +569,18 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits } else { + // NOTE from Leslie: + // + // AGL_NO_RECOVERY, when combined with AGL_ACCELERATED prevents software rendering + // fallback which means we won't hvae shaders that compile and link but then don't + // work. The drawback is that our shader compilation will be a bit more finicky though. + GLint windowedAttrib[] = { AGL_RGBA, - AGL_DOUBLEBUFFER, - AGL_CLOSEST_POLICY, + AGL_NO_RECOVERY, + AGL_DOUBLEBUFFER, + AGL_CLOSEST_POLICY, AGL_ACCELERATED, AGL_SAMPLE_BUFFERS_ARB, mFSAASamples > 0 ? 1 : 0, AGL_SAMPLES_ARB, mFSAASamples, @@ -1081,31 +1100,22 @@ BOOL LLWindowMacOSX::getVisible() BOOL LLWindowMacOSX::getMinimized() { - BOOL result = FALSE; - - // Since the set of states where we want to act "minimized" is non-trivial, it's easier to - // track things locally than to try and retrieve the state from the window manager. - result = mMinimized; - - return(result); + return mMinimized; } BOOL LLWindowMacOSX::getMaximized() { - BOOL result = FALSE; - - if (mWindow) - { - // TODO - } - - return(result); + return mMaximized; } BOOL LLWindowMacOSX::maximize() { - // TODO - return FALSE; + if (mWindow && !mMaximized) + { + ZoomWindow(mWindow, inContent, true); + } + + return mMaximized; } BOOL LLWindowMacOSX::getFullscreen() @@ -1261,6 +1271,7 @@ BOOL LLWindowMacOSX::setSize(const LLCoordScreen size) void LLWindowMacOSX::swapBuffers() { + glFinish(); aglSwapBuffers(mContext); } @@ -2005,7 +2016,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e // Although the spec. is unclear, replace range should // not present when there is an active preedit. We just // ignore the case. markAsPreedit will detect the case and warn it. - const LLWString & text = mPreeditor->getWText(); + const LLWString & text = mPreeditor->getPreeditString(); const S32 location = wstring_wstring_length_from_utf16_length(text, 0, range.location); const S32 length = wstring_wstring_length_from_utf16_length(text, location, range.length); mPreeditor->markAsPreedit(location, length); @@ -2125,8 +2136,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e // First, process the raw event. { - EventRef rawEvent; - + EventRef rawEvent = NULL; + // Get the original event and extract the modifier keys, so we can ignore command-key events. if (GetEventParameter(event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent) == noErr) { @@ -2135,6 +2146,9 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e // and call this function recursively to handle the raw key event. eventHandler (myHandler, rawEvent); + + // save the raw event until we're done processing the unicode input as well. + mRawKeyEvent = rawEvent; } } @@ -2162,11 +2176,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e } else { - MASK mask = 0; - if(modifiers & shiftKey) { mask |= MASK_SHIFT; } - if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; } - if(modifiers & optionKey) { mask |= MASK_ALT; } - + MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); + llassert( actualType == typeUnicodeText ); // The result is a UTF16 buffer. Pass the characters in turn to handleUnicodeChar. @@ -2188,6 +2199,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e delete[] buffer; } + mRawKeyEvent = NULL; result = err; } break; @@ -2203,7 +2215,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e { S32 preedit, preedit_length; mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getWText(); + const LLWString & text = mPreeditor->getPreeditString(); LLCoordGL caret_coord; LLRect preedit_bounds; @@ -2240,7 +2252,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e mPreeditor->getSelectionRange(&selection, &selection_length); if (selection_length) { - const LLWString text = mPreeditor->getWText().substr(selection, selection_length); + const LLWString text = mPreeditor->getPreeditString().substr(selection, selection_length); const llutf16string text_utf16 = wstring_to_utf16str(text); result = SetEventParameter(event, kEventParamTextInputReplyText, typeUnicodeText, text_utf16.length() * sizeof(U16), text_utf16.c_str()); @@ -2262,6 +2274,9 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e GetEventParameter (event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode); GetEventParameter (event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); + // save the raw event so getNativeKeyData can use it. + mRawKeyEvent = event; + // printf("key event, key code = 0x%08x, char code = 0x%02x (%c), modifiers = 0x%08x\n", keyCode, charCode, (char)charCode, modifiers); // fflush(stdout); @@ -2357,6 +2372,8 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e result = eventNotHandledErr; break; } + + mRawKeyEvent = NULL; } break; @@ -2527,31 +2544,92 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e } mCallbacks->handleFocusLost(this); break; + case kEventWindowBoundsChanging: { + // This is where we would constrain move/resize to a particular screen + + const S32 MIN_WIDTH = 320; + const S32 MIN_HEIGHT = 240; + Rect currentBounds; Rect previousBounds; GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, ¤tBounds); GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &previousBounds); - - // This is where we would constrain move/resize to a particular screen - if(0) + + // Put an offset into window un-maximize operation since the kEventWindowGetIdealSize + // event only allows the specification of size and not position. + if (mMaximized) { - SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds); + short leftOffset = mPreviousWindowRect.left - currentBounds.left; + currentBounds.left += leftOffset; + currentBounds.right += leftOffset; + + short topOffset = mPreviousWindowRect.top - currentBounds.top; + currentBounds.top += topOffset; + currentBounds.bottom += topOffset; } + else + { + // Store off the size for future un-maximize operations + mPreviousWindowRect = previousBounds; + } + + if ((currentBounds.right - currentBounds.left) < MIN_WIDTH) + { + currentBounds.right = currentBounds.left + MIN_WIDTH; + } + + if ((currentBounds.bottom - currentBounds.top) < MIN_HEIGHT) + { + currentBounds.bottom = currentBounds.top + MIN_HEIGHT; + } + + SetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, sizeof(Rect), ¤tBounds); + result = noErr; } break; case kEventWindowBoundsChanged: { + // Get new window bounds Rect newBounds; - GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &newBounds); + + // Get previous window bounds + Rect oldBounds; + GetEventParameter(event, kEventParamPreviousBounds, typeQDRectangle, NULL, sizeof(Rect), NULL, &oldBounds); + + // Determine if the new size is larger than the old + bool newBoundsLarger = ((newBounds.right - newBounds.left) >= (oldBounds.right - oldBounds.left)); + newBoundsLarger &= ((newBounds.bottom - newBounds.top) >= (oldBounds.bottom - oldBounds.top)); + + // Check to see if this is a zoom event (+ button on window pane) + unsigned int eventParams; + GetEventParameter(event, kEventParamAttributes, typeUInt32, NULL, sizeof(int), NULL, &eventParams); + bool isZoomEvent = ((eventParams & kWindowBoundsChangeZoom) != 0); + + // Maximized flag is if zoom event and increasing window size + mMaximized = (isZoomEvent && newBoundsLarger); + aglUpdateContext(mContext); + mCallbacks->handleResize(this, newBounds.right - newBounds.left, newBounds.bottom - newBounds.top); - - + } + break; + + case kEventWindowGetIdealSize: + // Only recommend a new ideal size when un-maximizing + if (mMaximized == TRUE) + { + Point nonMaximizedSize; + + nonMaximizedSize.v = mPreviousWindowRect.bottom - mPreviousWindowRect.top; + nonMaximizedSize.h = mPreviousWindowRect.right - mPreviousWindowRect.left; + + SetEventParameter(event, kEventParamDimensions, typeQDPoint, sizeof(Point), &nonMaximizedSize); + result = noErr; } break; @@ -2597,7 +2675,6 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e // BringToFront(mWindow); // result = noErr; break; - } break; @@ -2613,7 +2690,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e S32 preedit, preedit_length; mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getWText(); + const LLWString & text = mPreeditor->getPreeditString(); const CFIndex length = wstring_utf16_length(text, 0, preedit) + wstring_utf16_length(text, preedit + preedit_length, text.length()); result = SetEventParameter(event, kEventParamTSMDocAccessCharacterCount, typeCFIndex, sizeof(length), &length); @@ -2630,7 +2707,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e S32 preedit, preedit_length; mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getWText(); + const LLWString & text = mPreeditor->getPreeditString(); CFRange range; if (preedit_length) @@ -2664,7 +2741,7 @@ OSStatus LLWindowMacOSX::eventHandler (EventHandlerCallRef myHandler, EventRef e { S32 preedit, preedit_length; mPreeditor->getPreeditRange(&preedit, &preedit_length); - const LLWString & text = mPreeditor->getWText(); + const LLWString & text = mPreeditor->getPreeditString(); // The GetCharacters event of TSMDA has a fundamental flaw; // An input method need to decide the starting offset and length @@ -2739,14 +2816,14 @@ const char* cursorIDToName(int id) case UI_CURSOR_TOOLPAN: return "UI_CURSOR_TOOLPAN"; case UI_CURSOR_TOOLZOOMIN: return "UI_CURSOR_TOOLZOOMIN"; case UI_CURSOR_TOOLPICKOBJECT3: return "UI_CURSOR_TOOLPICKOBJECT3"; - case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT"; - case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY"; - case UI_CURSOR_TOOLPAY: return "UI_CURSOR_TOOLPAY"; - case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN"; case UI_CURSOR_TOOLPLAY: return "UI_CURSOR_TOOLPLAY"; case UI_CURSOR_TOOLPAUSE: return "UI_CURSOR_TOOLPAUSE"; case UI_CURSOR_TOOLMEDIAOPEN: return "UI_CURSOR_TOOLMEDIAOPEN"; case UI_CURSOR_PIPETTE: return "UI_CURSOR_PIPETTE"; + case UI_CURSOR_TOOLSIT: return "UI_CURSOR_TOOLSIT"; + case UI_CURSOR_TOOLBUY: return "UI_CURSOR_TOOLBUY"; + case UI_CURSOR_TOOLOPEN: return "UI_CURSOR_TOOLOPEN"; + case UI_CURSOR_TOOLPAY: return "UI_CURSOR_TOOLPAY"; } llerrs << "cursorIDToName: unknown cursor id" << id << llendl; @@ -2774,6 +2851,14 @@ void LLWindowMacOSX::setCursor(ECursorType cursor) { OSStatus result = noErr; + if (mDragOverrideCursor != -1) + { + // A drag is in progress...remember the requested cursor and we'll + // restore it when it is done + mCurrentCursor = cursor; + return; + } + if (cursor == UI_CURSOR_ARROW && mBusyCount > 0) { @@ -2838,13 +2923,13 @@ void LLWindowMacOSX::setCursor(ECursorType cursor) case UI_CURSOR_TOOLPAN: case UI_CURSOR_TOOLZOOMIN: case UI_CURSOR_TOOLPICKOBJECT3: - case UI_CURSOR_TOOLSIT: - case UI_CURSOR_TOOLBUY: - case UI_CURSOR_TOOLPAY: - case UI_CURSOR_TOOLOPEN: case UI_CURSOR_TOOLPLAY: case UI_CURSOR_TOOLPAUSE: case UI_CURSOR_TOOLMEDIAOPEN: + case UI_CURSOR_TOOLSIT: + case UI_CURSOR_TOOLBUY: + case UI_CURSOR_TOOLOPEN: + case UI_CURSOR_TOOLPAY: result = setImageCursor(gCursors[cursor]); break; @@ -2883,13 +2968,13 @@ void LLWindowMacOSX::initCursors() initPixmapCursor(UI_CURSOR_TOOLPAN, 7, 6); initPixmapCursor(UI_CURSOR_TOOLZOOMIN, 7, 6); initPixmapCursor(UI_CURSOR_TOOLPICKOBJECT3, 1, 1); - initPixmapCursor(UI_CURSOR_TOOLSIT, 1, 1); - initPixmapCursor(UI_CURSOR_TOOLBUY, 1, 1); - initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1); - initPixmapCursor(UI_CURSOR_TOOLOPEN, 1, 1); initPixmapCursor(UI_CURSOR_TOOLPLAY, 1, 1); initPixmapCursor(UI_CURSOR_TOOLPAUSE, 1, 1); initPixmapCursor(UI_CURSOR_TOOLMEDIAOPEN, 1, 1); + initPixmapCursor(UI_CURSOR_TOOLSIT, 1, 1); + initPixmapCursor(UI_CURSOR_TOOLBUY, 1, 1); + initPixmapCursor(UI_CURSOR_TOOLOPEN, 1, 1); + initPixmapCursor(UI_CURSOR_TOOLPAY, 1, 1); initPixmapCursor(UI_CURSOR_SIZENWSE, 10, 10); initPixmapCursor(UI_CURSOR_SIZENESW, 10, 10); @@ -3135,7 +3220,7 @@ S32 OSMessageBoxMacOSX(const std::string& text, const std::string& caption, U32 // Open a URL with the user's default web browser. // Must begin with protocol identifier. -void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url) +void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url, bool async) { bool found = false; S32 i; @@ -3188,8 +3273,62 @@ void LLWindowMacOSX::spawnWebBrowser(const std::string& escaped_url) } } +LLSD LLWindowMacOSX::getNativeKeyData() +{ + LLSD result = LLSD::emptyMap(); + + if(mRawKeyEvent) + { + char char_code = 0; + UInt32 key_code = 0; + UInt32 modifiers = 0; + UInt32 keyboard_type = 0; + + GetEventParameter (mRawKeyEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &char_code); + GetEventParameter (mRawKeyEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &key_code); + GetEventParameter (mRawKeyEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers); + GetEventParameter (mRawKeyEvent, kEventParamKeyboardType, typeUInt32, NULL, sizeof(UInt32), NULL, &keyboard_type); -BOOL LLWindowMacOSX::dialog_color_picker ( F32 *r, F32 *g, F32 *b) + result["char_code"] = (S32)char_code; + result["key_code"] = (S32)key_code; + result["modifiers"] = (S32)modifiers; + result["keyboard_type"] = (S32)keyboard_type; + +#if 0 + // This causes trouble for control characters -- apparently character codes less than 32 (escape, control-A, etc) + // cause llsd serialization to create XML that the llsd deserializer won't parse! + std::string unicode; + OSStatus err = noErr; + EventParamType actualType = typeUTF8Text; + UInt32 actualSize = 0; + char *buffer = NULL; + + err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, 0, &actualSize, NULL); + if(err == noErr) + { + // allocate a buffer and get the actual data. + buffer = new char[actualSize]; + err = GetEventParameter (mRawKeyEvent, kEventParamKeyUnicodes, typeUTF8Text, &actualType, actualSize, &actualSize, buffer); + if(err == noErr) + { + unicode.assign(buffer, actualSize); + } + delete[] buffer; + } + + result["unicode"] = unicode; +#endif + + } + + + lldebugs << "native key data is: " << result << llendl; + + return result; +} + + +BOOL LLWindowMacOSX::dialogColorPicker( F32 *r, F32 *g, F32 *b) { BOOL retval = FALSE; OSErr error = noErr; @@ -3305,6 +3444,8 @@ void LLWindowMacOSX::allowLanguageTextInput(LLPreeditor *preeditor, BOOL b) return; } + UseInputWindow(mTSMDocument, !b); + // Take care of old and new preeditors. if (preeditor != mPreeditor || !b) { @@ -3364,3 +3505,174 @@ std::vector<std::string> LLWindowMacOSX::getDynamicFallbackFontList() return std::vector<std::string>(); } +// static +MASK LLWindowMacOSX::modifiersToMask(SInt16 modifiers) +{ + MASK mask = 0; + if(modifiers & shiftKey) { mask |= MASK_SHIFT; } + if(modifiers & (cmdKey | controlKey)) { mask |= MASK_CONTROL; } + if(modifiers & optionKey) { mask |= MASK_ALT; } + return mask; +} + +#if LL_OS_DRAGDROP_ENABLED + +OSErr LLWindowMacOSX::dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, + void * handlerRefCon, DragRef drag) +{ + OSErr result = noErr; + LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon; + + lldebugs << "drag tracking handler, message = " << message << llendl; + + switch(message) + { + case kDragTrackingInWindow: + result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_TRACK); + break; + + case kDragTrackingEnterHandler: + result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_START_TRACKING); + break; + + case kDragTrackingLeaveHandler: + result = self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_STOP_TRACKING); + break; + + default: + break; + } + + return result; +} + +OSErr LLWindowMacOSX::dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, + DragRef drag) +{ + LLWindowMacOSX *self = (LLWindowMacOSX*)handlerRefCon; + return self->handleDragNDrop(drag, LLWindowCallbacks::DNDA_DROPPED); + +} + +OSErr LLWindowMacOSX::handleDragNDrop(DragRef drag, LLWindowCallbacks::DragNDropAction action) +{ + OSErr result = dragNotAcceptedErr; // overall function result + OSErr err = noErr; // for local error handling + + // Get the mouse position and modifiers of this drag. + SInt16 modifiers, mouseDownModifiers, mouseUpModifiers; + ::GetDragModifiers(drag, &modifiers, &mouseDownModifiers, &mouseUpModifiers); + MASK mask = LLWindowMacOSX::modifiersToMask(modifiers); + + Point mouse_point; + // This will return the mouse point in global screen coords + ::GetDragMouse(drag, &mouse_point, NULL); + LLCoordScreen screen_coords(mouse_point.h, mouse_point.v); + LLCoordGL gl_pos; + convertCoords(screen_coords, &gl_pos); + + // Look at the pasteboard and try to extract an URL from it + PasteboardRef pasteboard; + if(GetDragPasteboard(drag, &pasteboard) == noErr) + { + ItemCount num_items = 0; + // Treat an error here as an item count of 0 + (void)PasteboardGetItemCount(pasteboard, &num_items); + + // Only deal with single-item drags. + if(num_items == 1) + { + PasteboardItemID item_id = NULL; + CFArrayRef flavors = NULL; + CFDataRef data = NULL; + + err = PasteboardGetItemIdentifier(pasteboard, 1, &item_id); // Yes, this really is 1-based. + + // Try to extract an URL from the pasteboard + if(err == noErr) + { + err = PasteboardCopyItemFlavors( pasteboard, item_id, &flavors); + } + + if(err == noErr) + { + if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeURL)) + { + // This is an URL. + err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeURL, &data); + } + else if(CFArrayContainsValue(flavors, CFRangeMake(0, CFArrayGetCount(flavors)), kUTTypeUTF8PlainText)) + { + // This is a string that might be an URL. + err = PasteboardCopyItemFlavorData(pasteboard, item_id, kUTTypeUTF8PlainText, &data); + } + + } + + if(flavors != NULL) + { + CFRelease(flavors); + } + + if(data != NULL) + { + std::string url; + url.assign((char*)CFDataGetBytePtr(data), CFDataGetLength(data)); + CFRelease(data); + + if(!url.empty()) + { + LLWindowCallbacks::DragNDropResult res = + mCallbacks->handleDragNDrop(this, gl_pos, mask, action, url); + + switch (res) { + case LLWindowCallbacks::DND_NONE: // No drop allowed + if (action == LLWindowCallbacks::DNDA_TRACK) + { + mDragOverrideCursor = kThemeNotAllowedCursor; + } + else { + mDragOverrideCursor = -1; + } + break; + case LLWindowCallbacks::DND_MOVE: // Drop accepted would result in a "move" operation + mDragOverrideCursor = kThemePointingHandCursor; + result = noErr; + break; + case LLWindowCallbacks::DND_COPY: // Drop accepted would result in a "copy" operation + mDragOverrideCursor = kThemeCopyArrowCursor; + result = noErr; + break; + case LLWindowCallbacks::DND_LINK: // Drop accepted would result in a "link" operation: + mDragOverrideCursor = kThemeAliasArrowCursor; + result = noErr; + break; + default: + mDragOverrideCursor = -1; + break; + } + // This overrides the cursor being set by setCursor. + // This is a bit of a hack workaround because lots of areas + // within the viewer just blindly set the cursor. + if (mDragOverrideCursor == -1) + { + // Restore the cursor + ECursorType temp_cursor = mCurrentCursor; + // get around the "setting the same cursor" code in setCursor() + mCurrentCursor = UI_CURSOR_COUNT; + setCursor(temp_cursor); + } + else { + // Override the cursor + SetThemeCursor(mDragOverrideCursor); + } + + } + } + } + } + + return result; +} + +#endif // LL_OS_DRAGDROP_ENABLED diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h index 10ddc9ebc..504b446d1 100644 --- a/indra/llwindow/llwindowmacosx.h +++ b/indra/llwindow/llwindowmacosx.h @@ -34,6 +34,8 @@ #define LL_LLWINDOWMACOSX_H #include "llwindow.h" +#include "llwindowcallbacks.h" + #include "lltimer.h" #include <Carbon/Carbon.h> @@ -55,6 +57,8 @@ public: /*virtual*/ BOOL getMinimized(); /*virtual*/ BOOL getMaximized(); /*virtual*/ BOOL maximize(); + /*virtual*/ void minimize(); + /*virtual*/ void restore(); /*virtual*/ BOOL getFullscreen(); /*virtual*/ BOOL getPosition(LLCoordScreen *position); /*virtual*/ BOOL getSize(LLCoordScreen *size); @@ -104,7 +108,7 @@ public: /*virtual*/ void beforeDialog(); /*virtual*/ void afterDialog(); - /*virtual*/ BOOL dialog_color_picker(F32 *r, F32 *g, F32 *b); + /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b); /*virtual*/ void *getPlatformWindow(); /*virtual*/ void *getMediaWindow(); @@ -112,12 +116,16 @@ public: /*virtual*/ void allowLanguageTextInput(LLPreeditor *preeditor, BOOL b); /*virtual*/ void interruptLanguageTextInput(); - /*virtual*/ void spawnWebBrowser(const std::string& escaped_url); + /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); static std::vector<std::string> getDynamicFallbackFontList(); + // Provide native key event data + /*virtual*/ LLSD getNativeKeyData(); + + protected: - LLWindowMacOSX( + LLWindowMacOSX(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, @@ -138,9 +146,6 @@ protected: // Restore the display resolution to its value before we ran the app. BOOL resetDisplayResolution(); - void minimize(); - void restore(); - BOOL shouldPostQuit() { return mPostQuit; } @@ -157,10 +162,16 @@ protected: static pascal Boolean staticMoveEventComparator( EventRef event, void* data); OSStatus eventHandler (EventHandlerCallRef myHandler, EventRef event); void adjustCursorDecouple(bool warpingMouse = false); - void fixWindowSize(void); void stopDockTileBounce(); - - + static MASK modifiersToMask(SInt16 modifiers); + +#if LL_OS_DRAGDROP_ENABLED + static OSErr dragTrackingHandler(DragTrackingMessage message, WindowRef theWindow, + void * handlerRefCon, DragRef theDrag); + static OSErr dragReceiveHandler(WindowRef theWindow, void * handlerRefCon, DragRef theDrag); + OSErr handleDragNDrop(DragRef theDrag, LLWindowCallbacks::DragNDropAction action); +#endif // LL_OS_DRAGDROP_ENABLED + // // Platform specific variables // @@ -176,6 +187,7 @@ protected: EventComparatorUPP mMoveEventCampartorUPP; Rect mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse() + Rect mPreviousWindowRect; // Save previous window for un-maximize event Str255 mWindowTitle; double mOriginalAspectRatio; BOOL mSimulatedRightClick; @@ -189,15 +201,18 @@ protected: BOOL mNeedsResize; // Constructor figured out the window is too big, it needs a resize. LLCoordScreen mNeedsResizeSize; F32 mOverrideAspectRatio; + BOOL mMaximized; BOOL mMinimized; U32 mFSAASamples; BOOL mForceRebuild; + S32 mDragOverrideCursor; + F32 mBounceTime; NMRec mBounceRec; LLTimer mBounceTimer; - // Imput method management through Text Service Manager. + // Input method management through Text Service Manager. TSMDocumentID mTSMDocument; BOOL mLanguageTextInputAllowed; ScriptCode mTSMScriptCode; @@ -208,6 +223,7 @@ protected: friend class LLWindowManager; static WindowRef sMediaWindow; + EventRef mRawKeyEvent; }; diff --git a/indra/llwindow/llwindowmesaheadless.cpp b/indra/llwindow/llwindowmesaheadless.cpp index c1f9d2095..48736d920 100644 --- a/indra/llwindow/llwindowmesaheadless.cpp +++ b/indra/llwindow/llwindowmesaheadless.cpp @@ -44,10 +44,11 @@ U16 *gMesaBuffer = NULL; // // LLWindowMesaHeadless // -LLWindowMesaHeadless::LLWindowMesaHeadless(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, +LLWindowMesaHeadless::LLWindowMesaHeadless(LLWindowCallbacks* callbacks, + const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth) - : LLWindow(fullscreen, flags) + : LLWindow(callbacks, fullscreen, flags) { if (use_gl) { diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h index ab562d9ff..06146afde 100644 --- a/indra/llwindow/llwindowmesaheadless.h +++ b/indra/llwindow/llwindowmesaheadless.h @@ -49,6 +49,8 @@ public: /*virtual*/ BOOL getMinimized() {return FALSE;}; /*virtual*/ BOOL getMaximized() {return FALSE;}; /*virtual*/ BOOL maximize() {return FALSE;}; + /*virtual*/ void minimize() {}; + /*virtual*/ void restore() {}; /*virtual*/ BOOL getFullscreen() {return FALSE;}; /*virtual*/ BOOL getPosition(LLCoordScreen *position) {return FALSE;}; /*virtual*/ BOOL getSize(LLCoordScreen *size) {return FALSE;}; @@ -98,7 +100,8 @@ public: /*virtual*/ void *getPlatformWindow() { return 0; }; /*virtual*/ void bringToFront() {}; - LLWindowMesaHeadless(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, + LLWindowMesaHeadless(LLWindowCallbacks* callbacks, + const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth); ~LLWindowMesaHeadless(); diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp index 94177e6d5..2023beaf0 100644 --- a/indra/llwindow/llwindowsdl.cpp +++ b/indra/llwindow/llwindowsdl.cpp @@ -36,6 +36,8 @@ #include "linden_common.h" #include "llwindowsdl.h" + +#include "llwindowcallbacks.h" #include "llkeyboardsdl.h" #include "llerror.h" #include "llgl.h" @@ -188,16 +190,19 @@ Display* LLWindowSDL::get_SDL_Display(void) #endif // LL_X11 -LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width, +LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks, + const std::string& title, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples) - : LLWindow(fullscreen, flags), Lock_Display(NULL), + : LLWindow(callbacks, fullscreen, flags), + Lock_Display(NULL), Unlock_Display(NULL), mGamma(1.0f) { // Initialize the keyboard gKeyboard = new LLKeyboardSDL(); + gKeyboard->setCallbacks(callbacks); // Note that we can't set up key-repeat until after SDL has init'd video // Ignore use_gl for now, only used for drones on PC @@ -249,6 +254,10 @@ LLWindowSDL::LLWindowSDL(const std::string& title, S32 x, S32 y, S32 width, #if LL_X11 mFlashing = FALSE; #endif // LL_X11 + + mKeyScanCode = 0; + mKeyVirtualKey = 0; + mKeyModifiers = KMOD_NONE; } static SDL_Surface *Load_BMP_Resource(const char *basename) @@ -445,14 +454,20 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B << int(r_sdl_version->minor) << "." << int(r_sdl_version->patch) << llendl; - const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo( ); - if (!videoInfo) + const SDL_VideoInfo *video_info = SDL_GetVideoInfo( ); + if (!video_info) { llinfos << "SDL_GetVideoInfo() failed! " << SDL_GetError() << llendl; setupFailure("SDL_GetVideoInfo() failed, Window creation error", "Error", OSMB_OK); return FALSE; } + if (video_info->current_h > 0) + { + mOriginalAspectRatio = (float)video_info->current_w / (float)video_info->current_h; + llinfos << "Original aspect ratio was " << video_info->current_w << ":" << video_info->current_h << "=" << mOriginalAspectRatio << llendl; + } + SDL_EnableUNICODE(1); SDL_WM_SetCaption(mWindowTitle.c_str(), mWindowTitle.c_str()); @@ -653,7 +668,7 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B // fallback to letting SDL detect VRAM. // note: I've not seen SDL's detection ever actually find // VRAM != 0, but if SDL *does* detect it then that's a bonus. - gGLManager.mVRAM = videoInfo->video_mem / 1024; + gGLManager.mVRAM = video_info->video_mem / 1024; if (gGLManager.mVRAM != 0) { llinfos << "SDL detected " << gGLManager.mVRAM << "MB VRAM." << llendl; @@ -986,7 +1001,10 @@ BOOL LLWindowSDL::setSize(const LLCoordScreen size) void LLWindowSDL::swapBuffers() { if (mWindow) + { + glFinish(); SDL_GL_SwapBuffers(); + } } U32 LLWindowSDL::getFSAASamples() @@ -1282,6 +1300,49 @@ BOOL LLWindowSDL::copyTextToClipboard(const LLWString &text) return FALSE; // failure } + +BOOL LLWindowSDL::isPrimaryTextAvailable() +{ + if (ll_try_gtk_init()) + { + GtkClipboard * const clipboard = + gtk_clipboard_get(GDK_SELECTION_PRIMARY); + return gtk_clipboard_wait_is_text_available(clipboard) ? + TRUE : FALSE; + } + return FALSE; // failure +} + +BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &text) +{ + if (ll_try_gtk_init()) + { + GtkClipboard * const clipboard = + gtk_clipboard_get(GDK_SELECTION_PRIMARY); + gchar * const data = gtk_clipboard_wait_for_text(clipboard); + if (data) + { + text = LLWString(utf8str_to_wstring(data)); + g_free(data); + return TRUE; + } + } + return FALSE; // failure +} + +BOOL LLWindowSDL::copyTextToPrimary(const LLWString &text) +{ + if (ll_try_gtk_init()) + { + const std::string utf8 = wstring_to_utf8str(text); + GtkClipboard * const clipboard = + gtk_clipboard_get(GDK_SELECTION_PRIMARY); + gtk_clipboard_set_text(clipboard, utf8.c_str(), utf8.length()); + return TRUE; + } + return FALSE; // failure +} + #else BOOL LLWindowSDL::isClipboardTextAvailable() @@ -1298,6 +1359,22 @@ BOOL LLWindowSDL::copyTextToClipboard(const LLWString &s) { return FALSE; // unsupported } + +BOOL LLWindowSDL::isPrimaryTextAvailable() +{ + return FALSE; // unsupported +} + +BOOL LLWindowSDL::pasteTextFromPrimary(LLWString &dst) +{ + return FALSE; // unsupported +} + +BOOL LLWindowSDL::copyTextToPrimary(const LLWString &s) +{ + return FALSE; // unsupported +} + #endif // LL_GTK LLWindow::LLWindowResolution* LLWindowSDL::getSupportedResolutions(S32 &num_resolutions) @@ -1534,6 +1611,76 @@ U32 LLWindowSDL::SDLCheckGrabbyKeys(SDLKey keysym, BOOL gain) return mGrabbyKeyFlags; } + +void check_vm_bloat() +{ +#if LL_LINUX + // watch our own VM and RSS sizes, warn if we bloated rapidly + FILE *fp = fopen("/proc/self/stat", "r"); + if (fp) + { + static long long last_vm_size = 0; + static long long last_rss_size = 0; + const long long significant_vm_difference = 250 * 1024*1024; + const long long significant_rss_difference = 50 * 1024*1024; + + ssize_t res; + size_t dummy; + char *ptr; + for (int i=0; i<22; ++i) // parse past the values we don't want + { + ptr = NULL; + res = getdelim(&ptr, &dummy, ' ', fp); + free(ptr); + } + // 23rd space-delimited entry is vsize + ptr = NULL; + res = getdelim(&ptr, &dummy, ' ', fp); + llassert(ptr); + long long this_vm_size = atoll(ptr); + free(ptr); + // 24th space-delimited entry is RSS + ptr = NULL; + res = getdelim(&ptr, &dummy, ' ', fp); + llassert(ptr); + long long this_rss_size = getpagesize() * atoll(ptr); + free(ptr); + + llinfos << "VM SIZE IS NOW " << (this_vm_size/(1024*1024)) << " MB, RSS SIZE IS NOW " << (this_rss_size/(1024*1024)) << " MB" << llendl; + + if (llabs(last_vm_size - this_vm_size) > + significant_vm_difference) + { + if (this_vm_size > last_vm_size) + { + llwarns << "VM size grew by " << (this_vm_size - last_vm_size)/(1024*1024) << " MB in last frame" << llendl; + } + else + { + llinfos << "VM size shrank by " << (last_vm_size - this_vm_size)/(1024*1024) << " MB in last frame" << llendl; + } + } + + if (llabs(last_rss_size - this_rss_size) > + significant_rss_difference) + { + if (this_rss_size > last_rss_size) + { + llwarns << "RSS size grew by " << (this_rss_size - last_rss_size)/(1024*1024) << " MB in last frame" << llendl; + } + else + { + llinfos << "RSS size shrank by " << (last_rss_size - this_rss_size)/(1024*1024) << " MB in last frame" << llendl; + } + } + + last_rss_size = this_rss_size; + last_vm_size = this_vm_size; + + fclose(fp); + } +#endif // LL_LINUX +} // virtual void LLWindowSDL::processMiscNativeEvents() { @@ -1558,13 +1705,19 @@ void LLWindowSDL::processMiscNativeEvents() pump_timer.setTimerExpirySec(1.0f / 15.0f); do { // Always do at least one non-blocking pump - gtk_main_iteration_do(0); + gtk_main_iteration_do(FALSE); } while (gtk_events_pending() && !pump_timer.hasExpired()); setlocale(LC_ALL, saved_locale.c_str() ); } #endif // LL_GTK + + // hack - doesn't belong here - but this is just for debugging + if (getenv("LL_DEBUG_BLOAT")) + { + check_vm_bloat(); + } } void LLWindowSDL::gatherInput() @@ -1592,6 +1745,9 @@ void LLWindowSDL::gatherInput() } case SDL_KEYDOWN: + mKeyScanCode = event.key.keysym.scancode; + mKeyVirtualKey = event.key.keysym.unicode; + mKeyModifiers = event.key.keysym.mod; gKeyboard->handleKeyDown(event.key.keysym.sym, event.key.keysym.mod); // part of the fix for SL-13243 if (SDLCheckGrabbyKeys(event.key.keysym.sym, TRUE) != 0) @@ -1605,8 +1761,12 @@ void LLWindowSDL::gatherInput() break; case SDL_KEYUP: - if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0) - SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243 + mKeyScanCode = event.key.keysym.scancode; + mKeyVirtualKey = event.key.keysym.unicode; + mKeyModifiers = event.key.keysym.mod; + + if (SDLCheckGrabbyKeys(event.key.keysym.sym, FALSE) == 0) + SDLReallyCaptureInput(FALSE); // part of the fix for SL-13243 gKeyboard->handleKeyUp(event.key.keysym.sym, event.key.keysym.mod); break; @@ -1922,14 +2082,14 @@ void LLWindowSDL::initCursors() mSDLCursors[UI_CURSOR_TOOLPAN] = makeSDLCursorFromBMP("lltoolpan.BMP",7,5); mSDLCursors[UI_CURSOR_TOOLZOOMIN] = makeSDLCursorFromBMP("lltoolzoomin.BMP",7,5); mSDLCursors[UI_CURSOR_TOOLPICKOBJECT3] = makeSDLCursorFromBMP("toolpickobject3.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromBMP("toolsit.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromBMP("toolbuy.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLPAY] = makeSDLCursorFromBMP("toolpay.BMP",0,0); - mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromBMP("toolopen.BMP",0,0); mSDLCursors[UI_CURSOR_TOOLPLAY] = makeSDLCursorFromBMP("toolplay.BMP",0,0); mSDLCursors[UI_CURSOR_TOOLPAUSE] = makeSDLCursorFromBMP("toolpause.BMP",0,0); mSDLCursors[UI_CURSOR_TOOLMEDIAOPEN] = makeSDLCursorFromBMP("toolmediaopen.BMP",0,0); mSDLCursors[UI_CURSOR_PIPETTE] = makeSDLCursorFromBMP("lltoolpipette.BMP",2,28); + mSDLCursors[UI_CURSOR_TOOLSIT] = makeSDLCursorFromBMP("toolsit.BMP",0,0); + mSDLCursors[UI_CURSOR_TOOLBUY] = makeSDLCursorFromBMP("toolbuy.BMP",0,0); + mSDLCursors[UI_CURSOR_TOOLOPEN] = makeSDLCursorFromBMP("toolopen.BMP",0,0); + mSDLCursors[UI_CURSOR_TOOLPAY] = makeSDLCursorFromBMP("toolpay.BMP",0,0); if (getenv("LL_ATI_MOUSE_CURSOR_BUG") != NULL) { llinfos << "Disabling cursor updating due to LL_ATI_MOUSE_CURSOR_BUG" << llendl; @@ -2169,7 +2329,40 @@ static void color_changed_callback(GtkWidget *widget, gtk_color_selection_get_current_color(colorsel, colorp); } -BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b) + +/* + Make the raw keyboard data available - used to poke through to LLQtWebKit so + that Qt/Webkit has access to the virtual keycodes etc. that it needs +*/ +LLSD LLWindowSDL::getNativeKeyData() +{ + LLSD result = LLSD::emptyMap(); + + U32 modifiers = 0; // pretend-native modifiers... oh what a tangled web we weave! + + // we go through so many levels of device abstraction that I can't really guess + // what a plugin under GDK under Qt under SL under SDL under X11 considers + // a 'native' modifier mask. this has been sort of reverse-engineered... they *appear* + // to match GDK consts, but that may be co-incidence. + modifiers |= (mKeyModifiers & KMOD_LSHIFT) ? 0x0001 : 0; + modifiers |= (mKeyModifiers & KMOD_RSHIFT) ? 0x0001 : 0;// munge these into the same shift + modifiers |= (mKeyModifiers & KMOD_CAPS) ? 0x0002 : 0; + modifiers |= (mKeyModifiers & KMOD_LCTRL) ? 0x0004 : 0; + modifiers |= (mKeyModifiers & KMOD_RCTRL) ? 0x0004 : 0;// munge these into the same ctrl + modifiers |= (mKeyModifiers & KMOD_LALT) ? 0x0008 : 0;// untested + modifiers |= (mKeyModifiers & KMOD_RALT) ? 0x0008 : 0;// untested + // *todo: test ALTs - I don't have a case for testing these. Do you? + // *todo: NUM? - I don't care enough right now (and it's not a GDK modifier). + + result["scan_code"] = (S32)mKeyScanCode; + result["virtual_key"] = (S32)mKeyVirtualKey; + result["modifiers"] = (S32)modifiers; + + return result; +} + + +BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) { BOOL rtn = FALSE; @@ -2247,7 +2440,7 @@ S32 OSMessageBoxSDL(const std::string& text, const std::string& caption, U32 typ return 0; } -BOOL LLWindowSDL::dialog_color_picker ( F32 *r, F32 *g, F32 *b) +BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b) { return (FALSE); } @@ -2288,7 +2481,7 @@ void exec_cmd(const std::string& cmd, const std::string& arg) // Open a URL with the user's default web browser. // Must begin with protocol identifier. -void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url) +void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async) { llinfos << "spawn_web_browser: " << escaped_url << llendl; @@ -2304,8 +2497,10 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url) # endif // LL_X11 std::string cmd, arg; - cmd = gDirUtilp->getAppRODataDir().c_str(); - cmd += gDirUtilp->getDirDelimiter().c_str(); + cmd = gDirUtilp->getAppRODataDir(); + cmd += gDirUtilp->getDirDelimiter(); + cmd += "etc"; + cmd += gDirUtilp->getDirDelimiter(); cmd += "launch_url.sh"; arg = escaped_url; exec_cmd(cmd, arg); @@ -2364,6 +2559,7 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() // Use libfontconfig to find us a nice ordered list of fallback fonts // specific to this system. std::string final_fallback("/usr/share/fonts/truetype/kochi/kochi-gothic.ttf"); + const int max_font_count_cutoff = 40; // fonts are expensive in the current system, don't enumerate an arbitrary number of them // Our 'ideal' font properties which define the sorting results. // slant=0 means Roman, index=0 means the first face in a font file // (the one we actually use), weight=80 means medium weight, @@ -2379,7 +2575,6 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() std::vector<std::string> rtns; FcFontSet *fs = NULL; FcPattern *sortpat = NULL; - int font_count = 0; llinfos << "Getting system font list from FontConfig..." << llendl; @@ -2423,12 +2618,13 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() FcPatternDestroy(sortpat); } + int found_font_count = 0; if (fs) { // Get the full pathnames to the fonts, where available, // which is what we really want. - int i; - for (i=0; i<fs->nfont; ++i) + found_font_count = fs->nfont; + for (int i=0; i<fs->nfont; ++i) { FcChar8 *filename; if (FcResultMatch == FcPatternGetString(fs->fonts[i], @@ -2437,7 +2633,8 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() && filename) { rtns.push_back(std::string((const char*)filename)); - ++font_count; + if (rtns.size() >= max_font_count_cutoff) + break; // hit limit } } FcFontSetDestroy (fs); @@ -2450,7 +2647,7 @@ std::vector<std::string> LLWindowSDL::getDynamicFallbackFontList() { lldebugs << " file: " << *it << llendl; } - llinfos << "Using " << font_count << " system font(s)." << llendl; + llinfos << "Using " << rtns.size() << "/" << found_font_count << " system fonts." << llendl; rtns.push_back(final_fallback); return rtns; diff --git a/indra/llwindow/llwindowsdl.h b/indra/llwindow/llwindowsdl.h index 2363c510d..d46ffcdd9 100644 --- a/indra/llwindow/llwindowsdl.h +++ b/indra/llwindow/llwindowsdl.h @@ -62,6 +62,8 @@ public: /*virtual*/ BOOL getMinimized(); /*virtual*/ BOOL getMaximized(); /*virtual*/ BOOL maximize(); + /*virtual*/ void minimize(); + /*virtual*/ void restore(); /*virtual*/ BOOL getFullscreen(); /*virtual*/ BOOL getPosition(LLCoordScreen *position); /*virtual*/ BOOL getSize(LLCoordScreen *size); @@ -83,6 +85,11 @@ public: /*virtual*/ BOOL isClipboardTextAvailable(); /*virtual*/ BOOL pasteTextFromClipboard(LLWString &dst); /*virtual*/ BOOL copyTextToClipboard(const LLWString & src); + + /*virtual*/ BOOL isPrimaryTextAvailable(); + /*virtual*/ BOOL pasteTextFromPrimary(LLWString &dst); + /*virtual*/ BOOL copyTextToPrimary(const LLWString & src); + /*virtual*/ void flashIcon(F32 seconds); /*virtual*/ F32 getGamma(); /*virtual*/ BOOL setGamma(const F32 gamma); // Set the gamma @@ -112,12 +119,12 @@ public: /*virtual*/ void beforeDialog(); /*virtual*/ void afterDialog(); - /*virtual*/ BOOL dialog_color_picker(F32 *r, F32 *g, F32 *b); + /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b); /*virtual*/ void *getPlatformWindow(); /*virtual*/ void bringToFront(); - /*virtual*/ void spawnWebBrowser(const std::string& escaped_url); + /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); static std::vector<std::string> getDynamicFallbackFontList(); @@ -141,27 +148,25 @@ public: #endif // LL_X11 protected: - LLWindowSDL( + LLWindowSDL(LLWindowCallbacks* callbacks, const std::string& title, int x, int y, int width, int height, U32 flags, BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples); ~LLWindowSDL(); + /*virtual*/ BOOL isValid(); + /*virtual*/ LLSD getNativeKeyData(); + void initCursors(); void quitCursors(); - BOOL isValid(); void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size); - // Changes display resolution. Returns true if successful BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh); // Go back to last fullscreen display resolution. BOOL setFullscreenResolution(); - void minimize(); - void restore(); - BOOL shouldPostQuit() { return mPostQuit; } protected: @@ -199,12 +204,16 @@ protected: friend class LLWindowManager; -#if LL_X11 private: +#if LL_X11 void x11_set_urgent(BOOL urgent); BOOL mFlashing; LLTimer mFlashTimer; #endif //LL_X11 + + U32 mKeyScanCode; + U32 mKeyVirtualKey; + SDLMod mKeyModifiers; }; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 8abbb9018..68162447f 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -36,11 +36,25 @@ #include "llwindowwin32.h" +// LLWindow library includes +#include "llkeyboardwin32.h" +#include "lldragdropwin32.h" +#include "llpreeditor.h" +#include "llwindowcallbacks.h" + +// Linden library includes +#include "llerror.h" +#include "llgl.h" +#include "llstring.h" +#include "lldir.h" + +// System includes #include <commdlg.h> #include <WinUser.h> #include <mapi.h> #include <process.h> // for _spawn #include <shellapi.h> +#include <fstream> #include <Imm.h> // Require DirectInput version 8 @@ -49,16 +63,6 @@ #include <dinput.h> #include <Dbt.h.> -#include "llkeyboardwin32.h" -#include "llerror.h" -#include "llgl.h" -#include "llstring.h" -#include "lldir.h" - -#include "indra_constants.h" - -#include "llpreeditor.h" - #include "llfasttimer.h" // culled from winuser.h @@ -360,13 +364,14 @@ LLWinImm::~LLWinImm() } -LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name, S32 x, S32 y, S32 width, +LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks, + const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height, U32 flags, BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples) - : LLWindow(fullscreen, flags) + : LLWindow(callbacks, fullscreen, flags) { mFSAASamples = fsaa_samples; mIconResource = gIconResource; @@ -375,11 +380,18 @@ LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name, mMousePositionModified = FALSE; mInputProcessingPaused = FALSE; mPreeditor = NULL; + mKeyCharCode = 0; + mKeyScanCode = 0; + mKeyVirtualKey = 0; mhDC = NULL; mhRC = NULL; // Initialize the keyboard gKeyboard = new LLKeyboardWin32(); + gKeyboard->setCallbacks(callbacks); + + // Initialize the Drag and Drop functionality + mDragDrop = new LLDragDropWin32; // Initialize (boot strap) the Language text input management, // based on the system's (user's) default settings. @@ -494,6 +506,8 @@ LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name, //----------------------------------------------------------------------- DEVMODE dev_mode; + ::ZeroMemory(&dev_mode, sizeof(DEVMODE)); + dev_mode.dmSize = sizeof(DEVMODE); DWORD current_refresh; if (EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) { @@ -538,7 +552,26 @@ LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name, if (closest_refresh == 0) { LL_WARNS("Window") << "Couldn't find display mode " << width << " by " << height << " at " << BITS_PER_PIXEL << " bits per pixel" << LL_ENDL; - success = FALSE; + + if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dev_mode)) + { + success = FALSE; + } + else + { + if (dev_mode.dmBitsPerPel == BITS_PER_PIXEL) + { + LL_WARNS("Window") << "Current BBP is OK falling back to that" << LL_ENDL; + window_rect.right=width=dev_mode.dmPelsWidth; + window_rect.bottom=height=dev_mode.dmPelsHeight; + success = TRUE; + } + else + { + LL_WARNS("Window") << "Current BBP is BAD" << LL_ENDL; + success = FALSE; + } + } } // If we found a good resolution, use it. @@ -614,6 +647,8 @@ LLWindowWin32::LLWindowWin32(const std::string& title, const std::string& name, LLWindowWin32::~LLWindowWin32() { + delete mDragDrop; + delete [] mWindowTitle; mWindowTitle = NULL; @@ -664,6 +699,8 @@ void LLWindowWin32::close() return; } + mDragDrop->reset(); + // Make sure cursor is visible and we haven't mangled the clipping state. setMouseClipping(FALSE); showCursor(); @@ -842,6 +879,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO { GLuint pixel_format; DEVMODE dev_mode; + ::ZeroMemory(&dev_mode, sizeof(DEVMODE)); + dev_mode.dmSize = sizeof(DEVMODE); DWORD current_refresh; DWORD dw_ex_style; DWORD dw_style; @@ -1139,8 +1178,39 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO // First we try and get a 32 bit depth pixel format BOOL result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); + + while(!result && mFSAASamples > 0) + { + llwarns << "FSAASamples: " << mFSAASamples << " not supported." << llendl ; + + mFSAASamples /= 2 ; //try to decrease sample pixel number until to disable anti-aliasing + if(mFSAASamples < 2) + { + mFSAASamples = 0 ; + } + + if (mFSAASamples > 0) + { + attrib_list[end_attrib + 3] = mFSAASamples; + } + else + { + cur_attrib = end_attrib ; + end_attrib = 0 ; + attrib_list[cur_attrib++] = 0 ; //end + } + result = wglChoosePixelFormatARB(mhDC, attrib_list, NULL, 256, pixel_formats, &num_formats); + + if(result) + { + llwarns << "Only support FSAASamples: " << mFSAASamples << llendl ; + } + } + if (!result) { + llwarns << "mFSAASamples: " << mFSAASamples << llendl ; + close(); show_window_creation_error("Error after wglChoosePixelFormatARB 32-bit"); return FALSE; @@ -1368,6 +1438,11 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO } SetWindowLong(mWindowHandle, GWL_USERDATA, (U32)this); + + // register this window as handling drag/drop events from the OS + DragAcceptFiles( mWindowHandle, TRUE ); + + mDragDrop->init( mWindowHandle ); //register joystick timer callback SetTimer( mWindowHandle, 0, 1000 / 30, NULL ); // 30 fps timer @@ -1876,6 +1951,10 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ // allow system keys, such as ALT-F4 to be processed by Windows eat_keystroke = FALSE; case WM_KEYDOWN: + window_imp->mKeyCharCode = 0; // don't know until wm_char comes in next + window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff; + window_imp->mKeyVirtualKey = w_param; + window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYDOWN"); { if (gDebugWindowProc) @@ -1895,6 +1974,9 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ eat_keystroke = FALSE; case WM_KEYUP: { + window_imp->mKeyScanCode = ( l_param >> 16 ) & 0xff; + window_imp->mKeyVirtualKey = w_param; + window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_KEYUP"); LLFastTimer t2(LLFastTimer::FTM_KEYHANDLER); @@ -1980,6 +2062,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ break; case WM_CHAR: + window_imp->mKeyCharCode = w_param; + // Should really use WM_UNICHAR eventually, but it requires a specific Windows version and I need // to figure out how that works. - Doug // @@ -2232,7 +2316,27 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEWHEEL"); static short z_delta = 0; - z_delta += HIWORD(w_param); + RECT client_rect; + + // eat scroll events that occur outside our window, since we use mouse position to direct scroll + // instead of keyboard focus + // NOTE: mouse_coord is in *window* coordinates for scroll events + POINT mouse_coord = {(S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param)}; + + if (ScreenToClient(window_imp->mWindowHandle, &mouse_coord) + && GetClientRect(window_imp->mWindowHandle, &client_rect)) + { + // we have a valid mouse point and client rect + if (mouse_coord.x < client_rect.left || client_rect.right < mouse_coord.x + || mouse_coord.y < client_rect.top || client_rect.bottom < mouse_coord.y) + { + // mouse is outside of client rect, so don't do anything + return 0; + } + } + + S16 incoming_z_delta = HIWORD(w_param); + z_delta += incoming_z_delta; // cout << "z_delta " << z_delta << endl; // current mouse wheels report changes in increments of zDelta (+120, -120) @@ -2352,11 +2456,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_ return 0; case WM_COPYDATA: - window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA"); - // received a URL - PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param; - window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData); + { + window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_COPYDATA"); + // received a URL + PCOPYDATASTRUCT myCDS = (PCOPYDATASTRUCT) l_param; + window_imp->mCallbacks->handleDataCopy(window_imp, myCDS->dwData, myCDS->lpData); + }; return 0; + + break; } window_imp->mCallbacks->handlePauseWatchdog(window_imp); @@ -2661,6 +2769,8 @@ LLWindow::LLWindowResolution* LLWindowWin32::getSupportedResolutions(S32 &num_re { mSupportedResolutions = new LLWindowResolution[MAX_NUM_RESOLUTIONS]; DEVMODE dev_mode; + ::ZeroMemory(&dev_mode, sizeof(DEVMODE)); + dev_mode.dmSize = sizeof(DEVMODE); mNumSupportedResolutions = 0; for (S32 mode_num = 0; mNumSupportedResolutions < MAX_NUM_RESOLUTIONS; mode_num++) @@ -2736,7 +2846,8 @@ F32 LLWindowWin32::getPixelAspectRatio() BOOL LLWindowWin32::setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh) { DEVMODE dev_mode; - dev_mode.dmSize = sizeof(dev_mode); + ::ZeroMemory(&dev_mode, sizeof(DEVMODE)); + dev_mode.dmSize = sizeof(DEVMODE); BOOL success = FALSE; // Don't change anything if we don't have to @@ -2808,6 +2919,7 @@ BOOL LLWindowWin32::resetDisplayResolution() void LLWindowWin32::swapBuffers() { + glFinish(); SwapBuffers(mhDC); } @@ -2942,7 +3054,7 @@ void LLWindowWin32::ShellEx(const std::string& command ) } -void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url ) +void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url, bool async) { bool found = false; S32 i; @@ -2972,16 +3084,36 @@ void LLWindowWin32::spawnWebBrowser(const std::string& escaped_url ) // let the OS decide what to use to open the URL SHELLEXECUTEINFO sei = { sizeof( sei ) }; - sei.fMask = SEE_MASK_FLAG_DDEWAIT; + if (async) + { + sei.fMask = SEE_MASK_ASYNCOK; + } + + else + { + sei.fMask = SEE_MASK_FLAG_DDEWAIT; + } sei.nShow = SW_SHOWNORMAL; sei.lpVerb = L"open"; sei.lpFile = url_utf16.c_str(); ShellExecuteEx( &sei ); - } +/* + Make the raw keyboard data available - used to poke through to LLQtWebKit so + that Qt/Webkit has access to the virtual keycodes etc. that it needs +*/ +LLSD LLWindowWin32::getNativeKeyData() +{ + LLSD result = LLSD::emptyMap(); -BOOL LLWindowWin32::dialog_color_picker ( F32 *r, F32 *g, F32 *b ) + result["scan_code"] = (S32)mKeyScanCode; + result["virtual_key"] = (S32)mKeyVirtualKey; + + return result; +} + +BOOL LLWindowWin32::dialogColorPicker( F32 *r, F32 *g, F32 *b ) { BOOL retval = FALSE; @@ -3475,6 +3607,13 @@ static LLWString find_context(const LLWString & wtext, S32 focus, S32 focus_leng return wtext.substr(start, end - start); } +// final stage of handling drop requests - both from WM_DROPFILES message +// for files and via IDropTarget interface requests. +LLWindowCallbacks::DragNDropResult LLWindowWin32::completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ) +{ + return mCallbacks->handleDragNDrop( this, gl_coord, mask, action, url ); +} + // Handle WM_IME_REQUEST message. // If it handled the message, returns TRUE. Otherwise, FALSE. // When it handled the message, the value to be returned from @@ -3508,7 +3647,7 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result) // WCHARs, i.e., UTF-16 encoding units, so we can't simply pass the // number to getPreeditLocation. - const LLWString & wtext = mPreeditor->getWText(); + const LLWString & wtext = mPreeditor->getPreeditString(); S32 preedit, preedit_length; mPreeditor->getPreeditRange(&preedit, &preedit_length); LLCoordGL caret_coord; @@ -3535,7 +3674,7 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result) case IMR_RECONVERTSTRING: { mPreeditor->resetPreedit(); - const LLWString & wtext = mPreeditor->getWText(); + const LLWString & wtext = mPreeditor->getPreeditString(); S32 select, select_length; mPreeditor->getSelectionRange(&select, &select_length); @@ -3577,7 +3716,7 @@ BOOL LLWindowWin32::handleImeRequests(U32 request, U32 param, LRESULT *result) } case IMR_DOCUMENTFEED: { - const LLWString & wtext = mPreeditor->getWText(); + const LLWString & wtext = mPreeditor->getPreeditString(); S32 preedit, preedit_length; mPreeditor->getPreeditRange(&preedit, &preedit_length); diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index d3ae3250f..9343593f6 100644 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -39,6 +39,8 @@ #include <windows.h> #include "llwindow.h" +#include "llwindowcallbacks.h" +#include "lldragdropwin32.h" // Hack for async host by name #define LL_WM_HOST_RESOLVED (WM_APP + 1) @@ -54,6 +56,8 @@ public: /*virtual*/ BOOL getMinimized(); /*virtual*/ BOOL getMaximized(); /*virtual*/ BOOL maximize(); + /*virtual*/ void minimize(); + /*virtual*/ void restore(); /*virtual*/ BOOL getFullscreen(); /*virtual*/ BOOL getPosition(LLCoordScreen *position); /*virtual*/ BOOL getSize(LLCoordScreen *size); @@ -100,7 +104,7 @@ public: /*virtual*/ F32 getPixelAspectRatio(); /*virtual*/ void setNativeAspectRatio(F32 ratio) { mOverrideAspectRatio = ratio; } - /*virtual*/ BOOL dialog_color_picker (F32 *r, F32 *g, F32 *b ); + /*virtual*/ BOOL dialogColorPicker(F32 *r, F32 *g, F32 *b ); /*virtual*/ void *getPlatformWindow(); /*virtual*/ void bringToFront(); @@ -110,13 +114,15 @@ public: /*virtual*/ void setLanguageTextInput( const LLCoordGL & pos ); /*virtual*/ void updateLanguageTextInputArea(); /*virtual*/ void interruptLanguageTextInput(); - /*virtual*/ void spawnWebBrowser(const std::string& escaped_url); - /*virtual*/ void ShellEx(const std::string& command); + void ShellEx(const std::string& command); + /*virtual*/ void spawnWebBrowser(const std::string& escaped_url, bool async); + + LLWindowCallbacks::DragNDropResult completeDragNDropRequest( const LLCoordGL gl_coord, const MASK mask, LLWindowCallbacks::DragNDropAction action, const std::string url ); static std::vector<std::string> getDynamicFallbackFontList(); protected: - LLWindowWin32( + LLWindowWin32(LLWindowCallbacks* callbacks, const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags, BOOL fullscreen, BOOL clearBg, BOOL disable_vsync, BOOL use_gl, BOOL ignore_pixel_depth, U32 fsaa_samples); @@ -127,7 +133,7 @@ protected: HCURSOR loadColorCursor(LPCTSTR name); BOOL isValid(); void moveWindow(const LLCoordScreen& position,const LLCoordScreen& size); - + LLSD getNativeKeyData(); // Changes display resolution. Returns true if successful BOOL setDisplayResolution(S32 width, S32 height, S32 bits, S32 refresh); @@ -138,9 +144,6 @@ protected: // Restore the display resolution to its value before we ran the app. BOOL resetDisplayResolution(); - void minimize(); - void restore(); - BOOL shouldPostQuit() { return mPostQuit; } void fillCompositionForm(const LLRect& bounds, COMPOSITIONFORM *form); @@ -207,6 +210,12 @@ protected: LLPreeditor *mPreeditor; + LLDragDropWin32* mDragDrop; + + U32 mKeyCharCode; + U32 mKeyScanCode; + U32 mKeyVirtualKey; + friend class LLWindowManager; }; diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 806660a38..c750351ed 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -407,7 +407,8 @@ private: // Add a listener to the controls signal... // and store the connection... mConnection = controlp->getSignal()->connect( - boost::bind(&LLControlCache<T>::handleValueChange, this, _2) + boost::bind(&LLControlCache<T>::handleValueChange, this, _2), + boost::signals2::at_front //make sure cachedctrl slots are inserted before anything else. ); mType = controlp->type(); mControl = controlp; diff --git a/indra/lscript/lscript_compile/CMakeLists.txt b/indra/lscript/lscript_compile/CMakeLists.txt index d6faba060..fc002a612 100644 --- a/indra/lscript/lscript_compile/CMakeLists.txt +++ b/indra/lscript/lscript_compile/CMakeLists.txt @@ -5,6 +5,7 @@ include(LLCommon) include(LLMath) include(LLMessage) include(LLInventory) +include(LLPrimitive) include(LScript) include(FindCygwin) @@ -41,6 +42,7 @@ include_directories( ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLINVENTORY_INCLUDE_DIRS} + ${LLPRIMITIVE_INCLUDE_DIRS} ${LSCRIPT_INCLUDE_DIRS} ) diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index 4ce149e52..2235dc134 100644 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -7,14 +7,11 @@ FS (f|F) %n 4000 %p 5000 +%top { + #include "linden_common.h" +} + %{ -// We maintain a pre-generated lexer source file to simplify user builds. -// Before committing changes to this file, manually run -// -// flex -o indra_generated.l.cpp indra.l -// -// to update the pre-generated lexer. Then commit all files simultaneously. -#include "linden_common.h" // Deal with the fact that lex/yacc generates unreachable code #ifdef LL_WINDOWS #pragma warning (disable : 4018) // warning C4018: signed/unsigned mismatch @@ -39,6 +36,7 @@ FS (f|F) #include "llregionflags.h" #include "lscript_http.h" #include "llclickaction.h" +#include "llmediaentry.h" void count(); void line_comment(); @@ -155,6 +153,7 @@ extern "C" { int yyerror(const char *fmt, ...); } "AGENT_CROUCHING" { count(); yylval.ival = AGENT_CROUCHING; return(INTEGER_CONSTANT); } "AGENT_BUSY" { count(); yylval.ival = AGENT_BUSY; return(INTEGER_CONSTANT); } "AGENT_ALWAYS_RUN" { count(); yylval.ival = AGENT_ALWAYS_RUN; return(INTEGER_CONSTANT); } +"AGENT_AUTOPILOT" { count(); yylval.ival = AGENT_AUTOPILOT; return(INTEGER_CONSTANT); } "CAMERA_PITCH" { count(); yylval.ival = FOLLOWCAM_PITCH; return(INTEGER_CONSTANT); } "CAMERA_FOCUS_OFFSET" { count(); yylval.ival = FOLLOWCAM_FOCUS_OFFSET; return (INTEGER_CONSTANT); } @@ -237,7 +236,8 @@ extern "C" { int yyerror(const char *fmt, ...); } "CHANGED_OWNER" { count(); yylval.ival = CHANGED_OWNER; return(INTEGER_CONSTANT); } "CHANGED_REGION" { count(); yylval.ival = CHANGED_REGION; return(INTEGER_CONSTANT); } "CHANGED_TELEPORT" { count(); yylval.ival = CHANGED_TELEPORT; return(INTEGER_CONSTANT); } -"CHANGED_REGION_START" { count(); yylval.ival = CHANGED_REGION_START; return(INTEGER_CONSTANT); } +"CHANGED_REGION_START" { count(); yylval.ival = CHANGED_REGION_START; return(INTEGER_CONSTANT); } +"CHANGED_MEDIA" { count(); yylval.ival = CHANGED_MEDIA; return(INTEGER_CONSTANT); } "OBJECT_UNKNOWN_DETAIL" { count(); yylval.ival = OBJECT_UNKNOWN_DETAIL; return(INTEGER_CONSTANT); } "OBJECT_NAME" { count(); yylval.ival = OBJECT_NAME; return(INTEGER_CONSTANT); } @@ -248,6 +248,10 @@ extern "C" { int yyerror(const char *fmt, ...); } "OBJECT_OWNER" { count(); yylval.ival = OBJECT_OWNER; return(INTEGER_CONSTANT); } "OBJECT_GROUP" { count(); yylval.ival = OBJECT_GROUP; return(INTEGER_CONSTANT); } "OBJECT_CREATOR" { count(); yylval.ival = OBJECT_CREATOR; return(INTEGER_CONSTANT); } +"OBJECT_RUNNING_SCRIPT_COUNT" { count(); yylval.ival = OBJECT_RUNNING_SCRIPT_COUNT; return(INTEGER_CONSTANT); } +"OBJECT_TOTAL_SCRIPT_COUNT" { count(); yylval.ival = OBJECT_TOTAL_SCRIPT_COUNT; return(INTEGER_CONSTANT); } +"OBJECT_SCRIPT_MEMORY" { count(); yylval.ival = OBJECT_SCRIPT_MEMORY; return(INTEGER_CONSTANT); } +"OBJECT_SCRIPT_TIME" { count(); yylval.ival = OBJECT_SCRIPT_TIME; return(INTEGER_CONSTANT); } "TYPE_INTEGER" { count(); yylval.ival = LST_INTEGER; return(INTEGER_CONSTANT); } "TYPE_FLOAT" { count(); yylval.ival = LST_FLOATINGPOINT; return(INTEGER_CONSTANT); } @@ -602,6 +606,8 @@ extern "C" { int yyerror(const char *fmt, ...); } "PARCEL_DETAILS_OWNER" { count(); yylval.ival = PARCEL_DETAILS_OWNER; return(INTEGER_CONSTANT); } "PARCEL_DETAILS_GROUP" { count(); yylval.ival = PARCEL_DETAILS_GROUP; return(INTEGER_CONSTANT); } "PARCEL_DETAILS_AREA" { count(); yylval.ival = PARCEL_DETAILS_AREA; return(INTEGER_CONSTANT); } +"PARCEL_DETAILS_ID" { count(); yylval.ival = PARCEL_DETAILS_ID; return(INTEGER_CONSTANT); } +"PARCEL_DETAILS_SEE_AVATARS" { count(); yylval.ival = PARCEL_DETAILS_SEE_AVATARS; return(INTEGER_CONSTANT); } "STRING_TRIM_HEAD" { count(); yylval.ival = STRING_TRIM_HEAD; return(INTEGER_CONSTANT); } "STRING_TRIM_TAIL" { count(); yylval.ival = STRING_TRIM_TAIL; return(INTEGER_CONSTANT); } @@ -615,6 +621,7 @@ extern "C" { int yyerror(const char *fmt, ...); } "CLICK_ACTION_OPEN" { count(); yylval.ival = CLICK_ACTION_OPEN; return(INTEGER_CONSTANT); } "CLICK_ACTION_PLAY" { count(); yylval.ival = CLICK_ACTION_PLAY; return(INTEGER_CONSTANT); } "CLICK_ACTION_OPEN_MEDIA" { count(); yylval.ival = CLICK_ACTION_OPEN_MEDIA; return(INTEGER_CONSTANT); } +"CLICK_ACTION_ZOOM" { count(); yylval.ival = CLICK_ACTION_ZOOM; return(INTEGER_CONSTANT); } "TEXTURE_BLANK" { yylval.sval = new char[UUID_STR_LENGTH]; strcpy(yylval.sval, "5748decc-f629-461c-9a36-a35a221fe21f"); return(STRING_CONSTANT); } "TEXTURE_DEFAULT" { yylval.sval = new char[UUID_STR_LENGTH]; strcpy(yylval.sval, "89556747-24cb-43ed-920b-47caed15465f"); return(STRING_CONSTANT); } @@ -626,6 +633,45 @@ extern "C" { int yyerror(const char *fmt, ...); } "TOUCH_INVALID_VECTOR" { count(); return(TOUCH_INVALID_VECTOR); } "TOUCH_INVALID_TEXCOORD" { count(); return(TOUCH_INVALID_TEXCOORD); } +"PRIM_MEDIA_ALT_IMAGE_ENABLE" { count(); yylval.ival = LLMediaEntry::ALT_IMAGE_ENABLE_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_CONTROLS" { count(); yylval.ival = LLMediaEntry::CONTROLS_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_CURRENT_URL" { count(); yylval.ival = LLMediaEntry::CURRENT_URL_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_HOME_URL" { count(); yylval.ival = LLMediaEntry::HOME_URL_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_AUTO_LOOP" { count(); yylval.ival = LLMediaEntry::AUTO_LOOP_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_AUTO_PLAY" { count(); yylval.ival = LLMediaEntry::AUTO_PLAY_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_AUTO_SCALE" { count(); yylval.ival = LLMediaEntry::AUTO_SCALE_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_AUTO_ZOOM" { count(); yylval.ival = LLMediaEntry::AUTO_ZOOM_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_FIRST_CLICK_INTERACT" { count(); yylval.ival = LLMediaEntry::FIRST_CLICK_INTERACT_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_WIDTH_PIXELS" { count(); yylval.ival = LLMediaEntry::WIDTH_PIXELS_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_HEIGHT_PIXELS" { count(); yylval.ival = LLMediaEntry::HEIGHT_PIXELS_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_WHITELIST_ENABLE" { count(); yylval.ival = LLMediaEntry::WHITELIST_ENABLE_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_WHITELIST" { count(); yylval.ival = LLMediaEntry::WHITELIST_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_PERMS_INTERACT" { count(); yylval.ival = LLMediaEntry::PERMS_INTERACT_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_PERMS_CONTROL" { count(); yylval.ival = LLMediaEntry::PERMS_CONTROL_ID; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_PARAM_MAX" { count(); yylval.ival = LLMediaEntry::PARAM_MAX_ID; return(INTEGER_CONSTANT); } + +"PRIM_MEDIA_CONTROLS_STANDARD" { count(); yylval.ival = LLMediaEntry::STANDARD; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_CONTROLS_MINI" { count(); yylval.ival = LLMediaEntry::MINI; return(INTEGER_CONSTANT); } + +"PRIM_MEDIA_PERM_NONE" { count(); yylval.ival = LLMediaEntry::PERM_NONE; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_PERM_OWNER" { count(); yylval.ival = LLMediaEntry::PERM_OWNER; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_PERM_GROUP" { count(); yylval.ival = LLMediaEntry::PERM_GROUP; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_PERM_ANYONE" { count(); yylval.ival = LLMediaEntry::PERM_ANYONE; return(INTEGER_CONSTANT); } + +"PRIM_MEDIA_MAX_URL_LENGTH" { count(); yylval.ival = LLMediaEntry::MAX_URL_LENGTH; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_MAX_WHITELIST_SIZE" { count(); yylval.ival = LLMediaEntry::MAX_WHITELIST_SIZE; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_MAX_WHITELIST_COUNT" { count(); yylval.ival = LLMediaEntry::MAX_WHITELIST_COUNT; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_MAX_WIDTH_PIXELS" { count(); yylval.ival = LLMediaEntry::MAX_WIDTH_PIXELS; return(INTEGER_CONSTANT); } +"PRIM_MEDIA_MAX_HEIGHT_PIXELS" { count(); yylval.ival = LLMediaEntry::MAX_HEIGHT_PIXELS; return(INTEGER_CONSTANT); } + +"STATUS_OK" { count(); yylval.ival = LSL_STATUS_OK; return(INTEGER_CONSTANT); } +"STATUS_MALFORMED_PARAMS" { count(); yylval.ival = LSL_STATUS_MALFORMED_PARAMS; return(INTEGER_CONSTANT); } +"STATUS_TYPE_MISMATCH" { count(); yylval.ival = LSL_STATUS_TYPE_MISMATCH; return(INTEGER_CONSTANT); } +"STATUS_BOUNDS_ERROR" { count(); yylval.ival = LSL_STATUS_BOUNDS_ERROR; return(INTEGER_CONSTANT); } +"STATUS_NOT_FOUND" { count(); yylval.ival = LSL_STATUS_NOT_FOUND; return(INTEGER_CONSTANT); } +"STATUS_NOT_SUPPORTED" { count(); yylval.ival = LSL_STATUS_NOT_SUPPORTED; return(INTEGER_CONSTANT); } +"STATUS_INTERNAL_ERROR" { count(); yylval.ival = LSL_STATUS_INTERNAL_ERROR; return(INTEGER_CONSTANT); } +"STATUS_WHITELIST_FAILED" { count(); yylval.ival = LSL_STATUS_WHITELIST_FAILED; return(INTEGER_CONSTANT); } {L}({L}|{N})* { count(); yylval.sval = new char[strlen(yytext) + 1]; strcpy(yylval.sval, yytext); return(IDENTIFIER); } diff --git a/indra/lscript/lscript_compile/indra.y b/indra/lscript/lscript_compile/indra.y index 8834ce9b9..e4b10ffdd 100644 --- a/indra/lscript/lscript_compile/indra.y +++ b/indra/lscript/lscript_compile/indra.y @@ -1,13 +1,4 @@ %{ -// We maintain a pre-generated parser source file to simplify user builds. -// Before committing changes to this file, manually run -// -// bison -d -o indra_generated.y.cpp indra.y -// -// to update the pre-generated parser. Note that some versions of -// bison use a different default file name for the parser token -// header. Make sure the file is called 'indra_generated.y.hpp'. -// Then commit all files simultaneously. #include "linden_common.h" #include "lscript_tree.h" diff --git a/indra/lscript/lscript_execute/lscript_readlso.cpp b/indra/lscript/lscript_execute/lscript_readlso.cpp index 2948ebca6..a5dbd6221 100644 --- a/indra/lscript/lscript_execute/lscript_readlso.cpp +++ b/indra/lscript/lscript_execute/lscript_readlso.cpp @@ -120,7 +120,7 @@ void LLScriptLSOParse::printRegisters(LLFILE *fp) else if (gMajorVersion == LSL2_MAJOR_VERSION_TWO) { U64 data = get_register_u64(mRawData, (LSCRIPTRegisters)i); - fprintf(fp, "%s: 0x%X%X\n", gLSCRIPTRegisterNames[i], (U32)(data>>32), (U32)(data && 0xFFFFFFFF)); + fprintf(fp, "%s: 0x%X%X\n", gLSCRIPTRegisterNames[i], (U32)(data>>32), (U32)(data & 0xFFFFFFFF)); } } fprintf(fp, "=============================\n\n"); diff --git a/indra/lscript/lscript_library/lscript_library.cpp b/indra/lscript/lscript_library/lscript_library.cpp index c78a72cdb..ffbb91340 100644 --- a/indra/lscript/lscript_library/lscript_library.cpp +++ b/indra/lscript/lscript_library/lscript_library.cpp @@ -1,11 +1,11 @@ -/** +/** * @file lscript_library.cpp * @brief external library interface * * $LicenseInfo:firstyear=2002&license=viewergpl$ - * + * * Copyright (c) 2002-2009, Linden Research, Inc. - * + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 @@ -13,17 +13,17 @@ * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or * online at * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. @@ -37,7 +37,7 @@ // ## ## ## ## ## ######## ## ## ## ## ## ## ## ## #### ## ## // ## ## ## ######### ## ## ## #### ## ## #### ## ## // ## ## ## ## ## ## ## ## ### ## ## ### ## ## #### #### -// ### ### ## ## ## ## ## ## #### ## ## ###### #### #### +// ### ### ## ## ## ## ## ## #### ## ## ###### #### #### // // When adding functions, they <b>MUST</b> be appended to the end of // the init() method. The init() associates the name with a number, @@ -327,7 +327,7 @@ void LLScriptLibrary::init() addFunction(10.f, 0.2f, dummy_func, "llSetRemoteScriptAccessPin", NULL, "i"); addFunction(10.f, 3.f, dummy_func, "llRemoteLoadScriptPin", NULL, "ksiii"); - + addFunction(10.f, 1.f, dummy_func, "llOpenRemoteDataChannel", NULL, NULL); addFunction(10.f, 3.f, dummy_func, "llSendRemoteData", "k", "ksis"); addFunction(10.f, 3.f, dummy_func, "llRemoteDataReply", NULL, "kksi"); @@ -343,7 +343,7 @@ void LLScriptLibrary::init() addFunction(10.f, 0.f, dummy_func, "llLog", "f", "f"); addFunction(10.f, 0.f, dummy_func, "llGetAnimationList", "l", "k"); addFunction(10.f, 2.f, dummy_func, "llSetParcelMusicURL", NULL, "s"); - + addFunction(10.f, 0.f, dummy_func, "llGetRootPosition", "v", NULL); addFunction(10.f, 0.f, dummy_func, "llGetRootRotation", "q", NULL); @@ -362,7 +362,7 @@ void LLScriptLibrary::init() addFunction(10.f, 0.0f, dummy_func, "llBase64ToInteger", "i", "s"); addFunction(10.f, 0.f, dummy_func, "llGetGMTclock", "f", ""); addFunction(10.f, 10.f, dummy_func, "llGetSimulatorHostname", "s", ""); - + addFunction(10.f, 0.2f, dummy_func, "llSetLocalRot", NULL, "q"); addFunction(10.f, 0.f, dummy_func, "llParseStringKeepNulls", "l", "sll"); @@ -385,12 +385,12 @@ void LLScriptLibrary::init() addFunction(10.f, 2.f, dummy_func, "llParcelMediaQuery", "l", "l"); addFunction(10.f, 1.f, dummy_func, "llModPow", "i", "iii"); - + addFunction(10.f, 0.f, dummy_func, "llGetInventoryType", "i", "s"); addFunction(10.f, 0.f, dummy_func, "llSetPayPrice", NULL, "il"); addFunction(10.f, 0.f, dummy_func, "llGetCameraPos", "v", ""); addFunction(10.f, 0.f, dummy_func, "llGetCameraRot", "q", ""); - + addFunction(10.f, 20.f, dummy_func, "llSetPrimURL", NULL, "s"); addFunction(10.f, 20.f, dummy_func, "llRefreshPrimURL", NULL, ""); addFunction(10.f, 0.f, dummy_func, "llEscapeURL", "s", "s"); @@ -403,7 +403,7 @@ void LLScriptLibrary::init() addFunction(10.f, 0.f, dummy_func, "llSetCameraParams", NULL, "l"); addFunction(10.f, 0.f, dummy_func, "llClearCameraParams", NULL, NULL); - + addFunction(10.f, 0.f, dummy_func, "llListStatistics", "f", "il"); addFunction(10.f, 0.f, dummy_func, "llGetUnixTime", "i", NULL); addFunction(10.f, 0.f, dummy_func, "llGetParcelFlags", "i", "v"); @@ -425,7 +425,7 @@ void LLScriptLibrary::init() addFunction(10.f, 0.2f, dummy_func, "llSetLinkPrimitiveParams", NULL, "il"); addFunction(10.f, 0.2f, dummy_func, "llSetLinkTexture", NULL, "isi"); - + addFunction(10.f, 0.f, dummy_func, "llStringTrim", "s", "si"); addFunction(10.f, 0.f, dummy_func, "llRegionSay", NULL, "is"); addFunction(10.f, 0.f, dummy_func, "llGetObjectDetails", "l", "kl"); @@ -470,11 +470,135 @@ void LLScriptLibrary::init() addFunction(10.f, 0.f, dummy_func, "llGetEnv", "s", "s"); addFunction(10.f, 0.f, dummy_func, "llRegionSayTo", NULL, "kis"); + // Adding missing (more recent) LSL functions. + + addFunction(10.f, 0.f, dummy_func, "llCastRay", "l", "vvl"); + addFunction(10.f, 0.f, dummy_func, "llGetSPMaxMemory", "i", NULL); + addFunction(10.f, 0.f, dummy_func, "llGetUsedMemory", "i", NULL); + addFunction(10.f, 0.f, dummy_func, "llGodLikeRezObject", NULL, "kv"); + addFunction(10.f, 0.f, dummy_func, "llScriptProfiler", NULL, "i"); + addFunction(10.f, 0.f, dummy_func, "llSetInventoryPermMask", NULL, "sii"); + addFunction(10.f, 0.f, dummy_func, "llSetObjectPermMask", NULL, "ii"); + // energy, sleep, dummy_func, name, return type, parameters, help text, gods-only // IF YOU ADD NEW SCRIPT CALLS, YOU MUST PUT THEM AT THE END OF THIS LIST. // Otherwise the bytecode numbers for each call will be wrong, and all // existing scripts will crash. + + // REGARDING OSSL FUNCTIONS + // These additions should be posted underneath the llFunctions + // These functions pertain to OpenSimulator and are in no part applicable to SecondLife by Linden Labs + // The Current State of these functions are in flux and development is ongoing. Not all the functions are presently + // documented and therefore the description may be incomplete and require further attention. + // OpenSimulator is written in C# and not CPP therefore some values for example "double = float" etc. are different. + + // OSSL corrections and syntax additions added + set in same order as found in OSSL_stub.cs of OpenSim Source (Updated PM October-21-2010 + // based on OpenSimulator Ver. 0.7.x DEV/Master Git # a7acb650d400a280a7b9edabd304376dff9c81af - a7acb65-r/14142 + // Updates by WhiteStar Magic + + addFunction(10.f, 0.f, dummy_func, "osSetRegionWaterHeight", NULL, "f"); + addFunction(10.f, 0.f, dummy_func, "osSetRegionSunSettings", NULL, "iif"); + addFunction(10.f, 0.f, dummy_func, "osSetEstateSunSettings", NULL, "if"); + addFunction(10.f, 0.f, dummy_func, "osGetCurrentSunHour", "f", NULL); + addFunction(10.f, 0.f, dummy_func, "osSunGetParam","f", "s"); // Deprecated. Use osGetSunParam instead + addFunction(10.f, 0.f, dummy_func, "osSunSetParam", "sf", NULL); // Deprecated. Use osSetSunParam instead + addFunction(10.f, 0.f, dummy_func, "osWindActiveModelPluginName", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osParcelJoin", NULL, "vv"); + addFunction(10.f, 0.f, dummy_func, "osParcelSubdivide", NULL, "vv"); + addFunction(10.f, 0.f, dummy_func, "osParcelSetDetails", NULL, "vv"); // Deprecated. Use osSetParcelDetails instead. + // addFunction(10.f, 0.f, dummy_func, "osWindParamSet", NULL, "ssf"); // This function was renamed before it was implemented. Leaving this in for now. + // addFunction(10.f, 0.f, dummy_func, "osWindParamGet", "f", "ss"); // This function was renamed before it was implemented. Leaving this in for now. + addFunction(10.f, 0.f, dummy_func, "osList2Double", "f", "li"); + addFunction(10.f, 0.f, dummy_func, "osSetDynamicTextureURL", NULL, "ksssi"); + addFunction(10.f, 0.f, dummy_func, "osSetDynamicTextureData", NULL, "ksssi"); + addFunction(10.f, 0.f, dummy_func, "osSetDynamicTextureURLBlend", NULL, "ksssii"); + addFunction(10.f, 0.f, dummy_func, "osSetDynamicTextureDataBlend", NULL, "ksssii"); + addFunction(10.f, 0.f, dummy_func, "osSetDynamicTextureURLBlendFace", NULL, "ksssfiiii"); + addFunction(10.f, 0.f, dummy_func, "osSetDynamicTextureDataBlendFace", NULL, "ksssfiiii"); + addFunction(10.f, 0.f, dummy_func, "osTerrainGetHeight", "f", "ii"); // Deprecated. Use osGetTerrainHeight instead + addFunction(10.f, 0.f, dummy_func, "osTerrainSetHeight", NULL, "iif"); // Deprecated. Use osSetTerrainHeight instead + addFunction(10.f, 0.f, dummy_func, "osTerrainFlush", NULL, NULL); + addFunction(10.f, 0.f, dummy_func, "osRegionRestart", "i", "f"); + addFunction(10.f, 0.f, dummy_func, "osRegionNotice",NULL, "s"); + addFunction(10.f, 0.f, dummy_func, "osConsoleCommand", NULL, "s"); + addFunction(10.f, 0.f, dummy_func, "osSetParcelMediaURL", NULL, "s"); + addFunction(10.f, 0.f, dummy_func, "osSetParcelSIPAddress", NULL, "s"); + addFunction(10.f, 0.f, dummy_func, "osSetPrimFloatOnWater", NULL, "i"); + addFunction(10.f, 0.f, dummy_func, "osTeleportAgent", NULL, "ksvv"); + addFunction(10.f, 0.f, dummy_func, "osGetAgentIP", "s", "k"); + addFunction(10.f, 0.f, dummy_func, "osGetAgents", "l", NULL); + addFunction(10.f, 0.f, dummy_func, "osAvatarPlayAnimation", NULL, "ks"); + addFunction(10.f, 0.f, dummy_func, "osAvatarStopAnimation", NULL, "ks"); + addFunction(10.f, 0.f, dummy_func, "osMovePen", NULL, "sii"); + addFunction(10.f, 0.f, dummy_func, "osDrawLine", NULL, "siiii"); + addFunction(10.f, 0.f, dummy_func, "osDrawText", NULL, "ss"); + addFunction(10.f, 0.f, dummy_func, "osDrawEllipse", NULL, "sii"); + addFunction(10.f, 0.f, dummy_func, "osDrawRectangle", NULL, "sii"); + addFunction(10.f, 0.f, dummy_func, "osDrawFilledRectangle", NULL, "sii"); + addFunction(10.f, 0.f, dummy_func, "osDrawPolygon", "s", "sll"); + addFunction(10.f, 0.f, dummy_func, "osDrawFilledPolygon", "s", "sll"); + addFunction(10.f, 0.f, dummy_func, "osSetFontSize", NULL, "si"); + addFunction(10.f, 0.f, dummy_func, "osSetFontName", NULL, "ss"); + addFunction(10.f, 0.f, dummy_func, "osSetPenSize", NULL, "si"); + addFunction(10.f, 0.f, dummy_func, "osSetPenCap", NULL, "sss"); + addFunction(10.f, 0.f, dummy_func, "osSetPenColour", NULL, "ss"); // Deprecated. Use osSetPenColor instead + addFunction(10.f, 0.f, dummy_func, "osDrawImage", NULL, "siis"); + addFunction(10.f, 0.f, dummy_func, "osGetDrawStringSize", "v", "sssi"); + addFunction(10.f, 0.f, dummy_func, "osSetStateEvents", NULL, "i"); + addFunction(10.f, 0.f, dummy_func, "osGetScriptEngineName", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osGetSimulatorVersion", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osParseJSON", "s", "s"); + addFunction(10.f, 0.f, dummy_func, "osMessageObject", NULL, "ks"); + addFunction(10.f, 0.f, dummy_func, "osMakeNotecard", NULL, "sl"); + addFunction(10.f, 0.f, dummy_func, "osGetNotecardLine", "s", "si"); + addFunction(10.f, 0.f, dummy_func, "osGetNotecard", "s", "s"); + addFunction(10.f, 0.f, dummy_func, "osGetNumberOfNotecardLines", "i", "s"); + addFunction(10.f, 0.f, dummy_func, "osAvatarName2Key", "k", "ss"); + addFunction(10.f, 0.f, dummy_func, "osKey2Name", "s", "k"); + addFunction(10.f, 0.f, dummy_func, "osGetGridNick", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osGetGridName", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osGetGridLoginURI", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osFormatString", "s", "sl"); + addFunction(10.f, 0.f, dummy_func, "osMatchString", "l", "ssi"); + addFunction(10.f, 0.f, dummy_func, "osLoadedCreationDate", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osLoadedCreationTime", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osLoadedCreationID", "s", NULL); + addFunction(10.f, 0.f, dummy_func, "osGetLinkPrimitiveParams", "l", "il"); + addFunction(10.f, 0.f, dummy_func, "osNpcCreate", "k", "ssvk"); + addFunction(10.f, 0.f, dummy_func, "osNpcMoveTo", NULL, "kv"); + addFunction(10.f, 0.f, dummy_func, "osNpcSay", NULL, "ks"); + addFunction(10.f, 0.f, dummy_func, "osNpcRemove", NULL, "k"); + addFunction(10.f, 0.f, dummy_func, "osGetMapTexture", "k", NULL); + addFunction(10.f, 0.f, dummy_func, "osGetRegionMapTexture", "k", "s"); + addFunction(10.f, 0.f, dummy_func, "osGetRegionStats", "l", NULL); + addFunction(10.f, 0.f, dummy_func, "osGetSimulatorMemory", "i", NULL); + addFunction(10.f, 0.f, dummy_func, "osKickAvatar", NULL, "sss"); + addFunction(10.f, 0.f, dummy_func, "osSetSpeed", NULL, "kf"); + addFunction(10.f, 0.f, dummy_func, "osCauseDamage", NULL, "kf"); + addFunction(10.f, 0.f, dummy_func, "osCauseHealing", NULL, "kf"); + addFunction(10.f, 0.f, dummy_func, "osGetPrimitiveParams", "l", "kl"); + addFunction(10.f, 0.f, dummy_func, "osSetPrimitiveParams", NULL, "kl"); + addFunction(10.f, 0.f, dummy_func, "osSetProjectionParams", NULL, "kikfff"); + addFunction(10.f, 0.f, dummy_func, "osUnixTimeToTimestamp", "s", "i"); + addFunction(10.f, 0.f, dummy_func, "osSetPenColor", NULL, "ss"); + addFunction(10.f, 0.f, dummy_func, "osGetSunParam","f", "s"); + addFunction(10.f, 0.f, dummy_func, "osSetSunParam", "sf", NULL); + addFunction(10.f, 0.f, dummy_func, "osSetParcelDetails", NULL, "vl"); + addFunction(10.f, 0.f, dummy_func, "osGetTerrainHeight", "f", "ii"); + addFunction(10.f, 0.f, dummy_func, "osSetTerrainHeight", NULL, "iif"); + addFunction(10.f, 0.f, dummy_func, "osGetAvatarList", "l", NULL); + addFunction(10.f, 0.f, dummy_func, "osTeleportOwner", NULL, "svv"); + + // LightShare functions + addFunction(10.f, 0.f, dummy_func, "cmSetWindlightScene", "i", "l"); + addFunction(10.f, 0.f, dummy_func, "cmSetWindlightSceneTargeted", "i", "lk"); + addFunction(10.f, 0.f, dummy_func, "cmGetWindlightScene", "l", "l"); + // LightShare functions - alternate versions + // don't ask me why they renamed 'em, but we need to include both versions -- MC + addFunction(10.f, 0.f, dummy_func, "lsSetWindlightScene", "i", "l"); + addFunction(10.f, 0.f, dummy_func, "lsSetWindlightSceneTargeted", "i", "lk"); + addFunction(10.f, 0.f, dummy_func, "lsGetWindlightScene", "l", "l"); } LLScriptLibraryFunction::LLScriptLibraryFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &), const char *name, const char *ret_type, const char *args, BOOL god_only) @@ -494,7 +618,7 @@ void LLScriptLibrary::addFunction(F32 eu, F32 st, void (*exec_func)(LLScriptLibD void LLScriptLibrary::assignExec(const char *name, void (*exec_func)(LLScriptLibData *, LLScriptLibData *, const LLUUID &)) { - for (std::vector<LLScriptLibraryFunction>::iterator i = mFunctions.begin(); + for (std::vector<LLScriptLibraryFunction>::iterator i = mFunctions.begin(); i != mFunctions.end(); ++i) { if (!strcmp(name, i->mName)) @@ -503,7 +627,7 @@ void LLScriptLibrary::assignExec(const char *name, void (*exec_func)(LLScriptLib return; } } - + llerrs << "Unknown LSL function in assignExec: " << name << llendl; } diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 21f321452..f274020ef 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -100,12 +100,14 @@ set(viewer_SOURCE_FILES jcfloaterareasearch.cpp chatbar_as_cmdline.cpp qtoolalign.cpp + llaccountingcostmanager.cpp llagent.cpp llagentaccess.cpp llagentcamera.cpp llagentdata.cpp llagentlanguage.cpp llagentpilot.cpp + llagentui.cpp llagentwearables.cpp llanimstatelabels.cpp llappviewer.cpp @@ -114,7 +116,6 @@ set(viewer_SOURCE_FILES llassetuploadqueue.cpp llattachmentsmgr.cpp llaudiosourcevo.cpp - llbbox.cpp llbox.cpp llbuildnewviewsscheduler.cpp llcallbacklist.cpp @@ -293,6 +294,7 @@ set(viewer_SOURCE_FILES llmediaremotectrl.cpp llmemoryview.cpp llmenucommands.cpp + llmeshrepository.cpp llmimetypes.cpp llmorphview.cpp llmoveview.cpp @@ -577,12 +579,14 @@ set(viewer_HEADER_FILES lgghunspell_wrapper.h chatbar_as_cmdline.h qtoolalign.h + llaccountingcostmanager.h llagent.h llagentaccess.h llagentcamera.h llagentdata.h llagentlanguage.h llagentpilot.h + llagentui.h llagentwearables.h llanimstatelabels.h llappearance.h @@ -592,7 +596,6 @@ set(viewer_HEADER_FILES llassetuploadqueue.h llattachmentsmgr.h llaudiosourcevo.h - llbbox.h llbox.h llbuildnewviewsscheduler.h llcallbacklist.h @@ -771,6 +774,7 @@ set(viewer_HEADER_FILES llmediaremotectrl.h llmemoryview.h llmenucommands.h + llmeshrepository.h llmimetypes.h llmorphview.h llmoveview.h @@ -1226,6 +1230,7 @@ set_source_files_properties(${viewer_XUI_FILES} list(APPEND viewer_SOURCE_FILES ${viewer_XUI_FILES}) set(viewer_APPSETTINGS_FILES + viewer_manifest.py app_settings/anim.ini app_settings/cmd_line.xml app_settings/grass.xml @@ -1607,6 +1612,13 @@ endif (LL_TESTS) if (WINDOWS) get_target_property(BUILT_LLCOMMON llcommon LOCATION) + + set_target_properties(llcommon + PROPERTIES + LINK_FLAGS "/debug /NODEFAULTLIB:LIBCMT" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMT;LIBCMTD;MSVCRT\"" + ) + add_custom_command( TARGET ${VIEWER_BINARY_NAME} POST_BUILD COMMAND ${CMAKE_COMMAND} diff --git a/indra/newview/app_settings/dictionaries/en_sl.dic b/indra/newview/app_settings/dictionaries/en_sl.dic index 09076f788..0f25bd233 100644 --- a/indra/newview/app_settings/dictionaries/en_sl.dic +++ b/indra/newview/app_settings/dictionaries/en_sl.dic @@ -1182,6 +1182,10 @@ OBJECT_VELOCITY OBJECT_OWNER OBJECT_GROUP OBJECT_CREATOR +OBJECT_RUNNING_SCRIPT_COUNT +OBJECT_TOTAL_SCRIPT_COUNT +OBJECT_SCRIPT_MEMORY +OBJECT_SCRIPT_TIME VEHICLE_TYPE_NONE VEHICLE_TYPE_SLED VEHICLE_TYPE_CAR @@ -1478,6 +1482,8 @@ PARCEL_DETAILS_DESC PARCEL_DETAILS_OWNER PARCEL_DETAILS_GROUP PARCEL_DETAILS_AREA +PARCEL_DETAILS_ID +PARCEL_DETAILS_SEE_AVATARS STRING_TRIM_HEAD STRING_TRIM_TAIL STRING_TRIM diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index 75c1740aa..455dc9e88 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -162,6 +162,10 @@ OBJECT_VELOCITY Used with llGetObjectDetails to get an object's velocity. OBJECT_OWNER Used with llGetObjectDetails to get an object's owner's key. Will be NULL_KEY if group owned. OBJECT_GROUP Used with llGetObjectDetails to get an object's group's key. OBJECT_CREATOR Used with llGetObjectDetails to get an object's creator's key. +OBJECT_RUNNING_SCRIPT_COUNT Used with llGetObjectDetails to get an object's velocity. +OBJECT_TOTAL_SCRIPT_COUNT Used with llGetObjectDetails to get an object's owner's key. Will be NULL_KEY if group owned. +OBJECT_SCRIPT_MEMORY Used with llGetObjectDetails to get an object's group's key. +OBJECT_SCRIPT_TIME Used with llGetObjectDetails to get an object's creator's key. # some vehicle params VEHICLE_TYPE_NONE @@ -502,6 +506,8 @@ PARCEL_DETAILS_DESC Used with llGetParcelDetails to get the parcel description. PARCEL_DETAILS_OWNER Used with llGetParcelDetails to get the parcel owner id. PARCEL_DETAILS_GROUP Used with llGetParcelDetails to get the parcel group id. PARCEL_DETAILS_AREA Used with llGetParcelDetails to get the parcel area in square meters. +PARCEL_DETAILS_ID Used with llGetParcelDetails to get the parcel id. +PARCEL_DETAILS_SEE_AVATARS Used with llGetParcelDetails to get the avatars visibility setting. STRING_TRIM_HEAD Used with llStringTrim to trim leading spaces from a string. STRING_TRIM_TAIL Used with llStringTrim to trim trailing spaces from a string. diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 43b63e135..ae3059556 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9,10 +9,56 @@ <string>settings_rlv.xml</string> </array> + <key>CCSAllowNameplateOverride</key> + <map> + <key>Comment</key> + <string>Allow CCS HUD to override nameplates.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> + + <key>HTTPRequestRate</key> + <map> + <key>Comment</key> + <string>Number of HTTP texture requests fired per second.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>30</integer> + </map> + <key>HTTPMaxRequests</key> + <map> + <key>Comment</key> + <string>Maximum number of simultaneous HTTP requests in progress.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>32</integer> + </map> + <key>HTTPMinRequests</key> + <map> + <key>Comment</key> + <string>Attempt to maintain at least this many HTTP requests in progress by ignoring bandwidth</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>2</integer> + </map> + <key>TeleportHistoryMaxEntries</key> <map> <key>Comment</key> - <string>Maximum number of entries to allow in teleport history list.</string> + <string>Maximum number of entries to allow in teleport history list.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -20,7 +66,7 @@ <key>Value</key> <integer>100</integer> </map> - + <key>AllowLargeSounds</key> <map> <key>Comment</key> @@ -429,7 +475,42 @@ <key>Value</key> <integer>0</integer> </map> - <key>ResetFocusOnSelfClick</key> + <key>ShyotlRenderVBOStrideMode</key> + <map> + <key>Comment</key> + <string>0 = Standard behavior +1 = Force strided VBOs +2 = Force unstrided(dense) VBOs</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShyotlUseLegacyRenderPath</key> + <map> + <key>Comment</key> + <string>Use deprecated pre-3.x OpenGL api calls.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ShyotlUseLegacyTextureBatching</key> + <map> + <key>Comment</key> + <string>Disable usage of extra samplers in shaders. Decreases batch sizes, however also reduces branching in shaders drastcially.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>ResetFocusOnSelfClick</key> <map> <key>Comment</key> <string>Setting this to TRUE resets your camera when you left-click your avatar</string> @@ -440,7 +521,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>MoyFastMiniMap</key> <map> <key>Comment</key> @@ -3712,10 +3792,21 @@ <key>Value</key> <integer>0</integer> </map> + <key>CurlUseMultipleThreads</key> + <map> + <key>Comment</key> + <string>Use background threads for executing curl_multi_perform (requires restart)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>Cursor3D</key> <map> <key>Comment</key> - <string>Tread Joystick values as absolute positions (not deltas).</string> + <string>Treat Joystick values as absolute positions (not deltas).</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -3789,10 +3880,21 @@ <key>Value</key> <integer>0</integer> </map> + <key>DebugShowMemory</key> + <map> + <key>Comment</key> + <string>Show Total Allocated Memory</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>DebugShowRenderInfo</key> <map> <key>Comment</key> - <string>Show depth buffer contents</string> + <string>Show stats about current scene</string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -7131,7 +7233,40 @@ <string>F32</string> <key>Value</key> <real>0.25</real> - </map> + </map> + <key>Jpeg2000AdvancedCompression</key> + <map> + <key>Comment</key> + <string>Use advanced Jpeg2000 compression options (precincts, blocks, ordering, markers)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>Jpeg2000PrecinctsSize</key> + <map> + <key>Comment</key> + <string>Size of image precincts. Assumed square and same for all levels. Must be power of 2.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>256</integer> + </map> + <key>Jpeg2000BlocksSize</key> + <map> + <key>Comment</key> + <string>Size of encoding blocks. Assumed square and same for all levels. Must be power of 2. Max 64, Min 4.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <integer>64</integer> + </map> <key>KeepAspectForSnapshot</key> <map> <key>Comment</key> @@ -7511,7 +7646,7 @@ <key>Value</key> <integer>0</integer> </map> - <key>LogMessages</key> + <key>LogMessages</key> <map> <key>Comment</key> <string>Log network traffic</string> @@ -7522,6 +7657,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>LogTextureNetworkTraffic</key> + <map> + <key>Comment</key> + <string>Log network traffic for textures</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>LoginAsGod</key> <map> <key>Comment</key> @@ -7874,6 +8020,51 @@ <key>Value</key> <integer>410</integer> </map> + <key>MeshEnabled</key> + <map> + <key>Comment</key> + <string>Expose UI for mesh functionality (may require restart to take effect).</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <real>1</real> + </map> + <key>MeshImportUseSLM</key> + <map> + <key>Comment</key> + <string>Use cached copy of last upload for a dae if available instead of loading dae file from scratch.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <real>0</real> + </map> + <key>MeshUploadLogXML</key> + <map> + <key>Comment</key> + <string>Verbose XML logging on mesh upload</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <real>0</real> + </map> + <key>MeshUploadFakeErrors</key> + <map> + <key>Comment</key> + <string>Force upload errors (for testing)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>S32</string> + <key>Value</key> + <real>0</real> + </map> + <key>MigrateCacheDirectory</key> <map> <key>Comment</key> @@ -9419,17 +9610,28 @@ <key>Value</key> <integer>0</integer> </map> - <key>RenderDebugPipeline</key> + <key>RenderDebugPipeline</key> <map> <key>Comment</key> <string>Enable strict pipeline debugging.</string> <key>Persist</key> <integer>1</integer> <key>Type</key> - <string>Boolean</string> + <string>Boolean</string> <key>Value</key> <integer>0</integer> </map> + <key>RenderMaxTextureIndex</key> + <map> + <key>Comment</key> + <string>Maximum texture index to use for indexed texture rendering.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>6</integer> + </map> <key>RenderDebugTextureBind</key> <map> <key>Comment</key> @@ -9732,6 +9934,18 @@ <key>Value</key> <real>0</real> </map> + + <key>RenderDepthOfField</key> + <map> + <key>Comment</key> + <string>Whether to use depth of field effect when lighting and shadows are enabled</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>RenderSpotLightsInNondeferred</key> <map> @@ -9754,7 +9968,7 @@ <key>Type</key> <string>F32</string> <key>Value</key> - <real>0.0</real> + <real>-0.001</real> </map> <key>RenderSpotShadowOffset</key> <map> @@ -11026,6 +11240,62 @@ <key>Value</key> <real>1.0</real> </map> + <key>MeshTriangleBudget</key> + <map> + <key>Comment</key> + <string>Target visible triangle budget to use when estimating streaming cost.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>250000</real> + </map> + <key>MeshMetaDataDiscount</key> + <map> + <key>Comment</key> + <string>Number of bytes to deduct for metadata when determining streaming cost.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>384</real> + </map> + <key>MeshMinimumByteSize</key> + <map> + <key>Comment</key> + <string>Minimum number of bytes per LoD block when determining streaming cost.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>16</real> + </map> + <key>MeshBytesPerTriangle</key> + <map> + <key>Comment</key> + <string>Approximation of bytes per triangle to use for determining mesh streaming cost.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <real>16</real> + </map> + + <key>MeshMaxConcurrentRequests</key> + <map> + <key>Comment</key> + <string>Number of threads to use for loading meshes.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>32</integer> + </map> <key>RunBtnState</key> <map> <key>Comment</key> @@ -12248,6 +12518,17 @@ <key>Value</key> <integer>0</integer> </map> + <key>SnapshotBtnState</key> + <map> + <key>Comment</key> + <string/> + <key>Persist</key> + <integer>0</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> <key>SnapshotFormat</key> <map> <key>Comment</key> @@ -12506,6 +12787,28 @@ <key>Value</key> <integer>0</integer> </map> + <key>TextureDisable</key> + <map> + <key>Comment</key> + <string>If TRUE, do not load textures for in-world content</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>TextureDiscardLevel</key> + <map> + <key>Comment</key> + <string>Specify texture resolution (0 = highest, 5 = lowest)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>U32</string> + <key>Value</key> + <integer>0</integer> + </map> <key>TextureLoadFullRes</key> <map> <key>Comment</key> @@ -13181,6 +13484,28 @@ <key>Value</key> <integer>1</integer> </map> + <key>InterpolationTime</key> + <map> + <key>Comment</key> + <string>How long to extrapolate object motion after last packet received</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>3</integer> + </map> + <key>InterpolationPhaseOut</key> + <map> + <key>Comment</key> + <string>Seconds to phase out interpolated motion</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <integer>1</integer> + </map> <key>VerboseLogs</key> <map> <key>Comment</key> @@ -14191,17 +14516,6 @@ <integer>473</integer> </array> </map> - <key>RadarListBtnState</key> - <map> - <key>Comment</key> - <string/> - <key>Persist</key> - <integer>0</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>WindEnabled</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/settings_files.xml b/indra/newview/app_settings/settings_files.xml index ec5574535..ac304f759 100644 --- a/indra/newview/app_settings/settings_files.xml +++ b/indra/newview/app_settings/settings_files.xml @@ -61,7 +61,7 @@ <key>Global</key> <map> <key>Name</key> - <string>settings.xml</string> + <string>settings_singularity.xml</string> <key>NameFromSetting</key> <string>ClientSettingsFile</string> </map> diff --git a/indra/newview/app_settings/settings_per_account.xml b/indra/newview/app_settings/settings_per_account.xml index c740123ab..97ff2cd19 100644 --- a/indra/newview/app_settings/settings_per_account.xml +++ b/indra/newview/app_settings/settings_per_account.xml @@ -365,17 +365,6 @@ <string>This is an autoresponse!</string> </map> </map> - <key>AscentInstantMessageAnnounceIncoming</key> - <map> - <key>Comment</key> - <string>Open a new IM tab when another person begins typing to you and announce that they are doing so.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> <key>MoyMiniMapCustomColor</key> <map> <key>Comment</key> @@ -392,131 +381,6 @@ <real>1.0</real> </array> </map> - <!-- Ascent Account-Specific (If active) --> - <key>AscentFriendColor</key> - <map> - <key>Comment</key> - <string>Color of chat messages from other residents</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Color4</string> - <key>Value</key> - <array> - <real>1.0</real> - <real>1.0</real> - <real>0.0</real> - <real>1.0</real> - </array> - </map> - <key>AscentLindenColor</key> - <map> - <key>Comment</key> - <string>Color of chat messages from other residents</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Color4</string> - <key>Value</key> - <array> - <real>0.0</real> - <real>0.0</real> - <real>1.0</real> - <real>1.0</real> - </array> - </map> - <key>AscentMutedColor</key> - <map> - <key>Comment</key> - <string>Color of chat messages from other residents</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Color4</string> - <key>Value</key> - <array> - <real>0.7</real> - <real>0.7</real> - <real>0.7</real> - <real>1.0</real> - </array> - </map> - <key>AscentEstateOwnerColor</key> - <map> - <key>Comment</key> - <string>Color of chat messages from other residents</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Color4</string> - <key>Value</key> - <array> - <real>1.0</real> - <real>0.6</real> - <real>1.0</real> - <real>1.0</real> - </array> - </map> - <key>AscentUseCustomTag</key> - <map> - <key>Comment</key> - <string>Show a custom local tag.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Boolean</string> - <key>Value</key> - <integer>0</integer> - </map> - <key>AscentCustomTagColor</key> - <map> - <key>Comment</key> - <string>Color of custom local tag.</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>Color4</string> - <key>Value</key> - <array> - <real>0.5</real> - <real>1.0</real> - <real>0.25</real> - <real>1.0</real> - </array> - </map> - <key>AscentCustomTagLabel</key> - <map> - <key>Comment</key> - <string>Label for the custom local tag</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>Custom</string> - </map> - <key>AscentReportClientIndex</key> - <map> - <key>Comment</key> - <string>Show your own tag</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>U32</string> - <key>Value</key> - <integer>1</integer> - </map> - <key>AscentReportClientUUID</key> - <map> - <key>Comment</key> - <string>Broadcasted Client Key</string> - <key>Persist</key> - <integer>1</integer> - <key>Type</key> - <string>String</string> - <key>Value</key> - <string>f25263b7-6167-4f34-a4ef-af65213b2e39</string> - </map> <!-- Ascent Account-Specific (Always) --> <!-- General additions --> <key>rkeastInventoryPreviousCount</key> diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl index 431c7f8e1..8a9c1f64c 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarF.glsl @@ -5,7 +5,6 @@ * $License$ */ -#version 120 void default_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl index 9057560e6..d11fd8d49 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarSkinV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + attribute vec4 weight; //1 diff --git a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl index 7b36d03c3..1f69de175 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/avatarV.glsl @@ -5,7 +5,6 @@ * $License$ */ -#version 120 vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl index cc49fe9f7..601e6cc5d 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballF.glsl @@ -5,7 +5,6 @@ * $License$ */ -#version 120 void default_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl index af9c28a6e..6f497acb7 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/eyeballV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl new file mode 100644 index 000000000..7613e50dc --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/avatar/objectSkinV.glsl @@ -0,0 +1,30 @@ +/** + * @file objectSkinV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +attribute vec4 object_weight; + +uniform mat4 matrixPalette[32]; + +mat4 getObjectSkinnedTransform() +{ + int i; + + vec4 w = fract(object_weight); + vec4 index = floor(object_weight); + + float scale = 1.0/(w.x+w.y+w.z+w.w); + w *= scale; + + mat4 mat = matrixPalette[int(index.x)]*w.x; + mat += matrixPalette[int(index.y)]*w.y; + mat += matrixPalette[int(index.z)]*w.z; + mat += matrixPalette[int(index.w)]*w.w; + + return mat; +} diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl index 0b9943479..0f5d17d7d 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl index 801a8e06d..fcea1baba 100644 --- a/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/avatar/pickAvatarV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl index 22cae7a34..bd07c51ca 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl @@ -1,17 +1,18 @@ /** * @file alphaF.glsl * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable -uniform sampler2D diffuseMap; uniform sampler2DRect depthMap; +vec4 diffuseLookup(vec2 texcoord); + uniform mat4 shadow_matrix[6]; uniform vec4 shadow_clip; uniform vec2 screen_res; @@ -47,7 +48,7 @@ void main() vec4 pos = vec4(vary_position, 1.0); - vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 diff= diffuseLookup(gl_TexCoord[0].xy); vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a); vec4 color = diff * col; diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl new file mode 100644 index 000000000..b0d029dbf --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl @@ -0,0 +1,67 @@ +/** + * @file alphaF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect depthMap; +uniform sampler2D diffuseMap; + + +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform vec2 screen_res; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; +varying vec3 vary_pointlight_col; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + + vec4 pos = vec4(vary_position, 1.0); + + vec4 diff= texture2D(diffuseMap,gl_TexCoord[0].xy); + + vec4 col = vec4(vary_ambient + vary_directional.rgb, gl_Color.a); + vec4 color = diff * col; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + color.rgb += diff.rgb * vary_pointlight_col.rgb; + + gl_FragColor = color; + //gl_FragColor = vec4(1,0,1,1); + //gl_FragColor = vec4(1,0,1,1)*shadow; + +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl new file mode 100644 index 000000000..ac3f7189c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl @@ -0,0 +1,112 @@ +/** + * @file alphaSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +mat4 getObjectSkinnedTransform(); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); + +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec3 vary_position; +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_normal; +varying vec3 vary_fragcoord; +varying vec3 vary_pointlight_col; + +uniform float near_clip; + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + float da = 0.0; + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float dist2 = d*d/(la*la); + da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + } + + return da; +} + +void main() +{ + gl_TexCoord[0] = gl_MultiTexCoord0; + + vec4 pos; + vec3 norm; + + mat4 trans = getObjectSkinnedTransform(); + trans = gl_ModelViewMatrix * trans; + + pos = trans * gl_Vertex; + + norm = gl_Vertex.xyz + gl_Normal.xyz; + norm = normalize(( trans*vec4(norm, 1.0) ).xyz-pos.xyz); + + vec4 frag_pos = gl_ProjectionMatrix * pos; + gl_Position = frag_pos; + + vary_position = pos.xyz; + vary_normal = norm; + + calcAtmospherics(pos.xyz); + + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); + + // Collect normal lights + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a); + + vary_pointlight_col = col.rgb*gl_Color.rgb; + + col.rgb = vec3(0,0,0); + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + + vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip); +} + + diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index d1c678f30..cb6414deb 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); @@ -23,6 +23,7 @@ varying vec3 vary_fragcoord; varying vec3 vary_position; varying vec3 vary_light; varying vec3 vary_pointlight_col; +varying float vary_texture_index; uniform float near_clip; uniform float shadow_offset; @@ -35,20 +36,25 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa //get distance float d = length(lv); - - //normalize light vector - lv *= 1.0/d; - - //distance attenuation - float dist2 = d*d/(la*la); - float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 - //angular attenuation - da *= calcDirectionalLight(n, lv); + float da = 0.0; + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float dist2 = d*d/(la*la); + da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + } return da; } @@ -56,34 +62,35 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa void main() { //transform vertex - gl_Position = ftransform(); + vec4 vert = vec4(gl_Vertex.xyz, 1.0); + vary_texture_index = gl_Vertex.w; + gl_Position = gl_ModelViewProjectionMatrix * vert; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vec4 pos = (gl_ModelViewMatrix * gl_Vertex); + vec4 pos = (gl_ModelViewMatrix * vert); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz)); vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset; - + calcAtmospherics(pos.xyz); //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); - vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); // Collect normal lights col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a); - col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation, gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a); col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a); col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a); col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a); col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a); - + vary_pointlight_col = col.rgb*gl_Color.rgb; - + col.rgb = vec3(0,0,0); - + // Add windlight lights col.rgb = atmosAmbient(vec3(0.)); @@ -98,7 +105,7 @@ void main() gl_FogFragCoord = pos.z; - pos = gl_ModelViewProjectionMatrix * gl_Vertex; + pos = gl_ModelViewProjectionMatrix * vert; vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl new file mode 100644 index 000000000..870d59331 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowF.glsl @@ -0,0 +1,18 @@ +/** + * @file avatarShadowF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +uniform sampler2D diffuseMap; + + +void main() +{ + //gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a); + gl_FragColor = vec4(1,1,1,1); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl new file mode 100644 index 000000000..c7a4f8672 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/attachmentShadowV.glsl @@ -0,0 +1,27 @@ +/** + * @file attachmentShadowV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +mat4 getObjectSkinnedTransform(); + +void main() +{ + //transform vertex + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + gl_FrontColor = gl_Color; + + vec4 p = gl_ProjectionMatrix * vec4(pos, 1.0); + p.z = max(p.z, -p.w+0.01); + gl_Position = p; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index 616990560..68e4055cf 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -1,11 +1,11 @@ /** * @file avatarAlphaV.glsl * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ */ -#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); @@ -35,19 +35,24 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa //get distance float d = length(lv); - //normalize light vector - lv *= 1.0/d; + float da = 0.0; + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv *= 1.0/d; - //distance attenuation - float dist2 = d*d/(la*la); - float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + //distance attenuation + float dist2 = d*d/(la*la); + da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 - //angular attenuation - da *= calcDirectionalLight(n, lv); + //angular attenuation + da *= calcDirectionalLight(n, lv); + } return da; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index e2a36719c..b580a8f12 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl index 61574d0be..78986ab12 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowF.glsl @@ -1,18 +1,21 @@ /** * @file avatarShadowF.glsl * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ */ -#version 120 + uniform sampler2D diffuseMap; +varying vec4 post_pos; void main() { //gl_FragColor = vec4(1,1,1,gl_Color.a * texture2D(diffuseMap, gl_TexCoord[0].xy).a); gl_FragColor = vec4(1,1,1,1); + + gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl index 49ddd2b19..f177fcd8f 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarShadowV.glsl @@ -1,16 +1,18 @@ /** * @file avatarShadowV.glsl * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ */ -#version 120 + mat4 getSkinnedTransform(); attribute vec4 weight; +varying vec4 post_pos; + void main() { gl_TexCoord[0] = gl_MultiTexCoord0; @@ -30,8 +32,9 @@ void main() norm = normalize(norm); pos = gl_ProjectionMatrix * pos; - pos.z = max(pos.z, -pos.w+0.01); - gl_Position = pos; + post_pos = pos; + + gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); gl_FrontColor = gl_Color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl index 3465cef2b..d7b9418f8 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl index d04bfb3ad..8c75c8045 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl @@ -1,11 +1,11 @@ /** * @file blurLightF.glsl * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable @@ -26,7 +26,7 @@ uniform vec2 screen_res; vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -39,7 +39,7 @@ vec4 getPosition(vec2 pos_screen) void main() { - vec2 tc = vary_fragcoord.xy; + vec2 tc = vary_fragcoord.xy; vec3 norm = texture2DRect(normalMap, tc).xyz; norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm vec3 pos = getPosition(tc).xyz; @@ -55,8 +55,7 @@ void main() float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005; // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large - //This causes some pretty nasty artifacting, so disabling for now. - //tc += ( (mod(tc.x+tc.y,2) - 0.5) * kern[1].z * dlt * 0.5 ); + tc += ( (mod(tc.x+tc.y,2) - 0.5) * kern[1].z * dlt * 0.5 ); for (int i = 1; i < 4; i++) { diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl index 3f2d7d7b1..3999869f2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl index 7a423f394..479976e55 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl new file mode 100644 index 000000000..dc69519a8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl @@ -0,0 +1,37 @@ +/** + * @file bumpV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +varying vec3 vary_mat0; +varying vec3 vary_mat1; +varying vec3 vary_mat2; + +mat4 getObjectSkinnedTransform(); + +void main() +{ + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + + vec3 pos = (mat*gl_Vertex).xyz; + + + vec3 n = normalize((mat * vec4(gl_Normal.xyz+gl_Vertex.xyz, 1.0)).xyz-pos.xyz); + vec3 b = normalize((mat * vec4(gl_MultiTexCoord2.xyz+gl_Vertex.xyz, 1.0)).xyz-pos.xyz); + vec3 t = cross(b, n); + + vary_mat0 = vec3(t.x, b.x, n.x); + vary_mat1 = vec3(t.y, b.y, n.y); + vary_mat2 = vec3(t.z, b.z, n.z); + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl index c83f781e2..65ff4cbad 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec3 vary_mat0; varying vec3 vary_mat1; diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl new file mode 100644 index 000000000..ef300d563 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsF.glsl @@ -0,0 +1,79 @@ +/** + * @file WLCloudsF.glsl + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +///////////////////////////////////////////////////////////////////////// +// The fragment shader for the sky +///////////////////////////////////////////////////////////////////////// + +varying vec4 vary_CloudColorSun; +varying vec4 vary_CloudColorAmbient; +varying float vary_CloudDensity; + +uniform sampler2D cloud_noise_texture; +uniform vec4 cloud_pos_density1; +uniform vec4 cloud_pos_density2; +uniform vec4 gamma; + +/// Soft clips the light with a gamma correction +vec3 scaleSoftClip(vec3 light) { + //soft clip effect: + light = 1. - clamp(light, vec3(0.), vec3(1.)); + light = 1. - pow(light, gamma.xxx); + + return light; +} + +void main() +{ + // Set variables + vec2 uv1 = gl_TexCoord[0].xy; + vec2 uv2 = gl_TexCoord[1].xy; + + vec4 cloudColorSun = vary_CloudColorSun; + vec4 cloudColorAmbient = vary_CloudColorAmbient; + float cloudDensity = vary_CloudDensity; + vec2 uv3 = gl_TexCoord[2].xy; + vec2 uv4 = gl_TexCoord[3].xy; + + // Offset texture coords + uv1 += cloud_pos_density1.xy; //large texture, visible density + uv2 += cloud_pos_density1.xy; //large texture, self shadow + uv3 += cloud_pos_density2.xy; //small texture, visible density + uv4 += cloud_pos_density2.xy; //small texture, self shadow + + + // Compute alpha1, the main cloud opacity + float alpha1 = (texture2D(cloud_noise_texture, uv1).x - 0.5) + (texture2D(cloud_noise_texture, uv3).x - 0.5) * cloud_pos_density2.z; + alpha1 = min(max(alpha1 + cloudDensity, 0.) * 10. * cloud_pos_density1.z, 1.); + + // And smooth + alpha1 = 1. - alpha1 * alpha1; + alpha1 = 1. - alpha1 * alpha1; + + + // Compute alpha2, for self shadowing effect + // (1 - alpha2) will later be used as percentage of incoming sunlight + float alpha2 = (texture2D(cloud_noise_texture, uv2).x - 0.5); + alpha2 = min(max(alpha2 + cloudDensity, 0.) * 2.5 * cloud_pos_density1.z, 1.); + + // And smooth + alpha2 = 1. - alpha2; + alpha2 = 1. - alpha2 * alpha2; + + // Combine + vec4 color; + color = (cloudColorSun*(1.-alpha2) + cloudColorAmbient); + color *= 2.; + + /// Gamma correct for WL (soft clip effect). + gl_FragData[0] = vec4(scaleSoftClip(color.rgb), alpha1); + gl_FragData[1] = vec4(0.0,0.0,0.0,0.0); + gl_FragData[2] = vec4(0,0,1,0); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl new file mode 100644 index 000000000..3eac63076 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl @@ -0,0 +1,165 @@ +/** + * @file WLCloudsV.glsl + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +////////////////////////////////////////////////////////////////////////// +// The vertex shader for creating the atmospheric sky +/////////////////////////////////////////////////////////////////////////////// + +// Output parameters +varying vec4 vary_CloudColorSun; +varying vec4 vary_CloudColorAmbient; +varying float vary_CloudDensity; + +// Inputs +uniform vec3 camPosLocal; + +uniform vec4 lightnorm; +uniform vec4 sunlight_color; +uniform vec4 ambient; +uniform vec4 blue_horizon; +uniform vec4 blue_density; +uniform vec4 haze_horizon; +uniform vec4 haze_density; + +uniform vec4 cloud_shadow; +uniform vec4 density_multiplier; +uniform vec4 max_y; + +uniform vec4 glow; + +uniform vec4 cloud_color; + +uniform vec4 cloud_scale; + +void main() +{ + + // World / view / projection + gl_Position = ftransform(); + + gl_TexCoord[0] = gl_MultiTexCoord0; + + // Get relative position + vec3 P = gl_Vertex.xyz - camPosLocal.xyz + vec3(0,50,0); + + // Set altitude + if (P.y > 0.) + { + P *= (max_y.x / P.y); + } + else + { + P *= (-32000. / P.y); + } + + // Can normalize then + vec3 Pn = normalize(P); + float Plen = length(P); + + // Initialize temp variables + vec4 temp1 = vec4(0.); + vec4 temp2 = vec4(0.); + vec4 blue_weight; + vec4 haze_weight; + vec4 sunlight = sunlight_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 * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); + + // Calculate relative weights + temp1 = blue_density + haze_density.x; + blue_weight = blue_density / temp1; + haze_weight = haze_density.x / temp1; + + // Compute sunlight from P & lightnorm (for long rays like sky) + temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // Distance + temp2.z = Plen * density_multiplier.x; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z); + + + // Compute haze glow + temp2.x = dot(Pn, lightnorm.xyz); + temp2.x = 1. - temp2.x; + // temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .001); + // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + // Higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + // glow.z should be negative, so we're doing a sort of (1 / "angle") function + + // Add "minimum anti-solar illumination" + temp2.x += .25; + + // Increase ambient when there are more clouds + vec4 tmpAmbient = ambient; + tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5; + + // Dim sunlight by cloud shadow percentage + sunlight *= (1. - cloud_shadow.x); + + // Haze color below cloud + vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient) + + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) + ); + + // CLOUDS + + sunlight = sunlight_color; + temp2.y = max(0., lightnorm.y * 2.); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // Cloud color out + vary_CloudColorSun = (sunlight * temp2.x) * cloud_color; + vary_CloudColorAmbient = tmpAmbient * cloud_color; + + // Attenuate cloud color by atmosphere + temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds + vary_CloudColorSun *= temp1; + vary_CloudColorAmbient *= temp1; + vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1); + + // Make a nice cloud density based on the cloud_shadow value that was passed in. + vary_CloudDensity = 2. * (cloud_shadow.x - 0.25); + + + // Texture coords + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[0].xy -= 0.5; + gl_TexCoord[0].xy /= cloud_scale.x; + gl_TexCoord[0].xy += 0.5; + + gl_TexCoord[1] = gl_TexCoord[0]; + gl_TexCoord[1].x += lightnorm.x * 0.0125; + gl_TexCoord[1].y += lightnorm.z * 0.0125; + + gl_TexCoord[2] = gl_TexCoord[0] * 16.; + gl_TexCoord[3] = gl_TexCoord[1] * 16.; + + // Combine these to minimize register use + vary_CloudColorAmbient += oHazeColorBelowCloud; + + // needs this to compile on mac + //vary_AtmosAttenuation = vec3(0.0,0.0,0.0); + + // END CLOUDS +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl new file mode 100644 index 000000000..338d0ebb2 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskF.glsl @@ -0,0 +1,30 @@ +/** + * @file diffuseF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + +uniform float minimum_alpha; +uniform float maximum_alpha; + +uniform sampler2D diffuseMap; + +varying vec3 vary_normal; + +void main() +{ + vec4 col = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color; + + if (col.a < minimum_alpha || col.a > maximum_alpha) + { + discard; + } + + gl_FragData[0] = vec4(col.rgb, 0.0); + gl_FragData[1] = vec4(0,0,0,0); // spec + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl new file mode 100644 index 000000000..0671cb94b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseAlphaMaskIndexedF.glsl @@ -0,0 +1,26 @@ +/** + * @file diffuseAlphaMaskIndexedF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +varying vec3 vary_normal; + +uniform float minimum_alpha; +uniform float maximum_alpha; + +void main() +{ + vec4 col = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (col.a < minimum_alpha || col.a > maximum_alpha) + { + discard; + } + + gl_FragData[0] = vec4(col.rgb, 0.0); + gl_FragData[1] = vec4(0,0,0,0); + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl index 451195f97..e1d5d5062 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl new file mode 100644 index 000000000..e7b5dcce7 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseIndexedF.glsl @@ -0,0 +1,19 @@ +/** + * @file diffuseIndexedF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +varying vec3 vary_normal; + +void main() +{ + vec3 col = gl_Color.rgb * diffuseLookup(gl_TexCoord[0].xy).rgb; + + gl_FragData[0] = vec4(col, 0.0); + gl_FragData[1] = gl_Color.aaaa; // spec + //gl_FragData[1] = vec4(vec3(gl_Color.a), gl_Color.a+(1.0-gl_Color.a)*gl_Color.a); // spec - from former class3 - maybe better, but not so well tested + vec3 nvn = normalize(vary_normal); + gl_FragData[2] = vec4(nvn.xy * 0.5 + 0.5, nvn.z, 0.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl new file mode 100644 index 000000000..2c4caea10 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl @@ -0,0 +1,33 @@ +/** + * @file diffuseSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +varying vec3 vary_normal; + +mat4 getObjectSkinnedTransform(); + +void main() +{ + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + vary_normal = norm.xyz; + + gl_FrontColor = gl_Color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl index af0314a75..3154b5431 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl @@ -5,16 +5,18 @@ * $/LicenseInfo$ */ -#version 120 + varying vec3 vary_normal; +varying float vary_texture_index; void main() { //transform vertex - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.xyz, 1.0); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + vary_texture_index = gl_Vertex.w; vary_normal = normalize(gl_NormalMatrix * gl_Normal); gl_FrontColor = gl_Color; diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl index 342987739..d781e0854 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightF.glsl @@ -5,60 +5,24 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable -uniform sampler2D diffuseMap; -uniform sampler2DRect depthMap; -uniform sampler2D noiseMap; - -uniform vec4 shadow_clip; -uniform vec2 screen_res; - vec3 fullbrightAtmosTransport(vec3 light); vec3 fullbrightScaleSoftClip(vec3 light); -varying vec3 vary_ambient; -varying vec3 vary_directional; -varying vec4 vary_position; -varying vec3 vary_normal; -varying vec3 vary_fragcoord; - -uniform mat4 inv_proj; - -vec4 getPosition(vec2 pos_screen) -{ - float depth = texture2DRect(depthMap, pos_screen.xy).a; - vec2 sc = pos_screen.xy*2.0; - sc /= screen_res; - sc -= vec2(1.0,1.0); - vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); - vec4 pos = inv_proj * ndc; - pos /= pos.w; - pos.w = 1.0; - return pos; -} void main() { - vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; - frag *= screen_res; - - vec3 samp_pos = getPosition(frag).xyz; - float shadow = 1.0; - vec4 pos = vary_position; - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy)*gl_Color; + vec4 color = diffuseLookup(gl_TexCoord[0].xy)*gl_Color; color.rgb = fullbrightAtmosTransport(color.rgb); color.rgb = fullbrightScaleSoftClip(color.rgb); - //gl_FragColor = gl_Color; gl_FragColor = color; - //gl_FragColor = vec4(1,0,1,1); - } diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl index 94f653541..800cfed64 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void calcAtmospherics(vec3 inPositionEye); @@ -14,30 +14,23 @@ vec3 atmosAffectDirectionalLight(float lightIntensity); vec3 scaleDownLight(vec3 light); vec3 scaleUpLight(vec3 light); -varying vec3 vary_ambient; -varying vec3 vary_directional; -varying vec3 vary_normal; -varying vec3 vary_fragcoord; -uniform float near_clip; -varying vec4 vary_position; +varying float vary_texture_index; void main() { //transform vertex - gl_Position = ftransform(); + vec4 vert = vec4(gl_Vertex.xyz, 1.0); + vary_texture_index = gl_Vertex.w; + + gl_Position = gl_ModelViewProjectionMatrix*vert; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vec4 pos = (gl_ModelViewMatrix * gl_Vertex); - vary_position = pos; - + vec4 pos = (gl_ModelViewMatrix * vert); + calcAtmospherics(pos.xyz); gl_FrontColor = gl_Color; gl_FogFragCoord = pos.z; - - pos = gl_ModelViewProjectionMatrix * gl_Vertex; - vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); - } diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl index 75b555e8a..41c149e77 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl index 8dc1410ea..e86f2896d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/giV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/giV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl index 6b3bfcf2a..d60333893 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl @@ -5,7 +5,8 @@ * $License$ */ -#version 120 +uniform float minimum_alpha; +uniform float maximum_alpha; uniform sampler2D diffuseMap; uniform sampler2D normalMap; @@ -14,6 +15,10 @@ uniform sampler2D specularMap; void main() { vec4 col = texture2D(diffuseMap, gl_TexCoord[0].xy); + if (col.a < minimum_alpha || col.a > maximum_alpha) + { + discard; + } gl_FragData[0] = vec4(col.rgb, col.a * 0.005); gl_FragData[1] = texture2D(specularMap, gl_TexCoord[0].xy); gl_FragData[2] = vec4(texture2D(normalMap, gl_TexCoord[0].xy).xyz, 0.0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl index d90c4478c..a209f95f5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/impostorV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void main() { diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl index 78df54d5d..25e93ae26 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + uniform sampler2DRect diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl index 0c820bfc6..4baf1fc65 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/luminanceV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl index 89e258887..3c5c780d9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl @@ -1,11 +1,11 @@ /** * @file multiPointLightF.glsl * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable @@ -36,7 +36,7 @@ uniform mat4 inv_proj; vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -123,4 +123,6 @@ void main() gl_FragColor.rgb = out_col; gl_FragColor.a = 0.0; + + //gl_FragColor = vec4(0.1, 0.025, 0.025/4.0, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl index 2e3e84dd1..434fb6f53 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec4 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl index a9f03f761..0d25d7792 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + //class 1 -- no shadows diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl index 22ed9dcd4..5efa3200d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ - #version 120 + #extension GL_ARB_texture_rectangle : enable @@ -30,7 +30,7 @@ uniform vec4 viewport; vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = (pos_screen.xy-viewport.xy)*2.0; sc /= viewport.zw; sc -= vec2(1.0,1.0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl index 1a426dddf..756843b8b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightV.glsl @@ -5,19 +5,14 @@ * $License$ */ -#version 120 + varying vec4 vary_light; varying vec4 vary_fragcoord; -uniform vec2 screen_res; -uniform float near_clip; - void main() { //transform vertex - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex; vary_fragcoord = pos; @@ -25,6 +20,8 @@ void main() tex.w = 1.0; vary_light = gl_MultiTexCoord0; + + gl_Position = pos; gl_FrontColor = gl_Color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl index 77f1b2224..f6b0402bb 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable @@ -29,7 +29,7 @@ varying vec2 vary_fragcoord; float getDepth(vec2 pos_screen) { - float z = texture2DRect(depthMap, pos_screen.xy).a; + float z = texture2DRect(depthMap, pos_screen.xy).r; z = z*2.0-1.0; vec4 ndc = vec4(0.0, 0.0, z, 1.0); vec4 p = inv_proj*ndc; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl index ab48d08bb..bf829bfc5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredNoDoFF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl index 12983baa9..876f65ee3 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl index 63b3c9f20..fa3f04bcc 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + uniform sampler2DRect depthMap; uniform sampler2DRect normalMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl index ae57227fe..eebe93066 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/postgiV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl new file mode 100644 index 000000000..e24d0b666 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskF.glsl @@ -0,0 +1,27 @@ +/** + * @file shadowAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +uniform sampler2D diffuseMap; + +varying vec4 post_pos; + +void main() +{ + float alpha = texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a; + + if (alpha < minimum_alpha || alpha > maximum_alpha) + { + discard; + } + + gl_FragColor = vec4(1,1,1,1); + + gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl new file mode 100644 index 000000000..58e9bcec5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskV.glsl @@ -0,0 +1,23 @@ +/** + * @file shadowAlphaMaskV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +varying vec4 post_pos; + +void main() +{ + //transform vertex + vec4 pos = gl_ModelViewProjectionMatrix*gl_Vertex; + + post_pos = pos; + + gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl index 4d85bbf62..9d1122080 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowF.glsl @@ -5,15 +5,13 @@ * $License$ */ -#version 120 -uniform sampler2D diffuseMap; varying vec4 post_pos; void main() { - gl_FragColor = vec4(1,1,1,texture2D(diffuseMap, gl_TexCoord[0].xy).a * gl_Color.a); + gl_FragColor = vec4(1,1,1,1); gl_FragDepth = max(post_pos.z/post_pos.w*0.5+0.5, 0.0); } diff --git a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl index 9baa39814..a5d4f91c1 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/shadowV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec4 post_pos; @@ -17,7 +17,4 @@ void main() post_pos = pos; gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w); - - gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - gl_FrontColor = gl_Color; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl new file mode 100644 index 000000000..820c82ffd --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/skyF.glsl @@ -0,0 +1,44 @@ +/** + * @file WLSkyF.glsl + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +///////////////////////////////////////////////////////////////////////// +// The fragment shader for the sky +///////////////////////////////////////////////////////////////////////// + +varying vec4 vary_HazeColor; + +uniform sampler2D cloud_noise_texture; +uniform vec4 gamma; + +/// Soft clips the light with a gamma correction +vec3 scaleSoftClip(vec3 light) { + //soft clip effect: + light = 1. - clamp(light, vec3(0.), vec3(1.)); + light = 1. - pow(light, gamma.xxx); + + return light; +} + +void main() +{ + // Potential Fill-rate optimization. Add cloud calculation + // back in and output alpha of 0 (so that alpha culling kills + // the fragment) if the sky wouldn't show up because the clouds + // are fully opaque. + + vec4 color; + color = vary_HazeColor; + color *= 2.; + + /// Gamma correct for WL (soft clip effect). + gl_FragData[0] = vec4(scaleSoftClip(color.rgb), 1.0); + gl_FragData[1] = vec4(0.0,0.0,0.0,0.0); + gl_FragData[2] = vec4(0,0,1,0); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl new file mode 100644 index 000000000..1ea00f723 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -0,0 +1,140 @@ +/** + * @file WLSkyV.glsl + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +// SKY //////////////////////////////////////////////////////////////////////// +// The vertex shader for creating the atmospheric sky +/////////////////////////////////////////////////////////////////////////////// + +// Output parameters +varying vec4 vary_HazeColor; + +// Inputs +uniform vec3 camPosLocal; + +uniform vec4 lightnorm; +uniform vec4 sunlight_color; +uniform vec4 ambient; +uniform vec4 blue_horizon; +uniform vec4 blue_density; +uniform vec4 haze_horizon; +uniform vec4 haze_density; + +uniform vec4 cloud_shadow; +uniform vec4 density_multiplier; +uniform vec4 max_y; + +uniform vec4 glow; + +uniform vec4 cloud_color; + +uniform vec4 cloud_scale; + +void main() +{ + + // World / view / projection + gl_Position = ftransform(); + gl_TexCoord[0] = gl_MultiTexCoord0; + + // Get relative position + vec3 P = gl_Vertex.xyz - camPosLocal.xyz + vec3(0,50,0); + //vec3 P = gl_Vertex.xyz + vec3(0,50,0); + + // Set altitude + if (P.y > 0.) + { + P *= (max_y.x / P.y); + } + else + { + P *= (-32000. / P.y); + } + + // Can normalize then + vec3 Pn = normalize(P); + float Plen = length(P); + + // Initialize temp variables + vec4 temp1 = vec4(0.); + vec4 temp2 = vec4(0.); + vec4 blue_weight; + vec4 haze_weight; + vec4 sunlight = sunlight_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 * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); + + // Calculate relative weights + temp1 = blue_density + haze_density.x; + blue_weight = blue_density / temp1; + haze_weight = haze_density.x / temp1; + + // Compute sunlight from P & lightnorm (for long rays like sky) + temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // Distance + temp2.z = Plen * density_multiplier.x; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z); + + + // Compute haze glow + temp2.x = dot(Pn, lightnorm.xyz); + temp2.x = 1. - temp2.x; + // temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .001); + // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + // Higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + // glow.z should be negative, so we're doing a sort of (1 / "angle") function + + // Add "minimum anti-solar illumination" + temp2.x += .25; + + + // Haze color above cloud + vary_HazeColor = ( blue_horizon * blue_weight * (sunlight + ambient) + + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient) + ); + + + // Increase ambient when there are more clouds + vec4 tmpAmbient = ambient; + tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5; + + // Dim sunlight by cloud shadow percentage + sunlight *= (1. - cloud_shadow.x); + + // Haze color below cloud + vec4 additiveColorBelowCloud = ( blue_horizon * blue_weight * (sunlight + tmpAmbient) + + (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) + ); + + // Final atmosphere additive + vary_HazeColor *= (1. - temp1); + + // Attenuate cloud color by atmosphere + temp1 = sqrt(temp1); //less atmos opacity (more transparency) below clouds + + // At horizon, blend high altitude sky color towards the darker color below the clouds + vary_HazeColor += (additiveColorBelowCloud - vary_HazeColor) * (1. - sqrt(temp1)); + + // won't compile on mac without this being set + //vary_AtmosAttenuation = vec3(0.0,0.0,0.0); +} + diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index cffab338d..d327216a0 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -1,19 +1,22 @@ /** * @file softenLightF.glsl * - * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. - * $License$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect diffuseRect; uniform sampler2DRect specularRect; +uniform sampler2DRect positionMap; uniform sampler2DRect normalMap; uniform sampler2DRect lightMap; uniform sampler2DRect depthMap; +uniform sampler2D noiseMap; +uniform samplerCube environmentMap; uniform sampler2D lightFunc; uniform float blur_size; @@ -256,7 +259,7 @@ vec3 scaleSoftClip(vec3 light) void main() { vec2 tc = vary_fragcoord.xy; - float depth = texture2DRect(depthMap, tc.xy).a; + float depth = texture2DRect(depthMap, tc.xy).r; vec3 pos = getPosition_d(tc, depth).xyz; vec3 norm = texture2DRect(normalMap, tc).xyz; norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm @@ -267,74 +270,41 @@ void main() vec4 diffuse = texture2DRect(diffuseRect, tc); vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; - float scol = max(scol_ambocc.r, diffuse.a); - float ambocc = scol_ambocc.g; - - calcAtmospherics(pos.xyz, ambocc); - - vec3 col = atmosAmbient(vec3(0)); - col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); - col *= diffuse.rgb; - - if (spec.a > 0.0) // specular reflection + vec3 col; + float bloom = 0.0; + if (diffuse.a < 0.9) { - // the old infinite-sky shiny reflection - // - vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(refnormpersp, vary_light.xyz); - vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; - /* - // screen-space cheap fakey reflection map - // - vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); - depth -= 0.5; // unbias depth - // first figure out where we'll make our 2D guess from - vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; - // Offset the guess source a little according to a trivial - // checkerboard dither function and spec.a. - // This is meant to be similar to sampling a blurred version - // of the diffuse map. LOD would be better in that regard. - // The goal of the blur is to soften reflections in surfaces - // with low shinyness, and also to disguise our lameness. - float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); - ref2d += vec2(checkoffset, checkoffset); - ref2d += tc.xy; // use as offset from destination - // Get attributes from the 2D guess point. - // We average two samples of diffuse (not of anything else) per - // pixel to try to reduce aliasing some more. - vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + - texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); - float refdepth = texture2DRect(depthMap, ref2d).a; - vec3 refpos = getPosition_d(ref2d, refdepth).xyz; - vec3 refn = texture2DRect(normalMap, ref2d).rgb; - refn = normalize(vec3((refn.xy-0.5)*2.0,refn.z)); // unpack norm - // figure out how appropriate our guess actually was - float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); - // darken reflections from points which face away from the reflected ray - our guess was a back-face - //refapprop *= step(dot(refnorm, refn), 0.0); - refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant - // get appropriate light strength for guess-point. - // reflect light direction to increase the illusion that - // these are reflections. - vec3 reflight = reflect(lightnorm.xyz, norm.xyz); - float reflit = max(dot(refn, reflight.xyz), 0.0); - // apply sun color to guess-point, dampen according to inappropriateness of guess - float refmod = min(refapprop, reflit); - vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; - vec3 ssshiny = (refprod * spec.a); - ssshiny *= 0.3; // dampen it even more - */ - vec3 ssshiny = vec3(0,0,0); - - // add the two types of shiny together - col += (ssshiny + dumbshiny) * spec.rgb; - } + calcAtmospherics(pos.xyz, 1.0); - col = atmosLighting(col); - col = scaleSoftClip(col); - + col = atmosAmbient(vec3(0)); + col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a)); + + col *= diffuse.rgb; + + if (spec.a > 0.0) // specular reflection + { + // the old infinite-sky shiny reflection + // + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a; + + // add the two types of shiny together + vec3 spec_contrib = dumbshiny * spec.rgb; + bloom = dot(spec_contrib, spec_contrib); + col += spec_contrib; + } + + col = atmosLighting(col); + col = scaleSoftClip(col); + + col = mix(col.rgb, diffuse.rgb, diffuse.a); + } + else + { + col = diffuse.rgb; + } + gl_FragColor.rgb = col; - gl_FragColor.a = 0.0; + gl_FragColor.a = bloom; } diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl index bca692cab..c438fd3d9 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl @@ -5,7 +5,6 @@ * $License$ */ -#version 120 #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl index 3bc94e70d..1abdc943b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl index 29fac46bf..9aaffc15b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/spotLightF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl new file mode 100644 index 000000000..2cf7d194c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/starsF.glsl @@ -0,0 +1,19 @@ +/** + * @file starsF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +uniform sampler2D diffuseMap; + +void main() +{ + vec4 col = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); + + gl_FragData[0] = col; + gl_FragData[1] = vec4(0,0,0,0); + gl_FragData[2] = vec4(0,0,1,0); +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl new file mode 100644 index 000000000..c43125dad --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/deferred/starsV.glsl @@ -0,0 +1,17 @@ +/** + * @file starsV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + + +void main() +{ + //transform vertex + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl index 5db627ab1..686b6eb3d 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + //class 1, no shadow, no SSAO, should never be called diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl index cd91351ad..665d8126a 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable @@ -35,7 +35,7 @@ uniform float shadow_offset; vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl index 9aef0a6bb..703a5ee4c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec4 vary_light; varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl index 0a3fae592..eba9eb651 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D detail_0; uniform sampler2D detail_1; diff --git a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl index 06507f456..4b3f81bfb 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/terrainV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec3 vary_normal; diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl index 123520190..3b869efd4 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl index d1500393b..448dccdf6 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/treeV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec3 vary_normal; diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 606e44eae..9271160fd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl index 2be8d4286..31c7710df 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl index 61e5ba0d9..76c3cb7f8 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl index fd5300a1f..9e74df765 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowExtractV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void main() { diff --git a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl index 817d6c1c5..b27434d5b 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowF.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowF.glsl @@ -5,25 +5,25 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; uniform float glowStrength; -float kern[4] = float[4](.25,.5,.8,1.0); //Initialize the correct (non nVidia cg) way +vec4 kern = vec4(.25,.5,.8,1.0); void main() { vec4 col = vec4(0.0, 0.0, 0.0, 0.0); - col += kern[0] * texture2D(diffuseMap, gl_TexCoord[0].xy); - col += kern[1] * texture2D(diffuseMap, gl_TexCoord[1].xy); - col += kern[2] * texture2D(diffuseMap, gl_TexCoord[2].xy); - col += kern[3] * texture2D(diffuseMap, gl_TexCoord[3].xy); - col += kern[3] * texture2D(diffuseMap, gl_TexCoord[0].zw); - col += kern[2] * texture2D(diffuseMap, gl_TexCoord[1].zw); - col += kern[1] * texture2D(diffuseMap, gl_TexCoord[2].zw); - col += kern[0] * texture2D(diffuseMap, gl_TexCoord[3].zw); + col += kern.x * texture2D(diffuseMap, gl_TexCoord[0].xy); + col += kern.y * texture2D(diffuseMap, gl_TexCoord[1].xy); + col += kern.z * texture2D(diffuseMap, gl_TexCoord[2].xy); + col += kern.w * texture2D(diffuseMap, gl_TexCoord[3].xy); + col += kern.w * texture2D(diffuseMap, gl_TexCoord[0].zw); + col += kern.z * texture2D(diffuseMap, gl_TexCoord[1].zw); + col += kern.y * texture2D(diffuseMap, gl_TexCoord[2].zw); + col += kern.x * texture2D(diffuseMap, gl_TexCoord[3].zw); gl_FragColor = vec4(col.rgb * glowStrength, col.a); } diff --git a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl index 744eff196..71ef6666e 100644 --- a/indra/newview/app_settings/shaders/class1/effects/glowV.glsl +++ b/indra/newview/app_settings/shaders/class1/effects/glowV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform vec2 glowDelta; diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl index 51b3cdd99..276cfe06c 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D detail0; uniform sampler2D detail1; diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl index fc4cb14c4..6f7e9c65b 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); diff --git a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl index 7db3133f6..c4f132a2e 100644 --- a/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/terrainWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + // this class1 shader is just a copy of terrainF diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl index 6f65b0179..46cf6669a 100644 --- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl index 89217484f..30f43cb84 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); diff --git a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl index 94296e0ba..35265edac 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterFogF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec4 applyWaterFog(vec4 color) { diff --git a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl index 4dae985a7..293efc106 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterV.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl new file mode 100644 index 000000000..3827c72f4 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/customalphaF.glsl @@ -0,0 +1,17 @@ +/** + * @file customalphaF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D diffuseMap; + +uniform float custom_alpha; + +void main() +{ + vec4 color = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy); + color.a *= custom_alpha; + gl_FragColor = color; +} diff --git a/indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl b/indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl new file mode 100644 index 000000000..04bfff22c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/customalphaV.glsl @@ -0,0 +1,16 @@ +/** + * @file customalphaV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl new file mode 100644 index 000000000..a60fb1eaa --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineF.glsl @@ -0,0 +1,17 @@ +/** + * @file glowcombineF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2D glowMap; +uniform sampler2DRect screenMap; + +void main() +{ + gl_FragColor = texture2D(glowMap, gl_TexCoord[0].xy) + + texture2DRect(screenMap, gl_TexCoord[1].xy); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl new file mode 100644 index 000000000..ce183ec15 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/glowcombineV.glsl @@ -0,0 +1,15 @@ +/** + * @file glowcombineV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_MultiTexCoord1; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl index 5e4c123a8..bf2996a32 100644 --- a/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/highlightF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl index 4c052a35a..75cc00b12 100644 --- a/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl +++ b/indra/newview/app_settings/shaders/class1/interface/highlightV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void main() { diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl new file mode 100644 index 000000000..b140712f1 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/occlusionF.glsl @@ -0,0 +1,11 @@ +/** + * @file occlusionF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +void main() +{ + gl_FragColor = vec4(1,1,1,1); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl new file mode 100644 index 000000000..5a5d0ec50 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/occlusionV.glsl @@ -0,0 +1,12 @@ +/** + * @file uiV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl new file mode 100644 index 000000000..5b7cc5757 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/solidcolorF.glsl @@ -0,0 +1,15 @@ +/** + * @file twotextureaddF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D tex0; + +void main() +{ + float alpha = texture2D(tex0, gl_TexCoord[0].xy).a * gl_Color.a; + + gl_FragColor = vec4(gl_Color.rgb, alpha); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl b/indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl new file mode 100644 index 000000000..8401208e2 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/solidcolorV.glsl @@ -0,0 +1,16 @@ +/** + * @file solidcolorV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_FrontColor = gl_Color; + gl_TexCoord[0] = gl_MultiTexCoord0; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl b/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl new file mode 100644 index 000000000..d81b56fdb --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/twotextureaddF.glsl @@ -0,0 +1,14 @@ +/** + * @file twotextureaddF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D tex0; +uniform sampler2D tex1; + +void main() +{ + gl_FragColor = texture2D(tex0, gl_TexCoord[0].xy)+texture2D(tex1, gl_TexCoord[1].xy); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl b/indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl new file mode 100644 index 000000000..f685b112b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/twotextureaddV.glsl @@ -0,0 +1,16 @@ +/** + * @file twotextureaddV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_TexCoord[1] = gl_MultiTexCoord1; +} + diff --git a/indra/newview/app_settings/shaders/class1/interface/uiF.glsl b/indra/newview/app_settings/shaders/class1/interface/uiF.glsl new file mode 100644 index 000000000..9dec7a56b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/uiF.glsl @@ -0,0 +1,13 @@ +/** + * @file uiF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D diffuseMap; + +void main() +{ + gl_FragColor = gl_Color*texture2D(diffuseMap, gl_TexCoord[0].xy); +} diff --git a/indra/newview/app_settings/shaders/class1/interface/uiV.glsl b/indra/newview/app_settings/shaders/class1/interface/uiV.glsl new file mode 100644 index 000000000..9ca6cae5c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/uiV.glsl @@ -0,0 +1,16 @@ +/** + * @file uiV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void main() +{ + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + gl_TexCoord[0] = gl_MultiTexCoord0; + gl_FrontColor = gl_Color; +} + diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl index 65a87b5f6..a524bacfb 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl index 7bfea160e..a913504fa 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl index 32f52fbe8..2e43117f6 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl index 1bdaccf9b..19072cd05 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyWaterF.glsl @@ -6,7 +6,7 @@ */ -#version 120 + uniform sampler2D diffuseMap; uniform samplerCube environmentMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl index 89afa0ab2..a45b19a28 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterF.glsl @@ -6,7 +6,7 @@ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl index 4ce4bc0cb..c248a9a69 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncSpecularV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLight(vec3 n, vec3 l) { diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl index a437d075a..542161032 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightFuncV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLight(vec3 n, vec3 l) diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl index 28dabb494..2410dbd2c 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl index 7985c17e0..501534f04 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightShinyWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl index fddba5cff..42cbcbcef 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightSpecularV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLight(vec3 n, vec3 l); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl index 8c01f3dd5..ba90c4277 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLight(vec3 n, vec3 l); diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl index 97506312a..3c5b82128 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl index 4146b8121..c97db7393 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsSpecularV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 atmosAmbient(vec3 light); diff --git a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl index df198eafc..30741d6f7 100644 --- a/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class1/lighting/sumLightsV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLight(vec3 n, vec3 l); diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl new file mode 100644 index 000000000..587ab93a8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/bumpF.glsl @@ -0,0 +1,17 @@ +/** + * @file bumpF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform sampler2D texture0; +uniform sampler2D texture1; + +void main() +{ + float tex0 = texture2D(texture0, gl_TexCoord[0].xy).a; + float tex1 = texture2D(texture1, gl_TexCoord[1].xy).a; + + gl_FragColor = vec4(tex0+(1.0-tex1)-0.5); +} diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl new file mode 100644 index 000000000..056d1a958 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl @@ -0,0 +1,16 @@ +/** + * @file bumpV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + +void main() +{ + //transform vertex + gl_Position = gl_ModelViewProjectionMatrix*gl_Vertex; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1; + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl index 028b51cbb..77029c2d3 100755 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void fullbright_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl index b474ac55d..ede6b5041 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void fullbright_shiny_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl new file mode 100644 index 000000000..5283e8040 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl @@ -0,0 +1,37 @@ +/** + * @file shinySimpleSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +void calcAtmospherics(vec3 inPositionEye); +mat4 getObjectSkinnedTransform(); + +void main() +{ + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + vec3 ref = reflect(pos.xyz, -norm.xyz); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0); + + calcAtmospherics(pos.xyz); + + gl_FrontColor = gl_Color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); + + gl_FogFragCoord = pos.z; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl index 75b841a5f..01020743e 100755 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl index 5daf66fb3..8ffb252f5 100644 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void fullbright_shiny_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl new file mode 100644 index 000000000..1db79791d --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl @@ -0,0 +1,35 @@ +/** + * @file fullbrightSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +void calcAtmospherics(vec3 inPositionEye); +mat4 getObjectSkinnedTransform(); + +void main() +{ + //transform vertex + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + calcAtmospherics(pos.xyz); + + gl_FrontColor = gl_Color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); + + gl_FogFragCoord = pos.z; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl index 690a5d996..d87e5298d 100755 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl index 8645dc3a8..9e4825067 100755 --- a/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void fullbright_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl b/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl new file mode 100644 index 000000000..13597ee43 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/impostorF.glsl @@ -0,0 +1,26 @@ +/** + * @file impostorF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 fullbrightAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +uniform sampler2D diffuseMap; + +void main() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + gl_FragColor = color; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/impostorV.glsl b/indra/newview/app_settings/shaders/class1/objects/impostorV.glsl new file mode 100644 index 000000000..724b86a1b --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/impostorV.glsl @@ -0,0 +1,16 @@ +/** + * @file impostorV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + +void main() +{ + //transform vertex + gl_Position = ftransform(); + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + gl_FrontColor = gl_Color; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl index 1d83116b1..f2c86c064 100644 --- a/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void shiny_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl new file mode 100644 index 000000000..eea41bb4f --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl @@ -0,0 +1,37 @@ +/** + * @file shinySimpleSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); +mat4 getObjectSkinnedTransform(); + +void main() +{ + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + vec3 ref = reflect(pos.xyz, -norm.xyz); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0); + + calcAtmospherics(pos.xyz); + + vec4 color = calcLighting(pos.xyz, norm.xyz, gl_Color, vec4(0.)); + gl_FrontColor = color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); +} diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl index 3fb9a298c..120ad7f0a 100644 --- a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl index 1fc497e49..eba6f763c 100755 --- a/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/shinyWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void shiny_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl index 97f5741b3..8a2c76ead 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void default_lighting(); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl new file mode 100644 index 000000000..af92e5e00 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl @@ -0,0 +1,37 @@ +/** + * @file simpleSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); +mat4 getObjectSkinnedTransform(); + +void main() +{ + //transform vertex + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + vec3 pos = (mat*gl_Vertex).xyz; + + vec4 norm = gl_Vertex; + norm.xyz += gl_Normal.xyz; + norm.xyz = (mat*norm).xyz; + norm.xyz = normalize(norm.xyz-pos.xyz); + + calcAtmospherics(pos.xyz); + + vec4 color = calcLighting(pos.xyz, norm.xyz, gl_Color, vec4(0.)); + gl_FrontColor = color; + + gl_Position = gl_ProjectionMatrix*vec4(pos, 1.0); + + gl_FogFragCoord = pos.z; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl index 03167cfc6..85219f041 100644 --- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl index e133dcf41..dd8596704 100755 --- a/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/simpleWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void default_lighting_water(); diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl index 4c20ad758..2c6be7c9c 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec3 atmosLighting(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl index e83180714..45d2121b3 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsHelpersV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec3 atmosAmbient(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl index c5adb50e4..37eb630a8 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void setPositionEye(vec3 v); diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl index f8405b4d5..db175c6f2 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl index 658767427..77d7b18c6 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl index 76a072000..9c32d1a6a 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/gammaF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform vec4 gamma; diff --git a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl index 77ed3ea2b..eef8dfbaa 100644 --- a/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl +++ b/indra/newview/app_settings/shaders/class1/windlight/transportF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec3 atmosTransport(vec3 light) { diff --git a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl index 4af024f17..263fbcc02 100644 --- a/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl +++ b/indra/newview/app_settings/shaders/class2/avatar/eyeballV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec4 calcLightingSpecular(vec3 pos, vec3 norm, vec4 color, inout vec4 specularColor, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl index f234f57d4..c0014d4cc 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaF.glsl @@ -5,11 +5,10 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable -uniform sampler2D diffuseMap; uniform sampler2DRectShadow shadowMap0; uniform sampler2DRectShadow shadowMap1; uniform sampler2DRectShadow shadowMap2; @@ -105,7 +104,7 @@ void main() } } - vec4 diff= texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 diff = diffuseLookup(gl_TexCoord[0].xy); vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a); vec4 color = diff * col; diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl new file mode 100644 index 000000000..5350359f7 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl @@ -0,0 +1,125 @@ +/** + * @file alphaF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRectShadow shadowMap0; +uniform sampler2DRectShadow shadowMap1; +uniform sampler2DRectShadow shadowMap2; +uniform sampler2DRectShadow shadowMap3; +uniform sampler2DRect depthMap; +uniform sampler2D diffuseMap; + +uniform mat4 shadow_matrix[6]; +uniform vec4 shadow_clip; +uniform vec2 screen_res; +uniform vec2 shadow_res; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; +varying vec3 vary_pointlight_col; + +uniform float shadow_bias; + +uniform mat4 inv_proj; + +vec4 getPosition(vec2 pos_screen) +{ + float depth = texture2DRect(depthMap, pos_screen.xy).a; + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos.xyz /= pos.w; + pos.w = 1.0; + return pos; +} + +float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl) +{ + stc.xyz /= stc.w; + stc.z += shadow_bias; + + float cs = shadow2DRect(shadowMap, stc.xyz).x; + float shadow = cs; + + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs); + shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs); + + return shadow/5.0; +} + + +void main() +{ + vec2 frag = vary_fragcoord.xy/vary_fragcoord.z*0.5+0.5; + frag *= screen_res; + + float shadow = 1.0; + vec4 pos = vec4(vary_position, 1.0); + + vec4 spos = pos; + + if (spos.z > -shadow_clip.w) + { + vec4 lpos; + + if (spos.z < -shadow_clip.z) + { + lpos = shadow_matrix[3]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap3, lpos, 1.5); + shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0); + } + else if (spos.z < -shadow_clip.y) + { + lpos = shadow_matrix[2]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap2, lpos, 1.5); + } + else if (spos.z < -shadow_clip.x) + { + lpos = shadow_matrix[1]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap1, lpos, 1.5); + } + else + { + lpos = shadow_matrix[0]*spos; + lpos.xy *= shadow_res; + shadow = pcfShadow(shadowMap0, lpos, 1.5); + } + } + + vec4 diff = texture2D(diffuseMap,gl_TexCoord[0].xy); + + vec4 col = vec4(vary_ambient + vary_directional.rgb*shadow, gl_Color.a); + vec4 color = diff * col; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + color.rgb += diff.rgb * vary_pointlight_col.rgb; + + //gl_FragColor = gl_Color; + gl_FragColor = color; + //gl_FragColor.r = 0.0; + //gl_FragColor = vec4(1,shadow,1,1); + +} + diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl new file mode 100644 index 000000000..948a52da5 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl @@ -0,0 +1,115 @@ +/** + * @file alphaSkinnedV.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); + +float calcDirectionalLight(vec3 n, vec3 l); +mat4 getObjectSkinnedTransform(); +vec3 atmosAmbient(vec3 light); +vec3 atmosAffectDirectionalLight(float lightIntensity); +vec3 scaleDownLight(vec3 light); +vec3 scaleUpLight(vec3 light); + +varying vec3 vary_ambient; +varying vec3 vary_directional; +varying vec3 vary_fragcoord; +varying vec3 vary_position; +varying vec3 vary_pointlight_col; + +uniform float near_clip; +uniform float shadow_offset; +uniform float shadow_bias; + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + float da = 0.0; + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float dist2 = d*d/(la*la); + da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + } + + return da; +} + +void main() +{ + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + mat4 mat = getObjectSkinnedTransform(); + + mat = gl_ModelViewMatrix * mat; + + vec3 pos = (mat*gl_Vertex).xyz; + + gl_Position = gl_ProjectionMatrix * vec4(pos, 1.0); + + vec4 n = gl_Vertex; + n.xyz += gl_Normal.xyz; + n.xyz = (mat*n).xyz; + n.xyz = normalize(n.xyz-pos.xyz); + + vec3 norm = n.xyz; + + float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz)); + vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset; + + calcAtmospherics(pos.xyz); + + //vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a); + + // Collect normal lights + col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a); + col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a); + col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a); + col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a); + col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a); + col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a); + + vary_pointlight_col = col.rgb*gl_Color.rgb; + + col.rgb = vec3(0,0,0); + + // Add windlight lights + col.rgb = atmosAmbient(vec3(0.)); + + vary_ambient = col.rgb*gl_Color.rgb; + vary_directional.rgb = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a))); + + col.rgb = min(col.rgb*gl_Color.rgb, 1.0); + + gl_FrontColor = col; + + gl_FogFragCoord = pos.z; + + pos.xyz = (gl_ModelViewProjectionMatrix * gl_Vertex).xyz; + vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); + +} + diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 7024025f7..f616ecc87 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); @@ -22,6 +22,7 @@ varying vec3 vary_directional; varying vec3 vary_fragcoord; varying vec3 vary_position; varying vec3 vary_pointlight_col; +varying float vary_texture_index; uniform float near_clip; uniform float shadow_offset; @@ -34,32 +35,39 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa //get distance float d = length(lv); - - //normalize light vector - lv *= 1.0/d; - //distance attenuation - float dist2 = d*d/(la*la); - float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + float da = 0.0; - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv *= 1.0/d; - //angular attenuation - da *= calcDirectionalLight(n, lv); + //distance attenuation + float dist2 = d*d/(la*la); + da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - return da; + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + } + + return da; } void main() { //transform vertex - gl_Position = ftransform(); + vec4 vert = vec4(gl_Vertex.xyz, 1.0); + vary_texture_index = gl_Vertex.w; + gl_Position = gl_ModelViewProjectionMatrix * vert; gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; - vec4 pos = (gl_ModelViewMatrix * gl_Vertex); + vec4 pos = (gl_ModelViewMatrix * vert); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz)); @@ -94,7 +102,7 @@ void main() gl_FogFragCoord = pos.z; - pos = gl_ModelViewProjectionMatrix * gl_Vertex; + pos = gl_ModelViewProjectionMatrix * vert; vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip); } diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index 495e86c8d..01e40afc4 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); @@ -37,19 +37,24 @@ float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, floa //get distance float d = length(lv); - //normalize light vector - lv *= 1.0/d; + float da = 0.0; + + if (d > 0.0 && la > 0.0 && fa > 0.0) + { + //normalize light vector + lv *= 1.0/d; - //distance attenuation - float dist2 = d*d/(la*la); - float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); + //distance attenuation + float dist2 = d*d/(la*la); + da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0); - // spotlight coefficient. - float spot = max(dot(-ln, lv), is_pointlight); - da *= spot*spot; // GL_SPOT_EXPONENT=2 + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 - //angular attenuation - da *= calcDirectionalLight(n, lv); + //angular attenuation + da *= calcDirectionalLight(n, lv); + } return da; } diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl index 3155f3f92..729e4b554 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/edgeF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable @@ -22,7 +22,7 @@ uniform vec2 screen_res; float getDepth(vec2 pos_screen) { - float z = texture2DRect(depthMap, pos_screen.xy).a; + float z = texture2DRect(depthMap, pos_screen.xy).r; z = z*2.0-1.0; vec4 ndc = vec4(0.0, 0.0, z, 1.0); vec4 p = inv_proj*ndc; diff --git a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl index b3413c301..393084a3d 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/edgeV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl index d6cd984eb..f54186ffc 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable @@ -91,7 +91,7 @@ vec4 texture2DLodAmbient(sampler2D projectionMap, vec2 tc, float lod) vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl new file mode 100644 index 000000000..f0c9b0167 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -0,0 +1,315 @@ +/** + * @file softenLightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +#extension GL_ARB_texture_rectangle : enable + +uniform sampler2DRect diffuseRect; +uniform sampler2DRect specularRect; +uniform sampler2DRect normalMap; +uniform sampler2DRect lightMap; +uniform sampler2DRect depthMap; +uniform sampler2D noiseMap; +uniform samplerCube environmentMap; +uniform sampler2D lightFunc; +uniform vec3 gi_quad; + +uniform float blur_size; +uniform float blur_fidelity; + +// Inputs +uniform vec4 morphFactor; +uniform vec3 camPosLocal; +//uniform vec4 camPosWorld; +uniform vec4 gamma; +uniform vec4 lightnorm; +uniform vec4 sunlight_color; +uniform vec4 ambient; +uniform vec4 blue_horizon; +uniform vec4 blue_density; +uniform vec4 haze_horizon; +uniform vec4 haze_density; +uniform vec4 cloud_shadow; +uniform vec4 density_multiplier; +uniform vec4 distance_multiplier; +uniform vec4 max_y; +uniform vec4 glow; +uniform float scene_light_strength; +uniform vec3 env_mat[3]; +uniform vec4 shadow_clip; +uniform mat3 ssao_effect_mat; + +uniform mat4 inv_proj; +uniform vec2 screen_res; + +varying vec4 vary_light; +varying vec2 vary_fragcoord; + +vec3 vary_PositionEye; + +vec3 vary_SunlitColor; +vec3 vary_AmblitColor; +vec3 vary_AdditiveColor; +vec3 vary_AtmosAttenuation; + +vec4 getPosition_d(vec2 pos_screen, float depth) +{ + vec2 sc = pos_screen.xy*2.0; + sc /= screen_res; + sc -= vec2(1.0,1.0); + vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); + vec4 pos = inv_proj * ndc; + pos /= pos.w; + pos.w = 1.0; + return pos; +} + +vec4 getPosition(vec2 pos_screen) +{ //get position in screen space (world units) given window coordinate and depth map + float depth = texture2DRect(depthMap, pos_screen.xy).r; + return getPosition_d(pos_screen, depth); +} + +vec3 getPositionEye() +{ + return vary_PositionEye; +} +vec3 getSunlitColor() +{ + return vary_SunlitColor; +} +vec3 getAmblitColor() +{ + return vary_AmblitColor; +} +vec3 getAdditiveColor() +{ + return vary_AdditiveColor; +} +vec3 getAtmosAttenuation() +{ + return vary_AtmosAttenuation; +} + + +void setPositionEye(vec3 v) +{ + vary_PositionEye = v; +} + +void setSunlitColor(vec3 v) +{ + vary_SunlitColor = v; +} + +void setAmblitColor(vec3 v) +{ + vary_AmblitColor = v; +} + +void setAdditiveColor(vec3 v) +{ + vary_AdditiveColor = v; +} + +void setAtmosAttenuation(vec3 v) +{ + vary_AtmosAttenuation = v; +} + +void calcAtmospherics(vec3 inPositionEye, float ambFactor) { + + vec3 P = inPositionEye; + setPositionEye(P); + + //(TERRAIN) limit altitude + if (P.y > max_y.x) P *= (max_y.x / P.y); + if (P.y < -max_y.x) P *= (-max_y.x / P.y); + + vec3 tmpLightnorm = lightnorm.xyz; + + vec3 Pn = normalize(P); + float Plen = length(P); + + vec4 temp1 = vec4(0); + vec3 temp2 = vec3(0); + vec4 blue_weight; + vec4 haze_weight; + vec4 sunlight = sunlight_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 * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); + //I had thought blue_density and haze_density should have equal weighting, + //but attenuation due to haze_density tends to seem too strong + + temp1 = blue_density + vec4(haze_density.r); + blue_weight = blue_density / temp1; + haze_weight = vec4(haze_density.r) / temp1; + + //(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain) + temp2.y = max(0.0, tmpLightnorm.y); + temp2.y = 1. / temp2.y; + sunlight *= exp( - light_atten * temp2.y); + + // main atmospheric scattering line integral + temp2.z = Plen * density_multiplier.x; + + // Transparency (-> temp1) + // ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati + // compiler gets confused. + temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); + + //final atmosphere attenuation factor + setAtmosAttenuation(temp1.rgb); + + //compute haze glow + //(can use temp2.x as temp because we haven't used it yet) + temp2.x = dot(Pn, tmpLightnorm.xyz); + temp2.x = 1. - temp2.x; + //temp2.x is 0 at the sun and increases away from sun + temp2.x = max(temp2.x, .03); //was glow.y + //set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot) + temp2.x *= glow.x; + //higher glow.x gives dimmer glow (because next step is 1 / "angle") + temp2.x = pow(temp2.x, glow.z); + //glow.z should be negative, so we're doing a sort of (1 / "angle") function + + //add "minimum anti-solar illumination" + temp2.x += .25; + + //increase ambient when there are more clouds + vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; + + /* decrease value and saturation (that in HSV, not HSL) for occluded areas + * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html + * // The following line of code performs the equivalent of: + * float ambAlpha = tmpAmbient.a; + * float ambValue = dot(vec3(tmpAmbient), vec3(0.577)); // projection onto <1/rt(3), 1/rt(3), 1/rt(3)>, the neutral white-black axis + * vec3 ambHueSat = vec3(tmpAmbient) - vec3(ambValue); + * tmpAmbient = vec4(RenderSSAOEffect.valueFactor * vec3(ambValue) + RenderSSAOEffect.saturationFactor *(1.0 - ambFactor) * ambHueSat, ambAlpha); + */ + tmpAmbient = vec4(mix(ssao_effect_mat * tmpAmbient.rgb, tmpAmbient.rgb, ambFactor), tmpAmbient.a); + + //haze color + setAdditiveColor( + vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) + + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x + + tmpAmbient))); + + //brightness of surface both sunlight and ambient + setSunlitColor(vec3(sunlight * .5)); + setAmblitColor(vec3(tmpAmbient * .25)); + setAdditiveColor(getAdditiveColor() * vec3(1.0 - temp1)); +} + +vec3 atmosLighting(vec3 light) +{ + light *= getAtmosAttenuation().r; + light += getAdditiveColor(); + return (2.0 * light); +} + +vec3 atmosTransport(vec3 light) { + light *= getAtmosAttenuation().r; + light += getAdditiveColor() * 2.0; + return light; +} +vec3 atmosGetDiffuseSunlightColor() +{ + return getSunlitColor(); +} + +vec3 scaleDownLight(vec3 light) +{ + return (light / scene_light_strength ); +} + +vec3 scaleUpLight(vec3 light) +{ + return (light * scene_light_strength); +} + +vec3 atmosAmbient(vec3 light) +{ + return getAmblitColor() + light / 2.0; +} + +vec3 atmosAffectDirectionalLight(float lightIntensity) +{ + return getSunlitColor() * lightIntensity; +} + +vec3 scaleSoftClip(vec3 light) +{ + //soft clip effect: + light = 1. - clamp(light, vec3(0.), vec3(1.)); + light = 1. - pow(light, gamma.xxx); + + return light; +} + +void main() +{ + vec2 tc = vary_fragcoord.xy; + float depth = texture2DRect(depthMap, tc.xy).r; + vec3 pos = getPosition_d(tc, depth).xyz; + vec3 norm = texture2DRect(normalMap, tc).xyz; + norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm + //vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0).xyz; + + float da = max(dot(norm.xyz, vary_light.xyz), 0.0); + + vec4 diffuse = texture2DRect(diffuseRect, tc); + + vec3 col; + float bloom = 0.0; + + if (diffuse.a < 0.9) + { + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); + + vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + float scol = max(scol_ambocc.r, diffuse.a); + float ambocc = scol_ambocc.g; + + calcAtmospherics(pos.xyz, ambocc); + + col = atmosAmbient(vec3(0)); + col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); + + col *= diffuse.rgb; + + if (spec.a > 0.0) // specular reflection + { + // the old infinite-sky shiny reflection + // + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a; + + // add the two types of shiny together + vec3 spec_contrib = dumbshiny * spec.rgb; + bloom = dot(spec_contrib, spec_contrib); + col += spec_contrib; + } + + col = atmosLighting(col); + col = scaleSoftClip(col); + + col = mix(col, diffuse.rgb, diffuse.a); + } + else + { + col = diffuse.rgb; + } + + gl_FragColor.rgb = col; + gl_FragColor.a = bloom; +} diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl index 8f0bcca76..745cc0199 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl index d0e242c2d..ccc2406b8 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl index 4369b3b34..315139b41 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable @@ -45,7 +45,7 @@ uniform float spot_shadow_offset; vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl index fcea7aaf1..d53850b48 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable @@ -45,7 +45,7 @@ uniform float spot_shadow_offset; vec4 getPosition(vec2 pos_screen) { - float depth = texture2DRect(depthMap, pos_screen.xy).a; + float depth = texture2DRect(depthMap, pos_screen.xy).r; vec2 sc = pos_screen.xy*2.0; sc /= screen_res; sc -= vec2(1.0,1.0); @@ -60,9 +60,7 @@ vec4 getPosition(vec2 pos_screen) float calcAmbientOcclusion(vec4 pos, vec3 norm) { float ret = 1.0; - - float dist = dot(pos.xyz,pos.xyz); - + vec2 kern[8]; // exponentially (^2) distant occlusion samples spread around origin kern[0] = vec2(-1.0, 0.0) * 0.125*0.125; @@ -70,13 +68,13 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) kern[2] = vec2(0.0, 1.0) * 0.375*0.375; kern[3] = vec2(0.0, -1.0) * 0.500*0.500; kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625; - kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; - kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; - kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; + kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750; + kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875; + kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000; - vec2 pos_screen = vary_fragcoord.xy; - vec3 pos_world = pos.xyz; - vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; + vec2 pos_screen = vary_fragcoord.xy; + vec3 pos_world = pos.xyz; + vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy; float angle_hidden = 0.0; int points = 0; @@ -106,7 +104,6 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm) angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0); ret = (1.0 - (float(points != 0) * angle_hidden)); - ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0); return min(ret, 1.0); } @@ -237,7 +234,7 @@ void main() gl_FragColor[0] = shadow; gl_FragColor[1] = calcAmbientOcclusion(pos, norm); - spos.xyz = shadow_pos+offset*spot_shadow_offset; + spos.xyz = shadow_pos+norm*spot_shadow_offset; //spotlight shadow 1 vec4 lpos = shadow_matrix[4]*spos; diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl index 9beb513ad..814deb367 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec4 vary_light; varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl index 43f37a80a..19641ac0c 100644 --- a/indra/newview/app_settings/shaders/class2/effects/blurF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/blurF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl index cf4218bf7..9f57ab8a5 100644 --- a/indra/newview/app_settings/shaders/class2/effects/blurV.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/blurV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform vec2 texelSize; uniform vec2 blurDirection; diff --git a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl index f57633950..1347d957c 100644 --- a/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/colorFilterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl index 229ede470..b4a6786ce 100644 --- a/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/drawQuadV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void main(void) { diff --git a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl index fdf547264..9ae4a0d8c 100644 --- a/indra/newview/app_settings/shaders/class2/effects/extractF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/extractF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl index f6dfa52a9..5f6986e3f 100644 --- a/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/nightVisionF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl index 3dbed8e01..b905913d1 100644 --- a/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl +++ b/indra/newview/app_settings/shaders/class2/effects/simpleF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable uniform sampler2DRect RenderTexture; diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl index 9ccc776ad..57925fc72 100644 --- a/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/terrainF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D detail_0; uniform sampler2D detail_1; diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl index 19211b8e6..caec960e4 100644 --- a/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/terrainV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + void calcAtmospherics(vec3 inPositionEye); diff --git a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl index 6f2f560a9..fdbe4212e 100755 --- a/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/terrainWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D detail_0; uniform sampler2D detail_1; diff --git a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl index 246b55440..7f3685f1c 100644 --- a/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/underWaterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform sampler2D diffuseMap; uniform sampler2D bumpMap; diff --git a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl index 246377382..7df3aaf23 100644 --- a/indra/newview/app_settings/shaders/class2/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/waterF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec3 scaleSoftClip(vec3 inColor); vec3 atmosTransport(vec3 inColor); diff --git a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl index dd1c8ee64..f8cb7e1e2 100644 --- a/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl +++ b/indra/newview/app_settings/shaders/class2/environment/waterFogF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform vec4 lightnorm; uniform vec4 waterPlane; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskF.glsl new file mode 100644 index 000000000..1211ad7a8 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskF.glsl @@ -0,0 +1,30 @@ +/** + * @file lightAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +void default_lighting() +{ + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskNonIndexedF.glsl new file mode 100644 index 000000000..1a7d67b94 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightAlphaMaskNonIndexedF.glsl @@ -0,0 +1,33 @@ +/** + * @file lightAlphaMaskNonIndexedF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + +uniform float minimum_alpha; +uniform float maximum_alpha; + + +uniform sampler2D diffuseMap; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +void default_lighting() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl index e7779d357..22060bfcc 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl @@ -5,16 +5,14 @@ * $License$ */ -#version 120 -uniform sampler2D diffuseMap; vec3 atmosLighting(vec3 light); vec3 scaleSoftClip(vec3 light); void default_lighting() { - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color; + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; color.rgb = atmosLighting(color.rgb); diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightAlphaMaskF.glsl new file mode 100644 index 000000000..73e885a7e --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightAlphaMaskF.glsl @@ -0,0 +1,29 @@ +/** + * @file lightFullbrightAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 fullbrightAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +void fullbright_lighting() +{ + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = fullbrightAtmosTransport(color.rgb); + + color.rgb = fullbrightScaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl index 509ac80b2..52ad40008 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightF.glsl @@ -5,16 +5,14 @@ * $License$ */ -#version 120 -uniform sampler2D diffuseMap; vec3 fullbrightAtmosTransport(vec3 light); vec3 fullbrightScaleSoftClip(vec3 light); void fullbright_lighting() { - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color; + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; color.rgb = fullbrightAtmosTransport(color.rgb); diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl new file mode 100644 index 000000000..55dfe9b16 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedAlphaMaskF.glsl @@ -0,0 +1,31 @@ +/** + * @file lightFullbrightNonIndexedAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 fullbrightAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +uniform sampler2D diffuseMap; + +void fullbright_lighting() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = fullbrightAtmosTransport(color.rgb); + + color.rgb = fullbrightScaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl new file mode 100644 index 000000000..b1e61e1a3 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightNonIndexedF.glsl @@ -0,0 +1,25 @@ +/** + * @file lightFullbrightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +vec3 fullbrightAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +uniform sampler2D diffuseMap; + +void fullbright_lighting() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + color.rgb = fullbrightAtmosTransport(color.rgb); + + color.rgb = fullbrightScaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl index 17a4cb03f..a0050f887 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyF.glsl @@ -5,9 +5,8 @@ * $License$ */ -#version 120 -uniform sampler2D diffuseMap; + uniform samplerCube environmentMap; vec3 fullbrightShinyAtmosTransport(vec3 light); @@ -15,7 +14,7 @@ vec3 fullbrightScaleSoftClip(vec3 light); void fullbright_shiny_lighting() { - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 color = diffuseLookup(gl_TexCoord[0].xy); color.rgb *= gl_Color.rgb; vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl new file mode 100644 index 000000000..953298da0 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyNonIndexedF.glsl @@ -0,0 +1,32 @@ +/** + * @file lightFullbrightShinyF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +uniform samplerCube environmentMap; +uniform sampler2D diffuseMap; + +vec3 fullbrightShinyAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); + +void fullbright_shiny_lighting() +{ + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy); + color.rgb *= gl_Color.rgb; + + vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; + color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a); + + color.rgb = fullbrightShinyAtmosTransport(color.rgb); + + color.rgb = fullbrightScaleSoftClip(color.rgb); + + color.a = max(color.a, gl_Color.a); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl index 9b4b58436..a6e10a249 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterF.glsl @@ -5,9 +5,9 @@ * $License$ */ -#version 120 -uniform sampler2D diffuseMap; + + uniform samplerCube environmentMap; vec3 fullbrightShinyAtmosTransport(vec3 light); @@ -16,7 +16,7 @@ vec4 applyWaterFog(vec4 color); void fullbright_shiny_lighting_water() { - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 color = diffuseLookup(gl_TexCoord[0].xy); color.rgb *= gl_Color.rgb; vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl new file mode 100644 index 000000000..b4bb665a2 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightShinyWaterNonIndexedF.glsl @@ -0,0 +1,32 @@ +/** + * @file lightFullbrightShinyWaterF.glsl + * + * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc. + * $License$ + */ + + + + +uniform samplerCube environmentMap; +uniform sampler2D diffuseMap; + +vec3 fullbrightShinyAtmosTransport(vec3 light); +vec3 fullbrightScaleSoftClip(vec3 light); +vec4 applyWaterFog(vec4 color); + +void fullbright_shiny_lighting_water() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy); + color.rgb *= gl_Color.rgb; + + vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; + color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a); + + color.rgb = fullbrightShinyAtmosTransport(color.rgb); + color.rgb = fullbrightScaleSoftClip(color.rgb); + color.a = max(color.a, gl_Color.a); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterAlphaMaskF.glsl new file mode 100644 index 000000000..e4cea077f --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterAlphaMaskF.glsl @@ -0,0 +1,29 @@ +/** + * @file lightFullbrightWaterAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec4 diffuseLookup(vec2 texcoord); + +vec3 fullbrightAtmosTransport(vec3 light); +vec4 applyWaterFog(vec4 color); + +void fullbright_lighting_water() +{ + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = fullbrightAtmosTransport(color.rgb); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl index 548d1c9ee..667464a02 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterF.glsl @@ -5,16 +5,16 @@ * $License$ */ -#version 120 -uniform sampler2D diffuseMap; + +vec4 diffuseLookup(vec2 texcoord); vec3 fullbrightAtmosTransport(vec3 light); vec4 applyWaterFog(vec4 color); void fullbright_lighting_water() { - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color; + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; color.rgb = fullbrightAtmosTransport(color.rgb); diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl new file mode 100644 index 000000000..e8533f94a --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl @@ -0,0 +1,29 @@ +/** + * @file lightFullbrightWaterNonIndexedAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +uniform sampler2D diffuseMap; + +vec3 fullbrightAtmosTransport(vec3 light); +vec4 applyWaterFog(vec4 color); + +void fullbright_lighting_water() +{ + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = fullbrightAtmosTransport(color.rgb); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl new file mode 100644 index 000000000..1234682ae --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightFullbrightWaterNonIndexedF.glsl @@ -0,0 +1,23 @@ +/** + * @file lightFullbrightWaterF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +uniform sampler2D diffuseMap; + +vec3 fullbrightAtmosTransport(vec3 light); +vec4 applyWaterFog(vec4 color); + +void fullbright_lighting_water() +{ + vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color; + + color.rgb = fullbrightAtmosTransport(color.rgb); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl new file mode 100644 index 000000000..149cf791f --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightNonIndexedF.glsl @@ -0,0 +1,25 @@ +/** + * @file lightF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +uniform sampler2D diffuseMap; + +vec3 atmosLighting(vec3 light); +vec3 scaleSoftClip(vec3 light); + +void default_lighting() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl index 675fd4adf..ef8c2602d 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyF.glsl @@ -5,9 +5,9 @@ * $License$ */ -#version 120 -uniform sampler2D diffuseMap; + + uniform samplerCube environmentMap; vec3 scaleSoftClip(vec3 light); @@ -16,7 +16,7 @@ vec4 applyWaterFog(vec4 color); void shiny_lighting() { - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 color = diffuseLookup(gl_TexCoord[0].xy); color.rgb *= gl_Color.rgb; vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl new file mode 100644 index 000000000..e877c0abb --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyNonIndexedF.glsl @@ -0,0 +1,32 @@ +/** + * @file lightShinyF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + + +uniform samplerCube environmentMap; +uniform sampler2D diffuseMap; + +vec3 scaleSoftClip(vec3 light); +vec3 atmosLighting(vec3 light); +vec4 applyWaterFog(vec4 color); + +void shiny_lighting() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy); + color.rgb *= gl_Color.rgb; + + vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; + color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a); + + color.rgb = atmosLighting(color.rgb); + + color.rgb = scaleSoftClip(color.rgb); + color.a = max(color.a, gl_Color.a); + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl index 4e8a0d189..8885aae09 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterF.glsl @@ -5,10 +5,9 @@ * $License$ */ -#version 120 -uniform sampler2D diffuseMap; + uniform samplerCube environmentMap; vec3 atmosLighting(vec3 light); @@ -16,7 +15,7 @@ vec4 applyWaterFog(vec4 color); void shiny_lighting_water() { - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy); + vec4 color = diffuseLookup(gl_TexCoord[0].xy); color.rgb *= gl_Color.rgb; vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl new file mode 100644 index 000000000..390417942 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightShinyWaterNonIndexedF.glsl @@ -0,0 +1,29 @@ +/** + * @file lightShinyWaterF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + + +uniform sampler2D diffuseMap; +uniform samplerCube environmentMap; + +vec3 atmosLighting(vec3 light); +vec4 applyWaterFog(vec4 color); + +void shiny_lighting_water() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy); + color.rgb *= gl_Color.rgb; + + vec3 envColor = textureCube(environmentMap, gl_TexCoord[1].xyz).rgb; + color.rgb = mix(color.rgb, envColor.rgb, gl_Color.a); + + color.rgb = atmosLighting(color.rgb); + color.a = max(color.a, gl_Color.a); + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl index 4e9fa16a1..f324ae939 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightSpecularV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + // All lights, no specular highlights diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl index 75c0d7414..5971c22bc 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + // All lights, no specular highlights diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskF.glsl new file mode 100644 index 000000000..7b3c20f09 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskF.glsl @@ -0,0 +1,27 @@ +/** + * @file lightWaterAlphaMaskF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +vec3 atmosLighting(vec3 light); +vec4 applyWaterFog(vec4 color); + +void default_lighting_water() +{ + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = atmosLighting(color.rgb); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskNonIndexedF.glsl new file mode 100644 index 000000000..907140eff --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterAlphaMaskNonIndexedF.glsl @@ -0,0 +1,31 @@ +/** + * @file lightWaterAlphaMaskNonIndexedF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + +uniform float minimum_alpha; +uniform float maximum_alpha; + +uniform sampler2D diffuseMap; + +vec3 atmosLighting(vec3 light); +vec4 applyWaterFog(vec4 color); + +void default_lighting_water() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + if (color.a < minimum_alpha || color.a > maximum_alpha) + { + discard; + } + + color.rgb = atmosLighting(color.rgb); + + color = applyWaterFog(color); + + gl_FragColor = color; +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl index 64df7f0f9..9c5d07832 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterF.glsl @@ -5,16 +5,14 @@ * $License$ */ -#version 120 -uniform sampler2D diffuseMap; vec3 atmosLighting(vec3 light); vec4 applyWaterFog(vec4 color); void default_lighting_water() { - vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * gl_Color; + vec4 color = diffuseLookup(gl_TexCoord[0].xy) * gl_Color; color.rgb = atmosLighting(color.rgb); diff --git a/indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl b/indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl new file mode 100644 index 000000000..ba850b61d --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/lighting/lightWaterNonIndexedF.glsl @@ -0,0 +1,23 @@ +/** + * @file lightWaterF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +uniform sampler2D diffuseMap; + +vec3 atmosLighting(vec3 light); +vec4 applyWaterFog(vec4 color); + +void default_lighting_water() +{ + vec4 color = texture2D(diffuseMap,gl_TexCoord[0].xy) * gl_Color; + + color.rgb = atmosLighting(color.rgb); + + gl_FragColor = applyWaterFog(color); +} + diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl index 2408e11d9..9b5c565de 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsSpecularV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol); diff --git a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl index 5f5b426da..dab7ba6d2 100644 --- a/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class2/lighting/sumLightsV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLight(vec3 n, vec3 l); float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); diff --git a/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl new file mode 100644 index 000000000..f49e74406 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/objects/fullbrightShinyV.glsl @@ -0,0 +1,35 @@ +/** + * @file fullbrightShinyV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void calcAtmospherics(vec3 inPositionEye); + +uniform vec4 origin; + +varying float vary_texture_index; + +void main() +{ + //transform vertex + vec4 vert = vec4(gl_Vertex.xyz,1.0); + vary_texture_index = gl_Vertex.w; + gl_Position = gl_ModelViewProjectionMatrix*vert; + + vec4 pos = (gl_ModelViewMatrix * vert); + vec3 norm = normalize(gl_NormalMatrix * gl_Normal); + vec3 ref = reflect(pos.xyz, -norm); + + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + gl_TexCoord[1] = gl_TextureMatrix[1]*vec4(ref,1.0); + + calcAtmospherics(pos.xyz); + + gl_FrontColor = gl_Color; + + gl_FogFragCoord = pos.z; +} diff --git a/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl new file mode 100644 index 000000000..3076fa326 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/objects/fullbrightV.glsl @@ -0,0 +1,29 @@ +/** + * @file fullbrightV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +void calcAtmospherics(vec3 inPositionEye); + +varying float vary_texture_index; + +void main() +{ + //transform vertex + vec4 vert = vec4(gl_Vertex.xyz,1.0); + vary_texture_index = gl_Vertex.w; + gl_Position = gl_ModelViewProjectionMatrix*vert; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vec4 pos = (gl_ModelViewMatrix * vert); + + calcAtmospherics(pos.xyz); + + gl_FrontColor = gl_Color; + + gl_FogFragCoord = pos.z; +} diff --git a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl index 76e96cb27..29d4a9a32 100755 --- a/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl +++ b/indra/newview/app_settings/shaders/class2/objects/shinyV.glsl @@ -5,20 +5,24 @@ * $License$ */ -#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); void calcAtmospherics(vec3 inPositionEye); +varying float vary_texture_index; + uniform vec4 origin; void main() { //transform vertex - gl_Position = ftransform(); + vec4 vert = vec4(gl_Vertex.xyz,1.0); + vary_texture_index = gl_Vertex.w; + gl_Position = gl_ModelViewProjectionMatrix*vert; - vec4 pos = (gl_ModelViewMatrix * gl_Vertex); + vec4 pos = (gl_ModelViewMatrix * vert); vec3 norm = normalize(gl_NormalMatrix * gl_Normal); vec3 ref = reflect(pos.xyz, -norm); diff --git a/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl new file mode 100644 index 000000000..5e0239176 --- /dev/null +++ b/indra/newview/app_settings/shaders/class2/objects/simpleV.glsl @@ -0,0 +1,33 @@ +/** + * @file simpleV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * $/LicenseInfo$ + */ + + + +vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); +void calcAtmospherics(vec3 inPositionEye); + +varying float vary_texture_index; + +void main() +{ + //transform vertex + vec4 vert = vec4(gl_Vertex.xyz,1.0); + vary_texture_index = gl_Vertex.w; + gl_Position = gl_ModelViewProjectionMatrix*vert; + gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0; + + vec4 pos = (gl_ModelViewMatrix * vert); + + vec3 norm = normalize(gl_NormalMatrix * gl_Normal); + + calcAtmospherics(pos.xyz); + + vec4 color = calcLighting(pos.xyz, norm, gl_Color, vec4(0.)); + gl_FrontColor = color; + + gl_FogFragCoord = pos.z; +} diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl index 80da3ee23..dabd34f08 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + ////////////////////////////////////////////////////////// // The fragment shader for the terrain atmospherics diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl index c806655dc..83cd447a5 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsHelpersV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + // Output variables vec3 getSunlitColor(); diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl index 8b73c07ac..9c00c81f3 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + // varying param funcs void setSunlitColor(vec3 v); diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl index 3a5eeb853..f4378d6af 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl index aef449775..807812324 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + varying vec3 vary_PositionEye; diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl index 69262ec7d..d3b742542 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + ///////////////////////////////////////////////////////////////////////// // The fragment shader for the sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl index 881bb90b8..16f9ec285 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + ////////////////////////////////////////////////////////////////////////// // The vertex shader for creating the atmospheric sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl index 3ca7a962d..964fdef45 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/gammaF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + uniform vec4 gamma; diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl index 6737d2617..a1507b8cd 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/skyF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + ///////////////////////////////////////////////////////////////////////// // The fragment shader for the sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl index e1a6844d2..a857a4cc7 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + // SKY //////////////////////////////////////////////////////////////////////// // The vertex shader for creating the atmospheric sky diff --git a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl index e1e385496..34f8dadac 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/transportF.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + ////////////////////////////////////////////////////////// // The fragment shader for the terrain atmospherics diff --git a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl index 1b6e843c0..648ebef94 100644 --- a/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl +++ b/indra/newview/app_settings/shaders/class3/avatar/avatarV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); mat4 getSkinnedTransform(); diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl index fc370ef36..498fee7c6 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + uniform sampler2DRect giLightMap; diff --git a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl index ae57227fe..eebe93066 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giDownsampleV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl index 951e3e97a..9896f8daf 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl index b2f8b2c63..df4c6b3e0 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl index 19c4e07b8..7e20d7152 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giFinalV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl index 8dc1410ea..e86f2896d 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/giV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/giV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl index 5f3bf68b2..980def644 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl index a24eda35d..9afeac6dd 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/luminanceV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl index ab99a8897..6d4c20f68 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl index 12983baa9..876f65ee3 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/postDeferredV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl index f03775470..fc6588168 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/postgiF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable diff --git a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl index ae57227fe..eebe93066 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/postgiV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + varying vec2 vary_fragcoord; uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl index 56f3f9697..69e79bd94 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + #extension GL_ARB_texture_rectangle : enable @@ -266,91 +266,50 @@ void main() float da = max(dot(norm.xyz, vary_light.xyz), 0.0); vec4 diffuse = texture2DRect(diffuseRect, tc); - vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - - da = texture2D(lightFunc, vec2(da, 0.0)).a; - - vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; - float scol = max(scol_ambocc.r, diffuse.a); - float ambocc = scol_ambocc.g; - - calcAtmospherics(pos.xyz, ambocc); - - vec3 col = atmosAmbient(vec3(0)); - col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); - - col *= diffuse.rgb; - - if (spec.a > 0.0) // specular reflection + vec3 col; + float bloom = 0.0; + + if (diffuse.a < 0.9) { - // the old infinite-sky shiny reflection - // - vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); - float sa = dot(refnormpersp, vary_light.xyz); - vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a; - - /* - // screen-space cheap fakey reflection map - // - vec3 refnorm = normalize(reflect(vec3(0,0,-1), norm.xyz)); - depth -= 0.5; // unbias depth - // first figure out where we'll make our 2D guess from - vec2 ref2d = (0.25 * screen_res.y) * (refnorm.xy) * abs(refnorm.z) / depth; - // Offset the guess source a little according to a trivial - // checkerboard dither function and spec.a. - // This is meant to be similar to sampling a blurred version - // of the diffuse map. LOD would be better in that regard. - // The goal of the blur is to soften reflections in surfaces - // with low shinyness, and also to disguise our lameness. - float checkerboard = floor(mod(tc.x+tc.y, 2.0)); // 0.0, 1.0 - float checkoffset = (3.0 + (7.0*(1.0-spec.a)))*(checkerboard-0.5); - - ref2d += vec2(checkoffset, checkoffset); - ref2d += tc.xy; // use as offset from destination - // Get attributes from the 2D guess point. - // We average two samples of diffuse (not of anything else) per - // pixel to try to reduce aliasing some more. - vec3 refcol = 0.5 * (texture2DRect(diffuseRect, ref2d + vec2(0.0, -checkoffset)).rgb + - texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb); - float refdepth = texture2DRect(depthMap, ref2d).a; - vec3 refpos = getPosition_d(ref2d, refdepth).xyz; - float refshad = texture2DRect(lightMap, ref2d).r; - vec3 refn = texture2DRect(normalMap, ref2d).rgb; - refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm - refn = normalize(refn); - // figure out how appropriate our guess actually was - float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos))); - // darken reflections from points which face away from the reflected ray - our guess was a back-face - //refapprop *= step(dot(refnorm, refn), 0.0); - refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant - // get appropriate light strength for guess-point. - // reflect light direction to increase the illusion that - // these are reflections. - vec3 reflight = reflect(lightnorm.xyz, norm.xyz); - float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad); - // apply sun color to guess-point, dampen according to inappropriateness of guess - float refmod = min(refapprop, reflit); - vec3 refprod = vary_SunlitColor * refcol.rgb * refmod; - vec3 ssshiny = (refprod * spec.a); - ssshiny *= 0.3; // dampen it even more - */ - vec3 ssshiny = vec3(0,0,0); - - // add the two types of shiny together - col += (ssshiny + dumbshiny) * spec.rgb; - } + vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy); - col = atmosLighting(col); - col = scaleSoftClip(col); + da = texture2D(lightFunc, vec2(da, 0.0)).a; + + vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg; + float scol = max(scol_ambocc.r, diffuse.a); + float ambocc = scol_ambocc.g; + + calcAtmospherics(pos.xyz, ambocc); + + col = atmosAmbient(vec3(0)); + col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a)); + + col *= diffuse.rgb; + + if (spec.a > 0.0) // specular reflection + { + // the old infinite-sky shiny reflection + // + vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz)); + float sa = dot(refnormpersp, vary_light.xyz); + vec3 dumbshiny = vary_SunlitColor*scol*texture2D(lightFunc, vec2(sa, spec.a)).a; + + // add the two types of shiny together + vec3 spec_contrib = dumbshiny * spec.rgb; + bloom = dot(spec_contrib, spec_contrib); + col += spec_contrib; + } + + col = atmosLighting(col); + col = scaleSoftClip(col); + + col = mix(col, diffuse.rgb, diffuse.a); + } + else + { + col = diffuse.rgb; + } gl_FragColor.rgb = col; - - //gl_FragColor.rgb = gi_col.rgb; - gl_FragColor.a = 0.0; - - //gl_FragColor.rg = scol_ambocc.rg; - //gl_FragColor.rgb = texture2DRect(lightMap, vary_fragcoord.xy).rgb; - //gl_FragColor.rgb = norm.rgb*0.5+0.5; - //gl_FragColor.rgb = vec3(ambocc); - //gl_FragColor.rgb = vec3(scol); + gl_FragColor.a = bloom; } diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl index 8f0bcca76..745cc0199 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightV.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + uniform vec2 screen_res; diff --git a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl index c54d9a1e3..de7e03840 100644 --- a/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl +++ b/indra/newview/app_settings/shaders/class3/deferred/treeF.glsl @@ -5,7 +5,7 @@ * $/LicenseInfo$ */ -#version 120 + uniform sampler2D diffuseMap; diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl index ee61162c0..f59175972 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsSpecularV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLightSpecular(inout vec4 specular, vec3 view, vec3 n, vec3 l, vec3 lightCol, float da); vec3 calcPointLightSpecular(inout vec4 specular, vec3 view, vec3 v, vec3 n, vec3 l, float r, float pw, vec3 lightCol); diff --git a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl index ae84fcb9c..b8d03284e 100644 --- a/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl +++ b/indra/newview/app_settings/shaders/class3/lighting/sumLightsV.glsl @@ -5,7 +5,7 @@ * $License$ */ -#version 120 + float calcDirectionalLight(vec3 n, vec3 l); float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight); diff --git a/indra/newview/ascentprefschat.cpp b/indra/newview/ascentprefschat.cpp index bd52eb5f0..f80d86a22 100644 --- a/indra/newview/ascentprefschat.cpp +++ b/indra/newview/ascentprefschat.cpp @@ -491,6 +491,8 @@ void LLPrefsAscentChat::cancel() // Update local copy so cancel has no effect void LLPrefsAscentChat::apply() { + gSavedPerAccountSettings.setString("AscentInstantMessageResponse", childGetValue("im_response")); + refreshValues(); refresh(); } diff --git a/indra/newview/dofloaterhex.cpp b/indra/newview/dofloaterhex.cpp index 90cc9b321..c74aff66e 100644 --- a/indra/newview/dofloaterhex.cpp +++ b/indra/newview/dofloaterhex.cpp @@ -23,6 +23,7 @@ #include "llinventorymodel.h" // gInventory.updateItem #include "llappviewer.h" // System Folders #include "llfloaterperms.h" //get default perms +#include "llnotificationsutil.h" std::list<DOFloaterHex*> DOFloaterHex::sInstances; S32 DOFloaterHex::sUploadAmount = 10; @@ -291,7 +292,7 @@ void DOFloaterHex::onClickUpload(void* user_data) { LLSD args; args["ERROR_MESSAGE"] = "Couldn't write data to file"; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); return; } delete[] buffer; @@ -366,7 +367,7 @@ void DOFloaterHex::onClickSave(void* user_data) { LLSD args; args["ERROR_MESSAGE"] = "Couldn't write data to file"; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); return; } delete[] buffer; @@ -431,7 +432,7 @@ void DOFloaterHex::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 { LLSD args; args["ERROR_MESSAGE"] = llformat("Upload failed with status %d, also %d", status, ext_status); - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); } } diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index e3a8ca0de..9b91d32f8 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -1,4 +1,4 @@ -version 20 +version 32 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences // Should be combined into one table @@ -23,9 +23,11 @@ version 20 // NOTE: All settings are set to the MIN of applied values, including 'all'! // list all -RenderAnisotropic 1 0 +RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxVisible 1 12 RenderAvatarVP 1 1 RenderCubeMap 1 1 RenderFarClip 1 256 @@ -34,12 +36,13 @@ RenderFogRatio 1 4.0 RenderGamma 1 0 RenderGlowResolutionPow 1 9 RenderGround 1 1 -RenderLocalLights 1 1 RenderMaxPartCount 1 8192 RenderObjectBump 1 1 +RenderLocalLights 1 1 RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVBOEnable 1 1 @@ -51,14 +54,16 @@ WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 -RenderShaderLightingMaxLevel 1 3 RenderTextureMemoryMultiple 1 1.0 -RenderUseFBO 1 1 -RenderFastAlpha 1 1 +RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 -RenderDeferredGI 1 1 +RenderDeferredSSAO 1 1 RenderShadowDetail 1 2 -RenderAvatarPhysicsLODFactor 1 1.0 +WatchdogDisabled 1 1 +ShyotlRenderUseStreamVBO 1 1 +RenderDeferredGI 1 0 +RenderFastAlpha 1 1 +RenderUseFBO 1 1 // // Low Graphics Settings @@ -66,29 +71,32 @@ RenderAvatarPhysicsLODFactor 1 1.0 list Low RenderAnisotropic 1 0 RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0.25 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 RenderAvatarVP 1 0 RenderFarClip 1 64 -RenderFlexTimeFactor 1 0.1 +RenderFlexTimeFactor 1 0 RenderGlowResolutionPow 1 8 -RenderLocalLights 1 0 RenderMaxPartCount 1 1024 RenderObjectBump 1 0 +RenderLocalLights 1 0 RenderReflectionDetail 1 0 RenderTerrainDetail 1 0 RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 RenderTreeLODFactor 1 0.25 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 VertexShaderEnable 1 0 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 0 0 -RenderFastAlpha 1 1 -RenderDeferred 0 0 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 RenderDeferredGI 0 0 -RenderShadowDetail 0 0 -RenderAvatarPhysicsLODFactor 1 0.0 +RenderFastAlpha 1 1 +RenderUseFBO 1 0 // // Mid Graphics Settings @@ -97,28 +105,30 @@ list Mid RenderAnisotropic 1 0 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 +RenderAvatarPhysicsLODFactor 1 0.5 RenderAvatarVP 1 1 RenderFarClip 1 96 -RenderFlexTimeFactor 1 0.5 +RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 -RenderLocalLights 1 1 RenderMaxPartCount 1 2048 RenderObjectBump 1 1 +RenderLocalLights 1 1 RenderReflectionDetail 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 1.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderFastAlpha 1 0 RenderDeferred 1 0 -RenderDeferredGI 1 0 +RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderAvatarPhysicsLODFactor 1 0.5 +RenderDeferredGI 1 0 +RenderFastAlpha 1 0 +RenderUseFBO 1 0 // @@ -128,29 +138,30 @@ list High RenderAnisotropic 1 1 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 .75 RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLocalLights 1 1 RenderMaxPartCount 1 4096 RenderObjectBump 1 1 +RenderLocalLights 1 1 RenderReflectionDetail 1 2 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderFastAlpha 1 0 RenderDeferred 1 0 -RenderDeferredGI 1 0 +RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderAvatarPhysicsLODFactor 1 0.75 - +RenderDeferredGI 1 0 +RenderFastAlpha 1 0 +RenderUseFBO 1 0 // // Ultra graphics (REALLY PURTY!) @@ -163,24 +174,25 @@ RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 9 -RenderLocalLights 1 1 RenderMaxPartCount 1 8192 RenderObjectBump 1 1 +RenderLocalLights 1 1 RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 2.0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 -RenderUseFBO 1 1 -RenderFastAlpha 1 0 RenderDeferred 1 1 -RenderDeferredGI 1 0 +RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderAvatarPhysicsLODFactor 1 1.0 +RenderDeferredGI 1 0 +RenderFastAlpha 1 0 +RenderUseFBO 1 1 // // Class Unknown Hardware (unknown) @@ -222,6 +234,8 @@ RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 // // No Vertex Shaders available @@ -233,6 +247,8 @@ RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 // "Default" setups for safe, low, medium, high // @@ -240,16 +256,18 @@ list safe RenderAnisotropic 1 0 RenderAvatarCloth 0 0 RenderAvatarVP 0 0 -RenderLocalLights 1 0 RenderObjectBump 0 0 +RenderLocalLights 1 0 RenderMaxPartCount 1 1024 RenderTerrainDetail 1 0 RenderUseImpostors 0 0 RenderVBOEnable 1 0 RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 -RenderUseFBO 1 0 -RenderDeferred 1 0 +RenderUseFBO 0 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 // // CPU based feature masks @@ -271,10 +289,12 @@ RenderObjectBump 0 0 list OpenGLPre15 RenderVBOEnable 1 0 +list OpenGLPre30 +RenderDeferred 0 0 list Intel RenderAnisotropic 1 0 +RenderVBOEnable 1 0 RenderLocalLights 1 0 -RenderUseImpostors 0 0 RenderDeferred 1 0 list GeForce2 @@ -291,30 +311,37 @@ UseOcclusion 0 0 list Intel_830M RenderTerrainDetail 1 0 RenderVBOEnable 1 0 +RenderUseImpostors 0 0 list Intel_845G RenderTerrainDetail 1 0 RenderVBOEnable 1 0 +RenderUseImpostors 0 0 list Intel_855GM RenderTerrainDetail 1 0 RenderVBOEnable 1 0 +RenderUseImpostors 0 0 list Intel_865G RenderTerrainDetail 1 0 RenderVBOEnable 1 0 +RenderUseImpostors 0 0 list Intel_900 RenderTerrainDetail 1 0 RenderVBOEnable 1 0 +RenderUseImpostors 0 0 list Intel_915GM RenderTerrainDetail 1 0 RenderVBOEnable 1 0 +RenderUseImpostors 0 0 list Intel_915G RenderTerrainDetail 1 0 RenderVBOEnable 1 0 +RenderUseImpostors 0 0 list Intel_945GM RenderTerrainDetail 1 0 @@ -449,6 +476,14 @@ list ATIOldDriver RenderAvatarVP 0 0 RenderAvatarCloth 0 0 +// ATI cards generally perform better when not using VBOs for streaming data + +list ATI +ShyotlRenderUseStreamVBO 1 0 + +// Disable vertex buffer objects by default for ATI cards with little video memory +list ATIVramLT256 +RenderVBOEnable 1 0 /// Tweaked NVIDIA diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index e64bfa3e3..97dda7be6 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -1,4 +1,4 @@ -version 20 +version 27 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences // Should be combined into one table @@ -26,6 +26,8 @@ list all RenderAnisotropic 1 0 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxVisible 1 12 RenderAvatarVP 1 1 RenderCubeMap 1 1 RenderFarClip 1 256 @@ -40,6 +42,7 @@ RenderObjectBump 1 1 RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVBOEnable 1 1 @@ -51,14 +54,14 @@ WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 -RenderShaderLightingMaxLevel 1 3 RenderTextureMemoryMultiple 1 1.0 -RenderUseFBO 1 1 -RenderFastAlpha 1 1 +RenderShaderLightingMaxLevel 1 3 RenderDeferred 1 1 -RenderDeferredGI 1 1 +RenderDeferredSSAO 1 1 RenderShadowDetail 1 2 -RenderAvatarPhysicsLODFactor 1 1.0 +RenderDeferredGI 1 0 +RenderFastAlpha 1 1 +RenderUseFBO 1 1 // // Low Graphics Settings @@ -66,10 +69,12 @@ RenderAvatarPhysicsLODFactor 1 1.0 list Low RenderAnisotropic 1 0 RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0.25 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 RenderAvatarVP 1 0 RenderFarClip 1 64 -RenderFlexTimeFactor 1 0.1 +RenderFlexTimeFactor 1 0 RenderGlowResolutionPow 1 8 RenderLocalLights 1 0 RenderMaxPartCount 1 1024 @@ -77,18 +82,19 @@ RenderObjectBump 1 0 RenderReflectionDetail 1 0 RenderTerrainDetail 1 0 RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 RenderTreeLODFactor 1 0.25 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 VertexShaderEnable 1 0 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 0 0 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderDeferredGI 1 0 RenderFastAlpha 1 1 -RenderDeferred 0 0 -RenderDeferredGI 0 0 -RenderShadowDetail 0 0 -RenderAvatarPhysicsLODFactor 1 0.0 +RenderUseFBO 1 0 // // Mid Graphics Settings @@ -97,9 +103,10 @@ list Mid RenderAnisotropic 1 0 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 +RenderAvatarPhysicsLODFactor 1 0.5 RenderAvatarVP 1 1 RenderFarClip 1 96 -RenderFlexTimeFactor 1 0.5 +RenderFlexTimeFactor 1 1.0 RenderGlowResolutionPow 1 8 RenderLocalLights 1 1 RenderMaxPartCount 1 2048 @@ -107,19 +114,19 @@ RenderObjectBump 1 1 RenderReflectionDetail 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 1.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderFastAlpha 1 0 RenderDeferred 1 0 -RenderDeferredGI 1 0 +RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderAvatarPhysicsLODFactor 1 0.5 - +RenderDeferredGI 1 0 +RenderFastAlpha 1 0 +RenderUseFBO 1 0 // // High Graphics Settings (purty) @@ -128,6 +135,7 @@ list High RenderAnisotropic 1 1 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 0.75 RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 @@ -138,18 +146,19 @@ RenderObjectBump 1 1 RenderReflectionDetail 1 2 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderFastAlpha 1 0 RenderDeferred 1 0 -RenderDeferredGI 1 0 +RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderAvatarPhysicsLODFactor 1 0.75 +RenderDeferredGI 1 0 +RenderFastAlpha 1 0 +RenderUseFBO 1 0 // @@ -159,6 +168,7 @@ list Ultra RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 @@ -169,18 +179,20 @@ RenderObjectBump 1 1 RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 2.0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 -RenderUseFBO 1 1 -RenderFastAlpha 1 0 RenderDeferred 1 1 -RenderDeferredGI 1 0 +RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderAvatarPhysicsLODFactor 1 1.0 +RenderDeferredGI 1 0 +RenderFastAlpha 1 0 +RenderUseFBO 1 1 + // @@ -223,6 +235,8 @@ RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 // // No Vertex Shaders available @@ -234,6 +248,8 @@ RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 // "Default" setups for safe, low, medium, high // @@ -249,9 +265,13 @@ RenderUseImpostors 0 0 RenderVBOEnable 1 0 RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 -RenderUseFBO 1 0 -RenderDeferred 1 0 - +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 +RenderShadowDetail 0 0 +RenderDeferredGI 0 0 +RenderFastAlpha 0 0 +RenderUseFBO 0 0 // // CPU based feature masks @@ -494,17 +514,47 @@ list NVIDIA_GeForce_Go_6 RenderVBOEnable 1 0 Disregard128DefaultDrawDistance 1 0 +list NVIDIA_GeForce_7000 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7100 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7200 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7300 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_7400 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7500 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_7900 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7200 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7300 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7300_LE +RenderShaderLightingMaxLevel 1 2 list NVIDIA_GeForce_Go_7400 Disregard128DefaultDrawDistance 1 0 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7600 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7700 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7800 +RenderShaderLightingMaxLevel 1 2 +list NVIDIA_GeForce_Go_7900 +RenderShaderLightingMaxLevel 1 2 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 16156fe42..61afc26ab 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -1,4 +1,4 @@ -version 20 +version 30 // NOTE: This is mostly identical to featuretable_mac.txt with a few differences // Should be combined into one table @@ -25,8 +25,10 @@ version 20 list all RenderAnisotropic 1 0 RenderAvatarCloth 1 1 -RenderAvatarLODFactor 1 1.0 -RenderAvatarVP 1 1 +RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 +RenderAvatarMaxVisible 1 12 +RenderAvatarVP 1 1 RenderCubeMap 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 @@ -39,10 +41,11 @@ RenderMaxPartCount 1 8192 RenderObjectBump 1 1 RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 -RenderTerrainLODFactor 1 2.0 +RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 -RenderVBOEnable 1 1 +RenderVBOEnable 1 0 RenderVolumeLODFactor 1 2.0 UseStartScreen 1 1 UseOcclusion 1 1 @@ -51,14 +54,19 @@ WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 Disregard128DefaultDrawDistance 1 1 Disregard96DefaultDrawDistance 1 1 +RenderTextureMemoryMultiple 1 0.5 RenderShaderLightingMaxLevel 1 3 -RenderTextureMemoryMultiple 1 1.0 -RenderUseFBO 1 1 -RenderFastAlpha 1 1 + + RenderDeferred 1 1 -RenderDeferredGI 1 1 + RenderShadowDetail 1 2 -RenderAvatarPhysicsLODFactor 1 1.0 +WatchdogDisabled 1 1 +ShyotlRenderUseStreamVBO 1 0 +RenderDeferredGI 1 1 +RenderFastAlpha 1 1 +RenderUseFBO 1 1 + // // Low Graphics Settings @@ -66,10 +74,12 @@ RenderAvatarPhysicsLODFactor 1 1.0 list Low RenderAnisotropic 1 0 RenderAvatarCloth 1 0 -RenderAvatarLODFactor 1 0.25 +RenderAvatarLODFactor 1 0 +RenderAvatarPhysicsLODFactor 1 0 +RenderAvatarMaxVisible 1 3 RenderAvatarVP 1 0 RenderFarClip 1 64 -RenderFlexTimeFactor 1 0.1 +RenderFlexTimeFactor 1 0 RenderGlowResolutionPow 1 8 RenderLocalLights 1 0 RenderMaxPartCount 1 1024 @@ -77,18 +87,19 @@ RenderObjectBump 1 0 RenderReflectionDetail 1 0 RenderTerrainDetail 1 0 RenderTerrainLODFactor 1 1 +RenderTransparentWater 1 0 RenderTreeLODFactor 1 0.25 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 0.5 VertexShaderEnable 1 0 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 0 0 +RenderDeferred 1 0 +RenderDeferredSSAO 1 0 +RenderShadowDetail 1 0 +RenderDeferredGI 1 0 +RenderUseFBO 1 0 RenderFastAlpha 1 1 -RenderDeferred 0 0 -RenderDeferredGI 0 0 -RenderShadowDetail 0 0 -RenderAvatarPhysicsLODFactor 1 0.0 // // Mid Graphics Settings @@ -97,6 +108,7 @@ list Mid RenderAnisotropic 1 0 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 0.5 +RenderAvatarPhysicsLODFactor 1 0.5 RenderAvatarVP 1 1 RenderFarClip 1 96 RenderFlexTimeFactor 1 0.5 @@ -107,18 +119,19 @@ RenderObjectBump 1 1 RenderReflectionDetail 1 0 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 1.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 0 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderFastAlpha 1 0 RenderDeferred 1 0 -RenderDeferredGI 1 0 +RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderAvatarPhysicsLODFactor 1 0.5 +RenderDeferredGI 1 0 +RenderFastAlpha 1 0 +RenderUseFBO 1 0 // @@ -128,6 +141,7 @@ list High RenderAnisotropic 1 1 RenderAvatarCloth 1 0 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 0.75 RenderAvatarVP 1 1 RenderFarClip 1 128 RenderFlexTimeFactor 1 1.0 @@ -138,18 +152,19 @@ RenderObjectBump 1 1 RenderReflectionDetail 1 2 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 0.5 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 1.125 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 48 -RenderUseFBO 1 0 -RenderFastAlpha 1 0 RenderDeferred 1 0 -RenderDeferredGI 1 0 +RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderAvatarPhysicsLODFactor 1 0.75 +RenderDeferredGI 1 0 +RenderFastAlpha 1 0 +RenderUseFBO 1 0 // @@ -159,6 +174,7 @@ list Ultra RenderAnisotropic 1 1 RenderAvatarCloth 1 1 RenderAvatarLODFactor 1 1.0 +RenderAvatarPhysicsLODFactor 1 1.0 RenderAvatarVP 1 1 RenderFarClip 1 256 RenderFlexTimeFactor 1 1.0 @@ -169,18 +185,19 @@ RenderObjectBump 1 1 RenderReflectionDetail 1 4 RenderTerrainDetail 1 1 RenderTerrainLODFactor 1 2.0 +RenderTransparentWater 1 1 RenderTreeLODFactor 1 1.0 RenderUseImpostors 1 1 RenderVolumeLODFactor 1 2.0 VertexShaderEnable 1 1 WindLightUseAtmosShaders 1 1 WLSkyDetail 1 128 -RenderUseFBO 1 1 -RenderFastAlpha 1 0 RenderDeferred 1 1 -RenderDeferredGI 1 0 +RenderDeferredSSAO 1 0 RenderShadowDetail 1 0 -RenderAvatarPhysicsLODFactor 1 1.0 +RenderDeferredGI 1 0 +RenderFastAlpha 1 0 +RenderUseFBO 1 1 // // Class Unknown Hardware (unknown) @@ -222,6 +239,8 @@ RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 // // No Vertex Shaders available @@ -233,7 +252,10 @@ RenderReflectionDetail 0 0 VertexShaderEnable 0 0 WindLightUseAtmosShaders 0 0 RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 +// // "Default" setups for safe, low, medium, high // list safe @@ -248,8 +270,10 @@ RenderUseImpostors 0 0 RenderVBOEnable 1 0 RenderReflectionDetail 0 0 WindLightUseAtmosShaders 0 0 -RenderUseFBO 1 0 -RenderDeferred 1 0 +RenderDeferred 0 0 +RenderDeferredSSAO 0 0 +RenderShadowDetail 0 0 +RenderUseFBO 0 0 // // CPU based feature masks @@ -271,10 +295,15 @@ RenderObjectBump 0 0 list OpenGLPre15 RenderVBOEnable 1 0 +list TexUnit8orLess +RenderDeferredSSAO 0 0 + +list ATI +RenderDeferredSSAO 1 0 + list Intel RenderAnisotropic 1 0 RenderLocalLights 1 0 -RenderDeferred 1 0 list GeForce2 RenderAnisotropic 1 0 @@ -407,23 +436,23 @@ Disregard128DefaultDrawDistance 1 0 // invisible avatars on HD 2600... so I masked // out other possible bad ones till it's fixed -list ATI_Radeon_HD_2300 -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_HD_2400 -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -Disregard128DefaultDrawDistance 1 0 -list ATI_Radeon_HD_2600 -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -list ATI_Radeon_HD_2900 -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 -list ATI_Radeon_HD_3800 -RenderAvatarVP 0 0 -RenderAvatarCloth 0 0 +//list ATI_Radeon_HD_2300 +//RenderAvatarVP 0 0 +//RenderAvatarCloth 0 0 +//Disregard128DefaultDrawDistance 1 0 +//list ATI_Radeon_HD_2400 +//RenderAvatarVP 0 0 +//RenderAvatarCloth 0 0 +//Disregard128DefaultDrawDistance 1 0 +//list ATI_Radeon_HD_2600 +//RenderAvatarVP 0 0 +//RenderAvatarCloth 0 0 +//list ATI_Radeon_HD_2900 +//RenderAvatarVP 0 0 +//RenderAvatarCloth 0 0 +//list ATI_Radeon_HD_3800 +//RenderAvatarVP 0 0 +//RenderAvatarCloth 0 0 /// Tweaked NVIDIA diff --git a/indra/newview/featuretable_solaris.txt b/indra/newview/featuretable_solaris.txt index f24cbde5e..7df75687f 100644 --- a/indra/newview/featuretable_solaris.txt +++ b/indra/newview/featuretable_solaris.txt @@ -37,6 +37,9 @@ VertexShaderEnable 1 1 RenderTextureMemoryMultiple 1 1.0 UseOcclusion 1 1 RenderCubeMap 1 1 +WatchdogDisabled 1 1 +RenderUseFBO 1 1 + // // Class 0 Hardware (Unknown or just old) @@ -50,6 +53,7 @@ RenderAvatarMode 1 0 RenderLighting 1 0 RenderObjectBump 1 0 RenderRippleWater 1 0 +RenderUseFBO 1 0 // // Class 1 Hardware @@ -63,6 +67,7 @@ RenderAvatarMode 1 0 RenderLighting 1 0 RenderObjectBump 1 0 RenderRippleWater 1 0 +RenderUseFBO 1 0 // // Class 2 Hardware (make it purty) @@ -74,6 +79,7 @@ RenderAvatarMode 1 1 RenderLighting 1 1 RenderObjectBump 1 1 RenderRippleWater 1 1 +RenderUseFBO 1 1 // // Class 3 Hardware (make it purty) @@ -85,6 +91,7 @@ RenderAvatarMode 1 1 RenderLighting 1 1 RenderObjectBump 1 1 RenderRippleWater 1 1 +RenderUseFBO 1 1 // // No Pixel Shaders available @@ -112,11 +119,13 @@ RenderParticleCount 1 1024 RenderTerrainDetail 1 0 RenderCubeMap 0 0 UseOcclusion 0 0 +RenderUseFBO 1 0 list low RenderVBO 1 0 RenderAniso 1 0 +RenderAvatarMaxVisible 1 3 RenderLighting 1 0 list medium diff --git a/indra/newview/floatersculptpreview.cpp b/indra/newview/floatersculptpreview.cpp index da8d33331..97d20083f 100644 --- a/indra/newview/floatersculptpreview.cpp +++ b/indra/newview/floatersculptpreview.cpp @@ -730,8 +730,8 @@ void LLPreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) } const LLVolumeFace &vf = mVolume->getVolumeFace(0); - U32 num_indices = vf.mIndices.size(); - U32 num_vertices = vf.mVertices.size(); + U32 num_indices = vf.mNumIndices; + U32 num_vertices = vf.mNumVertices; mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL, 0); mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE); @@ -747,17 +747,15 @@ void LLPreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) // build vertices and normals for (U32 i = 0; (S32)i < num_vertices; i++) { - *(vertex_strider++) = vf.mVertices[i].mPosition; - LLVector3 normal = vf.mVertices[i].mNormal; - normal.normalize(); - *(normal_strider++) = normal; + LLVector4a normal = vf.mNormals[i]; + normal.normalize3(); + (normal_strider++)->set(normal.getF32ptr()); } + //build vertices + vertex_strider.assignArray((U8*)vf.mPositions,sizeof(vf.mPositions[0]),num_vertices); // build indices - for (U16 i = 0; i < num_indices; i++) - { - *(index_strider++) = vf.mIndices[i]; - } + index_strider.assignArray((U8*)vf.mIndices,sizeof(vf.mIndices[0]),num_indices); } @@ -812,7 +810,7 @@ BOOL LLPreviewSculpted::render() LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); const LLVolumeFace &vf = mVolume->getVolumeFace(0); - U32 num_indices = vf.mIndices.size(); + U32 num_indices = vf.mNumIndices; mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL); diff --git a/indra/newview/hgfloatertexteditor.cpp b/indra/newview/hgfloatertexteditor.cpp index acd7755ec..044c32040 100644 --- a/indra/newview/hgfloatertexteditor.cpp +++ b/indra/newview/hgfloatertexteditor.cpp @@ -24,6 +24,7 @@ #include "llappviewer.h" // System Folders #include "llfloaterperms.h" //get default perms #include "lllocalinventory.h" +#include "llnotificationsutil.h" std::list<HGFloaterTextEditor*> HGFloaterTextEditor::sInstances; S32 HGFloaterTextEditor::sUploadAmount = 10; @@ -255,7 +256,7 @@ void HGFloaterTextEditor::onClickUpload(void* user_data) { LLSD args; args["ERROR_MESSAGE"] = "Couldn't write data to file"; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); return; } @@ -328,7 +329,7 @@ void HGFloaterTextEditor::onClickSave(void* user_data) { LLSD args; args["ERROR_MESSAGE"] = "Couldn't write data to file"; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); return; } @@ -391,7 +392,7 @@ void HGFloaterTextEditor::onSaveComplete(const LLUUID& asset_uuid, void* user_da { LLSD args; args["ERROR_MESSAGE"] = llformat("Upload failed with status %d, also %d", status, ext_status); - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); } } diff --git a/indra/newview/hippogridmanager.cpp b/indra/newview/hippogridmanager.cpp index bcacddb42..22989cb43 100644 --- a/indra/newview/hippogridmanager.cpp +++ b/indra/newview/hippogridmanager.cpp @@ -39,10 +39,9 @@ HippoGridInfo HippoGridInfo::FALLBACK_GRIDINFO(""); // ******************************************************************** // Initialize -HippoGridInfo::HippoGridInfo(const std::string& gridNick) : - mPlatform(PLATFORM_OPENSIM), - mGridNick(gridNick), - mGridName(LLStringUtil::null), +HippoGridInfo::HippoGridInfo(const std::string& gridName) : + mPlatform(PLATFORM_AURORA), + mGridName(gridName), mLoginUri(LLStringUtil::null), mLoginPage(LLStringUtil::null), mHelperUri(LLStringUtil::null), @@ -54,6 +53,7 @@ HippoGridInfo::HippoGridInfo(const std::string& gridNick) : mFirstName(LLStringUtil::null), mLastName(LLStringUtil::null), mAvatarPassword(LLStringUtil::null), + mGridMessage(""), mXmlState(XML_VOID), mVoiceConnector("SLVoice"), mRenderCompat(true), @@ -63,8 +63,6 @@ HippoGridInfo::HippoGridInfo(const std::string& gridNick) : mRealCurrencySymbol("US$"), mDirectoryFee(30) { - std::string nick = gridNick; - mGridNick = sanitizeGridNick( nick ); } @@ -86,11 +84,6 @@ bool HippoGridInfo::isSecondLife() const return (mPlatform == HippoGridInfo::PLATFORM_SECONDLIFE); } -const std::string& HippoGridInfo::getGridNick() const -{ - return mGridNick; -} - const std::string& HippoGridInfo::getGridName() const { return mGridName; @@ -145,6 +138,11 @@ const std::string& HippoGridInfo::getSearchUrl() const return mSearchUrl; } +const std::string& HippoGridInfo::getGridMessage() const +{ + return mGridMessage; +} + const std::string& HippoGridInfo::getFirstName() const { return mFirstName; @@ -196,7 +194,11 @@ void HippoGridInfo::setPlatform(const std::string& platform) for (unsigned i=0; i<platform.size(); i++) tmp[i] = tolower(tmp[i]); - if (tmp == "opensim") + if (tmp == "aurora") + { + setPlatform(PLATFORM_AURORA); + } + else if (tmp == "opensim") { setPlatform(PLATFORM_OPENSIM); } @@ -207,7 +209,7 @@ void HippoGridInfo::setPlatform(const std::string& platform) else { setPlatform(PLATFORM_OTHER); - llwarns << "Unknown platform '" << platform << "'." << llendl; + llwarns << "Unknown platform '" << platform << "' for " << mGridName << "." << llendl; } } @@ -258,6 +260,11 @@ void HippoGridInfo::setSearchUrl(const std::string& url) mSearchUrl = url; } +void HippoGridInfo::setGridMessage(const std::string& message) +{ + mGridMessage = message; +} + void HippoGridInfo::setFirstName(const std::string& firstName) { mFirstName = firstName; @@ -395,9 +402,7 @@ std::string HippoGridInfo::getSearchUrl(SearchType ty, bool is_web) const void HippoGridInfo::onXmlElementStart(void* userData, const XML_Char* name, const XML_Char** atts) { HippoGridInfo* self = (HippoGridInfo*)userData; - if (strcasecmp(name, "gridnick") == 0) - self->mXmlState = XML_GRIDNICK; - else if (strcasecmp(name, "gridname") == 0) + if (strcasecmp(name, "gridname") == 0) self->mXmlState = XML_GRIDNAME; else if (strcasecmp(name, "platform") == 0) self->mXmlState = XML_PLATFORM; @@ -417,6 +422,8 @@ void HippoGridInfo::onXmlElementStart(void* userData, const XML_Char* name, cons self->mXmlState = XML_PASSWORD; else if (strcasecmp(name, "search") == 0) self->mXmlState = XML_SEARCH; + else if (strcasecmp(name, "message") == 0) + self->mXmlState = XML_MESSAGE; } //static @@ -432,13 +439,6 @@ void HippoGridInfo::onXmlCharacterData(void* userData, const XML_Char* s, int le HippoGridInfo* self = (HippoGridInfo*)userData; switch (self->mXmlState) { - case XML_GRIDNICK: - { - if (self->mGridNick == "") self->mGridNick.assign(s, len); - self->mGridNick = sanitizeGridNick(self->mGridNick); - break; - } - case XML_PLATFORM: { std::string platform(s, len); @@ -473,6 +473,7 @@ void HippoGridInfo::onXmlCharacterData(void* userData, const XML_Char* s, int le case XML_SUPPORT: self->mSupportUrl.assign(s, len); break; case XML_REGISTER: self->mRegisterUrl.assign(s, len); break; case XML_PASSWORD: self->mPasswordUrl.assign(s, len); break; + case XML_MESSAGE: self->mGridMessage.assign(s, len); break; case XML_VOID: break; } @@ -555,7 +556,7 @@ const char* HippoGridInfo::getPlatformString(Platform platform) { static const char* platformStrings[PLATFORM_LAST] = { - "Other", "OpenSim", "SecondLife" + "Other", "Aurora", "OpenSim", "SecondLife" }; if ((platform < PLATFORM_OTHER) || (platform >= PLATFORM_LAST)) @@ -563,27 +564,6 @@ const char* HippoGridInfo::getPlatformString(Platform platform) return platformStrings[platform]; } - -// static -std::string HippoGridInfo::sanitizeGridNick(std::string &gridnick) -{ - std::string tmp; - int size = gridnick.size(); - for (int i=0; i<size; i++) - { - char c = gridnick[i]; - if ((c == '_') || isalnum(c)) - { - tmp += tolower(c); - } - else if (isspace(c)) - { - tmp += "_"; - } - } - return tmp; -} - // static std::string HippoGridInfo::sanitizeUri(std::string &uri) { @@ -603,7 +583,6 @@ std::string HippoGridInfo::sanitizeUri(std::string &uri) void HippoGridInfo::initFallback() { - FALLBACK_GRIDINFO.mGridNick = "localhost"; FALLBACK_GRIDINFO.setPlatform(PLATFORM_OPENSIM); FALLBACK_GRIDINFO.setGridName("Local Host"); FALLBACK_GRIDINFO.setLoginUri("http://127.0.0.1:9000/"); @@ -638,8 +617,8 @@ void HippoGridInfo::setSupportsInvLinks(bool b) { HippoGridManager::HippoGridManager() : mConnectedGrid(0), mDefaultGridsVersion(0), - mCurrentGrid("osgrid"), - mDefaultGrid("osgrid") + mCurrentGrid("Local Host"), + mDefaultGrid("Local Host") { } @@ -739,7 +718,7 @@ void HippoGridManager::setCurrentGridAsConnected() void HippoGridManager::addGrid(HippoGridInfo* grid) { if (!grid) return; - const std::string& nick = grid->getGridNick(); + const std::string& nick = grid->getGridName(); if (nick == "") { llwarns << "Ignoring to try adding grid with empty nick." << llendl; @@ -907,16 +886,16 @@ void HippoGridManager::parseData(LLSD &gridInfo, bool mergeIfNewer) { mDefaultGridsVersion = gridMap["default_grids_version"]; } - else if (gridMap.has("gridnick") && gridMap.has("loginuri")) + else if (gridMap.has("gridname") && gridMap.has("loginuri")) { - std::string gridnick = gridMap["gridnick"]; + std::string gridname = gridMap["gridname"]; HippoGridInfo* grid; - GridIterator it = mGridInfo.find(gridnick); + GridIterator it = mGridInfo.find(gridname); bool newGrid = (it == mGridInfo.end()); if (newGrid) { // create new grid info - grid = new HippoGridInfo(gridnick); + grid = new HippoGridInfo(gridname); } else { @@ -959,7 +938,6 @@ void HippoGridManager::saveFile() for (it = mGridInfo.begin(); it != end; ++it, i++) { HippoGridInfo* grid = it->second; - gridInfo[i]["gridnick"] = grid->getGridNick(); gridInfo[i]["platform"] = HippoGridInfo::getPlatformString(grid->getPlatform()); gridInfo[i]["gridname"] = grid->getGridName(); gridInfo[i]["loginuri"] = grid->getLoginUri(); diff --git a/indra/newview/hippogridmanager.h b/indra/newview/hippogridmanager.h index 1301ae1cc..a5b26415d 100644 --- a/indra/newview/hippogridmanager.h +++ b/indra/newview/hippogridmanager.h @@ -23,6 +23,7 @@ class HippoGridInfo public: enum Platform { PLATFORM_OTHER = 0, + PLATFORM_AURORA, PLATFORM_OPENSIM, PLATFORM_SECONDLIFE, PLATFORM_LAST @@ -33,12 +34,11 @@ public: SEARCH_ALL_TEMPLATE }; - explicit HippoGridInfo(const std::string& gridNick); + explicit HippoGridInfo(const std::string& gridName); Platform getPlatform(); bool isOpenSimulator() const; bool isSecondLife() const; - const std::string& getGridNick() const; const std::string& getGridName() const; const std::string& getGridOwner() const; const std::string& getLoginUri() const; @@ -50,6 +50,7 @@ public: const std::string& getPasswordUrl() const; // Returns the url base used for the Web Search tab const std::string& getSearchUrl() const; + const std::string& getGridMessage() const; const std::string& getFirstName() const; const std::string& getLastName() const; const std::string& getAvatarPassword() const; @@ -76,6 +77,7 @@ public: void setPasswordUrl(const std::string& url); // sets the url base used for the Web Search tab void setSearchUrl(const std::string& url); + void setGridMessage(const std::string& message); void setRenderCompat(bool compat); void setMaxAgentGroups(int max) { mMaxAgentGroups = max; } void setFirstName(const std::string& firstName); @@ -92,14 +94,12 @@ public: bool retrieveGridInfo(); static const char* getPlatformString(Platform platform); - static std::string sanitizeGridNick(std::string &gridnick); static HippoGridInfo FALLBACK_GRIDINFO; static void initFallback(); private: Platform mPlatform; - std::string mGridNick; std::string mGridName; std::string mLoginUri; std::string mLoginPage; @@ -120,13 +120,14 @@ private: std::string mCurrencySymbol; std::string mRealCurrencySymbol; int mDirectoryFee; + std::string mGridMessage; // for parsing grid info XML enum XmlState { - XML_VOID, XML_GRIDNICK, XML_PLATFORM, XML_GRIDNAME, + XML_VOID, XML_PLATFORM, XML_GRIDNAME, XML_LOGINURI, XML_LOGINPAGE, XML_HELPERURI, - XML_WEBSITE, XML_SUPPORT, XML_REGISTER, XML_PASSWORD, XML_SEARCH + XML_WEBSITE, XML_SUPPORT, XML_REGISTER, XML_PASSWORD, XML_SEARCH, XML_MESSAGE }; XmlState mXmlState; diff --git a/indra/newview/hippopanelgrids.cpp b/indra/newview/hippopanelgrids.cpp index e0c40731c..f64a7466d 100644 --- a/indra/newview/hippopanelgrids.cpp +++ b/indra/newview/hippopanelgrids.cpp @@ -41,7 +41,7 @@ #include "llstartup.h" #include "lluictrlfactory.h" #include "llviewerwindow.h" - +#include "llnotificationsutil.h" // ******************************************************************** @@ -77,6 +77,7 @@ class HippoPanelGridsImpl : public HippoPanelGrids static void onClickDefault(void *data); static void onClickGridInfo(void *data); static void onClickHelpRenderCompat(void *data); + static void onClickAdvanced(void *data); }; @@ -118,7 +119,6 @@ HippoPanelGridsImpl::~HippoPanelGridsImpl() BOOL HippoPanelGridsImpl::postBuild() { requires<LLComboBox>("grid_selector"); - requires<LLLineEditor>("gridnick"); requires<LLComboBox>("platform"); requires<LLLineEditor>("gridname"); requires<LLLineEditor>("loginuri"); @@ -148,6 +148,7 @@ BOOL HippoPanelGridsImpl::postBuild() childSetAction("btn_default", onClickDefault, this); childSetAction("btn_gridinfo", onClickGridInfo, this); childSetAction("btn_help_render_compat", onClickHelpRenderCompat, this); + childSetAction("btn_advanced", onClickAdvanced, this); childSetCommitCallback("grid_selector", onSelectGrid, this); childSetCommitCallback("platform", onSelectPlatform, this); @@ -174,7 +175,7 @@ void HippoPanelGridsImpl::refresh() } HippoGridManager::GridIterator it, end = gHippoGridManager->endGrid(); for (it = gHippoGridManager->beginGrid(); it != end; ++it) { - const std::string &grid = it->second->getGridNick(); + const std::string &grid = it->second->getGridName(); if (grid != defaultGrid) { grids->add(grid); if (grid == mCurGrid) selectIndex = i; @@ -196,13 +197,13 @@ void HippoPanelGridsImpl::refresh() childSetEnabled("btn_delete", (selectIndex >= 0)); childSetEnabled("btn_copy", (mState == NORMAL) && (selectIndex >= 0)); childSetEnabled("btn_default", (mState == NORMAL) && (selectIndex > 0)); - childSetEnabled("gridnick", (mState == ADD_NEW) || (mState == ADD_COPY)); + childSetEnabled("gridname", (mState == ADD_NEW) || (mState == ADD_COPY)); if (childGetValue("platform").asString() == "SecondLife") { // disable platform selector, if logged into the grid edited and it is SL // so object export restrictions cannot be circumvented by changing the platform bool enablePlatform = (LLStartUp::getStartupState() < STATE_LOGIN_CLEANUP) || - (mCurGrid != gHippoGridManager->getConnectedGrid()->getGridNick()); + (mCurGrid != gHippoGridManager->getConnectedGrid()->getGridName()); childSetEnabled("platform", enablePlatform); childSetEnabled("search", false); childSetText("search", LLStringExplicit("")); @@ -230,7 +231,7 @@ void HippoPanelGridsImpl::apply() gHippoGridManager->saveFile(); refresh(); // update render compatibility - if (mCurGrid == gHippoGridManager->getConnectedGrid()->getGridNick()) + if (mCurGrid == gHippoGridManager->getConnectedGrid()->getGridName()) gHippoLimits->setLimits(); } @@ -248,7 +249,6 @@ void HippoPanelGridsImpl::loadCurGrid() { HippoGridInfo *gridInfo = gHippoGridManager->getGrid(mCurGrid); if (gridInfo && (mState != ADD_NEW)) { - childSetText("gridnick", gridInfo->getGridNick()); LLComboBox *platform = getChild<LLComboBox>("platform"); if (platform) platform->setCurrentByIndex(gridInfo->getPlatform()); childSetText("gridname", gridInfo->getGridName()); @@ -262,7 +262,6 @@ void HippoPanelGridsImpl::loadCurGrid() childSetValue("render_compat", gridInfo->isRenderCompat()); } else { std::string empty = ""; - childSetText("gridnick", empty); LLComboBox *platform = getChild<LLComboBox>("platform"); if (platform) platform->setCurrentByIndex(HippoGridInfo::PLATFORM_OTHER); childSetText("gridname", empty); @@ -279,10 +278,10 @@ void HippoPanelGridsImpl::loadCurGrid() if (mState == ADD_NEW) { std::string required = "<required>"; - childSetText("gridnick", required); + childSetText("gridname", required); childSetText("loginuri", required); } else if (mState == ADD_COPY) { - childSetText("gridnick", std::string("<required>")); + childSetText("gridname", std::string("<required>")); } else if (mState != NORMAL) { llwarns << "Illegal state " << mState << '.' << llendl; } @@ -298,22 +297,22 @@ bool HippoPanelGridsImpl::saveCurGrid() if (mState == NORMAL) { gridInfo = gHippoGridManager->getGrid(mCurGrid); - + gridInfo->retrieveGridInfo(); + refresh(); } else if ((mState == ADD_NEW) || (mState == ADD_COPY)) { // check nickname - std::string gridnick = childGetValue("gridnick"); - if (gridnick == "<required>") gridnick = ""; - HippoGridInfo::sanitizeGridNick(gridnick); - childSetValue("gridnick", (gridnick != "")? gridnick: "<required>"); - if (gridnick == "") { - LLNotifications::instance().add("GridsNoNick"); + std::string gridname = childGetValue("gridname"); + if (gridname == "<required>") gridname = ""; + childSetValue("gridname", (gridname != "")? gridname: "<required>"); + if (gridname == "") { + LLNotificationsUtil::add("GridsNoNick"); return false; } - if (gHippoGridManager->getGrid(gridnick)) { + if (gHippoGridManager->getGrid(gridname)) { LLSD args; - args["NAME"] = gridnick; - LLNotifications::instance().add("GridExists", args); + args["NAME"] = gridname; + LLNotificationsUtil::add("GridExists", args); return false; } @@ -321,16 +320,16 @@ bool HippoPanelGridsImpl::saveCurGrid() std::string loginuri = childGetValue("loginuri"); if ((loginuri == "") || (loginuri == "<required>")) { LLSD args; - args["NAME"] = gridnick; - LLNotifications::instance().add("GridsNoLoginUri", args); + args["NAME"] = gridname; + LLNotificationsUtil::add("GridsNoLoginUri", args); return false; } mState = NORMAL; - mCurGrid = gridnick; - gridInfo = new HippoGridInfo(gridnick); + mCurGrid = gridname; + gridInfo = new HippoGridInfo(gridname); gHippoGridManager->addGrid(gridInfo); - + gridInfo->retrieveGridInfo(); } else { llwarns << "Illegal state " << mState << '.' << llendl; @@ -342,12 +341,7 @@ bool HippoPanelGridsImpl::saveCurGrid() llwarns << "Grid not found, ignoring changes." << llendl; return true; } - - if (gridInfo->getGridNick() != childGetValue("gridnick").asString()) { - llwarns << "Grid nickname mismatch, ignoring changes." << llendl; - return true; - } - + gridInfo->setPlatform(childGetValue("platform")); gridInfo->setGridName(childGetValue("gridname")); gridInfo->setLoginUri(childGetValue("loginuri")); @@ -380,7 +374,7 @@ void HippoPanelGridsImpl::retrieveGridInfo() { std::string loginuri = childGetValue("loginuri"); if ((loginuri == "") || (loginuri == "<required>")) { - LLNotifications::instance().add("GridInfoNoLoginUri"); + LLNotificationsUtil::add("GridInfoNoLoginUri"); return; } @@ -402,7 +396,6 @@ void HippoPanelGridsImpl::retrieveGridInfo() grid->setLoginUri(loginuri); if (grid->retrieveGridInfo()) { - if (grid->getGridNick() != "") childSetText("gridnick", grid->getGridNick()); if (grid->getPlatform() != HippoGridInfo::PLATFORM_OTHER) getChild<LLComboBox>("platform")->setCurrentByIndex(grid->getPlatform()); if (grid->getGridName() != "") childSetText("gridname", grid->getGridName()); @@ -414,8 +407,9 @@ void HippoPanelGridsImpl::retrieveGridInfo() if (grid->getRegisterUrl() != "") childSetText("register", grid->getRegisterUrl()); if (grid->getPasswordUrl() != "") childSetText("password", grid->getPasswordUrl()); if (grid->getSearchUrl() != "") childSetText("search", grid->getSearchUrl()); + if (grid->getGridMessage() != "") childSetText("gridmessage", grid->getGridMessage()); } else { - LLNotifications::instance().add("GridInfoError"); + LLNotificationsUtil::add("GridInfoError"); } if (cleanupGrid) delete grid; @@ -492,8 +486,56 @@ void HippoPanelGridsImpl::onClickGridInfo(void *data) self->retrieveGridInfo(); } +// static +void HippoPanelGridsImpl::onClickAdvanced(void *data) +{ + HippoPanelGridsImpl *self = (HippoPanelGridsImpl*)data; + if(self->mState != NORMAL) + { + self->retrieveGridInfo(); + } + if(self->childIsVisible("loginpage_label")) + { + self->childSetVisible("loginpage_label", false); + self->childSetVisible("loginpage", false); + self->childSetVisible("helperuri_label", false); + self->childSetVisible("helperuri", false); + self->childSetVisible("website_label", false); + self->childSetVisible("website", false); + self->childSetVisible("support_label", false); + self->childSetVisible("support", false); + self->childSetVisible("register_label", false); + self->childSetVisible("register", false); + self->childSetVisible("password_label", false); + self->childSetVisible("password", false); + self->childSetVisible("search_label", false); + self->childSetVisible("search", false); + self->childSetVisible("render_compat", false); + self->childSetVisible("btn_help_render_compat", false); + } + else + { + self->childSetVisible("loginpage_label", true); + self->childSetVisible("loginpage", true); + self->childSetVisible("helperuri_label", true); + self->childSetVisible("helperuri", true); + self->childSetVisible("website_label", true); + self->childSetVisible("website", true); + self->childSetVisible("support_label", true); + self->childSetVisible("support", true); + self->childSetVisible("register_label", true); + self->childSetVisible("register", true); + self->childSetVisible("password_label", true); + self->childSetVisible("password", true); + self->childSetVisible("search_label", true); + self->childSetVisible("search", true); + self->childSetVisible("render_compat", true); + self->childSetVisible("btn_help_render_compat", true); + } +} + // static void HippoPanelGridsImpl::onClickHelpRenderCompat(void *data) { - LLNotifications::instance().add("HelpRenderCompat"); + LLNotificationsUtil::add("HelpRenderCompat"); } diff --git a/indra/newview/lgghunspell_wrapper.cpp b/indra/newview/lgghunspell_wrapper.cpp index 6eb1297f9..8c4f3c802 100644 --- a/indra/newview/lgghunspell_wrapper.cpp +++ b/indra/newview/lgghunspell_wrapper.cpp @@ -21,6 +21,7 @@ #include "llweb.h" #include "llviewercontrol.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "lldiriterator.h" #include "llfile.h" #include "llhttpclient.h" diff --git a/indra/newview/linux_tools/wrapper.sh b/indra/newview/linux_tools/wrapper.sh index 77dd4d023..34cb59877 100755 --- a/indra/newview/linux_tools/wrapper.sh +++ b/indra/newview/linux_tools/wrapper.sh @@ -68,6 +68,13 @@ if [ "$GTK_IM_MODULE" = "scim" ]; then export GTK_IM_MODULE=xim fi +# Work around for a crash bug when restarting OpenGL after a change in the +# graphic settings (anti-aliasing, VBO, FSAA, full screen mode, UI scale). +# When you enable this work around, you can change the settings without +# crashing, but you will have to restart the viewer after changing them +# because the display still gets corrupted. +export LL_OPENGL_RESTART_CRASH_BUG=x + ## - Automatically work around the ATI mouse cursor crash bug: ## (this workaround is disabled as most fglrx users do not see the bug) #if lsmod | grep fglrx &>/dev/null ; then diff --git a/indra/newview/llaccountingcostmanager.cpp b/indra/newview/llaccountingcostmanager.cpp new file mode 100644 index 000000000..bbf0c4205 --- /dev/null +++ b/indra/newview/llaccountingcostmanager.cpp @@ -0,0 +1,164 @@ +/** + * @file LLAccountingQuotaManager.cpp + * @ Handles the setting and accessing for costs associated with mesh + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#if MESH_ENABLED +#include "llaccountingcostmanager.h" +#include "llagent.h" +#include "llcurl.h" +#include "llhttpclient.h" + +//=============================================================================== +LLAccountingCostManager::LLAccountingCostManager() +{ +} +//=============================================================================== +class LLAccountingCostResponder : public LLCurl::Responder +{ +public: + LLAccountingCostResponder( const LLSD& objectIDs ) + : mObjectIDs( objectIDs ) + { + } + + void clearPendingRequests ( void ) + { + for ( LLSD::array_iterator iter = mObjectIDs.beginArray(); iter != mObjectIDs.endArray(); ++iter ) + { + LLAccountingCostManager::getInstance()->removePendingObject( iter->asUUID() ); + } + } + + void error( U32 statusNum, const std::string& reason ) + { + llwarns << "Transport error "<<reason<<llendl; + clearPendingRequests(); + } + + void result( const LLSD& content ) + { + //Check for error + if ( !content.isMap() || content.has("error") ) + { + llwarns << "Error on fetched data"<< llendl; + clearPendingRequests(); + } + else if (content.has("selected")) + { + F32 physicsCost = 0.0f; + F32 networkCost = 0.0f; + F32 simulationCost = 0.0f; + + //LLTransactionID transactionID; + + //transactionID = content["selected"][i]["local_id"].asUUID(); + physicsCost = content["selected"]["physics"].asReal(); + networkCost = content["selected"]["streaming"].asReal(); + simulationCost = content["selected"]["simulation"].asReal(); + + SelectionCost selectionCost( /*transactionID,*/ physicsCost, networkCost, simulationCost ); + + } + + clearPendingRequests(); + } + +private: + //List of posted objects + LLSD mObjectIDs; +}; +//=============================================================================== +void LLAccountingCostManager::fetchCosts( eSelectionType selectionType, const std::string& url ) +{ + // Invoking system must have already determined capability availability + if ( !url.empty() ) + { + LLSD objectList; + U32 objectIndex = 0; + + IDIt IDIter = mObjectList.begin(); + IDIt IDIterEnd = mObjectList.end(); + + for ( ; IDIter != IDIterEnd; ++IDIter ) + { + // Check to see if a request for this object has already been made. + if ( mPendingObjectQuota.find( *IDIter ) == mPendingObjectQuota.end() ) + { + mPendingObjectQuota.insert( *IDIter ); + objectList[objectIndex++] = *IDIter; + } + } + + mObjectList.clear(); + + //Post results + if ( objectList.size() > 0 ) + { + std::string keystr; + if ( selectionType == Roots ) + { + keystr="selected_roots"; + } + else + if ( selectionType == Prims ) + { + keystr="selected_prims"; + } + else + { + llinfos<<"Invalid selection type "<<llendl; + mObjectList.clear(); + mPendingObjectQuota.clear(); + return; + } + + LLSD dataToPost = LLSD::emptyMap(); + dataToPost[keystr.c_str()] = objectList; + + LLHTTPClient::post( url, dataToPost, new LLAccountingCostResponder( objectList )); + } + } + else + { + //url was empty - warn & continue + llwarns<<"Supplied url is empty "<<llendl; + mObjectList.clear(); + mPendingObjectQuota.clear(); + } +} +//=============================================================================== +void LLAccountingCostManager::addObject( const LLUUID& objectID ) +{ + mObjectList.insert( objectID ); +} +//=============================================================================== +void LLAccountingCostManager::removePendingObject( const LLUUID& objectID ) +{ + mPendingObjectQuota.erase( objectID ); +} +//=============================================================================== +#endif //MESH_ENABLED + diff --git a/indra/newview/llaccountingcostmanager.h b/indra/newview/llaccountingcostmanager.h new file mode 100644 index 000000000..8ae696a98 --- /dev/null +++ b/indra/newview/llaccountingcostmanager.h @@ -0,0 +1,55 @@ +/** + * @file lllAccountingQuotaManager.h + * @ + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_ACCOUNTINGQUOTAMANAGER_H +#define LL_ACCOUNTINGQUOTAMANAGER_H +//=============================================================================== +#include "llaccountingcost.h" +//=============================================================================== +class LLAccountingCostManager : public LLSingleton<LLAccountingCostManager> +{ +public: + //Ctor + LLAccountingCostManager(); + //Store an object that will be eventually fetched + void addObject( const LLUUID& objectID ); + //Request quotas for object list + void fetchCosts( eSelectionType selectionType, const std::string& url ); + //Delete a specific object from the pending list + void removePendingObject( const LLUUID& objectID ); + +private: + //Set of objects that will be used to generate a cost + std::set<LLUUID> mObjectList; + //During fetchCosts we move object into a the pending set to signify that + //a fetch has been instigated. + std::set<LLUUID> mPendingObjectQuota; + typedef std::set<LLUUID>::iterator IDIt; +}; +//=============================================================================== + +#endif // LLACCOUNTINGCOSTMANAGER + diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 000f4067e..f241eeaec 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -39,6 +39,7 @@ #include "llagentaccess.h" #include "llagentcamera.h" #include "llagentwearables.h" +#include "llagentui.h" #include "llanimationstates.h" #include "llcallingcard.h" #include "llconsole.h" @@ -53,6 +54,7 @@ #include "llmorphview.h" #include "llmoveview.h" #include "llchatbar.h" +#include "llnotificationsutil.h" #include "llnotify.h" #include "llparcel.h" #include "llrendersphere.h" @@ -247,7 +249,8 @@ LLAgent::LLAgent() : mFirstLogin(FALSE), mGenderChosen(FALSE), mAppearanceSerialNum(0), - + mMouselookModeInSignal(NULL), + mMouselookModeOutSignal(NULL), mPendingLure(NULL) { for (U32 i = 0; i < TOTAL_CONTROLS; i++) @@ -294,6 +297,11 @@ LLAgent::~LLAgent() { cleanup(); + delete mMouselookModeInSignal; + mMouselookModeInSignal = NULL; + delete mMouselookModeOutSignal; + mMouselookModeOutSignal = NULL; + delete mAgentAccess; mAgentAccess = NULL; delete mEffectColor; @@ -543,7 +551,7 @@ void LLAgent::setFlying(BOOL fly) { if (isAgentAvatarValid()) { - if(mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end()) + if(fly && mAvatarObject->mSignaledAnimations.find(ANIM_AGENT_STANDUP) != mAvatarObject->mSignaledAnimations.end()) { return; } @@ -1328,7 +1336,7 @@ void LLAgent::startAutoPilotGlobal( else { // Guess at a reasonable stop distance. - mAutoPilotStopDistance = fsqrtf( distance ); + mAutoPilotStopDistance = (F32) sqrt( distance ); if (mAutoPilotStopDistance < 0.5f) { mAutoPilotStopDistance = 0.5f; @@ -1437,11 +1445,11 @@ void LLAgent::stopAutoPilot(BOOL user_cancel) if (user_cancel && !mAutoPilotBehaviorName.empty()) { if (mAutoPilotBehaviorName == "Sit") - LLNotifications::instance().add("CancelledSit"); + LLNotificationsUtil::add("CancelledSit"); else if (mAutoPilotBehaviorName == "Attach") - LLNotifications::instance().add("CancelledAttach"); + LLNotificationsUtil::add("CancelledAttach"); else - LLNotifications::instance().add("Cancelled"); + LLNotificationsUtil::add("Cancelled"); } } } @@ -1845,6 +1853,11 @@ void LLAgent::endAnimationUpdateUI() LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); + + if (mMouselookModeOutSignal) + { + (*mMouselookModeOutSignal)(); + } // Only pop if we have pushed... if (TRUE == mViewsPushed) { @@ -1937,6 +1950,10 @@ void LLAgent::endAnimationUpdateUI() mViewsPushed = TRUE; + if (mMouselookModeInSignal) + { + (*mMouselookModeInSignal)(); + } gFloaterView->pushVisibleAll(FALSE, get_skip_list()); if( gMorphView ) @@ -2027,6 +2044,17 @@ void LLAgent::endAnimationUpdateUI() gAgentCamera.updateLastCamera(); } +boost::signals2::connection LLAgent::setMouselookModeInCallback( const camera_signal_t::slot_type& cb ) +{ + if (!mMouselookModeInSignal) mMouselookModeInSignal = new camera_signal_t(); + return mMouselookModeInSignal->connect(cb); +} + +boost::signals2::connection LLAgent::setMouselookModeOutCallback( const camera_signal_t::slot_type& cb ) +{ + if (!mMouselookModeOutSignal) mMouselookModeOutSignal = new camera_signal_t(); + return mMouselookModeOutSignal->connect(cb); +} //----------------------------------------------------------------------------- // heardChat() @@ -2197,6 +2225,11 @@ bool LLAgent::isGodlike() const return mAgentAccess->isGodlike(); } +bool LLAgent::isGodlikeWithoutAdminMenuFakery() const +{ + return mAgentAccess->isGodlikeWithoutAdminMenuFakery(); +} + U8 LLAgent::getGodLevel() const { return mAgentAccess->getGodLevel(); @@ -2518,61 +2551,6 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO return FALSE; } -// utility to build a location string -void LLAgent::buildLocationString(std::string& str) -{ -// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) - if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) - { - str = RlvStrings::getString(RLV_STRING_HIDDEN); - return; - } -// [/RLVa:KB] - - const LLVector3& agent_pos_region = getPositionAgent(); - S32 pos_x = S32(agent_pos_region.mV[VX]); - S32 pos_y = S32(agent_pos_region.mV[VY]); - S32 pos_z = S32(agent_pos_region.mV[VZ]); - - // Round the numbers based on the velocity - LLVector3 agent_velocity = getVelocity(); - F32 velocity_mag_sq = agent_velocity.magVecSquared(); - - const F32 FLY_CUTOFF = 6.f; // meters/sec - const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; - const F32 WALK_CUTOFF = 1.5f; // meters/sec - const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; - - if (velocity_mag_sq > FLY_CUTOFF_SQ) - { - pos_x -= pos_x % 4; - pos_y -= pos_y % 4; - } - else if (velocity_mag_sq > WALK_CUTOFF_SQ) - { - pos_x -= pos_x % 2; - pos_y -= pos_y % 2; - } - - // create a defult name and description for the landmark - std::string buffer; - if( LLViewerParcelMgr::getInstance()->getAgentParcelName().empty() ) - { - // the parcel doesn't have a name - buffer = llformat("%.32s (%d, %d, %d)", - getRegion()->getName().c_str(), - pos_x, pos_y, pos_z); - } - else - { - // the parcel has a name, so include it in the landmark name - buffer = llformat("%.32s, %.32s (%d, %d, %d)", - LLViewerParcelMgr::getInstance()->getAgentParcelName().c_str(), - getRegion()->getName().c_str(), - pos_x, pos_y, pos_z); - } - str = buffer; -} LLQuaternion LLAgent::getHeadRotation() { @@ -3256,7 +3234,7 @@ void LLAgent::processAgentCachedTextureResponse(LLMessageSystem *mesgsys, void * { gAgentQueryManager.mNumPendingQueries--; - if (!isAgentAvatarValid()) + if (!isAgentAvatarValid() || gAgent.getAvatarObject()->isDead()) { llwarns << "No avatar for user in cached texture update!" << llendl; return; @@ -3658,14 +3636,29 @@ void LLAgent::setTeleportState(ETeleportState state) { LLFloaterSnapshot::hide(0); } - if (mTeleportState == TELEPORT_NONE) - { - mbTeleportKeepsLookAt = false; - } - if ((mTeleportState == TELEPORT_MOVING)) - { + + switch (mTeleportState) + + { + case TELEPORT_NONE: + mbTeleportKeepsLookAt = false; + break; + + case TELEPORT_MOVING: // We're outa here. Save "back" slurl. mTeleportSourceSLURL = getSLURL(); + break; + + case TELEPORT_ARRIVING: + // First two position updates after a teleport tend to be weird + LLViewerStats::getInstance()->mAgentPositionSnaps.mCountOfNextUpdatesToIgnore = 2; + + // Let the interested parties know we've teleported. + LLViewerParcelMgr::getInstance()->onTeleportFinished(false, getPositionGlobal()); + break; + + default: + break; } // [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Version: 1.23.4 | Checked: 2009-07-07 (RLVa-1.0.0d) | Added: RLVa-0.2.0b if ( (rlv_handler_t::isEnabled()) && (TELEPORT_NONE == mTeleportState) ) @@ -3982,6 +3975,16 @@ void LLAgent::sendAgentDataUpdateRequest() sendReliableMessage(); } +void LLAgent::sendAgentUserInfoRequest() +{ + if(getID().isNull()) + return; // not logged in + gMessageSystem->newMessageFast(_PREHASH_UserInfoRequest); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); + sendReliableMessage(); +} void LLAgent::observeFriends() { @@ -4045,6 +4048,18 @@ void LLAgent::parseTeleportMessages(const std::string& xml_filename) }//end for (all message sets in xml file) } + +void LLAgent::sendAgentUpdateUserInfo(bool im_via_email, const std::string& directory_visibility ) +{ + gMessageSystem->newMessageFast(_PREHASH_UpdateUserInfo); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_UserData); + gMessageSystem->addBOOLFast(_PREHASH_IMViaEMail, im_via_email); + gMessageSystem->addString("DirectoryVisibility", directory_visibility); + gAgent.sendReliableMessage(); +} // Draw a representation of current autopilot target void LLAgent::renderAutoPilotTarget() { diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index ff109d2ea..6c36d5392 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -47,6 +47,8 @@ #include "llinventorymodel.h" #include "v3dmath.h" +#include <boost/signals2.hpp> + extern const BOOL ANIMATE; extern const U8 AGENT_STATE_TYPING; // Typing indication extern const U8 AGENT_STATE_EDITING; // Set when agent has objects selected @@ -108,8 +110,7 @@ public: //-------------------------------------------------------------------- public: LLAgent(); - ~LLAgent(); - + virtual ~LLAgent(); void init(); void cleanup(); @@ -253,7 +254,6 @@ public: const LLHost& getRegionHost() const; BOOL inPrelude(); std::string getSLURL() const; //Return uri for current region - void buildLocationString(std::string& str); //Build a description string for current location // <edit> struct SHLureRequest @@ -454,6 +454,14 @@ public: void unpauseAnimation() { mPauseRequest = NULL; } BOOL getCustomAnim() const { return mCustomAnim; } void setCustomAnim(BOOL anim) { mCustomAnim = anim; } + + typedef boost::signals2::signal<void ()> camera_signal_t; + boost::signals2::connection setMouselookModeInCallback( const camera_signal_t::slot_type& cb ); + boost::signals2::connection setMouselookModeOutCallback( const camera_signal_t::slot_type& cb ); + +private: + camera_signal_t* mMouselookModeInSignal; + camera_signal_t* mMouselookModeOutSignal; BOOL mCustomAnim; // Current animation is ANIM_AGENT_CUSTOMIZE ? LLPointer<LLPauseRequestHandle> mPauseRequest; BOOL mViewsPushed; // Keep track of whether or not we have pushed views @@ -500,8 +508,16 @@ public: // Autopilot //-------------------------------------------------------------------- public: - BOOL getAutoPilot() const { return mAutoPilot; } - LLVector3d getAutoPilotTargetGlobal() const { return mAutoPilotTargetGlobal; } + BOOL getAutoPilot() const { return mAutoPilot; } + LLVector3d getAutoPilotTargetGlobal() const { return mAutoPilotTargetGlobal; } + LLUUID getAutoPilotLeaderID() const { return mLeaderID; } + F32 getAutoPilotStopDistance() const { return mAutoPilotStopDistance; } + F32 getAutoPilotTargetDist() const { return mAutoPilotTargetDist; } + BOOL getAutoPilotUseRotation() const { return mAutoPilotUseRotation; } + LLVector3 getAutoPilotTargetFacing() const { return mAutoPilotTargetFacing; } + F32 getAutoPilotRotationThreshold() const { return mAutoPilotRotationThreshold; } + std::string getAutoPilotBehaviorName() const { return mAutoPilotBehaviorName; } + void startAutoPilotGlobal(const LLVector3d &pos_global, const std::string& behavior_name = std::string(), const LLQuaternion *target_rotation = NULL, @@ -621,6 +637,7 @@ private: //-------------------------------------------------------------------- public: bool isGodlike() const; + bool isGodlikeWithoutAdminMenuFakery() const; U8 getGodLevel() const; void setAdminOverride(BOOL b); void setGodLevel(U8 god_level); @@ -774,7 +791,10 @@ public: void sendReliableMessage(); void sendAgentSetAppearance(); void sendAgentDataUpdateRequest(); - + void sendAgentUserInfoRequest(); + // IM to Email and Online visibility + void sendAgentUpdateUserInfo(bool im_to_email, const std::string& directory_visibility); + //-------------------------------------------------------------------- // Receive //-------------------------------------------------------------------- diff --git a/indra/newview/llagentaccess.cpp b/indra/newview/llagentaccess.cpp index bff32502f..a43f358e6 100644 --- a/indra/newview/llagentaccess.cpp +++ b/indra/newview/llagentaccess.cpp @@ -69,6 +69,15 @@ bool LLAgentAccess::isGodlike() const #endif } +bool LLAgentAccess::isGodlikeWithoutAdminMenuFakery() const +{ +#ifdef HACKED_GODLIKE_VIEWER + return true; +#else + return mGodLevel > GOD_NOT; +#endif +} + U8 LLAgentAccess::getGodLevel() const { #ifdef HACKED_GODLIKE_VIEWER @@ -163,6 +172,20 @@ int LLAgentAccess::convertTextToMaturity(char text) void LLAgentAccess::setMaturity(char text) { mAccess = LLAgentAccess::convertTextToMaturity(text); + U32 preferred_access = mSavedSettings.getU32("PreferredMaturity"); + while (!canSetMaturity(preferred_access)) + { + if (preferred_access == SIM_ACCESS_ADULT) + { + preferred_access = SIM_ACCESS_MATURE; + } + else + { + // Mature or invalid access gets set to PG + preferred_access = SIM_ACCESS_PG; + } + } + mSavedSettings.setU32("PreferredMaturity", preferred_access); } void LLAgentAccess::setTransition() @@ -175,3 +198,14 @@ bool LLAgentAccess::isInTransition() const return mAOTransition; } +bool LLAgentAccess::canSetMaturity(S32 maturity) +{ + if (isGodlike()) // Gods can always set their Maturity level + return true; + if (isAdult()) // Adults can always set their Maturity level + return true; + if (maturity == SIM_ACCESS_PG || (maturity == SIM_ACCESS_MATURE && isMature())) + return true; + else + return false; +} diff --git a/indra/newview/llagentaccess.h b/indra/newview/llagentaccess.h index dbd9bf8ea..49da5f44c 100644 --- a/indra/newview/llagentaccess.h +++ b/indra/newview/llagentaccess.h @@ -48,6 +48,7 @@ public: void setGodLevel(U8 god_level); bool isGodlike() const; + bool isGodlikeWithoutAdminMenuFakery() const; U8 getGodLevel() const; @@ -71,6 +72,7 @@ public: void setTransition(); // sets the transition bit, which defaults to false bool isInTransition() const; + bool canSetMaturity(S32 maturity); private: U8 mAccess; // SIM_ACCESS_MATURE etc diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 77baa02e5..2e3f7a829 100644 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -411,8 +411,9 @@ LLVector3 LLAgentCamera::calcFocusOffset(LLViewerObject *object, LLVector3 origi LLQuaternion inv_obj_rot = ~obj_rot; // get inverse of rotation LLVector3 object_extents = object->getScale(); //this stuff just seems to make camera snapping worse... - //const LLVector3* oe3 = object->mDrawable->getSpatialExtents(); - //object_extents.set( oe3[1][0], oe3[1][1], oe3[1][2] ); + //const LLVector4a* oe4 = object->mDrawable->getSpatialExtents(); + //object_extents.set( oe4[1][0], oe4[1][1], oe4[1][2] ); + // make sure they object extents are non-zero object_extents.clamp(0.001f, F32_MAX); @@ -572,7 +573,9 @@ BOOL LLAgentCamera::calcCameraMinDistance(F32 &obj_min_distance) BOOL soft_limit = FALSE; // is the bounding box to be treated literally (volumes) or as an approximation (avatars) if (!mFocusObject || mFocusObject->isDead() || - //mFocusObject->isMesh() || +#if MESH_ENABLED + mFocusObject->isMesh() || +#endif //MESH_ENABLED gSavedSettings.getBOOL("DisableCameraConstraints")) { obj_min_distance = 0.f; diff --git a/indra/newview/llagentui.cpp b/indra/newview/llagentui.cpp new file mode 100644 index 000000000..c0e1e6e68 --- /dev/null +++ b/indra/newview/llagentui.cpp @@ -0,0 +1,184 @@ +/** + * @file llagentui.cpp + * @brief Utility methods to process agent's data as slurl's etc. before displaying + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llagentui.h" + +// Library includes +#include "llparcel.h" + +// Viewer includes +#include "llagent.h" +#include "llviewercontrol.h" +#include "llviewerregion.h" +#include "llviewerparcelmgr.h" +// [RLVa:KB] - Checked: 2010-09-27 (RLVa-1.1.3b) +#include "rlvhandler.h" +// [/RLVa:KB] + +//static +void LLAgentUI::buildFullname(std::string& name) +{ + if (isAgentAvatarValid()) + name = gAgent.getAvatarObject()->getFullname(); +} + +/* +//static +void LLAgentUI::buildSLURL(LLSLURL& slurl, const bool escaped /= true/ ) +{ + LLSLURL return_slurl; + LLViewerRegion *regionp = gAgent.getRegion(); + if (regionp) + { + return_slurl = LLSLURL(regionp->getName(), gAgent.getPositionGlobal()); + } + slurl = return_slurl; +}*/ + +//static +BOOL LLAgentUI::checkAgentDistance(const LLVector3& pole, F32 radius) +{ + F32 delta_x = gAgent.getPositionAgent().mV[VX] - pole.mV[VX]; + F32 delta_y = gAgent.getPositionAgent().mV[VY] - pole.mV[VY]; + + return sqrt( delta_x* delta_x + delta_y* delta_y ) < radius; +} +BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region) +{ +// [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0a) + if (gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) + { + str = RlvStrings::getString(RLV_STRING_HIDDEN); + return TRUE; + } +// [/RLVa:KB] + LLViewerRegion* region = gAgent.getRegion(); + LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); + + if (!region || !parcel) return FALSE; + + S32 pos_x = S32(agent_pos_region.mV[VX]); + S32 pos_y = S32(agent_pos_region.mV[VY]); + S32 pos_z = S32(agent_pos_region.mV[VZ]); + + // Round the numbers based on the velocity + F32 velocity_mag_sq = gAgent.getVelocity().magVecSquared(); + + const F32 FLY_CUTOFF = 6.f; // meters/sec + const F32 FLY_CUTOFF_SQ = FLY_CUTOFF * FLY_CUTOFF; + const F32 WALK_CUTOFF = 1.5f; // meters/sec + const F32 WALK_CUTOFF_SQ = WALK_CUTOFF * WALK_CUTOFF; + + if (velocity_mag_sq > FLY_CUTOFF_SQ) + { + pos_x -= pos_x % 4; + pos_y -= pos_y % 4; + } + else if (velocity_mag_sq > WALK_CUTOFF_SQ) + { + pos_x -= pos_x % 2; + pos_y -= pos_y % 2; + } + + // create a default name and description for the landmark + std::string parcel_name = LLViewerParcelMgr::getInstance()->getAgentParcelName(); + std::string region_name = region->getName(); + std::string sim_access_string = region->getSimAccessString(); + std::string buffer; + if( parcel_name.empty() ) + { + // the parcel doesn't have a name + switch (fmt) + { + case LOCATION_FORMAT_LANDMARK: + buffer = llformat("%.100s", region_name.c_str()); + break; + case LOCATION_FORMAT_NORMAL: + buffer = llformat("%s", region_name.c_str()); + break; + case LOCATION_FORMAT_NO_COORDS: + buffer = llformat("%s%s%s", + region_name.c_str(), + sim_access_string.empty() ? "" : " - ", + sim_access_string.c_str()); + break; + case LOCATION_FORMAT_NO_MATURITY: + buffer = llformat("%s (%d, %d, %d)", + region_name.c_str(), + pos_x, pos_y, pos_z); + break; + case LOCATION_FORMAT_FULL: + buffer = llformat("%s (%d, %d, %d)%s%s", + region_name.c_str(), + pos_x, pos_y, pos_z, + sim_access_string.empty() ? "" : " - ", + sim_access_string.c_str()); + break; + } + } + else + { + // the parcel has a name, so include it in the landmark name + switch (fmt) + { + case LOCATION_FORMAT_LANDMARK: + buffer = llformat("%.100s", parcel_name.c_str()); + break; + case LOCATION_FORMAT_NORMAL: + buffer = llformat("%s, %s", parcel_name.c_str(), region_name.c_str()); + break; + case LOCATION_FORMAT_NO_MATURITY: + buffer = llformat("%s, %s (%d, %d, %d)", + parcel_name.c_str(), + region_name.c_str(), + pos_x, pos_y, pos_z); + break; + case LOCATION_FORMAT_NO_COORDS: + buffer = llformat("%s, %s%s%s", + parcel_name.c_str(), + region_name.c_str(), + sim_access_string.empty() ? "" : " - ", + sim_access_string.c_str()); + break; + case LOCATION_FORMAT_FULL: + buffer = llformat("%s, %s (%d, %d, %d)%s%s", + parcel_name.c_str(), + region_name.c_str(), + pos_x, pos_y, pos_z, + sim_access_string.empty() ? "" : " - ", + sim_access_string.c_str()); + break; + } + } + str = buffer; + return TRUE; +} +BOOL LLAgentUI::buildLocationString(std::string& str, ELocationFormat fmt) +{ + return buildLocationString(str,fmt, gAgent.getPositionAgent()); +} diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h new file mode 100644 index 000000000..dda5dc1fd --- /dev/null +++ b/indra/newview/llagentui.h @@ -0,0 +1,58 @@ +/** + * @file llagentui.h + * @brief Utility methods to process agent's data as slurl's etc. before displaying + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LLAGENTUI_H +#define LLAGENTUI_H + +class LLSLURL; + +class LLAgentUI +{ +public: + enum ELocationFormat + { + LOCATION_FORMAT_NORMAL, // Parcel + LOCATION_FORMAT_LANDMARK, // Parcel, Region + LOCATION_FORMAT_NO_MATURITY, // Parcel, Region (x, y, z) + LOCATION_FORMAT_NO_COORDS, // Parcel, Region - Maturity + LOCATION_FORMAT_FULL, // Parcel, Region (x, y, z) - Maturity + }; + + static void buildFullname(std::string &name); + + static void buildSLURL(LLSLURL& slurl, const bool escaped = true); + //build location string using the current position of gAgent. + static BOOL buildLocationString(std::string& str, ELocationFormat fmt = LOCATION_FORMAT_LANDMARK); + //build location string using a region position of the avatar. + static BOOL buildLocationString(std::string& str, ELocationFormat fmt,const LLVector3& agent_pos_region); + /** + * @brief Check whether the agent is in neighborhood of the pole Within same region + * @return true if the agent is in neighborhood. + */ + static BOOL checkAgentDistance(const LLVector3& local_pole, F32 radius); +}; + +#endif //LLAGENTUI_H diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 852a58e4e..33a61ba3b 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -42,7 +42,7 @@ #include "llinventorybridge.h" #include "llinventoryview.h" #include "llmd5.h" -#include "llnotifications.h" +#include "llnotificationsutil.h" #include "lltexlayer.h" #include "llviewerregion.h" #include "llvoavatar.h" @@ -724,7 +724,7 @@ void LLAgentWearables::onInitialWearableAssetArrived( LLWearable* wearable, void void LLAgentWearables::recoverMissingWearable( EWearableType type ) { // Try to recover by replacing missing wearable with a new one. - LLNotifications::instance().add("ReplacedMissingWearable"); + LLNotificationsUtil::add("ReplacedMissingWearable"); lldebugs << "Wearable " << LLWearable::typeToTypeLabel( type ) << " could not be downloaded. Replaced inventory item with default wearable." << llendl; LLWearable* new_wearable = gWearableList.createNewWearable(type); @@ -1104,7 +1104,7 @@ void LLAgentWearables::removeWearable( EWearableType type ) LLSD payload; payload["wearable_type"] = (S32)type; // Bring up view-modal dialog: Save changes? Yes, No, Cancel - LLNotifications::instance().add("WearableSave", LLSD(), payload, &LLAgentWearables::onRemoveWearableDialog); + LLNotificationsUtil::add("WearableSave", LLSD(), payload, &LLAgentWearables::onRemoveWearableDialog); return; } else @@ -1117,7 +1117,7 @@ void LLAgentWearables::removeWearable( EWearableType type ) // static bool LLAgentWearables::onRemoveWearableDialog(const LLSD& notification, const LLSD& response ) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); EWearableType type = (EWearableType)notification["payload"]["wearable_type"].asInteger(); switch( option ) { @@ -1220,7 +1220,7 @@ static bool isFirstPhysicsWearable(EWearableType type, LLInventoryItem *new_item } } }; - LLNotifications::instance().add("FirstPhysicsWearable",LLSD(),LLSD(),boost::bind(WearableDelayedCallback::setDelayedWearable, _1, _2, new_item->getUUID(),new_wearable)); + LLNotificationsUtil::add("FirstPhysicsWearable",LLSD(),LLSD(),boost::bind(WearableDelayedCallback::setDelayedWearable, _1, _2, new_item->getUUID(),new_wearable)); return true; } return false; @@ -1384,7 +1384,7 @@ void LLAgentWearables::setWearableItem( LLInventoryItem* new_item, LLWearable* n // Bring up modal dialog: Save changes? Yes, No, Cancel LLSD payload; payload["item_id"] = new_item->getUUID(); - LLNotifications::instance().add( "WearableSave", LLSD(), payload, boost::bind(LLAgentWearables::onSetWearableDialog, _1, _2, new_wearable)); + LLNotificationsUtil::add( "WearableSave", LLSD(), payload, boost::bind(LLAgentWearables::onSetWearableDialog, _1, _2, new_wearable)); return; } } @@ -1395,7 +1395,7 @@ void LLAgentWearables::setWearableItem( LLInventoryItem* new_item, LLWearable* n // static bool LLAgentWearables::onSetWearableDialog( const LLSD& notification, const LLSD& response, LLWearable* wearable ) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLInventoryItem* new_item = gInventory.getItem( notification["payload"]["item_id"].asUUID()); if( !new_item ) { diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 72ebc6db4..41f91748b 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -52,6 +52,9 @@ #include "llwindow.h" #include "llviewerstats.h" #include "llmd5.h" +#if MESH_ENABLED +#include "llmeshrepository.h" +#endif //MESH_ENABLED #include "llpumpio.h" #include "llimpanel.h" #include "llmimetypes.h" @@ -77,6 +80,7 @@ #include "statemachine/aifilepicker.h" #include "llfirstuse.h" #include "llrender.h" +#include "llvector4a.h" #include "llfont.h" #include "llvocache.h" #include "llfloaterteleporthistory.h" @@ -89,6 +93,8 @@ #include "lldiriterator.h" #include "llimagej2c.h" #include "llprimitive.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include <boost/bind.hpp> #if LL_WINDOWS @@ -562,6 +568,8 @@ bool LLAppViewer::init() // we run the "program crashed last time" error handler below. // + // initialize SSE options + LLVector4a::initClass(); // Need to do this initialization before we do anything else, since anything // that touches files should really go through the lldir API gDirUtilp->initAppDirs("SecondLife"); @@ -586,7 +594,7 @@ bool LLAppViewer::init() // *NOTE:Mani - LLCurl::initClass is not thread safe. // Called before threads are created. - LLCurl::initClass(); + LLCurl::initClass(gSavedSettings.getBOOL("CurlUseMultipleThreads")); LL_INFOS("InitInfo") << "LLCurl initialized." << LL_ENDL ; initThreads(); @@ -683,7 +691,13 @@ bool LLAppViewer::init() LLViewerJointMesh::updateVectorize(); // load MIME type -> media impl mappings - LLMIMETypes::parseMIMETypes( std::string("mime_types.xml") ); +#if LL_WINDOWS + LLMIMETypes::parseMIMETypes( std::string("mime_types_windows.xml") ); +#elif LL_DARWIN + LLMIMETypes::parseMIMETypes( std::string("mime_types_mac.xml") ); +#elif LL_LINUX + LLMIMETypes::parseMIMETypes( std::string("mime_types_linux.xml") ); +#endif // Copy settings to globals. *TODO: Remove or move to appropriage class initializers settings_to_globals(); @@ -855,7 +869,7 @@ bool LLAppViewer::init() if (LLFeatureManager::getInstance()->getGPUClass() == GPU_CLASS_UNKNOWN) { - LLNotifications::instance().add("UnknownGPU"); + LLNotificationsUtil::add("UnknownGPU"); } if(unsupported) @@ -864,7 +878,7 @@ bool LLAppViewer::init() || gSavedSettings.getBOOL("WarnUnsupportedHardware")) { args["MINSPECS"] = minSpecs; - LLNotifications::instance().add("UnsupportedHardware", args ); + LLNotificationsUtil::add("UnsupportedHardware", args ); } } @@ -1107,6 +1121,9 @@ bool LLAppViewer::mainLoop() break; } } +#if MESH_ENABLED + gMeshRepo.update() ; +#endif //MESH_ENABLED if ((LLStartUp::getStartupState() >= STATE_CLEANUP) && (frameTimer.getElapsedTimeF64() > FRAME_STALL_THRESHOLD)) { @@ -1230,6 +1247,11 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning Up" << llendflush; +#if MESH_ENABLED + // shut down mesh streamer + gMeshRepo.shutdown(); +#endif //MESH_ENABLED + // Must clean up texture references before viewer window is destroyed. if(LLHUDManager::instanceExists()) { @@ -1367,8 +1389,6 @@ bool LLAppViewer::cleanup() LLViewerObject::cleanupVOClasses(); - LLWaterParamManager::cleanupClass(); - LLWLParamManager::cleanupClass(); LLPostProcess::cleanupClass(); LLTracker::cleanupInstance(); @@ -1652,6 +1672,11 @@ bool LLAppViewer::initThreads() LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true); LLImage::initClass(); + +#if MESH_ENABLED + // Mesh streaming and caching + gMeshRepo.init(); +#endif //MESH_ENABLED // *FIX: no error handling here! return true; } @@ -2609,7 +2634,7 @@ void LLAppViewer::handleViewerCrash() gDebugInfo["CurrentPath"] = gDirUtilp->getCurPath(); gDebugInfo["SessionLength"] = F32(LLFrameTimer::getElapsedSeconds()); gDebugInfo["StartupState"] = LLStartUp::getStartupStateString(); - gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) getCurrentRSS() >> 10; + gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer) LLMemory::getCurrentRSS() >> 10; gDebugInfo["FirstLogin"] = (LLSD::Boolean) gAgent.isFirstLogin(); gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall"); @@ -2843,6 +2868,23 @@ void LLAppViewer::forceQuit() LLApp::setQuitting(); } +//TODO: remove +void LLAppViewer::fastQuit(S32 error_code) +{ + // finish pending transfers + flushVFSIO(); + // let sim know we're logging out + sendLogoutRequest(); + // flush network buffers by shutting down messaging system + end_messaging_system(); + // figure out the error code + S32 final_error_code = error_code ? error_code : (S32)isError(); + // this isn't a crash + removeMarkerFile(); + // get outta here + _exit(final_error_code); +} + void LLAppViewer::requestQuit() { llinfos << "requestQuit" << llendl; @@ -2885,7 +2927,7 @@ void LLAppViewer::requestQuit() static bool finish_quit(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { @@ -2902,7 +2944,9 @@ void LLAppViewer::userQuit() requestQuit(); } else - LLNotifications::instance().add("ConfirmQuit"); + { + LLNotificationsUtil::add("ConfirmQuit"); + } } static bool finish_early_exit(const LLSD& notification, const LLSD& response) @@ -2915,16 +2959,9 @@ void LLAppViewer::earlyExit(const std::string& name, const LLSD& substitutions) { llwarns << "app_early_exit: " << name << llendl; gDoDisconnect = TRUE; - LLNotifications::instance().add(name, substitutions, LLSD(), finish_early_exit); + LLNotificationsUtil::add(name, substitutions, LLSD(), finish_early_exit); } -void LLAppViewer::forceExit(S32 arg) -{ - removeMarkerFile(); - - // *FIX:Mani - This kind of exit hardly seems appropriate. - exit(arg); -} void LLAppViewer::abortQuit() { @@ -3323,7 +3360,7 @@ const std::string& LLAppViewer::getWindowTitle() const // Callback from a dialog indicating user was logged out. bool finish_disconnect(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (1 == option) { @@ -3363,12 +3400,12 @@ void LLAppViewer::forceDisconnect(const std::string& mesg) { // Tell users what happened args["ERROR_MESSAGE"] = big_reason; - LLNotifications::instance().add("ErrorMessage", args, LLSD(), &finish_forced_disconnect); + LLNotificationsUtil::add("ErrorMessage", args, LLSD(), &finish_forced_disconnect); } else { args["MESSAGE"] = big_reason; - LLNotifications::instance().add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect ); + LLNotificationsUtil::add("YouHaveBeenLoggedOut", args, LLSD(), &finish_disconnect ); } } @@ -3520,8 +3557,7 @@ void LLAppViewer::idle() // Update frame timers static LLTimer idle_timer; - LLFrameTimer::updateFrameTime(); - LLFrameTimer::updateFrameCount(); + LLFrameTimer::updateFrameTimeAndCount(); LLEventTimer::updateClass(); LLCriticalDamp::updateInterpolants(); LLMortician::updateClass(); @@ -3723,7 +3759,7 @@ void LLAppViewer::idle() { // Handle pending gesture processing - gGestureManager.update(); + LLGestureMgr::instance().update(); gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY); } @@ -3968,6 +4004,44 @@ void LLAppViewer::idleShutdown() } } +void LLAppViewer::sendLogoutRequest() +{ + if(!mLogoutRequestSent && gMessageSystem) + { + + LLMessageSystem* msg = gMessageSystem; + msg->newMessageFast(_PREHASH_LogoutRequest); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + + gLogoutTimer.reset(); + gLogoutMaxTime = LOGOUT_REQUEST_TIME; + mLogoutRequestSent = TRUE; + + if(gVoiceClient) + gVoiceClient->leaveChannel(); + + //Set internal status variables and marker files + gLogoutInProgress = TRUE; + mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); + + LLAPRFile outfile ; + outfile.open(mLogoutMarkerFileName, LL_APR_W, LLAPRFile::global); + mLogoutMarkerFile = outfile.getFileHandle() ; + if (mLogoutMarkerFile) + { + llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl; + apr_file_close(mLogoutMarkerFile); + } + else + { + llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl; + } + } +} + void LLAppViewer::idleNameCache() { // Neither old nor new name cache can function before agent has a region @@ -4022,43 +4096,6 @@ void LLAppViewer::idleNameCache() LLAvatarNameCache::idle(); } -void LLAppViewer::sendLogoutRequest() -{ - if(!mLogoutRequestSent) - { - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_LogoutRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gAgent.sendReliableMessage(); - - gLogoutTimer.reset(); - gLogoutMaxTime = LOGOUT_REQUEST_TIME; - mLogoutRequestSent = TRUE; - - gVoiceClient->leaveChannel(); - - //Set internal status variables and marker files - gLogoutInProgress = TRUE; - mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME); - - LLAPRFile outfile ; - outfile.open(mLogoutMarkerFileName, LL_APR_W, LLAPRFile::global); - mLogoutMarkerFile = outfile.getFileHandle() ; - if (mLogoutMarkerFile) - { - llinfos << "Created logout marker file " << mLogoutMarkerFileName << llendl; - apr_file_close(mLogoutMarkerFile); - } - else - { - llwarns << "Cannot create logout marker file " << mLogoutMarkerFileName << llendl; - } - } -} - // // Handle messages, and all message related stuff // @@ -4153,7 +4190,7 @@ void LLAppViewer::idleNetwork() } } llpushcallstacks ; - gObjectList.mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects); + LLViewerStats::getInstance()->mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects); // Retransmit unacknowledged packets. gXferManager->retransmitUnackedPackets(); diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index a1dde2646..71a84d589 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -66,11 +66,11 @@ public: // Application control void flushVFSIO(); // waits for vfs transfers to complete void forceQuit(); // Puts the viewer into 'shutting down without error' mode. + void fastQuit(S32 error_code = 0); // Shuts down the viewer immediately after sending a logout message void requestQuit(); // Request a quit. A kinder, gentler quit. void userQuit(); // The users asks to quit. Confirm, then requestQuit() void earlyExit(const std::string& name, const LLSD& substitutions = LLSD()); // Display an error dialog and forcibly quit. - void forceExit(S32 arg); // exit() immediately (after some cleanup). void abortQuit(); // Called to abort a quit request. bool quitRequested() { return mQuitRequested; } diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp index 435f67ebf..a121d5556 100644 --- a/indra/newview/llassetuploadresponders.cpp +++ b/indra/newview/llassetuploadresponders.cpp @@ -39,6 +39,7 @@ #include "llcompilequeue.h" #include "llfloaterbuycurrency.h" #include "llnotify.h" +#include "llinventorydefines.h" #include "llinventorymodel.h" #include "llinventoryview.h" #include "llpermissionsflags.h" @@ -59,6 +60,7 @@ // library includes #include "lleconomy.h" #include "llfocusmgr.h" +#include "llnotificationsutil.h" #include "llscrolllistctrl.h" #include "llsdserialize.h" @@ -117,14 +119,14 @@ void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason) args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); args["REASON"] = "Error in upload request. Please visit " "http://secondlife.com/support for help fixing this problem."; - LLNotifications::instance().add("CannotUploadReason", args); + LLNotificationsUtil::add("CannotUploadReason", args); break; case 500: default: args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); args["REASON"] = "The server is experiencing unexpected " "difficulties."; - LLNotifications::instance().add("CannotUploadReason", args); + LLNotificationsUtil::add("CannotUploadReason", args); break; } LLUploadDialog::modalUploadFinished(); @@ -187,7 +189,7 @@ void LLAssetUploadResponder::uploadFailure(const LLSD& content) LLSD args; args["FILE"] = (mFileName.empty() ? mVFileID.asString() : mFileName); args["REASON"] = content["message"].asString(); - LLNotifications::instance().add("CannotUploadReason", args); + LLNotificationsUtil::add("CannotUploadReason", args); } } @@ -231,7 +233,7 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) LLSD args; args["AMOUNT"] = llformat("%d", expected_upload_cost); args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); - LLNotifications::instance().add("UploadPayment", args); + LLNotificationsUtil::add("UploadPayment", args); } // Actually add the upload to viewer inventory @@ -480,10 +482,10 @@ void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content) { // If this gesture is active, then we need to update the in-memory // active map with the new pointer. - if (gGestureManager.isGestureActive(item_id)) + if (LLGestureMgr::instance().isGestureActive(item_id)) { LLUUID asset_id = new_item->getAssetUUID(); - gGestureManager.replaceGesture(item_id, asset_id); + LLGestureMgr::instance().replaceGesture(item_id, asset_id); gInventory.notifyObservers(); } diff --git a/indra/newview/llbbox.cpp b/indra/newview/llbbox.cpp deleted file mode 100644 index 7bc1213c5..000000000 --- a/indra/newview/llbbox.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @file llbbox.cpp - * @brief General purpose bounding box class (Not axis aligned) - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -// self include -#include "llbbox.h" - -// library includes -#include "m4math.h" - -void LLBBox::addPointLocal(const LLVector3& p) -{ - if (mEmpty) - { - mMinLocal = p; - mMaxLocal = p; - mEmpty = FALSE; - } - else - { - mMinLocal.mV[VX] = llmin( p.mV[VX], mMinLocal.mV[VX] ); - mMinLocal.mV[VY] = llmin( p.mV[VY], mMinLocal.mV[VY] ); - mMinLocal.mV[VZ] = llmin( p.mV[VZ], mMinLocal.mV[VZ] ); - mMaxLocal.mV[VX] = llmax( p.mV[VX], mMaxLocal.mV[VX] ); - mMaxLocal.mV[VY] = llmax( p.mV[VY], mMaxLocal.mV[VY] ); - mMaxLocal.mV[VZ] = llmax( p.mV[VZ], mMaxLocal.mV[VZ] ); - } -} - -void LLBBox::addPointAgent( LLVector3 p) -{ - p -= mPosAgent; - p.rotVec( ~mRotation ); - addPointLocal( p ); -} - - -void LLBBox::addBBoxAgent(const LLBBox& b) -{ - if (mEmpty) - { - mPosAgent = b.mPosAgent; - mRotation = b.mRotation; - mMinLocal.clearVec(); - mMaxLocal.clearVec(); - } - LLVector3 vertex[8]; - vertex[0].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[1].setVec( b.mMinLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - vertex[2].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[3].setVec( b.mMinLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - vertex[4].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[5].setVec( b.mMaxLocal.mV[VX], b.mMinLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - vertex[6].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMinLocal.mV[VZ] ); - vertex[7].setVec( b.mMaxLocal.mV[VX], b.mMaxLocal.mV[VY], b.mMaxLocal.mV[VZ] ); - - LLMatrix4 m( b.mRotation ); - m.translate( b.mPosAgent ); - m.translate( -mPosAgent ); - m.rotate( ~mRotation ); - - for( S32 i=0; i<8; i++ ) - { - addPointLocal( vertex[i] * m ); - } -} - - -void LLBBox::expand( F32 delta ) -{ - mMinLocal.mV[VX] -= delta; - mMinLocal.mV[VY] -= delta; - mMinLocal.mV[VZ] -= delta; - mMaxLocal.mV[VX] += delta; - mMaxLocal.mV[VY] += delta; - mMaxLocal.mV[VZ] += delta; -} - -LLVector3 LLBBox::localToAgent(const LLVector3& v) const -{ - LLMatrix4 m( mRotation ); - m.translate( mPosAgent ); - return v * m; -} - -LLVector3 LLBBox::agentToLocal(const LLVector3& v) const -{ - LLMatrix4 m; - m.translate( -mPosAgent ); - m.rotate( ~mRotation ); // inverse rotation - return v * m; -} - -LLVector3 LLBBox::localToAgentBasis(const LLVector3& v) const -{ - LLMatrix4 m( mRotation ); - return v * m; -} - -LLVector3 LLBBox::agentToLocalBasis(const LLVector3& v) const -{ - LLMatrix4 m( ~mRotation ); // inverse rotation - return v * m; -} - -BOOL LLBBox::containsPointLocal(const LLVector3& p) const -{ - if ( (p.mV[VX] < mMinLocal.mV[VX]) - ||(p.mV[VX] > mMaxLocal.mV[VX]) - ||(p.mV[VY] < mMinLocal.mV[VY]) - ||(p.mV[VY] > mMaxLocal.mV[VY]) - ||(p.mV[VZ] < mMinLocal.mV[VZ]) - ||(p.mV[VZ] > mMaxLocal.mV[VZ])) - { - return FALSE; - } - return TRUE; -} - -BOOL LLBBox::containsPointAgent(const LLVector3& p) const -{ - LLVector3 point_local = agentToLocal(p); - return containsPointLocal(point_local); -} - - -/* -LLBBox operator*(const LLBBox &a, const LLMatrix4 &b) -{ - return LLBBox( a.mMin * b, a.mMax * b ); -} -*/ diff --git a/indra/newview/llbbox.h b/indra/newview/llbbox.h deleted file mode 100644 index 1b4d2b4dd..000000000 --- a/indra/newview/llbbox.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @file llbbox.h - * @brief General purpose bounding box class - * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * - * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 - * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception - * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. - * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. - * $/LicenseInfo$ - */ - -#ifndef LL_BBOX_H -#define LL_BBOX_H - -#include "v3math.h" -#include "llquaternion.h" - -// Note: "local space" for an LLBBox is defined relative to agent space in terms of -// a translation followed by a rotation. There is no scale term since the LLBBox's min and -// max are not necessarily symetrical and define their own extents. - -class LLBBox -{ -public: - LLBBox() {mEmpty = TRUE;} - LLBBox( const LLVector3& pos_agent, - const LLQuaternion& rot, - const LLVector3& min_local, - const LLVector3& max_local ) - : - mMinLocal( min_local ), mMaxLocal( max_local ), mPosAgent(pos_agent), mRotation( rot), mEmpty( TRUE ) - {} - - // Default copy constructor is OK. - - const LLVector3& getPositionAgent() const { return mPosAgent; } - const LLQuaternion& getRotation() const { return mRotation; } - - const LLVector3& getMinLocal() const { return mMinLocal; } - void setMinLocal( const LLVector3& min ) { mMinLocal = min; } - - const LLVector3& getMaxLocal() const { return mMaxLocal; } - void setMaxLocal( const LLVector3& max ) { mMaxLocal = max; } - - LLVector3 getCenterLocal() const { return (mMaxLocal - mMinLocal) * 0.5f + mMinLocal; } - LLVector3 getCenterAgent() const { return localToAgent( getCenterLocal() ); } - - LLVector3 getExtentLocal() const { return mMaxLocal - mMinLocal; } - - BOOL containsPointLocal(const LLVector3& p) const; - BOOL containsPointAgent(const LLVector3& p) const; - - BOOL intersects(const LLBBox& b) const; - - void addPointAgent(LLVector3 p); - void addBBoxAgent(const LLBBox& b); - - void addPointLocal(const LLVector3& p); - void addBBoxLocal(const LLBBox& b) { addPointLocal( b.mMinLocal ); addPointLocal( b.mMaxLocal ); } - - void expand( F32 delta ); - - LLVector3 localToAgent( const LLVector3& v ) const; - LLVector3 agentToLocal( const LLVector3& v ) const; - - // Changes rotation but not position - LLVector3 localToAgentBasis(const LLVector3& v) const; - LLVector3 agentToLocalBasis(const LLVector3& v) const; - - -// friend LLBBox operator*(const LLBBox& a, const LLMatrix4& b); - -private: - LLVector3 mMinLocal; - LLVector3 mMaxLocal; - LLVector3 mPosAgent; // Position relative to Agent's Region - LLQuaternion mRotation; - BOOL mEmpty; // Nothing has been added to this bbox yet -}; - -//LLBBox operator*(const LLBBox &a, const LLMatrix4 &b); - - -#endif // LL_BBOX_H diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 0f591c968..97206d2c0 100644 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -53,7 +53,8 @@ #include "llbutton.h" //#include "llinventory.h" #include "llinventorymodel.h" -#include "llnotify.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llresmgr.h" #include "llimview.h" #include "llviewercontrol.h" @@ -656,11 +657,11 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) payload["from_id"] = agent_id; if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights) { - LLNotifications::instance().add("GrantedModifyRights",args, payload); + LLNotificationsUtil::add("GrantedModifyRights",args, payload); } else { - LLNotifications::instance().add("RevokedModifyRights",args, payload); + LLNotificationsUtil::add("RevokedModifyRights",args, payload); } } (mBuddyInfo[agent_id])->setRightsFrom(new_rights); @@ -748,7 +749,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, } // Popup a notify box with online status of this agent - LLNotificationPtr notification = LLNotifications::instance().add(online ? "FriendOnline" : "FriendOffline", args, payload); + LLNotificationPtr notification = LLNotificationsUtil::add(online ? "FriendOnline" : "FriendOffline", args, payload); // If there's an open IM session with this agent, send a notification there too. LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, agent_id); diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index c3a02ce54..61d619f40 100644 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -127,7 +127,7 @@ LLChatBar::LLChatBar() LLChatBar::~LLChatBar() { - gGestureManager.removeObserver(mObserver); + LLGestureMgr::instance().removeObserver(mObserver); delete mObserver; mObserver = NULL; // LLView destructor cleans up children @@ -247,8 +247,8 @@ void LLChatBar::refreshGestures() // collect list of unique gestures std::map <std::string, BOOL> unique; - LLGestureManager::item_map_t::iterator it; - for (it = gGestureManager.mActive.begin(); it != gGestureManager.mActive.end(); ++it) + LLGestureMgr::item_map_t::const_iterator it; + for (it = LLGestureMgr::instance().getActiveGestures().begin(); it != LLGestureMgr::instance().getActiveGestures().end(); ++it) { LLMultiGesture* gesture = (*it).second; if (gesture) @@ -334,7 +334,7 @@ void LLChatBar::setGestureCombo(LLComboBox* combo) // now register observer since we have a place to put the results mObserver = new LLChatBarGestureObserver(this); - gGestureManager.addObserver(mObserver); + LLGestureMgr::instance().addObserver(mObserver); // refresh list from current active gestures refreshGestures(); @@ -469,7 +469,7 @@ void LLChatBar::sendChat( EChatType type ) } } // discard returned "found" boolean - gGestureManager.triggerAndReviseString(utf8text, &utf8_revised_text); + LLGestureMgr::instance().triggerAndReviseString(utf8text, &utf8_revised_text); } else { @@ -601,7 +601,7 @@ void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata ) std::string utf8_trigger = wstring_to_utf8str(raw_text); std::string utf8_out_str(utf8_trigger); - if (gGestureManager.matchPrefix(utf8_trigger, &utf8_out_str)) + if (LLGestureMgr::instance().matchPrefix(utf8_trigger, &utf8_out_str)) { if (self->mInputEditor) { @@ -826,7 +826,7 @@ void LLChatBar::onCommitGesture(LLUICtrl* ctrl, void* data) // substitution and logging. std::string text(trigger); std::string revised_text; - gGestureManager.triggerAndReviseString(text, &revised_text); + LLGestureMgr::instance().triggerAndReviseString(text, &revised_text); revised_text = utf8str_trim(revised_text); if (!revised_text.empty()) diff --git a/indra/newview/llcloud.cpp b/indra/newview/llcloud.cpp index ca35c3711..116d227cc 100644 --- a/indra/newview/llcloud.cpp +++ b/indra/newview/llcloud.cpp @@ -437,7 +437,7 @@ void LLCloudLayer::decompress(LLBitPack &bitpack, LLGroupHeader *group_headerp) group_headerp->stride = group_headerp->patch_size; // offset required to step up one row set_group_of_patch_header(group_headerp); - decode_patch_header(bitpack, &patch_header); + decode_patch_header(bitpack, &patch_header, FALSE); decode_patch(bitpack, gBuffer); decompress_patch(mDensityp, gBuffer, &patch_header); } diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 1d4ff5770..4504fb986 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -37,12 +37,12 @@ // Linden library includes #include "v4color.h" +#include "llwindow.h" // setCursor() // Project includes #include "llui.h" #include "llrender.h" #include "lluiconstants.h" -#include "llviewerwindow.h" #include "llviewercontrol.h" #include "llbutton.h" #include "lltextbox.h" @@ -330,7 +330,11 @@ void LLColorSwatchCtrl::showPicker(BOOL take_focus) if (!pickerp) { pickerp = new LLFloaterColorPicker(this, mCanApplyImmediately); - gFloaterView->getParentFloater(this)->addDependentFloater(pickerp); + LLFloater* parent = gFloaterView->getParentFloater(this); + if (parent) + { + parent->addDependentFloater(pickerp); + } mPickerHandle = pickerp->getHandle(); } diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 3d01eeff3..97831b4b2 100644 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -57,6 +57,7 @@ #include "llresmgr.h" #include "llbutton.h" #include "lldir.h" +#include "llnotificationsutil.h" #include "llfloaterchat.h" #include "llviewerstats.h" #include "lluictrlfactory.h" @@ -527,7 +528,7 @@ void LLFloaterCompileQueue::onSaveTextComplete(const LLUUID& asset_id, void* use llwarns << "Unable to save text for script." << llendl; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("CompileQueueSaveText", args); + LLNotificationsUtil::add("CompileQueueSaveText", args); } } @@ -548,7 +549,7 @@ void LLFloaterCompileQueue::onSaveBytecodeComplete(const LLUUID& asset_id, void* llwarns << "Unable to save bytecode for script." << llendl; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("CompileQueueSaveBytecode", args); + LLNotificationsUtil::add("CompileQueueSaveBytecode", args); } delete data; data = NULL; diff --git a/indra/newview/llconfirmationmanager.cpp b/indra/newview/llconfirmationmanager.cpp index 00ffff79a..4b7333995 100644 --- a/indra/newview/llconfirmationmanager.cpp +++ b/indra/newview/llconfirmationmanager.cpp @@ -37,9 +37,9 @@ #include "lluictrlfactory.h" // viewer includes -#include "llviewerwindow.h" -#include "lllineeditor.h" +#include "llnotificationsutil.h" #include "llstring.h" +#include "llxmlnode.h" LLConfirmationManager::ListenerBase::~ListenerBase() { @@ -48,7 +48,7 @@ LLConfirmationManager::ListenerBase::~ListenerBase() static bool onConfirmAlert(const LLSD& notification, const LLSD& response, LLConfirmationManager::ListenerBase* listener) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { listener->confirmed(""); @@ -61,7 +61,7 @@ static bool onConfirmAlert(const LLSD& notification, const LLSD& response, LLCon static bool onConfirmAlertPassword(const LLSD& notification, const LLSD& response, LLConfirmationManager::ListenerBase* listener) { std::string text = response["message"].asString(); - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { @@ -83,11 +83,11 @@ void LLConfirmationManager::confirm(Type type, switch (type) { case TYPE_CLICK: - LLNotifications::instance().add("ConfirmPurchase", args, LLSD(), boost::bind(onConfirmAlert, _1, _2, listener)); + LLNotificationsUtil::add("ConfirmPurchase", args, LLSD(), boost::bind(onConfirmAlert, _1, _2, listener)); break; case TYPE_PASSWORD: - LLNotifications::instance().add("ConfirmPurchasePassword", args, LLSD(), boost::bind(onConfirmAlertPassword, _1, _2, listener)); + LLNotificationsUtil::add("ConfirmPurchasePassword", args, LLSD(), boost::bind(onConfirmAlertPassword, _1, _2, listener)); break; case TYPE_NONE: default: diff --git a/indra/newview/llconsole.cpp b/indra/newview/llconsole.cpp index 937ccec24..db2d474b0 100644 --- a/indra/newview/llconsole.cpp +++ b/indra/newview/llconsole.cpp @@ -456,6 +456,14 @@ void LLConsole::Paragraph::updateLines(F32 screen_width, LLFontGL* font, bool fo LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time) : mParagraphText(str), mAddTime(add_time), mMaxWidth(-1) { - makeParagraphColorSegments(color); + // Only call makeParagraphColorSegments if the user logged in already (we come + // here before he logged in when they disabled login/logout screens). + // Otherwise makeParagraphColorSegments calls LLTextParser::getInstance() which + // causes a one-time initialization by reading highlights.xml, which fails + // when not logged in because it's per account. + if (!gDirUtilp->getLindenUserDir(true).empty()) + { + makeParagraphColorSegments(color); + } } diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp index 8b2aac6e9..e6fed3c30 100644 --- a/indra/newview/lldebugview.cpp +++ b/indra/newview/lldebugview.cpp @@ -75,8 +75,9 @@ LLDebugView::LLDebugView(const std::string& name, const LLRect &rect) mFrameStatView->setVisible(FALSE); // start invisible addChild(mFrameStatView); - r.set(25, rect.getHeight() - 50, (S32) (gViewerWindow->getVirtualWindowRect().getWidth() * 0.75f), - (S32) (gViewerWindow->getVirtualWindowRect().getHeight() * 0.75f)); + r.setLeftTopAndSize(25, rect.getHeight() - 50, + (S32) (gViewerWindow->getVirtualWindowRect().getWidth() * 0.75f), + (S32) (gViewerWindow->getVirtualWindowRect().getHeight() * 0.75f)); mFastTimerView = new LLFastTimerView("fast timers", r); mFastTimerView->setFollowsTop(); mFastTimerView->setFollowsLeft(); diff --git a/indra/newview/lldelayedgestureerror.cpp b/indra/newview/lldelayedgestureerror.cpp index 1af94b350..ead377deb 100644 --- a/indra/newview/lldelayedgestureerror.cpp +++ b/indra/newview/lldelayedgestureerror.cpp @@ -33,8 +33,9 @@ #include "llviewerprecompiledheaders.h" #include "lldelayedgestureerror.h" + #include <list> -#include "llnotify.h" +#include "llnotificationsutil.h" #include "llcallbacklist.h" #include "llinventory.h" #include "llviewerinventory.h" @@ -119,7 +120,7 @@ bool LLDelayedGestureError::doDialog(const LLErrorEntry &ent, bool uuid_ok) } - LLNotifications::instance().add(ent.mNotifyName, args); + LLNotificationsUtil::add(ent.mNotifyName, args); return true; } diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 89bc66dfc..f5754505d 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -41,6 +41,7 @@ #include "llcriticaldamp.h" #include "llface.h" #include "lllightconstants.h" +#include "llmatrix4a.h" #include "llsky.h" #include "llsurfacepatch.h" #include "llviewercamera.h" @@ -86,7 +87,7 @@ LLDynamicArrayPtr<LLPointer<LLDrawable> > LLDrawable::sDeadList; void LLDrawable::incrementVisible() { sCurVisible++; - sCurPixelAngle = (F32) gViewerWindow->getWindowDisplayHeight()/LLViewerCamera::getInstance()->getView(); + sCurPixelAngle = (F32) gViewerWindow->getWindowHeightRaw()/LLViewerCamera::getInstance()->getView(); } void LLDrawable::init() { @@ -95,7 +96,7 @@ void LLDrawable::init() mRenderType = 0; mCurrentScale = LLVector3(1,1,1); mDistanceWRTCamera = 0.0f; - mPositionGroup.clearVec(); + mPositionGroup.clear(); mExtents[0].clear(); mExtents[1].clear(); mQuietCount = 0; @@ -201,16 +202,22 @@ void LLDrawable::cleanupReferences() { LLFastTimer t(LLFastTimer::FTM_PIPELINE); - std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); - mFaces.clear(); + { + //LLFastTimer t(FTM_DELETE_FACES); + std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); + mFaces.clear(); + } gObjectList.removeDrawable(this); gPipeline.unlinkDrawable(this); - // Cleanup references to other objects - mVObjp = NULL; - mParent = NULL; + { + //LLFastTimer t(FTM_DEREF_DRAWABLE); + // Cleanup references to other objects + mVObjp = NULL; + mParent = NULL; + } } void LLDrawable::cleanupDeadDrawables() @@ -705,7 +712,7 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) { if (getSpatialGroup()) { - pos.set(getPositionGroup()); + pos.set(getPositionGroup().getF32ptr()); } else { @@ -714,26 +721,28 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) if (isState(LLDrawable::HAS_ALPHA)) { - for (S32 i = 0; i < getNumFaces(); i++) - { - LLFace* facep = getFace(i); - if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA) + for (S32 i = 0; i < getNumFaces(); i++) { - LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f; - LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); + LLFace* facep = getFace(i); + if (force_update || facep->getPoolType() == LLDrawPool::POOL_ALPHA) + { + LLVector4a box; + box.setSub(facep->mExtents[1], facep->mExtents[0]); + box.mul(0.25f); + LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); const LLVector3& at = camera.getAtAxis(); for (U32 j = 0; j < 3; j++) - { - v.mV[j] -= box.mV[j] * at.mV[j]; + { + v.mV[j] -= box[j] * at.mV[j]; + } + facep->mDistance = v * camera.getAtAxis(); } - facep->mDistance = v * camera.getAtAxis(); } } - } } else { - pos = LLVector3(getPositionGroup()); + pos = LLVector3(getPositionGroup().getF32ptr()); } pos -= camera.getOrigin(); @@ -782,7 +791,7 @@ BOOL LLDrawable::updateGeometry(BOOL priority) return res; } -void LLDrawable::shiftPos(const LLVector3 &shift_vector) +void LLDrawable::shiftPos(const LLVector4a &shift_vector) { if (isDead()) { @@ -814,9 +823,9 @@ void LLDrawable::shiftPos(const LLVector3 &shift_vector) for (S32 i = 0; i < getNumFaces(); i++) { LLFace *facep = getFace(i); - facep->mCenterAgent += shift_vector; - facep->mExtents[0] += shift_vector; - facep->mExtents[1] += shift_vector; + facep->mCenterAgent += LLVector3(shift_vector.getF32ptr()); + facep->mExtents[0].add(shift_vector); + facep->mExtents[1].add(shift_vector); if (!volume && facep->hasGeometry()) { @@ -824,9 +833,9 @@ void LLDrawable::shiftPos(const LLVector3 &shift_vector) } } - mExtents[0] += shift_vector; - mExtents[1] += shift_vector; - mPositionGroup += LLVector3d(shift_vector); + mExtents[0].add(shift_vector); + mExtents[1].add(shift_vector); + mPositionGroup.add(shift_vector); } else if (mSpatialBridge) { @@ -834,9 +843,9 @@ void LLDrawable::shiftPos(const LLVector3 &shift_vector) } else if (isAvatar()) { - mExtents[0] += shift_vector; - mExtents[1] += shift_vector; - mPositionGroup += LLVector3d(shift_vector); + mExtents[0].add(shift_vector); + mExtents[1].add(shift_vector); + mPositionGroup.add(shift_vector); } mVObjp->onShift(shift_vector); @@ -848,21 +857,26 @@ const LLVector3& LLDrawable::getBounds(LLVector3& min, LLVector3& max) const return mXform.getPositionW(); } -const LLVector3* LLDrawable::getSpatialExtents() const +const LLVector4a* LLDrawable::getSpatialExtents() const { return mExtents; } -void LLDrawable::setSpatialExtents(LLVector3 min, LLVector3 max) +void LLDrawable::setSpatialExtents(const LLVector3& min, const LLVector3& max) { - LLVector3 size = max - min; - mExtents[0] = min; - mExtents[1] = max; + mExtents[0].load3(min.mV); + mExtents[1].load3(max.mV); } -void LLDrawable::setPositionGroup(const LLVector3d& pos) +void LLDrawable::setSpatialExtents(const LLVector4a& min, const LLVector4a& max) +{ + mExtents[0] = min; + mExtents[1] = max; +} + +void LLDrawable::setPositionGroup(const LLVector4a& pos) { - mPositionGroup.setVec(pos); + mPositionGroup = pos; } void LLDrawable::updateSpatialExtents() @@ -876,7 +890,7 @@ void LLDrawable::updateSpatialExtents() if (mSpatialBridge.notNull()) { - mPositionGroup.setVec(0,0,0); + mPositionGroup.splat(0.f); } } @@ -1099,59 +1113,72 @@ void LLSpatialBridge::updateSpatialExtents() root->rebound(); } - LLXformMatrix* mat = mDrawable->getXform(); - - LLVector3 offset = root->mBounds[0]; - LLVector3 size = root->mBounds[1]; + LLVector4a offset; + LLVector4a size = root->mBounds[1]; - LLVector3 center = LLVector3(0,0,0) * mat->getWorldMatrix(); - LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix()); - - offset *= rotation; - center += offset; - - LLVector3 v[4]; - //get 4 corners of bounding box - v[0] = (size * rotation); - v[1] = (LLVector3(-size.mV[0], -size.mV[1], size.mV[2]) * rotation); - v[2] = (LLVector3(size.mV[0], -size.mV[1], -size.mV[2]) * rotation); - v[3] = (LLVector3(-size.mV[0], size.mV[1], -size.mV[2]) * rotation); + //VECTORIZE THIS + LLMatrix4a mat; + mat.loadu(mDrawable->getXform()->getWorldMatrix()); - LLVector3& newMin = mExtents[0]; - LLVector3& newMax = mExtents[1]; + LLVector4a t; + t.splat(0.f); + + LLVector4a center; + mat.affineTransform(t, center); + + mat.rotate(root->mBounds[0], offset); + center.add(offset); + + LLVector4a v[4]; + + //get 4 corners of bounding box + mat.rotate(size,v[0]); + + LLVector4a scale; + + scale.set(-1.f, -1.f, 1.f); + scale.mul(size); + mat.rotate(scale, v[1]); + + scale.set(1.f, -1.f, -1.f); + scale.mul(size); + mat.rotate(scale, v[2]); + + scale.set(-1.f, 1.f, -1.f); + scale.mul(size); + mat.rotate(scale, v[3]); + + + LLVector4a& newMin = mExtents[0]; + LLVector4a& newMax = mExtents[1]; newMin = newMax = center; for (U32 i = 0; i < 4; i++) { - for (U32 j = 0; j < 3; j++) - { - F32 delta = fabsf(v[i].mV[j]); - F32 min = center.mV[j] - delta; - F32 max = center.mV[j] + delta; - - if (min < newMin.mV[j]) - { - newMin.mV[j] = min; - } - - if (max > newMax.mV[j]) - { - newMax.mV[j] = max; - } - } - } + LLVector4a delta; + delta.setAbs(v[i]); + LLVector4a min; + min.setSub(center, delta); + LLVector4a max; + max.setAdd(center, delta); - LLVector3 diagonal = newMax - newMin; - mRadius = diagonal.magVec() * 0.5f; + newMin.setMin(newMin, min); + newMax.setMax(newMax, max); + } - mPositionGroup.setVec((newMin + newMax) * 0.5f); + LLVector4a diagonal; + diagonal.setSub(newMax, newMin); + mRadius = diagonal.getLength3().getF32() * 0.5f; + + mPositionGroup.setAdd(newMin,newMax); + mPositionGroup.mul(0.5f); updateBinRadius(); } void LLSpatialBridge::updateBinRadius() { - mBinRadius = llmin((F32) mOctree->getSize().mdV[0]*0.5f, 256.f); + mBinRadius = llmin( mOctree->getSize()[0]*0.5f, 256.f); } LLCamera LLSpatialBridge::transformCamera(LLCamera& camera) @@ -1292,8 +1319,12 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); - LLVector3 center = (mExtents[0] + mExtents[1]) * 0.5f; - LLVector3 size = (mExtents[1]-mExtents[0]) * 0.5f; + LLVector4a center; + center.setAdd(mExtents[0], mExtents[1]); + center.mul(0.5f); + LLVector4a size; + size.setSub(mExtents[1], mExtents[0]); + size.mul(0.5f); if ((LLPipeline::sShadowRender && camera_in.AABBInFrustum(center, size)) || LLPipeline::sImpostorRender || @@ -1397,6 +1428,7 @@ BOOL LLSpatialBridge::updateMove() llassert_always(mDrawable->getRegion()); LLSpatialPartition* part = mDrawable->getRegion()->getSpatialPartition(mPartitionType); llassert_always(part); + mOctree->balance(); if (part) { @@ -1405,11 +1437,11 @@ BOOL LLSpatialBridge::updateMove() return TRUE; } -void LLSpatialBridge::shiftPos(const LLVector3& vec) +void LLSpatialBridge::shiftPos(const LLVector4a& vec) { - mExtents[0] += vec; - mExtents[1] += vec; - mPositionGroup += LLVector3d(vec); + mExtents[0].add(vec); + mExtents[1].add(vec); + mPositionGroup.add(vec); } void LLSpatialBridge::cleanupReferences() @@ -1527,7 +1559,7 @@ F32 LLHUDBridge::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) } -void LLHUDBridge::shiftPos(const LLVector3& vec) +void LLHUDBridge::shiftPos(const LLVector4a& vec) { //don't shift hud bridges on region crossing } diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h index a515612e6..6c044978f 100644 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -41,6 +41,7 @@ #include "v4math.h" #include "m4math.h" #include "v4coloru.h" +#include "llvector4a.h" #include "llquaternion.h" #include "xform.h" #include "llmemtype.h" @@ -63,7 +64,6 @@ class LLViewerTexture; // Can have multiple silhouettes for each object const U32 SILHOUETTE_HIGHLIGHT = 0; - // All data for new renderer goes into this class. class LLDrawable : public LLRefCount { @@ -107,7 +107,7 @@ public: const LLVector3& getPosition() const { return mXform.getPosition(); } const LLVector3& getWorldPosition() const { return mXform.getPositionW(); } const LLVector3 getPositionAgent() const; - const LLVector3d& getPositionGroup() const { return mPositionGroup; } + const LLVector4a& getPositionGroup() const { return mPositionGroup; } const LLVector3& getScale() const { return mCurrentScale; } void setScale(const LLVector3& scale) { mCurrentScale = scale; } const LLQuaternion& getWorldRotation() const { return mXform.getWorldRotation(); } @@ -168,7 +168,7 @@ public: void updateSpecialHoverCursor(BOOL enabled); - virtual void shiftPos(const LLVector3 &shift_vector); + virtual void shiftPos(const LLVector4a &shift_vector); S32 getGeneration() const { return mGeneration; } @@ -186,10 +186,11 @@ public: const LLVector3& getBounds(LLVector3& min, LLVector3& max) const; virtual void updateSpatialExtents(); virtual void updateBinRadius(); - const LLVector3* getSpatialExtents() const; - void setSpatialExtents(LLVector3 min, LLVector3 max); - void setPositionGroup(const LLVector3d& pos); - void setPositionGroup(const LLVector3& pos) { setPositionGroup(LLVector3d(pos)); } + const LLVector4a* getSpatialExtents() const; + void setSpatialExtents(const LLVector3& min, const LLVector3& max); + void setSpatialExtents(const LLVector4a& min, const LLVector4a& max); + + void setPositionGroup(const LLVector4a& pos); void setRenderType(S32 type) { mRenderType = type; } BOOL isRenderType(S32 type) { return mRenderType == type; } @@ -268,6 +269,9 @@ public: REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR, REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR, REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_VOLUME, +#if MESH_ENABLED + REBUILD_RIGGED = 0x00008000, +#endif //MESH_ENABLED ON_SHIFT_LIST = 0x00010000, BLOCKER = 0x00020000, ACTIVE = 0x00040000, @@ -279,9 +283,17 @@ public: CLEAR_INVISIBLE = 0x01000000, // clear FORCE_INVISIBLE next draw frame REBUILD_SHADOW = 0x02000000, HAS_ALPHA = 0x04000000, +#if MESH_ENABLED + RIGGED = 0x08000000, +#endif //MESH_ENABLED PARTITION_MOVE = 0x10000000, } EDrawableFlags; +private: //aligned members + LLVector4a mExtents[2]; + LLVector4a mPositionGroup; + +public: LLXformMatrix mXform; // vis data @@ -293,7 +305,7 @@ public: static S32 getCurrentFrame() { return sCurVisible; } static S32 getMinVisFrameRange(); - + void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; } LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; } @@ -311,8 +323,6 @@ private: mutable U32 mVisible; F32 mRadius; - LLVector3 mExtents[2]; - LLVector3d mPositionGroup; F32 mBinRadius; S32 mGeneration; diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 474538a17..e32d1b70d 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -197,6 +197,15 @@ void LLDrawPool::renderPostDeferred(S32 pass) //virtual void LLDrawPool::endRenderPass( S32 pass ) { + /*for (U32 i = 0; i < (U32)gGLManager.mNumTextureImageUnits; i++) + { //dummy cleanup of any currently bound textures + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } + }*/ + gGL.getTexUnit(0)->activate(); } //virtual @@ -249,11 +258,6 @@ void LLFacePool::dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures { } -BOOL LLFacePool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data) -{ - return TRUE; -} - // static S32 LLFacePool::drawLoop(face_array_t& face_list) { @@ -441,14 +445,14 @@ void LLRenderPass::renderTexture(U32 type, U32 mask) pushBatches(type, mask, TRUE); } -void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture) +void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures) { for (LLCullResult::drawinfo_list_t::iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i) { LLDrawInfo* pparams = *i; if (pparams) { - pushBatch(*pparams, mask, texture); + pushBatch(*pparams, mask, texture, batch_textures); } } } @@ -467,26 +471,43 @@ void LLRenderPass::applyModelMatrix(LLDrawInfo& params) } } -void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) +void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { applyModelMatrix(params); + bool tex_setup = false; + if (texture) { - if (params.mTexture.notNull()) + if (batch_textures && params.mTextureList.size() > 1) { - params.mTexture->addTextureStats(params.mVSize); - gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; - if (params.mTextureMatrix) + for (U32 i = 0; i < params.mTextureList.size(); ++i) { - glMatrixMode(GL_TEXTURE); - glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; + if (params.mTextureList[i].notNull()) + { + gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + } } } else - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + { //not batching textures or batch has only 1 texture -- might need a texture matrix + if (params.mTexture.notNull()) + { + params.mTexture->addTextureStats(params.mVSize); + gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; + if (params.mTextureMatrix) + { + tex_setup = true; + gGL.getTexUnit(0)->activate(); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + } + } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } } } @@ -501,7 +522,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) gPipeline.addTrianglesDrawn(params.mCount/3); } - if (params.mTextureMatrix && texture && params.mTexture.notNull()) + if (tex_setup) { glLoadIdentity(); glMatrixMode(GL_MODELVIEW); diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h index 440a2a845..481614592 100644 --- a/indra/newview/lldrawpool.h +++ b/indra/newview/lldrawpool.h @@ -147,8 +147,8 @@ public: void resetDrawOrders() { } static void applyModelMatrix(LLDrawInfo& params); - virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE); - virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture); + virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); + virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); virtual void renderGroups(U32 type, U32 mask, BOOL texture = TRUE); virtual void renderTexture(U32 type, U32 mask); @@ -169,10 +169,7 @@ public: LLFacePool(const U32 type); virtual ~LLFacePool(); - virtual void renderForSelect() {}; //Override if neded. BOOL isDead() { return mReferences.empty(); } - virtual void renderFaceSelected(LLFace *facep, LLViewerTexture *image, const LLColor4 &color, - const S32 index_offset = 0, const S32 index_count = 0) {}; //Override if neded. virtual LLViewerTexture *getTexture(); virtual void dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures); @@ -186,8 +183,6 @@ public: virtual void resetDrawOrders(); void resetAll(); - BOOL moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data = FALSE); - void destroy(); void buildEdges(); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index d6ea59ff7..664db16b7 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -95,31 +95,57 @@ void LLDrawPoolAlpha::endDeferredPass(S32 pass) void LLDrawPoolAlpha::renderDeferred(S32 pass) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); - { - LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); - gDeferredTreeProgram.bind(); - LLGLEnable test(GL_ALPHA_TEST); - //render alpha masked objects - LLRenderPass::renderTexture(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); - gDeferredTreeProgram.unbind(); - } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + gDeferredDiffuseAlphaMaskProgram.bind(); + gDeferredDiffuseAlphaMaskProgram.setAlphaRange(0.33f, 1.f); + + //render alpha masked objects + LLRenderPass::pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + gDeferredDiffuseAlphaMaskProgram.unbind(); } S32 LLDrawPoolAlpha::getNumPostDeferredPasses() { - return 1; + if (LLPipeline::sImpostorRender) + { //skip depth buffer filling pass when rendering impostors + return 1; + } + else if (gSavedSettings.getBOOL("RenderDepthOfField")) + { + return 2; + } + else + { + return 1; + } } void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); - simple_shader = &gDeferredAlphaProgram; - fullbright_shader = &gDeferredFullbrightProgram; - + if (pass == 0) + { + simple_shader = &gDeferredAlphaProgram; + fullbright_shader = &gObjectFullbrightAlphaMaskProgram; + + //prime simple shader (loads shadow relevant uniforms) + gPipeline.bindDeferredShader(*simple_shader); + } + else + { + //update depth buffer sampler + gPipeline.mScreen.flush(); + gPipeline.mDeferredDepth.copyContents(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(), gPipeline.mDeferredScreen.getHeight(), + 0, 0, gPipeline.mDeferredDepth.getWidth(), gPipeline.mDeferredDepth.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST); + gPipeline.mDeferredDepth.bindTarget(); + simple_shader = NULL; + fullbright_shader = NULL; + gObjectFullbrightAlphaMaskProgram.bind(); + gObjectFullbrightAlphaMaskProgram.setAlphaRange(0.33f, 1.f); + } + deferred_render = TRUE; if (mVertexShaderLevel > 0) { @@ -131,6 +157,14 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass) void LLDrawPoolAlpha::endPostDeferredPass(S32 pass) { + + if (pass == 1) + { + gPipeline.mDeferredDepth.flush(); + gPipeline.mScreen.bindTarget(); + gObjectFullbrightAlphaMaskProgram.unbind(); + } + deferred_render = FALSE; endRenderPass(pass); } @@ -146,13 +180,13 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass) if (LLPipeline::sUnderWaterRender) { - simple_shader = &gObjectSimpleWaterProgram; - fullbright_shader = &gObjectFullbrightWaterProgram; + simple_shader = &gObjectSimpleWaterAlphaMaskProgram; + fullbright_shader = &gObjectFullbrightWaterAlphaMaskProgram; } else { - simple_shader = &gObjectSimpleProgram; - fullbright_shader = &gObjectFullbrightProgram; + simple_shader = &gObjectSimpleAlphaMaskProgram; + fullbright_shader = &gObjectFullbrightAlphaMaskProgram; } if (mVertexShaderLevel > 0) @@ -181,8 +215,15 @@ void LLDrawPoolAlpha::render(S32 pass) LLGLSPipelineAlpha gls_pipeline_alpha; - gGL.setColorMask(true, true); - if (LLPipeline::sFastAlpha && !deferred_render) + if (deferred_render && pass == 1) + { //depth only + gGL.setColorMask(false, false); + } + else + { + gGL.setColorMask(true, true); + } + if (LLPipeline::sFastAlpha) { mColorSFactor = LLRender::BF_ONE; // } mColorDFactor = LLRender::BF_ZERO; // } these are like disabling blend on the color channels, but we're still blending on the alpha channel so that we can suppress glow @@ -190,60 +231,115 @@ void LLDrawPoolAlpha::render(S32 pass) mAlphaDFactor = LLRender::BF_ZERO; // block (zero-out) glow where the alpha test succeeds gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); if (mVertexShaderLevel > 0) { - if (!LLPipeline::sRenderDeferred) + if (!LLPipeline::sRenderDeferred || !deferred_render) { simple_shader->bind(); - pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + simple_shader->setAlphaRange(0.33f, 1.f); + + pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } if (fullbright_shader) { fullbright_shader->bind(); + fullbright_shader->setAlphaRange(0.33f, 1.f); } - pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); - LLGLSLShader::bindNoShader(); + pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + //LLGLSLShader::bindNoShader(); } else { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.33f); //OK gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); pushBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask()); gPipeline.enableLightsDynamic(); pushBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask()); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } - LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy ? GL_TRUE : GL_FALSE); + LLGLDepthTest depth(GL_TRUE, LLDrawPoolWater::sSkipScreenCopy || + (deferred_render && pass == 1) ? GL_TRUE : GL_FALSE); - mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend - mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } - mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression - mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } - gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); + if (deferred_render && pass == 1) + { + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + } + else + { + mColorSFactor = LLRender::BF_SOURCE_ALPHA; // } regular alpha blend + mColorDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + mAlphaSFactor = LLRender::BF_ZERO; // } glow suppression + mAlphaDFactor = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; // } + gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - renderAlpha(getVertexDataMask()); + if (mVertexShaderLevel > 0) + { + if (LLPipeline::sImpostorRender) + { + fullbright_shader->bind(); + fullbright_shader->setAlphaRange(0.5f, 1.f); + simple_shader->bind(); + simple_shader->setAlphaRange(0.5f, 1.f); + } + else + { + fullbright_shader->bind(); + fullbright_shader->setAlphaRange(0.f, 1.f); + simple_shader->bind(); + simple_shader->setAlphaRange(0.f, 1.f); + } + } + else + { + if (LLPipeline::sImpostorRender) + { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK + } + else + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK + } + } + } + + if (mVertexShaderLevel > 0) + { + renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX); + } + else + { + renderAlpha(getVertexDataMask()); + } gGL.setColorMask(true, false); - if (deferred_render && current_shader != NULL) + if (deferred_render && pass == 1) { - gPipeline.unbindDeferredShader(*current_shader); + gGL.setSceneBlendType(LLRender::BT_ALPHA); } if (sShowDebugAlpha) { - if(gPipeline.canUseWindLightShaders()) + BOOL shaders = gPipeline.canUseVertexShaders(); + if(shaders) { - LLGLSLShader::bindNoShader(); + gObjectFullbrightNonIndexedProgram.bind(); + } + else + { + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); } - gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); glColor4f(1,0,0,1); LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f); gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sSmokeImagep, TRUE) ; renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + if(shaders) + { + gObjectFullbrightNonIndexedProgram.unbind(); + } } } @@ -283,24 +379,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { BOOL initialized_lighting = FALSE; BOOL light_enabled = TRUE; - S32 diffuse_channel = 0; - - //BOOL is_particle = FALSE; - BOOL use_shaders = (LLPipeline::sUnderWaterRender && gPipeline.canUseVertexShaders()) - || gPipeline.canUseWindLightShadersOnObjects(); - // check to see if it's a particle and if it's "close" - { - if (LLPipeline::sImpostorRender) - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - } - } - + BOOL use_shaders = gPipeline.canUseVertexShaders(); + for (LLCullResult::sg_list_t::iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; @@ -324,7 +405,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) LLRenderPass::applyModelMatrix(params); - { if (params.mFullbright) { // Turn off lighting if it hasn't already been so. @@ -358,58 +438,55 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } // If we need shaders, and we're not ALREADY using the proper shader, then bind it - // (this way we won't rebind shaders unnecessarily). - if(use_shaders && (current_shader != target_shader)) - { - llassert(target_shader != NULL); - if (deferred_render && current_shader != NULL) - { - gPipeline.unbindDeferredShader(*current_shader); - diffuse_channel = 0; - } - current_shader = target_shader; - if (deferred_render) - { - gPipeline.bindDeferredShader(*current_shader); - diffuse_channel = current_shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); - } - else - { - current_shader->bind(); - } - } - else if (!use_shaders && current_shader != NULL) - { - if (deferred_render) - { - gPipeline.unbindDeferredShader(*current_shader); - diffuse_channel = 0; - } - LLGLSLShader::bindNoShader(); - current_shader = NULL; - } + // (this way we won't rebind shaders unnecessarily). + if(use_shaders && (current_shader != target_shader)) + { + llassert(target_shader != NULL); + current_shader = target_shader; + current_shader->bind(); + } + else if (!use_shaders && current_shader != NULL) + { + LLGLSLShader::bindNoShader(); + current_shader = NULL; + } if (params.mGroup) { params.mGroup->rebuildMesh(); } - + bool tex_setup = false; + + if (use_shaders && params.mTextureList.size() > 1) + { + for (U32 i = 0; i < params.mTextureList.size(); ++i) + { + if (params.mTextureList[i].notNull()) + { + gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + } + } + } + else + { //not batching textures or batch has only 1 texture -- might need a texture matrix if (params.mTexture.notNull()) { - gGL.getTexUnit(diffuse_channel)->bind(params.mTexture.get()); - if(params.mTexture.notNull()) - { - params.mTexture->addTextureStats(params.mVSize); - } + params.mTexture->addTextureStats(params.mVSize); + gGL.getTexUnit(0)->bind(params.mTexture, TRUE) ; if (params.mTextureMatrix) { + tex_setup = true; gGL.getTexUnit(0)->activate(); glMatrixMode(GL_TEXTURE); glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); gPipeline.mTextureMatrixOps++; } } + else + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + } } params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); @@ -435,7 +512,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); } - if (params.mTextureMatrix && params.mTexture.notNull()) + if (tex_setup) { gGL.getTexUnit(0)->activate(); glLoadIdentity(); @@ -445,15 +522,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) } } - if (deferred_render && current_shader != NULL) - { - gPipeline.unbindDeferredShader(*current_shader); - LLVertexBuffer::unbind(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - } - + LLVertexBuffer::unbind(); + if (!light_enabled) { gPipeline.enableLightsDynamic(); diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 92d257734..a43169547 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -37,16 +37,23 @@ #include "llvoavatar.h" #include "m3math.h" +#include "llmatrix4a.h" -#include "llagent.h" +#include "llagent.h" //for gAgent.needsRenderAvatar() #include "lldrawable.h" +#include "lldrawpoolbump.h" #include "llface.h" +#if MESH_ENABLED +#include "llmeshrepository.h" +#endif //MESH_ENABLED #include "llsky.h" #include "llviewercamera.h" #include "llviewerregion.h" #include "noise.h" #include "pipeline.h" #include "llviewershadermgr.h" +#include "llvovolume.h" +#include "llvolume.h" #include "llappviewer.h" #include "llrendersphere.h" #include "llviewerpartsim.h" @@ -54,10 +61,16 @@ static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; static U32 sBufferUsage = GL_STREAM_DRAW_ARB; static U32 sShaderLevel = 0; -static LLGLSLShader* sVertexProgram = NULL; +LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL; BOOL LLDrawPoolAvatar::sSkipOpaque = FALSE; BOOL LLDrawPoolAvatar::sSkipTransparent = FALSE; +S32 LLDrawPoolAvatar::sDiffuseChannel = 0; + +#if MESH_ENABLED +static bool is_deferred_render = false; +static bool is_skipped_pass = false; +#endif //MESH_ENABLED extern BOOL gUseGLPick; @@ -94,7 +107,7 @@ BOOL gAvatarEmbossBumpMap = FALSE; static BOOL sRenderingSkinned = FALSE; S32 normal_channel = -1; S32 specular_channel = -1; -S32 diffuse_channel = -1; +S32 cube_channel = -1; LLDrawPoolAvatar::LLDrawPoolAvatar() : LLFacePool(POOL_AVATAR) @@ -150,20 +163,21 @@ LLMatrix4& LLDrawPoolAvatar::getModelView() //----------------------------------------------------------------------------- // render() //----------------------------------------------------------------------------- - - -S32 LLDrawPoolAvatar::getNumDeferredPasses() -{ - return getNumPasses(); -} - void LLDrawPoolAvatar::beginDeferredPass(S32 pass) { sSkipTransparent = TRUE; +#if MESH_ENABLED + is_deferred_render = true; +#endif //MESH_ENABLED if (LLPipeline::sImpostorRender) + { //impostor pass does not have rigid or impostor rendering + pass += 2; + } + + if(pass >= 3 && mRiggedFace[pass + 4].empty()) { - beginDeferredSkinned(); + is_skipped_pass = true; return; } @@ -178,16 +192,33 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass) case 2: beginDeferredSkinned(); break; +#if MESH_ENABLED + case 3: + beginDeferredRiggedSimple(); + break; + case 4: + beginDeferredRiggedBump(); + break; +#endif //MESH_ENABLED } } void LLDrawPoolAvatar::endDeferredPass(S32 pass) { + sSkipTransparent = FALSE; +#if MESH_ENABLED + is_deferred_render = false; +#endif //MESH_ENABLED if (LLPipeline::sImpostorRender) { - endDeferredSkinned(); + pass += 2; + } + + if(is_skipped_pass) + { + is_skipped_pass = false; return; } @@ -202,6 +233,14 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass) case 2: endDeferredSkinned(); break; +#if MESH_ENABLED + case 3: + endDeferredRiggedSimple(); + break; + case 4: + endDeferredRiggedBump(); + break; +#endif //MESH_ENABLED } } @@ -212,10 +251,47 @@ void LLDrawPoolAvatar::renderDeferred(S32 pass) S32 LLDrawPoolAvatar::getNumPostDeferredPasses() { +#if MESH_ENABLED + return 6; +#endif //MESH_ENABLED +#if !MESH_ENABLED return 1; +#endif //!MESH_ENABLED } void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) +{ + if(pass >= 1 && mRiggedFace[pass + (S32)(pass != 1)].empty()) + { + is_skipped_pass = true; + return; + } + + switch (pass) + { + case 0: + beginPostDeferredAlpha(); + break; +#if MESH_ENABLED + case 1: + beginRiggedFullbright(); + break; + case 2: + beginRiggedFullbrightShiny(); + break; + case 3: + beginDeferredRiggedAlpha(); + break; + case 4: + beginRiggedFullbrightAlpha(); + break; + case 5: + beginRiggedGlow(); + break; +#endif //MESH_ENABLED + } +} +void LLDrawPoolAvatar::beginPostDeferredAlpha() { sSkipOpaque = TRUE; sShaderLevel = mVertexShaderLevel; @@ -225,10 +301,63 @@ void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass) gPipeline.bindDeferredShader(*sVertexProgram); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); } +#if MESH_ENABLED +void LLDrawPoolAvatar::beginDeferredRiggedAlpha() +{ + sVertexProgram = &gDeferredSkinnedAlphaProgram; + gPipeline.bindDeferredShader(*sVertexProgram); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + gPipeline.enableLightsDynamic(); +} + +void LLDrawPoolAvatar::endDeferredRiggedAlpha() +{ + LLVertexBuffer::unbind(); + gPipeline.unbindDeferredShader(*sVertexProgram); + sDiffuseChannel = 0; + LLVertexBuffer::sWeight4Loc = -1; + sVertexProgram = NULL; +} +#endif //MESH_ENABLED void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) +{ + if(is_skipped_pass) + { + is_skipped_pass = false; + return; + } + + switch (pass) + { + case 0: + endPostDeferredAlpha(); + break; +#if MESH_ENABLED + case 1: + endRiggedFullbright(); + break; + case 2: + endRiggedFullbrightShiny(); + break; + case 3: + endDeferredRiggedAlpha(); + break; + case 4: + endRiggedFullbrightAlpha(); + break; + case 5: + endRiggedGlow(); + break; +#endif //MESH_ENABLED + } +} + +void LLDrawPoolAvatar::endPostDeferredAlpha() { // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done sRenderingSkinned = FALSE; @@ -236,55 +365,106 @@ void LLDrawPoolAvatar::endPostDeferredPass(S32 pass) disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); gPipeline.unbindDeferredShader(*sVertexProgram); - + sDiffuseChannel = 0; sShaderLevel = mVertexShaderLevel; } void LLDrawPoolAvatar::renderPostDeferred(S32 pass) { - render(2); //pass 2 = skinned +#if MESH_ENABLED + const S32 actual_pass[] = + { //map post deferred pass numbers to what render() expects + 2, //skinned + 4, // rigged fullbright + 6, //rigged fullbright shiny + 7, //rigged alpha + 8, //rigged fullbright alpha + 9, //rigged glow + }; + + pass = actual_pass[pass]; +#endif //MESH_ENABLED +#if !MESH_ENABLED + if(pass > 0) return; + pass = 2; +#endif //!MESH_ENABLED + + if (LLPipeline::sImpostorRender) + { //HACK for impostors so actual pass ends up being proper pass + pass -= 2; + } + + render(pass); + } S32 LLDrawPoolAvatar::getNumShadowPasses() { +#if MESH_ENABLED + return 2; +#endif //MESH_ENABLED +#if !MESH_ENABLED return 1; +#endif //!MESH_ENABLED } void LLDrawPoolAvatar::beginShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); - - sVertexProgram = &gDeferredAvatarShadowProgram; - if (sShaderLevel > 0) + if (pass == 0) { - gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; - } - gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f); - - glColor4f(1,1,1,1); + sVertexProgram = &gDeferredAvatarShadowProgram; + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } + //gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f); + + glColor4f(1,1,1,1); - if ((sShaderLevel > 0)) // for hardware blending + if ((sShaderLevel > 0)) // for hardware blending + { + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + } + } +#if MESH_ENABLED + else { - sRenderingSkinned = TRUE; + sVertexProgram = &gDeferredAttachmentShadowProgram; + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); - enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); } - +#endif //MESH_ENABLED } void LLDrawPoolAvatar::endShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_AVATAR); - if (sShaderLevel > 0) + if (pass == 0) { - sRenderingSkinned = FALSE; - sVertexProgram->unbind(); - disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + if (sShaderLevel > 0) + { + sRenderingSkinned = FALSE; + sVertexProgram->unbind(); + disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + } } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); +#if MESH_ENABLED + else + { + LLVertexBuffer::unbind(); + sVertexProgram->unbind(); + LLVertexBuffer::sWeight4Loc = -1; + sVertexProgram = NULL; + } +#endif //MESH_ENABLED + } void LLDrawPoolAvatar::renderShadow(S32 pass) @@ -318,25 +498,58 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) return; } - if (sShaderLevel > 0) + if (pass == 0) { - gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; - } - avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); + if (sShaderLevel > 0) + { + gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; + } + avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); + } +#if MESH_ENABLED + else + { + renderRigged(avatarp, RIGGED_SIMPLE); + renderRigged(avatarp, RIGGED_ALPHA); + renderRigged(avatarp, RIGGED_FULLBRIGHT); + renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY); + renderRigged(avatarp, RIGGED_SHINY); + renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA); + } +#endif //MESH_ENABLED } S32 LLDrawPoolAvatar::getNumPasses() { +#if MESH_ENABLED + return LLPipeline::sImpostorRender ? 8 : 10; +#endif //MESH_ENABLED +#if !MESH_ENABLED return LLPipeline::sImpostorRender ? 1 : 3; +#endif //!MESH_ENABLED +} + +S32 LLDrawPoolAvatar::getNumDeferredPasses() +{ +#if MESH_ENABLED + return LLPipeline::sImpostorRender ? 3 : 5; +#endif //MESH_ENABLED +#if !MESH_ENABLED + return getNumPasses(); +#endif //!MESH_ENABLED + } void LLDrawPoolAvatar::render(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); + if(is_skipped_pass) + return; + if (LLPipeline::sImpostorRender) { - renderAvatars(NULL, 2); + renderAvatars(NULL, pass+2); return; } @@ -349,9 +562,19 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) //reset vertex buffer mappings LLVertexBuffer::unbind(); + if (pass == 0) + { //make sure no stale colors are left over from a previous render + glColor4f(1,1,1,1); + } + if (LLPipeline::sImpostorRender) + { //impostor render does not have impostors or rigid rendering + pass += 2; + } + + if(pass >= 3 && mRiggedFace[pass - 3].empty()) { - beginSkinned(); + is_skipped_pass = true; return; } @@ -366,6 +589,29 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass) case 2: beginSkinned(); break; +#if MESH_ENABLED + case 3: + beginRiggedSimple(); + break; + case 4: + beginRiggedFullbright(); + break; + case 5: + beginRiggedShinySimple(); + break; + case 6: + beginRiggedFullbrightShiny(); + break; + case 7: + beginRiggedAlpha(); + break; + case 8: + beginRiggedFullbrightAlpha(); + break; + case 9: + beginRiggedGlow(); + break; +#endif //MESH_ENABLED } } @@ -375,7 +621,12 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) if (LLPipeline::sImpostorRender) { - endSkinned(); + pass += 2; + } + + if(is_skipped_pass) + { + is_skipped_pass = false; return; } @@ -389,6 +640,30 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass) break; case 2: endSkinned(); +#if MESH_ENABLED + break; + case 3: + endRiggedSimple(); + break; + case 4: + endRiggedFullbright(); + break; + case 5: + endRiggedShinySimple(); + break; + case 6: + endRiggedFullbrightShiny(); + break; + case 7: + endRiggedAlpha(); + break; + case 8: + endRiggedFullbrightAlpha(); + break; + case 9: + endRiggedGlow(); + break; +#endif //MESH_ENABLED } } @@ -400,12 +675,22 @@ void LLDrawPoolAvatar::beginImpostor() LLVOAvatar::sNumVisibleAvatars = 0; } + if (LLGLSLShader::sNoFixedFunction) + { + gImpostorProgram.bind(); + gImpostorProgram.setAlphaRange(0.01f, 1.f); + } + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); - diffuse_channel = 0; + sDiffuseChannel = 0; } void LLDrawPoolAvatar::endImpostor() { + if (LLGLSLShader::sNoFixedFunction) + { + gImpostorProgram.unbind(); + } gPipeline.enableLightsDynamic(); } @@ -415,16 +700,17 @@ void LLDrawPoolAvatar::beginRigid() { if (LLPipeline::sUnderWaterRender) { - sVertexProgram = &gObjectSimpleWaterProgram; + sVertexProgram = &gObjectAlphaMaskNonIndexedWaterProgram; } else { - sVertexProgram = &gObjectSimpleProgram; + sVertexProgram = &gObjectAlphaMaskNonIndexedProgram; } if (sVertexProgram != NULL) { //eyeballs render with the specular shader sVertexProgram->bind(); + sVertexProgram->setAlphaRange(0.2f, 1.f); } } else @@ -452,11 +738,12 @@ void LLDrawPoolAvatar::beginDeferredImpostor() sVertexProgram = &gDeferredImpostorProgram; - normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP); - diffuse_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); sVertexProgram->bind(); + sVertexProgram->setAlphaRange(0.01f, 1.f); } void LLDrawPoolAvatar::endDeferredImpostor() @@ -471,7 +758,7 @@ void LLDrawPoolAvatar::endDeferredImpostor() void LLDrawPoolAvatar::beginDeferredRigid() { - sVertexProgram = &gDeferredDiffuseProgram; + sVertexProgram = &gDeferredNonIndexedDiffuseProgram; sVertexProgram->bind(); } @@ -502,11 +789,11 @@ void LLDrawPoolAvatar::beginSkinned() { if (LLPipeline::sUnderWaterRender) { - sVertexProgram = &gObjectSimpleWaterProgram; + sVertexProgram = &gObjectAlphaMaskNonIndexedWaterProgram; } else { - sVertexProgram = &gObjectSimpleProgram; + sVertexProgram = &gObjectAlphaMaskNonIndexedProgram; } } @@ -538,6 +825,11 @@ void LLDrawPoolAvatar::beginSkinned() sVertexProgram->bind(); } } + + if (LLGLSLShader::sNoFixedFunction) + { + sVertexProgram->setAlphaRange(0.2f, 1.f); + } } void LLDrawPoolAvatar::endSkinned() @@ -574,6 +866,255 @@ void LLDrawPoolAvatar::endSkinned() gGL.getTexUnit(0)->activate(); } +#if MESH_ENABLED +void LLDrawPoolAvatar::beginRiggedSimple() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectSimpleWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectSimpleProgram; + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectSimpleNonIndexedWaterProgram; + } + else + { + sVertexProgram = &gObjectSimpleNonIndexedProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sDiffuseChannel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + } +} + +void LLDrawPoolAvatar::endRiggedSimple() +{ + LLVertexBuffer::unbind(); + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; + } +} + +void LLDrawPoolAvatar::beginRiggedAlpha() +{ + beginRiggedSimple(); +} + +void LLDrawPoolAvatar::endRiggedAlpha() +{ + endRiggedSimple(); +} + + +void LLDrawPoolAvatar::beginRiggedFullbrightAlpha() +{ + beginRiggedFullbright(); +} + +void LLDrawPoolAvatar::endRiggedFullbrightAlpha() +{ + endRiggedFullbright(); +} + +void LLDrawPoolAvatar::beginRiggedGlow() +{ + beginRiggedFullbright(); +} + +void LLDrawPoolAvatar::endRiggedGlow() +{ + endRiggedFullbright(); +} + +void LLDrawPoolAvatar::beginRiggedFullbright() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightProgram; + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectFullbrightNonIndexedWaterProgram; + } + else + { + sVertexProgram = &gObjectFullbrightNonIndexedProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sDiffuseChannel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + } +} + +void LLDrawPoolAvatar::endRiggedFullbright() +{ + LLVertexBuffer::unbind(); + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; + } +} + +void LLDrawPoolAvatar::beginRiggedShinySimple() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectShinySimpleWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectShinySimpleProgram; + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectShinyNonIndexedWaterProgram; + } + else + { + sVertexProgram = &gObjectShinyNonIndexedProgram; + } + } + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->bind(); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + } +} + +void LLDrawPoolAvatar::endRiggedShinySimple() +{ + LLVertexBuffer::unbind(); + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; + } +} + +void LLDrawPoolAvatar::beginRiggedFullbrightShiny() +{ + if (sShaderLevel > 0) + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gSkinnedObjectFullbrightShinyWaterProgram; + } + else + { + sVertexProgram = &gSkinnedObjectFullbrightShinyProgram; + } + } + else + { + if (LLPipeline::sUnderWaterRender) + { + sVertexProgram = &gObjectFullbrightShinyNonIndexedWaterProgram; + } + else + { + sVertexProgram = &gObjectFullbrightShinyNonIndexedProgram; + } + } + + + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + sVertexProgram->bind(); + LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); + } +} + +void LLDrawPoolAvatar::endRiggedFullbrightShiny() +{ + LLVertexBuffer::unbind(); + if (sShaderLevel > 0 || gPipeline.canUseVertexShaders()) + { + LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false); + sVertexProgram->unbind(); + sVertexProgram = NULL; + LLVertexBuffer::sWeight4Loc = -1; + } +} + + +void LLDrawPoolAvatar::beginDeferredRiggedSimple() +{ + sVertexProgram = &gDeferredSkinnedDiffuseProgram; + sDiffuseChannel = 0; + sVertexProgram->bind(); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endDeferredRiggedSimple() +{ + LLVertexBuffer::unbind(); + sVertexProgram->unbind(); + LLVertexBuffer::sWeight4Loc = -1; + sVertexProgram = NULL; +} + +void LLDrawPoolAvatar::beginDeferredRiggedBump() +{ + sVertexProgram = &gDeferredSkinnedBumpProgram; + sVertexProgram->bind(); + normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + LLVertexBuffer::sWeight4Loc = sVertexProgram->getAttribLocation(LLViewerShaderMgr::OBJECT_WEIGHT); +} + +void LLDrawPoolAvatar::endDeferredRiggedBump() +{ + LLVertexBuffer::unbind(); + sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sVertexProgram->unbind(); + LLVertexBuffer::sWeight4Loc = -1; + normal_channel = -1; + sDiffuseChannel = 0; + sVertexProgram = NULL; +} +#endif //MESH_ENABLED void LLDrawPoolAvatar::beginDeferredSkinned() { sShaderLevel = mVertexShaderLevel; @@ -583,6 +1124,7 @@ void LLDrawPoolAvatar::beginDeferredSkinned() sVertexProgram->bind(); + sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); gGL.getTexUnit(0)->activate(); @@ -595,6 +1137,8 @@ void LLDrawPoolAvatar::endDeferredSkinned() disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); sVertexProgram->unbind(); + sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); + sShaderLevel = mVertexShaderLevel; gGL.getTexUnit(0)->activate(); @@ -651,10 +1195,10 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (!single_avatar && !avatarp->isFullyLoaded() ) { - if (pass==1 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0)) + if (pass==0 && (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES) || LLViewerPartSim::getMaxPartCount() <= 0)) { // debug code to draw a sphere in place of avatar - gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep.get()); + gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep); gGL.setColorMask(true, true); LLVector3 pos = avatarp->getPositionAgent(); gGL.color4f(1.0f, 1.0f, 1.0f, 0.7f); @@ -697,7 +1241,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if (impostor) { - if (LLPipeline::sRenderDeferred && avatarp->mImpostor.isComplete()) + if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete()) { if (normal_channel > -1) { @@ -708,7 +1252,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) avatarp->mImpostor.bindTexture(1, specular_channel); } } - avatarp->renderImpostor(LLColor4U(255,255,255,255), diffuse_channel); + avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel); } else if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS) && !LLPipeline::sRenderDeferred) { @@ -729,6 +1273,90 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) return; } +#if MESH_ENABLED + if (pass == 3) + { + if (is_deferred_render) + { + renderDeferredRiggedSimple(avatarp); + } + else + { + renderRiggedSimple(avatarp); + } + return; + } + + if (pass == 4) + { + if (is_deferred_render) + { + renderDeferredRiggedBump(avatarp); + } + else + { + renderRiggedFullbright(avatarp); + } + + return; + } + + if (pass == 5) + { + renderRiggedShinySimple(avatarp); + return; + } + + if (pass == 6) + { + renderRiggedFullbrightShiny(avatarp); + return; + } + + if (pass >= 7 && pass < 9) + { + LLGLEnable blend(GL_BLEND); + + gGL.setColorMask(true, true); + gGL.blendFunc(LLRender::BF_SOURCE_ALPHA, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA, + LLRender::BF_ZERO, + LLRender::BF_ONE_MINUS_SOURCE_ALPHA); + + + if (pass == 7) + { + renderRiggedAlpha(avatarp); + return; + } + + if (pass == 8) + { + renderRiggedFullbrightAlpha(avatarp); + return; + } + } + + if (pass == 9) + { + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.flush(); + + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.setColorMask(false, true); + + renderRiggedGlow(avatarp); + gGL.setColorMask(true, false); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + return; + } +#endif //MESH_ENABLED + if (sShaderLevel > 0) { gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; @@ -765,83 +1393,322 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) } } -//----------------------------------------------------------------------------- -// renderForSelect() -//----------------------------------------------------------------------------- -void LLDrawPoolAvatar::renderForSelect() +#if MESH_ENABLED +void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, LLFace* face, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face) { - if (!gRenderAvatar) + LLVector4a* weight = vol_face.mWeights; + if (!weight) { return; } - if (mDrawFace.empty()) - { - return; - } + LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer(); + LLDrawable* drawable = face->getDrawable(); - const LLFace *facep = mDrawFace[0]; - if (!facep->getDrawable()) - { - return; - } - LLVOAvatar *avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get(); - - if (avatarp->isDead() || avatarp->mIsDummy || avatarp->mDrawable.isNull()) - { - return; - } - - S32 curr_shader_level = getVertexShaderLevel(); - S32 name = avatarp->mDrawable->getVObj()->mGLName; - LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name); - - BOOL impostor = avatarp->isImpostor(); - if (impostor) - { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); - - avatarp->renderImpostor(color); - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - return; - } - - sVertexProgram = &gAvatarPickProgram; - if (curr_shader_level > 0) - { - gAvatarMatrixParam = sVertexProgram->mUniform[LLViewerShaderMgr::AVATAR_MATRIX]; - } - gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.2f); - gGL.setSceneBlendType(LLRender::BT_REPLACE); - - glColor4ubv(color.mV); - - if (curr_shader_level > 0) // for hardware blending - { - sRenderingSkinned = TRUE; - sVertexProgram->bind(); - enable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); - } + U32 data_mask = face->getRiggedVertexBufferDataMask(); - avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); - - // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done - if (curr_shader_level > 0) + if (buffer.isNull() || + buffer->getTypeMask() != data_mask || + buffer->getRequestedVerts() != vol_face.mNumVertices || + buffer->getRequestedIndices() != vol_face.mNumIndices || + (drawable && drawable->isState(LLDrawable::REBUILD_ALL))) { - sRenderingSkinned = FALSE; - sVertexProgram->unbind(); - disable_vertex_weighting(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT]); + face->setGeomIndex(0); + face->setIndicesIndex(0); + + if (buffer.isNull() || buffer->getTypeMask() != data_mask) + { //make a new buffer + if (sShaderLevel > 0) + { + buffer = new LLVertexBuffer(data_mask, GL_DYNAMIC_DRAW_ARB); + } + else + { + buffer = new LLVertexBuffer(data_mask, GL_STREAM_DRAW_ARB); + } + buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true); + } + else //resize existing buffer + { + buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices); + } + + face->setSize(vol_face.mNumVertices, vol_face.mNumIndices); + + face->setVertexBuffer(buffer); + + U16 offset = 0; + + LLMatrix4 mat_vert = skin->mBindShapeMatrix; + glh::matrix4f m((F32*) mat_vert.mMatrix); + m = m.inverse().transpose(); + + F32 mat3[] = + { m.m[0], m.m[1], m.m[2], + m.m[4], m.m[5], m.m[6], + m.m[8], m.m[9], m.m[10] }; + + LLMatrix3 mat_normal(mat3); + + face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true); } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + if (sShaderLevel <= 0 && face->mLastSkinTime < avatar->getLastSkinTime()) + { //perform software vertex skinning for this face + LLStrider<LLVector3> position; + LLStrider<LLVector3> normal; - // restore texture mode - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + bool has_normal = buffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + buffer->getVertexStrider(position); + + if (has_normal) + { + buffer->getNormalStrider(normal); + } + + //LLVector4a* pos = (LLVector4a*) position.get(); + + //LLVector4a* norm = has_normal ? (LLVector4a*) normal.get() : NULL; + + //build matrix palette + LLMatrix4a mp[64]; + LLMatrix4* mat = (LLMatrix4*) mp; + + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); + if (joint) + { + mat[j] = skin->mInvBindMatrix[j]; + mat[j] *= joint->getWorldMatrix(); + } + } + + LLMatrix4a bind_shape_matrix; + bind_shape_matrix.loadu(skin->mBindShapeMatrix); + + for (U32 j = 0; j < (U32)buffer->getRequestedVerts(); ++j) + { + LLMatrix4a final_mat; + final_mat.clear(); + + S32 idx[4]; + + LLVector4 wght; + + F32 scale = 0.f; + for (U32 k = 0; k < 4; k++) + { + F32 w = weight[j][k]; + + idx[k] = llclamp((S32) floorf(w), 0, 63); + wght[k] = w - floorf(w); + scale += wght[k]; + } + + wght *= 1.f/scale; + + for (U32 k = 0; k < 4; k++) + { + F32 w = wght[k]; + + LLMatrix4a src; + src.setMul(mp[idx[k]], w); + + final_mat.add(src); + } + + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + position[j].set(dst.getF32ptr()); + + if (has_normal && normal.get()) + { + LLVector4a& n = vol_face.mNormals[j]; + bind_shape_matrix.rotate(n, t); + final_mat.rotate(t, dst); + normal[j].set(dst.getF32ptr()); + } + } + } + + if (drawable && (face->getTEOffset() == drawable->getNumFaces()-1)) + { + drawable->clearState(LLDrawable::REBUILD_ALL); + } } +void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow) +{ + if (avatar->isSelf() && !gAgent.needsRenderAvatar() || !gMeshRepo.meshRezEnabled()) + { + return; + } + + stop_glerror(); + + for (U32 i = 0; i < mRiggedFace[type].size(); ++i) + { + LLFace* face = mRiggedFace[type][i]; + LLDrawable* drawable = face->getDrawable(); + if (!drawable) + { + continue; + } + + LLVOVolume* vobj = drawable->getVOVolume(); + + if (!vobj) + { + continue; + } + + LLVolume* volume = vobj->getVolume(); + S32 te = face->getTEOffset(); + + if (!volume || volume->getNumVolumeFaces() <= te || !volume->isMeshAssetLoaded()) + { + continue; + } + + LLUUID mesh_id = volume->getParams().getSculptID(); + if (mesh_id.isNull()) + { + continue; + } + + const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(mesh_id, vobj); + if (!skin) + { + continue; + } + + stop_glerror(); + + const LLVolumeFace& vol_face = volume->getVolumeFace(te); + updateRiggedFaceVertexBuffer(avatar, face, skin, volume, vol_face); + + stop_glerror(); + + U32 data_mask = LLFace::getRiggedDataMask(type); + + LLVertexBuffer* buff = face->getVertexBuffer(); + + if (buff) + { + if (sShaderLevel > 0) + { //upload matrix palette to shader + LLMatrix4 mat[64]; + + for (U32 i = 0; i < skin->mJointNames.size(); ++i) + { + LLJoint* joint = avatar->getJoint(skin->mJointNames[i]); + if (joint) + { + mat[i] = skin->mInvBindMatrix[i]; + mat[i] *= joint->getWorldMatrix(); + } + } + + stop_glerror(); + + LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette", + skin->mJointNames.size(), + FALSE, + (GLfloat*) mat[0].mMatrix); + + stop_glerror(); + } + else + { + data_mask &= ~LLVertexBuffer::MAP_WEIGHT4; + } + + buff->setBuffer(data_mask); + + U16 start = face->getGeomStart(); + U16 end = start + face->getGeomCount()-1; + S32 offset = face->getIndicesStart(); + U32 count = face->getIndicesCount(); + + if (glow) + { + glColor4f(0,0,0,face->getTextureEntry()->getGlow()); + } + + gGL.getTexUnit(sDiffuseChannel)->bind(face->getTexture()); + if (normal_channel > -1) + { + LLDrawPoolBump::bindBumpMap(face, normal_channel); + } + + if (face->mTextureMatrix) + { + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((F32*) face->mTextureMatrix->mMatrix); + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + } + else + { + buff->drawRange(LLRender::TRIANGLES, start, end, count, offset); + } + } + } +} + +void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_DEFERRED_SIMPLE); +} + +void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_DEFERRED_BUMP); +} + +void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_SIMPLE); +} + +void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_FULLBRIGHT); +} + + +void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_SHINY); +} + +void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY); +} + +void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_ALPHA); +} + +void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA); +} + +void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar) +{ + renderRigged(avatar, RIGGED_GLOW, true); +} +#endif //MESH_ENABLED + //----------------------------------------------------------------------------- // getDebugTexture() //----------------------------------------------------------------------------- @@ -868,6 +1735,52 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const return LLColor3(0.f, 1.f, 0.f); } +#if MESH_ENABLED +void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type) +{ + if (type >= NUM_RIGGED_PASSES) + { + llerrs << "Invalid rigged face type." << llendl; + } + + if (facep->getRiggedIndex(type) != -1) + { + llerrs << "Tried to add a rigged face that's referenced elsewhere." << llendl; + } + + facep->setRiggedIndex(type, mRiggedFace[type].size()); + facep->setPool(this); + mRiggedFace[type].push_back(facep); +} + +void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep) +{ + facep->setPool(NULL); + + for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i) + { + S32 index = facep->getRiggedIndex(i); + + if (index > -1) + { + if ((S32)mRiggedFace[i].size() > index && mRiggedFace[i][index] == facep) + { + facep->setRiggedIndex(i,-1); + mRiggedFace[i].erase(mRiggedFace[i].begin()+index); + for (U32 j = index; j < mRiggedFace[i].size(); ++j) + { //bump indexes down for faces referenced after erased face + mRiggedFace[i][j]->setRiggedIndex(i, j); + } + } + else + { + llerrs << "Face reference data corrupt for rigged type " << i << llendl; + } + } + } +} +#endif //MESH_ENABLED + LLVertexBufferAvatar::LLVertexBufferAvatar() : LLVertexBuffer(sDataMask, //LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) > 0 ? @@ -882,22 +1795,22 @@ void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const { if (sRenderingSkinned) { - volatile U8* base = useVBOs() ? NULL : mMappedData; + volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; - glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0)); - glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL])); - glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glVertexPointer(3,GL_FLOAT, getStride(TYPE_VERTEX), (void*)(base + 0)); + glNormalPointer(GL_FLOAT, getStride(TYPE_NORMAL), (void*)(base + mOffsets[TYPE_NORMAL])); + glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD0), (void*)(base + mOffsets[TYPE_TEXCOORD0])); - set_vertex_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT])); + set_vertex_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_WEIGHT], getStride(TYPE_WEIGHT), (F32*)(base + mOffsets[TYPE_WEIGHT])); if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP) { - set_binormals(sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); + set_binormals(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::BINORMAL], getStride(TYPE_BINORMAL), (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); } if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH) { - set_vertex_clothing_weights(sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + set_vertex_clothing_weights(LLDrawPoolAvatar::sVertexProgram->mAttribute[LLViewerShaderMgr::AVATAR_CLOTHING], getStride(TYPE_CLOTHWEIGHT), (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); } } else diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index d24726052..30fcf3794 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -36,6 +36,12 @@ #include "lldrawpool.h" class LLVOAvatar; +class LLGLSLShader; +class LLFace; +class LLMeshSkinInfo; +class LLVolume; +class LLVolumeFace; + class LLDrawPoolAvatar : public LLFacePool { @@ -70,7 +76,6 @@ public: /*virtual*/ void endRenderPass(S32 pass); /*virtual*/ void prerender(); /*virtual*/ void render(S32 pass = 0); - /*virtual*/ void renderForSelect(); /*virtual*/ S32 getNumDeferredPasses(); /*virtual*/ void beginDeferredPass(S32 pass); @@ -102,6 +107,107 @@ public: void endDeferredImpostor(); void endDeferredRigid(); void endDeferredSkinned(); + + void beginPostDeferredAlpha(); + void endPostDeferredAlpha(); + +#if MESH_ENABLED + void beginRiggedSimple(); + void beginRiggedFullbright(); + void beginRiggedFullbrightShiny(); + void beginRiggedShinySimple(); + void beginRiggedAlpha(); + void beginRiggedFullbrightAlpha(); + void beginRiggedGlow(); + void beginDeferredRiggedAlpha(); + + void endRiggedSimple(); + void endRiggedFullbright(); + void endRiggedFullbrightShiny(); + void endRiggedShinySimple(); + void endRiggedAlpha(); + void endRiggedFullbrightAlpha(); + void endRiggedGlow(); + void endDeferredRiggedAlpha(); + + void beginDeferredRiggedSimple(); + void beginDeferredRiggedBump(); + + void endDeferredRiggedSimple(); + void endDeferredRiggedBump(); + + void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar, + LLFace* facep, + const LLMeshSkinInfo* skin, + LLVolume* volume, + const LLVolumeFace& vol_face); + + void renderRigged(LLVOAvatar* avatar, U32 type, bool glow = false); + void renderRiggedSimple(LLVOAvatar* avatar); + void renderRiggedAlpha(LLVOAvatar* avatar); + void renderRiggedFullbrightAlpha(LLVOAvatar* avatar); + void renderRiggedFullbright(LLVOAvatar* avatar); + void renderRiggedShinySimple(LLVOAvatar* avatar); + void renderRiggedFullbrightShiny(LLVOAvatar* avatar); + void renderRiggedGlow(LLVOAvatar* avatar); + void renderDeferredRiggedSimple(LLVOAvatar* avatar); + void renderDeferredRiggedBump(LLVOAvatar* avatar); + + //do NOT screw the the order of these. They are ordered in a way such that they cleanly align with render passes in drawpoolavatar. + typedef enum + { + RIGGED_SIMPLE = 0, + RIGGED_FULLBRIGHT, + RIGGED_SHINY, + RIGGED_FULLBRIGHT_SHINY, + //RIGGED_GLOW, + RIGGED_ALPHA, + RIGGED_FULLBRIGHT_ALPHA, + RIGGED_GLOW, + //RIGGED_DEFERRED_BUMP, + RIGGED_DEFERRED_SIMPLE, + RIGGED_DEFERRED_BUMP, + NUM_RIGGED_PASSES, + RIGGED_UNKNOWN, + } eRiggedPass; + + typedef enum + { + RIGGED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_FULLBRIGHT_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_SHINY_MASK = RIGGED_SIMPLE_MASK, + RIGGED_FULLBRIGHT_SHINY_MASK = RIGGED_SIMPLE_MASK, + RIGGED_GLOW_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_ALPHA_MASK = RIGGED_SIMPLE_MASK, + RIGGED_FULLBRIGHT_ALPHA_MASK = RIGGED_FULLBRIGHT_MASK, + RIGGED_DEFERRED_BUMP_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_BINORMAL | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + RIGGED_DEFERRED_SIMPLE_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD0 | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_WEIGHT4, + } eRiggedDataMask; + + void addRiggedFace(LLFace* facep, U32 type); + void removeRiggedFace(LLFace* facep); + + std::vector<LLFace*> mRiggedFace[NUM_RIGGED_PASSES]; + +#endif //MESH_ENABLED /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display @@ -110,6 +216,9 @@ public: static BOOL sSkipOpaque; static BOOL sSkipTransparent; + static S32 sDiffuseChannel; + + static LLGLSLShader* sVertexProgram; }; class LLVertexBufferAvatar : public LLVertexBuffer diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index 83495217c..20d169853 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -162,6 +162,7 @@ void LLStandardBumpmap::addstandard() LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id)); gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->setLoadedCallback(LLBumpImageList::onSourceStandardLoaded, 0, TRUE, FALSE, NULL, NULL ); + gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage->forceToSaveRawImage(0) ; LLStandardBumpmap::sStandardBumpmapCount++; } @@ -324,6 +325,9 @@ void LLDrawPoolBump::endRenderPass(S32 pass) llassert(0); break; } + + //to cleanup texture channels + LLRenderPass::endRenderPass(pass); } //static @@ -362,6 +366,11 @@ void LLDrawPoolBump::beginShiny(bool invisible) } bindCubeMap(shader, mVertexShaderLevel, diffuse_channel, cube_channel, invisible); + + if (mVertexShaderLevel > 1) + { //indexed texture rendering, channel 0 is always diffuse + diffuse_channel = 0; + } } //static @@ -429,16 +438,16 @@ void LLDrawPoolBump::renderShiny(bool invisible) LLGLEnable blend_enable(GL_BLEND); if (!invisible && mVertexShaderLevel > 1) { - LLRenderPass::renderTexture(LLRenderPass::PASS_SHINY, sVertexMask); + LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } else if (!invisible) { renderGroups(LLRenderPass::PASS_SHINY, sVertexMask); } - else // invisible - { - renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask); - } + //else // invisible (deprecated) + //{ + //renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask); + //} } } @@ -464,11 +473,15 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& } } } - gGL.getTexUnit(diffuse_channel)->disable(); - gGL.getTexUnit(cube_channel)->disable(); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + if (!LLGLSLShader::sNoFixedFunction) + { + gGL.getTexUnit(diffuse_channel)->disable(); + gGL.getTexUnit(cube_channel)->disable(); + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } } void LLDrawPoolBump::endShiny(bool invisible) @@ -537,6 +550,12 @@ void LLDrawPoolBump::beginFullbrightShiny() gGL.getTexUnit(cube_channel)->bind(cube_map); gGL.getTexUnit(0)->activate(); } + + if (mVertexShaderLevel > 1) + { //indexed texture rendering, channel 0 is always diffuse + diffuse_channel = 0; + } + mShiny = TRUE; } @@ -551,7 +570,15 @@ void LLDrawPoolBump::renderFullbrightShiny() if( gSky.mVOSkyp->getCubeMap() ) { LLGLEnable blend_enable(GL_BLEND); - LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask); + + if (mVertexShaderLevel > 1) + { + LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + } + else + { + LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask); + } } } @@ -569,19 +596,19 @@ void LLDrawPoolBump::endFullbrightShiny() cube_map->disable(); cube_map->restoreMatrix(); - if (diffuse_channel != 0) + /*if (diffuse_channel != 0) { shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); } gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);*/ shader->unbind(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); diffuse_channel = -1; cube_channel = 0; @@ -692,36 +719,44 @@ void LLDrawPoolBump::beginBump(U32 pass) // Optional second pass: emboss bump map stop_glerror(); - // TEXTURE UNIT 0 - // Output.rgb = texture at texture coord 0 - gGL.getTexUnit(0)->activate(); + if (LLGLSLShader::sNoFixedFunction) + { + gObjectBumpProgram.bind(); + } + else + { + // TEXTURE UNIT 0 + // Output.rgb = texture at texture coord 0 + gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - // TEXTURE UNIT 1 - gGL.getTexUnit(1)->activate(); + // TEXTURE UNIT 1 + gGL.getTexUnit(1)->activate(); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA); - gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); + gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD_SIGNED, LLTexUnit::TBS_PREV_COLOR, LLTexUnit::TBS_ONE_MINUS_TEX_ALPHA); + gGL.getTexUnit(1)->setTextureAlphaBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_ALPHA); - // src = tex0 + (1 - tex1) - 0.5 - // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5 - // = (1 + bump0 - bump1) / 2 + // src = tex0 + (1 - tex1) - 0.5 + // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5 + // = (1 + bump0 - bump1) / 2 - // Blend: src * dst + dst * src - // = 2 * src * dst - // = 2 * ((1 + bump0 - bump1) / 2) * dst [0 - 2 * dst] - // = (1 + bump0 - bump1) * dst.rgb - // = dst.rgb + dst.rgb * (bump0 - bump1) + // Blend: src * dst + dst * src + // = 2 * src * dst + // = 2 * ((1 + bump0 - bump1) / 2) * dst [0 - 2 * dst] + // = (1 + bump0 - bump1) * dst.rgb + // = dst.rgb + dst.rgb * (bump0 - bump1) + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); + } + gGL.setSceneBlendType(LLRender::BT_MULT_X2); - gGL.getTexUnit(0)->activate(); stop_glerror(); - - gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); } //static @@ -751,14 +786,21 @@ void LLDrawPoolBump::endBump(U32 pass) return; } - // Disable texture unit 1 - gGL.getTexUnit(1)->activate(); - gGL.getTexUnit(1)->disable(); - gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); + if (LLGLSLShader::sNoFixedFunction) + { + gObjectBumpProgram.unbind(); + } + else + { + // Disable texture blending on unit 1 + gGL.getTexUnit(1)->activate(); + //gGL.getTexUnit(1)->disable(); + gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); - // Disable texture unit 0 - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + // Disable texture blending on unit 0 + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } gGL.setSceneBlendType(LLRender::BT_ALPHA); } @@ -845,6 +887,9 @@ void LLDrawPoolBump::endPostDeferredPass(S32 pass) endBump(LLRenderPass::PASS_POST_BUMP); break; } + + //to disable texture channels + LLRenderPass::endRenderPass(pass); } void LLDrawPoolBump::renderPostDeferred(S32 pass) @@ -930,7 +975,6 @@ void LLBumpImageList::addTextureStats(U8 bump, const LLUUID& base_image_id, F32 void LLBumpImageList::updateImages() { - llpushcallstacks ; for (bump_image_map_t::iterator iter = mBrightnessEntries.begin(); iter != mBrightnessEntries.end(); ) { bump_image_map_t::iterator curiter = iter++; @@ -957,7 +1001,7 @@ void LLBumpImageList::updateImages() } } } - llpushcallstacks ; + for (bump_image_map_t::iterator iter = mDarknessEntries.begin(); iter != mDarknessEntries.end(); ) { bump_image_map_t::iterator curiter = iter++; @@ -984,7 +1028,6 @@ void LLBumpImageList::updateImages() } } } - llpushcallstacks ; } @@ -1032,11 +1075,12 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText if (!src_image->hasCallbacks()) { //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again if (src_image->getWidth() != bump->getWidth() || - src_image->getHeight() != bump->getHeight() || - (LLPipeline::sRenderDeferred && bump->getComponents() != 4)) + src_image->getHeight() != bump->getHeight())// || + //(LLPipeline::sRenderDeferred && bump->getComponents() != 4)) { src_image->setBoostLevel(LLViewerTexture::BOOST_BUMP) ; src_image->setLoadedCallback( callback_func, 0, TRUE, FALSE, new LLUUID(src_image->getID()), NULL ); + src_image->forceToSaveRawImage(0) ; } } } @@ -1304,43 +1348,59 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask) } } -void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) +void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { applyModelMatrix(params); - if (params.mTextureMatrix) + bool tex_setup = false; + + if (batch_textures && params.mTextureList.size() > 1) { - if (mShiny) + for (U32 i = 0; i < params.mTextureList.size(); ++i) { - gGL.getTexUnit(0)->activate(); - glMatrixMode(GL_TEXTURE); + if (params.mTextureList[i].notNull()) + { + gGL.getTexUnit(i)->bind(params.mTextureList[i], TRUE); + } } - else + } + else + { //not batching textures or batch has only 1 texture -- might need a texture matrix + if (params.mTextureMatrix) { - gGL.getTexUnit(1)->activate(); - glMatrixMode(GL_TEXTURE); + if (mShiny) + { + gGL.getTexUnit(0)->activate(); + glMatrixMode(GL_TEXTURE); + } + else + { + gGL.getTexUnit(1)->activate(); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + gPipeline.mTextureMatrixOps++; + gGL.getTexUnit(0)->activate(); + } + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); gPipeline.mTextureMatrixOps++; - gGL.getTexUnit(0)->activate(); + + tex_setup = true; } - glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); - gPipeline.mTextureMatrixOps++; - } - - if (mShiny && mVertexShaderLevel > 1 && texture) - { - if (params.mTexture.notNull()) + if (mShiny && mVertexShaderLevel > 1 && texture) { - gGL.getTexUnit(diffuse_channel)->bind(params.mTexture) ; - params.mTexture->addTextureStats(params.mVSize); - } - else - { - gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); + if (params.mTexture.notNull()) + { + gGL.getTexUnit(diffuse_channel)->bind(params.mTexture) ; + params.mTexture->addTextureStats(params.mVSize); + } + else + { + gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE); + } } } - if (params.mGroup) { params.mGroup->rebuildMesh(); @@ -1348,7 +1408,7 @@ void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) params.mVertexBuffer->setBuffer(mask); params.mVertexBuffer->drawRange(LLRender::TRIANGLES, params.mStart, params.mEnd, params.mCount, params.mOffset); gPipeline.addTrianglesDrawn(params.mCount/3); - if (params.mTextureMatrix) + if (tex_setup) { if (mShiny) { @@ -1369,6 +1429,11 @@ void LLDrawPoolInvisible::render(S32 pass) { //render invisiprims LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE); + if (gPipeline.canUseVertexShaders()) + { + gOcclusionProgram.bind(); + } + U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; glStencilMask(0); gGL.setColorMask(false, false); @@ -1376,6 +1441,11 @@ void LLDrawPoolInvisible::render(S32 pass) gGL.setColorMask(true, false); glStencilMask(0xFFFFFFFF); + if (gPipeline.canUseVertexShaders()) + { + gOcclusionProgram.unbind(); + } + if (gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)) { beginShiny(true); diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h index 9c6569665..2611730ee 100644 --- a/indra/newview/lldrawpoolbump.h +++ b/indra/newview/lldrawpoolbump.h @@ -61,7 +61,7 @@ public: virtual void endRenderPass( S32 pass ); virtual S32 getNumPasses(); /*virtual*/ void prerender(); - /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture); + /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE); void renderBump(U32 type, U32 mask); void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture); diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp index 7ca763a18..638563ccb 100644 --- a/indra/newview/lldrawpoolsimple.cpp +++ b/indra/newview/lldrawpoolsimple.cpp @@ -48,6 +48,39 @@ static LLGLSLShader* simple_shader = NULL; static LLGLSLShader* fullbright_shader = NULL; +void LLDrawPoolGlow::beginPostDeferredPass(S32 pass) +{ + gDeferredFullbrightProgram.bind(); +} + +void LLDrawPoolGlow::renderPostDeferred(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_GLOW); + LLGLEnable blend(GL_BLEND); + LLGLDisable test(GL_ALPHA_TEST); + gGL.flush(); + /// Get rid of z-fighting with non-glow pass. + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); + gGL.setSceneBlendType(LLRender::BT_ADD); + + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + gGL.setColorMask(false, true); + + { + //LLFastTimer t(FTM_RENDER_GLOW_PUSH); + pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + } + + gGL.setColorMask(true, false); + gGL.setSceneBlendType(LLRender::BT_ALPHA); +} + +void LLDrawPoolGlow::endPostDeferredPass(S32 pass) +{ + gDeferredFullbrightProgram.unbind(); + LLRenderPass::endRenderPass(pass); +} void LLDrawPoolGlow::render(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_GLOW); @@ -72,7 +105,15 @@ void LLDrawPoolGlow::render(S32 pass) LLGLDepthTest depth(GL_TRUE, GL_FALSE); gGL.setColorMask(false, true); - renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask()); + + if (shader_level > 1) + { + pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); + } + else + { + renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask()); + } gGL.setColorMask(true, false); gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -83,10 +124,10 @@ void LLDrawPoolGlow::render(S32 pass) } } -void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) +void LLDrawPoolGlow::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures) { glColor4ubv(params.mGlowColor.mV); - LLRenderPass::pushBatch(params, mask, texture); + LLRenderPass::pushBatch(params, mask, texture, batch_textures); } @@ -130,10 +171,11 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass) void LLDrawPoolSimple::endRenderPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + stop_glerror(); LLRenderPass::endRenderPass(pass); - - if (mVertexShaderLevel > 0){ - + stop_glerror(); + if (mVertexShaderLevel > 0) + { simple_shader->unbind(); } } @@ -141,17 +183,29 @@ void LLDrawPoolSimple::endRenderPass(S32 pass) void LLDrawPoolSimple::render(S32 pass) { LLGLDisable blend(GL_BLEND); - LLGLDisable alpha_test(GL_ALPHA_TEST); { //render simple LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); gPipeline.enableLightsDynamic(); - renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); - if (LLPipeline::sRenderDeferred) + if (mVertexShaderLevel > 0) { - renderTexture(LLRenderPass::PASS_BUMP, getVertexDataMask()); + U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX; + + pushBatches(LLRenderPass::PASS_SIMPLE, mask, TRUE, TRUE); + + if (LLPipeline::sRenderDeferred) + { //if deferred rendering is enabled, bump faces aren't registered as simple + //render bump faces here as simple so bump faces will appear under water + pushBatches(LLRenderPass::PASS_BUMP, mask, TRUE, TRUE); + } } + else + { + LLGLDisable alpha_test(GL_ALPHA_TEST); + renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); + } + } } @@ -180,7 +234,7 @@ void LLDrawPoolSimple::renderDeferred(S32 pass) { //render simple LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); - renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); + pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE); } } @@ -203,19 +257,21 @@ void LLDrawPoolGrass::beginRenderPass(S32 pass) if (LLPipeline::sUnderWaterRender) { - simple_shader = &gObjectSimpleWaterProgram; + simple_shader = &gObjectAlphaMaskNonIndexedWaterProgram; } else { - simple_shader = &gObjectSimpleProgram; + simple_shader = &gObjectAlphaMaskNonIndexedProgram; } if (mVertexShaderLevel > 0) { simple_shader->bind(); + simple_shader->setAlphaRange(0.5f, 1.f); } else { + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); // don't use shaders! if (gGLManager.mHasShaderObjects) { @@ -233,22 +289,23 @@ void LLDrawPoolGrass::endRenderPass(S32 pass) { simple_shader->unbind(); } + else + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } } void LLDrawPoolGrass::render(S32 pass) { LLGLDisable blend(GL_BLEND); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - + { LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); LLGLEnable test(GL_ALPHA_TEST); gGL.setSceneBlendType(LLRender::BT_ALPHA); //render grass LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); - } - - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } } void LLDrawPoolGrass::beginDeferredPass(S32 pass) @@ -263,17 +320,14 @@ void LLDrawPoolGrass::endDeferredPass(S32 pass) void LLDrawPoolGrass::renderDeferred(S32 pass) { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); - { LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); - gDeferredTreeProgram.bind(); - LLGLEnable test(GL_ALPHA_TEST); + //LLFastTimer t(FTM_RENDER_GRASS_DEFERRED); + gDeferredNonIndexedDiffuseAlphaMaskProgram.bind(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.setAlphaRange(0.5f, 1.f); //render grass LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); } - - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } @@ -288,6 +342,26 @@ void LLDrawPoolFullbright::prerender() mVertexShaderLevel = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT); } +void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass) +{ + gDeferredFullbrightProgram.bind(); +} + +void LLDrawPoolFullbright::renderPostDeferred(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + + gGL.setSceneBlendType(LLRender::BT_ALPHA); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; + pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE); +} + +void LLDrawPoolFullbright::endPostDeferredPass(S32 pass) +{ + gDeferredFullbrightProgram.unbind(); + LLRenderPass::endRenderPass(pass); +} + void LLDrawPoolFullbright::beginRenderPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); @@ -307,34 +381,38 @@ void LLDrawPoolFullbright::endRenderPass(S32 pass) LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); LLRenderPass::endRenderPass(pass); + stop_glerror(); + if (mVertexShaderLevel > 0) { fullbright_shader->unbind(); } + + stop_glerror(); } void LLDrawPoolFullbright::render(S32 pass) { //render fullbright LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + stop_glerror(); + if (mVertexShaderLevel > 0) { fullbright_shader->bind(); fullbright_shader->uniform1f(LLViewerShaderMgr::FULLBRIGHT, 1.f); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX; + pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE); } else { gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR; + renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); } - - //gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.25f); - - //LLGLEnable test(GL_ALPHA_TEST); - //LLGLEnable blend(GL_BLEND); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR; - renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); - //gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + stop_glerror(); } S32 LLDrawPoolFullbright::getNumPasses() diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h index f56151037..54277cad3 100644 --- a/indra/newview/lldrawpoolsimple.h +++ b/indra/newview/lldrawpoolsimple.h @@ -104,9 +104,9 @@ public: LLDrawPoolFullbright(); /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } - /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } - /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } - /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); /*virtual*/ void beginRenderPass(S32 pass); /*virtual*/ void endRenderPass(S32 pass); @@ -132,12 +132,12 @@ public: virtual void prerender() { } /*virtual*/ S32 getNumPostDeferredPasses() { return 1; } - /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } - /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } - /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ void beginPostDeferredPass(S32 pass); + /*virtual*/ void endPostDeferredPass(S32 pass); + /*virtual*/ void renderPostDeferred(S32 pass); void render(S32 pass = 0); - void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE); + void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE); }; diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp index b5cc0d31d..8c8a2266b 100644 --- a/indra/newview/lldrawpoolsky.cpp +++ b/indra/newview/lldrawpoolsky.cpp @@ -70,6 +70,7 @@ void LLDrawPoolSky::prerender() void LLDrawPoolSky::render(S32 pass) { gGL.flush(); + if (mDrawFace.empty()) { return; @@ -87,6 +88,10 @@ void LLDrawPoolSky::render(S32 pass) mShader = &gObjectFullbrightWaterProgram; mShader->bind(); } + else if (LLGLSLShader::sNoFixedFunction) + { //just use the UI shader (generic single texture no lighting) + gUIProgram.bind(); + } else { // don't use shaders! diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 97af1285b..5a221b7a8 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -147,7 +147,7 @@ void LLDrawPoolTerrain::beginRenderPass( S32 pass ) void LLDrawPoolTerrain::endRenderPass( S32 pass ) { LLFastTimer t(LLFastTimer::FTM_RENDER_TERRAIN); - LLFacePool::endRenderPass(pass); + //LLFacePool::endRenderPass(pass); if (mVertexShaderLevel > 1 && sShader->mShaderLevel > 0) { sShader->unbind(); @@ -220,8 +220,10 @@ void LLDrawPoolTerrain::render(S32 pass) { //use fullbright shader for highlighting LLGLSLShader* old_shader = sShader; sShader->unbind(); - sShader = &gObjectFullbrightProgram; + sShader = &gObjectFullbrightNonIndexedProgram; sShader->bind(); + LLGLEnable polyOffset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.0f, -1.0f); renderOwnership(); sShader = old_shader; sShader->bind(); @@ -903,28 +905,6 @@ void LLDrawPoolTerrain::renderOwnership() glMatrixMode(GL_MODELVIEW); } - -void LLDrawPoolTerrain::renderForSelect() -{ - if (mDrawFace.empty()) - { - return; - } - - - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *facep = *iter; - if (!facep->getDrawable()->isDead() && (facep->getDrawable()->getVObj()->mGLName)) - { - facep->renderForSelect(LLVertexBuffer::MAP_VERTEX); - } - } -} - void LLDrawPoolTerrain::dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures) { LLViewerFetchedTexture* tex = LLViewerTextureManager::staticCastToFetchedTexture(mTexturep) ; diff --git a/indra/newview/lldrawpoolterrain.h b/indra/newview/lldrawpoolterrain.h index 61cec0e47..8eb5c5737 100644 --- a/indra/newview/lldrawpoolterrain.h +++ b/indra/newview/lldrawpoolterrain.h @@ -74,7 +74,6 @@ public: /*virtual*/ void prerender(); /*virtual*/ void beginRenderPass( S32 pass ); /*virtual*/ void endRenderPass( S32 pass ); - /*virtual*/ void renderForSelect(); /*virtual*/ void dirtyTextures(const std::set<LLViewerFetchedTexture*>& textures); /*virtual*/ LLViewerTexture *getTexture(); /*virtual*/ LLViewerTexture *getDebugTexture(); diff --git a/indra/newview/lldrawpooltree.cpp b/indra/newview/lldrawpooltree.cpp index 762a087ff..5da531216 100644 --- a/indra/newview/lldrawpooltree.cpp +++ b/indra/newview/lldrawpooltree.cpp @@ -37,7 +37,6 @@ #include "lldrawable.h" #include "llface.h" #include "llsky.h" -#include "llviewerwindow.h" #include "llvotree.h" #include "pipeline.h" #include "llviewercamera.h" @@ -68,24 +67,25 @@ void LLDrawPoolTree::prerender() void LLDrawPoolTree::beginRenderPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - + if (LLPipeline::sUnderWaterRender) { - shader = &gObjectSimpleWaterProgram; + shader = &gObjectAlphaMaskNonIndexedWaterProgram; } else { - shader = &gObjectSimpleProgram; + shader = &gObjectAlphaMaskNonIndexedProgram; } - if (gPipeline.canUseWindLightShadersOnObjects()) + if (gPipeline.canUseVertexShaders()) { shader->bind(); + shader->setAlphaRange(0.5f, 1.f); } else { gPipeline.enableLightsDynamic(); + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } } @@ -98,7 +98,7 @@ void LLDrawPoolTree::render(S32 pass) return; } - LLGLEnable test(GL_ALPHA_TEST); + LLGLState test(GL_ALPHA_TEST, LLGLSLShader::sNoFixedFunction ? 0 : 1); LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); static const LLCachedControl<bool> render_animate_trees("RenderAnimateTrees",false); @@ -128,12 +128,16 @@ void LLDrawPoolTree::render(S32 pass) void LLDrawPoolTree::endRenderPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - + if (gPipeline.canUseWindLightShadersOnObjects()) { shader->unbind(); } + + if (mVertexShaderLevel <= 0) + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } } //============================================ @@ -142,10 +146,10 @@ void LLDrawPoolTree::endRenderPass(S32 pass) void LLDrawPoolTree::beginDeferredPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); - - shader = &gDeferredTreeProgram; + + shader = &gDeferredNonIndexedDiffuseAlphaMaskProgram; shader->bind(); + shader->setAlphaRange(0.5f, 1.f); } void LLDrawPoolTree::renderDeferred(S32 pass) @@ -156,7 +160,6 @@ void LLDrawPoolTree::renderDeferred(S32 pass) void LLDrawPoolTree::endDeferredPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_TREES); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); shader->unbind(); } @@ -167,12 +170,12 @@ void LLDrawPoolTree::endDeferredPass(S32 pass) void LLDrawPoolTree::beginShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + static const LLCachedControl<F32> render_deferred_offset("RenderDeferredTreeShadowOffset",1.f); static const LLCachedControl<F32> render_deferred_bias("RenderDeferredTreeShadowBias",1.f); glPolygonOffset(render_deferred_offset,render_deferred_bias); - - gDeferredShadowProgram.bind(); + gDeferredShadowAlphaMaskProgram.bind(); + gDeferredShadowAlphaMaskProgram.setAlphaRange(0.5f, 1.f); } void LLDrawPoolTree::renderShadow(S32 pass) @@ -183,77 +186,10 @@ void LLDrawPoolTree::renderShadow(S32 pass) void LLDrawPoolTree::endShadowPass(S32 pass) { LLFastTimer t(LLFastTimer::FTM_SHADOW_TREE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - static const LLCachedControl<F32> render_deferred_offset("RenderDeferredTreeShadowOffset",1.f); - static const LLCachedControl<F32> render_deferred_bias("RenderDeferredTreeShadowBias",1.f); + + static const LLCachedControl<F32> render_deferred_offset("RenderDeferredSpotShadowOffset",1.f); + static const LLCachedControl<F32> render_deferred_bias("RenderDeferredSpotShadowBias",1.f); glPolygonOffset(render_deferred_offset,render_deferred_bias); - - //gDeferredShadowProgram.unbind(); -} - - -void LLDrawPoolTree::renderForSelect() -{ - if (mDrawFace.empty()) - { - return; - } - - LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); - - LLGLSObjectSelectAlpha gls_alpha; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - gGL.setSceneBlendType(LLRender::BT_REPLACE); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); - - static const LLCachedControl<bool> render_animate_trees("RenderAnimateTrees",false); - if (render_animate_trees) - { - renderTree(TRUE); - } - else - { - gGL.getTexUnit(sDiffTex)->bind(mTexturep); - - for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *face = *iter; - LLDrawable *drawablep = face->getDrawable(); - - if (drawablep->isDead() || face->getVertexBuffer()) - { - continue; - } - - // Render each of the trees - LLVOTree *treep = (LLVOTree *)drawablep->getVObj().get(); - - LLColor4U color(255,255,255,255); - - if (treep->mGLName != 0) - { - S32 name = treep->mGLName; - color = LLColor4U((U8)(name >> 16), (U8)(name >> 8), (U8)name, 255); - - LLFacePool::LLOverrideFaceColor col(this, color); - - LLVertexBuffer *buff = face->getVertexBuffer(); - buff->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); - buff->drawRange(LLRender::TRIANGLES, 0, buff->getRequestedVerts()-1, buff->getRequestedIndices(), 0); - gPipeline.addTrianglesDrawn(buff->getRequestedIndices()/3); - } - } - } - - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - gGL.setSceneBlendType(LLRender::BT_ALPHA); - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); } void LLDrawPoolTree::renderTree(BOOL selecting) diff --git a/indra/newview/lldrawpooltree.h b/indra/newview/lldrawpooltree.h index bc7711d4e..714dc25e1 100644 --- a/indra/newview/lldrawpooltree.h +++ b/indra/newview/lldrawpooltree.h @@ -68,7 +68,6 @@ public: /*virtual*/ void render(S32 pass = 0); /*virtual*/ void endRenderPass( S32 pass ); /*virtual*/ S32 getNumPasses() { return 1; } - /*virtual*/ void renderForSelect(); /*virtual*/ BOOL verify() const; /*virtual*/ LLViewerTexture *getTexture(); /*virtual*/ LLViewerTexture *getDebugTexture(); diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 2b93af7b1..7dcc82218 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -114,7 +114,7 @@ void LLDrawPoolWater::prerender() // got rid of modulation by light color since it got a little too // green at sunset and sl-57047 (underwater turns black at 8:00) - sWaterFogColor = LLWaterParamManager::instance()->getFogColor(); + sWaterFogColor = LLWaterParamManager::getInstance()->getFogColor(); sWaterFogColor.mV[3] = 0; } @@ -532,7 +532,7 @@ void LLDrawPoolWater::shade() //bind normal map S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP); - LLWaterParamManager * param_mgr = LLWaterParamManager::instance(); + LLWaterParamManager * param_mgr = LLWaterParamManager::getInstance(); // change mWaterNormp if needed if (mWaterNormp->getID() != param_mgr->getNormalMapID()) diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index 4a6321a69..e6da1e631 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -40,6 +40,8 @@ #include "llviewercamera.h" #include "llimage.h" #include "llwlparammanager.h" +#include "llviewershadermgr.h" +#include "llglslshader.h" #include "llsky.h" #include "llvowlsky.h" #include "llviewerregion.h" @@ -50,6 +52,8 @@ LLPointer<LLViewerTexture> LLDrawPoolWLSky::sCloudNoiseTexture = NULL; LLPointer<LLImageRaw> LLDrawPoolWLSky::sCloudNoiseRawImage = NULL; +static LLGLSLShader* cloud_shader = NULL; +static LLGLSLShader* sky_shader = NULL; LLDrawPoolWLSky::LLDrawPoolWLSky(void) : @@ -64,15 +68,26 @@ LLDrawPoolWLSky::LLDrawPoolWLSky(void) : llerrs << "Error: Failed to load cloud noise image " << cloudNoiseFilename << llendl; } - cloudNoiseFile->load(cloudNoiseFilename); + if(cloudNoiseFile->load(cloudNoiseFilename)) + { + sCloudNoiseRawImage = new LLImageRaw(); - sCloudNoiseRawImage = new LLImageRaw(); + if(cloudNoiseFile->decode(sCloudNoiseRawImage, 0.0f)) + { + //debug use + lldebugs << "cloud noise raw image width: " << sCloudNoiseRawImage->getWidth() << " : height: " << sCloudNoiseRawImage->getHeight() << " : components: " << + (S32)sCloudNoiseRawImage->getComponents() << " : data size: " << sCloudNoiseRawImage->getDataSize() << llendl ; + llassert_always(sCloudNoiseRawImage->getData()) ; - cloudNoiseFile->decode(sCloudNoiseRawImage, 0.0f); + sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE); + } + else + { + sCloudNoiseRawImage = NULL ; + } + } - sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE); - - LLWLParamManager::instance()->propagateParameters(); + LLWLParamManager::getInstance()->propagateParameters(); } LLDrawPoolWLSky::~LLDrawPoolWLSky() @@ -89,12 +104,32 @@ LLViewerTexture *LLDrawPoolWLSky::getDebugTexture() void LLDrawPoolWLSky::beginRenderPass( S32 pass ) { + sky_shader = + LLPipeline::sUnderWaterRender ? + &gObjectSimpleWaterProgram : + &gWLSkyProgram; + + cloud_shader = + LLPipeline::sUnderWaterRender ? + &gObjectSimpleWaterProgram : + &gWLCloudProgram; } void LLDrawPoolWLSky::endRenderPass( S32 pass ) { } +void LLDrawPoolWLSky::beginDeferredPass(S32 pass) +{ + sky_shader = &gDeferredWLSkyProgram; + cloud_shader = &gDeferredWLCloudProgram; +} + +void LLDrawPoolWLSky::endDeferredPass(S32 pass) +{ + +} + void LLDrawPoolWLSky::renderDome(F32 camHeightLocal, LLGLSLShader * shader) const { LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin(); @@ -134,19 +169,14 @@ void LLDrawPoolWLSky::renderSkyHaze(F32 camHeightLocal) const { if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) { - LLGLSLShader* shader = - LLPipeline::sUnderWaterRender ? - &gObjectSimpleWaterProgram : - &gWLSkyProgram; - LLGLDisable blend(GL_BLEND); - shader->bind(); + sky_shader->bind(); /// Render the skydome - renderDome(camHeightLocal, shader); + renderDome(camHeightLocal, sky_shader); - shader->unbind(); + sky_shader->unbind(); } } @@ -172,7 +202,7 @@ void LLDrawPoolWLSky::renderStars(void) const // clamping and allow the star_alpha param to brighten the stars. bool error; LLColor4 star_alpha(LLColor4::black); - star_alpha.mV[3] = LLWLParamManager::instance()->mCurParams.getFloat("star_brightness", error) / 2.f; + star_alpha.mV[3] = LLWLParamManager::getInstance()->mCurParams.getFloat("star_brightness", error) / 2.f; llassert_always(!error); // gl_FragColor.rgb = gl_Color.rgb; @@ -182,43 +212,50 @@ void LLDrawPoolWLSky::renderStars(void) const gGL.pushMatrix(); glRotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f); - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA); - /*//Old - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_PREV_ALPHA, LLTexUnit::TBS_CONST_ALPHA); */ - glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV); - + // gl_FragColor.rgb = gl_Color.rgb; + // gl_FragColor.a = gl_Color.a * star_alpha.a; + if (LLGLSLShader::sNoFixedFunction) + { + gCustomAlphaProgram.bind(); + gCustomAlphaProgram.uniform1f("custom_alpha", star_alpha.mV[3]); + } + else + { + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_VERT_COLOR); + gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT_X2, LLTexUnit::TBS_CONST_ALPHA, LLTexUnit::TBS_TEX_ALPHA); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, star_alpha.mV); + } + gSky.mVOWLSkyp->drawStars(); - gGL.popMatrix(); //New - //glPointSize(1.f); - - // and disable the combiner states - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + gGL.popMatrix(); + + if (LLGLSLShader::sNoFixedFunction) + { + gCustomAlphaProgram.unbind(); + } + else + { + // and disable the combiner states + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } } void LLDrawPoolWLSky::renderSkyClouds(F32 camHeightLocal) const { - if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WL_CLOUDS)) + if (gPipeline.canUseWindLightShaders() && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_WL_CLOUDS) && sCloudNoiseTexture.notNull()) { - LLGLSLShader* shader = - LLPipeline::sUnderWaterRender ? - &gObjectSimpleWaterProgram : - &gWLCloudProgram; - LLGLEnable blend(GL_BLEND); gGL.setSceneBlendType(LLRender::BT_ALPHA); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); - + gGL.getTexUnit(0)->bind(sCloudNoiseTexture); - shader->bind(); + cloud_shader->bind(); /// Render the skydome - renderDome(camHeightLocal, shader); + renderDome(camHeightLocal, cloud_shader); - shader->unbind(); + cloud_shader->unbind(); } } @@ -244,6 +281,10 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() if (gSky.mVOSkyp->getMoon().getDraw() && face->getGeomCount()) { + if (gPipeline.canUseVertexShaders()) + { + gUIProgram.bind(); + } // *NOTE: even though we already bound this texture above for the // stars register combiners, we bind again here for defensive reasons, // since LLImageGL::bind detects that it's a noop, and optimizes it out. @@ -259,9 +300,61 @@ void LLDrawPoolWLSky::renderHeavenlyBodies() LLFacePool::LLOverrideFaceColor color_override(this, color); face->renderIndexed(); + + if (gPipeline.canUseVertexShaders()) + { + gUIProgram.unbind(); + } } } +void LLDrawPoolWLSky::renderDeferred(S32 pass) +{ + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) + { + return; + } + LLFastTimer ftm(LLFastTimer::FTM_RENDER_WL_SKY); + + const F32 camHeightLocal = LLWLParamManager::getInstance()->getDomeOffset() * LLWLParamManager::getInstance()->getDomeRadius(); + + LLGLSNoFog disableFog; + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + LLGLDisable clip(GL_CLIP_PLANE0); + + gGL.setColorMask(true, false); + + LLGLSquashToFarClip far_clip(glh_get_current_projection()); + + renderSkyHaze(camHeightLocal); + + LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin(); + glPushMatrix(); + + + glTranslatef(origin.mV[0], origin.mV[1], origin.mV[2]); + + gDeferredStarProgram.bind(); + // *NOTE: have to bind a texture here since register combiners blending in + // renderStars() requires something to be bound and we might as well only + // bind the moon's texture once. + gGL.getTexUnit(0)->bind(gSky.mVOSkyp->mFace[LLVOSky::FACE_MOON]->getTexture()); + + renderHeavenlyBodies(); + + renderStars(); + + gDeferredStarProgram.unbind(); + + glPopMatrix(); + + renderSkyClouds(camHeightLocal); + + gGL.setColorMask(true, true); + //gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + +} + void LLDrawPoolWLSky::render(S32 pass) { if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SKY)) @@ -270,7 +363,7 @@ void LLDrawPoolWLSky::render(S32 pass) } LLFastTimer ftm(LLFastTimer::FTM_RENDER_WL_SKY); - const F32 camHeightLocal = LLWLParamManager::instance()->getDomeOffset() * LLWLParamManager::instance()->getDomeRadius(); + const F32 camHeightLocal = LLWLParamManager::getInstance()->getDomeOffset() * LLWLParamManager::getInstance()->getDomeRadius(); LLGLSNoFog disableFog; LLGLDepthTest depth(GL_TRUE, GL_FALSE); @@ -330,5 +423,8 @@ void LLDrawPoolWLSky::cleanupGL() //static void LLDrawPoolWLSky::restoreGL() { - sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE); + if(sCloudNoiseRawImage.notNull()) + { + sCloudNoiseTexture = LLViewerTextureManager::getLocalTexture(sCloudNoiseRawImage.get(), TRUE); + } } diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h index 9059f6382..1057ef7bd 100644 --- a/indra/newview/lldrawpoolwlsky.h +++ b/indra/newview/lldrawpoolwlsky.h @@ -50,10 +50,10 @@ public: /*virtual*/ BOOL isDead() { return FALSE; } - /*virtual*/ S32 getNumPostDeferredPasses() { return getNumPasses(); } - /*virtual*/ void beginPostDeferredPass(S32 pass) { beginRenderPass(pass); } - /*virtual*/ void endPostDeferredPass(S32 pass) { endRenderPass(pass); } - /*virtual*/ void renderPostDeferred(S32 pass) { render(pass); } + /*virtual*/ S32 getNumDeferredPasses() { return 1; } + /*virtual*/ void beginDeferredPass(S32 pass); + /*virtual*/ void endDeferredPass(S32 pass); + /*virtual*/ void renderDeferred(S32 pass); /*virtual*/ LLViewerTexture *getDebugTexture(); /*virtual*/ void beginRenderPass( S32 pass ); diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp index 7fcfa5504..fb220d24a 100644 --- a/indra/newview/lldriverparam.cpp +++ b/indra/newview/lldriverparam.cpp @@ -160,7 +160,7 @@ BOOL LLDriverParam::parseData(LLXmlTreeNode* node) } #endif -void LLDriverParam::setWeight(F32 weight, BOOL set_by_user) +void LLDriverParam::setWeight(F32 weight, BOOL upload_bake) { F32 min_weight = getMinWeight(); F32 max_weight = getMaxWeight(); @@ -219,7 +219,7 @@ void LLDriverParam::setWeight(F32 weight, BOOL set_by_user) driven_weight = driven_min; } - driven->mParam->setWeight( driven_weight, set_by_user ); + setDrivenWeight(driven,driven_weight,upload_bake); continue; } else @@ -243,13 +243,13 @@ void LLDriverParam::setWeight(F32 weight, BOOL set_by_user) driven_weight = driven_min; } - driven->mParam->setWeight( driven_weight, set_by_user ); + setDrivenWeight(driven,driven_weight,upload_bake); continue; } } driven_weight = getDrivenWeight(driven, mCurWeight); - driven->mParam->setWeight( driven_weight, set_by_user ); + setDrivenWeight(driven,driven_weight,upload_bake); } } @@ -379,9 +379,9 @@ const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_ //----------------------------------------------------------------------------- // setAnimationTarget() //----------------------------------------------------------------------------- -void LLDriverParam::setAnimationTarget( F32 target_value, BOOL set_by_user ) +void LLDriverParam::setAnimationTarget( F32 target_value, BOOL upload_bake ) { - LLVisualParam::setAnimationTarget(target_value, set_by_user); + LLVisualParam::setAnimationTarget(target_value, upload_bake); for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { @@ -390,16 +390,16 @@ void LLDriverParam::setAnimationTarget( F32 target_value, BOOL set_by_user ) // this isn't normally necessary, as driver params handle interpolation of their driven params // but texture params need to know to assume their final value at beginning of interpolation - driven->mParam->setAnimationTarget(driven_weight, set_by_user); + driven->mParam->setAnimationTarget(driven_weight, upload_bake); } } //----------------------------------------------------------------------------- // stopAnimating() //----------------------------------------------------------------------------- -void LLDriverParam::stopAnimating(BOOL set_by_user) +void LLDriverParam::stopAnimating(BOOL upload_bake) { - LLVisualParam::stopAnimating(set_by_user); + LLVisualParam::stopAnimating(upload_bake); for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ ) { @@ -464,3 +464,19 @@ F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight return driven_weight; } + +void LLDriverParam::setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake) +{ + /*if(isAgentAvatarValid() && + mWearablep && + driven->mParam->getCrossWearable() && + mWearablep->isOnTop()) + { + // call setWeight through LLVOAvatarSelf so other wearables can be updated with the correct values + gAgentAvatarp->setVisualParamWeight( (LLVisualParam*)driven->mParam, driven_weight, upload_bake ); + } + else*/ + { + driven->mParam->setWeight( driven_weight, upload_bake ); + } +} diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h index 2e53ce563..f881e445e 100644 --- a/indra/newview/lldriverparam.h +++ b/indra/newview/lldriverparam.h @@ -92,9 +92,9 @@ public: // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex sex ) {} // apply is called separately for each driven param. - /*virtual*/ void setWeight(F32 weight, BOOL set_by_user); - /*virtual*/ void setAnimationTarget( F32 target_value, BOOL set_by_user ); - /*virtual*/ void stopAnimating(BOOL set_by_user); + /*virtual*/ void setWeight(F32 weight, BOOL upload_bake); + /*virtual*/ void setAnimationTarget( F32 target_value, BOOL upload_bake ); + /*virtual*/ void stopAnimating(BOOL upload_bake); // LLViewerVisualParam Virtual functions /*virtual*/ F32 getTotalDistortion(); @@ -103,8 +103,10 @@ public: /*virtual*/ LLVector3 getVertexDistortion(S32 index, LLPolyMesh *poly_mesh); /*virtual*/ const LLVector3* getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh); /*virtual*/ const LLVector3* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh); + protected: F32 getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight); + void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); LLVector3 mDefaultVec; // temp holder diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp index 609fdc64b..b53cfd649 100644 --- a/indra/newview/lldynamictexture.cpp +++ b/indra/newview/lldynamictexture.cpp @@ -34,6 +34,7 @@ #include "lldynamictexture.h" #include "llglheaders.h" +#include "llwindow.h" // getPosition() #include "llviewerwindow.h" #include "llviewercamera.h" #include "llviewercontrol.h" @@ -41,6 +42,7 @@ #include "llvertexbuffer.h" #include "llviewerdisplay.h" #include "llrender.h" +#include "llglslshader.h" // static LLViewerDynamicTexture::instance_list_t LLViewerDynamicTexture::sInstances[ LLViewerDynamicTexture::ORDER_COUNT ]; @@ -55,6 +57,13 @@ LLViewerDynamicTexture::LLViewerDynamicTexture(S32 width, S32 height, S32 compon { llassert((1 <= components) && (components <= 4)); + if(gGLManager.mDebugGPU) + { + if(components == 3) + { + mComponents = 4 ; //convert to 32bits. + } + } generateGLTexture(); llassert( 0 <= order && order < ORDER_COUNT ); @@ -123,7 +132,7 @@ void LLViewerDynamicTexture::preRender(BOOL clear_depth) // force rendering to on-screen portion of frame buffer LLCoordScreen window_pos; gViewerWindow->getWindow()->getPosition( &window_pos ); - mOrigin.set(0, gViewerWindow->getWindowDisplayHeight() - mFullHeight); // top left corner + mOrigin.set(0, gViewerWindow->getWindowHeightRaw() - mFullHeight); // top left corner if (window_pos.mX < 0) { @@ -178,7 +187,7 @@ void LLViewerDynamicTexture::postRender(BOOL success) } // restore viewport - gViewerWindow->setupViewport(); + gViewerWindow->setup2DViewport(); // restore camera LLViewerCamera* camera = LLViewerCamera::getInstance(); @@ -202,6 +211,14 @@ BOOL LLViewerDynamicTexture::updateAllInstances() return TRUE; } + LLGLSLShader::bindNoShader(); + LLVertexBuffer::unbind(); + + bool no_ff = LLGLSLShader::sNoFixedFunction; + static const LLCachedControl<bool> force_fixed_functions("ShyotlUseLegacyDynamicTexture",false); + if(force_fixed_functions) + LLGLSLShader::sNoFixedFunction = false; + BOOL result = FALSE; BOOL ret = FALSE ; for( S32 order = 0; order < ORDER_COUNT; order++ ) @@ -232,6 +249,8 @@ BOOL LLViewerDynamicTexture::updateAllInstances() } } + LLGLSLShader::sNoFixedFunction = no_ff; + return ret; } diff --git a/indra/newview/lldynamictexture.h b/indra/newview/lldynamictexture.h index 2342669f2..14b8e582d 100644 --- a/indra/newview/lldynamictexture.h +++ b/indra/newview/lldynamictexture.h @@ -33,6 +33,7 @@ #ifndef LL_LLDYNAMICTEXTURE_H #define LL_LLDYNAMICTEXTURE_H +#include "llcamera.h" #include "llgl.h" #include "llcoord.h" #include "llviewertexture.h" diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp index 1e915a266..20422369d 100644 --- a/indra/newview/lleventnotifier.cpp +++ b/indra/newview/lleventnotifier.cpp @@ -34,6 +34,7 @@ #include "lleventnotifier.h" +#include "llnotificationsutil.h" #include "message.h" #include "llnotify.h" @@ -78,24 +79,42 @@ void LLEventNotifier::update() { LLEventNotification *np = iter->second; + iter++; if (np->getEventDate() < (alert_time)) { LLSD args; args["NAME"] = np->getEventName(); args["DATE"] = np->getEventDateStr(); - LLNotifications::instance().add("EventNotification", args, LLSD(), - boost::bind(&LLEventNotification::handleResponse, np, _1, _2)); - mEventNotifications.erase(iter++); - } - else - { - iter++; + LLNotificationsUtil::add("EventNotification", args, LLSD(), + boost::bind(&LLEventNotifier::handleResponse, this, np->getEventID(), np->getEventPosGlobal(), _1, _2)); + remove(np->getEventID()); } } mNotificationTimer.reset(); } } +bool LLEventNotifier::handleResponse(U32 eventId, LLVector3d eventPos, const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + switch (option) + { + case 0: + gAgent.teleportViaLocation(eventPos); + gFloaterWorldMap->trackLocation(eventPos); + break; + case 1: + gDisplayEventHack = TRUE; + LLFloaterDirectory::showEvents(eventId); + break; + case 2: + break; + } + + // We could clean up the notification on the server now if we really wanted to. + return true; +} + void LLEventNotifier::load(const LLUserAuth::options_t& event_options) { LLUserAuth::options_t::const_iterator resp_it; @@ -117,6 +136,19 @@ void LLEventNotifier::load(const LLUserAuth::options_t& event_options) } } +void LLEventNotifier::add(U32 eventId) +{ + + gMessageSystem->newMessageFast(_PREHASH_EventInfoRequest); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); + gMessageSystem->nextBlockFast(_PREHASH_EventData); + gMessageSystem->addU32Fast(_PREHASH_EventID, eventId); + gAgent.sendReliableMessage(); + +} + BOOL LLEventNotifier::hasNotification(const U32 event_id) { if (mEventNotifications.find(event_id) != mEventNotifications.end()) @@ -137,14 +169,7 @@ void LLEventNotifier::add(LLEventInfo &event_info) return; } - // Push up a message to tell the server we have this notification. - gMessageSystem->newMessage("EventNotificationAddRequest"); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlock("EventData"); - gMessageSystem->addU32("EventID", event_info.mID); - gAgent.sendReliableMessage(); + serverPushRequest(event_info.mID, true); LLEventNotification *enp = new LLEventNotification; enp->load(event_info); @@ -161,17 +186,22 @@ void LLEventNotifier::remove(const U32 event_id) return; } - // Push up a message to tell the server to remove this notification. - gMessageSystem->newMessage("EventNotificationRemoveRequest"); + serverPushRequest(event_id, false); + delete iter->second; + mEventNotifications.erase(iter); +} + + +void LLEventNotifier::serverPushRequest(U32 event_id, bool add) +{ + // Push up a message to tell the server we have this notification. + gMessageSystem->newMessage(add?"EventNotificationAddRequest":"EventNotificationRemoveRequest"); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gMessageSystem->nextBlock("EventData"); gMessageSystem->addU32("EventID", event_id); gAgent.sendReliableMessage(); - - delete iter->second; - mEventNotifications.erase(iter); } LLEventNotification::LLEventNotification() : @@ -185,26 +215,6 @@ LLEventNotification::~LLEventNotification() { } -bool LLEventNotification::handleResponse(const LLSD& notification, const LLSD& response) -{ - S32 option = LLNotification::getSelectedOption(notification, response); - switch (option) - { - case 0: - gAgent.teleportViaLocation(getEventPosGlobal()); - gFloaterWorldMap->trackLocation(getEventPosGlobal()); - break; - case 1: - gDisplayEventHack = TRUE; - LLFloaterDirectory::showEvents(getEventID()); - break; - case 2: - break; - } - - // We could clean up the notification on the server now if we really wanted to. - return false; -} BOOL LLEventNotification::load(const LLUserAuth::response_t &response) { diff --git a/indra/newview/lleventnotifier.h b/indra/newview/lleventnotifier.h index feb734948..f5e03a3fb 100644 --- a/indra/newview/lleventnotifier.h +++ b/indra/newview/lleventnotifier.h @@ -39,6 +39,7 @@ class LLEventInfo; class LLEventNotification; +class LLMessageSystem; class LLEventNotifier @@ -48,14 +49,17 @@ public: virtual ~LLEventNotifier(); void update(); // Notify the user of the event if it's coming up + void add(LLEventInfo &event_info); // Add a new notification for an event + void add(U32 eventId); void load(const LLUserAuth::options_t& event_options); // In the format that it comes in from LLUserAuth - void add(LLEventInfo &event_info); // Add a new notification for an event void remove(U32 event_id); BOOL hasNotification(const U32 event_id); + void serverPushRequest(U32 event_id, bool add); typedef std::map<U32, LLEventNotification *> en_map; + bool handleResponse(U32 eventId, LLVector3d eventPos, const LLSD& notification, const LLSD& response); protected: en_map mEventNotifications; @@ -78,7 +82,6 @@ public: time_t getEventDate() const { return mEventDate; } const std::string &getEventDateStr() const { return mEventDateStr; } LLVector3d getEventPosGlobal() const { return mEventPosGlobal; } - bool handleResponse(const LLSD& notification, const LLSD& payload); protected: U32 mEventID; // EventID for this event std::string mEventName; diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 55e3dd5d1..4a57b390e 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -39,8 +39,10 @@ #include "llviewercontrol.h" #include "llvolume.h" #include "m3math.h" +#include "llmatrix4a.h" #include "v3color.h" +#include "lldrawpoolavatar.h" #include "lldrawpoolbump.h" #include "llgl.h" #include "llrender.h" @@ -73,35 +75,43 @@ The resulting texture coordinate <u,v> is: u = 2(B dot P) v = 2(T dot P) */ -void planarProjection(LLVector2 &tc, const LLVector3& normal, - const LLVector3 &mCenter, const LLVector3& vec) -{ //DONE! - LLVector3 binormal; - float d = normal * LLVector3(1,0,0); +void planarProjection(LLVector2 &tc, const LLVector4a& normal, + const LLVector4a ¢er, const LLVector4a& vec) +{ + LLVector4a binormal; + F32 d = normal[0]; + if (d >= 0.5f || d <= -0.5f) { - binormal = LLVector3(0,1,0); - if (normal.mV[0] < 0) + if (d < 0) { - binormal = -binormal; + binormal.set(0,-1,0); + } + else + { + binormal.set(0, 1, 0); } } else { - binormal = LLVector3(1,0,0); - if (normal.mV[1] > 0) + if (normal[1] > 0) { - binormal = -binormal; + binormal.set(-1,0,0); + } + else + { + binormal.set(1,0,0); } } - LLVector3 tangent = binormal % normal; + LLVector4a tangent; + tangent.setCross3(binormal,normal); - tc.mV[1] = -((tangent*vec)*2 - 0.5f); - tc.mV[0] = 1.0f+((binormal*vec)*2 - 0.5f); + tc.mV[1] = -((tangent.dot3(vec).getF32())*2 - 0.5f); + tc.mV[0] = 1.0f+((binormal.dot3(vec).getF32())*2 - 0.5f); } -void sphericalProjection(LLVector2 &tc, const LLVector3& normal, - const LLVector3 &mCenter, const LLVector3& vec) +void sphericalProjection(LLVector2 &tc, const LLVector4a& normal, + const LLVector4a &mCenter, const LLVector4a& vec) { //BROKEN /*tc.mV[0] = acosf(vd.mNormal * LLVector3(1,0,0))/3.14159f; @@ -112,7 +122,7 @@ void sphericalProjection(LLVector2 &tc, const LLVector3& normal, }*/ } -void cylindricalProjection(LLVector2 &tc, const LLVector3& normal, const LLVector3 &mCenter, const LLVector3& vec) +void cylindricalProjection(LLVector2 &tc, const LLVector4a& normal, const LLVector4a &mCenter, const LLVector4a& vec) { //BROKEN /*LLVector3 binormal; float d = vd.mNormal * LLVector3(1,0,0); @@ -144,6 +154,9 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) { mLastUpdateTime = gFrameTimeSeconds; mLastMoveTime = 0.f; +#if MESH_ENABLED + mLastSkinTime = gFrameTimeSeconds; +#endif //MESH_ENABLED mVSize = 0.f; mPixelArea = 16.f; mState = GLOBAL; @@ -160,6 +173,7 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mIndexInTex = 0; mTexture = NULL; mTEOffset = -1; + mTextureIndex = 255; setDrawable(drawablep); mVObjp = objp; @@ -196,7 +210,17 @@ void LLFace::destroy() if (mDrawPoolp) { - mDrawPoolp->removeFace(this); +#if MESH_ENABLED + if (this->isState(LLFace::RIGGED) && mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR) + { + ((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this); + } + else +#endif //MESH_ENABLED + { + mDrawPoolp->removeFace(this); + } + mDrawPoolp = NULL; } @@ -358,6 +382,44 @@ void LLFace::setSize(S32 num_vertices, const S32 num_indices, bool align) llassert(verify()); } +void LLFace::setGeomIndex(U16 idx) +{ + if (mGeomIndex != idx) + { + mGeomIndex = idx; + mVertexBuffer = NULL; + } +} + +void LLFace::setTextureIndex(U8 index) +{ + if (index != mTextureIndex) + { + mTextureIndex = index; + + if (mTextureIndex != 255) + { + mDrawablep->setState(LLDrawable::REBUILD_POSITION); + } + else + { + if (mDrawInfo && !mDrawInfo->mTextureList.empty()) + { + llerrs << "Face with no texture index references indexed texture draw info." << llendl; + } + } + } +} + +void LLFace::setIndicesIndex(S32 idx) +{ + if (mIndicesIndex != idx) + { + mIndicesIndex = idx; + mVertexBuffer = NULL; + } +} + //============================================================================ U16 LLFace::getGeometryAvatar( @@ -416,83 +478,6 @@ void LLFace::updateCenterAgent() } } -void LLFace::renderForSelect(U32 data_mask) -{ - if(mDrawablep.isNull() || mVertexBuffer.isNull()) - { - return; - } - - LLSpatialGroup* group = mDrawablep->getSpatialGroup(); - if (!group || group->isState(LLSpatialGroup::GEOM_DIRTY)) - { - return; - } - - if (mVObjp->mGLName) - { - S32 name = mVObjp->mGLName; - - LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name); -#if 0 // *FIX: Postponing this fix until we have texcoord pick info... - if (mTEOffset != -1) - { - color.mV[VALPHA] = (U8)(getTextureEntry()->getColor().mV[VALPHA] * 255.f); - } -#endif - glColor4ubv(color.mV); - - if (!getPool()) - { - switch (getPoolType()) - { - case LLDrawPool::POOL_ALPHA: - gGL.getTexUnit(0)->bind(getTexture()); - break; - default: - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - break; - } - } - - mVertexBuffer->setBuffer(data_mask); -#if !LL_RELEASE_FOR_DOWNLOAD - LLGLState::checkClientArrays("", data_mask); -#endif - if (mTEOffset != -1) - { - // mask off high 4 bits (16 total possible faces) - color.mV[0] &= 0x0f; - color.mV[0] |= (mTEOffset & 0x0f) << 4; - glColor4ubv(color.mV); - } - - if (mIndicesCount) - { - if (isState(GLOBAL)) - { - if (mDrawablep->getVOVolume()) - { - glPushMatrix(); - glMultMatrixf((float*) mDrawablep->getRegion()->mRenderMatrix.mMatrix); - mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); - glPopMatrix(); - } - else - { - mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); - } - } - else - { - glPushMatrix(); - glMultMatrixf((float*)getRenderMatrix().mMatrix); - mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); - glPopMatrix(); - } - } - } -} void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) { if (mDrawablep->getSpatialGroup() == NULL) @@ -523,11 +508,40 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color) } glColor4fv(color.mV); - mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); -#if !LL_RELEASE_FOR_DOWNLOAD - LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); -#endif - mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); +#if MESH_ENABLED + if (mDrawablep->isState(LLDrawable::RIGGED)) + { + LLVOVolume* volume = mDrawablep->getVOVolume(); + if (volume) + { + LLRiggedVolume* rigged = volume->getRiggedVolume(); + if (rigged) + { + LLGLEnable offset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.f, -1.f); + glMultMatrixf((F32*) volume->getRelativeXform().mMatrix); + const LLVolumeFace& vol_face = rigged->getVolumeFace(getTEOffset()); + LLVertexBuffer::unbind(); + glVertexPointer(3, GL_FLOAT, 16, vol_face.mPositions); + if (vol_face.mTexCoords) + { + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(2, GL_FLOAT, 8, vol_face.mTexCoords); + } + glDrawElements(GL_TRIANGLES, vol_face.mNumIndices, GL_UNSIGNED_SHORT, vol_face.mIndices); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + } + } + } + else +#endif //MESH_ENABLED + { + mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + #if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays("", LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); + #endif + mVertexBuffer->draw(LLRender::TRIANGLES, mIndicesCount, mIndicesIndex); + } gGL.popMatrix(); } @@ -687,96 +701,152 @@ static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 of } +bool less_than_max_mag(const LLVector4a& vec) +{ + LLVector4a MAX_MAG; + MAX_MAG.splat(1024.f*1024.f); + + LLVector4a val; + val.setAbs(vec); + + S32 lt = val.lessThan(MAX_MAG).getGatheredBits() & 0x7; + + return lt == 0x7; +} + BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, - const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL global_volume) + const LLMatrix4& mat_vert_in, const LLMatrix3& mat_normal_in, BOOL global_volume) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); //get bounding box - if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION)) + if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION +#if MESH_ENABLED + | LLDrawable::REBUILD_RIGGED +#endif //MESH_ENABLED + )) { + //VECTORIZE THIS + LLMatrix4a mat_vert; + mat_vert.loadu(mat_vert_in); + + LLMatrix4a mat_normal; + mat_normal.loadu(mat_normal_in); + //if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) //{ //vertex buffer no longer valid // mVertexBuffer = NULL; // mLastVertexBuffer = NULL; //} - LLVector3 min,max; + //VECTORIZE THIS + LLVector4a min,max; if (f >= volume.getNumVolumeFaces()) { - min = LLVector3(-1,-1,-1); - max = LLVector3(1,1,1); - } - else - { - const LLVolumeFace &face = volume.getVolumeFace(f); - min = face.mExtents[0]; - max = face.mExtents[1]; + llwarns << "Generating bounding box for invalid face index!" << llendl; + f = 0; } + const LLVolumeFace &face = volume.getVolumeFace(f); + min = face.mExtents[0]; + max = face.mExtents[1]; + + llassert(less_than_max_mag(min)); + llassert(less_than_max_mag(max)); + //min, max are in volume space, convert to drawable render space - LLVector3 center = ((min + max) * 0.5f)*mat_vert; - LLVector3 size = ((max-min) * 0.5f); + LLVector4a center; + LLVector4a t; + t.setAdd(min, max); + t.mul(0.5f); + mat_vert.affineTransform(t, center); + LLVector4a size; + size.setSub(max, min); + size.mul(0.5f); + + llassert(less_than_max_mag(min)); + llassert(less_than_max_mag(max)); + if (!global_volume) { - size.scaleVec(mDrawablep->getVObj()->getScale()); + //VECTORIZE THIS + LLVector4a scale; + scale.load3(mDrawablep->getVObj()->getScale().mV); + size.mul(scale); } - LLMatrix3 mat = mat_normal; - LLVector3 x = mat.getFwdRow(); - LLVector3 y = mat.getLeftRow(); - LLVector3 z = mat.getUpRow(); - x.normVec(); - y.normVec(); - z.normVec(); - - mat.setRows(x,y,z); - - LLQuaternion rotation = LLQuaternion(mat); + mat_normal.mMatrix[0].normalize3fast(); + mat_normal.mMatrix[1].normalize3fast(); + mat_normal.mMatrix[2].normalize3fast(); - LLVector3 v[4]; - //get 4 corners of bounding box - v[0] = (size * rotation); - v[1] = (LLVector3(-size.mV[0], -size.mV[1], size.mV[2]) * rotation); - v[2] = (LLVector3(size.mV[0], -size.mV[1], -size.mV[2]) * rotation); - v[3] = (LLVector3(-size.mV[0], size.mV[1], -size.mV[2]) * rotation); + LLVector4a v[4]; - LLVector3& newMin = mExtents[0]; - LLVector3& newMax = mExtents[1]; + //get 4 corners of bounding box + mat_normal.rotate(size,v[0]); + + //VECTORIZE THIS + LLVector4a scale; + + scale.set(-1.f, -1.f, 1.f); + scale.mul(size); + mat_normal.rotate(scale, v[1]); + + scale.set(1.f, -1.f, -1.f); + scale.mul(size); + mat_normal.rotate(scale, v[2]); + + scale.set(-1.f, 1.f, -1.f); + scale.mul(size); + mat_normal.rotate(scale, v[3]); + + LLVector4a& newMin = mExtents[0]; + LLVector4a& newMax = mExtents[1]; newMin = newMax = center; + llassert(less_than_max_mag(center)); + for (U32 i = 0; i < 4; i++) { - for (U32 j = 0; j < 3; j++) - { - F32 delta = fabsf(v[i].mV[j]); - F32 min = center.mV[j] - delta; - F32 max = center.mV[j] + delta; - - if (min < newMin.mV[j]) - { - newMin.mV[j] = min; - } - - if (max > newMax.mV[j]) - { - newMax.mV[j] = max; - } - } + LLVector4a delta; + delta.setAbs(v[i]); + LLVector4a min; + min.setSub(center, delta); + LLVector4a max; + max.setAdd(center, delta); + + newMin.setMin(newMin,min); + newMax.setMax(newMax,max); + + llassert(less_than_max_mag(newMin)); + llassert(less_than_max_mag(newMax)); } if (!mDrawablep->isActive()) { - LLVector3 offset = mDrawablep->getRegion()->getOriginAgent(); - newMin += offset; - newMax += offset; + LLVector4a offset; + offset.load3(mDrawablep->getRegion()->getOriginAgent().mV); + newMin.add(offset); + newMax.add(offset); + + llassert(less_than_max_mag(newMin)); + llassert(less_than_max_mag(newMax)); } - mCenterLocal = (newMin+newMax)*0.5f; - LLVector3 tmp = (newMin - newMax) ; - mBoundingSphereRadius = tmp.length() * 0.5f ; + t.setAdd(newMin, newMax); + t.mul(0.5f); + + llassert(less_than_max_mag(t)); + + //VECTORIZE THIS + mCenterLocal.set(t.getF32ptr()); + + llassert(less_than_max_mag(newMin)); + llassert(less_than_max_mag(newMax)); + + t.setSub(newMax,newMin); + mBoundingSphereRadius = t.getLength3().getF32()*0.5f; updateCenterAgent(); } @@ -803,18 +873,26 @@ LLVector2 LLFace::surfaceToTexture(LLVector2 surface_coord, LLVector3 position, return surface_coord; } + //VECTORIZE THIS // see if we have a non-default mapping U8 texgen = getTextureEntry()->getTexGen(); if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) { - LLVector3 center = mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter; + LLVector4a& center = *(mDrawablep->getVOVolume()->getVolume()->getVolumeFace(mTEOffset).mCenter); - LLVector3 scale = (mDrawablep->getVOVolume()->isVolumeGlobal()) ? LLVector3(1,1,1) : mVObjp->getScale(); - LLVector3 volume_position = mDrawablep->getVOVolume()->agentPositionToVolume(position); - volume_position.scaleVec(scale); + LLVector4a volume_position; + volume_position.load3(mDrawablep->getVOVolume()->agentPositionToVolume(position).mV); - LLVector3 volume_normal = mDrawablep->getVOVolume()->agentDirectionToVolume(normal); - volume_normal.normalize(); + if (!mDrawablep->getVOVolume()->isVolumeGlobal()) + { + LLVector4a scale; + scale.load3(mVObjp->getScale().mV); + volume_position.mul(scale); + } + + LLVector4a volume_normal; + volume_normal.load3(mDrawablep->getVOVolume()->agentDirectionToVolume(normal).mV); + volume_normal.normalize3fast(); switch (texgen) { @@ -855,17 +933,21 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po { const LLMatrix4& vol_mat = getWorldMatrix(); const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset); - LLVector3 normal = vf.mVertices[0].mNormal; - LLVector3 binormal = vf.mVertices[0].mBinormal; + const LLVector4a& normal4a = vf.mNormals[0]; + const LLVector4a& binormal4a = vf.mBinormals[0]; LLVector2 projected_binormal; - planarProjection(projected_binormal, normal, vf.mCenter, binormal); + planarProjection(projected_binormal, normal4a, *vf.mCenter, binormal4a); projected_binormal -= LLVector2(0.5f, 0.5f); // this normally happens in xform() *scale = projected_binormal.length(); // rotate binormal to match what planarProjection() thinks it is, - // then find face's rotation from normal and rotated binormal: + // then find rotation from that: projected_binormal.normalize(); F32 ang = acos(projected_binormal.mV[VY]); ang = (projected_binormal.mV[VX] < 0.f) ? -ang : ang; + + //VECTORIZE THIS + LLVector3 binormal(binormal4a.getF32ptr()); + LLVector3 normal(normal4a.getF32ptr()); binormal.rotVec(ang, normal); LLQuaternion local_rot( binormal % normal, binormal, normal ); *face_rot = local_rot * vol_mat.quaternion(); @@ -966,13 +1048,14 @@ bool LLFace::canRenderAsMask() BOOL LLFace::getGeometryVolume(const LLVolume& volume, const S32 &f, - const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, - const U16 &index_offset) + const LLMatrix4& mat_vert_in, const LLMatrix3& mat_norm_in, + const U16 &index_offset, + bool force_rebuild) { llassert(verify()); const LLVolumeFace &vf = volume.getVolumeFace(f); - S32 num_vertices = (S32)vf.mVertices.size(); - S32 num_indices = (S32)vf.mIndices.size(); + S32 num_vertices = (S32)vf.mNumVertices; + S32 num_indices = (S32) vf.mNumIndices; if (mVertexBuffer.notNull()) { @@ -997,15 +1080,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, } } - LLStrider<LLVector3> vertices; + LLStrider<LLVector3> vert; LLStrider<LLVector2> tex_coords; LLStrider<LLVector2> tex_coords2; - LLStrider<LLVector3> normals; + LLStrider<LLVector3> norm; LLStrider<LLColor4U> colors; - LLStrider<LLVector3> binormals; + LLStrider<LLVector3> binorm; LLStrider<U16> indicesp; +#if MESH_ENABLED + LLStrider<LLVector4> wght; +#endif //MESH_ENABLED - BOOL full_rebuild = mDrawablep->isState(LLDrawable::REBUILD_VOLUME); + BOOL full_rebuild = force_rebuild || mDrawablep->isState(LLDrawable::REBUILD_VOLUME); BOOL global_volume = mDrawablep->getVOVolume()->isVolumeGlobal(); LLVector3 scale; @@ -1018,43 +1104,18 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, scale = mVObjp->getScale(); } - BOOL rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION); - BOOL rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR); - BOOL rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); - BOOL rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); - BOOL rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL); + bool rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION); + bool rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR); + bool rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); + bool rebuild_normal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + bool rebuild_binormal = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_BINORMAL); +#if MESH_ENABLED + bool rebuild_weights = rebuild_pos && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_WEIGHT4); +#endif //MESH_ENABLED const LLTextureEntry *tep = mVObjp->getTE(f); if (!tep) rebuild_color = FALSE; // can't get color when tep is NULL U8 bump_code = tep ? tep->getBumpmap() : 0; - - if (rebuild_pos) - { - mVertexBuffer->getVertexStrider(vertices, mGeomIndex); - } - if (rebuild_normal) - { - mVertexBuffer->getNormalStrider(normals, mGeomIndex); - } - if (rebuild_binormal) - { - mVertexBuffer->getBinormalStrider(binormals, mGeomIndex); - } - - if (rebuild_tcoord) - { - mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); - if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) - { - mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); - } - } - if (rebuild_color) - { - mVertexBuffer->getColorStrider(colors, mGeomIndex); - } - - F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; BOOL is_static = mDrawablep->isStatic(); BOOL is_global = is_static; @@ -1070,59 +1131,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, clearState(GLOBAL); } - LLVector2 tmin, tmax; - - - - if (rebuild_tcoord) - { - if (tep) - { - r = tep->getRotation(); - os = tep->mOffsetS; - ot = tep->mOffsetT; - ms = tep->mScaleS; - mt = tep->mScaleT; - cos_ang = cos(r); - sin_ang = sin(r); - } - else - { - cos_ang = 1.0f; - sin_ang = 0.0f; - os = 0.0f; - ot = 0.0f; - ms = 1.0f; - mt = 1.0f; - } - } - - U8 tex_mode = 0; - - if (isState(TEXTURE_ANIM)) - { - LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; - tex_mode = vobj->mTexAnimMode; - - if (!tex_mode) - { - clearState(TEXTURE_ANIM); - } - else - { - os = ot = 0.f; - r = 0.f; - cos_ang = 1.f; - sin_ang = 0.f; - ms = mt = 1.f; - } - - if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) - { //don't override texture transform during tc bake - tex_mode = 0; - } - } - LLColor4U color = (tep ? LLColor4U(tep->getColor()) : LLColor4U::white); if (rebuild_color) // FALSE if tep == NULL @@ -1148,164 +1156,491 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, if (full_rebuild) { mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); - for (U32 i = 0; i < (U32) num_indices; i++) - { - *indicesp++ = vf.mIndices[i] + index_offset; - } - } - - - //bump setup - LLVector3 binormal_dir( -sin_ang, cos_ang, 0 ); - LLVector3 bump_s_primary_light_ray; - LLVector3 bump_t_primary_light_ray; - LLQuaternion bump_quat; - if (mDrawablep->isActive()) - { - bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); - } - - if (bump_code) - { - mVObjp->getVolume()->genBinormals(f); - F32 offset_multiple; - switch( bump_code ) - { - case BE_NO_BUMP: - offset_multiple = 0.f; - break; - case BE_BRIGHTNESS: - case BE_DARKNESS: - if( mTexture.notNull() && mTexture->hasGLTexture()) - { - // Offset by approximately one texel - S32 cur_discard = mTexture->getDiscardLevel(); - S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); - max_size <<= cur_discard; - const F32 ARTIFICIAL_OFFSET = 2.f; - offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; - } - else - { - offset_multiple = 1.f/256; - } - break; + __m128i* dst = (__m128i*) indicesp.get(); + __m128i* src = (__m128i*) vf.mIndices; + __m128i offset = _mm_set1_epi16(index_offset); - default: // Standard bumpmap textures. Assumed to be 256x256 - offset_multiple = 1.f / 256; - break; - } - - F32 s_scale = 1.f; - F32 t_scale = 1.f; - if( tep ) - { - tep->getScale( &s_scale, &t_scale ); - } - // Use the nudged south when coming from above sun angle, such - // that emboss mapping always shows up on the upward faces of cubes when - // it's noon (since a lot of builders build with the sun forced to noon). - LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; - LLVector3 moon_ray = gSky.getMoonDirection(); - LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; - - bump_s_primary_light_ray = offset_multiple * s_scale * primary_light_ray; - bump_t_primary_light_ray = offset_multiple * t_scale * primary_light_ray; - } + S32 end = num_indices/8; - U8 texgen = getTextureEntry()->getTexGen(); - if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { //planar texgen needs binormals - mVObjp->getVolume()->genBinormals(f); - } - - for (S32 i = 0; i < num_vertices; i++) - { - if (rebuild_tcoord) + for (S32 i = 0; i < end; i++) { - LLVector2 tc = vf.mVertices[i].mTexCoord; - - if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { - LLVector3 vec = vf.mVertices[i].mPosition; + __m128i res = _mm_add_epi16(src[i], offset); + _mm_storeu_si128(dst+i, res); + } + + for (S32 i = end*8; i < num_indices; ++i) + { + indicesp[i] = vf.mIndices[i]+index_offset; + } + } + + LLMatrix4a mat_normal; + mat_normal.loadu(mat_norm_in); + + //if it's not fullbright and has no normals, bake sunlight based on face normal + //bool bake_sunlight = !getTextureEntry()->getFullbright() && + // !mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL); + + F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; + + if (rebuild_tcoord) + { + bool do_xform; - vec.scaleVec(scale); + if (tep) + { + r = tep->getRotation(); + os = tep->mOffsetS; + ot = tep->mOffsetT; + ms = tep->mScaleS; + mt = tep->mScaleT; + cos_ang = cos(r); + sin_ang = sin(r); - switch (texgen) - { - case LLTextureEntry::TEX_GEN_PLANAR: - planarProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec); - break; - case LLTextureEntry::TEX_GEN_SPHERICAL: - sphericalProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec); - break; - case LLTextureEntry::TEX_GEN_CYLINDRICAL: - cylindricalProjection(tc, vf.mVertices[i].mNormal, vf.mCenter, vec); - break; - default: - break; - } - } - - if (tex_mode && mTextureMatrix) + if (cos_ang != 1.f || + sin_ang != 0.f || + os != 0.f || + ot != 0.f || + ms != 1.f || + mt != 1.f) { - LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); - tmp = tmp * *mTextureMatrix; - tc.mV[0] = tmp.mV[0]; - tc.mV[1] = tmp.mV[1]; + do_xform = true; } else { - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); - } - - *tex_coords++ = tc; - - if (bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1)) - { - LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal; - - LLMatrix3 tangent_to_object; - tangent_to_object.setRows(tangent, vf.mVertices[i].mBinormal, vf.mVertices[i].mNormal); - LLVector3 binormal = binormal_dir * tangent_to_object; - binormal = binormal * mat_normal; - - if (mDrawablep->isActive()) - { - binormal *= bump_quat; - } - - binormal.normVec(); - tc += LLVector2( bump_s_primary_light_ray * tangent, bump_t_primary_light_ray * binormal ); - - *tex_coords2++ = tc; + do_xform = false; } } + else + { + do_xform = false; + } + + //bump setup + LLVector4a binormal_dir( -sin_ang, cos_ang, 0.f ); + LLVector4a bump_s_primary_light_ray(0.f, 0.f, 0.f); + LLVector4a bump_t_primary_light_ray(0.f, 0.f, 0.f); + + LLQuaternion bump_quat; + if (mDrawablep->isActive()) + { + bump_quat = LLQuaternion(mDrawablep->getRenderMatrix()); + } + + if (bump_code) + { + mVObjp->getVolume()->genBinormals(f); + F32 offset_multiple; + switch( bump_code ) + { + case BE_NO_BUMP: + offset_multiple = 0.f; + break; + case BE_BRIGHTNESS: + case BE_DARKNESS: + if( mTexture.notNull() && mTexture->hasGLTexture()) + { + // Offset by approximately one texel + S32 cur_discard = mTexture->getDiscardLevel(); + S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); + max_size <<= cur_discard; + const F32 ARTIFICIAL_OFFSET = 2.f; + offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; + } + else + { + offset_multiple = 1.f/256; + } + break; + + default: // Standard bumpmap textures. Assumed to be 256x256 + offset_multiple = 1.f / 256; + break; + } + + F32 s_scale = 1.f; + F32 t_scale = 1.f; + if( tep ) + { + tep->getScale( &s_scale, &t_scale ); + } + // Use the nudged south when coming from above sun angle, such + // that emboss mapping always shows up on the upward faces of cubes when + // it's noon (since a lot of builders build with the sun forced to noon). + LLVector3 sun_ray = gSky.mVOSkyp->mBumpSunDir; + LLVector3 moon_ray = gSky.getMoonDirection(); + LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; + + bump_s_primary_light_ray.load3((offset_multiple * s_scale * primary_light_ray).mV); + bump_t_primary_light_ray.load3((offset_multiple * t_scale * primary_light_ray).mV); + } + + U8 texgen = getTextureEntry()->getTexGen(); + if (rebuild_tcoord && texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { //planar texgen needs binormals + mVObjp->getVolume()->genBinormals(f); + } + + U8 tex_mode = 0; + + if (isState(TEXTURE_ANIM)) + { + LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; + tex_mode = vobj->mTexAnimMode; + + if (!tex_mode) + { + clearState(TEXTURE_ANIM); + } + else + { + os = ot = 0.f; + r = 0.f; + cos_ang = 1.f; + sin_ang = 0.f; + ms = mt = 1.f; + + do_xform = false; + } + + if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) + { //don't override texture transform during tc bake + tex_mode = 0; + } + } + + LLVector4a scalea; + scalea.load3(scale.mV); + + bool do_bump = bump_code && mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD1); + bool do_tex_mat = tex_mode && mTextureMatrix; + + if (!do_bump) + { //not in atlas or not bump mapped, might be able to do a cheap update + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); + + if (texgen != LLTextureEntry::TEX_GEN_PLANAR) + { + if (!do_tex_mat) + { + if (!do_xform) + { + tex_coords.assignArray((U8*) vf.mTexCoords, sizeof(vf.mTexCoords[0]), num_vertices); + } + else + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + *tex_coords++ = tc; + } + } + } + else + { //do tex mat, no texgen, no atlas, no bump + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + //LLVector4a& norm = vf.mNormals[i]; + //LLVector4a& center = *(vf.mCenter); + + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + *tex_coords++ = tc; + } + } + } + else + { //no bump, no atlas, tex gen planar + if (do_tex_mat) + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); + + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + + *tex_coords++ = tc; + } + } + else + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); + LLVector4a& norm = vf.mNormals[i]; + LLVector4a& center = *(vf.mCenter); + LLVector4a vec = vf.mPositions[i]; + vec.mul(scalea); + planarProjection(tc, norm, center, vec); + + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + + *tex_coords++ = tc; + } + } + } + + } + else + { //either bump mapped or in atlas, just do the whole expensive loop + mVertexBuffer->getTexCoord0Strider(tex_coords, mGeomIndex); + + std::vector<LLVector2> bump_tc; + + for (S32 i = 0; i < num_vertices; i++) + { + LLVector2 tc(vf.mTexCoords[i]); - if (rebuild_pos) - { - *vertices++ = vf.mVertices[i].mPosition * mat_vert; - } + LLVector4a& norm = vf.mNormals[i]; + + LLVector4a& center = *(vf.mCenter); + + if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { + LLVector4a vec = vf.mPositions[i]; + + vec.mul(scalea); + + switch (texgen) + { + case LLTextureEntry::TEX_GEN_PLANAR: + planarProjection(tc, norm, center, vec); + break; + case LLTextureEntry::TEX_GEN_SPHERICAL: + sphericalProjection(tc, norm, center, vec); + break; + case LLTextureEntry::TEX_GEN_CYLINDRICAL: + cylindricalProjection(tc, norm, center, vec); + break; + default: + break; + } + } + + if (tex_mode && mTextureMatrix) + { + LLVector3 tmp(tc.mV[0], tc.mV[1], 0.f); + tmp = tmp * *mTextureMatrix; + tc.mV[0] = tmp.mV[0]; + tc.mV[1] = tmp.mV[1]; + } + else + { + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + } + + + *tex_coords++ = tc; + if (do_bump) + { + bump_tc.push_back(tc); + } + } + + + if (do_bump) + { + mVertexBuffer->getTexCoord1Strider(tex_coords2, mGeomIndex); - if (rebuild_normal) - { - LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; - normal.normVec(); - - *normals++ = normal; + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a tangent; + tangent.setCross3(vf.mBinormals[i], vf.mNormals[i]); + + LLMatrix4a tangent_to_object; + tangent_to_object.setRows(tangent, vf.mBinormals[i], vf.mNormals[i]); + LLVector4a t; + tangent_to_object.rotate(binormal_dir, t); + LLVector4a binormal; + mat_normal.rotate(t, binormal); + + //VECTORIZE THIS + if (mDrawablep->isActive()) + { + LLVector3 t; + t.set(binormal.getF32ptr()); + t *= bump_quat; + binormal.load3(t.mV); + } + + binormal.normalize3fast(); + LLVector2 tc = bump_tc[i]; + tc += LLVector2( bump_s_primary_light_ray.dot3(tangent).getF32(), bump_t_primary_light_ray.dot3(binormal).getF32() ); + + *tex_coords2++ = tc; + } + + } } + } + + if (rebuild_pos) + { + llassert(num_vertices > 0); + mVertexBuffer->getVertexStrider(vert, mGeomIndex); + LLMatrix4a mat_vert; + mat_vert.loadu(mat_vert_in); - if (rebuild_binormal) + LLVector4a* src = vf.mPositions; + + if(!vert.isStrided()) { - LLVector3 binormal = vf.mVertices[i].mBinormal * mat_normal; - binormal.normVec(); - *binormals++ = binormal; + LLVector4a* vertices = (LLVector4a*) vert.get(); + + LLVector4a* dst = vertices; + + LLVector4a* end = dst+num_vertices; + do + { + mat_vert.affineTransform(*src++, *dst++); + } + while(dst < end); + + F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0); + F32 *index_dst = (F32*) vertices; + F32 *index_end = (F32*) end; + + index_dst += 3; + index_end += 3; + do + { + *index_dst = index; + index_dst += 4; + } + while (index_dst < index_end); + + S32 aligned_pad_vertices = mGeomCount - num_vertices; + LLVector4a* last_vec = end - 1; + while (aligned_pad_vertices > 0) + { + --aligned_pad_vertices; + *dst++ = *last_vec; + } + } - - if (rebuild_color) + else { - *colors++ = color; + LLVector4a position; + F32 index = (F32) (mTextureIndex < 255 ? mTextureIndex : 0); + for (S32 i = 0; i < num_vertices; i++) + { + mat_vert.affineTransform(src[i], position); + //Still using getF32ptr() because if the array is strided then theres no guarantee vertices will aligned, which LLVector4a requires + vert[i].set(position.getF32ptr()); //This assignment and the one below are oddly sensitive. Suspect something's off around here. + *(vert[i].mV+3) = index; + } + for (S32 i = num_vertices; i < mGeomCount; i++) + { + memcpy(vert[i].mV,vert[num_vertices-1].mV,sizeof(LLVector4)); + } + } + } + + if (rebuild_normal) + { + mVertexBuffer->getNormalStrider(norm, mGeomIndex); + if(!norm.isStrided()) + { + LLVector4a* normals = (LLVector4a*) norm.get(); + + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a normal; + mat_normal.rotate(vf.mNormals[i], normal); + normal.normalize3fast(); + normals[i] = normal; + } + } + else + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a normal; + mat_normal.rotate(vf.mNormals[i], normal); + normal.normalize3fast(); + norm[i].set(normal.getF32ptr()); + } + } + } + + if (rebuild_binormal) + { + mVertexBuffer->getBinormalStrider(binorm, mGeomIndex); + if(!binorm.isStrided()) + { + LLVector4a* binormals = (LLVector4a*) binorm.get(); + + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a binormal; + mat_normal.rotate(vf.mBinormals[i], binormal); + binormal.normalize3fast(); + binormals[i] = binormal; + } + } + else + { + for (S32 i = 0; i < num_vertices; i++) + { + LLVector4a binormal; + mat_normal.rotate(vf.mBinormals[i], binormal); + binormal.normalize3fast(); + binorm[i].set(binormal.getF32ptr()); + } + } + } + +#if MESH_ENABLED + if (rebuild_weights && vf.mWeights) + { + mVertexBuffer->getWeight4Strider(wght, mGeomIndex); + wght.assignArray((U8*) vf.mWeights, sizeof(vf.mWeights[0]), num_vertices); + } +#endif //MESH_ENABLED + + if (rebuild_color) + { + mVertexBuffer->getColorStrider(colors, mGeomIndex); + if(!colors.isStrided()) + { + LLVector4a src; + + U32 vec[4]; + vec[0] = vec[1] = vec[2] = vec[3] = color.mAll; + + src.loadua((F32*) vec); + + LLVector4a* dst = (LLVector4a*) colors.get(); + S32 num_vecs = num_vertices/4; + if (num_vertices%4 > 0) + { + ++num_vecs; + } + + for (S32 i = 0; i < num_vecs; i++) + { + dst[i] = src; + } + } + else + { + for (S32 i = 0; i < num_vertices; i++) + { + colors[i] = color; + } } } @@ -1314,7 +1649,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, mTexExtents[0].setVec(0,0); mTexExtents[1].setVec(1,1); xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt); - xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt); + xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt); F32 es = vf.mTexCoordExtents[1].mV[0] - vf.mTexCoordExtents[0].mV[0] ; F32 et = vf.mTexCoordExtents[1].mV[1] - vf.mTexCoordExtents[0].mV[1] ; @@ -1386,20 +1721,32 @@ F32 LLFace::getTextureVirtualSize() BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) { + //VECTORIZE THIS //get area of circle around face - LLVector3 center = getPositionAgent(); - LLVector3 size = (mExtents[1] - mExtents[0]) * 0.5f; + LLVector4a center; + center.load3(getPositionAgent().mV); + LLVector4a size; + size.setSub(mExtents[1], mExtents[0]); + size.mul(0.5f); + LLViewerCamera* camera = LLViewerCamera::getInstance(); - - F32 size_squared = size.lengthSquared() ; - LLVector3 lookAt = center - camera->getOrigin(); - F32 dist = lookAt.normVec() ; + + F32 size_squared = size.dot3(size).getF32(); + LLVector4a lookAt; + LLVector4a t; + t.load3(camera->getOrigin().mV); + lookAt.setSub(center, t); + F32 dist = lookAt.getLength3().getF32(); + dist = llmax(dist-size.getLength3().getF32(), 0.f); + lookAt.normalize3fast() ; //get area of circle around node - F32 app_angle = atanf(fsqrtf(size_squared) / dist); + F32 app_angle = atanf((F32) sqrt(size_squared) / dist); radius = app_angle*LLDrawable::sCurPixelAngle; mPixelArea = radius*radius * 3.14159f; - cos_angle_to_view_dir = lookAt * camera->getXAxis(); + LLVector4a x_axis; + x_axis.load3(camera->getXAxis().mV); + cos_angle_to_view_dir = lookAt.dot3(x_axis).getF32(); if(dist < mBoundingSphereRadius) //camera is very close { @@ -1417,7 +1764,7 @@ BOOL LLFace::calcPixelArea(F32& cos_angle_to_view_dir, F32& radius) //the projection of the face partially overlaps with the screen F32 LLFace::adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ) { - F32 screen_radius = (F32)llmax(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight()) ; + F32 screen_radius = (F32)llmax(gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw()) ; F32 center_angle = acosf(cos_angle_to_view_dir) ; F32 d = center_angle * LLDrawable::sCurPixelAngle ; @@ -1523,10 +1870,10 @@ BOOL LLFace::verify(const U32* indices_array) const } // First, check whether the face data fits within the pool's range. - if ((mGeomIndex + mGeomCount) > mVertexBuffer->getNumVerts()) + if ((mGeomIndex + mGeomCount) > mVertexBuffer->getRequestedVerts()) { ok = FALSE; - llinfos << "Face not within pool range!" << llendl; + llinfos << "Face references invalid vertices!" << llendl; } S32 indices_count = (S32)getIndicesCount(); @@ -1542,6 +1889,12 @@ BOOL LLFace::verify(const U32* indices_array) const llinfos << "Face has bogus indices count" << llendl; } + if (mIndicesIndex + mIndicesCount > (U32)mVertexBuffer->getRequestedIndices()) + { + ok = FALSE; + llinfos << "Face references invalid indices!" << llendl; + } + #if 0 S32 geom_start = getGeomStart(); S32 geom_count = mGeomCount; @@ -1709,3 +2062,71 @@ void LLFace::clearVertexBuffer() mLastVertexBuffer = NULL; } +#if MESH_ENABLED +//static +//do NOT screw the the order of these. Must match order of LLDrawPoolAvatar::eRiggedPass. Order differs from LL's. +U32 LLFace::getRiggedDataMask(U32 type) +{ + static const U32 rigged_data_mask[] = { + LLDrawPoolAvatar::RIGGED_SIMPLE_MASK, + LLDrawPoolAvatar::RIGGED_FULLBRIGHT_MASK, + LLDrawPoolAvatar::RIGGED_SHINY_MASK, + LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY_MASK, + //LLDrawPoolAvatar::RIGGED_GLOW_MASK, + LLDrawPoolAvatar::RIGGED_ALPHA_MASK, + LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA_MASK, + LLDrawPoolAvatar::RIGGED_GLOW_MASK, + //LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK, + LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_MASK, + LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP_MASK, + }; + + llassert(type < sizeof(rigged_data_mask)/sizeof(U32)); + + return rigged_data_mask[type]; +} + +U32 LLFace::getRiggedVertexBufferDataMask() const +{ + U32 data_mask = 0; + for (U32 i = 0; i < mRiggedIndex.size(); ++i) + { + if (mRiggedIndex[i] > -1) + { + data_mask |= LLFace::getRiggedDataMask(i); + } + } + + return data_mask; +} + +S32 LLFace::getRiggedIndex(U32 type) const +{ + if (mRiggedIndex.empty()) + { + return -1; + } + + llassert(type < mRiggedIndex.size()); + + return mRiggedIndex[type]; +} + +void LLFace::setRiggedIndex(U32 type, S32 index) +{ + if (mRiggedIndex.empty()) + { + mRiggedIndex.resize(LLDrawPoolAvatar::NUM_RIGGED_PASSES); + for (U32 i = 0; i < mRiggedIndex.size(); ++i) + { + mRiggedIndex[i] = -1; + } + } + + llassert(type < mRiggedIndex.size()); + + mRiggedIndex[type] = index; +} + + +#endif //MESH_ENABLED diff --git a/indra/newview/llface.h b/indra/newview/llface.h index edbf0bafd..2f77abbb0 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -83,6 +83,9 @@ public: HUD_RENDER = 0x0008, USE_FACE_COLOR = 0x0010, TEXTURE_ANIM = 0x0020, +#if MESH_ENABLED + RIGGED = 0x0040, +#endif //MESH_ENABLED }; static void initClass(); @@ -98,6 +101,8 @@ public: U16 getGeomCount() const { return mGeomCount; } // vertex count for this face U16 getGeomIndex() const { return mGeomIndex; } // index into draw pool U16 getGeomStart() const { return mGeomIndex; } // index into draw pool + void setTextureIndex(U8 index); + U8 getTextureIndex() const { return mTextureIndex; } void setTexture(LLViewerTexture* tex) ; void switchTexture(LLViewerTexture* new_texture); void dirtyTexture(); @@ -159,7 +164,8 @@ public: BOOL getGeometryVolume(const LLVolume& volume, const S32 &f, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, - const U16 &index_offset); + const U16 &index_offset, + bool force_rebuild = false); // For avatar U16 getGeometryAvatar( @@ -190,7 +196,6 @@ public: void updateCenterAgent(); // Update center when xform has changed. void renderSelectedUV(); - void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0); void renderSelected(LLViewerTexture *image, const LLColor4 &color); F32 getKey() const { return mDistance; } @@ -201,8 +206,8 @@ public: BOOL verify(const U32* indices_array = NULL) const; void printDebugInfo() const; - void setGeomIndex(U16 idx) { mGeomIndex = idx; } - void setIndicesIndex(S32 idx) { mIndicesIndex = idx; } + void setGeomIndex(U16 idx); + void setIndicesIndex(S32 idx); void setDrawInfo(LLDrawInfo* draw_info); F32 getTextureVirtualSize() ; @@ -211,6 +216,15 @@ public: void setVertexBuffer(LLVertexBuffer* buffer); void clearVertexBuffer(); //sets mVertexBuffer and mLastVertexBuffer to NULL LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; } +#if MESH_ENABLED + U32 getRiggedVertexBufferDataMask() const; + S32 getRiggedIndex(U32 type) const; + void setRiggedIndex(U32 type, S32 index); + + static U32 getRiggedDataMask(U32 type); +#endif //MESH_ENABLED +public: //aligned members + LLVector4a mExtents[2]; private: F32 adjustPartialOverlapPixelArea(F32 cos_angle_to_view_dir, F32 radius ); @@ -223,10 +237,12 @@ public: LLVector3 mCenterLocal; LLVector3 mCenterAgent; - LLVector3 mExtents[2]; LLVector2 mTexExtents[2]; F32 mDistance; F32 mLastUpdateTime; +#if MESH_ENABLED + F32 mLastSkinTime; +#endif //MESH_ENABLED F32 mLastMoveTime; LLMatrix4* mTextureMatrix; LLDrawInfo* mDrawInfo; @@ -245,6 +261,7 @@ private: U16 mGeomCount; // vertex count for this face U16 mGeomIndex; // index into draw pool + U8 mTextureIndex; // index of texture channel to use for pseudo-atlasing U32 mIndicesCount; U32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) S32 mIndexInTex ; @@ -262,6 +279,10 @@ private: S32 mTEOffset; S32 mReferenceIndex; +#if MESH_ENABLED + std::vector<S32> mRiggedIndex; +#endif //MESH_ENABLED + F32 mVSize; F32 mPixelArea; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index ab0868237..b981eb46d 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -127,6 +127,11 @@ static struct ft_display_info ft_display_table[] = { LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 }, { LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 1 }, { LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 }, +#if MESH_ENABLED + { LLFastTimer::FTM_UPDATE_RIGGED_VOLUME," Rigged", &LLColor4::red3, 0 }, + { LLFastTimer::FTM_SKIN_RIGGED, " Skin", &LLColor4::green1, 0 }, + { LLFastTimer::FTM_RIGGED_OCTREE, " Octree", &LLColor4::green5, 0 }, +#endif //MESH_ENABLED { LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 }, { LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 }, { LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 }, @@ -155,6 +160,12 @@ static struct ft_display_info ft_display_table[] = { LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 }, { LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable", &LLColor4::orange2, 0 }, { LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort", &LLColor4::orange3, 0 }, +#if MESH_ENABLED + { LLFastTimer::FTM_MESH_UPDATE, " Mesh Update", &LLColor4::orange4, 0 }, + { LLFastTimer::FTM_MESH_LOCK1, " Lock 1", &LLColor4::orange5, 0 }, + { LLFastTimer::FTM_MESH_LOCK2, " Lock 2", &LLColor4::orange6, 0 }, + { LLFastTimer::FTM_LOAD_MESH_LOD, " Load LOD", &LLColor4::yellow3, 0 }, +#endif //MESH_ENABLED { LLFastTimer::FTM_REBUILD_OCCLUSION_VB," Occlusion", &LLColor4::cyan5, 0 }, { LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild", &LLColor4::red4, 0 }, { LLFastTimer::FTM_REBUILD_VOLUME_VB, " Volume", &LLColor4::blue1, 0 }, @@ -233,7 +244,7 @@ static const int FTV_DISPLAY_NUM = LL_ARRAY_SIZE(ft_display_table); S32 ft_display_idx[FTV_DISPLAY_NUM]; // line of table entry for display purposes (for collapse) LLFastTimerView::LLFastTimerView(const std::string& name, const LLRect& rect) - : LLFloater(name, rect, std::string("Fast Timers")) + : LLFloater(name, rect, std::string(), FALSE, 1, 1, FALSE, FALSE, TRUE) { setVisible(FALSE); mDisplayMode = 0; @@ -320,6 +331,15 @@ S32 LLFastTimerView::getLegendIndex(S32 y) BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) { + { + S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft; + S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom; + if (mButtons[BUTTON_CLOSE]->getVisible() && + mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y)) + { + return LLFloater::handleMouseDown(x, y, mask); + } + } if (x < mBarRect.mLeft) { S32 legend_index = getLegendIndex(y); @@ -381,6 +401,15 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask) { + { + S32 local_x = x - mButtons[BUTTON_CLOSE]->getRect().mLeft; + S32 local_y = y - mButtons[BUTTON_CLOSE]->getRect().mBottom; + if (mButtons[BUTTON_CLOSE]->getVisible() && + mButtons[BUTTON_CLOSE]->pointInView(local_x, local_y)) + { + return LLFloater::handleMouseUp(x, y, mask); + } + } return FALSE; } @@ -429,6 +458,18 @@ BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks) return TRUE; } +void LLFastTimerView::onClose(bool app_quitting) +{ + if (app_quitting) + { + LLFloater::close(app_quitting); + } + else + { + setVisible(FALSE); + } +} + void LLFastTimerView::draw() { LLFastTimer t(LLFastTimer::FTM_RENDER_TIMER); @@ -442,8 +483,9 @@ void LLFastTimerView::draw() S32 height = (S32) (gViewerWindow->getVirtualWindowRect().getHeight()*0.75f); S32 width = (S32) (gViewerWindow->getVirtualWindowRect().getWidth() * 0.75f); - // HACK: casting away const. Should use setRect or some helper function instead. - const_cast<LLRect&>(getRect()).setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); + LLRect new_rect; + new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); + setRect(new_rect); S32 left, top, right, bottom; S32 x, y, barw, barh, dx, dy; @@ -591,11 +633,14 @@ void LLFastTimerView::draw() left = x; right = x + texth; top = y; bottom = y - texth; S32 scale_offset = 0; - if (i == mHoverIndex) + if (y > 3 * texth) { - scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f); + if (i == mHoverIndex) + { + scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f); + } + gl_rect_2d(left - scale_offset, top + scale_offset, right + scale_offset, bottom - scale_offset, *ft_display_table[i].color); } - gl_rect_2d(left - scale_offset, top + scale_offset, right + scale_offset, bottom - scale_offset, *ft_display_table[i].color); int tidx = ft_display_table[i].timer; F32 ms = 0; @@ -625,7 +670,7 @@ void LLFastTimerView::draw() dx = (texth+4) + level*8; LLColor4 color = disabled > 1 ? LLColor4::grey : LLColor4::white; - if (level > 0) + if (level > 0 && y > 3 * texth) { S32 line_start_y = (top + bottom) / 2; S32 line_end_y = line_start_y + ((texth + 2) * (display_line[i] - display_line[parent])) - (texth / 2); @@ -647,13 +692,16 @@ void LLFastTimerView::draw() next_parent = ft_display_table[next_parent].parent; } - if (is_child_of_hover_item) + if (y > 3 * texth) { - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD); - } - else - { - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP); + if (is_child_of_hover_item) + { + LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD); + } + else + { + LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP); + } } y -= (texth + 2); @@ -661,6 +709,11 @@ void LLFastTimerView::draw() if (textw > legendwidth) legendwidth = textw; } + if (y <= 3 * texth) + { + LLFontGL::getFontMonospace()->renderUTF8("<list truncated>", 0, 3 * texth, 2 * texth, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD); + } + for (S32 i=cur_line; i<FTV_DISPLAY_NUM; i++) { ft_display_idx[i] = -1; diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 86fc19461..b25a1da15 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -47,6 +47,7 @@ public: virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + virtual void onClose(bool app_quitting); virtual void draw(); S32 getLegendIndex(S32 y); diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp index 4c7cedf9b..d59167ddf 100644 --- a/indra/newview/llfirstuse.cpp +++ b/indra/newview/llfirstuse.cpp @@ -36,6 +36,8 @@ // library includes #include "indra_constants.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" // viewer includes #include "llagent.h" // for gAgent.inPrelude() @@ -94,7 +96,7 @@ void LLFirstUse::useBalanceIncrease(S32 delta) LLSD args; args["AMOUNT"] = llformat("%d",delta); args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); - LLNotifications::instance().add("FirstBalanceIncrease", args); + LLNotificationsUtil::add("FirstBalanceIncrease", args); } } @@ -109,7 +111,7 @@ void LLFirstUse::useBalanceDecrease(S32 delta) LLSD args; args["AMOUNT"] = llformat("%d",-delta); args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); - LLNotifications::instance().add("FirstBalanceDecrease", args); + LLNotificationsUtil::add("FirstBalanceDecrease", args); } } @@ -123,7 +125,7 @@ void LLFirstUse::useSit() //{ // gSavedSettings.setWarning("FirstSit", FALSE); // - // LLNotifications::instance().add("FirstSit"); + // LLNotificationsUtil::add("FirstSit"); //} } @@ -134,7 +136,7 @@ void LLFirstUse::useMap() { gSavedSettings.setWarning("FirstMap", FALSE); - LLNotifications::instance().add("FirstMap"); + LLNotificationsUtil::add("FirstMap"); } } @@ -151,7 +153,7 @@ void LLFirstUse::useBuild() { gSavedSettings.setWarning("FirstBuild", FALSE); - LLNotifications::instance().add("FirstBuild"); + LLNotificationsUtil::add("FirstBuild"); } } @@ -162,7 +164,7 @@ void LLFirstUse::useLeftClickNoHit() { gSavedSettings.setWarning("FirstLeftClickNoHit", FALSE); - LLNotifications::instance().add("FirstLeftClickNoHit"); + LLNotificationsUtil::add("FirstLeftClickNoHit"); } } @@ -176,7 +178,7 @@ void LLFirstUse::useTeleport() { gSavedSettings.setWarning("FirstTeleport", FALSE); - LLNotifications::instance().add("FirstTeleport"); + LLNotificationsUtil::add("FirstTeleport"); } } } @@ -192,7 +194,7 @@ void LLFirstUse::useOverrideKeys() { gSavedSettings.setWarning("FirstOverrideKeys", FALSE); - LLNotifications::instance().add("FirstOverrideKeys"); + LLNotificationsUtil::add("FirstOverrideKeys"); } } } @@ -210,7 +212,7 @@ void LLFirstUse::useAO() { gSavedSettings.setWarning("FirstAO", FALSE); - LLNotifications::instance().add("FirstAO"); + LLNotificationsUtil::add("FirstAO"); } } @@ -221,7 +223,7 @@ void LLFirstUse::useAppearance() { gSavedSettings.setWarning("FirstAppearance", FALSE); - LLNotifications::instance().add("FirstAppearance"); + LLNotificationsUtil::add("FirstAppearance"); } } @@ -232,7 +234,7 @@ void LLFirstUse::useInventory() { gSavedSettings.setWarning("FirstInventory", FALSE); - LLNotifications::instance().add("FirstInventory"); + LLNotificationsUtil::add("FirstInventory"); } } @@ -247,7 +249,7 @@ void LLFirstUse::useSandbox() LLSD args; args["HOURS"] = llformat("%d",SANDBOX_CLEAN_FREQ); args["TIME"] = llformat("%d",SANDBOX_FIRST_CLEAN_HOUR); - LLNotifications::instance().add("FirstSandbox", args); + LLNotificationsUtil::add("FirstSandbox", args); } } @@ -258,7 +260,7 @@ void LLFirstUse::useFlexible() { gSavedSettings.setWarning("FirstFlexible", FALSE); - LLNotifications::instance().add("FirstFlexible"); + LLNotificationsUtil::add("FirstFlexible"); } } @@ -269,7 +271,7 @@ void LLFirstUse::useDebugMenus() { gSavedSettings.setWarning("FirstDebugMenus", FALSE); - LLNotifications::instance().add("FirstDebugMenus"); + LLNotificationsUtil::add("FirstDebugMenus"); } } @@ -280,7 +282,7 @@ void LLFirstUse::useSculptedPrim() { gSavedSettings.setWarning("FirstSculptedPrim", FALSE); - LLNotifications::instance().add("FirstSculptedPrim"); + LLNotificationsUtil::add("FirstSculptedPrim"); } } @@ -292,7 +294,7 @@ void LLFirstUse::useMedia() { gSavedSettings.setWarning("FirstMedia", FALSE); - LLNotifications::instance().add("FirstMedia"); + LLNotificationsUtil::add("FirstMedia"); } } diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index 6ce035e5b..b5a87c2b3 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -94,11 +94,13 @@ void LLVolumeImplFlexible::onParameterChanged(U16 param_type, LLNetworkData *dat } } -void LLVolumeImplFlexible::onShift(const LLVector3 &shift_vector) +void LLVolumeImplFlexible::onShift(const LLVector4a &shift_vector) { + //VECTORIZE THIS + LLVector3 shift(shift_vector.getF32ptr()); for (int section = 0; section < (1<<FLEXIBLE_OBJECT_MAX_SECTIONS)+1; ++section) { - mSection[section].mPosition += shift_vector; + mSection[section].mPosition += shift; } } @@ -194,7 +196,6 @@ void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 so } } - //----------------------------------------------------------------------------- void LLVolumeImplFlexible::setAttributesOfAllSections(LLVector3* inScale) { diff --git a/indra/newview/llflexibleobject.h b/indra/newview/llflexibleobject.h index 895701da3..375658143 100644 --- a/indra/newview/llflexibleobject.h +++ b/indra/newview/llflexibleobject.h @@ -91,7 +91,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface void onSetVolume(const LLVolumeParams &volume_params, const S32 detail); void onSetScale(const LLVector3 &scale, BOOL damped); void onParameterChanged(U16 param_type, LLNetworkData *data, BOOL in_use, bool local_origin); - void onShift(const LLVector3 &shift_vector); + void onShift(const LLVector4a &shift_vector); bool isVolumeUnique() const { return true; } bool isVolumeGlobal() const { return true; } bool isActive() const { return true; } diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 952b5d168..0bd2ba83d 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -145,8 +145,7 @@ LLFloaterAbout::LLFloaterAbout() std::string support; support.append("\n\n"); - support.append("Grid: " + gHippoGridManager->getConnectedGrid()->getGridName() - + " (" + gHippoGridManager->getConnectedGrid()->getGridNick() + ")\n\n"); + support.append("Grid: " + gHippoGridManager->getConnectedGrid()->getGridName() + "\n\n"); #if LL_MSVC support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER)); diff --git a/indra/newview/llfloateractivespeakers.cpp b/indra/newview/llfloateractivespeakers.cpp index a641ac69d..27d35c6bb 100644 --- a/indra/newview/llfloateractivespeakers.cpp +++ b/indra/newview/llfloateractivespeakers.cpp @@ -91,7 +91,7 @@ LLSpeaker::LLSpeaker(const LLUUID& id, const std::string& name, const ESpeakerTy gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id)); - mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); + mActivityTimer.reset(SPEAKER_TIMEOUT); } @@ -1021,7 +1021,7 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin { // keep highest priority status (lowest value) instead of overriding current value speakerp->mStatus = llmin(speakerp->mStatus, status); - speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); + speakerp->mActivityTimer.reset(SPEAKER_TIMEOUT); // RN: due to a weird behavior where IMs from attached objects come from the wearer's agent_id // we need to override speakers that we think are objects when we find out they are really // residents @@ -1329,7 +1329,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) { speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; speakerp->mDotColor = INACTIVE_COLOR; - speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); + speakerp->mActivityTimer.reset(SPEAKER_TIMEOUT); } else if (agent_data["transition"].asString() == "ENTER") { @@ -1377,7 +1377,7 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update) { speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; speakerp->mDotColor = INACTIVE_COLOR; - speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); + speakerp->mActivityTimer.reset(SPEAKER_TIMEOUT); } else if ( agent_transition == "ENTER") { @@ -1476,7 +1476,7 @@ void LLLocalSpeakerMgr::updateSpeakerList() { speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL; speakerp->mDotColor = INACTIVE_COLOR; - speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT); + speakerp->mActivityTimer.reset(SPEAKER_TIMEOUT); } } } diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp index 2fcc7a135..73627253e 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloateranimpreview.cpp @@ -37,6 +37,7 @@ #include "llbvhloader.h" #include "lldatapacker.h" #include "lldir.h" +#include "llnotificationsutil.h" #include "llvfile.h" #include "llapr.h" #include "llstring.h" @@ -1444,7 +1445,7 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata) else { llwarns << "Failure writing animation data." << llendl; - LLNotifications::instance().add("WriteAnimationFail"); + LLNotificationsUtil::add("WriteAnimationFail"); } } diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp index fd886f10b..c4121fae9 100644 --- a/indra/newview/llfloaterauction.cpp +++ b/indra/newview/llfloaterauction.cpp @@ -41,10 +41,13 @@ #include "llparcel.h" #include "llvfile.h" #include "llvfs.h" +#include "llwindow.h" +#include "message.h" #include "llagent.h" #include "llcombobox.h" -#include "llnotify.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llviewertexturelist.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" @@ -238,7 +241,7 @@ void LLFloaterAuction::onClickOK(void* data) FALSE); self->getWindow()->incBusyCount(); - LLNotifications::instance().add("UploadingAuctionSnapshot"); + LLNotificationsUtil::add("UploadingAuctionSnapshot"); } LLMessageSystem* msg = gMessageSystem; @@ -277,13 +280,13 @@ void auction_tga_upload_done(const LLUUID& asset_id, void* user_data, S32 status if (0 == status) { - LLNotifications::instance().add("UploadWebSnapshotDone"); + LLNotificationsUtil::add("UploadWebSnapshotDone"); } else { LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("UploadAuctionSnapshotFail", args); + LLNotificationsUtil::add("UploadAuctionSnapshotFail", args); } } @@ -298,12 +301,12 @@ void auction_j2c_upload_done(const LLUUID& asset_id, void* user_data, S32 status if (0 == status) { - LLNotifications::instance().add("UploadSnapshotDone"); + LLNotificationsUtil::add("UploadSnapshotDone"); } else { LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("UploadAuctionSnapshotFail", args); + LLNotificationsUtil::add("UploadAuctionSnapshotFail", args); } } diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index 13a10a0f7..b02ca306d 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -22,9 +22,11 @@ #include "lluictrlfactory.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llscrolllistctrl.h" #include "llradiogroup.h" #include "llviewercontrol.h" +#include "llnotificationsutil.h" #include "llvoavatar.h" #include "llimview.h" @@ -59,6 +61,10 @@ #include "llviewermenu.h" //</edit> +// [RLVa:KB] +#include "rlvhandler.h" +// [/RLVa:KB] + /** * @brief How long to keep people who are gone in the list and in memory. */ @@ -229,23 +235,22 @@ void LLFloaterAvatarList::createInstance(bool visible) sInstance = new LLFloaterAvatarList(); LLUICtrlFactory::getInstance()->buildFloater(sInstance, "floater_radar.xml"); if(!visible) + { sInstance->setVisible(FALSE); + gSavedSettings.setBOOL("ShowRadar", FALSE); + } } //static void LLFloaterAvatarList::toggle(void*) { -#ifdef LL_RRINTERFACE_H //MK - if (gRRenabled && gAgent.mRRInterface.mContainsShownames) - { - if (sInstance && sInstance->getVisible()) - { - sInstance->close(false); - } - } -#endif //mk if (sInstance) { - if (sInstance->getVisible()) + if (sInstance->getVisible() +// [RLVa:KB] + || gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) +// [/RLVa:KB] + ) + { sInstance->close(false); } @@ -263,12 +268,10 @@ void LLFloaterAvatarList::toggle(void*) //static void LLFloaterAvatarList::showInstance() { -#ifdef LL_RRINTERFACE_H //MK - if (gRRenabled && gAgent.mRRInterface.mContainsShownames) - { +// [RLVa:KB] + if(gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) return; - } -#endif //mk +// [/RLVa:KB] if (sInstance) { if (!sInstance->getVisible()) @@ -454,12 +457,6 @@ void LLFloaterAvatarList::updateAvatarList() continue; } } -#ifdef LL_RRINTERFACE_H //MK - if (gRRenabled && gAgent.mRRInterface.mContainsShownames) - { - name = gAgent.mRRInterface.getDummyName(name); - } -#endif //mk if (avid.isNull()) { @@ -498,12 +495,6 @@ void LLFloaterAvatarList::updateAvatarList() //name = gCacheName->getDefaultName(); continue; //prevent (Loading...) } -#ifdef LL_RRINTERFACE_H //MK - if (gRRenabled && gAgent.mRRInterface.mContainsShownames) - { - name = gAgent.mRRInterface.getDummyName(name); - } -#endif //mk if (mAvatars.count(avid) > 0) { @@ -1284,7 +1275,7 @@ void LLFloaterAvatarList::sound_trigger_hook(LLMessageSystem* msg,void **) { LLSD args; args["MESSAGE"] = "An object owned by you has request the keys from your radar.\nWould you like to enable announcing keys to objects in the sim?"; - LLNotifications::instance().add("GenericAlertYesCancel", args, LLSD(), onConfirmRadarChatKeys); + LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(), onConfirmRadarChatKeys); } } } @@ -1512,7 +1503,7 @@ void LLFloaterAvatarList::onClickFreeze(void *userdata) LLSD args; LLSD payload; args["AVATAR_NAME"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames(); - LLNotifications::instance().add("FreezeAvatarFullname", args, payload, callbackFreeze); + LLNotificationsUtil::add("FreezeAvatarFullname", args, payload, callbackFreeze); } //static @@ -1521,7 +1512,7 @@ void LLFloaterAvatarList::onClickEject(void *userdata) LLSD args; LLSD payload; args["AVATAR_NAME"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames(); - LLNotifications::instance().add("EjectAvatarFullname", args, payload, callbackEject); + LLNotificationsUtil::add("EjectAvatarFullname", args, payload, callbackEject); } //static @@ -1560,7 +1551,7 @@ void LLFloaterAvatarList::onClickEjectFromEstate(void *userdata) LLSD args; LLSD payload; args["EVIL_USER"] = ((LLFloaterAvatarList*)userdata)->getSelectedNames(); - LLNotifications::instance().add("EstateKickUser", args, payload, callbackEjectFromEstate); + LLNotificationsUtil::add("EstateKickUser", args, payload, callbackEjectFromEstate); } //static diff --git a/indra/newview/llfloaterblacklist.cpp b/indra/newview/llfloaterblacklist.cpp index 65c64cce7..07c0a94cb 100644 --- a/indra/newview/llfloaterblacklist.cpp +++ b/indra/newview/llfloaterblacklist.cpp @@ -9,6 +9,7 @@ #include "llcheckboxctrl.h" #include "statemachine/aifilepicker.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llviewercontrol.h" #include "lldate.h" #include "llagent.h" diff --git a/indra/newview/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp index 3216a8de0..a79527456 100644 --- a/indra/newview/llfloaterbulkpermission.cpp +++ b/indra/newview/llfloaterbulkpermission.cpp @@ -35,6 +35,7 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterbulkpermission.h" #include "llfloaterperms.h" // for utilities +#include "llinventorydefines.h" #include "llagent.h" #include "llchat.h" #include "llviewerwindow.h" @@ -52,6 +53,7 @@ #include "llviewerstats.h" #include "lluictrlfactory.h" #include "llselectmgr.h" +#include "llnotificationsutil.h" #include "roles_constants.h" // for GP_OBJECT_MANIPULATE @@ -152,7 +154,7 @@ void LLFloaterBulkPermission::onApplyBtn(void* user_data) void LLFloaterBulkPermission::onHelpBtn(void* user_data) { - LLNotifications::instance().add("HelpBulkPermission"); + LLNotificationsUtil::add("HelpBulkPermission"); } void LLFloaterBulkPermission::onCloseBtn(void* user_data) diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index 49199fff2..b7de17cc6 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -43,7 +43,9 @@ #include "llagent.h" // for agent id #include "llalertdialog.h" #include "llinventorymodel.h" // for gInventory +#include "llinventorydefines.h" #include "llinventoryview.h" // for get_item_icon +#include "llnotificationsutil.h" #include "llselectmgr.h" #include "llscrolllistctrl.h" #include "llviewerobject.h" @@ -89,7 +91,7 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info) if (selection->getRootObjectCount() != 1) { - LLNotifications::instance().add("BuyOneObjectOnly"); + LLNotificationsUtil::add("BuyOneObjectOnly"); return; } @@ -139,7 +141,7 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info) BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); if (!owners_identical) { - LLNotifications::instance().add("BuyObjectOneOwner"); + LLNotificationsUtil::add("BuyObjectOneOwner"); return; } diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index f78ab995a..cb72659cb 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -46,7 +46,9 @@ #include "llalertdialog.h" #include "llcheckboxctrl.h" #include "llinventorymodel.h" // for gInventory +#include "llinventorydefines.h" #include "llinventoryview.h" // for get_item_icon +#include "llnotificationsutil.h" #include "llselectmgr.h" #include "llscrolllistctrl.h" #include "llviewerobject.h" @@ -86,7 +88,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info) if (selection->getRootObjectCount() != 1) { - LLNotifications::instance().add("BuyContentsOneOnly"); + LLNotificationsUtil::add("BuyContentsOneOnly"); return; } @@ -116,7 +118,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info) BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); if (!owners_identical) { - LLNotifications::instance().add("BuyContentsOneOwner"); + LLNotificationsUtil::add("BuyContentsOneOwner"); return; } diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 1340ad905..bd8cd5286 100644 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -47,7 +47,7 @@ #include "llframetimer.h" #include "lliconctrl.h" #include "lllineeditor.h" -#include "llnotify.h" +#include "llnotificationsutil.h" #include "llparcel.h" #include "llstatusbar.h" #include "lltextbox.h" @@ -215,7 +215,7 @@ void LLFloaterBuyLand::buyLand( { if(is_for_group && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED)) { - LLNotifications::instance().add("OnlyOfficerCanBuyLand"); + LLNotificationsUtil::add("OnlyOfficerCanBuyLand"); return; } @@ -334,9 +334,8 @@ LLFloaterBuyLandUI::LLFloaterBuyLandUI() LLFloaterBuyLandUI::~LLFloaterBuyLandUI() { + LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo); delete mTransaction; - - LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo); if (sInstance == this) { @@ -494,10 +493,18 @@ void LLFloaterBuyLandUI::updateParcelInfo() return; } - if (!authorizedBuyer.isNull() && buyer != authorizedBuyer) + if (!authorizedBuyer.isNull() && buyer != authorizedBuyer) { - mCannotBuyReason = getString("set_to_sell_to_other"); - return; + // Maybe the parcel is set for sale to a group we are in. + bool authorized_group = + gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_DEED) + && gAgent.hasPowerInGroup(authorizedBuyer,GP_LAND_SET_SALE_INFO); + + if (!authorized_group) + { + mCannotBuyReason = getString("set_to_sell_to_other"); + return; + } } } else @@ -807,7 +814,7 @@ void LLFloaterBuyLandUI::sendBuyLand() if (mParcelBuyInfo) { LLViewerParcelMgr::getInstance()->sendParcelBuy(mParcelBuyInfo); - LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo); + LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo); mBought = true; } } @@ -984,7 +991,7 @@ BOOL LLFloaterBuyLandUI::canClose() if (!can_close) { // explain to user why they can't do this, see DEV-9605 - LLNotifications::instance().add("CannotCloseFloaterBuyLand"); + LLNotificationsUtil::add("CannotCloseFloaterBuyLand"); } return can_close; } diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp index 133986dfa..eac5187f0 100644 --- a/indra/newview/llfloaterchat.cpp +++ b/indra/newview/llfloaterchat.cpp @@ -497,6 +497,10 @@ void LLFloaterChat::addChat(const LLChat& chat, //static void LLFloaterChat::triggerAlerts(const std::string& text) { + // Cannot instantiate LLTextParser before logging in. + if (gDirUtilp->getLindenUserDir(true).empty()) + return; + LLTextParser* parser = LLTextParser::getInstance(); // bool spoken=FALSE; for (S32 i=0;i<parser->mHighlights.size();i++) diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index 88d925490..717922394 100644 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -50,6 +50,7 @@ #include "llviewercontrol.h" #include "lluictrlfactory.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llgl.h" #include "llmemory.h" #include "llimage.h" @@ -203,7 +204,7 @@ showUI () { LLColor4 curCol = swatch->get (); send_agent_pause(); - gViewerWindow->getWindow ()->dialog_color_picker ( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] ); + gViewerWindow->getWindow()->dialogColorPicker( &curCol [ 0 ], &curCol [ 1 ], &curCol [ 2 ] ); send_agent_resume(); setOrigRgb ( curCol [ 0 ], curCol [ 1 ], curCol [ 2 ] ); diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp index 36853413c..b199cb939 100644 --- a/indra/newview/llfloatercustomize.cpp +++ b/indra/newview/llfloatercustomize.cpp @@ -75,6 +75,7 @@ #include "llviewermessage.h" #include "llviewercontrol.h" #include "lluictrlfactory.h" +#include "llnotificationsutil.h" #include "statemachine/aifilepicker.h" #include "hippogridmanager.h" @@ -708,7 +709,7 @@ void LLPanelEditWearable::onBtnCreateNew( void* userdata ) LLPanelEditWearable* self = (LLPanelEditWearable*) userdata; LLSD payload; payload["wearable_type"] = (S32)self->getType(); - LLNotifications::instance().add("AutoWearNewClothing", LLSD(), payload, &onSelectAutoWearOption); + LLNotificationsUtil::add("AutoWearNewClothing", LLSD(), payload, &onSelectAutoWearOption); } bool LLPanelEditWearable::onSelectAutoWearOption(const LLSD& notification, const LLSD& response) @@ -2723,7 +2724,7 @@ void LLFloaterCustomize::askToSaveIfDirty( void(*next_step_callback)(BOOL procee mNextStepAfterSaveUserdata = userdata; // Bring up view-modal dialog: Save changes? Yes, No, Cancel - LLNotifications::instance().add("SaveClothingBodyChanges", LLSD(), LLSD(), + LLNotificationsUtil::add("SaveClothingBodyChanges", LLSD(), LLSD(), boost::bind(&LLFloaterCustomize::onSaveDialog, this, _1, _2)); return; } diff --git a/indra/newview/llfloaterdaycycle.cpp b/indra/newview/llfloaterdaycycle.cpp index 07106e6b1..0799ca330 100644 --- a/indra/newview/llfloaterdaycycle.cpp +++ b/indra/newview/llfloaterdaycycle.cpp @@ -41,6 +41,8 @@ #include "llsliderctrl.h" #include "llmultislider.h" #include "llmultisliderctrl.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llspinctrl.h" #include "llcheckboxctrl.h" #include "lluictrlfactory.h" @@ -77,9 +79,9 @@ LLFloaterDayCycle::LLFloaterDayCycle() : LLFloater(std::string("Day Cycle Floate if(keyCombo != NULL) { - std::map<std::string, LLWLParamSet>::iterator mIt = - LLWLParamManager::instance()->mParamList.begin(); - for(; mIt != LLWLParamManager::instance()->mParamList.end(); mIt++) + std::map<std::string, LLWLParamSet>::const_iterator mIt = + LLWLParamManager::getInstance()->getPresets().begin(); + for(; mIt != LLWLParamManager::getInstance()->getPresets().end(); mIt++) { keyCombo->add(std::string(mIt->first)); } @@ -181,11 +183,11 @@ void LLFloaterDayCycle::initCallbacks(void) void LLFloaterDayCycle::syncMenu() { -// std::map<std::string, LLVector4> & currentParams = LLWLParamManager::instance()->mCurParams.mParamValues; +// std::map<std::string, LLVector4> & currentParams = LLWLParamManager::getInstance()->mCurParams.mParamValues; // set time LLMultiSliderCtrl* sldr = LLFloaterDayCycle::sDayCycle->getChild<LLMultiSliderCtrl>("WLTimeSlider"); - sldr->setCurSliderValue((F32)LLWLParamManager::instance()->mAnimator.getDayTime() * sHoursPerDay); + sldr->setCurSliderValue((F32)LLWLParamManager::getInstance()->mAnimator.getDayTime() * sHoursPerDay); LLSpinCtrl* secSpin = sDayCycle->getChild<LLSpinCtrl>("WLLengthOfDaySec"); LLSpinCtrl* minSpin = sDayCycle->getChild<LLSpinCtrl>("WLLengthOfDayMin"); @@ -195,7 +197,7 @@ void LLFloaterDayCycle::syncMenu() F32 hours, min, sec; // get the current rate - curRate = LLWLParamManager::instance()->mDay.mDayRate; + curRate = LLWLParamManager::getInstance()->mDay.mDayRate; hours = (F32)((int)(curRate / 60 / 60)); curRate -= (hours * 60 * 60); min = (F32)((int)(curRate / 60)); @@ -207,7 +209,7 @@ void LLFloaterDayCycle::syncMenu() secSpin->setValue(sec); // turn off Use Estate Time button if it's already being used - if( LLWLParamManager::instance()->mAnimator.mUseLindenTime == true) + if( LLWLParamManager::getInstance()->mAnimator.mUseLindenTime == true) { LLFloaterDayCycle::sDayCycle->childDisable("WLUseLindenTime"); } @@ -227,8 +229,8 @@ void LLFloaterDayCycle::syncSliderTrack() // add sliders std::map<F32, std::string>::iterator mIt = - LLWLParamManager::instance()->mDay.mTimeMap.begin(); - for(; mIt != LLWLParamManager::instance()->mDay.mTimeMap.end(); mIt++) + LLWLParamManager::getInstance()->mDay.mTimeMap.begin(); + for(; mIt != LLWLParamManager::getInstance()->mDay.mTimeMap.end(); mIt++) { addSliderKey(mIt->first * sHoursPerDay, mIt->second); } @@ -252,22 +254,22 @@ void LLFloaterDayCycle::syncTrack() "WLTimeSlider"); // create a new animation track - LLWLParamManager::instance()->mDay.clearKeys(); + LLWLParamManager::getInstance()->mDay.clearKeys(); // add the keys one by one std::map<std::string, LLWLSkyKey>::iterator mIt = sSliderToKey.begin(); for(; mIt != sSliderToKey.end(); mIt++) { - LLWLParamManager::instance()->mDay.addKey(mIt->second.time / sHoursPerDay, + LLWLParamManager::getInstance()->mDay.addKey(mIt->second.time / sHoursPerDay, mIt->second.presetName); } // set the param manager's track to the new one - LLWLParamManager::instance()->resetAnimator( + LLWLParamManager::getInstance()->resetAnimator( tSldr->getCurSliderValue() / sHoursPerDay, false); - LLWLParamManager::instance()->mAnimator.update( - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->mAnimator.update( + LLWLParamManager::getInstance()->mCurParams); } // static @@ -315,7 +317,7 @@ void LLFloaterDayCycle::onClose(bool app_quitting) void LLFloaterDayCycle::onNewPreset(void* userData) { - LLNotifications::instance().add("NewDaycyclePreset", LLSD(), LLSD(), newPromptCallback); + LLNotificationsUtil::add("NewDaycyclePreset", LLSD(), LLSD(), newPromptCallback); } void LLFloaterDayCycle::onSavePreset(void* userData) @@ -335,14 +337,14 @@ void LLFloaterDayCycle::onSavePreset(void* userData) comboBox->getSelectedItemLabel()); if(sIt != sDefaultPresets.end() && !gSavedSettings.getBOOL("SkyEditPresets")) { - LLNotifications::instance().add("WLNoEditDefault"); + LLNotificationsUtil::add("WLNoEditDefault"); return; } - LLWLParamManager::instance()->mCurParams.mName = + LLWLParamManager::getInstance()->mCurParams.mName = comboBox->getSelectedItemLabel(); - LLNotifications::instance().add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback); + LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback); } bool LLFloaterDayCycle::saveAlertCallback(const LLSD& notification, const LLSD& response) @@ -353,7 +355,7 @@ bool LLFloaterDayCycle::saveAlertCallback(const LLSD& notification, const LLSD& { LLComboBox* combo_box = sDayCycle->getChild<LLComboBox>("DayCyclePresetsCombo"); // comment this back in to save to file - LLWLParamManager::instance()->mDay.saveDayCycle(combo_box->getSelectedValue().asString()); + LLWLParamManager::getInstance()->mDay.saveDayCycle(combo_box->getSelectedValue().asString()); } return false; } @@ -370,7 +372,7 @@ void LLFloaterDayCycle::onDeletePreset(void* userData) LLSD args; args["SKY"] = combo_box->getSelectedValue().asString(); - LLNotifications::instance().add("WLDeletePresetAlert", args, LLSD(), + LLNotificationsUtil::add("WLDeletePresetAlert", args, LLSD(), boost::bind(&LLFloaterDayCycle::deleteAlertCallback, sDayCycle, _1, _2)); } @@ -401,7 +403,7 @@ bool LLFloaterDayCycle::deleteAlertCallback(const LLSD& notification, const LLSD std::set<std::string>::iterator sIt = sDefaultPresets.find(name); if(sIt != sDefaultPresets.end()) { - LLNotifications::instance().add("WLNoEditDefault"); + LLNotificationsUtil::add("WLNoEditDefault"); return false; } @@ -483,13 +485,13 @@ bool LLFloaterDayCycle::newPromptCallback(const LLSD& notification, const LLSD& keyCombo->add(text); keyCombo->sortByName(); } - LLWLParamManager::instance()->mDay.saveDayCycle(text); + LLWLParamManager::getInstance()->mDay.saveDayCycle(text); // otherwise, send a message to the user } else { - LLNotifications::instance().add("ExistsSkyPresetAlert"); + LLNotificationsUtil::add("ExistsSkyPresetAlert"); } } return false; @@ -505,7 +507,7 @@ void LLFloaterDayCycle::onChangePresetName(LLUICtrl* ctrl, void * userData) return; } - LLWLParamManager::instance()->mDay.loadDayCycle(combo_box->getSelectedValue().asString()); + LLWLParamManager::getInstance()->mDay.loadDayCycle(combo_box->getSelectedValue().asString()); gSavedSettings.setString("AscentActiveDayCycle", combo_box->getSelectedValue().asString()); // sync it all up syncSliderTrack(); @@ -515,12 +517,12 @@ void LLFloaterDayCycle::onChangePresetName(LLUICtrl* ctrl, void * userData) LLMultiSliderCtrl* tSldr; tSldr = sDayCycle->getChild<LLMultiSliderCtrl>( "WLTimeSlider"); - LLWLParamManager::instance()->resetAnimator( + LLWLParamManager::getInstance()->resetAnimator( tSldr->getCurSliderValue() / sHoursPerDay, false); // and draw it - LLWLParamManager::instance()->mAnimator.update( - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->mAnimator.update( + LLWLParamManager::getInstance()->mCurParams); } void LLFloaterDayCycle::onRunAnimSky(void* userData) @@ -539,13 +541,13 @@ void LLFloaterDayCycle::onRunAnimSky(void* userData) tSldr = sDayCycle->getChild<LLMultiSliderCtrl>("WLTimeSlider"); // turn off linden time - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; // set the param manager's track to the new one - LLWLParamManager::instance()->resetAnimator( + LLWLParamManager::getInstance()->resetAnimator( tSldr->getCurSliderValue() / sHoursPerDay, true); - llassert_always(LLWLParamManager::instance()->mAnimator.mTimeTrack.size() == sldr->getValue().size()); + llassert_always(LLWLParamManager::getInstance()->mAnimator.mTimeTrack.size() == sldr->getValue().size()); } void LLFloaterDayCycle::onStopAnimSky(void* userData) @@ -556,8 +558,8 @@ void LLFloaterDayCycle::onStopAnimSky(void* userData) } // turn off animation and using linden time - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; } void LLFloaterDayCycle::onUseLindenTime(void* userData) @@ -566,13 +568,13 @@ void LLFloaterDayCycle::onUseLindenTime(void* userData) LLComboBox* box = dc->getChild<LLComboBox>("DayCyclePresetsCombo"); box->selectByValue(""); - LLWLParamManager::instance()->mAnimator.mIsRunning = true; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = true; + LLWLParamManager::getInstance()->mAnimator.mIsRunning = true; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = true; } void LLFloaterDayCycle::onLoadDayCycle(void* userData) { - //LLWLParamManager::instance()->mDay.loadDayCycle("Default.xml"); + //LLWLParamManager::getInstance()->mDay.loadDayCycle("Default.xml"); // sync it all up syncSliderTrack(); @@ -582,17 +584,17 @@ void LLFloaterDayCycle::onLoadDayCycle(void* userData) LLMultiSliderCtrl* tSldr; tSldr = sDayCycle->getChild<LLMultiSliderCtrl>( "WLTimeSlider"); - LLWLParamManager::instance()->resetAnimator( + LLWLParamManager::getInstance()->resetAnimator( tSldr->getCurSliderValue() / sHoursPerDay, false); // and draw it - LLWLParamManager::instance()->mAnimator.update( - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->mAnimator.update( + LLWLParamManager::getInstance()->mCurParams); } void LLFloaterDayCycle::onSaveDayCycle(void* userData) { - //LLWLParamManager::instance()->mDay.saveDayCycle("Default.xml"); + //LLWLParamManager::getInstance()->mDay.saveDayCycle("Default.xml"); } @@ -605,13 +607,13 @@ void LLFloaterDayCycle::onTimeSliderMoved(LLUICtrl* ctrl, void* userData) F32 val = sldr->getCurSliderValue() / sHoursPerDay; // set the value, turn off animation - LLWLParamManager::instance()->mAnimator.setDayTime((F64)val); - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.setDayTime((F64)val); + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; // then call update once - LLWLParamManager::instance()->mAnimator.update( - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->mAnimator.update( + LLWLParamManager::getInstance()->mCurParams); } void LLFloaterDayCycle::onKeyTimeMoved(LLUICtrl* ctrl, void* userData) @@ -736,7 +738,7 @@ void LLFloaterDayCycle::onTimeRateChanged(LLUICtrl* ctrl, void* userData) if(time <= 0) { time = 1; } - LLWLParamManager::instance()->mDay.mDayRate = time; + LLWLParamManager::getInstance()->mDay.mDayRate = time; syncTrack(); } diff --git a/indra/newview/llfloaterdisplayname.cpp b/indra/newview/llfloaterdisplayname.cpp index 25d103c61..1eb0ca856 100644 --- a/indra/newview/llfloaterdisplayname.cpp +++ b/indra/newview/llfloaterdisplayname.cpp @@ -29,7 +29,7 @@ #include "llviewerprecompiledheaders.h" #include "llfloater.h" -#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llviewerdisplayname.h" #include "llnotify.h" @@ -152,7 +152,7 @@ void LLFloaterDisplayName::onCacheSetName(bool success, // to percolate. LLSD args; args["DISPLAY_NAME"] = content["display_name"]; - LLNotifications::instance().add("SetDisplayNameSuccess", args); + LLNotificationsUtil::add("SetDisplayNameSuccess", args); // Re-fetch my name, as it may have been sanitized by the service //LLAvatarNameCache::get(getAvatarId(), @@ -180,12 +180,12 @@ void LLFloaterDisplayName::onCacheSetName(bool success, { LLSD args; args["MESSAGE"] = error_desc[lang_code].asString(); - LLNotifications::instance().add("GenericAlert", args); + LLNotificationsUtil::add("GenericAlert", args); return; } // No specific error, throw a generic one - LLNotifications::instance().add("SetDisplayNameFailedGeneric"); + LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); } void LLFloaterDisplayName::onCancel(void* data) @@ -204,7 +204,7 @@ void LLFloaterDisplayName::onReset(void* data) } else { - LLNotifications::instance().add("SetDisplayNameFailedGeneric"); + LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); } self->setVisible(false); @@ -219,7 +219,7 @@ void LLFloaterDisplayName::onSave(void* data) if (display_name_utf8.compare(display_name_confirm)) { - LLNotifications::instance().add("SetDisplayNameMismatch"); + LLNotificationsUtil::add("SetDisplayNameMismatch"); return; } @@ -229,7 +229,7 @@ void LLFloaterDisplayName::onSave(void* data) { LLSD args; args["LENGTH"] = llformat("%d", DISPLAY_NAME_MAX_LENGTH); - LLNotifications::instance().add("SetDisplayNameFailedLength", args); + LLNotificationsUtil::add("SetDisplayNameFailedLength", args); return; } @@ -240,7 +240,7 @@ void LLFloaterDisplayName::onSave(void* data) } else { - LLNotifications::instance().add("SetDisplayNameFailedGeneric"); + LLNotificationsUtil::add("SetDisplayNameFailedGeneric"); } self->setVisible(false); diff --git a/indra/newview/llfloaterenvsettings.cpp b/indra/newview/llfloaterenvsettings.cpp index 6a55b8598..196cf92b7 100644 --- a/indra/newview/llfloaterenvsettings.cpp +++ b/indra/newview/llfloaterenvsettings.cpp @@ -79,11 +79,11 @@ void LLFloaterEnvSettings::initCallbacks(void) childSetCommitCallback("EnvTimeSlider", onChangeDayTime, NULL); childSetCommitCallback("EnvCloudSlider", onChangeCloudCoverage, NULL); childSetCommitCallback("EnvWaterFogSlider", onChangeWaterFogDensity, - &LLWaterParamManager::instance()->mFogDensity); + &LLWaterParamManager::getInstance()->mFogDensity); // color picker childSetCommitCallback("EnvWaterColor", onChangeWaterColor, - &LLWaterParamManager::instance()->mFogColor); + &LLWaterParamManager::getInstance()->mFogColor); // WL Top childSetAction("EnvAdvancedSkyButton", onOpenAdvancedSky, NULL); @@ -102,7 +102,7 @@ void LLFloaterEnvSettings::syncMenu() sldr = sEnvSettings->getChild<LLSliderCtrl>("EnvTimeSlider"); // sync the clock - F32 val = (F32)LLWLParamManager::instance()->mAnimator.getDayTime(); + F32 val = (F32)LLWLParamManager::getInstance()->mAnimator.getDayTime(); std::string timeStr = timeToString(val); LLTextBox* textBox; @@ -120,9 +120,9 @@ void LLFloaterEnvSettings::syncMenu() // sync cloud coverage bool err; - childSetValue("EnvCloudSlider", LLWLParamManager::instance()->mCurParams.getFloat("cloud_shadow", err)); + childSetValue("EnvCloudSlider", LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_shadow", err)); - LLWaterParamManager * param_mgr = LLWaterParamManager::instance(); + LLWaterParamManager * param_mgr = LLWaterParamManager::getInstance(); // sync water params LLColor4 col = param_mgr->getFogColor(); LLColorSwatchCtrl* colCtrl = sEnvSettings->getChild<LLColorSwatchCtrl>("EnvWaterColor"); @@ -133,7 +133,7 @@ void LLFloaterEnvSettings::syncMenu() param_mgr->setDensitySliderValue(param_mgr->mFogDensity.mExp); // turn off Use Estate Time button if it's already being used - if(LLWLParamManager::instance()->mAnimator.mUseLindenTime) + if(LLWLParamManager::getInstance()->mAnimator.mUseLindenTime) { childDisable("EnvUseEstateTimeButton"); } else { @@ -218,8 +218,8 @@ void LLFloaterEnvSettings::onChangeDayTime(LLUICtrl* ctrl, void* userData) sldr = sEnvSettings->getChild<LLSliderCtrl>("EnvTimeSlider"); // deactivate animator - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; F32 val = sldr->getValueF32() + 0.25f; if(val > 1.0) @@ -227,9 +227,9 @@ void LLFloaterEnvSettings::onChangeDayTime(LLUICtrl* ctrl, void* userData) val--; } - LLWLParamManager::instance()->mAnimator.setDayTime((F64)val); - LLWLParamManager::instance()->mAnimator.update( - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->mAnimator.setDayTime((F64)val); + LLWLParamManager::getInstance()->mAnimator.update( + LLWLParamManager::getInstance()->mCurParams); } void LLFloaterEnvSettings::onChangeCloudCoverage(LLUICtrl* ctrl, void* userData) @@ -238,11 +238,11 @@ void LLFloaterEnvSettings::onChangeCloudCoverage(LLUICtrl* ctrl, void* userData) sldr = sEnvSettings->getChild<LLSliderCtrl>("EnvCloudSlider"); // deactivate animator - //LLWLParamManager::instance()->mAnimator.mIsRunning = false; - //LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + //LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + //LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; F32 val = sldr->getValueF32(); - LLWLParamManager::instance()->mCurParams.set("cloud_shadow", val); + LLWLParamManager::getInstance()->mCurParams.set("cloud_shadow", val); } void LLFloaterEnvSettings::onChangeWaterFogDensity(LLUICtrl* ctrl, void* userData) @@ -259,10 +259,10 @@ void LLFloaterEnvSettings::onChangeWaterFogDensity(LLUICtrl* ctrl, void* userDat F32 val = sldr->getValueF32(); expFloatControl->mExp = val; - LLWaterParamManager::instance()->setDensitySliderValue(val); + LLWaterParamManager::getInstance()->setDensitySliderValue(val); - expFloatControl->update(LLWaterParamManager::instance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + expFloatControl->update(LLWaterParamManager::getInstance()->mCurParams); + LLWaterParamManager::getInstance()->propagateParameters(); } void LLFloaterEnvSettings::onChangeWaterColor(LLUICtrl* ctrl, void* userData) @@ -271,8 +271,8 @@ void LLFloaterEnvSettings::onChangeWaterColor(LLUICtrl* ctrl, void* userData) WaterColorControl * colorControl = static_cast<WaterColorControl *>(userData); *colorControl = swatch->get(); - colorControl->update(LLWaterParamManager::instance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + colorControl->update(LLWaterParamManager::getInstance()->mCurParams); + LLWaterParamManager::getInstance()->propagateParameters(); } @@ -290,7 +290,7 @@ void LLFloaterEnvSettings::onSubmitWindlight(void* userData) { Meta7WindlightPacket * wl = new Meta7WindlightPacket(); - LLWaterParamManager * param_mgr = LLWaterParamManager::instance(); + LLWaterParamManager * param_mgr = LLWaterParamManager::getInstance(); wl->reflectionWaveletScale.X = param_mgr->mNormalScale.mX; wl->reflectionWaveletScale.Y = param_mgr->mNormalScale.mY; wl->reflectionWaveletScale.Z = param_mgr->mNormalScale.mZ; @@ -311,8 +311,8 @@ void LLFloaterEnvSettings::onUseEstateTime(void* userData) box->selectByValue(""); } - LLWLParamManager::instance()->mAnimator.mIsRunning = true; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = true; + LLWLParamManager::getInstance()->mAnimator.mIsRunning = true; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = true; } std::string LLFloaterEnvSettings::timeToString(F32 curTime) diff --git a/indra/newview/llfloaterfriends.cpp b/indra/newview/llfloaterfriends.cpp index 608078119..03eaa4ac5 100644 --- a/indra/newview/llfloaterfriends.cpp +++ b/indra/newview/llfloaterfriends.cpp @@ -55,7 +55,7 @@ #include "llfloateravatarinfo.h" #include "llinventorymodel.h" #include "llnamelistctrl.h" -#include "llnotify.h" +#include "llnotificationsutil.h" #include "llresmgr.h" #include "llimview.h" #include "lluictrlfactory.h" @@ -820,7 +820,7 @@ void LLPanelFriends::onMaximumSelect(void* user_data) { LLSD args; args["MAX_SELECT"] = llformat("%d", MAX_FRIEND_SELECT); - LLNotifications::instance().add("MaxListSelectMessage", args); + LLNotificationsUtil::add("MaxListSelectMessage", args); }; // static @@ -942,7 +942,7 @@ void LLPanelFriends::requestFriendship(const LLUUID& target_id, const std::strin // static bool LLPanelFriends::callbackAddFriendWithMessage(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { requestFriendship(notification["payload"]["id"].asUUID(), @@ -985,7 +985,7 @@ void LLPanelFriends::requestFriendshipDialog(const LLUUID& id, { if(id == gAgentID) { - LLNotifications::instance().add("AddSelfFriend"); + LLNotificationsUtil::add("AddSelfFriend"); return; } @@ -999,11 +999,11 @@ void LLPanelFriends::requestFriendshipDialog(const LLUUID& id, { // Old and busted server version, doesn't support friend // requests with messages. - LLNotifications::instance().add("AddFriend", args, payload, &callbackAddFriend); + LLNotificationsUtil::add("AddFriend", args, payload, &callbackAddFriend); } else { - LLNotifications::instance().add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage); + LLNotificationsUtil::add("AddFriendWithMessage", args, payload, &callbackAddFriendWithMessage); } } @@ -1325,14 +1325,14 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command if (command == GRANT) { - LLNotifications::instance().add("GrantModifyRights", + LLNotificationsUtil::add("GrantModifyRights", args, LLSD(), boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights)); } else { - LLNotifications::instance().add("RevokeModifyRights", + LLNotificationsUtil::add("RevokeModifyRights", args, LLSD(), boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights)); @@ -1342,14 +1342,14 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command { if (command == GRANT) { - LLNotifications::instance().add("GrantModifyRightsMultiple", + LLNotificationsUtil::add("GrantModifyRightsMultiple", args, LLSD(), boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights)); } else { - LLNotifications::instance().add("RevokeModifyRightsMultiple", + LLNotificationsUtil::add("RevokeModifyRightsMultiple", args, LLSD(), boost::bind(&LLPanelFriends::modifyRightsConfirmation, this, _1, _2, rights)); @@ -1360,7 +1360,7 @@ void LLPanelFriends::confirmModifyRights(rights_map_t& ids, EGrantRevoke command bool LLPanelFriends::modifyRightsConfirmation(const LLSD& notification, const LLSD& response, rights_map_t* rights) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if(0 == option) { sendRightsGrant(*rights); @@ -1504,7 +1504,7 @@ void LLPanelFriends::sendRightsGrant(rights_map_t& ids) // static bool LLPanelFriends::handleRemove(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); const LLSD& ids = notification["payload"]["ids"]; for(LLSD::array_const_iterator itr = ids.beginArray(); itr != ids.endArray(); ++itr) diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp index cf641e0ea..78d7a6b28 100644 --- a/indra/newview/llfloatergesture.cpp +++ b/indra/newview/llfloatergesture.cpp @@ -86,13 +86,13 @@ LLFloaterGesture::LLFloaterGesture() sInstance = this; sObserver = new LLFloaterGestureObserver; - gGestureManager.addObserver(sObserver); + LLGestureMgr::instance().addObserver(sObserver); } // virtual LLFloaterGesture::~LLFloaterGesture() { - gGestureManager.removeObserver(sObserver); + LLGestureMgr::instance().removeObserver(sObserver); delete sObserver; sObserver = NULL; @@ -223,8 +223,8 @@ void LLFloaterGesture::buildGestureList() list->operateOnAll(LLCtrlListInterface::OP_DELETE); - LLGestureManager::item_map_t::iterator it; - for (it = gGestureManager.mActive.begin(); it != gGestureManager.mActive.end(); ++it) + LLGestureMgr::item_map_t::const_iterator it; + for (it = LLGestureMgr::instance().getActiveGestures().begin(); it != LLGestureMgr::instance().getActiveGestures().end(); ++it) { const LLUUID& item_id = (*it).first; LLMultiGesture* gesture = (*it).second; @@ -344,13 +344,13 @@ void LLFloaterGesture::onClickPlay(void* data) if (!list) return; const LLUUID& item_id = list->getCurrentID(); - if (gGestureManager.isGesturePlaying(item_id)) + if (LLGestureMgr::instance().isGesturePlaying(item_id)) { - gGestureManager.stopGesture(item_id); + LLGestureMgr::instance().stopGesture(item_id); } else { - gGestureManager.playGesture(item_id); + LLGestureMgr::instance().playGesture(item_id); } } @@ -411,7 +411,7 @@ void LLFloaterGesture::onCommitList(LLUICtrl* ctrl, void* data) const LLUUID& item_id = self->childGetValue("gesture_list").asUUID(); self->mSelectedID = item_id; - if (gGestureManager.isGesturePlaying(item_id)) + if (LLGestureMgr::instance().isGesturePlaying(item_id)) { self->childSetVisible("play_btn", false); self->childSetVisible("stop_btn", true); diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp index f918e8a46..9eff1a2c4 100644 --- a/indra/newview/llfloatergodtools.cpp +++ b/indra/newview/llfloatergodtools.cpp @@ -39,6 +39,7 @@ #include "llframetimer.h" #include "llgl.h" #include "llhost.h" +#include "llnotificationsutil.h" #include "llregionflags.h" #include "llstring.h" #include "message.h" @@ -931,7 +932,7 @@ void LLPanelGridTools::onClickKickAll(void* userdata) gFloaterView->getNewFloaterPosition(&left, &top); LLRect rect(left, top, left+400, top-300); - LLNotifications::instance().add("KickAllUsers", LLSD(), LLSD(), LLPanelGridTools::confirmKick); + LLNotificationsUtil::add("KickAllUsers", LLSD(), LLSD(), LLPanelGridTools::confirmKick); } @@ -941,7 +942,7 @@ bool LLPanelGridTools::confirmKick(const LLSD& notification, const LLSD& respons { LLSD payload; payload["kick_message"] = response["message"].asString(); - LLNotifications::instance().add("ConfirmKick", LLSD(), payload, LLPanelGridTools::finishKick); + LLNotificationsUtil::add("ConfirmKick", LLSD(), payload, LLPanelGridTools::finishKick); } return false; } @@ -973,7 +974,7 @@ bool LLPanelGridTools::finishKick(const LLSD& notification, const LLSD& response // static void LLPanelGridTools::onClickFlushMapVisibilityCaches(void* data) { - LLNotifications::instance().add("FlushMapVisibilityCaches", LLSD(), LLSD(), flushMapVisibilityCachesConfirm); + LLNotificationsUtil::add("FlushMapVisibilityCaches", LLSD(), LLSD(), flushMapVisibilityCachesConfirm); } // static @@ -1435,7 +1436,7 @@ void LLPanelRequestTools::onClickRequest(void* data) void terrain_download_done(void** data, S32 status, LLExtStat ext_status) { - LLNotifications::instance().add("TerrainDownloaded"); + LLNotificationsUtil::add("TerrainDownloaded"); } diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp index 72455bb8b..0e2f8d6d0 100644 --- a/indra/newview/llfloatergroups.cpp +++ b/indra/newview/llfloatergroups.cpp @@ -54,6 +54,7 @@ #include "llalertdialog.h" #include "llselectmgr.h" #include "llscrolllistctrl.h" +#include "llnotificationsutil.h" #include "lltextbox.h" #include "lluictrlfactory.h" #include "llviewerwindow.h" @@ -425,7 +426,7 @@ void LLPanelGroups::leave() args["GROUP"] = gAgent.mGroups.get(i).mName; LLSD payload; payload["group_id"] = group_id; - LLNotifications::instance().add("GroupLeaveConfirmMember", args, payload, callbackLeaveGroup); + LLNotificationsUtil::add("GroupLeaveConfirmMember", args, payload, callbackLeaveGroup); } } } diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index 23da0629b..d1d19e86c 100644 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -35,6 +35,7 @@ #include "llfloaterhardwaresettings.h" #include "llfloaterpreference.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llviewercontrol.h" #include "llviewertexturelist.h" #include "llfeaturemanager.h" diff --git a/indra/newview/llfloaterhud.cpp b/indra/newview/llfloaterhud.cpp index 6324b5656..33fbec1d4 100644 --- a/indra/newview/llfloaterhud.cpp +++ b/indra/newview/llfloaterhud.cpp @@ -40,6 +40,7 @@ #include "llalertdialog.h" // Linden libs +#include "llnotificationsutil.h" #include "lluictrlfactory.h" // statics @@ -125,7 +126,7 @@ void LLFloaterHUD::showHUD() // do not build the floater if there the url is empty if (gSavedSettings.getString("TutorialURL") == "") { - LLNotifications::instance().add("TutorialNotFound"); + LLNotificationsUtil::add("TutorialNotFound"); return; } diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 27cd5055d..2fc241cc4 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -348,24 +348,7 @@ bool LLFloaterImagePreview::loadImage(const std::string& src_filename) { std::string exten = gDirUtilp->getExtension(src_filename); - U32 codec = IMG_CODEC_INVALID; - std::string temp_str; - if( exten == "bmp") - { - codec = IMG_CODEC_BMP; - } - else if( exten == "tga") - { - codec = IMG_CODEC_TGA; - } - else if( exten == "jpg" || exten == "jpeg") - { - codec = IMG_CODEC_JPEG; - } - else if( exten == "png" ) - { - codec = IMG_CODEC_PNG; - } + U32 codec = LLImageBase::getCodecFromExtension(exten); LLPointer<LLImageRaw> raw_image = new LLImageRaw; @@ -854,8 +837,8 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) } const LLVolumeFace &vf = mVolume->getVolumeFace(0); - U32 num_indices = vf.mIndices.size(); - U32 num_vertices = vf.mVertices.size(); + U32 num_indices = vf.mNumIndices; + U32 num_vertices = vf.mNumVertices; mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL, 0); mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE); @@ -869,12 +852,12 @@ void LLImagePreviewSculpted::setPreviewTarget(LLImageRaw* imagep, F32 distance) mVertexBuffer->getIndexStrider(index_strider); // build vertices and normals - for (U32 i = 0; (S32)i < num_vertices; i++) + for (U32 i = 0; (U32)i < num_vertices; i++) { - *(vertex_strider++) = vf.mVertices[i].mPosition; - LLVector3 normal = vf.mVertices[i].mNormal; - normal.normalize(); - *(normal_strider++) = normal; + (vertex_strider++)->set(vf.mPositions[i].getF32ptr()); + LLVector4a normal(vf.mNormals[i]); + normal.normalize3fast(); + (normal_strider++)->set(normal.getF32ptr()); } // build indices @@ -936,7 +919,7 @@ BOOL LLImagePreviewSculpted::render() LLViewerCamera::getInstance()->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, FALSE); const LLVolumeFace &vf = mVolume->getVolumeFace(0); - U32 num_indices = vf.mIndices.size(); + U32 num_indices = (U32)vf.mNumIndices; mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL); @@ -948,8 +931,7 @@ BOOL LLImagePreviewSculpted::render() gGL.color3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0); - gGL.popMatrix(); - + gGL.popMatrix(); return TRUE; } diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 57d5a004e..6ccc45376 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -39,6 +39,7 @@ #include "llcachename.h" #include "llfocusmgr.h" +#include "llnotificationsutil.h" #include "llparcel.h" #include "message.h" #include "lluserauth.h" @@ -932,7 +933,7 @@ void LLPanelLandGeneral::onClickBuyPass(void* data) args["PARCEL_NAME"] = parcel_name; args["TIME"] = time; - LLNotifications::instance().add("LandBuyPass", args, LLSD(), cbBuyPass); + LLNotificationsUtil::add("LandBuyPass", args, LLSD(), cbBuyPass); } // static @@ -944,7 +945,7 @@ void LLPanelLandGeneral::onClickStartAuction(void* data) { if(parcelp->getForSale()) { - LLNotifications::instance().add("CannotStartAuctionAlreadyForSale"); + LLNotificationsUtil::add("CannotStartAuctionAlreadyForSale"); } else { @@ -956,7 +957,7 @@ void LLPanelLandGeneral::onClickStartAuction(void* data) // static bool LLPanelLandGeneral::cbBuyPass(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (0 == option) { // User clicked OK @@ -1303,7 +1304,7 @@ void send_return_objects_message(S32 parcel_local_id, S32 return_type, bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLParcel *parcel = mParcel->getParcel(); if (0 == option) { @@ -1313,14 +1314,14 @@ bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, co LLSD args; if (owner_id == gAgentID) { - LLNotifications::instance().add("OwnedObjectsReturned"); + LLNotificationsUtil::add("OwnedObjectsReturned"); } else { std::string full_name; gCacheName->getFullName(owner_id, full_name); args["NAME"] = full_name; - LLNotifications::instance().add("OtherObjectsReturned", args); + LLNotificationsUtil::add("OtherObjectsReturned", args); } send_return_objects_message(parcel->getLocalID(), RT_OWNER); } @@ -1334,7 +1335,7 @@ bool LLPanelLandObjects::callbackReturnOwnerObjects(const LLSD& notification, co bool LLPanelLandObjects::callbackReturnGroupObjects(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLParcel *parcel = mParcel->getParcel(); if (0 == option) { @@ -1344,7 +1345,7 @@ bool LLPanelLandObjects::callbackReturnGroupObjects(const LLSD& notification, co gCacheName->getGroupName(parcel->getGroupID(), group_name); LLSD args; args["GROUPNAME"] = group_name; - LLNotifications::instance().add("GroupObjectsReturned", args); + LLNotificationsUtil::add("GroupObjectsReturned", args); send_return_objects_message(parcel->getLocalID(), RT_GROUP); } } @@ -1356,13 +1357,13 @@ bool LLPanelLandObjects::callbackReturnGroupObjects(const LLSD& notification, co bool LLPanelLandObjects::callbackReturnOtherObjects(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLParcel *parcel = mParcel->getParcel(); if (0 == option) { if (parcel) { - LLNotifications::instance().add("UnOwnedObjectsReturned"); + LLNotificationsUtil::add("UnOwnedObjectsReturned"); send_return_objects_message(parcel->getLocalID(), RT_OTHER); } } @@ -1374,7 +1375,7 @@ bool LLPanelLandObjects::callbackReturnOtherObjects(const LLSD& notification, co bool LLPanelLandObjects::callbackReturnOwnerList(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLParcel *parcel = mParcel->getParcel(); if (0 == option) { @@ -1388,12 +1389,12 @@ bool LLPanelLandObjects::callbackReturnOwnerList(const LLSD& notification, const if (mSelectedIsGroup) { args["GROUPNAME"] = mSelectedName; - LLNotifications::instance().add("GroupObjectsReturned", args); + LLNotificationsUtil::add("GroupObjectsReturned", args); } else { args["NAME"] = mSelectedName; - LLNotifications::instance().add("OtherObjectsReturned2", args); + LLNotificationsUtil::add("OtherObjectsReturned2", args); } send_return_objects_message(parcel->getLocalID(), RT_LIST, &(mSelectedOwners)); @@ -1430,11 +1431,11 @@ void LLPanelLandObjects::onClickReturnOwnerList(void* userdata) args["N"] = llformat("%d",self->mSelectedCount); if (self->mSelectedIsGroup) { - LLNotifications::instance().add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2)); } else { - LLNotifications::instance().add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerList, self, _1, _2)); } } @@ -1659,14 +1660,14 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata) if (owner_id == gAgent.getID()) { - LLNotifications::instance().add("ReturnObjectsOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2)); } else { std::string name; gCacheName->getFullName(owner_id, name); args["NAME"] = name; - LLNotifications::instance().add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOwnerObjects, panelp, _1, _2)); } } @@ -1687,7 +1688,7 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata) args["N"] = llformat("%d", parcel->getGroupPrimCount()); // create and show confirmation textbox - LLNotifications::instance().add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnGroupObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsDeededToGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnGroupObjects, panelp, _1, _2)); } // static @@ -1712,7 +1713,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) gCacheName->getGroupName(parcel->getGroupID(), group_name); args["NAME"] = group_name; - LLNotifications::instance().add("ReturnObjectsNotOwnedByGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsNotOwnedByGroup", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2)); } else { @@ -1720,15 +1721,14 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) if (owner_id == gAgent.getID()) { - LLNotifications::instance().add("ReturnObjectsNotOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsNotOwnedBySelf", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2)); } else { std::string name; gCacheName->getFullName(owner_id, name); args["NAME"] = name; - - LLNotifications::instance().add("ReturnObjectsNotOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2)); + LLNotificationsUtil::add("ReturnObjectsNotOwnedByUser", args, LLSD(), boost::bind(&LLPanelLandObjects::callbackReturnOtherObjects, panelp, _1, _2)); } } } @@ -2221,7 +2221,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) if (!allow_other_scripts && region && region->getAllowDamage()) { - LLNotifications::instance().add("UnableToDisableOutsideScripts"); + LLNotificationsUtil::add("UnableToDisableOutsideScripts"); return; } @@ -2265,7 +2265,7 @@ void LLPanelLandOptions::onClickSet(void* userdata) if (agent_parcel->getLocalID() != selected_parcel->getLocalID()) { - LLNotifications::instance().add("MustBeInParcel"); + LLNotificationsUtil::add("MustBeInParcel"); return; } @@ -2308,11 +2308,11 @@ void LLPanelLandOptions::onClickPublishHelp(void*) if(! can_change_identity) { - LLNotifications::instance().add("ClickPublishHelpLandDisabled"); + LLNotificationsUtil::add("ClickPublishHelpLandDisabled"); } else { - LLNotifications::instance().add("ClickPublishHelpLand"); + LLNotificationsUtil::add("ClickPublishHelpLand"); } } diff --git a/indra/newview/llfloaterlandmark.cpp b/indra/newview/llfloaterlandmark.cpp index 25b955526..49d3874d6 100644 --- a/indra/newview/llfloaterlandmark.cpp +++ b/indra/newview/llfloaterlandmark.cpp @@ -35,6 +35,7 @@ #include "llfloaterlandmark.h" #include "llagent.h" +#include "llagentui.h" #include "llcheckboxctrl.h" #include "llviewerparcelmgr.h" #include "llfolderview.h" @@ -45,6 +46,7 @@ #include "llpermissions.h" #include "llsaleinfo.h" #include "llparcel.h" +#include "llnotificationsutil.h" #include "llviewerwindow.h" // alertXml #include "llviewercontrol.h" @@ -295,18 +297,19 @@ void LLFloaterLandmark::onBtnNew(void* userdata) if (!agent_parcel->getAllowLandmark() && !LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK)) { - LLNotifications::instance().add("CannotCreateLandmarkNotOwner"); + LLNotificationsUtil::add("CannotCreateLandmarkNotOwner"); return; } - LLUUID folder_id; - folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); - std::string pos_string; - gAgent.buildLocationString(pos_string); + std::string landmark_name, landmark_desc; + + LLAgentUI::buildLocationString(landmark_name, LLAgentUI::LOCATION_FORMAT_LANDMARK); + LLAgentUI::buildLocationString(landmark_desc, LLAgentUI::LOCATION_FORMAT_FULL); + const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); create_inventory_item(gAgent.getID(), gAgent.getSessionID(), folder_id, LLTransactionID::tnull, - pos_string, pos_string, // name, desc + landmark_name, landmark_desc, // name, desc LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, NOT_WEARABLE, PERM_ALL, diff --git a/indra/newview/llfloatermediabrowser.cpp b/indra/newview/llfloatermediabrowser.cpp index def015943..d73cfde72 100644 --- a/indra/newview/llfloatermediabrowser.cpp +++ b/indra/newview/llfloatermediabrowser.cpp @@ -45,13 +45,14 @@ #include "llweb.h" #include "llui.h" #include "roles_constants.h" +#include "llwindow.h" #include "llurlhistory.h" #include "llmediactrl.h" #include "llviewermedia.h" #include "llviewerparcelmedia.h" #include "llcombobox.h" - +#include "llnotificationsutil.h" // TEMP #include "llsdutil.h" @@ -62,6 +63,28 @@ LLFloaterMediaBrowser::LLFloaterMediaBrowser(const LLSD& media_data) } + +void LLFloaterMediaBrowser::geometryChanged(S32 x, S32 y, S32 width, S32 height) +{ + // Make sure the layout of the browser control is updated, so this calculation is correct. + LLLayoutStack::updateClass(); + + // TODO: need to adjust size and constrain position to make sure floaters aren't moved outside the window view, etc. + LLCoordWindow window_size; + getWindow()->getSize(&window_size); + + // Adjust width and height for the size of the chrome on the Media Browser window. + width += getRect().getWidth() - mBrowser->getRect().getWidth(); + height += getRect().getHeight() - mBrowser->getRect().getHeight(); + + LLRect geom; + geom.setOriginAndSize(x, window_size.mY - (y + height), width, height); + + lldebugs << "geometry change: " << geom << llendl; + + handleReshape(geom,false); +} + void LLFloaterMediaBrowser::draw() { childSetEnabled("go", !mAddressCombo->getValue().asString().empty()); @@ -105,6 +128,7 @@ BOOL LLFloaterMediaBrowser::postBuild() mAddressCombo = getChild<LLComboBox>("address"); mAddressCombo->setCommitCallback(onEnterAddress); mAddressCombo->setCallbackUserData(this); + mAddressCombo->sortByName(); childSetAction("back", onClickBack, this); childSetAction("forward", onClickForward, this); @@ -146,7 +170,10 @@ void LLFloaterMediaBrowser::buildURLHistory() } // initialize URL history in the plugin - mBrowser->getMediaPlugin()->initializeUrlHistory(browser_history); + if(mBrowser && mBrowser->getMediaPlugin()) + { + mBrowser->getMediaPlugin()->initializeUrlHistory(browser_history); + } } std::string LLFloaterMediaBrowser::getSupportURL() @@ -171,6 +198,15 @@ void LLFloaterMediaBrowser::handleMediaEvent(LLPluginClassMedia* self, EMediaEve childSetEnabled("back", self->getHistoryBackAvailable()); childSetEnabled("forward", self->getHistoryForwardAvailable()); } + else if(event == MEDIA_EVENT_CLOSE_REQUEST) + { + // The browser instance wants its window closed. + close(); + } + else if(event == MEDIA_EVENT_GEOMETRY_CHANGE) + { + geometryChanged(self->getGeometryX(), self->getGeometryY(), self->getGeometryWidth(), self->getGeometryHeight()); + } } void LLFloaterMediaBrowser::setCurrentURL(const std::string& url) { @@ -213,7 +249,15 @@ void LLFloaterMediaBrowser::onClickRefresh(void* user_data) LLFloaterMediaBrowser* self = (LLFloaterMediaBrowser*)user_data; self->mAddressCombo->remove(0); - self->mBrowser->navigateTo(self->mCurrentURL); + if( self->mBrowser->getMediaPlugin() && self->mBrowser->getMediaPlugin()->pluginSupportsMediaBrowser()) + { + bool ignore_cache = true; + self->mBrowser->getMediaPlugin()->browse_reload( ignore_cache ); + } + else + { + self->mBrowser->navigateTo(self->mCurrentURL); + } } //static @@ -371,7 +415,7 @@ void LLViewerHtmlHelp::show(std::string url) LLSD notificationData; notificationData["url"] = url; - LLNotifications::instance().add("ClickOpenF1Help", notificationData, LLSD(), onClickF1HelpLoadURL); + LLNotificationsUtil::add("ClickOpenF1Help", notificationData, LLSD(), onClickF1HelpLoadURL); floater_html->close(); } else diff --git a/indra/newview/llfloatermediabrowser.h b/indra/newview/llfloatermediabrowser.h index 47a3b158d..afdd6e733 100644 --- a/indra/newview/llfloatermediabrowser.h +++ b/indra/newview/llfloatermediabrowser.h @@ -64,6 +64,9 @@ class LLFloaterMediaBrowser : public: LLFloaterMediaBrowser(const LLSD& media_data); + + void geometryChanged(S32 x, S32 y, S32 width, S32 height); + /*virtual*/ BOOL postBuild(); /*virtual*/ void onClose(bool app_quitting); /*virtual*/ void draw(); diff --git a/indra/newview/llfloatermessagelog.cpp b/indra/newview/llfloatermessagelog.cpp index 74241d35e..57ffac013 100644 --- a/indra/newview/llfloatermessagelog.cpp +++ b/indra/newview/llfloatermessagelog.cpp @@ -3,6 +3,7 @@ #include "llfloatermessagelog.h" #include "lluictrlfactory.h" #include "llworld.h" +#include "llnotificationsutil.h" #include "llviewerregion.h" #include "llscrolllistctrl.h" #include "lltexteditor.h" @@ -819,7 +820,7 @@ BOOL LLFloaterMessageLog::onClickCloseCircuit(void* user_data) args["MESSAGE"] = "This will delete local circuit data.\nDo you want to tell the remote host to close the circuit too?"; LLSD payload; payload["circuittoclose"] = myhost.getString(); - LLNotifications::instance().add("GenericAlertYesCancel", args, payload, onConfirmCloseCircuit); + LLNotificationsUtil::add("GenericAlertYesCancel", args, payload, onConfirmCloseCircuit); return TRUE; } // static @@ -853,7 +854,7 @@ bool LLFloaterMessageLog::onConfirmCloseCircuit(const LLSD& notification, const args["MESSAGE"] = "That host had a region associated with it.\nDo you want to clean that up?"; LLSD payload; payload["regionhost"] = myhost.getString(); - LLNotifications::instance().add("GenericAlertYesCancel", args, payload, onConfirmRemoveRegion); + LLNotificationsUtil::add("GenericAlertYesCancel", args, payload, onConfirmRemoveRegion); } return false; } diff --git a/indra/newview/llfloatermute.cpp b/indra/newview/llfloatermute.cpp index 179650ce5..8e071dcde 100644 --- a/indra/newview/llfloatermute.cpp +++ b/indra/newview/llfloatermute.cpp @@ -39,6 +39,7 @@ #include "llerror.h" #include "llstring.h" #include "message.h" +#include "llnotificationsutil.h" // project include #include "llagent.h" @@ -349,6 +350,6 @@ void LLFloaterMute::callbackMuteByName(const std::string& text, void* data) BOOL success = LLMuteList::getInstance()->add(mute); if (!success) { - LLNotifications::instance().add("MuteByNameFailed"); + LLNotificationsUtil::add("MuteByNameFailed"); } } diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp index 6d2d1f7ab..71d413f33 100644 --- a/indra/newview/llfloateropenobject.cpp +++ b/indra/newview/llfloateropenobject.cpp @@ -41,6 +41,7 @@ #include "llcachename.h" #include "llbutton.h" +#include "llnotificationsutil.h" #include "lltextbox.h" #include "llagent.h" // for agent id @@ -76,6 +77,28 @@ LLFloaterOpenObject::~LLFloaterOpenObject() sInstance = NULL; } +// static +void LLFloaterOpenObject::show() +{ + LLObjectSelectionHandle object_selection = LLSelectMgr::getInstance()->getSelection(); + if (object_selection->getRootObjectCount() != 1) + { + LLNotificationsUtil::add("UnableToViewContentsMoreThanOne"); + return; + } + + // Create a new instance only if needed + if (!sInstance) + { + sInstance = new LLFloaterOpenObject(); + sInstance->center(); + } + + sInstance->open(); /* Flawfinder: ignore */ + sInstance->setFocus(TRUE); + + sInstance->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); +} void LLFloaterOpenObject::refresh() { mPanelInventory->refresh(); @@ -104,35 +127,13 @@ void LLFloaterOpenObject::dirty() if (sInstance) sInstance->mDirty = TRUE; } -// static -void LLFloaterOpenObject::show() -{ - LLObjectSelectionHandle object_selection = LLSelectMgr::getInstance()->getSelection(); - if (object_selection->getRootObjectCount() != 1) - { - LLNotifications::instance().add("UnableToViewContentsMoreThanOne"); - return; - } - - // Create a new instance only if needed - if (!sInstance) - { - sInstance = new LLFloaterOpenObject(); - sInstance->center(); - } - - sInstance->open(); /* Flawfinder: ignore */ - sInstance->setFocus(TRUE); - - sInstance->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); -} void LLFloaterOpenObject::moveToInventory(bool wear) { if (mObjectSelection->getRootObjectCount() != 1) { - LLNotifications::instance().add("OnlyCopyContentsOfSingleItem"); + LLNotificationsUtil::add("OnlyCopyContentsOfSingleItem"); return; } @@ -173,7 +174,7 @@ void LLFloaterOpenObject::moveToInventory(bool wear) delete data; data = NULL; - LLNotifications::instance().add("OpenObjectCannotCopy"); + LLNotificationsUtil::add("OpenObjectCannotCopy"); } } diff --git a/indra/newview/llfloaterperms.cpp b/indra/newview/llfloaterperms.cpp index cd3553b92..ccbeb8c5c 100644 --- a/indra/newview/llfloaterperms.cpp +++ b/indra/newview/llfloaterperms.cpp @@ -35,6 +35,7 @@ #include "llalertdialog.h" #include "llcheckboxctrl.h" #include "llfloaterperms.h" +#include "llnotificationsutil.h" #include "llviewercontrol.h" #include "llviewerwindow.h" #include "lluictrlfactory.h" @@ -155,5 +156,5 @@ U32 LLFloaterPerms::getNextOwnerPerms(std::string prefix) //static void LLFloaterPerms::onClickHelp(void* data) { - LLNotifications::instance().add("ClickUploadHelpPermissions"); + LLNotificationsUtil::add("ClickUploadHelpPermissions"); } diff --git a/indra/newview/llfloaterpostcard.cpp b/indra/newview/llfloaterpostcard.cpp index c2f76c354..fe7d7816f 100644 --- a/indra/newview/llfloaterpostcard.cpp +++ b/indra/newview/llfloaterpostcard.cpp @@ -45,6 +45,7 @@ #include "lllineeditor.h" #include "llviewertexteditor.h" #include "llbutton.h" +#include "llnotificationsutil.h" #include "llviewercontrol.h" #include "llviewernetwork.h" #include "lluictrlfactory.h" @@ -255,20 +256,20 @@ void LLFloaterPostcard::onClickSend(void* data) if (to.empty() || !boost::regex_match(to, emailFormat)) { - LLNotifications::instance().add("PromptRecipientEmail"); + LLNotificationsUtil::add("PromptRecipientEmail"); return; } if (from.empty() || !boost::regex_match(from, emailFormat)) { - LLNotifications::instance().add("PromptSelfEmail"); + LLNotificationsUtil::add("PromptSelfEmail"); return; } std::string subject(self->childGetValue("subject_form").asString()); if(subject.empty() || !self->mHasFirstMsgFocus) { - LLNotifications::instance().add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLFloaterPostcard::missingSubjMsgAlertCallback, self, _1, _2)); + LLNotificationsUtil::add("PromptMissingSubjMsg", LLSD(), LLSD(), boost::bind(&LLFloaterPostcard::missingSubjMsgAlertCallback, self, _1, _2)); return; } @@ -278,7 +279,7 @@ void LLFloaterPostcard::onClickSend(void* data) } else { - LLNotifications::instance().add("ErrorProcessingSnapshot"); + LLNotificationsUtil::add("ErrorProcessingSnapshot"); } } } @@ -294,7 +295,7 @@ void LLFloaterPostcard::uploadCallback(const LLUUID& asset_id, void *user_data, { LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); - LLNotifications::instance().add("ErrorUploadingPostcard", args); + LLNotificationsUtil::add("ErrorUploadingPostcard", args); } else { @@ -353,7 +354,7 @@ void LLFloaterPostcard::onMsgFormFocusRecieved(LLFocusableElement* receiver, voi bool LLFloaterPostcard::missingSubjMsgAlertCallback(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if(0 == option) { // User clicked OK diff --git a/indra/newview/llfloaterpostprocess.cpp b/indra/newview/llfloaterpostprocess.cpp index a7e4e7a3e..19346c19b 100644 --- a/indra/newview/llfloaterpostprocess.cpp +++ b/indra/newview/llfloaterpostprocess.cpp @@ -36,6 +36,7 @@ #include "llsliderctrl.h" #include "llcheckboxctrl.h" +#include "llnotificationsutil.h" #include "lluictrlfactory.h" #include "llviewerdisplay.h" #include "llpostprocess.h" @@ -180,7 +181,7 @@ void LLFloaterPostProcess::onSaveEffect(void* userData) { LLSD payload; payload["effect_name"] = effectName; - LLNotifications::instance().add("PPSaveEffectAlert", LLSD(), payload, &LLFloaterPostProcess::saveAlertCallback); + LLNotificationsUtil::add("PPSaveEffectAlert", LLSD(), payload, &LLFloaterPostProcess::saveAlertCallback); } else { @@ -201,7 +202,7 @@ void LLFloaterPostProcess::onChangeEffectName(LLUICtrl* ctrl, void * userData) bool LLFloaterPostProcess::saveAlertCallback(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); // if they choose save, do it. Otherwise, don't do anything if (option == 0) diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp index 62ecd8faf..c9c8e0482 100644 --- a/indra/newview/llfloaterproperties.cpp +++ b/indra/newview/llfloaterproperties.cpp @@ -38,6 +38,7 @@ #include "llcachename.h" #include "lldbstrings.h" #include "llinventory.h" +#include "llinventorydefines.h" #include "llagent.h" #include "llbutton.h" diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index deae4fa92..6e07e2b03 100644 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -64,6 +64,8 @@ #include "lllineeditor.h" #include "llalertdialog.h" #include "llnamelistctrl.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llsliderctrl.h" #include "llspinctrl.h" #include "lltabcontainer.h" @@ -79,7 +81,7 @@ #include "llviewertexteditor.h" #include "llviewerwindow.h" #include "llvlcomposition.h" - +#include "llagentui.h" // [RLVa:KB] #include "rlvhandler.h" // [/RLVa:KB] @@ -656,7 +658,7 @@ void LLPanelRegionGeneralInfo::onKickCommit(const std::vector<std::string>& name void LLPanelRegionGeneralInfo::onClickKickAll(void* userdata) { llinfos << "LLPanelRegionGeneralInfo::onClickKickAll" << llendl; - LLNotifications::instance().add("KickUsersFromRegion", + LLNotificationsUtil::add("KickUsersFromRegion", LLSD(), LLSD(), boost::bind(&LLPanelRegionGeneralInfo::onKickAllCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2)); @@ -664,7 +666,7 @@ void LLPanelRegionGeneralInfo::onClickKickAll(void* userdata) bool LLPanelRegionGeneralInfo::onKickAllCommit(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { strings_t strings; @@ -684,7 +686,7 @@ bool LLPanelRegionGeneralInfo::onKickAllCommit(const LLSD& notification, const L void LLPanelRegionGeneralInfo::onClickMessage(void* userdata) { llinfos << "LLPanelRegionGeneralInfo::onClickMessage" << llendl; - LLNotifications::instance().add("MessageRegion", + LLNotificationsUtil::add("MessageRegion", LLSD(), LLSD(), boost::bind(&LLPanelRegionGeneralInfo::onMessageCommit, (LLPanelRegionGeneralInfo*)userdata, _1, _2)); @@ -693,7 +695,7 @@ void LLPanelRegionGeneralInfo::onClickMessage(void* userdata) // static bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const LLSD& response) { - if(LLNotification::getSelectedOption(notification, response) != 0) return false; + if(LLNotificationsUtil::getSelectedOption(notification, response) != 0) return false; std::string text = response["message"].asString(); if (text.empty()) return false; @@ -711,7 +713,7 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L gAgent.getID().toString(buffer); strings.push_back(buffer); std::string name; - gAgent.buildFullname(name); + LLAgentUI::buildFullname(name); strings.push_back(strings_t::value_type(name)); strings.push_back(strings_t::value_type(text)); LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); @@ -802,7 +804,7 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate() LLViewerRegion* region = gAgent.getRegion(); if (region && (childGetValue("access_combo").asInteger() != region->getSimAccess()) ) { - LLNotifications::instance().add("RegionMaturityChange"); + LLNotificationsUtil::add("RegionMaturityChange"); } return TRUE; @@ -916,13 +918,13 @@ void LLPanelRegionDebugInfo::onClickReturn(void* data) } payload["flags"] = int(flags); payload["return_estate_wide"] = panelp->childGetValue("return_estate_wide").asBoolean(); - LLNotifications::instance().add("EstateObjectReturn", args, payload, + LLNotificationsUtil::add("EstateObjectReturn", args, payload, boost::bind(&LLPanelRegionDebugInfo::callbackReturn, panelp, _1, _2)); } bool LLPanelRegionDebugInfo::callbackReturn(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) return false; LLUUID target_avatar = notification["payload"]["avatar_id"].asUUID(); @@ -978,13 +980,13 @@ void LLPanelRegionDebugInfo::onClickTopScripts(void* data) // static void LLPanelRegionDebugInfo::onClickRestart(void* data) { - LLNotifications::instance().add("ConfirmRestart", LLSD(), LLSD(), + LLNotificationsUtil::add("ConfirmRestart", LLSD(), LLSD(), boost::bind(&LLPanelRegionDebugInfo::callbackRestart, (LLPanelRegionDebugInfo*)data, _1, _2)); } bool LLPanelRegionDebugInfo::callbackRestart(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) return false; strings_t strings; @@ -1089,10 +1091,11 @@ BOOL LLPanelRegionTextureInfo::sendUpdate() llinfos << "LLPanelRegionTextureInfo::sendUpdate()" << llendl; // Make sure user hasn't chosen wacky textures. - if (!validateTextureSizes()) - { - return FALSE; - } + // -Revolution Allow 'wacky' things + //if (!validateTextureSizes()) + //{ + // return FALSE; + //} LLTextureCtrl* texture_ctrl; std::string buffer; @@ -1152,7 +1155,7 @@ BOOL LLPanelRegionTextureInfo::validateTextureSizes() LLSD args; args["TEXTURE_NUM"] = i+1; args["TEXTURE_BIT_DEPTH"] = llformat("%d",components * 8); - LLNotifications::instance().add("InvalidTerrainBitDepth", args); + LLNotificationsUtil::add("InvalidTerrainBitDepth", args); return FALSE; } @@ -1163,7 +1166,7 @@ BOOL LLPanelRegionTextureInfo::validateTextureSizes() args["TEXTURE_NUM"] = i+1; args["TEXTURE_SIZE_X"] = width; args["TEXTURE_SIZE_Y"] = height; - LLNotifications::instance().add("InvalidTerrainSize", args); + LLNotificationsUtil::add("InvalidTerrainSize", args); return FALSE; } @@ -1369,20 +1372,18 @@ void LLPanelRegionTerrainInfo::onClickUploadRaw_continued(AIFilePicker* filepick LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); sendEstateOwnerMessage(gMessageSystem, "terrain", invoice, strings); - LLNotifications::instance().add("RawUploadStarted"); + LLNotificationsUtil::add("RawUploadStarted"); } // static void LLPanelRegionTerrainInfo::onClickBakeTerrain(void* data) { - LLNotifications::instance().add( - LLNotification::Params("ConfirmBakeTerrain") - .functor(boost::bind(&LLPanelRegionTerrainInfo::callbackBakeTerrain, (LLPanelRegionTerrainInfo*)data, _1, _2))); + LLNotificationsUtil::add("ConfirmBakeTerrain", LLSD(), LLSD(), boost::bind(&LLPanelRegionTerrainInfo::callbackBakeTerrain, (LLPanelRegionTerrainInfo*)data, _1, _2)); } bool LLPanelRegionTerrainInfo::callbackBakeTerrain(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) return false; strings_t strings; @@ -1478,7 +1479,7 @@ void LLPanelEstateInfo::onClickAddAllowedAgent(void* user_data) LLSD args; args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); - LLNotifications::instance().add("MaxAllowedAgentOnRegion", args); + LLNotificationsUtil::add("MaxAllowedAgentOnRegion", args); return; } accessAddCore(ESTATE_ACCESS_ALLOWED_AGENT_ADD, "EstateAllowedAgentAdd"); @@ -1500,7 +1501,7 @@ void LLPanelEstateInfo::onClickAddAllowedGroup(void* user_data) { LLSD args; args["MAX_GROUPS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); - LLNotifications::instance().add("MaxAllowedGroupsOnRegion", args); + LLNotificationsUtil::add("MaxAllowedGroupsOnRegion", args); return; } @@ -1518,7 +1519,7 @@ void LLPanelEstateInfo::onClickAddAllowedGroup(void* user_data) bool LLPanelEstateInfo::addAllowedGroup(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) return false; LLFloater* parent_floater = gFloaterView->getParentFloater(this); @@ -1555,7 +1556,7 @@ void LLPanelEstateInfo::onClickAddBannedAgent(void* user_data) { LLSD args; args["MAX_BANNED"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); - LLNotifications::instance().add("MaxBannedAgentsOnRegion", args); + LLNotificationsUtil::add("MaxBannedAgentsOnRegion", args); return; } accessAddCore(ESTATE_ACCESS_BANNED_AGENT_ADD, "EstateBannedAgentAdd"); @@ -1577,7 +1578,7 @@ void LLPanelEstateInfo::onClickAddEstateManager(void* user_data) { // Tell user they can't add more managers LLSD args; args["MAX_MANAGER"] = llformat("%d",ESTATE_MAX_MANAGERS); - LLNotifications::instance().add("MaxManagersOnRegion", args); + LLNotificationsUtil::add("MaxManagersOnRegion", args); } else { // Go pick managers to add @@ -1635,13 +1636,13 @@ void LLPanelEstateInfo::onKickUserCommit(const std::vector<std::string>& names, args["EVIL_USER"] = names[0]; LLSD payload; payload["agent_id"] = ids[0]; - LLNotifications::instance().add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, self, _1, _2)); + LLNotificationsUtil::add("EstateKickUser", args, payload, boost::bind(&LLPanelEstateInfo::kickUserConfirm, self, _1, _2)); } bool LLPanelEstateInfo::kickUserConfirm(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); switch(option) { case 0: @@ -1788,7 +1789,7 @@ void LLPanelEstateInfo::accessAddCore(U32 operation_flag, const std::string& dia // static bool LLPanelEstateInfo::accessAddCore2(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) { // abort change @@ -1832,7 +1833,7 @@ void LLPanelEstateInfo::accessAddCore3(const std::vector<std::string>& names, co args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); args["LIST_TYPE"] = "Allowed Residents"; args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS); - LLNotifications::instance().add("MaxAgentOnRegionBatch", args); + LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); delete change_info; return; } @@ -1848,7 +1849,7 @@ void LLPanelEstateInfo::accessAddCore3(const std::vector<std::string>& names, co args["MAX_AGENTS"] = llformat("%d",ESTATE_MAX_ACCESS_IDS); args["LIST_TYPE"] = "Banned Residents"; args["NUM_EXCESS"] = llformat("%d",(ids.size()+currentCount)-ESTATE_MAX_ACCESS_IDS); - LLNotifications::instance().add("MaxAgentOnRegionBatch", args); + LLNotificationsUtil::add("MaxAgentOnRegionBatch", args); delete change_info; return; } @@ -1917,7 +1918,7 @@ void LLPanelEstateInfo::accessRemoveCore(U32 operation_flag, const std::string& // static bool LLPanelEstateInfo::accessRemoveCore2(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) { // abort @@ -1934,7 +1935,7 @@ bool LLPanelEstateInfo::accessRemoveCore2(const LLSD& notification, const LLSD& { LLSD args; args["ALL_ESTATES"] = all_estates_text(); - LLNotifications::instance().add(notification["payload"]["dialog_name"], + LLNotificationsUtil::add(notification["payload"]["dialog_name"], args, notification["payload"], accessCoreConfirm); @@ -1947,7 +1948,7 @@ bool LLPanelEstateInfo::accessRemoveCore2(const LLSD& notification, const LLSD& // static bool LLPanelEstateInfo::accessCoreConfirm(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); const U32 originalFlags = (U32)notification["payload"]["operation"].asInteger(); LLViewerRegion* region = gAgent.getRegion(); @@ -1966,7 +1967,7 @@ bool LLPanelEstateInfo::accessCoreConfirm(const LLSD& notification, const LLSD& if (((U32)notification["payload"]["operation"].asInteger() & ESTATE_ACCESS_BANNED_AGENT_ADD) && region && (region->getOwner() == id)) { - LLNotifications::instance().add("OwnerCanNotBeDenied"); + LLNotificationsUtil::add("OwnerCanNotBeDenied"); break; } switch(option) @@ -2242,7 +2243,7 @@ BOOL LLPanelEstateInfo::sendUpdate() bool LLPanelEstateInfo::callbackChangeLindenEstate(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); switch(option) { case 0: @@ -2649,12 +2650,12 @@ BOOL LLPanelEstateInfo::checkSunHourSlider(LLUICtrl* child_ctrl) void LLPanelEstateInfo::onClickMessageEstate(void* userdata) { llinfos << "LLPanelEstateInfo::onClickMessageEstate" << llendl; - LLNotifications::instance().add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2)); + LLNotificationsUtil::add("MessageEstate", LLSD(), LLSD(), boost::bind(&LLPanelEstateInfo::onMessageCommit, (LLPanelEstateInfo*)userdata, _1, _2)); } bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); std::string text = response["message"].asString(); if(option != 0) return false; if(text.empty()) return false; @@ -2662,7 +2663,7 @@ bool LLPanelEstateInfo::onMessageCommit(const LLSD& notification, const LLSD& re strings_t strings; //integers_t integers; std::string name; - gAgent.buildFullname(name); + LLAgentUI::buildFullname(name); strings.push_back(strings_t::value_type(name)); strings.push_back(strings_t::value_type(text)); LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); @@ -2785,7 +2786,7 @@ BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop { LLSD payload; payload["item_id"] = item->getUUID(); - LLNotifications::instance().add("EstateChangeCovenant", LLSD(), payload, + LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), payload, LLPanelEstateCovenant::confirmChangeCovenantCallback); } break; @@ -2800,7 +2801,7 @@ BOOL LLPanelEstateCovenant::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop // static bool LLPanelEstateCovenant::confirmChangeCovenantCallback(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLInventoryItem* item = gInventory.getItem(notification["payload"]["item_id"].asUUID()); LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); @@ -2820,7 +2821,7 @@ bool LLPanelEstateCovenant::confirmChangeCovenantCallback(const LLSD& notificati // static void LLPanelEstateCovenant::resetCovenantID(void* userdata) { - LLNotifications::instance().add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback); + LLNotificationsUtil::add("EstateChangeCovenant", LLSD(), LLSD(), confirmResetCovenantCallback); } // static @@ -2829,7 +2830,7 @@ bool LLPanelEstateCovenant::confirmResetCovenantCallback(const LLSD& notificatio LLPanelEstateCovenant* self = LLFloaterRegionInfo::getPanelCovenant(); if (!self) return false; - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); switch(option) { case 0: @@ -2899,7 +2900,7 @@ void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs, if( !panelp->mEditor->importBuffer( buffer, file_length+1 ) ) { llwarns << "Problem importing estate covenant." << llendl; - LLNotifications::instance().add("ProblemImportingEstateCovenant"); + LLNotificationsUtil::add("ProblemImportingEstateCovenant"); } else { @@ -2920,15 +2921,15 @@ void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs, if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { - LLNotifications::instance().add("MissingNotecardAssetID"); + LLNotificationsUtil::add("MissingNotecardAssetID"); } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { - LLNotifications::instance().add("NotAllowedToViewNotecard"); + LLNotificationsUtil::add("NotAllowedToViewNotecard"); } else { - LLNotifications::instance().add("UnableToLoadNotecardAsset"); + LLNotificationsUtil::add("UnableToLoadNotecardAsset"); } llwarns << "Problem loading notecard: " << status << llendl; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index 2219ab235..9dec6b49f 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -43,6 +43,7 @@ #include "llfontgl.h" #include "llgl.h" // for renderer #include "llinventory.h" +#include "llnotificationsutil.h" #include "llimagej2c.h" #include "llstring.h" #include "llsys.h" @@ -232,10 +233,10 @@ void LLFloaterReporter::processRegionInfo(LLMessageSystem* msg) { if ( gEmailToEstateOwner ) { - LLNotifications::instance().add("HelpReportAbuseEmailEO"); + LLNotificationsUtil::add("HelpReportAbuseEmailEO"); } else - LLNotifications::instance().add("HelpReportAbuseEmailLL"); + LLNotificationsUtil::add("HelpReportAbuseEmailLL"); }; } @@ -443,7 +444,7 @@ void LLFloaterReporter::onClickSend(void *userdata) category_value == IP_CONTENT_REMOVAL || category_value == IP_PERMISSONS_EXPLOIT) { - LLNotifications::instance().add("HelpReportAbuseContainsCopyright"); + LLNotificationsUtil::add("HelpReportAbuseContainsCopyright"); self->mCopyrightWarningSeen = TRUE; return; } @@ -452,7 +453,7 @@ void LLFloaterReporter::onClickSend(void *userdata) { // IP_CONTENT_REMOVAL *always* shows the dialog - // ergo you can never send that abuse report type. - LLNotifications::instance().add("HelpReportAbuseContainsCopyright"); + LLNotificationsUtil::add("HelpReportAbuseContainsCopyright"); return; } } @@ -561,7 +562,7 @@ void LLFloaterReporter::showFromMenu(EReportType report_type) if (report_type == BUG_REPORT) { - LLNotifications::instance().add("HelpReportBug"); + LLNotificationsUtil::add("HelpReportBug"); } else { @@ -653,11 +654,11 @@ bool LLFloaterReporter::validateReport() { if ( mReportType != BUG_REPORT ) { - LLNotifications::instance().add("HelpReportAbuseSelectCategory"); + LLNotificationsUtil::add("HelpReportAbuseSelectCategory"); } else { - LLNotifications::instance().add("HelpReportBugSelectCategory"); + LLNotificationsUtil::add("HelpReportAbuseAbuserNameEmpty"); } return false; } @@ -666,13 +667,13 @@ bool LLFloaterReporter::validateReport() { if ( childGetText("abuser_name_edit").empty() ) { - LLNotifications::instance().add("HelpReportAbuseAbuserNameEmpty"); + LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty"); return false; }; if ( childGetText("abuse_location_edit").empty() ) { - LLNotifications::instance().add("HelpReportAbuseAbuserLocationEmpty"); + LLNotificationsUtil::add("HelpReportAbuseAbuserLocationEmpty"); return false; }; }; @@ -681,11 +682,11 @@ bool LLFloaterReporter::validateReport() { if ( mReportType != BUG_REPORT ) { - LLNotifications::instance().add("HelpReportAbuseSummaryEmpty"); + LLNotificationsUtil::add("HelpReportAbuseSummaryEmpty"); } else { - LLNotifications::instance().add("HelpReportBugSummaryEmpty"); + LLNotificationsUtil::add("HelpReportBugSummaryEmpty"); } return false; }; @@ -694,11 +695,11 @@ bool LLFloaterReporter::validateReport() { if ( mReportType != BUG_REPORT ) { - LLNotifications::instance().add("HelpReportAbuseDetailsEmpty"); + LLNotificationsUtil::add("HelpReportAbuseDetailsEmpty"); } else { - LLNotifications::instance().add("HelpReportBugDetailsEmpty"); + LLNotificationsUtil::add("HelpReportBugDetailsEmpty"); } return false; }; @@ -1001,7 +1002,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, { LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); - LLNotifications::instance().add("ErrorUploadingReportScreenshot", args); + LLNotificationsUtil::add("ErrorUploadingReportScreenshot", args); std::string err_msg("There was a problem uploading a report screenshot"); err_msg += " due to the following reason: " + args["REASON"].asString(); diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp index 3c5b9cfa9..f4cc7c30e 100644 --- a/indra/newview/llfloatersellland.cpp +++ b/indra/newview/llfloatersellland.cpp @@ -37,7 +37,8 @@ #include "llfloater.h" #include "llfloaterland.h" #include "lllineeditor.h" -#include "llnotify.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llparcel.h" #include "llselectmgr.h" #include "lltexturectrl.h" @@ -448,7 +449,7 @@ void LLFloaterSellLandUI::doShowObjects(void *userdata) send_parcel_select_objects(parcel->getLocalID(), RT_SELL); - LLNotifications::instance().add("TransferObjectsHighlighted", + LLNotificationsUtil::add("TransferObjectsHighlighted", LLSD(), LLSD(), &LLFloaterSellLandUI::callbackHighlightTransferable); } @@ -483,7 +484,7 @@ void LLFloaterSellLandUI::doSellLand(void *userdata) && (sale_price == 0) && sell_to_anyone) { - LLNotifications::instance().add("SalePriceRestriction"); + LLNotificationsUtil::add("SalePriceRestriction"); return; } @@ -516,7 +517,7 @@ void LLFloaterSellLandUI::doSellLand(void *userdata) bool LLFloaterSellLandUI::onConfirmSale(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option != 0) { return false; diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index 9289ff7b0..3f60a27e0 100644 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -61,6 +61,7 @@ #include "llviewerstats.h" #include "llviewercamera.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llviewermenufile.h" // upload_new_resource() #include "llfloaterpostcard.h" #include "llcheckboxctrl.h" @@ -68,6 +69,7 @@ #include "lltoolfocus.h" #include "lltoolmgr.h" #include "llworld.h" +#include "llagentui.h" #include "llgl.h" #include "llglheaders.h" @@ -75,6 +77,7 @@ #include "llimagepng.h" #include "llimagebmp.h" #include "llimagej2c.h" +#include "llnotificationsutil.h" #include "llvfile.h" #include "llvfs.h" @@ -228,7 +231,6 @@ LLSnapshotLivePreview::LLSnapshotLivePreview (const LLRect& rect) : mSnapshotBufferType(LLViewerWindow::SNAPSHOT_TYPE_COLOR) { setSnapshotQuality(gSavedSettings.getS32("SnapshotQuality")); - mSnapshotDelayTimer.setTimerExpirySec(0.0f); mSnapshotDelayTimer.start(); // gIdleCallbacks.addFunction( &LLSnapshotLivePreview::onIdle, (void*)this ); sList.insert(this); @@ -349,8 +351,7 @@ void LLSnapshotLivePreview::updateSnapshot(BOOL new_snapshot, BOOL new_thumbnail mShineAnimTimer.stop(); if (new_snapshot) { - mSnapshotDelayTimer.start(); - mSnapshotDelayTimer.setTimerExpirySec(delay); + mSnapshotDelayTimer.start(delay); } if(new_thumbnail) { @@ -753,7 +754,7 @@ BOOL LLSnapshotLivePreview::onIdle( void* snapshot_preview ) // see if it's time yet to snap the shot and bomb out otherwise. previewp->mSnapshotActive = - (previewp->mSnapshotDelayTimer.getStarted() && previewp->mSnapshotDelayTimer.hasExpired()) + (previewp->mSnapshotDelayTimer.getStarted() && previewp->mSnapshotDelayTimer.hasExpired()) && !LLToolCamera::getInstance()->hasMouseCapture(); // don't take snapshots while ALT-zoom active if ( ! previewp->mSnapshotActive) { @@ -975,9 +976,9 @@ void LLSnapshotLivePreview::saveTexture() { LLVFile::writeFile(formatted->getData(), formatted->getDataSize(), gVFS, new_asset_id, LLAssetType::AT_TEXTURE); std::string pos_string; - gAgent.buildLocationString(pos_string); + LLAgentUI::buildLocationString(pos_string, LLAgentUI::LOCATION_FORMAT_FULL); std::string who_took_it; - gAgent.buildFullname(who_took_it); + LLAgentUI::buildFullname(who_took_it); LLAssetStorage::LLStoreAssetCallback callback = NULL; S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(); void *userdata = NULL; @@ -997,7 +998,7 @@ void LLSnapshotLivePreview::saveTexture() } else { - LLNotifications::instance().add("ErrorEncodingSnapshot"); + LLNotificationsUtil::add("ErrorEncodingSnapshot"); llwarns << "Error encoding snapshot" << llendl; } @@ -1136,8 +1137,6 @@ LLViewerWindow::ESnapshotType LLFloaterSnapshot::Impl::getLayerType(LLFloaterSna type = LLViewerWindow::SNAPSHOT_TYPE_COLOR; else if (id == "depth") type = LLViewerWindow::SNAPSHOT_TYPE_DEPTH; - else if (id == "objects") - type = LLViewerWindow::SNAPSHOT_TYPE_OBJECT_ID; return type; } @@ -2110,11 +2109,17 @@ void LLFloaterSnapshot::draw() } } +void LLFloaterSnapshot::onOpen() +{ + gSavedSettings.setBOOL("SnapshotBtnState", TRUE); +} + void LLFloaterSnapshot::onClose(bool app_quitting) { gSnapshotFloaterView->setEnabled(FALSE); // Set invisible so it doesn't eat tooltips. JC gSnapshotFloaterView->setVisible(FALSE); + gSavedSettings.setBOOL("SnapshotBtnState", FALSE); destroy(); } diff --git a/indra/newview/llfloatersnapshot.h b/indra/newview/llfloatersnapshot.h index 14f1872cd..8fb51c945 100644 --- a/indra/newview/llfloatersnapshot.h +++ b/indra/newview/llfloatersnapshot.h @@ -56,6 +56,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ void draw(); /*virtual*/ void onClose(bool app_quitting); + /*virtual*/ void onOpen(); static void show(void*); static void hide(void*); diff --git a/indra/newview/llfloaterstats.cpp b/indra/newview/llfloaterstats.cpp index f19b86040..4d8fd7099 100644 --- a/indra/newview/llfloaterstats.cpp +++ b/indra/newview/llfloaterstats.cpp @@ -107,7 +107,7 @@ void LLFloaterStats::buildStats() LLStatView *render_statviewp = stat_viewp->addStatView("render stat view", "Render", "OpenDebugStatRender", rect); - stat_barp = render_statviewp->addStat("KTris Drawn", &(gPipeline.mTrianglesDrawnStat), "DebugStatModeKTrisDrawnFr"); + stat_barp = render_statviewp->addStat("KTris Drawn", &(LLViewerStats::getInstance()->mTrianglesDrawnStat), "DebugStatModeKTrisDrawnFr"); stat_barp->setUnitLabel("/fr"); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 500.f; @@ -116,7 +116,7 @@ void LLFloaterStats::buildStats() stat_barp->mPrecision = 1; stat_barp->mPerSec = FALSE; - stat_barp = render_statviewp->addStat("KTris Drawn", &(gPipeline.mTrianglesDrawnStat), "DebugStatModeKTrisDrawnSec"); + stat_barp = render_statviewp->addStat("KTris Drawn", &(LLViewerStats::getInstance()->mTrianglesDrawnStat), "DebugStatModeKTrisDrawnSec"); stat_barp->setUnitLabel("/sec"); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 3000.f; @@ -124,14 +124,14 @@ void LLFloaterStats::buildStats() stat_barp->mLabelSpacing = 1000.f; stat_barp->mPrecision = 1; - stat_barp = render_statviewp->addStat("Total Objs", &(gObjectList.mNumObjectsStat), "DebugStatModeTotalObjs"); + stat_barp = render_statviewp->addStat("Total Objs", &(LLViewerStats::getInstance()->mNumObjectsStat), "DebugStatModeTotalObjs"); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 10000.f; stat_barp->mTickSpacing = 2500.f; stat_barp->mLabelSpacing = 5000.f; stat_barp->mPerSec = FALSE; - stat_barp = render_statviewp->addStat("New Objs", &(gObjectList.mNumNewObjectsStat), "DebugStatModeNewObjs"); + stat_barp = render_statviewp->addStat("New Objs", &(LLViewerStats::getInstance()->mNumNewObjectsStat), "DebugStatModeNewObjs"); stat_barp->setLabel("New Objs"); stat_barp->setUnitLabel("/sec"); stat_barp->mMinBar = 0.f; @@ -144,7 +144,7 @@ void LLFloaterStats::buildStats() // Texture statistics LLStatView *texture_statviewp = render_statviewp->addStatView("texture stat view", "Texture", "OpenDebugStatTexture", rect); - stat_barp = texture_statviewp->addStat("Count", &(gTextureList.sNumImagesStat), "DebugStatModeTextureCount"); + stat_barp = texture_statviewp->addStat("Count", &(LLViewerStats::getInstance()->mNumImagesStat), "DebugStatModeTextureCount"); stat_barp->setUnitLabel(""); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 8000.f; @@ -152,7 +152,7 @@ void LLFloaterStats::buildStats() stat_barp->mLabelSpacing = 4000.f; stat_barp->mPerSec = FALSE; - stat_barp = texture_statviewp->addStat("Raw Count", &(gTextureList.sNumRawImagesStat), "DebugStatModeRawCount"); + stat_barp = texture_statviewp->addStat("Raw Count", &(LLViewerStats::getInstance()->mNumRawImagesStat), "DebugStatModeRawCount"); stat_barp->setUnitLabel(""); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 8000.f; @@ -160,7 +160,7 @@ void LLFloaterStats::buildStats() stat_barp->mLabelSpacing = 4000.f; stat_barp->mPerSec = FALSE; - stat_barp = texture_statviewp->addStat("GL Mem", &(gTextureList.sGLTexMemStat), "DebugStatModeGLMem"); + stat_barp = texture_statviewp->addStat("GL Mem", &(LLViewerStats::getInstance()->mGLTexMemStat), "DebugStatModeGLMem"); stat_barp->setUnitLabel(""); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 400.f; @@ -169,7 +169,7 @@ void LLFloaterStats::buildStats() stat_barp->mPrecision = 1; stat_barp->mPerSec = FALSE; - stat_barp = texture_statviewp->addStat("Formatted Mem", &(gTextureList.sFormattedMemStat), "DebugStatModeFormattedMem"); + stat_barp = texture_statviewp->addStat("Formatted Mem", &(LLViewerStats::getInstance()->mFormattedMemStat), "DebugStatModeFormattedMem"); stat_barp->setUnitLabel(""); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 400.f; @@ -178,7 +178,7 @@ void LLFloaterStats::buildStats() stat_barp->mPrecision = 1; stat_barp->mPerSec = FALSE; - stat_barp = texture_statviewp->addStat("Raw Mem", &(gTextureList.sRawMemStat), "DebugStatModeRawMem"); + stat_barp = texture_statviewp->addStat("Raw Mem", &(LLViewerStats::getInstance()->mRawMemStat), "DebugStatModeRawMem"); stat_barp->setUnitLabel(""); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 400.f; @@ -187,7 +187,7 @@ void LLFloaterStats::buildStats() stat_barp->mPrecision = 1; stat_barp->mPerSec = FALSE; - stat_barp = texture_statviewp->addStat("Bound Mem", &(gTextureList.sGLBoundMemStat), "DebugStatModeBoundMem"); + stat_barp = texture_statviewp->addStat("Bound Mem", &(LLViewerStats::getInstance()->mGLBoundMemStat), "DebugStatModeBoundMem"); stat_barp->setUnitLabel(""); stat_barp->mMinBar = 0.f; stat_barp->mMaxBar = 400.f; diff --git a/indra/newview/llfloaterteleport.cpp b/indra/newview/llfloaterteleport.cpp index df2226be2..a4a88bfd0 100644 --- a/indra/newview/llfloaterteleport.cpp +++ b/indra/newview/llfloaterteleport.cpp @@ -82,7 +82,7 @@ public: args["REASON"] = reason; - LLNotifications::instance().add("CouldNotTeleportReason", args); + LLNotificationsUtil::add("CouldNotTeleportReason", args); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); @@ -131,7 +131,7 @@ public: args["REASON"] = "Place Avatar Failed"; //gViewerWindow->alertXml("CouldNotTeleportReason", args); - LLNotifications::instance().add("CouldNotTeleportReason",args); + LLNotificationsUtil::add("CouldNotTeleportReason",args); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); @@ -164,7 +164,7 @@ public: LLSD args; args["REASON"] = "Failed to resolve host."; //gViewerWindow->alertXml("CouldNotTeleportReason", args); - LLNotifications::instance().add("CouldNotTeleportReason", args); + LLNotificationsUtil::add("CouldNotTeleportReason", args); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); return; } diff --git a/indra/newview/llfloaterteleporthistory.cpp b/indra/newview/llfloaterteleporthistory.cpp index f32fa55be..14ddd9541 100644 --- a/indra/newview/llfloaterteleporthistory.cpp +++ b/indra/newview/llfloaterteleporthistory.cpp @@ -34,6 +34,8 @@ #include "linden_common.h" +#include <algorithm> + //MK #include "llworld.h" #include "lleventpoll.h" @@ -48,8 +50,12 @@ #include "llurlsimstring.h" #include "llviewercontrol.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llweb.h" #include "llsdserialize.h" +// [RLVa:KB] +#include "rlvhandler.h" +// [/RLVa:KB] LLFloaterTeleportHistory::LLFloaterTeleportHistory(const LLSD& seed) : LLFloater(std::string("teleporthistory")), @@ -101,12 +107,11 @@ BOOL LLFloaterTeleportHistory::postBuild() void LLFloaterTeleportHistory::addPendingEntry(std::string regionName, S16 x, S16 y, S16 z) { -#ifdef LL_RRINTERFACE_H //MK - if (gRRenabled && gAgent.mRRInterface.mContainsShowloc) - { +// [RLVa:KB] + if(gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC)) return; - } -#endif //mk +// [/RLVa:KB] + // Set pending entry timestamp U32 utc_time; @@ -238,6 +243,13 @@ void LLFloaterTeleportHistory::loadFile(const std::string &file_name) } } } + +struct SortByAge{ + inline bool operator() (LLScrollListItem* const i,LLScrollListItem* const j) const { + return (i->getValue().asInteger()>j->getValue().asInteger()); + } +}; + //static void LLFloaterTeleportHistory::saveFile(const std::string &file_name) { @@ -265,10 +277,7 @@ void LLFloaterTeleportHistory::saveFile(const std::string &file_name) if (pScrollList) { std::vector<LLScrollListItem*> data_list = pScrollList->getAllData(); - struct SortByAge { - bool operator() (LLScrollListItem* i,LLScrollListItem* j) { return (i->getValue().asInteger()>j->getValue().asInteger());} - } sorter; - std::sort(data_list.begin(),data_list.end(),sorter);//Re-sort. Column sorting may have mucked the list up. Newer entries in front. + std::sort(data_list.begin(),data_list.end(),SortByAge());//Re-sort. Column sorting may have mucked the list up. Newer entries in front. for (std::vector<LLScrollListItem*>::iterator itr = data_list.begin(); itr != data_list.end(); ++itr) { //Pack into LLSD mimicing one passed to addElement diff --git a/indra/newview/llfloaterteleporthistory.h b/indra/newview/llfloaterteleporthistory.h index 8b79f2510..7778de60d 100644 --- a/indra/newview/llfloaterteleporthistory.h +++ b/indra/newview/llfloaterteleporthistory.h @@ -43,7 +43,7 @@ #include "llfloater.h" #include "llscrolllistctrl.h" -class LLFloaterTeleportHistory : public LLFloater, public LLUISingleton<LLFloaterTeleportHistory, VisibilityPolicy<LLFloater>> +class LLFloaterTeleportHistory : public LLFloater, public LLUISingleton<LLFloaterTeleportHistory, VisibilityPolicy<LLFloater> > { public: LLFloaterTeleportHistory(const LLSD& seed); diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index d0e41a96a..0a9b5dd1d 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -81,9 +81,13 @@ #include "llviewercontrol.h" #include "llviewerjoystick.h" #include "lluictrlfactory.h" +#if MESH_ENABLED +#include "llmeshrepository.h" +#endif #include "qtoolalign.h" //Thank Qarl! + // Globals LLFloaterTools *gFloaterTools = NULL; @@ -511,9 +515,23 @@ void LLFloaterTools::refresh() childSetTextArg("link_num_obj_count", "[DESC]", desc_string); childSetTextArg("link_num_obj_count", "[NUM]", value_string); - std::string prim_count_string; - LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount()); - childSetTextArg("prim_count", "[COUNT]", prim_count_string); + LLStringUtil::format_map_t selection_args; + selection_args["COUNT"] = llformat("%.1d", (S32)prim_count); +#if MESH_ENABLED + if(gMeshRepo.meshRezEnabled()) + { + F32 link_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectCost(); + LLStringUtil::format_map_t prim_equiv_args; + prim_equiv_args["SEL_WEIGHT"] = llformat("%.1d", (S32)link_cost); + selection_args["PE_STRING"] = getString("status_selectprimequiv", prim_equiv_args); + } + else +#endif //MESH_ENABLED + { + selection_args["PE_STRING"] = ""; + } + std::string prim_count_string = getString("status_selectcount",selection_args); + childSetText("prim_count", prim_count_string); // Refresh child tabs mPanelPermissions->refresh(); diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp index 76ea40008..8abbc2d26 100644 --- a/indra/newview/llfloatertopobjects.cpp +++ b/indra/newview/llfloatertopobjects.cpp @@ -41,6 +41,7 @@ #include "llbutton.h" #include "llfloatergodtools.h" #include "llfloateravatarinfo.h" +#include "llnotificationsutil.h" #include "llparcel.h" #include "llscrolllistctrl.h" #include "lllineeditor.h" @@ -398,7 +399,7 @@ void LLFloaterTopObjects::doToObjects(int action, bool all) //static bool LLFloaterTopObjects::callbackReturnAll(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { sInstance->doToObjects(ACTION_RETURN, true); @@ -408,7 +409,7 @@ bool LLFloaterTopObjects::callbackReturnAll(const LLSD& notification, const LLSD void LLFloaterTopObjects::onReturnAll(void* data) { - LLNotifications::instance().add("ReturnAllTopObjects", LLSD(), LLSD(), &callbackReturnAll); + LLNotificationsUtil::add("ReturnAllTopObjects", LLSD(), LLSD(), &callbackReturnAll); } @@ -541,7 +542,7 @@ void LLFloaterTopObjects::onTP(void* data) //static bool LLFloaterTopObjects::callbackDisableAll(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0) { sInstance->doToObjects(ACTION_DISABLE, true); @@ -551,7 +552,7 @@ bool LLFloaterTopObjects::callbackDisableAll(const LLSD& notification, const LLS void LLFloaterTopObjects::onDisableAll(void* data) { - LLNotifications::instance().add("DisableAllTopObjects", LLSD(), LLSD(), callbackDisableAll); + LLNotificationsUtil::add("DisableAllTopObjects", LLSD(), LLSD(), callbackDisableAll); } void LLFloaterTopObjects::onDisableSelected(void* data) diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp index 2dedc79af..d83dab9fd 100644 --- a/indra/newview/llfloatertos.cpp +++ b/indra/newview/llfloatertos.cpp @@ -46,6 +46,7 @@ #include "llbutton.h" #include "llhttpclient.h" #include "llhttpstatuscodes.h" // for HTTP_FOUND +#include "llnotificationsutil.h" #include "llradiogroup.h" #include "lltextbox.h" #include "llui.h" @@ -254,7 +255,7 @@ void LLFloaterTOS::onCancel( void* userdata ) { LLFloaterTOS* self = (LLFloaterTOS*) userdata; llinfos << "User disagrees with TOS." << llendl; - LLNotifications::instance().add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done); + LLNotificationsUtil::add("MustAgreeToLogIn", LLSD(), LLSD(), login_alert_done); LLStartUp::setStartupState( STATE_LOGIN_SHOW ); self->mLoadCompleteCount = 0; // reset counter for next time we come to TOS self->close(); // destroys this object diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index 8d483e59e..35dc9ddda 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -38,6 +38,7 @@ // project includes #include "llcombobox.h" +#include "llnotificationsutil.h" #include "llurlhistory.h" #include "lluictrlfactory.h" #include "llwindow.h" @@ -263,13 +264,13 @@ void LLFloaterURLEntry::onBtnCancel( void* userdata ) //----------------------------------------------------------------------------- void LLFloaterURLEntry::onBtnClear( void* userdata ) { - LLNotifications::instance().add( "ConfirmClearMediaUrlList", LLSD(), LLSD(), + LLNotificationsUtil::add( "ConfirmClearMediaUrlList", LLSD(), LLSD(), boost::bind(&LLFloaterURLEntry::callback_clear_url_list, (LLFloaterURLEntry*)userdata, _1, _2) ); } bool LLFloaterURLEntry::callback_clear_url_list(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if ( option == 0 ) // YES { // clear saved list diff --git a/indra/newview/llfloaterwater.cpp b/indra/newview/llfloaterwater.cpp index 4ea21cf10..e35d7e6c0 100644 --- a/indra/newview/llfloaterwater.cpp +++ b/indra/newview/llfloaterwater.cpp @@ -49,6 +49,7 @@ #include "llfloaterdaycycle.h" #include "llboost.h" #include "llmultisliderctrl.h" +#include "llnotificationsutil.h" #include "v4math.h" #include "llviewerdisplay.h" @@ -74,9 +75,9 @@ LLFloaterWater::LLFloaterWater() : LLFloater(std::string("water floater")) if(comboBox != NULL) { - std::map<std::string, LLWaterParamSet>::iterator mIt = - LLWaterParamManager::instance()->mParamList.begin(); - for(; mIt != LLWaterParamManager::instance()->mParamList.end(); mIt++) + std::map<std::string, LLWaterParamSet>::const_iterator mIt = + LLWaterParamManager::getInstance()->getPresets().begin(); + for(; mIt != LLWaterParamManager::getInstance()->getPresets().end(); mIt++) { comboBox->add(mIt->first); } @@ -123,7 +124,7 @@ void LLFloaterWater::initCallbacks(void) { initHelpBtn("WaterWave1Help", "HelpWaterWave1"); initHelpBtn("WaterWave2Help", "HelpWaterWave2"); - LLWaterParamManager * param_mgr = LLWaterParamManager::instance(); + LLWaterParamManager * param_mgr = LLWaterParamManager::getInstance(); childSetCommitCallback("WaterFogColor", onWaterFogColorMoved, ¶m_mgr->mFogColor); @@ -197,15 +198,15 @@ bool LLFloaterWater::newPromptCallback(const LLSD& notification, const LLSD& res if(option == 0) { LLComboBox* comboBox = sWaterMenu->getChild<LLComboBox>( "WaterPresetsCombo"); - LLWaterParamManager * param_mgr = LLWaterParamManager::instance(); + LLWaterParamManager * param_mgr = LLWaterParamManager::getInstance(); // add the current parameters to the list // see if it's there first - std::map<std::string, LLWaterParamSet>::iterator mIt = - param_mgr->mParamList.find(text); + std::map<std::string, LLWaterParamSet>::const_iterator mIt = + param_mgr->getPresets().find(text); // if not there, add a new one - if(mIt == param_mgr->mParamList.end()) + if(mIt == param_mgr->getPresets().end()) { param_mgr->addParamSet(text, param_mgr->mCurParams); comboBox->add(text); @@ -219,7 +220,7 @@ bool LLFloaterWater::newPromptCallback(const LLSD& notification, const LLSD& res } else { - LLNotifications::instance().add("ExistsWaterPresetAlert"); + LLNotificationsUtil::add("ExistsWaterPresetAlert"); } } return false; @@ -229,7 +230,7 @@ void LLFloaterWater::syncMenu() { bool err; - LLWaterParamManager * param_mgr = LLWaterParamManager::instance(); + LLWaterParamManager * param_mgr = LLWaterParamManager::getInstance(); LLWaterParamSet & current_params = param_mgr->mCurParams; @@ -337,9 +338,9 @@ void LLFloaterWater::onVector3ControlXMoved(LLUICtrl* ctrl, void* userData) vectorControl->mX = sldrCtrl->getValueF32(); - vectorControl->update(LLWaterParamManager::instance()->mCurParams); + vectorControl->update(LLWaterParamManager::getInstance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + LLWaterParamManager::getInstance()->propagateParameters(); } // vector control callbacks @@ -350,9 +351,9 @@ void LLFloaterWater::onVector3ControlYMoved(LLUICtrl* ctrl, void* userData) vectorControl->mY = sldrCtrl->getValueF32(); - vectorControl->update(LLWaterParamManager::instance()->mCurParams); + vectorControl->update(LLWaterParamManager::getInstance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + LLWaterParamManager::getInstance()->propagateParameters(); } // vector control callbacks @@ -363,9 +364,9 @@ void LLFloaterWater::onVector3ControlZMoved(LLUICtrl* ctrl, void* userData) vectorControl->mZ = sldrCtrl->getValueF32(); - vectorControl->update(LLWaterParamManager::instance()->mCurParams); + vectorControl->update(LLWaterParamManager::getInstance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + LLWaterParamManager::getInstance()->propagateParameters(); } @@ -377,9 +378,9 @@ void LLFloaterWater::onVector2ControlXMoved(LLUICtrl* ctrl, void* userData) vectorControl->mX = sldrCtrl->getValueF32(); - vectorControl->update(LLWaterParamManager::instance()->mCurParams); + vectorControl->update(LLWaterParamManager::getInstance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + LLWaterParamManager::getInstance()->propagateParameters(); } // vector control callbacks @@ -390,9 +391,9 @@ void LLFloaterWater::onVector2ControlYMoved(LLUICtrl* ctrl, void* userData) vectorControl->mY = sldrCtrl->getValueF32(); - vectorControl->update(LLWaterParamManager::instance()->mCurParams); + vectorControl->update(LLWaterParamManager::getInstance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + LLWaterParamManager::getInstance()->propagateParameters(); } // color control callbacks @@ -415,9 +416,9 @@ void LLFloaterWater::onColorControlRMoved(LLUICtrl* ctrl, void* userData) sWaterMenu->childSetValue(name, colorControl->mR); } - colorControl->update(LLWaterParamManager::instance()->mCurParams); + colorControl->update(LLWaterParamManager::getInstance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + LLWaterParamManager::getInstance()->propagateParameters(); } void LLFloaterWater::onColorControlGMoved(LLUICtrl* ctrl, void* userData) @@ -440,9 +441,9 @@ void LLFloaterWater::onColorControlGMoved(LLUICtrl* ctrl, void* userData) } - colorControl->update(LLWaterParamManager::instance()->mCurParams); + colorControl->update(LLWaterParamManager::getInstance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + LLWaterParamManager::getInstance()->propagateParameters(); } void LLFloaterWater::onColorControlBMoved(LLUICtrl* ctrl, void* userData) @@ -464,9 +465,9 @@ void LLFloaterWater::onColorControlBMoved(LLUICtrl* ctrl, void* userData) sWaterMenu->childSetValue(name, colorControl->mB); } - colorControl->update(LLWaterParamManager::instance()->mCurParams); + colorControl->update(LLWaterParamManager::getInstance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + LLWaterParamManager::getInstance()->propagateParameters(); } void LLFloaterWater::onColorControlAMoved(LLUICtrl* ctrl, void* userData) @@ -476,9 +477,9 @@ void LLFloaterWater::onColorControlAMoved(LLUICtrl* ctrl, void* userData) colorControl->mA = sldrCtrl->getValueF32(); - colorControl->update(LLWaterParamManager::instance()->mCurParams); + colorControl->update(LLWaterParamManager::getInstance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + LLWaterParamManager::getInstance()->propagateParameters(); } @@ -538,8 +539,8 @@ void LLFloaterWater::onColorControlIMoved(LLUICtrl* ctrl, void* userData) } // now update the current parameters and send them to shaders - colorControl->update(LLWaterParamManager::instance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + colorControl->update(LLWaterParamManager::getInstance()->mCurParams); + LLWaterParamManager::getInstance()->propagateParameters(); } void LLFloaterWater::onExpFloatControlMoved(LLUICtrl* ctrl, void* userData) @@ -549,10 +550,10 @@ void LLFloaterWater::onExpFloatControlMoved(LLUICtrl* ctrl, void* userData) F32 val = sldrCtrl->getValueF32(); expFloatControl->mExp = val; - LLWaterParamManager::instance()->setDensitySliderValue(val); + LLWaterParamManager::getInstance()->setDensitySliderValue(val); - expFloatControl->update(LLWaterParamManager::instance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + expFloatControl->update(LLWaterParamManager::getInstance()->mCurParams); + LLWaterParamManager::getInstance()->propagateParameters(); } void LLFloaterWater::onFloatControlMoved(LLUICtrl* ctrl, void* userData) @@ -562,8 +563,8 @@ void LLFloaterWater::onFloatControlMoved(LLUICtrl* ctrl, void* userData) floatControl->mX = sldrCtrl->getValueF32() / floatControl->mMult; - floatControl->update(LLWaterParamManager::instance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + floatControl->update(LLWaterParamManager::getInstance()->mCurParams); + LLWaterParamManager::getInstance()->propagateParameters(); } void LLFloaterWater::onWaterFogColorMoved(LLUICtrl* ctrl, void* userData) { @@ -571,8 +572,8 @@ void LLFloaterWater::onWaterFogColorMoved(LLUICtrl* ctrl, void* userData) WaterColorControl * colorControl = static_cast<WaterColorControl *>(userData); *colorControl = swatch->get(); - colorControl->update(LLWaterParamManager::instance()->mCurParams); - LLWaterParamManager::instance()->propagateParameters(); + colorControl->update(LLWaterParamManager::getInstance()->mCurParams); + LLWaterParamManager::getInstance()->propagateParameters(); } void LLFloaterWater::onBoolToggle(LLUICtrl* ctrl, void* userData) @@ -587,12 +588,12 @@ void LLFloaterWater::onNormalMapPicked(LLUICtrl* ctrl, void* userData) { LLTextureCtrl* textCtrl = static_cast<LLTextureCtrl*>(ctrl); LLUUID textID = textCtrl->getImageAssetID(); - LLWaterParamManager::instance()->setNormalMapID(textID); + LLWaterParamManager::getInstance()->setNormalMapID(textID); } void LLFloaterWater::onNewPreset(void* userData) { - LLNotifications::instance().add("NewWaterPreset", LLSD(), LLSD(), newPromptCallback); + LLNotificationsUtil::add("NewWaterPreset", LLSD(), LLSD(), newPromptCallback); } void LLFloaterWater::onSavePreset(void* userData) @@ -606,7 +607,7 @@ void LLFloaterWater::onSavePreset(void* userData) return; } - LLWaterParamManager::instance()->mCurParams.mName = + LLWaterParamManager::getInstance()->mCurParams.mName = comboBox->getSelectedItemLabel(); // check to see if it's a default and shouldn't be overwritten @@ -614,11 +615,11 @@ void LLFloaterWater::onSavePreset(void* userData) comboBox->getSelectedItemLabel()); if(sIt != sDefaultPresets.end() && !gSavedSettings.getBOOL("WaterEditPresets")) { - LLNotifications::instance().add("WLNoEditDefault"); + LLNotificationsUtil::add("WLNoEditDefault"); return; } - LLNotifications::instance().add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback); + LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback); } bool LLFloaterWater::saveAlertCallback(const LLSD& notification, const LLSD& response) @@ -627,7 +628,7 @@ bool LLFloaterWater::saveAlertCallback(const LLSD& notification, const LLSD& res // if they choose save, do it. Otherwise, don't do anything if(option == 0) { - LLWaterParamManager * param_mgr = LLWaterParamManager::instance(); + LLWaterParamManager * param_mgr = LLWaterParamManager::getInstance(); param_mgr->setParamSet( param_mgr->mCurParams.mName, @@ -650,7 +651,7 @@ void LLFloaterWater::onDeletePreset(void* userData) LLSD args; args["SKY"] = combo_box->getSelectedValue().asString(); - LLNotifications::instance().add("WLDeletePresetAlert", args, LLSD(), deleteAlertCallback); + LLNotificationsUtil::add("WLDeletePresetAlert", args, LLSD(), deleteAlertCallback); } bool LLFloaterWater::deleteAlertCallback(const LLSD& notification, const LLSD& response) @@ -677,11 +678,11 @@ bool LLFloaterWater::deleteAlertCallback(const LLSD& notification, const LLSD& r std::set<std::string>::iterator sIt = sDefaultPresets.find(name); if(sIt != sDefaultPresets.end()) { - LLNotifications::instance().add("WaterNoEditDefault"); + LLNotificationsUtil::add("WaterNoEditDefault"); return false; } - LLWaterParamManager::instance()->removeParamSet(name, true); + LLWaterParamManager::getInstance()->removeParamSet(name, true); // remove and choose another S32 new_index = combo_box->getCurrentIndex(); @@ -720,7 +721,7 @@ void LLFloaterWater::onChangePresetName(LLUICtrl* ctrl, void * userData) return; } - LLWaterParamManager::instance()->loadPreset( + LLWaterParamManager::getInstance()->loadPreset( combo_box->getSelectedValue().asString()); sWaterMenu->syncMenu(); } diff --git a/indra/newview/llfloaterwindlight.cpp b/indra/newview/llfloaterwindlight.cpp index 898c5dc2a..dba360b88 100644 --- a/indra/newview/llfloaterwindlight.cpp +++ b/indra/newview/llfloaterwindlight.cpp @@ -48,6 +48,7 @@ #include "lllineeditor.h" #include "llfloaterdaycycle.h" #include "llboost.h" +#include "llnotificationsutil.h" #include "v4math.h" #include "llviewerdisplay.h" @@ -75,9 +76,9 @@ LLFloaterWindLight::LLFloaterWindLight() : LLFloater(std::string("windlight floa if(comboBox != NULL) { - std::map<std::string, LLWLParamSet>::iterator mIt = - LLWLParamManager::instance()->mParamList.begin(); - for(; mIt != LLWLParamManager::instance()->mParamList.end(); mIt++) + std::map<std::string, LLWLParamSet>::const_iterator mIt = + LLWLParamManager::getInstance()->getPresets().begin(); + for(; mIt != LLWLParamManager::getInstance()->getPresets().end(); mIt++) { comboBox->add(mIt->first); } @@ -141,7 +142,7 @@ void LLFloaterWindLight::initCallbacks(void) { initHelpBtn("WLClassicCloudsHelp", "HelpClassicClouds"); - LLWLParamManager * param_mgr = LLWLParamManager::instance(); + LLWLParamManager * param_mgr = LLWLParamManager::getInstance(); // blue horizon childSetCommitCallback("WLBlueHorizonR", onColorControlRMoved, ¶m_mgr->mBlueHorizon); @@ -267,14 +268,14 @@ bool LLFloaterWindLight::newPromptCallback(const LLSD& notification, const LLSD& // add the current parameters to the list // see if it's there first - std::map<std::string, LLWLParamSet>::iterator mIt = - LLWLParamManager::instance()->mParamList.find(text); + std::map<std::string, LLWLParamSet>::const_iterator mIt = + LLWLParamManager::getInstance()->getPresets().find(text); // if not there, add a new one - if(mIt == LLWLParamManager::instance()->mParamList.end()) + if(mIt == LLWLParamManager::getInstance()->getPresets().end()) { - LLWLParamManager::instance()->addParamSet(text, - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->addParamSet(text, + LLWLParamManager::getInstance()->mCurParams); comboBox->add(text); comboBox->sortByName(); @@ -292,13 +293,13 @@ bool LLFloaterWindLight::newPromptCallback(const LLSD& notification, const LLSD& keyCombo->add(text); keyCombo->sortByName(); } - LLWLParamManager::instance()->savePreset(text); + LLWLParamManager::getInstance()->savePreset(text); // otherwise, send a message to the user } else { - LLNotifications::instance().add("ExistsSkyPresetAlert"); + LLNotificationsUtil::add("ExistsSkyPresetAlert"); } } return false; @@ -308,7 +309,7 @@ void LLFloaterWindLight::syncMenu() { bool err; - LLWLParamManager * param_mgr = LLWLParamManager::instance(); + LLWLParamManager * param_mgr = LLWLParamManager::getInstance(); LLWLParamSet& currentParams = param_mgr->mCurParams; //std::map<std::string, LLVector4> & currentParams = param_mgr->mCurParams.mParamValues; @@ -518,9 +519,9 @@ void LLFloaterWindLight::onColorControlRMoved(LLUICtrl* ctrl, void* userData) } } - colorControl->update(LLWLParamManager::instance()->mCurParams); + colorControl->update(LLWLParamManager::getInstance()->mCurParams); - LLWLParamManager::instance()->propagateParameters(); + LLWLParamManager::getInstance()->propagateParameters(); } void LLFloaterWindLight::onColorControlGMoved(LLUICtrl* ctrl, void* userData) @@ -554,9 +555,9 @@ void LLFloaterWindLight::onColorControlGMoved(LLUICtrl* ctrl, void* userData) } } - colorControl->update(LLWLParamManager::instance()->mCurParams); + colorControl->update(LLWLParamManager::getInstance()->mCurParams); - LLWLParamManager::instance()->propagateParameters(); + LLWLParamManager::getInstance()->propagateParameters(); } void LLFloaterWindLight::onColorControlBMoved(LLUICtrl* ctrl, void* userData) @@ -590,9 +591,9 @@ void LLFloaterWindLight::onColorControlBMoved(LLUICtrl* ctrl, void* userData) } } - colorControl->update(LLWLParamManager::instance()->mCurParams); + colorControl->update(LLWLParamManager::getInstance()->mCurParams); - LLWLParamManager::instance()->propagateParameters(); + LLWLParamManager::getInstance()->propagateParameters(); } void LLFloaterWindLight::onColorControlIMoved(LLUICtrl* ctrl, void* userData) @@ -679,8 +680,8 @@ void LLFloaterWindLight::onColorControlIMoved(LLUICtrl* ctrl, void* userData) } // now update the current parameters and send them to shaders - colorControl->update(LLWLParamManager::instance()->mCurParams); - LLWLParamManager::instance()->propagateParameters(); + colorControl->update(LLWLParamManager::getInstance()->mCurParams); + LLWLParamManager::getInstance()->propagateParameters(); } /// GLOW SPECIFIC CODE @@ -694,8 +695,8 @@ void LLFloaterWindLight::onGlowRMoved(LLUICtrl* ctrl, void* userData) // scaled by 20 colorControl->r = (2 - sldrCtrl->getValueF32()) * 20; - colorControl->update(LLWLParamManager::instance()->mCurParams); - LLWLParamManager::instance()->propagateParameters(); + colorControl->update(LLWLParamManager::getInstance()->mCurParams); + LLWLParamManager::getInstance()->propagateParameters(); } /// \NOTE that we want NEGATIVE (-) B @@ -709,8 +710,8 @@ void LLFloaterWindLight::onGlowBMoved(LLUICtrl* ctrl, void* userData) /// \NOTE that we want NEGATIVE (-) B and NOT by 20 as 20 is too big colorControl->b = -sldrCtrl->getValueF32() * 5; - colorControl->update(LLWLParamManager::instance()->mCurParams); - LLWLParamManager::instance()->propagateParameters(); + colorControl->update(LLWLParamManager::getInstance()->mCurParams); + LLWLParamManager::getInstance()->propagateParameters(); } void LLFloaterWindLight::onFloatControlMoved(LLUICtrl* ctrl, void* userData) @@ -722,8 +723,8 @@ void LLFloaterWindLight::onFloatControlMoved(LLUICtrl* ctrl, void* userData) floatControl->x = sldrCtrl->getValueF32() / floatControl->mult; - floatControl->update(LLWLParamManager::instance()->mCurParams); - LLWLParamManager::instance()->propagateParameters(); + floatControl->update(LLWLParamManager::getInstance()->mCurParams); + LLWLParamManager::getInstance()->propagateParameters(); } void LLFloaterWindLight::onBoolToggle(LLUICtrl* ctrl, void* userData) @@ -750,7 +751,7 @@ void LLFloaterWindLight::onSunMoved(LLUICtrl* ctrl, void* userData) WLColorControl * colorControl = static_cast<WLColorControl *>(userData); // get the two angles - LLWLParamManager * param_mgr = LLWLParamManager::instance(); + LLWLParamManager * param_mgr = LLWLParamManager::getInstance(); param_mgr->mCurParams.setSunAngle(F_TWO_PI * sunSldr->getValueF32()); param_mgr->mCurParams.setEastAngle(F_TWO_PI * eastSldr->getValueF32()); @@ -775,7 +776,7 @@ void LLFloaterWindLight::onFloatTweakMoved(LLUICtrl* ctrl, void* userData) F32 * tweak = static_cast<F32 *>(userData); (*tweak) = sldrCtrl->getValueF32(); - LLWLParamManager::instance()->propagateParameters(); + LLWLParamManager::getInstance()->propagateParameters(); } void LLFloaterWindLight::onStarAlphaMoved(LLUICtrl* ctrl, void* userData) @@ -784,12 +785,12 @@ void LLFloaterWindLight::onStarAlphaMoved(LLUICtrl* ctrl, void* userData) LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); - LLWLParamManager::instance()->mCurParams.setStarBrightness(sldrCtrl->getValueF32()); + LLWLParamManager::getInstance()->mCurParams.setStarBrightness(sldrCtrl->getValueF32()); } void LLFloaterWindLight::onNewPreset(void* userData) { - LLNotifications::instance().add("NewSkyPreset", LLSD(), LLSD(), newPromptCallback); + LLNotificationsUtil::add("NewSkyPreset", LLSD(), LLSD(), newPromptCallback); } void LLFloaterWindLight::onSavePreset(void* userData) @@ -809,14 +810,14 @@ void LLFloaterWindLight::onSavePreset(void* userData) comboBox->getSelectedItemLabel()); if(sIt != sDefaultPresets.end() && !gSavedSettings.getBOOL("SkyEditPresets")) { - LLNotifications::instance().add("WLNoEditDefault"); + LLNotificationsUtil::add("WLNoEditDefault"); return; } - LLWLParamManager::instance()->mCurParams.mName = + LLWLParamManager::getInstance()->mCurParams.mName = comboBox->getSelectedItemLabel(); - LLNotifications::instance().add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback); + LLNotificationsUtil::add("WLSavePresetAlert", LLSD(), LLSD(), saveAlertCallback); } bool LLFloaterWindLight::saveAlertCallback(const LLSD& notification, const LLSD& response) @@ -825,7 +826,7 @@ bool LLFloaterWindLight::saveAlertCallback(const LLSD& notification, const LLSD& // if they choose save, do it. Otherwise, don't do anything if(option == 0) { - LLWLParamManager * param_mgr = LLWLParamManager::instance(); + LLWLParamManager * param_mgr = LLWLParamManager::getInstance(); param_mgr->setParamSet(param_mgr->mCurParams.mName, param_mgr->mCurParams); @@ -847,7 +848,7 @@ void LLFloaterWindLight::onDeletePreset(void* userData) LLSD args; args["SKY"] = combo_box->getSelectedValue().asString(); - LLNotifications::instance().add("WLDeletePresetAlert", args, LLSD(), + LLNotificationsUtil::add("WLDeletePresetAlert", args, LLSD(), boost::bind(&LLFloaterWindLight::deleteAlertCallback, sWindLight, _1, _2)); } @@ -878,11 +879,11 @@ bool LLFloaterWindLight::deleteAlertCallback(const LLSD& notification, const LLS std::set<std::string>::iterator sIt = sDefaultPresets.find(name); if(sIt != sDefaultPresets.end()) { - LLNotifications::instance().add("WLNoEditDefault"); + LLNotificationsUtil::add("WLNoEditDefault"); return false; } - LLWLParamManager::instance()->removeParamSet(name, true); + LLWLParamManager::getInstance()->removeParamSet(name, true); // remove and choose another S32 new_index = combo_box->getCurrentIndex(); @@ -922,7 +923,7 @@ void LLFloaterWindLight::onChangePresetName(LLUICtrl* ctrl, void * userData) return; } - LLWLParamManager::instance()->loadPreset( + LLWLParamManager::getInstance()->loadPreset( combo_box->getSelectedValue().asString()); sWindLight->syncMenu(); } @@ -939,7 +940,7 @@ void LLFloaterWindLight::onCloudScrollXMoved(LLUICtrl* ctrl, void* userData) LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); // *HACK all cloud scrolling is off by an additive of 10. - LLWLParamManager::instance()->mCurParams.setCloudScrollX(sldrCtrl->getValueF32() + 10.0f); + LLWLParamManager::getInstance()->mCurParams.setCloudScrollX(sldrCtrl->getValueF32() + 10.0f); } void LLFloaterWindLight::onCloudScrollYMoved(LLUICtrl* ctrl, void* userData) @@ -949,7 +950,7 @@ void LLFloaterWindLight::onCloudScrollYMoved(LLUICtrl* ctrl, void* userData) LLSliderCtrl* sldrCtrl = static_cast<LLSliderCtrl*>(ctrl); // *HACK all cloud scrolling is off by an additive of 10. - LLWLParamManager::instance()->mCurParams.setCloudScrollY(sldrCtrl->getValueF32() + 10.0f); + LLWLParamManager::getInstance()->mCurParams.setCloudScrollY(sldrCtrl->getValueF32() + 10.0f); } void LLFloaterWindLight::onCloudScrollXToggled(LLUICtrl* ctrl, void* userData) @@ -959,7 +960,7 @@ void LLFloaterWindLight::onCloudScrollXToggled(LLUICtrl* ctrl, void* userData) LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl); bool lock = cbCtrl->get(); - LLWLParamManager::instance()->mCurParams.setEnableCloudScrollX(!lock); + LLWLParamManager::getInstance()->mCurParams.setEnableCloudScrollX(!lock); LLSliderCtrl* sldr = sWindLight->getChild<LLSliderCtrl>( "WLCloudScrollX"); @@ -981,7 +982,7 @@ void LLFloaterWindLight::onCloudScrollYToggled(LLUICtrl* ctrl, void* userData) LLCheckBoxCtrl* cbCtrl = static_cast<LLCheckBoxCtrl*>(ctrl); bool lock = cbCtrl->get(); - LLWLParamManager::instance()->mCurParams.setEnableCloudScrollY(!lock); + LLWLParamManager::getInstance()->mCurParams.setEnableCloudScrollY(!lock); LLSliderCtrl* sldr = sWindLight->getChild<LLSliderCtrl>( "WLCloudScrollY"); @@ -998,6 +999,6 @@ void LLFloaterWindLight::onCloudScrollYToggled(LLUICtrl* ctrl, void* userData) void LLFloaterWindLight::deactivateAnimator() { - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; } diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp index 0dde8c746..fa514014d 100644 --- a/indra/newview/llfloaterworldmap.cpp +++ b/indra/newview/llfloaterworldmap.cpp @@ -43,6 +43,7 @@ #include "llagent.h" #include "llagentcamera.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llbutton.h" #include "llcallingcard.h" #include "llcolorscheme.h" @@ -52,6 +53,7 @@ #include "llfirstuse.h" #include "llfocusmgr.h" #include "lllandmarklist.h" +#include "llnotificationsutil.h" #include "lllineeditor.h" #include "llpreviewlandmark.h" #include "llregionhandle.h" @@ -502,17 +504,26 @@ void LLFloaterWorldMap::draw() getDragHandle()->setMouseOpaque(TRUE); //RN: snaps to zoom value because interpolation caused jitter in the text rendering - if (!mZoomTimer.getStarted() && mCurZoomVal != (F32)childGetValue("zoom slider").asReal()) + F32 interp = 1.f; + if (!mZoomTimer.getStarted()) { - mZoomTimer.start(); + mCurZoomValInterpolationStart = mCurZoomVal; + if (mCurZoomVal < (F32)childGetValue("zoom slider").asReal()) + { + mZoomTimer.start(); + } } - F32 interp = mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME; - if (interp > 1.f) + if (mZoomTimer.getStarted()) + { + interp = mZoomTimer.getElapsedTimeF32() / MAP_ZOOM_TIME; + } + if (interp >= 1.f) { interp = 1.f; mZoomTimer.stop(); } - mCurZoomVal = lerp(mCurZoomVal, (F32)childGetValue("zoom slider").asReal(), interp); + // Interpolate between mCurZoomValInterpolationStart and "zoom slider". + mCurZoomVal = lerp(mCurZoomValInterpolationStart, (F32)childGetValue("zoom slider").asReal(), interp); F32 map_scale = 256.f*pow(2.f, mCurZoomVal); LLWorldMapView::setScale( map_scale ); @@ -1331,7 +1342,7 @@ void LLFloaterWorldMap::onCopySLURL(void* data) LLSD args; args["SLURL"] = self->mSLURL; - LLNotifications::instance().add("CopySLURL", args); + LLNotificationsUtil::add("CopySLURL", args); } void LLFloaterWorldMap::onCheckEvents(LLUICtrl*, void* data) diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h index 5c8c976d6..03baa3eef 100644 --- a/indra/newview/llfloaterworldmap.h +++ b/indra/newview/llfloaterworldmap.h @@ -164,6 +164,7 @@ protected: // Sets sMapScale, in pixels per region F32 mCurZoomVal; + F32 mCurZoomValInterpolationStart; // Used during mZoomTimer interpolation. LLFrameTimer mZoomTimer; LLDynamicArray<LLUUID> mLandmarkAssetIDList; diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 5878a8b48..73e902df0 100644 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -43,6 +43,7 @@ #include "lldatapacker.h" #include "llinventory.h" #include "llmultigesture.h" +#include "llnotificationsutil.h" #include "llstl.h" #include "llstring.h" // todo: remove #include "llvfile.h" @@ -53,7 +54,6 @@ #include "llchatbar.h" #include "lldelayedgestureerror.h" #include "llinventorymodel.h" -#include "llnotify.h" #include "llviewermessage.h" #include "llvoavatar.h" #include "llviewerstats.h" @@ -64,8 +64,6 @@ #include "shcommandhandler.h" #endif //shy_mod -LLGestureManager gGestureManager; - // Longest time, in seconds, to wait for all animations to stop playing const F32 MAX_WAIT_ANIM_SECS = 30.f; @@ -75,7 +73,7 @@ static const LLUUID& get_linked_uuid(const LLUUID& item_id); // Lightweight constructor. // init() does the heavy lifting. -LLGestureManager::LLGestureManager() +LLGestureMgr::LLGestureMgr() : mValid(FALSE), mPlaying(), mActive(), @@ -84,7 +82,7 @@ LLGestureManager::LLGestureManager() // We own the data for gestures, so clean them up. -LLGestureManager::~LLGestureManager() +LLGestureMgr::~LLGestureMgr() { item_map_t::iterator it; for (it = mActive.begin(); it != mActive.end(); ++it) @@ -97,7 +95,7 @@ LLGestureManager::~LLGestureManager() } -void LLGestureManager::init() +void LLGestureMgr::init() { // TODO } @@ -105,10 +103,12 @@ void LLGestureManager::init() // Use this version when you have the item_id but not the asset_id, // and you KNOW the inventory is loaded. -void LLGestureManager::activateGesture(const LLUUID& item_id) +void LLGestureMgr::activateGesture(const LLUUID& item_id) { LLViewerInventoryItem* item = gInventory.getItem(item_id); if (!item) return; + if (item->getType() != LLAssetType::AT_GESTURE) + return; LLUUID asset_id = item->getAssetUUID(); @@ -121,7 +121,7 @@ void LLGestureManager::activateGesture(const LLUUID& item_id) } -void LLGestureManager::activateGestures(LLViewerInventoryItem::item_array_t& items) +void LLGestureMgr::activateGestures(LLViewerInventoryItem::item_array_t& items) { // Load up the assets S32 count = 0; @@ -214,7 +214,10 @@ struct LLLoadInfo // If inform_server is true, will send a message upstream to update // the user_gesture_active table. -void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id, +/** + * It will load a gesture from remote storage + */ +void LLGestureMgr::activateGestureWithAsset(const LLUUID& item_id, const LLUUID& asset_id, BOOL inform_server, BOOL deactivate_similar) @@ -223,7 +226,7 @@ void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id, if( !gAssetStorage ) { - llwarns << "LLGestureManager::activateGestureWithAsset without valid gAssetStorage" << llendl; + llwarns << "LLGestureMgr::activateGestureWithAsset without valid gAssetStorage" << llendl; return; } // If gesture is already active, nothing to do. @@ -265,7 +268,7 @@ void LLGestureManager::activateGestureWithAsset(const LLUUID& item_id, } -void LLGestureManager::deactivateGesture(const LLUUID& item_id) +void LLGestureMgr::deactivateGesture(const LLUUID& item_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); item_map_t::iterator it = mActive.find(base_item_id); @@ -308,10 +311,10 @@ void LLGestureManager::deactivateGesture(const LLUUID& item_id) } -void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id) +void LLGestureMgr::deactivateSimilarGestures(LLMultiGesture* in, const LLUUID& in_item_id) { const LLUUID& base_in_item_id = get_linked_uuid(in_item_id); - std::vector<LLUUID> gest_item_ids; + uuid_vec_t gest_item_ids; // Deactivate all gestures that match item_map_t::iterator it; @@ -350,7 +353,7 @@ void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUI // Inform database of the change LLMessageSystem* msg = gMessageSystem; BOOL start_message = TRUE; - std::vector<LLUUID>::const_iterator vit = gest_item_ids.begin(); + uuid_vec_t::const_iterator vit = gest_item_ids.begin(); while (vit != gest_item_ids.end()) { if (start_message) @@ -395,7 +398,7 @@ void LLGestureManager::deactivateSimilarGestures(LLMultiGesture* in, const LLUUI } -BOOL LLGestureManager::isGestureActive(const LLUUID& item_id) +BOOL LLGestureMgr::isGestureActive(const LLUUID& item_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); item_map_t::iterator it = mActive.find(base_item_id); @@ -403,7 +406,7 @@ BOOL LLGestureManager::isGestureActive(const LLUUID& item_id) } -BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id) +BOOL LLGestureMgr::isGesturePlaying(const LLUUID& item_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); item_map_t::iterator it = mActive.find(base_item_id); @@ -415,7 +418,17 @@ BOOL LLGestureManager::isGesturePlaying(const LLUUID& item_id) return gesture->mPlaying; } -void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id) +BOOL LLGestureMgr::isGesturePlaying(LLMultiGesture* gesture) +{ + if(!gesture) + { + return FALSE; + } + + return gesture->mPlaying; +} + +void LLGestureMgr::replaceGesture(const LLUUID& item_id, LLMultiGesture* new_gesture, const LLUUID& asset_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); item_map_t::iterator it = mActive.find(base_item_id); @@ -456,10 +469,11 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, LLMultiGesture* new notifyObservers(); } -void LLGestureManager::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id) +void LLGestureMgr::replaceGesture(const LLUUID& item_id, const LLUUID& new_asset_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); - item_map_t::iterator it = gGestureManager.mActive.find(base_item_id); + + item_map_t::iterator it = LLGestureMgr::instance().mActive.find(base_item_id); if (it == mActive.end()) { llwarns << "replaceGesture for inactive gesture " << base_item_id << llendl; @@ -468,10 +482,10 @@ void LLGestureManager::replaceGesture(const LLUUID& item_id, const LLUUID& new_a // mActive owns this gesture pointer, so clean up memory. LLMultiGesture* gesture = (*it).second; - gGestureManager.replaceGesture(base_item_id, gesture, new_asset_id); + LLGestureMgr::instance().replaceGesture(base_item_id, gesture, new_asset_id); } -void LLGestureManager::playGesture(LLMultiGesture* gesture) +void LLGestureMgr::playGesture(LLMultiGesture* gesture) { if (!gesture) return; @@ -490,9 +504,10 @@ void LLGestureManager::playGesture(LLMultiGesture* gesture) // Convenience function that looks up the item_id for you. -void LLGestureManager::playGesture(const LLUUID& item_id) +void LLGestureMgr::playGesture(const LLUUID& item_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); + item_map_t::iterator it = mActive.find(base_item_id); if (it == mActive.end()) return; @@ -506,7 +521,7 @@ void LLGestureManager::playGesture(const LLUUID& item_id) // Iterates through space delimited tokens in string, triggering any gestures found. // Generates a revised string that has the found tokens replaced by their replacement strings // and (as a minor side effect) has multiple spaces in a row replaced by single spaces. -BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::string* revised_string) +BOOL LLGestureMgr::triggerAndReviseString(const std::string &utf8str, std::string* revised_string) { std::string tokenized = utf8str; @@ -599,7 +614,7 @@ BOOL LLGestureManager::triggerAndReviseString(const std::string &utf8str, std::s } -BOOL LLGestureManager::triggerGesture(KEY key, MASK mask) +BOOL LLGestureMgr::triggerGesture(KEY key, MASK mask) { std::vector <LLMultiGesture *> matching; item_map_t::iterator it; @@ -633,7 +648,7 @@ BOOL LLGestureManager::triggerGesture(KEY key, MASK mask) } -S32 LLGestureManager::getPlayingCount() const +S32 LLGestureMgr::getPlayingCount() const { return mPlaying.size(); } @@ -647,7 +662,7 @@ struct IsGesturePlaying : public std::unary_function<LLMultiGesture*, bool> } }; -void LLGestureManager::update() +void LLGestureMgr::update() { S32 i; for (i = 0; i < (S32)mPlaying.size(); ++i) @@ -690,7 +705,7 @@ void LLGestureManager::update() // Run all steps until you're either done or hit a wait. -void LLGestureManager::stepGesture(LLMultiGesture* gesture) +void LLGestureMgr::stepGesture(LLMultiGesture* gesture) { if (!gesture) { @@ -838,7 +853,7 @@ void LLGestureManager::stepGesture(LLMultiGesture* gesture) } -void LLGestureManager::runStep(LLMultiGesture* gesture, LLGestureStep* step) +void LLGestureMgr::runStep(LLMultiGesture* gesture, LLGestureStep* step) { switch(step->getType()) { @@ -929,7 +944,7 @@ void LLGestureManager::runStep(LLMultiGesture* gesture, LLGestureStep* step) // static -void LLGestureManager::onLoadComplete(LLVFS *vfs, +void LLGestureMgr::onLoadComplete(LLVFS *vfs, const LLUUID& asset_uuid, LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status) @@ -942,8 +957,8 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs, delete info; info = NULL; - - gGestureManager.mLoadingCount--; + LLGestureMgr& self = LLGestureMgr::instance(); + self.mLoadingCount--; if (0 == status) { @@ -970,21 +985,22 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs, { if (deactivate_similar) { - gGestureManager.deactivateSimilarGestures(gesture, item_id); + self.deactivateSimilarGestures(gesture, item_id); // Display deactivation message if this was the last of the bunch. - if (gGestureManager.mLoadingCount == 0 - && gGestureManager.mDeactivateSimilarNames.length() > 0) + if (self.mLoadingCount == 0 + && self.mDeactivateSimilarNames.length() > 0) { // we're done with this set of deactivations LLSD args; - args["NAMES"] = gGestureManager.mDeactivateSimilarNames; - LLNotifications::instance().add("DeactivatedGesturesTrigger", args); + args["NAMES"] = self.mDeactivateSimilarNames; + LLNotificationsUtil::add("DeactivatedGesturesTrigger", args); } } + self.mActive[item_id] = gesture; + // Everything has been successful. Add to the active list. - gGestureManager.mActive[item_id] = gesture; gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id); if (inform_server) { @@ -1004,13 +1020,13 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs, gAgent.sendReliableMessage(); } - gGestureManager.notifyObservers(); + self.notifyObservers(); } else { llwarns << "Unable to load gesture" << llendl; - gGestureManager.mActive.erase(item_id); + self.mActive.erase(item_id); delete gesture; gesture = NULL; @@ -1035,12 +1051,13 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs, llwarns << "Problem loading gesture: " << status << llendl; - gGestureManager.mActive.erase(item_id); + LLGestureMgr::instance().mActive.erase(item_id); } } -void LLGestureManager::stopGesture(LLMultiGesture* gesture) + +void LLGestureMgr::stopGesture(LLMultiGesture* gesture) { if (!gesture) return; @@ -1080,7 +1097,7 @@ void LLGestureManager::stopGesture(LLMultiGesture* gesture) } -void LLGestureManager::stopGesture(const LLUUID& item_id) +void LLGestureMgr::stopGesture(const LLUUID& item_id) { const LLUUID& base_item_id = get_linked_uuid(item_id); item_map_t::iterator it = mActive.find(base_item_id); @@ -1093,12 +1110,12 @@ void LLGestureManager::stopGesture(const LLUUID& item_id) } -void LLGestureManager::addObserver(LLGestureManagerObserver* observer) +void LLGestureMgr::addObserver(LLGestureManagerObserver* observer) { mObservers.push_back(observer); } -void LLGestureManager::removeObserver(LLGestureManagerObserver* observer) +void LLGestureMgr::removeObserver(LLGestureManagerObserver* observer) { std::vector<LLGestureManagerObserver*>::iterator it; it = std::find(mObservers.begin(), mObservers.end(), observer); @@ -1111,9 +1128,9 @@ void LLGestureManager::removeObserver(LLGestureManagerObserver* observer) // Call this method when it's time to update everyone on a new state. // Copy the list because an observer could respond by removing itself // from the list. -void LLGestureManager::notifyObservers() +void LLGestureMgr::notifyObservers() { - lldebugs << "LLGestureManager::notifyObservers" << llendl; + lldebugs << "LLGestureMgr::notifyObservers" << llendl; for(std::vector<LLGestureManagerObserver*>::iterator iter = mObservers.begin(); iter != mObservers.end(); @@ -1124,7 +1141,7 @@ void LLGestureManager::notifyObservers() } } -BOOL LLGestureManager::matchPrefix(const std::string& in_str, std::string* out_str) +BOOL LLGestureMgr::matchPrefix(const std::string& in_str, std::string* out_str) { S32 in_len = in_str.length(); @@ -1155,7 +1172,7 @@ BOOL LLGestureManager::matchPrefix(const std::string& in_str, std::string* out_s } -void LLGestureManager::getItemIDs(std::vector<LLUUID>* ids) +void LLGestureMgr::getItemIDs(uuid_vec_t* ids) { item_map_t::const_iterator it; for (it = mActive.begin(); it != mActive.end(); ++it) diff --git a/indra/newview/llgesturemgr.h b/indra/newview/llgesturemgr.h index f564c1748..88d3b9c4a 100644 --- a/indra/newview/llgesturemgr.h +++ b/indra/newview/llgesturemgr.h @@ -52,11 +52,14 @@ public: virtual void changed() = 0; }; -class LLGestureManager +class LLGestureMgr : public LLSingleton<LLGestureMgr> { public: - LLGestureManager(); - ~LLGestureManager(); + // Maps inventory item_id to gesture + typedef std::map<LLUUID, LLMultiGesture*> item_map_t; + + LLGestureMgr(); + ~LLGestureMgr(); void init(); @@ -95,6 +98,9 @@ public: BOOL isGesturePlaying(const LLUUID& item_id); + BOOL isGesturePlaying(LLMultiGesture* gesture); + + const item_map_t& getActiveGestures() const { return mActive; } // Force a gesture to be played, for example, if it is being // previewed. void playGesture(LLMultiGesture* gesture); @@ -124,7 +130,7 @@ public: BOOL matchPrefix(const std::string& in_str, std::string* out_str); // Copy item ids into the vector - void getItemIDs(std::vector<LLUUID>* ids); + void getItemIDs(uuid_vec_t* ids); protected: // Handle the processing of a single gesture @@ -139,13 +145,10 @@ protected: LLAssetType::EType type, void* user_data, S32 status, LLExtStat ext_status); -public: - BOOL mValid; - std::vector<LLMultiGesture*> mPlaying; - // Maps inventory item_id to gesture - typedef std::map<LLUUID, LLMultiGesture*> item_map_t; + +private: // Active gestures. // NOTE: The gesture pointer CAN BE NULL. This means that // there is a gesture with that item_id, but the asset data @@ -156,8 +159,7 @@ public: std::string mDeactivateSimilarNames; std::vector<LLGestureManagerObserver*> mObservers; + std::vector<LLMultiGesture*> mPlaying; + BOOL mValid; }; - -extern LLGestureManager gGestureManager; - #endif diff --git a/indra/newview/llglsandbox.cpp b/indra/newview/llglsandbox.cpp index 092fdc6b5..c4829d326 100644 --- a/indra/newview/llglsandbox.cpp +++ b/indra/newview/llglsandbox.cpp @@ -613,7 +613,7 @@ void LLViewerParcelMgr::renderOneSegment(F32 x1, F32 y1, F32 x2, F32 y2, F32 hei return; // HACK: At edge of last region of world, we need to make sure the region // resolves correctly so we can get a height value. - const F32 BORDER = REGION_WIDTH_METERS - 0.1f; + const F32 BORDER = regionp->getWidth() - 0.1f; F32 clamped_x1 = x1; F32 clamped_y1 = y1; @@ -776,7 +776,7 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV F32 pos_y = pos.mV[VY]; LLGLSUIDefault gls_ui; - LLGLDepthTest gls_depth(GL_TRUE); + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); if (mCollisionBanned == BA_BANNED) @@ -819,12 +819,6 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV x2 = x1 + PARCEL_GRID_STEP_METERS; y2 = y1; - if (gRenderForSelect) - { - LLColor4U color((U8)(GL_NAME_PARCEL_WALL >> 16), (U8)(GL_NAME_PARCEL_WALL >> 8), (U8)GL_NAME_PARCEL_WALL); - gGL.color4ubv(color.mV); - } - else { dy = (pos_y - y1) + DIST_OFFSET; @@ -865,12 +859,6 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV x2 = x1; y2 = y1 + PARCEL_GRID_STEP_METERS; - if (gRenderForSelect) - { - LLColor4U color((U8)(GL_NAME_PARCEL_WALL >> 16), (U8)(GL_NAME_PARCEL_WALL >> 8), (U8)GL_NAME_PARCEL_WALL); - gGL.color4ubv(color.mV); - } - else { dx = (pos_x - x1) + DIST_OFFSET; diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index 6e1f6de57..3cea45937 100644 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -53,6 +53,7 @@ #include "llviewerwindow.h" #include "llfloaterdirectory.h" #include "llfloatergroupinfo.h" +#include "llnotificationsutil.h" #include "lluictrlfactory.h" #if LL_MSVC #pragma warning( disable : 4265 ) // "class has virtual functions, but destructor is not virtual" @@ -1376,7 +1377,7 @@ void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data) // *TODO:translate LLSD args; args["MESSAGE"] = message; - LLNotifications::instance().add("UnableToCreateGroup", args); + LLNotificationsUtil::add("UnableToCreateGroup", args); } } diff --git a/indra/newview/llhoverview.cpp b/indra/newview/llhoverview.cpp index 1821b7da7..171977066 100644 --- a/indra/newview/llhoverview.cpp +++ b/indra/newview/llhoverview.cpp @@ -179,7 +179,7 @@ void LLHoverView::pickCallback(const LLPickInfo& pick_info) { gHoverView->setHoverActive(TRUE); gHoverView->mHoverLandGlobal = pick_info.mPosGlobal; - LLViewerParcelMgr::getInstance()->requestHoverParcelProperties( gHoverView->mHoverLandGlobal ); + LLViewerParcelMgr::getInstance()->setHoverParcel( gHoverView->mHoverLandGlobal ); } else { diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp index e25efdf42..14c1f3000 100644 --- a/indra/newview/llhudeffectlookat.cpp +++ b/indra/newview/llhudeffectlookat.cpp @@ -543,7 +543,7 @@ void LLHUDEffectLookAt::render() const LLFontGL* font = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF); LLGLEnable gl_blend(GL_BLEND); glPushMatrix(); - gViewerWindow->setupViewport(); + gViewerWindow->setup2DViewport(); hud_render_utf8text(text, target + shadow_offset, *font, diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp index 273533798..9da28a2de 100644 --- a/indra/newview/llhudicon.cpp +++ b/indra/newview/llhudicon.cpp @@ -39,6 +39,7 @@ #include "llviewerobject.h" #include "lldrawable.h" +#include "llvector4a.h" #include "llviewercamera.h" #include "llviewertexture.h" #include "llviewerwindow.h" @@ -145,9 +146,9 @@ void LLHUDIcon::renderIcon(BOOL for_select) alpha_factor *= clamp_rescale(time_elapsed, MAX_VISIBLE_TIME - FADE_OUT_TIME, MAX_VISIBLE_TIME, 1.f, 0.f); } - F32 image_aspect = (F32)mImagep->getFullWidth() / (F32)mImagep->getFullHeight(); - LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * x_pixel_vec; - LLVector3 y_scale = (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * y_pixel_vec; + F32 image_aspect = (F32)mImagep->getFullWidth() / (F32)mImagep->getFullHeight() ; + LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * x_pixel_vec; + LLVector3 y_scale = (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * y_pixel_vec; LLVector3 lower_left = icon_position - (x_scale * 0.5f); LLVector3 lower_right = icon_position + (x_scale * 0.5f); @@ -207,11 +208,6 @@ void LLHUDIcon::render() renderIcon(FALSE); } -void LLHUDIcon::renderForSelect() -{ - renderIcon(TRUE); -} - BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, LLVector3* intersection) { if (mHidden) @@ -262,25 +258,46 @@ BOOL LLHUDIcon::lineSegmentIntersect(const LLVector3& start, const LLVector3& en return FALSE; } - F32 image_aspect = (F32)mImagep->getFullWidth() / (F32)mImagep->getFullHeight(); - LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * x_pixel_vec; - LLVector3 y_scale = (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * y_pixel_vec; + F32 image_aspect = (F32)mImagep->getFullWidth() / (F32)mImagep->getFullHeight() ; + LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * x_pixel_vec; + LLVector3 y_scale = (F32)gViewerWindow->getWindowHeightScaled() * mScale * scale_factor * y_pixel_vec; - LLVector3 lower_left = icon_position - (x_scale * 0.5f); - LLVector3 lower_right = icon_position + (x_scale * 0.5f); - LLVector3 upper_left = icon_position - (x_scale * 0.5f) + y_scale; - LLVector3 upper_right = icon_position + (x_scale * 0.5f) + y_scale; + LLVector4a x_scalea; + LLVector4a icon_positiona; + LLVector4a y_scalea; - - F32 t = 0.f; - LLVector3 dir = end-start; + x_scalea.load3(x_scale.mV); + x_scalea.mul(0.5f); + y_scalea.load3(y_scale.mV); - if (LLTriangleRayIntersect(upper_right, upper_left, lower_right, start, dir, NULL, NULL, &t, FALSE) || - LLTriangleRayIntersect(upper_left, lower_left, lower_right, start, dir, NULL, NULL, &t, FALSE)) + icon_positiona.load3(icon_position.mV); + + LLVector4a lower_left; + lower_left.setSub(icon_positiona, x_scalea); + LLVector4a lower_right; + lower_right.setAdd(icon_positiona, x_scalea); + LLVector4a upper_left; + upper_left.setAdd(lower_left, y_scalea); + LLVector4a upper_right; + upper_right.setAdd(lower_right, y_scalea); + + LLVector4a enda; + enda.load3(end.mV); + LLVector4a starta; + starta.load3(start.mV); + LLVector4a dir; + dir.setSub(enda, starta); + + F32 a,b,t; + + if (LLTriangleRayIntersect(upper_right, upper_left, lower_right, starta, dir, a,b,t) || + LLTriangleRayIntersect(upper_left, lower_left, lower_right, starta, dir, a,b,t)) { if (intersection) { - *intersection = start + dir*t; + dir.mul(t); + starta.add(dir); + *intersection = LLVector3(starta.getF32ptr()); } return TRUE; } @@ -331,6 +348,7 @@ LLHUDIcon* LLHUDIcon::lineSegmentIntersectAll(const LLVector3& start, const LLVe for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it) { LLHUDIcon* icon = *icon_it; + llassert(icon); if (icon->lineSegmentIntersect(start, local_end, &position)) { ret = icon; diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h index 6d523a287..5697cc94f 100644 --- a/indra/newview/llhudicon.h +++ b/indra/newview/llhudicon.h @@ -33,7 +33,7 @@ #ifndef LL_LLHUDICON_H #define LL_LLHUDICON_H -#include "llmemory.h" +#include "llpointer.h" #include "lldarrayptr.h" #include "llhudobject.h" @@ -58,7 +58,6 @@ friend class LLHUDObject; public: /*virtual*/ void render(); - /*virtual*/ void renderForSelect(); /*virtual*/ void markDead(); /*virtual*/ F32 getDistance() const { return mDistance; } diff --git a/indra/newview/llhudobject.cpp b/indra/newview/llhudobject.cpp index b2ba698bc..d136a1df7 100644 --- a/indra/newview/llhudobject.cpp +++ b/indra/newview/llhudobject.cpp @@ -286,26 +286,6 @@ void LLHUDObject::renderAll() LLVertexBuffer::unbind(); } -// static -void LLHUDObject::renderAllForSelect() -{ - LLHUDObject *hud_objp; - - hud_object_list_t::iterator object_it; - for (object_it = sHUDObjects.begin(); object_it != sHUDObjects.end(); ) - { - hud_object_list_t::iterator cur_it = object_it++; - hud_objp = (*cur_it); - if (hud_objp->getNumRefs() == 1) - { - sHUDObjects.erase(cur_it); - } - else if (hud_objp->isVisible()) - { - hud_objp->renderForSelect(); - } - } -} // static void LLHUDObject::renderAllForTimer() { diff --git a/indra/newview/llhudobject.h b/indra/newview/llhudobject.h index b645ae07a..73140eba6 100644 --- a/indra/newview/llhudobject.h +++ b/indra/newview/llhudobject.h @@ -74,7 +74,6 @@ public: static LLHUDEffect *addHUDEffect(const U8 type); static void updateAll(); static void renderAll(); - static void renderAllForSelect(); static void renderAllForTimer(); static void cleanupHUDObjects(); @@ -106,7 +105,6 @@ protected: ~LLHUDObject(); virtual void render() = 0; - virtual void renderForSelect() {} //Only override when needed. virtual void renderForTimer() {}; protected: diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 56fb13c87..9b5633872 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -75,8 +75,8 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, LLVector3 up_axis; if (orthographic) { - right_axis.setVec(0.f, -1.f / gViewerWindow->getWindowHeight(), 0.f); - up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWindowHeight()); + right_axis.setVec(0.f, -1.f / gViewerWindow->getWorldViewHeightScaled(), 0.f); + up_axis.setVec(0.f, 0.f, 1.f / gViewerWindow->getWorldViewHeightScaled()); } else { @@ -104,23 +104,31 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent, //get the render_pos in screen space F64 winX, winY, winZ; + LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); + S32 viewport[4]; + viewport[0] = world_view_rect.mLeft; + viewport[1] = world_view_rect.mBottom; + viewport[2] = world_view_rect.getWidth(); + viewport[3] = world_view_rect.getHeight(); gluProject(render_pos.mV[0], render_pos.mV[1], render_pos.mV[2], - gGLModelView, gGLProjection, (GLint*) gGLViewport, + gGLModelView, gGLProjection, (GLint*) viewport, &winX, &winY, &winZ); - //fonts all render orthographically, set up projection + //fonts all render orthographically, set up projection`` glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); gGL.pushMatrix(); LLUI::pushMatrix(); - gViewerWindow->setup2DRender(); - + gl_state_for_2d(world_view_rect.getWidth(), world_view_rect.getHeight()); + gViewerWindow->setup3DViewport(); + + winX -= world_view_rect.mLeft; + winY -= world_view_rect.mBottom; LLUI::loadIdentity(); + glLoadIdentity(); LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f)); - //glRotatef(angle * RAD_TO_DEG, axis.mV[VX], axis.mV[VY], axis.mV[VZ]); - //glScalef(right_scale, up_scale, 1.f); F32 right_x; font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, wstr.length(), 1000, &right_x); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index f824939ec..683f46a1f 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -215,8 +215,9 @@ BOOL LLHUDText::lineSegmentIntersect(const LLVector3& start, const LLVector3& en LLVector3 dir = end-start; F32 t = 0.f; - if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, NULL, NULL, &t, FALSE) || - LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, NULL, NULL, &t, FALSE) ) + F32 a, b; + if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE) || + LLTriangleRayIntersect(v[2], v[3], v[0], start, dir, a, b, t, FALSE) ) { if (t <= 1.f) { @@ -238,15 +239,6 @@ void LLHUDText::render() } } -void LLHUDText::renderForSelect() -{ - if (!mOnHUDAttachment) - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - renderText(TRUE); - } -} - void LLHUDText::renderText(BOOL for_select) { if (!mVisible || mHidden) diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h index ab266bd96..2c404cfad 100644 --- a/indra/newview/llhudtext.h +++ b/indra/newview/llhudtext.h @@ -146,7 +146,6 @@ protected: LLHUDText(const U8 type); /*virtual*/ void render(); - /*virtual*/ void renderForSelect(); void renderText(BOOL for_select); static void updateAll(); void setLOD(S32 lod); diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp index 2feae487d..ff574bea8 100644 --- a/indra/newview/llimpanel.cpp +++ b/indra/newview/llimpanel.cpp @@ -42,6 +42,7 @@ #include "llstring.h" #include "message.h" #include "lltextbox.h" +#include "llnotificationsutil.h" #include "llagent.h" #include "llbutton.h" @@ -394,13 +395,13 @@ void LLVoiceChannel::setChannelInfo( { if (mURI.empty()) { - LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs); + LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs); llwarns << "Received empty URI for channel " << mSessionName << llendl; deactivate(); } else if (mCredentials.empty()) { - LLNotifications::instance().add("VoiceChannelJoinFailed", mNotifyArgs); + LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs); llwarns << "Received empty credentials for channel " << mSessionName << llendl; deactivate(); } @@ -444,7 +445,7 @@ void LLVoiceChannel::handleStatusChange(EStatusType type) { case STATUS_LOGIN_RETRY: //mLoginNotificationHandle = LLNotifyBox::showXml("VoiceLoginRetry")->getHandle(); - LLNotifications::instance().add("VoiceLoginRetry"); + LLNotificationsUtil::add("VoiceLoginRetry"); break; case STATUS_LOGGED_IN: //if (!mLoginNotificationHandle.isDead()) @@ -462,7 +463,7 @@ void LLVoiceChannel::handleStatusChange(EStatusType type) { // if forceably removed from channel // update the UI and revert to default channel - LLNotifications::instance().add("VoiceChannelDisconnected", mNotifyArgs); + LLNotificationsUtil::add("VoiceChannelDisconnected", mNotifyArgs); deactivate(); } mIgnoreNextSessionLeave = FALSE; @@ -954,12 +955,12 @@ void LLVoiceChannelP2P::handleStatusChange(EStatusType type) if (mState == STATE_RINGING) { // other user declined call - LLNotifications::instance().add("P2PCallDeclined", mNotifyArgs); + LLNotificationsUtil::add("P2PCallDeclined", mNotifyArgs); } else { // other user hung up - LLNotifications::instance().add("VoiceChannelDisconnectedP2P", mNotifyArgs); + LLNotificationsUtil::add("VoiceChannelDisconnectedP2P", mNotifyArgs); } deactivate(); } @@ -977,7 +978,7 @@ void LLVoiceChannelP2P::handleError(EStatusType type) switch(type) { case ERROR_NOT_AVAILABLE: - LLNotifications::instance().add("P2PCallNoAnswer", mNotifyArgs); + LLNotificationsUtil::add("P2PCallNoAnswer", mNotifyArgs); break; default: break; diff --git a/indra/newview/llinventoryactions.cpp b/indra/newview/llinventoryactions.cpp index 61fdb29e4..aa0db9c4e 100644 --- a/indra/newview/llinventoryactions.cpp +++ b/indra/newview/llinventoryactions.cpp @@ -43,11 +43,13 @@ #include "llagent.h" #include "llcallingcard.h" #include "llcheckboxctrl.h" // for radio buttons +#include "llnotificationsutil.h" #include "llradiogroup.h" #include "llspinctrl.h" #include "lltextbox.h" #include "llui.h" + #include "llviewercontrol.h" #include "llfirstuse.h" #include "llfloateravatarinfo.h" @@ -289,7 +291,7 @@ class LLEmptyTrash : public inventory_panel_listener_t { LLInventoryModel* model = mPtr->getModel(); if(!model) return false; - LLNotifications::instance().add("ConfirmEmptyTrash", LLSD(), LLSD(), boost::bind(&LLEmptyTrash::callback_empty_trash, this, _1, _2)); + LLNotificationsUtil::add("ConfirmEmptyTrash", LLSD(), LLSD(), boost::bind(&LLEmptyTrash::callback_empty_trash, this, _1, _2)); return true; } @@ -313,7 +315,7 @@ class LLEmptyLostAndFound : public inventory_panel_listener_t { LLInventoryModel* model = mPtr->getModel(); if(!model) return false; - LLNotifications::instance().add("ConfirmEmptyLostAndFound", LLSD(), LLSD(), boost::bind(&LLEmptyLostAndFound::callback_empty_lost_and_found, this, _1, _2)); + LLNotificationsUtil::add("ConfirmEmptyLostAndFound", LLSD(), LLSD(), boost::bind(&LLEmptyLostAndFound::callback_empty_lost_and_found, this, _1, _2)); return true; } diff --git a/indra/newview/llinventorybackup.cpp b/indra/newview/llinventorybackup.cpp index 055cc2d61..3f58e3064 100644 --- a/indra/newview/llinventorybackup.cpp +++ b/indra/newview/llinventorybackup.cpp @@ -13,7 +13,7 @@ #include "lluictrlfactory.h" #include "llscrolllistctrl.h" #include "llimagetga.h" - +#include "llnotificationsutil.h" std::list<LLFloaterInventoryBackup*> LLFloaterInventoryBackup::sInstances; @@ -115,7 +115,7 @@ void LLFloaterInventoryBackupSettings::onClickNext(void* userdata) { LLSD args; args["ERROR_MESSAGE"] = "No items passed the filter \\o/"; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); return; } @@ -353,7 +353,7 @@ void LLInventoryBackup::imageCallback(BOOL success, { LLSD args; args["ERROR_MESSAGE"] = "Download didn't work on " + item->getName() + "."; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); return; } @@ -379,13 +379,13 @@ void LLInventoryBackup::imageCallback_continued(LLImageRaw* src, AIFilePicker* f { LLSD args; args["ERROR_MESSAGE"] = "Couldn't encode file."; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); } else if( !image_tga->save( filename ) ) { LLSD args; args["ERROR_MESSAGE"] = "Couldn't write file."; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); } } @@ -402,7 +402,7 @@ void LLInventoryBackup::assetCallback(LLVFS *vfs, { LLSD args; args["ERROR_MESSAGE"] = "Download didn't work on " + item->getName() + "."; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); return; } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 8282bf8ff..57194eba0 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -36,6 +36,7 @@ #include "llinventoryview.h" #include "llinventorybridge.h" +#include "llinventorydefines.h" #include "message.h" @@ -66,6 +67,8 @@ #include "llinventoryclipboard.h" #include "lllineeditor.h" #include "llmenugl.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llpreviewanim.h" #include "llpreviewgesture.h" #include "llpreviewlandmark.h" @@ -225,7 +228,7 @@ BOOL get_is_item_worn(const LLInventoryItem *item) return TRUE; break; case LLAssetType::AT_GESTURE: - if (gGestureManager.isGestureActive(item->getLinkedUUID())) + if (LLGestureMgr::instance().isGestureActive(item->getLinkedUUID())) return TRUE; break; default: @@ -361,7 +364,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc { if(LLAssetType::AT_GESTURE == item->getType()) { - gGestureManager.deactivateGesture(item->getUUID()); + LLGestureMgr::instance().deactivateGesture(item->getUUID()); } } } @@ -377,7 +380,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc { if(LLAssetType::AT_GESTURE == descendent_items[j]->getType()) { - gGestureManager.deactivateGesture(descendent_items[j]->getUUID()); + LLGestureMgr::instance().deactivateGesture(descendent_items[j]->getUUID()); } } } @@ -1653,7 +1656,7 @@ BOOL LLFolderBridge::isItemRemovable() return FALSE; } - if ( (LLAssetType::AT_NONE != category->getPreferredType()) && (LLFolderType::FT_OUTFIT != category->getPreferredType()) ) + if ( (LLFolderType::FT_NONE != category->getPreferredType()) && (LLFolderType::FT_OUTFIT != category->getPreferredType()) ) { return FALSE; } @@ -1666,7 +1669,7 @@ BOOL LLFolderBridge::isItemRemovable() for( i = 0; i < descendent_categories.count(); i++ ) { LLInventoryCategory* category = descendent_categories[i]; - if( LLAssetType::AT_NONE != category->getPreferredType() ) + if( LLFolderType::FT_NONE != category->getPreferredType() ) { return FALSE; } @@ -1792,7 +1795,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, const LLUUID& cat_id = inv_cat->getUUID(); const LLUUID &trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH, false); const BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id); - BOOL is_movable = (LLAssetType::AT_NONE == inv_cat->getPreferredType()); + BOOL is_movable = (LLFolderType::FT_NONE == inv_cat->getPreferredType()); if( is_movable ) { LLInventoryModel::cat_array_t descendent_categories; @@ -1837,9 +1840,9 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat, { LLInventoryItem* item = descendent_items[i]; if (item->getType() == LLAssetType::AT_GESTURE - && gGestureManager.isGestureActive(item->getUUID())) + && LLGestureMgr::instance().isGestureActive(item->getUUID())) { - gGestureManager.deactivateGesture(item->getUUID()); + LLGestureMgr::instance().deactivateGesture(item->getUUID()); } } } @@ -1875,7 +1878,7 @@ void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv) { dialog = "MoveInventoryFromObject"; } - LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); + LLNotificationsUtil::add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv)); } // Move/copy all inventory items from the Contents folder of an in-world @@ -2402,9 +2405,9 @@ BOOL LLFolderBridge::removeItem() { LLInventoryItem* item = descendent_items[i]; if (item->getType() == LLAssetType::AT_GESTURE - && gGestureManager.isGestureActive(item->getUUID())) + && LLGestureMgr::instance().isGestureActive(item->getUUID())) { - gGestureManager.deactivateGesture(item->getUUID()); + LLGestureMgr::instance().deactivateGesture(item->getUUID()); } } @@ -2931,7 +2934,7 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response { LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData; LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID); - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if(option == 0 && object) { @@ -3019,9 +3022,9 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, if(accept && drop) { if (inv_item->getType() == LLAssetType::AT_GESTURE - && gGestureManager.isGestureActive(inv_item->getUUID()) && move_is_into_trash) + && LLGestureMgr::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash) { - gGestureManager.deactivateGesture(inv_item->getUUID()); + LLGestureMgr::instance().deactivateGesture(inv_item->getUUID()); } // If an item is being dragged between windows, unselect // everything in the active window so that we don't follow @@ -3411,7 +3414,7 @@ void open_landmark(LLViewerInventoryItem* inv_item, static bool open_landmark_callback(const LLSD& notification, const LLSD& response) { - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); LLUUID asset_id = notification["payload"]["asset_id"].asUUID(); LLUUID item_id = notification["payload"]["item_id"].asUUID(); @@ -3445,7 +3448,7 @@ void LLLandmarkBridge::openItem() LLSD payload; payload["asset_id"] = item->getAssetUUID(); payload["item_id"] = item->getUUID(); - LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload); + LLNotificationsUtil::add("TeleportFromLandmark", LLSD(), payload); } } @@ -3748,7 +3751,7 @@ LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const { U8 font = LLFontGL::NORMAL; - if (gGestureManager.isGestureActive(mUUID)) + if (LLGestureMgr::instance().isGestureActive(mUUID)) { font |= LLFontGL::BOLD; } @@ -3764,7 +3767,7 @@ LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const std::string LLGestureBridge::getLabelSuffix() const { - if( gGestureManager.isGestureActive(mUUID) ) + if( LLGestureMgr::instance().isGestureActive(mUUID) ) { return LLItemBridge::getLabelSuffix() + " (active)"; } @@ -3779,7 +3782,7 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode { if ("activate" == action) { - gGestureManager.activateGesture(mUUID); + LLGestureMgr::instance().activateGesture(mUUID); LLViewerInventoryItem* item = gInventory.getItem(mUUID); if (!item) return; @@ -3791,7 +3794,7 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode } else if ("deactivate" == action) { - gGestureManager.deactivateGesture(mUUID); + LLGestureMgr::instance().deactivateGesture(mUUID); LLViewerInventoryItem* item = gInventory.getItem(mUUID); if (!item) return; @@ -3837,7 +3840,7 @@ BOOL LLGestureBridge::removeItem() const LLUUID item_id = mUUID; // Force close the preview window, if it exists - gGestureManager.deactivateGesture(item_id); + LLGestureMgr::instance().deactivateGesture(item_id); // If deactivateGesture deleted *this, then return out immediately. if (!model->getObject(item_id)) @@ -3867,7 +3870,7 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags) getClipboardEntries(true, items, disabled_items, flags); items.push_back(std::string("Gesture Separator")); - if (gGestureManager.isGestureActive(getUUID())) + if (LLGestureMgr::instance().isGestureActive(getUUID())) { items.push_back(std::string("Deactivate")); } @@ -4119,13 +4122,10 @@ void LLObjectBridge::openItem() } if (avatar->isWearingAttachment(mUUID)) { -#ifdef LL_RRINTERFACE_H //MK - if (gRRenabled && !gAgent.mRRInterface.canDetach(avatar->getWornAttachment(mUUID))) - { - return; - } -#endif //mk - performAction(NULL, NULL, "detach"); +// [RLVa:KB] + if ( !(rlv_handler_t::isEnabled()) || (gRlvAttachmentLocks.canDetach(getItem()))) + performAction(NULL, NULL, "detach"); +// [/RLVa:KB] } else { @@ -4194,7 +4194,7 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach if ( (rlv_handler_t::isEnabled()) && ((gRlvAttachmentLocks.canAttach(attachment) & RLV_WEAR_REPLACE) == 0) ) return; // [/RLVa:KB] - LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); + LLNotificationsUtil::add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez); } else { @@ -4213,11 +4213,11 @@ bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& respon { LLSD args; args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS); - LLNotifications::instance().add("MaxAttachmentsOnOutfit", args); + LLNotificationsUtil::add("MaxAttachmentsOnOutfit", args); return false; } - S32 option = LLNotification::getSelectedOption(notification, response); + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); if (option == 0/*YES*/) { LLUUID item_id = notification["payload"]["item_id"].asUUID(); @@ -4850,7 +4850,7 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata ) if( !wearable_count && !obj_count && !gest_count) { - LLNotifications::instance().add("CouldNotPutOnOutfit"); + LLNotificationsUtil::add("CouldNotPutOnOutfit"); delete wear_info; return; } @@ -4866,7 +4866,7 @@ void wear_inventory_category_on_avatar_step2( BOOL proceed, void* userdata ) { llinfos << "Activating " << gest_count << " gestures" << llendl; - gGestureManager.activateGestures(gest_item_array); + LLGestureMgr::instance().activateGestures(gest_item_array); // Update the inventory item labels to reflect the fact // they are active. @@ -5172,7 +5172,7 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, void* userdata) LLViewerInventoryItem *gest_item = gest_item_array.get(i); if (get_is_item_worn(gest_item->getUUID())) { - gGestureManager.deactivateGesture( gest_item_array.get(i)->getLinkedUUID() ); + LLGestureMgr::instance().deactivateGesture( gest_item_array.get(i)->getLinkedUUID() ); gInventory.updateItem( gest_item ); gInventory.notifyObservers(); } @@ -5262,7 +5262,7 @@ void LLWearableBridge::openItem() { if( isItemInTrash() ) { - LLNotifications::instance().add("CannotWearTrash"); + LLNotificationsUtil::add("CannotWearTrash"); } else if(isAgentInventory()) { @@ -5295,7 +5295,7 @@ void LLWearableBridge::openItem() { // *TODO: We should fetch the item details, and then do // the operation above. - LLNotifications::instance().add("CannotWearInfoNotComplete"); + LLNotificationsUtil::add("CannotWearInfoNotComplete"); } } } @@ -5419,7 +5419,7 @@ void LLWearableBridge::wearOnAvatar() // destroy clothing items. if (!gAgentWearables.areWearablesLoaded()) { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); return; } diff --git a/indra/newview/llinventoryview.cpp b/indra/newview/llinventoryview.cpp index 69fbc19cd..6b50d56ed 100644 --- a/indra/newview/llinventoryview.cpp +++ b/indra/newview/llinventoryview.cpp @@ -36,6 +36,7 @@ #include "llinventoryview.h" #include "llinventorybridge.h" +#include "llinventorydefines.h" #include "message.h" diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index e8cdcdfdd..85a893122 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -38,7 +38,7 @@ #include "llassetstorage.h" #include "llagent.h" -#include "llnotify.h" +#include "llnotificationsutil.h" #include "llvfile.h" #include "llviewerstats.h" @@ -120,11 +120,11 @@ void LLLandmarkList::processGetAssetReply( if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) { - LLNotifications::instance().add("LandmarkMissing"); + LLNotificationsUtil::add("LandmarkMissing"); } else { - LLNotifications::instance().add("UnableToLoadLandmark"); + LLNotificationsUtil::add("UnableToLoadLandmark"); } gLandmarkList.mBadList.insert(uuid); diff --git a/indra/newview/lllocalinventory.cpp b/indra/newview/lllocalinventory.cpp index 4d61a5c0e..9b1494edf 100644 --- a/indra/newview/lllocalinventory.cpp +++ b/indra/newview/lllocalinventory.cpp @@ -18,6 +18,7 @@ #include "lluictrlfactory.h" #include "llcombobox.h" +#include "llnotificationsutil.h" #include "llagent.h" // gAgent #include "llviewerwindow.h" // alertXml @@ -315,7 +316,7 @@ void LLLocalInventory::loadInvCache(std::string filename) LLSD args; args["ERROR_MESSAGE"] = message.str(); - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); } conflicting_cats.clear();// srsly dont think this is need but w/e :D } diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp index cf52896e8..574d70f4b 100644 --- a/indra/newview/lllogchat.cpp +++ b/indra/newview/lllogchat.cpp @@ -66,7 +66,7 @@ std::string LLLogChat::makeLogFileName(std::string filename) std::string LLLogChat::cleanFileName(std::string filename) { - std::string invalidChars = "\"\'\\/?*:<>|"; + std::string invalidChars = "\"\'\\/?*:<>|[]{}~"; // Cannot match glob or illegal filename chars S32 position = filename.find_first_of(invalidChars); while (position != filename.npos) { diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index f1ef63b67..6e3421f1f 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -70,11 +70,7 @@ S32 LLManip::sMaxTimesShowHelpText = 5; F32 LLManip::sGridMaxSubdivisionLevel = 32.f; F32 LLManip::sGridMinSubdivisionLevel = 1.f; LLVector2 LLManip::sTickLabelSpacing(60.f, 25.f); -bool LLManip::sActualRoot = false;// going to set these up in the main entry -bool LLManip::sPivotPerc = false; -F32 LLManip::sPivotX = 0.f; -F32 LLManip::sPivotY = 0.f; -F32 LLManip::sPivotZ = 0.f; + //static void LLManip::rebuild(LLViewerObject* vobj) @@ -106,53 +102,6 @@ LLManip::LLManip( const std::string& name, LLToolComposite* composite ) mHighlightedPart(LL_NO_PART), mManipPart(LL_NO_PART) { - initPivot(); - - gSavedSettings.getControl("AscentBuildPrefs_ActualRoot")->getSignal()->connect(boost::bind(&updateActualRoot)); - gSavedSettings.getControl("AscentBuildPrefs_PivotIsPercent")->getSignal()->connect(boost::bind(&updatePivotIsPercent)); - gSavedSettings.getControl("AscentBuildPrefs_PivotX")->getSignal()->connect(boost::bind(&updatePivotX)); - gSavedSettings.getControl("AscentBuildPrefs_PivotY")->getSignal()->connect(boost::bind(&updatePivotY)); - gSavedSettings.getControl("AscentBuildPrefs_PivotZ")->getSignal()->connect(boost::bind(&updatePivotZ)); -} -//static -void LLManip::initPivot() -{ - sActualRoot = (bool)gSavedSettings.getBOOL("AscentBuildPrefs_ActualRoot"); - sPivotPerc = (bool)gSavedSettings.getBOOL("AscentBuildPrefs_PivotIsPercent"); - sPivotX = gSavedSettings.getF32("AscentBuildPrefs_PivotX"); - sPivotY = gSavedSettings.getF32("AscentBuildPrefs_PivotY"); - sPivotZ = gSavedSettings.getF32("AscentBuildPrefs_PivotZ"); -} -//static -bool LLManip::updateActualRoot() -{ - //sActualRoot = (bool)data.asBoolean(); - sActualRoot = gSavedSettings.getBOOL("AscentBuildPrefs_ActualRoot"); - return true; -} -//static -bool LLManip::updatePivotIsPercent() -{ - sPivotPerc = gSavedSettings.getBOOL("AscentBuildPrefs_PivotIsPercent"); - return true; -} -//static -bool LLManip::updatePivotX() -{ - sPivotX = gSavedSettings.getF32("AscentBuildPrefs_PivotX"); - return true; -} -//static -bool LLManip::updatePivotY() -{ - sPivotY = gSavedSettings.getF32("AscentBuildPrefs_PivotY"); - return true; -} -//static -bool LLManip::updatePivotZ() -{ - sPivotZ = gSavedSettings.getF32("AscentBuildPrefs_PivotZ"); - return true; } void LLManip::getManipNormal(LLViewerObject* object, EManipPart manip, LLVector3 &normal) @@ -317,8 +266,8 @@ BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVect if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { BOOL result = FALSE; - F32 mouse_x = ((F32)x / gViewerWindow->getWindowWidth() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom; - F32 mouse_y = ((F32)y / gViewerWindow->getWindowHeight() - 0.5f) / gAgentCamera.mHUDCurZoom; + F32 mouse_x = ((F32)x / gViewerWindow->getWorldViewWidthScaled() - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom; + F32 mouse_y = ((F32)y / gViewerWindow->getWorldViewHeightScaled() - 0.5f) / gAgentCamera.mHUDCurZoom; LLVector3 origin_agent = gAgent.getPosAgentFromGlobal(origin); LLVector3 mouse_pos = LLVector3(0.f, -mouse_x, mouse_y); @@ -356,8 +305,8 @@ BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, co if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom; - F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeight()) - 0.5f) / gAgentCamera.mHUDCurZoom; + F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidthScaled()) - 0.5f) * LLViewerCamera::getInstance()->getAspect() / gAgentCamera.mHUDCurZoom; + F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeightScaled()) - 0.5f) / gAgentCamera.mHUDCurZoom; a1 = LLVector3(llmin(b1.mV[VX] - 0.1f, b2.mV[VX] - 0.1f, 0.f), -mouse_x, mouse_y); a2 = a1 + LLVector3(1.f, 0.f, 0.f); } @@ -404,43 +353,22 @@ LLVector3 LLManip::getSavedPivotPoint() const LLVector3 LLManip::getPivotPoint() { - LLVector3 pos; - LLVector3 scale; - LLQuaternion rot;// = mObjectSelection->getFirstObject()->getRotation(); - if (mObjectSelection->getFirstRootObject(TRUE) && (mObjectSelection->getObjectCount() == 1 || sActualRoot) && mObjectSelection->getSelectType() != SELECT_TYPE_HUD) + static LLCachedControl<bool> actual_root("AscentBuildPrefs_ActualRoot"); + static LLCachedControl<bool> pivot_as_percent("AscentBuildPrefs_PivotIsPercent"); + static LLCachedControl<F32> pivot_x("AscentBuildPrefs_PivotX"); + static LLCachedControl<F32> pivot_y("AscentBuildPrefs_PivotY"); + static LLCachedControl<F32> pivot_z("AscentBuildPrefs_PivotZ"); + LLVector3 offset(pivot_x,pivot_y,pivot_z); + + if (mObjectSelection->getFirstRootObject(TRUE) && (mObjectSelection->getObjectCount() == 1 || actual_root) && mObjectSelection->getSelectType() != SELECT_TYPE_HUD) { - pos = mObjectSelection->getFirstRootObject(TRUE)->getPivotPositionAgent(); - scale = mObjectSelection->getFirstRootObject(TRUE)->getScale(); - rot = mObjectSelection->getFirstRootObject(TRUE)->getRotation(); - }else - { - pos = LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent(); - scale = LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal(); - rot = LLSelectMgr::getInstance()->getBBoxOfSelection().getRotation(); + if(pivot_as_percent) + offset = ((offset * .01f) - LLVector3(.5f,.5f,.5f)).scaleVec(mObjectSelection->getFirstRootObject(TRUE)->getScale()); + return mObjectSelection->getFirstObject()->getPivotPositionAgent() + offset * mObjectSelection->getFirstRootObject(TRUE)->getRotation(); } - if(sPivotPerc) - { - - LLVector3 add( - (-scale[VX]*0.5) + (scale[VX]*(sPivotX*0.01)), - (-scale[VY]*0.5) + (scale[VY]*(sPivotY*0.01)), - (-scale[VZ]*0.5) + (scale[VZ]*(sPivotZ*0.01))); - add = add * rot; - pos = pos + add; - }else - { - //pos[VX] = pos[VX] + gSavedSettings.getF32("EmeraldBuildPrefs_PivotX"); - //pos[VY] = pos[VY] + gSavedSettings.getF32("EmeraldBuildPrefs_PivotY"); - //pos[VZ] = pos[VZ] + gSavedSettings.getF32("EmeraldBuildPrefs_PivotZ"); - LLVector3 add( - sPivotX, - sPivotY, - sPivotZ); - add = add * rot; - pos = pos + add; - } - //pos = pos * rot; - return pos; + if(pivot_as_percent) + offset = ((offset * .01f) - LLVector3(.5f,.5f,.5f)).scaleVec(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal()); + return LLSelectMgr::getInstance()->getBBoxOfSelection().getCenterAgent() + offset * LLSelectMgr::getInstance()->getBBoxOfSelection().getRotation(); } @@ -514,17 +442,17 @@ void LLManip::renderXYZ(const LLVector3 &vec) const S32 PAD = 10; std::string feedback_string; LLVector3 camera_pos = LLViewerCamera::getInstance()->getOrigin() + LLViewerCamera::getInstance()->getAtAxis(); - S32 window_center_x = gViewerWindow->getWindowWidth() / 2; - S32 window_center_y = gViewerWindow->getWindowHeight() / 2; - S32 vertical_offset = window_center_y - VERTICAL_OFFSET; + S32 window_center_x = gViewerWindow->getWorldViewRectScaled().getWidth() / 2; + S32 window_center_y = gViewerWindow->getWorldViewRectScaled().getHeight() / 2; + S32 vertical_offset = window_center_y - VERTICAL_OFFSET; - - glPushMatrix(); + + gGL.pushMatrix(); { LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); gViewerWindow->setup2DRender(); const LLVector2& display_scale = gViewerWindow->getDisplayScale(); - glScalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); + gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); gGL.color4f(0.f, 0.f, 0.f, 0.7f); imagep->draw( @@ -534,7 +462,7 @@ void LLManip::renderXYZ(const LLVector3 &vec) PAD * 2 + 10, LLColor4(0.f, 0.f, 0.f, 0.7f) ); } - glPopMatrix(); + gGL.popMatrix(); gViewerWindow->setup3DRender(); @@ -586,9 +514,9 @@ void LLManip::renderTickText(const LLVector3& pos, const std::string& text, cons // render shadow first LLColor4 shadow_color = LLColor4::black; shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f; - gViewerWindow->setupViewport(1, -1); + gViewerWindow->setup3DViewport(1, -1); hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); - gViewerWindow->setupViewport(); + gViewerWindow->setup3DViewport(); hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); glPopMatrix(); @@ -648,19 +576,19 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const std::string { fraction_string = llformat("%c%02d%s", LLResMgr::getInstance()->getDecimalPoint(), fractional_portion, suffix.c_str()); - gViewerWindow->setupViewport(1, -1); + gViewerWindow->setup3DViewport(1, -1); hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, -1.f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection); hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, 1.f, 3.f, shadow_color, hud_selection); - gViewerWindow->setupViewport(); + gViewerWindow->setup3DViewport(); hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, -1.f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection); hud_render_utf8text(fraction_string, render_pos, *small_fontp, LLFontGL::NORMAL, 1.f, 3.f, color, hud_selection); } else { - gViewerWindow->setupViewport(1, -1); + gViewerWindow->setup3DViewport(1, -1); hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection); - gViewerWindow->setupViewport(); + gViewerWindow->setup3DViewport(); hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(val_string), 3.f, color, hud_selection); } glPopMatrix(); @@ -679,14 +607,14 @@ LLColor4 LLManip::setupSnapGuideRenderPass(S32 pass) { case 0: // shadow - gViewerWindow->setupViewport(1, -1); + gViewerWindow->setup3DViewport(1, -1); line_color = grid_color_shadow; line_color.mV[VALPHA] *= line_alpha; LLUI::setLineWidth(2.f); break; case 1: // hidden lines - gViewerWindow->setupViewport(); + gViewerWindow->setup3DViewport(); line_color = grid_color_bg; line_color.mV[VALPHA] *= line_alpha; LLUI::setLineWidth(1.f); diff --git a/indra/newview/llmanip.h b/indra/newview/llmanip.h index 9577412ed..cdf6a3657 100644 --- a/indra/newview/llmanip.h +++ b/indra/newview/llmanip.h @@ -151,13 +151,6 @@ protected: BOOL getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector3 origin, LLVector3 normal); BOOL nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param ); LLColor4 setupSnapGuideRenderPass(S32 pass); -private: - static void initPivot(); - static bool updateActualRoot(); - static bool updatePivotIsPercent(); - static bool updatePivotX(); - static bool updatePivotY(); - static bool updatePivotZ(); protected: LLFrameTimer mHelpTextTimer; BOOL mInSnapRegime; @@ -172,11 +165,6 @@ protected: static F32 sGridMaxSubdivisionLevel; static F32 sGridMinSubdivisionLevel; static LLVector2 sTickLabelSpacing; - static bool sActualRoot; - static bool sPivotPerc; - static F32 sPivotX; - static F32 sPivotY; - static F32 sPivotZ; }; diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index 8db7d7cb6..90d17bed6 100644 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -1108,8 +1108,11 @@ BOOL LLManipRotate::updateVisiblity() mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag; mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm; - mCenterScreen.set((S32)((0.5f - mRotationCenter.mdV[VY]) / gAgentCamera.mHUDCurZoom * gViewerWindow->getWindowWidth()), - (S32)((mRotationCenter.mdV[VZ] + 0.5f) / gAgentCamera.mHUDCurZoom * gViewerWindow->getWindowHeight())); + // x axis range is (-aspect * 0.5f, +aspect * 0.5) + // y axis range is (-0.5, 0.5) + // so use getWorldViewHeightRaw as scale factor when converting to pixel coordinates + mCenterScreen.set((S32)((0.5f - center.mV[VY]) / gAgentCamera.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled()), + (S32)((center.mV[VZ] + 0.5f) / gAgentCamera.mHUDCurZoom * gViewerWindow->getWorldViewHeightScaled())); visible = TRUE; } else @@ -1129,7 +1132,7 @@ BOOL LLManipRotate::updateVisiblity() if (gSavedSettings.getBOOL("LimitSelectDistance")) { F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance"); - if (dist_vec(gAgent.getPositionAgent(), center) > max_select_distance) + if (dist_vec_squared(gAgent.getPositionAgent(), center) > (max_select_distance * max_select_distance)) { visible = FALSE; } @@ -1625,8 +1628,8 @@ void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_ { if (LLSelectMgr::getInstance()->getSelection()->getSelectType() == SELECT_TYPE_HUD) { - F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) / gAgentCamera.mHUDCurZoom; - F32 mouse_y = ((((F32)y) / gViewerWindow->getWindowHeight()) - 0.5f) / gAgentCamera.mHUDCurZoom; + F32 mouse_x = (((F32)x / gViewerWindow->getWorldViewRectScaled().getWidth()) - 0.5f) / gAgentCamera.mHUDCurZoom; + F32 mouse_y = ((((F32)y) / gViewerWindow->getWorldViewRectScaled().getHeight()) - 0.5f) / gAgentCamera.mHUDCurZoom; *ray_pt = LLVector3(-1.f, -mouse_x, mouse_y); *ray_dir = LLVector3(1.f, 0.f, 0.f); @@ -1700,7 +1703,7 @@ void LLManipRotate::highlightManipulators( S32 x, S32 y ) F32 dist_y = mouse_dir_y.normVec(); F32 dist_z = mouse_dir_z.normVec(); - F32 distance_threshold = (MAX_MANIP_SELECT_DISTANCE * mRadiusMeters) / gViewerWindow->getWindowHeight(); + F32 distance_threshold = (MAX_MANIP_SELECT_DISTANCE * mRadiusMeters) / gViewerWindow->getWorldViewHeightScaled(); if (llabs(dist_x - mRadiusMeters) * llmax(0.05f, proj_rot_x_axis) < distance_threshold) { diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index bec6a49f4..3441df1a2 100644 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -58,11 +58,16 @@ #include "llui.h" #include "llviewercamera.h" #include "llviewerobject.h" +#include "llviewerregion.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llhudrender.h" #include "llworld.h" #include "v2math.h" #include "llvoavatar.h" +#if MESH_ENABLED +#include "llmeshrepository.h" +#endif //MESH_ENABLED const F32 MAX_MANIP_SELECT_DISTANCE_SQUARED = 11.f * 11.f; @@ -91,6 +96,25 @@ const LLManip::EManipPart MANIPULATOR_IDS[NUM_MANIPULATORS] = }; +F32 get_default_max_prim_scale(bool is_flora) +{ + // a bit of a hack, but if it's foilage, we don't want to use the + // new larger scale which would result in giant trees and grass +#if MESH_ENABLED + if (gMeshRepo.meshRezEnabled() && + !is_flora) + { + return DEFAULT_MAX_PRIM_SCALE; + } + else + { + return DEFAULT_MAX_PRIM_SCALE_NO_MESH; + } +#endif //MESH_ENABLED +#if !MESH_ENABLED + return DEFAULT_MAX_PRIM_SCALE; +#endif //!MESH_ENABLED +} // static void LLManipScale::setUniform(BOOL b) @@ -493,8 +517,9 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) mProjectedManipulators.insert(projManipulator); } - F32 half_width = (F32)gViewerWindow->getWindowWidth() / 2.f; - F32 half_height = (F32)gViewerWindow->getWindowHeight() / 2.f; + LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled(); + F32 half_width = (F32)world_view_rect.getWidth() / 2.f; + F32 half_height = (F32)world_view_rect.getHeight() / 2.f; LLVector2 manip2d; LLVector2 mousePos((F32)x - half_width, (F32)y - half_height); LLVector2 delta; @@ -953,8 +978,8 @@ void LLManipScale::dragCorner( S32 x, S32 y ) mInSnapRegime = FALSE; } - F32 max_scale_factor = DEFAULT_MAX_PRIM_SCALE / MIN_PRIM_SCALE; - F32 min_scale_factor = MIN_PRIM_SCALE / DEFAULT_MAX_PRIM_SCALE; + F32 max_scale_factor = get_default_max_prim_scale() / MIN_PRIM_SCALE; + F32 min_scale_factor = MIN_PRIM_SCALE / get_default_max_prim_scale(); // find max and min scale factors that will make biggest object hit max absolute scale and smallest object hit min absolute scale for (LLObjectSelection::iterator iter = mObjectSelection->begin(); @@ -966,7 +991,7 @@ void LLManipScale::dragCorner( S32 x, S32 y ) { const LLVector3& scale = selectNode->mSavedScale; - F32 cur_max_scale_factor = llmin( DEFAULT_MAX_PRIM_SCALE / scale.mV[VX], DEFAULT_MAX_PRIM_SCALE / scale.mV[VY], DEFAULT_MAX_PRIM_SCALE / scale.mV[VZ] ); + F32 cur_max_scale_factor = llmin( get_default_max_prim_scale(LLPickInfo::isFlora(cur)) / scale.mV[VX], get_default_max_prim_scale(LLPickInfo::isFlora(cur)) / scale.mV[VY], get_default_max_prim_scale(LLPickInfo::isFlora(cur)) / scale.mV[VZ] ); max_scale_factor = llmin( max_scale_factor, cur_max_scale_factor ); F32 cur_min_scale_factor = llmax( MIN_PRIM_SCALE / scale.mV[VX], MIN_PRIM_SCALE / scale.mV[VY], MIN_PRIM_SCALE / scale.mV[VZ] ); @@ -1263,7 +1288,7 @@ void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVecto F32 denom = axis * dir_local; F32 desired_delta_size = is_approx_zero(denom) ? 0.f : (delta_local_mag / denom); // in meters - F32 desired_scale = llclamp(selectNode->mSavedScale.mV[axis_index] + desired_delta_size, MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); + F32 desired_scale = llclamp(selectNode->mSavedScale.mV[axis_index] + desired_delta_size, MIN_PRIM_SCALE, get_default_max_prim_scale(LLPickInfo::isFlora(cur))); // propagate scale constraint back to position offset desired_delta_size = desired_scale - selectNode->mSavedScale.mV[axis_index]; // propagate constraint back to position @@ -1368,7 +1393,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) else { F32 object_distance = dist_vec(mScaleCenter, LLViewerCamera::getInstance()->getOrigin()); - mSnapRegimeOffset = (SNAP_GUIDE_SCREEN_OFFSET * gViewerWindow->getWindowWidth() * object_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio(); + mSnapRegimeOffset = (SNAP_GUIDE_SCREEN_OFFSET * gViewerWindow->getWorldViewWidthRaw() * object_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio(); } LLVector3 cam_at_axis; F32 snap_guide_length; @@ -1381,7 +1406,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) { cam_at_axis = LLViewerCamera::getInstance()->getAtAxis(); F32 manipulator_distance = dist_vec(box_corner_agent, LLViewerCamera::getInstance()->getOrigin()); - snap_guide_length = (SNAP_GUIDE_SCREEN_LENGTH * gViewerWindow->getWindowWidth() * manipulator_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio(); + snap_guide_length = (SNAP_GUIDE_SCREEN_LENGTH * gViewerWindow->getWorldViewWidthRaw() * manipulator_distance) / LLViewerCamera::getInstance()->getPixelMeterRatio(); } mSnapGuideLength = snap_guide_length / llmax(0.1f, (llmin(mSnapGuideDir1 * cam_at_axis, mSnapGuideDir2 * cam_at_axis))); @@ -1964,7 +1989,7 @@ F32 LLManipScale::partToMaxScale( S32 part, const LLBBox &bbox ) const max_extent = bbox_extents.mV[i]; } } - max_scale_factor = bbox_extents.magVec() * DEFAULT_MAX_PRIM_SCALE / max_extent; + max_scale_factor = bbox_extents.magVec() * get_default_max_prim_scale() / max_extent; if (getUniform()) { @@ -1979,7 +2004,7 @@ F32 LLManipScale::partToMinScale( S32 part, const LLBBox &bbox ) const { LLVector3 bbox_extents = unitVectorToLocalBBoxExtent( partToUnitVector( part ), bbox ); bbox_extents.abs(); - F32 min_extent = DEFAULT_MAX_PRIM_SCALE; + F32 min_extent = get_default_max_prim_scale(); for (U32 i = VX; i <= VZ; i++) { if (bbox_extents.mV[i] > 0.f && bbox_extents.mV[i] < min_extent) diff --git a/indra/newview/llmanipscale.h b/indra/newview/llmanipscale.h index 1de045989..2de75f2ce 100644 --- a/indra/newview/llmanipscale.h +++ b/indra/newview/llmanipscale.h @@ -45,6 +45,9 @@ #include "llviewerobject.h" #include "llbbox.h" + +F32 get_default_max_prim_scale(bool is_flora = false); + class LLToolComposite; class LLColor4; diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index ed88881f8..81f2ea618 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -106,6 +106,16 @@ const U32 ARROW_TO_AXIS[4] = VZ }; +// Sort manipulator handles by their screen-space projection +struct ClosestToCamera +{ + bool operator()(const LLManipTranslate::ManipulatorHandle& a, + const LLManipTranslate::ManipulatorHandle& b) const + { + return a.mEndPosition.mV[VZ] < b.mEndPosition.mV[VZ]; + } +}; + LLManipTranslate::LLManipTranslate( LLToolComposite* composite ) : LLManip( std::string("Move"), composite ), mLastHoverMouseX(-1), @@ -118,9 +128,13 @@ LLManipTranslate::LLManipTranslate( LLToolComposite* composite ) mAxisArrowLength(50), mConeSize(0), mArrowLengthMeters(0.f), + mGridSizeMeters(1.f), mPlaneManipOffsetMeters(0.f), mUpdateTimer(), mSnapOffsetMeters(0.f), + mSubdivisions(10.f), + mInSnapRegime(FALSE), + mSnapped(FALSE), mArrowScales(1.f, 1.f, 1.f), mPlaneScales(1.f, 1.f, 1.f), mPlaneManipPositions(1.f, 1.f, 1.f, 1.f) @@ -278,7 +292,6 @@ void LLManipTranslate::restoreGL() LLManipTranslate::~LLManipTranslate() { - for_each(mProjectedManipulators.begin(), mProjectedManipulators.end(), DeletePointer()); } @@ -418,8 +431,9 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) } // Handle auto-rotation if necessary. + LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); const F32 ROTATE_ANGLE_PER_SECOND = 30.f * DEG_TO_RAD; - const S32 ROTATE_H_MARGIN = gViewerWindow->getWindowWidth() / 20; + const S32 ROTATE_H_MARGIN = world_rect.getWidth() / 20; const F32 rotate_angle = ROTATE_ANGLE_PER_SECOND / gFPSClamped; BOOL rotated = FALSE; @@ -431,7 +445,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) gAgentCamera.cameraOrbitAround(rotate_angle); rotated = TRUE; } - else if (x > gViewerWindow->getWindowWidth() - ROTATE_H_MARGIN) + else if (x > world_rect.getWidth() - ROTATE_H_MARGIN) { gAgentCamera.cameraOrbitAround(-rotate_angle); rotated = TRUE; @@ -729,7 +743,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) LLVector3d new_position_global = selectNode->mSavedPositionGlobal + clamped_relative_move; // Don't let object centers go too far underground - F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object); + F64 min_height = LLWorld::getInstance()->getMinAllowedZ(object, object->getPositionGlobal()); if (new_position_global.mdV[VZ] < min_height) { new_position_global.mdV[VZ] = min_height; @@ -899,8 +913,9 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) planar_manip_xy_visible = TRUE; } - for_each(mProjectedManipulators.begin(), mProjectedManipulators.end(), DeletePointer()); - mProjectedManipulators.clear(); + // Project up to 9 manipulators to screen space 2*X, 2*Y, 2*Z, 3*planes + std::vector<ManipulatorHandle> projected_manipulators; + projected_manipulators.reserve(9); for (S32 i = 0; i < num_arrow_manips; i+= 2) { @@ -910,12 +925,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; projected_end = projected_end * (1.f / projected_end.mV[VW]); - ManipulatorHandle* projManipulator = - new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), MANIPULATOR_IDS[i / 2], 10.f); // 10 pixel hotspot for arrows - mProjectedManipulators.insert(projManipulator); + projected_manipulators.push_back(projected_manip); } if (planar_manip_yz_visible) @@ -927,12 +942,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; projected_end = projected_end * (1.f / projected_end.mV[VW]); - ManipulatorHandle* projManipulator = - new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), MANIPULATOR_IDS[i / 2], 20.f); // 20 pixels for planar manipulators - mProjectedManipulators.insert(projManipulator); + projected_manipulators.push_back(projected_manip); } if (planar_manip_xz_visible) @@ -944,12 +959,12 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; projected_end = projected_end * (1.f / projected_end.mV[VW]); - ManipulatorHandle* projManipulator = - new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), MANIPULATOR_IDS[i / 2], 20.f); // 20 pixels for planar manipulators - mProjectedManipulators.insert(projManipulator); + projected_manipulators.push_back(projected_manip); } if (planar_manip_xy_visible) @@ -961,29 +976,35 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLVector4 projected_end = mManipulatorVertices[i + 1] * transform; projected_end = projected_end * (1.f / projected_end.mV[VW]); - ManipulatorHandle* projManipulator = - new ManipulatorHandle(LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), + ManipulatorHandle projected_manip( + LLVector3(projected_start.mV[VX], projected_start.mV[VY], projected_start.mV[VZ]), LLVector3(projected_end.mV[VX], projected_end.mV[VY], projected_end.mV[VZ]), MANIPULATOR_IDS[i / 2], 20.f); // 20 pixels for planar manipulators - mProjectedManipulators.insert(projManipulator); + projected_manipulators.push_back(projected_manip); } LLVector2 manip_start_2d; LLVector2 manip_end_2d; LLVector2 manip_dir; - F32 half_width = gViewerWindow->getWindowWidth() / 2.f; - F32 half_height = gViewerWindow->getWindowHeight() / 2.f; + LLRect world_view_rect = gViewerWindow->getWorldViewRectScaled(); + F32 half_width = (F32)world_view_rect.getWidth() / 2.f; + F32 half_height = (F32)world_view_rect.getHeight() / 2.f; LLVector2 mousePos((F32)x - half_width, (F32)y - half_height); LLVector2 mouse_delta; - for (minpulator_list_t::iterator iter = mProjectedManipulators.begin(); - iter != mProjectedManipulators.end(); ++iter) + // Keep order consistent with insertion via stable_sort + std::stable_sort( projected_manipulators.begin(), + projected_manipulators.end(), + ClosestToCamera() ); + + std::vector<ManipulatorHandle>::iterator it = projected_manipulators.begin(); + for ( ; it != projected_manipulators.end(); ++it) { - ManipulatorHandle* manipulator = *iter; + ManipulatorHandle& manipulator = *it; { - manip_start_2d.setVec(manipulator->mStartPosition.mV[VX] * half_width, manipulator->mStartPosition.mV[VY] * half_height); - manip_end_2d.setVec(manipulator->mEndPosition.mV[VX] * half_width, manipulator->mEndPosition.mV[VY] * half_height); + manip_start_2d.setVec(manipulator.mStartPosition.mV[VX] * half_width, manipulator.mStartPosition.mV[VY] * half_height); + manip_end_2d.setVec(manipulator.mEndPosition.mV[VX] * half_width, manipulator.mEndPosition.mV[VY] * half_height); manip_dir = manip_end_2d - manip_start_2d; mouse_delta = mousePos - manip_start_2d; @@ -995,9 +1016,9 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) if (mouse_pos_manip > 0.f && mouse_pos_manip < manip_length && - mouse_dist_manip_squared < manipulator->mHotSpotRadius * manipulator->mHotSpotRadius) + mouse_dist_manip_squared < manipulator.mHotSpotRadius * manipulator.mHotSpotRadius) { - mHighlightedPart = manipulator->mManipID; + mHighlightedPart = manipulator.mManipID; break; } } @@ -1238,7 +1259,7 @@ void LLManipTranslate::renderSnapGuides() { LLVector3 cam_to_selection = getPivotPoint() - LLViewerCamera::getInstance()->getOrigin(); F32 current_range = cam_to_selection.normVec(); - guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWindowHeight() * current_range / LLViewerCamera::getInstance()->getPixelMeterRatio(); + guide_size_meters = SNAP_GUIDE_SCREEN_SIZE * gViewerWindow->getWorldViewHeightRaw() * current_range / LLViewerCamera::getInstance()->getPixelMeterRatio(); F32 fraction_of_fov = mAxisArrowLength / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels(); F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians @@ -1813,7 +1834,7 @@ void LLManipTranslate::renderTranslationHandles() // Drag handles if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { - mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWindowHeight(); + mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWorldViewHeightRaw(); mArrowLengthMeters /= gAgentCamera.mHUDCurZoom; } else diff --git a/indra/newview/llmaniptranslate.h b/indra/newview/llmaniptranslate.h index 25ff35cc7..d20b86b2f 100644 --- a/indra/newview/llmaniptranslate.h +++ b/indra/newview/llmaniptranslate.h @@ -89,17 +89,6 @@ protected: F32 getMinGridScale(); private: - struct compare_manipulators - { - bool operator() (const ManipulatorHandle* const a, const ManipulatorHandle* const b) const - { - if (a->mEndPosition.mV[VZ] != b->mEndPosition.mV[VZ]) - return (a->mEndPosition.mV[VZ] < b->mEndPosition.mV[VZ]); - else - return a->mManipID < b->mManipID; - } - }; - S32 mLastHoverMouseX; S32 mLastHoverMouseY; BOOL mSendUpdateOnMouseUp; @@ -116,8 +105,6 @@ private: LLVector3d mDragCursorStartGlobal; LLVector3d mDragSelectionStartGlobal; LLTimer mUpdateTimer; - typedef std::set<ManipulatorHandle*, compare_manipulators> minpulator_list_t; - minpulator_list_t mProjectedManipulators; LLVector4 mManipulatorVertices[18]; F32 mSnapOffsetMeters; LLVector3 mSnapOffsetAxis; diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index f524be097..842ab3b97 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -45,7 +45,7 @@ #include "llviewercontrol.h" #include "llviewermedia.h" #include "llviewerwindow.h" -#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llweb.h" #include "llrender.h" #include "llpluginclassmedia.h" @@ -64,6 +64,7 @@ static LLRegisterWidget<LLMediaCtrl> r("web_browser"); LLMediaCtrl::LLMediaCtrl( const std::string& name, const LLRect& rect ) : LLUICtrl( name, rect, FALSE, NULL, NULL ), + LLInstanceTracker<LLMediaCtrl, LLUUID>(LLUUID::generateNewID()), mTextureDepthBytes( 4 ), mWebBrowserImage( 0 ), mBorder(NULL), @@ -82,28 +83,26 @@ LLMediaCtrl::LLMediaCtrl( const std::string& name, const LLRect& rect ) : mLastSetCursor( UI_CURSOR_ARROW ), mStretchToFill( true ), mMaintainAspectRatio ( true ), + mDecoupleTextureSize ( false ), + mTextureWidth ( 1024 ), + mTextureHeight ( 1024 ), mHideLoading (false) { - S32 screen_width = mIgnoreUIScale ? - llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth(); - S32 screen_height = mIgnoreUIScale ? - llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight(); - - mMediaSource = LLViewerMedia::newMediaImpl(mHomePageUrl, LLUUID::null, screen_width, screen_height, false, false, "text/html"); - if ( !mMediaSource ) + if(!getDecoupleTextureSize()) { - llwarns << "media source create failed " << llendl; - return; + S32 screen_width = mIgnoreUIScale ? + llround((F32)getRect().getWidth() * LLUI::sGLScaleFactor.mV[VX]) : getRect().getWidth(); + S32 screen_height = mIgnoreUIScale ? + llround((F32)getRect().getHeight() * LLUI::sGLScaleFactor.mV[VY]) : getRect().getHeight(); + + setTextureSize(screen_width, screen_height); } - else + // We don't need to create the media source up front anymore unless we have a non-empty home URL to navigate to. + if(!mHomePageUrl.empty()) { - // create a new texture (based on LLDynamic texture) that will be used to display the output - mWebBrowserImage = new LLWebBrowserTexture( screen_width, screen_height, this, mMediaSource ); + navigateHome(); } - - mMediaSource->setVisible( getVisible() ); - - mMediaSource->addObserver( this ); + LLRect border_rect( 0, getRect().getHeight() + 2, getRect().getWidth() + 2, 0 ); mBorder = new LLViewBorder( std::string("web control border"), border_rect, LLViewBorder::BEVEL_IN ); @@ -121,10 +120,7 @@ LLMediaCtrl::~LLMediaCtrl() mMediaSource = NULL; } - if ( mWebBrowserImage ) - { - mWebBrowserImage = NULL; - } + mWebBrowserImage = NULL; } //////////////////////////////////////////////////////////////////////////////// @@ -144,6 +140,7 @@ void LLMediaCtrl::setTakeFocusOnClick( bool take_focus ) mTakeFocusOnClick = take_focus; } + //////////////////////////////////////////////////////////////////////////////// // set flag that forces the embedded browser to open links in the external system browser void LLMediaCtrl::setOpenInExternalBrowser( bool valIn ) @@ -168,12 +165,15 @@ void LLMediaCtrl::setTrusted( bool valIn ) // BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask ) { + if (LLUICtrl::handleHover(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) + { mMediaSource->mouseMove(x, y); - gViewerWindow->setCursor(mLastSetCursor); + gViewerWindow->setCursor(mLastSetCursor); + } return TRUE; } @@ -182,6 +182,7 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask ) // BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks ) { + if (LLUICtrl::handleScrollWheel(x, y, clicks)) return TRUE; if (mMediaSource && mMediaSource->hasMedia()) mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, MASK_NONE); @@ -192,19 +193,20 @@ BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks ) // BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) { + if (LLUICtrl::handleMouseUp(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) { mMediaSource->mouseUp(x, y); - // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup, + /*// *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup, // in addition to the onFocusReceived() call below. Undo this. JC if (!mTakeFocusOnClick) { mMediaSource->focus(false); gViewerWindow->focusClient(); - } + }*/ } gFocusMgr.setMouseCapture( NULL ); @@ -216,6 +218,7 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) // BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask ) { + if (LLUICtrl::handleMouseDown(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) @@ -233,12 +236,60 @@ BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask ) //////////////////////////////////////////////////////////////////////////////// // -BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask ) +BOOL LLMediaCtrl::handleRightMouseUp( S32 x, S32 y, MASK mask ) { + /*if (LLPanel::handleRightMouseUp(x, y, mask)) return TRUE; convertInputCoords(x, y); if (mMediaSource) - mMediaSource->mouseLeftDoubleClick( x, y ); + { + mMediaSource->mouseUp(x, y, mask, 1); + + // *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup, + // in addition to the onFocusReceived() call below. Undo this. JC + if (!mTakeFocusOnClick) + { + mMediaSource->focus(false); + gViewerWindow->focusClient(); + } + } + + gFocusMgr.setMouseCapture( NULL ); + */ + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleRightMouseDown( S32 x, S32 y, MASK mask ) +{ + if (LLUICtrl::handleRightMouseDown(x, y, mask)) return TRUE; + + /*S32 media_x = x, media_y = y; + convertInputCoords(media_x, media_y); + + if (mMediaSource) + mMediaSource->mouseDown(media_x, media_y); + + gFocusMgr.setMouseCapture( this ); + + if (mTakeFocusOnClick) + { + setFocus( TRUE ); + } + */ + return TRUE; +} + +//////////////////////////////////////////////////////////////////////////////// +// +BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask ) +{ + if (LLUICtrl::handleDoubleClick(x, y, mask)) return TRUE; + convertInputCoords(x, y); + + if (mMediaSource) + mMediaSource->mouseLeftDoubleClick( x, y); gFocusMgr.setMouseCapture( this ); @@ -374,18 +425,18 @@ void LLMediaCtrl::onVisibilityChange ( BOOL new_visibility ) // void LLMediaCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) { - S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width; - S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height; - -// llinfos << "reshape called with width = " << width << ", height = " << height << llendl; - - // when floater is minimized, these sizes are negative - if ( mWebBrowserImage && screen_height > 0 && screen_width > 0 ) + if(!getDecoupleTextureSize()) { - mWebBrowserImage->resize( screen_width, screen_height ); - mForceUpdate = true; - } + S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width; + S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VY]) : height; + // when floater is minimized, these sizes are negative + if ( screen_height > 0 && screen_width > 0 ) + { + setTextureSize(screen_width, screen_height); + } + } + LLUICtrl::reshape( width, height, called_from_parent ); } @@ -460,9 +511,10 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) return; } - if (mMediaSource) + if (ensureMediaSourceExists()) { mCurrentNavUrl = url_in; + mMediaSource->setSize(mTextureWidth, mTextureHeight); mMediaSource->navigateTo(url_in, mime_type, mime_type.empty()); } } @@ -498,9 +550,10 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str return; } } - if (mMediaSource) + if (ensureMediaSourceExists()) { mCurrentNavUrl = expanded_filename; + mMediaSource->setSize(mTextureWidth, mTextureHeight); mMediaSource->navigateTo(expanded_filename, "text/html", false); } @@ -510,11 +563,11 @@ void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::str // void LLMediaCtrl::navigateHome() { - if( mHomePageUrl.length() ) + if (ensureMediaSourceExists()) { - if (mMediaSource) - mMediaSource->navigateTo(mHomePageUrl); - }; + mMediaSource->setSize(mTextureWidth, mTextureHeight); + mMediaSource->navigateHome(); + } } //////////////////////////////////////////////////////////////////////////////// @@ -522,6 +575,10 @@ void LLMediaCtrl::navigateHome() void LLMediaCtrl::setHomePageUrl( const std::string urlIn ) { mHomePageUrl = urlIn; + if (mMediaSource) + { + mMediaSource->setHomeURL(mHomePageUrl); + } } //////////////////////////////////////////////////////////////////////////////// @@ -531,6 +588,22 @@ bool LLMediaCtrl::setCaretColor(unsigned int red, unsigned int green, unsigned i //NOOP return false; } + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::setTextureSize(S32 width, S32 height) +{ + mTextureWidth = width; + mTextureHeight = height; + + if(mMediaSource) + { + mMediaSource->setSize(mTextureWidth, mTextureHeight); + mWebBrowserImage->resize( mTextureWidth, mTextureHeight ); + mForceUpdate = true; + } +} + //////////////////////////////////////////////////////////////////////////////// // std::string LLMediaCtrl::getHomePageUrl() @@ -538,6 +611,39 @@ std::string LLMediaCtrl::getHomePageUrl() return mHomePageUrl; } +//////////////////////////////////////////////////////////////////////////////// +// +bool LLMediaCtrl::ensureMediaSourceExists() +{ + if(mMediaSource.isNull()) + { + mMediaSource = LLViewerMedia::newMediaImpl(mHomePageUrl, LLUUID::null, mTextureWidth, mTextureWidth, false, false, "text/html"); + if ( mMediaSource ) + { + // create a new texture (based on LLDynamic texture) that will be used to display the output + mWebBrowserImage = new LLWebBrowserTexture( mTextureWidth, mTextureWidth, this, mMediaSource ); + mMediaSource->setHomeURL(mHomePageUrl); + mMediaSource->setVisible( getVisible() ); + mMediaSource->addObserver( this ); + } + else + { + llwarns << "media source create failed " << llendl; + // return; + } + } + + return !mMediaSource.isNull(); +} + +//////////////////////////////////////////////////////////////////////////////// +// +void LLMediaCtrl::unloadMediaSource() +{ + mMediaSource = NULL; + mWebBrowserImage = NULL; //release the dynamic texture too. +} + //////////////////////////////////////////////////////////////////////////////// // LLPluginClassMedia* LLMediaCtrl::getMediaPlugin() @@ -575,111 +681,132 @@ void LLMediaCtrl::draw() LLGLSUIDefault gls_ui; LLGLDisable gls_alphaTest( GL_ALPHA_TEST ); - gGL.pushMatrix(); + bool draw_media = false; + + LLPluginClassMedia* media_plugin = NULL; + LLWebBrowserTexture* media_texture = mWebBrowserImage; + + if(mMediaSource && mMediaSource->hasMedia()) { - if (mIgnoreUIScale) - { - glLoadIdentity(); - // font system stores true screen origin, need to scale this by UI scale factor - // to get render origin for this view (with unit scale) - gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), - floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), - LLFontGL::sCurOrigin.mZ); - } + media_plugin = mMediaSource->getMediaPlugin(); - // scale texture to fit the space using texture coords - gGL.getTexUnit(0)->bind(mWebBrowserImage); - gGL.color4fv( LLColor4::white.mV ); - F32 max_u = ( F32 )mWebBrowserImage->getMediaWidth() / ( F32 )mWebBrowserImage->getWidth(); - F32 max_v = ( F32 )mWebBrowserImage->getMediaHeight() / ( F32 )mWebBrowserImage->getHeight(); - - LLRect r = getRect(); - S32 width, height; - S32 x_offset = 0; - S32 y_offset = 0; - - if(mStretchToFill) + if(media_plugin && (media_plugin->textureValid())) { - if(mMaintainAspectRatio) + media_texture = mWebBrowserImage; + if(media_texture) { - F32 media_aspect = (F32)(mWebBrowserImage->getMediaWidth()) / (F32)(mWebBrowserImage->getMediaHeight()); - F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); - if(media_aspect > view_aspect) + draw_media = true; + } + } + } + if(draw_media) + { + gGL.pushMatrix(); + { + if (mIgnoreUIScale) + { + glLoadIdentity(); + // font system stores true screen origin, need to scale this by UI scale factor + // to get render origin for this view (with unit scale) + gGL.translatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), + floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), + LLFontGL::sCurOrigin.mZ); + } + + // scale texture to fit the space using texture coords + gGL.getTexUnit(0)->bind(media_texture); + LLColor4 media_color = LLColor4::white; + gGL.color4fv( media_color.mV ); + F32 max_u = ( F32 )media_plugin->getWidth() / ( F32 )media_plugin->getTextureWidth(); + F32 max_v = ( F32 )media_plugin->getHeight() / ( F32 )media_plugin->getTextureHeight(); + + LLRect r = getRect(); + S32 width, height; + S32 x_offset = 0; + S32 y_offset = 0; + + if(mStretchToFill) + { + if(mMaintainAspectRatio) { - // max width, adjusted height - width = r.getWidth(); - height = llmin(llmax(S32(width / media_aspect), 0), r.getHeight()); + F32 media_aspect = (F32)(media_plugin->getWidth()) / (F32)(media_plugin->getHeight()); + F32 view_aspect = (F32)(r.getWidth()) / (F32)(r.getHeight()); + if(media_aspect > view_aspect) + { + // max width, adjusted height + width = r.getWidth(); + height = llmin(llmax(llround(width / media_aspect), 0), r.getHeight()); + } + else + { + // max height, adjusted width + height = r.getHeight(); + width = llmin(llmax(llround(height * media_aspect), 0), r.getWidth()); + } } else { - // max height, adjusted width + width = r.getWidth(); height = r.getHeight(); - width = llmin(llmax(S32(height * media_aspect), 0), r.getWidth()); } } else { - width = r.getWidth(); - height = r.getHeight(); + width = llmin(media_plugin->getWidth(), r.getWidth()); + height = llmin(media_plugin->getHeight(), r.getHeight()); } + + x_offset = (r.getWidth() - width) / 2; + y_offset = (r.getHeight() - height) / 2; + + if (mIgnoreUIScale) + { + x_offset = llround((F32)x_offset * LLUI::sGLScaleFactor.mV[VX]); + y_offset = llround((F32)y_offset * LLUI::sGLScaleFactor.mV[VY]); + width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]); + height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]); + } + + // draw the browser + gGL.setSceneBlendType(LLRender::BT_REPLACE); + gGL.begin( LLRender::QUADS ); + if (! media_plugin->getTextureCoordsOpenGL()) + { + // render using web browser reported width and height, instead of trying to invert GL scale + gGL.texCoord2f( max_u, 0.f ); + gGL.vertex2i( x_offset + width, y_offset + height ); + + gGL.texCoord2f( 0.f, 0.f ); + gGL.vertex2i( x_offset, y_offset + height ); + + gGL.texCoord2f( 0.f, max_v ); + gGL.vertex2i( x_offset, y_offset ); + + gGL.texCoord2f( max_u, max_v ); + gGL.vertex2i( x_offset + width, y_offset ); + } + else + { + // render using web browser reported width and height, instead of trying to invert GL scale + gGL.texCoord2f( max_u, max_v ); + gGL.vertex2i( x_offset + width, y_offset + height ); + + gGL.texCoord2f( 0.f, max_v ); + gGL.vertex2i( x_offset, y_offset + height ); + + gGL.texCoord2f( 0.f, 0.f ); + gGL.vertex2i( x_offset, y_offset ); + + gGL.texCoord2f( max_u, 0.f ); + gGL.vertex2i( x_offset + width, y_offset ); + } + gGL.end(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); } - else - { - width = llmin(mWebBrowserImage->getMediaWidth(), r.getWidth()); - height = llmin(mWebBrowserImage->getMediaHeight(), r.getHeight()); - } - - x_offset = (r.getWidth() - width) / 2; - y_offset = (r.getHeight() - height) / 2; - - if (mIgnoreUIScale) - { - width = llround((F32)width * LLUI::sGLScaleFactor.mV[VX]); - height = llround((F32)height * LLUI::sGLScaleFactor.mV[VY]); - x_offset = llround((F32)x_offset * LLUI::sGLScaleFactor.mV[VX]); - y_offset = llround((F32)y_offset * LLUI::sGLScaleFactor.mV[VY]); - } - - // draw the browser - gGL.setSceneBlendType(LLRender::BT_REPLACE); - gGL.begin( LLRender::QUADS ); - if (! mWebBrowserImage->getTextureCoordsOpenGL()) - { - // render using web browser reported width and height, instead of trying to invert GL scale - gGL.texCoord2f( max_u, 0.f ); - gGL.vertex2i( x_offset + width, y_offset + height ); - - gGL.texCoord2f( 0.f, 0.f ); - gGL.vertex2i( x_offset, y_offset + height ); - - gGL.texCoord2f( 0.f, max_v ); - gGL.vertex2i( x_offset, y_offset ); - - gGL.texCoord2f( max_u, max_v ); - gGL.vertex2i( x_offset + width, y_offset ); - } - else - { - // render using web browser reported width and height, instead of trying to invert GL scale - gGL.texCoord2f( max_u, max_v ); - gGL.vertex2i( x_offset + width, y_offset + height ); - - gGL.texCoord2f( 0.f, max_v ); - gGL.vertex2i( x_offset, y_offset + height ); - - gGL.texCoord2f( 0.f, 0.f ); - gGL.vertex2i( x_offset, y_offset ); - - gGL.texCoord2f( max_u, 0.f ); - gGL.vertex2i( x_offset + width, y_offset ); - } - gGL.end(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + gGL.popMatrix(); } - gGL.popMatrix(); - // highlight if keyboard focus here. (TODO: this needs some work) - if ( mBorder->getVisible() ) + if ( mBorder && mBorder->getVisible() ) mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) ); @@ -690,8 +817,15 @@ void LLMediaCtrl::draw() // void LLMediaCtrl::convertInputCoords(S32& x, S32& y) { + bool coords_opengl = false; + + if(mMediaSource && mMediaSource->hasMedia()) + { + coords_opengl = mMediaSource->getMediaPlugin()->getTextureCoordsOpenGL(); + } + x = mIgnoreUIScale ? llround((F32)x * LLUI::sGLScaleFactor.mV[VX]) : x; - if ( ! mWebBrowserImage->getTextureCoordsOpenGL() ) + if ( ! coords_opengl ) { y = mIgnoreUIScale ? llround((F32)(y) * LLUI::sGLScaleFactor.mV[VY]) : y; } @@ -832,6 +966,11 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event) LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL; }; break; + + default: + { + LL_WARNS("Media") << "Media event: unknown event type" << LL_ENDL; + }; }; // chain all events to any potential observers of this object. @@ -903,7 +1042,7 @@ void LLMediaCtrl::onClickLinkNoFollow( LLPluginClassMedia* self ) && !mTrusted) { // block handling of this secondlife:///app/ URL - LLNotifications::instance().add("UnableToOpenCommandURL"); + LLNotificationsUtil::add("UnableToOpenCommandURL"); return; } @@ -930,7 +1069,6 @@ LLWebBrowserTexture::LLWebBrowserTexture( S32 width, S32 height, LLMediaCtrl* br LLWebBrowserTexture::~LLWebBrowserTexture() { mElapsedTime.stop(); - mMediaSource = NULL; } //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index bbf2dfa01..bd5fa03ac 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -48,7 +48,8 @@ class LLUICtrlFactory; class LLMediaCtrl : public LLUICtrl, public LLViewerMediaObserver, - public LLViewerMediaEventEmitter + public LLViewerMediaEventEmitter, + public LLInstanceTracker<LLMediaCtrl, LLUUID> { public: LLMediaCtrl( const std::string& name, const LLRect& rect ); @@ -69,6 +70,8 @@ class LLMediaCtrl : virtual BOOL handleHover( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseUp( S32 x, S32 y, MASK mask ); virtual BOOL handleMouseDown( S32 x, S32 y, MASK mask ); + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); virtual BOOL handleScrollWheel( S32 x, S32 y, S32 clicks ); @@ -112,10 +115,17 @@ class LLMediaCtrl : void setForceUpdate(bool force_update) { mForceUpdate = force_update; } bool getForceUpdate() { return mForceUpdate; } + bool ensureMediaSourceExists(); + void unloadMediaSource(); + LLPluginClassMedia* getMediaPlugin(); bool setCaretColor( unsigned int red, unsigned int green, unsigned int blue ); + + void setDecoupleTextureSize(bool decouple) { mDecoupleTextureSize = decouple; } + bool getDecoupleTextureSize() { return mDecoupleTextureSize; } + void setTextureSize(S32 width, S32 height); // over-rides virtual BOOL handleKeyHere( KEY key, MASK mask); @@ -143,6 +153,7 @@ class LLMediaCtrl : static bool onClickLinkExternalTarget( const LLSD&, const LLSD& ); const S32 mTextureDepthBytes; + LLUUID mMediaTextureID; LLPointer<LLWebBrowserTexture> mWebBrowserImage; LLViewBorder* mBorder; bool mFrequentUpdates; @@ -161,6 +172,9 @@ class LLMediaCtrl : bool mStretchToFill; bool mMaintainAspectRatio; bool mHideLoading; + bool mDecoupleTextureSize; + S32 mTextureWidth; + S32 mTextureHeight; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp new file mode 100644 index 000000000..bacde05f2 --- /dev/null +++ b/indra/newview/llmeshrepository.cpp @@ -0,0 +1,3612 @@ +/** + * @file llmeshrepository.cpp + * @brief Mesh repository implementation. + * + * $LicenseInfo:firstyear=2005&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#if MESH_ENABLED +#include "apr_pools.h" +#include "apr_dso.h" +#include "llhttpstatuscodes.h" +#include "llmeshrepository.h" + +#include "llagent.h" +#include "llappviewer.h" +#include "llbufferstream.h" +#include "llcurl.h" +#include "lldatapacker.h" +#include "llfasttimer.h" +#if MESH_IMPORT +#include "llfloatermodelpreview.h" +#endif //MESH_IMPORT +#include "llfloaterperms.h" +#include "lleconomy.h" +#include "llimagej2c.h" +#include "llhost.h" +#include "llnotificationsutil.h" +#include "llsd.h" +#include "llsdutil_math.h" +#include "llsdserialize.h" +#include "llthread.h" +#include "llvfile.h" +#include "llviewercontrol.h" +#include "llviewermenufile.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llviewertexturelist.h" +#include "llvolume.h" +#include "llvolumemgr.h" +#include "llvovolume.h" +#include "llworld.h" +#include "material_codes.h" +#include "pipeline.h" +#include "llinventorymodel.h" +#include "llfoldertype.h" +#include "llviewerparcelmgr.h" + +#include "boost/lexical_cast.hpp" +#ifndef LL_WINDOWS +#include "netdb.h" +#endif + +#include <queue> + +//LLFastTimer::DeclareTimer FTM_MESH_UPDATE("Mesh Update"); +//LLFastTimer::DeclareTimer FTM_LOAD_MESH("Load Mesh"); + +LLMeshRepository gMeshRepo; + +const U32 MAX_MESH_REQUESTS_PER_SECOND = 100; + +// Maximum mesh version to support. Three least significant digits are reserved for the minor version, +// with major version changes indicating a format change that is not backwards compatible and should not +// be parsed by viewers that don't specifically support that version. For example, if the integer "1" is +// present, the version is 0.001. A viewer that can parse version 0.001 can also parse versions up to 0.999, +// but not 1.0 (integer 1000). +// See wiki at https://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format +const S32 MAX_MESH_VERSION = 999; + +U32 LLMeshRepository::sBytesReceived = 0; +U32 LLMeshRepository::sHTTPRequestCount = 0; +U32 LLMeshRepository::sHTTPRetryCount = 0; +U32 LLMeshRepository::sCacheBytesRead = 0; +U32 LLMeshRepository::sCacheBytesWritten = 0; +U32 LLMeshRepository::sPeakKbps = 0; + + +const U32 MAX_TEXTURE_UPLOAD_RETRIES = 5; + +static S32 dump_num = 0; +std::string make_dump_name(std::string prefix, S32 num) +{ + return prefix + boost::lexical_cast<std::string>(num) + std::string(".xml"); + +} +void dump_llsd_to_file(const LLSD& content, std::string filename); +LLSD llsd_from_file(std::string filename); + +std::string header_lod[] = +{ + "lowest_lod", + "low_lod", + "medium_lod", + "high_lod" +}; + + +//get the number of bytes resident in memory for given volume +U32 get_volume_memory_size(const LLVolume* volume) +{ + U32 indices = 0; + U32 vertices = 0; + + for (U32 i = 0; i < (U32)volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + indices += face.mNumIndices; + vertices += face.mNumVertices; + } + + + return indices*2+vertices*11+sizeof(LLVolume)+sizeof(LLVolumeFace)*volume->getNumVolumeFaces(); +} + +void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res, F32 scale = 1.f) +{ + res.mPositions.clear(); + res.mNormals.clear(); + + const F32* v = mesh.mVertexBase; + + if (mesh.mIndexType == LLCDMeshData::INT_16) + { + U16* idx = (U16*) mesh.mIndexBase; + for (S32 j = 0; j < mesh.mNumTriangles; ++j) + { + F32* mp0 = (F32*) ((U8*)v+idx[0]*mesh.mVertexStrideBytes); + F32* mp1 = (F32*) ((U8*)v+idx[1]*mesh.mVertexStrideBytes); + F32* mp2 = (F32*) ((U8*)v+idx[2]*mesh.mVertexStrideBytes); + + idx = (U16*) (((U8*)idx)+mesh.mIndexStrideBytes); + + LLVector3 v0(mp0); + LLVector3 v1(mp1); + LLVector3 v2(mp2); + + LLVector3 n = (v1-v0)%(v2-v0); + n.normalize(); + + res.mPositions.push_back(v0*scale); + res.mPositions.push_back(v1*scale); + res.mPositions.push_back(v2*scale); + + res.mNormals.push_back(n); + res.mNormals.push_back(n); + res.mNormals.push_back(n); + } + } + else + { + U32* idx = (U32*) mesh.mIndexBase; + for (S32 j = 0; j < mesh.mNumTriangles; ++j) + { + F32* mp0 = (F32*) ((U8*)v+idx[0]*mesh.mVertexStrideBytes); + F32* mp1 = (F32*) ((U8*)v+idx[1]*mesh.mVertexStrideBytes); + F32* mp2 = (F32*) ((U8*)v+idx[2]*mesh.mVertexStrideBytes); + + idx = (U32*) (((U8*)idx)+mesh.mIndexStrideBytes); + + LLVector3 v0(mp0); + LLVector3 v1(mp1); + LLVector3 v2(mp2); + + LLVector3 n = (v1-v0)%(v2-v0); + n.normalize(); + + res.mPositions.push_back(v0*scale); + res.mPositions.push_back(v1*scale); + res.mPositions.push_back(v2*scale); + + res.mNormals.push_back(n); + res.mNormals.push_back(n); + res.mNormals.push_back(n); + } + } +} + +S32 LLMeshRepoThread::sActiveHeaderRequests = 0; +S32 LLMeshRepoThread::sActiveLODRequests = 0; +U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; + +class LLMeshHeaderResponder : public LLCurl::Responder +{ +public: + LLVolumeParams mMeshParams; + + LLMeshHeaderResponder(const LLVolumeParams& mesh_params) + : mMeshParams(mesh_params) + { + } + + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + +}; + +class LLMeshLODResponder : public LLCurl::Responder +{ +public: + LLVolumeParams mMeshParams; + S32 mLOD; + U32 mRequestedBytes; + U32 mOffset; + + LLMeshLODResponder(const LLVolumeParams& mesh_params, S32 lod, U32 offset, U32 requested_bytes) + : mMeshParams(mesh_params), mLOD(lod), mOffset(offset), mRequestedBytes(requested_bytes) + { + } + + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + +}; + +class LLMeshSkinInfoResponder : public LLCurl::Responder +{ +public: + LLUUID mMeshID; + U32 mRequestedBytes; + U32 mOffset; + + LLMeshSkinInfoResponder(const LLUUID& id, U32 offset, U32 size) + : mMeshID(id), mRequestedBytes(size), mOffset(offset) + { + } + + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + +}; + +class LLMeshDecompositionResponder : public LLCurl::Responder +{ +public: + LLUUID mMeshID; + U32 mRequestedBytes; + U32 mOffset; + + LLMeshDecompositionResponder(const LLUUID& id, U32 offset, U32 size) + : mMeshID(id), mRequestedBytes(size), mOffset(offset) + { + } + + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + +}; + +class LLMeshPhysicsShapeResponder : public LLCurl::Responder +{ +public: + LLUUID mMeshID; + U32 mRequestedBytes; + U32 mOffset; + + LLMeshPhysicsShapeResponder(const LLUUID& id, U32 offset, U32 size) + : mMeshID(id), mRequestedBytes(size), mOffset(offset) + { + } + + virtual void completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer); + +}; + +#if MESH_IMPORT +void log_upload_error(S32 status, const LLSD& content, std::string stage, std::string model_name) +{ + // Add notification popup. + LLSD args; + std::string message = content["error"]["message"]; + std::string identifier = content["error"]["identifier"]; + args["MESSAGE"] = message; + args["IDENTIFIER"] = identifier; + args["LABEL"] = model_name; + gMeshRepo.uploadError(args); + + // Log details. + llwarns << "stage: " << stage << " http status: " << status << llendl; + if (content.has("error")) + { + const LLSD& err = content["error"]; + llwarns << "err: " << err << llendl; + llwarns << "mesh upload failed, stage '" << stage + << "' error '" << err["error"].asString() + << "', message '" << err["message"].asString() + << "', id '" << err["identifier"].asString() + << "'" << llendl; + if (err.has("errors")) + { + S32 error_num = 0; + const LLSD& err_list = err["errors"]; + for (LLSD::array_const_iterator it = err_list.beginArray(); + it != err_list.endArray(); + ++it) + { + const LLSD& err_entry = *it; + llwarns << "error[" << error_num << "]:" << llendl; + for (LLSD::map_const_iterator map_it = err_entry.beginMap(); + map_it != err_entry.endMap(); + ++map_it) + { + llwarns << "\t" << map_it->first << ": " + << map_it->second << llendl; + } + error_num++; + } + } + } + else + { + llwarns << "bad mesh, no error information available" << llendl; + } +} + +class LLWholeModelFeeResponder: public LLCurl::Responder +{ + LLMeshUploadThread* mThread; + LLSD mModelData; + LLHandle<LLWholeModelFeeObserver> mObserverHandle; +public: + LLWholeModelFeeResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelFeeObserver> observer_handle): + mThread(thread), + mModelData(model_data), + mObserverHandle(observer_handle) + { + } + virtual void completed(U32 status, + const std::string& reason, + const LLSD& content) + { + LLSD cc = content; + if (gSavedSettings.getS32("MeshUploadFakeErrors")&1) + { + cc = llsd_from_file("fake_upload_error.xml"); + } + + mThread->mPendingUploads--; + dump_llsd_to_file(cc,make_dump_name("whole_model_fee_response_",dump_num)); + + LLWholeModelFeeObserver* observer = mObserverHandle.get(); + + if (isGoodStatus(status) && + cc["state"].asString() == "upload") + { + mThread->mWholeModelUploadURL = cc["uploader"].asString(); + + if (observer) + { + cc["data"]["upload_price"] = cc["upload_price"]; + observer->onModelPhysicsFeeReceived(cc["data"], mThread->mWholeModelUploadURL); + } + } + else + { + llwarns << "fee request failed" << llendl; + log_upload_error(status,cc,"fee",mModelData["name"]); + mThread->mWholeModelUploadURL = ""; + + if (observer) + { + observer->setModelPhysicsFeeErrorStatus(status, reason); + } + } + } + +}; + +class LLWholeModelUploadResponder: public LLCurl::Responder +{ + LLMeshUploadThread* mThread; + LLSD mModelData; + LLHandle<LLWholeModelUploadObserver> mObserverHandle; + +public: + LLWholeModelUploadResponder(LLMeshUploadThread* thread, LLSD& model_data, LLHandle<LLWholeModelUploadObserver> observer_handle): + mThread(thread), + mModelData(model_data), + mObserverHandle(observer_handle) + { + } + virtual void completed(U32 status, + const std::string& reason, + const LLSD& content) + { + LLSD cc = content; + if (gSavedSettings.getS32("MeshUploadFakeErrors")&2) + { + cc = llsd_from_file("fake_upload_error.xml"); + } + + //assert_main_thread(); + mThread->mPendingUploads--; + dump_llsd_to_file(cc,make_dump_name("whole_model_upload_response_",dump_num)); + + LLWholeModelUploadObserver* observer = mObserverHandle.get(); + + // requested "mesh" asset type isn't actually the type + // of the resultant object, fix it up here. + if (isGoodStatus(status) && + cc["state"].asString() == "complete") + { + mModelData["asset_type"] = "object"; + gMeshRepo.updateInventory(LLMeshRepository::inventory_data(mModelData,cc)); + + if (observer) + { + doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadSuccess, observer)); + } + } + else + { + llwarns << "upload failed" << llendl; + std::string model_name = mModelData["name"].asString(); + log_upload_error(status,cc,"upload",model_name); + + if (observer) + { + doOnIdleOneTime(boost::bind(&LLWholeModelUploadObserver::onModelUploadFailure, observer)); + } + } + } +}; +#endif //MESH_IMPORT + +LLMeshRepoThread::LLMeshRepoThread() +: LLThread("mesh repo") +{ + mWaiting = false; + mMutex = new LLMutex; + mHeaderMutex = new LLMutex; + mSignal = new LLCondition; +} + +LLMeshRepoThread::~LLMeshRepoThread() +{ + delete mMutex; + mMutex = NULL; + delete mHeaderMutex; + mHeaderMutex = NULL; + delete mSignal; + mSignal = NULL; +} + +void LLMeshRepoThread::run() +{ + mCurlRequest = new LLCurlRequest(); +#if MESH_IMPORT + LLCDResult res = LLConvexDecomposition::initThread(); + if (res != LLCD_OK) + { + llwarns << "convex decomposition unable to be loaded" << llendl; + } +#endif //MESH_IMPORT + + while (!LLApp::isQuitting()) + { + mWaiting = true; + mSignal->wait(); + mWaiting = false; + + if (!LLApp::isQuitting()) + { + static U32 count = 0; + + static F32 last_hundred = gFrameTimeSeconds; + + if (gFrameTimeSeconds - last_hundred > 1.f) + { //a second has gone by, clear count + last_hundred = gFrameTimeSeconds; + count = 0; + } + + // NOTE: throttling intentionally favors LOD requests over header requests + + while (!mLODReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveLODRequests < (S32)sMaxConcurrentRequests) + { + { + mMutex->lock(); + LODRequest req = mLODReqQ.front(); + mLODReqQ.pop(); + mMutex->unlock(); + if (fetchMeshLOD(req.mMeshParams, req.mLOD)) + { + count++; + } + } + } + + while (!mHeaderReqQ.empty() && count < MAX_MESH_REQUESTS_PER_SECOND && sActiveHeaderRequests < (S32)sMaxConcurrentRequests) + { + { + mMutex->lock(); + HeaderRequest req = mHeaderReqQ.front(); + mHeaderReqQ.pop(); + mMutex->unlock(); + if (fetchMeshHeader(req.mMeshParams)) + { + count++; + } + } + } + + { //mSkinRequests is protected by mSignal + std::set<LLUUID> incomplete; + for (std::set<LLUUID>::iterator iter = mSkinRequests.begin(); iter != mSkinRequests.end(); ++iter) + { + LLUUID mesh_id = *iter; + if (!fetchMeshSkinInfo(mesh_id)) + { + incomplete.insert(mesh_id); + } + } + mSkinRequests = incomplete; + } + + { //mDecompositionRequests is protected by mSignal + std::set<LLUUID> incomplete; + for (std::set<LLUUID>::iterator iter = mDecompositionRequests.begin(); iter != mDecompositionRequests.end(); ++iter) + { + LLUUID mesh_id = *iter; + if (!fetchMeshDecomposition(mesh_id)) + { + incomplete.insert(mesh_id); + } + } + mDecompositionRequests = incomplete; + } + + { //mPhysicsShapeRequests is protected by mSignal + std::set<LLUUID> incomplete; + for (std::set<LLUUID>::iterator iter = mPhysicsShapeRequests.begin(); iter != mPhysicsShapeRequests.end(); ++iter) + { + LLUUID mesh_id = *iter; + if (!fetchMeshPhysicsShape(mesh_id)) + { + incomplete.insert(mesh_id); + } + } + mPhysicsShapeRequests = incomplete; + } + + mCurlRequest->process(); + } + } + + if (mSignal->isLocked()) + { //make sure to let go of the mutex associated with the given signal before shutting down + mSignal->unlock(); + } + +#if MESH_IMPORT + res = LLConvexDecomposition::quitThread(); + if (res != LLCD_OK) + { + llwarns << "convex decomposition unable to be quit" << llendl; + } +#endif //MESH_IMPORT + + delete mCurlRequest; + mCurlRequest = NULL; +} + +void LLMeshRepoThread::loadMeshSkinInfo(const LLUUID& mesh_id) +{ //protected by mSignal, no locking needed here + mSkinRequests.insert(mesh_id); +} + +void LLMeshRepoThread::loadMeshDecomposition(const LLUUID& mesh_id) +{ //protected by mSignal, no locking needed here + mDecompositionRequests.insert(mesh_id); +} + +void LLMeshRepoThread::loadMeshPhysicsShape(const LLUUID& mesh_id) +{ //protected by mSignal, no locking needed here + mPhysicsShapeRequests.insert(mesh_id); +} + + +void LLMeshRepoThread::loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ //protected by mSignal, no locking needed here + + mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); + if (iter != mMeshHeader.end()) + { //if we have the header, request LOD byte range + LODRequest req(mesh_params, lod); + { + LLMutexLock lock(mMutex); + mLODReqQ.push(req); + } + } + else + { + HeaderRequest req(mesh_params); + + pending_lod_map::iterator pending = mPendingLOD.find(mesh_params); + + if (pending != mPendingLOD.end()) + { //append this lod request to existing header request + pending->second.push_back(lod); + llassert(pending->second.size() <= LLModel::NUM_LODS) + } + else + { //if no header request is pending, fetch header + LLMutexLock lock(mMutex); + mHeaderReqQ.push(req); + mPendingLOD[mesh_params].push_back(lod); + } + } +} + +//static +std::string LLMeshRepoThread::constructUrl(LLUUID mesh_id) +{ + std::string http_url; + + if (gAgent.getRegion()) + { + http_url = gMeshRepo.mGetMeshCapability; + } + + if (!http_url.empty()) + { + http_url += "/?mesh_id="; + http_url += mesh_id.asString().c_str(); + } + else + { + llwarns << "Current region does not have GetMesh capability! Cannot load " << mesh_id << ".mesh" << llendl; + } + + return http_url; +} + +bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id) +{ //protected by mMutex + mHeaderMutex->lock(); + + if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } + + U32 header_size = mMeshHeaderSize[mesh_id]; + + 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(); + + mHeaderMutex->unlock(); + + if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) + { + //check VFS for mesh skin info + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesRead += size; + file.seek(offset); + U8* buffer = new U8[size]; + file.read(buffer, size); + + //make sure buffer isn't all 0's (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (skinInfoReceived(mesh_id, buffer, size)) + { + delete[] buffer; + return true; + } + } + + delete[] buffer; + } + + //reading from VFS failed for whatever reason, fetch from sim + std::vector<std::string> headers; + headers.push_back("Accept: application/octet-stream"); + + std::string http_url = constructUrl(mesh_id); + if (!http_url.empty()) + { + ++sActiveLODRequests; + LLMeshRepository::sHTTPRequestCount++; + mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, + new LLMeshSkinInfoResponder(mesh_id, offset, size)); + } + } + } + else + { + mHeaderMutex->unlock(); + } + + //early out was not hit, effectively fetched + return true; +} + +bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id) +{ //protected by mMutex + mHeaderMutex->lock(); + + if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } + + U32 header_size = mMeshHeaderSize[mesh_id]; + + 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(); + + mHeaderMutex->unlock(); + + if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) + { + //check VFS for mesh skin info + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesRead += size; + file.seek(offset); + U8* buffer = new U8[size]; + file.read(buffer, size); + + //make sure buffer isn't all 0's (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (decompositionReceived(mesh_id, buffer, size)) + { + delete[] buffer; + return true; + } + } + + delete[] buffer; + } + + //reading from VFS failed for whatever reason, fetch from sim + std::vector<std::string> headers; + headers.push_back("Accept: application/octet-stream"); + + std::string http_url = constructUrl(mesh_id); + if (!http_url.empty()) + { + ++sActiveLODRequests; + LLMeshRepository::sHTTPRequestCount++; + mCurlRequest->getByteRange(http_url, headers, offset, size, + new LLMeshDecompositionResponder(mesh_id, offset, size)); + } + } + } + else + { + mHeaderMutex->unlock(); + } + + //early out was not hit, effectively fetched + return true; +} + +bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id) +{ //protected by mMutex + mHeaderMutex->lock(); + + if (mMeshHeader.find(mesh_id) == mMeshHeader.end()) + { //we have no header info for this mesh, do nothing + mHeaderMutex->unlock(); + return false; + } + + U32 header_size = mMeshHeaderSize[mesh_id]; + + 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(); + + mHeaderMutex->unlock(); + + if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) + { + //check VFS for mesh physics shape info + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesRead += size; + file.seek(offset); + U8* buffer = new U8[size]; + file.read(buffer, size); + + //make sure buffer isn't all 0's (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (physicsShapeReceived(mesh_id, buffer, size)) + { + delete[] buffer; + return true; + } + } + + delete[] buffer; + } + + //reading from VFS failed for whatever reason, fetch from sim + std::vector<std::string> headers; + headers.push_back("Accept: application/octet-stream"); + + std::string http_url = constructUrl(mesh_id); + if (!http_url.empty()) + { + ++sActiveLODRequests; + LLMeshRepository::sHTTPRequestCount++; + mCurlRequest->getByteRange(http_url, headers, offset, size, + new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); + } + } + else + { //no physics shape whatsoever, report back NULL + physicsShapeReceived(mesh_id, NULL, 0); + } + } + else + { + mHeaderMutex->unlock(); + } + + //early out was not hit, effectively fetched + return true; +} + +bool LLMeshRepoThread::fetchMeshHeader(const LLVolumeParams& mesh_params) +{ + bool retval = false; + + { + //look for mesh in asset in vfs + LLVFile file(gVFS, mesh_params.getSculptID(), LLAssetType::AT_MESH); + + S32 size = file.getSize(); + + if (size > 0) + { //NOTE -- if the header size is ever more than 4KB, this will break + U8 buffer[4096]; + S32 bytes = llmin(size, 4096); + LLMeshRepository::sCacheBytesRead += bytes; + file.read(buffer, bytes); + if (headerReceived(mesh_params, buffer, bytes)) + { //did not do an HTTP request, return false + return false; + } + } + } + + //either cache entry doesn't exist or is corrupt, request header from simulator + + std::vector<std::string> headers; + headers.push_back("Accept: application/octet-stream"); + + std::string http_url = constructUrl(mesh_params.getSculptID()); + if (!http_url.empty()) + { + ++sActiveHeaderRequests; + retval = true; + //grab first 4KB if we're going to bother with a fetch. Cache will prevent future fetches if a full mesh fits + //within the first 4KB + LLMeshRepository::sHTTPRequestCount++; + mCurlRequest->getByteRange(http_url, headers, 0, 4096, new LLMeshHeaderResponder(mesh_params)); + } + + return retval; +} + +bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ //protected by mMutex + mHeaderMutex->lock(); + + bool retval = false; + + LLUUID mesh_id = mesh_params.getSculptID(); + + U32 header_size = mMeshHeaderSize[mesh_id]; + + 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(); + mHeaderMutex->unlock(); + + if (version <= MAX_MESH_VERSION && offset >= 0 && size > 0) + { + + //check VFS for mesh asset + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH); + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesRead += size; + file.seek(offset); + U8* buffer = new U8[size]; + file.read(buffer, size); + + //make sure buffer isn't all 0's (reserved block but not written) + bool zero = true; + for (S32 i = 0; i < llmin(size, 1024) && zero; ++i) + { + zero = buffer[i] > 0 ? false : true; + } + + if (!zero) + { //attempt to parse + if (lodReceived(mesh_params, lod, buffer, size)) + { + delete[] buffer; + return false; + } + } + + delete[] buffer; + } + + //reading from VFS failed for whatever reason, fetch from sim + std::vector<std::string> headers; + headers.push_back("Accept: application/octet-stream"); + + std::string http_url = constructUrl(mesh_id); + if (!http_url.empty()) + { + ++sActiveLODRequests; + retval = true; + LLMeshRepository::sHTTPRequestCount++; + mCurlRequest->getByteRange(constructUrl(mesh_id), headers, offset, size, + new LLMeshLODResponder(mesh_params, lod, offset, size)); + } + else + { + mUnavailableQ.push(LODRequest(mesh_params, lod)); + } + } + else + { + mUnavailableQ.push(LODRequest(mesh_params, lod)); + } + } + else + { + mHeaderMutex->unlock(); + } + + return retval; +} + +bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size) +{ + LLSD header; + + U32 header_size = 0; + if (data_size > 0) + { + std::string res_str((char*) data, data_size); + + std::string deprecated_header("<? LLSD/Binary ?>"); + + 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(); + + std::istringstream stream(res_str); + + if (!LLSDSerialize::fromBinary(header, stream, data_size)) + { + llwarns << "Mesh header parse error. Not a valid mesh asset!" << llendl; + return false; + } + + header_size += stream.tellg(); + } + else + { + llinfos + << "Marking header as non-existent, will not retry." << llendl; + header["404"] = 1; + } + + { + LLUUID mesh_id = mesh_params.getSculptID(); + + mHeaderMutex->lock(); + mMeshHeaderSize[mesh_id] = header_size; + mMeshHeader[mesh_id] = header; + mHeaderMutex->unlock(); + + //check for pending requests + pending_lod_map::iterator iter = mPendingLOD.find(mesh_params); + if (iter != mPendingLOD.end()) + { + LLMutexLock lock(mMutex); + for (U32 i = 0; i < iter->second.size(); ++i) + { + LODRequest req(mesh_params, iter->second[i]); + mLODReqQ.push(req); + } + } + mPendingLOD.erase(iter); + } + + return true; +} + +bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size) +{ + LLVolume* volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); + std::string mesh_string((char*) data, data_size); + std::istringstream stream(mesh_string); + + if (volume->unpackVolumeFaces(stream, data_size)) + { + LoadedMesh mesh(volume, mesh_params, lod); + if (volume->getNumFaces() > 0) + { + LLMutexLock lock(mMutex); + mLoadedQ.push(mesh); + return true; + } + } + + return false; +} + +bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size) +{ + LLSD skin; + + if (data_size > 0) + { + std::string res_str((char*) data, data_size); + + std::istringstream stream(res_str); + + if (!unzip_llsd(skin, stream, data_size)) + { + llwarns << "Mesh skin info parse error. Not a valid mesh asset!" << llendl; + return false; + } + } + + { + LLMeshSkinInfo info(skin); + info.mMeshID = mesh_id; + + //llinfos<<"info pelvis offset"<<info.mPelvisOffset<<llendl; + mSkinInfoQ.push(info); + } + + return true; +} + +bool LLMeshRepoThread::decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size) +{ + LLSD decomp; + + if (data_size > 0) + { + std::string res_str((char*) data, data_size); + + std::istringstream stream(res_str); + + if (!unzip_llsd(decomp, stream, data_size)) + { + llwarns << "Mesh decomposition parse error. Not a valid mesh asset!" << llendl; + return false; + } + } + + { + LLModel::Decomposition* d = new LLModel::Decomposition(decomp); + d->mMeshID = mesh_id; + mDecompositionQ.push(d); + } + + return true; +} + +bool LLMeshRepoThread::physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size) +{ + LLSD physics_shape; + + LLModel::Decomposition* d = new LLModel::Decomposition(); + d->mMeshID = mesh_id; + + if (data == NULL) + { //no data, no physics shape exists + d->mPhysicsShapeMesh.clear(); + } + else + { + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + volume_params.setSculptID(mesh_id, LL_SCULPT_TYPE_MESH); + LLPointer<LLVolume> volume = new LLVolume(volume_params,0); + std::string mesh_string((char*) data, data_size); + std::istringstream stream(mesh_string); + + if (volume->unpackVolumeFaces(stream, data_size)) + { + //load volume faces into decomposition buffer + S32 vertex_count = 0; + S32 index_count = 0; + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + vertex_count += face.mNumVertices; + index_count += face.mNumIndices; + } + + d->mPhysicsShapeMesh.clear(); + + std::vector<LLVector3>& pos = d->mPhysicsShapeMesh.mPositions; + std::vector<LLVector3>& norm = d->mPhysicsShapeMesh.mNormals; + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + + for (S32 i = 0; i < face.mNumIndices; ++i) + { + U16 idx = face.mIndices[i]; + + pos.push_back(LLVector3(face.mPositions[idx].getF32ptr())); + norm.push_back(LLVector3(face.mNormals[idx].getF32ptr())); + } + } + } + } + + mDecompositionQ.push(d); + return true; +} + +#if MESH_IMPORT +LLMeshUploadThread::LLMeshUploadThread(LLMeshUploadThread::instance_list& data, LLVector3& scale, bool upload_textures, + bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload, + LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer) +: LLThread("mesh upload"), + mDiscarded(FALSE), + mDoUpload(do_upload), + mWholeModelUploadURL(upload_url), + mFeeObserverHandle(fee_observer), + mUploadObserverHandle(upload_observer) +{ + mInstanceList = data; + mUploadTextures = upload_textures; + mUploadSkin = upload_skin; + mUploadJoints = upload_joints; + mMutex = new LLMutex(NULL); + mCurlRequest = NULL; + mPendingUploads = 0; + mFinished = false; + mOrigin = gAgent.getPositionAgent(); + mHost = gAgent.getRegionHost(); + + mWholeModelFeeCapability = gAgent.getRegion()->getCapability("NewFileAgentInventory"); + + mOrigin += gAgent.getAtAxis() * scale.magVec(); + + mMeshUploadTimeOut = gSavedSettings.getS32("MeshUploadTimeOut") ; +} + +LLMeshUploadThread::~LLMeshUploadThread() +{ + +} + +LLMeshUploadThread::DecompRequest::DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread) +{ + mStage = "single_hull"; + mModel = mdl; + mDecompID = &mdl->mDecompID; + mBaseModel = base_model; + mThread = thread; + + //copy out positions and indices + assignData(mdl) ; + + mThread->mFinalDecomp = this; + mThread->mPhysicsComplete = false; +} + +void LLMeshUploadThread::DecompRequest::completed() +{ + if (mThread->mFinalDecomp == this) + { + mThread->mPhysicsComplete = true; + } + + llassert(mHull.size() == 1); + + mThread->mHullMap[mBaseModel] = mHull[0]; +} + +//called in the main thread. +void LLMeshUploadThread::preStart() +{ + //build map of LLModel refs to instances for callbacks + for (instance_list::iterator iter = mInstanceList.begin(); iter != mInstanceList.end(); ++iter) + { + mInstance[iter->mModel].push_back(*iter); + } +} + +void LLMeshUploadThread::discard() +{ + LLMutexLock lock(mMutex) ; + mDiscarded = TRUE ; +} + +BOOL LLMeshUploadThread::isDiscarded() +{ + LLMutexLock lock(mMutex) ; + return mDiscarded ; +} + +void LLMeshUploadThread::run() +{ + if (mDoUpload) + { + doWholeModelUpload(); + } + else + { + requestWholeModelFee(); + } +} +#endif //MESH_IMPORT + +void dump_llsd_to_file(const LLSD& content, std::string filename) +{ + if (gSavedSettings.getBOOL("MeshUploadLogXML")) + { + std::ofstream of(filename.c_str()); + LLSDSerialize::toPrettyXML(content,of); + } +} + +LLSD llsd_from_file(std::string filename) +{ + std::ifstream ifs(filename.c_str()); + LLSD result; + LLSDSerialize::fromXML(result,ifs); + return result; +} + +#if MESH_IMPORT +void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) +{ + LLSD result; + + LLSD res; + result["folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_OBJECT); + result["texture_folder_id"] = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE); + result["asset_type"] = "mesh"; + result["inventory_type"] = "object"; + result["description"] = "(No Description)"; + result["next_owner_mask"] = LLSD::Integer(LLFloaterPerms::getNextOwnerPerms()); + result["group_mask"] = LLSD::Integer(LLFloaterPerms::getGroupPerms()); + result["everyone_mask"] = LLSD::Integer(LLFloaterPerms::getEveryonePerms()); + + res["mesh_list"] = LLSD::emptyArray(); + res["texture_list"] = LLSD::emptyArray(); + res["instance_list"] = LLSD::emptyArray(); + S32 mesh_num = 0; + S32 texture_num = 0; + + std::set<LLViewerTexture* > textures; + std::map<LLViewerTexture*,S32> texture_index; + + std::map<LLModel*,S32> mesh_index; + std::string model_name; + std::string model_metric; + + S32 instance_num = 0; + + for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) + { + LLMeshUploadData data; + data.mBaseModel = iter->first; + LLModelInstance& first_instance = *(iter->second.begin()); + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = first_instance.mLOD[i]; + } + + if (mesh_index.find(data.mBaseModel) == mesh_index.end()) + { + // Have not seen this model before - create a new mesh_list entry for it. + if (model_name.empty()) + { + model_name = data.mBaseModel->getName(); + } + + if (model_metric.empty()) + { + model_metric = data.mBaseModel->getMetric(); + } + + std::stringstream ostr; + + LLModel::Decomposition& decomp = + data.mModel[LLModel::LOD_PHYSICS].notNull() ? + data.mModel[LLModel::LOD_PHYSICS]->mPhysics : + data.mBaseModel->mPhysics; + + decomp.mBaseHull = mHullMap[data.mBaseModel]; + + LLSD mesh_header = LLModel::writeModel( + ostr, + data.mModel[LLModel::LOD_PHYSICS], + data.mModel[LLModel::LOD_HIGH], + data.mModel[LLModel::LOD_MEDIUM], + data.mModel[LLModel::LOD_LOW], + data.mModel[LLModel::LOD_IMPOSTOR], + decomp, + mUploadSkin, + mUploadJoints); + + data.mAssetData = ostr.str(); + std::string str = ostr.str(); + + res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end()); + mesh_index[data.mBaseModel] = mesh_num; + mesh_num++; + } + + // For all instances that use this model + for (instance_list::iterator instance_iter = iter->second.begin(); + instance_iter != iter->second.end(); + ++instance_iter) + { + + LLModelInstance& instance = *instance_iter; + + LLSD instance_entry; + + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = instance.mLOD[i]; + } + + LLVector3 pos, scale; + LLQuaternion rot; + LLMatrix4 transformation = instance.mTransform; + decomposeMeshMatrix(transformation,pos,rot,scale); + instance_entry["position"] = ll_sd_from_vector3(pos); + instance_entry["rotation"] = ll_sd_from_quaternion(rot); + instance_entry["scale"] = ll_sd_from_vector3(scale); + + instance_entry["material"] = LL_MCODE_WOOD; + instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + instance_entry["mesh"] = mesh_index[data.mBaseModel]; + + instance_entry["face_list"] = LLSD::emptyArray(); + + S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ; + for (S32 face_num = 0; face_num < end; face_num++) + { + LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; + LLSD face_entry = LLSD::emptyMap(); + LLViewerFetchedTexture *texture = material.mDiffuseMap.get(); + + if ((texture != NULL) && + (textures.find(texture) == textures.end())) + { + textures.insert(texture); + } + + std::stringstream texture_str; + if (texture != NULL && include_textures && mUploadTextures) + { + if(texture->hasSavedRawImage()) + { + LLPointer<LLImageJ2C> upload_file = + LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); + } + } + + if (texture != NULL && + mUploadTextures && + texture_index.find(texture) == texture_index.end()) + { + texture_index[texture] = texture_num; + std::string str = texture_str.str(); + res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end()); + texture_num++; + } + + // Subset of TextureEntry fields. + if (texture != NULL && mUploadTextures) + { + face_entry["image"] = texture_index[texture]; + face_entry["scales"] = 1.0; + face_entry["scalet"] = 1.0; + face_entry["offsets"] = 0.0; + face_entry["offsett"] = 0.0; + face_entry["imagerot"] = 0.0; + } + face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor); + face_entry["fullbright"] = material.mFullbright; + instance_entry["face_list"][face_num] = face_entry; + } + + res["instance_list"][instance_num] = instance_entry; + instance_num++; + } + } + + if (model_name.empty()) model_name = "mesh model"; + result["name"] = model_name; + if (model_metric.empty()) model_metric = "MUT_Unspecified"; + res["metric"] = model_metric; + result["asset_resources"] = res; + dump_llsd_to_file(result,make_dump_name("whole_model_",dump_num)); + + dest = result; +} + +void LLMeshUploadThread::generateHulls() +{ + bool has_valid_requests = false ; + + for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) + { + LLMeshUploadData data; + data.mBaseModel = iter->first; + + LLModelInstance& instance = *(iter->second.begin()); + + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = instance.mLOD[i]; + } + + //queue up models for hull generation + LLModel* physics = NULL; + + if (data.mModel[LLModel::LOD_PHYSICS].notNull()) + { + physics = data.mModel[LLModel::LOD_PHYSICS]; + } + else if (data.mModel[LLModel::LOD_LOW].notNull()) + { + physics = data.mModel[LLModel::LOD_LOW]; + } + else if (data.mModel[LLModel::LOD_MEDIUM].notNull()) + { + physics = data.mModel[LLModel::LOD_MEDIUM]; + } + else + { + physics = data.mModel[LLModel::LOD_HIGH]; + } + + llassert(physics != NULL); + + DecompRequest* request = new DecompRequest(physics, data.mBaseModel, this); + if(request->isValid()) + { + gMeshRepo.mDecompThread->submitRequest(request); + has_valid_requests = true ; + } + } + + if(has_valid_requests) + { + while (!mPhysicsComplete) + { + apr_sleep(100); + } + } +} + +void LLMeshUploadThread::doWholeModelUpload() +{ + mCurlRequest = new LLCurlRequest(); + + if (mWholeModelUploadURL.empty()) + { + llinfos << "unable to upload, fee request failed" << llendl; + } + else + { + generateHulls(); + + LLSD full_model_data; + wholeModelToLLSD(full_model_data, true); + LLSD body = full_model_data["asset_resources"]; + dump_llsd_to_file(body,make_dump_name("whole_model_body_",dump_num)); + LLCurlRequest::headers_t headers; + mCurlRequest->post(mWholeModelUploadURL, headers, body, + new LLWholeModelUploadResponder(this, full_model_data, mUploadObserverHandle), mMeshUploadTimeOut); + do + { + mCurlRequest->process(); + //sleep for 10ms to prevent eating a whole core + apr_sleep(10000); + } while (mCurlRequest->getQueued() > 0); + } + + delete mCurlRequest; + mCurlRequest = NULL; + + // Currently a no-op. + mFinished = true; +} + +void LLMeshUploadThread::requestWholeModelFee() +{ + dump_num++; + + mCurlRequest = new LLCurlRequest(); + + generateHulls(); + + LLSD model_data; + wholeModelToLLSD(model_data,false); + dump_llsd_to_file(model_data,make_dump_name("whole_model_fee_request_",dump_num)); + + mPendingUploads++; + LLCurlRequest::headers_t headers; + mCurlRequest->post(mWholeModelFeeCapability, headers, model_data, + new LLWholeModelFeeResponder(this,model_data, mFeeObserverHandle), mMeshUploadTimeOut); + + do + { + mCurlRequest->process(); + //sleep for 10ms to prevent eating a whole core + apr_sleep(10000); + } while (mCurlRequest->getQueued() > 0); + + delete mCurlRequest; + mCurlRequest = NULL; + + // Currently a no-op. + mFinished = true; +} +#endif //MESH_IMPORT + +//static LLFastTimer::DeclareTimer FTM_NOTIFY_MESH_LOADED("Notify Loaded"); +//static LLFastTimer::DeclareTimer FTM_NOTIFY_MESH_UNAVAILABLE("Notify Unavailable"); + +void LLMeshRepoThread::notifyLoadedMeshes() +{//called via gMeshRepo.notifyLoadedMeshes(). mMutex already locked + while (!mLoadedQ.empty()) + { + mMutex->lock(); + LoadedMesh mesh = mLoadedQ.front(); + mLoadedQ.pop(); + mMutex->unlock(); + + if (mesh.mVolume && mesh.mVolume->getNumVolumeFaces() > 0) + { + gMeshRepo.notifyMeshLoaded(mesh.mMeshParams, mesh.mVolume); + } + else + { + gMeshRepo.notifyMeshUnavailable(mesh.mMeshParams, + LLVolumeLODGroup::getVolumeDetailFromScale(mesh.mVolume->getDetail())); + } + } + + while (!mUnavailableQ.empty()) + { + mMutex->lock(); + LODRequest req = mUnavailableQ.front(); + mUnavailableQ.pop(); + mMutex->unlock(); + + gMeshRepo.notifyMeshUnavailable(req.mMeshParams, req.mLOD); + } + + while (!mSkinInfoQ.empty()) + { + gMeshRepo.notifySkinInfoReceived(mSkinInfoQ.front()); + mSkinInfoQ.pop(); + } + + while (!mDecompositionQ.empty()) + { + gMeshRepo.notifyDecompositionReceived(mDecompositionQ.front()); + mDecompositionQ.pop(); + } +} + +S32 LLMeshRepoThread::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ //only ever called from main thread + LLMutexLock lock(mHeaderMutex); + mesh_header_map::iterator iter = mMeshHeader.find(mesh_params.getSculptID()); + + if (iter != mMeshHeader.end()) + { + LLSD& header = iter->second; + + return LLMeshRepository::getActualMeshLOD(header, lod); + } + + return lod; +} + +//static +S32 LLMeshRepository::getActualMeshLOD(LLSD& header, S32 lod) +{ + lod = llclamp(lod, 0, 3); + + S32 version = header["version"]; + + if (header.has("404") || version > MAX_MESH_VERSION) + { + return -1; + } + + if (header[header_lod[lod]]["size"].asInteger() > 0) + { + return lod; + } + + //search down to find the next available lower lod + for (S32 i = lod-1; i >= 0; --i) + { + if (header[header_lod[i]]["size"].asInteger() > 0) + { + return i; + } + } + + //search up to find then ext available higher lod + for (S32 i = lod+1; i < 4; ++i) + { + if (header[header_lod[i]]["size"].asInteger() > 0) + { + return i; + } + } + + //header exists and no good lod found, treat as 404 + header["404"] = 1; + return -1; +} + +#if MESH_IMPORT +void LLMeshRepository::cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header) +{ + mThread->mMeshHeader[data.mUUID] = header; + + // we cache the mesh for default parameters + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + volume_params.setSculptID(data.mUUID, LL_SCULPT_TYPE_MESH); + + for (U32 i = 0; i < 4; i++) + { + if (data.mModel[i].notNull()) + { + LLPointer<LLVolume> volume = new LLVolume(volume_params, LLVolumeLODGroup::getVolumeScaleFromDetail(i)); + volume->copyVolumeFaces(data.mModel[i]); + volume->setMeshAssetLoaded(TRUE); + } + } + +} +#endif //MESH_IMPORT + +void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + + LLMeshRepoThread::sActiveLODRequests--; + S32 data_size = buffer->countAfter(channels.in(), NULL); + + if (status < 200 || status > 400) + { + llwarns << status << ": " << reason << llendl; + } + + if (data_size < (S32)mRequestedBytes) + { + if (status == 499 || status == 503) + { //timeout or service unavailable, try again + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshLOD(mMeshParams, mLOD); + } + else + { + llwarns << "Unhandled status " << status << llendl; + } + return; + } + + LLMeshRepository::sBytesReceived += mRequestedBytes; + + U8* data = NULL; + + if (data_size > 0) + { + data = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, data, data_size); + } + + if (gMeshRepo.mThread->lodReceived(mMeshParams, mLOD, data, data_size)) + { + //good fetch from sim, write to VFS for caching + LLVFile file(gVFS, mMeshParams.getSculptID(), LLAssetType::AT_MESH, LLVFile::WRITE); + + S32 offset = mOffset; + S32 size = mRequestedBytes; + + if (file.getSize() >= offset+size) + { + file.seek(offset); + file.write(data, size); + LLMeshRepository::sCacheBytesWritten += size; + } + } + + delete [] data; +} + +void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + S32 data_size = buffer->countAfter(channels.in(), NULL); + + if (status < 200 || status > 400) + { + llwarns << status << ": " << reason << llendl; + } + + if (data_size < (S32)mRequestedBytes) + { + if (status == 499 || status == 503) + { //timeout or service unavailable, try again + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshSkinInfo(mMeshID); + } + else + { + llwarns << "Unhandled status " << status << llendl; + } + return; + } + + LLMeshRepository::sBytesReceived += mRequestedBytes; + + U8* data = NULL; + + if (data_size > 0) + { + data = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, data, data_size); + } + + if (gMeshRepo.mThread->skinInfoReceived(mMeshID, data, data_size)) + { + //good fetch from sim, write to VFS for caching + LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); + + S32 offset = mOffset; + S32 size = mRequestedBytes; + + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesWritten += size; + file.seek(offset); + file.write(data, size); + } + } + + delete [] data; +} + +void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + S32 data_size = buffer->countAfter(channels.in(), NULL); + + if (status < 200 || status > 400) + { + llwarns << status << ": " << reason << llendl; + } + + if (data_size < (S32)mRequestedBytes) + { + if (status == 499 || status == 503) + { //timeout or service unavailable, try again + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshDecomposition(mMeshID); + } + else + { + llwarns << "Unhandled status " << status << llendl; + } + return; + } + + LLMeshRepository::sBytesReceived += mRequestedBytes; + + U8* data = NULL; + + if (data_size > 0) + { + data = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, data, data_size); + } + + if (gMeshRepo.mThread->decompositionReceived(mMeshID, data, data_size)) + { + //good fetch from sim, write to VFS for caching + LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); + + S32 offset = mOffset; + S32 size = mRequestedBytes; + + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesWritten += size; + file.seek(offset); + file.write(data, size); + } + } + + delete [] data; +} + +void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + S32 data_size = buffer->countAfter(channels.in(), NULL); + + if (status < 200 || status > 400) + { + llwarns << status << ": " << reason << llendl; + } + + if (data_size < (S32)mRequestedBytes) + { + if (status == 499 || status == 503) + { //timeout or service unavailable, try again + LLMeshRepository::sHTTPRetryCount++; + gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID); + } + else + { + llwarns << "Unhandled status " << status << llendl; + } + return; + } + + LLMeshRepository::sBytesReceived += mRequestedBytes; + + U8* data = NULL; + + if (data_size > 0) + { + data = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, data, data_size); + } + + if (gMeshRepo.mThread->physicsShapeReceived(mMeshID, data, data_size)) + { + //good fetch from sim, write to VFS for caching + LLVFile file(gVFS, mMeshID, LLAssetType::AT_MESH, LLVFile::WRITE); + + S32 offset = mOffset; + S32 size = mRequestedBytes; + + if (file.getSize() >= offset+size) + { + LLMeshRepository::sCacheBytesWritten += size; + file.seek(offset); + file.write(data, size); + } + } + + delete [] data; +} + +void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason, + const LLChannelDescriptors& channels, + const LLIOPipe::buffer_ptr_t& buffer) +{ + LLMeshRepoThread::sActiveHeaderRequests--; + if (status < 200 || status > 400) + { + //llwarns + // << "Header responder failed with status: " + // << status << ": " << reason << llendl; + + // 503 (service unavailable) or 499 (timeout) + // can be due to server load and can be retried + + // TODO*: Add maximum retry logic, exponential backoff + // and (somewhat more optional than the others) retries + // again after some set period of time + if (status == 503 || status == 499) + { //retry + LLMeshRepository::sHTTPRetryCount++; + LLMeshRepoThread::HeaderRequest req(mMeshParams); + LLMutexLock lock(gMeshRepo.mThread->mMutex); + gMeshRepo.mThread->mHeaderReqQ.push(req); + + return; + } + } + + S32 data_size = buffer->countAfter(channels.in(), NULL); + + U8* data = NULL; + + if (data_size > 0) + { + data = new U8[data_size]; + buffer->readAfter(channels.in(), NULL, data, data_size); + } + + LLMeshRepository::sBytesReceived += llmin(data_size, 4096); + + if (!gMeshRepo.mThread->headerReceived(mMeshParams, data, data_size)) + { + llwarns + << "Unable to parse mesh header: " + << status << ": " << reason << llendl; + } + else if (data && data_size > 0) + { + //header was successfully retrieved from sim, cache in vfs + LLUUID mesh_id = mMeshParams.getSculptID(); + LLSD header = gMeshRepo.mThread->mMeshHeader[mesh_id]; + + S32 version = header["version"].asInteger(); + + if (version <= MAX_MESH_VERSION) + { + std::stringstream str; + + S32 lod_bytes = 0; + + for (U32 i = 0; i < LLModel::LOD_PHYSICS; ++i) + { //figure out how many bytes we'll need to reserve in the file + std::string lod_name = header_lod[i]; + lod_bytes = llmax(lod_bytes, header[lod_name]["offset"].asInteger()+header[lod_name]["size"].asInteger()); + } + + //just in case skin info or decomposition is at the end of the file (which it shouldn't be) + lod_bytes = llmax(lod_bytes, header["skin"]["offset"].asInteger() + header["skin"]["size"].asInteger()); + lod_bytes = llmax(lod_bytes, header["physics_convex"]["offset"].asInteger() + header["physics_convex"]["size"].asInteger()); + + S32 header_bytes = (S32) gMeshRepo.mThread->mMeshHeaderSize[mesh_id]; + S32 bytes = lod_bytes + header_bytes; + + + //it's possible for the remote asset to have more data than is needed for the local cache + //only allocate as much space in the VFS as is needed for the local cache + data_size = llmin(data_size, bytes); + + LLVFile file(gVFS, mesh_id, LLAssetType::AT_MESH, LLVFile::WRITE); + if (file.getMaxSize() >= bytes || file.setMaxSize(bytes)) + { + LLMeshRepository::sCacheBytesWritten += data_size; + + file.write((const U8*) data, data_size); + + //zero out the rest of the file + U8 block[4096]; + memset(block, 0, 4096); + + while (bytes-file.tell() > 4096) + { + file.write(block, 4096); + } + + S32 remaining = bytes-file.tell(); + + if (remaining > 0) + { + file.write(block, remaining); + } + } + } + } + + delete [] data; +} + + +LLMeshRepository::LLMeshRepository() +: mMeshMutex(NULL), + mMeshThreadCount(0), + mThread(NULL) +{ + +} + +void LLMeshRepository::init() +{ + mMeshMutex = new LLMutex; + +#if MESH_IMPORT + LLConvexDecomposition::getInstance()->initSystem(); +#endif //MESH_IMPORT + + mDecompThread = new LLPhysicsDecomp(); + mDecompThread->start(); + + while (!mDecompThread->mInited) + { //wait for physics decomp thread to init + apr_sleep(100); + } + + + + mThread = new LLMeshRepoThread(); + mThread->start(); +} + +void LLMeshRepository::shutdown() +{ + llinfos << "Shutting down mesh repository." << llendl; + +#if MESH_IMPORT + for (U32 i = 0; i < mUploads.size(); ++i) + { + llinfos << "Discard the pending mesh uploads " << llendl; + mUploads[i]->discard() ; //discard the uploading requests. + } +#endif //MESH_IMPORT + + mThread->mSignal->signal(); + + while (!mThread->isStopped()) + { + apr_sleep(10); + } + delete mThread; + mThread = NULL; + +#if MESH_IMPORT + for (U32 i = 0; i < mUploads.size(); ++i) + { + llinfos << "Waiting for pending mesh upload " << i << "/" << mUploads.size() << llendl; + while (!mUploads[i]->isStopped()) + { + apr_sleep(10); + } + delete mUploads[i]; + } + + mUploads.clear(); +#endif //MESH_IMPORT + + delete mMeshMutex; + mMeshMutex = NULL; + + llinfos << "Shutting down decomposition system." << llendl; + + if (mDecompThread) + { + mDecompThread->shutdown(); + delete mDecompThread; + mDecompThread = NULL; + } + +#if MESH_IMPORT + LLConvexDecomposition::quitSystem(); +#endif //MESH_IMPORT +} + +//called in the main thread. +S32 LLMeshRepository::update() +{ + S32 size = 0; +#if MESH_IMPORT + if(mUploadWaitList.empty()) + { + return 0 ; + } + + size = mUploadWaitList.size() ; + for (S32 i = 0; i < size; ++i) + { + mUploads.push_back(mUploadWaitList[i]); + mUploadWaitList[i]->preStart() ; + mUploadWaitList[i]->start() ; + } + mUploadWaitList.clear() ; +#endif //MESH_IMPORT + return size ; +} + +S32 LLMeshRepository::loadMesh(LLVOVolume* vobj, const LLVolumeParams& mesh_params, S32 detail, S32 last_lod) +{ + if (detail < 0 || detail > 4) + { + return detail; + } + + //LLFastTimer t(LLFastTimer::FTM_LOAD_MESH); + + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + mesh_load_map::iterator iter = mLoadingMeshes[detail].find(mesh_params); + if (iter != mLoadingMeshes[detail].end()) + { //request pending for this mesh, append volume id to list + iter->second.insert(vobj->getID()); + } + else + { + //first request for this mesh + mLoadingMeshes[detail][mesh_params].insert(vobj->getID()); + mPendingRequests.push_back(LLMeshRepoThread::LODRequest(mesh_params, detail)); + } + } + + //do a quick search to see if we can't display something while we wait for this mesh to load + LLVolume* volume = vobj->getVolume(); + + if (volume) + { + LLVolumeParams params = volume->getParams(); + + LLVolumeLODGroup* group = LLPrimitive::getVolumeManager()->getGroup(params); + + if (group) + { + //first, see if last_lod is available (don't transition down to avoid funny popping a la SH-641) + if (last_lod >= 0) + { + LLVolume* lod = group->refLOD(last_lod); + if (lod && lod->isMeshAssetLoaded() && lod->getNumVolumeFaces() > 0) + { + group->derefLOD(lod); + return last_lod; + } + group->derefLOD(lod); + } + + //next, see what the next lowest LOD available might be + for (S32 i = detail-1; i >= 0; --i) + { + LLVolume* lod = group->refLOD(i); + if (lod && lod->isMeshAssetLoaded() && lod->getNumVolumeFaces() > 0) + { + group->derefLOD(lod); + return i; + } + + group->derefLOD(lod); + } + + //no lower LOD is a available, is a higher lod available? + for (S32 i = detail+1; i < 4; ++i) + { + LLVolume* lod = group->refLOD(i); + if (lod && lod->isMeshAssetLoaded() && lod->getNumVolumeFaces() > 0) + { + group->derefLOD(lod); + return i; + } + + group->derefLOD(lod); + } + } + } + + return detail; +} + +/*static LLFastTimer::DeclareTimer FTM_START_MESH_THREAD("Start Thread"); +static LLFastTimer::DeclareTimer FTM_LOAD_MESH_LOD("Load LOD"); +static LLFastTimer::DeclareTimer FTM_MESH_LOCK1("Lock 1"); +static LLFastTimer::DeclareTimer FTM_MESH_LOCK2("Lock 2");*/ + +void LLMeshRepository::notifyLoadedMeshes() +{ //called from main thread + LLMeshRepoThread::sMaxConcurrentRequests = gSavedSettings.getU32("MeshMaxConcurrentRequests"); + +#if MESH_IMPORT + //clean up completed upload threads + for (std::vector<LLMeshUploadThread*>::iterator iter = mUploads.begin(); iter != mUploads.end(); ) + { + LLMeshUploadThread* thread = *iter; + + if (thread->isStopped() && thread->finished()) + { + iter = mUploads.erase(iter); + delete thread; + } + else + { + ++iter; + } + } + + //update inventory + if (!mInventoryQ.empty()) + { + LLMutexLock lock(mMeshMutex); + while (!mInventoryQ.empty()) + { + inventory_data& data = mInventoryQ.front(); + + LLAssetType::EType asset_type = LLAssetType::lookup(data.mPostData["asset_type"].asString()); + LLInventoryType::EType inventory_type = LLInventoryType::lookup(data.mPostData["inventory_type"].asString()); + + // Handle addition of texture, if any. + if ( data.mResponse.has("new_texture_folder_id") ) + { + const LLUUID& folder_id = data.mResponse["new_texture_folder_id"].asUUID(); + + if ( folder_id.notNull() ) + { + LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TEXTURE); + + std::string name; + // Check if the server built a different name for the texture folder + if ( data.mResponse.has("new_texture_folder_name") ) + { + name = data.mResponse["new_texture_folder_name"].asString(); + } + else + { + name = data.mPostData["name"].asString(); + } + + // Add the category to the internal representation + LLPointer<LLViewerInventoryCategory> cat = + new LLViewerInventoryCategory(folder_id, parent_id, + LLFolderType::FT_NONE, name, gAgent.getID()); + cat->setVersion(LLViewerInventoryCategory::VERSION_UNKNOWN); + + LLInventoryModel::LLCategoryUpdate update(cat->getParentUUID(), 1); + gInventory.accountForUpdate(update); + gInventory.updateCategory(cat); + } + } + + on_new_single_inventory_upload_complete( + asset_type, + inventory_type, + data.mPostData["asset_type"].asString(), + data.mPostData["folder_id"].asUUID(), + data.mPostData["name"], + data.mPostData["description"], + data.mResponse, + data.mResponse["upload_price"]); + //} + + mInventoryQ.pop(); + } + } + +#endif //MESH_IMPORT + + //call completed callbacks on finished decompositions + mDecompThread->notifyCompleted(); + + if (!mThread->mWaiting) + { //curl thread is churning, wait for it to go idle + return; + } + + static std::string region_name("never name a region this"); + + if (gAgent.getRegion()) + { //update capability url + if (gAgent.getRegion()->getName() != region_name && gAgent.getRegion()->capabilitiesReceived()) + { + region_name = gAgent.getRegion()->getName(); + + mGetMeshCapability = gAgent.getRegion()->getCapability("GetMesh"); + } + } + + LLFastTimer t(LLFastTimer::FTM_MESH_UPDATE); + + { + LLFastTimer t(LLFastTimer::FTM_MESH_LOCK1); + mMeshMutex->lock(); + } + + { + LLFastTimer t(LLFastTimer::FTM_MESH_LOCK2); + mThread->mMutex->lock(); + } + + //popup queued error messages from background threads + while (!mUploadErrorQ.empty()) + { + LLNotificationsUtil::add("MeshUploadError", mUploadErrorQ.front()); + mUploadErrorQ.pop(); + } + + S32 push_count = LLMeshRepoThread::sMaxConcurrentRequests-(LLMeshRepoThread::sActiveHeaderRequests+LLMeshRepoThread::sActiveLODRequests); + + if (push_count > 0) + { + //calculate "score" for pending requests + + //create score map + std::map<LLUUID, F32> score_map; + + for (U32 i = 0; i < 4; ++i) + { + for (mesh_load_map::iterator iter = mLoadingMeshes[i].begin(); iter != mLoadingMeshes[i].end(); ++iter) + { + F32 max_score = 0.f; + for (std::set<LLUUID>::iterator obj_iter = iter->second.begin(); obj_iter != iter->second.end(); ++obj_iter) + { + LLViewerObject* object = gObjectList.findObject(*obj_iter); + + if (object) + { + LLDrawable* drawable = object->mDrawable; + if (drawable) + { + F32 cur_score = drawable->getRadius()/llmax(drawable->mDistanceWRTCamera, 1.f); + max_score = llmax(max_score, cur_score); + } + } + } + + score_map[iter->first.getSculptID()] = max_score; + } + } + + //set "score" for pending requests + for (std::vector<LLMeshRepoThread::LODRequest>::iterator iter = mPendingRequests.begin(); iter != mPendingRequests.end(); ++iter) + { + iter->mScore = score_map[iter->mMeshParams.getSculptID()]; + } + + //sort by "score" + std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater()); + + while (!mPendingRequests.empty() && push_count > 0) + { + LLFastTimer t(LLFastTimer::FTM_LOAD_MESH_LOD); + LLMeshRepoThread::LODRequest& request = mPendingRequests.front(); + mThread->loadMeshLOD(request.mMeshParams, request.mLOD); + mPendingRequests.erase(mPendingRequests.begin()); + push_count--; + } + } + + //send skin info requests + while (!mPendingSkinRequests.empty()) + { + mThread->loadMeshSkinInfo(mPendingSkinRequests.front()); + mPendingSkinRequests.pop(); + } + + //send decomposition requests + while (!mPendingDecompositionRequests.empty()) + { + mThread->loadMeshDecomposition(mPendingDecompositionRequests.front()); + mPendingDecompositionRequests.pop(); + } + + //send physics shapes decomposition requests + while (!mPendingPhysicsShapeRequests.empty()) + { + mThread->loadMeshPhysicsShape(mPendingPhysicsShapeRequests.front()); + mPendingPhysicsShapeRequests.pop(); + } + + mThread->notifyLoadedMeshes(); + + mThread->mMutex->unlock(); + mMeshMutex->unlock(); + + mThread->mSignal->signal(); +} + +void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) +{ + mSkinMap[info.mMeshID] = info; + + skin_load_map::iterator iter = mLoadingSkins.find(info.mMeshID); + if (iter != mLoadingSkins.end()) + { + for (std::set<LLUUID>::iterator obj_id = iter->second.begin(); obj_id != iter->second.end(); ++obj_id) + { + LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*obj_id); + if (vobj) + { + vobj->notifyMeshLoaded(); + } + } + } + + mLoadingSkins.erase(info.mMeshID); +} + +void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decomp) +{ + decomposition_map::iterator iter = mDecompositionMap.find(decomp->mMeshID); + if (iter == mDecompositionMap.end()) + { //just insert decomp into map + mDecompositionMap[decomp->mMeshID] = decomp; + } + else + { //merge decomp with existing entry + iter->second->merge(decomp); + delete decomp; + } + + mLoadingDecompositions.erase(decomp->mMeshID); +} + +void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume) +{ //called from main thread + 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); + + if (volume && obj_iter != mLoadingMeshes[detail].end()) + { + //make sure target volume is still valid + if (volume->getNumVolumeFaces() <= 0) + { + llwarns << "Mesh loading returned empty volume." << llendl; + } + + { //update system volume + LLVolume* sys_volume = LLPrimitive::getVolumeManager()->refVolume(mesh_params, detail); + if (sys_volume) + { + sys_volume->copyVolumeFaces(volume); + sys_volume->setMeshAssetLoaded(TRUE); + LLPrimitive::getVolumeManager()->unrefVolume(sys_volume); + } + else + { + llwarns << "Couldn't find system volume for given mesh." << llendl; + } + } + + //notify waiting LLVOVolume instances that their requested mesh is available + for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + { + LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); + if (vobj) + { + vobj->notifyMeshLoaded(); + } + } + + mLoadingMeshes[detail].erase(mesh_params); + } +} + +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); + + if (obj_iter != mLoadingMeshes[lod].end()) + { + for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter) + { + LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter); + if (vobj) + { + LLVolume* obj_volume = vobj->getVolume(); + + if (obj_volume && + obj_volume->getDetail() == detail && + obj_volume->getParams() == mesh_params) + { //should force volume to find most appropriate LOD + vobj->setVolume(obj_volume->getParams(), lod); + } + } + } + + mLoadingMeshes[lod].erase(mesh_params); + } +} + +S32 LLMeshRepository::getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod) +{ + return mThread->getActualMeshLOD(mesh_params, lod); +} + +const LLMeshSkinInfo* LLMeshRepository::getSkinInfo(const LLUUID& mesh_id, const LLVOVolume* requesting_obj) +{ + if (mesh_id.notNull()) + { + skin_map::iterator iter = mSkinMap.find(mesh_id); + if (iter != mSkinMap.end()) + { + return &(iter->second); + } + + //no skin info known about given mesh, try to fetch it + { + 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 + mPendingSkinRequests.push(mesh_id); + } + mLoadingSkins[mesh_id].insert(requesting_obj->getID()); + } + } + + return NULL; +} + +void LLMeshRepository::fetchPhysicsShape(const LLUUID& mesh_id) +{ + if (mesh_id.notNull()) + { + LLModel::Decomposition* decomp = NULL; + decomposition_map::iterator iter = mDecompositionMap.find(mesh_id); + if (iter != mDecompositionMap.end()) + { + decomp = iter->second; + } + + //decomposition block hasn't been fetched yet + if (!decomp || decomp->mPhysicsShapeMesh.empty()) + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + std::set<LLUUID>::iterator iter = mLoadingPhysicsShapes.find(mesh_id); + if (iter == mLoadingPhysicsShapes.end()) + { //no request pending for this skin info + mLoadingPhysicsShapes.insert(mesh_id); + mPendingPhysicsShapeRequests.push(mesh_id); + } + } + } + +} + +LLModel::Decomposition* LLMeshRepository::getDecomposition(const LLUUID& mesh_id) +{ + LLModel::Decomposition* ret = NULL; + + if (mesh_id.notNull()) + { + decomposition_map::iterator iter = mDecompositionMap.find(mesh_id); + if (iter != mDecompositionMap.end()) + { + ret = iter->second; + } + + //decomposition block hasn't been fetched yet + if (!ret || ret->mBaseHullMesh.empty()) + { + LLMutexLock lock(mMeshMutex); + //add volume to list of loading meshes + std::set<LLUUID>::iterator iter = mLoadingDecompositions.find(mesh_id); + if (iter == mLoadingDecompositions.end()) + { //no request pending for this skin info + mLoadingDecompositions.insert(mesh_id); + mPendingDecompositionRequests.push(mesh_id); + } + } + } + + return ret; +} + +void LLMeshRepository::buildHull(const LLVolumeParams& params, S32 detail) +{ + LLVolume* volume = LLPrimitive::getVolumeManager()->refVolume(params, detail); + + if (!volume->mHullPoints) + { + //all default params + //execute first stage + //set simplify mode to retain + //set retain percentage to zero + //run second stage + } + + LLPrimitive::getVolumeManager()->unrefVolume(volume); +} + +bool LLMeshRepository::hasPhysicsShape(const LLUUID& mesh_id) +{ + LLSD mesh = mThread->getMeshHeader(mesh_id); + if (mesh.has("physics_mesh") && mesh["physics_mesh"].has("size") && (mesh["physics_mesh"]["size"].asInteger() > 0)) + { + return true; + } + + LLModel::Decomposition* decomp = getDecomposition(mesh_id); + if (decomp && !decomp->mHull.empty()) + { + return true; + } + + return false; +} + +LLSD& LLMeshRepository::getMeshHeader(const LLUUID& mesh_id) +{ + return mThread->getMeshHeader(mesh_id); +} + +LLSD& LLMeshRepoThread::getMeshHeader(const LLUUID& mesh_id) +{ + static LLSD dummy_ret; + if (mesh_id.notNull()) + { + LLMutexLock lock(mHeaderMutex); + mesh_header_map::iterator iter = mMeshHeader.find(mesh_id); + if (iter != mMeshHeader.end()) + { + return iter->second; + } + } + + return dummy_ret; +} + +#if MESH_IMPORT +void LLMeshRepository::uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures, + bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload, + LLHandle<LLWholeModelFeeObserver> fee_observer, LLHandle<LLWholeModelUploadObserver> upload_observer) +{ + LLMeshUploadThread* thread = new LLMeshUploadThread(data, scale, upload_textures, upload_skin, upload_joints, upload_url, + do_upload, fee_observer, upload_observer); + mUploadWaitList.push_back(thread); +} +#endif //MESH_IMPORT + +S32 LLMeshRepository::getMeshSize(const LLUUID& mesh_id, S32 lod) +{ + if (mThread) + { + LLMeshRepoThread::mesh_header_map::iterator iter = mThread->mMeshHeader.find(mesh_id); + if (iter != mThread->mMeshHeader.end()) + { + LLSD& header = iter->second; + + if (header.has("404")) + { + return -1; + } + + S32 size = header[header_lod[lod]]["size"].asInteger(); + return size; + } + + } + + return -1; + +} + +#if MESH_IMPORT + +void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation, + LLVector3& result_pos, + LLQuaternion& result_rot, + LLVector3& result_scale) +{ + // check for reflection + BOOL reflected = (transformation.determinant() < 0); + + // compute position + LLVector3 position = LLVector3(0, 0, 0) * transformation; + + // compute scale + LLVector3 x_transformed = LLVector3(1, 0, 0) * transformation - position; + LLVector3 y_transformed = LLVector3(0, 1, 0) * transformation - position; + LLVector3 z_transformed = LLVector3(0, 0, 1) * transformation - position; + F32 x_length = x_transformed.normalize(); + F32 y_length = y_transformed.normalize(); + F32 z_length = z_transformed.normalize(); + LLVector3 scale = LLVector3(x_length, y_length, z_length); + + // adjust for "reflected" geometry + LLVector3 x_transformed_reflected = x_transformed; + if (reflected) + { + x_transformed_reflected *= -1.0; + } + + // compute rotation + LLMatrix3 rotation_matrix; + rotation_matrix.setRows(x_transformed_reflected, y_transformed, z_transformed); + LLQuaternion quat_rotation = rotation_matrix.quaternion(); + quat_rotation.normalize(); // the rotation_matrix might not have been orthoginal. make it so here. + LLVector3 euler_rotation; + quat_rotation.getEulerAngles(&euler_rotation.mV[VX], &euler_rotation.mV[VY], &euler_rotation.mV[VZ]); + + result_pos = position + mOrigin; + result_scale = scale; + result_rot = quat_rotation; +} + +#endif //MESH_IMPORT + +bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const +{ + if (mDiffuseMap != rhs.mDiffuseMap) + { + return mDiffuseMap < rhs.mDiffuseMap; + } + + if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) + { + return mDiffuseMapFilename < rhs.mDiffuseMapFilename; + } + + if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) + { + return mDiffuseMapLabel < rhs.mDiffuseMapLabel; + } + + if (mDiffuseColor != rhs.mDiffuseColor) + { + return mDiffuseColor < rhs.mDiffuseColor; + } + + if (mBinding != rhs.mBinding) + { + return mBinding < rhs.mBinding; + } + + return mFullbright < rhs.mFullbright; +} + + +void LLMeshRepository::updateInventory(inventory_data data) +{ + LLMutexLock lock(mMeshMutex); + dump_llsd_to_file(data.mPostData,make_dump_name("update_inventory_post_data_",dump_num)); + dump_llsd_to_file(data.mResponse,make_dump_name("update_inventory_response_",dump_num)); + mInventoryQ.push(data); +} + +void LLMeshRepository::uploadError(LLSD& args) +{ + LLMutexLock lock(mMeshMutex); + mUploadErrorQ.push(args); +} + +//static +F32 LLMeshRepository::getStreamingCost(LLSD& header, F32 radius, S32* bytes, S32* bytes_visible, S32 lod, F32 *unscaled_value) +{ + F32 max_distance = 512.f; + + F32 dlowest = llmin(radius/0.03f, max_distance); + F32 dlow = llmin(radius/0.06f, max_distance); + F32 dmid = llmin(radius/0.24f, max_distance); + + static const LLCachedControl<U32> mesh_meta_data_discount("MeshMetaDataDiscount"); + static const LLCachedControl<U32> mesh_minimum_byte_size("MeshMinimumByteSize"); + static const LLCachedControl<U32> mesh_bytes_per_triangle("MeshBytesPerTriangle"); + static const LLCachedControl<U32> mesh_triangle_budget("MeshTriangleBudget"); + + F32 METADATA_DISCOUNT = (F32) mesh_meta_data_discount.get(); //discount 128 bytes to cover the cost of LLSD tags and compression domain overhead + F32 MINIMUM_SIZE = (F32) mesh_minimum_byte_size.get(); //make sure nothing is "free" + + F32 bytes_per_triangle = (F32) mesh_bytes_per_triangle.get(); + + S32 bytes_lowest = header["lowest_lod"]["size"].asInteger(); + S32 bytes_low = header["low_lod"]["size"].asInteger(); + S32 bytes_mid = header["medium_lod"]["size"].asInteger(); + S32 bytes_high = header["high_lod"]["size"].asInteger(); + + if (bytes_high == 0) + { + return 0.f; + } + + if (bytes_mid == 0) + { + bytes_mid = bytes_high; + } + + if (bytes_low == 0) + { + bytes_low = bytes_mid; + } + + if (bytes_lowest == 0) + { + bytes_lowest = bytes_low; + } + + F32 triangles_lowest = llmax((F32) bytes_lowest-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; + F32 triangles_low = llmax((F32) bytes_low-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; + F32 triangles_mid = llmax((F32) bytes_mid-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; + F32 triangles_high = llmax((F32) bytes_high-METADATA_DISCOUNT, MINIMUM_SIZE)/bytes_per_triangle; + + if (bytes) + { + *bytes = 0; + *bytes += header["lowest_lod"]["size"].asInteger(); + *bytes += header["low_lod"]["size"].asInteger(); + *bytes += header["medium_lod"]["size"].asInteger(); + *bytes += header["high_lod"]["size"].asInteger(); + } + + if (bytes_visible) + { + lod = LLMeshRepository::getActualMeshLOD(header, lod); + if (lod >= 0 && lod <= 3) + { + *bytes_visible = header[header_lod[lod]]["size"].asInteger(); + } + } + + F32 max_area = 102932.f; //area of circle that encompasses region + F32 min_area = 1.f; + + F32 high_area = llmin(F_PI*dmid*dmid, max_area); + F32 mid_area = llmin(F_PI*dlow*dlow, max_area); + F32 low_area = llmin(F_PI*dlowest*dlowest, max_area); + F32 lowest_area = max_area; + + lowest_area -= low_area; + low_area -= mid_area; + mid_area -= high_area; + + high_area = llclamp(high_area, min_area, max_area); + mid_area = llclamp(mid_area, min_area, max_area); + low_area = llclamp(low_area, min_area, max_area); + lowest_area = llclamp(lowest_area, min_area, max_area); + + F32 total_area = high_area + mid_area + low_area + lowest_area; + high_area /= total_area; + mid_area /= total_area; + low_area /= total_area; + lowest_area /= total_area; + + F32 weighted_avg = triangles_high*high_area + + triangles_mid*mid_area + + triangles_low*low_area + + triangles_lowest*lowest_area; + + if (unscaled_value) + { + *unscaled_value = weighted_avg; + } + + return weighted_avg/mesh_triangle_budget*15000.f; +} + + +LLPhysicsDecomp::LLPhysicsDecomp() +: LLThread("Physics Decomp") +{ + mInited = false; + mQuitting = false; + mDone = false; + + mSignal = new LLCondition; + mMutex = new LLMutex; +} + +LLPhysicsDecomp::~LLPhysicsDecomp() +{ + shutdown(); + + delete mSignal; + mSignal = NULL; + delete mMutex; + mMutex = NULL; +} + +void LLPhysicsDecomp::shutdown() +{ + if (mSignal) + { + mQuitting = true; + mSignal->signal(); + + while (!isStopped()) + { + apr_sleep(10); + } + } +} + +void LLPhysicsDecomp::submitRequest(LLPhysicsDecomp::Request* request) +{ + LLMutexLock lock(mMutex); + mRequestQ.push(request); + mSignal->signal(); +} + +//static +S32 LLPhysicsDecomp::llcdCallback(const char* status, S32 p1, S32 p2) +{ + if (gMeshRepo.mDecompThread && gMeshRepo.mDecompThread->mCurRequest.notNull()) + { + return gMeshRepo.mDecompThread->mCurRequest->statusCallback(status, p1, p2); + } + + return 1; +} + +void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh, bool vertex_based) +{ + mesh.mVertexBase = mCurRequest->mPositions[0].mV; + mesh.mVertexStrideBytes = 12; + mesh.mNumVertices = mCurRequest->mPositions.size(); + + if(!vertex_based) + { + mesh.mIndexType = LLCDMeshData::INT_16; + mesh.mIndexBase = &(mCurRequest->mIndices[0]); + mesh.mIndexStrideBytes = 6; + + mesh.mNumTriangles = mCurRequest->mIndices.size()/3; + } + +#if MESH_IMPORT + if ((vertex_based || mesh.mNumTriangles > 0) && mesh.mNumVertices > 2) + { + LLCDResult ret = LLCD_OK; + if (LLConvexDecomposition::getInstance() != NULL) + { + ret = LLConvexDecomposition::getInstance()->setMeshData(&mesh, vertex_based); + } + + if (ret) + { + llerrs << "Convex Decomposition thread valid but could not set mesh data" << llendl; + } + } +#endif //MESH_IMPORT +} + +void LLPhysicsDecomp::doDecomposition() +{ +#if MESH_IMPORT + LLCDMeshData mesh; + S32 stage = mStageID[mCurRequest->mStage]; + + if (LLConvexDecomposition::getInstance() == NULL) + { + // stub library. do nothing. + return; + } + + //load data intoLLCD + if (stage == 0) + { + setMeshData(mesh, false); + } + + //build parameter map + std::map<std::string, const LLCDParam*> param_map; + + static const LLCDParam* params = NULL; + static S32 param_count = 0; + if (!params) + { + param_count = LLConvexDecomposition::getInstance()->getParameters(¶ms); + } + + for (S32 i = 0; i < param_count; ++i) + { + param_map[params[i].mName] = params+i; + } + + //set parameter values + for (decomp_params::iterator iter = mCurRequest->mParams.begin(); iter != mCurRequest->mParams.end(); ++iter) + { + const std::string& name = iter->first; + const LLSD& value = iter->second; + + const LLCDParam* param = param_map[name]; + + if (param == NULL) + { //couldn't find valid parameter + continue; + } + + U32 ret = LLCD_OK; + + if (param->mType == LLCDParam::LLCD_FLOAT) + { + ret = LLConvexDecomposition::getInstance()->setParam(param->mName, (F32) value.asReal()); + } + else if (param->mType == LLCDParam::LLCD_INTEGER || + param->mType == LLCDParam::LLCD_ENUM) + { + ret = LLConvexDecomposition::getInstance()->setParam(param->mName, value.asInteger()); + } + else if (param->mType == LLCDParam::LLCD_BOOLEAN) + { + ret = LLConvexDecomposition::getInstance()->setParam(param->mName, value.asBoolean()); + } + } + + mCurRequest->setStatusMessage("Executing."); + + LLCDResult ret = LLCD_OK; + + if (LLConvexDecomposition::getInstance() != NULL) + { + ret = LLConvexDecomposition::getInstance()->executeStage(stage); + } + + if (ret) + { + llwarns << "Convex Decomposition thread valid but could not execute stage " << stage << llendl; + LLMutexLock lock(mMutex); + + mCurRequest->mHull.clear(); + mCurRequest->mHullMesh.clear(); + + mCurRequest->setStatusMessage("FAIL"); + + completeCurrent(); + } + else + { + mCurRequest->setStatusMessage("Reading results"); + + S32 num_hulls =0; + if (LLConvexDecomposition::getInstance() != NULL) + { + num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(stage); + } + + mMutex->lock(); + mCurRequest->mHull.clear(); + mCurRequest->mHull.resize(num_hulls); + + mCurRequest->mHullMesh.clear(); + mCurRequest->mHullMesh.resize(num_hulls); + mMutex->unlock(); + + for (S32 i = 0; i < num_hulls; ++i) + { + std::vector<LLVector3> p; + LLCDHull hull; + // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code + LLConvexDecomposition::getInstance()->getHullFromStage(stage, i, &hull); + + const F32* v = hull.mVertexBase; + + for (S32 j = 0; j < hull.mNumVertices; ++j) + { + LLVector3 vert(v[0], v[1], v[2]); + p.push_back(vert); + v = (F32*) (((U8*) v) + hull.mVertexStrideBytes); + } + + LLCDMeshData mesh; + // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code + LLConvexDecomposition::getInstance()->getMeshFromStage(stage, i, &mesh); + + get_vertex_buffer_from_mesh(mesh, mCurRequest->mHullMesh[i]); + + mMutex->lock(); + mCurRequest->mHull[i] = p; + mMutex->unlock(); + } + + { + LLMutexLock lock(mMutex); + + mCurRequest->setStatusMessage("FAIL"); + completeCurrent(); + } + } +#endif //MESH_IMPORT +} + +void LLPhysicsDecomp::completeCurrent() +{ + LLMutexLock lock(mMutex); + mCompletedQ.push(mCurRequest); + mCurRequest = NULL; +} + +void LLPhysicsDecomp::notifyCompleted() +{ + if (!mCompletedQ.empty()) + { + LLMutexLock lock(mMutex); + while (!mCompletedQ.empty()) + { + Request* req = mCompletedQ.front(); + req->completed(); + mCompletedQ.pop(); + } + } +} + + +void make_box(LLPhysicsDecomp::Request * request) +{ + LLVector3 min,max; + min = request->mPositions[0]; + max = min; + + for (U32 i = 0; i < request->mPositions.size(); ++i) + { + update_min_max(min, max, request->mPositions[i]); + } + + request->mHull.clear(); + + LLModel::hull box; + box.push_back(LLVector3(min[0],min[1],min[2])); + box.push_back(LLVector3(max[0],min[1],min[2])); + box.push_back(LLVector3(min[0],max[1],min[2])); + box.push_back(LLVector3(max[0],max[1],min[2])); + box.push_back(LLVector3(min[0],min[1],max[2])); + box.push_back(LLVector3(max[0],min[1],max[2])); + box.push_back(LLVector3(min[0],max[1],max[2])); + box.push_back(LLVector3(max[0],max[1],max[2])); + + request->mHull.push_back(box); +} + + +void LLPhysicsDecomp::doDecompositionSingleHull() +{ +#if !MESH_IMPORT + return; +#endif //!MESH_IMPORT +#if MESH_IMPORT + LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance(); + + if (decomp == NULL) + { + //stub. do nothing. + return; + } + + LLCDMeshData mesh; + +#if 1 + setMeshData(mesh, true); + + LLCDResult ret = decomp->buildSingleHull() ; + if(ret) + { + llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl; + make_box(mCurRequest); + } + else + { + mMutex->lock(); + mCurRequest->mHull.clear(); + mCurRequest->mHull.resize(1); + mCurRequest->mHullMesh.clear(); + mMutex->unlock(); + + std::vector<LLVector3> p; + LLCDHull hull; + + // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code + decomp->getSingleHull(&hull); + + const F32* v = hull.mVertexBase; + + for (S32 j = 0; j < hull.mNumVertices; ++j) + { + LLVector3 vert(v[0], v[1], v[2]); + p.push_back(vert); + v = (F32*) (((U8*) v) + hull.mVertexStrideBytes); + } + + mMutex->lock(); + mCurRequest->mHull[0] = p; + mMutex->unlock(); + } +#else + setMeshData(mesh, false); + + //set all parameters to default + std::map<std::string, const LLCDParam*> param_map; + + static const LLCDParam* params = NULL; + static S32 param_count = 0; + + if (!params) + { + param_count = decomp->getParameters(¶ms); + } + + for (S32 i = 0; i < param_count; ++i) + { + decomp->setParam(params[i].mName, params[i].mDefault.mIntOrEnumValue); + } + + const S32 STAGE_DECOMPOSE = mStageID["Decompose"]; + const S32 STAGE_SIMPLIFY = mStageID["Simplify"]; + const S32 DECOMP_PREVIEW = 0; + const S32 SIMPLIFY_RETAIN = 0; + + decomp->setParam("Decompose Quality", DECOMP_PREVIEW); + decomp->setParam("Simplify Method", SIMPLIFY_RETAIN); + decomp->setParam("Retain%", 0.f); + + LLCDResult ret = LLCD_OK; + ret = decomp->executeStage(STAGE_DECOMPOSE); + + if (ret) + { + llwarns << "Could not execute decomposition stage when attempting to create single hull." << llendl; + make_box(mCurRequest); + } + else + { + ret = decomp->executeStage(STAGE_SIMPLIFY); + + if (ret) + { + llwarns << "Could not execute simiplification stage when attempting to create single hull." << llendl; + make_box(mCurRequest); + } + else + { + S32 num_hulls =0; + if (LLConvexDecomposition::getInstance() != NULL) + { + num_hulls = LLConvexDecomposition::getInstance()->getNumHullsFromStage(STAGE_SIMPLIFY); + } + + mMutex->lock(); + mCurRequest->mHull.clear(); + mCurRequest->mHull.resize(num_hulls); + mCurRequest->mHullMesh.clear(); + mMutex->unlock(); + + for (S32 i = 0; i < num_hulls; ++i) + { + std::vector<LLVector3> p; + LLCDHull hull; + // if LLConvexDecomposition is a stub, num_hulls should have been set to 0 above, and we should not reach this code + LLConvexDecomposition::getInstance()->getHullFromStage(STAGE_SIMPLIFY, i, &hull); + + const F32* v = hull.mVertexBase; + + for (S32 j = 0; j < hull.mNumVertices; ++j) + { + LLVector3 vert(v[0], v[1], v[2]); + p.push_back(vert); + v = (F32*) (((U8*) v) + hull.mVertexStrideBytes); + } + + mMutex->lock(); + mCurRequest->mHull[i] = p; + mMutex->unlock(); + } + } + } +#endif + + { + completeCurrent(); + + } +#endif //MESH_IMPORT +} + + +void LLPhysicsDecomp::run() +{ +#if !MESH_IMPORT + mInited = true; +#endif //!MESH_IMPORT +#if MESH_IMPORT + LLConvexDecomposition* decomp = LLConvexDecomposition::getInstance(); + if (decomp == NULL) + { + // stub library. Set init to true so the main thread + // doesn't wait for this to finish. + mInited = true; + return; + } + + decomp->initThread(); + mInited = true; + + static const LLCDStageData* stages = NULL; + static S32 num_stages = 0; + + if (!stages) + { + num_stages = decomp->getStages(&stages); + } + + for (S32 i = 0; i < num_stages; i++) + { + mStageID[stages[i].mName] = i; + } + + while (!mQuitting) + { + mSignal->wait(); + while (!mQuitting && !mRequestQ.empty()) + { + { + LLMutexLock lock(mMutex); + mCurRequest = mRequestQ.front(); + mRequestQ.pop(); + } + + S32& id = *(mCurRequest->mDecompID); + if (id == -1) + { + decomp->genDecomposition(id); + } + decomp->bindDecomposition(id); + + if (mCurRequest->mStage == "single_hull") + { + doDecompositionSingleHull(); + } + else + { + doDecomposition(); + } + } + } + + decomp->quitThread(); + + if (mSignal->isLocked()) + { //let go of mSignal's associated mutex + mSignal->unlock(); + } + + mDone = true; +#endif //MESH_IMPORT +} + + +void LLPhysicsDecomp::Request::assignData(LLModel* mdl) +{ + if (!mdl) + { + return ; + } + + U16 index_offset = 0; + U16 tri[3] ; + + mPositions.clear(); + mIndices.clear(); + mBBox[1] = LLVector3(F32_MIN, F32_MIN, F32_MIN) ; + mBBox[0] = LLVector3(F32_MAX, F32_MAX, F32_MAX) ; + + //queue up vertex positions and indices + for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = mdl->getVolumeFace(i); + if (mPositions.size() + face.mNumVertices > 65535) + { + continue; + } + + for (U32 j = 0; j < (U32)face.mNumVertices; ++j) + { + mPositions.push_back(LLVector3(face.mPositions[j].getF32ptr())); + for(U32 k = 0 ; k < 3 ; k++) + { + mBBox[0].mV[k] = llmin(mBBox[0].mV[k], mPositions[j].mV[k]) ; + mBBox[1].mV[k] = llmax(mBBox[1].mV[k], mPositions[j].mV[k]) ; + } + } + + updateTriangleAreaThreshold() ; + + for (U32 j = 0; j+2 < (U32)face.mNumIndices; j += 3) + { + tri[0] = face.mIndices[j] + index_offset ; + tri[1] = face.mIndices[j + 1] + index_offset ; + tri[2] = face.mIndices[j + 2] + index_offset ; + + if(isValidTriangle(tri[0], tri[1], tri[2])) + { + mIndices.push_back(tri[0]); + mIndices.push_back(tri[1]); + mIndices.push_back(tri[2]); + } + } + + index_offset += face.mNumVertices; + } + + return ; +} + +void LLPhysicsDecomp::Request::updateTriangleAreaThreshold() +{ + F32 range = mBBox[1].mV[0] - mBBox[0].mV[0] ; + range = llmin(range, mBBox[1].mV[1] - mBBox[0].mV[1]) ; + range = llmin(range, mBBox[1].mV[2] - mBBox[0].mV[2]) ; + + mTriangleAreaThreshold = llmin(0.0002f, range * 0.000002f) ; +} + +//check if the triangle area is large enough to qualify for a valid triangle +bool LLPhysicsDecomp::Request::isValidTriangle(U16 idx1, U16 idx2, U16 idx3) +{ + LLVector3 a = mPositions[idx2] - mPositions[idx1] ; + LLVector3 b = mPositions[idx3] - mPositions[idx1] ; + F32 c = a * b ; + + return ((a*a) * (b*b) - c * c) > mTriangleAreaThreshold ; +} + +void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg) +{ + mStatusMessage = msg; +} + +LLModelInstance::LLModelInstance(LLSD& data) +{ + mLocalMeshID = data["mesh_id"].asInteger(); + mLabel = data["label"].asString(); + mTransform.setValue(data["transform"]); + + for (U32 i = 0; i < (U32)data["material"].size(); ++i) + { + LLImportMaterial mat(data["material"][i]); + mMaterial[mat.mBinding] = mat; + } +} + + +LLSD LLModelInstance::asLLSD() +{ + LLSD ret; + + ret["mesh_id"] = mModel->mLocalID; + ret["label"] = mLabel; + ret["transform"] = mTransform.getValue(); + + U32 i = 0; + for (std::map<std::string, LLImportMaterial>::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) + { + ret["material"][i++] = iter->second.asLLSD(); + } + + return ret; +} + +LLImportMaterial::LLImportMaterial(LLSD& data) +{ + mDiffuseMapFilename = data["diffuse"]["filename"].asString(); + mDiffuseMapLabel = data["diffuse"]["label"].asString(); + mDiffuseColor.setValue(data["diffuse"]["color"]); + mFullbright = data["fullbright"].asBoolean(); + mBinding = data["binding"].asString(); +} + + +LLSD LLImportMaterial::asLLSD() +{ + LLSD ret; + + ret["diffuse"]["filename"] = mDiffuseMapFilename; + ret["diffuse"]["label"] = mDiffuseMapLabel; + ret["diffuse"]["color"] = mDiffuseColor.getValue(); + ret["fullbright"] = mFullbright; + ret["binding"] = mBinding; + + return ret; +} + +void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp) +{ + decomp.mMesh.resize(decomp.mHull.size()); + + for (U32 i = 0; i < decomp.mHull.size(); ++i) + { + LLCDHull hull; + hull.mNumVertices = decomp.mHull[i].size(); + hull.mVertexBase = decomp.mHull[i][0].mV; + hull.mVertexStrideBytes = 12; + + LLCDMeshData mesh; +#if MESH_IMPORT + LLCDResult res = LLCD_OK; + if (LLConvexDecomposition::getInstance() != NULL) + { + res = LLConvexDecomposition::getInstance()->getMeshFromHull(&hull, &mesh); + } + if (res == LLCD_OK) +#endif //MESH_IMPORT + { + get_vertex_buffer_from_mesh(mesh, decomp.mMesh[i]); + } + } + + if (!decomp.mBaseHull.empty() && decomp.mBaseHullMesh.empty()) + { //get mesh for base hull + LLCDHull hull; + hull.mNumVertices = decomp.mBaseHull.size(); + hull.mVertexBase = decomp.mBaseHull[0].mV; + hull.mVertexStrideBytes = 12; + + LLCDMeshData mesh; +#if MESH_IMPORT + LLCDResult res = LLCD_OK; + if (LLConvexDecomposition::getInstance() != NULL) + { + res = LLConvexDecomposition::getInstance()->getMeshFromHull(&hull, &mesh); + } + if (res == LLCD_OK) +#endif //MESH_IMPORT + { + get_vertex_buffer_from_mesh(mesh, decomp.mBaseHullMesh); + } + } +} + + +bool LLMeshRepository::meshUploadEnabled() +{ + LLViewerRegion *region = gAgent.getRegion(); + if(gSavedSettings.getBOOL("MeshEnabled") && + region) + { + return region->meshUploadEnabled(); + } + return false; +} + +bool LLMeshRepository::meshRezEnabled() +{ + LLViewerRegion *region = gAgent.getRegion(); + if(gSavedSettings.getBOOL("MeshEnabled") && + region) + { + return region->meshRezEnabled(); + } + return false; +} +#endif //MESH_ENABLED + diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h new file mode 100644 index 000000000..e23a5981e --- /dev/null +++ b/indra/newview/llmeshrepository.h @@ -0,0 +1,590 @@ +/** + * @file llmeshrepository.h + * @brief Client-side repository of mesh assets. + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_MESH_REPOSITORY_H +#define LL_MESH_REPOSITORY_H + +#include "llassettype.h" +#include "llmodel.h" +#include "lluuid.h" +#include "llviewertexture.h" +#include "llvolume.h" + +#if MESH_IMPORT +#define LLCONVEXDECOMPINTER_STATIC 1 + +#include "llconvexdecomposition.h" +#endif //MESH_IMPORT + +#if !MESH_IMPORT +//Placeholder structs from LLConvexDecomposition.h: +struct LLCDMeshData +{ + enum IndexType + { + INT_16, + INT_32 + }; + + const float* mVertexBase; + int mVertexStrideBytes; + int mNumVertices; + const void* mIndexBase; + IndexType mIndexType; + int mIndexStrideBytes; + int mNumTriangles; +}; +struct LLCDHull +{ + const float* mVertexBase; + int mVertexStrideBytes; + int mNumVertices; +}; +#endif //!MESH_IMPORT + +class LLVOVolume; +class LLMeshResponder; +class LLCurlRequest; +class LLMutex; +class LLCondition; +class LLVFS; +class LLMeshRepository; + +class LLMeshUploadData +{ +public: + LLPointer<LLModel> mBaseModel; + LLPointer<LLModel> mModel[5]; + LLUUID mUUID; + U32 mRetries; + std::string mRSVP; + std::string mAssetData; + LLSD mPostData; + + LLMeshUploadData() + { + mRetries = 0; + } +}; + +class LLTextureUploadData +{ +public: + LLViewerFetchedTexture* mTexture; + LLUUID mUUID; + std::string mRSVP; + std::string mLabel; + U32 mRetries; + std::string mAssetData; + LLSD mPostData; + + LLTextureUploadData() + { + mRetries = 0; + } + + LLTextureUploadData(LLViewerFetchedTexture* texture, std::string& label) + : mTexture(texture), mLabel(label) + { + mRetries = 0; + } +}; + +class LLImportMaterial +{ +public: + LLPointer<LLViewerFetchedTexture> mDiffuseMap; + std::string mDiffuseMapFilename; + std::string mDiffuseMapLabel; + std::string mBinding; + LLColor4 mDiffuseColor; + bool mFullbright; + + bool operator<(const LLImportMaterial ¶ms) const; + + LLImportMaterial() + : mFullbright(false) + { + mDiffuseColor.set(1,1,1,1); + } + + LLImportMaterial(LLSD& data); + + LLSD asLLSD(); +}; + +class LLModelInstance +{ +public: + LLPointer<LLModel> mModel; + LLPointer<LLModel> mLOD[5]; + + std::string mLabel; + + LLUUID mMeshID; + S32 mLocalMeshID; + + LLMatrix4 mTransform; + std::map<std::string, LLImportMaterial> mMaterial; + + LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map<std::string, LLImportMaterial>& materials) + : mModel(model), mLabel(label), mTransform(transform), mMaterial(materials) + { + mLocalMeshID = -1; + } + + LLModelInstance(LLSD& data); + + LLSD asLLSD(); +}; + +class LLPhysicsDecomp : public LLThread +{ +public: + + typedef std::map<std::string, LLSD> decomp_params; + + class Request : public LLRefCount + { + public: + //input params + S32* mDecompID; + std::string mStage; + std::vector<LLVector3> mPositions; + std::vector<U16> mIndices; + decomp_params mParams; + + //output state + std::string mStatusMessage; + std::vector<LLModel::PhysicsMesh> mHullMesh; + LLModel::convex_hull_decomposition mHull; + + //status message callback, called from decomposition thread + virtual S32 statusCallback(const char* status, S32 p1, S32 p2) = 0; + + //completed callback, called from the main thread + virtual void completed() = 0; + + virtual void setStatusMessage(const std::string& msg); + + bool isValid() const {return mPositions.size() > 2 && mIndices.size() > 2 ;} + + protected: + //internal use + LLVector3 mBBox[2] ; + F32 mTriangleAreaThreshold ; + + void assignData(LLModel* mdl) ; + void updateTriangleAreaThreshold() ; + bool isValidTriangle(U16 idx1, U16 idx2, U16 idx3) ; + }; + + LLCondition* mSignal; + LLMutex* mMutex; + + bool mInited; + bool mQuitting; + bool mDone; + + LLPhysicsDecomp(); + ~LLPhysicsDecomp(); + + void shutdown(); + + void submitRequest(Request* request); + static S32 llcdCallback(const char*, S32, S32); + void cancel(); + + void setMeshData(LLCDMeshData& mesh, bool vertex_based); + void doDecomposition(); + void doDecompositionSingleHull(); + + virtual void run(); + + void completeCurrent(); + void notifyCompleted(); + + std::map<std::string, S32> mStageID; + + typedef std::queue<LLPointer<Request> > request_queue; + request_queue mRequestQ; + + LLPointer<Request> mCurRequest; + + std::queue<LLPointer<Request> > mCompletedQ; + +}; + +class LLMeshRepoThread : public LLThread +{ +public: + + static S32 sActiveHeaderRequests; + static S32 sActiveLODRequests; + static U32 sMaxConcurrentRequests; + + LLCurlRequest* mCurlRequest; + LLMutex* mMutex; + LLMutex* mHeaderMutex; + LLCondition* mSignal; + + bool mWaiting; + + //map of known mesh headers + typedef std::map<LLUUID, LLSD> mesh_header_map; + mesh_header_map mMeshHeader; + + std::map<LLUUID, U32> mMeshHeaderSize; + + class HeaderRequest + { + public: + const LLVolumeParams mMeshParams; + + HeaderRequest(const LLVolumeParams& mesh_params) + : mMeshParams(mesh_params) + { + } + + bool operator<(const HeaderRequest& rhs) const + { + return mMeshParams < rhs.mMeshParams; + } + }; + + class LODRequest + { + public: + LLVolumeParams mMeshParams; + S32 mLOD; + F32 mScore; + + LODRequest(const LLVolumeParams& mesh_params, S32 lod) + : mMeshParams(mesh_params), mLOD(lod), mScore(0.f) + { + } + }; + + struct CompareScoreGreater + { + bool operator()(const LODRequest& lhs, const LODRequest& rhs) + { + return lhs.mScore > rhs.mScore; // greatest = first + } + }; + + + class LoadedMesh + { + public: + LLPointer<LLVolume> mVolume; + LLVolumeParams mMeshParams; + S32 mLOD; + + LoadedMesh(LLVolume* volume, const LLVolumeParams& mesh_params, S32 lod) + : mVolume(volume), mMeshParams(mesh_params), mLOD(lod) + { + } + + }; + + //set of requested skin info + std::set<LLUUID> mSkinRequests; + + //queue of completed skin info requests + std::queue<LLMeshSkinInfo> mSkinInfoQ; + + //set of requested decompositions + std::set<LLUUID> mDecompositionRequests; + + //set of requested physics shapes + std::set<LLUUID> mPhysicsShapeRequests; + + //queue of completed Decomposition info requests + std::queue<LLModel::Decomposition*> mDecompositionQ; + + //queue of requested headers + std::queue<HeaderRequest> mHeaderReqQ; + + //queue of requested LODs + std::queue<LODRequest> mLODReqQ; + + //queue of unavailable LODs (either asset doesn't exist or asset doesn't have desired LOD) + std::queue<LODRequest> mUnavailableQ; + + //queue of successfully loaded meshes + std::queue<LoadedMesh> mLoadedQ; + + //map of pending header requests and currently desired LODs + typedef std::map<LLVolumeParams, std::vector<S32> > pending_lod_map; + pending_lod_map mPendingLOD; + + static std::string constructUrl(LLUUID mesh_id); + + LLMeshRepoThread(); + ~LLMeshRepoThread(); + + virtual void run(); + + void loadMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + bool fetchMeshHeader(const LLVolumeParams& mesh_params); + bool fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + bool headerReceived(const LLVolumeParams& mesh_params, U8* data, S32 data_size); + bool lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size); + bool skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 data_size); + bool decompositionReceived(const LLUUID& mesh_id, U8* data, S32 data_size); + bool physicsShapeReceived(const LLUUID& mesh_id, U8* data, S32 data_size); + LLSD& getMeshHeader(const LLUUID& mesh_id); + + void notifyLoadedMeshes(); + S32 getActualMeshLOD(const LLVolumeParams& mesh_params, S32 lod); + + void loadMeshSkinInfo(const LLUUID& mesh_id); + void loadMeshDecomposition(const LLUUID& mesh_id); + void loadMeshPhysicsShape(const LLUUID& mesh_id); + + //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); + + //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) + bool fetchMeshDecomposition(const LLUUID& mesh_id); + + //send request for PhysicsShape, returns true if header info exists + // (should hold onto mesh_id and try again later if header info does not exist) + bool fetchMeshPhysicsShape(const LLUUID& mesh_id); + + +}; + +#if MESH_IMPORT +class LLMeshUploadThread : public LLThread +{ +private: + S32 mMeshUploadTimeOut ; //maximum time in seconds to execute an uploading request. + +public: + class DecompRequest : public LLPhysicsDecomp::Request + { + public: + LLPointer<LLModel> mModel; + LLPointer<LLModel> mBaseModel; + + LLMeshUploadThread* mThread; + + DecompRequest(LLModel* mdl, LLModel* base_model, LLMeshUploadThread* thread); + + S32 statusCallback(const char* status, S32 p1, S32 p2) { return 1; } + void completed(); + }; + + LLPointer<DecompRequest> mFinalDecomp; + bool mPhysicsComplete; + + typedef std::map<LLPointer<LLModel>, std::vector<LLVector3> > hull_map; + hull_map mHullMap; + + typedef std::vector<LLModelInstance> instance_list; + instance_list mInstanceList; + + typedef std::map<LLPointer<LLModel>, instance_list> instance_map; + instance_map mInstance; + + LLMutex* mMutex; + LLCurlRequest* mCurlRequest; + S32 mPendingUploads; + LLVector3 mOrigin; + bool mFinished; + bool mUploadTextures; + bool mUploadSkin; + bool mUploadJoints; + BOOL mDiscarded ; + + LLHost mHost; + std::string mWholeModelFeeCapability; + std::string mWholeModelUploadURL; + + LLMeshUploadThread(instance_list& data, LLVector3& scale, bool upload_textures, + bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true, + LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>())); + ~LLMeshUploadThread(); + + bool finished() { return mFinished; } + virtual void run(); + void preStart(); + void discard() ; + BOOL isDiscarded(); + + void generateHulls(); + + void doWholeModelUpload(); + void requestWholeModelFee(); + + void wholeModelToLLSD(LLSD& dest, bool include_textures); + + void decomposeMeshMatrix(LLMatrix4& transformation, + LLVector3& result_pos, + LLQuaternion& result_rot, + LLVector3& result_scale); + + void setFeeObserverHandle(LLHandle<LLWholeModelFeeObserver> observer_handle) { mFeeObserverHandle = observer_handle; } + void setUploadObserverHandle(LLHandle<LLWholeModelUploadObserver> observer_handle) { mUploadObserverHandle = observer_handle; } + +private: + LLHandle<LLWholeModelFeeObserver> mFeeObserverHandle; + LLHandle<LLWholeModelUploadObserver> mUploadObserverHandle; + + bool mDoUpload; // if FALSE only model data will be requested, otherwise the model will be uploaded +}; +#endif //MESH_IMPORT + +class LLMeshRepository +{ +public: + + //metrics + static U32 sBytesReceived; + static U32 sHTTPRequestCount; + static U32 sHTTPRetryCount; + static U32 sCacheBytesRead; + static U32 sCacheBytesWritten; + static U32 sPeakKbps; + + static F32 getStreamingCost(LLSD& header, F32 radius, S32* bytes = NULL, S32* visible_bytes = NULL, S32 detail = -1, F32 *unscaled_value = NULL); + + LLMeshRepository(); + + void init(); + void shutdown(); + S32 update() ; + + //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 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); + LLModel::Decomposition* getDecomposition(const LLUUID& mesh_id); + void fetchPhysicsShape(const LLUUID& mesh_id); + bool hasPhysicsShape(const LLUUID& mesh_id); + + void buildHull(const LLVolumeParams& params, S32 detail); + void buildPhysicsMesh(LLModel::Decomposition& decomp); + + bool meshUploadEnabled(); + bool meshRezEnabled(); + + + LLSD& getMeshHeader(const LLUUID& mesh_id); + +#if MESH_IMPORT + void uploadModel(std::vector<LLModelInstance>& data, LLVector3& scale, bool upload_textures, + bool upload_skin, bool upload_joints, std::string upload_url, bool do_upload = true, + LLHandle<LLWholeModelFeeObserver> fee_observer= (LLHandle<LLWholeModelFeeObserver>()), LLHandle<LLWholeModelUploadObserver> upload_observer = (LLHandle<LLWholeModelUploadObserver>())); +#endif //MESH_IMPORT + + S32 getMeshSize(const LLUUID& mesh_id, S32 lod); + + typedef std::map<LLVolumeParams, std::set<LLUUID> > mesh_load_map; + mesh_load_map mLoadingMeshes[4]; + + typedef std::map<LLUUID, LLMeshSkinInfo> skin_map; + skin_map mSkinMap; + + typedef std::map<LLUUID, LLModel::Decomposition*> decomposition_map; + decomposition_map mDecompositionMap; + + LLMutex* mMeshMutex; + + std::vector<LLMeshRepoThread::LODRequest> mPendingRequests; + + //list of mesh ids awaiting skin info + typedef std::map<LLUUID, std::set<LLUUID> > skin_load_map; + skin_load_map mLoadingSkins; + + //list of mesh ids that need to send skin info fetch requests + std::queue<LLUUID> mPendingSkinRequests; + + //list of mesh ids awaiting decompositions + std::set<LLUUID> mLoadingDecompositions; + + //list of mesh ids that need to send decomposition fetch requests + std::queue<LLUUID> mPendingDecompositionRequests; + + //list of mesh ids awaiting physics shapes + std::set<LLUUID> mLoadingPhysicsShapes; + + //list of mesh ids that need to send physics shape fetch requests + std::queue<LLUUID> mPendingPhysicsShapeRequests; + + U32 mMeshThreadCount; + +#if MESH_IMPORT + void cacheOutgoingMesh(LLMeshUploadData& data, LLSD& header); +#endif //MESH_IMPORT + + LLMeshRepoThread* mThread; +#if MESH_IMPORT + std::vector<LLMeshUploadThread*> mUploads; + std::vector<LLMeshUploadThread*> mUploadWaitList; +#endif //MESH_IMPORT + + LLPhysicsDecomp* mDecompThread; + + class inventory_data + { + public: + LLSD mPostData; + LLSD mResponse; + + inventory_data(const LLSD& data, const LLSD& content) + : mPostData(data), mResponse(content) + { + } + }; + + std::queue<inventory_data> mInventoryQ; + + std::queue<LLSD> mUploadErrorQ; + + void uploadError(LLSD& args); + void updateInventory(inventory_data data); + + std::string mGetMeshCapability; + +}; + +extern LLMeshRepository gMeshRepo; + +#endif + diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp index a140c7421..752e9be35 100644 --- a/indra/newview/llmutelist.cpp +++ b/indra/newview/llmutelist.cpp @@ -67,7 +67,7 @@ #include "llfloaterchat.h" #include "llimpanel.h" #include "llimview.h" -#include "llnotifications.h" +#include "llnotificationsutil.h" #include "lluistring.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" @@ -302,7 +302,7 @@ BOOL LLMuteList::add(const LLMute& mute, U32 flags) if ((mute.mType == LLMute::AGENT) && isLinden(mute.mName) && (flags & LLMute::flagTextChat || flags == 0)) { - LLNotifications::instance().add("MuteLinden"); + LLNotificationsUtil::add("MuteLinden"); return FALSE; } diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 614d6d39c..02964a038 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -638,33 +638,22 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, std::string& msg, LLRect* sticky_rec } else { -#ifdef LL_RRINTERFACE_H //MK - if (gRRenabled && gAgent.mRRInterface.mContainsShownames) + if (LLAvatarNameCache::useDisplayNames()) { - fullname = gAgent.mRRInterface.getDummyName(fullname); - } - else - { -#endif //mk - if (LLAvatarNameCache::useDisplayNames()) - { - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(mClosestAgentToCursor, &avatar_name)) - { - static const LLCachedControl<S32> phoenix_name_system("PhoenixNameSystem", 0); - if (phoenix_name_system == 2 || (phoenix_name_system == 1 && avatar_name.mIsDisplayNameDefault)) - { - fullname = avatar_name.mDisplayName; - } - else - { - fullname = avatar_name.getCompleteName(true); - } - } - } -#ifdef LL_RRINTERFACE_H //MK - } -#endif //mk + LLAvatarName avatar_name; + if (LLAvatarNameCache::get(mClosestAgentToCursor, &avatar_name)) + { + static const LLCachedControl<S32> phoenix_name_system("PhoenixNameSystem", 0); + if (phoenix_name_system == 2 || (phoenix_name_system == 1 && avatar_name.mIsDisplayNameDefault)) + { + fullname = avatar_name.mDisplayName; + } + else + { + fullname = avatar_name.getCompleteName(true); + } + } + } msg.append(fullname); } // [/Ansariel: Display name support] diff --git a/indra/newview/llnotify.cpp b/indra/newview/llnotify.cpp index ffd264b6c..afa2f84af 100644 --- a/indra/newview/llnotify.cpp +++ b/indra/newview/llnotify.cpp @@ -101,7 +101,7 @@ bool LLNotifyBox::onNotification(const LLSD& notify) //bring existing notification to top //This getInstance is ugly, as LLNotifyBox is derived from both LLInstanceTracker and LLEventTimer, which also is derived from its own LLInstanceTracker //Have to explicitly determine which getInstance function to use. - LLNotifyBox* boxp = LLNotifyBox::LLInstanceTracker<LLNotifyBox, LLUUID>::getInstance(notification->getID()); + LLNotifyBox* boxp = LLInstanceTracker<LLNotifyBox, LLUUID>::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { gNotifyBoxView->showOnly(boxp); @@ -118,7 +118,7 @@ bool LLNotifyBox::onNotification(const LLSD& notify) } else if (notify["sigtype"].asString() == "delete") { - LLNotifyBox* boxp = LLNotifyBox::LLInstanceTracker<LLNotifyBox, LLUUID>::getInstance(notification->getID()); + LLNotifyBox* boxp = LLInstanceTracker<LLNotifyBox, LLUUID>::getInstance(notification->getID()); if (boxp && !boxp->isDead()) { boxp->close(); diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp index db52949c7..d2b3c76cc 100644 --- a/indra/newview/llpanelavatar.cpp +++ b/indra/newview/llpanelavatar.cpp @@ -61,6 +61,7 @@ #include "lllineeditor.h" #include "llnameeditor.h" #include "llmutelist.h" +#include "llnotificationsutil.h" #include "llpanelclassified.h" #include "llpanelpick.h" #include "llpreviewtexture.h" @@ -380,13 +381,13 @@ void LLPanelAvatarSecondLife::onDoubleClickGroup(void* data) // static void LLPanelAvatarSecondLife::onClickPublishHelp(void *) { - LLNotifications::instance().add("ClickPublishHelpAvatar"); + LLNotificationsUtil::add("ClickPublishHelpAvatar"); } // static void LLPanelAvatarSecondLife::onClickPartnerHelp(void *) { - LLNotifications::instance().add("ClickPartnerHelpAvatar", LLSD(), LLSD(), onClickPartnerHelpLoadURL); + LLNotificationsUtil::add("ClickPartnerHelpAvatar", LLSD(), LLSD(), onClickPartnerHelpLoadURL); } // static @@ -646,7 +647,7 @@ void LLPanelAvatarWeb::onCommitURL(LLUICtrl* ctrl, void* data) // static void LLPanelAvatarWeb::onClickWebProfileHelp(void *) { - LLNotifications::instance().add("ClickWebProfileHelpAvatar"); + LLNotificationsUtil::add("ClickWebProfileHelpAvatar"); } void LLPanelAvatarWeb::load(std::string url) @@ -1006,7 +1007,7 @@ void LLPanelAvatarClassified::onClickNew(void* data) // [/RLVa:KB] LLPanelAvatarClassified* self = (LLPanelAvatarClassified*)data; - LLNotifications::instance().add("AddClassified", LLSD(), LLSD(), boost::bind(&LLPanelAvatarClassified::callbackNew, self, _1, _2)); + LLNotificationsUtil::add("AddClassified", LLSD(), LLSD(), boost::bind(&LLPanelAvatarClassified::callbackNew, self, _1, _2)); } @@ -1043,7 +1044,7 @@ void LLPanelAvatarClassified::onClickDelete(void* data) LLSD args; args["NAME"] = panel_classified->getClassifiedName(); - LLNotifications::instance().add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelAvatarClassified::callbackDelete, self, _1, _2)); + LLNotificationsUtil::add("DeleteClassified", args, LLSD(), boost::bind(&LLPanelAvatarClassified::callbackDelete, self, _1, _2)); } @@ -1258,7 +1259,7 @@ void LLPanelAvatarPicks::onClickDelete(void* data) LLSD args; args["PICK"] = panel_pick->getPickName(); - LLNotifications::instance().add("DeleteAvatarPick", args, LLSD(), + LLNotificationsUtil::add("DeleteAvatarPick", args, LLSD(), boost::bind(&LLPanelAvatarPicks::callbackDelete, self, _1, _2)); } @@ -2471,7 +2472,7 @@ void LLPanelAvatar::onClickKick(void* userdata) LLSD payload; payload["avatar_id"] = self->mAvatarID; - LLNotifications::instance().add("KickUser", LLSD(), payload, finishKick); + LLNotificationsUtil::add("KickUser", LLSD(), payload, finishKick); } //static @@ -2502,7 +2503,7 @@ void LLPanelAvatar::onClickFreeze(void* userdata) LLPanelAvatar* self = (LLPanelAvatar*) userdata; LLSD payload; payload["avatar_id"] = self->mAvatarID; - LLNotifications::instance().add("FreezeUser", LLSD(), payload, LLPanelAvatar::finishFreeze); + LLNotificationsUtil::add("FreezeUser", LLSD(), payload, LLPanelAvatar::finishFreeze); } // static @@ -2533,7 +2534,7 @@ void LLPanelAvatar::onClickUnfreeze(void* userdata) LLPanelAvatar* self = (LLPanelAvatar*) userdata; LLSD payload; payload["avatar_id"] = self->mAvatarID; - LLNotifications::instance().add("UnFreezeUser", LLSD(), payload, LLPanelAvatar::finishUnfreeze); + LLNotificationsUtil::add("UnFreezeUser", LLSD(), payload, LLPanelAvatar::finishUnfreeze); } // static diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 7f67853fa..45dfb60b9 100644 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -40,6 +40,8 @@ #include "lldir.h" #include "lldispatcher.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llparcel.h" #include "message.h" @@ -327,12 +329,12 @@ BOOL LLPanelClassified::titleIsValid() const std::string& name = mNameEditor->getText(); if (name.empty()) { - LLNotifications::instance().add("BlankClassifiedName"); + LLNotificationsUtil::add("BlankClassifiedName"); return FALSE; } if (!isalnum(name[0])) { - LLNotifications::instance().add("ClassifiedMustBeAlphanumeric"); + LLNotificationsUtil::add("ClassifiedMustBeAlphanumeric"); return FALSE; } @@ -387,7 +389,7 @@ BOOL LLPanelClassified::canClose() LLSD args; args["NAME"] = mNameEditor->getText(); - LLNotifications::instance().add("ClassifiedSave", args, LLSD(), boost::bind(&LLPanelClassified::saveCallback, this, _1, _2)); + LLNotificationsUtil::add("ClassifiedSave", args, LLSD(), boost::bind(&LLPanelClassified::saveCallback, this, _1, _2)); return FALSE; } @@ -813,7 +815,7 @@ void LLPanelClassified::onClickUpdate(void* data) if(self->mMatureCombo->getCurrentIndex() == DECLINE_TO_STATE) { // Tell user about it - LLNotifications::instance().add("SetClassifiedMature", + LLNotificationsUtil::add("SetClassifiedMature", LLSD(), LLSD(), boost::bind(&LLPanelClassified::confirmMature, self, _1, _2)); @@ -883,7 +885,7 @@ void LLPanelClassified::callbackGotPriceForListing(S32 option, std::string text, args["MIN_PRICE"] = price_text; args["[CURRENCY]"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); - LLNotifications::instance().add("MinClassifiedPrice", args); + LLNotificationsUtil::add("MinClassifiedPrice", args); return; } @@ -894,7 +896,7 @@ void LLPanelClassified::callbackGotPriceForListing(S32 option, std::string text, LLSD args; args["AMOUNT"] = llformat("%d", price_for_listing); args["CURRENCY"] = gHippoGridManager->getConnectedGrid()->getCurrencySymbol(); - LLNotifications::instance().add("PublishClassified", args, LLSD(), + LLNotificationsUtil::add("PublishClassified", args, LLSD(), boost::bind(&LLPanelClassified::confirmPublish, self, _1, _2)); } diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp index 5ab510eed..b35b91b6c 100644 --- a/indra/newview/llpanelcontents.cpp +++ b/indra/newview/llpanelcontents.cpp @@ -45,6 +45,7 @@ #include "llpermissionsflags.h" #include "lleconomy.h" #include "material_codes.h" +#include "llinventorydefines.h" // project includes #include "llui.h" diff --git a/indra/newview/llpaneldirbrowser.cpp b/indra/newview/llpaneldirbrowser.cpp index e2a24c163..35f207ab2 100644 --- a/indra/newview/llpaneldirbrowser.cpp +++ b/indra/newview/llpaneldirbrowser.cpp @@ -56,6 +56,7 @@ #include "lllineeditor.h" #include "llmenucommands.h" #include "llmenugl.h" +#include "llnotificationsutil.h" #include "llpanelavatar.h" #include "llpanelevent.h" #include "llpanelgroup.h" @@ -72,7 +73,6 @@ #include "llviewertexturelist.h" #include "llviewermessage.h" #include "lluictrlfactory.h" -#include "llnotify.h" #include <string> #include <sstream> @@ -596,7 +596,7 @@ void LLPanelDirBrowser::processDirPlacesReply(LLMessageSystem* msg, void**) msg->getU32("StatusData", "Status", status); if (status & STATUS_SEARCH_PLACES_BANNEDWORD) { - LLNotifications::instance().add("SearchWordBanned"); + LLNotificationsUtil::add("SearchWordBanned"); } } @@ -690,7 +690,7 @@ void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**) msg->getU32("StatusData", "Status", status); if (status & STATUS_SEARCH_EVENTS_BANNEDWORD) { - LLNotifications::instance().add("SearchWordBanned"); + LLNotificationsUtil::add("SearchWordBanned"); } } @@ -926,7 +926,7 @@ void LLPanelDirBrowser::processDirClassifiedReply(LLMessageSystem* msg, void**) msg->getU32("StatusData", "Status", status); if (status & STATUS_SEARCH_CLASSIFIEDS_BANNEDWORD) { - LLNotifications::instance().add("SearchWordBanned"); + LLNotificationsUtil::add("SearchWordBanned"); } } diff --git a/indra/newview/llpaneldirclassified.cpp b/indra/newview/llpaneldirclassified.cpp index 6703ec39e..eaa83aff0 100644 --- a/indra/newview/llpaneldirclassified.cpp +++ b/indra/newview/llpaneldirclassified.cpp @@ -65,7 +65,7 @@ // #include "llfloateravatarinfo.h" #include "llviewermenu.h" -#include "llnotify.h" +#include "llnotificationsutil.h" //----------------------------------------------------------------------------- // Constants @@ -189,7 +189,7 @@ void LLPanelDirClassified::performQuery() BOOL inc_adult = childGetValue("incadult").asBoolean(); if (!(inc_pg || inc_mature || inc_adult)) { - LLNotifications::instance().add("NoContentToSearch"); + LLNotificationsUtil::add("NoContentToSearch"); return; } diff --git a/indra/newview/llpaneldirevents.cpp b/indra/newview/llpaneldirevents.cpp index 54d32a8ce..44bea8693 100644 --- a/indra/newview/llpaneldirevents.cpp +++ b/indra/newview/llpaneldirevents.cpp @@ -50,7 +50,7 @@ #include "lluiconstants.h" #include "llpanelevent.h" #include "llappviewer.h" -#include "llnotify.h" +#include "llnotificationsutil.h" BOOL gDisplayEventHack = FALSE; @@ -190,7 +190,7 @@ void LLPanelDirEvents::performQueryOrDelete(U32 event_id) if ( !( scope & (DFQ_INC_PG | DFQ_INC_MATURE | DFQ_INC_ADULT ))) { - LLNotifications::instance().add("NoContentToSearch"); + LLNotificationsUtil::add("NoContentToSearch"); return; } diff --git a/indra/newview/llpaneldirfind.cpp b/indra/newview/llpaneldirfind.cpp index 398cb2972..f960fbb69 100644 --- a/indra/newview/llpaneldirfind.cpp +++ b/indra/newview/llpaneldirfind.cpp @@ -50,6 +50,7 @@ #include "llviewercontrol.h" #include "llmenucommands.h" #include "llmenugl.h" +#include "llnotificationsutil.h" #include "llpluginclassmedia.h" #include "lltextbox.h" #include "lluiconstants.h" @@ -218,7 +219,7 @@ void LLPanelDirFindAll::search(const std::string& search_text) BOOL inc_adult = childGetValue("incadult").asBoolean(); if (!(inc_pg || inc_mature || inc_adult)) { - LLNotifications::instance().add("NoContentToSearch"); + LLNotificationsUtil::add("NoContentToSearch"); return; } @@ -445,7 +446,7 @@ void LLPanelDirFind::onClickBack( void* data ) // static void LLPanelDirFind::onClickHelp( void* data ) { - LLNotifications::instance().add("ClickSearchHelpAll"); + LLNotificationsUtil::add("ClickSearchHelpAll"); } // static @@ -597,7 +598,7 @@ void LLPanelDirFindAllOld::onClickSearch(void *userdata) BOOL inc_adult = self->childGetValue("incadult").asBoolean(); if (!(inc_pg || inc_mature || inc_adult)) { - LLNotifications::instance().add("NoContentToSearch"); + LLNotificationsUtil::add("NoContentToSearch"); return; } diff --git a/indra/newview/llpaneldirgroups.cpp b/indra/newview/llpaneldirgroups.cpp index 5345304ec..009e68367 100644 --- a/indra/newview/llpaneldirgroups.cpp +++ b/indra/newview/llpaneldirgroups.cpp @@ -41,6 +41,7 @@ #include "llqueryflags.h" #include "llviewercontrol.h" #include "llviewerwindow.h" +#include "llnotificationsutil.h" LLPanelDirGroups::LLPanelDirGroups(const std::string& name, LLFloaterDirectory* floater) : LLPanelDirBrowser(name, floater) @@ -92,7 +93,7 @@ void LLPanelDirGroups::performQuery() // possible we threw away all the short words in the query so check length if ( query_string.length() < mMinSearchChars ) { - LLNotifications::instance().add("SeachFilteredOnShortWordsEmpty"); + LLNotificationsUtil::add("SeachFilteredOnShortWordsEmpty"); return; }; @@ -101,7 +102,7 @@ void LLPanelDirGroups::performQuery() BOOL inc_adult = childGetValue("incadult").asBoolean(); if (!(inc_pg || inc_mature || inc_adult)) { - LLNotifications::instance().add("NoContentToSearch"); + LLNotificationsUtil::add("NoContentToSearch"); return; } @@ -110,7 +111,7 @@ void LLPanelDirGroups::performQuery() { LLSD args; args["[FINALQUERY]"] = query_string; - LLNotifications::instance().add("SeachFilteredOnShortWords", args); + LLNotificationsUtil::add("SeachFilteredOnShortWords", args); }; setupNewSearch(); diff --git a/indra/newview/llpaneldirland.cpp b/indra/newview/llpaneldirland.cpp index 98b65f98f..c1b4c8ce9 100644 --- a/indra/newview/llpaneldirland.cpp +++ b/indra/newview/llpaneldirland.cpp @@ -45,13 +45,13 @@ #include "llcheckboxctrl.h" #include "llcombobox.h" #include "lllineeditor.h" +#include "llnotificationsutil.h" #include "llscrolllistctrl.h" #include "llstatusbar.h" #include "lluiconstants.h" #include "lltextbox.h" #include "llviewercontrol.h" #include "llviewermessage.h" -#include "llnotify.h" #include "hippogridmanager.h" @@ -175,7 +175,7 @@ void LLPanelDirLand::performQuery() BOOL inc_adult = childGetValue("incadult").asBoolean(); if (!(inc_pg || inc_mature || inc_adult)) { - LLNotifications::instance().add("NoContentToSearch"); + LLNotificationsUtil::add("NoContentToSearch"); return; } diff --git a/indra/newview/llpaneldirpeople.cpp b/indra/newview/llpaneldirpeople.cpp index 053cad558..a771db70c 100644 --- a/indra/newview/llpaneldirpeople.cpp +++ b/indra/newview/llpaneldirpeople.cpp @@ -34,6 +34,7 @@ #include "llpaneldirpeople.h" #include "llviewerwindow.h" +#include "llnotificationsutil.h" // linden library includes #include "message.h" @@ -87,7 +88,7 @@ void LLPanelDirPeople::performQuery() // possible we threw away all the short words in the query so check length if ( query_string.length() < mMinSearchChars ) { - LLNotifications::instance().add("SeachFilteredOnShortWordsEmpty"); + LLNotificationsUtil::add("SeachFilteredOnShortWordsEmpty"); return; }; @@ -96,7 +97,7 @@ void LLPanelDirPeople::performQuery() { LLSD args; args["FINALQUERY"] = query_string; - LLNotifications::instance().add("SeachFilteredOnShortWords", args); + LLNotificationsUtil::add("SeachFilteredOnShortWords", args); }; setupNewSearch(); diff --git a/indra/newview/llpaneldirplaces.cpp b/indra/newview/llpaneldirplaces.cpp index 305d2e2ac..96070b4b0 100644 --- a/indra/newview/llpaneldirplaces.cpp +++ b/indra/newview/llpaneldirplaces.cpp @@ -50,6 +50,7 @@ #include "llcombobox.h" #include "llfloaterdirectory.h" #include "lllineeditor.h" +#include "llnotificationsutil.h" #include "llviewerwindow.h" #include "llpaneldirbrowser.h" #include "lltextbox.h" @@ -57,7 +58,6 @@ #include "llviewercontrol.h" #include "llviewermessage.h" #include "llworldmap.h" -#include "llnotify.h" LLPanelDirPlaces::LLPanelDirPlaces(const std::string& name, LLFloaterDirectory* floater) : LLPanelDirBrowser(name, floater) @@ -141,7 +141,7 @@ void LLPanelDirPlaces::performQuery() // possible we threw away all the short words in the query so check length if ( query_string.length() < mMinSearchChars ) { - LLNotifications::instance().add("SeachFilteredOnShortWordsEmpty"); + LLNotificationsUtil::add("SeachFilteredOnShortWordsEmpty"); return; }; @@ -150,7 +150,7 @@ void LLPanelDirPlaces::performQuery() { LLSD args; args["FINALQUERY"] = query_string; - LLNotifications::instance().add("SeachFilteredOnShortWords", args); + LLNotificationsUtil::add("SeachFilteredOnShortWords", args); }; std::string catstring = childGetValue("Category").asString(); @@ -207,7 +207,7 @@ void LLPanelDirPlaces::performQuery() if (0x0 == flags) { - LLNotifications::instance().add("NoContentToSearch"); + LLNotificationsUtil::add("NoContentToSearch"); return; } diff --git a/indra/newview/llpaneldisplay.cpp b/indra/newview/llpaneldisplay.cpp index c7aeabcce..925ca40c7 100644 --- a/indra/newview/llpaneldisplay.cpp +++ b/indra/newview/llpaneldisplay.cpp @@ -120,7 +120,7 @@ BOOL LLPanelDisplay::postBuild() // radio set for fullscreen size mCtrlWindowed = getChild<LLCheckBoxCtrl>( "windowed mode"); - mCtrlWindowed->setCommitCallback(onCommitWindowedMode); + mCtrlWindowed->setCommitCallback(&LLPanelDisplay::onCommitWindowedMode); mCtrlWindowed->setCallbackUserData(this); mAspectRatioLabel1 = getChild<LLTextBox>("AspectRatioLabel1"); @@ -215,7 +215,7 @@ BOOL LLPanelDisplay::postBuild() // radio performance box mCtrlSliderQuality = getChild<LLSliderCtrl>("QualityPerformanceSelection"); - mCtrlSliderQuality->setSliderMouseUpCallback(onChangeQuality); + mCtrlSliderQuality->setSliderMouseUpCallback(boost::bind(&LLPanelDisplay::onChangeQuality,mCtrlSliderQuality,this)); mCtrlSliderQuality->setCallbackUserData(this); mCtrlCustomSettings = getChild<LLCheckBoxCtrl>("CustomSettings"); diff --git a/indra/newview/llpanelevent.cpp b/indra/newview/llpanelevent.cpp index c8c49a872..0105180a4 100644 --- a/indra/newview/llpanelevent.cpp +++ b/indra/newview/llpanelevent.cpp @@ -45,6 +45,7 @@ #include "llfloater.h" #include "llfloaterworldmap.h" #include "llinventorymodel.h" +#include "llnotificationsutil.h" #include "llsecondlifeurls.h" #include "lltextbox.h" #include "llviewertexteditor.h" @@ -114,25 +115,10 @@ void LLPanelEvent::setEventID(const U32 event_id) if (event_id != 0) { - sendEventInfoRequest(); + gEventNotifier.add(event_id); } } - -void LLPanelEvent::sendEventInfoRequest() -{ - LLMessageSystem *msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_EventInfoRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() ); - msg->nextBlockFast(_PREHASH_EventData); - msg->addU32Fast(_PREHASH_EventID, mEventID); - gAgent.sendReliableMessage(); -} - - //static void LLPanelEvent::processEventInfoReply(LLMessageSystem *msg, void **) { @@ -277,7 +263,7 @@ void LLPanelEvent::onClickLandmark(void* data) // static void LLPanelEvent::onClickCreateEvent(void* data) { - LLNotifications::instance().add("PromptGoToEventsPage", LLSD(), LLSD(), callbackCreateEventWebPage); + LLNotificationsUtil::add("PromptGoToEventsPage", LLSD(), LLSD(), callbackCreateEventWebPage); } // static diff --git a/indra/newview/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp index add1f3caa..835d8e514 100644 --- a/indra/newview/llpanelgroup.cpp +++ b/indra/newview/llpanelgroup.cpp @@ -46,7 +46,7 @@ #include "lluictrlfactory.h" #include "llviewerwindow.h" #include "llappviewer.h" -#include "llnotifications.h" +#include "llnotificationsutil.h" // static void* LLPanelGroupTab::createTab(void* data) @@ -411,7 +411,7 @@ BOOL LLPanelGroup::attemptTransition() LLSD args; args["NEEDS_APPLY_MESSAGE"] = mesg; args["WANT_APPLY_MESSAGE"] = mWantApplyMesg; - LLNotifications::instance().add("PanelGroupApply", args, LLSD(), + LLNotificationsUtil::add("PanelGroupApply", args, LLSD(), boost::bind(&LLPanelGroup::handleNotifyCallback, this, _1, _2)); mShowingNotifyDialog = TRUE; @@ -559,7 +559,7 @@ bool LLPanelGroup::apply() { LLSD args; args["MESSAGE"] = apply_mesg; - LLNotifications::instance().add("GenericAlert", args); + LLNotificationsUtil::add("GenericAlert", args); } return false; diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp index 1c05d340f..044b40337 100644 --- a/indra/newview/llpanelgroupgeneral.cpp +++ b/indra/newview/llpanelgroupgeneral.cpp @@ -50,6 +50,7 @@ #include "llnamebox.h" #include "llnamelistctrl.h" #include "llnameeditor.h" +#include "llnotificationsutil.h" #include "llspinctrl.h" #include "llstatusbar.h" // can_afford_transaction() #include "lltextbox.h" @@ -377,11 +378,11 @@ void LLPanelGroupGeneral::onClickJoin(void *userdata) if (can_afford_transaction(cost)) { - LLNotifications::instance().add("JoinGroupCanAfford", args, payload, LLPanelGroupGeneral::joinDlgCB); + LLNotificationsUtil::add("JoinGroupCanAfford", args, payload, LLPanelGroupGeneral::joinDlgCB); } else { - LLNotifications::instance().add("JoinGroupCannotAfford", args, payload); + LLNotificationsUtil::add("JoinGroupCannotAfford", args, payload); } } else @@ -472,7 +473,7 @@ bool LLPanelGroupGeneral::apply(std::string& mesg) if(mComboMature && mComboMature->getCurrentIndex() == DECLINE_TO_STATE) { - LLNotifications::instance().add("SetGroupMature", LLSD(), LLSD(), + LLNotificationsUtil::add("SetGroupMature", LLSD(), LLSD(), boost::bind(&LLPanelGroupGeneral::confirmMatureApply, this, _1, _2)); return false; } @@ -493,7 +494,7 @@ bool LLPanelGroupGeneral::apply(std::string& mesg) LLSD args; args["MESSAGE"] = mConfirmGroupCreateStr; - LLNotifications::instance().add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupGeneral::createGroupCallback, this, _1, _2)); + LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupGeneral::createGroupCallback, this, _1, _2)); return false; } diff --git a/indra/newview/llpanelgroupinvite.cpp b/indra/newview/llpanelgroupinvite.cpp index f95a27aad..cff4637bd 100644 --- a/indra/newview/llpanelgroupinvite.cpp +++ b/indra/newview/llpanelgroupinvite.cpp @@ -39,6 +39,7 @@ #include "llcombobox.h" #include "llgroupmgr.h" #include "llnamelistctrl.h" +#include "llnotificationsutil.h" #include "llspinctrl.h" #include "lltextbox.h" #include "llviewerobject.h" @@ -161,7 +162,7 @@ void LLPanelGroupInvite::impl::submitInvitations() { LLSD args; args["MESSAGE"] = mOwnerWarning; - LLNotifications::instance().add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupInvite::impl::inviteOwnerCallback, this, _1, _2)); + LLNotificationsUtil::add("GenericAlertYesCancel", args, LLSD(), boost::bind(&LLPanelGroupInvite::impl::inviteOwnerCallback, this, _1, _2)); return; // we'll be called again if user confirms } } diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp index 950f08699..48115837a 100644 --- a/indra/newview/llpanelgroupnotices.cpp +++ b/indra/newview/llpanelgroupnotices.cpp @@ -39,6 +39,7 @@ #include "llinventory.h" #include "llviewerinventory.h" #include "llinventorymodel.h" +#include "llinventorydefines.h" #include "llinventoryview.h" #include "llagent.h" #include "lltooldraganddrop.h" @@ -48,6 +49,7 @@ #include "llbutton.h" #include "lliconctrl.h" #include "llcheckboxctrl.h" +#include "llnotificationsutil.h" #include "llscrolllistctrl.h" #include "lltextbox.h" @@ -55,7 +57,6 @@ #include "llviewerwindow.h" #include "llviewercontrol.h" #include "llviewermessage.h" -#include "llnotifications.h" const S32 NOTICE_DATE_STRING_SIZE = 30; @@ -351,7 +352,7 @@ void LLPanelGroupNotices::onClickSendMessage(void* data) if (self->mCreateSubject->getText().empty()) { // Must supply a subject - LLNotifications::instance().add("MustSpecifyGroupNoticeSubject"); + LLNotificationsUtil::add("MustSpecifyGroupNoticeSubject"); return; } send_group_notice( diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index fe42aef8d..be41b0f87 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -41,7 +41,7 @@ #include "lliconctrl.h" #include "lllineeditor.h" #include "llnamelistctrl.h" -#include "llnotify.h" +#include "llnotificationsutil.h" #include "llpanelgrouproles.h" #include "llscrolllistctrl.h" #include "lltabcontainer.h" @@ -241,7 +241,7 @@ BOOL LLPanelGroupRoles::attemptTransition() LLSD args; args["NEEDS_APPLY_MESSAGE"] = mesg; args["WANT_APPLY_MESSAGE"] = mWantApplyMesg; - LLNotifications::instance().add("PanelGroupApply", args, LLSD(), + LLNotificationsUtil::add("PanelGroupApply", args, LLSD(), boost::bind(&LLPanelGroupRoles::handleNotifyCallback, this, _1, _2)); mHasModal = TRUE; // We need to reselect the current tab, since it isn't finished. @@ -301,7 +301,7 @@ bool LLPanelGroupRoles::handleNotifyCallback(const LLSD& notification, const LLS mHasModal = TRUE; LLSD args; args["MESSAGE"] = apply_mesg; - LLNotifications::instance().add("GenericAlert", args, LLSD(), boost::bind(&LLPanelGroupRoles::onModalClose, this, _1, _2)); + LLNotificationsUtil::add("GenericAlert", args, LLSD(), boost::bind(&LLPanelGroupRoles::onModalClose, this, _1, _2)); } // Skip switching tabs. break; @@ -1370,7 +1370,7 @@ bool LLPanelGroupMembersSubTab::apply(std::string& mesg) { mHasModal = TRUE; args["ROLE_NAME"] = rd.mRoleName; - LLNotifications::instance().add("AddGroupOwnerWarning", + LLNotificationsUtil::add("AddGroupOwnerWarning", args, LLSD(), boost::bind(&LLPanelGroupMembersSubTab::addOwnerCB, this, _1, _2)); @@ -2397,7 +2397,7 @@ void LLPanelGroupRolesSubTab::handleDeleteRole() { LLSD args; args["MESSAGE"] = mRemoveEveryoneTxt; - LLNotifications::instance().add("GenericAlert", args); + LLNotificationsUtil::add("GenericAlert", args); return; } diff --git a/indra/newview/llpanelgroupvoting.cpp b/indra/newview/llpanelgroupvoting.cpp index 162806c63..5094d1c26 100644 --- a/indra/newview/llpanelgroupvoting.cpp +++ b/indra/newview/llpanelgroupvoting.cpp @@ -35,6 +35,7 @@ #include "roles_constants.h" #include "lllineeditor.h" +#include "llnotificationsutil.h" #include "lltextbox.h" #include "lltexteditor.h" #include "llscrolllistctrl.h" @@ -648,7 +649,7 @@ void LLPanelGroupVoting::handleResponse( args["MESSAGE"] = self->mPanel.getString("vote_previously_recorded"); } - LLNotifications::instance().add("SystemMessage", args); + LLNotificationsUtil::add("SystemMessage", args); self->sendGroupVoteHistoryRequest(self->mGroupID); } @@ -1357,7 +1358,7 @@ void LLPanelGroupVoting::impl::onClickSubmitProposal(void *userdata) //throw up an error dialog LLSD args; args["MESSAGE"] = self->mPanel.getString("empty_proposal_txt"); - LLNotifications::instance().add("GenericAlert", args); + LLNotificationsUtil::add("GenericAlert", args); return; } @@ -1400,7 +1401,7 @@ void LLPanelGroupVoting::impl::onClickViewProposalItem(void *userdata) } else { - LLNotifications::instance().add("SelectProposalToView"); + LLNotificationsUtil::add("SelectProposalToView"); } } } @@ -1440,7 +1441,7 @@ void LLPanelGroupVoting::impl::onClickViewHistoryItem(void *userdata) } else { - LLNotifications::instance().add("SelectHistoryItemToView"); + LLNotificationsUtil::add("SelectHistoryItemToView"); } } } diff --git a/indra/newview/llpanelinventory.cpp b/indra/newview/llpanelinventory.cpp index 8a1e7c112..4fc93bcc7 100644 --- a/indra/newview/llpanelinventory.cpp +++ b/indra/newview/llpanelinventory.cpp @@ -50,6 +50,8 @@ #include "llfontgl.h" #include "llassetstorage.h" #include "llinventory.h" +#include "llinventorydefines.h" +#include "llnotificationsutil.h" #include "llagent.h" #include "llcallbacklist.h" @@ -232,7 +234,7 @@ void LLTaskInvFVBridge::buyItem() LLViewerObject* obj; if( ( obj = gObjectList.findObject( mPanel->getTaskUUID() ) ) && obj->isAttachment() ) { - LLNotifications::instance().add("Cannot_Purchase_an_Attachment"); + LLNotificationsUtil::add("Cannot_Purchase_an_Attachment"); llinfos << "Attempt to purchase an attachment" << llendl; delete inv; } @@ -532,7 +534,7 @@ BOOL LLTaskInvFVBridge::removeItem() LLSD payload; payload["task_id"] = mPanel->getTaskUUID(); payload["inventory_ids"].append(mUUID); - LLNotifications::instance().add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel)); + LLNotificationsUtil::add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel)); return FALSE; } } @@ -562,7 +564,7 @@ void LLTaskInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& LLTaskInvFVBridge* itemp = (LLTaskInvFVBridge*)batch[i]; payload["inventory_ids"].append(itemp->getUUID()); } - LLNotifications::instance().add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel)); + LLNotificationsUtil::add("RemoveItemWarn", LLSD(), payload, boost::bind(&remove_task_inventory_callback, _1, _2, mPanel)); } else diff --git a/indra/newview/llpanelland.cpp b/indra/newview/llpanelland.cpp index d1eee80b3..f3591c0ad 100644 --- a/indra/newview/llpanelland.cpp +++ b/indra/newview/llpanelland.cpp @@ -40,6 +40,7 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "llfloaterland.h" +#include "llnotificationsutil.h" #include "lltextbox.h" #include "llviewercontrol.h" #include "llviewerparcelmgr.h" @@ -179,7 +180,7 @@ void LLPanelLandInfo::refresh() childSetEnabled("button abandon land",owner_release || manager_releaseable || gAgent.isGodlike()); // only mainland sims are subdividable by owner - if (regionp->getRegionFlags() && REGION_FLAGS_ALLOW_PARCEL_CHANGES) + if (regionp->getRegionFlags() & REGION_FLAGS_ALLOW_PARCEL_CHANGES) { childSetEnabled("button subdivide land",owner_divide || manager_divideable || gAgent.isGodlike()); } @@ -280,5 +281,5 @@ void LLPanelLandInfo::onClickAbout(void*) void LLPanelLandInfo::onShowOwnersHelp(void* user_data) { - LLNotifications::instance().add("ShowOwnersHelp"); + LLNotificationsUtil::add("ShowOwnersHelp"); } diff --git a/indra/newview/llpanellandaudio.cpp b/indra/newview/llpanellandaudio.cpp index dd38bdbd4..ce9f17f6e 100644 --- a/indra/newview/llpanellandaudio.cpp +++ b/indra/newview/llpanellandaudio.cpp @@ -47,6 +47,7 @@ #include "llfloaterurlentry.h" #include "llfocusmgr.h" #include "lllineeditor.h" +#include "llnotificationsutil.h" #include "llparcel.h" #include "lltextbox.h" #include "llradiogroup.h" @@ -197,5 +198,5 @@ void LLPanelLandAudio::onCommitAny(LLUICtrl*, void *userdata) // static void LLPanelLandAudio::onClickSoundHelp(void*) { - LLNotifications::instance().add("ClickSoundHelpLand"); + LLNotificationsUtil::add("ClickSoundHelpLand"); } diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 79da3805b..fde18272d 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -56,6 +56,7 @@ #include "llfloaterpreference.h" #include "llfocusmgr.h" #include "lllineeditor.h" +#include "llnotificationsutil.h" #include "llstartup.h" #include "lltextbox.h" #include "llui.h" @@ -109,7 +110,12 @@ static bool nameSplit(const std::string& full, std::string& first, std::string& return false; first = fragments[0]; if (fragments.size() == 1) - last = "resident"; + { + if (gHippoGridManager->getConnectedGrid()->isSecondLife()) + last = "resident"; + else + last = ""; + } else last = fragments[1]; return (fragments.size() <= 2); @@ -607,7 +613,7 @@ void LLPanelLogin::giveFocus() if( sInstance ) { // Grab focus and move cursor to first blank input field - std::string first = sInstance->childGetText("name_combo"); + std::string first = sInstance->getChild<LLComboBox>("name_combo")->getTextEntry(); std::string pass = sInstance->childGetText("password_edit"); BOOL have_first = !first.empty(); @@ -712,6 +718,7 @@ void LLPanelLogin::setFields(const LLSavedLoginEntry& entry, bool takeFocus) std::string fullname = nameJoin(entry.getFirstName(), entry.getLastName()); LLComboBox* login_combo = sInstance->getChild<LLComboBox>("name_combo"); login_combo->setTextEntry(fullname); + login_combo->resetTextDirty(); //sInstance->childSetText("name_combo", fullname); std::string grid = entry.getGrid(); @@ -854,7 +861,7 @@ void LLPanelLogin::updateGridCombo() } HippoGridManager::GridIterator it, end = gHippoGridManager->endGrid(); for (it = gHippoGridManager->beginGrid(); it != end; ++it) { - const std::string &grid = it->second->getGridNick(); + const std::string &grid = it->second->getGridName(); if (grid != defaultGrid) { grids->add(grid); if (grid == currentGrid) selectIndex = i; @@ -1110,9 +1117,9 @@ void LLPanelLogin::onClickConnect(void *) else { if (gHippoGridManager->getConnectedGrid()->getRegisterUrl().empty()) { - LLNotifications::instance().add("MustHaveAccountToLogInNoLinks"); + LLNotificationsUtil::add("MustHaveAccountToLogInNoLinks"); } else { - LLNotifications::instance().add("MustHaveAccountToLogIn", LLSD(), LLSD(), + LLNotificationsUtil::add("MustHaveAccountToLogIn", LLSD(), LLSD(), LLPanelLogin::newAccountAlertCallback); } } @@ -1206,7 +1213,7 @@ void LLPanelLogin::onPassKey(LLLineEditor* caller, void* user_data) { if (gKeyboard->getKeyDown(KEY_CAPSLOCK) && sCapslockDidNotification == FALSE) { - LLNotifications::instance().add("CapsKeyOn"); + LLNotificationsUtil::add("CapsKeyOn"); sCapslockDidNotification = TRUE; } } @@ -1237,16 +1244,10 @@ void LLPanelLogin::onLoginComboLostFocus(LLFocusableElement* fe, void*) if (sInstance) { LLComboBox* combo = sInstance->getChild<LLComboBox>("name_combo"); - if(fe == combo) + if(fe == combo && combo->isTextDirty()) { - if (combo->isTextDirty()) - { - clearPassword(); - } - else - { - onSelectLoginEntry(combo, NULL); - } + clearPassword(); + combo->resetTextDirty(); } } } diff --git a/indra/newview/llpanelmediahud.cpp b/indra/newview/llpanelmediahud.cpp index cd8b63f2d..2d0aa931c 100644 --- a/indra/newview/llpanelmediahud.cpp +++ b/indra/newview/llpanelmediahud.cpp @@ -41,6 +41,7 @@ #include "llrender.h" #include "lldrawable.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "lluictrlfactory.h" #include "llbutton.h" #include "llface.h" @@ -301,7 +302,7 @@ void LLPanelMediaHUD::updateShape() { const LLVolumeFace& vf = volume->getVolumeFace(nodep->getLastSelectedTE()); - const LLVector3* ext = vf.mExtents; + const LLVector3* ext = (LLVector3*)vf.mExtents->getF32ptr(); LLVector3 center = (ext[0]+ext[1])*0.5f; LLVector3 size = (ext[1]-ext[0])*0.5f; @@ -396,9 +397,8 @@ void LLPanelMediaHUD::updateShape() } } // If we need to start fading the UI (and we have not already started) - else if(! mFadeTimer.getStarted()) + else if (!mFadeTimer.getStarted()) { - mFadeTimer.reset(); mFadeTimer.start(); } } diff --git a/indra/newview/llpanelmsgs.cpp b/indra/newview/llpanelmsgs.cpp index e0b105293..96fe7129b 100644 --- a/indra/newview/llpanelmsgs.cpp +++ b/indra/newview/llpanelmsgs.cpp @@ -34,6 +34,7 @@ #include "llpanelmsgs.h" +#include "llnotificationsutil.h" #include "llscrolllistctrl.h" #include "llviewerwindow.h" #include "llviewercontrol.h" @@ -222,7 +223,7 @@ bool callback_reset_dialogs(const LLSD& notification, const LLSD& response, LLPa // static void LLPanelMsgs::onClickResetDialogs(void* user_data) { - LLNotifications::instance().add("ResetShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_reset_dialogs, _1, _2, (LLPanelMsgs*)user_data)); + LLNotificationsUtil::add("ResetShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_reset_dialogs, _1, _2, (LLPanelMsgs*)user_data)); } bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLPanelMsgs* panelp) @@ -243,5 +244,5 @@ bool callback_skip_dialogs(const LLSD& notification, const LLSD& response, LLPan // static void LLPanelMsgs::onClickSkipDialogs(void* user_data) { - LLNotifications::instance().add("SkipShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_skip_dialogs, _1, _2, (LLPanelMsgs*)user_data)); + LLNotificationsUtil::add("SkipShowNextTimeDialogs", LLSD(), LLSD(), boost::bind(&callback_skip_dialogs, _1, _2, (LLPanelMsgs*)user_data)); } diff --git a/indra/newview/llpanelnetwork.cpp b/indra/newview/llpanelnetwork.cpp index 003af8116..ebe4b1f84 100644 --- a/indra/newview/llpanelnetwork.cpp +++ b/indra/newview/llpanelnetwork.cpp @@ -41,6 +41,7 @@ #include "llradiogroup.h" #include "statemachine/aidirpicker.h" #include "lluictrlfactory.h" +#include "llnotificationsutil.h" #include "llviewercontrol.h" #include "llviewerwindow.h" @@ -126,7 +127,7 @@ void LLPanelNetwork::apply() { if (LLStartUp::getStartupState() != STATE_LOGIN_WAIT) { - LLNotifications::instance().add("ProxyNeedRestart"); + LLNotificationsUtil::add("ProxyNeedRestart"); } else { @@ -145,7 +146,7 @@ void LLPanelNetwork::onClickClearCache(void*) { // flag client cache for clearing next time the client runs gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE); - LLNotifications::instance().add("CacheWillClear"); + LLNotificationsUtil::add("CacheWillClear"); } // static @@ -172,7 +173,7 @@ void LLPanelNetwork::onClickSetCache_continued(void* user_data, AIDirPicker* dir if (!dir_name.empty() && dir_name != cur_name) { self->childSetText("cache_location", dir_name); - LLNotifications::instance().add("CacheWillBeMoved"); + LLNotificationsUtil::add("CacheWillBeMoved"); gSavedSettings.setString("NewCacheLocation", dir_name); } else @@ -192,7 +193,7 @@ void LLPanelNetwork::onClickResetCache(void* user_data) return; } gSavedSettings.setString("NewCacheLocation", ""); - LLNotifications::instance().add("CacheWillBeMoved"); + LLNotificationsUtil::add("CacheWillBeMoved"); std::string cache_location = gDirUtilp->getCacheDir(false); self->childSetText("cache_location", cache_location); } @@ -205,7 +206,7 @@ void LLPanelNetwork::onCommitPort(LLUICtrl* ctrl, void* data) if (!self || !check) return; self->childSetEnabled("connection_port", check->get()); - LLNotifications::instance().add("ChangeConnectionPort"); + LLNotificationsUtil::add("ChangeConnectionPort"); } // static diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index d448368ea..b92632337 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -53,6 +53,7 @@ #include "llcombobox.h" #include "llfocusmgr.h" #include "llmanipscale.h" +#include "llnotificationsutil.h" #include "llpanelinventory.h" #include "llpreviewscript.h" #include "llresmgr.h" @@ -67,6 +68,7 @@ #include "llviewerobject.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llvovolume.h" #include "llworld.h" #include "pipeline.h" @@ -476,7 +478,7 @@ void LLPanelObject::getState( ) } // can move or rotate only linked group with move permissions, or sub-object with move and modify perms - BOOL enable_move = objectp->permMove() && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); + BOOL enable_move = objectp->permMove() && (!objectp->isAttachment() && objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); BOOL enable_scale = objectp->permMove() && objectp->permModify(); BOOL enable_rotate = objectp->permMove() && ( (objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts")); BOOL enable_link = objectp->permMove() && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); @@ -492,15 +494,6 @@ void LLPanelObject::getState( ) enable_rotate = FALSE; } - - - - - - - - - // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) if ( (rlv_handler_t::isEnabled()) && ((gRlvHandler.hasBehaviour(RLV_BHVR_UNSIT)) || (gRlvHandler.hasBehaviour(RLV_BHVR_SITTP))) ) { @@ -735,7 +728,7 @@ void LLPanelObject::getState( ) BOOL enabled = FALSE; BOOL hole_enabled = FALSE; F32 scale_x=1.f, scale_y=1.f; - + BOOL isMesh = FALSE; if( !objectp || !objectp->getVolume() || !editable || !single_volume) { // Clear out all geometry fields. @@ -1125,14 +1118,14 @@ void LLPanelObject::getState( ) //top_shear_x_visible = FALSE; //top_shear_y_visible = FALSE; //advanced_cut_visible = TRUE; - //advanced_is_dimple = TRUE; + advanced_is_dimple = TRUE; //twist_min = OBJECT_TWIST_MIN; //twist_max = OBJECT_TWIST_MAX; //twist_inc = OBJECT_TWIST_INC; // Just like the others except no radius size_is_hole = TRUE; skew_visible = TRUE; - advanced_cut_visible = TRUE; + //advanced_cut_visible = TRUE; taper_visible = TRUE; radius_offset_visible = FALSE; revolutions_visible = TRUE; @@ -1145,8 +1138,9 @@ void LLPanelObject::getState( ) case MI_TEST_PRISM: case MI_TEST_HEMICYLINDER: cut_visible = FALSE; - advanced_cut_visible = TRUE; - taper_visible = FALSE; + //advanced_cut_visible = TRUE; + advanced_is_slice = TRUE; + //taper_visible = FALSE; radius_offset_visible = FALSE; revolutions_visible = FALSE; top_shear_x_visible = FALSE; @@ -1399,15 +1393,9 @@ void LLPanelObject::getState( ) mCtrlSculptTexture->setVisible(sculpt_texture_visible); mLabelSculptType->setVisible(sculpt_texture_visible); mCtrlSculptType->setVisible(sculpt_texture_visible); - mCtrlSculptMirror->setVisible(sculpt_texture_visible); - mCtrlSculptInvert->setVisible(sculpt_texture_visible); - - - // sculpt texture - if (selected_item == MI_SCULPT) { LLUUID id; @@ -1421,36 +1409,37 @@ void LLPanelObject::getState( ) mSculptTextureRevert = sculpt_params->getSculptTexture(); mSculptTypeRevert = sculpt_params->getSculptType(); } - + U8 sculpt_type = sculpt_params->getSculptType(); + U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; + BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; + BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; +#if MESH_ENABLED + isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH); +#endif //MESH_ENABLED + LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control"); if(mTextureCtrl) { mTextureCtrl->setTentative(FALSE); - mTextureCtrl->setEnabled(editable); + mTextureCtrl->setEnabled(editable && !isMesh); if (editable) mTextureCtrl->setImageAssetID(sculpt_params->getSculptTexture()); else mTextureCtrl->setImageAssetID(LLUUID::null); } - - - - U8 sculpt_type = sculpt_params->getSculptType(); - U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; - BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; - BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; + mComboBaseType->setEnabled(!isMesh); if (mCtrlSculptType) { mCtrlSculptType->setCurrentByIndex(sculpt_stitching); - mCtrlSculptType->setEnabled(editable); + mCtrlSculptType->setEnabled(editable && !isMesh); } if (mCtrlSculptMirror) { mCtrlSculptMirror->set(sculpt_mirror); - mCtrlSculptMirror->setEnabled(editable); + mCtrlSculptMirror->setEnabled(editable && !isMesh); } if (mCtrlSculptInvert) @@ -1463,18 +1452,16 @@ void LLPanelObject::getState( ) { mLabelSculptType->setEnabled(TRUE); } + } } - - - - - else { - mSculptTextureRevert = LLUUID::null; + mSculptTextureRevert = LLUUID::null; } + mCtrlSculptMirror->setVisible(sculpt_texture_visible && !isMesh); + mCtrlSculptInvert->setVisible(sculpt_texture_visible && !isMesh); //---------------------------------------------------------------------------- @@ -2169,7 +2156,7 @@ void LLPanelObject::sendPosition(BOOL btn_down) // Clamp the Z height const F32 height = newpos.mV[VZ]; - const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject); + const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal()); // <edit> //const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight(); const F32 max_height = F32(340282346638528859811704183484516925440.0f); @@ -2199,7 +2186,8 @@ void LLPanelObject::sendPosition(BOOL btn_down) // won't get dumped by the simulator. LLVector3d new_pos_global = regionp->getPosGlobalFromRegion(newpos); - if ( LLWorld::getInstance()->positionRegionValidGlobal(new_pos_global) ) + if (LLWorld::getInstance()->positionRegionValidGlobal(new_pos_global) || + mObject->isAttachment()) { // send only if the position is changed, that is, the delta vector is not zero LLVector3d old_pos_global = mObject->getPositionGlobal(); @@ -2261,6 +2249,20 @@ void LLPanelObject::sendSculpt() if (mCtrlSculptType) sculpt_type |= mCtrlSculptType->getCurrentIndex(); + bool enabled = true; +#if MESH_ENABLED + enabled = sculpt_type != LL_SCULPT_TYPE_MESH; +#endif //MESH_ENABLED + + if (mCtrlSculptMirror) + { + mCtrlSculptMirror->setEnabled(enabled ? TRUE : FALSE); + } + if (mCtrlSculptInvert) + { + mCtrlSculptInvert->setEnabled(enabled ? TRUE : FALSE); + } + if ((mCtrlSculptMirror) && (mCtrlSculptMirror->get())) sculpt_type |= LL_SCULPT_FLAG_MIRROR; @@ -2543,7 +2545,7 @@ void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) // static void LLPanelObject::onClickBuildConstants(void *) { - LLNotifications::instance().add("ClickBuildConstants"); + LLNotificationsUtil::add("ClickBuildConstants"); } std::string shortfloat(F32 in) @@ -2637,9 +2639,9 @@ void LLPanelObject::onPastePos(void* user_data) LLPanelObject* self = (LLPanelObject*) user_data; LLCalc* calcp = LLCalc::getInstance(); - mClipboardPos.mV[VX] = llclamp( mClipboardPos.mV[VX], 0.f, 256.f); - mClipboardPos.mV[VY] = llclamp( mClipboardPos.mV[VY], 0.f, 256.f); - mClipboardPos.mV[VZ] = llclamp( mClipboardPos.mV[VZ], 0.f, 4096.f); + mClipboardPos.mV[VX] = llclamp( mClipboardPos.mV[VX], -3.5f, 256.f); + mClipboardPos.mV[VY] = llclamp( mClipboardPos.mV[VY], -3.5f, 256.f); + mClipboardPos.mV[VZ] = llclamp( mClipboardPos.mV[VZ], -3.5f, 4096.f); self->mCtrlPosX->set( mClipboardPos.mV[VX] ); self->mCtrlPosY->set( mClipboardPos.mV[VY] ); @@ -2716,9 +2718,9 @@ void LLPanelObject::onPastePosClip(void* user_data) std::string stringVec = wstring_to_utf8str(temp_string); if(!getvectorfromclip(stringVec, &mClipboardPos)) return; - mClipboardPos.mV[VX] = llclamp(mClipboardPos.mV[VX], 0.f, 256.f); - mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], 0.f, 256.f); - mClipboardPos.mV[VZ] = llclamp(mClipboardPos.mV[VZ], 0.f, 4096.f); + mClipboardPos.mV[VX] = llclamp(mClipboardPos.mV[VX], -3.5f, 256.f); + mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], -3.5f, 256.f); + mClipboardPos.mV[VZ] = llclamp(mClipboardPos.mV[VZ], -3.5f, 4096.f); self->mCtrlPosX->set( mClipboardPos.mV[VX] ); self->mCtrlPosY->set( mClipboardPos.mV[VY] ); diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index d1819733f..8e42927fd 100644 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -41,9 +41,11 @@ #include "llcategory.h" #include "llclickaction.h" #include "llfocusmgr.h" +#include "llnotificationsutil.h" #include "llstring.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llresmgr.h" #include "lltextbox.h" #include "llbutton.h" @@ -1193,7 +1195,7 @@ void LLPanelPermissions::onCommitClickAction(LLUICtrl* ctrl, void*) LLSelectMgr::getInstance()->selectGetSaleInfo(sale_info); if (!sale_info.isForSale()) { - LLNotifications::instance().add("CantSetBuyObject"); + LLNotificationsUtil::add("CantSetBuyObject"); // Set click action back to its old value U8 click_action = 0; @@ -1211,7 +1213,7 @@ void LLPanelPermissions::onCommitClickAction(LLUICtrl* ctrl, void*) if (!can_pay) { // Warn, but do it anyway. - LLNotifications::instance().add("ClickActionNotPayable"); + LLNotificationsUtil::add("ClickActionNotPayable"); } } LLSelectMgr::getInstance()->selectionSetClickAction(click_action); diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp index a33b3dd60..aece29b17 100644 --- a/indra/newview/llpanelpick.cpp +++ b/indra/newview/llpanelpick.cpp @@ -59,6 +59,7 @@ #include "llfloaterworldmap.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "llnotificationsutil.h" // [RLVa:KB] #include "rlvhandler.h" @@ -596,7 +597,7 @@ void LLPanelPick::onClickSet(void* data) // is the location and nothing else if ( gAgent.getRegion ()->getName () != self->mSimName ) { - LLNotifications::instance().add("SetPickLocation"); + LLNotificationsUtil::add("SetPickLocation"); }; self->mLocationEditor->setText(location_text); diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp index 35499f581..38b75572a 100644 --- a/indra/newview/llpanelplace.cpp +++ b/indra/newview/llpanelplace.cpp @@ -47,6 +47,7 @@ #include "llbutton.h" #include "llfloaterworldmap.h" #include "lllineeditor.h" +#include "llnotificationsutil.h" #include "lluiconstants.h" #include "lltextbox.h" #include "llviewertexteditor.h" @@ -460,7 +461,7 @@ void LLPanelPlace::onClickAuction(void* data) LLSD payload; payload["auction_id"] = self->mAuctionID; - LLNotifications::instance().add("GoToAuctionPage", LLSD(), payload, callbackAuctionWebPage); + LLNotificationsUtil::add("GoToAuctionPage", LLSD(), payload, callbackAuctionWebPage); } // static diff --git a/indra/newview/llpanelskins.cpp b/indra/newview/llpanelskins.cpp index 7be656031..828598c3d 100644 --- a/indra/newview/llpanelskins.cpp +++ b/indra/newview/llpanelskins.cpp @@ -39,6 +39,7 @@ #include "llbutton.h" #include "lluictrlfactory.h" #include "lldiriterator.h" +#include "llnotificationsutil.h" // project includes #include "llviewercontrol.h" @@ -147,7 +148,7 @@ void LLPanelSkins::apply() if (oldSkin != mSkin) { oldSkin=mSkin; - LLNotifications::instance().add("ChangeSkin"); + LLNotificationsUtil::add("ChangeSkin"); refresh(); } } diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp index 2d4dc3246..19322dfb4 100644 --- a/indra/newview/llpanelvolume.cpp +++ b/indra/newview/llpanelvolume.cpp @@ -78,6 +78,11 @@ #include "lldrawpool.h" #include "lluictrlfactory.h" #include "lltexturectrl.h" +#if MESH_ENABLED +// For mesh physics +#include "llviewercontrol.h" +#include "llmeshrepository.h" +#endif //MESH_ENABLED // "Features" Tab @@ -87,21 +92,21 @@ BOOL LLPanelVolume::postBuild() { childSetCommitCallback("Flexible1D Checkbox Ctrl",onCommitIsFlexible,this); childSetCommitCallback("FlexNumSections",onCommitFlexible,this); - childSetValidate("FlexNumSections",precommitValidate); + getChild<LLUICtrl>("FlexNumSections")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("FlexGravity",onCommitFlexible,this); - childSetValidate("FlexGravity",precommitValidate); + getChild<LLUICtrl>("FlexGravity")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("FlexFriction",onCommitFlexible,this); - childSetValidate("FlexFriction",precommitValidate); + getChild<LLUICtrl>("FlexFriction")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("FlexWind",onCommitFlexible,this); - childSetValidate("FlexWind",precommitValidate); + getChild<LLUICtrl>("FlexWind")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("FlexTension",onCommitFlexible,this); - childSetValidate("FlexTension",precommitValidate); + getChild<LLUICtrl>("FlexTension")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("FlexForceX",onCommitFlexible,this); - childSetValidate("FlexForceX",precommitValidate); + getChild<LLUICtrl>("FlexForceX")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("FlexForceY",onCommitFlexible,this); - childSetValidate("FlexForceY",precommitValidate); + getChild<LLUICtrl>("FlexForceY")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("FlexForceZ",onCommitFlexible,this); - childSetValidate("FlexForceZ",precommitValidate); + getChild<LLUICtrl>("FlexForceZ")->setValidateBeforeCommit(precommitValidate); } // LIGHT Parameters @@ -123,20 +128,47 @@ BOOL LLPanelVolume::postBuild() } childSetCommitCallback("Light Intensity",onCommitLight,this); - childSetValidate("Light Intensity",precommitValidate); + getChild<LLUICtrl>("Light Intensity")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("Light Radius",onCommitLight,this); - childSetValidate("Light Radius",precommitValidate); + getChild<LLUICtrl>("Light Radius")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("Light Falloff",onCommitLight,this); - childSetValidate("Light Falloff",precommitValidate); + getChild<LLUICtrl>("Light Falloff")->setValidateBeforeCommit(precommitValidate); childSetCommitCallback("Light FOV", onCommitLight, this); - childSetValidate("Light FOV", precommitValidate); + getChild<LLUICtrl>("Light FOV")->setValidateBeforeCommit( precommitValidate); childSetCommitCallback("Light Focus", onCommitLight, this); - childSetValidate("Light Focus", precommitValidate); + getChild<LLUICtrl>("Light Focus")->setValidateBeforeCommit( precommitValidate); childSetCommitCallback("Light Ambiance", onCommitLight, this); - childSetValidate("Light Ambiance", precommitValidate); + getChild<LLUICtrl>("Light Ambiance")->setValidateBeforeCommit( precommitValidate); } + +#if MESH_ENABLED + // PHYSICS Parameters + { + // Label + mComboPhysicsShapeLabel = getChild<LLTextBox>("label physicsshapetype"); + + // PhysicsShapeType combobox + mComboPhysicsShapeType = getChild<LLComboBox>("Physics Shape Type Combo Ctrl"); + mComboPhysicsShapeType->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsShapeType, this, _1, mComboPhysicsShapeType)); + // PhysicsGravity + mSpinPhysicsGravity = getChild<LLSpinCtrl>("Physics Gravity"); + mSpinPhysicsGravity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsGravity, this, _1, mSpinPhysicsGravity)); + + // PhysicsFriction + mSpinPhysicsFriction = getChild<LLSpinCtrl>("Physics Friction"); + mSpinPhysicsFriction->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsFriction, this, _1, mSpinPhysicsFriction)); + + // PhysicsDensity + mSpinPhysicsDensity = getChild<LLSpinCtrl>("Physics Density"); + mSpinPhysicsDensity->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsDensity, this, _1, mSpinPhysicsDensity)); + + // PhysicsRestitution + mSpinPhysicsRestitution = getChild<LLSpinCtrl>("Physics Restitution"); + mSpinPhysicsRestitution->setCommitCallback(boost::bind(&LLPanelVolume::sendPhysicsRestitution, this, _1, mSpinPhysicsRestitution)); + } +#endif //MESH_ENABLED // Start with everyone disabled clearCtrls(); @@ -212,25 +244,25 @@ void LLPanelVolume::getState( ) // Select Single Message if (single_volume) { - childSetVisible("edit_object",true); - childSetEnabled("edit_object",true); - childSetVisible("select_single",false); + getChildView("edit_object")->setVisible(true); + getChildView("edit_object")->setEnabled(true); + getChildView("select_single")->setVisible(false); } else { - childSetVisible("edit_object",false); - childSetVisible("select_single",true); - childSetEnabled("select_single",true); + getChildView("edit_object")->setVisible(false); + getChildView("select_single")->setVisible(true); + getChildView("select_single")->setEnabled(true); } // Light properties BOOL is_light = volobjp && volobjp->getIsLight(); - childSetValue("Light Checkbox Ctrl",is_light); - childSetEnabled("Light Checkbox Ctrl",editable && single_volume && volobjp); + getChild<LLUICtrl>("Light Checkbox Ctrl")->setValue(is_light); + getChildView("Light Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp); if (is_light && editable && single_volume) { - childSetEnabled("label color",true); + getChildView("label color")->setEnabled(true); //mLabelColor ->setEnabled( TRUE ); LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch"); if(LightColorSwatch) @@ -248,22 +280,23 @@ void LLPanelVolume::getState( ) LightTextureCtrl->setValid(TRUE); LightTextureCtrl->setImageAssetID(volobjp->getLightTextureID()); } - childSetEnabled("Light Intensity",true); - childSetEnabled("Light Radius",true); - childSetEnabled("Light Falloff",true); - childSetEnabled("Light FOV",true); - childSetEnabled("Light Focus",true); - childSetEnabled("Light Ambiance",true); + getChildView("Light Intensity")->setEnabled(true); + getChildView("Light Radius")->setEnabled(true); + getChildView("Light Falloff")->setEnabled(true); + + getChildView("Light FOV")->setEnabled(true); + getChildView("Light Focus")->setEnabled(true); + getChildView("Light Ambiance")->setEnabled(true); - childSetValue("Light Intensity",volobjp->getLightIntensity()); - childSetValue("Light Radius",volobjp->getLightRadius()); - childSetValue("Light Falloff",volobjp->getLightFalloff()); + getChild<LLUICtrl>("Light Intensity")->setValue(volobjp->getLightIntensity()); + getChild<LLUICtrl>("Light Radius")->setValue(volobjp->getLightRadius()); + getChild<LLUICtrl>("Light Falloff")->setValue(volobjp->getLightFalloff()); LLVector3 params = volobjp->getSpotLightParams(); - childSetValue("Light FOV",params.mV[0]); - childSetValue("Light Focus",params.mV[1]); - childSetValue("Light Ambiance",params.mV[2]); + getChild<LLUICtrl>("Light FOV")->setValue(params.mV[0]); + getChild<LLUICtrl>("Light Focus")->setValue(params.mV[1]); + getChild<LLUICtrl>("Light Ambiance")->setValue(params.mV[2]); mLightSavedColor = volobjp->getLightColor(); } @@ -273,7 +306,7 @@ void LLPanelVolume::getState( ) getChild<LLSpinCtrl>("Light Radius", true)->clear(); getChild<LLSpinCtrl>("Light Falloff", true)->clear(); - childSetEnabled("label color",false); + getChildView("label color")->setEnabled(false); LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch"); if(LightColorSwatch) { @@ -287,56 +320,61 @@ void LLPanelVolume::getState( ) LightTextureCtrl->setEnabled(FALSE); LightTextureCtrl->setValid(FALSE); } - childSetEnabled("Light Intensity",false); - childSetEnabled("Light Radius",false); - childSetEnabled("Light Falloff",false); - childSetEnabled("Light FOV",false); - childSetEnabled("Light Focus",false); - childSetEnabled("Light Ambiance",false); + getChildView("Light Intensity")->setEnabled(false); + getChildView("Light Radius")->setEnabled(false); + getChildView("Light Falloff")->setEnabled(false); + + getChildView("Light FOV")->setEnabled(false); + getChildView("Light Focus")->setEnabled(false); + getChildView("Light Ambiance")->setEnabled(false); } // Flexible properties BOOL is_flexible = volobjp && volobjp->isFlexible(); - childSetValue("Flexible1D Checkbox Ctrl",is_flexible); + getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->setValue(is_flexible); if (is_flexible || (volobjp && volobjp->canBeFlexible())) { - childSetEnabled("Flexible1D Checkbox Ctrl", editable && single_volume && volobjp); + getChildView("Flexible1D Checkbox Ctrl")->setEnabled(editable && single_volume && volobjp +#if MESH_ENABLED + && !volobjp->isMesh() +#endif //MESH_ENABLED + ); } else { - childSetEnabled("Flexible1D Checkbox Ctrl", false); + getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false); } if (is_flexible && editable && single_volume) { - childSetVisible("FlexNumSections",true); - childSetVisible("FlexGravity",true); - childSetVisible("FlexTension",true); - childSetVisible("FlexFriction",true); - childSetVisible("FlexWind",true); - childSetVisible("FlexForceX",true); - childSetVisible("FlexForceY",true); - childSetVisible("FlexForceZ",true); + getChildView("FlexNumSections")->setVisible(true); + getChildView("FlexGravity")->setVisible(true); + getChildView("FlexTension")->setVisible(true); + getChildView("FlexFriction")->setVisible(true); + getChildView("FlexWind")->setVisible(true); + getChildView("FlexForceX")->setVisible(true); + getChildView("FlexForceY")->setVisible(true); + getChildView("FlexForceZ")->setVisible(true); - childSetEnabled("FlexNumSections",true); - childSetEnabled("FlexGravity",true); - childSetEnabled("FlexTension",true); - childSetEnabled("FlexFriction",true); - childSetEnabled("FlexWind",true); - childSetEnabled("FlexForceX",true); - childSetEnabled("FlexForceY",true); - childSetEnabled("FlexForceZ",true); + getChildView("FlexNumSections")->setEnabled(true); + getChildView("FlexGravity")->setEnabled(true); + getChildView("FlexTension")->setEnabled(true); + getChildView("FlexFriction")->setEnabled(true); + getChildView("FlexWind")->setEnabled(true); + getChildView("FlexForceX")->setEnabled(true); + getChildView("FlexForceY")->setEnabled(true); + getChildView("FlexForceZ")->setEnabled(true); LLFlexibleObjectData *attributes = (LLFlexibleObjectData *)objectp->getParameterEntry(LLNetworkData::PARAMS_FLEXIBLE); - childSetValue("FlexNumSections",(F32)attributes->getSimulateLOD()); - childSetValue("FlexGravity",attributes->getGravity()); - childSetValue("FlexTension",attributes->getTension()); - childSetValue("FlexFriction",attributes->getAirFriction()); - childSetValue("FlexWind",attributes->getWindSensitivity()); - childSetValue("FlexForceX",attributes->getUserForce().mV[VX]); - childSetValue("FlexForceY",attributes->getUserForce().mV[VY]); - childSetValue("FlexForceZ",attributes->getUserForce().mV[VZ]); + getChild<LLUICtrl>("FlexNumSections")->setValue((F32)attributes->getSimulateLOD()); + getChild<LLUICtrl>("FlexGravity")->setValue(attributes->getGravity()); + getChild<LLUICtrl>("FlexTension")->setValue(attributes->getTension()); + getChild<LLUICtrl>("FlexFriction")->setValue(attributes->getAirFriction()); + getChild<LLUICtrl>("FlexWind")->setValue(attributes->getWindSensitivity()); + getChild<LLUICtrl>("FlexForceX")->setValue(attributes->getUserForce().mV[VX]); + getChild<LLUICtrl>("FlexForceY")->setValue(attributes->getUserForce().mV[VY]); + getChild<LLUICtrl>("FlexForceZ")->setValue(attributes->getUserForce().mV[VZ]); } else { @@ -349,22 +387,73 @@ void LLPanelVolume::getState( ) getChild<LLSpinCtrl>("FlexForceY", true)->clear(); getChild<LLSpinCtrl>("FlexForceZ", true)->clear(); - childSetEnabled("FlexNumSections",false); - childSetEnabled("FlexGravity",false); - childSetEnabled("FlexTension",false); - childSetEnabled("FlexFriction",false); - childSetEnabled("FlexWind",false); - childSetEnabled("FlexForceX",false); - childSetEnabled("FlexForceY",false); - childSetEnabled("FlexForceZ",false); + getChildView("FlexNumSections")->setEnabled(false); + getChildView("FlexGravity")->setEnabled(false); + getChildView("FlexTension")->setEnabled(false); + getChildView("FlexFriction")->setEnabled(false); + getChildView("FlexWind")->setEnabled(false); + getChildView("FlexForceX")->setEnabled(false); + getChildView("FlexForceY")->setEnabled(false); + getChildView("FlexForceZ")->setEnabled(false); } +#if MESH_ENABLED + // Physics properties + + mComboPhysicsShapeLabel->setEnabled(editable); + mSpinPhysicsGravity->set(objectp->getPhysicsGravity()); + mSpinPhysicsGravity->setEnabled(editable); + + mSpinPhysicsFriction->set(objectp->getPhysicsFriction()); + mSpinPhysicsFriction->setEnabled(editable); + + mSpinPhysicsDensity->set(objectp->getPhysicsDensity()); + mSpinPhysicsDensity->setEnabled(editable); + + mSpinPhysicsRestitution->set(objectp->getPhysicsRestitution()); + mSpinPhysicsRestitution->setEnabled(editable); + + // update the physics shape combo to include allowed physics shapes + mComboPhysicsShapeType->removeall(); + mComboPhysicsShapeType->add(getString("None"), LLSD(1)); + + BOOL isMesh = FALSE; + LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); + if (sculpt_params) + { + U8 sculpt_type = sculpt_params->getSculptType(); + U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; + isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH); + } + + if(isMesh && objectp) + { + const LLVolumeParams &volume_params = objectp->getVolume()->getParams(); + LLUUID mesh_id = volume_params.getSculptID(); + if(gMeshRepo.hasPhysicsShape(mesh_id)) + { + // if a mesh contains an uploaded or decomposed physics mesh, + // allow 'Prim' + mComboPhysicsShapeType->add(getString("Prim"), LLSD(0)); + } + } + else + { + // simple prims always allow physics shape prim + mComboPhysicsShapeType->add(getString("Prim"), LLSD(0)); + } + + mComboPhysicsShapeType->add(getString("Convex Hull"), LLSD(2)); + mComboPhysicsShapeType->setValue(LLSD(objectp->getPhysicsShapeType())); + mComboPhysicsShapeType->setEnabled(editable); +#endif //MESH_ENABLED + mObject = objectp; mRootObject = root_objectp; } // static -BOOL LLPanelVolume::precommitValidate( LLUICtrl* ctrl, void* userdata ) +BOOL LLPanelVolume::precommitValidate(LLUICtrl* ctrl,void* userdata) { // TODO: Richard will fill this in later. return TRUE; // FALSE means that validation failed and new value should not be commited. @@ -386,11 +475,32 @@ void LLPanelVolume::refresh() BOOL visible = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 0 ? TRUE : FALSE; - childSetVisible("label texture", visible); - childSetVisible("Light FOV", visible); - childSetVisible("Light Focus", visible); - childSetVisible("Light Ambiance", visible); - childSetVisible("light texture control", visible); + getChildView("label texture")->setVisible( visible); + getChildView("Light FOV")->setVisible( visible); + getChildView("Light Focus")->setVisible( visible); + getChildView("Light Ambiance")->setVisible( visible); + getChildView("light texture control")->setVisible( visible); + +#if MESH_ENABLED + bool enable_mesh = false; + + LLSD sim_features; + LLViewerRegion *region = gAgent.getRegion(); + if(region) + { + LLSD sim_features; + region->getSimulatorFeatures(sim_features); + enable_mesh = sim_features.has("PhysicsShapeTypes"); + } + getChildView("label physicsshapetype")->setVisible(enable_mesh); + getChildView("Physics Shape Type Combo Ctrl")->setVisible(enable_mesh); + getChildView("Physics Gravity")->setVisible(enable_mesh); + getChildView("Physics Friction")->setVisible(enable_mesh); + getChildView("Physics Density")->setVisible(enable_mesh); + getChildView("Physics Restitution")->setVisible(enable_mesh); + + /* TODO: add/remove individual physics shape types as per the PhysicsShapeTypes simulator features */ +#endif //MESH_ENABLED } @@ -404,12 +514,12 @@ void LLPanelVolume::clearCtrls() { LLPanel::clearCtrls(); - childSetEnabled("select_single",false); - childSetVisible("select_single",true); - childSetEnabled("edit_object",false); - childSetVisible("edit_object",false); - childSetEnabled("Light Checkbox Ctrl",false); - childSetEnabled("label color",false); + getChildView("select_single")->setEnabled(false); + getChildView("select_single")->setVisible(true); + getChildView("edit_object")->setEnabled(false); + getChildView("edit_object")->setVisible(false); + getChildView("Light Checkbox Ctrl")->setEnabled(false); + getChildView("label color")->setEnabled(false); LLColorSwatchCtrl* LightColorSwatch = getChild<LLColorSwatchCtrl>("colorswatch"); if(LightColorSwatch) { @@ -424,19 +534,26 @@ void LLPanelVolume::clearCtrls() LightTextureCtrl->setValid( FALSE ); } - childSetEnabled("Light Intensity",false); - childSetEnabled("Light Radius",false); - childSetEnabled("Light Falloff",false); + getChildView("Light Intensity")->setEnabled(false); + getChildView("Light Radius")->setEnabled(false); + getChildView("Light Falloff")->setEnabled(false); - childSetEnabled("Flexible1D Checkbox Ctrl",false); - childSetEnabled("FlexNumSections",false); - childSetEnabled("FlexGravity",false); - childSetEnabled("FlexTension",false); - childSetEnabled("FlexFriction",false); - childSetEnabled("FlexWind",false); - childSetEnabled("FlexForceX",false); - childSetEnabled("FlexForceY",false); - childSetEnabled("FlexForceZ",false); + getChildView("Flexible1D Checkbox Ctrl")->setEnabled(false); + getChildView("FlexNumSections")->setEnabled(false); + getChildView("FlexGravity")->setEnabled(false); + getChildView("FlexTension")->setEnabled(false); + getChildView("FlexFriction")->setEnabled(false); + getChildView("FlexWind")->setEnabled(false); + getChildView("FlexForceX")->setEnabled(false); + getChildView("FlexForceY")->setEnabled(false); + getChildView("FlexForceZ")->setEnabled(false); + +#if MESH_ENABLED + mSpinPhysicsGravity->setEnabled(FALSE); + mSpinPhysicsFriction->setEnabled(FALSE); + mSpinPhysicsDensity->setEnabled(FALSE); + mSpinPhysicsRestitution->setEnabled(FALSE); +#endif //MESH_ENABLED } // @@ -452,7 +569,7 @@ void LLPanelVolume::sendIsLight() } LLVOVolume *volobjp = (LLVOVolume *)objectp; - BOOL value = childGetValue("Light Checkbox Ctrl"); + BOOL value = getChild<LLUICtrl>("Light Checkbox Ctrl")->getValue(); volobjp->setIsLight(value); llinfos << "update light sent" << llendl; } @@ -466,7 +583,7 @@ void LLPanelVolume::sendIsFlexible() } LLVOVolume *volobjp = (LLVOVolume *)objectp; - BOOL is_flexible = childGetValue("Flexible1D Checkbox Ctrl"); + BOOL is_flexible = getChild<LLUICtrl>("Flexible1D Checkbox Ctrl")->getValue(); //BOOL is_flexible = mCheckFlexible1D->get(); if (is_flexible) @@ -489,6 +606,50 @@ void LLPanelVolume::sendIsFlexible() llinfos << "update flexible sent" << llendl; } +#if MESH_ENABLED +void LLPanelVolume::sendPhysicsShapeType(LLUICtrl* ctrl, void* userdata) +{ + U8 type = ctrl->getValue().asInteger(); + LLSelectMgr::getInstance()->selectionSetPhysicsType(type); + + refreshCost(); +} + +void LLPanelVolume::sendPhysicsGravity(LLUICtrl* ctrl, void* userdata) +{ + F32 val = ctrl->getValue().asReal(); + LLSelectMgr::getInstance()->selectionSetGravity(val); +} + +void LLPanelVolume::sendPhysicsFriction(LLUICtrl* ctrl, void* userdata) +{ + F32 val = ctrl->getValue().asReal(); + LLSelectMgr::getInstance()->selectionSetFriction(val); +} + +void LLPanelVolume::sendPhysicsRestitution(LLUICtrl* ctrl, void* userdata) +{ + F32 val = ctrl->getValue().asReal(); + LLSelectMgr::getInstance()->selectionSetRestitution(val); +} + +void LLPanelVolume::sendPhysicsDensity(LLUICtrl* ctrl, void* userdata) +{ + F32 val = ctrl->getValue().asReal(); + LLSelectMgr::getInstance()->selectionSetDensity(val); +} + +void LLPanelVolume::refreshCost() +{ + LLViewerObject* obj = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); + + if (obj) + { + obj->getObjectCost(); + } +} +#endif //MESH_ENABLED + void LLPanelVolume::onLightCancelColor(LLUICtrl* ctrl, void* userdata) { LLPanelVolume* self = (LLPanelVolume*) userdata; @@ -531,6 +692,7 @@ void LLPanelVolume::onLightSelectColor(LLUICtrl* ctrl, void* userdata) } } + void LLPanelVolume::onLightSelectTexture(LLUICtrl* ctrl, void* userdata) { LLPanelVolume* self = (LLPanelVolume*) userdata; @@ -550,6 +712,7 @@ void LLPanelVolume::onLightSelectTexture(LLUICtrl* ctrl, void* userdata) } } + // static void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) { @@ -562,9 +725,9 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata ) LLVOVolume *volobjp = (LLVOVolume *)objectp; - volobjp->setLightIntensity((F32)self->childGetValue("Light Intensity").asReal()); - volobjp->setLightRadius((F32)self->childGetValue("Light Radius").asReal()); - volobjp->setLightFalloff((F32)self->childGetValue("Light Falloff").asReal()); + volobjp->setLightIntensity((F32)self->getChild<LLUICtrl>("Light Intensity")->getValue().asReal()); + volobjp->setLightRadius((F32)self->getChild<LLUICtrl>("Light Radius")->getValue().asReal()); + volobjp->setLightFalloff((F32)self->getChild<LLUICtrl>("Light Falloff")->getValue().asReal()); LLColorSwatchCtrl* LightColorSwatch = self->getChild<LLColorSwatchCtrl>("colorswatch"); if(LightColorSwatch) @@ -632,14 +795,14 @@ void LLPanelVolume::onCommitFlexible( LLUICtrl* ctrl, void* userdata ) new_attributes = *attributes; - new_attributes.setSimulateLOD(self->childGetValue("FlexNumSections").asInteger());//(S32)self->mSpinSections->get()); - new_attributes.setGravity((F32)self->childGetValue("FlexGravity").asReal()); - new_attributes.setTension((F32)self->childGetValue("FlexTension").asReal()); - new_attributes.setAirFriction((F32)self->childGetValue("FlexFriction").asReal()); - new_attributes.setWindSensitivity((F32)self->childGetValue("FlexWind").asReal()); - F32 fx = (F32)self->childGetValue("FlexForceX").asReal(); - F32 fy = (F32)self->childGetValue("FlexForceY").asReal(); - F32 fz = (F32)self->childGetValue("FlexForceZ").asReal(); + new_attributes.setSimulateLOD(self->getChild<LLUICtrl>("FlexNumSections")->getValue().asInteger());//(S32)self->mSpinSections->get()); + new_attributes.setGravity((F32)self->getChild<LLUICtrl>("FlexGravity")->getValue().asReal()); + new_attributes.setTension((F32)self->getChild<LLUICtrl>("FlexTension")->getValue().asReal()); + new_attributes.setAirFriction((F32)self->getChild<LLUICtrl>("FlexFriction")->getValue().asReal()); + new_attributes.setWindSensitivity((F32)self->getChild<LLUICtrl>("FlexWind")->getValue().asReal()); + F32 fx = (F32)self->getChild<LLUICtrl>("FlexForceX")->getValue().asReal(); + F32 fy = (F32)self->getChild<LLUICtrl>("FlexForceY")->getValue().asReal(); + F32 fz = (F32)self->getChild<LLUICtrl>("FlexForceZ")->getValue().asReal(); LLVector3 force(fx,fy,fz); new_attributes.setUserForce(force); diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h index bd9803b90..9cb744db6 100644 --- a/indra/newview/llpanelvolume.h +++ b/indra/newview/llpanelvolume.h @@ -70,16 +70,31 @@ public: static void onCommitLight( LLUICtrl* ctrl, void* userdata); static void onCommitIsFlexible( LLUICtrl* ctrl, void* userdata); static void onCommitFlexible( LLUICtrl* ctrl, void* userdata); +#if MESH_ENABLED + static void onCommitPhysicsParam( LLUICtrl* ctrl, void* userdata); +#endif //MESH_ENABLED static void onLightCancelColor(LLUICtrl* ctrl, void* userdata); static void onLightSelectColor(LLUICtrl* ctrl, void* userdata); static void onLightCancelTexture(LLUICtrl* ctrl, void* userdata); static void onLightSelectTexture(LLUICtrl* ctrl, void* userdata); -protected: - void getState(); + protected: + void getState(); +#if MESH_ENABLED + void refreshCost(); +#endif //MESH_ENABLED + +protected: +#if MESH_ENABLED + void sendPhysicsShapeType(LLUICtrl* ctrl, void* userdata); + void sendPhysicsGravity(LLUICtrl* ctrl, void* userdata); + void sendPhysicsFriction(LLUICtrl* ctrl, void* userdata); + void sendPhysicsRestitution(LLUICtrl* ctrl, void* userdata); + void sendPhysicsDensity(LLUICtrl* ctrl, void* userdata); +#endif //MESH_ENABLED /* LLTextBox* mLabelSelectSingleMessage; // Light @@ -104,6 +119,14 @@ protected: LLUUID mLightSavedTexture; LLPointer<LLViewerObject> mObject; LLPointer<LLViewerObject> mRootObject; +#if MESH_ENABLED + LLTextBox* mComboPhysicsShapeLabel; + LLComboBox* mComboPhysicsShapeType; + LLSpinCtrl* mSpinPhysicsGravity; + LLSpinCtrl* mSpinPhysicsFriction; + LLSpinCtrl* mSpinPhysicsDensity; + LLSpinCtrl* mSpinPhysicsRestitution; +#endif //MESH_ENABLED }; #endif diff --git a/indra/newview/llpanelweb.cpp b/indra/newview/llpanelweb.cpp index 955c4b668..9f60ecda4 100644 --- a/indra/newview/llpanelweb.cpp +++ b/indra/newview/llpanelweb.cpp @@ -37,6 +37,7 @@ // project includes #include "llcheckboxctrl.h" +#include "llnotificationsutil.h" #include "lluictrlfactory.h" #include "llviewercontrol.h" #include "llviewermedia.h" @@ -116,7 +117,7 @@ void LLPanelWeb::cancel() // static void LLPanelWeb::onClickClearCache(void*) { - LLNotifications::instance().add("ConfirmClearBrowserCache", LLSD(), LLSD(), callback_clear_browser_cache); + LLNotificationsUtil::add("ConfirmClearBrowserCache", LLSD(), LLSD(), callback_clear_browser_cache); } //static @@ -135,7 +136,7 @@ bool LLPanelWeb::callback_clear_browser_cache(const LLSD& notification, const LL // static void LLPanelWeb::onClickClearCookies(void*) { - LLNotifications::instance().add("ConfirmClearCookies", LLSD(), LLSD(), callback_clear_cookies); + LLNotificationsUtil::add("ConfirmClearCookies", LLSD(), LLSD(), callback_clear_cookies); } //static diff --git a/indra/newview/llparcelselection.h b/indra/newview/llparcelselection.h index 5f26fafc3..0481bea6f 100644 --- a/indra/newview/llparcelselection.h +++ b/indra/newview/llparcelselection.h @@ -33,7 +33,8 @@ #ifndef LLPARCELSELECTION_H #define LLPARCELSELECTION_H -#include "llmemory.h" +#include "llrefcount.h" +#include "llsafehandle.h" class LLParcel; diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp index af775f59f..12e1408e0 100644 --- a/indra/newview/llphysicsmotion.cpp +++ b/indra/newview/llphysicsmotion.cpp @@ -756,7 +756,7 @@ BOOL LLPhysicsMotion::onUpdate(F32 time) const F32 area_for_max_settings = 0.0; const F32 area_for_min_settings = 1400.0; const F32 area_for_this_setting = area_for_max_settings + (area_for_min_settings-area_for_max_settings)*(1.0-lod_factor); - const F32 pixel_area = fsqrtf(mCharacter->getPixelArea()); + const F32 pixel_area = (F32) sqrt(mCharacter->getPixelArea()); const BOOL is_self = (dynamic_cast<LLVOAvatar *>(mCharacter) != NULL && ((LLVOAvatar*)mCharacter)->isSelf()); if ((pixel_area > area_for_this_setting) || is_self) diff --git a/indra/newview/llphysicsshapebuilderutil.cpp b/indra/newview/llphysicsshapebuilderutil.cpp new file mode 100644 index 000000000..5bfe5c994 --- /dev/null +++ b/indra/newview/llphysicsshapebuilderutil.cpp @@ -0,0 +1,210 @@ +/** + * @file llphysicsshapebuilder.cpp + * @brief Generic system to convert LL(Physics)VolumeParams to physics shapes + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llphysicsshapebuilderutil.h" + +/* static */ +void LLPhysicsShapeBuilderUtil::determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut ) +{ + const LLProfileParams& profile_params = volume_params.getProfileParams(); + const LLPathParams& path_params = volume_params.getPathParams(); + + specOut.mScale = scale; + + const F32 avgScale = ( scale[VX] + scale[VY] + scale[VZ] )/3.0f; + + // count the scale elements that are small + S32 min_size_counts = 0; + for (S32 i = 0; i < 3; ++i) + { + if (scale[i] < SHAPE_BUILDER_CONVEXIFICATION_SIZE) + { + ++min_size_counts; + } + } + + const bool profile_complete = ( profile_params.getBegin() <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale ) && + ( profile_params.getEnd() >= (1.0f - SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale) ); + + const bool path_complete = ( path_params.getBegin() <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale ) && + ( path_params.getEnd() >= (1.0f - SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale) ); + + const bool simple_params = ( volume_params.getHollow() <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_HOLLOW/avgScale ) + && ( fabs(path_params.getShearX()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_SHEAR/avgScale ) + && ( fabs(path_params.getShearY()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_SHEAR/avgScale ) + && ( !volume_params.isMeshSculpt() && !volume_params.isSculpt() ); + + if (simple_params && profile_complete) + { + // Try to create an implicit shape or convexified + bool no_taper = ( fabs(path_params.getScaleX() - 1.0f) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TAPER/avgScale ) + && ( fabs(path_params.getScaleY() - 1.0f) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TAPER/avgScale ); + + bool no_twist = ( fabs(path_params.getTwistBegin()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TWIST/avgScale ) + && ( fabs(path_params.getTwistEnd()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TWIST/avgScale); + + // Box + if( + ( profile_params.getCurveType() == LL_PCODE_PROFILE_SQUARE ) + && ( path_params.getCurveType() == LL_PCODE_PATH_LINE ) + && no_taper + && no_twist + ) + { + specOut.mType = PhysicsShapeSpecification::BOX; + if ( path_complete ) + { + return; + } + else + { + // Side lengths + specOut.mScale[VX] = llmax( scale[VX], SHAPE_BUILDER_MIN_GEOMETRY_SIZE ); + specOut.mScale[VY] = llmax( scale[VY], SHAPE_BUILDER_MIN_GEOMETRY_SIZE ); + specOut.mScale[VZ] = llmax( scale[VZ] * (path_params.getEnd() - path_params.getBegin()), SHAPE_BUILDER_MIN_GEOMETRY_SIZE ); + + specOut.mCenter.set( 0.f, 0.f, 0.5f * scale[VZ] * ( path_params.getEnd() + path_params.getBegin() - 1.0f ) ); + return; + } + } + + // Sphere + if( path_complete + && ( profile_params.getCurveType() == LL_PCODE_PROFILE_CIRCLE_HALF ) + && ( path_params.getCurveType() == LL_PCODE_PATH_CIRCLE ) + && ( fabs(volume_params.getTaper()) <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_TAPER/avgScale ) + && no_twist + ) + { + if ( ( scale[VX] == scale[VZ] ) + && ( scale[VY] == scale[VZ] ) ) + { + // perfect sphere + specOut.mType = PhysicsShapeSpecification::SPHERE; + specOut.mScale = scale; + return; + } + else if (min_size_counts > 1) + { + // small or narrow sphere -- we can boxify + for (S32 i=0; i<3; ++i) + { + if (specOut.mScale[i] < SHAPE_BUILDER_CONVEXIFICATION_SIZE) + { + // reduce each small dimension size to split the approximation errors + specOut.mScale[i] *= 0.75f; + } + } + specOut.mType = PhysicsShapeSpecification::BOX; + return; + } + } + + // Cylinder + if( (scale[VX] == scale[VY]) + && ( profile_params.getCurveType() == LL_PCODE_PROFILE_CIRCLE ) + && ( path_params.getCurveType() == LL_PCODE_PATH_LINE ) + && ( volume_params.getBeginS() <= SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale ) + && ( volume_params.getEndS() >= (1.0f - SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT/avgScale) ) + && no_taper + ) + { + if (min_size_counts > 1) + { + // small or narrow sphere -- we can boxify + for (S32 i=0; i<3; ++i) + { + if (specOut.mScale[i] < SHAPE_BUILDER_CONVEXIFICATION_SIZE) + { + // reduce each small dimension size to split the approximation errors + specOut.mScale[i] *= 0.75f; + } + } + + specOut.mType = PhysicsShapeSpecification::BOX; + } + else + { + specOut.mType = PhysicsShapeSpecification::CYLINDER; + F32 length = (volume_params.getPathParams().getEnd() - volume_params.getPathParams().getBegin()) * scale[VZ]; + + specOut.mScale[VY] = specOut.mScale[VX]; + specOut.mScale[VZ] = length; + // The minus one below fixes the fact that begin and end range from 0 to 1 not -1 to 1. + specOut.mCenter.set( 0.f, 0.f, 0.5f * (volume_params.getPathParams().getBegin() + volume_params.getPathParams().getEnd() - 1.f) * scale[VZ] ); + } + + return; + } + } + + if ( (min_size_counts == 3 ) + // Possible dead code here--who wants to take it out? + || (path_complete + && profile_complete + && ( path_params.getCurveType() == LL_PCODE_PATH_LINE ) + && (min_size_counts > 1 ) ) + ) + { + // it isn't simple but + // we might be able to convexify this shape if the path and profile are complete + // or the path is linear and both path and profile are complete --> we can boxify it + specOut.mType = PhysicsShapeSpecification::BOX; + specOut.mScale = scale; + return; + } + + // Special case for big, very thin objects - bump the small dimensions up to the COLLISION_TOLERANCE + if (min_size_counts == 1 // One dimension is small + && avgScale > 3.f) // ... but others are fairly large + { + for (S32 i = 0; i < 3; ++i) + { + specOut.mScale[i] = llmax( specOut.mScale[i], COLLISION_TOLERANCE ); + } + } + + if ( volume_params.shouldForceConvex() ) + { + specOut.mType = PhysicsShapeSpecification::USER_CONVEX; + } + // Make a simpler convex shape if we can. + else if (volume_params.isConvex() // is convex + || min_size_counts > 1 ) // two or more small dimensions + { + specOut.mType = PhysicsShapeSpecification::PRIM_CONVEX; + } + else if ( volume_params.isSculpt() ) // Is a sculpt of any kind (mesh or legacy) + { + specOut.mType = volume_params.isMeshSculpt() ? PhysicsShapeSpecification::USER_MESH : PhysicsShapeSpecification::SCULPT; + } + else // Resort to mesh + { + specOut.mType = PhysicsShapeSpecification::PRIM_MESH; + } +} diff --git a/indra/newview/llphysicsshapebuilderutil.h b/indra/newview/llphysicsshapebuilderutil.h new file mode 100644 index 000000000..7dedfb05e --- /dev/null +++ b/indra/newview/llphysicsshapebuilderutil.h @@ -0,0 +1,138 @@ +/** + * @file llphysicsshapebuilder.h + * @brief Generic system to convert LL(Physics)VolumeParams to physics shapes + * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_PHYSICS_SHAPE_BUILDER_H +#define LL_PHYSICS_SHAPE_BUILDER_H + +#include "indra_constants.h" +#include "llvolume.h" + +#define USE_SHAPE_QUANTIZATION 0 + +#define SHAPE_BUILDER_DEFAULT_VOLUME_DETAIL 1 + +#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_HOLLOW 0.10f +#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_HOLLOW_SPHERES 0.90f +#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_PATH_CUT 0.05f +#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_TAPER 0.05f +#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_TWIST 0.09f +#define SHAPE_BUILDER_IMPLICIT_THRESHOLD_SHEAR 0.05f + +const F32 SHAPE_BUILDER_ENTRY_SNAP_SCALE_BIN_SIZE = 0.15f; +const F32 SHAPE_BUILDER_ENTRY_SNAP_PARAMETER_BIN_SIZE = 0.010f; +const F32 SHAPE_BUILDER_CONVEXIFICATION_SIZE = 2.f * COLLISION_TOLERANCE; +const F32 SHAPE_BUILDER_MIN_GEOMETRY_SIZE = 0.5f * COLLISION_TOLERANCE; + +class LLPhysicsVolumeParams : public LLVolumeParams +{ +public: + + LLPhysicsVolumeParams( const LLVolumeParams& params, bool forceConvex ) : + LLVolumeParams( params ), + mForceConvex(forceConvex) {} + + bool operator==(const LLPhysicsVolumeParams ¶ms) const + { + return ( LLVolumeParams::operator==(params) && (mForceConvex == params.mForceConvex) ); + } + + bool operator!=(const LLPhysicsVolumeParams ¶ms) const + { + return !operator==(params); + } + + bool operator<(const LLPhysicsVolumeParams ¶ms) const + { + if ( LLVolumeParams::operator!=(params) ) + { + return LLVolumeParams::operator<(params); + } + return (params.mForceConvex == false) && (mForceConvex == true); + } + + bool shouldForceConvex() const { return mForceConvex; } + +private: + bool mForceConvex; +}; + + +class LLPhysicsShapeBuilderUtil +{ +public: + + class PhysicsShapeSpecification + { + public: + enum ShapeType + { + // Primitive types + BOX, + SPHERE, + CYLINDER, + + USER_CONVEX, // User specified they wanted the convex hull of the volume + + PRIM_CONVEX, // Either a volume that is inherently convex but not a primitive type, or a shape + // with dimensions such that will convexify it anyway. + + SCULPT, // Special case for traditional sculpts--they are the convex hull of a single particular set of volume params + + USER_MESH, // A user mesh. May or may not contain a convex decomposition. + + PRIM_MESH, // A non-convex volume which we have to represent accurately + + INVALID + }; + + PhysicsShapeSpecification() : + mType( INVALID ), + mScale( 0.f, 0.f, 0.f ), + mCenter( 0.f, 0.f, 0.f ) {} + + bool isConvex() { return (mType != USER_MESH && mType != PRIM_MESH && mType != INVALID); } + bool isMesh() { return (mType == USER_MESH) || (mType == PRIM_MESH); } + + ShapeType getType() { return mType; } + const LLVector3& getScale() { return mScale; } + const LLVector3& getCenter() { return mCenter; } + + private: + friend class LLPhysicsShapeBuilderUtil; + + ShapeType mType; + + // Dimensions of an AABB around the shape + LLVector3 mScale; + + // Offset of shape from origin of primitive's reference frame + LLVector3 mCenter; + }; + + static void determinePhysicsShape( const LLPhysicsVolumeParams& volume_params, const LLVector3& scale, PhysicsShapeSpecification& specOut ); +}; + +#endif //LL_PHYSICS_SHAPE_BUILDER_H diff --git a/indra/newview/llpolymesh.cpp b/indra/newview/llpolymesh.cpp index 3a82e7304..180c3dd2e 100644 --- a/indra/newview/llpolymesh.cpp +++ b/indra/newview/llpolymesh.cpp @@ -769,29 +769,23 @@ LLPolyMesh::LLPolyMesh(LLPolyMeshSharedData *shared_data, LLPolyMesh *reference_ } else { -#if 1 // Allocate memory without initializing every vector + // Allocate memory without initializing every vector // NOTE: This makes asusmptions about the size of LLVector[234] int nverts = mSharedData->mNumVertices; - int nfloats = nverts * (3*5 + 2 + 4); - mVertexData = new F32[nfloats]; + int nfloats = nverts * (2*4 + 3*3 + 2 + 4); + //use 16 byte aligned vertex data to make LLPolyMesh SSE friendly + mVertexData = (F32*) ll_aligned_malloc_16(nfloats*4); int offset = 0; - mCoords = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mScaledNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; + mCoords = (LLVector4*)(mVertexData + offset); offset += 4*nverts; + mNormals = (LLVector4*)(mVertexData + offset); offset += 4*nverts; + mClothingWeights = (LLVector4*)(mVertexData + offset); offset += 4*nverts; + mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; + + // these members don't need to be 16-byte aligned, but the first one might be + // read during an aligned memcpy of mTexCoords + mScaledNormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; + mBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; mScaledBinormals = (LLVector3*)(mVertexData + offset); offset += 3*nverts; - mTexCoords = (LLVector2*)(mVertexData + offset); offset += 2*nverts; - mClothingWeights = (LLVector4*)(mVertexData + offset); offset += 4*nverts; -#else - mCoords = new LLVector3[mSharedData->mNumVertices]; - mNormals = new LLVector3[mSharedData->mNumVertices]; - mScaledNormals = new LLVector3[mSharedData->mNumVertices]; - mBinormals = new LLVector3[mSharedData->mNumVertices]; - mScaledBinormals = new LLVector3[mSharedData->mNumVertices]; - mTexCoords = new LLVector2[mSharedData->mNumVertices]; - mClothingWeights = new LLVector4[mSharedData->mNumVertices]; - memset(mClothingWeights, 0, sizeof(LLVector4) * mSharedData->mNumVertices); -#endif initializeForMorph(); } } @@ -806,19 +800,11 @@ LLPolyMesh::~LLPolyMesh() for (i = 0; i < mJointRenderData.count(); i++) { delete mJointRenderData[i]; - mJointRenderData[i] = NULL; - } -#if 0 // These are now allocated as one big uninitialized chunk - delete [] mCoords; - delete [] mNormals; - delete [] mScaledNormals; - delete [] mBinormals; - delete [] mScaledBinormals; - delete [] mClothingWeights; - delete [] mTexCoords; -#else - delete [] mVertexData; -#endif + mJointRenderData[i] = NULL; + } + + ll_aligned_free_16(mVertexData); + } @@ -1242,7 +1228,7 @@ BOOL LLPolyMesh::saveOBJ(LLFILE *fp) int nfaces = mSharedData->mNumFaces; int i; - LLVector3* coords = getWritableCoords(); + LLVector4* coords = getWritableCoords(); for ( i=0; i<nverts; i++) { std::string outstring = llformat("v %f %f %f\n", coords[i][0], @@ -1254,7 +1240,7 @@ BOOL LLPolyMesh::saveOBJ(LLFILE *fp) } } - LLVector3* normals = getWritableNormals(); + LLVector4* normals = getWritableNormals(); for ( i=0; i<nverts; i++) { std::string outstring = llformat("vn %f %f %f\n", normals[i][0], @@ -1311,8 +1297,8 @@ BOOL LLPolyMesh::loadOBJ(LLFILE *fp) int nnormals = 0; int ntexcoords = 0; - LLVector3* coords = getWritableCoords(); - LLVector3* normals = getWritableNormals(); + LLVector4* coords = getWritableCoords(); + LLVector4* normals = getWritableNormals(); LLVector3* binormals = getWritableBinormals(); LLVector2* tex = getWritableTexCoords(); LLPolyFace* faces = getFaces(); @@ -1426,20 +1412,24 @@ BOOL LLPolyMesh::loadOBJ(LLFILE *fp) S32 f1 = faces[f][1]; S32 f2 = faces[f][2]; - LLVector3& v0 = coords[f0]; - LLVector3& v1 = coords[f1]; - LLVector3& v2 = coords[f2]; - + LLVector4a v0; + LLVector4a v1; + LLVector4a v2; + v0.load3(coords[f0].mV);; + v1.load3(coords[f1].mV);; + v2.load3(coords[f2].mV);; LLVector2& t0 = tex[f0]; LLVector2& t1 = tex[f1]; LLVector2& t2 = tex[f2]; - LLVector3 binorm = calc_binormal_from_triangle(v0, t0, v1, t1, v2, t2); - binorm.normVec(); + LLVector4a binorm; + calc_binormal_from_triangle(binorm, v0, t0, v1, t1, v2, t2); + binorm.normalize3fast(); - binormals[f0] += binorm; - binormals[f1] += binorm; - binormals[f2] += binorm; + LLVector3 binormdelta(binorm.getF32ptr()); + binormals[f0] += binormdelta; + binormals[f1] += binormdelta; + binormals[f2] += binormdelta; } for ( v=0; v<nverts; v++) @@ -1463,8 +1453,8 @@ BOOL LLPolyMesh::setSharedFromCurrent() LLPolyMesh delta(mSharedData, NULL); U32 nverts = delta.getNumVertices(); - LLVector3 *delta_coords = delta.getWritableCoords(); - LLVector3 *delta_normals = delta.getWritableNormals(); + LLVector4 *delta_coords = delta.getWritableCoords(); + LLVector4 *delta_normals = delta.getWritableNormals(); LLVector3 *delta_binormals = delta.getWritableBinormals(); LLVector2 *delta_tex_coords = delta.getWritableTexCoords(); @@ -1493,8 +1483,8 @@ BOOL LLPolyMesh::setSharedFromCurrent() LLPolyMesh* mesh = avatarp->getMesh(mSharedData); if (mesh) { - LLVector3 *mesh_coords = mesh->getWritableCoords(); - LLVector3 *mesh_normals = mesh->getWritableNormals(); + LLVector4 *mesh_coords = mesh->getWritableCoords(); + LLVector4 *mesh_normals = mesh->getWritableNormals(); LLVector3 *mesh_binormals = mesh->getWritableBinormals(); LLVector2 *mesh_tex_coords = mesh->getWritableTexCoords(); LLVector3 *mesh_scaled_normals = mesh->getScaledNormals(); @@ -1505,10 +1495,10 @@ BOOL LLPolyMesh::setSharedFromCurrent() mesh_coords[vert_index] -= delta_coords[vert_index]; mesh_tex_coords[vert_index] -= delta_tex_coords[vert_index]; - mesh_scaled_normals[vert_index] -= delta_normals[vert_index]; + mesh_scaled_normals[vert_index] -= LLVector3(delta_normals[vert_index]); LLVector3 normalized_normal = mesh_scaled_normals[vert_index]; normalized_normal.normVec(); - mesh_normals[vert_index] = normalized_normal; + mesh_normals[vert_index] = LLVector4(normalized_normal); mesh_scaled_binormals[vert_index] -= delta_binormals[vert_index]; LLVector3 tangent = mesh_scaled_binormals[vert_index] % normalized_normal; @@ -1612,7 +1602,7 @@ void LLPolyMesh::dumpDiagInfo(void*) //----------------------------------------------------------------------------- // getWritableCoords() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getWritableCoords() +LLVector4 *LLPolyMesh::getWritableCoords() { return mCoords; } @@ -1620,7 +1610,7 @@ LLVector3 *LLPolyMesh::getWritableCoords() //----------------------------------------------------------------------------- // getWritableNormals() //----------------------------------------------------------------------------- -LLVector3 *LLPolyMesh::getWritableNormals() +LLVector4 *LLPolyMesh::getWritableNormals() { return mNormals; } @@ -1675,8 +1665,12 @@ void LLPolyMesh::initializeForMorph() if (!mSharedData) return; - memcpy(mCoords, mSharedData->mBaseCoords, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ - memcpy(mNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ + for (U32 i = 0; i < (U32)mSharedData->mNumVertices; ++i) + { + mCoords[i] = LLVector4(mSharedData->mBaseCoords[i]); + mNormals[i] = LLVector4(mSharedData->mBaseNormals[i]); + } + memcpy(mScaledNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ memcpy(mBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ memcpy(mScaledBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ diff --git a/indra/newview/llpolymesh.h b/indra/newview/llpolymesh.h index 15c284a1a..a91d88c71 100644 --- a/indra/newview/llpolymesh.h +++ b/indra/newview/llpolymesh.h @@ -240,15 +240,15 @@ public: } // Get coords - const LLVector3 *getCoords() const{ + const LLVector4 *getCoords() const{ return mCoords; } // non const version - LLVector3 *getWritableCoords(); + LLVector4 *getWritableCoords(); // Get normals - const LLVector3 *getNormals() const{ + const LLVector4 *getNormals() const{ return mNormals; } @@ -270,7 +270,7 @@ public: } // intermediate morphed normals and output normals - LLVector3 *getWritableNormals(); + LLVector4 *getWritableNormals(); LLVector3 *getScaledNormals(); LLVector3 *getWritableBinormals(); @@ -368,11 +368,11 @@ protected: // Single array of floats for allocation / deletion F32 *mVertexData; // deformed vertices (resulting from application of morph targets) - LLVector3 *mCoords; + LLVector4 *mCoords; // deformed normals (resulting from application of morph targets) LLVector3 *mScaledNormals; // output normals (after normalization) - LLVector3 *mNormals; + LLVector4 *mNormals; // deformed binormals (resulting from application of morph targets) LLVector3 *mScaledBinormals; // output binormals (after normalization) diff --git a/indra/newview/llpolymorph.cpp b/indra/newview/llpolymorph.cpp index 4cf59a209..9b2a7b4a5 100644 --- a/indra/newview/llpolymorph.cpp +++ b/indra/newview/llpolymorph.cpp @@ -282,16 +282,16 @@ BOOL LLPolyMorphData::saveOBJ(LLFILE *fp) LLPolyMesh mesh(mMesh, NULL); - LLVector3 *coords = mesh.getWritableCoords(); - LLVector3 *normals = mesh.getWritableNormals(); + LLVector4 *coords = mesh.getWritableCoords(); + LLVector4 *normals = mesh.getWritableNormals(); LLVector2 *tex_coords = mesh.getWritableTexCoords(); for(U32 vert_index_morph = 0; vert_index_morph < mNumIndices; vert_index_morph++) { S32 vert_index_mesh = mVertexIndices[vert_index_morph]; - coords[vert_index_mesh] += mCoords[vert_index_morph]; - normals[vert_index_mesh] += mNormals[vert_index_morph]; + coords[vert_index_mesh] += LLVector4(mCoords[vert_index_morph]); + normals[vert_index_mesh] += LLVector4(mNormals[vert_index_morph]); normals[vert_index_mesh].normVec(); tex_coords[vert_index_mesh] += mTexCoords[vert_index_morph]; } @@ -307,8 +307,8 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) if (!morph) return FALSE; - LLVector3 *morph_coords = morph->getWritableCoords(); - LLVector3 *morph_normals = morph->getWritableNormals(); + LLVector4 *morph_coords = morph->getWritableCoords(); + LLVector4 *morph_normals = morph->getWritableNormals(); LLVector3 *morph_binormals = morph->getWritableBinormals(); LLVector2 *morph_tex_coords = morph->getWritableTexCoords(); @@ -318,8 +318,8 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) LLPolyMesh delta(mMesh, NULL); U32 nverts = delta.getNumVertices(); - LLVector3 *delta_coords = delta.getWritableCoords(); - LLVector3 *delta_normals = delta.getWritableNormals(); + LLVector4 *delta_coords = delta.getWritableCoords(); + LLVector4 *delta_normals = delta.getWritableNormals(); LLVector3 *delta_binormals = delta.getWritableBinormals(); LLVector2 *delta_tex_coords = delta.getWritableTexCoords(); @@ -380,8 +380,8 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) { new_vertex_indices[morph_index] = vert_index; - new_coords[morph_index] = delta_coords[vert_index]; - new_normals[morph_index] = delta_normals[vert_index]; + new_coords[morph_index] = LLVector3(delta_coords[vert_index]); + new_normals[morph_index] = LLVector3(delta_normals[vert_index]); new_binormals[morph_index] = delta_binormals[vert_index]; new_tex_coords[morph_index] = delta_tex_coords[vert_index]; @@ -417,8 +417,8 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) { vert_index = mVertexIndices[morph_index]; - delta_coords[vert_index] -= mCoords[morph_index]; - delta_normals[vert_index] -= mNormals[morph_index]; + delta_coords[vert_index] -= LLVector4(mCoords[morph_index]); + delta_normals[vert_index] -= LLVector4(mNormals[morph_index]); delta_binormals[vert_index] -= mBinormals[morph_index]; delta_tex_coords[vert_index] -= mTexCoords[morph_index]; } @@ -456,8 +456,8 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) continue; } - LLVector3 *mesh_coords = mesh->getWritableCoords(); - LLVector3 *mesh_normals = mesh->getWritableNormals(); + LLVector4 *mesh_coords = mesh->getWritableCoords(); + LLVector4 *mesh_normals = mesh->getWritableNormals(); LLVector3 *mesh_binormals = mesh->getWritableBinormals(); LLVector2 *mesh_tex_coords = mesh->getWritableTexCoords(); LLVector3 *mesh_scaled_normals = mesh->getScaledNormals(); @@ -468,10 +468,10 @@ BOOL LLPolyMorphData::setMorphFromMesh(LLPolyMesh *morph) mesh_coords[vert_index] += delta_coords[vert_index] * weight; mesh_tex_coords[vert_index] += delta_tex_coords[vert_index] * weight; - mesh_scaled_normals[vert_index] += delta_normals[vert_index] * weight * NORMAL_SOFTEN_FACTOR; + mesh_scaled_normals[vert_index] += LLVector3(delta_normals[vert_index] * weight * NORMAL_SOFTEN_FACTOR); LLVector3 normalized_normal = mesh_scaled_normals[vert_index]; normalized_normal.normVec(); - mesh_normals[vert_index] = normalized_normal; + mesh_normals[vert_index] = LLVector4(normalized_normal); mesh_scaled_binormals[vert_index] += delta_binormals[vert_index] * weight * NORMAL_SOFTEN_FACTOR; LLVector3 tangent = mesh_scaled_binormals[vert_index] % normalized_normal; @@ -797,10 +797,10 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) if (delta_weight != 0.f) { llassert(!mMesh->isLOD()); - LLVector3 *coords = mMesh->getWritableCoords(); + LLVector4 *coords = mMesh->getWritableCoords(); LLVector3 *scaled_normals = mMesh->getScaledNormals(); - LLVector3 *normals = mMesh->getWritableNormals(); + LLVector4 *normals = mMesh->getWritableNormals(); LLVector3 *scaled_binormals = mMesh->getScaledBinormals(); LLVector3 *binormals = mMesh->getWritableBinormals(); @@ -820,7 +820,8 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) maskWeight = maskWeightArray[vert_index_morph]; } - coords[vert_index_mesh] += mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight; + coords[vert_index_mesh] += LLVector4(mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight); + if (getInfo()->mIsClothingMorph && clothing_weights) { LLVector3 clothing_offset = mMorphData->mCoords[vert_index_morph] * delta_weight * maskWeight; @@ -835,7 +836,7 @@ void LLPolyMorphTarget::apply( ESex avatar_sex ) scaled_normals[vert_index_mesh] += mMorphData->mNormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR; LLVector3 normalized_normal = scaled_normals[vert_index_mesh]; normalized_normal.normVec(); - normals[vert_index_mesh] = normalized_normal; + normals[vert_index_mesh] = LLVector4(normalized_normal); // calculate new binormals scaled_binormals[vert_index_mesh] += mMorphData->mBinormals[vert_index_morph] * delta_weight * maskWeight * NORMAL_SOFTEN_FACTOR; @@ -906,31 +907,31 @@ BOOL LLPolyMorphTarget::undoMask(BOOL delete_mask) F32 *mask_weights = mVertMask->getMorphMaskWeights(); - LLVector3 *coords = mMesh->getWritableCoords(); + LLVector4 *coords = mMesh->getWritableCoords(); LLVector3 *scaled_normals = mMesh->getScaledNormals(); LLVector3 *scaled_binormals = mMesh->getScaledBinormals(); LLVector2 *tex_coords = mMesh->getWritableTexCoords(); for(U32 vert = 0; vert < mMorphData->mNumIndices; vert++) { - F32 mask_weight = 1.f; - if (mask_weights) - { - mask_weight = mask_weights[vert]; - } + F32 mask_weight = 1.f; + if (mask_weights) + { + mask_weight = mask_weights[vert]; + } - F32 last_mask_weight = mLastWeight * mask_weight; + F32 lastMaskWeight = mLastWeight * mask_weights[vert]; S32 out_vert = mMorphData->mVertexIndices[vert]; // remove effect of existing masked morph - coords[out_vert] -= mMorphData->mCoords[vert] * last_mask_weight; - scaled_normals[out_vert] -= mMorphData->mNormals[vert] * last_mask_weight * NORMAL_SOFTEN_FACTOR; - scaled_binormals[out_vert] -= mMorphData->mBinormals[vert] * last_mask_weight * NORMAL_SOFTEN_FACTOR; - tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * last_mask_weight; + coords[out_vert] -= LLVector4(mMorphData->mCoords[vert]) * lastMaskWeight; + scaled_normals[out_vert] -= mMorphData->mNormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; + scaled_binormals[out_vert] -= mMorphData->mBinormals[vert] * lastMaskWeight * NORMAL_SOFTEN_FACTOR; + tex_coords[out_vert] -= mMorphData->mTexCoords[vert] * lastMaskWeight; if (clothing_weights) { - LLVector3 clothing_offset = mMorphData->mCoords[vert] * last_mask_weight; + LLVector3 clothing_offset = mMorphData->mCoords[vert] * lastMaskWeight; LLVector4* clothing_weight = &clothing_weights[out_vert]; clothing_weight->mV[VX] -= clothing_offset.mV[VX]; clothing_weight->mV[VY] -= clothing_offset.mV[VY]; diff --git a/indra/newview/llpreview.cpp b/indra/newview/llpreview.cpp index ba1508f62..63742e917 100644 --- a/indra/newview/llpreview.cpp +++ b/indra/newview/llpreview.cpp @@ -36,6 +36,7 @@ #include "llpreview.h" #include "lllineeditor.h" #include "llinventory.h" +#include "llinventorydefines.h" #include "llinventorymodel.h" #include "llresmgr.h" #include "lltextbox.h" diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp index 845129a38..6963f6a84 100644 --- a/indra/newview/llpreviewanim.cpp +++ b/indra/newview/llpreviewanim.cpp @@ -400,7 +400,7 @@ void LLPreviewAnim::gotAssetForSave(LLVFS *vfs, // static void LLPreviewAnim::gotAssetForSave_continued(char* buffer, S32 size, AIFilePicker* filepicker) { - if (!filepicker->hasFilename()) + if (filepicker->hasFilename()) { std::string filename = filepicker->getFilename(); std::ofstream export_file(filename.c_str(), std::ofstream::binary); diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index 9dba4df0b..1cd3b5162 100644 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -39,6 +39,7 @@ // libraries #include "lldatapacker.h" #include "lldarray.h" +#include "llinventorydefines.h" #include "llstring.h" #include "lldir.h" #include "llmultigesture.h" @@ -57,7 +58,7 @@ #include "llinventorymodel.h" #include "llkeyboard.h" #include "lllineeditor.h" -#include "llnotify.h" +#include "llnotificationsutil.h" #include "llradiogroup.h" #include "llscrolllistctrl.h" #include "lltextbox.h" @@ -286,7 +287,7 @@ BOOL LLPreviewGesture::canClose() else { // Bring up view-modal dialog: Save changes? Yes, No, Cancel - LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(), + LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLPreviewGesture::handleSaveChangesDialog, this, _1, _2) ); return FALSE; } @@ -295,7 +296,7 @@ BOOL LLPreviewGesture::canClose() // virtual void LLPreviewGesture::onClose(bool app_quitting) { - gGestureManager.stopGesture(mPreviewGesture); + LLGestureMgr::instance().stopGesture(mPreviewGesture); LLPreview::onClose(app_quitting); } @@ -327,13 +328,13 @@ bool LLPreviewGesture::handleSaveChangesDialog(const LLSD& notification, const L switch(option) { case 0: // "Yes" - gGestureManager.stopGesture(mPreviewGesture); + LLGestureMgr::instance().stopGesture(mPreviewGesture); mCloseAfterSave = TRUE; onClickSave(this); break; case 1: // "No" - gGestureManager.stopGesture(mPreviewGesture); + LLGestureMgr::instance().stopGesture(mPreviewGesture); mDirty = FALSE; // Force the dirty flag because user has clicked NO on confirm save dialog... close(); break; @@ -840,7 +841,7 @@ void LLPreviewGesture::refresh() mOptionsText->setText(optionstext); - BOOL active = gGestureManager.isGestureActive(mItemUUID); + BOOL active = LLGestureMgr::instance().isGestureActive(mItemUUID); mActiveCheck->set(active); // Can only preview if there are steps @@ -1126,14 +1127,14 @@ void LLPreviewGesture::saveIfNeeded() if(0) // </edit> { - LLNotifications::instance().add("GestureSaveFailedTooManySteps"); + LLNotificationsUtil::add("GestureSaveFailedTooManySteps"); delete gesture; gesture = NULL; } else if (!ok) { - LLNotifications::instance().add("GestureSaveFailedTryAgain"); + LLNotificationsUtil::add("GestureSaveFailedTryAgain"); delete gesture; gesture = NULL; } @@ -1194,10 +1195,10 @@ void LLPreviewGesture::saveIfNeeded() // If this gesture is active, then we need to update the in-memory // active map with the new pointer. - if (!delayedUpload && gGestureManager.isGestureActive(mItemUUID)) + if (!delayedUpload && LLGestureMgr::instance().isGestureActive(mItemUUID)) { // gesture manager now owns the pointer - gGestureManager.replaceGesture(mItemUUID, gesture, asset_id); + LLGestureMgr::instance().replaceGesture(mItemUUID, gesture, asset_id); // replaceGesture may deactivate other gestures so let the // inventory know. @@ -1272,7 +1273,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, } else { - LLNotifications::instance().add("GestureSaveFailedObjectNotFound"); + LLNotificationsUtil::add("GestureSaveFailedObjectNotFound"); } } @@ -1288,7 +1289,7 @@ void LLPreviewGesture::onSaveComplete(const LLUUID& asset_uuid, void* user_data, llwarns << "Problem saving gesture: " << status << llendl; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("GestureSaveFailedReason", args); + LLNotificationsUtil::add("GestureSaveFailedReason", args); } delete info; info = NULL; @@ -1720,13 +1721,13 @@ void LLPreviewGesture::onClickDelete(void* data) void LLPreviewGesture::onCommitActive(LLUICtrl* ctrl, void* data) { LLPreviewGesture* self = (LLPreviewGesture*)data; - if (!gGestureManager.isGestureActive(self->mItemUUID)) + if (!LLGestureMgr::instance().isGestureActive(self->mItemUUID)) { - gGestureManager.activateGesture(self->mItemUUID); + LLGestureMgr::instance().activateGesture(self->mItemUUID); } else { - gGestureManager.deactivateGesture(self->mItemUUID); + LLGestureMgr::instance().deactivateGesture(self->mItemUUID); } // Make sure the (active) label in the inventory gets updated. @@ -1765,14 +1766,14 @@ void LLPreviewGesture::onClickPreview(void* data) self->mPreviewBtn->setLabel(self->getString("stop_txt")); // play it, and delete when done - gGestureManager.playGesture(self->mPreviewGesture); + LLGestureMgr::instance().playGesture(self->mPreviewGesture); self->refresh(); } else { // Will call onDonePreview() below - gGestureManager.stopGesture(self->mPreviewGesture); + LLGestureMgr::instance().stopGesture(self->mPreviewGesture); self->refresh(); } diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 642a75a91..98ed9a409 100644 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -35,6 +35,7 @@ #include "llpreviewnotecard.h" #include "llinventory.h" +#include "llinventorydefines.h" #include "llagent.h" #include "llagentcamera.h" @@ -43,7 +44,7 @@ #include "llbutton.h" #include "llinventorymodel.h" #include "lllineeditor.h" -#include "llnotify.h" +#include "llnotificationsutil.h" #include "llresmgr.h" #include "roles_constants.h" #include "llscrollbar.h" @@ -237,7 +238,7 @@ BOOL LLPreviewNotecard::canClose() else { // Bring up view-modal dialog: Save changes? Yes, No, Cancel - LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleSaveChangesDialog,this, _1, _2)); + LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleSaveChangesDialog,this, _1, _2)); return FALSE; } @@ -412,15 +413,15 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs, if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { - LLNotifications::instance().add("NotecardMissing"); + LLNotificationsUtil::add("NotecardMissing"); } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { - LLNotifications::instance().add("NotecardNoPermissions"); + LLNotificationsUtil::add("NotecardNoPermissions"); } else { - LLNotifications::instance().add("UnableToLoadNotecard"); + LLNotificationsUtil::add("UnableToLoadNotecard"); } llwarns << "Problem loading notecard: " << status << llendl; @@ -631,7 +632,7 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data } else { - LLNotifications::instance().add("SaveNotecardFailObjectNotFound"); + LLNotificationsUtil::add("SaveNotecardFailObjectNotFound"); } } // Perform item copy to inventory @@ -656,7 +657,7 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data llwarns << "Problem saving notecard: " << status << llendl; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("SaveNotecardFailReason", args); + LLNotificationsUtil::add("SaveNotecardFailReason", args); } std::string uuid_string; diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index e4abac51d..3019fca11 100644 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -40,10 +40,12 @@ #include "llcheckboxctrl.h" #include "llcombobox.h" #include "lldir.h" +#include "llinventorydefines.h" #include "llinventorymodel.h" #include "llkeyboard.h" #include "lllineeditor.h" +#include "llnotificationsutil.h" #include "llresmgr.h" #include "llscrollbar.h" #include "llscrollcontainer.h" @@ -707,7 +709,7 @@ BOOL LLScriptEdCore::canClose() else { // Bring up view-modal dialog: Save changes? Yes, No, Cancel - LLNotifications::instance().add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleSaveChangesDialog, this, _1, _2)); + LLNotificationsUtil::add("SaveChanges", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleSaveChangesDialog, this, _1, _2)); return FALSE; } } @@ -765,7 +767,7 @@ void LLScriptEdCore::onBtnHelp(void* userdata) LLScriptEdCore* corep = (LLScriptEdCore*)userdata; LLSD payload; payload["help_url"] = corep->mHelpURL; - LLNotifications::instance().add("WebLaunchLSLGuide", LLSD(), payload, onHelpWebDialog); + LLNotificationsUtil::add("WebLaunchLSLGuide", LLSD(), payload, onHelpWebDialog); } // static @@ -924,7 +926,7 @@ void LLScriptEdCore::onBtnUndoChanges( void* userdata ) LLScriptEdCore* self = (LLScriptEdCore*) userdata; if( !self->mEditor->tryToRevertToPristineState() ) { - LLNotifications::instance().add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, self, _1, _2)); + LLNotificationsUtil::add("ScriptCannotUndo", LLSD(), LLSD(), boost::bind(&LLScriptEdCore::handleReloadFromServerDialog, self, _1, _2)); } } @@ -1562,7 +1564,7 @@ void LLPreviewLSL::onSaveComplete(const LLUUID& asset_uuid, void* user_data, S32 llwarns << "Problem saving script: " << status << llendl; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("SaveScriptFailReason", args); + LLNotificationsUtil::add("SaveScriptFailReason", args); } delete info; } @@ -1600,7 +1602,7 @@ void LLPreviewLSL::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* user_d llwarns << "Problem saving LSL Bytecode (Preview)" << llendl; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("SaveBytecodeFailReason", args); + LLNotificationsUtil::add("SaveBytecodeFailReason", args); } delete instance_uuid; } @@ -1646,15 +1648,15 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { - LLNotifications::instance().add("ScriptMissing"); + LLNotificationsUtil::add("ScriptMissing"); } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { - LLNotifications::instance().add("ScriptNoPermissions"); + LLNotificationsUtil::add("ScriptNoPermissions"); } else { - LLNotifications::instance().add("UnableToLoadScript"); + LLNotificationsUtil::add("UnableToLoadScript"); } preview->mAssetStatus = PREVIEW_ASSET_ERROR; @@ -1994,15 +1996,15 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id, if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { - LLNotifications::instance().add("ScriptMissing"); + LLNotificationsUtil::add("ScriptMissing"); } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { - LLNotifications::instance().add("ScriptNoPermissions"); + LLNotificationsUtil::add("ScriptNoPermissions"); } else { - LLNotifications::instance().add("UnableToLoadScript"); + LLNotificationsUtil::add("UnableToLoadScript"); } instance->mAssetStatus = PREVIEW_ASSET_ERROR; } @@ -2096,7 +2098,7 @@ void LLLiveLSLEditor::onRunningCheckboxClicked( LLUICtrl*, void* userdata ) else { runningCheckbox->set(!running); - LLNotifications::instance().add("CouldNotStartStopScript"); + LLNotificationsUtil::add("CouldNotStartStopScript"); } } @@ -2126,7 +2128,7 @@ void LLLiveLSLEditor::onReset(void *userdata) } else { - LLNotifications::instance().add("CouldNotStartStopScript"); + LLNotificationsUtil::add("CouldNotStartStopScript"); } } @@ -2220,7 +2222,7 @@ void LLLiveLSLEditor::saveIfNeeded() LLViewerObject* object = gObjectList.findObject(mObjectID); if(!object) { - LLNotifications::instance().add("SaveScriptFailObjectNotFound"); + LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); return; } @@ -2228,7 +2230,7 @@ void LLLiveLSLEditor::saveIfNeeded() { // $NOTE: While the error message may not be exactly correct, // it's pretty close. - LLNotifications::instance().add("SaveScriptFailObjectNotFound"); + LLNotificationsUtil::add("SaveScriptFailObjectNotFound"); return; } @@ -2432,7 +2434,7 @@ void LLLiveLSLEditor::onSaveTextComplete(const LLUUID& asset_uuid, void* user_da llwarns << "Unable to save text for a script." << llendl; LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("CompileQueueSaveText", args); + LLNotificationsUtil::add("CompileQueueSaveText", args); } else { @@ -2493,7 +2495,7 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use LLSD args; args["REASON"] = std::string(LLAssetStorage::getErrorString(status)); - LLNotifications::instance().add("CompileQueueSaveBytecode", args); + LLNotificationsUtil::add("CompileQueueSaveBytecode", args); } std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_uuid.asString()); diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index e23e662ec..7846bef47 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -41,6 +41,7 @@ #include "llimagetga.h" #include "llinventoryview.h" #include "llinventory.h" +#include "llnotificationsutil.h" #include "llresmgr.h" #include "lltextbox.h" #include "lltextureview.h" @@ -436,18 +437,17 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success, { LLSD args; args["FILE"] = self->mSaveFileName; - LLNotifications::instance().add("CannotEncodeFile", args); + LLNotificationsUtil::add("CannotEncodeFile", args); } else if( !image_tga->save( self->mSaveFileName ) ) { LLSD args; args["FILE"] = self->mSaveFileName; - LLNotifications::instance().add("CannotWriteFile", args); + LLNotificationsUtil::add("CannotWriteFile", args); } else { - self->mSavedFileTimer.reset(); - self->mSavedFileTimer.setTimerExpirySec( SECONDS_TO_SHOW_FILE_SAVED_MSG ); + self->mSavedFileTimer.reset(SECONDS_TO_SHOW_FILE_SAVED_MSG); } self->mSaveFileName.clear(); @@ -455,7 +455,7 @@ void LLPreviewTexture::onFileLoadedForSave(BOOL success, if( self && !success ) { - LLNotifications::instance().add("CannotDownloadFile"); + LLNotificationsUtil::add("CannotDownloadFile"); } } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 6bd7637bf..f9adea36b 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -42,6 +42,7 @@ #include "lleconomy.h" #include "llgl.h" #include "llrender.h" +#include "llnotifications.h" #include "llpermissions.h" #include "llpermissionsflags.h" #include "llundo.h" @@ -67,6 +68,7 @@ #include "llinventorymodel.h" #include "llmenugl.h" #include "llmutelist.h" +#include "llnotificationsutil.h" #include "llstatusbar.h" #include "llsurface.h" #include "lltool.h" @@ -571,7 +573,7 @@ bool LLSelectMgr::linkObjects() { if (!LLSelectMgr::getInstance()->selectGetAllRootsValid()) { - LLNotifications::getInstance()->add("UnableToLinkWhileDownloading"); + LLNotificationsUtil::add("UnableToLinkWhileDownloading"); return true; } @@ -582,19 +584,19 @@ bool LLSelectMgr::linkObjects() args["COUNT"] = llformat("%d", object_count); int max = MAX_CHILDREN_PER_TASK+1; args["MAX"] = llformat("%d", max); - LLNotifications::getInstance()->add("UnableToLinkObjects", args); + LLNotificationsUtil::add("UnableToLinkObjects", args); return true; } if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2) { - LLNotifications::instance().add("CannotLinkIncompleteSet"); + LLNotificationsUtil::add("CannotLinkIncompleteSet"); return true; } if (!LLSelectMgr::getInstance()->selectGetRootsModify()) { - LLNotifications::instance().add("CannotLinkModify"); + LLNotificationsUtil::add("CannotLinkModify"); return true; } @@ -605,7 +607,7 @@ bool LLSelectMgr::linkObjects() // we don't actually care if you're the owner, but novices are // the most likely to be stumped by this one, so offer the // easiest and most likely solution. - LLNotifications::instance().add("CannotLinkDifferentOwners"); + LLNotificationsUtil::add("CannotLinkDifferentOwners"); return true; } @@ -1215,8 +1217,8 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & mGridRotation = first_grid_object->getRenderRotation(); LLVector3 first_grid_obj_pos = first_grid_object->getRenderPosition(); - LLVector3 min_extents(F32_MAX, F32_MAX, F32_MAX); - LLVector3 max_extents(-F32_MAX, -F32_MAX, -F32_MAX); + LLVector4a min_extents(F32_MAX); + LLVector4a max_extents(-F32_MAX); BOOL grid_changed = FALSE; for (LLObjectSelection::iterator iter = mGridObjects.begin(); iter != mGridObjects.end(); ++iter) @@ -1225,7 +1227,7 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & LLDrawable* drawable = object->mDrawable; if (drawable) { - const LLVector3* ext = drawable->getSpatialExtents(); + const LLVector4a* ext = drawable->getSpatialExtents(); update_min_max(min_extents, max_extents, ext[0]); update_min_max(min_extents, max_extents, ext[1]); grid_changed = TRUE; @@ -1233,13 +1235,19 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & } if (grid_changed) { - mGridOrigin = lerp(min_extents, max_extents, 0.5f); + LLVector4a center, size; + center.setAdd(min_extents, max_extents); + center.mul(0.5f); + size.setSub(max_extents, min_extents); + size.mul(0.5f); + + mGridOrigin.set(center.getF32ptr()); LLDrawable* drawable = first_grid_object->mDrawable; if (drawable && drawable->isActive()) { mGridOrigin = mGridOrigin * first_grid_object->getRenderMatrix(); } - mGridScale = (max_extents - min_extents) * 0.5f; + mGridScale.set(size.getF32ptr()); } } else // GRID_MODE_WORLD or just plain default @@ -1986,6 +1994,103 @@ BOOL LLSelectMgr::selectionGetGlow(F32 *glow) return identical; } +#if MESH_ENABLED +void LLSelectMgr::selectionSetPhysicsType(U8 type) +{ + struct f : public LLSelectedObjectFunctor + { + U8 mType; + f(const U8& t) : mType(t) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsShapeType(mType); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(type); + getSelection()->applyToObjects(&sendfunc); +} + +void LLSelectMgr::selectionSetFriction(F32 friction) +{ + struct f : public LLSelectedObjectFunctor + { + F32 mFriction; + f(const F32& friction) : mFriction(friction) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsFriction(mFriction); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(friction); + getSelection()->applyToObjects(&sendfunc); +} + +void LLSelectMgr::selectionSetGravity(F32 gravity ) +{ + struct f : public LLSelectedObjectFunctor + { + F32 mGravity; + f(const F32& gravity) : mGravity(gravity) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsGravity(mGravity); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(gravity); + getSelection()->applyToObjects(&sendfunc); +} + +void LLSelectMgr::selectionSetDensity(F32 density ) +{ + struct f : public LLSelectedObjectFunctor + { + F32 mDensity; + f(const F32& density ) : mDensity(density) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsDensity(mDensity); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(density); + getSelection()->applyToObjects(&sendfunc); +} + +void LLSelectMgr::selectionSetRestitution(F32 restitution) +{ + struct f : public LLSelectedObjectFunctor + { + F32 mRestitution; + f(const F32& restitution ) : mRestitution(restitution) {} + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + object->setPhysicsRestitution(mRestitution); + object->updateFlags(TRUE); + } + return true; + } + } sendfunc(restitution); + getSelection()->applyToObjects(&sendfunc); +} +#endif //MESH_ENABLED + //----------------------------------------------------------------------------- // selectionSetMaterial() //----------------------------------------------------------------------------- @@ -3658,7 +3763,7 @@ void LLSelectMgr::deselectAllIfTooFar() { if (mDebugSelectMgr) { - llinfos << "Selection manager: auto-deselecting, select_dist = " << fsqrtf(select_dist_sq) << llendl; + llinfos << "Selection manager: auto-deselecting, select_dist = " << (F32) sqrt(select_dist_sq) << llendl; llinfos << "agent pos global = " << gAgent.getPositionGlobal() << llendl; llinfos << "selection pos global = " << selectionCenter << llendl; } @@ -3826,6 +3931,27 @@ void LLSelectMgr::sendDelink() return; } +#if MESH_ENABLED + struct f : public LLSelectedObjectFunctor + { //on delink, any modifyable object should + f() {} + + virtual bool apply(LLViewerObject* object) + { + if (object->permModify()) + { + if (object->getPhysicsShapeType() == LLViewerObject::PHYSICS_SHAPE_NONE) + { + object->setPhysicsShapeType(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + object->updateFlags(); + } + } + return true; + } + } sendfunc; + getSelection()->applyToObjects(&sendfunc); +#endif //MESH_ENABLED + // Delink needs to send individuals so you can unlink a single object from // a linked set. sendListToRegions( @@ -5031,7 +5157,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) gGL.getTexUnit(0)->bind(mSilhouetteImagep); LLGLSPipelineSelection gls_select; - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f); LLGLEnable blend(GL_BLEND); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); @@ -5147,7 +5272,6 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) } gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } void LLSelectMgr::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point) @@ -5218,7 +5342,6 @@ LLSelectNode::LLSelectNode(const LLSelectNode& nodep) mSilhouetteVertices = nodep.mSilhouetteVertices; mSilhouetteNormals = nodep.mSilhouetteNormals; - mSilhouetteSegments = nodep.mSilhouetteSegments; mSilhouetteExists = nodep.mSilhouetteExists; mObject = nodep.mObject; @@ -5452,6 +5575,111 @@ BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power) return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id)); } +#if MESH_ENABLED +void pushWireframe(LLDrawable* drawable) +{ + if (drawable->isState(LLDrawable::RIGGED)) + { //render straight from rigged volume if this is a rigged attachment + LLVOVolume* vobj = drawable->getVOVolume(); + if (vobj) + { + vobj->updateRiggedVolume(); + LLRiggedVolume* rigged_volume = vobj->getRiggedVolume(); + if (rigged_volume) + { + LLVertexBuffer::unbind(); + gGL.pushMatrix(); + glMultMatrixf((F32*) vobj->getRelativeXform().mMatrix); + for (S32 i = 0; i < rigged_volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = rigged_volume->getVolumeFace(i); + glVertexPointer(3, GL_FLOAT, 16, face.mPositions); + glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices); + } + gGL.popMatrix(); + } + } + } + else + { + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + LLFace* face = drawable->getFace(i); + if (face->verify()) + { + pushVerts(face, LLVertexBuffer::MAP_VERTEX); + } + } + } +} + +void LLSelectNode::renderOneWireframe(const LLColor4& color) +{ + LLViewerObject* objectp = getObject(); + if (!objectp) + { + return; + } + + LLDrawable* drawable = objectp->mDrawable; + if(!drawable) + { + return; + } + + glMatrixMode(GL_MODELVIEW); + gGL.pushMatrix(); + + BOOL is_hud_object = objectp->isHUDAttachment(); + + if (drawable->isActive()) + { + glLoadMatrixd(gGLModelView); + glMultMatrixf((F32*) objectp->getRenderMatrix().mMatrix); + } + else if (!is_hud_object) + { + glLoadIdentity(); + glMultMatrixd(gGLModelView); + LLVector3 trans = objectp->getRegion()->getOriginAgent(); + glTranslatef(trans.mV[0], trans.mV[1], trans.mV[2]); + } + + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible()) + { + gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE); + LLGLEnable fog(GL_FOG); + glFogi(GL_FOG_MODE, GL_LINEAR); + float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec(); + LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgentCamera.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0); + glFogf(GL_FOG_START, d); + glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV()))); + glFogfv(GL_FOG_COLOR, fogCol.mV); + + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL); + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + { + glColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); + pushWireframe(drawable); + } + } + + gGL.flush(); + gGL.setSceneBlendType(LLRender::BT_ALPHA); + + glColor4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); + LLGLEnable offset(GL_POLYGON_OFFSET_LINE); + glPolygonOffset(3.f, 3.f); + glLineWidth(3.f); + pushWireframe(drawable); + glLineWidth(1.f); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + gGL.popMatrix(); +} +#endif //MESH_ENABLED + //----------------------------------------------------------------------------- // renderOneSilhouette() //----------------------------------------------------------------------------- @@ -5469,6 +5697,15 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) return; } +#if MESH_ENABLED + LLVOVolume* vobj = drawable->getVOVolume(); + if (vobj && vobj->isMesh()) + { + renderOneWireframe(color); + return; + } +#endif //MESH_ENABLED + if (!mSilhouetteExists) { return; @@ -5530,17 +5767,15 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.begin(LLRender::LINES); { - S32 i = 0; - for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++) + for(S32 i = 0; i < (S32)mSilhouetteVertices.size(); i += 2) { - for(; i < mSilhouetteSegments[seg_num]; i++) - { - u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); - gGL.texCoord2f( u_coord, v_coord ); - gGL.vertex3fv( mSilhouetteVertices[i].mV ); - } + u_coord += u_divisor * LLSelectMgr::sHighlightUScale; + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); + gGL.texCoord2f( u_coord, v_coord ); + gGL.vertex3fv( mSilhouetteVertices[i].mV); + u_coord += u_divisor * LLSelectMgr::sHighlightUScale; + gGL.texCoord2f( u_coord, v_coord ); + gGL.vertex3fv(mSilhouetteVertices[i+1].mV); } } gGL.end(); @@ -5551,51 +5786,50 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) gGL.setSceneBlendType(LLRender::BT_ALPHA); gGL.begin(LLRender::TRIANGLES); { - S32 i = 0; - for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++) + for(S32 i = 0; i < (S32)mSilhouetteVertices.size(); i+=2) { - S32 first_i = i; - LLVector3 v; - LLVector2 t; - - for(; i < mSilhouetteSegments[seg_num]; i++) - { - - if (i == first_i) { - LLVector3 vert = (mSilhouetteNormals[i]) * silhouette_thickness; - vert += mSilhouetteVertices[i]; - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); - gGL.texCoord2f( u_coord, v_coord + LLSelectMgr::sHighlightVScale ); - gGL.vertex3fv( vert.mV ); - - u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - - gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); - gGL.texCoord2f( u_coord, v_coord ); - gGL.vertex3fv( mSilhouetteVertices[i].mV ); - - v = mSilhouetteVertices[i]; - t = LLVector2(u_coord, v_coord); - } - else { - LLVector3 vert = (mSilhouetteNormals[i]) * silhouette_thickness; - vert += mSilhouetteVertices[i]; - - gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); - gGL.texCoord2f( u_coord, v_coord + LLSelectMgr::sHighlightVScale ); - gGL.vertex3fv( vert.mV ); - gGL.vertex3fv( vert.mV ); - - gGL.texCoord2fv(t.mV); - u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); - gGL.vertex3fv(v.mV); - gGL.texCoord2f( u_coord, v_coord ); - gGL.vertex3fv( mSilhouetteVertices[i].mV ); - - } + if (!mSilhouetteNormals[i].isFinite() || + !mSilhouetteNormals[i+1].isFinite()) + { //skip skewed segments + continue; } + + LLVector3 v[4]; + LLVector2 tc[4]; + v[0] = mSilhouetteVertices[i] + (mSilhouetteNormals[i] * silhouette_thickness); + tc[0].set(u_coord, v_coord + LLSelectMgr::sHighlightVScale); + + v[1] = mSilhouetteVertices[i]; + tc[1].set(u_coord, v_coord); + + u_coord += u_divisor * LLSelectMgr::sHighlightUScale; + + v[2] = mSilhouetteVertices[i+1] + (mSilhouetteNormals[i+1] * silhouette_thickness); + tc[2].set(u_coord, v_coord + LLSelectMgr::sHighlightVScale); + + v[3] = mSilhouetteVertices[i+1]; + tc[3].set(u_coord,v_coord); + + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); + gGL.texCoord2fv(tc[0].mV); + gGL.vertex3fv( v[0].mV ); + + gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); + gGL.texCoord2fv( tc[1].mV ); + gGL.vertex3fv( v[1].mV ); + + gGL.color4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.0f); //LLSelectMgr::sHighlightAlpha); + gGL.texCoord2fv( tc[2].mV ); + gGL.vertex3fv( v[2].mV ); + + gGL.vertex3fv( v[2].mV ); + + gGL.color4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2); + gGL.texCoord2fv( tc[1].mV ); + gGL.vertex3fv( v[1].mV ); + + gGL.texCoord2fv( tc[3].mV ); + gGL.vertex3fv( v[3].mV ); } } gGL.end(); @@ -6161,6 +6395,222 @@ S32 LLObjectSelection::getObjectCount() return count; } +#if MESH_ENABLED +F32 LLObjectSelection::getSelectedObjectCost() +{ + cleanupNodes(); + F32 cost = 0.f; + + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object) + { + cost += object->getObjectCost(); + } + } + + return cost; +} + +F32 LLObjectSelection::getSelectedLinksetCost() +{ + cleanupNodes(); + F32 cost = 0.f; + + std::set<LLViewerObject*> me_roots; + + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object) + { + LLViewerObject* root = static_cast<LLViewerObject*>(object->getRoot()); + if (root) + { + if (me_roots.find(root) == me_roots.end()) + { + me_roots.insert(root); + cost += root->getLinksetCost(); + } + } + } + } + + return cost; +} + +F32 LLObjectSelection::getSelectedPhysicsCost() +{ + cleanupNodes(); + F32 cost = 0.f; + + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object) + { + cost += object->getPhysicsCost(); + } + } + + return cost; +} + +F32 LLObjectSelection::getSelectedLinksetPhysicsCost() +{ + cleanupNodes(); + F32 cost = 0.f; + + std::set<LLViewerObject*> me_roots; + + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object) + { + LLViewerObject* root = static_cast<LLViewerObject*>(object->getRoot()); + if (root) + { + if (me_roots.find(root) == me_roots.end()) + { + me_roots.insert(root); + cost += root->getLinksetPhysicsCost(); + } + } + } + } + + return cost; +} + +F32 LLObjectSelection::getSelectedObjectStreamingCost(S32* total_bytes, S32* visible_bytes) +{ + F32 cost = 0.f; + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object) + { + S32 bytes = 0; + S32 visible = 0; + cost += object->getStreamingCost(&bytes, &visible); + + if (total_bytes) + { + *total_bytes += bytes; + } + + if (visible_bytes) + { + *visible_bytes += visible; + } + } + } + + return cost; +} + +U32 LLObjectSelection::getSelectedObjectTriangleCount() +{ + U32 count = 0; + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLViewerObject* object = node->getObject(); + + if (object) + { + count += object->getTriangleCount(); + } + } + + return count; +} + + +S32 LLObjectSelection::getSelectedObjectRenderCost() +{ + S32 cost = 0; + LLVOVolume::texture_cost_t textures; + typedef std::set<LLUUID> uuid_list_t; + uuid_list_t computed_objects; + + typedef std::list<LLPointer<LLViewerObject> > child_list_t; + typedef const child_list_t const_child_list_t; + + // add render cost of complete linksets first, to get accurate texture counts + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + + LLVOVolume* object = (LLVOVolume*)node->getObject(); + + if (object && object->isRootEdit()) + { + cost += object->getRenderCost(textures); + computed_objects.insert(object->getID()); + + const_child_list_t children = object->getChildren(); + for (const_child_list_t::const_iterator child_iter = children.begin(); + child_iter != children.end(); + ++child_iter) + { + LLViewerObject* child_obj = *child_iter; + LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj ); + if (child) + { + cost += child->getRenderCost(textures); + computed_objects.insert(child->getID()); + } + } + + for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) + { + // add the cost of each individual texture in the linkset + cost += iter->second; + } + + textures.clear(); + } + } + + // add any partial linkset objects, texture cost may be slightly misleading + for (list_t::iterator iter = mList.begin(); iter != mList.end(); ++iter) + { + LLSelectNode* node = *iter; + LLVOVolume* object = (LLVOVolume*)node->getObject(); + + if (object && computed_objects.find(object->getID()) == computed_objects.end() ) + { + cost += object->getRenderCost(textures); + computed_objects.insert(object->getID()); + } + + for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) + { + // add the cost of each individual texture in the linkset + cost += iter->second; + } + + textures.clear(); + } + + return cost; +} + +#endif //MESH_ENABLED + //----------------------------------------------------------------------------- // getTECount() diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index be482b725..37027f450 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -37,7 +37,8 @@ #include "lleditmenuhandler.h" #include "llundo.h" #include "lluuid.h" -#include "llmemory.h" +#include "llpointer.h" +#include "llsafehandle.h" #include "llsaleinfo.h" #include "llcategory.h" #include "v3dmath.h" @@ -139,6 +140,9 @@ public: BOOL isTESelected(S32 te_index); S32 getLastSelectedTE(); S32 getTESelectMask() { return mTESelectMask; } +#if MESH_ENABLED + void renderOneWireframe(const LLColor4& color); +#endif void renderOneSilhouette(const LLColor4 &color); void setTransient(BOOL transient) { mTransient = transient; } BOOL isTransient() { return mTransient; } @@ -186,7 +190,6 @@ public: std::vector<LLVector3> mTextureScaleRatios; std::vector<LLVector3> mSilhouetteVertices; // array of vertices to render silhouette of object std::vector<LLVector3> mSilhouetteNormals; // array of normals to render silhouette of object - std::vector<S32> mSilhouetteSegments; // array of normals to render silhouette of object BOOL mSilhouetteExists; // need to generate silhouette? protected: @@ -282,6 +285,16 @@ public: // count members S32 getObjectCount(); +#if MESH_ENABLED + F32 getSelectedObjectCost(); + F32 getSelectedLinksetCost(); + F32 getSelectedPhysicsCost(); + F32 getSelectedLinksetPhysicsCost(); + S32 getSelectedObjectRenderCost(); + + F32 getSelectedObjectStreamingCost(S32* total_bytes = NULL, S32* visible_bytes = NULL); + U32 getSelectedObjectTriangleCount(); +#endif //MESH_ENABLED S32 getTECount(); S32 getRootObjectCount(); @@ -503,6 +516,13 @@ public: bool selectionGetIncludeInSearch(bool* include_in_search_out); // true if all selected objects have same BOOL selectionGetGlow(F32 *glow); +#if MESH_ENABLED + void selectionSetPhysicsType(U8 type); + void selectionSetGravity(F32 gravity); + void selectionSetFriction(F32 friction); + void selectionSetDensity(F32 density); + void selectionSetRestitution(F32 restitution); +#endif //MESH_ENABLED void selectionSetMaterial(U8 material); void selectionSetImage(const LLUUID& imageid); // could be item or asset id void selectionSetColor(const LLColor4 &color); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index 32dcd4c30..2bce7e36d 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -38,13 +38,18 @@ #include "llviewerobjectlist.h" #include "llvovolume.h" #include "llvolume.h" +#include "llvolumeoctree.h" #include "llviewercamera.h" #include "llface.h" +#include "llfloatertools.h" #include "llviewercontrol.h" #include "llagent.h" #include "llviewerregion.h" #include "llcamera.h" #include "pipeline.h" +#if MESH_ENABLED +#include "llmeshrepository.h" +#endif //MESH_ENABLED #include "llrender.h" #include "lloctree.h" #include "llvoavatar.h" @@ -110,23 +115,6 @@ void sg_assert(BOOL expr) #endif } -#if LL_DEBUG -void validate_drawable(LLDrawable* drawablep) -{ - F64 rad = drawablep->getBinRadius(); - const LLVector3* ext = drawablep->getSpatialExtents(); - - if (rad < 0 || rad > 4096 || - (ext[1]-ext[0]).magVec() > 4096) - { - llwarns << "Invalid drawable found in octree." << llendl; - } -} -#else -#define validate_drawable(x) -#endif - - S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad) { return AABBSphereIntersectR2(min, max, origin, rad*rad); @@ -166,6 +154,55 @@ S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVe } +S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad) +{ + return AABBSphereIntersectR2(min, max, origin, rad*rad); +} + +S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &r) +{ + F32 d = 0.f; + F32 t; + + LLVector4a origina; + origina.load3(origin.mV); + + LLVector4a v; + v.setSub(min, origina); + + if (v.dot3(v) < r) + { + v.setSub(max, origina); + if (v.dot3(v) < r) + { + return 2; + } + } + + + for (U32 i = 0; i < 3; i++) + { + if (origin.mV[i] < min[i]) + { + t = min[i] - origin.mV[i]; + d += t*t; + } + else if (origin.mV[i] > max[i]) + { + t = origin.mV[i] - max[i]; + d += t*t; + } + + if (d > r) + { + return 0; + } + } + + return 1; +} + + typedef enum { b000 = 0x00, @@ -183,76 +220,110 @@ typedef enum //gives you a triangle fan index array static U8 sOcclusionIndices[] = { - // 000 + //000 b111, b110, b010, b011, b001, b101, b100, b110, - //001 - b110, b000, b010, b011, b111, b101, b100, b000, + //001 + b011, b010, b000, b001, b101, b111, b110, b010, //010 b101, b100, b110, b111, b011, b001, b000, b100, //011 - b100, b010, b110, b111, b101, b001, b000, b010, - //100 - b011, b010, b000, b001, b101, b111, b110, b010, + b001, b000, b100, b101, b111, b011, b010, b000, + //100 + b110, b000, b010, b011, b111, b101, b100, b000, //101 b010, b100, b000, b001, b011, b111, b110, b100, //110 - b001, b000, b100, b101, b111, b011, b010, b000, + b100, b010, b110, b111, b101, b001, b000, b010, //111 b000, b110, b100, b101, b001, b011, b010, b110, }; -U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector3& center) +U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center) { - LLVector3 d = center - camera->getOrigin(); + LLVector4a origin; + origin.load3(camera->getOrigin().mV); - U8 cypher = 0; - if (d.mV[0] > 0) - { - cypher |= b100; - } - if (d.mV[1] > 0) - { - cypher |= b010; - } - if (d.mV[2] > 0) - { - cypher |= b001; - } + S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7; + + return cypher*8; +} +U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center) +{ + LLVector4a origin; + origin.load3(camera->getOrigin().mV); + + S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7; + return sOcclusionIndices+cypher*8; } void LLSpatialGroup::buildOcclusion() { - if (!mOcclusionVerts) + if (mOcclusionVerts.isNull()) { - mOcclusionVerts = new F32[8*3]; - } - LLVector3 r = mBounds[1] + LLVector3(SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE, SG_OCCLUSION_FUDGE); - - for (U32 k = 0; k < 3; k++) - { - r.mV[k] = llmin(mBounds[1].mV[k]+0.25f, r.mV[k]); - } - - F32* v = mOcclusionVerts; - F32* c = mBounds[0].mV; - F32* s = r.mV; + mOcclusionVerts = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX, + LLVertexBuffer::sUseStreamDraw ? mBufferUsage : 0); //if GL has a hard time with VBOs, don't use them for occlusion culling. + mOcclusionVerts->allocateBuffer(8, 64, true); - //vertex positions are encoded so the 3 bits of their vertex index - //correspond to their axis facing, with bit position 3,2,1 matching - //axis facing x,y,z, bit set meaning positive facing, bit clear - //meaning negative facing - v[0] = c[0]-s[0]; v[1] = c[1]-s[1]; v[2] = c[2]-s[2]; // 0 - 0000 - v[3] = c[0]-s[0]; v[4] = c[1]-s[1]; v[5] = c[2]+s[2]; // 1 - 0001 - v[6] = c[0]-s[0]; v[7] = c[1]+s[1]; v[8] = c[2]-s[2]; // 2 - 0010 - v[9] = c[0]-s[0]; v[10] = c[1]+s[1]; v[11] = c[2]+s[2]; // 3 - 0011 - - v[12] = c[0]+s[0]; v[13] = c[1]-s[1]; v[14] = c[2]-s[2]; // 4 - 0100 - v[15] = c[0]+s[0]; v[16] = c[1]-s[1]; v[17] = c[2]+s[2]; // 5 - 0101 - v[18] = c[0]+s[0]; v[19] = c[1]+s[1]; v[20] = c[2]-s[2]; // 6 - 0110 - v[21] = c[0]+s[0]; v[22] = c[1]+s[1]; v[23] = c[2]+s[2]; // 7 - 0111 + LLStrider<U16> idx; + mOcclusionVerts->getIndexStrider(idx); + for (U32 i = 0; i < 64; i++) + { + *idx++ = sOcclusionIndices[i]; + } + } + + LLVector4a fudge; + fudge.splat(SG_OCCLUSION_FUDGE); + + LLVector4a r; + r.setAdd(mBounds[1], fudge); + + LLStrider<LLVector3> pos; + + { + //LLFastTimer t(LLFastTimer::FTM_BUILD_OCCLUSION); + mOcclusionVerts->getVertexStrider(pos); + } + + { + LLVector4a* v = (LLVector4a*) pos.get(); + + const LLVector4a& c = mBounds[0]; + const LLVector4a& s = r; + + static const LLVector4a octant[] = + { + LLVector4a(-1.f, -1.f, -1.f), + LLVector4a(-1.f, -1.f, 1.f), + LLVector4a(-1.f, 1.f, -1.f), + LLVector4a(-1.f, 1.f, 1.f), + + LLVector4a(1.f, -1.f, -1.f), + LLVector4a(1.f, -1.f, 1.f), + LLVector4a(1.f, 1.f, -1.f), + LLVector4a(1.f, 1.f, 1.f), + }; + + //vertex positions are encoded so the 3 bits of their vertex index + //correspond to their axis facing, with bit position 3,2,1 matching + //axis facing x,y,z, bit set meaning positive facing, bit clear + //meaning negative facing + + for (S32 i = 0; i < 8; ++i) + { + LLVector4a p; + p.setMul(s, octant[i]); + p.add(c); + v[i] = p; + } + } + + { + mOcclusionVerts->setBuffer(0); + } clearState(LLSpatialGroup::OCCLUSION_DIRTY); } @@ -318,7 +389,6 @@ LLSpatialGroup::~LLSpatialGroup() } } - delete [] mOcclusionVerts; mOcclusionVerts = NULL; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -330,6 +400,11 @@ void LLSpatialGroup::clearDrawMap() mDrawMap.clear(); } +BOOL LLSpatialGroup::isHUDGroup() +{ + return mSpatialPartition && mSpatialPartition->isHUDPartition() ; +} + BOOL LLSpatialGroup::isRecentlyVisible() const { return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ; @@ -352,8 +427,10 @@ void LLSpatialGroup::validate() sg_assert(!isState(DIRTY)); sg_assert(!isDead()); - LLVector3 myMin = mBounds[0] - mBounds[1]; - LLVector3 myMax = mBounds[0] + mBounds[1]; + LLVector4a myMin; + myMin.setSub(mBounds[0], mBounds[1]); + LLVector4a myMax; + myMax.setAdd(mBounds[0], mBounds[1]); validateDrawMap(); @@ -385,16 +462,18 @@ void LLSpatialGroup::validate() group->validate(); //ensure all children are enclosed in this node - LLVector3 center = group->mBounds[0]; - LLVector3 size = group->mBounds[1]; + LLVector4a center = group->mBounds[0]; + LLVector4a size = group->mBounds[1]; - LLVector3 min = center - size; - LLVector3 max = center + size; + LLVector4a min; + min.setSub(center, size); + LLVector4a max; + max.setAdd(center, size); for (U32 j = 0; j < 3; j++) { - sg_assert(min.mV[j] >= myMin.mV[j]-0.02f); - sg_assert(max.mV[j] <= myMax.mV[j]+0.02f); + sg_assert(min[j] >= myMin[j]-0.02f); + sg_assert(max[j] <= myMax[j]+0.02f); } } @@ -409,52 +488,6 @@ void LLSpatialGroup::checkStates() #endif } -void validate_draw_info(LLDrawInfo& params) -{ -#if LL_OCTREE_PARANOIA_CHECK - if (!params.mVertexBuffer) - { - llerrs << "Draw batch has no vertex buffer." << llendl; - } - - //bad range - if (params.mStart >= params.mEnd) - { - llerrs << "Draw batch has invalid range." << llendl; - } - - if (params.mEnd >= (U32) params.mVertexBuffer->getNumVerts()) - { - llerrs << "Draw batch has buffer overrun error." << llendl; - } - - if (params.mOffset + params.mCount > (U32) params.mVertexBuffer->getNumIndices()) - { - llerrs << "Draw batch has index buffer ovverrun error." << llendl; - } - - //bad indices - U16* indicesp = (U16*) params.mVertexBuffer->getIndicesPointer(); - if (indicesp) - { - for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++) - { - if (indicesp[i] < (U16)params.mStart) - { - llerrs << "Draw batch has vertex buffer index out of range error (index too low). " - << "indicesp["<<i<<"]="<<indicesp[i]<< llendl; - } - - if (indicesp[i] > (U16)params.mEnd) - { - llerrs << "Draw batch has vertex buffer index out of range error (index too high)." - << "indicesp["<<i<<"]="<<indicesp[i]<< llendl; - } - } - } //Complains -SG -#endif -} - void LLSpatialGroup::validateDrawMap() { #if LL_OCTREE_PARANOIA_CHECK @@ -464,8 +497,8 @@ void LLSpatialGroup::validateDrawMap() for (drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) { LLDrawInfo& params = **j; - - validate_draw_info(params); + + params.validate(); } } #endif @@ -476,19 +509,17 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); drawablep->updateSpatialExtents(); - validate_drawable(drawablep); OctreeNode* parent = mOctreeNode->getOctParent(); if (mOctreeNode->isInside(drawablep->getPositionGroup()) && (mOctreeNode->contains(drawablep) || - (drawablep->getBinRadius() > mOctreeNode->getSize().mdV[0] && + (drawablep->getBinRadius() > mOctreeNode->getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { unbound(); setState(OBJECT_DIRTY); //setState(GEOM_DIRTY); - validate_drawable(drawablep); return TRUE; } @@ -506,7 +537,6 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc else { drawablep->setSpatialGroup(this); - validate_drawable(drawablep); setState(OBJECT_DIRTY | GEOM_DIRTY); setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); gPipeline.markRebuild(this, TRUE); @@ -604,7 +634,7 @@ void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group) } -BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut) +BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut) { const OctreeNode* node = mOctreeNode; @@ -617,8 +647,8 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO return FALSE; } - LLVector3& newMin = mObjectExtents[0]; - LLVector3& newMax = mObjectExtents[1]; + LLVector4a& newMin = mObjectExtents[0]; + LLVector4a& newMax = mObjectExtents[1]; if (isState(OBJECT_DIRTY)) { //calculate new bounding box @@ -627,10 +657,10 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO //initialize bounding box to first element OctreeNode::const_element_iter i = node->getData().begin(); LLDrawable* drawablep = *i; - const LLVector3* minMax = drawablep->getSpatialExtents(); + const LLVector4a* minMax = drawablep->getSpatialExtents(); - newMin.setVec(minMax[0]); - newMax.setVec(minMax[1]); + newMin = minMax[0]; + newMax = minMax[1]; for (++i; i != node->getData().end(); ++i) { @@ -654,8 +684,10 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO }*/ } - mObjectBounds[0] = (newMin + newMax) * 0.5f; - mObjectBounds[1] = (newMax - newMin) * 0.5f; + mObjectBounds[0].setAdd(newMin, newMax); + mObjectBounds[0].mul(0.5f); + mObjectBounds[1].setSub(newMax, newMin); + mObjectBounds[1].mul(0.5f); } if (empty) @@ -665,17 +697,8 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO } else { - for (U32 i = 0; i < 3; i++) - { - if (newMin.mV[i] < minOut.mV[i]) - { - minOut.mV[i] = newMin.mV[i]; - } - if (newMax.mV[i] > maxOut.mV[i]) - { - maxOut.mV[i] = newMax.mV[i]; - } - } + minOut.setMin(minOut, newMin); + maxOut.setMax(maxOut, newMax); } return TRUE; @@ -766,18 +789,19 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) return TRUE; } -void LLSpatialGroup::shift(const LLVector3 &offset) +void LLSpatialGroup::shift(const LLVector4a &offset) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - LLVector3d offsetd(offset); - mOctreeNode->setCenter(mOctreeNode->getCenter()+offsetd); + LLVector4a t = mOctreeNode->getCenter(); + t.add(offset); + mOctreeNode->setCenter(t); mOctreeNode->updateMinMax(); - mBounds[0] += offset; - mExtents[0] += offset; - mExtents[1] += offset; - mObjectBounds[0] += offset; - mObjectExtents[0] += offset; - mObjectExtents[1] += offset; + mBounds[0].add(offset); + mExtents[0].add(offset); + mExtents[1].add(offset); + mObjectBounds[0].add(offset); + mObjectExtents[0].add(offset); + mObjectExtents[1].add(offset); //if (!mSpatialPartition->mRenderByGroup) { @@ -785,16 +809,9 @@ void LLSpatialGroup::shift(const LLVector3 &offset) gPipeline.markRebuild(this, TRUE); } - if (mOcclusionVerts) + if (mOcclusionVerts.notNull()) { setState(OCCLUSION_DIRTY); - /*for (U32 i = 0; i < 8; i++) - { - F32* v = mOcclusionVerts+i*3; - v[0] += offset.mV[0]; - v[1] += offset.mV[1]; - v[2] += offset.mV[2]; - }*/ } } @@ -827,24 +844,16 @@ void LLSpatialGroup::setState(eSpatialState state) // if (LLSpatialPartition::sFreezeState) // return; mState |= state; - - if (state > LLSpatialGroup::STATE_MASK) - { - llerrs << "WTF?" << llendl; - } + + llassert(state <= LLSpatialGroup::STATE_MASK); } void LLSpatialGroup::setState(eSpatialState state, S32 mode) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); -// if (LLSpatialPartition::sFreezeState) -// return; - - if (state > LLSpatialGroup::STATE_MASK) - { - llerrs << "WTF?" << llendl; - } + llassert(state <= LLSpatialGroup::STATE_MASK); + if (mode > STATE_MODE_SINGLE) { if (mode == STATE_MODE_DIFF) @@ -890,25 +899,14 @@ public: void LLSpatialGroup::clearState(eSpatialState state) { -// if (LLSpatialPartition::sFreezeState) -// return; - if (state > LLSpatialGroup::STATE_MASK) - { - llerrs << "WTF?" << llendl; - } + llassert(state <= LLSpatialGroup::STATE_MASK); mState &= ~state; } void LLSpatialGroup::clearState(eSpatialState state, S32 mode) { - -// if (LLSpatialPartition::sFreezeState) -// return; - if (state > LLSpatialGroup::STATE_MASK) - { - llerrs << "WTF?" << llendl; - } + llassert(state <= LLSpatialGroup::STATE_MASK); LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -933,10 +931,7 @@ void LLSpatialGroup::clearState(eSpatialState state, S32 mode) BOOL LLSpatialGroup::isState(eSpatialState state) const { - if (state > LLSpatialGroup::STATE_MASK) - { - llerrs << "LLSpatialGroup::isState passed invalid state '" << state << "'" << llendl; - } + llassert(state <= LLSpatialGroup::STATE_MASK); return mState & state ? TRUE : FALSE; } @@ -1074,7 +1069,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mOctreeNode(node), mSpatialPartition(part), mVertexBuffer(NULL), - mBufferUsage(GL_STATIC_DRAW_ARB), + mBufferUsage(part->mBufferUsage), mDistance(0.f), mDepth(0.f), mLastUpdateDistance(-1.f), @@ -1085,6 +1080,8 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : sNodeCount++; LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + mViewAngle.splat(0.f); + mLastUpdateViewAngle.splat(-1.f); mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[1] = mObjectExtents[0] = mObjectExtents[1] = mViewAngle; @@ -1093,12 +1090,12 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : setState(SG_INITIAL_STATE_MASK); gPipeline.markRebuild(this, TRUE); - mBounds[0] = LLVector3(node->getCenter()); - mBounds[1] = LLVector3(node->getSize()); + mBounds[0] = node->getCenter(); + mBounds[1] = node->getSize(); part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod; mLODHash = part->mLODSeed; - + OctreeNode* oct_parent = node->getOctParent(); LLSpatialGroup* parent = oct_parent ? (LLSpatialGroup*) oct_parent->getListener(0) : NULL; @@ -1109,6 +1106,7 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0; mVisible[i] = 0; } + mOcclusionVerts = NULL; mRadius = 1; @@ -1119,7 +1117,8 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) { if (LLViewerCamera::sCurCameraID != LLViewerCamera::CAMERA_WORLD) { - llerrs << "WTF?" << llendl; + llwarns << "Attempted to update distance for camera other than world camera!" << llendl; + return; } #if !LL_RELEASE_FOR_DOWNLOAD @@ -1130,8 +1129,8 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) #endif if (!getData().empty() /*&& !LLSpatialPartition::sFreezeState*/) { - mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() : - (F32) mOctreeNode->getSize().magVec(); + mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : + (F32) mOctreeNode->getSize().getLength3().getF32(); mDistance = mSpatialPartition->calcDistance(this, camera); mPixelArea = mSpatialPartition->calcPixelArea(this, camera); } @@ -1139,24 +1138,31 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) { - LLVector3 eye = group->mObjectBounds[0] - camera.getOrigin(); + LLVector4a eye; + LLVector4a origin; + origin.load3(camera.getOrigin().mV); + + eye.setSub(group->mObjectBounds[0], origin); F32 dist = 0.f; if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end()) { - LLVector3 v = eye; - dist = eye.normVec(); + LLVector4a v = eye; + + dist = eye.getLength3().getF32(); + eye.normalize3fast(); if (!group->isState(LLSpatialGroup::ALPHA_DIRTY)) { if (!group->mSpatialPartition->isBridge()) { - LLVector3 view_angle = eye;/*LLVector3(eye * LLVector3(1,0,0), //WTF is this? - eye * LLVector3(0,1,0), - eye * LLVector3(0,0,1));*/ + LLVector4a view_angle = eye; - if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f) + LLVector4a diff; + diff.setSub(view_angle, group->mLastUpdateViewAngle); + + if (diff.getLength3().getF32() > 0.64f) { group->mViewAngle = view_angle; group->mLastUpdateViewAngle = view_angle; @@ -1173,17 +1179,20 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) LLVector3 at = camera.getAtAxis(); - //front of bounding box - for (U32 i = 0; i < 3; i++) - { - v.mV[i] -= group->mObjectBounds[1].mV[i]*0.25f * at.mV[i]; - } + LLVector4a ata; + ata.load3(at.mV); - group->mDepth = v * at; + LLVector4a t = ata; + //front of bounding box + t.mul(0.25f); + t.mul(group->mObjectBounds[1]); + v.sub(t); + + group->mDepth = v.dot3(ata).getF32(); } else { - dist = eye.magVec(); + dist = eye.getLength3().getF32(); } if (dist < 16.f) @@ -1211,7 +1220,7 @@ F32 LLSpatialGroup::getUpdateUrgency() const { //return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance; F32 time = gFrameTimeSeconds-mLastUpdateTime+4.f; - return (time + (mObjectBounds[1]*mObjectBounds[1]) + 1.f)/mDistance; + return time + (mObjectBounds[1].dot3(mObjectBounds[1]).getF32()+1.f)/mDistance; } } @@ -1223,7 +1232,7 @@ BOOL LLSpatialGroup::needsUpdate() BOOL LLSpatialGroup::changeLOD() { if (isState(ALPHA_DIRTY | OBJECT_DIRTY)) - { ///an alpha sort is going to happen, update distance and LOD + { ///a rebuild is going to happen, update distance and LoD return TRUE; } @@ -1236,7 +1245,6 @@ BOOL LLSpatialGroup::changeLOD() return TRUE; } - //if (mDistance > mRadius) if (mDistance > mRadius*2.f) { return FALSE; @@ -1323,6 +1331,7 @@ void LLSpatialGroup::destroyGL() { setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); gPipeline.markRebuild(this, TRUE); + mLastUpdateTime = gFrameTimeSeconds; mVertexBuffer = NULL; mBufferMap.clear(); @@ -1338,7 +1347,6 @@ void LLSpatialGroup::destroyGL() } } - delete [] mOcclusionVerts; mOcclusionVerts = NULL; for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i) @@ -1380,8 +1388,8 @@ BOOL LLSpatialGroup::rebound() } else { - LLVector3& newMin = mExtents[0]; - LLVector3& newMax = mExtents[1]; + LLVector4a& newMin = mExtents[0]; + LLVector4a& newMax = mExtents[1]; LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0); group->clearState(SKIP_FRUSTUM_CHECK); group->rebound(); @@ -1395,26 +1403,19 @@ BOOL LLSpatialGroup::rebound() group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0); group->clearState(SKIP_FRUSTUM_CHECK); group->rebound(); - const LLVector3& max = group->mExtents[1]; - const LLVector3& min = group->mExtents[0]; + const LLVector4a& max = group->mExtents[1]; + const LLVector4a& min = group->mExtents[0]; - for (U32 j = 0; j < 3; j++) - { - if (max.mV[j] > newMax.mV[j]) - { - newMax.mV[j] = max.mV[j]; - } - if (min.mV[j] < newMin.mV[j]) - { - newMin.mV[j] = min.mV[j]; - } - } + newMax.setMax(newMax, max); + newMin.setMin(newMin, min); } boundObjects(FALSE, newMin, newMax); - mBounds[0] = (newMin + newMax)*0.5f; - mBounds[1] = (newMax - newMin)*0.5f; + mBounds[0].setAdd(newMin, newMax); + mBounds[0].mul(0.5f); + mBounds[1].setSub(newMax, newMin); + mBounds[1].mul(0.5f); } setState(OCCLUSION_DIRTY); @@ -1448,10 +1449,10 @@ void LLSpatialGroup::checkOcclusion() if (available) { //result is available, read it back, otherwise wait until next frame - GLuint res = 1; - if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res); + GLuint res = 1; + if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { + glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res); #if LL_TRACK_PENDING_OCCLUSION_QUERIES sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]); #endif @@ -1462,25 +1463,25 @@ void LLSpatialGroup::checkOcclusion() mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; } - if (isOcclusionState(DISCARD_QUERY)) - { - res = 2; - } + if (isOcclusionState(DISCARD_QUERY)) + { + res = 2; + } - if (res > 0) - { - assert_states_valid(this); - clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); - assert_states_valid(this); - } - else - { - assert_states_valid(this); - setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); - assert_states_valid(this); - } + if (res > 0) + { + assert_states_valid(this); + clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } + else + { + assert_states_valid(this); + setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } - clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); + clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); } } else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED)) @@ -1519,7 +1520,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate(); } - if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY)) + if (mOcclusionVerts.isNull() || isState(LLSpatialGroup::OCCLUSION_DIRTY)) { buildOcclusion(); } @@ -1534,7 +1535,7 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0); #if !LL_DARWIN - U32 mode = gGLManager.mHasOcclusionQuery2 ? /*GL_ANY_SAMPLES_PASSED*/0x8C2F : GL_SAMPLES_PASSED_ARB; + U32 mode = gGLManager.mHasOcclusionQuery2 ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED_ARB; #else U32 mode = GL_SAMPLES_PASSED_ARB; #endif @@ -1546,37 +1547,32 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera) { //LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS); glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); - glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts); + + mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); + if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER) { LLGLSquashToFarClip squash(glh_get_current_projection(), 1); if (camera->getOrigin().isExactlyZero()) { //origin is invalid, draw entire box - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, sOcclusionIndices); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8); + mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); + mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); } else { - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_box_fan_indices_ptr(camera, mBounds[0])); + mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); } } else { if (camera->getOrigin().isExactlyZero()) { //origin is invalid, draw entire box - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, sOcclusionIndices); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8); - + mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); + mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); } else { - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_box_fan_indices_ptr(camera, mBounds[0])); + mOcclusionVerts->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); } } @@ -1611,9 +1607,11 @@ LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mSlopRatio = 0.25f; mInfiniteFarClip = FALSE; + LLVector4a center, size; + center.splat(0.f); + size.splat(1.f); - mOctree = new LLSpatialGroup::OctreeRoot(LLVector3d(0,0,0), - LLVector3d(1,1,1), + mOctree = new LLSpatialGroup::OctreeRoot(center,size, NULL); new LLSpatialGroup(mOctree, this); } @@ -1633,7 +1631,6 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); drawablep->updateSpatialExtents(); - validate_drawable(drawablep); //keep drawable from being garbage collected LLPointer<LLDrawable> ptr = drawablep; @@ -1717,15 +1714,16 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL class LLSpatialShift : public LLSpatialGroup::OctreeTraveler { public: - const LLVector3& mOffset; - LLSpatialShift(const LLVector3 &offset) : mOffset(offset) { } + const LLVector4a& mOffset; + + LLSpatialShift(const LLVector4a& offset) : mOffset(offset) { } virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); } }; -void LLSpatialPartition::shift(const LLVector3 &offset) +void LLSpatialPartition::shift(const LLVector4a &offset) { //shift octree node bounding boxes by offset LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); LLSpatialShift shifter(offset); @@ -1887,7 +1885,7 @@ public: class LLOctreeCullVisExtents: public LLOctreeCullShadow { public: - LLOctreeCullVisExtents(LLCamera* camera, LLVector3& min, LLVector3& max) + LLOctreeCullVisExtents(LLCamera* camera, LLVector4a& min, LLVector4a& max) : LLOctreeCullShadow(camera), mMin(min), mMax(max), mEmpty(TRUE) { } virtual bool earlyFail(LLSpatialGroup* group) @@ -1931,11 +1929,8 @@ public: virtual void processGroup(LLSpatialGroup* group) { - if (group->isState(LLSpatialGroup::DIRTY) || group->getData().empty()) - { - llerrs << "WTF?" << llendl; - } - + llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->getData().empty()) + if (mRes < 2) { if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0) @@ -1954,8 +1949,8 @@ public: } BOOL mEmpty; - LLVector3& mMin; - LLVector3& mMax; + LLVector4a& mMin; + LLVector4a& mMax; }; class LLOctreeCullDetectVisible: public LLOctreeCullShadow @@ -2061,6 +2056,11 @@ void drawBox(const LLVector3& c, const LLVector3& r) gGL.end(); } +void drawBox(const LLVector4a& c, const LLVector4a& r) +{ + drawBox(reinterpret_cast<const LLVector3&>(c), reinterpret_cast<const LLVector3&>(r)); +} + void drawBoxOutline(const LLVector3& pos, const LLVector3& size) { LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); @@ -2107,6 +2107,11 @@ void drawBoxOutline(const LLVector3& pos, const LLVector3& size) gGL.end(); } +void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size) +{ + drawBoxOutline(reinterpret_cast<const LLVector3&>(pos), reinterpret_cast<const LLVector3&>(size)); +} + class LLOctreeDirty : public LLOctreeTraveler<LLDrawable> { public: @@ -2150,13 +2155,20 @@ BOOL LLSpatialPartition::isOcclusionEnabled() BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) { + LLVector4a visMina, visMaxa; + visMina.load3(visMin.mV); + visMaxa.load3(visMax.mV); { LLFastTimer ftm( LLFastTimer::FTM_CULL_REBOUND); LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); group->rebound(); } - LLOctreeCullVisExtents vis(&camera, visMin, visMax); + + LLOctreeCullVisExtents vis(&camera, visMina, visMaxa); vis.traverse(mOctree); + + visMin.set(visMina.getF32ptr()); + visMax.set(visMaxa.getF32ptr()); return vis.mEmpty; } @@ -2222,25 +2234,36 @@ BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) } const F32 vel = SG_OCCLUSION_FUDGE*2.f; - LLVector3 c = group->mBounds[0]; - LLVector3 r = group->mBounds[1] + LLVector3(vel,vel,vel); - + LLVector4a fudge; + fudge.splat(vel); + + const LLVector4a& c = group->mBounds[0]; + LLVector4a r; + r.setAdd(group->mBounds[1], fudge); + /*if (r.magVecSquared() > 1024.0*1024.0) { return TRUE; }*/ - LLVector3 e = camera->getOrigin(); + LLVector4a e; + e.load3(camera->getOrigin().mV); - LLVector3 min = c - r; - LLVector3 max = c + r; + LLVector4a min; + min.setSub(c,r); + LLVector4a max; + max.setAdd(c,r); - for (U32 j = 0; j < 3; j++) + S32 lt = e.lessThan(min).getGatheredBits() & 0x7; + if (lt) { - if (e.mV[j] < min.mV[j] || e.mV[j] > max.mV[j]) - { - return FALSE; - } + return FALSE; + } + + S32 gt = e.greaterThan(max).getGatheredBits() & 0x7; + if (gt) + { + return FALSE; } return TRUE; @@ -2271,6 +2294,8 @@ void pushVerts(LLSpatialGroup* group, U32 mask) void pushVerts(LLFace* face, U32 mask) { + llassert(face->verify()); + LLVertexBuffer* buffer = face->getVertexBuffer(); if (buffer) @@ -2282,7 +2307,25 @@ void pushVerts(LLFace* face, U32 mask) U16 offset = face->getIndicesStart(); buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset); } +} +void pushVerts(LLDrawable* drawable, U32 mask) +{ + for (S32 i = 0; i < drawable->getNumFaces(); ++i) + { + pushVerts(drawable->getFace(i), mask); + } +} + +void pushVerts(LLVolume* volume) +{ + LLVertexBuffer::unbind(); + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& face = volume->getVolumeFace(i); + glVertexPointer(3, GL_FLOAT, 16, face.mPositions); + glDrawElements(GL_TRIANGLES, face.mNumIndices, GL_UNSIGNED_SHORT, face.mIndices); + } } void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) @@ -2446,10 +2489,15 @@ void renderOctree(LLSpatialGroup* group) } gGL.color4fv(col.mV); + LLVector4a fudge; + fudge.splat(0.001f); + LLVector4a size = group->mObjectBounds[1]; + size.mul(1.01f); + size.add(fudge); { LLGLDepthTest depth(GL_TRUE, GL_FALSE); - drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); + drawBox(group->mObjectBounds[0], fudge); } gGL.setSceneBlendType(LLRender::BT_ALPHA); @@ -2481,8 +2529,12 @@ void renderOctree(LLSpatialGroup* group) for (LLSpatialGroup::drawmap_elem_t::iterator j = i->second.begin(); j != i->second.end(); ++j) { LLDrawInfo* draw_info = *j; - LLVector3 center = (draw_info->mExtents[1] + draw_info->mExtents[0])*0.5f; - LLVector3 size = (draw_info->mExtents[1] - draw_info->mExtents[0])*0.5f; + LLVector4a center; + center.setAdd(draw_info->mExtents[1], draw_info->mExtents[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(draw_info->mExtents[1], draw_info->mExtents[0]); + size.mul(0.5f); drawBoxOutline(center, size); } } @@ -2655,8 +2707,8 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) } } - const LLVector3* ext; - LLVector3 pos, size; + const LLVector4a* ext; + LLVector4a pos, size; //render face bounding boxes for (S32 i = 0; i < drawable->getNumFaces(); i++) @@ -2665,20 +2717,21 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE) ext = facep->mExtents; - if (ext[0].isExactlyZero() && ext[1].isExactlyZero()) - { - continue; - } - pos = (ext[0] + ext[1]) * 0.5f; - size = (ext[1] - ext[0]) * 0.5f; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + drawBoxOutline(pos,size); } //render drawable bounding box ext = drawable->getSpatialExtents(); - pos = (ext[0] + ext[1]) * 0.5f; - size = (ext[1] - ext[0]) * 0.5f; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + size.setSub(ext[1], ext[0]); + size.mul(0.5f); LLViewerObject* vobj = drawable->getVObj(); if (vobj && vobj->onActiveList()) @@ -2734,8 +2787,13 @@ void renderTexturePriority(LLDrawable* drawable) // gGL.color4f(1,0,1,1); //} - LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f; - LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f); + LLVector4a center; + center.setAdd(facep->mExtents[1],facep->mExtents[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(facep->mExtents[1],facep->mExtents[0]); + size.mul(0.5f); + size.add(LLVector4a(0.01f)); drawBox(center, size); /*S32 boost = imagep->getBoostLevel(); @@ -2781,6 +2839,8 @@ void renderTextureAnim(LLDrawInfo* params) void renderBatchSize(LLDrawInfo* params) { + LLGLEnable offset(GL_POLYGON_OFFSET_FILL); + glPolygonOffset(-1.f, 1.f); glColor3ubv((GLubyte*) &(params->mDebugColor)); pushVerts(params, LLVertexBuffer::MAP_VERTEX); } @@ -2802,10 +2862,14 @@ void renderLights(LLDrawable* drawablep) pushVerts(drawablep->getFace(i), LLVertexBuffer::MAP_VERTEX); } - const LLVector3* ext = drawablep->getSpatialExtents(); + const LLVector4a* ext = drawablep->getSpatialExtents(); - LLVector3 pos = (ext[0] + ext[1]) * 0.5f; - LLVector3 size = (ext[1] - ext[0]) * 0.5f; + LLVector4a pos; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); { LLGLDepthTest depth(GL_FALSE, GL_TRUE); @@ -2815,7 +2879,7 @@ void renderLights(LLDrawable* drawablep) gGL.color4f(1,1,0,1); F32 rad = drawablep->getVOVolume()->getLightRadius(); - drawBoxOutline(pos, LLVector3(rad,rad,rad)); + drawBoxOutline(pos, LLVector4a(rad)); } } @@ -2864,11 +2928,15 @@ void renderRaycast(LLDrawable* drawablep) drawBox(LLVector3(0, 0, 0), LLVector3(0.02f, 0.02f, 0.1f)); glPopMatrix(); - // draw bounding box of prim - const LLVector3* ext = drawablep->getSpatialExtents(); + // draw bounding box of prim + const LLVector4a* ext = drawablep->getSpatialExtents(); - LLVector3 pos = (ext[0] + ext[1]) * 0.5f; - LLVector3 size = (ext[1] - ext[0]) * 0.5f; + LLVector4a pos; + pos.setAdd(ext[0], ext[1]); + pos.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); LLGLDepthTest depth(GL_FALSE, GL_TRUE); gGL.color4f(0,0.5f,0.5f,1); @@ -2955,8 +3023,8 @@ public: return; } - LLVector3 nodeCenter = group->mBounds[0]; - LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter()); + LLVector4a nodeCenter = group->mBounds[0]; + LLVector4a octCenter = group->mOctreeNode->getCenter(); group->rebuildGeom(); group->rebuildMesh(); @@ -2985,8 +3053,14 @@ public: if (drawable->isState(LLDrawable::IN_REBUILD_Q2)) { gGL.color4f(0.6f, 0.6f, 0.1f, 1.f); - const LLVector3* ext = drawable->getSpatialExtents(); - drawBoxOutline((ext[0]+ext[1])*0.5f, (ext[1]-ext[0])*0.5f); + const LLVector4a* ext = drawable->getSpatialExtents(); + LLVector4a center; + center.setAdd(ext[0], ext[1]); + center.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); + drawBoxOutline(center, size); } } @@ -3026,6 +3100,28 @@ public: renderAgentTarget(avatar); } + if (gDebugGL) + { + for (U32 i = 0; i < (U32)drawable->getNumFaces(); ++i) + { + LLFace* facep = drawable->getFace(i); + U8 index = facep->getTextureIndex(); + if (facep->mDrawInfo) + { + if (index < 255) + { + if (facep->mDrawInfo->mTextureList.size() <= index) + { + llerrs << "Face texture index out of bounds." << llendl; + } + else if (facep->mDrawInfo->mTextureList[index] != facep->getTexture()) + { + llerrs << "Face texture index incorrect." << llendl; + } + } + } + } + } } for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) @@ -3217,9 +3313,17 @@ void LLSpatialPartition::renderDebug() void LLSpatialGroup::drawObjectBox(LLColor4 col) { gGL.color4fv(col.mV); - drawBox(mObjectBounds[0], mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); + LLVector4a size; + size = mObjectBounds[1]; + size.mul(1.01f); + size.add(LLVector4a(0.001f)); + drawBox(mObjectBounds[0], size); } +bool LLSpatialPartition::isHUDPartition() +{ + return mPartitionType == LLViewerRegion::PARTITION_HUD ; +} BOOL LLSpatialPartition::isVisible(const LLVector3& v) { @@ -3277,8 +3381,8 @@ public: LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0); - LLVector3 size; - LLVector3 center; + LLVector4a size; + LLVector4a center; size = group->mBounds[1]; center = group->mBounds[0]; @@ -3295,7 +3399,11 @@ public: local_end = mEnd * local_matrix; } - if (LLLineSegmentBoxIntersect(local_start, local_end, center, size)) + LLVector4a start, end; + start.load3(local_start.mV); + end.load3(local_end.mV); + + if (LLLineSegmentBoxIntersect(start, end, center, size)) { check(child); } @@ -3330,7 +3438,31 @@ public: if (vobj) { LLVector3 intersection; - if (vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal)) + bool skip_check = false; +#if MESH_ENABLED + if (vobj->isAvatar()) + { + LLVOAvatar* avatar = (LLVOAvatar*) vobj; + if (avatar->isSelf() && gFloaterTools->getVisible()) + { + LLViewerObject* hit = avatar->lineSegmentIntersectRiggedAttachments(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal); + if (hit) + { + mEnd = intersection; + if (mIntersection) + { + *mIntersection = intersection; + } + + mHit = hit->mDrawable; + skip_check = true; + } + + } + } +#endif //MESH_ENABLED + + if (!skip_check && vobj->lineSegmentIntersect(mStart, mEnd, -1, mPickTransparent, mFaceHit, &intersection, mTexCoord, mNormal, mBinormal)) { mEnd = intersection; // shorten ray so we only find CLOSER hits if (mIntersection) @@ -3384,18 +3516,9 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, mFace(NULL), mDistance(0.f) { - mDebugColor = (rand() << 16) + rand(); - if (mStart >= mVertexBuffer->getRequestedVerts() || - mEnd >= mVertexBuffer->getRequestedVerts()) - { - llerrs << "Invalid draw info vertex range." << llendl; - } + mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); - if (mOffset >= (U32) mVertexBuffer->getRequestedIndices() || - mOffset + mCount > (U32) mVertexBuffer->getRequestedIndices()) - { - llerrs << "Invalid draw info index range." << llendl; - } + mDebugColor = (rand() << 16) + rand(); } LLDrawInfo::~LLDrawInfo() @@ -3416,6 +3539,11 @@ LLDrawInfo::~LLDrawInfo() } } +void LLDrawInfo::validate() +{ + mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); +} + LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) { return new LLVertexBuffer(type_mask, usage); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index debbeb780..803c63680 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -54,11 +54,16 @@ class LLSpatialPartition; class LLSpatialBridge; class LLSpatialGroup; +S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad); +S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &radius_squared); + S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad); S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared); +void pushVerts(LLFace* face, U32 mask); // get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera -U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector3& center); +U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center); +U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center); class LLDrawInfo : public LLRefCount { @@ -66,13 +71,31 @@ protected: ~LLDrawInfo(); public: + + LLDrawInfo(const LLDrawInfo& rhs) + { + *this = rhs; + } + + const LLDrawInfo& operator=(const LLDrawInfo& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + LLDrawInfo(U16 start, U16 end, U32 count, U32 offset, LLViewerTexture* image, LLVertexBuffer* buffer, BOOL fullbright = FALSE, U8 bump = 0, BOOL particle = FALSE, F32 part_size = 0); + void validate(); + + LLVector4a mExtents[2]; + LLPointer<LLVertexBuffer> mVertexBuffer; - LLPointer<LLViewerTexture> mTexture; + LLPointer<LLViewerTexture> mTexture; + std::vector<LLPointer<LLViewerTexture> > mTextureList; + LLColor4U mGlowColor; S32 mDebugColor; const LLMatrix4* mTextureMatrix; @@ -89,7 +112,6 @@ public: LLSpatialGroup* mGroup; LLFace* mFace; //associated face F32 mDistance; - LLVector3 mExtents[2]; struct CompareTexture { @@ -151,11 +173,24 @@ public: }; }; +LL_ALIGN_PREFIX(64) class LLSpatialGroup : public LLOctreeListener<LLDrawable> { friend class LLSpatialPartition; friend class LLOctreeStateCheck; public: + + LLSpatialGroup(const LLSpatialGroup& rhs) + { + *this = rhs; + } + + const LLSpatialGroup& operator=(const LLSpatialGroup& rhs) + { + llerrs << "Illegal operation!" << llendl; + return *this; + } + static std::set<GLuint> sPendingQueries; //pending occlusion queries static U32 sNodeCount; static BOOL sNoDelete; //deletion of spatial groups and draw info not allowed if TRUE @@ -165,7 +200,7 @@ public: typedef std::vector<LLPointer<LLDrawInfo> > drawmap_elem_t; typedef std::map<U32, drawmap_elem_t > draw_map_t; typedef std::vector<LLPointer<LLVertexBuffer> > buffer_list_t; - typedef std::map<LLPointer<LLViewerTexture>, buffer_list_t> buffer_texture_map_t; + typedef std::map<LLFace*, buffer_list_t> buffer_texture_map_t; typedef std::map<U32, buffer_texture_map_t> buffer_map_t; typedef LLOctreeListener<LLDrawable> BaseType; @@ -238,6 +273,7 @@ public: LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part); + BOOL isHUDGroup() ; BOOL isDead() { return isState(DEAD); } BOOL isState(eSpatialState state) const; //Using enum type here and below to force type-safeness. BOOL isOcclusionState(eOcclusionState state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; } @@ -265,8 +301,8 @@ public: BOOL isVisible() const; BOOL isRecentlyVisible() const; void setVisible(); - void shift(const LLVector3 &offset); - BOOL boundObjects(BOOL empty, LLVector3& newMin, LLVector3& newMax); + void shift(const LLVector4a &offset); + BOOL boundObjects(BOOL empty, LLVector4a& newMin, LLVector4a& newMax); void unbound(); BOOL rebound(); void buildOcclusion(); //rebuild mOcclusionVerts @@ -296,13 +332,24 @@ public: virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child); - LLVector3 mBounds[2]; - LLVector3 mExtents[2]; - - LLVector3 mObjectExtents[2]; - LLVector3 mObjectBounds[2]; - LLVector3 mViewAngle; - LLVector3 mLastUpdateViewAngle; + typedef enum + { + BOUNDS = 0, + EXTENTS = 2, + OBJECT_BOUNDS = 4, + OBJECT_EXTENTS = 6, + VIEW_ANGLE = 8, + LAST_VIEW_ANGLE = 9, + V4_COUNT = 10 + } eV4Index; + + LLVector4a mBounds[2]; // bounding box (center, size) of this node and all its children (tight fit to objects) + LLVector4a mExtents[2]; // extents (min, max) of this node and all its children + LLVector4a mObjectExtents[2]; // extents (min, max) of objects in this node + LLVector4a mObjectBounds[2]; // bounding box (center, size) of objects in this node + LLVector4a mViewAngle; + LLVector4a mLastUpdateViewAngle; + protected: virtual ~LLSpatialGroup(); @@ -318,9 +365,9 @@ public: F32 mBuilt; OctreeNode* mOctreeNode; LLSpatialPartition* mSpatialPartition; - + LLPointer<LLVertexBuffer> mVertexBuffer; - F32* mOcclusionVerts; + LLPointer<LLVertexBuffer> mOcclusionVerts; GLuint mOcclusionQuery[LLViewerCamera::NUM_CAMERAS]; U32 mBufferUsage; @@ -334,7 +381,7 @@ public: F32 mPixelArea; F32 mRadius; -}; +} LL_ALIGN_POSTFIX(64); inline LLSpatialGroup::eOcclusionState operator|(const LLSpatialGroup::eOcclusionState &a, const LLSpatialGroup::eOcclusionState &b) { @@ -380,7 +427,7 @@ public: // If the drawable moves, move it here. virtual void move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate = FALSE); - virtual void shift(const LLVector3 &offset); + virtual void shift(const LLVector4a &offset); virtual F32 calcDistance(LLSpatialGroup* group, LLCamera& camera); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); @@ -392,6 +439,7 @@ public: S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum BOOL isVisible(const LLVector3& v); + bool isHUDPartition() ; virtual LLSpatialBridge* asBridge() { return NULL; } virtual BOOL isBridge() { return asBridge() != NULL; } @@ -438,7 +486,7 @@ public: virtual void makeActive(); virtual void move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate = FALSE); virtual BOOL updateMove(); - virtual void shiftPos(const LLVector3& vec); + virtual void shiftPos(const LLVector4a& vec); virtual void cleanupReferences(); virtual LLSpatialPartition* asPartition() { return this; } virtual LLSpatialBridge* asBridge() { return this; } @@ -600,7 +648,7 @@ public: virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); - void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE); + void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); }; @@ -631,7 +679,7 @@ class LLHUDBridge : public LLVolumeBridge { public: LLHUDBridge(LLDrawable* drawablep); - virtual void shiftPos(const LLVector3& vec); + virtual void shiftPos(const LLVector4a& vec); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); }; @@ -648,11 +696,9 @@ class LLHUDPartition : public LLBridgePartition { public: LLHUDPartition(); - virtual void shift(const LLVector3 &offset); + virtual void shift(const LLVector4a &offset); }; -void validate_draw_info(LLDrawInfo& params); - extern const F32 SG_BOX_SIDE; extern const F32 SG_BOX_OFFSET; extern const F32 SG_BOX_RAD; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index b854358c9..8897d1f62 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -72,6 +72,8 @@ #include "llmemorystream.h" #include "llmessageconfig.h" #include "llmoveview.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llregionhandle.h" #include "llsd.h" #include "llsdserialize.h" @@ -370,6 +372,8 @@ bool idle_startup() static U64 first_sim_handle = 0; static LLHost first_sim; static std::string first_sim_seed_cap; + static U32 first_sim_size_x = 256; + static U32 first_sim_size_y = 256; static LLVector3 initial_sun_direction(1.f, 0.f, 0.f); static LLVector3 agent_start_position_region(10.f, 10.f, 10.f); // default for when no space server @@ -422,12 +426,12 @@ bool idle_startup() if (LLFeatureManager::getInstance()->isSafe()) { - LLNotifications::instance().add("DisplaySetToSafe"); + LLNotificationsUtil::add("DisplaySetToSafe"); } else if ((gSavedSettings.getS32("LastFeatureVersion") < LLFeatureManager::getInstance()->getVersion()) && (gSavedSettings.getS32("LastFeatureVersion") != 0)) { - LLNotifications::instance().add("DisplaySetToRecommended"); + LLNotificationsUtil::add("DisplaySetToRecommended"); } else if (!gViewerWindow->getInitAlert().empty()) { @@ -1586,7 +1590,7 @@ bool idle_startup() std::string history_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "saved_logins_sg2.xml"); LLSavedLogins history_data = LLSavedLogins::loadFile(history_file); - std::string grid_nick = gHippoGridManager->getConnectedGrid()->getGridNick(); + std::string grid_nick = gHippoGridManager->getConnectedGrid()->getGridName(); history_data.deleteEntry(firstname, lastname, grid_nick); if (gSavedSettings.getBOOL("RememberLogin")) { @@ -1657,7 +1661,17 @@ bool idle_startup() U32 region_y = strtoul(region_y_str.c_str(), NULL, 10); first_sim_handle = to_region_handle(region_x, region_y); } - + + text = LLUserAuth::getInstance()->getResponse("region_size_x"); + if(!text.empty()) { + first_sim_size_x = strtoul(text.c_str(), NULL, 10); + LLViewerParcelMgr::getInstance()->init(first_sim_size_x); + } + + //region Y size is currently unused, major refactoring required. - Patrick Sapinski (2/10/2011) + text = LLUserAuth::getInstance()->getResponse("region_size_y"); + if(!text.empty()) first_sim_size_y = strtoul(text.c_str(), NULL, 10); + const std::string look_at_str = LLUserAuth::getInstance()->getResponse("look_at"); if (!look_at_str.empty()) { @@ -1785,7 +1799,6 @@ bool idle_startup() { gSavedSettings.setString("MapServerURL", map_server_url); LLWorldMap::gotMapServerURL(true); - llinfos << "Got Map server URL: " << map_server_url << llendl; } // Override grid info with anything sent in the login response @@ -1862,7 +1875,7 @@ bool idle_startup() // Bounce back to the login screen. LLSD args; args["ERROR_MESSAGE"] = emsg.str(); - LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done); + LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); reset_login(); gSavedSettings.setBOOL("AutoLogin", FALSE); show_connect_box = true; @@ -1882,7 +1895,7 @@ bool idle_startup() // Bounce back to the login screen. LLSD args; args["ERROR_MESSAGE"] = emsg.str(); - LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done); + LLNotificationsUtil::add("ErrorMessage", args, LLSD(), login_alert_done); reset_login(); gSavedSettings.setBOOL("AutoLogin", FALSE); show_connect_box = true; @@ -1925,9 +1938,7 @@ bool idle_startup() // init the shader managers LLPostProcess::initClass(); - LLWLParamManager::initClass(); AscentDayCycleManager::initClass(); - LLWaterParamManager::initClass(); // RN: don't initialize VO classes in drone mode, they are too closely tied to rendering LLViewerObject::initVOClasses(); @@ -1946,7 +1957,7 @@ bool idle_startup() gAgent.initOriginGlobal(from_region_handle(first_sim_handle)); - LLWorld::getInstance()->addRegion(first_sim_handle, first_sim); + LLWorld::getInstance()->addRegion(first_sim_handle, first_sim, first_sim_size_x, first_sim_size_y); LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(first_sim_handle); LL_INFOS("AppInit") << "Adding initial simulator " << regionp->getOriginGlobal() << LL_ENDL; @@ -2617,7 +2628,7 @@ bool idle_startup() // Could schedule and delay these for later. const BOOL no_inform_server = FALSE; const BOOL no_deactivate_similar = FALSE; - gGestureManager.activateGestureWithAsset(item_id, asset_id, + LLGestureMgr::instance().activateGestureWithAsset(item_id, asset_id, no_inform_server, no_deactivate_similar); // We need to fetch the inventory items for these gestures @@ -2646,9 +2657,6 @@ bool idle_startup() gForegroundTime.reset(); if (gSavedSettings.getBOOL("FetchInventoryOnLogin") -#ifdef LL_RRINTERFACE_H //MK - || gRRenabled -#endif //mk ) { // Fetch inventory in the background @@ -2696,7 +2704,7 @@ bool idle_startup() args["TYPE"] = "home"; args["HELP"] = "You may want to set a new home location."; } - LLNotifications::instance().add("AvatarMoved", args); + LLNotificationsUtil::add("AvatarMoved", args); } else { @@ -2797,7 +2805,7 @@ bool idle_startup() // initial outfit, but if the load hasn't started // already then something is wrong so fall back // to generic outfits. JC - LLNotifications::instance().add("WelcomeChooseSex", LLSD(), LLSD(), + LLNotificationsUtil::add("WelcomeChooseSex", LLSD(), LLSD(), callback_choose_gender); LLStartUp::setStartupState( STATE_CLEANUP ); return TRUE; @@ -2805,7 +2813,7 @@ bool idle_startup() if (wearables_time > MAX_WEARABLES_TIME) { - LLNotifications::instance().add("ClothingLoading"); + LLNotificationsUtil::add("ClothingLoading"); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_WEARABLES_TOO_LONG); LLStartUp::setStartupState( STATE_CLEANUP ); return TRUE; @@ -3093,7 +3101,7 @@ void LLStartUp::deletePasswordFromDisk() void show_first_run_dialog() { - LLNotifications::instance().add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback); + LLNotificationsUtil::add("FirstRun", LLSD(), LLSD(), first_run_dialog_callback); } bool first_run_dialog_callback(const LLSD& notification, const LLSD& response) @@ -3380,7 +3388,7 @@ void use_circuit_callback(void**, S32 result) { // Make sure user knows something bad happened. JC LL_WARNS("AppInit") << "Backing up to login screen!" << LL_ENDL; - LLNotifications::instance().add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); + LLNotificationsUtil::add("LoginPacketNeverReceived", LLSD(), LLSD(), login_alert_status); reset_login(); } else @@ -3967,33 +3975,33 @@ bool LLStartUp::handleSocksProxy(bool reportOK) case SOCKS_OK: if (reportOK == true) { - LLNotifications::instance().add("SOCKS_CONNECT_OK", subs); + LLNotificationsUtil::add("SOCKS_CONNECT_OK", subs); } return true; break; case SOCKS_CONNECT_ERROR: // TCP Fail - LLNotifications::instance().add("SOCKS_CONNECT_ERROR", subs); + LLNotificationsUtil::add("SOCKS_CONNECT_ERROR", subs); break; case SOCKS_NOT_PERMITTED: // Socks5 server rule set refused connection - LLNotifications::instance().add("SOCKS_NOT_PERMITTED", subs); + LLNotificationsUtil::add("SOCKS_NOT_PERMITTED", subs); break; case SOCKS_NOT_ACCEPTABLE: // Selected authentication is not acceptable to server - LLNotifications::instance().add("SOCKS_NOT_ACCEPTABLE", subs); + LLNotificationsUtil::add("SOCKS_NOT_ACCEPTABLE", subs); break; case SOCKS_AUTH_FAIL: // Authentication failed - LLNotifications::instance().add("SOCKS_AUTH_FAIL", subs); + LLNotificationsUtil::add("SOCKS_AUTH_FAIL", subs); break; case SOCKS_UDP_FWD_NOT_GRANTED: // UDP forward request failed - LLNotifications::instance().add("SOCKS_UDP_FWD_NOT_GRANTED", subs); + LLNotificationsUtil::add("SOCKS_UDP_FWD_NOT_GRANTED", subs); break; case SOCKS_HOST_CONNECT_FAILED: // Failed to open a TCP channel to the socks server - LLNotifications::instance().add("SOCKS_HOST_CONNECT_FAILED", subs); + LLNotificationsUtil::add("SOCKS_HOST_CONNECT_FAILED", subs); break; } diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index bcfd312ae..5b0b508b5 100644 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -69,6 +69,7 @@ #include "llviewerthrottle.h" #include "lluictrlfactory.h" #include "llvoiceclient.h" // for gVoiceClient +#include "llagentui.h" #include "lltoolmgr.h" #include "llfocusmgr.h" @@ -79,6 +80,7 @@ #include "llfontgl.h" #include "llrect.h" #include "llerror.h" +#include "llnotificationsutil.h" #include "llparcel.h" #include "llstring.h" #include "message.h" @@ -495,11 +497,10 @@ void LLStatusBar::refresh() mRegionDetails.mPing = region->getNetDetailsForLCD(); if (parcel) { - location_name = region->getName() - + llformat(" %d, %d, %d (%s) - %s", - pos_x, pos_y, pos_z, - region->getSimAccessString().c_str(), - parcel->getName().c_str()); + if (!LLAgentUI::buildLocationString(location_name, LLAgentUI::LOCATION_FORMAT_FULL)) + { + location_name = "???"; + } // keep these around for the LCD to use mRegionDetails.mRegionName = region->getName(); @@ -683,8 +684,7 @@ void LLStatusBar::setBalance(S32 balance) if( balance != mBalance ) { - mBalanceTimer->reset(); - mBalanceTimer->setTimerExpirySec( ICON_TIMER_EXPIRY ); + mBalanceTimer->reset(ICON_TIMER_EXPIRY); mBalance = balance; } } @@ -728,8 +728,7 @@ void LLStatusBar::setHealth(S32 health) } } - mHealthTimer->reset(); - mHealthTimer->setTimerExpirySec( ICON_TIMER_EXPIRY ); + mHealthTimer->reset(ICON_TIMER_EXPIRY); } mHealth = health; @@ -794,7 +793,7 @@ static void onClickBuyCurrency(void* data) static void onClickHealth(void* ) { - LLNotifications::instance().add("NotSafe"); + LLNotificationsUtil::add("NotSafe"); } static void onClickScriptDebug(void*) @@ -804,22 +803,22 @@ static void onClickScriptDebug(void*) static void onClickFly(void* ) { - LLNotifications::instance().add("NoFly"); + LLNotificationsUtil::add("NoFly"); } static void onClickPush(void* ) { - LLNotifications::instance().add("PushRestricted"); + LLNotificationsUtil::add("PushRestricted"); } static void onClickVoice(void* ) { - LLNotifications::instance().add("NoVoice"); + LLNotificationsUtil::add("NoVoice"); } static void onClickBuild(void*) { - LLNotifications::instance().add("NoBuild"); + LLNotificationsUtil::add("NoBuild"); } static void onClickScripts(void*) @@ -827,15 +826,15 @@ static void onClickScripts(void*) LLViewerRegion* region = gAgent.getRegion(); if(region && region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) { - LLNotifications::instance().add("ScriptsStopped"); + LLNotificationsUtil::add("ScriptsStopped"); } else if(region && region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) { - LLNotifications::instance().add("ScriptsNotRunning"); + LLNotificationsUtil::add("ScriptsNotRunning"); } else { - LLNotifications::instance().add("NoOutsideScripts"); + LLNotificationsUtil::add("NoOutsideScripts"); } } diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp index 9d718e88c..e0dc129ad 100644 --- a/indra/newview/llsurface.cpp +++ b/indra/newview/llsurface.cpp @@ -176,6 +176,7 @@ void LLSurface::create(const S32 grids_per_edge, mNumberOfPatches = mPatchesPerEdge * mPatchesPerEdge; mMetersPerGrid = width / ((F32)(mGridsPerEdge - 1)); mMetersPerEdge = mMetersPerGrid * (mGridsPerEdge - 1); + sTextureSize = width; mOriginGlobal.setVec(origin_global); @@ -299,7 +300,7 @@ void LLSurface::initTextures() mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp); gPipeline.createObject(mWaterObjp); LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle()); - water_pos_global += LLVector3d(128.0, 128.0, DEFAULT_WATER_HEIGHT); + water_pos_global += LLVector3d(mRegionp->getWidth()/2, mRegionp->getWidth()/2, DEFAULT_WATER_HEIGHT); mWaterObjp->setPositionGlobal(water_pos_global); } } @@ -329,8 +330,8 @@ void LLSurface::setOriginGlobal(const LLVector3d &origin_global) // Hack! if (mWaterObjp.notNull() && mWaterObjp->mDrawable.notNull()) { - const F64 x = origin_global.mdV[VX] + 128.0; - const F64 y = origin_global.mdV[VY] + 128.0; + const F64 x = origin_global.mdV[VX] + (F64)mRegionp->getWidth()/2; + const F64 y = origin_global.mdV[VY] + (F64)mRegionp->getWidth()/2; const F64 z = mWaterObjp->getPositionGlobal().mdV[VZ]; LLVector3d water_origin_global(x, y, z); @@ -339,17 +340,28 @@ void LLSurface::setOriginGlobal(const LLVector3d &origin_global) } } +void LLSurface::getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions ) +{ + S32 i; + for (i = 0; i < 8; i++) + { + if ( mNeighbors[i] != NULL ) + { + uniqueRegions.push_back( mNeighbors[i]->getRegion() ); + } + } +} void LLSurface::connectNeighbor(LLSurface *neighborp, U32 direction) { - S32 i; - LLSurfacePatch *patchp, *neighbor_patchp; - if (gNoRender) { return; } + S32 i; + LLSurfacePatch *patchp, *neighbor_patchp; + mNeighbors[direction] = neighborp; neighborp->mNeighbors[gDirOpposite[direction]] = this; @@ -680,14 +692,22 @@ void LLSurface::decompressDCTPatch(LLBitPack &bitpack, LLGroupHeader *gopp, BOOL while (1) { - decode_patch_header(bitpack, &ph); + decode_patch_header(bitpack, &ph, b_large_patch); if (ph.quant_wbits == END_OF_PATCHES) { break; } - i = ph.patchids >> 5; - j = ph.patchids & 0x1F; + if (b_large_patch) + { + i = ph.patchids >> 16; //x + j = ph.patchids & 0xFFFF; //y + } + else + { + i = ph.patchids >> 5; //x + j = ph.patchids & 0x1F; //y + } if ((i >= mPatchesPerEdge) || (j >= mPatchesPerEdge)) { diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h index 7e11b9a22..127bec465 100644 --- a/indra/newview/llsurface.h +++ b/indra/newview/llsurface.h @@ -146,6 +146,9 @@ public: friend class LLSurfacePatch; friend std::ostream& operator<<(std::ostream &s, const LLSurface &S); + + void getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions ); + public: // Number of grid points on one side of a region, including +1 buffer for // north and east edge. diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp index 48e4a6ccc..06431d428 100644 --- a/indra/newview/llsurfacepatch.cpp +++ b/indra/newview/llsurfacepatch.cpp @@ -860,8 +860,10 @@ void LLSurfacePatch::updateVisibility() F32 stride_per_distance = DEFAULT_DELTA_ANGLE / mSurfacep->getMetersPerGrid(); U32 grids_per_patch_edge = mSurfacep->getGridsPerPatchEdge(); - LLVector3 center = mCenterRegion + mSurfacep->getOriginAgent(); - LLVector3 radius = LLVector3(mRadius, mRadius, mRadius); + LLVector4a center; + center.load3( (mCenterRegion + mSurfacep->getOriginAgent()).mV); + LLVector4a radius; + radius.splat(mRadius); // sphere in frustum on global coordinates if (LLViewerCamera::getInstance()->AABBInFrustumNoFarClip(center, radius)) diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp index 17a1a3ce9..e2ec067ca 100644 --- a/indra/newview/lltexlayer.cpp +++ b/indra/newview/lltexlayer.cpp @@ -266,11 +266,19 @@ BOOL LLTexLayerSetBuffer::render() BOOL upload_now = needsUploadNow(); BOOL success = TRUE; + //hack to use fixed function when updating tex layer sets + bool no_ff = LLGLSLShader::sNoFixedFunction; + static const LLCachedControl<bool> force_fixed_functions("ShyotlUseLegacyTextureBaking",true); + if(force_fixed_functions) + LLGLSLShader::sNoFixedFunction = false; + // Composite the color data LLGLSUIDefault gls_ui; success &= mTexLayerSet->render( mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight ); gGL.flush(); + LLGLSLShader::sNoFixedFunction = no_ff; + if( upload_now ) { if (!success) diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 73583c769..4da777c5b 100644 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -748,14 +748,13 @@ LLTextureCache::LLTextureCache(bool threaded) mTexturesSizeTotal(0), mDoPurge(FALSE) { - purgeTextureFilesTimeSliced(true); - clearDeleteList(); - writeUpdatedEntries(); } LLTextureCache::~LLTextureCache() { - purgeTextureFilesTimeSliced(TRUE); // VWR-3878 - NB - force-flush all pending file deletes + clearDeleteList(); + writeUpdatedEntries(); + purgeTextureFilesTimeSliced(true); // VWR-3878 - NB - force-flush all pending file deletes } ////////////////////////////////////////////////////////////////////////////// @@ -1556,7 +1555,7 @@ void LLTextureCache::purgeTextures(bool validate) return; } - if (!validate && mTexturesSizeTotal < sCacheMaxTexturesSize) + if (!validate && mTexturesSizeTotal <= sCacheMaxTexturesSize) { return; } @@ -1569,6 +1568,8 @@ void LLTextureCache::purgeTextures(bool validate) LLMutexLock lock(&mHeaderMutex); + llinfos << "TEXTURE CACHE: Purging." << llendl; + // Read the entries list std::vector<Entry> entries; U32 num_entries = openAndReadEntries(entries); @@ -1597,10 +1598,10 @@ void LLTextureCache::purgeTextures(bool validate) } else { - LL_WARNS("TextureCache") << "mTexturesSizeMap / mHeaderIDMap corrupted." << LL_ENDL; - clearCorruptedCache(); - LLAppViewer::instance()->resumeMainloopTimeout(); - return; + llerrs << "mTexturesSizeMap / mHeaderIDMap corrupted." << llendl ; + //clearCorruptedCache(); + //LLAppViewer::instance()->resumeMainloopTimeout(); + //return; } } } @@ -1652,9 +1653,10 @@ void LLTextureCache::purgeTextures(bool validate) if (purge_entry) { purge_count++; + LL_DEBUGS("TextureCache") << "PURGING: " << filename << LL_ENDL; mFilesToDelete.insert(std::make_pair(entries[idx].mID, filename)); - cache_size -= entries[idx].mBodySize; removeEntry(idx, entries[idx], filename, false); // remove the entry but not the file + cache_size -= entries[idx].mBodySize; } } @@ -1662,26 +1664,17 @@ void LLTextureCache::purgeTextures(bool validate) writeEntriesAndClose(entries); - if (purge_count > 0) - { - writeEntriesAndClose(entries); - - LL_INFOS("TextureCache") << "TEXTURE CACHE:" - << " Purged: " << purge_count - << " - Entries: " << num_entries - << " - Cache size: " << mTexturesSizeTotal / (1024 * 1024) << " MB" - << " - Files scheduled for deletion: " << mFilesToDelete.size() - << LL_ENDL; - } - else - { - LL_INFOS("TextureCache") << "TEXTURE CACHE: nothing to purge." << LL_ENDL; - } - - // *FIX:Mani - watchdog back on. - LLAppViewer::instance()->resumeMainloopTimeout(); + // *FIX:Mani - watchdog back on. + LLAppViewer::instance()->resumeMainloopTimeout(); mSlicedPurgeTimer.reset(); + + LL_INFOS("TextureCache") << "TEXTURE CACHE:" + << " PURGED: " << purge_count + << " ENTRIES: " << num_entries + << " CACHE SIZE: " << mTexturesSizeTotal / (1024 * 1024) << " MB" + << llendl; + } void LLTextureCache::purgeTextureFilesTimeSliced(bool force) @@ -1947,8 +1940,7 @@ void LLTextureCache::removeCachedTexture(const LLUUID& id) mTexturesSizeMap.erase(id); } mHeaderIDMap.erase(id); - std::string filename = getTextureFileName(id); - LLAPRFile::remove(filename); + LLAPRFile::remove(getTextureFileName(id)); } //called after mHeaderMutex is locked. diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index cd74d3d73..a72d6b5e0 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -308,9 +308,9 @@ public: const LLChannelDescriptors& channels, const LLIOPipe::buffer_ptr_t& buffer) { - static LLCachedControl<bool> log_to_viewer_log("LogTextureDownloadsToViewerLog",false); - static LLCachedControl<bool> log_to_sim("LogTextureDownloadsToSimulator",false); - static bool log_texture_traffic = false; + static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog"); + static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator"); + static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; if (log_to_viewer_log || log_to_sim) { @@ -472,6 +472,30 @@ public: LLMutex* SGHostBlackList::sMutex = 0; SGHostBlackList::blacklist_t SGHostBlackList::blacklist; +//call every time a connection is opened +//return true if connecting allowed +static bool sgConnectionThrottle() { + static LLMutex mutex; + LLMutexLock lock(&mutex); + const U32 THROTTLE_TIMESTEPS_PER_SECOND = 10; + static const LLCachedControl<U32> max_connections_per_second("HTTPRequestRate", 30); + U32 max_connections = max_connections_per_second/THROTTLE_TIMESTEPS_PER_SECOND; + const U32 timestep = USEC_PER_SEC/THROTTLE_TIMESTEPS_PER_SECOND; + U64 now = LLTimer::getTotalTime(); + std::deque<U64> timestamps; + while(!timestamps.empty() && (timestamps[0]<=now-timestep)) { + timestamps.pop_front(); + } + if(timestamps.size() < max_connections) { + //llinfos << "throttle pass" << llendl; + timestamps.push_back(now); + return true; + } else { + //llinfos << "throttle fail" << llendl; + return false; + } +} + #if HTTP_METRICS // Cross-thread messaging for asset metrics. @@ -637,7 +661,6 @@ public: * Corresponds to LLTextureFetch::commandSendMetrics() */ -#if HTTP_METRICS class TFReqSendMetrics : public LLTextureFetch::TFRequest { public: @@ -681,7 +704,6 @@ public: const LLUUID mAgentID; LLViewerAssetStats * mMainStats; }; -#endif /* * Examines the merged viewer metrics report and if found to be too long, @@ -1107,7 +1129,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == LOAD_FROM_NETWORK) { - static const LLCachedControl<bool> use_http("ImagePipelineUseHTTP", false); + static LLCachedControl<bool> use_http(gSavedSettings,"ImagePipelineUseHTTP"); // if (mHost != LLHost::invalid) use_http = false; if (use_http && mCanUseHTTP && mUrl.empty()) // get http url. @@ -1120,7 +1142,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (region) { - std::string http_url = region->getCapability("GetTexture"); + std::string http_url = region->getHttpUrl() ; if (!http_url.empty()) { mUrl = http_url + "/?texture_id=" + mID.asString().c_str(); @@ -1250,11 +1272,12 @@ bool LLTextureFetchWorker::doWork(S32 param) //1, not openning too many file descriptors at the same time; //2, control the traffic of http so udp gets bandwidth. // - static const S32 MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE = 32; - static const S32 NUM_REQUESTS_TILL_THRESHOLDING = 2; - if((mFetcher->getNumHTTPRequests() > MAX_NUM_OF_HTTP_REQUESTS_IN_QUEUE) || + static const LLCachedControl<U32> max_http_requests("HTTPMaxRequests", 32); + static const LLCachedControl<U32> min_http_requests("HTTPMinRequests", 2); + if(((U32)mFetcher->getNumHTTPRequests() > max_http_requests) || ((mFetcher->getTextureBandwidth() > mFetcher->mMaxBandwidth) && - mFetcher->getNumHTTPRequests() > NUM_REQUESTS_TILL_THRESHOLDING)) + ((U32)mFetcher->getNumHTTPRequests() > min_http_requests)) || + !sgConnectionThrottle()) { return false ; //wait. } @@ -1461,7 +1484,7 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == DECODE_IMAGE) { - static LLCachedControl<bool> textures_decode_disabled("TextureDecodeDisabled", false); + static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); if(textures_decode_disabled) { // for debug use, don't decode @@ -2058,8 +2081,8 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con unlockQueue() ; worker->lockWorkMutex(); - worker->mActiveCount++; - worker->mNeedsAux = needs_aux; + worker->mActiveCount++; + worker->mNeedsAux = needs_aux; worker->setCanUseHTTP(can_use_http) ; worker->unlockWorkMutex(); } @@ -2323,6 +2346,7 @@ void LLTextureFetch::commonUpdate() #endif // Update Curl on same thread as mCurlGetRequest was constructed + llassert_always(mCurlGetRequest); S32 processed = mCurlGetRequest->process(); if (processed > 0) { @@ -2334,12 +2358,13 @@ void LLTextureFetch::commonUpdate() //virtual S32 LLTextureFetch::update(U32 max_time_ms) { + static LLCachedControl<F32> band_width(gSavedSettings,"ThrottleBandwidthKBPS"); + { mNetworkQueueMutex.lock() ; - static const LLCachedControl<F32> max_bandwidth("ThrottleBandwidthKBPS", 2000); - mMaxBandwidth = max_bandwidth; - - gTextureList.sTextureBits += mHTTPTextureBits; + mMaxBandwidth = band_width ; + + gTextureList.sTextureBits += mHTTPTextureBits ; mHTTPTextureBits = 0 ; mNetworkQueueMutex.unlock() ; @@ -2541,8 +2566,8 @@ void LLTextureFetch::sendRequestListToSimulators() // llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard // << " Packet: " << packet << " Priority: " << req->mImagePriority << llendl; - static LLCachedControl<bool> log_to_viewer_log("LogTextureDownloadsToViewerLog",false); - static LLCachedControl<bool> log_to_sim("LogTextureDownloadsToSimulator",false); + static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog"); + static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator"); if (log_to_viewer_log || log_to_sim) { mTextureInfo.setRequestStartTime(req->mID, LLTimer::getTotalTime()); @@ -2709,8 +2734,8 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 res = worker->insertPacket(0, data, data_size); worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR; - worker->unlockWorkMutex(); - return res; + worker->unlockWorkMutex(); + return res; } bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data) @@ -2763,8 +2788,8 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 if(packet_num >= (worker->mTotalPackets - 1)) { - static LLCachedControl<bool> log_to_viewer_log("LogTextureDownloadsToViewerLog",false); - static LLCachedControl<bool> log_to_sim("LogTextureDownloadsToSimulator",false); + static LLCachedControl<bool> log_to_viewer_log(gSavedSettings,"LogTextureDownloadsToViewerLog"); + static LLCachedControl<bool> log_to_sim(gSavedSettings,"LogTextureDownloadsToSimulator"); if (log_to_viewer_log || log_to_sim) { diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 2ce0c5ff4..736a6dafa 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -421,12 +421,16 @@ void LLGLTexMemBar::draw() std::string text; + S32 global_raw_memory; + { + global_raw_memory = *AIAccess<S32>(LLImageRaw::sGlobalRawMemory); + } text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB", total_mem, max_total_mem, bound_mem, max_bound_mem, - LLImageRaw::sGlobalRawMemory >> 20, discard_bias, + global_raw_memory >> 20, discard_bias, cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded); //, cache_entries, cache_max_entries diff --git a/indra/newview/lltool.cpp b/indra/newview/lltool.cpp index da9f3c5bd..1a11957fb 100644 --- a/indra/newview/lltool.cpp +++ b/indra/newview/lltool.cpp @@ -39,6 +39,7 @@ #include "llview.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "lltoolcomp.h" #include "lltoolfocus.h" #include "llfocusmgr.h" diff --git a/indra/newview/lltoolbar.cpp b/indra/newview/lltoolbar.cpp index 593a382cd..8f5c767a5 100644 --- a/indra/newview/lltoolbar.cpp +++ b/indra/newview/lltoolbar.cpp @@ -126,7 +126,6 @@ LLToolBar::LLToolBar() BOOL LLToolBar::postBuild() { childSetCommitCallback("communicate_btn", onClickCommunicate, this); - childSetControlName("communicate_btn", "ShowCommunicate"); childSetAction("chat_btn", onClickChat, this); childSetControlName("chat_btn", "ChatVisible"); @@ -135,7 +134,7 @@ BOOL LLToolBar::postBuild() childSetControlName("appearance_btn", ""); childSetAction("radar_list_btn", onClickRadarList, this); - childSetControlName("radar_list_btn", "RadarListBtnState"); + childSetControlName("radar_list_btn", "ShowRadar"); childSetAction("fly_btn", onClickFly, this); childSetControlName("fly_btn", "FlyBtnState"); @@ -144,7 +143,7 @@ BOOL LLToolBar::postBuild() childSetControlName("sit_btn", "SitBtnState"); childSetAction("snapshot_btn", onClickSnapshot, this); - childSetControlName("snapshot_btn", ""); + childSetControlName("snapshot_btn", "SnapshotBtnState"); childSetAction("directory_btn", onClickDirectory, this); childSetControlName("directory_btn", "ShowDirectory"); @@ -301,7 +300,7 @@ void LLToolBar::refresh() childSetEnabled("fly_btn", (gAgent.canFly() || gAgent.getFlying() || gSavedSettings.getBOOL("AscentFlyAlwaysEnabled")) && !sitting ); - childSetEnabled("build_btn", (LLViewerParcelMgr::getInstance()->agentCanBuild() || gSavedSettings.getBOOL("AscentBuildAlwaysEnabled")) ); + childSetEnabled("build_btn", (LLViewerParcelMgr::getInstance()->allowAgentBuild() || gSavedSettings.getBOOL("AscentBuildAlwaysEnabled")) ); // Check to see if we're in build mode BOOL build_mode = LLToolMgr::getInstance()->inEdit(); @@ -478,11 +477,6 @@ void LLToolBar::onClickAppearance(void*) void LLToolBar::onClickRadarList(void*) { LLFloaterAvatarList::toggle(0); - bool vis = false; - if(LLFloaterAvatarList::getInstance()) - { - vis = (bool)LLFloaterAvatarList::getInstance()->getVisible(); - } } diff --git a/indra/newview/lltoolbrush.cpp b/indra/newview/lltoolbrush.cpp index c42693d03..b1268fc1d 100644 --- a/indra/newview/lltoolbrush.cpp +++ b/indra/newview/lltoolbrush.cpp @@ -36,6 +36,7 @@ #include "lltoolselectland.h" #include "llgl.h" +#include "llnotificationsutil.h" #include "llrender.h" #include "message.h" @@ -43,6 +44,7 @@ #include "llagent.h" #include "llcallbacklist.h" #include "llviewercontrol.h" +#include "llwindow.h" #include "llfloatertools.h" #include "llregionposition.h" #include "llstatusbar.h" @@ -672,7 +674,7 @@ void LLToolBrushLand::alertNoTerraform(LLViewerRegion* regionp) LLSD args; args["REGION"] = regionp->getName(); - LLNotifications::instance().add("RegionNoTerraforming", args); + LLNotificationsUtil::add("RegionNoTerraforming", args); } diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index a21dc6a61..64fd39527 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -35,6 +35,8 @@ #include "message.h" #include "lltooldraganddrop.h" +#include "llnotificationsutil.h" + #include "llinstantmessage.h" #include "lldir.h" @@ -49,6 +51,7 @@ #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llinventorybridge.h" +#include "llinventorydefines.h" #include "llinventorymodel.h" #include "llinventoryview.h" #include "llmutelist.h" @@ -98,7 +101,7 @@ public: virtual bool operator()(LLInventoryCategory* cat, LLInventoryItem* item) { - if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE)) + if(cat && (cat->getPreferredType() == LLFolderType::FT_NONE)) { return true; } @@ -115,7 +118,7 @@ public: LLInventoryItem* item) { if(item) return true; - if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE)) + if(cat && (cat->getPreferredType() == LLFolderType::FT_NONE)) { return true; } @@ -1086,7 +1089,7 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, hit_obj->fetchInventoryFromServer(); LLSD args; args["ERROR_MESSAGE"] = "Unable to add texture.\nPlease wait a few seconds and try again."; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); return FALSE; } if (hit_obj->getInventoryItemByAsset(item->getAssetUUID())) @@ -1579,7 +1582,7 @@ void LLToolDragAndDrop::giveInventory(const LLUUID& to_agent, LLSD payload; payload["agent_id"] = to_agent; payload["item_id"] = item->getUUID(); - LLNotifications::instance().add("CannotCopyWarning", LLSD(), payload, + LLNotificationsUtil::add("CannotCopyWarning", LLSD(), payload, &LLToolDragAndDrop::handleCopyProtectedItem); } } @@ -1603,12 +1606,12 @@ bool LLToolDragAndDrop::handleCopyProtectedItem(const LLSD& notification, const } else { - LLNotifications::instance().add("CannotGiveItem"); + LLNotificationsUtil::add("CannotGiveItem"); } break; default: // no, cancel, whatever, who cares, not yes. - LLNotifications::instance().add("TransactionCancelled"); + LLNotificationsUtil::add("TransactionCancelled"); break; } return false; @@ -1708,18 +1711,18 @@ void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent, } if(!complete) { - LLNotifications::instance().add("IncompleteInventory"); + LLNotificationsUtil::add("IncompleteInventory"); return; } count = items.count() + cats.count(); if(count > MAX_ITEMS) { - LLNotifications::instance().add("TooManyItems"); + LLNotificationsUtil::add("TooManyItems"); return; } else if(count == 0) { - LLNotifications::instance().add("NoItems"); + LLNotificationsUtil::add("NoItems"); return; } else @@ -1737,7 +1740,7 @@ void LLToolDragAndDrop::giveInventoryCategory(const LLUUID& to_agent, LLSD payload; payload["agent_id"] = to_agent; payload["folder_id"] = cat->getUUID(); - LLNotifications::instance().add("CannotCopyCountItems", args, payload, &LLToolDragAndDrop::handleCopyProtectedCategory); + LLNotificationsUtil::add("CannotCopyCountItems", args, payload, &LLToolDragAndDrop::handleCopyProtectedCategory); } } } @@ -1773,12 +1776,12 @@ bool LLToolDragAndDrop::handleCopyProtectedCategory(const LLSD& notification, co } else { - LLNotifications::instance().add("CannotGiveCategory"); + LLNotificationsUtil::add("CannotGiveCategory"); } break; default: // no, cancel, whatever, who cares, not yes. - LLNotifications::instance().add("TransactionCancelled"); + LLNotificationsUtil::add("TransactionCancelled"); break; } return false; @@ -1810,12 +1813,12 @@ void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent, S32 count = items.count() + cats.count(); if(count > MAX_ITEMS) { - LLNotifications::instance().add("TooManyItems"); + LLNotificationsUtil::add("TooManyItems"); return; } else if(count == 0) { - LLNotifications::instance().add("NoItems"); + LLNotificationsUtil::add("NoItems"); return; } else @@ -2561,7 +2564,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearItem( // destroy clothing items. if (!gAgentWearables.areWearablesLoaded()) { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); return ACCEPT_NO; } @@ -2628,7 +2631,7 @@ EAcceptance LLToolDragAndDrop::dad3dActivateGesture( } else { - gGestureManager.activateGesture(item->getUUID()); + LLGestureMgr::instance().activateGesture(item->getUUID()); gInventory.updateItem(item); gInventory.notifyObservers(); } @@ -2656,7 +2659,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory( // destroy clothing items. if (!gAgentWearables.areWearablesLoaded()) { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); return ACCEPT_NO; } } diff --git a/indra/newview/lltoolgun.cpp b/indra/newview/lltoolgun.cpp index fa65eafd9..055236f43 100644 --- a/indra/newview/lltoolgun.cpp +++ b/indra/newview/lltoolgun.cpp @@ -49,6 +49,9 @@ #include "lltoolmgr.h" #include "lltoolgrab.h" +// Linden library includes +#include "llwindow.h" // setMouseClipping() + LLToolGun::LLToolGun( LLToolComposite* composite ) : LLTool( std::string("gun"), composite ), mIsSelected(FALSE) @@ -138,7 +141,7 @@ void LLToolGun::draw() { LLUIImagePtr crosshair = LLUI::getUIImage("UIImgCrosshairsUUID"); crosshair->draw( - ( gViewerWindow->getWindowWidth() - crosshair->getWidth() ) / 2, - ( gViewerWindow->getWindowHeight() - crosshair->getHeight() ) / 2); + ( gViewerWindow->getWorldViewRectScaled().getWidth() - crosshair->getWidth() ) / 2, + ( gViewerWindow->getWorldViewRectScaled().getHeight() - crosshair->getHeight() ) / 2); } } diff --git a/indra/newview/lltoolobjpicker.cpp b/indra/newview/lltoolobjpicker.cpp index d69688706..db150bbed 100644 --- a/indra/newview/lltoolobjpicker.cpp +++ b/indra/newview/lltoolobjpicker.cpp @@ -47,6 +47,7 @@ #include "llviewermenu.h" #include "llviewercamera.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "lldrawable.h" diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index e26e039e4..82e30203e 100644 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -63,6 +63,7 @@ #include "llviewerobject.h" #include "llviewerparcelmgr.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llviewermedia.h" #include "llviewermediafocus.h" #include "llvoavatar.h" diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index b2a61a4ac..4710a096a 100644 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -50,6 +50,7 @@ #include "llviewerobject.h" #include "llviewerregion.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llworld.h" #include "llui.h" diff --git a/indra/newview/lltoolselectland.cpp b/indra/newview/lltoolselectland.cpp index f80b4e3ad..0c6637828 100644 --- a/indra/newview/lltoolselectland.cpp +++ b/indra/newview/lltoolselectland.cpp @@ -44,6 +44,7 @@ #include "llstatusbar.h" #include "llviewerparcelmgr.h" #include "llviewerwindow.h" +#include "llwindow.h" // // Member functions diff --git a/indra/newview/lltoolselectrect.cpp b/indra/newview/lltoolselectrect.cpp index 890666f34..f57820afd 100644 --- a/indra/newview/lltoolselectrect.cpp +++ b/indra/newview/lltoolselectrect.cpp @@ -48,6 +48,7 @@ #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llviewercamera.h" #include "llglheaders.h" diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp index 299db5c1a..d5b66e61b 100644 --- a/indra/newview/lltracker.cpp +++ b/indra/newview/lltracker.cpp @@ -56,6 +56,7 @@ #include "llfloaterworldmap.h" #include "llhudtext.h" #include "llhudview.h" +#include "llinventorydefines.h" #include "llinventorymodel.h" #include "lllandmarklist.h" #include "llsky.h" diff --git a/indra/newview/lltrans.cpp b/indra/newview/lltrans.cpp index b6a2382a9..187782d5e 100644 --- a/indra/newview/lltrans.cpp +++ b/indra/newview/lltrans.cpp @@ -36,6 +36,7 @@ #include "llxmlnode.h" #include "lluictrlfactory.h" #include "llalertdialog.h" +#include "llnotificationsutil.h" #include <map> @@ -93,7 +94,7 @@ std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil:: LLSD args; args["STRING_NAME"] = xml_desc; LL_WARNS_ONCE("configuration") << "Missing String in strings.xml: [" << xml_desc << "]" << LL_ENDL; - LLNotifications::instance().add("MissingString", args); + LLNotificationsUtil::add("MissingString", args); return xml_desc; } diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp index b0817f64b..5bab702cf 100644 --- a/indra/newview/llviewerassettype.cpp +++ b/indra/newview/llviewerassettype.cpp @@ -36,6 +36,7 @@ #include "llviewerassettype.h" #include "lldictionary.h" #include "llmemory.h" +#include "llsingleton.h" static const std::string empty_string; diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index be3330bda..d58a4d0f5 100644 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -31,19 +31,13 @@ */ #include "llviewerprecompiledheaders.h" + #include "llviewercamera.h" -#include <iomanip> // for setprecision - -#include "llquaternion.h" - #include "llagent.h" #include "llagentcamera.h" +#include "llmatrix4a.h" #include "llviewercontrol.h" -#include "lldrawable.h" -#include "llface.h" -#include "llgl.h" -#include "llglheaders.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llviewerwindow.h" @@ -52,6 +46,17 @@ #include "lltoolmgr.h" #include "llviewerjoystick.h" +// Linden library includes +#include "lldrawable.h" +#include "llface.h" +#include "llgl.h" +#include "llglheaders.h" +#include "llquaternion.h" +#include "llwindow.h" // getPixelAspectRatio() + +// System includes +#include <iomanip> // for setprecision + U32 LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; //glu pick matrix implementation borrowed from Mesa3D @@ -112,15 +117,15 @@ LLViewerCamera::LLViewerCamera() : LLCamera() mZoomSubregion = 1; mAverageSpeed = 0.f; mAverageAngularSpeed = 0.f; + gSavedSettings.getControl("CameraAngle")->getCommitSignal()->connect(boost::bind(&LLViewerCamera::updateCameraAngle, this, _2)); } void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, const LLVector3 &up_direction, const LLVector3 &point_of_interest) { - // do not update if we are in build mode AND avatar didn't move - if (LLToolMgr::getInstance()->inBuildMode() - && !LLViewerJoystick::getInstance()->getCameraNeedsUpdate()) + // do not update if avatar didn't move + if (!LLViewerJoystick::getInstance()->getCameraNeedsUpdate()) { return; } @@ -330,7 +335,12 @@ void LLViewerCamera::setPerspective(BOOL for_selection, { // make a tiny little viewport // anything drawn into this viewport will be "selected" - GLint* viewport = (GLint*) gGLViewport; + + GLint viewport[4]; + viewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + viewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + viewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + viewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); proj_mat = gl_pick_matrix(x+width/2.f, y_from_bot+height/2.f, (GLfloat) width, (GLfloat) height, viewport); @@ -397,10 +407,13 @@ void LLViewerCamera::setPerspective(BOOL for_selection, if (for_selection && (width > 1 || height > 1)) { - calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f, - (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f, - (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidth() - 0.5f, - (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeight() - 0.5f); + // NB: as of this writing, i believe the code below is broken (doesn't take into account the world view, assumes entire window) + // however, it is also unused (the GL matricies are used for selection, (see LLCamera::sphereInFrustum())) and so i'm not + // comfortable hacking on it. + calculateFrustumPlanesFromWindow((F32)(x - width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, + (F32)(y_from_bot - height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f, + (F32)(x + width / 2) / (F32)gViewerWindow->getWindowWidthScaled() - 0.5f, + (F32)(y_from_bot + height / 2) / (F32)gViewerWindow->getWindowHeightScaled() - 0.5f); } @@ -465,8 +478,15 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord } } + LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); + S32 viewport[4]; + viewport[0] = world_view_rect.mLeft; + viewport[1] = world_view_rect.mBottom; + viewport[2] = world_view_rect.getWidth(); + viewport[3] = world_view_rect.getHeight(); + if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ], - gGLModelView, gGLProjection, (GLint*)gGLViewport, + gGLModelView, gGLProjection, (GLint*)viewport, &x, &y, &z)) { // convert screen coordinates to virtual UI coordinates @@ -474,7 +494,7 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord y /= gViewerWindow->getDisplayScale().mV[VY]; // should now have the x,y coords of grab_point in screen space - const LLRect& window_rect = gViewerWindow->getWindowRect(); + LLRect world_rect = gViewerWindow->getWorldViewRectScaled(); // ...sanity check S32 int_x = lltrunc(x); @@ -484,14 +504,14 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord if (clamp) { - if (int_x < window_rect.mLeft) + if (int_x < world_rect.mLeft) { - out_point.mX = window_rect.mLeft; + out_point.mX = world_rect.mLeft; valid = FALSE; } - else if (int_x > window_rect.mRight) + else if (int_x > world_rect.mRight) { - out_point.mX = window_rect.mRight; + out_point.mX = world_rect.mRight; valid = FALSE; } else @@ -499,14 +519,14 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord out_point.mX = int_x; } - if (int_y < window_rect.mBottom) + if (int_y < world_rect.mBottom) { - out_point.mY = window_rect.mBottom; + out_point.mY = world_rect.mBottom; valid = FALSE; } - else if (int_y > window_rect.mTop) + else if (int_y > world_rect.mTop) { - out_point.mY = window_rect.mTop; + out_point.mY = world_rect.mTop; valid = FALSE; } else @@ -520,19 +540,19 @@ BOOL LLViewerCamera::projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoord out_point.mX = int_x; out_point.mY = int_y; - if (int_x < window_rect.mLeft) + if (int_x < world_rect.mLeft) { valid = FALSE; } - else if (int_x > window_rect.mRight) + else if (int_x > world_rect.mRight) { valid = FALSE; } - if (int_y < window_rect.mBottom) + if (int_y < world_rect.mBottom) { valid = FALSE; } - else if (int_y > window_rect.mTop) + else if (int_y > world_rect.mTop) { valid = FALSE; } @@ -561,24 +581,30 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, in_front = FALSE; } + LLRect world_view_rect = gViewerWindow->getWorldViewRectRaw(); + S32 viewport[4]; + viewport[0] = world_view_rect.mLeft; + viewport[1] = world_view_rect.mBottom; + viewport[2] = world_view_rect.getWidth(); + viewport[3] = world_view_rect.getHeight(); GLdouble x, y, z; // object's window coords, GL-style if (GL_TRUE == gluProject(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ], gGLModelView, - gGLProjection, (GLint*)gGLViewport, + gGLProjection, (GLint*)viewport, &x, &y, &z)) { x /= gViewerWindow->getDisplayScale().mV[VX]; y /= gViewerWindow->getDisplayScale().mV[VY]; // should now have the x,y coords of grab_point in screen space - const LLRect& window_rect = gViewerWindow->getVirtualWindowRect(); + const LLRect& world_rect = gViewerWindow->getWorldViewRectScaled(); // ...sanity check S32 int_x = lltrunc(x); S32 int_y = lltrunc(y); // find the center - GLdouble center_x = (GLdouble)(0.5f * (window_rect.mLeft + window_rect.mRight)); - GLdouble center_y = (GLdouble)(0.5f * (window_rect.mBottom + window_rect.mTop)); + GLdouble center_x = (GLdouble)world_rect.getCenterX(); + GLdouble center_y = (GLdouble)world_rect.getCenterY(); if (x == center_x && y == center_y) { @@ -599,41 +625,41 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, // the slope of the line is undefined if (line_y > 0.f) { - int_y = window_rect.mTop; + int_y = world_rect.mTop; } else { - int_y = window_rect.mBottom; + int_y = world_rect.mBottom; } } - else if (0 == window_rect.getWidth()) + else if (0 == world_rect.getWidth()) { // the diagonal slope of the view is undefined - if (y < window_rect.mBottom) + if (y < world_rect.mBottom) { - int_y = window_rect.mBottom; + int_y = world_rect.mBottom; } - else if ( y > window_rect.mTop) + else if ( y > world_rect.mTop) { - int_y = window_rect.mTop; + int_y = world_rect.mTop; } } else { F32 line_slope = (F32)(line_y / line_x); - F32 rect_slope = ((F32)window_rect.getHeight()) / ((F32)window_rect.getWidth()); + F32 rect_slope = ((F32)world_rect.getHeight()) / ((F32)world_rect.getWidth()); if (fabs(line_slope) > rect_slope) { if (line_y < 0.f) { // bottom - int_y = window_rect.mBottom; + int_y = world_rect.mBottom; } else { // top - int_y = window_rect.mTop; + int_y = world_rect.mTop; } int_x = lltrunc(((GLdouble)int_y - center_y) / line_slope + center_x); } @@ -642,12 +668,12 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, if (line_x < 0.f) { // left - int_x = window_rect.mLeft; + int_x = world_rect.mLeft; } else { // right - int_x = window_rect.mRight; + int_x = world_rect.mRight; } int_y = lltrunc(((GLdouble)int_x - center_x) * line_slope + center_y); } @@ -656,29 +682,30 @@ BOOL LLViewerCamera::projectPosAgentToScreenEdge(const LLVector3 &pos_agent, // exactly parallel ==> push to the corners if (line_x > 0.f) { - int_x = window_rect.mRight; + int_x = world_rect.mRight; } else { - int_x = window_rect.mLeft; + int_x = world_rect.mLeft; } if (line_y > 0.0f) { - int_y = window_rect.mTop; + int_y = world_rect.mTop; } else { - int_y = window_rect.mBottom; + int_y = world_rect.mBottom; } } } if (!in_front) { - int_x = window_rect.mLeft + window_rect.mRight - int_x; - int_y = window_rect.mBottom + window_rect.mTop - int_y; + int_x = world_rect.mLeft + world_rect.mRight - int_x; + int_y = world_rect.mBottom + world_rect.mTop - int_y; } - out_point.mX = int_x; - out_point.mY = int_y; + + out_point.mX = int_x + world_rect.mLeft; + out_point.mY = int_y + world_rect.mBottom; return TRUE; } return FALSE; @@ -760,21 +787,29 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition())); + LLMatrix4a render_mata; + render_mata.loadu(render_mat); + LLMatrix4a mata; + mata.loadu(mat); + num_faces = volume->getNumVolumeFaces(); for (i = 0; i < num_faces; i++) { const LLVolumeFace& face = volume->getVolumeFace(i); - for (U32 v = 0; v < face.mVertices.size(); v++) + for (U32 v = 0; v < (U32)face.mNumVertices; v++) { - LLVector4 vec = LLVector4(face.mVertices[v].mPosition) * mat; + const LLVector4a& src_vec = face.mPositions[v]; + LLVector4a vec; + mata.affineTransform(src_vec, vec); if (drawablep->isActive()) { - vec = vec * render_mat; + LLVector4a t = vec; + render_mata.affineTransform(t, vec); } - BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0; + BOOL in_frustum = pointInFrustum(LLVector3(vec.getF32ptr())) > 0; if (( !in_frustum && all_verts) || (in_frustum && !all_verts)) @@ -822,3 +857,10 @@ void LLViewerCamera::setDefaultFOV(F32 vertical_fov_rads) mCosHalfCameraFOV = cosf(mCameraFOVDefault * 0.5f); } + +// static +void LLViewerCamera::updateCameraAngle( void* user_data, const LLSD& value) +{ + LLViewerCamera* self=(LLViewerCamera*)user_data; + self->setDefaultFOV(value.asReal()); +} diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index 1fcda6362..2b8a0892b 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -34,8 +34,9 @@ #define LL_LLVIEWERCAMERA_H #include "llcamera.h" -#include "lltimer.h" +#include "llsingleton.h" #include "llstat.h" +#include "lltimer.h" #include "m4math.h" class LLCoordGL; @@ -79,6 +80,7 @@ public: const LLVector3 &point_of_interest); static void updateFrustumPlanes(LLCamera& camera, BOOL ortho = FALSE, BOOL zflip = FALSE, BOOL no_hacks = FALSE); + static void updateCameraAngle(void* user_data, const LLSD& value); void setPerspective(BOOL for_selection, S32 x, S32 y_from_bot, S32 width, S32 height, BOOL limit_select_distance, F32 z_near = 0, F32 z_far = 0); const LLMatrix4 &getProjection() const; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index a58d38329..0f13fbb3d 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -54,6 +54,7 @@ #include "llviewertexturelist.h" #include "llviewerthrottle.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llvoavatar.h" #include "llvoiceclient.h" #include "llvosky.h" @@ -522,6 +523,30 @@ bool handleVectorizeChanged(const LLSD& newvalue) return true; } +bool handleVelocityInterpolate(const LLSD& newvalue) +{ + LLMessageSystem* msg = gMessageSystem; + if ( newvalue.asBoolean() ) + { + msg->newMessageFast(_PREHASH_VelocityInterpolateOn); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + llinfos << "Velocity Interpolation On" << llendl; + } + else + { + msg->newMessageFast(_PREHASH_VelocityInterpolateOff); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + llinfos << "Velocity Interpolation Off" << llendl; + } + return true; +} + bool handleVoiceClientPrefsChanged(const LLSD& newvalue) { if(gVoiceClient) @@ -610,6 +635,7 @@ void settings_setup_listeners() gSavedSettings.getControl("OctreeMaxNodeCapacity")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeAlphaDistanceFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); gSavedSettings.getControl("OctreeAttachmentSizeFactor")->getSignal()->connect(boost::bind(&handleRepartition, _2)); + gSavedSettings.getControl("RenderMaxTextureIndex")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderAnimateTrees")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); @@ -646,6 +672,9 @@ void settings_setup_listeners() gSavedSettings.getControl("RenderMaxVBOSize")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); //See LL jira VWR-3258 comment section. Implemented by LL in 2.1 -Shyotl gSavedSettings.getControl("ShyotlRenderUseStreamVBO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); + gSavedSettings.getControl("ShyotlRenderVBOStrideMode")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); + gSavedSettings.getControl("ShyotlUseLegacyRenderPath")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); + gSavedSettings.getControl("ShyotlUseLegacyTextureBatching")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2)); gSavedSettings.getControl("SianaRenderOmitBlankVBO")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2)); gSavedSettings.getControl("RenderUseFBO")->getSignal()->connect(boost::bind(&handleRenderUseFBOChanged, _2)); gSavedSettings.getControl("RenderDeferredNoise")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2)); @@ -746,6 +775,7 @@ void settings_setup_listeners() gSavedSettings.getControl("VoiceOutputAudioDevice")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); gSavedSettings.getControl("AudioLevelMic")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); gSavedSettings.getControl("LipSyncEnabled")->getSignal()->connect(boost::bind(&handleVoiceClientPrefsChanged, _2)); + gSavedSettings.getControl("VelocityInterpolate")->getSignal()->connect(boost::bind(&handleVelocityInterpolate, _2)); gSavedSettings.getControl("TranslateChat")->getSignal()->connect(boost::bind(&handleTranslateChatPrefsChanged, _2)); gSavedSettings.getControl("StateMachineMaxTime")->getSignal()->connect(boost::bind(&handleStateMachineMaxTimeChanged, _2)); diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 8d5b1fef6..bef35f755 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -191,8 +191,8 @@ void display_update_camera(bool tiling=false) gViewerWindow->setup3DRender(); // update all the sky/atmospheric/water settings - LLWLParamManager::instance()->update(LLViewerCamera::getInstance()); - LLWaterParamManager::instance()->update(LLViewerCamera::getInstance()); + LLWLParamManager::getInstance()->update(LLViewerCamera::getInstance()); + LLWaterParamManager::getInstance()->update(LLViewerCamera::getInstance()); // Update land visibility too LLWorld::getInstance()->setLandFarClip(final_far); @@ -220,7 +220,7 @@ void display_stats() F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency"); if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq) { - gMemoryAllocated = getCurrentRSS(); + gMemoryAllocated = LLMemory::getCurrentRSS(); U32 memory = (U32)(gMemoryAllocated / (1024*1024)); llinfos << llformat("MEMORY: %d MB", memory) << llendl; gRecentMemoryTime.reset(); @@ -586,7 +586,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo } } - gViewerWindow->setupViewport(); + gViewerWindow->setup3DViewport(); gPipeline.resetFrameStats(); // Reset per-frame statistics. if (!gDisconnected) @@ -619,6 +619,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo gPipeline.createObjects(max_geom_update_time); gPipeline.processPartitionQ(); gPipeline.updateGeom(max_geom_update_time); + stop_glerror(); gPipeline.updateGL(); stop_glerror(); @@ -649,6 +650,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; + LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); /*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred) { //force occlusion on for all render types if doing deferred render @@ -680,7 +682,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); - BOOL to_texture = gPipeline.canUseVertexShaders() && LLPipeline::sRenderGlow; + BOOL to_texture = gPipeline.canUseVertexShaders() && + LLPipeline::sRenderGlow; LLAppViewer::instance()->pingMainloopTimeout("Display:Swap"); @@ -729,7 +732,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo glLoadMatrixf(proj.m); glMatrixMode(GL_MODELVIEW); glLoadMatrixf(mod.m); - gViewerWindow->setupViewport(); + gViewerWindow->setup3DViewport(); LLGLState::checkStates(); LLGLState::checkTextureChannels(); @@ -739,12 +742,18 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + LLGLState::checkStates(); + LLGLState::checkClientArrays(); + if (!for_snapshot || tiling) { LLAppViewer::instance()->pingMainloopTimeout("Display:Imagery"); gPipeline.generateWaterReflection(*LLViewerCamera::getInstance()); } + LLGLState::checkStates(); + LLGLState::checkClientArrays(); + ////////////////////////////////////// // // Update images, using the image stats generated during object update/culling @@ -774,6 +783,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo stop_glerror(); } llpushcallstacks ; + LLGLState::checkStates(); + LLGLState::checkClientArrays(); /////////////////////////////////// // // StateSort @@ -802,6 +813,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo } } + LLGLState::checkStates(); + LLGLState::checkClientArrays(); + LLPipeline::sUseOcclusion = occlusion; { @@ -862,6 +876,9 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo LLPipeline::sUnderWaterRender = LLViewerCamera::getInstance()->cameraUnderWater() ? TRUE : FALSE; LLPipeline::updateRenderDeferred(); + LLGLState::checkStates(); + LLGLState::checkClientArrays(); + stop_glerror(); if (to_texture) @@ -870,7 +887,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender) { gPipeline.mDeferredScreen.bindTarget(); - glClearColor(0,0,0,0); + glClearColor(1,0,1,1); gPipeline.mDeferredScreen.clear(); } else if(!tiling) @@ -910,6 +927,14 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo stop_glerror(); } + for (U32 i = 0; i < (U32)gGLManager.mNumTextureImageUnits; i++) + { //dummy cleanup of any currently bound textures + if (gGL.getTexUnit(i)->getCurrType() != LLTexUnit::TT_NONE) + { + gGL.getTexUnit(i)->unbind(gGL.getTexUnit(i)->getCurrType()); + gGL.getTexUnit(i)->disable(); + } + } LLAppViewer::instance()->pingMainloopTimeout("Display:RenderFlush"); if (to_texture) @@ -1031,7 +1056,6 @@ void render_hud_attachments() S32 use_occlusion = LLPipeline::sUseOcclusion; LLPipeline::sUseOcclusion = 0; - LLPipeline::sDisableShaders = TRUE; //cull, sort, and render hud objects static LLCullResult result; @@ -1060,6 +1084,7 @@ void render_hud_attachments() gPipeline.renderGeom(hud_cam); LLSpatialGroup::sNoDelete = FALSE; + //gPipeline.clearReferences(); render_hud_elements(); @@ -1071,7 +1096,6 @@ void render_hud_attachments() gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); } LLPipeline::sUseOcclusion = use_occlusion; - LLPipeline::sDisableShaders = FALSE; } glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -1084,20 +1108,20 @@ void render_hud_attachments() LLRect get_whole_screen_region() { - LLRect whole_screen = gViewerWindow->getVirtualWindowRect(); - + LLRect whole_screen = gViewerWindow->getWorldViewRectScaled(); + // apply camera zoom transform (for high res screenshots) F32 zoom_factor = LLViewerCamera::getInstance()->getZoomFactor(); S16 sub_region = LLViewerCamera::getInstance()->getZoomSubRegion(); if (zoom_factor > 1.f) { S32 num_horizontal_tiles = llceil(zoom_factor); - S32 tile_width = llround((F32)gViewerWindow->getWindowWidth() / zoom_factor); - S32 tile_height = llround((F32)gViewerWindow->getWindowHeight() / zoom_factor); + S32 tile_width = llround((F32)gViewerWindow->getWorldViewWidthScaled() / zoom_factor); + S32 tile_height = llround((F32)gViewerWindow->getWorldViewHeightScaled() / zoom_factor); int tile_y = sub_region / num_horizontal_tiles; int tile_x = sub_region - (tile_y * num_horizontal_tiles); - - whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWindowHeight() - (tile_y * tile_height), tile_width, tile_height); + + whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWorldViewHeightScaled() - (tile_y * tile_height), tile_width, tile_height); } return whole_screen; } @@ -1116,14 +1140,14 @@ bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::mat proj.element(2,2) = -0.01f; F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect(); - + glh::matrix4f mat; - F32 scale_x = (F32)gViewerWindow->getWindowWidth() / (F32)screen_region.getWidth(); - F32 scale_y = (F32)gViewerWindow->getWindowHeight() / (F32)screen_region.getHeight(); + F32 scale_x = (F32)gViewerWindow->getWorldViewWidthScaled() / (F32)screen_region.getWidth(); + F32 scale_y = (F32)gViewerWindow->getWorldViewHeightScaled() / (F32)screen_region.getHeight(); mat.set_scale(glh::vec3f(scale_x, scale_y, 1.f)); mat.set_translate( - glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWindowWidth(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), - clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWindowHeight(), 0.5f * scale_y, -0.5f * scale_y), + glh::vec3f(clamp_rescale((F32)(screen_region.getCenterX() - screen_region.mLeft), 0.f, (F32)gViewerWindow->getWorldViewWidthScaled(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio), + clamp_rescale((F32)(screen_region.getCenterY() - screen_region.mBottom), 0.f, (F32)gViewerWindow->getWorldViewHeightScaled(), 0.5f * scale_y, -0.5f * scale_y), 0.f)); proj *= mat; @@ -1375,19 +1399,19 @@ void render_ui_2d() int pos_y = sub_region / llceil(zoom_factor); int pos_x = sub_region - (pos_y*llceil(zoom_factor)); // offset for this tile - LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidth() * (F32)pos_x / zoom_factor); - LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeight() * (F32)pos_y / zoom_factor); + LLFontGL::sCurOrigin.mX -= llround((F32)gViewerWindow->getWindowWidthScaled() * (F32)pos_x / zoom_factor); + LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeightScaled() * (F32)pos_y / zoom_factor); } stop_glerror(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + //gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); // render outline for HUD - if (gAgent.getAvatarObject() && gAgentCamera.mHUDCurZoom < 0.98f) + if (isAgentAvatarValid() && gAgentCamera.mHUDCurZoom < 0.98f) { gGL.pushMatrix(); - S32 half_width = (gViewerWindow->getWindowWidth() / 2); - S32 half_height = (gViewerWindow->getWindowHeight() / 2); + S32 half_width = (gViewerWindow->getWorldViewWidthScaled() / 2); + S32 half_height = (gViewerWindow->getWorldViewHeightScaled() / 2); glScalef(LLUI::sGLScaleFactor.mV[0], LLUI::sGLScaleFactor.mV[1], 1.f); glTranslatef((F32)half_width, (F32)half_height, 0.f); F32 zoom = gAgentCamera.mHUDCurZoom; @@ -1455,8 +1479,8 @@ void render_disconnected_background() } // Make sure the progress view always fills the entire window. - S32 width = gViewerWindow->getWindowWidth(); - S32 height = gViewerWindow->getWindowHeight(); + S32 width = gViewerWindow->getWindowWidthScaled(); + S32 height = gViewerWindow->getWindowHeightScaled(); if (gDisconnectedImagep) { diff --git a/indra/newview/llviewerdisplayname.cpp b/indra/newview/llviewerdisplayname.cpp index 8aca75b43..f4f23c85a 100644 --- a/indra/newview/llviewerdisplayname.cpp +++ b/indra/newview/llviewerdisplayname.cpp @@ -23,9 +23,7 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -/* -Ported to Phoenix by Wolfspirit Magic. -*/ + #include "llviewerprecompiledheaders.h" #include "llviewerdisplayname.h" @@ -39,7 +37,7 @@ Ported to Phoenix by Wolfspirit Magic. #include "llavatarnamecache.h" #include "llhttpclient.h" #include "llhttpnode.h" -#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llui.h" // getLanguage() namespace LLViewerDisplayName @@ -194,7 +192,7 @@ class LLDisplayNameUpdate : public LLHTTPNode args["OLD_NAME"] = old_display_name; args["SLID"] = av_name.mUsername; args["NEW_NAME"] = av_name.mDisplayName; - LLNotifications::instance().add("DisplayNameUpdate", args); + LLNotificationsUtil::add("DisplayNameUpdate", args); if (agent_id == gAgent.getID()) { LLViewerDisplayName::sNameChangedSignal(); diff --git a/indra/newview/llviewerdisplayname.h b/indra/newview/llviewerdisplayname.h index 6066cc880..16d59ae43 100644 --- a/indra/newview/llviewerdisplayname.h +++ b/indra/newview/llviewerdisplayname.h @@ -23,9 +23,7 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -/* -Ported to Phoenix by Wolfspirit Magic. -*/ + #ifndef LLVIEWERDISPLAYNAME_H #define LLVIEWERDISPLAYNAME_H diff --git a/indra/newview/llviewergenericmessage.cpp b/indra/newview/llviewergenericmessage.cpp index b541104fd..796a49fa4 100644 --- a/indra/newview/llviewergenericmessage.cpp +++ b/indra/newview/llviewergenericmessage.cpp @@ -109,8 +109,12 @@ void process_generic_message(LLMessageSystem* msg, void**) Meta7WindlightPacket* wl = (Meta7WindlightPacket*)buf; - LLWaterParamManager * param_mgr = LLWaterParamManager::instance(); + LLWaterParamManager * param_mgr = LLWaterParamManager::getInstance(); LLWaterParamSet & param_set = param_mgr->mCurParams; + LLWaterParamSet backup; + if(!param_mgr->getParamSet("LightShare-Backup", backup)) { + param_mgr->addParamSet("LightShare-Backup", param_set); + } param_set.set("waterFogColor", wl->waterColor.red / 256.f, wl->waterColor.green / 256.f, wl->waterColor.blue / 256.f); param_set.set("waterFogDensity", pow(2.0f, wl->waterFogDensityExponent)); @@ -147,11 +151,16 @@ void process_generic_message(LLMessageSystem* msg, void**) normalMapTexture.set(out); - param_mgr->setParamSet( "Meta7CurrentRegion", param_set); + param_mgr->setParamSet( "LightShare-CurrentRegion", param_set); param_mgr->setNormalMapID(normalMapTexture); - LLWLParamManager * wl_param_mgr = LLWLParamManager::instance(); + LLWLParamManager * wl_param_mgr = LLWLParamManager::getInstance(); LLWLParamSet & wl_param_set = wl_param_mgr->mCurParams; + LLWLParamSet wl_backup; + if(!wl_param_mgr->getParamSet("LightShare-Backup", wl_backup)) { + wl_param_mgr->addParamSet("LightShare-Backup", wl_param_set); + } + wl_param_set.setSunAngle(F_TWO_PI * wl->sunMoonPosiiton); wl_param_set.setEastAngle(F_TWO_PI * wl->eastAngle); wl_param_set.set("sunlight_color", wl->sunMoonColor.red * 3.0f, wl->sunMoonColor.green * 3.0f, wl->sunMoonColor.blue * 3.0f, wl->sunMoonColor.alpha * 3.0f); @@ -175,12 +184,12 @@ void process_generic_message(LLMessageSystem* msg, void**) wl_param_set.setEnableCloudScrollX(!wl->cloudScrollXLock); wl_param_set.setEnableCloudScrollY(!wl->cloudScrollYLock); wl_param_set.setStarBrightness(wl->starBrightness); - wl_param_mgr->removeParamSet("Meta7-CurrentRegion",true); - wl_param_mgr->addParamSet( "Meta7-CurrentRegion", wl_param_set); - wl_param_mgr->savePreset( "Meta7-CurrentRegion"); - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; - wl_param_mgr->loadPreset( "Meta7-CurrentRegion",true); + wl_param_mgr->removeParamSet("LightShare-CurrentRegion",true); + wl_param_mgr->addParamSet( "LightShare-CurrentRegion", wl_param_set); + wl_param_mgr->savePreset( "LightShare-CurrentRegion"); + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; + wl_param_mgr->loadPreset( "LightShare-CurrentRegion",true); } } } diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 63d3a4440..ef2c4e9ab 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -33,6 +33,7 @@ #include "llviewerprecompiledheaders.h" #include "llviewerinventory.h" +#include "llnotificationsutil.h" #include "message.h" #include "indra_constants.h" @@ -46,6 +47,7 @@ #include "llgesturemgr.h" #include "llinventorybridge.h" +#include "llinventorydefines.h" #include "llinventoryview.h" #include "llviewerregion.h" @@ -192,7 +194,7 @@ void LLViewerInventoryItem::updateServer(BOOL is_new) const // *FIX: deal with this better. llwarns << "LLViewerInventoryItem::updateServer() - for incomplete item" << llendl; - LLNotifications::instance().add("IncompleteInventoryItem"); + LLNotificationsUtil::add("IncompleteInventoryItem"); return; } LLInventoryModel::LLCategoryUpdate up(mParentUUID, is_new ? 1 : 0); @@ -390,7 +392,7 @@ LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& uuid, mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN) { - mDescendentsRequested.reset(); + mDescendentsRequested.stop(); } LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& owner_id) : @@ -398,7 +400,7 @@ LLViewerInventoryCategory::LLViewerInventoryCategory(const LLUUID& owner_id) : mVersion(LLViewerInventoryCategory::VERSION_UNKNOWN), mDescendentCount(LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN) { - mDescendentsRequested.reset(); + mDescendentsRequested.stop(); } LLViewerInventoryCategory::LLViewerInventoryCategory(const LLViewerInventoryCategory* other) @@ -441,9 +443,9 @@ void LLViewerInventoryCategory::updateParentOnServer(BOOL restamp) const void LLViewerInventoryCategory::updateServer(BOOL is_new) const { // communicate that change with the server. - if ( (LLAssetType::AT_NONE != mPreferredType) && (LLFolderType::FT_OUTFIT != mPreferredType) ) + if ( (LLFolderType::FT_NONE != mPreferredType) && (LLFolderType::FT_OUTFIT != mPreferredType) ) { - LLNotifications::instance().add("CannotModifyProtectedCategories"); + LLNotificationsUtil::add("CannotModifyProtectedCategories"); return; } @@ -465,9 +467,9 @@ void LLViewerInventoryCategory::removeFromServer( void ) llinfos << "Removing inventory category " << mUUID << " from server." << llendl; // communicate that change with the server. - if ( (LLAssetType::AT_NONE != mPreferredType) && (LLFolderType::FT_OUTFIT != mPreferredType) ) + if ( (LLFolderType::FT_NONE != mPreferredType) && (LLFolderType::FT_OUTFIT != mPreferredType) ) { - LLNotifications::instance().add("CannotRemoveProtectedCategories"); + LLNotificationsUtil::add("CannotRemoveProtectedCategories"); return; } @@ -489,12 +491,12 @@ bool LLViewerInventoryCategory::fetchDescendents() // <edit> if((mUUID == gSystemFolderRoot) || (gInventory.isObjectDescendentOf(mUUID, gSystemFolderRoot))) return false; // </edit> - if((VERSION_UNKNOWN == mVersion) - && mDescendentsRequested.hasExpired()) //Expired check prevents multiple downloads. + if (VERSION_UNKNOWN == mVersion && + (!mDescendentsRequested.getStarted() || + mDescendentsRequested.hasExpired())) // Expired check prevents multiple downloads. { const F32 FETCH_TIMER_EXPIRY = 10.0f; - mDescendentsRequested.reset(); - mDescendentsRequested.setTimerExpirySec(FETCH_TIMER_EXPIRY); + mDescendentsRequested.start(FETCH_TIMER_EXPIRY); // bitfield // 1 = by date @@ -719,13 +721,12 @@ void RezAttachmentCallback::fire(const LLUUID& inv_item) } } -extern LLGestureManager gGestureManager; void ActivateGestureCallback::fire(const LLUUID& inv_item) { if (inv_item.isNull()) return; - gGestureManager.activateGesture(inv_item); + LLGestureMgr::instance().activateGesture(inv_item); } void CreateGestureCallback::fire(const LLUUID& inv_item) @@ -733,7 +734,7 @@ void CreateGestureCallback::fire(const LLUUID& inv_item) if (inv_item.isNull()) return; - gGestureManager.activateGesture(inv_item); + LLGestureMgr::instance().activateGesture(inv_item); LLViewerInventoryItem* item = gInventory.getItem(inv_item); if (!item) return; diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp index 8f2006b43..aa8c78296 100644 --- a/indra/newview/llviewerjoint.cpp +++ b/indra/newview/llviewerjoint.cpp @@ -263,7 +263,7 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy ) // if object is transparent, defer it, otherwise // give the joint subclass a chance to draw itself //---------------------------------------------------------------- - if ( gRenderForSelect || is_dummy ) + if ( is_dummy ) { triangle_count += drawShape( pixelArea, first_pass, is_dummy ); } diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 36e9b71f6..d457a1a2d 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -61,13 +61,13 @@ #include "v4math.h" #include "m3math.h" #include "m4math.h" +#include "llmatrix4a.h" #if !LL_DARWIN && !LL_LINUX && !LL_SOLARIS extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB; extern PFNGLWEIGHTFVARBPROC glWeightfvARB; extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB; #endif -extern BOOL gRenderForSelect; static LLPointer<LLVertexBuffer> sRenderBuffer = NULL; static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX | @@ -382,6 +382,7 @@ const S32 NUM_AXES = 3; // pivot parent 0-n -- child = n+1 static LLMatrix4 gJointMatUnaligned[32]; +static LLMatrix4a gJointMatAligned[32]; static LLMatrix3 gJointRotUnaligned[32]; static LLVector4 gJointPivot[32]; @@ -467,6 +468,14 @@ void LLViewerJointMesh::uploadJointMatrices() glUniform4fvARB(gAvatarMatrixParam, 45, mat); stop_glerror(); } + else + { + //load gJointMatUnaligned into gJointMatAligned + for (joint_num = 0; joint_num < reference_mesh->mJointRenderData.count(); ++joint_num) + { + gJointMatAligned[joint_num].loadu(gJointMatUnaligned[joint_num]); + } + } } //-------------------------------------------------------------------- @@ -516,22 +525,21 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) U32 triangle_count = 0; + S32 diffuse_channel = LLDrawPoolAvatar::sDiffuseChannel; + stop_glerror(); //---------------------------------------------------------------- // setup current color //---------------------------------------------------------------- - if (!gRenderForSelect) - { - if (is_dummy) - glColor4fv(LLVOAvatar::getDummyColor().mV); - else - glColor4fv(mColor.mV); - } + if (is_dummy) + glColor4fv(LLVOAvatar::getDummyColor().mV); + else + glColor4fv(mColor.mV); stop_glerror(); - LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0)); + LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), (mFace->getPool()->getVertexShaderLevel() > 0) ? 0.f : mShiny); //---------------------------------------------------------------- // setup current texture @@ -541,7 +549,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) LLTexUnit::eTextureAddressMode old_mode = LLTexUnit::TAM_WRAP; if (mTestImageName) { - gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); + gGL.getTexUnit(diffuse_channel)->bindManual(LLTexUnit::TT_TEXTURE, mTestImageName); if (mIsTransparent) { @@ -550,14 +558,14 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) else { glColor4f(0.7f, 0.6f, 0.3f, 1.f); - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); + gGL.getTexUnit(diffuse_channel)->setTextureColorBlend(LLTexUnit::TBO_LERP_TEX_ALPHA, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); } } else if( !is_dummy && mLayerSet ) { if( mLayerSet->hasComposite() ) { - gGL.getTexUnit(0)->bind(mLayerSet->getComposite()); + gGL.getTexUnit(diffuse_channel)->bind(mLayerSet->getComposite()); } else { @@ -567,7 +575,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { llwarns << "Layerset without composite" << llendl; } - gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); + gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT)); } } else @@ -577,25 +585,13 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) { old_mode = mTexture->getAddressMode(); } - gGL.getTexUnit(0)->bind(mTexture); - gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + gGL.getTexUnit(diffuse_channel)->bind(mTexture); + gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(LLTexUnit::TAM_CLAMP); + } else { - gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR)); - } - - if (gRenderForSelect) - { - if (isTransparent()) - { - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_PREV_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_CONST_ALPHA); - } - else - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - } + gGL.getTexUnit(diffuse_channel)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR)); } mFace->getVertexBuffer()->setBuffer(sRenderMask); @@ -631,13 +627,13 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) if (mTestImageName) { - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + gGL.getTexUnit(diffuse_channel)->setTextureBlendType(LLTexUnit::TB_MULT); } if (mTexture.notNull() && !is_dummy) { - gGL.getTexUnit(0)->bind(mTexture.get()); - gGL.getTexUnit(0)->setTextureAddressMode(old_mode); + gGL.getTexUnit(diffuse_channel)->bind(mTexture); + gGL.getTexUnit(diffuse_channel)->setTextureAddressMode(old_mode); } return triangle_count; @@ -648,6 +644,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy) //----------------------------------------------------------------------------- void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) { + num_vertices = (num_vertices + 0x3) & ~0x3; // Do a pre-alloc pass to determine sizes of data. if (mMesh && mValid) { @@ -676,6 +673,16 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w return; } + LLDrawPool *poolp = mFace->getPool(); + BOOL hardware_skinning = (poolp && poolp->getVertexShaderLevel() > 0) ? TRUE : FALSE; + + if (!hardware_skinning && terse_update) + { //no need to do terse updates if we're doing software vertex skinning + // since mMesh is being copied into mVertexBuffer every frame + return; + } + + LLStrider<LLVector3> verticesp; LLStrider<LLVector3> normalsp; LLStrider<LLVector2> tex_coordsp; @@ -686,111 +693,63 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w // Copy data into the faces from the polymesh data. if (mMesh && mValid) { - if (mMesh->getNumVertices()) + const U32 num_verts = mMesh->getNumVertices(); + + if (num_verts) { - stop_glerror(); face->getGeometryAvatar(verticesp, normalsp, tex_coordsp, vertex_weightsp, clothing_weightsp); - stop_glerror(); face->getVertexBuffer()->getIndexStrider(indicesp); - stop_glerror(); verticesp += mMesh->mFaceVertexOffset; - tex_coordsp += mMesh->mFaceVertexOffset; normalsp += mMesh->mFaceVertexOffset; - vertex_weightsp += mMesh->mFaceVertexOffset; - clothing_weightsp += mMesh->mFaceVertexOffset; - - const U32* __restrict coords = (U32*) mMesh->getCoords(); - const U32* __restrict tex_coords = (U32*) mMesh->getTexCoords(); - const U32* __restrict normals = (U32*) mMesh->getNormals(); - const U32* __restrict weights = (U32*) mMesh->getWeights(); - const U32* __restrict cloth_weights = (U32*) mMesh->getClothingWeights(); - - const U32 num_verts = mMesh->getNumVertices(); - - U32 i = 0; - - const U32 skip = verticesp.getSkip()/sizeof(U32); - - U32* __restrict v = (U32*) verticesp.get(); - U32* __restrict n = (U32*) normalsp.get(); - if (terse_update) + //F32* v = (F32*) verticesp.get(); + //F32* n = (F32*) normalsp.get(); + + //U32 words = num_verts*4; + + //LLVector4a::memcpyNonAliased16(v, (F32*) mMesh->getCoords(), words*sizeof(F32)); + verticesp.assignArray((U8*)mMesh->getCoords(), sizeof(mMesh->getCoords()[0]), num_verts); + //LLVector4a::memcpyNonAliased16(n, (F32*) mMesh->getNormals(), words*sizeof(F32)); + normalsp.assignArray((U8*)mMesh->getNormals(), sizeof(mMesh->getNormals()[0]), num_verts); + + if (!terse_update) { - for (S32 i = num_verts; i > 0; --i) - { - //morph target application only, only update positions and normals - v[0] = coords[0]; - v[1] = coords[1]; - v[2] = coords[2]; - coords += 3; - v += skip; - } + vertex_weightsp += mMesh->mFaceVertexOffset; + clothing_weightsp += mMesh->mFaceVertexOffset; + tex_coordsp += mMesh->mFaceVertexOffset; + + //F32* tc = (F32*) tex_coordsp.get(); + //F32* vw = (F32*) vertex_weightsp.get(); + //F32* cw = (F32*) clothing_weightsp.get(); - for (S32 i = num_verts; i > 0; --i) - { - n[0] = normals[0]; - n[1] = normals[1]; - n[2] = normals[2]; - normals += 3; - n += skip; - } + //LLVector4a::memcpyNonAliased16(tc, (F32*) mMesh->getTexCoords(), num_verts*2*sizeof(F32)); + tex_coordsp.assignArray((U8*)mMesh->getTexCoords(), sizeof(mMesh->getTexCoords()[0]), num_verts); + //LLVector4a::memcpyNonAliased16(vw, (F32*) mMesh->getWeights(), num_verts*sizeof(F32)); + vertex_weightsp.assignArray((U8*)mMesh->getWeights(), sizeof(mMesh->getWeights()[0]), num_verts); + //LLVector4a::memcpyNonAliased16(cw, (F32*) mMesh->getClothingWeights(), num_verts*4*sizeof(F32)); + clothing_weightsp.assignArray((U8*)mMesh->getClothingWeights(), sizeof(mMesh->getClothingWeights()[0]), num_verts); } - else - { - U32* __restrict tc = (U32*) tex_coordsp.get(); - U32* __restrict vw = (U32*) vertex_weightsp.get(); - U32* __restrict cw = (U32*) clothing_weightsp.get(); - - do - { - v[0] = *(coords++); - v[1] = *(coords++); - v[2] = *(coords++); - v += skip; - - tc[0] = *(tex_coords++); - tc[1] = *(tex_coords++); - tc += skip; - - n[0] = *(normals++); - n[1] = *(normals++); - n[2] = *(normals++); - n += skip; - - vw[0] = *(weights++); - vw += skip; - - cw[0] = *(cloth_weights++); - cw[1] = *(cloth_weights++); - cw[2] = *(cloth_weights++); - cw[3] = *(cloth_weights++); - cw += skip; - } - while (++i < num_verts); - - const U32 idx_count = mMesh->getNumFaces()*3; + const U32 idx_count = mMesh->getNumFaces()*3; indicesp += mMesh->mFaceIndexOffset; - U16* __restrict idx = indicesp.get(); - S32* __restrict src_idx = (S32*) mMesh->getFaces(); + U16* __restrict idx = indicesp.get(); + S32* __restrict src_idx = (S32*) mMesh->getFaces(); - i = 0; + const S32 offset = (S32) mMesh->mFaceVertexOffset; - const S32 offset = (S32) mMesh->mFaceVertexOffset; - - do - { - *(idx++) = *(src_idx++)+offset; - } - while (++i < idx_count); + for (S32 i = 0; i < (S32)idx_count; ++i) + { + *(idx++) = *(src_idx++)+offset; } } } } + + //----------------------------------------------------------------------------- // updateLOD() //----------------------------------------------------------------------------- @@ -812,85 +771,49 @@ void LLViewerJointMesh::updateGeometryOriginal(LLFace *mFace, LLPolyMesh *mMesh) buffer->getVertexStrider(o_vertices, 0); buffer->getNormalStrider(o_normals, 0); - F32 last_weight = F32_MAX; - LLMatrix4 gBlendMat; - LLMatrix3 gBlendRotMat; + //F32* __restrict vert = o_vertices[0].mV; + //F32* __restrict norm = o_normals[0].mV; + + const F32* __restrict weights = mMesh->getWeights(); + const LLVector4a* __restrict coords = (LLVector4a*) mMesh->getCoords(); + const LLVector4a* __restrict normals = (LLVector4a*) mMesh->getNormals(); + + U32 offset = mMesh->mFaceVertexOffset; + o_vertices += offset; + o_normals += offset; - const F32* weights = mMesh->getWeights(); - const LLVector3* coords = mMesh->getCoords(); - const LLVector3* normals = mMesh->getNormals(); for (U32 index = 0; index < mMesh->getNumVertices(); index++) { - U32 bidx = index + mMesh->mFaceVertexOffset; - - // blend by first matrix - F32 w = weights[index]; - - // Maybe we don't have to change gBlendMat. - // Profiles of a single-avatar scene on a Mac show this to be a very - // common case. JC - if (w == last_weight) + // equivalent to joint = floorf(weights[index]); + S32 joint = _mm_cvtt_ss2si(_mm_load_ss(weights+index)); + F32 w = weights[index] - joint; + + LLMatrix4a gBlendMat; + + if (w != 0.f) { - o_vertices[bidx] = coords[index] * gBlendMat; - o_normals[bidx] = normals[index] * gBlendRotMat; - continue; + // blend between matrices and apply + gBlendMat.setLerp(gJointMatAligned[joint+0], + gJointMatAligned[joint+1], w); + + LLVector4a res; + gBlendMat.affineTransform(coords[index], res); + (o_vertices++)->set(res.getF32ptr()); + //res.store4a(vert+index*4); + gBlendMat.rotate(normals[index], res); + (o_normals++)->set(res.getF32ptr()); + //res.store4a(norm+index*4); } - - last_weight = w; - - S32 joint = llfloor(w); - w -= joint; - - // No lerp required in this case. - if (w == 1.0f) - { - gBlendMat = gJointMatUnaligned[joint+1]; - o_vertices[bidx] = coords[index] * gBlendMat; - gBlendRotMat = gJointRotUnaligned[joint+1]; - o_normals[bidx] = normals[index] * gBlendRotMat; - continue; + else + { // No lerp required in this case. + LLVector4a res; + gJointMatAligned[joint].affineTransform(coords[index], res); + (o_vertices++)->set(res.getF32ptr()); + //res.store4a(vert+index*4); + gJointMatAligned[joint].rotate(normals[index], res); + (o_normals++)->set(res.getF32ptr()); + //res.store4a(norm+index*4); } - - // Try to keep all the accesses to the matrix data as close - // together as possible. This function is a hot spot on the - // Mac. JC - LLMatrix4 &m0 = gJointMatUnaligned[joint+1]; - LLMatrix4 &m1 = gJointMatUnaligned[joint+0]; - - gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w); - gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w); - gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w); - - gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w); - gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w); - gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w); - - gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w); - gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w); - gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w); - - gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w); - gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w); - gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w); - - o_vertices[bidx] = coords[index] * gBlendMat; - - LLMatrix3 &n0 = gJointRotUnaligned[joint+1]; - LLMatrix3 &n1 = gJointRotUnaligned[joint+0]; - - gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w); - gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w); - gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w); - - gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w); - gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w); - gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w); - - gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w); - gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w); - gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w); - - o_normals[bidx] = normals[index] * gBlendRotMat; } buffer->setBuffer(0); @@ -932,31 +855,33 @@ void LLViewerJointMesh::updateVectorize() LL_INFOS("AppInit") << "Vectorization : " << ( vectorizeEnable ? "ENABLED" : "DISABLED" ) << LL_ENDL ; LL_INFOS("AppInit") << "Vector Processor : " << vp << LL_ENDL ; LL_INFOS("AppInit") << "Vectorized Skinning : " << ( vectorizeSkin ? "ENABLED" : "DISABLED" ) << LL_ENDL ; + + sUpdateGeometryFunc = &updateGeometryOriginal; + if(vectorizeEnable && vectorizeSkin) { switch(sVectorizeProcessor) { case 2: - sUpdateGeometryFunc = &updateGeometrySSE2; if(!supportsSSE2()) LL_INFOS("AppInit") << "VectorizeProcessor set to unsupported implementation! (SSE2)" << LL_ENDL ; + else + sUpdateGeometryFunc = &updateGeometrySSE2; break; case 1: - sUpdateGeometryFunc = &updateGeometrySSE; if(!supportsSSE()) LL_INFOS("AppInit") << "VectorizeProcessor set to unsupported implementation! (SSE)" << LL_ENDL ; + else + sUpdateGeometryFunc = &updateGeometrySSE; break; default: - sUpdateGeometryFunc = &updateGeometryVectorized; if(!gSysCPU.hasAltivec()) LL_INFOS("AppInit") << "VectorizeProcessor set to unsupported implementation! (Altivec)" << LL_ENDL ; + else + sUpdateGeometryFunc = &updateGeometryVectorized; break; } } - else - { - sUpdateGeometryFunc = &updateGeometryOriginal; - } } void LLViewerJointMesh::updateJointGeometry() diff --git a/indra/newview/llviewerjointmesh_sse.cpp b/indra/newview/llviewerjointmesh_sse.cpp index 2f2635246..36d6bd61a 100644 --- a/indra/newview/llviewerjointmesh_sse.cpp +++ b/indra/newview/llviewerjointmesh_sse.cpp @@ -94,8 +94,8 @@ void LLViewerJointMesh::updateGeometrySSE(LLFace *face, LLPolyMesh *mesh) buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); const F32* weights = mesh->getWeights(); - const LLVector3* coords = mesh->getCoords(); - const LLVector3* normals = mesh->getNormals(); + const LLVector4* coords = mesh->getCoords(); + const LLVector4* normals = mesh->getNormals(); for (U32 index = 0, index_end = mesh->getNumVertices(); index < index_end; ++index) { if( weight != weights[index]) @@ -103,8 +103,8 @@ void LLViewerJointMesh::updateGeometrySSE(LLFace *face, LLPolyMesh *mesh) S32 joint = llfloor(weight = weights[index]); blend_mat.lerp(sJointMat[joint], sJointMat[joint+1], weight - joint); } - blend_mat.multiply(coords[index], o_vertices[index]); - ((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]); + blend_mat.multiply((const LLVector3)coords[index], o_vertices[index]); + ((LLV4Matrix3)blend_mat).multiply((const LLVector3)normals[index], o_normals[index]); } buffer->setBuffer(0); diff --git a/indra/newview/llviewerjointmesh_sse2.cpp b/indra/newview/llviewerjointmesh_sse2.cpp index bfd8bb69b..5bcdb6224 100644 --- a/indra/newview/llviewerjointmesh_sse2.cpp +++ b/indra/newview/llviewerjointmesh_sse2.cpp @@ -101,8 +101,8 @@ void LLViewerJointMesh::updateGeometrySSE2(LLFace *face, LLPolyMesh *mesh) buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); const F32* weights = mesh->getWeights(); - const LLVector3* coords = mesh->getCoords(); - const LLVector3* normals = mesh->getNormals(); + const LLVector4* coords = mesh->getCoords(); + const LLVector4* normals = mesh->getNormals(); for (U32 index = 0, index_end = mesh->getNumVertices(); index < index_end; ++index) { if( weight != weights[index]) @@ -110,8 +110,8 @@ void LLViewerJointMesh::updateGeometrySSE2(LLFace *face, LLPolyMesh *mesh) S32 joint = llfloor(weight = weights[index]); blend_mat.lerp(sJointMat[joint], sJointMat[joint+1], weight - joint); } - blend_mat.multiply(coords[index], o_vertices[index]); - ((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]); + blend_mat.multiply((const LLVector3)coords[index], o_vertices[index]); + ((LLV4Matrix3)blend_mat).multiply((const LLVector3)normals[index], o_normals[index]); } buffer->setBuffer(0); diff --git a/indra/newview/llviewerjointmesh_vec.cpp b/indra/newview/llviewerjointmesh_vec.cpp index 91b97b07d..6a7bb587b 100644 --- a/indra/newview/llviewerjointmesh_vec.cpp +++ b/indra/newview/llviewerjointmesh_vec.cpp @@ -84,8 +84,8 @@ void LLViewerJointMesh::updateGeometryVectorized(LLFace *face, LLPolyMesh *mesh) buffer->getNormalStrider(o_normals, mesh->mFaceVertexOffset); const F32* weights = mesh->getWeights(); - const LLVector3* coords = mesh->getCoords(); - const LLVector3* normals = mesh->getNormals(); + const LLVector4* coords = mesh->getCoords(); + const LLVector4* normals = mesh->getNormals(); for (U32 index = 0, index_end = mesh->getNumVertices(); index < index_end; ++index) { if( weight != weights[index]) @@ -93,8 +93,8 @@ void LLViewerJointMesh::updateGeometryVectorized(LLFace *face, LLPolyMesh *mesh) S32 joint = llfloor(weight = weights[index]); blend_mat.lerp(sJointMat[joint], sJointMat[joint+1], weight - joint); } - blend_mat.multiply(coords[index], o_vertices[index]); - ((LLV4Matrix3)blend_mat).multiply(normals[index], o_normals[index]); + blend_mat.multiply((const LLVector3)coords[index], o_vertices[index]); + ((LLV4Matrix3)blend_mat).multiply((const LLVector3)normals[index], o_normals[index]); } buffer->setBuffer(0); diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index f810de5ad..722c31492 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -714,7 +714,7 @@ void LLViewerJoystick::moveAvatar(bool reset) sDelta[RX_I] += (cur_delta[RX_I] - sDelta[RX_I]) * time * feather; sDelta[RY_I] += (cur_delta[RY_I] - sDelta[RY_I]) * time * feather; - handleRun(fsqrtf(sDelta[Z_I]*sDelta[Z_I] + sDelta[X_I]*sDelta[X_I])); + handleRun((F32) sqrt(sDelta[Z_I]*sDelta[Z_I] + sDelta[X_I]*sDelta[X_I])); // Allow forward/backward movement some priority if (dom_axis == Z_I) diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 4b086f808..911813104 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -43,7 +43,9 @@ #include "llpluginclassmedia.h" +#include "llnotifications.h" #include "llevent.h" // LLSimpleListener +#include "llnotificationsutil.h" #include "lluuid.h" #include "llkeyboard.h" @@ -334,7 +336,7 @@ bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type) LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << mime_type << LL_ENDL; LLSD args; args["MIME_TYPE"] = mime_type; - LLNotifications::instance().add("NoPlugin", args); + LLNotificationsUtil::add("NoPlugin", args); return false; } @@ -440,7 +442,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_ LL_WARNS("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL; LLSD args; args["MIME_TYPE"] = media_type; - LLNotifications::instance().add("NoPlugin", args); + LLNotificationsUtil::add("NoPlugin", args); return NULL; } @@ -682,9 +684,16 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi LLURI uri(url); std::string scheme = uri.scheme(); - if(scheme.empty() || "http" == scheme || "https" == scheme) + if(scheme.empty() || ("http" == scheme || "https" == scheme)) { - LLHTTPClient::getHeaderOnly( url, new LLMimeDiscoveryResponder(this)); + if(mime_type.empty()) + { + LLHTTPClient::getHeaderOnly( url, new LLMimeDiscoveryResponder(this)); + } + else if(initializeMedia(mime_type) && (plugin = getMediaPlugin())) + { + plugin->loadURI( url ); + } } else if("data" == scheme || "file" == scheme || "about" == scheme) { @@ -1124,7 +1133,7 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* self, LLPluginClass { LLSD args; args["PLUGIN"] = LLMIMETypes::implType(mMimeType); - LLNotifications::instance().add("MediaPluginFailed", args); + LLNotificationsUtil::add("MediaPluginFailed", args); } break; default: diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 6b8bd2217..aebfbec76 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -122,7 +122,8 @@ public: bool canNavigateForward(); bool canNavigateBack(); std::string getMediaURL() { return mMediaURL; } - std::string getMediaHomeURL() { return mHomeURL; } + std::string getHomeURL() { return mHomeURL; } + void setHomeURL(const std::string& home_url) { mHomeURL = home_url; } std::string getMimeType() { return mMimeType; } void getTextureSize(S32 *texture_width, S32 *texture_height); void scaleMouse(S32 *mouse_x, S32 *mouse_y); diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index a0c263cf2..0debf03b6 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -44,6 +44,8 @@ #include "indra_constants.h" #include "llassetstorage.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llchat.h" #include "llfeaturemanager.h" #include "llfocusmgr.h" @@ -167,6 +169,7 @@ #include "llimagebmp.h" #include "llimagej2c.h" #include "llimagetga.h" +#include "llinventorydefines.h" #include "llinventorymodel.h" #include "llinventoryview.h" #include "llkeyboard.h" @@ -252,6 +255,7 @@ #include "floaterao.h" #include "slfloatermediafilter.h" #include "llviewerobjectbackup.h" +#include "llagentui.h" #include "hippogridmanager.h" @@ -1540,7 +1544,7 @@ void init_debug_rendering_menu(LLMenuGL* menu) item = new LLMenuItemCheckGL("Animate Textures", menu_toggle_control, NULL, menu_check_control, (void*)"AnimateTextures"); menu->append(item); - item = new LLMenuItemCheckGL("Disable Textures", menu_toggle_variable, NULL, menu_check_variable, (void*)&LLViewerTexture::sDontLoadVolumeTextures); + item = new LLMenuItemCheckGL("Disable Textures", menu_toggle_control, NULL, menu_check_control, (void*)"TextureDisable"); menu->append(item); item = new LLMenuItemCheckGL("HTTP Get Textures", menu_toggle_control, NULL, menu_check_control, (void*)"ImagePipelineUseHTTP"); @@ -2359,7 +2363,7 @@ class LLEnableEdit : public view_listener_t bool enable = true; if (gAgent.inPrelude()) { - enable = LLViewerParcelMgr::getInstance()->agentCanBuild() + enable = LLViewerParcelMgr::getInstance()->allowAgentBuild() || LLSelectMgr::getInstance()->getSelection()->isAttachment(); } // [RLVa:KB] - Checked: 2009-07-05 (RLVa-1.0.0b) @@ -2772,9 +2776,6 @@ bool handle_go_to() std::string val; LLVector3d pos = LLToolPie::getInstance()->getPick().mPosGlobal; if (gSavedSettings.getBOOL("DoubleClickTeleport") -#ifdef LL_RRINTERFACE_H //MK - && !(gRRenabled && gAgent.mRRInterface.contains ("tploc")) -#endif //mk ) { LLVector3d hips_offset(0.0f, 0.0f, 1.2f); @@ -2863,15 +2864,10 @@ class LLObjectExport : public view_listener_t bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); - if (!object) return true; - - LLVOAvatar* avatar = find_avatar_from_object(object); - - if (!avatar) + if (object) { LLObjectBackup::getInstance()->exportObject(); } - return true; } }; @@ -3011,14 +3007,14 @@ class LLAvatarFreeze : public view_listener_t // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.0e | OK args["AVATAR_NAME"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? fullname : RlvStrings::getAnonym(fullname); // [/RLVa:KB] - LLNotifications::instance().add("FreezeAvatarFullname", + LLNotificationsUtil::add("FreezeAvatarFullname", args, payload, callback_freeze); } else { - LLNotifications::instance().add("FreezeAvatar", + LLNotificationsUtil::add("FreezeAvatar", LLSD(), payload, callback_freeze); @@ -3153,14 +3149,14 @@ class LLAvatarEject : public view_listener_t // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.0e | OK args["AVATAR_NAME"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? fullname : RlvStrings::getAnonym(fullname); // [/RLVa:KB] - LLNotifications::instance().add("EjectAvatarFullname", + LLNotificationsUtil::add("EjectAvatarFullname", args, payload, callback_eject); } else { - LLNotifications::instance().add("EjectAvatarFullname", + LLNotificationsUtil::add("EjectAvatarFullname", LLSD(), payload, callback_eject); @@ -3176,14 +3172,14 @@ class LLAvatarEject : public view_listener_t // [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.2.1f) | Modified: RLVa-1.0.0e | OK args["AVATAR_NAME"] = (!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? fullname : RlvStrings::getAnonym(fullname); // [/RLVa:KB] - LLNotifications::instance().add("EjectAvatarFullnameNoBan", + LLNotificationsUtil::add("EjectAvatarFullnameNoBan", args, payload, callback_eject); } else { - LLNotifications::instance().add("EjectAvatarNoBan", + LLNotificationsUtil::add("EjectAvatarNoBan", LLSD(), payload, callback_eject); @@ -3296,11 +3292,11 @@ class LLAvatarGiveCard : public view_listener_t transaction_id.generate(); msg->addUUIDFast(_PREHASH_TransactionID, transaction_id); msg->sendReliable(dest_host); - LLNotifications::instance().add("OfferedCard", args); + LLNotificationsUtil::add("OfferedCard", args); } else { - LLNotifications::instance().add("CantOfferCallingCard", old_args); + LLNotificationsUtil::add("CantOfferCallingCard", old_args); } } return true; @@ -3341,7 +3337,7 @@ void handle_leave_group(void *) { LLSD args; args["GROUP"] = gAgent.getGroupName(); - LLNotifications::instance().add("GroupLeaveConfirmMember", args, LLSD(), callback_leave_group); + LLNotificationsUtil::add("GroupLeaveConfirmMember", args, LLSD(), callback_leave_group); } } @@ -3404,7 +3400,7 @@ void handle_buy_object(LLSaleInfo sale_info) { if(!LLSelectMgr::getInstance()->selectGetAllRootsValid()) { - LLNotifications::instance().add("UnableToBuyWhileDownloading"); + LLNotificationsUtil::add("UnableToBuyWhileDownloading"); return; } @@ -3413,7 +3409,7 @@ void handle_buy_object(LLSaleInfo sale_info) BOOL owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); if (!owners_identical) { - LLNotifications::instance().add("CannotBuyObjectsFromDifferentOwners"); + LLNotificationsUtil::add("CannotBuyObjectsFromDifferentOwners"); return; } @@ -3423,7 +3419,7 @@ void handle_buy_object(LLSaleInfo sale_info) valid &= LLSelectMgr::getInstance()->selectGetAggregatePermissions(ag_perm); if(!valid || !sale_info.isForSale() || !perm.allowTransferTo(gAgent.getID())) { - LLNotifications::instance().add("ObjectNotForSale"); + LLNotificationsUtil::add("ObjectNotForSale"); return; } @@ -3636,12 +3632,12 @@ void set_god_level(U8 god_level) if(god_level > GOD_NOT) { args["LEVEL"] = llformat("%d",(S32)god_level); - LLNotifications::instance().add("EnteringGodMode", args); + LLNotificationsUtil::add("EnteringGodMode", args); } else { args["LEVEL"] = llformat("%d",(S32)old_god_level); - LLNotifications::instance().add("LeavingGodMode", args); + LLNotificationsUtil::add("LeavingGodMode", args); } @@ -3888,7 +3884,7 @@ void request_friendship(const LLUUID& dest_id) } else { - LLNotifications::instance().add("CantOfferFriendship"); + LLNotificationsUtil::add("CantOfferFriendship"); } } } @@ -4288,7 +4284,7 @@ void disabled_duplicate(void*) { if (LLSelectMgr::getInstance()->getSelection()->getPrimaryObject()) { - LLNotifications::instance().add("CopyFailed"); + LLNotificationsUtil::add("CopyFailed"); } } @@ -4421,7 +4417,7 @@ void handle_claim_public_land(void*) { if (LLViewerParcelMgr::getInstance()->getSelectionRegion() != gAgent.getRegion()) { - LLNotifications::instance().add("ClaimPublicLand"); + LLNotificationsUtil::add("ClaimPublicLand"); return; } @@ -4699,7 +4695,7 @@ class LLObjectReturn : public view_listener_t mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); - LLNotifications::instance().add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2)); + LLNotificationsUtil::add("ReturnToOwner", LLSD(), LLSD(), boost::bind(&LLObjectReturn::onReturnToOwner, this, _1, _2)); return true; } @@ -5090,7 +5086,7 @@ void show_buy_currency(const char* extra) args["EXTRA"] = extra; } args["URL"] = BUY_CURRENCY_URL; - LLNotifications::instance().add("PromptGoToCurrencyPage", args, LLSD(), callback_show_buy_currency); + LLNotificationsUtil::add("PromptGoToCurrencyPage", args, LLSD(), callback_show_buy_currency); } void handle_buy_currency(void*) @@ -5641,11 +5637,6 @@ class LLViewToggleRadar: public view_listener_t bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { LLFloaterAvatarList::toggle(0); - bool vis = false; - if(LLFloaterAvatarList::getInstance()) - { - vis = (bool)LLFloaterAvatarList::getInstance()->getVisible(); - } return true; } }; @@ -5987,7 +5978,7 @@ class LLWorldSetBusy : public view_listener_t else { gAgent.setBusy(); - LLNotifications::instance().add("BusyModeSet"); + LLNotificationsUtil::add("BusyModeSet"); } return true; } @@ -6020,14 +6011,14 @@ class LLWorldCreateLandmark : public view_listener_t if (!agent_parcel->getAllowLandmark() && !LLViewerParcelMgr::isParcelOwnedByAgent(agent_parcel, GP_LAND_ALLOW_LANDMARK)) { - LLNotifications::instance().add("CannotCreateLandmarkNotOwner"); + LLNotificationsUtil::add("CannotCreateLandmarkNotOwner"); return true; } LLUUID folder_id; folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK); std::string pos_string; - gAgent.buildLocationString(pos_string); + LLAgentUI::buildLocationString(pos_string); create_inventory_item(gAgent.getID(), gAgent.getSessionID(), folder_id, LLTransactionID::tnull, @@ -7158,7 +7149,7 @@ class LLAttachmentEnableDrop : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { - BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->agentCanBuild()); + BOOL can_build = gAgent.isGodlike() || (LLViewerParcelMgr::getInstance()->allowAgentBuild()); //Add an inventory observer to only allow dropping the newly attached item //once it exists in your inventory. Look at Jira 2422. @@ -8963,7 +8954,7 @@ void handle_save_to_xml(void*) LLFloater* frontmost = gFloaterView->getFrontmost(); if (!frontmost) { - LLNotifications::instance().add("NoFrontmostFloater"); + LLNotificationsUtil::add("NoFrontmostFloater"); return; } @@ -9370,51 +9361,51 @@ class LLWorldEnvSettings : public view_listener_t if (tod == "sunrise") { // set the value, turn off animation - LLWLParamManager::instance()->mAnimator.setDayTime(0.25); - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.setDayTime(0.25); + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; // then call update once - LLWLParamManager::instance()->mAnimator.update( - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->mAnimator.update( + LLWLParamManager::getInstance()->mCurParams); } else if (tod == "noon") { // set the value, turn off animation - LLWLParamManager::instance()->mAnimator.setDayTime(0.567); - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.setDayTime(0.567); + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; // then call update once - LLWLParamManager::instance()->mAnimator.update( - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->mAnimator.update( + LLWLParamManager::getInstance()->mCurParams); } else if (tod == "sunset") { // set the value, turn off animation - LLWLParamManager::instance()->mAnimator.setDayTime(0.75); - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.setDayTime(0.75); + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; // then call update once - LLWLParamManager::instance()->mAnimator.update( - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->mAnimator.update( + LLWLParamManager::getInstance()->mCurParams); } else if (tod == "midnight") { // set the value, turn off animation - LLWLParamManager::instance()->mAnimator.setDayTime(0.0); - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.setDayTime(0.0); + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; // then call update once - LLWLParamManager::instance()->mAnimator.update( - LLWLParamManager::instance()->mCurParams); + LLWLParamManager::getInstance()->mAnimator.update( + LLWLParamManager::getInstance()->mCurParams); } else { - LLWLParamManager::instance()->mAnimator.mIsRunning = true; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = true; + LLWLParamManager::getInstance()->mAnimator.mIsRunning = true; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = true; } return true; } diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index a0479296d..db4ca65dd 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -77,6 +77,7 @@ #include "llassetuploadresponders.h" #include "lleconomy.h" #include "llhttpclient.h" +#include "llnotificationsutil.h" #include "llmemberlistener.h" #include "llsdserialize.h" #include "llstring.h" @@ -154,16 +155,13 @@ std::string build_extensions_string(ELoadFilter filter) } class AIFileUpload { - protected: - AIFilePicker* mPicker; - public: - AIFileUpload(void) : mPicker(NULL) { } - virtual ~AIFileUpload() { llassert(!mPicker); if (mPicker) { mPicker->abort(); mPicker = NULL; } } + AIFileUpload(void) { } + virtual ~AIFileUpload() { } public: bool is_valid(std::string const& filename, ELoadFilter type); - void filepicker_callback(ELoadFilter type); + void filepicker_callback(ELoadFilter type, AIFilePicker* picker); void start_filepicker(ELoadFilter type, char const* context); protected: @@ -179,21 +177,22 @@ void AIFileUpload::start_filepicker(ELoadFilter filter, char const* context) // display(); } - llassert(!mPicker); - mPicker = AIFilePicker::create(); - mPicker->open(filter, "", context); - mPicker->run(boost::bind(&AIFileUpload::filepicker_callback, this, filter)); + AIFilePicker* picker = AIFilePicker::create(); + picker->open(filter, "", context); + // Note that when the call back is called then we're still in the main loop of + // the viewer and therefore the AIFileUpload still exists, since that is only + // destructed at the end of main when exiting the viewer. + picker->run(boost::bind(&AIFileUpload::filepicker_callback, this, filter, picker)); } -void AIFileUpload::filepicker_callback(ELoadFilter type) +void AIFileUpload::filepicker_callback(ELoadFilter type, AIFilePicker* picker) { - if (mPicker->hasFilename()) + if (picker->hasFilename()) { - std::string filename = mPicker->getFilename(); + std::string filename = picker->getFilename(); if (is_valid(filename, type)) handle_event(filename); } - mPicker = NULL; } bool AIFileUpload::is_valid(std::string const& filename, ELoadFilter type) @@ -208,7 +207,7 @@ bool AIFileUpload::is_valid(std::string const& filename, ELoadFilter type) // No extension LLSD args; args["FILE"] = short_name; - LLNotifications::instance().add("NoFileExtension", args); + LLNotificationsUtil::add("NoFileExtension", args); return false; } else @@ -251,7 +250,7 @@ bool AIFileUpload::is_valid(std::string const& filename, ELoadFilter type) LLSD args; args["EXTENSION"] = ext; args["VALIDS"] = valid_extensions; - LLNotifications::instance().add("InvalidFileExtension", args); + LLNotificationsUtil::add("InvalidFileExtension", args); return false; } }//end else (non-null extension) @@ -356,7 +355,7 @@ class LLFileUploadBulk : public view_listener_t if(expected_upload_cost) msg.append(llformat("\nWARNING: Each upload costs L$%d if it's not temporary.",expected_upload_cost)); args["MESSAGE"] = msg; - LLNotifications::instance().add("GenericAlertYesNoCancel", args, LLSD(), onConfirmBulkUploadTemp); + LLNotificationsUtil::add("GenericAlertYesNoCancel", args, LLSD(), onConfirmBulkUploadTemp); return true; } @@ -478,7 +477,7 @@ class LLFileMinimizeAllWindows : public view_listener_t }; // </edit> -class LLFileSaveTexture : public view_listener_t +class LLFileSavePreview : public view_listener_t { bool handleEvent(LLPointer<LLEvent> event, const LLSD& userdata) { @@ -961,7 +960,7 @@ void upload_new_resource(const std::string& src_filename, std::string name, llwarns << error_message << llendl; LLSD args; args["ERROR_MESSAGE"] = error_message; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); if(LLFile::remove(filename) == -1) { lldebugs << "unable to remove temp file" << llendl; @@ -1023,7 +1022,7 @@ void temp_upload_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt LLSD args; args["FILE"] = LLInventoryType::lookupHumanReadable(data->mInventoryType); args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); - LLNotifications::instance().add("CannotUploadReason", args); + LLNotificationsUtil::add("CannotUploadReason", args); } LLUploadDialog::modalUploadFinished(); @@ -1116,7 +1115,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt LLSD args; args["FILE"] = LLInventoryType::lookupHumanReadable(data->mInventoryType); args["REASON"] = std::string(LLAssetStorage::getErrorString(result)); - LLNotifications::instance().add("CannotUploadReason", args); + LLNotificationsUtil::add("CannotUploadReason", args); } LLUploadDialog::modalUploadFinished(); @@ -1275,12 +1274,11 @@ void init_menu_file() // <edit> (new LLFileMinimizeAllWindows())->registerListener(gMenuHolder, "File.MinimizeAllWindows"); // </edit> - (new LLFileSaveTexture())->registerListener(gMenuHolder, "File.SaveTexture"); + (new LLFileSavePreview())->registerListener(gMenuHolder, "File.SavePreview"); (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot"); (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk"); (new LLFileQuit())->registerListener(gMenuHolder, "File.Quit"); (new LLFileLogOut())->registerListener(gMenuHolder, "File.LogOut"); - //Emerald has a second llFileSaveTexture here... Same as the original. Odd. -HgB (new LLFileEnableUpload())->registerListener(gMenuHolder, "File.EnableUpload"); (new LLFileEnableSaveAs())->registerListener(gMenuHolder, "File.EnableSaveAs"); } diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index d4042d312..5c69f3471 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -38,6 +38,7 @@ #include <deque> #include "llimagejpeg.h" +#include "llanimationstates.h" #include "llaudioengine.h" #include "llavatarnamecache.h" #include "indra_constants.h" @@ -95,12 +96,14 @@ #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llimpanel.h" +#include "llinventorydefines.h" #include "llinventorymodel.h" #include "llinventoryview.h" #include "llmenugl.h" #include "llmutelist.h" -#include "llnotifications.h" #include "llnotify.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llpanelgrouplandmoney.h" #include "llselectmgr.h" #include "llstartup.h" @@ -360,9 +363,9 @@ void give_money(const LLUUID& uuid, LLViewerRegion* region, S32 amount, BOOL is_ S32 trx_type, const std::string& desc) { // <edit> - //if(0 == amount || !region) return; - if(!region) return; + //if(!region) return; // </edit> + if(0 == amount || !region) return; amount = abs(amount); LL_INFOS("Messaging") << "give_money(" << uuid << "," << amount << ")"<< LL_ENDL; if(can_afford_transaction(amount)) @@ -739,7 +742,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response) LLFloaterGroupInfo::showFromUUID(group_id); LLSD args; args["MESSAGE"] = message; - LLNotifications::instance().add("JoinGroup", args, notification["payload"]); + LLNotificationsUtil::add("JoinGroup", args, notification["payload"]); return false; } if(option == 0 && !group_id.isNull()) @@ -758,7 +761,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response) LLSD args; args["NAME"] = name; args["INVITE"] = message; - LLNotifications::instance().add("JoinedTooManyGroupsMember", args, notification["payload"]); + LLNotificationsUtil::add("JoinedTooManyGroupsMember", args, notification["payload"]); } } @@ -776,7 +779,7 @@ bool join_group_response(const LLSD& notification, const LLSD& response) // asking about a fee. LLSD next_payload = notification["payload"]; next_payload["fee"] = 0; - LLNotifications::instance().add("JoinGroupCanAfford", + LLNotificationsUtil::add("JoinGroupCanAfford", args, next_payload); } @@ -1952,7 +1955,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Note: don't put the message in the IM history, even though was sent // via the IM mechanism. - LLNotifications::instance().add("SystemMessageTip",args); + LLNotificationsUtil::add("SystemMessageTip",args); break; case IM_NOTHING_SPECIAL: @@ -2053,7 +2056,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Message to everyone from GOD args["NAME"] = name; args["MESSAGE"] = message; - LLNotifications::instance().add("GodMessage", args); + LLNotificationsUtil::add("GodMessage", args); // Treat like a system message and put in chat history. // Claim to be from a local agent so it doesn't go into @@ -2134,7 +2137,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // This is a block, modeless dialog. //*TODO:translate args["MESSAGE"] = message; - LLNotifications::instance().add("SystemMessage", args); + LLNotificationsUtil::add("SystemMessage", args); } break; case IM_GROUP_NOTICE: @@ -2270,7 +2273,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLSD args; args["MESSAGE"] = message; - LLNotifications::instance().add("JoinGroup", args, payload, join_group_response); + LLNotificationsUtil::add("JoinGroup", args, payload, join_group_response); } } break; @@ -2370,7 +2373,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) args["NAME"] = (!fRlvObfuscate) ? name : RlvStrings::getAnonym(name); // [/RLVa:KB] //args["NAME"] = name; - LLNotifications::instance().add("InventoryAccepted", args); + LLNotificationsUtil::add("InventoryAccepted", args); break; } case IM_INVENTORY_DECLINED: @@ -2381,7 +2384,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) args["NAME"] = (!fRlvObfuscate) ? name : RlvStrings::getAnonym(name); // [/RLVa:KB] //args["NAME"] = name; - LLNotifications::instance().add("InventoryDeclined", args); + LLNotificationsUtil::add("InventoryDeclined", args); break; } case IM_GROUP_VOTE: @@ -2392,7 +2395,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLSD payload; payload["group_id"] = session_id; - LLNotifications::instance().add("GroupVote", args, payload); + LLNotificationsUtil::add("GroupVote", args, payload); } break; @@ -2539,7 +2542,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Construct a viewer alert for this message. args["NAME"] = name; args["MESSAGE"] = message; - LLNotifications::instance().add("ObjectMessage", args); + LLNotificationsUtil::add("ObjectMessage", args); } break; case IM_BUSY_AUTO_RESPONSE: @@ -2607,7 +2610,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) payload["from_id"] = from_id; payload["lure_id"] = session_id; payload["godlike"] = FALSE; - //LLNotifications::instance().add("TeleportOffered", args, payload); + //LLNotificationsUtil::add("TeleportOffered", args, payload); // [RLVa:KB] - Version: 1.23.4 | Checked: 2009-07-07 (RLVa-1.0.0d) | Modified: RLVa-0.2.0b if ( (rlv_handler_t::isEnabled()) && @@ -2618,7 +2621,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else { - LLNotifications::instance().add("TeleportOffered", args, payload); + LLNotificationsUtil::add("TeleportOffered", args, payload); // <edit> if(binary_bucket_size) { @@ -2679,7 +2682,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // </edit> } // [/RLVa:KB] - //LLNotifications::instance().add("TeleportOffered", args, payload); + //LLNotificationsUtil::add("TeleportOffered", args, payload); } } break; @@ -2716,7 +2719,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) args["URL"] = url; LLSD payload; payload["url"] = url; - LLNotifications::instance().add("GotoURL", args, payload ); + LLNotificationsUtil::add("GotoURL", args, payload ); } break; @@ -2743,12 +2746,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) if(message.empty()) { //support for frienship offers from clients before July 2008 - LLNotifications::instance().add("OfferFriendshipNoMessage", args, payload); + LLNotificationsUtil::add("OfferFriendshipNoMessage", args, payload); } else { args["[MESSAGE]"] = message; - LLNotifications::instance().add("OfferFriendship", args, payload); + LLNotificationsUtil::add("OfferFriendship", args, payload); } } } @@ -2766,7 +2769,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) send_generic_message("requestonlinenotification", strings); args["NAME"] = name; - LLNotifications::instance().add("FriendshipAccepted", args); + LLNotificationsUtil::add("FriendshipAccepted", args); } break; @@ -2889,7 +2892,7 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) static SH_SpamHandler<LLUUID> spam_check("SGBlockCardSpam","SHSpamTime","SGSpamCount"); if(spam_check.isBlocked(source_id,source_id,"BlockedCards",args)) return; - LLNotifications::instance().add("OfferCallingCard", args, payload); + LLNotificationsUtil::add("OfferCallingCard", args, payload); } } else @@ -2900,12 +2903,12 @@ void process_offer_callingcard(LLMessageSystem* msg, void**) void process_accept_callingcard(LLMessageSystem* msg, void**) { - LLNotifications::instance().add("CallingCardAccepted"); + LLNotificationsUtil::add("CallingCardAccepted"); } void process_decline_callingcard(LLMessageSystem* msg, void**) { - LLNotifications::instance().add("CallingCardDeclined"); + LLNotificationsUtil::add("CallingCardDeclined"); } class ChatTranslationReceiver : public LLTranslate::TranslationReceiver @@ -3085,7 +3088,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // RELEASE-RLVa: if this code changes, remember to change the code down below as well if ( (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mChatType != CHAT_TYPE_DEBUG_MSG) && (gSavedSettings.getBOOL("EffectScriptChatParticles")) && - ((!rlv_handler_t::isEnabled()) || (CHAT_TYPE_OWNER != chat.mChatType)) ) + (CHAT_TYPE_OWNER != chat.mChatType) ) // [/RLVa:KB] { LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); @@ -3113,18 +3116,20 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) U32 links_for_chatting_objects = gSavedSettings.getU32("LinksForChattingObjects"); if (links_for_chatting_objects != 0 && chatter && chat.mSourceType == CHAT_SOURCE_OBJECT && -#ifdef LL_RRINTERFACE_H //MK - (!gRRenabled || !gAgent.mRRInterface.mContainsShownames) && -#endif //mk - (!is_owned_by_me || links_for_chatting_objects == 2)) + (!is_owned_by_me || links_for_chatting_objects == 2) +// [RLVa:KB] + && !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES) +// [/RLVa:KB] + ) { LLSD query_string; query_string["name"] = from_name; query_string["owner"] = owner_id; -#ifdef LL_RRINTERFACE_H //MK - if (!gRRenabled || !gAgent.mRRInterface.mContainsShowloc) + +// [RLVa:KB] + if( !gRlvHandler.hasBehaviour(RLV_BHVR_SHOWLOC) ) +// [/RLVa:KB] { -#endif //mk // Compute the object SLURL. LLVector3 pos = chatter->getPositionRegion(); S32 x = llround((F32)fmod((F64)pos.mV[VX], (F64)REGION_WIDTH_METERS)); @@ -3133,9 +3138,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) std::ostringstream location; location << chatter->getRegion()->getName() << "/" << x << "/" << y << "/" << z; query_string["slurl"] = location.str(); -#ifdef LL_RRINTERFACE_H //MK } -#endif //mk + std::ostringstream link; link << "secondlife:///app/objectim/" << from_id << LLURI::mapToQueryString(query_string); chat.mURL = link.str(); @@ -3199,30 +3203,23 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) // [Ansariel/Henri: Display name support] if (chatter && chatter->isAvatar()) { -#ifdef LL_RRINTERFACE_H //MK - if (!gRRenabled || !gAgent.mRRInterface.mContainsShownames) + if (LLAvatarNameCache::useDisplayNames()) { -#endif //mk - if (LLAvatarNameCache::useDisplayNames()) + LLAvatarName avatar_name; + if (LLAvatarNameCache::get(from_id, &avatar_name)) { - LLAvatarName avatar_name; - if (LLAvatarNameCache::get(from_id, &avatar_name)) + static const LLCachedControl<S32> phoenix_name_system("PhoenixNameSystem", 0); + if (phoenix_name_system == 2 || (phoenix_name_system == 1 && avatar_name.mIsDisplayNameDefault)) { - static const LLCachedControl<S32> phoenix_name_system("PhoenixNameSystem", 0); - if (phoenix_name_system == 2 || (phoenix_name_system == 1 && avatar_name.mIsDisplayNameDefault)) - { - from_name = avatar_name.mDisplayName; - } - else - { - from_name = avatar_name.getCompleteName(); - } + from_name = avatar_name.mDisplayName; + } + else + { + from_name = avatar_name.getCompleteName(); } - chat.mFromName = from_name; } -#ifdef LL_RRINTERFACE_H //MK + chat.mFromName = from_name; } -#endif //mk } // [/Ansariel/Henri: Display name support] @@ -3419,8 +3416,9 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) #endif //shy_mod // [RLVa:KB] - Alternate: Snowglobe-1.2.4 | Checked: 2009-07-10 (RLVa-1.0.0g) // Copy/paste from above - if ( (chatter) && (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mChatType != CHAT_TYPE_DEBUG_MSG) && - (gSavedSettings.getBOOL("EffectScriptChatParticles")) ) + if ( chatter && (chat.mSourceType == CHAT_SOURCE_OBJECT && chat.mChatType != CHAT_TYPE_DEBUG_MSG) && + (gSavedSettings.getBOOL("EffectScriptChatParticles")) && + (CHAT_TYPE_OWNER != chat.mChatType) ) { LLPointer<LLViewerPartSourceChat> psc = new LLViewerPartSourceChat(chatter->getPositionAgent()); psc->setSourceObject(chatter); @@ -3601,13 +3599,13 @@ public: { // Show notification that they can now teleport to landmarks. Use a random landmark from the inventory S32 random_land = ll_rand( land_items.count() - 1 ); args["NAME"] = land_items[random_land]->getName(); - LLNotifications::instance().add("TeleportToLandmark",args); + LLNotificationsUtil::add("TeleportToLandmark",args); } if ( card_items.count() > 0 ) { // Show notification that they can now contact people. Use a random calling card from the inventory S32 random_card = ll_rand( card_items.count() - 1 ); args["NAME"] = card_items[random_card]->getName(); - LLNotifications::instance().add("TeleportToPerson",args); + LLNotificationsUtil::add("TeleportToPerson",args); } gInventory.removeObserver(this); @@ -3707,6 +3705,18 @@ void process_teleport_finish(LLMessageSystem* msg, void**) U32 teleport_flags; msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags); + U32 region_size_x = 256; + msg->getU32Fast(_PREHASH_Info, _PREHASH_RegionSizeX, region_size_x); + + U32 region_size_y = 256; + msg->getU32Fast(_PREHASH_Info, _PREHASH_RegionSizeY, region_size_y); + + //and a little hack for Second Life compatibility + if (region_size_y == 0 || region_size_x == 0) + { + region_size_x = 256; + region_size_y = 256; + } std::string seedCap; msg->getStringFast(_PREHASH_Info, _PREHASH_SeedCapability, seedCap); @@ -3726,7 +3736,7 @@ void process_teleport_finish(LLMessageSystem* msg, void**) // Viewer trusts the simulator. gMessageSystem->enableCircuit(sim_host, TRUE); - LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); + LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host, region_size_x, region_size_y); /* // send camera update to new region @@ -3749,10 +3759,18 @@ void process_teleport_finish(LLMessageSystem* msg, void**) */ //Reset the windlight profile to default - /*LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; - LLWLParamManager::instance()->loadPreset("Default", true); - LLWaterParamManager::instance()->loadPreset("Default",true);*/ + //LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + //LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; + LLWLParamSet wl_backup; + if(LLWLParamManager::getInstance()->getParamSet("LightShare-Backup", wl_backup)) { + LLWLParamManager::getInstance()->propagateParameters(); + LLWLParamManager::getInstance()->removeParamSet("LightShare-Backup", true); + } + LLWaterParamSet backup; + if(LLWaterParamManager::getInstance()->getParamSet("LightShare-Backup", backup)) { + LLWaterParamManager::getInstance()->propagateParameters(); + LLWaterParamManager::getInstance()->removeParamSet("LightShare-Backup", true); + } // now, use the circuit info to tell simulator about us! LL_INFOS("Messaging") << "process_teleport_finish() Enabling " @@ -3993,7 +4011,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) { LLSD payload; payload["message"] = version_channel; - LLNotifications::instance().add("ServerVersionChanged", LLSD(), payload); + LLNotificationsUtil::add("ServerVersionChanged", LLSD(), payload); } gLastVersionChannel = version_channel; @@ -4024,9 +4042,22 @@ void process_crossed_region(LLMessageSystem* msg, void**) std::string seedCap; msg->getStringFast(_PREHASH_RegionData, _PREHASH_SeedCapability, seedCap); + U32 region_size_x = 256; + msg->getU32(_PREHASH_RegionData, _PREHASH_RegionSizeX, region_size_x); + + U32 region_size_y = 256; + msg->getU32(_PREHASH_RegionData, _PREHASH_RegionSizeY, region_size_y); + + //and a little hack for Second Life compatibility + if (region_size_y == 0 || region_size_x == 0) + { + region_size_x = 256; + region_size_y = 256; + } + send_complete_agent_movement(sim_host); - LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host); + LLViewerRegion* regionp = LLWorld::getInstance()->addRegion(region_handle, sim_host, region_size_x, region_size_y); regionp->setSeedCapability(seedCap); } @@ -4816,6 +4847,17 @@ void process_avatar_animation(LLMessageSystem *mesgsys, void **user_data) avatarp->mSignaledAnimations[animation_id] = anim_sequence_id; + // *HACK: Disabling flying mode if it has been enabled shortly before the agent + // stand up animation is signaled. In this case we don't get a signal to start + // flying animation from server, the AGENT_CONTROL_FLY flag remains set but the + // avatar does not play flying animation, so we switch flying mode off. + // See LLAgent::setFlying(). This may cause "Stop Flying" button to blink. + // See EXT-2781. + if (animation_id == ANIM_AGENT_STANDUP && gAgent.getFlying()) + { + gAgent.setFlying(FALSE); + } + if (i < num_source_blocks) { mesgsys->getUUIDFast(_PREHASH_AnimationSourceList, _PREHASH_ObjectID, object_id, i); @@ -4922,6 +4964,9 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) } gAgentCamera.setForceMouselook(force_mouselook); + // Forcing turning off flying here to prevent flying after pressing "Stand" + // to stand up from an object. See EXT-1655. + gAgent.setFlying(FALSE); LLViewerObject* object = gObjectList.findObject(sitObjectID); if (object) @@ -5236,7 +5281,7 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) // *TODO:translate LLSD args; args["MESSAGE"] = desc; - LLNotifications::instance().add("SystemMessage", args); + LLNotificationsUtil::add("SystemMessage", args); // Also send notification to chat -- MC LLChat chat(desc); @@ -5313,7 +5358,7 @@ bool handle_special_notification(std::string notificationID, LLSD& llsdBlock) bool attempt_standard_notification(LLMessageSystem* msgsystem) { // if we have additional alert data - if (msgsystem->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0) + if (msgsystem->has(_PREHASH_AlertInfo) && msgsystem->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0) { // notification was specified using the new mechanism, so we can just handle it here std::string notificationID; @@ -5419,7 +5464,7 @@ void process_alert_core(const std::string& message, BOOL modal) std::string snap_filename = gDirUtilp->getLindenUserDir(); snap_filename += gDirUtilp->getDirDelimiter(); snap_filename += SCREEN_HOME_FILENAME; - gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight(), FALSE, FALSE); + gViewerWindow->saveSnapshot(snap_filename, gViewerWindow->getWindowWidthRaw(), gViewerWindow->getWindowHeightRaw(), FALSE, FALSE); } const std::string ALERT_PREFIX("ALERT: "); @@ -5448,20 +5493,20 @@ void process_alert_core(const std::string& message, BOOL modal) S32 mins = 0; LLStringUtil::convertToS32(text.substr(18), mins); args["MINUTES"] = llformat("%d",mins); - LLNotifications::instance().add("RegionRestartMinutes", args); + LLNotificationsUtil::add("RegionRestartMinutes", args); } else if (text.substr(0,17) == "RESTART_X_SECONDS") { S32 secs = 0; LLStringUtil::convertToS32(text.substr(18), secs); args["SECONDS"] = llformat("%d",secs); - LLNotifications::instance().add("RegionRestartSeconds", args); + LLNotificationsUtil::add("RegionRestartSeconds", args); } else { // *TODO:translate args["MESSAGE"] = text; - LLNotifications::instance().add("SystemMessage", args); + LLNotificationsUtil::add("SystemMessage", args); } } else if (modal) @@ -5469,14 +5514,14 @@ void process_alert_core(const std::string& message, BOOL modal) // *TODO:translate LLSD args; args["ERROR_MESSAGE"] = message; - LLNotifications::instance().add("ErrorMessage", args); + LLNotificationsUtil::add("ErrorMessage", args); } else { // *TODO:translate LLSD args; args["MESSAGE"] = message; - LLNotifications::instance().add("SystemMessageTip", args); + LLNotificationsUtil::add("SystemMessageTip", args); } } @@ -5772,7 +5817,7 @@ bool script_question_cb(const LLSD& notification, const LLSD& response) LLNotifications::instance().add(notification["name"], notification["substitutions"], notification["payload"]); // ...with description on top - LLNotifications::instance().add("DebitPermissionDetails"); + LLNotificationsUtil::add("DebitPermissionDetails"); } return false; } @@ -5901,7 +5946,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data) else { // fall back to default behavior if cautions are entirely disabled - LLNotifications::instance().add("ScriptQuestion", args, payload); + LLNotificationsUtil::add("ScriptQuestion", args, payload); } } @@ -6040,7 +6085,7 @@ void process_teleport_failed(LLMessageSystem *msg, void**) LLSD args; // if we have additional alert data - if (msg->getNumberOfBlocksFast(_PREHASH_AlertInfo) > 0) + if (msg->has(_PREHASH_AlertInfo) && msg->getSizeFast(_PREHASH_AlertInfo, _PREHASH_Message) > 0) { // Get the message ID msg->getStringFast(_PREHASH_AlertInfo, _PREHASH_Message, reason); @@ -6095,7 +6140,10 @@ void process_teleport_failed(LLMessageSystem *msg, void**) } } - LLNotifications::instance().add("CouldNotTeleportReason", args); + LLNotificationsUtil::add("CouldNotTeleportReason", args); + + // Let the interested parties know that teleport failed. + LLViewerParcelMgr::getInstance()->onTeleportFailed(); if( gAgent.getTeleportState() != LLAgent::TELEPORT_NONE ) { @@ -6156,9 +6204,14 @@ void process_teleport_local(LLMessageSystem *msg,void**) } // send camera update to new region - //gAgent.updateCamera(); + gAgentCamera.updateCamera(); send_agent_update(TRUE, TRUE); + + // Let the interested parties know we've teleported. + // Vadim *HACK: Agent position seems to get reset (to render position?) + // on each frame, so we have to pass the new position manually. + LLViewerParcelMgr::getInstance()->onTeleportFinished(true, gAgent.getPosGlobalFromAgent(pos)); } void send_simple_im(const LLUUID& to_id, @@ -6316,11 +6369,11 @@ void handle_lure(const uuid_vec_t& ids) } if (gAgent.isGodlike()) { - LLNotifications::instance().add("OfferTeleportFromGod", edit_args, payload, handle_lure_callback); + LLNotificationsUtil::add("OfferTeleportFromGod", edit_args, payload, handle_lure_callback); } else { - LLNotifications::instance().add("OfferTeleport", edit_args, payload, handle_lure_callback); + LLNotificationsUtil::add("OfferTeleport", edit_args, payload, handle_lure_callback); } } @@ -6450,7 +6503,14 @@ void process_script_dialog(LLMessageSystem* msg, void**) LLUUID object_id; msg->getUUID("Data", "ObjectID", object_id); - if (LLMuteList::getInstance()->isMuted(object_id)) +// For compability with OS grids first check for presence of extended packet before fetching data. + LLUUID owner_id; + if (gMessageSystem->getNumberOfBlocks("OwnerData") > 0) + { + msg->getUUID("OwnerData", "OwnerID", owner_id); + } + + if (LLMuteList::getInstance()->isMuted(object_id) || LLMuteList::getInstance()->isMuted(owner_id)) { return; } @@ -6528,7 +6588,7 @@ void process_script_dialog(LLMessageSystem* msg, void**) { args["DEFAULT"] = default_text; payload["textbox"] = "true"; - LLNotifications::instance().add("ScriptTextBoxDialog", args, payload, callback_script_dialog); + LLNotificationsUtil::add("ScriptTextBoxDialog", args, payload, callback_script_dialog); } else { @@ -6596,7 +6656,7 @@ void callback_load_url_name(const LLUUID& id, const std::string& full_name, bool args["OBJECTNAME"] = load_url_info["object_name"].asString(); args["NAME"] = owner_name; - LLNotifications::instance().add("LoadWebPage", args, load_url_info); + LLNotificationsUtil::add("LoadWebPage", args, load_url_info); } else { @@ -6652,7 +6712,7 @@ void callback_download_complete(void** data, S32 result, LLExtStat ext_status) std::string* filepath = (std::string*)data; LLSD args; args["DOWNLOAD_PATH"] = *filepath; - LLNotifications::instance().add("FinishedRawDownload", args); + LLNotificationsUtil::add("FinishedRawDownload", args); delete filepath; } diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp index 2ef8f6973..a2625495c 100644 --- a/indra/newview/llviewernetwork.cpp +++ b/indra/newview/llviewernetwork.cpp @@ -52,7 +52,7 @@ void LLViewerLogin::getLoginURIs(std::vector<std::string>& uris) const const std::string &LLViewerLogin::getGridLabel() const { - return gHippoGridManager->getConnectedGrid()->getGridNick(); + return gHippoGridManager->getConnectedGrid()->getGridName(); } const std::string &LLViewerLogin::getLoginPage() const diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 0708a587d..71a0e6a58 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -45,6 +45,7 @@ #include "llfontgl.h" #include "llframetimer.h" #include "llinventory.h" +#include "llinventorydefines.h" #include "llmaterialtable.h" #include "llmutelist.h" #include "llnamevalue.h" @@ -66,6 +67,7 @@ #include "lldrawable.h" #include "llface.h" #include "llfloaterproperties.h" +#include "llfloatertools.h" #include "llfollowcam.h" #include "llselectmgr.h" #include "llrendersphere.h" @@ -77,6 +79,7 @@ #include "llviewerparceloverlay.h" #include "llviewerpartsource.h" #include "llviewerregion.h" +#include "llviewerstats.h" #include "llviewertextureanim.h" #include "llviewerwindow.h" // For getSpinAxis #include "llvoavatar.h" @@ -105,8 +108,8 @@ //#define DEBUG_UPDATE_TYPE -BOOL gVelocityInterpolate = TRUE; -BOOL gPingInterpolate = TRUE; +BOOL LLViewerObject::sVelocityInterpolate = TRUE; +BOOL LLViewerObject::sPingInterpolate = TRUE; U32 LLViewerObject::sNumZombieObjects = 0; S32 LLViewerObject::sNumObjects = 0; @@ -117,6 +120,10 @@ S32 LLViewerObject::sAxisArrowLength(50); BOOL LLViewerObject::sPulseEnabled(FALSE); BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE +// sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime +F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion +F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction + // static LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) { @@ -150,9 +157,9 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco case LL_VO_SKY: res = new LLVOSky(id, pcode, regionp); break; case LL_VO_VOID_WATER: - res = new LLVOVoidWater(id, pcode, regionp); break; + res = new LLVOVoidWater(id, pcode, regionp); break; case LL_VO_WATER: - res = new LLVOWater(id, pcode, regionp); break; + res = new LLVOWater(id, pcode, regionp); break; case LL_VO_GROUND: res = new LLVOGround(id, pcode, regionp); break; case LL_VO_PART_GROUP: @@ -178,6 +185,13 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mGLName(0), mbCanSelect(TRUE), mFlags(0), +#if MESH_ENABLED + mPhysicsShapeType(0), + mPhysicsGravity(0), + mPhysicsFriction(0), + mPhysicsDensity(0), + mPhysicsRestitution(0), +#endif //MESH_ENABLED mDrawable(), mCreateSelected(FALSE), mRenderMedia(FALSE), @@ -210,6 +224,14 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mState(0), mMedia(NULL), mClickAction(0), +#if MESH_ENABLED + mObjectCost(0), + mLinksetCost(0), + mPhysicsCost(0), + mLinksetPhysicsCost(0.f), + mCostStale(true), + mPhysicsShapeUnknown(true), +#endif //MESH_ENABLED mAttachmentItemID(LLUUID::null), mLastUpdateType(OUT_UNKNOWN), mLastUpdateCached(FALSE) @@ -649,14 +671,13 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) } BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL); - if (!ret) + if(!ret) { return FALSE ; } LLDrawable* old_parent = mDrawable->mParent; - mDrawable->mParent = parentp; - + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); if( (old_parent != parentp && old_parent) || (parentp && parentp->isActive())) @@ -792,6 +813,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, #ifdef DEBUG_UPDATE_TYPE llinfos << "Full:" << getID() << llendl; #endif +#if MESH_ENABLED + //clear cost and linkset cost + mCostStale = true; + if (isSelected()) + { + gFloaterTools->dirty(); + } +#endif //MESH_ENABLED LLUUID audio_uuid; LLUUID owner_id; // only valid if audio_uuid or particle system is not null F32 gain; @@ -836,6 +865,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); ((LLVOAvatar*)this)->setFootPlane(collision_plane); count += sizeof(LLVector4); + // fall through case 60: this_update_precision = 32; // this is a terse update @@ -875,6 +905,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); ((LLVOAvatar*)this)->setFootPlane(collision_plane); count += sizeof(LLVector4); + // fall through case 32: this_update_precision = 16; test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); @@ -1180,6 +1211,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); ((LLVOAvatar*)this)->setFootPlane(collision_plane); count += sizeof(LLVector4); + // fall through case 60: // this is a terse 32 update // pos @@ -1219,6 +1251,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); ((LLVOAvatar*)this)->setFootPlane(collision_plane); count += sizeof(LLVector4); + // fall through case 32: // this is a terse 16 update this_update_precision = 16; @@ -1386,6 +1419,15 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, #ifdef DEBUG_UPDATE_TYPE llinfos << "CompFull:" << getID() << llendl; #endif + +#if MESH_ENABLED + mCostStale = true; + + if (isSelected()) + { + gFloaterTools->dirty(); + } +#endif //MESH_ENABLED dp->unpackU32(crc, "CRC"); mTotalCRC = crc; dp->unpackU8(material, "Material"); @@ -1863,9 +1905,9 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } } - new_rot.normalize(); + new_rot.normQuat(); - if (gPingInterpolate) + if (sPingInterpolate) { LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); if (cdp) @@ -1938,6 +1980,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, avatar->clampAttachmentPositions(); } + + // If we're snapping the position by more than 0.5m, update LLViewerStats::mAgentPositionSnaps + if ( isAvatar() && gAgent.getAvatarObject() == this && (mag_sqr > 0.25f) ) + { + LLViewerStats::getInstance()->mAgentPositionSnaps.push( diff.length() ); + } } if (new_rot != mLastRot @@ -2028,7 +2076,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay(); mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds(); - mLastMessageUpdateSecs = LLFrameTimer::getElapsedSeconds(); + mLastMessageUpdateSecs = mLastInterpUpdateSecs; if (mDrawable.notNull()) { // Don't clear invisibility flag on update if still orphaned! @@ -2065,7 +2113,7 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // CRO - don't velocity interp linked objects! // Leviathan - but DO velocity interp joints - if (!mStatic && gVelocityInterpolate && !isSelected()) + if (!mStatic && sVelocityInterpolate && !isSelected()) { // calculate dt from last update F32 dt_raw = (F32)(time - mLastInterpUpdateSecs); @@ -2155,48 +2203,170 @@ BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return TRUE; } else - { - // linear motion - // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object - // updates represents the average velocity of the last timestep, rather than the final velocity. - // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically - // - // There is a problem here if dt is negative. . . - - // *TODO: should also wrap linear accel/velocity in check - // to see if object is selected, instead of explicitly - // zeroing it out - LLVector3 accel = getAcceleration(); - LLVector3 vel = getVelocity(); - - if (!(accel.isExactlyZero() && vel.isExactlyZero())) - { - LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; - - // region local - setPositionRegion(pos + getPositionRegion()); - setVelocity(vel + accel*dt); - - // for objects that are spinning but not translating, make sure to flag them as having moved - setChanged(MOVED | SILHOUETTE); - } - - mLastInterpUpdateSecs = time; + { // Move object based on it's velocity and rotation + interpolateLinearMotion(time, dt); } } - if (gNoRender) - { - // Skip drawable stuff if not rendering. - return TRUE; - } - updateDrawable(FALSE); return TRUE; } +// Move an object due to idle-time viewer side updates by iterpolating motion +void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) +{ + // linear motion + // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object + // updates represents the average velocity of the last timestep, rather than the final velocity. + // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically + // + // *TODO: should also wrap linear accel/velocity in check + // to see if object is selected, instead of explicitly + // zeroing it out + + F64 time_since_last_update = time - mLastMessageUpdateSecs; + if (time_since_last_update <= 0.0 || dt <= 0.f) + { + return; + } + + LLVector3 accel = getAcceleration(); + LLVector3 vel = getVelocity(); + + if (sMaxUpdateInterpolationTime <= 0.0) + { // Old code path ... unbounded, simple interpolation + if (!(accel.isExactlyZero() && vel.isExactlyZero())) + { + LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; + + // region local + setPositionRegion(pos + getPositionRegion()); + setVelocity(vel + accel*dt); + + // for objects that are spinning but not translating, make sure to flag them as having moved + setChanged(MOVED | SILHOUETTE); + } + } + else if (!accel.isExactlyZero() || !vel.isExactlyZero()) // object is moving + { // Object is moving, and hasn't been too long since we got an update from the server + + // Calculate predicted position and velocity + LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; + LLVector3 new_v = accel * dt; + + if (time_since_last_update > sPhaseOutUpdateInterpolationTime && + sPhaseOutUpdateInterpolationTime > 0.0) + { // Haven't seen a viewer update in a while, check to see if the ciruit is still active + if (mRegionp) + { // The simulator will NOT send updates if the object continues normally on the path + // predicted by the velocity and the acceleration (often gravity) sent to the viewer + // So check to see if the circuit is blocked, which means the sim is likely in a long lag + LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit( mRegionp->getHost() ); + if (cdp) + { + // Find out how many seconds since last packet arrived on the circuit + F64 time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); + + if (!cdp->isAlive() || // Circuit is dead or blocked + cdp->isBlocked() || // or doesn't seem to be getting any packets + (time_since_last_packet > sPhaseOutUpdateInterpolationTime)) + { + // Start to reduce motion interpolation since we haven't seen a server update in a while + F64 time_since_last_interpolation = time - mLastInterpUpdateSecs; + F64 phase_out = 1.0; + if (time_since_last_update > sMaxUpdateInterpolationTime) + { // Past the time limit, so stop the object + phase_out = 0.0; + //llinfos << "Motion phase out to zero" << llendl; + + // Kill angular motion as well. Note - not adding this due to paranoia + // about stopping rotation for llTargetOmega objects and not having it restart + // setAngularVelocity(LLVector3::zero); + } + else if (mLastInterpUpdateSecs - mLastMessageUpdateSecs > sPhaseOutUpdateInterpolationTime) + { // Last update was already phased out a bit + phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / + (sMaxUpdateInterpolationTime - time_since_last_interpolation); + //llinfos << "Continuing motion phase out of " << (F32) phase_out << llendl; + } + else + { // Phase out from full value + phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / + (sMaxUpdateInterpolationTime - sPhaseOutUpdateInterpolationTime); + //llinfos << "Starting motion phase out of " << (F32) phase_out << llendl; + } + phase_out = llclamp(phase_out, 0.0, 1.0); + + new_pos = new_pos * ((F32) phase_out); + new_v = new_v * ((F32) phase_out); + } + } + } + } + + new_pos = new_pos + getPositionRegion(); + new_v = new_v + vel; + + + // Clamp interpolated position to minimum underground and maximum region height + LLVector3d new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); + F32 min_height; + if (isAvatar()) + { // Make a better guess about AVs not going underground + min_height = LLWorld::getInstance()->resolveLandHeightGlobal(new_pos_global); + min_height += (0.5f * getScale().mV[VZ]); + } + else + { // This will put the object underground, but we can't tell if it will stop + // at ground level or not + min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global); + } + + new_pos.mV[VZ] = llmax(min_height, new_pos.mV[VZ]); + new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]); + + // Check to see if it's going off the region + LLVector3 temp(new_pos); + if (temp.clamp(0.f, mRegionp->getWidth())) + { // Going off this region, so see if we might end up on another region + LLVector3d old_pos_global = mRegionp->getPosGlobalFromRegion(getPositionRegion()); + new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); // Re-fetch in case it got clipped above + + // Clip the positions to known regions + LLVector3d clip_pos_global = LLWorld::getInstance()->clipToVisibleRegions(old_pos_global, new_pos_global); + if (clip_pos_global != new_pos_global) + { // Was clipped, so this means we hit a edge where there is no region to enter + + //llinfos << "Hit empty region edge, clipped predicted position to " << mRegionp->getPosRegionFromGlobal(clip_pos_global) + // << " from " << new_pos << llendl; + new_pos = mRegionp->getPosRegionFromGlobal(clip_pos_global); + + // Stop motion and get server update for bouncing on the edge + new_v.clear(); + setAcceleration(LLVector3::zero); + } + else + { // Let predicted movement cross into another region + //llinfos << "Predicting region crossing to " << new_pos << llendl; + } + } + + // Set new position and velocity + setPositionRegion(new_pos); + setVelocity(new_v); + + // for objects that are spinning but not translating, make sure to flag them as having moved + setChanged(MOVED | SILHOUETTE); + } + + // Update the last time we did anything + mLastInterpUpdateSecs = time; +} + + + BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size) { LLMemType mt(LLMemType::MTYPE_OBJECT); @@ -2894,6 +3064,8 @@ void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped) { if (!mOnMap) { + llassert_always(LLWorld::getInstance()->getRegionFromHandle(getRegion()->getHandle())); + gObjectList.addToMap(this); mOnMap = TRUE; } @@ -2909,22 +3081,130 @@ void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped) } } -void LLViewerObject::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax) +#if MESH_ENABLED +void LLViewerObject::setObjectCost(F32 cost) { - LLVector3 center = getRenderPosition(); - LLVector3 size = getScale(); - newMin.setVec(center-size); - newMax.setVec(center+size); - if(mDrawable.notNull()) - mDrawable->setPositionGroup((newMin + newMax) * 0.5f); + mObjectCost = cost; + mCostStale = false; + + if (isSelected()) + { + gFloaterTools->dirty(); + } +} + +void LLViewerObject::setLinksetCost(F32 cost) +{ + mLinksetCost = cost; + mCostStale = false; + + if (isSelected()) + { + gFloaterTools->dirty(); + } +} + +void LLViewerObject::setPhysicsCost(F32 cost) +{ + mPhysicsCost = cost; + mCostStale = false; + + if (isSelected()) + { + gFloaterTools->dirty(); + } +} + +void LLViewerObject::setLinksetPhysicsCost(F32 cost) +{ + mLinksetPhysicsCost = cost; + mCostStale = false; + + if (isSelected()) + { + gFloaterTools->dirty(); + } +} + + +F32 LLViewerObject::getObjectCost() +{ + if (mCostStale) + { + gObjectList.updateObjectCost(this); + } + + return mObjectCost; +} + +F32 LLViewerObject::getLinksetCost() +{ + if (mCostStale) + { + gObjectList.updateObjectCost(this); + } + + return mLinksetCost; +} + +F32 LLViewerObject::getPhysicsCost() +{ + if (mCostStale) + { + gObjectList.updateObjectCost(this); + } + + return mPhysicsCost; +} + +F32 LLViewerObject::getLinksetPhysicsCost() +{ + if (mCostStale) + { + gObjectList.updateObjectCost(this); + } + + return mLinksetPhysicsCost; +} + +F32 LLViewerObject::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_value) const +{ + return 0.f; +} + +U32 LLViewerObject::getTriangleCount() const +{ + return 0; +} + +U32 LLViewerObject::getHighLODTriangleCount() +{ + return 0; +} +#endif //MESH_ENABLED + +void LLViewerObject::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) +{ + if(mDrawable.isNull()) + return; + LLVector4a center; + center.load3(getRenderPosition().mV); + LLVector4a size; + size.load3(getScale().mV); + newMin.setSub(center, size); + newMax.setAdd(center, size); + + mDrawable->setPositionGroup(center); } F32 LLViewerObject::getBinRadius() { if (mDrawable.notNull()) { - const LLVector3* ext = mDrawable->getSpatialExtents(); - return (ext[1]-ext[0]).magVec(); + const LLVector4a* ext = mDrawable->getSpatialExtents(); + LLVector4a diff; + diff.setSub(ext[1], ext[0]); + return diff.getLength3().getF32(); } return getScale().magVec(); @@ -2990,7 +3270,12 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) getTEImage(i)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); } - if (isSculpted()) + + if (isSculpted() +#if MESH_ENABLED + && !isMesh() +#endif //MESH_ENABLED + ) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); LLUUID sculpt_id = sculpt_params->getSculptTexture(); @@ -3230,6 +3515,16 @@ const LLVector3 LLViewerObject::getPositionEdit() const const LLVector3 LLViewerObject::getRenderPosition() const { +#if MESH_ENABLED + if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) + { + LLVOAvatar* avatar = getAvatar(); + if (avatar) + { + return avatar->getPositionAgent(); + } + } +#endif //MESH_ENABLED if (mDrawable.isNull() || mDrawable->getGeneration() < 0) { return getPositionAgent(); @@ -3248,6 +3543,12 @@ const LLVector3 LLViewerObject::getPivotPositionAgent() const const LLQuaternion LLViewerObject::getRenderRotation() const { LLQuaternion ret; +#if MESH_ENABLED + if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) + { + return ret; + } +#endif //MESH_ENABLED if (mDrawable.isNull() || mDrawable->isStatic()) { ret = getRotationEdit(); @@ -3516,12 +3817,21 @@ BOOL LLViewerObject::lineSegmentBoundingBox(const LLVector3& start, const LLVect return FALSE; } - const LLVector3* ext = mDrawable->getSpatialExtents(); + const LLVector4a* ext = mDrawable->getSpatialExtents(); - LLVector3 center = (ext[1]+ext[0])*0.5f; - LLVector3 size = (ext[1]-ext[0])*0.5f; + //VECTORIZE THIS + LLVector4a center; + center.setAdd(ext[1], ext[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); - return LLLineSegmentBoxIntersect(start, end, center, size); + LLVector4a starta, enda; + starta.load3(start.mV); + enda.load3(end.mV); + + return LLLineSegmentBoxIntersect(starta, enda, center, size); } U8 LLViewerObject::getMediaType() const @@ -3742,7 +4052,7 @@ void LLViewerObject::sendTEUpdate() const msg->addString("MediaURL", NULL); } - // JAMESDEBUG TODO send media type + // TODO send media type packTEMessage(msg); @@ -3753,7 +4063,7 @@ void LLViewerObject::sendTEUpdate() const void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) { LLPrimitive::setTE(te, texture_entry); -// JAMESDEBUG This doesn't work, don't get any textures. +// This doesn't work, don't get any textures. // if (mDrawable.notNull() && mDrawable->isVisible()) // { const LLUUID& image_id = getTE(te)->getID(); @@ -3927,7 +4237,7 @@ S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright) S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags) { - // JAMESDEBUG this might need work for media type + // this might need work for media type S32 retval = 0; const LLTextureEntry *tep = getTE(te); if (!tep) @@ -4543,6 +4853,12 @@ void LLViewerObject::adjustAudioGain(const F32 gain) bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp) { +#if MESH_ENABLED + if (LLNetworkData::PARAMS_MESH == param_type) + { + param_type = LLNetworkData::PARAMS_SCULPT; + } +#endif //MESH_ENABLED ExtraParameter* param = getExtraParameterEntryCreate(param_type); if (param) { @@ -4584,7 +4900,7 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para } default: { - llinfos << "Unknown param type." << llendl; + llinfos << "Unknown param type. (" << llformat("0x%2x",param_type) << ")" << llendl; break; } }; @@ -5015,7 +5331,7 @@ bool LLViewerObject::specialHoverCursor() const || (mClickAction != 0); } -void LLViewerObject::updateFlags() +void LLViewerObject::updateFlags(BOOL physics_changed) { LLViewerRegion* regionp = getRegion(); if(!regionp) return; @@ -5028,6 +5344,17 @@ void LLViewerObject::updateFlags() gMessageSystem->addBOOL("IsTemporary", flagTemporaryOnRez() ); gMessageSystem->addBOOL("IsPhantom", flagPhantom() ); gMessageSystem->addBOOL("CastsShadows", flagCastShadows() ); +#if MESH_ENABLED + if (physics_changed) + { + gMessageSystem->nextBlock("ExtraPhysics"); + gMessageSystem->addU8("PhysicsShapeType", getPhysicsShapeType() ); + gMessageSystem->addF32("Density", getPhysicsDensity() ); + gMessageSystem->addF32("Friction", getPhysicsFriction() ); + gMessageSystem->addF32("Restitution", getPhysicsRestitution() ); + gMessageSystem->addF32("GravityMultiplier", getPhysicsGravity() ); + } +#endif //MESH_ENABLED gMessageSystem->sendReliable( regionp->getHost() ); } @@ -5060,6 +5387,46 @@ BOOL LLViewerObject::setFlags(U32 flags, BOOL state) return setit; } +#if MESH_ENABLED +void LLViewerObject::setPhysicsShapeType(U8 type) +{ + mPhysicsShapeUnknown = false; + mPhysicsShapeType = type; + mCostStale = true; +} + +void LLViewerObject::setPhysicsGravity(F32 gravity) +{ + mPhysicsGravity = gravity; +} + +void LLViewerObject::setPhysicsFriction(F32 friction) +{ + mPhysicsFriction = friction; +} + +void LLViewerObject::setPhysicsDensity(F32 density) +{ + mPhysicsDensity = density; +} + +void LLViewerObject::setPhysicsRestitution(F32 restitution) +{ + mPhysicsRestitution = restitution; +} + +U8 LLViewerObject::getPhysicsShapeType() const +{ + if (mPhysicsShapeUnknown) + { + mPhysicsShapeUnknown = false; + gObjectList.updatePhysicsFlags(this); + } + + return mPhysicsShapeType; +} +#endif //MESH_ENABLED + void LLViewerObject::applyAngularVelocity(F32 dt) { //do target omega here @@ -5324,3 +5691,76 @@ const LLUUID &LLViewerObject::extractAttachmentItemID() return getAttachmentItemID(); } +//virtual +LLVOAvatar* LLViewerObject::getAvatar() const +{ + if (isAttachment()) + { + LLViewerObject* vobj = (LLViewerObject*) getParent(); + + while (vobj && !vobj->isAvatar()) + { + vobj = (LLViewerObject*) vobj->getParent(); + } + + return (LLVOAvatar*) vobj; + } + + return NULL; +} + +#if MESH_ENABLED +class ObjectPhysicsProperties : public LLHTTPNode +{ +public: + virtual void post( + ResponsePtr responder, + const LLSD& context, + const LLSD& input) const + { + LLSD object_data = input["body"]["ObjectData"]; + S32 num_entries = object_data.size(); + + for ( S32 i = 0; i < num_entries; i++ ) + { + LLSD& curr_object_data = object_data[i]; + U32 local_id = curr_object_data["LocalID"].asInteger(); + + // Iterate through nodes at end, since it can be on both the regular AND hover list + struct f : public LLSelectedNodeFunctor + { + U32 mID; + f(const U32& id) : mID(id) {} + virtual bool apply(LLSelectNode* node) + { + return (node->getObject() && node->getObject()->mLocalID == mID ); + } + } func(local_id); + + LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); + + if (node) + { + // The LLSD message builder doesn't know how to handle U8, so we need to send as S8 and cast + U8 type = (U8)curr_object_data["PhysicsShapeType"].asInteger(); + F32 density = (F32)curr_object_data["Density"].asReal(); + F32 friction = (F32)curr_object_data["Friction"].asReal(); + F32 restitution = (F32)curr_object_data["Restitution"].asReal(); + F32 gravity = (F32)curr_object_data["GravityMultiplier"].asReal(); + + node->getObject()->setPhysicsShapeType(type); + node->getObject()->setPhysicsGravity(gravity); + node->getObject()->setPhysicsFriction(friction); + node->getObject()->setPhysicsDensity(density); + node->getObject()->setPhysicsRestitution(restitution); + } + } + + dialog_refresh_all(); + }; +}; + +LLHTTPRegistration<ObjectPhysicsProperties> + gHTTPRegistrationObjectPhysicsProperties("/message/ObjectPhysicsProperties"); + +#endif //MESH_ENABLED diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index f81a3a149..fe31ec725 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -63,6 +63,7 @@ class LLWorld; class LLNameValue; class LLNetMap; class LLMessageSystem; +class LLPartSysData; class LLPrimitive; class LLPipeline; class LLTextureEntry; @@ -73,7 +74,7 @@ class LLViewerPartSourceScript; class LLViewerRegion; class LLViewerObjectMedia; class LLVOInventoryListener; -class LLPartSysData; +class LLVOAvatar; typedef enum e_object_update_type { @@ -172,6 +173,7 @@ public: void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; } virtual BOOL isAttachment() const { return FALSE; } + virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment virtual BOOL isHUDAttachment() const { return FALSE; } virtual void updateRadius() {}; virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius() @@ -220,6 +222,9 @@ public: virtual BOOL isFlexible() const { return FALSE; } virtual BOOL isSculpted() const { return FALSE; } +#if MESH_ENABLED + virtual BOOL isMesh() const { return FALSE; } +#endif //MESH_ENABLED // This method returns true if the object is over land owned by // the agent. @@ -322,6 +327,23 @@ public: virtual void setScale(const LLVector3 &scale, BOOL damped = FALSE); +#if MESH_ENABLED + virtual F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL, F32* unscaled_value = NULL) const; + virtual U32 getTriangleCount() const; + virtual U32 getHighLODTriangleCount(); + + void setObjectCost(F32 cost); + F32 getObjectCost(); + + void setLinksetCost(F32 cost); + F32 getLinksetCost(); + + void setPhysicsCost(F32 cost); + F32 getPhysicsCost(); + + void setLinksetPhysicsCost(F32 cost); + F32 getLinksetPhysicsCost(); +#endif //MESH_ENABLED void sendShapeUpdate(); // U8 getState() { return mState; } @@ -367,7 +389,7 @@ public: void markForUpdate(BOOL priority); void updateVolume(const LLVolumeParams& volume_params); - virtual void updateSpatialExtents(LLVector3& min, LLVector3& max); + virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); virtual F32 getBinRadius(); LLBBox getBoundingBoxAgent() const; @@ -380,7 +402,7 @@ public: void clearDrawableState(U32 state, BOOL recursive = TRUE); // Called when the drawable shifts - virtual void onShift(const LLVector3 &shift_vector) { } + virtual void onShift(const LLVector4a &shift_vector) { } ////////////////////////////////////// // @@ -455,6 +477,14 @@ public: inline BOOL flagCameraDecoupled() const { return ((mFlags & FLAGS_CAMERA_DECOUPLED) != 0); } inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); } +#if MESH_ENABLED + U8 getPhysicsShapeType() const; + inline F32 getPhysicsGravity() const { return mPhysicsGravity; } + inline F32 getPhysicsFriction() const { return mPhysicsFriction; } + inline F32 getPhysicsDensity() const { return mPhysicsDensity; } + inline F32 getPhysicsRestitution() const { return mPhysicsRestitution; } +#endif //MESH_ENABLED + bool getIncludeInSearch() const; void setIncludeInSearch(bool include_in_search); @@ -468,8 +498,15 @@ public: void setRegion(LLViewerRegion *regionp); virtual void updateRegion(LLViewerRegion *regionp) {} - void updateFlags(); + void updateFlags(BOOL physics_changed = FALSE); BOOL setFlags(U32 flag, BOOL state); +#if MESH_ENABLED + void setPhysicsShapeType(U8 type); + void setPhysicsGravity(F32 gravity); + void setPhysicsFriction(F32 friction); + void setPhysicsDensity(F32 density); + void setPhysicsRestitution(F32 restitution); +#endif //MESH_ENABLED virtual void dump() const; static U32 getNumZombieObjects() { return sNumZombieObjects; } @@ -508,6 +545,9 @@ private: ExtraParameter* getExtraParameterEntryCreate(U16 param_type); bool unpackParameterEntry(U16 param_type, LLDataPacker *dp); + // Motion prediction between updates + void interpolateLinearMotion(const F64 & time, const F32 & dt); + public: // // Viewer-side only types - use the LL_PCODE_APP mask. @@ -527,6 +567,15 @@ public: LL_VO_HUD_PART_GROUP = LL_PCODE_APP | 0xc0, } EVOType; +#if MESH_ENABLED + typedef enum e_physics_shape_types + { + PHYSICS_SHAPE_PRIM = 0, + PHYSICS_SHAPE_NONE, + PHYSICS_SHAPE_CONVEX_HULL, + } EPhysicsShapeType; +#endif //MESH_ENABLED + LLUUID mID; // unique within region, not unique across regions @@ -545,6 +594,15 @@ public: // Grabbed from UPDATE_FLAGS U32 mFlags; +#if MESH_ENABLED + // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties + U8 mPhysicsShapeType; + F32 mPhysicsGravity; + F32 mPhysicsFriction; + F32 mPhysicsDensity; + F32 mPhysicsRestitution; +#endif //MESH_ENABLED + // Pipeline classes LLPointer<LLDrawable> mDrawable; @@ -599,6 +657,8 @@ protected: void deleteParticleSource(); void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); +public: + private: void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string void deleteTEImages(); // correctly deletes list of images @@ -654,6 +714,15 @@ protected: U8 mState; // legacy LLViewerObjectMedia* mMedia; // NULL if no media associated U8 mClickAction; +#if MESH_ENABLED + F32 mObjectCost; //resource cost of this object or -1 if unknown + F32 mLinksetCost; + F32 mPhysicsCost; + F32 mLinksetPhysicsCost; + + bool mCostStale; + mutable bool mPhysicsShapeUnknown; +#endif //MESH_ENABLED static U32 sNumZombieObjects; // Objects which are dead, but not deleted @@ -669,8 +738,24 @@ protected: mutable LLVector3 mPositionRegion; mutable LLVector3 mPositionAgent; + static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64) value; } + static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64) value; } + + static void setVelocityInterpolate(BOOL value) { sVelocityInterpolate = value; } + static void setPingInterpolate(BOOL value) { sPingInterpolate = value; } + private: static S32 sNumObjects; + + static F64 sPhaseOutUpdateInterpolationTime; // For motion interpolation + static F64 sMaxUpdateInterpolationTime; // For motion interpolation + + static BOOL sVelocityInterpolate; + static BOOL sPingInterpolate; + + //-------------------------------------------------------------------- + // For objects that are attachments + //-------------------------------------------------------------------- public: // <edit> S32 getAttachmentPoint(); @@ -750,7 +835,4 @@ public: virtual void updateDrawable(BOOL force_damped); }; -extern BOOL gVelocityInterpolate; -extern BOOL gPingInterpolate; - #endif diff --git a/indra/newview/llviewerobjectbackup.cpp b/indra/newview/llviewerobjectbackup.cpp index c76281c5a..7f6325350 100644 --- a/indra/newview/llviewerobjectbackup.cpp +++ b/indra/newview/llviewerobjectbackup.cpp @@ -34,12 +34,10 @@ #include <fstream> #include <sstream> -#include "hippogridmanager.h" - // linden library includes #include "indra_constants.h" -#include "llapr.h" #include "llalertdialog.h" +#include "llapr.h" #include "llcallbacklist.h" #include "lldir.h" #include "lleconomy.h" @@ -51,6 +49,7 @@ #include "llsdutil.h" #include "llsdutil_math.h" #include "lltransactiontypes.h" +#include "llinventorydefines.h" // newview includes #include "llagent.h" @@ -63,7 +62,7 @@ #include "llfloaternamedesc.h" #include "llfloatersnapshot.h" #include "llinventorymodel.h" // gInventory -#include "llnotify.h" +#include "llnotificationsutil.h" #include "llresourcedata.h" #include "llselectmgr.h" #include "llstatusbar.h" @@ -79,9 +78,37 @@ #include "llviewerstats.h" #include "llviewerwindow.h" +#include "hippogridmanager.h" + #include "llviewerobjectbackup.h" -LLObjectBackup* LLObjectBackup::sInstance = 0; +LLObjectBackup* LLObjectBackup::sInstance = NULL; + +// Note: these default textures are initialized with hard coded values to +// prevent cheating. When not in SL, the user-configurable values are used +// instead (see setDefaultTextures() below). +static LLUUID LL_TEXTURE_PLYWOOD = LLUUID("89556747-24cb-43ed-920b-47caed15465f"); +static LLUUID LL_TEXTURE_BLANK = LLUUID("5748decc-f629-461c-9a36-a35a221fe21f"); +static LLUUID LL_TEXTURE_INVISIBLE = LLUUID("38b86f85-2575-52a9-a531-23108d8da837"); +static LLUUID LL_TEXTURE_TRANSPARENT = LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"); +static LLUUID LL_TEXTURE_MEDIA = LLUUID("8b5fec65-8d8d-9dc5-cda8-8fdf2716e361"); + +void setDefaultTextures() +{ + if (!gHippoGridManager->getConnectedGrid()->isSecondLife()) + { + // When not in SL (no texture perm check needed), we can get these + // defaults from the user settings... + LL_TEXTURE_PLYWOOD = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); + LL_TEXTURE_BLANK = LLUUID(gSavedSettings.getString("UIImgWhiteUUID")); + if (gSavedSettings.controlExists("UIImgInvisibleUUID")) + { + // This control only exists in the Cool VL Viewer (added by the + // AllowInvisibleTextureInPicker patch) + LL_TEXTURE_INVISIBLE = LLUUID(gSavedSettings.getString("UIImgInvisibleUUID")); + } + } +} class importResponder: public LLNewAgentInventoryResponder { @@ -95,7 +122,7 @@ public: //virtual virtual void uploadComplete(const LLSD& content) { - lldebugs << "LLNewAgentInventoryResponder::result from capabilities" << llendl; + LL_DEBUGS("ObjectBackup") << "LLNewAgentInventoryResponder::result from capabilities" << LL_ENDL; LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString()); LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString()); @@ -120,8 +147,8 @@ public: } // Actually add the upload to viewer inventory - llinfos << "Adding " << content["new_inventory_item"].asUUID() << " " - << content["new_asset"].asUUID() << " to inventory." << llendl; + LL_INFOS("ObjectBackup") << "Adding " << content["new_inventory_item"].asUUID() << " " + << content["new_asset"].asUUID() << " to inventory." << LL_ENDL; if (mPostData["folder_id"].asUUID().notNull()) { LLPermissions perm; @@ -154,7 +181,7 @@ public: } else { - llwarns << "Can't find a folder to put it into" << llendl; + LL_WARNS("ObjectBackup") << "Can't find a folder to put it into" << LL_ENDL; } // remove the "Uploading..." message @@ -177,7 +204,7 @@ public: { if (imageformat == IMG_CODEC_TGA && mFormattedImage->getCodec() == IMG_CODEC_J2C) { - llwarns << "FAILED: texture " << mID << " is formatted as TGA. Not saving." << llendl; + LL_WARNS("ObjectBackup") << "FAILED: texture " << mID << " is formatted as TGA. Not saving." << LL_ENDL; LLObjectBackup::getInstance()->mNonExportedTextures |= LLObjectBackup::TEXTURE_BAD_ENCODING; mFormattedImage = NULL; mImageSize = 0; @@ -202,14 +229,14 @@ public: { if (success && mFormattedImage.notNull() && mImageSize > 0) { - llinfos << "SUCCESS getting texture " << mID << llendl; + LL_INFOS("ObjectBackup") << "SUCCESS getting texture " << mID << LL_ENDL; std::string name; mID.toString(name); name = LLObjectBackup::getInstance()->getfolder() + "//" + name; - llinfos << "Saving to " << name << llendl; + LL_INFOS("ObjectBackup") << "Saving to " << name << LL_ENDL; if (!mFormattedImage->save(name)) { - llwarns << "FAILED to save texture " << mID << llendl; + LL_WARNS("ObjectBackup") << "FAILED to save texture " << mID << LL_ENDL; LLObjectBackup::getInstance()->mNonExportedTextures |= LLObjectBackup::TEXTURE_SAVED_FAILED; } } @@ -217,12 +244,12 @@ public: { if (!success) { - llwarns << "FAILED to get texture " << mID << llendl; + LL_WARNS("ObjectBackup") << "FAILED to get texture " << mID << LL_ENDL; LLObjectBackup::getInstance()->mNonExportedTextures |= LLObjectBackup::TEXTURE_MISSING; } if (mFormattedImage.isNull()) { - llwarns << "FAILED: NULL texture " << mID << llendl; + LL_WARNS("ObjectBackup") << "FAILED: NULL texture " << mID << LL_ENDL; LLObjectBackup::getInstance()->mNonExportedTextures |= LLObjectBackup::TEXTURE_IS_NULL; } } @@ -340,6 +367,9 @@ void LLObjectBackup::exportObject() mLLSD.clear(); mThisGroup.clear(); + setDefaultTextures(); + LLSelectMgr::getInstance()->getSelection()->ref(); + // Open the file save dialog AIFilePicker* filepicker = AIFilePicker::create(); filepicker->open("", FFSAVE_XML); @@ -351,6 +381,7 @@ void LLObjectBackup::exportObject_continued(AIFilePicker* filepicker) if (!filepicker->hasFilename()) { // User canceled save. + LLSelectMgr::getInstance()->getSelection()->unref(); return; } @@ -365,7 +396,7 @@ void LLObjectBackup::exportObject_continued(AIFilePicker* filepicker) bool LLObjectBackup::validatePerms(const LLPermissions *item_permissions) { - if (gHippoGridManager->getConnectedGrid()->getPlatform() == HippoGridInfo::PLATFORM_SECONDLIFE) + if (gHippoGridManager->getConnectedGrid()->isSecondLife()) { // In Second Life, you must be the creator to be permitted to export the asset. return (gAgent.getID() == item_permissions->getOwner() && @@ -390,12 +421,21 @@ bool LLObjectBackup::validatePerms(const LLPermissions *item_permissions) // the textures in the Library), whoever is the actual creator... Go figure ! LLUUID LLObjectBackup::validateTextureID(LLUUID asset_id) { - if (gHippoGridManager->getConnectedGrid()->getPlatform() != HippoGridInfo::PLATFORM_SECONDLIFE) + if (!gHippoGridManager->getConnectedGrid()->isSecondLife()) { // If we are not in Second Life, don't bother. return asset_id; } - LLUUID texture = LLUUID(gSavedSettings.getString("DefaultObjectTexture")); + LLUUID texture = LL_TEXTURE_PLYWOOD; + if (asset_id == texture || + asset_id == LL_TEXTURE_BLANK || + asset_id == LL_TEXTURE_INVISIBLE || + asset_id == LL_TEXTURE_TRANSPARENT || + asset_id == LL_TEXTURE_MEDIA) + { + // Allow to export a few default SL textures. + return asset_id; + } LLViewerInventoryCategory::cat_array_t cats; LLViewerInventoryItem::item_array_t items; LLAssetIDMatches asset_id_matches(asset_id); @@ -434,7 +474,6 @@ void LLObjectBackup::exportWorker(void *userdata) case EXPORT_INIT: { LLObjectBackup::getInstance()->show(true); - LLSelectMgr::getInstance()->getSelection()->ref(); struct ff : public LLSelectedNodeFunctor { virtual bool apply(LLSelectNode* node) @@ -449,7 +488,7 @@ void LLObjectBackup::exportWorker(void *userdata) } else { - llwarns << "Incorrect permission to export" << llendl; + LL_WARNS("ObjectBackup") << "Incorrect permission to export" << LL_ENDL; LLObjectBackup::getInstance()->mExportState = EXPORT_FAILED; LLSelectMgr::getInstance()->getSelection()->unref(); } @@ -462,13 +501,22 @@ void LLObjectBackup::exportWorker(void *userdata) { virtual bool apply(LLViewerObject* object) { + bool is_attachment = object->isAttachment(); object->boostTexturePriority(TRUE); LLViewerObject::child_list_t children = object->getChildren(); children.push_front(object); //push root onto list - LLSD prim_llsd = LLObjectBackup::getInstance()->primsToLLSD(children); + LLSD prim_llsd = LLObjectBackup::getInstance()->primsToLLSD(children, is_attachment); LLSD stuff; - stuff["root_position"] = object->getPosition().getValue(); - stuff["root_rotation"] = ll_sd_from_quaternion(object->getRotation()); + if (is_attachment) + { + stuff["root_position"] = object->getPositionEdit().getValue(); + stuff["root_rotation"] = ll_sd_from_quaternion(object->getRotationEdit()); + } + else + { + stuff["root_position"] = object->getPosition().getValue(); + stuff["root_rotation"] = ll_sd_from_quaternion(object->getRotation()); + } stuff["group_body"] = prim_llsd; LLObjectBackup::getInstance()->mLLSD["data"].append(stuff); return true; @@ -512,12 +560,12 @@ void LLObjectBackup::exportWorker(void *userdata) gIdleCallbacks.deleteFunction(exportWorker); if (LLObjectBackup::getInstance()->mNonExportedTextures == LLObjectBackup::TEXTURE_OK) { - llinfos << "Export successful and complete." << llendl; - LLNotifications::instance().add("ExportSuccessful"); + LL_INFOS("ObjectBackup") << "Export successful and complete." << LL_ENDL; + LLNotificationsUtil::add("ExportSuccessful"); } else { - llinfos << "Export successful but incomplete: some texture(s) not saved." << llendl; + LL_INFOS("ObjectBackup") << "Export successful but incomplete: some texture(s) not saved." << LL_ENDL; std::string reason; if (LLObjectBackup::getInstance()->mNonExportedTextures & LLObjectBackup::TEXTURE_BAD_PERM) { @@ -525,7 +573,7 @@ void LLObjectBackup::exportWorker(void *userdata) } if (LLObjectBackup::getInstance()->mNonExportedTextures & LLObjectBackup::TEXTURE_MISSING) { - reason += "\nMissing texture."; + reason += "\nMissing texture (retrying after full rezzing might work)."; } if (LLObjectBackup::getInstance()->mNonExportedTextures & LLObjectBackup::TEXTURE_BAD_ENCODING) { @@ -541,21 +589,21 @@ void LLObjectBackup::exportWorker(void *userdata) } LLSD args; args["REASON"] = reason; - LLNotifications::instance().add("ExportPartial", args); + LLNotificationsUtil::add("ExportPartial", args); } LLObjectBackup::getInstance()->close(); break; case EXPORT_FAILED: gIdleCallbacks.deleteFunction(exportWorker); - llwarns << "Export process aborted." << llendl; - LLNotifications::instance().add("ExportFailed"); + LL_WARNS("ObjectBackup") << "Export process aborted." << LL_ENDL; + LLNotificationsUtil::add("ExportFailed"); LLObjectBackup::getInstance()->close(); break; } } -LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list) +LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list, bool is_attachment) { LLViewerObject* object; LLSD llsd; @@ -566,7 +614,7 @@ LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list) object = (*i); LLUUID id = object->getID(); - llinfos << "Exporting prim " << object->getID().asString() << llendl; + LL_INFOS("ObjectBackup") << "Exporting prim " << object->getID().asString() << LL_ENDL; // Create an LLSD object that represents this prim. It will be injected in to the overall LLSD // tree structure @@ -588,9 +636,17 @@ LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list) } // Transforms - prim_llsd["position"] = object->getPosition().getValue(); + if (is_attachment) + { + prim_llsd["position"] = object->getPositionEdit().getValue(); + prim_llsd["rotation"] = ll_sd_from_quaternion(object->getRotationEdit()); + } + else + { + prim_llsd["position"] = object->getPosition().getValue(); + prim_llsd["rotation"] = ll_sd_from_quaternion(object->getRotation()); + } prim_llsd["scale"] = object->getScale().getValue(); - prim_llsd["rotation"] = ll_sd_from_quaternion(object->getRotation()); // Flags prim_llsd["shadows"] = object->flagCastShadows(); @@ -632,13 +688,13 @@ LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list) } if (alreadyseen == false) { - llinfos << "Found a sculpt texture, adding to list " << sculpt_texture << llendl; + LL_INFOS("ObjectBackup") << "Found a sculpt texture, adding to list " << sculpt_texture << LL_ENDL; mTexturesList.push_back(sculpt_texture); } } else { - llwarns << "Incorrect permission to export a sculpt texture." << llendl; + LL_WARNS("ObjectBackup") << "Incorrect permission to export a sculpt texture." << LL_ENDL; LLObjectBackup::getInstance()->mExportState = EXPORT_FAILED; } } @@ -655,14 +711,22 @@ LLSD LLObjectBackup::primsToLLSD(LLViewerObject::child_list_t child_list) this_te_llsd = object->getTE(i)->asLLSD(); this_te_llsd["imageid"] = t_id; te_llsd.append(this_te_llsd); - std::list<LLUUID>::iterator iter; - for (iter = mTexturesList.begin(); iter != mTexturesList.end(); iter++) - { - if ((*iter) == t_id) - alreadyseen = true; + // Do not export Linden textures even though they don't taint creation. + if (t_id != LL_TEXTURE_PLYWOOD && + t_id != LL_TEXTURE_BLANK && + t_id != LL_TEXTURE_TRANSPARENT && + t_id != LL_TEXTURE_INVISIBLE && + t_id != LL_TEXTURE_MEDIA) + { + std::list<LLUUID>::iterator iter; + for (iter = mTexturesList.begin(); iter != mTexturesList.end(); iter++) + { + if ((*iter) == t_id) + alreadyseen = true; + } + if (alreadyseen == false) + mTexturesList.push_back(t_id); } - if (alreadyseen == false) - mTexturesList.push_back(t_id); } prim_llsd["textures"] = te_llsd; @@ -679,7 +743,7 @@ void LLObjectBackup::exportNextTexture() { if (mTexturesList.empty()) { - llinfos << "Finished exporting textures." << llendl; + LL_INFOS("ObjectBackup") << "Finished exporting textures." << LL_ENDL; return; } @@ -687,7 +751,7 @@ void LLObjectBackup::exportNextTexture() std::list<LLUUID>::iterator iter; iter = mTexturesList.begin(); - while (1) + while (true) { if (iter == mTexturesList.end()) { @@ -696,6 +760,13 @@ void LLObjectBackup::exportNextTexture() } id = (*iter); + if (id.isNull()) + { + // NULL texture id: just remove and ignore. + mTexturesList.remove(id); + iter = mTexturesList.begin(); + continue; + } LLViewerTexture* imagep = LLViewerTextureManager::findTexture(id); if (imagep != NULL) @@ -716,15 +787,17 @@ void LLObjectBackup::exportNextTexture() } else { - llwarns << "We *DON'T* have the texture " << llendl; + LL_WARNS("ObjectBackup") << "We *DON'T* have the texture " << id.asString() << LL_ENDL; mNonExportedTextures |= TEXTURE_MISSING; + mTexturesList.remove(id); + return; } iter++; } mTexturesList.remove(id); - llinfos << "Requesting texture " << id << llendl; + LL_INFOS("ObjectBackup") << "Requesting texture " << id << LL_ENDL; LLImageJ2C* mFormattedImage = new LLImageJ2C; CacheReadResponder* responder = new CacheReadResponder(id, mFormattedImage); LLAppViewer::getTextureCache()->readFromCache(id, LLWorkerThread::PRIORITY_HIGH, 0, 999999, responder); @@ -735,27 +808,33 @@ void LLObjectBackup::importObject(bool upload) mTexturesList.clear(); mAssetMap.clear(); mCurrentAsset = LLUUID::null; - + + setDefaultTextures(); + mRetexture = upload; - + // Open the file open dialog - AIFilePicker* filepicker = AIFilePicker::create(); + AIFilePicker* filepicker = new AIFilePicker; filepicker->open(FFLOAD_XML, "", "import"); filepicker->run(boost::bind(&LLObjectBackup::importObject_continued, this, filepicker)); - + return; } void LLObjectBackup::importObject_continued(AIFilePicker* filepicker) { if (!filepicker->hasFilename()) + { + // User canceled save. return; - - std::string file_name = filepicker->getFilename(); + } + + std::string file_name = filepicker->getFilename(); mFolder = gDirUtilp->getDirName(file_name); llifstream import_file(file_name); LLSDSerialize::fromXML(mLLSD, import_file); import_file.close(); + show(false); mAgentPos = gAgent.getPositionAgent(); mAgentRot = LLQuaternion(gAgent.getAtAxis(), gAgent.getLeftAxis(), gAgent.getUpAxis()); @@ -770,17 +849,6 @@ void LLObjectBackup::importObject_continued(AIFilePicker* filepicker) mObjects = mLLSD["data"].size(); mPrims = 0; mRezCount = 0; - - if (mObjects <= 0) { - LLSD args; - args["MESSAGE"] = std::string("Object import failed.\nThe XML file has an incompatible format or does not contain any objects."); - LLNotifications::instance().add("GenericAlert", args); - llwarns << "Trying to import illegal XML object file." << llendl; - return; - } - - show(false); - updateImportNumbers(); for (prim_arr_it = mLLSD["data"].beginArray(); prim_arr_it != mLLSD["data"].endArray(); prim_arr_it++) @@ -806,7 +874,7 @@ void LLObjectBackup::importObject_continued(AIFilePicker* filepicker) } if (alreadyseen == false) { - llinfos << "Found a new SCULPT texture to upload " << orig << llendl; + LL_INFOS("ObjectBackup") << "Found a new SCULPT texture to upload " << orig << LL_ENDL; mTexturesList.push_back(orig); } } @@ -819,18 +887,21 @@ void LLObjectBackup::importObject_continued(AIFilePicker* filepicker) LLTextureEntry te; te.fromLLSD(the_te); - te.getID(); - bool alreadyseen = false; + LLUUID id = te.getID(); + if (id != LL_TEXTURE_PLYWOOD && id != LL_TEXTURE_BLANK && id != LL_TEXTURE_INVISIBLE) // Do not upload the default textures + { + bool alreadyseen = false; - for (iter = mTexturesList.begin(); iter != mTexturesList.end(); iter++) - { - if ((*iter) == te.getID()) - alreadyseen = true; - } - if (alreadyseen == false) - { - llinfos << "Found a new texture to upload "<< te.getID() << llendl; - mTexturesList.push_back(te.getID()); + for (iter = mTexturesList.begin(); iter != mTexturesList.end(); iter++) + { + if ((*iter) == te.getID()) + alreadyseen = true; + } + if (alreadyseen == false) + { + LL_INFOS("ObjectBackup") << "Found a new texture to upload "<< te.getID() << LL_ENDL; + mTexturesList.push_back(te.getID()); + } } } } @@ -970,7 +1041,7 @@ void LLObjectBackup::xmlToPrim(LLSD prim_llsd, LLViewerObject* object) } // Textures - llinfos << "Processing textures for prim" << llendl; + LL_INFOS("ObjectBackup") << "Processing textures for prim" << LL_ENDL; LLSD te_llsd = prim_llsd["textures"]; LLSD::array_iterator text_it; U8 i = 0; @@ -990,7 +1061,7 @@ void LLObjectBackup::xmlToPrim(LLSD prim_llsd, LLViewerObject* object) object->setTE(i++, te); } - llinfos << "Textures done !" << llendl; + LL_INFOS("ObjectBackup") << "Textures done !" << LL_ENDL; //bump the iterator now so the callbacks hook together nicely //if (mPrimImportIter != mThisGroup.endMap()) @@ -1023,7 +1094,7 @@ void LLObjectBackup::primUpdate(LLViewerObject* object) if (mPrimImportIter == mThisGroup.endMap()) { - llinfos << "Trying to link" << llendl; + LL_INFOS("ObjectBackup") << "Trying to link" << LL_ENDL; if (mToSelect.size() > 1) { @@ -1053,7 +1124,7 @@ void LLObjectBackup::primUpdate(LLViewerObject* object) if (mToSelect.empty()) { - llwarns << "error: ran out of objects to mod." << llendl; + LL_WARNS("ObjectBackup") << "error: ran out of objects to mod." << LL_ENDL; return; } @@ -1085,7 +1156,7 @@ bool LLObjectBackup::newPrim(LLViewerObject* pobject) } else { - llinfos << "All prims rezzed, moving to build stage" << llendl; + LL_INFOS("ObjectBackup") << "All prims rezzed, moving to build stage" << LL_ENDL; // Deselecting is required to ensure that the first child prim // in the link set (which is also the last rezzed prim and thus // currently selected) will be properly renamed and desced. @@ -1104,7 +1175,7 @@ void LLObjectBackup::updateMap(LLUUID uploaded_asset) if (mCurrentAsset.isNull()) return; - llinfos << "Mapping " << mCurrentAsset << " to " << uploaded_asset << llendl; + LL_INFOS("ObjectBackup") << "Mapping " << mCurrentAsset << " to " << uploaded_asset << LL_ENDL; mAssetMap.insert(std::pair<LLUUID, LLUUID>(mCurrentAsset, uploaded_asset)); } @@ -1140,13 +1211,13 @@ void myupload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ std::ostringstream llsdxml; LLSDSerialize::toXML(body, llsdxml); - lldebugs << "posting body to capability: " << llsdxml.str() << llendl; + LL_DEBUGS("ObjectBackup") << "posting body to capability: " << llsdxml.str() << LL_ENDL; //LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); LLHTTPClient::post(url, body, new importResponder(body, uuid, asset_type)); } else { - llinfos << "NewAgentInventory capability not found. Can't upload !" << llendl; + LL_INFOS("ObjectBackup") << "NewAgentInventory capability not found. Can't upload !" << LL_ENDL; } } @@ -1154,7 +1225,7 @@ void LLObjectBackup::uploadNextAsset() { if (mTexturesList.empty()) { - llinfos << "Texture list is empty, moving to rez stage." << llendl; + LL_INFOS("ObjectBackup") << "Texture list is empty, moving to rez stage." << LL_ENDL; mCurrentAsset = LLUUID::null; importFirstObject(); return; @@ -1167,7 +1238,7 @@ void LLObjectBackup::uploadNextAsset() LLUUID id = *iter; mTexturesList.pop_front(); - llinfos << "Got texture ID " << id << ": trying to upload" << llendl; + LL_INFOS("ObjectBackup") << "Got texture ID " << id << ": trying to upload" << LL_ENDL; mCurrentAsset = id; std::string struid; @@ -1182,7 +1253,7 @@ void LLObjectBackup::uploadNextAsset() S32 file_size; LLAPRFile outfile; - outfile.open(filename, LL_APR_RB, LLAPRFile::global, &file_size); + outfile.open(filename, LL_APR_RB, LLAPRFile::local, &file_size); if (outfile.getFileHandle()) { const S32 buf_size = 65536; @@ -1197,7 +1268,7 @@ void LLObjectBackup::uploadNextAsset() } else { - llwarns << "Unable to access output file " << filename << llendl; + LL_WARNS("ObjectBackup") << "Unable to access output file " << filename << LL_ENDL; uploadNextAsset(); return; } diff --git a/indra/newview/llviewerobjectbackup.h b/indra/newview/llviewerobjectbackup.h index 5ae33c382..8fa577dfe 100644 --- a/indra/newview/llviewerobjectbackup.h +++ b/indra/newview/llviewerobjectbackup.h @@ -107,7 +107,7 @@ private: LLUUID validateTextureID(LLUUID asset_id); // Convert a selection list of objects to LLSD - LLSD primsToLLSD(LLViewerObject::child_list_t child_list); + LLSD primsToLLSD(LLViewerObject::child_list_t child_list, bool is_attachment); // Start the import process void importFirstObject(); @@ -176,3 +176,4 @@ private: LLVector3 mAgentPos; LLQuaternion mAgentRot; }; + diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index 9be2aacc3..0330f9670 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -38,12 +38,14 @@ #include "timing.h" #include "llfasttimer.h" #include "llrender.h" +#include "llwindow.h" // decBusyCount() #include "llviewercontrol.h" #include "llface.h" #include "llvoavatar.h" #include "llviewerobject.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llnetmap.h" #include "llagent.h" #include "llagentcamera.h" @@ -61,6 +63,7 @@ #include "llresmgr.h" #include "llviewerregion.h" #include "llviewerstats.h" +#include "llvovolume.h" #include "lltoolmgr.h" #include "lltoolpie.h" #include "llkeyboard.h" @@ -597,33 +600,30 @@ void LLViewerObjectList::dirtyAllObjectInventory() void LLViewerObjectList::updateApparentAngles(LLAgent &agent) { S32 i; - S32 const objects_size = mObjects.size(); + S32 num_objects = 0; LLViewerObject *objectp; S32 num_updates, max_value; - // The list can have shrinked since mCurLazyUpdateIndex was last updated. - if (mCurLazyUpdateIndex >= objects_size) - { - mCurLazyUpdateIndex = 0; - } if (NUM_BINS - 1 == mCurBin) { - num_updates = objects_size - mCurLazyUpdateIndex; - max_value = objects_size; + num_updates = (S32) mObjects.size() - mCurLazyUpdateIndex; + max_value = (S32) mObjects.size(); gTextureList.setUpdateStats(TRUE); } else { - num_updates = (objects_size / NUM_BINS) + 1; - max_value = llmin(objects_size, mCurLazyUpdateIndex + num_updates); + num_updates = ((S32) mObjects.size() / NUM_BINS) + 1; + max_value = llmin((S32) mObjects.size(), mCurLazyUpdateIndex + num_updates); } - if (!gNoRender) + + // Slam priorities for textures that we care about (hovered, selected, and focused) + // Hovered + // Assumes only one level deep of parenting + LLSelectNode* nodep = LLSelectMgr::instance().getHoverNode(); + if (nodep) { - // Slam priorities for textures that we care about (hovered, selected, and focused) - // Hovered - // Assumes only one level deep of parenting - objectp = gHoverView->getLastHoverObject(); + objectp = nodep->getObject(); if (objectp) { objectp->boostTexturePriority(); @@ -654,6 +654,8 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) objectp = mObjects[i]; if (!objectp->isDead()) { + num_objects++; + // Update distance & gpw objectp->setPixelAreaAndAngle(agent); // Also sets the approx. pixel area objectp->updateTextures(); // Update the image levels of textures for this object. @@ -661,7 +663,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) } mCurLazyUpdateIndex = max_value; - if (mCurLazyUpdateIndex == objects_size) + if (mCurLazyUpdateIndex == mObjects.size()) { mCurLazyUpdateIndex = 0; } @@ -671,13 +673,214 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) LLVOAvatar::cullAvatarsByPixelArea(); } +#if MESH_ENABLED + +class LLObjectCostResponder : public LLCurl::Responder +{ +public: + LLObjectCostResponder(const LLSD& object_ids) + : mObjectIDs(object_ids) + { + } + + // Clear's the global object list's pending + // request list for all objects requested + void clear_object_list_pending_requests() + { + // TODO*: No more hard coding + for ( + LLSD::array_iterator iter = mObjectIDs.beginArray(); + iter != mObjectIDs.endArray(); + ++iter) + { + gObjectList.onObjectCostFetchFailure(iter->asUUID()); + } + } + + void error(U32 statusNum, const std::string& reason) + { + llwarns + << "Transport error requesting object cost " + << "HTTP status: " << statusNum << ", reason: " + << reason << "." << llendl; + + // TODO*: Error message to user + // For now just clear the request from the pending list + clear_object_list_pending_requests(); + } + + void result(const LLSD& content) + { + if ( !content.isMap() || content.has("error") ) + { + // Improper response or the request had an error, + // show an error to the user? + llwarns + << "Application level error when fetching object " + << "cost. Message: " << content["error"]["message"].asString() + << ", identifier: " << content["error"]["identifier"].asString() + << llendl; + + // TODO*: Adaptively adjust request size if the + // service says we've requested too many and retry + + // TODO*: Error message if not retrying + clear_object_list_pending_requests(); + return; + } + + // Success, grab the resource cost and linked set costs + // for an object if one was returned + for ( + LLSD::array_iterator iter = mObjectIDs.beginArray(); + iter != mObjectIDs.endArray(); + ++iter) + { + LLUUID object_id = iter->asUUID(); + + // Check to see if the request contains data for the object + if ( content.has(iter->asString()) ) + { + F32 link_cost = + content[iter->asString()]["linked_set_resource_cost"].asReal(); + F32 object_cost = + content[iter->asString()]["resource_cost"].asReal(); + + F32 physics_cost = content[iter->asString()]["physics_cost"].asReal(); + F32 link_physics_cost = content[iter->asString()]["linked_set_physics_cost"].asReal(); + + gObjectList.updateObjectCost(object_id, object_cost, link_cost, physics_cost, link_physics_cost); + } + else + { + // TODO*: Give user feedback about the missing data? + gObjectList.onObjectCostFetchFailure(object_id); + } + } + } + +private: + LLSD mObjectIDs; +}; + + +class LLPhysicsFlagsResponder : public LLCurl::Responder +{ +public: + LLPhysicsFlagsResponder(const LLSD& object_ids) + : mObjectIDs(object_ids) + { + } + + // Clear's the global object list's pending + // request list for all objects requested + void clear_object_list_pending_requests() + { + // TODO*: No more hard coding + for ( + LLSD::array_iterator iter = mObjectIDs.beginArray(); + iter != mObjectIDs.endArray(); + ++iter) + { + gObjectList.onPhysicsFlagsFetchFailure(iter->asUUID()); + } + } + + void error(U32 statusNum, const std::string& reason) + { + llwarns + << "Transport error requesting object physics flags " + << "HTTP status: " << statusNum << ", reason: " + << reason << "." << llendl; + + // TODO*: Error message to user + // For now just clear the request from the pending list + clear_object_list_pending_requests(); + } + + void result(const LLSD& content) + { + if ( !content.isMap() || content.has("error") ) + { + // Improper response or the request had an error, + // show an error to the user? + llwarns + << "Application level error when fetching object " + << "physics flags. Message: " << content["error"]["message"].asString() + << ", identifier: " << content["error"]["identifier"].asString() + << llendl; + + // TODO*: Adaptively adjust request size if the + // service says we've requested too many and retry + + // TODO*: Error message if not retrying + clear_object_list_pending_requests(); + return; + } + + // Success, grab the resource cost and linked set costs + // for an object if one was returned + for ( + LLSD::array_iterator iter = mObjectIDs.beginArray(); + iter != mObjectIDs.endArray(); + ++iter) + { + LLUUID object_id = iter->asUUID(); + + // Check to see if the request contains data for the object + if ( content.has(iter->asString()) ) + { + const LLSD& data = content[iter->asString()]; + + S32 shape_type = data["PhysicsShapeType"].asInteger(); + + gObjectList.updatePhysicsShapeType(object_id, shape_type); + + if (data.has("Density")) + { + F32 density = data["Density"].asReal(); + F32 friction = data["Friction"].asReal(); + F32 restitution = data["Restitution"].asReal(); + F32 gravity_multiplier = data["GravityMultiplier"].asReal(); + + gObjectList.updatePhysicsProperties(object_id, + density, friction, restitution, gravity_multiplier); + } + } + else + { + // TODO*: Give user feedback about the missing data? + gObjectList.onPhysicsFlagsFetchFailure(object_id); + } + } + } + +private: + LLSD mObjectIDs; +}; +#endif //MESH_ENABLED void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) { LLMemType mt(LLMemType::MTYPE_OBJECT); + // Update globals - gVelocityInterpolate = gSavedSettings.getBOOL("VelocityInterpolate"); - gPingInterpolate = gSavedSettings.getBOOL("PingInterpolate"); + LLViewerObject::setVelocityInterpolate( gSavedSettings.getBOOL("VelocityInterpolate") ); + LLViewerObject::setPingInterpolate( gSavedSettings.getBOOL("PingInterpolate") ); + + F32 interp_time = gSavedSettings.getF32("InterpolationTime"); + F32 phase_out_time = gSavedSettings.getF32("InterpolationPhaseOut"); + if (interp_time < 0.0 || + phase_out_time < 0.0 || + phase_out_time > interp_time) + { + llwarns << "Invalid values for InterpolationTime or InterpolationPhaseOut, resetting to defaults" << llendl; + interp_time = 3.0f; + phase_out_time = 1.0f; + } + LLViewerObject::setPhaseOutUpdateInterpolationTime( interp_time ); + LLViewerObject::setMaxUpdateInterpolationTime( phase_out_time ); + gAnimateTextures = gSavedSettings.getBOOL("AnimateTextures"); // update global timer @@ -763,9 +966,16 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) } } +#if MESH_ENABLED + fetchObjectCosts(); + fetchPhysicsFlags(); +#endif //MESH_ENABLED mNumSizeCulled = 0; mNumVisCulled = 0; + // update max computed render cost + LLVOVolume::updateRenderComplexity(); + // compute all sorts of time-based stats // don't factor frames that were paused into the stats if (! mWasPaused) @@ -822,12 +1032,130 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) } */ - mNumObjectsStat.addValue((S32) mObjects.size() - mNumDeadObjects); - mNumActiveObjectsStat.addValue(num_active_objects); - mNumSizeCulledStat.addValue(mNumSizeCulled); - mNumVisCulledStat.addValue(mNumVisCulled); + LLViewerStats::getInstance()->mNumObjectsStat.addValue((S32) mObjects.size() - mNumDeadObjects); + LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(num_active_objects); + LLViewerStats::getInstance()->mNumSizeCulledStat.addValue(mNumSizeCulled); + LLViewerStats::getInstance()->mNumVisCulledStat.addValue(mNumVisCulled); } +#if MESH_ENABLED +void LLViewerObjectList::fetchObjectCosts() +{ + // issue http request for stale object physics costs + if (!mStaleObjectCost.empty()) + { + LLViewerRegion* regionp = gAgent.getRegion(); + + if (regionp) + { + std::string url = regionp->getCapability("GetObjectCost"); + + if (!url.empty()) + { + LLSD id_list; + U32 object_index = 0; + + U32 count = 0; + + for ( + std::set<LLUUID>::iterator iter = mStaleObjectCost.begin(); + iter != mStaleObjectCost.end(); + ) + { + // Check to see if a request for this object + // has already been made. + if ( mPendingObjectCost.find(*iter) == + mPendingObjectCost.end() ) + { + mPendingObjectCost.insert(*iter); + id_list[object_index++] = *iter; + } + + mStaleObjectCost.erase(iter++); + + if (count++ >= 450) + { + break; + } + } + + if ( id_list.size() > 0 ) + { + LLSD post_data = LLSD::emptyMap(); + + post_data["object_ids"] = id_list; + LLHTTPClient::post( + url, + post_data, + new LLObjectCostResponder(id_list)); + } + } + else + { + mStaleObjectCost.clear(); + mPendingObjectCost.clear(); + } + } + } +} + +void LLViewerObjectList::fetchPhysicsFlags() +{ + // issue http request for stale object physics flags + if (!mStalePhysicsFlags.empty()) + { + LLViewerRegion* regionp = gAgent.getRegion(); + + if (regionp) + { + std::string url = regionp->getCapability("GetObjectPhysicsData"); + + if (!url.empty()) + { + LLSD id_list; + U32 object_index = 0; + + for ( + std::set<LLUUID>::iterator iter = mStalePhysicsFlags.begin(); + iter != mStalePhysicsFlags.end(); + ++iter) + { + // Check to see if a request for this object + // has already been made. + if ( mPendingPhysicsFlags.find(*iter) == + mPendingPhysicsFlags.end() ) + { + mPendingPhysicsFlags.insert(*iter); + id_list[object_index++] = *iter; + } + } + + // id_list should now contain all + // requests in mStalePhysicsFlags before, so clear + // it now + mStalePhysicsFlags.clear(); + + if ( id_list.size() > 0 ) + { + LLSD post_data = LLSD::emptyMap(); + + post_data["object_ids"] = id_list; + LLHTTPClient::post( + url, + post_data, + new LLPhysicsFlagsResponder(id_list)); + } + } + else + { + mStalePhysicsFlags.clear(); + mPendingPhysicsFlags.clear(); + } + } + } +} +#endif //MESH_ENABLED + void LLViewerObjectList::clearDebugText() { for (vobj_list_t::iterator iter = mObjects.begin(); iter != mObjects.end(); ++iter) @@ -1084,6 +1412,75 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) } } +#if MESH_ENABLED +void LLViewerObjectList::updateObjectCost(LLViewerObject* object) +{ + if (!object->isRoot()) + { //always fetch cost for the parent when fetching cost for children + mStaleObjectCost.insert(((LLViewerObject*)object->getParent())->getID()); + } + mStaleObjectCost.insert(object->getID()); +} + +void LLViewerObjectList::updateObjectCost(const LLUUID& object_id, F32 object_cost, F32 link_cost, F32 physics_cost, F32 link_physics_cost) +{ + mPendingObjectCost.erase(object_id); + + LLViewerObject* object = findObject(object_id); + if (object) + { + object->setObjectCost(object_cost); + object->setLinksetCost(link_cost); + object->setPhysicsCost(physics_cost); + object->setLinksetPhysicsCost(link_physics_cost); + } +} + +void LLViewerObjectList::onObjectCostFetchFailure(const LLUUID& object_id) +{ + //llwarns << "Failed to fetch object cost for object: " << object_id << llendl; + mPendingObjectCost.erase(object_id); +} + +void LLViewerObjectList::updatePhysicsFlags(const LLViewerObject* object) +{ + mStalePhysicsFlags.insert(object->getID()); +} + +void LLViewerObjectList::updatePhysicsShapeType(const LLUUID& object_id, S32 type) +{ + mPendingPhysicsFlags.erase(object_id); + LLViewerObject* object = findObject(object_id); + if (object) + { + object->setPhysicsShapeType(type); + } +} + +void LLViewerObjectList::updatePhysicsProperties(const LLUUID& object_id, + F32 density, + F32 friction, + F32 restitution, + F32 gravity_multiplier) +{ + mPendingPhysicsFlags.erase(object_id); + + LLViewerObject* object = findObject(object_id); + if (object) + { + object->setPhysicsDensity(density); + object->setPhysicsFriction(friction); + object->setPhysicsGravity(gravity_multiplier); + object->setPhysicsRestitution(restitution); + } +} + +void LLViewerObjectList::onPhysicsFlagsFetchFailure(const LLUUID& object_id) +{ + //llwarns << "Failed to fetch physics flags for object: " << object_id << llendl; + mPendingPhysicsFlags.erase(object_id); +} +#endif //MESH_ENABLED void LLViewerObjectList::shiftObjects(const LLVector3 &offset) @@ -1283,12 +1680,6 @@ void LLViewerObjectList::renderObjectBounds(const LLVector3 ¢er) { } -void LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent) -{ - generatePickList(camera); - renderPickList(screen_rect, pick_parcel_wall, render_transparent); -} - void LLViewerObjectList::generatePickList(LLCamera &camera) { LLViewerObject *objectp; @@ -1412,34 +1803,6 @@ void LLViewerObjectList::generatePickList(LLCamera &camera) } } -void LLViewerObjectList::renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent) -{ - gRenderForSelect = TRUE; - - gPipeline.renderForSelect(mSelectPickList, render_transparent, screen_rect); - - // - // Render pass for selected objects - // - gGL.color4f(1,1,1,1); - gViewerWindow->renderSelections( TRUE, pick_parcel_wall, FALSE ); - - //fix for DEV-19335. Don't pick hud objects when customizing avatar (camera mode doesn't play nice with nametags). - if (!gAgentCamera.cameraCustomizeAvatar()) - { - // render pickable ui elements, like names, etc. - LLHUDObject::renderAllForSelect(); - } - - gGL.flush(); - LLVertexBuffer::unbind(); - - gRenderForSelect = FALSE; - - //llinfos << "Rendered " << count << " for select" << llendl; - //llinfos << "Took " << pick_timer.getElapsedTimeF32()*1000.f << "ms to pick" << llendl; -} - LLViewerObject *LLViewerObjectList::getSelectedObject(const U32 object_id) { std::set<LLViewerObject*>::iterator pick_it; diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 90d100044..a458f8e10 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -44,6 +44,7 @@ #include "llviewerobject.h" #include "llvoavatar.h" +class LLCamera; class LLNetMap; class LLDebugBeacon; @@ -94,6 +95,24 @@ public: void updateApparentAngles(LLAgent &agent); void update(LLAgent &agent, LLWorld &world); +#if MESH_ENABLED + void fetchObjectCosts(); + void fetchPhysicsFlags(); + + void updateObjectCost(LLViewerObject* object); + void updateObjectCost(const LLUUID& object_id, F32 object_cost, F32 link_cost, F32 physics_cost, F32 link_physics_cost); + void onObjectCostFetchFailure(const LLUUID& object_id); + + void updatePhysicsFlags(const LLViewerObject* object); + void onPhysicsFlagsFetchFailure(const LLUUID& object_id); + void updatePhysicsShapeType(const LLUUID& object_id, S32 type); + void updatePhysicsProperties(const LLUUID& object_id, + F32 density, + F32 friction, + F32 restitution, + F32 gravity_multiplier); + +#endif //MESH_ENABLED void shiftObjects(const LLVector3 &offset); void repartitionObjects(); @@ -116,9 +135,7 @@ public: void updateAvatarVisibility(); // Selection related stuff - void renderObjectsForSelect(LLCamera &camera, const LLRect& screen_rect, BOOL pick_parcel_wall = FALSE, BOOL render_transparent = TRUE); void generatePickList(LLCamera &camera); - void renderPickList(const LLRect& screen_rect, BOOL pick_parcel_wall, BOOL render_transparent); LLViewerObject *getSelectedObject(const U32 object_id); @@ -157,17 +174,6 @@ public: U32 mCurBin; // Current bin we're working on... - ////////////////////// - // - // Statistics data - // - // - LLStat mNumObjectsStat; - LLStat mNumActiveObjectsStat; - LLStat mNumNewObjectsStat; - LLStat mNumSizeCulledStat; - LLStat mNumVisCulledStat; - S32 mNumNewObjects; S32 mNumSizeCulled; @@ -212,6 +218,16 @@ protected: std::map<LLUUID, LLPointer<LLViewerObject> > mUUIDObjectMap; std::map<LLUUID, LLPointer<LLVOAvatar> > mUUIDAvatarMap; +#if MESH_ENABLED + //set of objects that need to update their cost + std::set<LLUUID> mStaleObjectCost; + std::set<LLUUID> mPendingObjectCost; + + //set of objects that need to update their physics flags + std::set<LLUUID> mStalePhysicsFlags; + std::set<LLUUID> mPendingPhysicsFlags; +#endif //MESH_ENABLED + std::vector<LLDebugBeacon> mDebugBeacons; S32 mCurLazyUpdateIndex; diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp index be304fc9f..a233136b5 100644 --- a/indra/newview/llviewerparcelmedia.cpp +++ b/indra/newview/llviewerparcelmedia.cpp @@ -43,6 +43,7 @@ #include "message.h" #include "llviewermediafocus.h" #include "llviewerparcelmediaautoplay.h" +#include "llnotificationsutil.h" #include "llviewerwindow.h" #include "llfirstuse.h" #include "llpluginclassmedia.h" @@ -120,7 +121,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel) // First use warning if( ! mediaUrl.empty() && gSavedSettings.getWarning("FirstStreamingVideo") ) { - LLNotifications::instance().add("ParcelCanPlayMedia", LLSD(), LLSD(), + LLNotificationsUtil::add("ParcelCanPlayMedia", LLSD(), LLSD(), boost::bind(callback_play_media, _1, _2, parcel)); return; @@ -176,7 +177,7 @@ void LLViewerParcelMedia::update(LLParcel* parcel) { gSavedSettings.setWarning("QuickTimeInstalled", FALSE); - LLNotifications::instance().add("NoQuickTime" ); + LLNotificationsUtil::add("NoQuickTime" ); }; } } @@ -560,6 +561,11 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent LL_DEBUGS("Media") << "Media event: MEDIA_EVENT_NAME_CHANGED" << LL_ENDL; }; break; + + default: + { + LL_WARNS("Media") << "Media event: unknown event type" << LL_ENDL; + }; }; } @@ -777,7 +783,7 @@ void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type) if (media_action == "deny") { - LLNotifications::instance().add("MediaBlocked", args); + LLNotificationsUtil::add("MediaBlocked", args); if (type == 1) { LLViewerParcelMedia::stopStreamingMusic(); @@ -800,7 +806,7 @@ void LLViewerParcelMedia::filterMedia(LLParcel* parcel, U32 type) { args["TYPE"] = "audio"; } - LLNotifications::instance().add("MediaAlert", args, LLSD(), boost::bind(callback_media_alert, _1, _2, parcel, type, domain)); + LLNotificationsUtil::add("MediaAlert", args, LLSD(), boost::bind(callback_media_alert, _1, _2, parcel, type, domain)); } } @@ -838,7 +844,7 @@ void callback_media_alert(const LLSD ¬ification, const LLSD &response, LLParc } LLViewerParcelMedia::saveDomainFilterList(); args["LISTED"] = "whitelisted"; - LLNotifications::instance().add("MediaListed", args); + LLNotificationsUtil::add("MediaListed", args); } if (type == 0) { @@ -862,7 +868,7 @@ void callback_media_alert(const LLSD ¬ification, const LLSD &response, LLParc } if (option == 1) // Deny { - LLNotifications::instance().add("MediaBlocked", args); + LLNotificationsUtil::add("MediaBlocked", args); } else // Blacklist { @@ -877,7 +883,7 @@ void callback_media_alert(const LLSD ¬ification, const LLSD &response, LLParc } LLViewerParcelMedia::saveDomainFilterList(); args["LISTED"] = "blacklisted"; - LLNotifications::instance().add("MediaListed", args); + LLNotificationsUtil::add("MediaListed", args); } } @@ -928,7 +934,7 @@ void LLViewerParcelMedia::clearDomainFilterList() sAllowedMedia.clear(); sDeniedMedia.clear(); saveDomainFilterList(); - LLNotifications::instance().add("MediaFiltersCleared"); + LLNotificationsUtil::add("MediaFiltersCleared"); SLFloaterMediaFilter::setDirty(); } diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp index e68223285..c79ea10e7 100644 --- a/indra/newview/llviewerparcelmgr.cpp +++ b/indra/newview/llviewerparcelmgr.cpp @@ -39,6 +39,8 @@ #include "indra_constants.h" #include "llcachename.h" #include "llgl.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" #include "llparcel.h" #include "llsecondlifeurls.h" #include "message.h" @@ -137,21 +139,24 @@ LLViewerParcelMgr::LLViewerParcelMgr() mAgentParcel = new LLParcel(); mHoverParcel = new LLParcel(); mCollisionParcel = new LLParcel(); + mBlockedImage = LLViewerTextureManager::getFetchedTextureFromFile("noentrylines.j2c"); + mPassImage = LLViewerTextureManager::getFetchedTextureFromFile("noentrypasslines.j2c"); +} - mParcelsPerEdge = S32( REGION_WIDTH_METERS / PARCEL_GRID_STEP_METERS ); +//moved this stuff out of the constructor and into a function that we can call again after we get the region size. +//LLViewerParcelMgr needs to be changed so we either get an instance per region, or it handles various region sizes +//on a single grid properly - Patrick Sapinski (2/10/2011) +void LLViewerParcelMgr::init(F32 region_size) +{ + mParcelsPerEdge = S32( region_size / PARCEL_GRID_STEP_METERS ); mHighlightSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)]; resetSegments(mHighlightSegments); mCollisionSegments = new U8[(mParcelsPerEdge+1)*(mParcelsPerEdge+1)]; resetSegments(mCollisionSegments); - // JC: Resolved a merge conflict here, eliminated - // mBlockedImage->setAddressMode(LLTexUnit::TAM_WRAP); - // because it is done in llviewertexturelist.cpp - mBlockedImage = LLViewerTextureManager::getFetchedTextureFromFile("noentrylines.j2c"); - mPassImage = LLViewerTextureManager::getFetchedTextureFromFile("noentrypasslines.j2c"); - - S32 overlay_size = mParcelsPerEdge * mParcelsPerEdge / PARCEL_OVERLAY_CHUNKS; + S32 mParcelOverLayChunks = region_size * region_size / (128 * 128); + S32 overlay_size = mParcelsPerEdge * mParcelsPerEdge / mParcelOverLayChunks; sPackedOverlay = new U8[overlay_size]; mAgentParcelOverlay = new U8[mParcelsPerEdge * mParcelsPerEdge]; @@ -160,6 +165,8 @@ LLViewerParcelMgr::LLViewerParcelMgr() { mAgentParcelOverlay[i] = 0; } + + mTeleportInProgress = TRUE; // the initial parcel update is treated like teleport } @@ -521,7 +528,7 @@ LLParcelSelectionHandle LLViewerParcelMgr::selectLand(const LLVector3d &corner1, if (region != region_other) { - LLNotifications::instance().add("CantSelectLandFromMultipleRegions"); + LLNotificationsUtil::add("CantSelectLandFromMultipleRegions"); mSelected = FALSE; notifyObservers(); return NULL; @@ -651,14 +658,13 @@ LLParcel *LLViewerParcelMgr::getAgentParcel() const } // Return whether the agent can build on the land they are on -BOOL LLViewerParcelMgr::agentCanBuild() const +bool LLViewerParcelMgr::allowAgentBuild() const { if (mAgentParcel) { - return (gAgent.isGodlike() - || (mAgentParcel->allowModifyBy( - gAgent.getID(), - gAgent.getGroupID()))); + return (gAgent.isGodlike() || + (mAgentParcel->allowModifyBy(gAgent.getID(), gAgent.getGroupID())) || + (isParcelOwnedByAgent(mAgentParcel, GP_LAND_ALLOW_CREATE))); } else { @@ -666,19 +672,53 @@ BOOL LLViewerParcelMgr::agentCanBuild() const } } -BOOL LLViewerParcelMgr::agentCanTakeDamage() const +// Return whether anyone can build on the given parcel +bool LLViewerParcelMgr::allowAgentBuild(const LLParcel* parcel) const { - return mAgentParcel->getAllowDamage(); + return parcel->getAllowModify(); } -BOOL LLViewerParcelMgr::agentCanFly() const +bool LLViewerParcelMgr::allowAgentVoice() const { - return TRUE; + return allowAgentVoice(gAgent.getRegion(), mAgentParcel); } -F32 LLViewerParcelMgr::agentDrawDistance() const +bool LLViewerParcelMgr::allowAgentVoice(const LLViewerRegion* region, const LLParcel* parcel) const { - return 512.f; + return region && region->isVoiceEnabled() + && parcel && parcel->getParcelFlagAllowVoice(); +} + +bool LLViewerParcelMgr::allowAgentFly(const LLViewerRegion* region, const LLParcel* parcel) const +{ + return region && !region->getBlockFly() + && parcel && parcel->getAllowFly(); +} + +// Can the agent be pushed around by LLPushObject? +bool LLViewerParcelMgr::allowAgentPush(const LLViewerRegion* region, const LLParcel* parcel) const +{ + return region && !region->getRestrictPushObject() + && parcel && !parcel->getRestrictPushObject(); +} + +bool LLViewerParcelMgr::allowAgentScripts(const LLViewerRegion* region, const LLParcel* parcel) const +{ + // *NOTE: This code does not take into account group-owned parcels + // and the flag to allow group-owned scripted objects to run. + // This mirrors the traditional menu bar parcel icon code, but is not + // technically correct. + return region + && !(region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) + && !(region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) + && parcel + && parcel->getAllowOtherScripts(); +} + +bool LLViewerParcelMgr::allowAgentDamage(const LLViewerRegion* region, const LLParcel* parcel) const +{ + return (region && region->getAllowDamage()) + || (parcel && parcel->getAllowDamage()); } BOOL LLViewerParcelMgr::isOwnedAt(const LLVector3d& pos_global) const @@ -917,7 +957,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id) { if (!mSelected) { - LLNotifications::instance().add("CannotSetLandOwnerNothingSelected"); + LLNotificationsUtil::add("CannotSetLandOwnerNothingSelected"); return; } @@ -932,7 +972,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id) if (!region) { // TODO: Add a force owner version of this alert. - LLNotifications::instance().add("CannotContentifyNoRegion"); + LLNotificationsUtil::add("CannotContentifyNoRegion"); return; } @@ -940,7 +980,7 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id) LLViewerRegion *region2 = LLWorld::getInstance()->getRegionFromPosGlobal( east_north_region_check ); if (region != region2) { - LLNotifications::instance().add("CannotSetLandOwnerMultipleRegions"); + LLNotificationsUtil::add("CannotSetLandOwnerMultipleRegions"); return; } @@ -985,13 +1025,13 @@ void LLViewerParcelMgr::sendParcelGodForceToContent() { if (!mSelected) { - LLNotifications::instance().add("CannotContentifyNothingSelected"); + LLNotificationsUtil::add("CannotContentifyNothingSelected"); return; } LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); if (!region) { - LLNotifications::instance().add("CannotContentifyNoRegion"); + LLNotificationsUtil::add("CannotContentifyNoRegion"); return; } @@ -1009,14 +1049,14 @@ void LLViewerParcelMgr::sendParcelRelease() { if (!mSelected) { - LLNotifications::instance().add("CannotReleaseLandNothingSelected"); + LLNotificationsUtil::add("CannotReleaseLandNothingSelected"); return; } LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); if (!region) { - LLNotifications::instance().add("CannotReleaseLandNoRegion"); + LLNotificationsUtil::add("CannotReleaseLandNoRegion"); return; } @@ -1071,14 +1111,14 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy( { if (!mSelected || !mCurrentParcel) { - LLNotifications::instance().add("CannotBuyLandNothingSelected"); + LLNotificationsUtil::add("CannotBuyLandNothingSelected"); return NULL; } LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); if (!region) { - LLNotifications::instance().add("CannotBuyLandNoRegion"); + LLNotificationsUtil::add("CannotBuyLandNoRegion"); return NULL; } @@ -1096,7 +1136,7 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy( if (region != region2) { - LLNotifications::instance().add("CantBuyLandAcrossMultipleRegions"); + LLNotificationsUtil::add("CantBuyLandAcrossMultipleRegions"); return NULL; } } @@ -1167,28 +1207,29 @@ void LLViewerParcelMgr::sendParcelBuy(ParcelBuyInfo* info) msg->sendReliable(info->mHost); } -void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo*& info) +void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo* *info) { - delete info; - info = NULL; + // Must be here because ParcelBuyInfo is local to this .cpp file + delete *info; + *info = NULL; } void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id) { if (!mSelected || !mCurrentParcel) { - LLNotifications::instance().add("CannotDeedLandNothingSelected"); + LLNotificationsUtil::add("CannotDeedLandNothingSelected"); return; } if(group_id.isNull()) { - LLNotifications::instance().add("CannotDeedLandNoGroup"); + LLNotificationsUtil::add("CannotDeedLandNoGroup"); return; } LLViewerRegion *region = LLWorld::getInstance()->getRegionFromPosGlobal( mWestSouth ); if (!region) { - LLNotifications::instance().add("CannotDeedLandNoRegion"); + LLNotificationsUtil::add("CannotDeedLandNoRegion"); return; } @@ -1288,9 +1329,15 @@ void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, bool use_ag } -void LLViewerParcelMgr::requestHoverParcelProperties(const LLVector3d& pos) +void LLViewerParcelMgr::setHoverParcel(const LLVector3d& pos) { static U32 last_west, last_south; + + // only request parcel info when tooltip is shown + if (!gSavedSettings.getBOOL("ShowLandHoverTip")) + { + return; + } // only request parcel info if position has changed outside of the // last parcel grid step U32 west_parcel_step = (U32) floor( pos.mdV[VX] / PARCEL_GRID_STEP_METERS ); @@ -1359,8 +1406,7 @@ void LLViewerParcelMgr::processParcelOverlay(LLMessageSystem *msg, void **user) return; } - S32 parcels_per_edge = LLViewerParcelMgr::getInstance()->mParcelsPerEdge; - S32 expected_size = parcels_per_edge * parcels_per_edge / PARCEL_OVERLAY_CHUNKS; + S32 expected_size = 1024; if (packed_overlay_size != expected_size) { llwarns << "Got parcel overlay size " << packed_overlay_size @@ -1542,9 +1588,19 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use LLViewerParcelMgr::getInstance()->writeAgentParcelFromBitmap(bitmap); delete[] bitmap; + + // Let interesting parties know about agent parcel change. + LLViewerParcelMgr* instance = LLViewerParcelMgr::getInstance(); + + instance->mAgentParcelChangedSignal(); + + if (instance->mTeleportInProgress) + { + instance->mTeleportInProgress = FALSE; + instance->mTeleportFinishedSignal(gAgent.getPositionGlobal()); + } } } - // Add any pending entry to the TP history now that we got the *new* parcel name. LLFloaterTeleportHistory::getInstance()->addEntry(LLViewerParcelMgr::getInstance()->getAgentParcelName()); @@ -2021,11 +2077,11 @@ void LLViewerParcelMgr::deedLandToGroup() std::string full_name; gCacheName->getFullName(mCurrentParcel->getOwnerID(),full_name); args["NAME"] = full_name; - LLNotifications::instance().add("DeedLandToGroupWithContribution",args, LLSD(), deedAlertCB); + LLNotificationsUtil::add("DeedLandToGroupWithContribution",args, LLSD(), deedAlertCB); } else { - LLNotifications::instance().add("DeedLandToGroup",args, LLSD(), deedAlertCB); + LLNotificationsUtil::add("DeedLandToGroup",args, LLSD(), deedAlertCB); } } @@ -2051,26 +2107,26 @@ void LLViewerParcelMgr::startReleaseLand() { if (!mSelected) { - LLNotifications::instance().add("CannotReleaseLandNothingSelected"); + LLNotificationsUtil::add("CannotReleaseLandNothingSelected"); return; } if (mRequestResult == PARCEL_RESULT_NO_DATA) { - LLNotifications::instance().add("CannotReleaseLandWatingForServer"); + LLNotificationsUtil::add("CannotReleaseLandWatingForServer"); return; } if (mRequestResult == PARCEL_RESULT_MULTIPLE) { - LLNotifications::instance().add("CannotReleaseLandSelected"); + LLNotificationsUtil::add("CannotReleaseLandSelected"); return; } if (!isParcelOwnedByAgent(mCurrentParcel, GP_LAND_RELEASE) && !(gAgent.canManageEstate())) { - LLNotifications::instance().add("CannotReleaseLandDontOwn"); + LLNotificationsUtil::add("CannotReleaseLandDontOwn"); return; } @@ -2078,7 +2134,7 @@ void LLViewerParcelMgr::startReleaseLand() LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center); if (!region) { - LLNotifications::instance().add("CannotReleaseLandRegionNotFound"); + LLNotificationsUtil::add("CannotReleaseLandRegionNotFound"); return; } /* @@ -2087,21 +2143,21 @@ void LLViewerParcelMgr::startReleaseLand() { LLSD args; args["REGION"] = region->getName(); - LLNotifications::instance().add("CannotReleaseLandNoTransfer", args); + LLNotificationsUtil::add("CannotReleaseLandNoTransfer", args); return; } */ if (!mCurrentParcelSelection->mWholeParcelSelected) { - LLNotifications::instance().add("CannotReleaseLandPartialSelection"); + LLNotificationsUtil::add("CannotReleaseLandPartialSelection"); return; } // Compute claim price LLSD args; args["AREA"] = llformat("%d",mCurrentParcel->getArea()); - LLNotifications::instance().add("ReleaseLandWarning", args, LLSD(), releaseAlertCB); + LLNotificationsUtil::add("ReleaseLandWarning", args, LLSD(), releaseAlertCB); } bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const @@ -2156,7 +2212,10 @@ bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const = parcelOwner == (forGroup ? gAgent.getGroupID() : gAgent.getID()); bool isAuthorized - = (authorizeBuyer.isNull() || (gAgent.getID() == authorizeBuyer)); + = (authorizeBuyer.isNull() + || (gAgent.getID() == authorizeBuyer) + || (gAgent.hasPowerInGroup(authorizeBuyer,GP_LAND_DEED) + && gAgent.hasPowerInGroup(authorizeBuyer,GP_LAND_SET_SALE_INFO))); return isForSale && !isOwner && isAuthorized && isEmpowered; } @@ -2176,13 +2235,13 @@ void LLViewerParcelMgr::startDivideLand() { if (!mSelected) { - LLNotifications::instance().add("CannotDivideLandNothingSelected"); + LLNotificationsUtil::add("CannotDivideLandNothingSelected"); return; } if (mCurrentParcelSelection->mWholeParcelSelected) { - LLNotifications::instance().add("CannotDivideLandPartialSelection"); + LLNotificationsUtil::add("CannotDivideLandPartialSelection"); return; } @@ -2190,7 +2249,7 @@ void LLViewerParcelMgr::startDivideLand() payload["west_south_border"] = ll_sd_from_vector3d(mWestSouth); payload["east_north_border"] = ll_sd_from_vector3d(mEastNorth); - LLNotifications::instance().add("LandDivideWarning", LLSD(), payload, callbackDivideLand); + LLNotificationsUtil::add("LandDivideWarning", LLSD(), payload, callbackDivideLand); } // static @@ -2204,7 +2263,7 @@ bool LLViewerParcelMgr::callbackDivideLand(const LLSD& notification, const LLSD& LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center); if (!region) { - LLNotifications::instance().add("CannotDivideLandNoRegion"); + LLNotificationsUtil::add("CannotDivideLandNoRegion"); return false; } @@ -2233,19 +2292,19 @@ void LLViewerParcelMgr::startJoinLand() { if (!mSelected) { - LLNotifications::instance().add("CannotJoinLandNothingSelected"); + LLNotificationsUtil::add("CannotJoinLandNothingSelected"); return; } if (mCurrentParcelSelection->mWholeParcelSelected) { - LLNotifications::instance().add("CannotJoinLandEntireParcelSelected"); + LLNotificationsUtil::add("CannotJoinLandEntireParcelSelected"); return; } if (!mCurrentParcelSelection->mSelectedMultipleOwners) { - LLNotifications::instance().add("CannotJoinLandSelection"); + LLNotificationsUtil::add("CannotJoinLandSelection"); return; } @@ -2253,7 +2312,7 @@ void LLViewerParcelMgr::startJoinLand() payload["west_south_border"] = ll_sd_from_vector3d(mWestSouth); payload["east_north_border"] = ll_sd_from_vector3d(mEastNorth); - LLNotifications::instance().add("JoinLandWarning", LLSD(), payload, callbackJoinLand); + LLNotificationsUtil::add("JoinLandWarning", LLSD(), payload, callbackJoinLand); } // static @@ -2267,7 +2326,7 @@ bool LLViewerParcelMgr::callbackJoinLand(const LLSD& notification, const LLSD& r LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center); if (!region) { - LLNotifications::instance().add("CannotJoinLandNoRegion"); + LLNotificationsUtil::add("CannotJoinLandNoRegion"); return false; } @@ -2296,19 +2355,19 @@ void LLViewerParcelMgr::startDeedLandToGroup() { if (!mSelected || !mCurrentParcel) { - LLNotifications::instance().add("CannotDeedLandNothingSelected"); + LLNotificationsUtil::add("CannotDeedLandNothingSelected"); return; } if (mRequestResult == PARCEL_RESULT_NO_DATA) { - LLNotifications::instance().add("CannotDeedLandWaitingForServer"); + LLNotificationsUtil::add("CannotDeedLandWaitingForServer"); return; } if (mRequestResult == PARCEL_RESULT_MULTIPLE) { - LLNotifications::instance().add("CannotDeedLandMultipleSelected"); + LLNotificationsUtil::add("CannotDeedLandMultipleSelected"); return; } @@ -2316,7 +2375,7 @@ void LLViewerParcelMgr::startDeedLandToGroup() LLViewerRegion* region = LLWorld::getInstance()->getRegionFromPosGlobal(parcel_center); if (!region) { - LLNotifications::instance().add("CannotDeedLandNoRegion"); + LLNotificationsUtil::add("CannotDeedLandNoRegion"); return; } @@ -2328,7 +2387,7 @@ void LLViewerParcelMgr::startDeedLandToGroup() { LLSD args; args["REGION"] = region->getName(); - LLNotifications::instance().add("CannotDeedLandNoTransfer", args); + LLNotificationsUtil::add("CannotDeedLandNoTransfer", args); return; } } @@ -2478,3 +2537,52 @@ LLViewerTexture* LLViewerParcelMgr::getPassImage() const { return sPassImage; } + +boost::signals2::connection LLViewerParcelMgr::addAgentParcelChangedCallback(parcel_changed_callback_t cb) +{ + return mAgentParcelChangedSignal.connect(cb); +} +/* + * Set finish teleport callback. You can use it to observe all teleport events. + * NOTE: + * After local( in one region) teleports we + * cannot rely on gAgent.getPositionGlobal(), + * so the new position gets passed explicitly. + * Use args of this callback to get global position of avatar after teleport event. + */ +boost::signals2::connection LLViewerParcelMgr::setTeleportFinishedCallback(teleport_finished_callback_t cb) +{ + return mTeleportFinishedSignal.connect(cb); +} + +boost::signals2::connection LLViewerParcelMgr::setTeleportFailedCallback(parcel_changed_callback_t cb) +{ + return mTeleportFailedSignal.connect(cb); +} + +/* Ok, we're notified that teleport has been finished. + * We should now propagate the notification via mTeleportFinishedSignal + * to all interested parties. + */ +void LLViewerParcelMgr::onTeleportFinished(bool local, const LLVector3d& new_pos) +{ + // Treat only teleports within the same parcel as local (EXT-3139). + if (local && LLViewerParcelMgr::getInstance()->inAgentParcel(new_pos)) + { + // Local teleport. We already have the agent parcel data. + // Emit the signal immediately. + getInstance()->mTeleportFinishedSignal(new_pos); + } + else + { + // Non-local teleport (inter-region or between different parcels of the same region). + // The agent parcel data has not been updated yet. + // Let's wait for the update and then emit the signal. + mTeleportInProgress = TRUE; + } +} + +void LLViewerParcelMgr::onTeleportFailed() +{ + mTeleportFailedSignal(); +} diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h index 236dbcbec..bdbd471aa 100644 --- a/indra/newview/llviewerparcelmgr.h +++ b/indra/newview/llviewerparcelmgr.h @@ -68,6 +68,9 @@ const F32 PARCEL_POST_HEIGHT = 0.666f; // Base class for people who want to "observe" changes in the viewer // parcel selection. + +//FIXME: this should be done by grabbing a floating parcel selection and observing changes on it, not the parcel mgr +//--RN class LLParcelObserver { public: @@ -79,9 +82,16 @@ class LLViewerParcelMgr : public LLSingleton<LLViewerParcelMgr> { public: + typedef boost::function<void (const LLVector3d&)> teleport_finished_callback_t; + typedef boost::signals2::signal<void (const LLVector3d&)> teleport_finished_signal_t; + typedef boost::function<void()> parcel_changed_callback_t; + typedef boost::signals2::signal<void()> parcel_changed_signal_t; + LLViewerParcelMgr(); ~LLViewerParcelMgr(); + void init(F32 region_size); + static void cleanupGlobals(); BOOL selectionEmpty() const; @@ -160,10 +170,31 @@ public: LLParcel* getCollisionParcel() const; - BOOL agentCanTakeDamage() const; - BOOL agentCanFly() const; - F32 agentDrawDistance() const; - BOOL agentCanBuild() const; + // Can this agent build on the parcel he is on? + // Used for parcel property icons in nav bar. + bool allowAgentBuild() const; + bool allowAgentBuild(const LLParcel* parcel) const; + + // Can this agent speak on the parcel he is on? + // Used for parcel property icons in nav bar. + bool allowAgentVoice() const; + bool allowAgentVoice(const LLViewerRegion* region, const LLParcel* parcel) const; + + // Can this agent start flying on this parcel? + // Used for parcel property icons in nav bar. + bool allowAgentFly(const LLViewerRegion* region, const LLParcel* parcel) const; + + // Can this agent be pushed by llPushObject() on this parcel? + // Used for parcel property icons in nav bar. + bool allowAgentPush(const LLViewerRegion* region, const LLParcel* parcel) const; + + // Can scripts written by non-parcel-owners run on the agent's current + // parcel? Used for parcel property icons in nav bar. + bool allowAgentScripts(const LLViewerRegion* region, const LLParcel* parcel) const; + + // Can the agent be damaged here? + // Used for parcel property icons in nav bar. + bool allowAgentDamage(const LLViewerRegion* region, const LLParcel* parcel) const; F32 getHoverParcelWidth() const { return F32(mHoverEastNorth.mdV[VX] - mHoverWestSouth.mdV[VX]); } @@ -209,7 +240,7 @@ public: void sendParcelDwellRequest(); // If the point is outside the current hover parcel, request more data - void requestHoverParcelProperties(const LLVector3d& pos_global); + void setHoverParcel(const LLVector3d& pos_global); bool canAgentBuyParcel(LLParcel*, bool forGroup) const; @@ -235,7 +266,7 @@ public: BOOL remove_contribution); // callers responsibility to call deleteParcelBuy() on return value void sendParcelBuy(ParcelBuyInfo*); - void deleteParcelBuy(ParcelBuyInfo*&); + void deleteParcelBuy(ParcelBuyInfo* *); void sendParcelDeed(const LLUUID& group_id); @@ -261,6 +292,12 @@ public: // the agent is banned or not in the allowed group BOOL isCollisionBanned(); + boost::signals2::connection addAgentParcelChangedCallback(parcel_changed_callback_t cb); + boost::signals2::connection setTeleportFinishedCallback(teleport_finished_callback_t cb); + boost::signals2::connection setTeleportFailedCallback(parcel_changed_callback_t cb); + void onTeleportFinished(bool local, const LLVector3d& new_pos); + void onTeleportFailed(); + static BOOL isParcelOwnedByAgent(const LLParcel* parcelp, U64 group_proxy_power); static BOOL isParcelModifiableByAgent(const LLParcel* parcelp, U64 group_proxy_power); @@ -308,6 +345,11 @@ private: LLDynamicArray<LLParcelObserver*> mObservers; + BOOL mTeleportInProgress; + teleport_finished_signal_t mTeleportFinishedSignal; + parcel_changed_signal_t mTeleportFailedSignal; + parcel_changed_signal_t mAgentParcelChangedSignal; + // Array of pieces of parcel edges to potentially draw // Has (parcels_per_edge + 1) * (parcels_per_edge + 1) elements so // we can represent edges of the grid. diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp index fc6e1b1d0..7989b6686 100644 --- a/indra/newview/llviewerparceloverlay.cpp +++ b/indra/newview/llviewerparceloverlay.cpp @@ -43,21 +43,23 @@ // newview includes #include "llagentcamera.h" +#include "llviewertexture.h" #include "llviewercontrol.h" #include "llsurface.h" #include "llviewerregion.h" -#include "llagent.h" #include "llviewercamera.h" #include "llviewertexturelist.h" #include "llselectmgr.h" #include "llfloatertools.h" #include "llglheaders.h" +#include "pipeline.h" const U8 OVERLAY_IMG_COMPONENTS = 4; LLViewerParcelOverlay::LLViewerParcelOverlay(LLViewerRegion* region, F32 region_width_meters) : mRegion( region ), mParcelGridsPerEdge( S32( region_width_meters / PARCEL_GRID_STEP_METERS ) ), + mRegionSize(S32(region_width_meters)), mDirty( FALSE ), mTimeSinceLastUpdate(), mOverlayTextureIdx(-1), @@ -148,6 +150,120 @@ BOOL LLViewerParcelOverlay::isOwnedOther(const LLVector3& pos) const return (PARCEL_OWNED == overlay || PARCEL_FOR_SALE == overlay); } +bool LLViewerParcelOverlay::encroachesOwned(const std::vector<LLBBox>& boxes) const +{ + // boxes are expected to already be axis aligned + for (U32 i = 0; i < boxes.size(); ++i) + { + LLVector3 min = boxes[i].getMinAgent(); + LLVector3 max = boxes[i].getMaxAgent(); + + S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + + for (S32 row = top; row <= bottom; row++) + { + for (S32 column = left; column <= right; column++) + { + U8 type = ownership(row, column); + if ((PARCEL_SELF == type) + || (PARCEL_GROUP == type)) + { + return true; + } + } + } + } + return false; +} +bool LLViewerParcelOverlay::encroachesOnUnowned(const std::vector<LLBBox>& boxes) const +{ + // boxes are expected to already be axis aligned + for (U32 i = 0; i < boxes.size(); ++i) + { + LLVector3 min = boxes[i].getMinAgent(); + LLVector3 max = boxes[i].getMaxAgent(); + + S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 top = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 bottom = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + + for (S32 row = top; row <= bottom; row++) + { + for (S32 column = left; column <= right; column++) + { + U8 type = ownership(row, column); + if ((PARCEL_SELF != type)) + { + return true; + } + } + } + } + return false; +} + +bool LLViewerParcelOverlay::encroachesOnNearbyParcel(const std::vector<LLBBox>& boxes) const +{ + // boxes are expected to already be axis aligned + for (U32 i = 0; i < boxes.size(); ++i) + { + LLVector3 min = boxes[i].getMinAgent(); + LLVector3 max = boxes[i].getMaxAgent(); + + // If an object crosses region borders it crosses a parcel + if ( min.mV[VX] < 0 + || min.mV[VY] < 0 + || max.mV[VX] > REGION_WIDTH_METERS + || max.mV[VY] > REGION_WIDTH_METERS) + { + return true; + } + + S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 bottom = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + S32 top = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1)); + + const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge; + + for (S32 row = bottom; row <= top; row++) + { + for (S32 col = left; col <= right; col++) + { + // This is not the rightmost column + if (col < GRIDS_PER_EDGE-1) + { + U8 east_overlay = mOwnership[row*GRIDS_PER_EDGE+col+1]; + // If the column to the east of the current one marks + // the other parcel's west edge and the box extends + // to the west it crosses the parcel border. + if ((east_overlay & PARCEL_WEST_LINE) && col < right) + { + return true; + } + } + + // This is not the topmost column + if (row < GRIDS_PER_EDGE-1) + { + U8 north_overlay = mOwnership[(row+1)*GRIDS_PER_EDGE+col]; + // If the row to the north of the current one marks + // the other parcel's south edge and the box extends + // to the south it crosses the parcel border. + if ((north_overlay & PARCEL_SOUTH_LINE) && row < top) + { + return true; + } + } + } + } + } + return false; +} BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const { S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS); @@ -298,7 +414,8 @@ void LLViewerParcelOverlay::uncompressLandOverlay(S32 chunk, U8 *packed_overlay) { // Unpack the message data into the ownership array S32 size = mParcelGridsPerEdge * mParcelGridsPerEdge; - S32 chunk_size = size / PARCEL_OVERLAY_CHUNKS; + S32 mParcelOverLayChunks = mRegionSize * mRegionSize / (128 * 128); + S32 chunk_size = size / mParcelOverLayChunks; memcpy(mOwnership + chunk*chunk_size, packed_overlay, chunk_size); /*Flawfinder: ignore*/ @@ -807,7 +924,7 @@ S32 LLViewerParcelOverlay::renderPropertyLines () F32* vertexp; U8* colorp; - const F32 PROPERTY_LINE_CLIP_DIST = 256.f; + const F32 PROPERTY_LINE_CLIP_DIST_SQUARED = 256.f * 256.f; for (i = 0; i < mVertexCount; i += vertex_per_edge) { @@ -818,7 +935,7 @@ S32 LLViewerParcelOverlay::renderPropertyLines () vertex.mV[VY] = *(vertexp+1); vertex.mV[VZ] = *(vertexp+2); - if (dist_vec_squared2D(vertex, camera_region) > PROPERTY_LINE_CLIP_DIST*PROPERTY_LINE_CLIP_DIST) + if (dist_vec_squared2D(vertex, camera_region) > PROPERTY_LINE_CLIP_DIST_SQUARED) { continue; } diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h index 161b7a386..111ccd687 100644 --- a/indra/newview/llviewerparceloverlay.h +++ b/indra/newview/llviewerparceloverlay.h @@ -36,6 +36,7 @@ // The ownership data for land parcels. // One of these structures per region. +#include "llbbox.h" #include "lldarray.h" #include "llframetimer.h" #include "lluuid.h" @@ -60,6 +61,14 @@ public: BOOL isOwnedSelf(const LLVector3& pos) const; BOOL isOwnedGroup(const LLVector3& pos) const; BOOL isOwnedOther(const LLVector3& pos) const; + + // "encroaches" means the prim hangs over the parcel, but its center + // might be in another parcel. for now, we simply test axis aligned + // bounding boxes which isn't perfect, but is close + bool encroachesOwned(const std::vector<LLBBox>& boxes) const; + bool encroachesOnUnowned(const std::vector<LLBBox>& boxes) const; + bool encroachesOnNearbyParcel(const std::vector<LLBBox>& boxes) const; + BOOL isSoundLocal(const LLVector3& pos) const; BOOL isBuildCameraAllowed(const LLVector3& pos) const; @@ -100,6 +109,7 @@ private: LLViewerRegion* mRegion; S32 mParcelGridsPerEdge; + S32 mRegionSize; LLPointer<LLViewerTexture> mTexture; LLPointer<LLImageRaw> mImageRaw; diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 216adc892..21c180e09 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -161,8 +161,8 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 ¢er_agent, const F32 bo if (group != NULL) { - LLVector3 center(group->mOctreeNode->getCenter()); - LLVector3 size(group->mOctreeNode->getSize()); + LLVector3 center(group->mOctreeNode->getCenter().getF32ptr()); + LLVector3 size(group->mOctreeNode->getSize().getF32ptr()); size += LLVector3(0.01f, 0.01f, 0.01f); mMinObjPos = center - size; mMaxObjPos = center + size; diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index f13a9a89f..8f1f72518 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -35,7 +35,7 @@ #include "lldarrayptr.h" #include "llframetimer.h" -#include "llmemory.h" +#include "llpointer.h" #include "llpartdata.h" #include "llviewerpartsource.h" diff --git a/indra/newview/llviewerpartsource.h b/indra/newview/llviewerpartsource.h index 2aa2bfaa1..540e30eb1 100644 --- a/indra/newview/llviewerpartsource.h +++ b/indra/newview/llviewerpartsource.h @@ -33,8 +33,9 @@ #ifndef LL_LLVIEWERPARTSOURCE_H #define LL_LLVIEWERPARTSOURCE_H -#include "llmemory.h" +#include "llrefcount.h" #include "llpartdata.h" +#include "llpointer.h" #include "llquaternion.h" #include "v3math.h" diff --git a/indra/newview/llviewerpluginmanager.cpp b/indra/newview/llviewerpluginmanager.cpp index fdd48736e..4dc8b0e14 100644 --- a/indra/newview/llviewerpluginmanager.cpp +++ b/indra/newview/llviewerpluginmanager.cpp @@ -32,7 +32,7 @@ #include "llviewerprecompiledheaders.h" #include "llviewerpluginmanager.h" -#include "llnotifications.h" +#include "llnotificationsutil.h" void LLViewerPluginManager::destroyPlugin() { @@ -61,6 +61,6 @@ void LLViewerPluginManager::send_plugin_failure_warning(std::string const& plugi LL_WARNS("Plugin") << "plugin intialization failed for plugin: " << plugin_basename << LL_ENDL; LLSD args; args["MIME_TYPE"] = plugin_basename; // FIXME: Use different notification. - LLNotifications::instance().add("NoPlugin", args); + LLNotificationsUtil::add("NoPlugin", args); } diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index 85eaabee9..d2681503b 100644 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -96,7 +96,6 @@ #include "llstack.h" #include "llstat.h" #include "llstl.h" -#include "llstrider.h" #include "llstring.h" #include "llstringtable.h" #include "llsys.h" diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index a6cbec632..51a02a053 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -69,7 +69,8 @@ #include "llspatialpartition.h" #include "stringize.h" #include "llviewercontrol.h" - +#include "llsdserialize.h" +#include "llviewerparcelmgr.h" extern BOOL gNoRender; @@ -101,6 +102,8 @@ public: { } + void buildCapabilityNames(LLSD& capabilityNames); + // The surfaces and other layers LLSurface* mLandp; @@ -239,9 +242,9 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mCacheLoaded(FALSE), mCacheDirty(FALSE), mReleaseNotesRequested(FALSE), - mCapabilitiesReceived(false) + mCapabilitiesReceived(false), + mWidth(region_width_meters) { - mWidth = region_width_meters; mImpl->mOriginGlobal = from_region_handle(handle); updateRenderMatrix(); @@ -253,7 +256,7 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mImpl->mCompositionp = new LLVLComposition(mImpl->mLandp, grids_per_region_edge, - region_width_meters / grids_per_region_edge); + mWidth / grids_per_region_edge); mImpl->mCompositionp->setSurface(mImpl->mLandp); // Create the surfaces @@ -266,7 +269,9 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, if (!gNoRender) { - mParcelOverlay = new LLViewerParcelOverlay(this, region_width_meters); + mParcelOverlay = new LLViewerParcelOverlay(this, mWidth); + //Re-init the parcel mgr for this sim + LLViewerParcelMgr::getInstance()->init(mWidth); } else { @@ -1142,6 +1147,20 @@ void LLViewerRegion::getInfo(LLSD& info) info["Region"]["Handle"]["y"] = (LLSD::Integer)y; } +void LLViewerRegion::getSimulatorFeatures(LLSD& sim_features) +{ + sim_features = mSimulatorFeatures; +} + +void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) +{ + std::stringstream str; + + LLSDSerialize::toPrettyXML(sim_features, str); + llinfos << str.str() << llendl; + mSimulatorFeatures = sim_features; +} + LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp) { U32 local_id = objectp->getLocalID(); @@ -1466,6 +1485,82 @@ void LLViewerRegion::unpackRegionHandshake() msg->sendReliable(host); } + +void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) +{ + //capabilityNames.append("AttachmentResources"); //Script limits (llfloaterscriptlimits.cpp) + //capabilityNames.append("AvatarPickerSearch"); //Display name/SLID lookup (llfloateravatarpicker.cpp) + capabilityNames.append("ChatSessionRequest"); + capabilityNames.append("CopyInventoryFromNotecard"); + capabilityNames.append("DispatchRegionInfo"); + capabilityNames.append("EstateChangeInfo"); + capabilityNames.append("EventQueueGet"); + /*capabilityNames.append("EnvironmentSettings"); + capabilityNames.append("ObjectMedia"); + capabilityNames.append("ObjectMediaNavigate");*/ + + if (false)//gSavedSettings.getBOOL("UseHTTPInventory")) //Caps suffixed with 2 by LL. Don't update until rest of fetch system is updated first. + { + capabilityNames.append("FetchLib"); + capabilityNames.append("FetchLibDescendents"); + capabilityNames.append("FetchInventory"); + capabilityNames.append("FetchInventoryDescendents"); + } + + capabilityNames.append("GetDisplayNames"); + capabilityNames.append("GetTexture"); +#if MESH_ENABLED + capabilityNames.append("GetMesh"); + capabilityNames.append("GetObjectCost"); + capabilityNames.append("GetObjectPhysicsData"); +#endif //MESH_ENABLED + capabilityNames.append("GroupProposalBallot"); + + capabilityNames.append("HomeLocation"); + //capabilityNames.append("LandResources"); //Script limits (llfloaterscriptlimits.cpp) + capabilityNames.append("MapLayer"); + capabilityNames.append("MapLayerGod"); +#if MESH_IMPORT + capabilityNames.append("MeshUploadFlag"); +#endif //MESH_IMPORT + capabilityNames.append("NewFileAgentInventory"); + capabilityNames.append("ParcelPropertiesUpdate"); + capabilityNames.append("ParcelMediaURLFilterList"); + capabilityNames.append("ParcelNavigateMedia"); + capabilityNames.append("ParcelVoiceInfoRequest"); + capabilityNames.append("ProductInfoRequest"); + capabilityNames.append("ProvisionVoiceAccountRequest"); + capabilityNames.append("RemoteParcelRequest"); + capabilityNames.append("RequestTextureDownload"); + capabilityNames.append("ResourceCostSelected"); //Unreferenced? + capabilityNames.append("SearchStatRequest"); + capabilityNames.append("SearchStatTracking"); + capabilityNames.append("SendPostcard"); + capabilityNames.append("SendUserReport"); + capabilityNames.append("SendUserReportWithScreenshot"); + capabilityNames.append("ServerReleaseNotes"); + //capabilityNames.append("SimConsole"); + capabilityNames.append("SimulatorFeatures"); + capabilityNames.append("SetDisplayName"); + //capabilityNames.append("SimConsoleAsync"); + capabilityNames.append("StartGroupProposal"); + capabilityNames.append("TextureStats"); + capabilityNames.append("UntrustedSimulatorMessage"); + capabilityNames.append("UpdateAgentInformation"); + capabilityNames.append("UpdateAgentLanguage"); + capabilityNames.append("UpdateGestureAgentInventory"); + capabilityNames.append("UpdateNotecardAgentInventory"); + capabilityNames.append("UpdateScriptAgent"); + capabilityNames.append("UpdateGestureTaskInventory"); + capabilityNames.append("UpdateNotecardTaskInventory"); + capabilityNames.append("UpdateScriptTask"); + capabilityNames.append("UploadBakedTexture"); + //capabilityNames.append("ViewerMetrics"); + capabilityNames.append("ViewerStartAuction"); + capabilityNames.append("ViewerStats"); + // Please add new capabilities alphabetically to reduce + // merge conflicts. +} void LLViewerRegion::setSeedCapability(const std::string& url) { if (getCapability("Seed") == url) @@ -1481,57 +1576,9 @@ void LLViewerRegion::setSeedCapability(const std::string& url) setCapability("Seed", url); LLSD capabilityNames = LLSD::emptyArray(); - capabilityNames.append("ChatSessionRequest"); - capabilityNames.append("CopyInventoryFromNotecard"); - capabilityNames.append("DispatchRegionInfo"); - capabilityNames.append("EstateChangeInfo"); - capabilityNames.append("EventQueueGet"); - if (false)//gSavedSettings.getBOOL("UseHTTPInventory")) //Caps suffixed with 2 by LL. Don't update until rest of fetch system is updated first. - { - capabilityNames.append("FetchLib"); - capabilityNames.append("FetchLibDescendents"); - capabilityNames.append("FetchInventory"); - capabilityNames.append("FetchInventoryDescendents"); - } - capabilityNames.append("GetDisplayNames"); - capabilityNames.append("GetTexture"); - capabilityNames.append("GroupProposalBallot"); - - capabilityNames.append("HomeLocation"); - capabilityNames.append("MapLayer"); - capabilityNames.append("MapLayerGod"); - capabilityNames.append("NewFileAgentInventory"); - capabilityNames.append("ParcelPropertiesUpdate"); - capabilityNames.append("ParcelMediaURLFilterList"); - capabilityNames.append("ParcelNavigateMedia"); - capabilityNames.append("ParcelVoiceInfoRequest"); - capabilityNames.append("ProductInfoRequest"); - capabilityNames.append("ProvisionVoiceAccountRequest"); - capabilityNames.append("RemoteParcelRequest"); - capabilityNames.append("RequestTextureDownload"); - capabilityNames.append("SearchStatRequest"); - capabilityNames.append("SearchStatTracking"); - capabilityNames.append("SendPostcard"); - capabilityNames.append("SendUserReport"); - capabilityNames.append("SendUserReportWithScreenshot"); - capabilityNames.append("ServerReleaseNotes"); - capabilityNames.append("SetDisplayName"); - capabilityNames.append("StartGroupProposal"); - capabilityNames.append("TextureStats"); - capabilityNames.append("UntrustedSimulatorMessage"); - capabilityNames.append("UpdateAgentInformation"); - capabilityNames.append("UpdateAgentLanguage"); - capabilityNames.append("UpdateGestureAgentInventory"); - capabilityNames.append("UpdateNotecardAgentInventory"); - capabilityNames.append("UpdateScriptAgent"); - capabilityNames.append("UpdateGestureTaskInventory"); - capabilityNames.append("UpdateNotecardTaskInventory"); - capabilityNames.append("UpdateScriptTask"); - capabilityNames.append("UploadBakedTexture"); - capabilityNames.append("ViewerStartAuction"); - capabilityNames.append("ViewerStats"); - // Please add new capabilities alphabetically to reduce - // merge conflicts. + + mImpl->buildCapabilityNames(capabilityNames); + llinfos << "posting to seed " << url << llendl; @@ -1539,6 +1586,42 @@ void LLViewerRegion::setSeedCapability(const std::string& url) LLHTTPClient::post(url, capabilityNames, mImpl->mHttpResponderPtr); } +class SimulatorFeaturesReceived : public LLHTTPClient::Responder +{ + LOG_CLASS(SimulatorFeaturesReceived); +public: + SimulatorFeaturesReceived(LLViewerRegion* region) + : mRegion(region) + { } + + + void error(U32 statusNum, const std::string& reason) + { + LL_WARNS2("AppInit", "SimulatorFeatures") << statusNum << ": " << reason << LL_ENDL; + } + + void result(const LLSD& content) + { + if(!mRegion) //region is removed or responder is not created. + { + return ; + } + + mRegion->setSimulatorFeatures(content); + } + + static boost::intrusive_ptr<SimulatorFeaturesReceived> build( + LLViewerRegion* region) + { + return boost::intrusive_ptr<SimulatorFeaturesReceived>( + new SimulatorFeaturesReceived(region)); + } + +private: + LLViewerRegion* mRegion; +}; + + void LLViewerRegion::setCapability(const std::string& name, const std::string& url) { if(name == "EventQueueGet") @@ -1551,6 +1634,11 @@ void LLViewerRegion::setCapability(const std::string& name, const std::string& u { LLHTTPSender::setSender(mImpl->mHost, new LLCapHTTPSender(url)); } + else if (name == "SimulatorFeatures") + { + // kick off a request for simulator features + LLHTTPClient::get(url, new SimulatorFeaturesReceived(this)); + } else { mImpl->mCapabilities[name] = url; @@ -1584,6 +1672,21 @@ bool LLViewerRegion::capabilitiesReceived() const void LLViewerRegion::setCapabilitiesReceived(bool received) { mCapabilitiesReceived = received; + + // Tell interested parties that we've received capabilities, + // so that they can safely use getCapability(). + if (received) + { + mCapabilitiesReceivedSignal(getRegionID()); + + // This is a single-shot signal. Forget callbacks to save resources. + mCapabilitiesReceivedSignal.disconnect_all_slots(); + } +} + +boost::signals2::connection LLViewerRegion::setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb) +{ + return mCapabilitiesReceivedSignal.connect(cb); } void LLViewerRegion::logActiveCapabilities() const @@ -1628,3 +1731,18 @@ std::string LLViewerRegion::getDescription() const { return stringize(*this); } + +#if MESH_ENABLED +bool LLViewerRegion::meshUploadEnabled() const +{ + return (mSimulatorFeatures.has("MeshUploadEnabled") && + mSimulatorFeatures["MeshUploadEnabled"].asBoolean()); +} + +bool LLViewerRegion::meshRezEnabled() const +{ + return (mSimulatorFeatures.has("MeshRezEnabled") && + mSimulatorFeatures["MeshRezEnabled"].asBoolean()); +} +#endif //MESH_ENABLED + diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 645c240fc..86f657d60 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -96,6 +96,8 @@ public: NUM_PARTITIONS } eObjectPartitions; + typedef boost::signals2::signal<void(const LLUUID& region_id)> caps_received_signal_t; + LLViewerRegion(const U64 &handle, const LLHost &host, const U32 surface_grid_width, @@ -240,6 +242,7 @@ public: // has region received its final (not seed) capability list? bool capabilitiesReceived() const; void setCapabilitiesReceived(bool received); + boost::signals2::connection setCapabilitiesReceivedCallback(const caps_received_signal_t::slot_type& cb); static bool isSpecialCapabilityName(const std::string &name); void logActiveCapabilities() const; @@ -279,6 +282,13 @@ public: void getInfo(LLSD& info); +#if MESH_ENABLED + bool meshRezEnabled() const; + bool meshUploadEnabled() const; +#endif //MESH_ENABLED + + void getSimulatorFeatures(LLSD& info); + void setSimulatorFeatures(const LLSD& info); typedef enum { @@ -406,8 +416,11 @@ private: bool mAlive; // can become false if circuit disconnects bool mCapabilitiesReceived; + caps_received_signal_t mCapabilitiesReceivedSignal; BOOL mReleaseNotesRequested; + + LLSD mSimulatorFeatures; }; inline BOOL LLViewerRegion::getAllowDamage() const diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 0ab17f6d7..f7f860385 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -72,17 +72,56 @@ LLVector4 gShinyOrigin; LLGLSLShader gWLSkyProgram(LLViewerShaderMgr::SHADER_WINDLIGHT); LLGLSLShader gWLCloudProgram(LLViewerShaderMgr::SHADER_WINDLIGHT); +//utility shaders +LLGLSLShader gOcclusionProgram(LLViewerShaderMgr::SHADER_INTERFACE); +LLGLSLShader gCustomAlphaProgram(LLViewerShaderMgr::SHADER_INTERFACE); +LLGLSLShader gGlowCombineProgram(LLViewerShaderMgr::SHADER_INTERFACE); +LLGLSLShader gTwoTextureAddProgram(LLViewerShaderMgr::SHADER_INTERFACE); +LLGLSLShader gUIProgram(LLViewerShaderMgr::SHADER_INTERFACE); +LLGLSLShader gSolidColorProgram(LLViewerShaderMgr::SHADER_INTERFACE); + //object shaders LLGLSLShader gObjectSimpleProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectSimpleWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectSimpleAlphaMaskProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectSimpleWaterAlphaMaskProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectFullbrightProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectFullbrightWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectFullbrightAlphaMaskProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectFullbrightShinyProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectFullbrightShinyWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectShinyProgram(LLViewerShaderMgr::SHADER_OBJECT); LLGLSLShader gObjectShinyWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); - +LLGLSLShader gObjectBumpProgram(LLViewerShaderMgr::SHADER_OBJECT); + +LLGLSLShader gObjectSimpleNonIndexedProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectSimpleNonIndexedWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectAlphaMaskNonIndexedProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectFullbrightNonIndexedProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectFullbrightNonIndexedWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectFullbrightShinyNonIndexedProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectFullbrightShinyNonIndexedWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectShinyNonIndexedProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gObjectShinyNonIndexedWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); + + + +#if MESH_ENABLED +//object hardware skinning shaders +LLGLSLShader gSkinnedObjectSimpleProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gSkinnedObjectFullbrightProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gSkinnedObjectFullbrightShinyProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gSkinnedObjectShinySimpleProgram(LLViewerShaderMgr::SHADER_OBJECT); + +LLGLSLShader gSkinnedObjectSimpleWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gSkinnedObjectFullbrightWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +LLGLSLShader gSkinnedObjectShinySimpleWaterProgram(LLViewerShaderMgr::SHADER_OBJECT); +#endif //MESH_ENABLED + //environment shaders LLGLSLShader gTerrainProgram(LLViewerShaderMgr::SHADER_ENVIRONMENT); LLGLSLShader gTerrainWaterProgram(LLViewerShaderMgr::SHADER_WATER); //note, water. @@ -97,7 +136,8 @@ LLGLSLShader gAvatarProgram(LLViewerShaderMgr::SHADER_AVATAR); LLGLSLShader gAvatarWaterProgram(LLViewerShaderMgr::SHADER_AVATAR); LLGLSLShader gAvatarEyeballProgram(LLViewerShaderMgr::SHADER_AVATAR); LLGLSLShader gAvatarPickProgram(LLViewerShaderMgr::SHADER_AVATAR); //Not in mShaderList - +LLGLSLShader gImpostorProgram(LLViewerShaderMgr::SHADER_OBJECT); + // Effects Shaders LLGLSLShader gGlowProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList LLGLSLShader gGlowExtractProgram(LLViewerShaderMgr::SHADER_EFFECT); //Not in mShaderList @@ -110,6 +150,14 @@ LLGLSLShader gDeferredImpostorProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredEdgeProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredWaterProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics LLGLSLShader gDeferredDiffuseProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList +LLGLSLShader gDeferredDiffuseAlphaMaskProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredNonIndexedDiffuseProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram(LLViewerShaderMgr::SHADER_DEFERRED); +#if MESH_ENABLED +LLGLSLShader gDeferredSkinnedDiffuseProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredSkinnedBumpProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredSkinnedAlphaProgram(LLViewerShaderMgr::SHADER_DEFERRED); +#endif //MESH_ENABLED LLGLSLShader gDeferredBumpProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList LLGLSLShader gDeferredTerrainProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList LLGLSLShader gDeferredTreeProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList @@ -123,7 +171,11 @@ LLGLSLShader gDeferredSunProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredBlurLightProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredSoftenProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED); //Not in mShaderList +LLGLSLShader gDeferredShadowAlphaMaskProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredAvatarShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED);//Not in mShaderList +#if MESH_ENABLED +LLGLSLShader gDeferredAttachmentShadowProgram(LLViewerShaderMgr::SHADER_DEFERRED); +#endif //MESH_ENABLED LLGLSLShader gDeferredAlphaProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics LLGLSLShader gDeferredFullbrightProgram(LLViewerShaderMgr::SHADER_DEFERRED); //calculatesAtmospherics LLGLSLShader gDeferredGIProgram(LLViewerShaderMgr::SHADER_DEFERRED); @@ -131,8 +183,12 @@ LLGLSLShader gDeferredGIFinalProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredPostGIProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredPostProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gDeferredPostNoDoFProgram(LLViewerShaderMgr::SHADER_DEFERRED); - +LLGLSLShader gDeferredWLSkyProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredWLCloudProgram(LLViewerShaderMgr::SHADER_DEFERRED); +LLGLSLShader gDeferredStarProgram(LLViewerShaderMgr::SHADER_DEFERRED); LLGLSLShader gLuminanceGatherProgram(LLViewerShaderMgr::SHADER_DEFERRED); + + //current avatar shader parameter pointer GLint gAvatarMatrixParam; @@ -295,6 +351,9 @@ void LLViewerShaderMgr::setShaders() return; } + //setup preprocessor definitions + LLShaderMgr::instance()->mDefinitions["samples"] = llformat("%d", gSavedSettings.getU32("RenderFSAASamples")/*gGLManager.getNumFBOFSAASamples(gSavedSettings.getU32("RenderFSAASamples"))*/); + LLShaderMgr::instance()->mDefinitions["NUM_TEX_UNITS"] = llformat("%d", gGLManager.mNumTextureImageUnits); reentrance = true; initAttribsAndUniforms(); @@ -331,9 +390,13 @@ void LLViewerShaderMgr::setShaders() } mMaxAvatarShaderLevel = 0; + LLGLSLShader::sNoFixedFunction = false; if (LLFeatureManager::getInstance()->isFeatureAvailable("VertexShaderEnable") && gSavedSettings.getBOOL("VertexShaderEnable")) { + //using shaders, disable fixed function + static const LLCachedControl<bool> renderforcefixedfuncs("ShyotlUseLegacyRenderPath",false); + LLGLSLShader::sNoFixedFunction = !renderforcefixedfuncs; S32 light_class = 2; S32 env_class = 2; S32 obj_class = 2; @@ -410,16 +473,15 @@ void LLViewerShaderMgr::setShaders() // Load all shaders to set max levels loadShadersEnvironment(); loadShadersWater(); - loadShadersObject(); loadShadersWindLight(); loadShadersEffects(); loadShadersInterface(); - -#if 0 && LL_DARWIN // force avatar shaders off for mac - mVertexShaderLevel[SHADER_AVATAR] = 0; - sMaxAvatarShaderLevel = 0; -#else - if (gSavedSettings.getBOOL("RenderAvatarVP")) + + // Load max avatar shaders to set the max level + mVertexShaderLevel[SHADER_AVATAR] = 3; + mMaxAvatarShaderLevel = 3; + + if (gSavedSettings.getBOOL("RenderAvatarVP") && loadShadersObject()) { BOOL avatar_cloth = gSavedSettings.getBOOL("RenderAvatarCloth"); S32 avatar_class = 1; @@ -453,18 +515,30 @@ void LLViewerShaderMgr::setShaders() else { mVertexShaderLevel[SHADER_AVATAR] = 0; - gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); + mVertexShaderLevel[SHADER_DEFERRED] = 0; + + if (gSavedSettings.getBOOL("RenderAvatarVP")) + { + gSavedSettings.setBOOL("RenderDeferred", FALSE); + gSavedSettings.setBOOL("RenderAvatarCloth", FALSE); + gSavedSettings.setBOOL("RenderAvatarVP", FALSE); + } + loadShadersAvatar(); // unloads + loadShadersObject(); } if (!loadShadersDeferred()) { gSavedSettings.setBOOL("RenderDeferred", FALSE); + reentrance = false; + setShaders(); + return; } -#endif } else { + LLGLSLShader::sNoFixedFunction = false; gPipeline.mVertexShadersEnabled = FALSE; gPipeline.mVertexShadersLoaded = 0; for (S32 i = 0; i < SHADER_COUNT; i++) @@ -481,6 +555,7 @@ void LLViewerShaderMgr::setShaders() } else { + LLGLSLShader::sNoFixedFunction = false; gPipeline.mVertexShadersEnabled = FALSE; gPipeline.mVertexShadersLoaded = 0; for (S32 i = 0; i < SHADER_COUNT; i++) @@ -491,6 +566,10 @@ void LLViewerShaderMgr::setShaders() { gViewerWindow->setCursor(UI_CURSOR_ARROW); } + + LLWaterParamManager::getInstance()->updateShaderLinks(); + LLWLParamManager::getInstance()->updateShaderLinks(); + gPipeline.createGLBuffers(); reentrance = false; } @@ -554,6 +633,9 @@ BOOL LLViewerShaderMgr::loadBasicShaders() shaders.push_back( make_pair( "lighting/lightSpecularV.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); shaders.push_back( make_pair( "windlight/atmosphericsV.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); shaders.push_back( make_pair( "avatar/avatarSkinV.glsl", 1 ) ); +#if MESH_ENABLED + shaders.push_back( make_pair( "avatar/objectSkinV.glsl", 1 ) ); +#endif //MESH_ENABLED // We no longer have to bind the shaders to global glhandles, they are automatically added to a map now. for (U32 i = 0; i < shaders.size(); i++) @@ -570,24 +652,49 @@ BOOL LLViewerShaderMgr::loadBasicShaders() shaders.clear(); shaders.reserve(13); - shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "windlight/gammaF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT]) ); - shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "windlight/transportF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); - shaders.push_back( make_pair( "environment/waterFogF.glsl", mVertexShaderLevel[SHADER_WATER] ) ); - shaders.push_back( make_pair( "lighting/lightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/lightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/lightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); - shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + S32 ch = gGLManager.mNumTextureImageUnits-1; + + static const LLCachedControl<bool> no_texture_indexing("ShyotlUseLegacyTextureBatching",false); + if (gGLManager.mGLVersion < 3.1f || no_texture_indexing) + { //force to 1 texture index channel for old drivers + ch = 1; + } + + std::vector<S32> index_channels; + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsVarsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/gammaF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT]) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/atmosphericsF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "windlight/transportF.glsl", mVertexShaderLevel[SHADER_WINDLIGHT] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "environment/waterFogF.glsl", mVertexShaderLevel[SHADER_WATER] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightAlphaMaskNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightNonIndexedAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterNonIndexedF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightWaterAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightWaterAlphaMaskF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); + index_channels.push_back(ch); shaders.push_back( make_pair( "lighting/lightFullbrightShinyWaterF.glsl", mVertexShaderLevel[SHADER_LIGHTING] ) ); for (U32 i = 0; i < shaders.size(); i++) { // Note usage of GL_FRAGMENT_SHADER_ARB - if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB) == 0) + if (loadShaderFile(shaders[i].first, shaders[i].second, GL_FRAGMENT_SHADER_ARB, index_channels[i]) == 0) { return FALSE; } @@ -818,7 +925,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (mVertexShaderLevel[SHADER_DEFERRED] == 0) { unloadShaderClass(SHADER_DEFERRED); - return FALSE; + return TRUE; } mVertexShaderLevel[SHADER_AVATAR] = 1; @@ -830,11 +937,84 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredDiffuseProgram.mName = "Deferred Diffuse Shader"; gDeferredDiffuseProgram.mShaderFiles.clear(); gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits; gDeferredDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredDiffuseProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Alpha Mask Shader"; + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.clear(); + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits; + gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredNonIndexedDiffuseAlphaMaskProgram.mName = "Deferred Diffuse Non-Indexed Alpha Mask Shader"; + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.clear(); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredNonIndexedDiffuseAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredNonIndexedDiffuseAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredNonIndexedDiffuseProgram.mName = "Non Indexed Deferred Diffuse Shader"; + gDeferredNonIndexedDiffuseProgram.mShaderFiles.clear(); + gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredNonIndexedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredNonIndexedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredNonIndexedDiffuseProgram.createShader(NULL, NULL); + } + +#if MESH_ENABLED + if (success) + { + gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader"; + gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedDiffuseProgram.mShaderFiles.clear(); + gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedDiffuseProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader"; + gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedBumpProgram.mShaderFiles.clear(); + gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL); + } + + if (success) + { + gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader"; + gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true; + gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true; + gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true; + gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true; + gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true; + gDeferredSkinnedAlphaProgram.mShaderFiles.clear(); + gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL); + } +#endif //MESH_ENABLED + if (success) { gDeferredBumpProgram.mName = "Deferred Bump Shader"; @@ -944,6 +1124,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAlphaProgram.mFeatures.hasGamma = true; gDeferredAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredAlphaProgram.mFeatures.hasLighting = true; + gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels + if (mVertexShaderLevel[SHADER_DEFERRED] < 1) + { + gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits; + } + else + { //shave off some texture units for shadow maps + gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits - 6; + } + gDeferredAlphaProgram.mShaderFiles.clear(); gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -957,7 +1147,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredFullbrightProgram.mFeatures.calculatesAtmospherics = true; gDeferredFullbrightProgram.mFeatures.hasGamma = true; gDeferredFullbrightProgram.mFeatures.hasTransport = true; - gDeferredFullbrightProgram.mFeatures.isFullbright = true; + gDeferredFullbrightProgram.mFeatures.mIndexedTextureChannels = gGLManager.mNumTextureImageUnits; gDeferredFullbrightProgram.mShaderFiles.clear(); gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -982,12 +1172,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (success) { std::string fragment; - + + /*//Keep this! Fixes shadow softening with ssao off. + //Disabled for now. if (mVertexShaderLevel[SHADER_DEFERRED] < 2 && !gSavedSettings.getBOOL("RenderDeferredSSAO")) { fragment = "deferred/softenLightNoSSAOF.glsl"; } - else + else*/ { fragment = "deferred/softenLightF.glsl"; } @@ -997,6 +1189,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB)); gDeferredSoftenProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB)); gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + + if (gSavedSettings.getBOOL("RenderDeferredSSAO")) + { //if using SSAO, take screen space light map into account as if shadows are enabled + gDeferredSoftenProgram.mShaderLevel = llmax(gDeferredSoftenProgram.mShaderLevel, 2); + } + success = gDeferredSoftenProgram.createShader(NULL, NULL); } @@ -1010,6 +1208,16 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredShadowProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader"; + gDeferredShadowAlphaMaskProgram.mShaderFiles.clear(); + gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredShadowAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL); + } + if (success) { gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader"; @@ -1021,6 +1229,19 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredAvatarShadowProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); } +#if MESH_ENABLED + if (success) + { + gDeferredAttachmentShadowProgram.mName = "Deferred Attachment Shadow Shader"; + gDeferredAttachmentShadowProgram.mFeatures.hasObjectSkinning = true; + gDeferredAttachmentShadowProgram.mShaderFiles.clear(); + gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredAttachmentShadowProgram.mShaderFiles.push_back(make_pair("deferred/attachmentShadowF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAttachmentShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + success = gDeferredAttachmentShadowProgram.createShader(NULL, NULL); + } +#endif //MESH_ENABLED + if (success) { gTerrainProgram.mName = "Deferred Terrain Shader"; @@ -1051,9 +1272,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true; gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; + gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true; gDeferredAvatarAlphaProgram.mShaderFiles.clear(); gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB)); gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms); } @@ -1078,6 +1300,40 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() success = gDeferredPostNoDoFProgram.createShader(NULL, NULL); } + if (success) + { + gDeferredWLSkyProgram.mName = "Deferred Windlight Sky Shader"; + //gWLSkyProgram.mFeatures.hasGamma = true; + gDeferredWLSkyProgram.mShaderFiles.clear(); + gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY; + success = gDeferredWLSkyProgram.createShader(NULL, &mWLUniforms); + } + + if (success) + { + gDeferredWLCloudProgram.mName = "Deferred Windlight Cloud Program"; + gDeferredWLCloudProgram.mShaderFiles.clear(); + gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY; + success = gDeferredWLCloudProgram.createShader(NULL, &mWLUniforms); + } + + if (success) + { + gDeferredStarProgram.mName = "Deferred Star Program"; + gDeferredStarProgram.mShaderFiles.clear(); + gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsV.glsl", GL_VERTEX_SHADER_ARB)); + gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB)); + gDeferredStarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; + gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY; + success = gDeferredStarProgram.createShader(NULL, &mWLUniforms); + } + if (mVertexShaderLevel[SHADER_DEFERRED] > 1) { if (success) @@ -1093,16 +1349,6 @@ BOOL LLViewerShaderMgr::loadShadersDeferred() if (mVertexShaderLevel[SHADER_DEFERRED] > 2) { - if (success) - { - gDeferredPostProgram.mName = "Deferred Post Shader"; - gDeferredPostProgram.mShaderFiles.clear(); - gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB)); - gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB)); - gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; - success = gDeferredPostProgram.createShader(NULL, NULL); - } - if (success) { gDeferredPostGIProgram.mName = "Deferred Post GI Shader"; @@ -1154,7 +1400,184 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (mVertexShaderLevel[SHADER_OBJECT] == 0) { unloadShaderClass(SHADER_OBJECT); - return FALSE; + return TRUE; + } + + if (success) + { + gObjectSimpleNonIndexedProgram.mName = "Non indexed Shader"; + gObjectSimpleNonIndexedProgram.mFeatures.calculatesLighting = true; + gObjectSimpleNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleNonIndexedProgram.mFeatures.hasGamma = true; + gObjectSimpleNonIndexedProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleNonIndexedProgram.mFeatures.hasLighting = true; + gObjectSimpleNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectSimpleNonIndexedProgram.mShaderFiles.clear(); + gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectSimpleNonIndexedWaterProgram.mName = "Non indexed Water Shader"; + gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesLighting = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.hasLighting = true; + gObjectSimpleNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectSimpleNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectAlphaMaskNonIndexedProgram.mName = "Non indexed alpha mask Shader"; + gObjectAlphaMaskNonIndexedProgram.mFeatures.calculatesLighting = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasGamma = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasAtmospherics = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasLighting = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectAlphaMaskNonIndexedProgram.mFeatures.hasAlphaMask = true; + gObjectAlphaMaskNonIndexedProgram.mShaderFiles.clear(); + gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectAlphaMaskNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectAlphaMaskNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectAlphaMaskNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectAlphaMaskNonIndexedWaterProgram.mName = "Non indexed alpha mask Water Shader"; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.calculatesLighting = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasLighting = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectAlphaMaskNonIndexedWaterProgram.mFeatures.hasAlphaMask = true; + gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectAlphaMaskNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectAlphaMaskNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectAlphaMaskNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectAlphaMaskNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightNonIndexedProgram.mName = "Non Indexed Fullbright Shader"; + gObjectFullbrightNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightNonIndexedProgram.mFeatures.hasGamma = true; + gObjectFullbrightNonIndexedProgram.mFeatures.hasTransport = true; + gObjectFullbrightNonIndexedProgram.mFeatures.isFullbright = true; + gObjectFullbrightNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightNonIndexedProgram.mShaderFiles.clear(); + gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightNonIndexedProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightNonIndexedWaterProgram.mName = "Non Indexed Fullbright Water Shader"; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.isFullbright = true; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.hasTransport = true; + gObjectFullbrightNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectShinyNonIndexedProgram.mName = "Non Indexed Shiny Shader"; + gObjectShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectShinyNonIndexedProgram.mFeatures.calculatesLighting = true; + gObjectShinyNonIndexedProgram.mFeatures.hasGamma = true; + gObjectShinyNonIndexedProgram.mFeatures.hasAtmospherics = true; + gObjectShinyNonIndexedProgram.mFeatures.isShiny = true; + gObjectShinyNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectShinyNonIndexedProgram.mShaderFiles.clear(); + gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectShinyNonIndexedProgram.createShader(NULL, &mShinyUniforms); + } + + if (success) + { + gObjectShinyNonIndexedWaterProgram.mName = "Non Indexed Shiny Water Shader"; + gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.calculatesLighting = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.isShiny = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.hasAtmospherics = true; + gObjectShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectShinyNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, &mShinyUniforms); + } + + if (success) + { + gObjectFullbrightShinyNonIndexedProgram.mName = "Non Indexed Fullbright Shiny Shader"; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.isFullbright = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.isShiny = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasGamma = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.hasTransport = true; + gObjectFullbrightShinyNonIndexedProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.clear(); + gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, &mShinyUniforms); + } + + if (success) + { + gObjectFullbrightShinyNonIndexedWaterProgram.mName = "Non Indexed Fullbright Shiny Water Shader"; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isFullbright = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.isShiny = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasGamma = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasTransport = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mFeatures.disableTextureIndex = true; + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.clear(); + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, &mShinyUniforms); + } + + if (success) + { + gImpostorProgram.mName = "Impostor Shader"; + gImpostorProgram.mFeatures.disableTextureIndex = true; + gImpostorProgram.mShaderFiles.clear(); + gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorV.glsl", GL_VERTEX_SHADER_ARB)); + gImpostorProgram.mShaderFiles.push_back(make_pair("objects/impostorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gImpostorProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gImpostorProgram.createShader(NULL, NULL); } if (success) @@ -1165,12 +1588,46 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleProgram.mFeatures.hasGamma = true; gObjectSimpleProgram.mFeatures.hasAtmospherics = true; gObjectSimpleProgram.mFeatures.hasLighting = true; + gObjectSimpleProgram.mFeatures.mIndexedTextureChannels = 0; gObjectSimpleProgram.mShaderFiles.clear(); gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; success = gObjectSimpleProgram.createShader(NULL, NULL); } + + if (success) + { + gObjectSimpleAlphaMaskProgram.mName = "Simple Alpha Mask Shader"; + gObjectSimpleAlphaMaskProgram.mFeatures.calculatesLighting = true; + gObjectSimpleAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasGamma = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasLighting = true; + gObjectSimpleAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectSimpleAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectSimpleAlphaMaskProgram.mShaderFiles.clear(); + gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectBumpProgram.mName = "Bump Shader"; + /*gObjectBumpProgram.mFeatures.calculatesLighting = true; + gObjectBumpProgram.mFeatures.calculatesAtmospherics = true; + gObjectBumpProgram.mFeatures.hasGamma = true; + gObjectBumpProgram.mFeatures.hasAtmospherics = true; + gObjectBumpProgram.mFeatures.hasLighting = true; + gObjectBumpProgram.mFeatures.mIndexedTextureChannels = 0;*/ + gObjectBumpProgram.mShaderFiles.clear(); + gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectBumpProgram.createShader(NULL, NULL); + } if (success) { @@ -1180,6 +1637,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; gObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; gObjectSimpleWaterProgram.mFeatures.hasLighting = true; + gObjectSimpleWaterProgram.mFeatures.mIndexedTextureChannels = 0; gObjectSimpleWaterProgram.mShaderFiles.clear(); gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1188,6 +1646,24 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gObjectSimpleWaterProgram.createShader(NULL, NULL); } + if (success) + { + gObjectSimpleWaterAlphaMaskProgram.mName = "Simple Water Alpha Mask Shader"; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.calculatesLighting = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasWaterFog = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasAtmospherics = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasLighting = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectSimpleWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.clear(); + gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL); + } + if (success) { gObjectFullbrightProgram.mName = "Fullbright Shader"; @@ -1195,6 +1671,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightProgram.mFeatures.hasGamma = true; gObjectFullbrightProgram.mFeatures.hasTransport = true; gObjectFullbrightProgram.mFeatures.isFullbright = true; + gObjectFullbrightProgram.mFeatures.mIndexedTextureChannels = 0; gObjectFullbrightProgram.mShaderFiles.clear(); gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1209,6 +1686,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightWaterProgram.mFeatures.isFullbright = true; gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; gObjectFullbrightWaterProgram.mFeatures.hasTransport = true; + gObjectFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = 0; gObjectFullbrightWaterProgram.mShaderFiles.clear(); gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1217,6 +1695,39 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gObjectFullbrightWaterProgram.createShader(NULL, NULL); } + if (success) + { + gObjectFullbrightAlphaMaskProgram.mName = "Fullbright Alpha Mask Shader"; + gObjectFullbrightAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasGamma = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasTransport = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.isFullbright = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightAlphaMaskProgram.mShaderFiles.clear(); + gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL); + } + + if (success) + { + gObjectFullbrightWaterAlphaMaskProgram.mName = "Fullbright Water Shader"; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.isFullbright = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasTransport = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasAlphaMask = true; + gObjectFullbrightWaterAlphaMaskProgram.mFeatures.mIndexedTextureChannels = 0; + gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.clear(); + gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightV.glsl", GL_VERTEX_SHADER_ARB)); + gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER; + success = gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL); + } + if (success) { gObjectShinyProgram.mName = "Shiny Shader"; @@ -1225,6 +1736,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectShinyProgram.mFeatures.hasGamma = true; gObjectShinyProgram.mFeatures.hasAtmospherics = true; gObjectShinyProgram.mFeatures.isShiny = true; + gObjectShinyProgram.mFeatures.mIndexedTextureChannels = 0; gObjectShinyProgram.mShaderFiles.clear(); gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1240,6 +1752,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectShinyWaterProgram.mFeatures.isShiny = true; gObjectShinyWaterProgram.mFeatures.hasWaterFog = true; gObjectShinyWaterProgram.mFeatures.hasAtmospherics = true; + gObjectShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0; gObjectShinyWaterProgram.mShaderFiles.clear(); gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB)); @@ -1256,6 +1769,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyProgram.mFeatures.isShiny = true; gObjectFullbrightShinyProgram.mFeatures.hasGamma = true; gObjectFullbrightShinyProgram.mFeatures.hasTransport = true; + gObjectFullbrightShinyProgram.mFeatures.mIndexedTextureChannels = 0; gObjectFullbrightShinyProgram.mShaderFiles.clear(); gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1272,6 +1786,7 @@ BOOL LLViewerShaderMgr::loadShadersObject() gObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true; gObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true; gObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true; + gObjectFullbrightShinyWaterProgram.mFeatures.mIndexedTextureChannels = 0; gObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB)); gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1280,6 +1795,154 @@ BOOL LLViewerShaderMgr::loadShadersObject() success = gObjectFullbrightShinyWaterProgram.createShader(NULL, &mShinyUniforms); } +#if MESH_ENABLED + + if (mVertexShaderLevel[SHADER_AVATAR] > 0) + { //load hardware skinned attachment shaders + if (success) + { + gSkinnedObjectSimpleProgram.mName = "Skinned Simple Shader"; + gSkinnedObjectSimpleProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectSimpleProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectSimpleProgram.mFeatures.hasGamma = true; + gSkinnedObjectSimpleProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectSimpleProgram.mFeatures.hasLighting = true; + gSkinnedObjectSimpleProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectSimpleProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectSimpleProgram.mShaderFiles.clear(); + gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectSimpleProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectSimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectSimpleProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightProgram.mName = "Skinned Fullbright Shader"; + gSkinnedObjectFullbrightProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectFullbrightProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader"; + gSkinnedObjectFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.isShiny = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightShinyProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectFullbrightShinyProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms); + } + + if (success) + { + gSkinnedObjectShinySimpleProgram.mName = "Skinned Shiny Simple Shader"; + gSkinnedObjectShinySimpleProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectShinySimpleProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasGamma = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectShinySimpleProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectShinySimpleProgram.mFeatures.isShiny = true; + gSkinnedObjectShinySimpleProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectShinySimpleProgram.mShaderFiles.clear(); + gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectShinySimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectShinySimpleProgram.createShader(NULL, &mShinyUniforms); + } + + if (success) + { + gSkinnedObjectSimpleWaterProgram.mName = "Skinned Simple Water Shader"; + gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasLighting = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectSimpleWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectSimpleWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectSimpleWaterProgram.mShaderFiles.clear(); + gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectSimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectSimpleWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightWaterProgram.mName = "Skinned Fullbright Water Shader"; + gSkinnedObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectFullbrightWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectFullbrightWaterProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightWaterProgram.createShader(NULL, NULL); + } + + if (success) + { + gSkinnedObjectFullbrightShinyWaterProgram.mName = "Skinned Fullbright Shiny Water Shader"; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasTransport = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isShiny = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.isFullbright = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectFullbrightShinyWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.clear(); + gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, &mShinyUniforms); + } + + if (success) + { + gSkinnedObjectShinySimpleWaterProgram.mName = "Skinned Shiny Simple Water Shader"; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesLighting = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.calculatesAtmospherics = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasGamma = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasAtmospherics = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasObjectSkinning = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.isShiny = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.hasWaterFog = true; + gSkinnedObjectShinySimpleWaterProgram.mFeatures.disableTextureIndex = true; + gSkinnedObjectShinySimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; + gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.clear(); + gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB)); + gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; + success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, &mShinyUniforms); + } + } +#endif //MESH_ENABLED if( !success ) { mVertexShaderLevel[SHADER_OBJECT] = 0; @@ -1308,6 +1971,8 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarProgram.mFeatures.hasGamma = true; gAvatarProgram.mFeatures.hasAtmospherics = true; gAvatarProgram.mFeatures.hasLighting = true; + gAvatarProgram.mFeatures.hasAlphaMask = true; + gAvatarProgram.mFeatures.disableTextureIndex = true; gAvatarProgram.mShaderFiles.clear(); gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1323,6 +1988,8 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarWaterProgram.mFeatures.hasWaterFog = true; gAvatarWaterProgram.mFeatures.hasAtmospherics = true; gAvatarWaterProgram.mFeatures.hasLighting = true; + gAvatarWaterProgram.mFeatures.hasAlphaMask = true; + gAvatarWaterProgram.mFeatures.disableTextureIndex = true; gAvatarWaterProgram.mShaderFiles.clear(); gAvatarWaterProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB)); gAvatarWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1343,6 +2010,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() { gAvatarPickProgram.mName = "Avatar Pick Shader"; gAvatarPickProgram.mFeatures.hasSkinning = true; + gAvatarPickProgram.mFeatures.disableTextureIndex = true; gAvatarPickProgram.mShaderFiles.clear(); gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB)); gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1359,6 +2027,8 @@ BOOL LLViewerShaderMgr::loadShadersAvatar() gAvatarEyeballProgram.mFeatures.hasGamma = true; gAvatarEyeballProgram.mFeatures.hasAtmospherics = true; gAvatarEyeballProgram.mFeatures.hasLighting = true; + gAvatarEyeballProgram.mFeatures.hasAlphaMask = true; + gAvatarEyeballProgram.mFeatures.disableTextureIndex = true; gAvatarEyeballProgram.mShaderFiles.clear(); gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballV.glsl", GL_VERTEX_SHADER_ARB)); gAvatarEyeballProgram.mShaderFiles.push_back(make_pair("avatar/eyeballF.glsl", GL_FRAGMENT_SHADER_ARB)); @@ -1396,6 +2066,85 @@ BOOL LLViewerShaderMgr::loadShadersInterface() success = gHighlightProgram.createShader(NULL, NULL); } + if (success) + { + gUIProgram.mName = "UI Shader"; + gUIProgram.mShaderFiles.clear(); + gUIProgram.mShaderFiles.push_back(make_pair("interface/uiV.glsl", GL_VERTEX_SHADER_ARB)); + gUIProgram.mShaderFiles.push_back(make_pair("interface/uiF.glsl", GL_FRAGMENT_SHADER_ARB)); + gUIProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gUIProgram.createShader(NULL, NULL); + } + + if (success) + { + gCustomAlphaProgram.mName = "Custom Alpha Shader"; + gCustomAlphaProgram.mShaderFiles.clear(); + gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaV.glsl", GL_VERTEX_SHADER_ARB)); + gCustomAlphaProgram.mShaderFiles.push_back(make_pair("interface/customalphaF.glsl", GL_FRAGMENT_SHADER_ARB)); + gCustomAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gCustomAlphaProgram.createShader(NULL, NULL); + } + + if (success) + { + gGlowCombineProgram.mName = "Glow Combine Shader"; + gGlowCombineProgram.mShaderFiles.clear(); + gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineV.glsl", GL_VERTEX_SHADER_ARB)); + gGlowCombineProgram.mShaderFiles.push_back(make_pair("interface/glowcombineF.glsl", GL_FRAGMENT_SHADER_ARB)); + gGlowCombineProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gGlowCombineProgram.createShader(NULL, NULL); + if (success) + { + gGlowCombineProgram.bind(); + gGlowCombineProgram.uniform1i("glowMap", 0); + gGlowCombineProgram.uniform1i("screenMap", 1); + gGlowCombineProgram.unbind(); + } + } + + if (success) + { + gTwoTextureAddProgram.mName = "Two Texture Add Shader"; + gTwoTextureAddProgram.mShaderFiles.clear(); + gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddV.glsl", GL_VERTEX_SHADER_ARB)); + gTwoTextureAddProgram.mShaderFiles.push_back(make_pair("interface/twotextureaddF.glsl", GL_FRAGMENT_SHADER_ARB)); + gTwoTextureAddProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gTwoTextureAddProgram.createShader(NULL, NULL); + if (success) + { + gTwoTextureAddProgram.bind(); + gTwoTextureAddProgram.uniform1i("tex0", 0); + gTwoTextureAddProgram.uniform1i("tex1", 1); + } + } + + if (success) + { + gSolidColorProgram.mName = "Solid Color Shader"; + gSolidColorProgram.mShaderFiles.clear(); + gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorV.glsl", GL_VERTEX_SHADER_ARB)); + gSolidColorProgram.mShaderFiles.push_back(make_pair("interface/solidcolorF.glsl", GL_FRAGMENT_SHADER_ARB)); + gSolidColorProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gSolidColorProgram.createShader(NULL, NULL); + if (success) + { + gSolidColorProgram.bind(); + gSolidColorProgram.uniform1i("tex0", 0); + gSolidColorProgram.unbind(); + } + } + + if (success) + { + gOcclusionProgram.mName = "Occlusion Shader"; + gOcclusionProgram.mShaderFiles.clear(); + gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionV.glsl", GL_VERTEX_SHADER_ARB)); + gOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOcclusionProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gOcclusionProgram.createShader(NULL, NULL); + } + if( !success ) { mVertexShaderLevel[SHADER_INTERFACE] = 0; @@ -1449,8 +2198,8 @@ std::string LLViewerShaderMgr::getShaderDirPrefix(void) void LLViewerShaderMgr::updateShaderUniforms(LLGLSLShader * shader) { - LLWLParamManager::instance()->updateShaderUniforms(shader); - LLWaterParamManager::instance()->updateShaderUniforms(shader); + LLWLParamManager::getInstance()->updateShaderUniforms(shader); + LLWaterParamManager::getInstance()->updateShaderUniforms(shader); } /*static*/ void LLShaderMgr::unloadShaderClass(int shader_class) diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index f952b1a6f..9bdde5b2c 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -287,9 +287,9 @@ private: std::vector<std::string> mAvatarUniforms; // the list of shaders we need to propagate parameters to. - // Currently this is replaced with a global list of all shaders - // which isn't quite as efficient. However, if other changes prove - // stable then I will mimic mShaderList on a per-ParamManager basis. + // This is no longer needed, as param managers iterate down the global list + // after shaders have been loaded and automagically add relevant shaders to + // their own local lists. //std::vector<LLGLSLShader *> mShaderList; }; //LLViewerShaderMgr @@ -305,19 +305,55 @@ inline bool operator != (LLViewerShaderMgr::shader_iter const & a, LLViewerShade extern LLVector4 gShinyOrigin; +//utility shaders +extern LLGLSLShader gOcclusionProgram; +extern LLGLSLShader gCustomAlphaProgram; +extern LLGLSLShader gGlowCombineProgram; + +//output tex0[tc0] + tex1[tc1] +extern LLGLSLShader gTwoTextureAddProgram; + //object shaders extern LLGLSLShader gObjectSimpleProgram; +extern LLGLSLShader gObjectSimpleAlphaMaskProgram; extern LLGLSLShader gObjectSimpleWaterProgram; +extern LLGLSLShader gObjectSimpleWaterAlphaMaskProgram; +extern LLGLSLShader gObjectSimpleNonIndexedProgram; +extern LLGLSLShader gObjectSimpleNonIndexedWaterProgram; +extern LLGLSLShader gObjectAlphaMaskNonIndexedProgram; +extern LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram; extern LLGLSLShader gObjectFullbrightProgram; extern LLGLSLShader gObjectFullbrightWaterProgram; +extern LLGLSLShader gObjectFullbrightAlphaMaskProgram; +extern LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram; +extern LLGLSLShader gObjectFullbrightNonIndexedProgram; +extern LLGLSLShader gObjectFullbrightNonIndexedWaterProgram; +extern LLGLSLShader gObjectBumpProgram; extern LLGLSLShader gObjectSimpleLODProgram; extern LLGLSLShader gObjectFullbrightLODProgram; extern LLGLSLShader gObjectFullbrightShinyProgram; extern LLGLSLShader gObjectFullbrightShinyWaterProgram; +extern LLGLSLShader gObjectFullbrightShinyNonIndexedProgram; +extern LLGLSLShader gObjectFullbrightShinyNonIndexedWaterProgram; + extern LLGLSLShader gObjectShinyProgram; extern LLGLSLShader gObjectShinyWaterProgram; +extern LLGLSLShader gObjectShinyNonIndexedProgram; +extern LLGLSLShader gObjectShinyNonIndexedWaterProgram; + +#if MESH_ENABLED +extern LLGLSLShader gSkinnedObjectSimpleProgram; +extern LLGLSLShader gSkinnedObjectFullbrightProgram; +extern LLGLSLShader gSkinnedObjectFullbrightShinyProgram; +extern LLGLSLShader gSkinnedObjectShinySimpleProgram; + +extern LLGLSLShader gSkinnedObjectSimpleWaterProgram; +extern LLGLSLShader gSkinnedObjectFullbrightWaterProgram; +extern LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram; +extern LLGLSLShader gSkinnedObjectShinySimpleWaterProgram; +#endif //MESH_ENABLED //environment shaders extern LLGLSLShader gTerrainProgram; @@ -335,6 +371,7 @@ extern LLGLSLShader gAvatarProgram; extern LLGLSLShader gAvatarWaterProgram; extern LLGLSLShader gAvatarEyeballProgram; extern LLGLSLShader gAvatarPickProgram; +extern LLGLSLShader gImpostorProgram; // WindLight shader handles extern LLGLSLShader gWLSkyProgram; @@ -350,6 +387,14 @@ extern LLGLSLShader gDeferredImpostorProgram; extern LLGLSLShader gDeferredEdgeProgram; extern LLGLSLShader gDeferredWaterProgram; extern LLGLSLShader gDeferredDiffuseProgram; +extern LLGLSLShader gDeferredDiffuseAlphaMaskProgram; +extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram; +extern LLGLSLShader gDeferredNonIndexedDiffuseProgram; +extern LLGLSLShader gDeferredSkinnedDiffuseProgram; +#if MESH_ENABLED +extern LLGLSLShader gDeferredSkinnedBumpProgram; +extern LLGLSLShader gDeferredSkinnedAlphaProgram; +#endif //MESH_ENABLED extern LLGLSLShader gDeferredBumpProgram; extern LLGLSLShader gDeferredTerrainProgram; extern LLGLSLShader gDeferredTreeProgram; @@ -364,14 +409,20 @@ extern LLGLSLShader gDeferredBlurLightProgram; extern LLGLSLShader gDeferredAvatarProgram; extern LLGLSLShader gDeferredSoftenProgram; extern LLGLSLShader gDeferredShadowProgram; +extern LLGLSLShader gDeferredShadowAlphaMaskProgram; extern LLGLSLShader gDeferredPostGIProgram; extern LLGLSLShader gDeferredPostProgram; extern LLGLSLShader gDeferredPostNoDoFProgram; extern LLGLSLShader gDeferredAvatarShadowProgram; +#if MESH_ENABLED +extern LLGLSLShader gDeferredAttachmentShadowProgram; +#endif //MESH_ENABLED extern LLGLSLShader gDeferredAlphaProgram; extern LLGLSLShader gDeferredFullbrightProgram; extern LLGLSLShader gDeferredAvatarAlphaProgram; - +extern LLGLSLShader gDeferredWLSkyProgram; +extern LLGLSLShader gDeferredWLCloudProgram; +extern LLGLSLShader gDeferredStarProgram; extern LLGLSLShader gLuminanceGatherProgram; //current avatar shader parameter pointer diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index c1b87cc34..ca4606f7c 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -60,6 +60,7 @@ #include "llworld.h" #include "llfeaturemanager.h" #include "llviewernetwork.h" +#include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived #if LL_LCD_COMPILE #include "lllcd.h" #endif @@ -206,9 +207,72 @@ const StatAttributes STAT_INFO[LLViewerStats::ST_COUNT] = }; -LLViewerStats::LLViewerStats() - : mPacketsLostPercentStat(64), - mLastTimeDiff(0.0) +LLViewerStats::LLViewerStats() : + mKBitStat("kbitstat"), + mLayersKBitStat("layerskbitstat"), + mObjectKBitStat("objectkbitstat"), + mAssetKBitStat("assetkbitstat"), + mTextureKBitStat("texturekbitstat"), + mVFSPendingOperations("vfspendingoperations"), + mObjectsDrawnStat("objectsdrawnstat"), + mObjectsCulledStat("objectsculledstat"), + mObjectsTestedStat("objectstestedstat"), + mObjectsComparedStat("objectscomparedstat"), + mObjectsOccludedStat("objectsoccludedstat"), + mFPSStat("fpsstat"), + mPacketsInStat("packetsinstat"), + mPacketsLostStat("packetsloststat"), + mPacketsOutStat("packetsoutstat"), + mPacketsLostPercentStat("packetslostpercentstat", 64), + mTexturePacketsStat("texturepacketsstat"), + mActualInKBitStat("actualinkbitstat"), + mActualOutKBitStat("actualoutkbitstat"), + mTrianglesDrawnStat("trianglesdrawnstat"), + mSimTimeDilation("simtimedilation"), + mSimFPS("simfps"), + mSimPhysicsFPS("simphysicsfps"), + mSimAgentUPS("simagentups"), + mSimScriptEPS("simscripteps"), + mSimFrameMsec("simframemsec"), + mSimNetMsec("simnetmsec"), + mSimSimOtherMsec("simsimothermsec"), + mSimSimPhysicsMsec("simsimphysicsmsec"), + mSimSimPhysicsStepMsec("simsimphysicsstepmsec"), + mSimSimPhysicsShapeUpdateMsec("simsimphysicsshapeupdatemsec"), + mSimSimPhysicsOtherMsec("simsimphysicsothermsec"), + mSimAgentMsec("simagentmsec"), + mSimImagesMsec("simimagesmsec"), + mSimScriptMsec("simscriptmsec"), + mSimSpareMsec("simsparemsec"), + mSimSleepMsec("simsleepmsec"), + mSimPumpIOMsec("simpumpiomsec"), + mSimMainAgents("simmainagents"), + mSimChildAgents("simchildagents"), + mSimObjects("simobjects"), + mSimActiveObjects("simactiveobjects"), + mSimActiveScripts("simactivescripts"), + mSimInPPS("siminpps"), + mSimOutPPS("simoutpps"), + mSimPendingDownloads("simpendingdownloads"), + mSimPendingUploads("simpendinguploads"), + mSimPendingLocalUploads("simpendinglocaluploads"), + mSimTotalUnackedBytes("simtotalunackedbytes"), + mPhysicsPinnedTasks("physicspinnedtasks"), + mPhysicsLODTasks("physicslodtasks"), + mPhysicsMemoryAllocated("physicsmemoryallocated"), + mSimPingStat("simpingstat"), + mNumImagesStat("numimagesstat", 32, TRUE), + mNumRawImagesStat("numrawimagesstat", 32, TRUE), + mGLTexMemStat("gltexmemstat", 32, TRUE), + mGLBoundMemStat("glboundmemstat", 32, TRUE), + mRawMemStat("rawmemstat", 32, TRUE), + mFormattedMemStat("formattedmemstat", 32, TRUE), + mNumObjectsStat("numobjectsstat"), + mNumActiveObjectsStat("numactiveobjectsstat"), + mNumNewObjectsStat("numnewobjectsstat"), + mNumSizeCulledStat("numsizeculledstat"), + mNumVisCulledStat("numvisculledstat"), + mLastTimeDiff(0.0) { for (S32 i = 0; i < ST_COUNT; i++) { @@ -219,6 +283,8 @@ LLViewerStats::LLViewerStats() { mStats[ST_HAS_BAD_TIMER] = 1.0; } + + mAgentPositionSnaps.reset(); } LLViewerStats::~LLViewerStats() @@ -238,6 +304,8 @@ void LLViewerStats::resetStats() LLViewerStats::getInstance()->mPacketsOutStat.reset(); LLViewerStats::getInstance()->mFPSStat.reset(); LLViewerStats::getInstance()->mTexturePacketsStat.reset(); + + LLViewerStats::getInstance()->mAgentPositionSnaps.reset(); } @@ -332,6 +400,10 @@ void LLViewerStats::addToMessage(LLSD &body) const << llendl; } } + + body["AgentPositionSnaps"] = mAgentPositionSnaps.getData(); + llinfos << "STAT: AgentPositionSnaps: Mean = " << mAgentPositionSnaps.getMean() << "; StdDev = " << mAgentPositionSnaps.getStdDev() + << "; Count = " << mAgentPositionSnaps.getCount() << llendl; } // static @@ -362,12 +434,16 @@ void reset_statistics() void output_statistics(void*) { + S32 global_raw_memory; + { + global_raw_memory = *AIAccess<S32>(LLImageRaw::sGlobalRawMemory); + } llinfos << "Number of orphans: " << gObjectList.getOrphanCount() << llendl; llinfos << "Number of dead objects: " << gObjectList.mNumDeadObjects << llendl; llinfos << "Num images: " << gTextureList.getNumImages() << llendl; llinfos << "Texture usage: " << LLImageGL::sGlobalTextureMemoryInBytes << llendl; llinfos << "Texture working set: " << LLImageGL::sBoundTextureMemoryInBytes << llendl; - llinfos << "Raw usage: " << LLImageRaw::sGlobalRawMemory << llendl; + llinfos << "Raw usage: " << global_raw_memory << llendl; llinfos << "Formatted usage: " << LLImageFormatted::sGlobalFormattedMemory << llendl; llinfos << "Zombie Viewer Objects: " << LLViewerObject::getNumZombieObjects() << llendl; llinfos << "Number of lights: " << gPipeline.getLightCount() << llendl; @@ -532,7 +608,7 @@ void update_statistics(U32 frame_count) } } LLViewerStats::getInstance()->setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); - //LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gSavedSettings.getS32("RenderLightingDetail")); + LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail()); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); #if 0 // 1.9.2 @@ -599,7 +675,7 @@ void update_statistics(U32 frame_count) // Only update texture stats ones per second so that they are less noisy { - static const F32 texture_stats_freq = 1.f; + static const F32 texture_stats_freq = 10.f; static LLFrameTimer texture_stats_timer; if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) { @@ -707,16 +783,18 @@ void send_stats() agent["ping"] = gAvgSimPing; agent["meters_traveled"] = gAgent.getDistanceTraveled(); agent["regions_visited"] = gAgent.getRegionsVisited(); - agent["mem_use"] = getCurrentRSS() / 1024.0; + agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0; LLSD &system = body["system"]; system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB(); system["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple(); system["cpu"] = gSysCPU.getCPUString(); + unsigned char MACAddress[MAC_ADDRESS_BYTES]; + LLUUID::getNodeID(MACAddress); std::string macAddressString = llformat("%02x-%02x-%02x-%02x-%02x-%02x", - gMACAddress[0],gMACAddress[1],gMACAddress[2], - gMACAddress[3],gMACAddress[4],gMACAddress[5]); + MACAddress[0],MACAddress[1],MACAddress[2], + MACAddress[3],MACAddress[4],MACAddress[5]); system["mac_address"] = macAddressString; system["serial_number"] = LLAppViewer::instance()->getSerialNumber(); std::string gpu_desc = llformat( @@ -735,6 +813,7 @@ void send_stats() download["world_kbytes"] = gTotalWorldBytes / 1024.0; download["object_kbytes"] = gTotalObjectBytes / 1024.0; download["texture_kbytes"] = gTotalTextureBytes / 1024.0; + download["mesh_kbytes"] = LLMeshRepository::sBytesReceived/1024.0; LLSD &in = body["stats"]["net"]["in"]; @@ -770,13 +849,15 @@ void send_stats() // Screen size so the UI team can figure out how big the widgets // appear and use a "typical" size for end user tests. - S32 window_width = gViewerWindow->getWindowDisplayWidth(); - S32 window_height = gViewerWindow->getWindowDisplayHeight(); + S32 window_width = gViewerWindow->getWindowWidthRaw(); + S32 window_height = gViewerWindow->getWindowHeightRaw(); S32 window_size = (window_width * window_height) / 1024; misc["string_1"] = llformat("%d", window_size); - // misc["string_2"] = -// misc["int_1"] = LLFloaterDirectory::sOldSearchCount; // Steve: 1.18.6 -// misc["int_2"] = LLFloaterDirectory::sNewSearchCount; // Steve: 1.18.6 + if (gDebugTimers.find(0) != gDebugTimers.end() && gFrameTimeSeconds > 0) + { + misc["string_2"] = llformat("Texture Time: %.2f, Total Time: %.2f", gDebugTimers[0].getElapsedTimeF32(), gFrameTimeSeconds); + } + // misc["int_1"] = LLSD::Integer(gSavedSettings.getU32("RenderQualityPerformance")); // Steve: 1.21 // misc["int_2"] = LLSD::Integer(gFrameStalls); // Steve: 1.21 @@ -787,6 +868,11 @@ void send_stats() llinfos << "Misc Stats: int_1: " << misc["int_1"] << " int_2: " << misc["int_2"] << llendl; llinfos << "Misc Stats: string_1: " << misc["string_1"] << " string_2: " << misc["string_2"] << llendl; + + body["DisplayNamesEnabled"] = gSavedSettings.getS32("PhoenixNameSystem") > 0; + body["DisplayNamesShowUsername"] = gSavedSettings.getS32("PhoenixNameSystem") == 1; + + body["MinimalSkin"] = false; LLViewerStats::getInstance()->addToMessage(body); LLHTTPClient::post(url, body, new ViewerStatsResponder()); diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 1cea273ad..7f0f2d8cf 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -58,6 +58,7 @@ public: LLStat mTexturePacketsStat; LLStat mActualInKBitStat; // From the packet ring (when faking a bad connection) LLStat mActualOutKBitStat; // From the packet ring (when faking a bad connection) + LLStat mTrianglesDrawnStat; // Simulator stats LLStat mSimTimeDilation; @@ -99,15 +100,22 @@ public: LLStat mPhysicsPinnedTasks; LLStat mPhysicsLODTasks; LLStat mPhysicsMemoryAllocated; - /* - LLStat mSimCPUUsageStat; - LLStat mSimMemTotalStat; - LLStat mSimMemRSSStat; - */ - LLStat mSimPingStat; + LLStat mNumImagesStat; + LLStat mNumRawImagesStat; + LLStat mGLTexMemStat; + LLStat mGLBoundMemStat; + LLStat mRawMemStat; + LLStat mFormattedMemStat; + + LLStat mNumObjectsStat; + LLStat mNumActiveObjectsStat; + LLStat mNumNewObjectsStat; + LLStat mNumSizeCulledStat; + LLStat mNumVisCulledStat; + void resetStats(); public: // If you change this, please also add a corresponding text label @@ -190,6 +198,90 @@ public: void addToMessage(LLSD &body) const; + struct StatsAccumulator + { + S32 mCount; + F32 mSum; + F32 mSumOfSquares; + F32 mMinValue; + F32 mMaxValue; + U32 mCountOfNextUpdatesToIgnore; + + inline StatsAccumulator() + { + reset(); + } + + inline void push( F32 val ) + { + if ( mCountOfNextUpdatesToIgnore > 0 ) + { + mCountOfNextUpdatesToIgnore--; + return; + } + + mCount++; + mSum += val; + mSumOfSquares += val * val; + if (mCount == 1 || val > mMaxValue) + { + mMaxValue = val; + } + if (mCount == 1 || val < mMinValue) + { + mMinValue = val; + } + } + + inline F32 getMean() const + { + return (mCount == 0) ? 0.f : ((F32)mSum)/mCount; + } + + inline F32 getMinValue() const + { + return mMinValue; + } + + inline F32 getMaxValue() const + { + return mMaxValue; + } + + inline F32 getStdDev() const + { + const F32 mean = getMean(); + return (mCount == 0) ? 0.f : sqrt( mSumOfSquares/mCount - (mean * mean) ); + } + + inline U32 getCount() const + { + return mCount; + } + + inline void reset() + { + mCount = 0; + mSum = mSumOfSquares = 0.f; + mMinValue = 0.0f; + mMaxValue = 0.0f; + mCountOfNextUpdatesToIgnore = 0; + } + + inline LLSD getData() const + { + LLSD data; + data["mean"] = getMean(); + data["std_dev"] = getStdDev(); + data["count"] = (S32)mCount; + data["min"] = getMinValue(); + data["max"] = getMaxValue(); + return data; + } + }; + + StatsAccumulator mAgentPositionSnaps; + private: F64 mStats[ST_COUNT]; diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index a4590160e..2ec7cf396 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -36,6 +36,7 @@ #include "llaudioengine.h" #include "llagent.h" #include "llinventory.h" +#include "llinventorydefines.h" #include "llinventorymodel.h" #include "llinventoryview.h" #include "llinventorybridge.h" // for landmark prefix string diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index d1c3a40f2..0a8ab1c0d 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -66,7 +66,9 @@ //#include "lltextureatlas.h" //#include "lltextureatlasmanager.h" #include "lltextureentry.h" -//#include "llmediaentry.h" +#if NEW_MEDIA_TEXTURE +#include "llmediaentry.h" +#endif //NEW_MEDIA_TEXTURE #include "llvovolume.h" #include "llviewermedia.h" /////////////////////////////////////////////////////////////////////////////// @@ -79,9 +81,11 @@ LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sDefaultImagep = NULL; LLPointer<LLViewerFetchedTexture> LLViewerFetchedTexture::sSmokeImagep = NULL; #if NEW_MEDIA_TEXTURE LLViewerMediaTexture::media_map_t LLViewerMediaTexture::sMediaMap ; +#endif //NEW_MEDIA_TEXTURE +#if 0 +LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ; #endif -//LLTexturePipelineTester* LLViewerTextureManager::sTesterp = NULL ; -//const std::string sTesterName("TextureTester"); +const std::string sTesterName("TextureTester"); S32 LLViewerTexture::sImageCount = 0; S32 LLViewerTexture::sRawCount = 0; @@ -104,7 +108,6 @@ S32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA ; BOOL LLViewerTexture::sFreezeImageScalingDown = FALSE ; F32 LLViewerTexture::sCurrentTime = 0.0f ; //BOOL LLViewerTexture::sUseTextureAtlas = FALSE ; -BOOL LLViewerTexture::sDontLoadVolumeTextures = FALSE ; const F32 desired_discard_bias_min = -2.0f; // -max number of levels to improve image quality by const F32 desired_discard_bias_max = (F32)MAX_DISCARD_LEVEL; // max number of levels to reduce image quality by @@ -171,7 +174,7 @@ LLViewerMediaTexture* LLViewerTextureManager::createMediaTexture(const LLUUID &m { return new LLViewerMediaTexture(media_id, usemipmaps, gl_image) ; } -#endif +#endif //NEW_MEDIA_TEXTURE LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id) { @@ -185,7 +188,7 @@ LLViewerTexture* LLViewerTextureManager::findTexture(const LLUUID& id) { tex = LLViewerTextureManager::findMediaTexture(id) ; } -#endif +#endif //NEW_MEDIA_TEXTURE return tex ; } @@ -207,7 +210,7 @@ LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id, return tex ; } -#endif +#endif //NEW_MEDIA_TEXTURE LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error) { @@ -358,7 +361,8 @@ void LLViewerTextureManager::init() LLViewerTexture::initClass() ; - /*if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) +#if 0 + if (LLMetricPerformanceTesterBasic::isMetricLogRequested(sTesterName) && !LLMetricPerformanceTesterBasic::getTester(sTesterName)) { sTesterp = new LLTexturePipelineTester() ; if (!sTesterp->isValid()) @@ -366,7 +370,8 @@ void LLViewerTextureManager::init() delete sTesterp; sTesterp = NULL; } - }*/ + } +#endif } void LLViewerTextureManager::cleanup() @@ -382,7 +387,7 @@ void LLViewerTextureManager::cleanup() #if NEW_MEDIA_TEXTURE LLViewerMediaTexture::cleanUpClass() ; -#endif +#endif //NEW_MEDIA_TEXTURE } //---------------------------------------------------------------------------------------------- @@ -432,14 +437,16 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity { sCurrentTime = gFrameTimeSeconds ; - /*LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); +#if 0 + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { tester->update() ; - }*/ + } +#endif #if NEW_MEDIA_TEXTURE LLViewerMediaTexture::updateClass() ; -#endif +#endif //NEW_MEDIA_TEXTURE sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes @@ -560,7 +567,9 @@ void LLViewerTexture::init(bool firstinit) mFaceList.clear() ; mVolumeList.clear(); +#if !NEW_MEDIA_TEXTURE mIsMediaTexture = false; +#endif //!NEW_MEDIA_TEXTURE } //virtual @@ -632,11 +641,13 @@ bool LLViewerTexture::bindDefaultImage(S32 stage) //check if there is cached raw image and switch to it if possible switchToCachedImage() ; - /*LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); +#if 0 + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { tester->updateGrayTextureBinding() ; - }*/ + } +#endif return res; } @@ -1096,11 +1107,13 @@ BOOL LLViewerTexture::isLargeImage() //virtual void LLViewerTexture::updateBindStatsForTester() { - /*LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); +#if 0 + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { tester->updateTextureBindingStats(this) ; - }*/ + } +#endif } //---------------------------------------------------------------------------------------------- @@ -1192,6 +1205,7 @@ void LLViewerFetchedTexture::init(bool firstinit) mSavedRawDiscardLevel = -1 ; mDesiredSavedRawDiscardLevel = -1 ; mLastReferencedSavedRawImageTime = 0.0f ; + mKeptSavedRawImageTime = 0.f ; mLastCallBackActiveTime = 0.f; } @@ -1451,9 +1465,16 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) mOrigWidth = mRawImage->getWidth(); mOrigHeight = mRawImage->getHeight(); - // leave black border, do not scale image content - mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE); + if (mBoostLevel == BOOST_PREVIEW) + { + mRawImage->biasedScaleToPowerOfTwo(1024); + } + else + { // leave black border, do not scale image content + mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE); + } + mFullWidth = mRawImage->getWidth(); mFullHeight = mRawImage->getHeight(); setTexelsPerImage(); @@ -1537,7 +1558,7 @@ void LLViewerFetchedTexture::processTextureStats() { updateVirtualSize() ; - static LLCachedControl<bool> textures_fullres("TextureLoadFullRes",false); + static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); if (textures_fullres) { @@ -1613,7 +1634,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority() S32 cur_discard = getCurrentDiscardLevelForFetching(); bool have_all_data = (cur_discard >= 0 && (cur_discard <= mDesiredDiscardLevel)); - F32 pixel_priority = fsqrtf(mMaxVirtualSize); + F32 pixel_priority = (F32) sqrt(mMaxVirtualSize); F32 priority = 0.f; @@ -1825,7 +1846,7 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching() bool LLViewerFetchedTexture::updateFetch() { - static LLCachedControl<bool> textures_decode_disabled("TextureDecodeDisabled",false); + static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); if(textures_decode_disabled) { return false ; @@ -1888,12 +1909,14 @@ bool LLViewerFetchedTexture::updateFetch() // We may have data ready regardless of whether or not we are finished (e.g. waiting on write) if (mRawImage.notNull()) { - /*LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); +#if 0 + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { mIsFetched = TRUE ; tester->updateTextureLoadingStats(this, mRawImage, LLAppViewer::getTextureFetch()->isFromLocalCache(mID)) ; - }*/ + } +#endif mRawDiscardLevel = fetch_discard; if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && (current_discard < 0 || mRawDiscardLevel < current_discard)) @@ -2027,11 +2050,11 @@ bool LLViewerFetchedTexture::updateFetch() c = mComponents; } - /*const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); + const U32 override_tex_discard_level = gSavedSettings.getU32("TextureDiscardLevel"); if (override_tex_discard_level != 0) { desired_discard = override_tex_discard_level; - }*/ + } // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; @@ -2739,8 +2762,16 @@ void LLViewerFetchedTexture::saveRawImage() mLastReferencedSavedRawImageTime = sCurrentTime ; } -void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard) +void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time) { + mKeptSavedRawImageTime = kept_time ; + mLastReferencedSavedRawImageTime = sCurrentTime ; + + if(mSavedRawDiscardLevel > -1 && mSavedRawDiscardLevel <= desired_discard) + { + return ; //raw imge is ready. + } + if(!mForceToSaveRawImage || mDesiredSavedRawDiscardLevel < 0 || mDesiredSavedRawDiscardLevel > desired_discard) { mForceToSaveRawImage = TRUE ; @@ -2761,6 +2792,14 @@ void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard) } void LLViewerFetchedTexture::destroySavedRawImage() { + if(mLastReferencedSavedRawImageTime < mKeptSavedRawImageTime) + { + return ; //keep the saved raw image. + } + + mForceToSaveRawImage = FALSE ; + mSaveRawImage = FALSE ; + clearCallbackEntryList() ; mSavedRawImage = NULL ; @@ -2769,6 +2808,7 @@ void LLViewerFetchedTexture::destroySavedRawImage() mSavedRawDiscardLevel = -1 ; mDesiredSavedRawDiscardLevel = -1 ; mLastReferencedSavedRawImageTime = 0.0f ; + mKeptSavedRawImageTime = 0.f ; } LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() @@ -3014,8 +3054,8 @@ BOOL LLViewerLODTexture::isUpdateFrozen() void LLViewerLODTexture::processTextureStats() { updateVirtualSize() ; - - static LLCachedControl<bool> textures_fullres("TextureLoadFullRes", false); + + static LLCachedControl<bool> textures_fullres(gSavedSettings,"TextureLoadFullRes"); if (textures_fullres) { @@ -3134,11 +3174,13 @@ void LLViewerLODTexture::scaleDown() { switchToCachedImage() ; - /*LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); +#if 0 + LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName); if (tester) { tester->setStablizingTime() ; - }*/ + } +#endif } } //---------------------------------------------------------------------------------------------- @@ -3154,7 +3196,7 @@ void LLViewerMediaTexture::updateClass() { static const F32 MAX_INACTIVE_TIME = 30.f ; -#if NEW_MEDIA_TEXTURE +#if 0 //force to play media. gSavedSettings.setBOOL("AudioStreamingMedia", true) ; #endif @@ -3247,7 +3289,7 @@ LLViewerMediaTexture::~LLViewerMediaTexture() tex->setParcelMedia(NULL) ; } } -#endif +#endif //NEW_MEDIA_TEXTURE void LLViewerMediaTexture::reinit(BOOL usemipmaps /* = TRUE */) { llassert(mGLTexturep.notNull()) ; @@ -3641,7 +3683,7 @@ F32 LLViewerMediaTexture::getMaxVirtualSize() return mMaxVirtualSize ; } -#endif +#endif //NEW_MEDIA_TEXTURE //---------------------------------------------------------------------------------------------- //end of LLViewerMediaTexture //---------------------------------------------------------------------------------------------- @@ -3743,22 +3785,23 @@ void LLTexturePipelineTester::reset() //virtual void LLTexturePipelineTester::outputTestRecord(LLSD *sd) { - (*sd)[mCurLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ; - (*sd)[mCurLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ; - (*sd)[mCurLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ; - (*sd)[mCurLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ; + std::string currentLabel = getCurrentLabelName(); + (*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ; + (*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ; + (*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ; + (*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ; - (*sd)[mCurLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ; - (*sd)[mCurLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ; - (*sd)[mCurLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ; + (*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ; + (*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ; + (*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ; - (*sd)[mCurLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ; - (*sd)[mCurLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ; + (*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ; + (*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ; - (*sd)[mCurLabel]["Time"] = LLImageGL::sLastFrameTime ; - (*sd)[mCurLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ; - (*sd)[mCurLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ; - (*sd)[mCurLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ; + (*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime ; + (*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ; + (*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ; + (*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ; } void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep) @@ -3847,7 +3890,7 @@ void LLTexturePipelineTester::compareTestSessions(std::ofstream* os) } //compare and output the comparison - *os << llformat("%s\n", mName.c_str()) ; + *os << llformat("%s\n", getTesterName().c_str()) ; *os << llformat("AggregateResults\n") ; compareTestResults(os, "TotalFetchingTime", base_sessionp->mTotalFetchingTime, current_sessionp->mTotalFetchingTime) ; @@ -3902,7 +3945,7 @@ void LLTexturePipelineTester::compareTestSessions(std::ofstream* os) } //virtual -LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log) +LLMetricPerformanceTesterWithSession::LLTestSession* LLTexturePipelineTester::loadTestSession(LLSD* log) { LLTexturePipelineTester::LLTextureTestSession* sessionp = new LLTexturePipelineTester::LLTextureTestSession() ; if(!sessionp) @@ -3929,12 +3972,11 @@ LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSessi sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ; //load a session - BOOL in_log = (*log).has(mCurLabel) ; - while(in_log) + std::string currentLabel = getCurrentLabelName(); + BOOL in_log = (*log).has(currentLabel) ; + while (in_log) { - LLSD::String label = mCurLabel ; - incLabel() ; - in_log = (*log).has(mCurLabel) ; + LLSD::String label = currentLabel ; if(sessionp->mInstantPerformanceListCounter >= (S32)sessionp->mInstantPerformanceList.size()) { @@ -4000,7 +4042,11 @@ LLMetricPerformanceTester::LLTestSession* LLTexturePipelineTester::loadTestSessi sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAverageBytesUsedForLargeImagePerSecond = 0 ; sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mAveragePercentageBytesUsedPerSecond = 0.f ; sessionp->mInstantPerformanceList[sessionp->mInstantPerformanceListCounter].mTime = 0.f ; - } + } + // Next label + incrementCurrentCount() ; + currentLabel = getCurrentLabelName(); + in_log = (*log).has(currentLabel) ; } sessionp->mTotalFetchingTime += total_fetching_time ; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index ad59d37c8..5fd4275aa 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -40,7 +40,9 @@ #include "llhost.h" #include "llgltypes.h" #include "llrender.h" -//#include "llmetricperformancetester.h" +#if 0 +#include "llmetricperformancetester.h" +#endif #include <map> #include <list> @@ -336,7 +338,6 @@ public: static BOOL sFreezeImageScalingDown ;//do not scale down image res if set. static F32 sCurrentTime ; //static BOOL sUseTextureAtlas ; - static BOOL sDontLoadVolumeTextures ; static LLPointer<LLViewerTexture> sNullImagep; // Null texture for non-textured objects. }; @@ -474,7 +475,7 @@ public: S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;} BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;} BOOL isRawImageValid()const { return mIsRawImageValid ; } - void forceToSaveRawImage(S32 desired_discard = 0) ; + void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ; /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; void destroySavedRawImage() ; LLImageRaw* getSavedRawImage() ; @@ -560,6 +561,7 @@ protected: S32 mSavedRawDiscardLevel; S32 mDesiredSavedRawDiscardLevel; F32 mLastReferencedSavedRawImageTime ; + F32 mKeptSavedRawImageTime ; //a small version of the copy of the raw image (<= 64 * 64) LLPointer<LLImageRaw> mCachedRawImage; @@ -620,14 +622,16 @@ class LLViewerMediaTexture : public LLViewerTexture { #if NEW_MEDIA_TEXTURE protected: - *virtual*/ ~LLViewerMediaTexture() ; + /*virtual*/ ~LLViewerMediaTexture() ; public: LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; - /*virtual*/* S8 getType() const; -#endif + /*virtual*/ S8 getType() const; +#endif //NEW_MEDIA_TEXTURE +#if !NEW_MEDIA_TEXTURE public: +#endif //!NEW_MEDIA_TEXTURE void reinit(BOOL usemipmaps = TRUE); BOOL getUseMipMaps() {return mUseMipMaps ; } @@ -642,7 +646,7 @@ public: void invalidateMediaImpl() ; void addMediaToFace(LLFace* facep) ; - void removeMediaFromFace(LLFace* facep) ;*/ + void removeMediaFromFace(LLFace* facep) ; /*virtual*/ void addFace(LLFace* facep) ; /*virtual*/ void removeFace(LLFace* facep) ; @@ -678,7 +682,7 @@ public: private: typedef std::map< LLUUID, LLPointer<LLViewerMediaTexture> > media_map_t ; static media_map_t sMediaMap ; -#endif +#endif //NEW_MEDIA_TEXTURE }; //just an interface class, do not create instance from this class. @@ -690,7 +694,9 @@ private: public: //texture pipeline tester - //static LLTexturePipelineTester* sTesterp ; +#if 0 + static LLTexturePipelineTester* sTesterp ; +#endif //returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture. static LLViewerFetchedTexture* staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ; @@ -708,7 +714,7 @@ public: //"get-texture" will create a new texture if the texture does not exist. // static LLViewerMediaTexture* getMediaTexture(const LLUUID& id, BOOL usemipmaps = TRUE, LLImageGL* gl_image = NULL) ; -#endif +#endif //NEW_MEDIA_TEXTURE static LLPointer<LLViewerTexture> getLocalTexture(BOOL usemipmaps = TRUE, BOOL generate_gl_tex = TRUE); static LLPointer<LLViewerTexture> getLocalTexture(const LLUUID& id, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; @@ -839,8 +845,8 @@ private: S32 mInstantPerformanceListCounter ; }; - /*virtual*/ LLMetricPerformanceTester::LLTestSession* loadTestSession(LLSD* log) ; + /*virtual*/ LLMetricPerformanceTesterWithSession::LLTestSession* loadTestSession(LLSD* log) ; /*virtual*/ void compareTestSessions(std::ofstream* os) ; }; -#endif //0 +#endif #endif diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index c2cb0c5a4..5de2a805e 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -72,12 +72,6 @@ void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL; U32 LLViewerTextureList::sTextureBits = 0; U32 LLViewerTextureList::sTexturePackets = 0; S32 LLViewerTextureList::sNumImages = 0; -LLStat LLViewerTextureList::sNumImagesStat(32, TRUE); -LLStat LLViewerTextureList::sNumRawImagesStat(32, TRUE); -LLStat LLViewerTextureList::sGLTexMemStat(32, TRUE); -LLStat LLViewerTextureList::sGLBoundMemStat(32, TRUE); -LLStat LLViewerTextureList::sRawMemStat(32, TRUE); -LLStat LLViewerTextureList::sFormattedMemStat(32, TRUE); LLViewerTextureList gTextureList; @@ -125,7 +119,7 @@ void LLViewerTextureList::doPreloadImages() // Set the "white" image LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); - + LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); LLUIImageList* image_list = LLUIImageList::getInstance(); image_list->initFromFile(); @@ -608,12 +602,16 @@ void LLViewerTextureList::updateImages(F32 max_time) { LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec()); - sNumImagesStat.addValue(sNumImages); - sNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); - sGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes)); - sGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes)); - sRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageRaw::sGlobalRawMemory)); - sFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); + S32 global_raw_memory; + { + global_raw_memory = *AIAccess<S32>(LLImageRaw::sGlobalRawMemory); + } + LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages); + LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); + LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes)); + LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes)); + LLViewerStats::getInstance()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(global_raw_memory)); + LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); updateImagesDecodePriorities(); @@ -677,10 +675,7 @@ void LLViewerTextureList::updateImagesDecodePriorities() const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding const F32 MAX_INACTIVE_TIME = 50.f; // actually delete S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference - if (imagep->hasCallbacks()) - { - min_refs++; // Add an extra reference if we're on the loaded callback list - } + S32 num_refs = imagep->getNumRefs(); if (num_refs == min_refs) { @@ -975,99 +970,54 @@ void LLViewerTextureList::decodeAllImages(F32 max_time) BOOL LLViewerTextureList::createUploadFile(const std::string& filename, const std::string& out_filename, const U8 codec) -{ - // First, load the image. +{ + // Load the image + LLPointer<LLImageFormatted> image = LLImageFormatted::createFromType(codec); + if (image.isNull()) + { + image->setLastError("Couldn't open the image to be uploaded."); + return FALSE; + } + if (!image->load(filename)) + { + image->setLastError("Couldn't load the image to be uploaded."); + return FALSE; + } + // Decompress or expand it in a raw image structure LLPointer<LLImageRaw> raw_image = new LLImageRaw; - - switch (codec) + if (!image->decode(raw_image, 0.0f)) { - case IMG_CODEC_BMP: - { - LLPointer<LLImageBMP> bmp_image = new LLImageBMP; - - if (!bmp_image->load(filename)) - { - return FALSE; - } - - if (!bmp_image->decode(raw_image, 0.0f)) - { - return FALSE; - } - } - break; - case IMG_CODEC_TGA: - { - LLPointer<LLImageTGA> tga_image = new LLImageTGA; - - if (!tga_image->load(filename)) - { - return FALSE; - } - - if (!tga_image->decode(raw_image)) - { - return FALSE; - } - - if( (tga_image->getComponents() != 3) && - (tga_image->getComponents() != 4) ) - { - tga_image->setLastError( "Image files with less than 3 or more than 4 components are not supported." ); - return FALSE; - } - } - break; - case IMG_CODEC_JPEG: - { - LLPointer<LLImageJPEG> jpeg_image = new LLImageJPEG; - - if (!jpeg_image->load(filename)) - { - return FALSE; - } - - if (!jpeg_image->decode(raw_image, 0.0f)) - { - return FALSE; - } - } - break; - case IMG_CODEC_PNG: - { - LLPointer<LLImagePNG> png_image = new LLImagePNG; - - if (!png_image->load(filename)) - { - return FALSE; - } - - if (!png_image->decode(raw_image, 0.0f)) - { - return FALSE; - } - } - break; - default: - return FALSE; - } - - LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image); - - if( !compressedImage->save(out_filename) ) - { - llinfos << "Couldn't create output file " << out_filename << llendl; + image->setLastError("Couldn't decode the image to be uploaded."); return FALSE; } - - // test to see if the encode and save worked. + // Check the image constraints + if ((image->getComponents() != 3) && (image->getComponents() != 4)) + { + image->setLastError("Image files with less than 3 or more than 4 components are not supported."); + return FALSE; + } + // Convert to j2c (JPEG2000) and save the file locally + LLPointer<LLImageJ2C> compressedImage = convertToUploadFile(raw_image); + if (compressedImage.isNull()) + { + image->setLastError("Couldn't convert the image to jpeg2000."); + llinfos << "Couldn't convert to j2c, file : " << filename << llendl; + return FALSE; + } + if (!compressedImage->save(out_filename)) + { + image->setLastError("Couldn't create the jpeg2000 image for upload."); + llinfos << "Couldn't create output file : " << out_filename << llendl; + return FALSE; + } + // Test to see if the encode and save worked LLPointer<LLImageJ2C> integrity_test = new LLImageJ2C; - if( !integrity_test->loadAndValidate( out_filename ) ) + if (!integrity_test->loadAndValidate( out_filename )) { - llinfos << "Image: " << out_filename << " is corrupt." << llendl; + image->setLastError("The created jpeg2000 image is corrupt."); + llinfos << "Image file : " << out_filename << " is corrupt" << llendl; return FALSE; } - return TRUE; } @@ -1082,7 +1032,25 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage (raw_image->getWidth() * raw_image->getHeight() <= LL_IMAGE_REZ_LOSSLESS_CUTOFF * LL_IMAGE_REZ_LOSSLESS_CUTOFF)) compressedImage->setReversible(TRUE); - compressedImage->encode(raw_image, 0.0f); + +/* if (gSavedSettings.getBOOL("Jpeg2000AdvancedCompression")) + { + // This test option will create jpeg2000 images with precincts for each level, RPCL ordering + // and PLT markers. The block size is also optionally modifiable. + // Note: the images hence created are compatible with older versions of the viewer. + // Read the blocks and precincts size settings + S32 block_size = gSavedSettings.getS32("Jpeg2000BlocksSize"); + S32 precinct_size = gSavedSettings.getS32("Jpeg2000PrecinctsSize"); + llinfos << "Advanced JPEG2000 Compression: precinct = " << precinct_size << ", block = " << block_size << llendl; + compressedImage->initEncode(*raw_image, block_size, precinct_size, 0); + }*/ + + if (!compressedImage->encode(raw_image, 0.0f)) + { + llinfos << "convertToUploadFile : encode returns with error!!" << llendl; + // Clear up the pointer so we don't leak that one + compressedImage = NULL; + } return compressedImage; } @@ -1091,8 +1059,12 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage S32 LLViewerTextureList::getMinVideoRamSetting() { S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); - //min texture mem sets to 64M if total physical mem is more than 1.5GB - return (system_ram > 1500) ? 64 : MIN_VIDEO_RAM_IN_MEGA_BYTES ; + if (system_ram > 2000) + return 128; + else if (system_ram > 1000) + return 64; + else + return MIN_VIDEO_RAM_IN_MEGA_BYTES; } //static @@ -1193,7 +1165,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem) // static void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_data) { - static LLCachedControl<bool> log_texture_traffic("LogTextureNetworkTraffic",false) ; + static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); @@ -1265,7 +1237,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d // static void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_data) { - static LLCachedControl<bool> log_texture_traffic("LogTextureNetworkTraffic",FALSE) ; + static LLCachedControl<bool> log_texture_traffic(gSavedSettings,"LogTextureNetworkTraffic") ; LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index cabaa6764..fd09c60cd 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -207,13 +207,6 @@ public: static U32 sTextureBits; static U32 sTexturePackets; - static LLStat sNumImagesStat; - static LLStat sNumRawImagesStat; - static LLStat sGLTexMemStat; - static LLStat sGLBoundMemStat; - static LLStat sRawMemStat; - static LLStat sFormattedMemStat; - private: static S32 sNumImages; static void (*sUUIDCallback)(void**, const LLUUID &); diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 3aba0cffb..3ee8be54f 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -39,6 +39,9 @@ #include "llagent.h" #include "llagentcamera.h" +#if MESH_ENABLED +#include "llmeshrepository.h" +#endif //MESH_ENABLED #include "llpanellogin.h" #include "llviewerkeyboard.h" #include "llviewerwindow.h" @@ -188,6 +191,9 @@ #include "llviewernetwork.h" #include "llpostprocess.h" +#include "llnotifications.h" +#include "llnotificationsutil.h" + #include "llfloatertest.h" // HACK! #include "llfloaternotificationsconsole.h" @@ -232,6 +238,8 @@ LLVector2 gDebugRaycastTexCoord; LLVector3 gDebugRaycastNormal; LLVector3 gDebugRaycastBinormal; S32 gDebugRaycastFaceHit; +LLVector3 gDebugRaycastStart; +LLVector3 gDebugRaycastEnd; // HUD display lines in lower right BOOL gDisplayWindInfo = FALSE; @@ -302,11 +310,12 @@ public: mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f ); // Draw stuff growing up from right lower corner of screen - U32 xpos = mWindow->getWindowWidth() - 350; + U32 xpos = mWindow->getWorldViewWidthScaled() - 350; U32 ypos = 64; const U32 y_inc = 20; - if (gSavedSettings.getBOOL("DebugShowTime")) + static const LLCachedControl<bool> debug_show_time("DebugShowTime"); + if (debug_show_time) { const U32 y_inc2 = 15; for (std::map<S32,LLFrameTimer>::reverse_iterator iter = gDebugTimers.rbegin(); @@ -330,6 +339,14 @@ public: addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; } +#if LL_WINDOWS + static const LLCachedControl<bool> debug_show_memory("DebugShowMemory"); + if (debug_show_memory) + { + addText(xpos, ypos, llformat("Memory: %d (KB)", LLMemory::getWorkingSetSize() / 1024)); + ypos += y_inc; + } +#endif if (gDisplayCameraPos) { std::string camera_view_text; @@ -414,13 +431,90 @@ public: ypos += y_inc; }*/ - if (gSavedSettings.getBOOL("DebugShowRenderInfo")) + static const LLCachedControl<bool> debug_show_render_info("DebugShowRenderInfo"); + if (debug_show_render_info) { if (gPipeline.getUseVertexShaders() == 0) { addText(xpos, ypos, "Shaders Disabled"); ypos += y_inc; } + + if (gGLManager.mHasATIMemInfo) + { + S32 meminfo[4]; + glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); + + addText(xpos, ypos, llformat("%.2f MB Texture Memory Free", meminfo[0]/1024.f)); + ypos += y_inc; + + if (gGLManager.mHasVertexBufferObject) + { + glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, meminfo); + addText(xpos, ypos, llformat("%.2f MB VBO Memory Free", meminfo[0]/1024.f)); + ypos += y_inc; + } + } + else if (gGLManager.mHasNVXMemInfo) + { + S32 free_memory; + glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, &free_memory); + addText(xpos, ypos, llformat("%.2f MB Video Memory Free", free_memory/1024.f)); + ypos += y_inc; + } + +#if MESH_ENABLED + //show streaming cost/triangle count of known prims in current region OR selection + //Note: This is SUPER slow + { + F32 cost = 0.f; + S32 count = 0; + S32 object_count = 0; + S32 total_bytes = 0; + S32 visible_bytes = 0; + + const char* label = "Region"; + if (LLSelectMgr::getInstance()->getSelection()->getObjectCount() == 0) + { //region + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + for (U32 i = 0; i < (U32)gObjectList.getNumObjects(); ++i) + { + LLViewerObject* object = gObjectList.getObject(i); + if (object && + object->getRegion() == region && + object->getVolume()) + { + object_count++; + S32 bytes = 0; + S32 visible = 0; + cost += object->getStreamingCost(&bytes, &visible); + count += object->getTriangleCount(); + total_bytes += bytes; + visible_bytes += visible; + } + } + } + } + else + { + label = "Selection"; + cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectStreamingCost(&total_bytes, &visible_bytes); + count = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectTriangleCount(); + object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); + } + + addText(xpos,ypos, llformat("%s streaming cost: %.1f", label, cost)); + ypos += y_inc; + + addText(xpos, ypos, llformat(" %.3f KTris, %.1f/%.1f KB, %d objects", + count/1000.f, visible_bytes/1024.f, total_bytes/1024.f, object_count)); + ypos += y_inc; + + } +#endif //MESH_ENABLED + addText(xpos, ypos, llformat("%d MB Vertex Data", LLVertexBuffer::sAllocatedBytes/(1024*1024))); ypos += y_inc; @@ -469,6 +563,12 @@ public: ypos += y_inc; + if (!LLSpatialGroup::sPendingQueries.empty()) + { + addText(xpos,ypos, llformat("%d Queries pending", LLSpatialGroup::sPendingQueries.size())); + ypos += y_inc; + } + addText(xpos,ypos, llformat("%d Avatars visible", LLVOAvatar::sNumVisibleAvatars)); @@ -478,11 +578,30 @@ public: ypos += y_inc; +#if MESH_ENABLED + if (gMeshRepo.meshRezEnabled()) + { + addText(xpos, ypos, llformat("%.3f MB Mesh Data Received", LLMeshRepository::sBytesReceived/(1024.f*1024.f))); + + ypos += y_inc; + + addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount, + LLMeshRepository::sHTTPRetryCount)); + + ypos += y_inc; + + addText(xpos, ypos, llformat("%.3f/%.3f MB Mesh Cache Read/Write ", LLMeshRepository::sCacheBytesRead/(1024.f*1024.f), LLMeshRepository::sCacheBytesWritten/(1024.f*1024.f))); + + ypos += y_inc; + } +#endif //MESH_ENABLED + LLVertexBuffer::sBindCount = LLImageGL::sBindCount = LLVertexBuffer::sSetCount = LLImageGL::sUniqueCount = gPipeline.mNumVisibleNodes = LLPipeline::sVisibleLightCount = 0; } - if (gSavedSettings.getBOOL("DebugShowRenderMatrices")) + static const LLCachedControl<bool> debug_show_render_matrices("DebugShowRenderMatrices"); + if (debug_show_render_matrices) { addText(xpos, ypos, llformat("%.4f .%4f %.4f %.4f", gGLProjection[12], gGLProjection[13], gGLProjection[14], gGLProjection[15])); ypos += y_inc; @@ -515,7 +634,8 @@ public: addText(xpos, ypos, "View Matrix"); ypos += y_inc; } - if (gSavedSettings.getBOOL("DebugShowColor")) + static const LLCachedControl<bool> debug_show_color("DebugShowColor"); + if (debug_show_color) { U8 color[4]; LLCoordGL coord = gViewerWindow->getCurrentMouse(); @@ -1105,11 +1225,16 @@ void LLViewerWindow::handleMouseMove(LLWindow *window, LLCoordGL pos, MASK mask LLCoordGL prev_saved_mouse_point = mCurrentMousePoint; LLCoordGL mouse_point(x, y); + + if (mouse_point != mCurrentMousePoint) + { + gMouseIdleTimer.reset(); + } saveLastMouse(mouse_point); BOOL mouse_actually_moved = !gFocusMgr.getMouseCapture() && // mouse is not currenty captured ((prev_saved_mouse_point.mX != mCurrentMousePoint.mX) || (prev_saved_mouse_point.mY != mCurrentMousePoint.mY)); // mouse moved from last recorded position - gMouseIdleTimer.reset(); + mWindow->showCursorFromMouseMove(); @@ -1457,11 +1582,12 @@ LLViewerWindow::LLViewerWindow( S32 width, S32 height, BOOL fullscreen, BOOL ignore_pixel_depth) : + mWindow(NULL), mActive(TRUE), mWantFullscreen(fullscreen), mShowFullscreenProgress(FALSE), - mWindowRect(0, height, width, 0), - mVirtualWindowRect(0, height, width, 0), + mWindowRectRaw(0, height, width, 0), + mWindowRectScaled(0, height, width, 0), mLeftMouseDown(FALSE), mRightMouseDown(FALSE), mToolTip(NULL), @@ -1491,15 +1617,33 @@ LLViewerWindow::LLViewerWindow( resetSnapshotLoc(); // create window - mWindow = LLWindowManager::createWindow( + mWindow = LLWindowManager::createWindow(this, title, name, x, y, width, height, 0, fullscreen, gNoRender, gSavedSettings.getBOOL("DisableVerticalSync"), !gNoRender, ignore_pixel_depth, - gSavedSettings.getU32("RenderFSAASamples")); + gSavedSettings.getBOOL("RenderUseFBO") ? 0 : gSavedSettings.getU32("RenderFSAASamples")); //don't use window level anti-aliasing if FBOs are enabled + if (NULL == mWindow) + { + LLSplashScreen::update("Graphics Initialization Failed. Please Update Your Graphics Driver!"); + + LL_WARNS("Window") << "Failed to create window, to be shutting Down, be sure your graphics driver is updated." << llendl ; + + ms_sleep(5000) ; //wait for 5 seconds. + LLSplashScreen::update("Shutting down..."); +#if LL_LINUX || LL_SOLARIS + llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly. See README-linux.txt or README-solaris.txt for further information." + << llendl; +#else + LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings" + << LL_ENDL; +#endif + LLAppViewer::instance()->fastQuit(1); + } + if (!LLAppViewer::instance()->restoreErrorTrap()) { LL_WARNS("Window") << " Someone took over my signal/exception handler (post createWindow)!" << LL_ENDL; @@ -1514,19 +1658,6 @@ LLViewerWindow::LLViewerWindow( gSavedSettings.setS32("FullScreenWidth",scr.mX); gSavedSettings.setS32("FullScreenHeight",scr.mY); } - - if (NULL == mWindow) - { - LLSplashScreen::update("Shutting down..."); -#if LL_LINUX || LL_SOLARIS - llwarns << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly. See README-linux.txt or README-solaris.txt for further information." - << llendl; -#else - LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings" - << LL_ENDL; -#endif - LLAppViewer::instance()->forceExit(1); - } // Get the real window rect the window was created with (since there are various OS-dependent reasons why // the size of a window or fullscreen context may have been adjusted slightly...) @@ -1539,8 +1670,8 @@ LLViewerWindow::LLViewerWindow( { LLCoordWindow size; mWindow->getSize(&size); - mWindowRect.set(0, size.mY, size.mX, 0); - mVirtualWindowRect.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0); + mWindowRectRaw.set(0, size.mY, size.mX, 0); + mWindowRectScaled.set(0, llround((F32)size.mY / mDisplayScale.mV[VY]), llround((F32)size.mX / mDisplayScale.mV[VX]), 0); } LLFontManager::initClass(); @@ -1581,12 +1712,8 @@ LLViewerWindow::LLViewerWindow( mInitAlert = "DisplaySettingsNoShaders"; LLFeatureManager::getInstance()->setGraphicsLevel(0, false); gSavedSettings.setU32("RenderQualityPerformance", 0); - } - // set callbacks - mWindow->setCallbacks(this); - // Init the image list. Must happen after GL is initialized and before the images that // LLViewerWindow needs are requested. LLImageGL::initClass(LLViewerTexture::MAX_GL_IMAGE_CATEGORY) ; @@ -1595,7 +1722,7 @@ LLViewerWindow::LLViewerWindow( gBumpImageList.init(); // Create container for all sub-views - mRootView = new LLRootView("root", mVirtualWindowRect, FALSE); + mRootView = new LLRootView("root", mWindowRectScaled, FALSE); if (!gNoRender) { @@ -1604,8 +1731,8 @@ LLViewerWindow::LLViewerWindow( } // Make avatar head look forward at start - mCurrentMousePoint.mX = getWindowWidth() / 2; - mCurrentMousePoint.mY = getWindowHeight() / 2; + mCurrentMousePoint.mX = getWindowWidthScaled() / 2; + mCurrentMousePoint.mY = getWindowHeightScaled() / 2; gShowOverlayTitle = gSavedSettings.getBOOL("ShowOverlayTitle"); mOverlayTitle = gSavedSettings.getString("OverlayTitle"); @@ -1652,8 +1779,8 @@ void LLViewerWindow::initGLDefaults() void LLViewerWindow::initBase() { - S32 height = getWindowHeight(); - S32 width = getWindowWidth(); + S32 height = getWindowHeightScaled(); + S32 width = getWindowWidthScaled(); LLRect full_window(0, height, width, 0); @@ -2139,8 +2266,8 @@ void LLViewerWindow::sendShapeToSim() msg->addU32Fast(_PREHASH_CircuitCode, gMessageSystem->mOurCircuitCode); msg->nextBlockFast(_PREHASH_HeightWidthBlock); msg->addU32Fast(_PREHASH_GenCounter, 0); - U16 height16 = (U16) mWindowRect.getHeight(); - U16 width16 = (U16) mWindowRect.getWidth(); + U16 height16 = (U16) mWindowRectRaw.getHeight(); + U16 width16 = (U16) mWindowRectRaw.getWidth(); msg->addU16Fast(_PREHASH_Height, height16); msg->addU16Fast(_PREHASH_Width, width16); gAgent.sendReliableMessage(); @@ -2179,18 +2306,18 @@ void LLViewerWindow::reshape(S32 width, S32 height) } // update our window rectangle - mWindowRect.mRight = mWindowRect.mLeft + width; - mWindowRect.mTop = mWindowRect.mBottom + height; + mWindowRectRaw.mRight = mWindowRectRaw.mLeft + width; + mWindowRectRaw.mTop = mWindowRectRaw.mBottom + height; calcDisplayScale(); BOOL display_scale_changed = mDisplayScale != LLUI::sGLScaleFactor; LLUI::setScaleFactor(mDisplayScale); // update our window rectangle - mVirtualWindowRect.mRight = mVirtualWindowRect.mLeft + llround((F32)width / mDisplayScale.mV[VX]); - mVirtualWindowRect.mTop = mVirtualWindowRect.mBottom + llround((F32)height / mDisplayScale.mV[VY]); + mWindowRectScaled.mRight = mWindowRectScaled.mLeft + llround((F32)width / mDisplayScale.mV[VX]); + mWindowRectScaled.mTop = mWindowRectScaled.mBottom + llround((F32)height / mDisplayScale.mV[VY]); - setupViewport(); + setup2DViewport(); // Inform lower views of the change // round up when converting coordinates to make sure there are no gaps at edge of window @@ -2335,8 +2462,8 @@ void LLViewerWindow::draw() microsecondsToTimecodeString(gFrameTime,text); const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); font->renderUTF8(text, 0, - llround((getWindowWidth()/2)-100.f), - llround((getWindowHeight()-60.f)), + llround((getWindowWidthScaled()/2)-100.f), + llround((getWindowHeightScaled()-60.f)), LLColor4( 1.f, 1.f, 1.f, 1.f ), LLFontGL::LEFT, LLFontGL::TOP); } @@ -2344,6 +2471,10 @@ void LLViewerWindow::draw() // Draw all nested UI views. // No translation needed, this view is glued to 0,0 + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } gGL.pushMatrix(); { // scale view by UI global scale factor and aspect ratio correction factor @@ -2359,8 +2490,8 @@ void LLViewerWindow::draw() int pos_y = sub_region / llceil(zoom_factor); int pos_x = sub_region - (pos_y*llceil(zoom_factor)); // offset for this tile - glTranslatef((F32)getWindowWidth() * -(F32)pos_x, - (F32)getWindowHeight() * -(F32)pos_y, + glTranslatef((F32)getWindowWidthScaled() * -(F32)pos_x, + (F32)getWindowHeightScaled() * -(F32)pos_y, 0.f); glScalef(zoom_factor, zoom_factor, 1.f); LLUI::sGLScaleFactor *= zoom_factor; @@ -2425,8 +2556,8 @@ void LLViewerWindow::draw() const S32 DIST_FROM_TOP = 20; LLFontGL::getFontSansSerifBig()->renderUTF8( mOverlayTitle, 0, - llround( getWindowWidth() * 0.5f), - getWindowHeight() - DIST_FROM_TOP, + llround( getWindowWidthScaled() * 0.5f), + getWindowHeightScaled() - DIST_FROM_TOP, LLColor4(1, 1, 1, 0.4f), LLFontGL::HCENTER, LLFontGL::TOP); } @@ -2435,6 +2566,10 @@ void LLViewerWindow::draw() } gGL.popMatrix(); + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.unbind(); + } #if LL_DEBUG LLView::sIsDrawing = FALSE; #endif @@ -2587,7 +2722,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) } // Try for a new-format gesture - if (gGestureManager.triggerGesture(key, mask)) + if (LLGestureMgr::instance().triggerGesture(key, mask)) { return TRUE; } @@ -2745,6 +2880,10 @@ void LLViewerWindow::handleScrollWheel(S32 clicks) } // Zoom the camera in and out behavior + + if(top_ctrl == 0 + && getWorldViewRectScaled().pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) + && gAgentCamera.isInitialized()) gAgentCamera.handleScrollWheel(clicks); return; @@ -2752,8 +2891,8 @@ void LLViewerWindow::handleScrollWheel(S32 clicks) void LLViewerWindow::moveCursorToCenter() { - S32 x = mVirtualWindowRect.getWidth() / 2; - S32 y = mVirtualWindowRect.getHeight() / 2; + S32 x = getWorldViewWidthScaled() / 2; + S32 y = getWorldViewHeightScaled() / 2; //on a forced move, all deltas get zeroed out to prevent jumping mCurrentMousePoint.set(x,y); @@ -2778,15 +2917,28 @@ BOOL LLViewerWindow::handlePerFrameHover() S32 x = mCurrentMousePoint.mX; S32 y = mCurrentMousePoint.mY; + MASK mask = gKeyboard->currentMask(TRUE); + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) + { + gDebugRaycastFaceHit = -1; + gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, + &gDebugRaycastFaceHit, + &gDebugRaycastIntersection, + &gDebugRaycastTexCoord, + &gDebugRaycastNormal, + &gDebugRaycastBinormal, + &gDebugRaycastStart, + &gDebugRaycastEnd); + } //RN: fix for asynchronous notification of mouse leaving window not working LLCoordWindow mouse_pos; mWindow->getCursorPosition(&mouse_pos); if (mouse_pos.mX < 0 || mouse_pos.mY < 0 || - mouse_pos.mX > mWindowRect.getWidth() || - mouse_pos.mY > mWindowRect.getHeight()) + mouse_pos.mX > mWindowRectRaw.getWidth() || + mouse_pos.mY > mWindowRectRaw.getHeight()) { mMouseInWindow = FALSE; } @@ -3174,16 +3326,6 @@ BOOL LLViewerWindow::handlePerFrameHover() LLSelectMgr::getInstance()->deselectUnused(); } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_RAYCAST)) - { - gDebugRaycastFaceHit = -1; - gDebugRaycastObject = cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE, - &gDebugRaycastFaceHit, - &gDebugRaycastIntersection, - &gDebugRaycastTexCoord, - &gDebugRaycastNormal, - &gDebugRaycastBinormal); - } // per frame picking - for tooltips and changing cursor over interactive objects @@ -3229,9 +3371,9 @@ void LLViewerWindow::saveLastMouse(const LLCoordGL &point) { mCurrentMousePoint.mX = 0; } - else if (point.mX > getWindowWidth()) + else if (point.mX > getWindowWidthScaled()) { - mCurrentMousePoint.mX = getWindowWidth(); + mCurrentMousePoint.mX = getWindowWidthScaled(); } else { @@ -3242,9 +3384,9 @@ void LLViewerWindow::saveLastMouse(const LLCoordGL &point) { mCurrentMousePoint.mY = 0; } - else if (point.mY > getWindowHeight() ) + else if (point.mY > getWindowHeightScaled() ) { - mCurrentMousePoint.mY = getWindowHeight(); + mCurrentMousePoint.mY = getWindowHeightScaled(); } else { @@ -3501,8 +3643,8 @@ void LLViewerWindow::pickAsync(S32 x, S32 y_from_bot, MASK mask, void (*callback if (mPickScreenRegion.mLeft < 0) mPickScreenRegion.translate(-mPickScreenRegion.mLeft, 0); if (mPickScreenRegion.mBottom < 0) mPickScreenRegion.translate(0, -mPickScreenRegion.mBottom); - if (mPickScreenRegion.mRight > mWindowRect.getWidth() ) mPickScreenRegion.translate(mWindowRect.getWidth() - mPickScreenRegion.mRight, 0); - if (mPickScreenRegion.mTop > mWindowRect.getHeight() ) mPickScreenRegion.translate(0, mWindowRect.getHeight() - mPickScreenRegion.mTop); + if (mPickScreenRegion.mRight > mWindowRectRaw.getWidth() ) mPickScreenRegion.translate(mWindowRectRaw.getWidth() - mPickScreenRegion.mRight, 0); + if (mPickScreenRegion.mTop > mWindowRectRaw.getHeight() ) mPickScreenRegion.translate(0, mWindowRectRaw.getHeight() - mPickScreenRegion.mTop); } // set frame buffer region for picking results @@ -3529,77 +3671,6 @@ void LLViewerWindow::schedulePick(LLPickInfo& pick_info) } llassert_always(pick_info.mScreenRegion.notEmpty()); mPicks.push_back(pick_info); - - /*S32 scaled_x = llround((F32)pick_info.mMousePt.mX * mDisplayScale.mV[VX]); - S32 scaled_y = llround((F32)pick_info.mMousePt.mY * mDisplayScale.mV[VY]); - - // Default to not hitting anything - LLCamera pick_camera; - pick_camera.setOrigin(LLViewerCamera::getInstance()->getOrigin()); - pick_camera.setOriginAndLookAt(LLViewerCamera::getInstance()->getOrigin(), - LLViewerCamera::getInstance()->getUpAxis(), - LLViewerCamera::getInstance()->getOrigin() + mouseDirectionGlobal(pick_info.mMousePt.mX, pick_info.mMousePt.mY)); - pick_camera.setView(0.5f*DEG_TO_RAD); - pick_camera.setNear(LLViewerCamera::getInstance()->getNear()); - pick_camera.setFar(LLViewerCamera::getInstance()->getFar()); - pick_camera.setAspect(1.f); - - // save our drawing state - // *TODO: should we be saving using the new method here using - // glh_get_current_projection/glh_set_current_projection? -brad - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - // clear work area - { - LLGLState scissor_state(GL_SCISSOR_TEST); - scissor_state.enable(); - glScissor(pick_info.mScreenRegion.mLeft, pick_info.mScreenRegion.mBottom, pick_info.mScreenRegion.getWidth(), pick_info.mScreenRegion.getHeight()); - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - //glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - } - - // build perspective transform and picking viewport - // Perform pick on a PICK_DIAMETER x PICK_DIAMETER pixel region around cursor point. - // Don't limit the select distance for this pick. - LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, scaled_x - PICK_HALF_WIDTH, scaled_y - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER, FALSE); - - // render for object picking - - // make viewport big enough to handle antialiased frame buffers - gGLViewport[0] = pick_info.mScreenRegion.mLeft; - gGLViewport[1] = pick_info.mScreenRegion.mBottom; - gGLViewport[2] = pick_info.mScreenRegion.getWidth(); - gGLViewport[3] = pick_info.mScreenRegion.getHeight(); - - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - LLViewerCamera::updateFrustumPlanes(pick_camera); - stop_glerror(); - - // Draw the objects so the user can select them. - // The starting ID is 1, since land is zero. - LLRect pick_region; - pick_region.setOriginAndSize(pick_info.mMousePt.mX - PICK_HALF_WIDTH, - pick_info.mMousePt.mY - PICK_HALF_WIDTH, PICK_DIAMETER, PICK_DIAMETER); - gObjectList.renderObjectsForSelect(pick_camera, pick_region, FALSE, pick_info.mPickTransparent); - - stop_glerror(); - - // restore drawing state - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - setup3DRender(); - setup2DRender(); - setupViewport();*/ // delay further event processing until we receive results of pick mWindow->delayInputProcessing(); @@ -3689,7 +3760,9 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de LLVector3 *intersection, LLVector2 *uv, LLVector3 *normal, - LLVector3 *binormal) + LLVector3 *binormal, + LLVector3* start, + LLVector3* end) { S32 x = mouse_x; S32 y = mouse_y; @@ -3721,7 +3794,22 @@ LLViewerObject* LLViewerWindow::cursorIntersect(S32 mouse_x, S32 mouse_y, F32 de LLVector3 mouse_world_start = mouse_point_global; LLVector3 mouse_world_end = mouse_point_global + mouse_direction_global * depth; - + if (!LLViewerJoystick::getInstance()->getOverrideCamera()) + { //always set raycast intersection to mouse_world_end unless + //flycam is on (for DoF effect) + gDebugRaycastIntersection = mouse_world_end; + } + + if (start) + { + *start = mouse_world_start; + } + + if (end) + { + *end = mouse_world_end; + } + LLViewerObject* found = NULL; if (this_object) // check only this object @@ -3793,16 +3881,16 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const // find vertical field of view F32 fov = LLViewerCamera::getInstance()->getView(); - // find screen resolution - S32 height = getWindowHeight(); - S32 width = getWindowWidth(); + // find world view center in scaled ui coordinates + F32 center_x = getWorldViewRectScaled().getCenterX(); + F32 center_y = getWorldViewRectScaled().getCenterY(); // calculate pixel distance to screen - F32 distance = (height / 2.f) / (tan(fov / 2.f)); + F32 distance = ((F32)getWorldViewHeightScaled() * 0.5f) / (tan(fov / 2.f)); // calculate click point relative to middle of screen - F32 click_x = x - width / 2.f; - F32 click_y = y - height / 2.f; + F32 click_x = x - center_x; + F32 click_y = y - center_y; // compute mouse vector LLVector3 mouse_vector = distance * LLViewerCamera::getInstance()->getAtAxis() @@ -3817,12 +3905,15 @@ LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const LLVector3 LLViewerWindow::mousePointHUD(const S32 x, const S32 y) const { // find screen resolution - S32 height = getWindowHeight(); - S32 width = getWindowWidth(); + S32 height = getWorldViewHeightScaled(); + + // find world view center + F32 center_x = getWorldViewRectScaled().getCenterX(); + F32 center_y = getWorldViewRectScaled().getCenterY(); // remap with uniform scale (1/height) so that top is -0.5, bottom is +0.5 - F32 hud_x = -((F32)x - (F32)width/2.f) / height; - F32 hud_y = ((F32)y - (F32)height/2.f) / height; + F32 hud_x = -((F32)x - center_x) / height; + F32 hud_y = ((F32)y - center_y) / height; return LLVector3(0.f, hud_x/gAgentCamera.mHUDCurZoom, hud_y/gAgentCamera.mHUDCurZoom); } @@ -3836,12 +3927,16 @@ LLVector3 LLViewerWindow::mouseDirectionCamera(const S32 x, const S32 y) const F32 fov_width = fov_height * LLViewerCamera::getInstance()->getAspect(); // find screen resolution - S32 height = getWindowHeight(); - S32 width = getWindowWidth(); + S32 height = getWorldViewHeightScaled(); + S32 width = getWorldViewWidthScaled(); + + // find world view center + F32 center_x = getWorldViewRectScaled().getCenterX(); + F32 center_y = getWorldViewRectScaled().getCenterY(); // calculate click point relative to middle of screen - F32 click_x = (((F32)x / (F32)width) - 0.5f) * fov_width * -1.f; - F32 click_y = (((F32)y / (F32)height) - 0.5f) * fov_height; + F32 click_x = (((F32)x - center_x) / (F32)width) * fov_width * -1.f; + F32 click_y = (((F32)y - center_y) / (F32)height) * fov_height; // compute mouse vector LLVector3 mouse_vector = LLVector3(0.f, 0.f, -1.f); @@ -4092,8 +4187,8 @@ void LLViewerWindow::movieSize(S32 new_width, S32 new_height) ||(size.mY != new_height + BORDERHEIGHT)) { // use actual display dimensions, not virtual UI dimensions - S32 x = gViewerWindow->getWindowDisplayWidth(); - S32 y = gViewerWindow->getWindowDisplayHeight(); + S32 x = gViewerWindow->getWindowWidthRaw(); + S32 y = gViewerWindow->getWindowHeightRaw(); BORDERWIDTH = size.mX - x; BORDERHEIGHT = size.mY- y; LLCoordScreen new_size(new_width + BORDERWIDTH, @@ -4191,9 +4286,9 @@ BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 p S32 w = preview_width ; S32 h = preview_height ; LLVector2 display_scale = mDisplayScale ; - mDisplayScale.setVec((F32)w / mWindowRect.getWidth(), (F32)h / mWindowRect.getHeight()) ; + mDisplayScale.setVec((F32)w / mWindowRectRaw.getWidth(), (F32)h / mWindowRectRaw.getHeight()) ; LLRect window_rect = mWindowRect; - mWindowRect.set(0, h, w, 0); + mWindowRectRaw.set(0, h, w, 0); gDisplaySwapBuffers = FALSE; gDepthDirty = TRUE; @@ -4322,10 +4417,11 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei LLPipeline::sShowHUDAttachments = FALSE; } + // Copy screen to a buffer // crop sides or top and bottom, if taking a snapshot of different aspect ratio // from window - LLRect window_rect = mWindowRect; + LLRect window_rect = show_ui ? getWindowRectRaw() : getWorldViewRectRaw(); S32 snapshot_width = window_rect.getWidth(); S32 snapshot_height = window_rect.getHeight(); @@ -4392,7 +4488,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei window_width = snapshot_width; window_height = snapshot_height; scale_factor = 1.f; - mWindowRect.set(0, snapshot_height, snapshot_width, 0); + mWindowRectRaw.set(0, snapshot_height, snapshot_width, 0); target.bindTarget(); } } @@ -4445,7 +4541,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei //rescale fonts initFonts(scale_factor); LLHUDText::reshape(); - } + } } S32 output_buffer_offset_y = 0; @@ -4467,17 +4563,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei { gDisplaySwapBuffers = FALSE; gDepthDirty = TRUE; - if (type == SNAPSHOT_TYPE_OBJECT_ID) - { - glClearColor(0.f, 0.f, 0.f, 0.f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - LLViewerCamera::getInstance()->setZoomParameters(scale_factor, subimage_x+(subimage_y*llceil(scale_factor))); - setup3DRender(); - setupViewport(); - gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE); - } - else { const U32 subfield = subimage_x+(subimage_y*llceil(scale_factor)); display(do_rebuild, scale_factor, subfield, TRUE, is_tiling); @@ -4506,7 +4591,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei LLAppViewer::instance()->pingMainloopTimeout("LLViewerWindow::rawSnapshot"); } - if (type == SNAPSHOT_TYPE_OBJECT_ID || type == SNAPSHOT_TYPE_COLOR) + if (type == SNAPSHOT_TYPE_COLOR) { glReadPixels( subimage_x_offset, @@ -4608,7 +4693,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei gPipeline.resetDrawOrders(); } - if (high_res) + if (high_res && (show_ui || !hide_hud)) { send_agent_resume(); } @@ -4654,44 +4739,71 @@ void LLViewerWindow::drawMouselookInstructions() LLFontGL::LEFT, LLFontGL::TOP); } +void* LLViewerWindow::getPlatformWindow() const +{ + return mWindow->getPlatformWindow(); +} +void* LLViewerWindow::getMediaWindow() const +{ + return mWindow->getMediaWindow(); +} + +void LLViewerWindow::focusClient() const +{ + return mWindow->focusClient(); +} S32 LLViewerWindow::getWindowHeight() const { - return mVirtualWindowRect.getHeight(); + return mWindowRectScaled.getHeight(); } S32 LLViewerWindow::getWindowWidth() const { - return mVirtualWindowRect.getWidth(); + return mWindowRectScaled.getWidth(); } S32 LLViewerWindow::getWindowDisplayHeight() const { - return mWindowRect.getHeight(); + return mWindowRectRaw.getHeight(); } S32 LLViewerWindow::getWindowDisplayWidth() const { - return mWindowRect.getWidth(); -} - -void LLViewerWindow::setupViewport(S32 x_offset, S32 y_offset) -{ - gGLViewport[0] = x_offset; - gGLViewport[1] = y_offset; - gGLViewport[2] = mWindowRect.getWidth(); - gGLViewport[3] = mWindowRect.getHeight(); - glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); -} - -void LLViewerWindow::setup3DRender() -{ - LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, 0, 0, mWindowRect.getWidth(), mWindowRect.getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f); + return mWindowRectRaw.getWidth(); } void LLViewerWindow::setup2DRender() { - gl_state_for_2d(mWindowRect.getWidth(), mWindowRect.getHeight()); + // setup ortho camera + gl_state_for_2d(mWindowRectRaw.getWidth(), mWindowRectRaw.getHeight()); + setup2DViewport(); +} + +void LLViewerWindow::setup2DViewport(S32 x_offset, S32 y_offset) +{ + gGLViewport[0] = mWindowRectRaw.mLeft + x_offset; + gGLViewport[1] = mWindowRectRaw.mBottom + y_offset; + gGLViewport[2] = mWindowRectRaw.getWidth(); + gGLViewport[3] = mWindowRectRaw.getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); +} + + +void LLViewerWindow::setup3DRender() +{ + // setup perspective camera + LLViewerCamera::getInstance()->setPerspective(NOT_FOR_SELECTION, getWindowRectRaw().mLeft, getWindowRectRaw().mBottom, getWindowRectRaw().getWidth(), getWindowRectRaw().getHeight(), FALSE, LLViewerCamera::getInstance()->getNear(), MAX_FAR_CLIP*2.f); + setup3DViewport(); +} + +void LLViewerWindow::setup3DViewport(S32 x_offset, S32 y_offset) +{ + gGLViewport[0] = getWindowRectRaw().mLeft + x_offset; + gGLViewport[1] = getWindowRectRaw().mBottom + y_offset; + gGLViewport[2] = getWindowRectRaw().getWidth(); + gGLViewport[3] = getWindowRectRaw().getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); } @@ -4704,10 +4816,7 @@ void LLViewerWindow::setShowProgress(const BOOL show) } } -BOOL LLViewerWindow::getShowProgress() const -{ - return (mProgressView && mProgressView->getVisible()); -} + void LLViewerWindow::moveProgressViewToFront() @@ -4719,6 +4828,11 @@ void LLViewerWindow::moveProgressViewToFront() } } +BOOL LLViewerWindow::getShowProgress() const +{ + return (mProgressView && mProgressView->getVisible()); +} + void LLViewerWindow::setProgressString(const std::string& string) { if (mProgressView) @@ -4944,7 +5058,7 @@ BOOL LLViewerWindow::checkSettings() getWindow()->setNativeAspectRatio(gSavedSettings.getF32("FullScreenAspectRatio")); } - reshape(getWindowDisplayWidth(), getWindowDisplayHeight()); + reshape(getWindowWidthRaw(), getWindowHeightRaw()); // force aspect ratio if (mIsFullscreenChecked) @@ -5106,7 +5220,7 @@ BOOL LLViewerWindow::changeDisplaySettings(BOOL fullscreen, LLCoordScreen size, LLSD args; args["RESX"] = llformat("%d",size.mX); args["RESY"] = llformat("%d",size.mY); - LLNotifications::instance().add("ResolutionSwitchFail", args); + LLNotificationsUtil::add("ResolutionSwitchFail", args); size = old_size; // for reshape below } @@ -5178,7 +5292,7 @@ void LLViewerWindow::calcDisplayScale() F32 ui_scale_factor = gSavedSettings.getF32("UIScaleFactor"); LLVector2 display_scale; display_scale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f)); - F32 height_normalization = gSavedSettings.getBOOL("UIAutoScale") ? ((F32)mWindowRect.getHeight() / display_scale.mV[VY]) / 768.f : 1.f; + F32 height_normalization = gSavedSettings.getBOOL("UIAutoScale") ? ((F32)mWindowRectRaw.getHeight() / display_scale.mV[VY]) / 768.f : 1.f; if(mWindow->getFullscreen()) { display_scale *= (ui_scale_factor * height_normalization); @@ -5196,8 +5310,8 @@ void LLViewerWindow::calcDisplayScale() if (mWindow->getFullscreen()) { - display_scale.mV[0] = llround(display_scale.mV[0], 2.0f/(F32) mWindowRect.getWidth()); - display_scale.mV[1] = llround(display_scale.mV[1], 2.0f/(F32) mWindowRect.getHeight()); + display_scale.mV[0] = llround(display_scale.mV[0], 2.0f/(F32) mWindowRectRaw.getWidth()); + display_scale.mV[1] = llround(display_scale.mV[1], 2.0f/(F32) mWindowRectRaw.getHeight()); } if (display_scale != mDisplayScale) @@ -5221,7 +5335,7 @@ S32 LLViewerWindow::getChatConsoleBottomPad() LLRect LLViewerWindow::getChatConsoleRect() { - LLRect full_window(0, getWindowHeight(), getWindowWidth(), 0); + LLRect full_window(0, getWindowHeightScaled(), getWindowWidthScaled(), 0); LLRect console_rect = full_window; const S32 CONSOLE_PADDING_TOP = 24; @@ -5242,7 +5356,7 @@ LLRect LLViewerWindow::getChatConsoleRect() { // Make console rect somewhat narrow so having inventory open is // less of a problem. - console_rect.mRight = console_rect.mLeft + 2 * getWindowWidth() / 3; + console_rect.mRight = console_rect.mLeft + 2 * getWindowWidthScaled() / 3; } return console_rect; @@ -5391,9 +5505,9 @@ void LLPickInfo::fetchResults() //glReadPixels(mScreenRegion.mLeft, mScreenRegion.mBottom, mScreenRegion.getWidth(), mScreenRegion.getHeight(), GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, mPickDepthBuffer ); // find pick region that is fully onscreen - LLCoordGL scaled_pick_point;; - scaled_pick_point.mX = llclamp(llround((F32)mMousePt.mX * gViewerWindow->getDisplayScale().mV[VX]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayWidth() - PICK_HALF_WIDTH); - scaled_pick_point.mY = llclamp(llround((F32)mMousePt.mY * gViewerWindow->getDisplayScale().mV[VY]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayHeight() - PICK_HALF_WIDTH); + //LLCoordGL scaled_pick_point;; + //scaled_pick_point.mX = llclamp(llround((F32)mMousePt.mX * gViewerWindow->getDisplayScale().mV[VX]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayWidth() - PICK_HALF_WIDTH); + //scaled_pick_point.mY = llclamp(llround((F32)mMousePt.mY * gViewerWindow->getDisplayScale().mV[VY]), PICK_HALF_WIDTH, gViewerWindow->getWindowDisplayHeight() - PICK_HALF_WIDTH); //S32 pixel_index = PICK_HALF_WIDTH * PICK_DIAMETER + PICK_HALF_WIDTH; //S32 pick_id = (U32)mPickBuffer[(pixel_index * 4) + 0] << 16 | (U32)mPickBuffer[(pixel_index * 4) + 1] << 8 | (U32)mPickBuffer[(pixel_index * 4) + 2]; //F32 depth = mPickDepthBuffer[pixel_index]; diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index dec5a177c..036d23bb6 100644 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -44,9 +44,11 @@ #include "v3dmath.h" #include "v2math.h" -#include "llwindow.h" +#include "llcursortypes.h" +#include "llwindowcallbacks.h" #include "lltimer.h" #include "llstat.h" +#include "llmousehandler.h" #include "llalertdialog.h" #include "llnotifications.h" @@ -58,8 +60,9 @@ class LLTool; class LLVelocityBar; class LLTextBox; class LLImageRaw; +class LLImageFormatted; class LLHUDIcon; -class LLMouseHandler; +class LLWindow; class AIFilePicker; #define PICK_HALF_WIDTH 5 @@ -67,6 +70,17 @@ class AIFilePicker; class LLPickInfo { +public: + typedef enum e_pick_type + { + PICK_OBJECT, + PICK_FLORA, + PICK_LAND, + PICK_ICON, + PICK_PARCEL_WALL, + PICK_INVALID + } EPickType; + public: LLPickInfo(); LLPickInfo(const LLCoordGL& mouse_pos, @@ -80,20 +94,11 @@ public: void fetchResults(); LLPointer<LLViewerObject> getObject() const; LLUUID getObjectID() const { return mObjectID; } + bool isValid() const { return mPickType != PICK_INVALID; } void drawPickBuffer() const; static bool isFlora(LLViewerObject* object); - typedef enum e_pick_type - { - PICK_OBJECT, - PICK_FLORA, - PICK_LAND, - PICK_ICON, - PICK_PARCEL_WALL, - PICK_INVALID - } EPickType; - public: LLCoordGL mMousePt; MASK mKeyMask; @@ -190,20 +195,35 @@ public: LLView* getRootView() const { return mRootView; } // Window in raw pixels as seen on screen. - const LLRect& getWindowRect() const { return mWindowRect; }; + const LLRect& getWindowRect() const { return mWindowRectRaw; }; S32 getWindowDisplayHeight() const; S32 getWindowDisplayWidth() const; + //Temporary wrappers. + const LLRect& getWindowRectRaw() const { return getWindowRect(); } + S32 getWindowHeightRaw() const { return getWindowDisplayHeight(); } + S32 getWindowWidthRaw() const { return getWindowDisplayWidth(); } + const LLRect& getWorldViewRectRaw() const { return getWindowRect(); } + S32 getWorldViewHeightRaw() const { return getWindowDisplayHeight(); } + S32 getWorldViewWidthRaw() const { return getWindowDisplayWidth(); } // Window in scaled pixels (via UI scale), use this for // UI elements checking size. - const LLRect& getVirtualWindowRect() const { return mVirtualWindowRect; }; + const LLRect& getVirtualWindowRect() const { return mWindowRectScaled; }; S32 getWindowHeight() const; S32 getWindowWidth() const; + //Temporary wrappers. + const LLRect& getWindowRectScaled() const { return getVirtualWindowRect(); } + S32 getWindowHeightScaled() const { return getWindowHeight(); }; + S32 getWindowWidthScaled() const { return getWindowWidth(); }; + const LLRect& getWorldViewRectScaled() const { return getVirtualWindowRect(); } + S32 getWorldViewHeightScaled() const { return getWindowHeight(); }; + S32 getWorldViewWidthScaled() const { return getWindowWidth(); }; + LLWindow* getWindow() const { return mWindow; } - void* getPlatformWindow() const { return mWindow->getPlatformWindow(); } - void* getMediaWindow() const { return mWindow->getMediaWindow(); } - void focusClient() const { return mWindow->focusClient(); }; + void* getPlatformWindow() const; + void* getMediaWindow() const; + void focusClient() const; LLCoordGL getLastMouse() const { return mLastMousePoint; } S32 getLastMouseX() const { return mLastMousePoint.mX; } @@ -221,7 +241,8 @@ public: const LLPickInfo& getLastPick() const { return mLastPick; } const LLPickInfo& getHoverPick() const { return mHoverPick; } - void setupViewport(S32 x_offset = 0, S32 y_offset = 0); + void setup2DViewport(S32 x_offset = 0, S32 y_offset = 0); + void setup3DViewport(S32 x_offset = 0, S32 y_offset = 0); void setup3DRender(); void setup2DRender(); @@ -287,7 +308,6 @@ public: { SNAPSHOT_TYPE_COLOR, SNAPSHOT_TYPE_DEPTH, - SNAPSHOT_TYPE_OBJECT_ID }; BOOL saveSnapshot(const std::string& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR); BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL is_texture = FALSE, @@ -327,7 +347,9 @@ public: LLVector3 *intersection = NULL, LLVector2 *uv = NULL, LLVector3 *normal = NULL, - LLVector3 *binormal = NULL); + LLVector3 *binormal = NULL, + LLVector3* start = NULL, + LLVector3* end = NULL); // Returns a pointer to the last object hit @@ -382,9 +404,9 @@ protected: BOOL mActive; BOOL mWantFullscreen; BOOL mShowFullscreenProgress; - LLRect mWindowRect; - LLRect mVirtualWindowRect; - LLView* mRootView; // a view of size mWindowRect, containing all child views + LLRect mWindowRectRaw; + LLRect mWindowRectScaled; + LLView* mRootView; // a view of size mWindowRectRaw, containing all child views LLVector2 mDisplayScale; LLCoordGL mCurrentMousePoint; // last mouse position in GL coords diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp index fa5970a7b..3fa6a38e6 100644 --- a/indra/newview/llvlcomposition.cpp +++ b/indra/newview/llvlcomposition.cpp @@ -39,6 +39,7 @@ #include "v3math.h" #include "llsurface.h" #include "lltextureview.h" +#include "llviewertexture.h" #include "llviewertexturelist.h" #include "llviewerregion.h" #include "noise.h" @@ -163,7 +164,7 @@ BOOL LLVLComposition::generateHeights(const F32 x, const F32 y, const F32 xyScaleInv = (1.f / xyScale); const F32 zScaleInv = (1.f / zScale); - const F32 inv_width = 1.f/mWidth; + const F32 inv_width = 1.f/256.f; // OK, for now, just have the composition value equal the height at the point. for (S32 j = y_begin; j < y_end; j++) diff --git a/indra/newview/llvlmanager.cpp b/indra/newview/llvlmanager.cpp index 07ef26266..19ebe05fa 100644 --- a/indra/newview/llvlmanager.cpp +++ b/indra/newview/llvlmanager.cpp @@ -56,18 +56,26 @@ LLVLManager::~LLVLManager() void LLVLManager::addLayerData(LLVLData *vl_datap, const S32 mesg_size) { - if (LAND_LAYER_CODE == vl_datap->mType) + if (LAND_LAYER_CODE == vl_datap->mType || + AURORA_LAND_LAYER_CODE == vl_datap->mType) { mLandBits += mesg_size * 8; } - else if (WIND_LAYER_CODE == vl_datap->mType) + else if (WIND_LAYER_CODE == vl_datap->mType || + AURORA_WIND_LAYER_CODE == vl_datap->mType) { mWindBits += mesg_size * 8; } - else if (CLOUD_LAYER_CODE == vl_datap->mType) + else if (CLOUD_LAYER_CODE == vl_datap->mType || + AURORA_CLOUD_LAYER_CODE == vl_datap->mType) { mCloudBits += mesg_size * 8; } + else if (WATER_LAYER_CODE == vl_datap->mType || + AURORA_CLOUD_LAYER_CODE == vl_datap->mType) + { + mWaterBits += mesg_size * 8; + } else { llerrs << "Unknown layer type!" << (S32)vl_datap->mType << llendl; @@ -93,15 +101,25 @@ void LLVLManager::unpackData(const S32 num_packets) { datap->mRegionp->getLand().decompressDCTPatch(bit_pack, &goph, FALSE); } - else if (WIND_LAYER_CODE == datap->mType) + else if (AURORA_LAND_LAYER_CODE == datap->mType) + { + datap->mRegionp->getLand().decompressDCTPatch(bit_pack, &goph, TRUE); + } + else if (WIND_LAYER_CODE == datap->mType || + AURORA_WIND_LAYER_CODE == datap->mType) { datap->mRegionp->mWind.decompress(bit_pack, &goph); } - else if (CLOUD_LAYER_CODE == datap->mType) + else if (CLOUD_LAYER_CODE == datap->mType || + AURORA_CLOUD_LAYER_CODE == datap->mType) { datap->mRegionp->mCloudLayer.decompress(bit_pack, &goph); } + else if (WATER_LAYER_CODE == datap->mType || + AURORA_WATER_LAYER_CODE == datap->mType) + { + } } for (i = 0; i < mPacketData.count(); i++) diff --git a/indra/newview/llvlmanager.h b/indra/newview/llvlmanager.h index 9d64d6f24..4d7137fac 100644 --- a/indra/newview/llvlmanager.h +++ b/indra/newview/llvlmanager.h @@ -65,6 +65,7 @@ protected: U32 mLandBits; U32 mWindBits; U32 mCloudBits; + U32 mWaterBits; }; class LLVLData diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 16b04a5ff..2993b141f 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -63,6 +63,10 @@ #include "llkeyframefallmotion.h" #include "llkeyframestandmotion.h" #include "llkeyframewalkmotion.h" +#if MESH_ENABLED +#include "llmanipscale.h" // for get_default_max_prim_scale() +#include "llmeshrepository.h" +#endif //MESH_ENABLED #include "llmutelist.h" #include "llnotify.h" #include "llquantize.h" @@ -721,10 +725,16 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mTexHairColor( NULL ), mTexEyeColor( NULL ), mNeedsSkin(FALSE), +#if MESH_ENABLED + mLastSkinTime(0.f), +#endif //MESH_ENABLED mUpdatePeriod(1), mFullyLoadedInitialized(FALSE), mHasBakedHair( FALSE ), mSupportsAlphaLayers(FALSE), +#if MESH_ENABLED + mHasPelvisOffset( FALSE ), +#endif //MESH_ENABLED mFirstSetActualBoobGravRan( false ), mSupportsPhysics( false ) //mFirstSetActualButtGravRan( false ), @@ -834,6 +844,12 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRuthTimer.reset(); +#if MESH_ENABLED + mPelvisOffset = LLVector3(0.0f,0.0f,0.0f); + mLastPelvisToFoot = 0.0f; + mPelvisFixup = 0.0f; + mLastPelvisFixup = 0.0f; +#endif //MESH_ENABLED //------------------------------------------------------------------------- // initialize joint, mesh and shape members //------------------------------------------------------------------------- @@ -1523,6 +1539,16 @@ const LLVector3 LLVOAvatar::getRenderPosition() const } else if (isRoot() || !mDrawable->getParent()) { +#if MESH_ENABLED + if ( mHasPelvisOffset ) + { + //Apply a pelvis fixup (as defined by the avs skin) + LLVector3 pos = mDrawable->getPositionAgent(); + pos[VZ] += mPelvisFixup; + return pos; + } + else +#endif //MESH_ENABLED return mDrawable->getPositionAgent(); } else @@ -1536,41 +1562,46 @@ void LLVOAvatar::updateDrawable(BOOL force_damped) clearChanged(SHIFTED); } -void LLVOAvatar::onShift(const LLVector3& shift_vector) +void LLVOAvatar::onShift(const LLVector4a& shift_vector) { - mLastAnimExtents[0] += shift_vector; - mLastAnimExtents[1] += shift_vector; + const LLVector3& shift = reinterpret_cast<const LLVector3&>(shift_vector); + mLastAnimExtents[0] += shift; + mLastAnimExtents[1] += shift; mNeedsImpostorUpdate = TRUE; mNeedsAnimUpdate = TRUE; } -void LLVOAvatar::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax) +void LLVOAvatar::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) { if (isImpostor() && !needsImpostorUpdate()) { LLVector3 delta = getRenderPosition() - - ((LLVector3(mDrawable->getPositionGroup())-mImpostorOffset)); + ((LLVector3(mDrawable->getPositionGroup().getF32ptr())-mImpostorOffset)); - newMin = mLastAnimExtents[0] + delta; - newMax = mLastAnimExtents[1] + delta; + newMin.load3( (mLastAnimExtents[0] + delta).mV); + newMax.load3( (mLastAnimExtents[1] + delta).mV); } else { getSpatialExtents(newMin,newMax); - mLastAnimExtents[0] = newMin; - mLastAnimExtents[1] = newMax; - LLVector3 pos_group = (newMin+newMax)*0.5f; - mImpostorOffset = pos_group-getRenderPosition(); + mLastAnimExtents[0].set(newMin.getF32ptr()); + mLastAnimExtents[1].set(newMax.getF32ptr()); + LLVector4a pos_group; + pos_group.setAdd(newMin,newMax); + pos_group.mul(0.5f); + mImpostorOffset = LLVector3(pos_group.getF32ptr())-getRenderPosition(); mDrawable->setPositionGroup(pos_group); } } -void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax) +void LLVOAvatar::getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { - LLVector3 buffer(0.25f, 0.25f, 0.25f); - LLVector3 pos = getRenderPosition(); - newMin = pos - buffer; - newMax = pos + buffer; + LLVector4a buffer(0.25f); + LLVector4a pos; + pos.load3(getRenderPosition().mV); + newMin.setSub(pos, buffer); + newMax.setAdd(pos, buffer); + float max_attachment_span = DEFAULT_MAX_PRIM_SCALE * 5.0f; //stretch bounding box by joint positions @@ -1579,12 +1610,20 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax) LLPolyMesh* mesh = i->second; for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.count(); joint_num++) { - update_min_max(newMin, newMax, - mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation()); + LLVector4a trans; + trans.load3( mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation().mV); + update_min_max(newMin, newMax, trans); } } - mPixelArea = LLPipeline::calcPixelArea((newMin+newMax)*0.5f, (newMax-newMin)*0.5f, *LLViewerCamera::getInstance()); + LLVector4a center, size; + center.setAdd(newMin, newMax); + center.mul(0.5f); + + size.setSub(newMax,newMin); + size.mul(0.5f); + + mPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); //stretch bounding box by attachments for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); @@ -1605,20 +1644,26 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax) if (attached_object && !attached_object->isHUDAttachment()) { LLDrawable* drawable = attached_object->mDrawable; - if (drawable) + if (drawable +#if MESH_ENABLED + && !drawable->isState(LLDrawable::RIGGED) +#endif //MESH_ENABLED + ) { LLSpatialBridge* bridge = drawable->getSpatialBridge(); if (bridge) { - const LLVector3* ext = bridge->getSpatialExtents(); - LLVector3 distance = (ext[1] - ext[0]); + const LLVector4a* ext = bridge->getSpatialExtents(); + LLVector4a distance; + distance.setSub(ext[1], ext[0]); + LLVector4a max_span(max_attachment_span); + + S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7; // Only add the prim to spatial extents calculations if it isn't a megaprim. // max_attachment_span calculated at the start of the function // (currently 5 times our max prim size) - if (distance.mV[0] < max_attachment_span - && distance.mV[1] < max_attachment_span - && distance.mV[2] < max_attachment_span) + if (lt == 0x7) { update_min_max(newMin,newMax,ext[0]); update_min_max(newMin,newMax,ext[1]); @@ -1630,8 +1675,9 @@ void LLVOAvatar::getSpatialExtents(LLVector3& newMin, LLVector3& newMax) } //pad bounding box - newMin -= buffer; - newMax += buffer; + + newMin.sub(buffer); + newMax.add(buffer); } //----------------------------------------------------------------------------- @@ -1707,6 +1753,33 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e return TRUE; } } +#if MESH_ENABLED + if (isSelf()) + { + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* attached_object = (*attachment_iter); + + if (attached_object && !attached_object->isDead() && attachment->getValid()) + { + LLDrawable* drawable = attached_object->mDrawable; + if (drawable->isState(LLDrawable::RIGGED)) + { //regenerate octree for rigged attachment + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_RIGGED, TRUE); + } + } + } + } + } +#endif //MESH_ENABLED } LLVector3 position; @@ -1723,6 +1796,58 @@ BOOL LLVOAvatar::lineSegmentIntersect(const LLVector3& start, const LLVector3& e return FALSE; } +#if MESH_ENABLED +LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector3& start, const LLVector3& end, + S32 face, + BOOL pick_transparent, + S32* face_hit, + LLVector3* intersection, + LLVector2* tex_coord, + LLVector3* normal, + LLVector3* bi_normal) +{ + if (isSelf() && !gAgent.needsRenderAvatar()) + { + return NULL; + } + + LLViewerObject* hit = NULL; + + if (lineSegmentBoundingBox(start, end)) + { + LLVector3 local_end = end; + LLVector3 local_intersection; + + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; + + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { + LLViewerObject* attached_object = (*attachment_iter); + + if (attached_object->lineSegmentIntersect(start, local_end, face, pick_transparent, face_hit, &local_intersection, tex_coord, normal, bi_normal)) + { + local_end = local_intersection; + if (intersection) + { + *intersection = local_intersection; + } + + hit = attached_object; + } + } + } + } + + return hit; +} +#endif //MESH_ENABLED + //----------------------------------------------------------------------------- // parseSkeletonFile() //----------------------------------------------------------------------------- @@ -2424,27 +2549,29 @@ void LLVOAvatar::updateMeshData() bool terse_update = false; + facep->setGeomIndex(0); + facep->setIndicesIndex(0); + + LLVertexBuffer* buff = facep->getVertexBuffer(); if(!facep->getVertexBuffer()) { - LLVertexBuffer *buff = new LLVertexBufferAvatar(); + buff = new LLVertexBufferAvatar(); buff->allocateBuffer(num_vertices, num_indices, TRUE); facep->setVertexBuffer(buff); } else { - if (facep->getVertexBuffer()->getRequestedIndices() == num_indices && - facep->getVertexBuffer()->getRequestedVerts() == num_vertices) + if (buff->getRequestedIndices() == num_indices && + buff->getRequestedVerts() == num_vertices) { terse_update = true; } else { - facep->getVertexBuffer()->resizeBuffer(num_vertices, num_indices) ; + buff->resizeBuffer(num_vertices, num_indices); } } - - facep->setGeomIndex(0); - facep->setIndicesIndex(0); + // This is a hack! Avatars have their own pool, so we are detecting // the case of more than one avatar in the pool (thus > 0 instead of >= 0) @@ -2459,7 +2586,7 @@ void LLVOAvatar::updateMeshData() } stop_glerror(); - facep->getVertexBuffer()->setBuffer(0); + buff->setBuffer(0); if(!f_num) { @@ -2803,7 +2930,7 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) else { llinfos << "oops - CurrentGesticulationLevel can be only 0, 1, or 2" << llendl; } // this is the call that Karl S. created for triggering gestures from within the code. - gGestureManager.triggerAndReviseString( gestureString ); + LLGestureMgr::instance().triggerAndReviseString( gestureString ); } } @@ -2855,9 +2982,20 @@ void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) // here we get the approximate head position and set as sound source for the voice symbol // (the following version uses a tweak of "mHeadOffset" which handle sitting vs. standing) //-------------------------------------------------------------------------------------------- +#if MESH_ENABLED + if( !mIsSitting ) + { + LLVector3 tagPos = mRoot.getWorldPosition(); + tagPos[VZ] -= mPelvisToFoot; + tagPos[VZ] += ( mBodySize[VZ] + 0.125f ); + mVoiceVisualizer->setVoiceSourceWorldPosition( tagPos ); + } + else +#endif //MESH_ENABLED + { LLVector3 headOffset = LLVector3( 0.0f, 0.0f, mHeadOffset.mV[2] ); mVoiceVisualizer->setVoiceSourceWorldPosition( mRoot.getWorldPosition() + headOffset ); - + } }//if ( voiceEnabled ) } @@ -2926,7 +3064,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (isImpostor() && !mNeedsImpostorUpdate) { - LLVector3 ext[2]; + LLVector4a ext[2]; F32 distance; LLVector3 angle; @@ -2938,7 +3076,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) F32 old_angle = mImpostorAngle.mV[i]; F32 angle_diff = fabsf(cur_angle-old_angle); - if (angle_diff > 3.14159f/512.f*distance*mUpdatePeriod) + if (angle_diff > F_PI/512.f*distance*mUpdatePeriod) { mNeedsImpostorUpdate = TRUE; } @@ -2955,16 +3093,25 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) } else { + //VECTORIZE THIS getSpatialExtents(ext[0], ext[1]); - if ((ext[1]-mImpostorExtents[1]).length() > 0.05f || - (ext[0]-mImpostorExtents[0]).length() > 0.05f) + LLVector4a diff; + diff.setSub(ext[1], mImpostorExtents[1]); + if (diff.getLength3().getF32() > 0.05f) { mNeedsImpostorUpdate = TRUE; } + else + { + diff.setSub(ext[0], mImpostorExtents[0]); + if (diff.getLength3().getF32() > 0.05f) + { + mNeedsImpostorUpdate = TRUE; + } + } } } } - if(mDrawable) { mDrawable->movePartition(); @@ -3212,7 +3359,7 @@ void LLVOAvatar::idleUpdateLoadingEffect() particle_parameters.mPartImageID = cloud->getID(); particle_parameters.mMaxAge = 0.f; particle_parameters.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE; - particle_parameters.mInnerAngle = 3.14159f; + particle_parameters.mInnerAngle = F_PI; particle_parameters.mOuterAngle = 0.f; particle_parameters.mBurstRate = 0.02f; particle_parameters.mBurstRadius = 0.0f; @@ -3523,9 +3670,10 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } // check attachments for nameplate override + static const LLCachedControl<bool> allow_nameplate_override ("CCSAllowNameplateOverride", true); std::string nameplate; attachment_map_t::iterator it, end=mAttachmentPoints.end(); - for (it=mAttachmentPoints.begin(); it!=end; ++it) { + if (allow_nameplate_override) for (it=mAttachmentPoints.begin(); it!=end; ++it) { // get attached object LLViewerJointAttachment *atm = it->second; if (!atm) continue; @@ -3816,7 +3964,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) } //idle text std::string idle_string; - if(!mIsSelf && mIdleTimer.getElapsedTimeF32() > 120 && gSavedSettings.getBOOL("AscentShowIdleTime")) + if(!mIsSelf && mIdleTimer.getElapsedTimeF32() > 120.f && gSavedSettings.getBOOL("AscentShowIdleTime")) { idle_string = getIdleTime(); } @@ -4317,34 +4465,39 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) if (visible && !isSelf() && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter) { + const LLVector4a* ext = mDrawable->getSpatialExtents(); + LLVector4a size; + size.setSub(ext[1],ext[0]); + F32 mag = size.getLength3().getF32()*0.5f; + F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f); if (LLMuteList::getInstance()->isMuted(getID())) { // muted avatars update at 16 hz mUpdatePeriod = 16; } - else if (mVisibilityRank <= LLVOAvatar::sMaxVisible * 0.25f) + else if (mVisibilityRank <= LLVOAvatar::sMaxVisible || + mDrawable->mDistanceWRTCamera < 1.f + mag) { //first 25% of max visible avatars are not impostored + //also, don't impostor avatars whose bounding box may be penetrating the + //impostor camera near clip plane mUpdatePeriod = 1; } - else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 0.75f) - { //back 25% of max visible avatars are slow updating impostors - mUpdatePeriod = 8; - } - else if (mVisibilityRank > (U32) LLVOAvatar::sMaxVisible) + else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 4) { //background avatars are REALLY slow updating impostors mUpdatePeriod = 16; } + else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 3) + { //back 25% of max visible avatars are slow updating impostors + mUpdatePeriod = 8; + } else if (mImpostorPixelArea <= impostor_area) { // stuff in between gets an update period based on pixel area mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mImpostorPixelArea), 2, 8); } - else if (mVisibilityRank > LLVOAvatar::sMaxVisible * 0.25f) - { // force nearby impostors in ultra crowded areas - mUpdatePeriod = 2; - } else - { // not impostored - mUpdatePeriod = 1; + { + //nearby avatars, update the impostors more frequently. + mUpdatePeriod = 4; } visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE; @@ -4766,7 +4919,43 @@ void LLVOAvatar::updateHeadOffset() mHeadOffset = lerp(midEyePt, mHeadOffset, u); } } - +#if MESH_ENABLED +//------------------------------------------------------------------------ +// setPelvisOffset +//------------------------------------------------------------------------ +void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, F32 pelvisFixup ) +{ + mHasPelvisOffset = hasOffset; + if ( mHasPelvisOffset ) + { + //Store off last pelvis to foot value + mLastPelvisToFoot = mPelvisToFoot; + mPelvisOffset = offsetAmount; + mLastPelvisFixup = mPelvisFixup; + mPelvisFixup = pelvisFixup; + } +} +//------------------------------------------------------------------------ +// postPelvisSetRecalc +//------------------------------------------------------------------------ +void LLVOAvatar::postPelvisSetRecalc( void ) +{ + computeBodySize(); + mRoot.touch(); + mRoot.updateWorldMatrixChildren(); + dirtyMesh(); + updateHeadOffset(); +} +//------------------------------------------------------------------------ +// pelisPoke +//------------------------------------------------------------------------ +void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount ) +{ + mHasPelvisOffset = true; + mLastPelvisFixup = mPelvisFixup; + mPelvisFixup = pelvisFixupAmount; +} +#endif //MESH_ENABLED //------------------------------------------------------------------------ // updateVisibility() //------------------------------------------------------------------------ @@ -4916,6 +5105,7 @@ bool LLVOAvatar::shouldAlphaMask() } + //------------------------------------------------------------------------ // needsRenderBeam() //------------------------------------------------------------------------ @@ -4984,6 +5174,9 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) mMeshLOD[MESH_ID_HAIR]->updateJointGeometry(); } mNeedsSkin = FALSE; +#if MESH_ENABLED + mLastSkinTime = gFrameTimeSeconds; +#endif //MESH_ENABLED LLVertexBuffer* vb = mDrawable->getFace(0)->getVertexBuffer(); if (vb) @@ -5036,7 +5229,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) // *NOTE: this is disabled (there is no UI for enabling sShowFootPlane) due // to DEV-14477. the code is left here to aid in tracking down the cause // of the crash in the future. -brad - if (!gRenderForSelect && sShowFootPlane && mDrawable.notNull()) + if (sShowFootPlane && mDrawable.notNull()) { LLVector3 slaved_pos = mDrawable->getPositionAgent(); LLVector3 foot_plane_normal(mFootPlane.mV[VX], mFootPlane.mV[VY], mFootPlane.mV[VZ]); @@ -5081,7 +5274,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) const bool should_alpha_mask = shouldAlphaMask(); LLGLState test(GL_ALPHA_TEST, should_alpha_mask); - if (should_alpha_mask) + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } @@ -5110,7 +5303,10 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) } } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) { @@ -5193,7 +5389,7 @@ U32 LLVOAvatar::renderRigid() const bool should_alpha_mask = shouldAlphaMask(); LLGLState test(GL_ALPHA_TEST, should_alpha_mask); - if (should_alpha_mask) + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) { gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } @@ -5204,7 +5400,10 @@ U32 LLVOAvatar::renderRigid() num_indices += mMeshLOD[MESH_ID_EYEBALL_RIGHT]->render(mAdjustedPixelArea, TRUE, mIsDummy); } - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } return num_indices; } @@ -5411,7 +5610,7 @@ void LLVOAvatar::updateTextures() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - setDebugText(llformat("%4.0f:%4.0f", fsqrtf(mMinPixelArea),fsqrtf(mMaxPixelArea))); + setDebugText(llformat("%4.0f:%4.0f", (F32) sqrt(mMinPixelArea),(F32) sqrt(mMaxPixelArea))); } if( render_avatar ) @@ -5970,13 +6169,89 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) } return jointp; } +#if MESH_ENABLED +//----------------------------------------------------------------------------- +// resetJointPositions +//----------------------------------------------------------------------------- +void LLVOAvatar::resetJointPositions( void ) +{ + for(S32 i = 0; i < (S32)mNumJoints; ++i) + { + mSkeleton[i].restoreOldXform(); + mSkeleton[i].setId( LLUUID::null ); + } + mHasPelvisOffset = false; + mPelvisFixup = mLastPelvisFixup; +} +//----------------------------------------------------------------------------- +// resetSpecificJointPosition +//----------------------------------------------------------------------------- +void LLVOAvatar::resetSpecificJointPosition( const std::string& name ) +{ + LLJoint* pJoint = mRoot.findJoint( name ); + + if ( pJoint && pJoint->doesJointNeedToBeReset() ) + { + pJoint->restoreOldXform(); + pJoint->setId( LLUUID::null ); + //If we're reseting the pelvis position make sure not to apply offset + if ( name == "mPelvis" ) + { + mHasPelvisOffset = false; + } + } + else + { + llinfos<<"Did not find "<< name.c_str()<<llendl; + } +} +//----------------------------------------------------------------------------- +// resetJointPositionsToDefault +//----------------------------------------------------------------------------- +void LLVOAvatar::resetJointPositionsToDefault( void ) +{ + const LLVector3& avPos = getCharacterPosition(); + + //Reposition the pelvis + LLJoint* pPelvis = mRoot.findJoint("mPelvis"); + if ( pPelvis ) + { + pPelvis->setPosition( avPos + pPelvis->getPosition() ); + } + else + { + llwarns<<"Can't get pelvis joint."<<llendl; + return; + } + + //Subsequent joints are relative to pelvis + for( S32 i = 0; i < (S32)mNumJoints; ++i ) + { + LLJoint* pJoint = (LLJoint*)&mSkeleton[i]; + if ( pJoint->doesJointNeedToBeReset() ) + { + + pJoint->setId( LLUUID::null ); + //restore joints to default positions, however skip over the pelvis + if ( pJoint && pPelvis != pJoint ) + { + pJoint->restoreOldXform(); + } + } + } + //make sure we don't apply the joint offset + mHasPelvisOffset = false; + mPelvisFixup = mLastPelvisFixup; + postPelvisSetRecalc(); +} +#endif //MESH_ENABLED //----------------------------------------------------------------------------- // getCharacterPosition() //----------------------------------------------------------------------------- LLVector3 LLVOAvatar::getCharacterPosition() { - if (mDrawable && mDrawable.notNull()) + if (mDrawable.notNull()) { return mDrawable->getPositionAgent(); } @@ -6600,14 +6875,18 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) { LLMemType mt(LLMemType::MTYPE_AVATAR); - if (!mDrawable || mDrawable.isNull()) + if (mDrawable.isNull()) { return; } - const LLVector3* ext = mDrawable->getSpatialExtents(); - LLVector3 center = (ext[1] + ext[0]) * 0.5f; - LLVector3 size = (ext[1]-ext[0])*0.5f; + const LLVector4a* ext = mDrawable->getSpatialExtents(); + LLVector4a center; + center.setAdd(ext[1], ext[0]); + center.mul(0.5f); + LLVector4a size; + size.setSub(ext[1], ext[0]); + size.mul(0.5f); mImpostorPixelArea = LLPipeline::calcPixelArea(center, size, *LLViewerCamera::getInstance()); @@ -6619,7 +6898,7 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) } else { - F32 radius = size.length(); + F32 radius = size.getLength3().getF32(); mAppAngle = (F32) atan2( radius, range) * RAD_TO_DEG; } @@ -7059,6 +7338,7 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) if (attachment->isObjectAttached(viewer_object)) { LLCOFMgr::instance().addAttachment(viewer_object->getAttachmentItemID()); + updateLODRiggedAttachments(); } } @@ -7111,7 +7391,8 @@ void LLVOAvatar::lazyAttach() void LLVOAvatar::resetHUDAttachments() { for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); iter++) + iter != mAttachmentPoints.end(); + ++iter) { LLViewerJointAttachment* attachment = iter->second; if (attachment->getIsHUDAttachment()) @@ -7130,6 +7411,56 @@ void LLVOAvatar::resetHUDAttachments() } } +#if MESH_ENABLED +void LLVOAvatar::rebuildRiggedAttachments( void ) +{ + for ( attachment_map_t::iterator iter = mAttachmentPoints.begin(); iter != mAttachmentPoints.end(); ++iter ) + { + LLViewerJointAttachment* pAttachment = iter->second; + LLViewerJointAttachment::attachedobjs_vec_t::iterator attachmentIterEnd = pAttachment->mAttachedObjects.end(); + + for ( LLViewerJointAttachment::attachedobjs_vec_t::iterator attachmentIter = pAttachment->mAttachedObjects.begin(); + attachmentIter != attachmentIterEnd; ++attachmentIter) + { + const LLViewerObject* pAttachedObject = *attachmentIter; + if ( pAttachment && pAttachedObject->mDrawable.notNull() ) + { + gPipeline.markRebuild(pAttachedObject->mDrawable); + } + } + } +} + +//----------------------------------------------------------------------------- +// cleanupAttachedMesh() +//----------------------------------------------------------------------------- +void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) +{ + //If a VO has a skin that we'll reset the joint positions to their default + if ( pVO && pVO->mDrawable ) + { + LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); + if ( pVObj ) + { + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); + if ( pSkinData ) + { + const int jointCnt = pSkinData->mJointNames.size(); + bool fullRig = ( jointCnt>=20 ) ? true : false; + if ( fullRig ) + { + const int bindCnt = pSkinData->mAlternateBindMatrix.size(); + if ( bindCnt > 0 ) + { + LLVOAvatar::resetJointPositionsToDefault(); + } + } + } + } + } +} +#endif //MESH_ENABLED + //----------------------------------------------------------------------------- // detachObject() //----------------------------------------------------------------------------- @@ -8417,6 +8748,22 @@ void LLVOAvatar::setCompositeUpdatesEnabled( BOOL b ) } } +void LLVOAvatar::setNameFromChat(const std::string &text) { + static const LLCachedControl<bool> allow_nameplate_override ("CCSAllowNameplateOverride", true); + if(allow_nameplate_override) { + mNameFromChatOverride = true; + mNameFromChatChanged = true; + mNameFromChatText = text; + } +} + +void LLVOAvatar::clearNameFromChat() { + mNameFromChatOverride = false; + mNameFromChatChanged = true; + mNameFromChatText = ""; +} + + void LLVOAvatar::addChat(const LLChat& chat) { std::deque<LLChat>::iterator chat_iter; @@ -9685,7 +10032,7 @@ void LLVOAvatar::cullAvatarsByPixelArea() std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater()); // Update the avatars that have changed status - U32 rank = 0; + U32 rank = 2; //1 is reserved for self. for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) { @@ -9709,7 +10056,7 @@ void LLVOAvatar::cullAvatarsByPixelArea() if (inst->isSelf()) { - inst->setVisibilityRank(0); + inst->setVisibilityRank(1); } else if (inst->mDrawable.notNull() && inst->mDrawable->isVisible()) { @@ -10476,6 +10823,13 @@ BOOL LLVOAvatar::updateLOD() return res; } +#if MESH_ENABLED +void LLVOAvatar::updateLODRiggedAttachments( void ) +{ + updateLOD(); + rebuildRiggedAttachments(); +} +#endif //MESH_ENABLED U32 LLVOAvatar::getPartitionType() const { // Avatars merely exist as drawables in the bridge partition @@ -10485,16 +10839,19 @@ U32 LLVOAvatar::getPartitionType() const //static void LLVOAvatar::updateImpostors() { + LLCharacter::sAllowInstancesChange = FALSE ; + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) + iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* avatar = (LLVOAvatar*) *iter; - if (!avatar->isDead() && avatar->needsImpostorUpdate() && avatar->isVisible() && avatar->isImpostor()) { gPipeline.generateImpostor(avatar); } } + + LLCharacter::sAllowInstancesChange = TRUE ; } BOOL LLVOAvatar::isImpostor() const @@ -10528,9 +10885,9 @@ void LLVOAvatar::cacheImpostorValues() getImpostorValues(mImpostorExtents, mImpostorAngle, mImpostorDistance); } -void LLVOAvatar::getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const +void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& distance) const { - const LLVector3* ext = mDrawable->getSpatialExtents(); + const LLVector4a* ext = mDrawable->getSpatialExtents(); extents[0] = ext[0]; extents[1] = ext[1]; diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index b50111e40..ad3c2f641 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -124,10 +124,13 @@ public: /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); virtual BOOL updateLOD(); BOOL updateJointLODs(); +#if MESH_ENABLED + void updateLODRiggedAttachments( void ); +#endif //MESH_ENABLED /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. /*virtual*/ void updateTextures(); /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); // If setting a baked texture, need to request it from a non-local sim. - /*virtual*/ void onShift(const LLVector3& shift_vector); + /*virtual*/ void onShift(const LLVector4a& shift_vector); virtual U32 getPartitionType() const; virtual const LLVector3 getRenderPosition() const; virtual void updateDrawable(BOOL force_damped); @@ -135,8 +138,8 @@ public: /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); virtual void updateRegion(LLViewerRegion *regionp); - void updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax); - void getSpatialExtents(LLVector3& newMin, LLVector3& newMax); + void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); + void getSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, @@ -145,7 +148,17 @@ public: LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point LLVector3* normal = NULL, // return the surface normal at the intersection point LLVector3* bi_normal = NULL); // return the surface bi-normal at the intersection point +#if MESH_ENABLED + LLViewerObject* lineSegmentIntersectRiggedAttachments(const LLVector3& start, const LLVector3& end, + S32 face = -1, // which face to check, -1 = ALL_SIDES + BOOL pick_transparent = FALSE, + S32* face_hit = NULL, // which face was hit + LLVector3* intersection = NULL, // return the intersection point + LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point + LLVector3* normal = NULL, // return the surface normal at the intersection point + LLVector3* bi_normal = NULL); // return the surface bi-normal at the intersection point +#endif //MESH_ENABLED //-------------------------------------------------------------------- // LLCharacter interface and related //-------------------------------------------------------------------- @@ -168,6 +181,11 @@ public: virtual LLJoint* getJoint(const std::string &name); virtual LLJoint* getRootJoint() { return &mRoot; } +#if MESH_ENABLED + void resetJointPositions( void ); + void resetJointPositionsToDefault( void ); + void resetSpecificJointPosition( const std::string& name ); +#endif //MESH_ENABLED virtual const char* getAnimationPrefix() { return "avatar"; } virtual const LLUUID& getID(); virtual LLVector3 getVolumePos(S32 joint_index, LLVector3& volume_offset); @@ -196,6 +214,10 @@ public: public: bool isSelf() const { return mIsSelf; } // True if this avatar is for this viewer's agent bool isBuilt() const { return mIsBuilt; } + +private: //aligned members + LLVector4a mImpostorExtents[2]; + private: BOOL mSupportsAlphaLayers; // For backwards compatibility, TRUE for 1.23+ clients @@ -282,7 +304,18 @@ private: public: void updateHeadOffset(); F32 getPelvisToFoot() const { return mPelvisToFoot; } +#if MESH_ENABLED + void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ; + bool hasPelvisOffset( void ) { return mHasPelvisOffset; } + void postPelvisSetRecalc( void ); + void setPelvisOffset( F32 pelvixFixupAmount ); + bool mHasPelvisOffset; + LLVector3 mPelvisOffset; + F32 mLastPelvisToFoot; + F32 mPelvisFixup; + F32 mLastPelvisFixup; +#endif //MESH_ENABLED LLVector3 mHeadOffset; // current head position LLViewerJoint mRoot; protected: @@ -351,6 +384,10 @@ public: U32 renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); U32 renderRigid(); U32 renderSkinned(EAvatarRenderPass pass); +#if MESH_ENABLED + F32 getLastSkinTime() { return mLastSkinTime; } + U32 renderSkinnedAttachments(); +#endif //MESH_ENABLED U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); static void deleteCachedImages(bool clearAll=true); @@ -362,6 +399,9 @@ private: bool shouldAlphaMask(); BOOL mNeedsSkin; // avatar has been animated and verts have not been updated +#if MESH_ENABLED + F32 mLastSkinTime; //value of gFrameTimeSeconds at last skin update +#endif //MESH_ENABLED S32 mUpdatePeriod; S32 mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. @@ -393,7 +433,7 @@ public: BOOL needsImpostorUpdate() const; const LLVector3& getImpostorOffset() const; const LLVector2& getImpostorDim() const; - void getImpostorValues(LLVector3* extents, LLVector3& angle, F32& distance) const; + void getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& distance) const; void cacheImpostorValues(); void setImpostorDim(const LLVector2& dim); static void resetImpostors(); @@ -404,7 +444,6 @@ private: LLVector3 mImpostorOffset; LLVector2 mImpostorDim; BOOL mNeedsAnimUpdate; - LLVector3 mImpostorExtents[2]; LLVector3 mImpostorAngle; F32 mImpostorDistance; F32 mImpostorPixelArea; @@ -559,8 +598,8 @@ public: void setCompositeUpdatesEnabled(BOOL b); - void setNameFromChat(const std::string &text) { mNameFromChatOverride = mNameFromChatChanged = true; mNameFromChatText = text; } - void clearNameFromChat() { mNameFromChatOverride = false; mNameFromChatChanged = true; mNameFromChatText = ""; } + void setNameFromChat(const std::string &text); + void clearNameFromChat(); public: @@ -719,12 +758,18 @@ public: void clampAttachmentPositions(); BOOL attachObject(LLViewerObject *viewer_object); BOOL detachObject(LLViewerObject *viewer_object); +#if MESH_ENABLED + void cleanupAttachedMesh( LLViewerObject* pVO ); +#endif //MESH_ENABLED static LLVOAvatar* findAvatarFromAttachment( LLViewerObject* obj ); protected: // [RLVa:KB] - Checked: 2009-12-18 (RLVa-1.1.0i) | Added: RLVa-1.1.0i LLViewerJointAttachment* getTargetAttachmentPoint(const LLViewerObject* viewer_object) const; // [/RLVa:KB] void lazyAttach(); +#if MESH_ENABLED + void rebuildRiggedAttachments( void ); +#endif //MESH_ENABLED //-------------------------------------------------------------------- // Map of attachment points, by ID diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index 0346301ff..e56c78638 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -246,10 +246,14 @@ void LLVOClouds::getGeometry(S32 te, vtx[2] = puff_pos_agent + right + up; vtx[3] = puff_pos_agent + right - up; + *(verticesp->mV+3) = 0.f; *verticesp++ = vtx[0]; + *(verticesp->mV+3) = 0.f; *verticesp++ = vtx[1]; + *(verticesp->mV+3) = 0.f; *verticesp++ = vtx[2]; - *verticesp++ = vtx[3]; + *(verticesp->mV+3) = 0.f; + *verticesp++ = vtx[3];; *texcoordsp++ = uvs[0]; *texcoordsp++ = uvs[1]; diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index fa291580c..1d350d635 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -38,6 +38,7 @@ #include "llviewercontrol.h" #include "llagentcamera.h" +#include "llnotificationsutil.h" #include "llviewerwindow.h" #include "lldrawable.h" #include "llface.h" @@ -222,7 +223,7 @@ void LLVOGrass::initClass() { LLSD args; args["SPECIES"] = err; - LLNotifications::instance().add("ErrorUndefinedGrasses", args); + LLNotificationsUtil::add("ErrorUndefinedGrasses", args); } for (S32 i = 0; i < GRASS_MAX_BLADES; ++i) @@ -355,7 +356,7 @@ void LLVOGrass::updateTextures() { if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - setDebugText(llformat("%4.0f", fsqrtf(mPixelArea))); + setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea))); } getTEImage(0)->addTextureStats(mPixelArea); } @@ -706,23 +707,23 @@ BOOL LLVOGrass::lineSegmentIntersect(const LLVector3& start, const LLVector3& en U32 idx0 = 0,idx1 = 0,idx2 = 0; - if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, &a, &b, &t, FALSE)) + if (LLTriangleRayIntersect(v[0], v[1], v[2], start, dir, a, b, t, FALSE)) { hit = TRUE; idx0 = 0; idx1 = 1; idx2 = 2; } - else if (LLTriangleRayIntersect(v[1], v[3], v[2], start, dir, &a, &b, &t, FALSE)) + else if (LLTriangleRayIntersect(v[1], v[3], v[2], start, dir, a, b, t, FALSE)) { hit = TRUE; idx0 = 1; idx1 = 3; idx2 = 2; } - else if (LLTriangleRayIntersect(v[2], v[1], v[0], start, dir, &a, &b, &t, FALSE)) + else if (LLTriangleRayIntersect(v[2], v[1], v[0], start, dir, a, b, t, FALSE)) { normal1 = -normal1; hit = TRUE; idx0 = 2; idx1 = 1; idx2 = 0; } - else if (LLTriangleRayIntersect(v[2], v[3], v[1], start, dir, &a, &b, &t, FALSE)) + else if (LLTriangleRayIntersect(v[2], v[3], v[1], start, dir, a, b, t, FALSE)) { normal1 = -normal1; hit = TRUE; diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp index 7c3022f06..53b7177ce 100644 --- a/indra/newview/llvoiceclient.cpp +++ b/indra/newview/llvoiceclient.cpp @@ -62,6 +62,7 @@ #include "llfirstuse.h" #include "llviewerwindow.h" #include "llviewercamera.h" +#include "llnotificationsutil.h" #include "llfloaterfriends.h" //VIVOX, inorder to refresh communicate panel #include "llfloaterchat.h" // for LLFloaterChat::addChat() @@ -1120,6 +1121,7 @@ LLVoiceClient::LLVoiceClient() mSpeakerVolume = 0; mMicVolume = 0; + mNextAudioSession = NULL; mAudioSession = NULL; mAudioSessionChanged = false; @@ -7039,7 +7041,7 @@ class LLViewerRequiredVoiceVersion : public LLHTTPNode if (!sAlertedUser) { //sAlertedUser = TRUE; - LLNotifications::instance().add("VoiceVersionMismatch"); + LLNotificationsUtil::add("VoiceVersionMismatch"); gSavedSettings.setBOOL("EnableVoiceChat", FALSE); // toggles listener } } diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index d850ced0d..5391d5841 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -79,12 +79,14 @@ F32 LLVOPartGroup::getBinRadius() return mScale.mV[0]*2.f; } -void LLVOPartGroup::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) +void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { const LLVector3& pos_agent = getPositionAgent(); - newMin = pos_agent - mScale; - newMax = pos_agent + mScale; - mDrawable->setPositionGroup(pos_agent); + newMin.load3( (pos_agent - mScale).mV); + newMax.load3( (pos_agent + mScale).mV); + LLVector4a pos; + pos.load3(pos_agent.mV); + mDrawable->setPositionGroup(pos); } BOOL LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) @@ -321,10 +323,18 @@ void LLVOPartGroup::getGeometry(S32 idx, LLVector3 normal = -LLViewerCamera::getInstance()->getXAxis(); - + + //HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) + // this works because there is actually a 4th float stored after the vertex position which is used as a texture index + // also, somebody please VECTORIZE THIS + + *(verticesp->mV+3) = 0.f; *verticesp++ = part_pos_agent + up - right; + *(verticesp->mV+3) = 0.f; *verticesp++ = part_pos_agent - up - right; + *(verticesp->mV+3) = 0.f; *verticesp++ = part_pos_agent + up + right; + *(verticesp->mV+3) = 0.f; *verticesp++ = part_pos_agent - up + right; *colorsp++ = part.mColor; @@ -357,7 +367,7 @@ U32 LLVOPartGroup::getPartitionType() const } LLParticlePartition::LLParticlePartition() -: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB) { mRenderPass = LLRenderPass::PASS_ALPHA; mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES; @@ -415,6 +425,7 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co mFaceList.push_back(facep); vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); + llassert(facep->getIndicesCount() < 65536); } obj->mDepth /= count; diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index 18583b4be..771ae1c1e 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -57,7 +57,7 @@ public: BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); virtual F32 getBinRadius(); - virtual void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); + virtual void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); virtual U32 getPartitionType() const; /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index b143b6bea..b259c0acd 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -377,7 +377,7 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) mAtmHeight = ATM_HEIGHT; mEarthCenter = LLVector3(mCameraPosAgent.mV[0], mCameraPosAgent.mV[1], -EARTH_RADIUS); - mSunDefaultPosition = LLVector3(LLWLParamManager::instance()->mCurParams.getVector("lightnorm", error)); + mSunDefaultPosition = LLVector3(LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error)); if (gSavedSettings.getBOOL("SkyOverrideSimSunPosition")) { initSunDirection(mSunDefaultPosition, LLVector3(0, 0, 0)); @@ -654,24 +654,24 @@ void LLVOSky::initAtmospherics(void) bool error; // uniform parameters for convenience - dome_radius = LLWLParamManager::instance()->getDomeRadius(); - dome_offset_ratio = LLWLParamManager::instance()->getDomeOffset(); - sunlight_color = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("sunlight_color", error)); - ambient = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("ambient", error)); - //lightnorm = LLWLParamManager::instance()->mCurParams.getVector("lightnorm", error); - gamma = LLWLParamManager::instance()->mCurParams.getVector("gamma", error)[0]; - blue_density = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("blue_density", error)); - blue_horizon = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("blue_horizon", error)); - haze_density = LLWLParamManager::instance()->mCurParams.getVector("haze_density", error)[0]; - haze_horizon = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("haze_horizon", error)); - density_multiplier = LLWLParamManager::instance()->mCurParams.getVector("density_multiplier", error)[0]; - max_y = LLWLParamManager::instance()->mCurParams.getVector("max_y", error)[0]; - glow = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("glow", error)); - cloud_shadow = LLWLParamManager::instance()->mCurParams.getVector("cloud_shadow", error)[0]; - cloud_color = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_color", error)); - cloud_scale = LLWLParamManager::instance()->mCurParams.getVector("cloud_scale", error)[0]; - cloud_pos_density1 = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_pos_density1", error)); - cloud_pos_density2 = LLColor3(LLWLParamManager::instance()->mCurParams.getVector("cloud_pos_density2", error)); + dome_radius = LLWLParamManager::getInstance()->getDomeRadius(); + dome_offset_ratio = LLWLParamManager::getInstance()->getDomeOffset(); + sunlight_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("sunlight_color", error)); + ambient = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("ambient", error)); + //lightnorm = LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error); + gamma = LLWLParamManager::getInstance()->mCurParams.getVector("gamma", error)[0]; + blue_density = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_density", error)); + blue_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_horizon", error)); + haze_density = LLWLParamManager::getInstance()->mCurParams.getVector("haze_density", error)[0]; + haze_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("haze_horizon", error)); + density_multiplier = LLWLParamManager::getInstance()->mCurParams.getVector("density_multiplier", error)[0]; + max_y = LLWLParamManager::getInstance()->mCurParams.getVector("max_y", error)[0]; + glow = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("glow", error)); + cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_shadow", error)[0]; + cloud_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_color", error)); + cloud_scale = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_scale", error)[0]; + cloud_pos_density1 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density1", error)); + cloud_pos_density2 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density2", error)); // light norm is different. We need the sun's direction, not the light direction // which could be from the moon. And we need to clamp it @@ -763,6 +763,11 @@ void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLCo // project the direction ray onto the sky dome. F32 phi = acos(Pn[1]); F32 sinA = sin(F_PI - phi); + if (fabsf(sinA) < 0.01f) + { //avoid division by zero + sinA = 0.01f; + } + F32 Plen = dome_radius * sin(F_PI + phi + asin(dome_offset_ratio * sinA)) / sinA; Pn *= Plen; @@ -1042,7 +1047,7 @@ void LLVOSky::calcAtmospherics(void) // between sunlight and point lights in windlight to normalize point lights. static const LLCachedControl<F32> render_sun_dynamic_range("RenderSunDynamicRange", 1.f); F32 sun_dynamic_range = llmax((float)render_sun_dynamic_range, 0.0001f); - LLWLParamManager::instance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp); + LLWLParamManager::getInstance()->mSceneLightStrength = 2.0f * (1.0f + sun_dynamic_range * dp); mSunDiffuse = vary_SunlightColor; mSunAmbient = vary_AmbientColor; @@ -1489,6 +1494,7 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons facep->setVertexBuffer(buff); } + llassert(facep->getVertexBuffer()->getNumIndices() == 6); index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); if (-1 == index_offset) @@ -2133,7 +2139,7 @@ void LLVOSky::updateFog(const F32 distance) F32 depth = water_height - camera_height; // get the water param manager variables - float water_fog_density = LLWaterParamManager::instance()->getFogDensity(); + float water_fog_density = LLWaterParamManager::getInstance()->getFogDensity(); LLColor4 water_fog_color = LLDrawPoolWater::sWaterFogColor.mV; // adjust the color based on depth. We're doing linear approximations diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index 70ffbd794..e4af0224f 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -60,27 +60,77 @@ public: LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD0 | MAP_TEXCOORD1 | MAP_COLOR, GL_DYNAMIC_DRAW_ARB) { //texture coordinates 2 and 3 exist, but use the same data as texture coordinate 1 - mOffsets[TYPE_TEXCOORD3] = mOffsets[TYPE_TEXCOORD2] = mOffsets[TYPE_TEXCOORD1]; - mTypeMask |= MAP_TEXCOORD2 | MAP_TEXCOORD3; }; - /*// virtual + // virtual void setupVertexBuffer(U32 data_mask) const - { - if (LLDrawPoolTerrain::getDetailMode() == 0 || LLPipeline::sShadowRender) + { + volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData; + + //assume tex coords 2 and 3 are present + U32 type_mask = mTypeMask | MAP_TEXCOORD2 | MAP_TEXCOORD3; + + if ((data_mask & type_mask) != data_mask) { - LLVertexBuffer::setupVertexBuffer(data_mask); + llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; } - else if (data_mask & LLVertexBuffer::MAP_TEXCOORD1) + + if (data_mask & MAP_NORMAL) { - LLVertexBuffer::setupVertexBuffer(data_mask); + glNormalPointer(GL_FLOAT, getStride(TYPE_NORMAL), (void*)(base + mOffsets[TYPE_NORMAL])); } - else + if (data_mask & MAP_TEXCOORD3) + { //substitute tex coord 0 for tex coord 3 + glClientActiveTextureARB(GL_TEXTURE3_ARB); + glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD0), (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + if (data_mask & MAP_TEXCOORD2) + { //substitute tex coord 0 for tex coord 2 + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD0), (void*)(base + mOffsets[TYPE_TEXCOORD0])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + if (data_mask & MAP_TEXCOORD1) { - LLVertexBuffer::setupVertexBuffer(data_mask); + glClientActiveTextureARB(GL_TEXTURE1_ARB); + glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD1), (void*)(base + mOffsets[TYPE_TEXCOORD1])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); } - llglassertok(); - }*/ + if (data_mask & MAP_BINORMAL) + { + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glTexCoordPointer(3,GL_FLOAT, getStride(TYPE_BINORMAL), (void*)(base + mOffsets[TYPE_BINORMAL])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + } + if (data_mask & MAP_TEXCOORD0) + { + glTexCoordPointer(2,GL_FLOAT, getStride(TYPE_TEXCOORD0), (void*)(base + mOffsets[TYPE_TEXCOORD0])); + } + if (data_mask & MAP_COLOR) + { + glColorPointer(4, GL_UNSIGNED_BYTE, getStride(TYPE_COLOR), (void*)(base + mOffsets[TYPE_COLOR])); + } + + if (data_mask & MAP_WEIGHT) + { + glVertexAttribPointerARB(1, 1, GL_FLOAT, FALSE, getStride(TYPE_WEIGHT), (void*)(base + mOffsets[TYPE_WEIGHT])); + } + + if (data_mask & MAP_WEIGHT4 && sWeight4Loc != -1) + { + glVertexAttribPointerARB(sWeight4Loc, 4, GL_FLOAT, FALSE, getStride(TYPE_WEIGHT4), (void*)(base+mOffsets[TYPE_WEIGHT4])); + } + + if (data_mask & MAP_CLOTHWEIGHT) + { + glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, getStride(TYPE_CLOTHWEIGHT), (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + } + if (data_mask & MAP_VERTEX) + { + glVertexPointer(3,GL_FLOAT, getStride(TYPE_VERTEX), (void*)(base + 0)); + } + } }; //============================================================================ @@ -330,6 +380,8 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, S32 num_vertices, num_indices; U32 index; + llassert(mLastStride > 0); + render_stride = mLastStride; patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); S32 vert_size = patch_size / render_stride; @@ -944,7 +996,13 @@ BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector3& start, const LLVect //step one meter at a time until intersection point found - const LLVector3* ext = mDrawable->getSpatialExtents(); + //VECTORIZE THIS + const LLVector4a* exta = mDrawable->getSpatialExtents(); + + LLVector3 ext[2]; + ext[0].set(exta[0].getF32ptr()); + ext[1].set(exta[1].getF32ptr()); + F32 rad = (delta*tdelta).magVecSquared(); F32 t = 0.f; @@ -1006,13 +1064,16 @@ BOOL LLVOSurfacePatch::lineSegmentIntersect(const LLVector3& start, const LLVect return FALSE; } -void LLVOSurfacePatch::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax) +void LLVOSurfacePatch::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) { LLVector3 posAgent = getPositionAgent(); LLVector3 scale = getScale(); - newMin = posAgent-scale*0.5f; // Changing to 2.f makes the culling a -little- better, but still wrong - newMax = posAgent+scale*0.5f; - mDrawable->setPositionGroup((newMin+newMax)*0.5f); + newMin.load3( (posAgent-scale*0.5f).mV); // Changing to 2.f makes the culling a -little- better, but still wrong + newMax.load3( (posAgent+scale*0.5f).mV); + LLVector4a pos; + pos.setAdd(newMin,newMax); + pos.mul(0.5f); + mDrawable->setPositionGroup(pos); } U32 LLVOSurfacePatch::getPartitionType() const diff --git a/indra/newview/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index 10a588852..15442e194 100644 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -78,7 +78,7 @@ public: /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area - /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); + /*virtual*/ void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. void setPatch(LLSurfacePatch *patchp); diff --git a/indra/newview/llvotextbubble.cpp b/indra/newview/llvotextbubble.cpp index f35f3d533..df3677539 100644 --- a/indra/newview/llvotextbubble.cpp +++ b/indra/newview/llvotextbubble.cpp @@ -46,6 +46,7 @@ #include "llviewertexturelist.h" #include "llvolume.h" #include "pipeline.h" +#include "llvector4a.h" #include "llviewerregion.h" LLVOTextBubble::LLVOTextBubble(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) @@ -215,7 +216,7 @@ void LLVOTextBubble::updateFaceSize(S32 idx) else { const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - face->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); + face->setSize(vol_face.mNumVertices, vol_face.mNumIndices); } } @@ -233,19 +234,29 @@ void LLVOTextBubble::getGeometry(S32 idx, const LLVolumeFace& face = getVolume()->getVolumeFace(idx); - LLVector3 pos = getPositionAgent(); + LLVector4a pos; + pos.load3(getPositionAgent().mV); + + LLVector4a scale; + scale.load3(getScale().mV); + LLColor4U color = LLColor4U(getTE(idx)->getColor()); U32 offset = mDrawable->getFace(idx)->getGeomIndex(); - for (U32 i = 0; i < face.mVertices.size(); i++) + normalsp.assignArray((U8*)face.mNormals, sizeof(face.mNormals[0]), face.mNumVertices); + texcoordsp.assignArray((U8*)face.mTexCoords, sizeof(face.mTexCoords[0]), face.mNumVertices); + + + for (U32 i = 0; i < (U32)face.mNumVertices; i++) { - *verticesp++ = face.mVertices[i].mPosition.scaledVec(getScale()) + pos; - *normalsp++ = face.mVertices[i].mNormal; - *texcoordsp++ = face.mVertices[i].mTexCoord; + LLVector4a t; + t.setMul(face.mPositions[i],scale); + t.add(pos); + (verticesp++)->set(t.getF32ptr()); *colorsp++ = color; } - for (U32 i = 0; i < face.mIndices.size(); i++) + for (U32 i = 0; i < (U32)face.mNumIndices; i++) { *indicesp++ = face.mIndices[i] + offset; } diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 548dab8b0..08dbc4df5 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -57,6 +57,7 @@ #include "noise.h" #include "pipeline.h" #include "llspatialpartition.h" +#include "llnotificationsutil.h" #include "llviewerwindow.h" extern LLPipeline gPipeline; @@ -267,7 +268,7 @@ void LLVOTree::initClass() { LLSD args; args["SPECIES"] = err; - LLNotifications::instance().add("ErrorUndefinedTrees", args); + LLNotificationsUtil::add("ErrorUndefinedTrees", args); } }; @@ -496,7 +497,7 @@ void LLVOTree::updateTextures() { if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - setDebugText(llformat("%4.0f", fsqrtf(mPixelArea))); + setDebugText(llformat("%4.0f", (F32) sqrt(mPixelArea))); } mTreeImagep->addTextureStats(mPixelArea); } @@ -1274,7 +1275,7 @@ void LLVOTree::updateRadius() mDrawable->setRadius(32.0f); } -void LLVOTree::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) +void LLVOTree::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { F32 radius = getScale().length()*0.05f; LLVector3 center = getRenderPosition(); @@ -1284,9 +1285,11 @@ void LLVOTree::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) center += LLVector3(0, 0, size.mV[2]) * getRotation(); - newMin.set(center-size); - newMax.set(center+size); - mDrawable->setPositionGroup(center); + newMin.load3((center-size).mV); + newMax.load3((center+size).mV); + LLVector4a pos; + pos.load3(center.mV); + mDrawable->setPositionGroup(pos); } BOOL LLVOTree::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face, BOOL pick_transparent, S32 *face_hitp, @@ -1299,8 +1302,13 @@ BOOL LLVOTree::lineSegmentIntersect(const LLVector3& start, const LLVector3& end return FALSE; } - const LLVector3* ext = mDrawable->getSpatialExtents(); + const LLVector4a* exta = mDrawable->getSpatialExtents(); + //VECTORIZE THIS + LLVector3 ext[2]; + ext[0].set(exta[0].getF32ptr()); + ext[1].set(exta[1].getF32ptr()); + LLVector3 center = (ext[1]+ext[0])*0.5f; LLVector3 size = (ext[1]-ext[0]); diff --git a/indra/newview/llvotree.h b/indra/newview/llvotree.h index 89c15b587..7e961471f 100644 --- a/indra/newview/llvotree.h +++ b/indra/newview/llvotree.h @@ -74,7 +74,7 @@ public: /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - /*virtual*/ void updateSpatialExtents(LLVector3 &min, LLVector3 &max); + /*virtual*/ void updateSpatialExtents(LLVector4a &min, LLVector4a &max); virtual U32 getPartitionType() const; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bad1cfe1d..7115f16b1 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -42,12 +42,13 @@ #include "llmaterialtable.h" #include "llprimitive.h" #include "llvolume.h" +#include "llvolumeoctree.h" #include "llvolumemgr.h" #include "llvolumemessage.h" #include "material_codes.h" #include "message.h" #include "object_flags.h" -#include "llagent.h" +#include "llagentconstants.h" #include "lldrawable.h" #include "lldrawpoolbump.h" #include "llface.h" @@ -56,13 +57,26 @@ #include "llflexibleobject.h" #include "llsky.h" #include "lltexturefetch.h" +#include "llvector4a.h" #include "llviewercamera.h" #include "llviewertexturelist.h" +#include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llviewertextureanim.h" #include "llworld.h" #include "llselectmgr.h" #include "pipeline.h" +#include "llsdutil.h" +#include "llmatrix4a.h" +#include "llagent.h" +#if MESH_ENABLED +#include "lldrawpoolavatar.h" +#include "llmeshrepository.h" +#include "lldatapacker.h" +#include "llviewershadermgr.h" +#include "llvoavatar.h" +#include "llfloatertools.h" +#endif //MESH_ENABLED #include "llvocache.h" // [RLVa:KB] - Checked: 2010-04-04 (RLVa-1.2.0d) @@ -80,6 +94,8 @@ F32 LLVOVolume::sLODFactor = 1.f; F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; +S32 LLVOVolume::mRenderComplexity_last = 0; +S32 LLVOVolume::mRenderComplexity_current = 0; LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) : LLViewerObject(id, pcode, regionp), @@ -476,21 +492,29 @@ BOOL LLVOVolume::isVisible() const return FALSE ; } -void LLVOVolume::updateTextureVirtualSize() + +void LLVOVolume::updateTextureVirtualSize(bool forced) { // Update the pixel area of all faces - if(!isVisible() || mDrawable.isNull()) - { + if(mDrawable.isNull()) return; + if(!forced) + { + if(!isVisible()) + { + return; + } + + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) + { + return; + } } - if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) - { - return; - } - - if (LLViewerTexture::sDontLoadVolumeTextures || LLAppViewer::getTextureFetch()->mDebugPause) + static LLCachedControl<bool> dont_load_textures(gSavedSettings,"TextureDisable"); + + if (dont_load_textures || LLAppViewer::getTextureFetch()->mDebugPause) // || !mDrawable->isVisible()) { return; } @@ -509,7 +533,7 @@ void LLVOVolume::updateTextureVirtualSize() const LLTextureEntry *te = face->getTextureEntry(); LLViewerTexture *imagep = face->getTexture(); if (!imagep || !te || - face->mExtents[0] == face->mExtents[1]) + face->mExtents[0].equals3(face->mExtents[1])) { continue; } @@ -530,24 +554,29 @@ void LLVOVolume::updateTextureVirtualSize() vsize = face->getTextureVirtualSize(); if (isAttachment()) { - // Rez attachments faster and at full details ! if (permYouOwner()) { - // Our attachments must really rez fast and fully: - // we shouldn't have to zoom on them to get the textures - // fully loaded ! - imagep->setBoostLevel(LLViewerTexture::BOOST_HUD); - imagep->dontDiscard(); + imagep->setBoostLevel(LLViewerTexture::BOOST_HIGH); } } } mPixelArea = llmax(mPixelArea, face->getPixelArea()); - + if (face->mTextureMatrix != NULL) { + // Animating textures also rez badly in Snowglobe because the + // actual displayed area is only a fraction (corresponding to one + // frame) of the animating texture. Let's fix that here: + /* if (mTextureAnimp && mTextureAnimp->mScaleS > 0.0f && mTextureAnimp->mScaleT > 0.0f) + { + // Adjust to take into account the actual frame size which is only a + // portion of the animating texture + vsize = vsize / mTextureAnimp->mScaleS / mTextureAnimp->mScaleT; + }*/ + if ((vsize < MIN_TEX_ANIM_SIZE && old_size > MIN_TEX_ANIM_SIZE) || - (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) + (vsize > MIN_TEX_ANIM_SIZE && old_size < MIN_TEX_ANIM_SIZE)) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, FALSE); } @@ -558,13 +587,17 @@ void LLVOVolume::updateTextureVirtualSize() if (vsize < min_vsize) min_vsize = vsize; if (vsize > max_vsize) max_vsize = vsize; } -// else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) -// { -// F32 pri = imagep->getDecodePriority(); -// pri = llmax(pri, 0.0f); -// if (pri < min_vsize) min_vsize = pri; -// if (pri > max_vsize) max_vsize = pri; -// } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + LLViewerFetchedTexture* img = LLViewerTextureManager::staticCastToFetchedTexture(imagep) ; + if(img) + { + F32 pri = img->getDecodePriority(); + pri = llmax(pri, 0.0f); + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } + } else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) { F32 pri = mPixelArea; @@ -635,15 +668,15 @@ void LLVOVolume::updateTextureVirtualSize() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); } -// else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) -// { -// setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); -// } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); + } else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) { - setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); + setDebugText(llformat("%.0f:%.0f", (F32) sqrt(min_vsize),(F32) sqrt(max_vsize))); } if (mPixelArea == 0) @@ -729,8 +762,31 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) return mDrawable; } -BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume) +BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bool unique_volume) { + LLVolumeParams volume_params = params_in; + S32 lod = mLOD; +#if MESH_ENABLED + S32 last_lod = mVolumep.notNull() ? LLVolumeLODGroup::getVolumeDetailFromScale(mVolumep->getDetail()) : -1; + + BOOL is404 = FALSE; + + if (isSculpted()) + { + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + { //meshes might not have all LODs, get the force detail to best existing LOD + LLUUID mesh_id = volume_params.getSculptID(); + + lod = gMeshRepo.getActualMeshLOD(volume_params, lod); + if (lod == -1) + { + is404 = TRUE; + lod = 0; + } + } + } +#endif //MESH_ENABLED // Check if we need to change implementations bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE); if (is_flexible) @@ -758,13 +814,21 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail } } - if ((LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) +#if MESH_ENABLED + if (is404) + { + setIcon(LLViewerTextureManager::getFetchedTextureFromFile("icons/Inv_Mesh.png", TRUE, LLViewerTexture::BOOST_UI)); + //render prim proxy when mesh loading attempts give up + volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); + } +#endif //MESH_ENABLED + if ((LLPrimitive::setVolume(volume_params, lod, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) || mSculptChanged) { mFaceMappingChanged = TRUE; if (mVolumeImpl) { - mVolumeImpl->onSetVolume(volume_params, detail); + mVolumeImpl->onSetVolume(volume_params, mLOD); //detail ? } updateSculptTexture(); @@ -772,10 +836,31 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail if (isSculpted()) { updateSculptTexture(); - - if (mSculptTexture.notNull()) +#if MESH_ENABLED + // if it's a mesh + if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) { - sculpt(); + 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) + { + LLPrimitive::setVolume(volume_params, available_lod); + } + } + + } + else // otherwise is sculptie +#endif //MESH_ENABLED + + + { + if (mSculptTexture.notNull()) + { + sculpt(); + } } } @@ -788,7 +873,11 @@ void LLVOVolume::updateSculptTexture() { LLPointer<LLViewerFetchedTexture> old_sculpt = mSculptTexture; - if (isSculpted()) + if (isSculpted() +#if MESH_ENABLED + && !isMesh() +#endif //MESH_ENABLED + ) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); LLUUID id = sculpt_params->getSculptTexture(); @@ -813,8 +902,17 @@ void LLVOVolume::updateSculptTexture() mSculptTexture->addVolume(this); } } + } +#if MESH_ENABLED +void LLVOVolume::notifyMeshLoaded() +{ + mSculptChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); +} +#endif //MESH_ENABLED + // sculpt replaces generate() for sculpted surfaces void LLVOVolume::sculpt() { @@ -906,8 +1004,24 @@ BOOL LLVOVolume::calcLOD() S32 cur_detail = 0; - F32 radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length(); - F32 distance = mDrawable->mDistanceWRTCamera; + F32 radius; + F32 distance; + +#if MESH_ENABLED + if (mDrawable->isState(LLDrawable::RIGGED) && getAvatar()) + { + LLVOAvatar* avatar = getAvatar(); + distance = avatar->mDrawable->mDistanceWRTCamera; + radius = avatar->getBinRadius(); + } + else +#endif //MESH_ENABLED + { + distance = mDrawable->mDistanceWRTCamera; + radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length(); + } + + distance *= sDistanceFactor; F32 rampDist = LLVOVolume::sLODFactor * 2; @@ -1066,18 +1180,35 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) { BOOL res = TRUE; - LLVector3 min,max; + LLVector4a min,max; - BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION); + min.clear(); + max.clear(); - for (S32 i = 0; i < getVolume()->getNumFaces(); i++) + BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION +#if MESH_ENABLED + | LLDrawable::REBUILD_RIGGED +#endif //MESH_ENABLED + ); + +#if MESH_ENABLED + LLVolume* volume = mRiggedVolume; + if (!volume) + { + volume = getVolume(); + } +#endif //MESH_ENABLED +#if !MESH_ENABLED + LLVolume* volume = getVolume(); +#endif //!MESH_ENABLED + for (S32 i = 0; i < getVolume()->getNumVolumeFaces(); i++) { LLFace *face = mDrawable->getFace(i); if (!face) { continue; } - res &= face->genVolumeBBoxes(*getVolume(), i, + res &= face->genVolumeBBoxes(*volume, i, mRelativeXform, mRelativeXformInvTrans, (mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global); @@ -1090,17 +1221,8 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) } else { - for (U32 i = 0; i < 3; i++) - { - if (face->mExtents[0].mV[i] < min.mV[i]) - { - min.mV[i] = face->mExtents[0].mV[i]; - } - if (face->mExtents[1].mV[i] > max.mV[i]) - { - max.mV[i] = face->mExtents[1].mV[i]; - } - } + min.setMin(min, face->mExtents[0]); + max.setMax(max, face->mExtents[1]); } } } @@ -1108,7 +1230,9 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global) if (rebuild) { mDrawable->setSpatialExtents(min,max); - mDrawable->setPositionGroup((min+max)*0.5f); + min.add(max); + min.mul(0.5f); + mDrawable->setPositionGroup(min); } updateRadius(); @@ -1134,8 +1258,27 @@ void LLVOVolume::updateRelativeXform() } LLDrawable* drawable = mDrawable; - + +#if MESH_ENABLED + if (drawable->isState(LLDrawable::RIGGED) && mRiggedVolume.notNull()) + { //rigged volume (which is in agent space) is used for generating bounding boxes etc + //inverse of render matrix should go to partition space + mRelativeXform = getRenderMatrix(); + + F32* dst = (F32*) mRelativeXformInvTrans.mMatrix; + F32* src = (F32*) mRelativeXform.mMatrix; + dst[0] = src[0]; dst[1] = src[1]; dst[2] = src[2]; + dst[3] = src[4]; dst[4] = src[5]; dst[5] = src[6]; + dst[6] = src[8]; dst[7] = src[9]; dst[8] = src[10]; + + mRelativeXform.invert(); + mRelativeXformInvTrans.transpose(); + } + else if (drawable->isActive()) +#endif //MESH_ENABLED +#if !MESH_ENABLED if (drawable->isActive()) +#endif //!MESH_ENABLED { // setup relative transforms LLQuaternion delta_rot; @@ -1219,6 +1362,17 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES); +#if MESH_ENABLED + if (mDrawable->isState(LLDrawable::REBUILD_RIGGED)) + { + { + LLFastTimer t2(LLFastTimer::FTM_UPDATE_RIGGED_VOLUME); + updateRiggedVolume(); + } + genBBoxes(FALSE); + mDrawable->clearState(LLDrawable::REBUILD_RIGGED); + } +#endif //MESH_ENABLED if (mVolumeImpl != NULL) { BOOL res; @@ -1286,11 +1440,16 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) compiled = TRUE; sNumLODChanges += new_num_faces ; + if((S32)getNumTEs() != getVolume()->getNumFaces()) + { + setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. + } + drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() { LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); - if (new_num_faces != old_num_faces) + if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs()) { regenFaces(); } @@ -1339,12 +1498,14 @@ void LLVOVolume::updateFaceSize(S32 idx) LLFace* facep = mDrawable->getFace(idx); if (idx >= getVolume()->getNumVolumeFaces()) { - facep->setSize(0,0); + facep->setSize(0,0, true); } else { const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); - facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); + facep->setSize(vol_face.mNumVertices, vol_face.mNumIndices, + true); // <--- volume faces should be padded for 16-byte alignment + } } @@ -1882,6 +2043,25 @@ BOOL LLVOVolume::isSculpted() const return FALSE; } +#if MESH_ENABLED +BOOL LLVOVolume::isMesh() const +{ + + if (isSculpted()) + { + LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); + U8 sculpt_type = sculpt_params->getSculptType(); + + if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + // mesh is a mesh + { + return TRUE; + } + } + + return FALSE; +} +#endif //MESH_ENABLED BOOL LLVOVolume::hasLightTexture() const { if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE)) @@ -1898,6 +2078,12 @@ BOOL LLVOVolume::isVolumeGlobal() const { return mVolumeImpl->isVolumeGlobal() ? TRUE : FALSE; } +#if MESH_ENABLED + else if (mRiggedVolume.notNull()) + { + return TRUE; + } +#endif //MESH_ENABLED return FALSE; } @@ -1982,7 +2168,7 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p trans_mat.translate(getRegion()->getOriginAgent()); } - volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); + volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, view_vector, trans_mat, mRelativeXformInvTrans, nodep->getTESelectMask()); nodep->mSilhouetteExists = TRUE; } @@ -2035,6 +2221,346 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const return mDrawable->getWorldMatrix(); } +// Returns a base cost and adds textures to passed in set. +// total cost is returned value + 5 * size of the resulting set. +// Cannot include cost of textures, as they may be re-used in linked +// children, and cost should only be increased for unique textures -Nyx +U32 LLVOVolume::getRenderCost(texture_cost_t &textures) const +{ + // Get access to params we'll need at various points. + // Skip if this is object doesn't have a volume (e.g. is an avatar). + BOOL has_volume = (getVolume() != NULL); + LLVolumeParams volume_params; + LLPathParams path_params; + LLProfileParams profile_params; + + U32 num_triangles = 0; + + // per-prim costs + static const U32 ARC_PARTICLE_COST = 1; // determined experimentally + static const U32 ARC_PARTICLE_MAX = 2048; // default values + static const U32 ARC_TEXTURE_COST = 16; // multiplier for texture resolution - performance tested + static const U32 ARC_LIGHT_COST = 500; // static cost for light-producing prims + static const U32 ARC_MEDIA_FACE_COST = 1500; // static cost per media-enabled face + + + // per-prim multipliers + static const F32 ARC_GLOW_MULT = 1.5f; // tested based on performance + static const F32 ARC_BUMP_MULT = 1.25f; // tested based on performance + static const F32 ARC_FLEXI_MULT = 5; // tested based on performance + static const F32 ARC_SHINY_MULT = 1.6f; // tested based on performance + static const F32 ARC_INVISI_COST = 1.2f; // tested based on performance + static const F32 ARC_WEIGHTED_MESH = 1.2f; // tested based on performance + + static const F32 ARC_PLANAR_COST = 1.0f; // tested based on performance to have negligible impact + static const F32 ARC_ANIM_TEX_COST = 4.f; // tested based on performance + static const F32 ARC_ALPHA_COST = 4.f; // 4x max - based on performance + + F32 shame = 0; + + U32 invisi = 0; + U32 shiny = 0; + U32 glow = 0; + U32 alpha = 0; + U32 flexi = 0; + U32 animtex = 0; + U32 particles = 0; + U32 bump = 0; + U32 planar = 0; + U32 weighted_mesh = 0; + U32 produces_light = 0; + U32 media_faces = 0; + + const LLDrawable* drawablep = mDrawable; + U32 num_faces = drawablep->getNumFaces(); + + if (has_volume) + { + volume_params = getVolume()->getParams(); + path_params = volume_params.getPathParams(); + profile_params = volume_params.getProfileParams(); + + F32 weighted_triangles = -1.0; + getStreamingCost(NULL, NULL, &weighted_triangles); + + if (weighted_triangles > 0.0) + { + num_triangles = (U32)(weighted_triangles); + } + } + + if (num_triangles == 0) + { + num_triangles = 4; + } + + if (isSculpted()) + { + if (isMesh()) + { + // base cost is dependent on mesh complexity + // note that 3 is the highest LOD as of the time of this coding. + S32 size = gMeshRepo.getMeshSize(volume_params.getSculptID(),3); + if ( size > 0) + { + if (gMeshRepo.getSkinInfo(volume_params.getSculptID(), this)) + { + // weighted attachment - 1 point for every 3 bytes + weighted_mesh = 1; + } + + } + else + { + // something went wrong - user should know their content isn't render-free + return 0; + } + } + else + { + const LLSculptParams *sculpt_params = (LLSculptParams *) getParameterEntry(LLNetworkData::PARAMS_SCULPT); + LLUUID sculpt_id = sculpt_params->getSculptTexture(); + if (textures.find(sculpt_id) == textures.end()) + { + LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(sculpt_id); + if (texture) + { + S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (texture->getFullHeight() / 128.f + texture->getFullWidth() / 128.f)); + textures.insert(texture_cost_t::value_type(sculpt_id, texture_cost)); + } + } + } + } + + if (isFlexible()) + { + flexi = 1; + } + if (isParticleSource()) + { + particles = 1; + } + + if (getIsLight()) + { + produces_light = 1; + } + + for (U32 i = 0; i < num_faces; ++i) + { + const LLFace* face = drawablep->getFace(i); + const LLTextureEntry* te = face->getTextureEntry(); + const LLViewerTexture* img = face->getTexture(); + + if (img) + { + if (textures.find(img->getID()) == textures.end()) + { + S32 texture_cost = 256 + (S32)(ARC_TEXTURE_COST * (img->getFullHeight() / 128.f + img->getFullWidth() / 128.f)); + textures.insert(texture_cost_t::value_type(img->getID(), texture_cost)); + } + } + + if (face->getPoolType() == LLDrawPool::POOL_ALPHA) + { + alpha = 1; + } + else if (img && img->getPrimaryFormat() == GL_ALPHA) + { + invisi = 1; + } + /*if (face->hasMedia()) + { + media_faces++; + }*/ + + if (te) + { + if (te->getBumpmap()) + { + // bump is a multiplier, don't add per-face + bump = 1; + } + if (te->getShiny()) + { + // shiny is a multiplier, don't add per-face + shiny = 1; + } + if (te->getGlow() > 0.f) + { + // glow is a multiplier, don't add per-face + glow = 1; + } + if (face->mTextureMatrix != NULL) + { + animtex = 1; + } + if (te->getTexGen()) + { + planar = 1; + } + } + } + + // shame currently has the "base" cost of 1 point per 15 triangles, min 2. + shame = num_triangles * 5.f; + shame = shame < 2.f ? 2.f : shame; + + // multiply by per-face modifiers + if (planar) + { + shame *= planar * ARC_PLANAR_COST; + } + + if (animtex) + { + shame *= animtex * ARC_ANIM_TEX_COST; + } + + if (alpha) + { + shame *= alpha * ARC_ALPHA_COST; + } + + if(invisi) + { + shame *= invisi * ARC_INVISI_COST; + } + + if (glow) + { + shame *= glow * ARC_GLOW_MULT; + } + + if (bump) + { + shame *= bump * ARC_BUMP_MULT; + } + + if (shiny) + { + shame *= shiny * ARC_SHINY_MULT; + } + + + // multiply shame by multipliers + if (weighted_mesh) + { + shame *= weighted_mesh * ARC_WEIGHTED_MESH; + } + + if (flexi) + { + shame *= flexi * ARC_FLEXI_MULT; + } + + + // add additional costs + if (particles) + { + const LLPartSysData *part_sys_data = &(mPartSourcep->mPartSysData); + const LLPartData *part_data = &(part_sys_data->mPartData); + U32 num_particles = (U32)(part_sys_data->mBurstPartCount * llceil( part_data->mMaxAge / part_sys_data->mBurstRate)); + num_particles = num_particles > ARC_PARTICLE_MAX ? ARC_PARTICLE_MAX : num_particles; + F32 part_size = (llmax(part_data->mStartScale[0], part_data->mEndScale[0]) + llmax(part_data->mStartScale[1], part_data->mEndScale[1])) / 2.f; + shame += num_particles * part_size * ARC_PARTICLE_COST; + } + + if (produces_light) + { + shame += ARC_LIGHT_COST; + } + + if (media_faces) + { + shame += media_faces * ARC_MEDIA_FACE_COST; + } + + if (shame > mRenderComplexity_current) + { + mRenderComplexity_current = (S32)shame; + } + + return (U32)shame; +} +#if MESH_ENABLED +F32 LLVOVolume::getStreamingCost(S32* bytes, S32* visible_bytes, F32* unscaled_value) const +{ + F32 radius = getScale().length()*0.5f; + + if (isMesh()) + { + LLSD& header = gMeshRepo.getMeshHeader(getVolume()->getParams().getSculptID()); + + return LLMeshRepository::getStreamingCost(header, radius, bytes, visible_bytes, mLOD, unscaled_value); + } + else + { + LLVolume* volume = getVolume(); + S32 counts[4]; + LLVolume::getLoDTriangleCounts(volume->getParams(), counts); + + LLSD header; + header["lowest_lod"]["size"] = counts[0] * 10; + header["low_lod"]["size"] = counts[1] * 10; + header["medium_lod"]["size"] = counts[2] * 10; + header["high_lod"]["size"] = counts[3] * 10; + + return LLMeshRepository::getStreamingCost(header, radius, NULL, NULL, -1, unscaled_value); + } +} +#endif //MESH_ENABLED +//static +void LLVOVolume::updateRenderComplexity() +{ + mRenderComplexity_last = mRenderComplexity_current; + mRenderComplexity_current = 0; +} + +U32 LLVOVolume::getTriangleCount() const +{ + U32 count = 0; + LLVolume* volume = getVolume(); + if (volume) + { + count = volume->getNumTriangles(); + } + + return count; +} + +U32 LLVOVolume::getHighLODTriangleCount() +{ + U32 ret = 0; + + LLVolume* volume = getVolume(); + + if (!isSculpted()) + { + LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); + ret = ref->getNumTriangles(); + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } +#if MESH_ENABLED + else if (isMesh()) + { + LLVolume* ref = LLPrimitive::getVolumeManager()->refVolume(volume->getParams(), 3); + if (!ref->isMeshAssetLoaded() || ref->getNumVolumeFaces() == 0) + { + gMeshRepo.loadMesh(this, volume->getParams(), LLModel::LOD_HIGH); + } + ret = ref->getNumTriangles(); + LLPrimitive::getVolumeManager()->unrefVolume(ref); + } +#endif //MESH_ENABLED + else + { //default sculpts have a constant number of triangles + ret = 31*2*31; //31 rows of 31 columns of quads for a 32x32 vertex patch + } + + return ret; +} + //static void LLVOVolume::preUpdateGeom() { @@ -2072,7 +2598,7 @@ void LLVOVolume::setSelected(BOOL sel) } } -void LLVOVolume::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) +void LLVOVolume::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { } @@ -2090,7 +2616,7 @@ F32 LLVOVolume::getBinRadius() const S32 attachment_size_factor = llmax(size_factor_setting.get(),1); const LLVector3& distance_factor = distance_factor_setting; const LLVector3& alpha_distance_factor = alpha_distance_factor_setting; - const LLVector3* ext = mDrawable->getSpatialExtents(); + const LLVector4a* ext = mDrawable->getSpatialExtents(); BOOL shrink_wrap = mDrawable->isAnimating(); BOOL alpha_wrap = FALSE; @@ -2124,7 +2650,10 @@ F32 LLVOVolume::getBinRadius() } else if (shrink_wrap) { - radius = (ext[1]-ext[0]).length()*0.5f; + LLVector4a rad; + rad.setSub(ext[1], ext[0]); + + radius = rad.getLength3().getF32()*0.5f; } else if (mDrawable->isStatic()) { @@ -2155,7 +2684,7 @@ const LLVector3 LLVOVolume::getPivotPositionAgent() const return LLViewerObject::getPivotPositionAgent(); } -void LLVOVolume::onShift(const LLVector3 &shift_vector) +void LLVOVolume::onShift(const LLVector4a &shift_vector) { if (mVolumeImpl) { @@ -2237,12 +2766,39 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e BOOL ret = FALSE; LLVolume* volume = getVolume(); + + bool transform = true; + +#if MESH_ENABLED + if (mDrawable->isState(LLDrawable::RIGGED)) + { + if (gFloaterTools->getVisible() && getAvatar()->isSelf()) + { + updateRiggedVolume(); + genBBoxes(FALSE); + volume = mRiggedVolume; + transform = false; + } + else + { //cannot pick rigged attachments on other avatars or when not in build mode + return FALSE; + } + } +#endif //MESH_ENABLED if (volume) { LLVector3 v_start, v_end, v_dir; - v_start = agentPositionToVolume(start); - v_end = agentPositionToVolume(end); + if (transform) + { + v_start = agentPositionToVolume(start); + v_end = agentPositionToVolume(end); + } + else + { + v_start = start; + v_end = end; + } LLVector3 p; LLVector3 n; @@ -2283,8 +2839,15 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e end_face = face+1; } + bool special_cursor = specialHoverCursor(); for (S32 i = start_face; i < end_face; ++i) { + if (!special_cursor && !pick_transparent && getTE(i)->getColor().mV[3] == 0.f) + { //don't attempt to pick completely transparent faces unless + //pick_transparent is true + continue; + } + face_hit = volume->lineSegmentIntersect(v_start, v_end, i, &p, &tc, &n, &bn); @@ -2302,18 +2865,40 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e if (intersection != NULL) { - *intersection = volumePositionToAgent(p); // must map back to agent space + if (transform) + { + *intersection = volumePositionToAgent(p); // must map back to agent space + } + else + { + *intersection = p; + } } if (normal != NULL) { - *normal = volumeDirectionToAgent(n); + if (transform) + { + *normal = volumeDirectionToAgent(n); + } + else + { + *normal = n; + } + (*normal).normVec(); } if (bi_normal != NULL) { - *bi_normal = volumeDirectionToAgent(bn); + if (transform) + { + *bi_normal = volumeDirectionToAgent(bn); + } + else + { + *bi_normal = bn; + } (*bi_normal).normVec(); } @@ -2331,6 +2916,203 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e return ret; } +#if MESH_ENABLED +bool LLVOVolume::treatAsRigged() +{ + return gFloaterTools->getVisible() && + isAttachment() && + getAvatar() && + getAvatar()->isSelf() && + mDrawable.notNull() && + mDrawable->isState(LLDrawable::RIGGED); +} + +LLRiggedVolume* LLVOVolume::getRiggedVolume() +{ + return mRiggedVolume; +} + +void LLVOVolume::clearRiggedVolume() +{ + if (mRiggedVolume.notNull()) + { + mRiggedVolume = NULL; + updateRelativeXform(); + } +} + +void LLVOVolume::updateRiggedVolume() +{ + //Update mRiggedVolume to match current animation frame of avatar. + //Also update position/size in octree. + + if (!treatAsRigged()) + { + clearRiggedVolume(); + + return; + } + + LLVolume* volume = getVolume(); + + const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(volume->getParams().getSculptID(), this); + + if (!skin) + { + clearRiggedVolume(); + return; + } + + LLVOAvatar* avatar = getAvatar(); + + if (!avatar) + { + clearRiggedVolume(); + return; + } + + if (!mRiggedVolume) + { + LLVolumeParams p; + mRiggedVolume = new LLRiggedVolume(p); + updateRelativeXform(); + } + + mRiggedVolume->update(skin, avatar, volume); + +} + + +//static LLFastTimer::DeclareTimer FTM_SKIN_RIGGED("Skin"); +//static LLFastTimer::DeclareTimer FTM_RIGGED_OCTREE("Octree"); + +void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* volume) +{ + bool copy = false; + if (volume->getNumVolumeFaces() != getNumVolumeFaces()) + { + copy = true; + } + + for (S32 i = 0; i < volume->getNumVolumeFaces() && !copy; ++i) + { + const LLVolumeFace& src_face = volume->getVolumeFace(i); + const LLVolumeFace& dst_face = getVolumeFace(i); + + if (src_face.mNumIndices != dst_face.mNumIndices || + src_face.mNumVertices != dst_face.mNumVertices) + { + copy = true; + } + } + + if (copy) + { + copyVolumeFaces(volume); + } + + //build matrix palette + LLMatrix4a mp[64]; + LLMatrix4* mat = (LLMatrix4*) mp; + + for (U32 j = 0; j < skin->mJointNames.size(); ++j) + { + LLJoint* joint = avatar->getJoint(skin->mJointNames[j]); + if (joint) + { + mat[j] = skin->mInvBindMatrix[j]; + mat[j] *= joint->getWorldMatrix(); + } + } + + for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i) + { + const LLVolumeFace& vol_face = volume->getVolumeFace(i); + + LLVolumeFace& dst_face = mVolumeFaces[i]; + + LLVector4a* weight = vol_face.mWeights; + + LLMatrix4a bind_shape_matrix; + bind_shape_matrix.loadu(skin->mBindShapeMatrix); + + LLVector4a* pos = dst_face.mPositions; + + { + LLFastTimer t(LLFastTimer::FTM_SKIN_RIGGED); + + for (U32 j = 0; j < (U32)dst_face.mNumVertices; ++j) + { + LLMatrix4a final_mat; + final_mat.clear(); + + S32 idx[4]; + + LLVector4 wght; + + F32 scale = 0.f; + for (U32 k = 0; k < 4; k++) + { + F32 w = weight[j][k]; + + idx[k] = (S32) floorf(w); + wght[k] = w - floorf(w); + scale += wght[k]; + } + + wght *= 1.f/scale; + + for (U32 k = 0; k < 4; k++) + { + F32 w = wght[k]; + + LLMatrix4a src; + src.setMul(mp[idx[k]], w); + + final_mat.add(src); + } + + + LLVector4a& v = vol_face.mPositions[j]; + LLVector4a t; + LLVector4a dst; + bind_shape_matrix.affineTransform(v, t); + final_mat.affineTransform(t, dst); + pos[j] = dst; + } + + //update bounding box + LLVector4a& min = dst_face.mExtents[0]; + LLVector4a& max = dst_face.mExtents[1]; + + min = pos[0]; + max = pos[1]; + + for (U32 j = 1; j < (U32)dst_face.mNumVertices; ++j) + { + min.setMin(min, pos[j]); + max.setMax(max, pos[j]); + } + + dst_face.mCenter->setAdd(dst_face.mExtents[0], dst_face.mExtents[1]); + dst_face.mCenter->mul(0.5f); + + } + + { + LLFastTimer t(LLFastTimer::FTM_RIGGED_OCTREE); + delete dst_face.mOctree; + dst_face.mOctree = NULL; + + LLVector4a size; + size.setSub(dst_face.mExtents[1], dst_face.mExtents[0]); + size.splat(size.getLength3().getF32()*0.5f); + + dst_face.createOctree(1.f); + } + } +} +#endif //MESH_ENABLED U32 LLVOVolume::getPartitionType() const { if (isHUDAttachment()) @@ -2365,6 +3147,26 @@ LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) mSlopRatio = 0.25f; } +bool can_batch_texture(LLFace* facep) +{ + if (facep->getTextureEntry()->getBumpmap()) + { //bump maps aren't worked into texture batching yet + return false; + } + + if (facep->getTexture() && facep->getTexture()->getPrimaryFormat() == GL_ALPHA) + { //can't batch invisiprims + return false; + } + + if (facep->isState(LLFace::TEXTURE_ANIM) && facep->getVirtualSize() > MIN_TEX_ANIM_SIZE) + { //texture animation breaks batches + return false; + } + + return true; +} + void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -2410,29 +3212,47 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, else { model_mat = &(drawable->getRegion()->mRenderMatrix); + if (model_mat->isIdentity()) + { + model_mat = NULL; + } } - U8 bump = (type == LLRenderPass::PASS_BUMP || type == LLRenderPass::PASS_POST_BUMP) ? facep->getTextureEntry()->getBumpmap() : 0; LLViewerTexture* tex = facep->getTexture(); - U8 glow = 0; - - if (type == LLRenderPass::PASS_GLOW || type==LLRenderPass::PASS_ALPHA) //Alpha pass now handles glow internally - { - glow = (U8) (facep->getTextureEntry()->getGlow() * 255); - } - if (!facep->getVertexBuffer()) + U8 index = facep->getTextureIndex(); + + bool batchable = false; + + if (index < 255 && idx >= 0) { - llerrs << "WTF?" << llendl; + if (index < draw_vec[idx]->mTextureList.size()) + { + if (draw_vec[idx]->mTextureList[index].isNull()) + { + batchable = true; + draw_vec[idx]->mTextureList[index] = tex; + } + else if (draw_vec[idx]->mTextureList[index] == tex) + { //this face's texture index can be used with this batch + batchable = true; + } + } + else + { //texture list can be expanded to fit this texture index + batchable = true; + } } + + U8 glow = (U8) (facep->getTextureEntry()->getGlow() * 255); if (idx >= 0 && draw_vec[idx]->mVertexBuffer == facep->getVertexBuffer() && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && - (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex) && + (LLPipeline::sTextureBindTest || draw_vec[idx]->mTexture == tex || batchable) && #if LL_DARWIN draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && @@ -2446,7 +3266,13 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, draw_vec[idx]->mCount += facep->getIndicesCount(); draw_vec[idx]->mEnd += facep->getGeomCount(); draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); - validate_draw_info(*draw_vec[idx]); + + if (index >= draw_vec[idx]->mTextureList.size()) + { + draw_vec[idx]->mTextureList.resize(index+1); + draw_vec[idx]->mTextureList[index] = tex; + } + draw_vec[idx]->validate(); update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[0]); update_min_max(draw_vec[idx]->mExtents[0], draw_vec[idx]->mExtents[1], facep->mExtents[1]); } @@ -2470,7 +3296,13 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, } draw_info->mExtents[0] = facep->mExtents[0]; draw_info->mExtents[1] = facep->mExtents[1]; - validate_draw_info(*draw_info); + + if (index < 255) + { //initialize texture list for texture batching + draw_info->mTextureList.resize(index+1); + draw_info->mTextureList[index] = tex; + } + draw_info->validate(); } } @@ -2479,6 +3311,35 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) } +#if MESH_ENABLED +static LLDrawPoolAvatar* get_avatar_drawpool(LLViewerObject* vobj) +{ + LLVOAvatar* avatar = vobj->getAvatar(); + + if (avatar) + { + LLDrawable* drawable = avatar->mDrawable; + if (drawable && drawable->getNumFaces() > 0) + { + LLFace* face = drawable->getFace(0); + if (face) + { + LLDrawPool* drawpool = face->getPool(); + if (drawpool) + { + if (drawpool->getType() == LLDrawPool::POOL_AVATAR) + { + return (LLDrawPoolAvatar*) drawpool; + } + } + } + } + } + + return NULL; +} + +#endif //MESH_ENABLED void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (LLPipeline::sSkipUpdate) @@ -2523,8 +3384,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) static const LLCachedControl<S32> render_max_vbo_size("RenderMaxVBOSize", 512); static const LLCachedControl<S32> render_max_node_size("RenderMaxNodeSize",8192); - U32 max_vertices = (render_max_vbo_size*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); - U32 max_total = (render_max_node_size*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); + U32 max_vertices = (render_max_vbo_size*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); + U32 max_total = (render_max_node_size*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); U32 cur_total = 0; @@ -2545,12 +3406,27 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } LLVOVolume* vobj = drawablep->getVOVolume(); + +#if MESH_ENABLED + if (vobj->isMesh() && + (vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded() || !gMeshRepo.meshRezEnabled())) + { + continue; + } +#endif //MESH_ENABLED llassert_always(vobj); - vobj->updateTextureVirtualSize(); + vobj->updateTextureVirtualSize(true); vobj->preRebuild(); drawablep->clearState(LLDrawable::HAS_ALPHA); +#if MESH_ENABLED + bool rigged = vobj->isAttachment() && + vobj->isMesh() && + gMeshRepo.getSkinInfo(vobj->getVolume()->getParams().getSculptID(), vobj); + + bool is_rigged = false; +#endif //MESH_ENABLED //for each face for (S32 i = 0; i < drawablep->getNumFaces(); i++) { @@ -2562,6 +3438,170 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //sum up face verts and indices drawablep->updateFaceSize(i); + +#if MESH_ENABLED + if (rigged) + { + if (!facep->isState(LLFace::RIGGED)) + { //completely reset vertex buffer + facep->clearVertexBuffer(); + } + + facep->setState(LLFace::RIGGED); + is_rigged = true; + + //get drawpool of avatar with rigged face + LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); + + //Determine if we've received skininfo that contains an + //alternate bind matrix - if it does then apply the translational component + //to the joints of the avatar. + LLVOAvatar* pAvatarVO = vobj->getAvatar(); + bool pelvisGotSet = false; + + if ( pAvatarVO ) + { + LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); + + if ( pSkinData ) + { + const int bindCnt = pSkinData->mAlternateBindMatrix.size(); + if ( bindCnt > 0 ) + { + const int jointCnt = pSkinData->mJointNames.size(); + const F32 pelvisZOffset = pSkinData->mPelvisOffset; + bool fullRig = (jointCnt>=20) ? true : false; + if ( fullRig ) + { + for ( int i=0; i<jointCnt; ++i ) + { + std::string lookingForJoint = pSkinData->mJointNames[i].c_str(); + //llinfos<<"joint name "<<lookingForJoint.c_str()<<llendl; + LLJoint* pJoint = pAvatarVO->getJoint( lookingForJoint ); + if ( pJoint && pJoint->getId() != currentId ) + { + pJoint->setId( currentId ); + const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); + //Set the joint position + pJoint->storeCurrentXform( jointPos ); + //If joint is a pelvis then handle old/new pelvis to foot values + if ( lookingForJoint == "mPelvis" ) + { + pJoint->storeCurrentXform( jointPos ); + if ( !pAvatarVO->hasPelvisOffset() ) + { + pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); + //Trigger to rebuild viewer AV + pelvisGotSet = true; + } + } + } + } + } + } + } + } + //If we've set the pelvis to a new position we need to also rebuild some information that the + //viewer does at launch (e.g. body size etc.) + if ( pelvisGotSet ) + { + pAvatarVO->postPelvisSetRecalc(); + } + + if (pool) + { + const LLTextureEntry* te = facep->getTextureEntry(); + + //remove face from old pool if it exists + LLDrawPool* old_pool = facep->getPool(); + if (old_pool && old_pool->getType() == LLDrawPool::POOL_AVATAR) + { + ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep); + } + + //add face to new pool + LLViewerTexture* tex = facep->getTexture(); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + + if (type == LLDrawPool::POOL_ALPHA) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_ALPHA); + } + } + else if (te->getShiny()) + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY); + } + else + { + if (LLPipeline::sRenderDeferred) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SHINY); + } + } + } + else + { + if (te->getFullbright()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_SIMPLE); + } + } + + if (te->getGlow()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW); + } + + if (LLPipeline::sRenderDeferred) + { + if (type != LLDrawPool::POOL_ALPHA && !te->getFullbright()) + { + if (te->getBumpmap()) + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_BUMP); + } + else + { + pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE); + } + } + } + } + + continue; + } + else + { + if (facep->isState(LLFace::RIGGED)) + { //face is not rigged but used to be, remove from rigged face pool + LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*) facep->getPool(); + if (pool) + { + pool->removeRiggedFace(facep); + } + facep->clearState(LLFace::RIGGED); + } + } +#endif //MESH_ENABLED + if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0) { facep->clearVertexBuffer(); @@ -2672,6 +3712,17 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->clearVertexBuffer(); } } + +#if MESH_ENABLED + if (is_rigged) + { + drawablep->setState(LLDrawable::RIGGED); + } + else + { + drawablep->clearState(LLDrawable::RIGGED); + } +#endif //MESH_ENABLED } group->mBufferUsage = useage; @@ -2682,15 +3733,24 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) U32 bump_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; U32 fullbright_mask = LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR; - if (LLPipeline::sRenderDeferred) + bool batch_textures = LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1; + + if (batch_textures) { bump_mask |= LLVertexBuffer::MAP_BINORMAL; + genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, TRUE); + genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, TRUE); + genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, FALSE, TRUE); + genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, TRUE, TRUE); } - - genDrawInfo(group, simple_mask, simple_faces); - genDrawInfo(group, bump_mask, bump_faces); - genDrawInfo(group, fullbright_mask, fullbright_faces); - genDrawInfo(group, alpha_mask, alpha_faces, TRUE); + else + { + genDrawInfo(group, simple_mask, simple_faces); + genDrawInfo(group, fullbright_mask, fullbright_faces); + genDrawInfo(group, bump_mask, bump_faces, FALSE, TRUE); + genDrawInfo(group, alpha_mask, alpha_faces, TRUE); + } + if (!LLPipeline::sDelayVBUpdate) { @@ -2716,6 +3776,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { + llassert(group); static int warningsCount = 20; if (group && group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY)) { @@ -2723,50 +3784,49 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) group->mBuilt = 1.f; + std::set<LLVertexBuffer*> mapped_buffers; + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) { LLDrawable* drawablep = *drawable_iter; - if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + /*if (drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) { continue; - } + }*/ - if (drawablep->isState(LLDrawable::REBUILD_ALL)) + if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) ) { LLVOVolume* vobj = drawablep->getVOVolume(); vobj->preRebuild(); + LLVolume* volume = vobj->getVolume(); for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { LLFace* face = drawablep->getFace(i); - if (face && face->getVertexBuffer()) + if (face) { - face->getGeometryVolume(*volume, face->getTEOffset(), - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); + LLVertexBuffer* buff = face->getVertexBuffer(); + if (buff) + { + face->getGeometryVolume(*volume, face->getTEOffset(), + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex()); + + if (buff->isLocked()) + { + mapped_buffers.insert(buff); + } + } } } - + drawablep->clearState(LLDrawable::REBUILD_ALL); } } - //unmap all the buffers - for (LLSpatialGroup::buffer_map_t::iterator i = group->mBufferMap.begin(); i != group->mBufferMap.end(); ++i) + for (std::set<LLVertexBuffer*>::iterator iter = mapped_buffers.begin(); iter != mapped_buffers.end(); ++iter) { - LLSpatialGroup::buffer_texture_map_t& map = i->second; - for (LLSpatialGroup::buffer_texture_map_t::iterator j = map.begin(); j != map.end(); ++j) - { - LLSpatialGroup::buffer_list_t& list = j->second; - for (LLSpatialGroup::buffer_list_t::iterator k = list.begin(); k != list.end(); ++k) - { - LLVertexBuffer* buffer = *k; - if (buffer->isLocked()) - { - buffer->setBuffer(0); - } - } - } + (*iter)->setBuffer(0); } // don't forget alpha @@ -2802,19 +3862,48 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) group->clearState(LLSpatialGroup::MESH_DIRTY | LLSpatialGroup::NEW_DRAWINFO); } + + llassert(!group || !group->isState(LLSpatialGroup::NEW_DRAWINFO)); } -void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort) +struct CompareBatchBreakerModified +{ + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + const LLTextureEntry* lte = lhs->getTextureEntry(); + const LLTextureEntry* rte = rhs->getTextureEntry(); + + if (lte->getBumpmap() != rte->getBumpmap()) + { + return lte->getBumpmap() < rte->getBumpmap(); + } + else if (lte->getFullbright() != rte->getFullbright()) + { + return lte->getFullbright() < rte->getFullbright(); + } + else if (lte->getGlow() != rte->getGlow()) + { + return lte->getGlow() < rte->getGlow(); + } + else + { + return lhs->getTexture() < rhs->getTexture(); + } + + } +}; + +void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures) { //calculate maximum number of vertices to store in a single buffer static const LLCachedControl<S32> render_max_vbo_size("RenderMaxVBOSize", 512); - U32 max_vertices = (render_max_vbo_size*1024)/LLVertexBuffer::calcStride(group->mSpatialPartition->mVertexDataMask); + U32 max_vertices = (render_max_vbo_size*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); if (!distance_sort) { //sort faces by things that break batches - std::sort(faces.begin(), faces.end(), LLFace::CompareBatchBreaker()); + std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); } else { @@ -2822,6 +3911,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); } + bool hud_group = group->isHUDGroup() ; std::vector<LLFace*>::iterator face_iter = faces.begin(); LLSpatialGroup::buffer_map_t buffer_map; @@ -2834,6 +3924,21 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: buffer_index = -1; } + S32 texture_index_channels = gGLManager.mNumTextureImageUnits-1; //always reserve one for shiny for now just for simplicity + + static const LLCachedControl<bool> no_texture_indexing("ShyotlUseLegacyTextureBatching",false); + if (gGLManager.mGLVersion < 3.1f || no_texture_indexing) + { + texture_index_channels = 1; + } + + if (LLPipeline::sRenderDeferred && distance_sort) + { + texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels; + } + + texture_index_channels = llmin(texture_index_channels, (S32) gSavedSettings.getU32("RenderMaxTextureIndex")); + while (face_iter != faces.end()) { //pull off next face @@ -2858,28 +3963,105 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: U32 index_count = facep->getIndicesCount(); U32 geom_count = facep->getGeomCount(); - //sum up vertices needed for this texture + //sum up vertices needed for this render batch std::vector<LLFace*>::iterator i = face_iter; ++i; - while (i != faces.end() && - (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + std::vector<LLViewerTexture*> texture_list; + + if (batch_textures) { - facep = *i; - - if (geom_count + facep->getGeomCount() > max_vertices) - { //cut vertex buffers on geom count too big - break; + U8 cur_tex = 0; + facep->setTextureIndex(cur_tex); + texture_list.push_back(tex); + + //if (can_batch_texture(facep)) + { + while (i != faces.end()) + { + facep = *i; + if (facep->getTexture() != tex) + { + if (distance_sort) + { //textures might be out of order, see if texture exists in current batch + bool found = false; + for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) + { + if (facep->getTexture() == texture_list[tex_idx]) + { + cur_tex = tex_idx; + found = true; + break; + } + } + + if (!found) + { + cur_tex = texture_list.size(); + } + } + else + { + cur_tex++; + } + + if (!can_batch_texture(facep)) + { //face is bump mapped or has an animated texture matrix -- can't + //batch more than 1 texture at a time + break; + } + + if (cur_tex >= texture_index_channels) + { //cut batches when index channels are depleted + break; + } + + tex = facep->getTexture(); + + texture_list.push_back(tex); + } + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } + + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + + facep->setTextureIndex(cur_tex); + } } - ++i; - index_count += facep->getIndicesCount(); - geom_count += facep->getGeomCount(); + tex = texture_list[0]; + } + else + { + while (i != faces.end() && + (LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex))) + { + facep = *i; + + + //face has no texture index + facep->mDrawInfo = NULL; + facep->setTextureIndex(255); + + if (geom_count + facep->getGeomCount() > max_vertices) + { //cut batches on geom count too big + break; + } + + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + } } //create/delete/resize vertex buffer if needed LLVertexBuffer* buffer = NULL; - LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(tex); + LLSpatialGroup::buffer_texture_map_t::iterator found_iter = group->mBufferMap[mask].find(*face_iter); if (found_iter != group->mBufferMap[mask].end()) { @@ -2910,7 +4092,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } } - buffer_map[mask][tex].push_back(buffer); + buffer_map[mask][*face_iter].push_back(buffer); //add face geometry @@ -2924,22 +4106,25 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: facep->setGeomIndex(index_offset); facep->setVertexBuffer(buffer); + if (batch_textures && facep->getTextureIndex() == 255) { + llerrs << "Invalid texture index." << llendl; + } + + { + //for debugging, set last time face was updated vs moved facep->updateRebuildFlags(); + if (!LLPipeline::sDelayVBUpdate) - { + { //copy face geometry into vertex buffer LLDrawable* drawablep = facep->getDrawable(); LLVOVolume* vobj = drawablep->getVOVolume(); LLVolume* volume = vobj->getVolume(); U32 te_idx = facep->getTEOffset(); - if (facep->getGeometryVolume(*volume, te_idx, - vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset)) - { - buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), - facep->getIndicesStart(), facep->getIndicesCount()); - } + facep->getGeometryVolume(*volume, te_idx, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset); } } @@ -2957,6 +4142,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } const LLTextureEntry* te = facep->getTextureEntry(); + tex = facep->getTexture(); BOOL is_alpha = (facep->getPoolType() == LLDrawPool::POOL_ALPHA) ? TRUE : FALSE; @@ -2965,9 +4151,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: // can we safely treat this as an alpha mask? if (facep->canRenderAsMask()) { - const LLDrawable* drawablep = facep->getDrawable(); - const LLVOVolume* vobj = drawablep ? drawablep->getVOVolume() : NULL; - if (te->getFullbright() || (vobj && vobj->isHUDAttachment())) + //const LLDrawable* drawablep = facep->getDrawable(); + //const LLVOVolume* vobj = drawablep ? drawablep->getVOVolume() : NULL; + if (te->getFullbright() /*|| (vobj && vobj->isHUDAttachment())*/) { registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK); } @@ -2996,7 +4182,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: registerFace(group, facep, LLRenderPass::PASS_INVISI_SHINY); registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); } - else if (LLPipeline::sRenderDeferred) + else if (LLPipeline::sRenderDeferred && !hud_group) { //deferred rendering if (te->getFullbright()) { //register in post deferred fullbright shiny pass @@ -3034,7 +4220,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: else if (fullbright) { //fullbright registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); - if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap()) + if (LLPipeline::sRenderDeferred && !hud_group && LLPipeline::sRenderBump && te->getBumpmap()) { //if this is the deferred render and a bump map is present, register in post deferred bump registerFace(group, facep, LLRenderPass::PASS_POST_BUMP); } @@ -3060,7 +4246,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: } //not sure why this is here, and looks like it might cause bump mapped objects to get rendered redundantly -- davep 5/11/2010 - if (!is_alpha && !LLPipeline::sRenderDeferred) + if (!is_alpha && (hud_group || !LLPipeline::sRenderDeferred)) { llassert((mask & LLVertexBuffer::MAP_NORMAL) || fullbright); facep->setPoolType((fullbright) ? LLDrawPool::POOL_FULLBRIGHT : LLDrawPool::POOL_SIMPLE); @@ -3122,7 +4308,7 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun { vertex_count += facep->getGeomCount(); index_count += facep->getIndicesCount(); - + llassert(facep->getIndicesCount() < 65536); //remember face (for sorting) mFaceList.push_back(facep); } @@ -3144,7 +4330,7 @@ LLHUDPartition::LLHUDPartition() mLODPeriod = 1; } -void LLHUDPartition::shift(const LLVector3 &offset) +void LLHUDPartition::shift(const LLVector4a &offset) { //HUD objects don't shift with region crossing. That would be silly. } diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index 71e4f0323..ec97df042 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -44,12 +44,27 @@ class LLViewerTextureAnim; class LLDrawPool; class LLSelectNode; +class LLVOAvatar; +class LLMeshSkinInfo; enum LLVolumeInterfaceType { INTERFACE_FLEXIBLE = 1, }; +#if MESH_ENABLED +class LLRiggedVolume : public LLVolume +{ +public: + LLRiggedVolume(const LLVolumeParams& params) + : LLVolume(params, 0.f) + { + } + + void update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, const LLVolume* src_volume); +}; +#endif //MESH_ENABLED + // Base class for implementations of the volume - Primitive, Flexible Object, etc. class LLVolumeInterface { @@ -62,7 +77,7 @@ public: virtual void onSetVolume(const LLVolumeParams &volume_params, const S32 detail) = 0; virtual void onSetScale(const LLVector3 &scale, BOOL damped) = 0; virtual void onParameterChanged(U16 param_type, LLNetworkData *data, BOOL in_use, bool local_origin) = 0; - virtual void onShift(const LLVector3 &shift_vector) = 0; + virtual void onShift(const LLVector4a &shift_vector) = 0; virtual bool isVolumeUnique() const = 0; // Do we need a unique LLVolume instance? virtual bool isVolumeGlobal() const = 0; // Are we in global space? virtual bool isActive() const = 0; // Is this object currently active? @@ -75,6 +90,7 @@ public: // Class which embodies all Volume objects (with pcode LL_PCODE_VOLUME) class LLVOVolume : public LLViewerObject { + LOG_CLASS(LLVOVolume); protected: virtual ~LLVOVolume(); @@ -116,8 +132,13 @@ public: const LLMatrix4& getRelativeXform() const { return mRelativeXform; } const LLMatrix3& getRelativeXformInvTrans() const { return mRelativeXformInvTrans; } /*virtual*/ const LLMatrix4 getRenderMatrix() const; - - + typedef std::map<LLUUID, S32> texture_cost_t; + U32 getRenderCost(texture_cost_t &textures) const; +#if MESH_ENABLED + /*virtual*/ F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL, F32* unscaled_value = NULL) const; +#endif //MESH_ENABLED + /*virtual*/ U32 getTriangleCount() const; + /*virtual*/ U32 getHighLODTriangleCount(); /*virtual*/ BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, S32 face = -1, // which face to check, -1 = ALL_SIDES BOOL pick_transparent = FALSE, @@ -141,7 +162,7 @@ public: void markForUpdate(BOOL priority) { LLViewerObject::markForUpdate(priority); mVolumeChanged = TRUE; } - /*virtual*/ void onShift(const LLVector3 &shift_vector); // Called when the drawable shifts + /*virtual*/ void onShift(const LLVector4a &shift_vector); // Called when the drawable shifts /*virtual*/ void parameterChanged(U16 param_type, bool local_origin); /*virtual*/ void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin); @@ -179,19 +200,25 @@ public: void updateSculptTexture(); void setIndexInTex(S32 index) { mIndexInTex = index ;} void sculpt(); +#if MESH_ENABLED + static void rebuildMeshAssetCallback(LLVFS *vfs, + const LLUUID& asset_uuid, + LLAssetType::EType type, + void* user_data, S32 status, LLExtStat ext_status); +#endif //MESH_ENABLED void updateRelativeXform(); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ void updateFaceSize(S32 idx); /*virtual*/ BOOL updateLOD(); void updateRadius(); /*virtual*/ void updateTextures(); - void updateTextureVirtualSize(); + void updateTextureVirtualSize(bool forced = false); void updateFaceFlags(); void regenFaces(); BOOL genBBoxes(BOOL force_global); void preRebuild(); - virtual void updateSpatialExtents(LLVector3& min, LLVector3& max); + virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); virtual F32 getBinRadius(); virtual U32 getPartitionType() const; @@ -225,6 +252,9 @@ public: U32 getVolumeInterfaceID() const; virtual BOOL isFlexible() const; virtual BOOL isSculpted() const; +#if MESH_ENABLED + virtual BOOL isMesh() const; +#endif //MESH_ENABLED virtual BOOL hasLightTexture() const; BOOL isVolumeGlobal() const; @@ -234,13 +264,42 @@ public: // tag: vaa emerald local_asset_browser void setSculptChanged(BOOL has_changed) { mSculptChanged = has_changed; } +#if MESH_ENABLED + void notifyMeshLoaded(); + + // Returns 'true' iff the media data for this object is in flight + bool isMediaDataBeingFetched() const; + + + + //rigged volume update (for raycasting) + void updateRiggedVolume(); + LLRiggedVolume* getRiggedVolume(); + + //returns true if volume should be treated as a rigged volume + // - Build tools are open + // - object is an attachment + // - object is attached to self + // - object is rendered as rigged + bool treatAsRigged(); + + //clear out rigged volume and revert back to non-rigged state for picking/LOD/distance updates + void clearRiggedVolume(); +#endif //MESH_ENABLED + protected: S32 computeLODDetail(F32 distance, F32 radius); BOOL calcLOD(); LLFace* addFace(S32 face_index); void updateTEData(); + // stats tracking for render complexity + static S32 mRenderComplexity_last; + static S32 mRenderComplexity_current; public: + + static S32 getRenderComplexityMax() {return mRenderComplexity_last;} + static void updateRenderComplexity(); LLViewerTextureAnim *mTextureAnimp; U8 mTexAnimMode; private: @@ -260,7 +319,9 @@ private: LLPointer<LLViewerFetchedTexture> mSculptTexture; LLPointer<LLViewerFetchedTexture> mLightTexture; S32 mIndexInTex; - +#if MESH_ENABLED + LLPointer<LLRiggedVolume> mRiggedVolume; +#endif //MESH_ENABLED // statics public: static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 347eb21b3..3eb24514b 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -74,7 +74,7 @@ LLVOWater::LLVOWater(const LLUUID &id, { // Terrain must draw during selection passes so it can block objects behind it. mbCanSelect = FALSE; - setScale(LLVector3(256.f, 256.f, 0.f)); // Hack for setting scale for bounding boxes/visibility. + setScale(LLVector3(mRegionp->getWidth(), mRegionp->getWidth(), 0.f)); // Hack for setting scale for bounding boxes/visibility. mUseTexture = TRUE; mIsEdgePatch = FALSE; @@ -267,19 +267,30 @@ void LLVOWater::setIsEdgePatch(const BOOL edge_patch) mIsEdgePatch = edge_patch; } -void LLVOWater::updateSpatialExtents(LLVector3 &newMin, LLVector3& newMax) +void LLVOWater::updateSpatialExtents(LLVector4a &newMin, LLVector4a& newMax) { - LLVector3 pos = getPositionAgent(); - LLVector3 scale = getScale(); + LLVector4a pos; + pos.load3(getPositionAgent().mV); + LLVector4a scale; + scale.load3(getScale().mV); + scale.mul(0.5f); - newMin = pos - scale * 0.5f; - newMax = pos + scale * 0.5f; + newMin.setSub(pos, scale); + newMax.setAdd(pos, scale); + + pos.setAdd(newMin,newMax); + pos.mul(0.5f); - mDrawable->setPositionGroup((newMin + newMax) * 0.5f); + mDrawable->setPositionGroup(pos); } U32 LLVOWater::getPartitionType() const { + if (mIsEdgePatch) + { + //return LLViewerRegion::PARTITION_VOIDWATER; + } + return LLViewerRegion::PARTITION_WATER; } @@ -298,6 +309,7 @@ LLWaterPartition::LLWaterPartition() LLVoidWaterPartition::LLVoidWaterPartition() { + //mOcclusionEnabled = FALSE; mDrawableType = LLPipeline::RENDER_TYPE_VOIDWATER; mPartitionType = LLViewerRegion::PARTITION_VOIDWATER; } diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h index 43b2b55dc..02a577a50 100644 --- a/indra/newview/llvowater.h +++ b/indra/newview/llvowater.h @@ -67,7 +67,7 @@ public: /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); + /*virtual*/ void updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax); /*virtual*/ void updateTextures(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 8d63b069c..fe0dbde4a 100644 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -336,7 +336,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) { const U32 max_buffer_bytes = gSavedSettings.getS32("RenderMaxVBOSize")*1024; const U32 data_mask = LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK; - const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcStride(data_mask); + const U32 max_verts = max_buffer_bytes / LLVertexBuffer::calcVertexSize(data_mask); const U32 total_stacks = getNumStacks(); @@ -571,7 +571,7 @@ void LLVOWLSky::buildFanBuffer(LLStrider<LLVector3> & vertices, LLStrider<LLVector2> & texCoords, LLStrider<U16> & indices) { - const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius(); + const F32 RADIUS = LLWLParamManager::getInstance()->getDomeRadius(); U32 i, num_slices; F32 phi0, theta, x0, y0, z0; @@ -632,7 +632,7 @@ void LLVOWLSky::buildStripsBuffer(U32 begin_stack, U32 end_stack, LLStrider<LLVector2> & texCoords, LLStrider<U16> & indices) { - const F32 RADIUS = LLWLParamManager::instance()->getDomeRadius(); + const F32 RADIUS = LLWLParamManager::getInstance()->getDomeRadius(); U32 i, j, num_slices, num_stacks; F32 phi0, theta, x0, y0, z0; diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index bf8956960..c3c64e17c 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -66,8 +66,6 @@ #include "curl/curl.h" -LLWaterParamManager * LLWaterParamManager::sInstance = NULL; - LLWaterParamManager::LLWaterParamManager() : mFogColor(22.f/255.f, 43.f/255.f, 54.f/255.f, 0.0f, 0.0f, "waterFogColor", "WaterFogColor"), mFogDensity(4, "waterFogDensity", 2), @@ -226,15 +224,10 @@ void LLWaterParamManager::propagateParameters(void) // bind the variables only if we're using shaders if(gPipeline.canUseVertexShaders()) { - LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; - end_shaders = LLViewerShaderMgr::instance()->endShaders(); - for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) + std::vector<LLGLSLShader*>::iterator shaders_iter=mShaderList.begin(); + for(; shaders_iter != mShaderList.end(); ++shaders_iter) { - if (shaders_iter->mProgramObject != 0 - && shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER) - { - shaders_iter->mUniformsDirty = TRUE; - } + (*shaders_iter)->mUniformsDirty = TRUE; } } @@ -250,7 +243,7 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader) { if (shader->mShaderGroup == LLGLSLShader::SG_WATER) { - shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLWLParamManager::instance()->getRotatedLightDir().mV); + shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLWLParamManager::getInstance()->getRotatedLightDir().mV); shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV); shader->uniform4fv("waterFogColor", 1, LLDrawPoolWater::sWaterFogColor.mV); shader->uniform4fv("waterPlane", 1, mWaterPlane.mV); @@ -260,6 +253,28 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader) } } +void LLWaterParamManager::updateShaderLinks() +{ + mShaderList.clear(); + LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; + end_shaders = LLViewerShaderMgr::instance()->endShaders(); + for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) + { + if (shaders_iter->mProgramObject != 0 + && shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER) + { + if( glGetUniformLocationARB(shaders_iter->mProgramObject,"lightnorm")>=0 || + glGetUniformLocationARB(shaders_iter->mProgramObject,"camPosLocal")>=0 || + glGetUniformLocationARB(shaders_iter->mProgramObject,"waterFogColor")>=0 || + glGetUniformLocationARB(shaders_iter->mProgramObject,"waterPlane")>=0 || + glGetUniformLocationARB(shaders_iter->mProgramObject,"waterFogDensity")>=0 || + glGetUniformLocationARB(shaders_iter->mProgramObject,"waterFogKS")>=0 || + glGetUniformLocationARB(shaders_iter->mProgramObject,"distance_multiplier")>=0) + mShaderList.push_back(&(*shaders_iter)); + } + } +} + void LLWaterParamManager::update(LLViewerCamera * cam) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM); @@ -315,31 +330,14 @@ void LLWaterParamManager::update(LLViewerCamera * cam) sunMoonDir.normVec(); mWaterFogKS = 1.f/llmax(sunMoonDir.mV[2], WATER_FOG_LIGHT_CLAMP); - LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; - end_shaders = LLViewerShaderMgr::instance()->endShaders(); - for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) + std::vector<LLGLSLShader*>::iterator shaders_iter=mShaderList.begin(); + for(; shaders_iter != mShaderList.end(); ++shaders_iter) { - if (shaders_iter->mProgramObject != 0 - && shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER) - { - shaders_iter->mUniformsDirty = TRUE; - } + (*shaders_iter)->mUniformsDirty = TRUE; } } } -// static -void LLWaterParamManager::initClass(void) -{ - instance(); -} - -// static -void LLWaterParamManager::cleanupClass(void) -{ - delete sInstance; - sInstance = NULL; -} bool LLWaterParamManager::addParamSet(const std::string& name, LLWaterParamSet& param) { @@ -445,16 +443,11 @@ F32 LLWaterParamManager::getFogDensity(void) } // static -LLWaterParamManager * LLWaterParamManager::instance() +void LLWaterParamManager::initSingleton() { - if(NULL == sInstance) - { - sInstance = new LLWaterParamManager(); + + loadAllPresets(LLStringUtil::null); - sInstance->loadAllPresets(LLStringUtil::null); - - sInstance->getParamSet("Default", sInstance->mCurParams); - } - - return sInstance; + getParamSet("Default", mCurParams); } + diff --git a/indra/newview/llwaterparammanager.h b/indra/newview/llwaterparammanager.h index babaf0076..c1042d06a 100644 --- a/indra/newview/llwaterparammanager.h +++ b/indra/newview/llwaterparammanager.h @@ -218,19 +218,14 @@ struct WaterExpFloatControl /// WindLight parameter manager class - what controls all the wind light shaders -class LLWaterParamManager +class LLWaterParamManager : public LLSingleton<LLWaterParamManager> { + LOG_CLASS(LLWaterParamManager); public: - LLWaterParamManager(); - ~LLWaterParamManager(); - - /// load a preset file - void loadAllPresets(const std::string & fileName); - - /// load an individual preset into the sky - - void loadPreset(const std::string & name,bool propagate=true); + typedef std::map<std::string, LLWaterParamSet> preset_map_t; + + void updateShaderLinks(); /// save the parameter presets to file void savePreset(const std::string & name); @@ -244,12 +239,6 @@ public: /// Update shader uniforms that have changed. void updateShaderUniforms(LLGLSLShader * shader); - /// Perform global initialization for this class. - static void initClass(void); - - // Cleanup of global data that's only inited once per class. - static void cleanupClass(); - /// add a param to the list bool addParamSet(const std::string& name, LLWaterParamSet& param); @@ -268,6 +257,9 @@ public: /// gets rid of a parameter and any references to it /// returns true if successful bool removeParamSet(const std::string& name, bool delete_from_disk); + /// @return all named water presets. + const preset_map_t& getPresets() const { return mParamList; } + /// set the normap map we want for water bool setNormalMapID(const LLUUID& img); @@ -311,17 +303,29 @@ public: WaterFloatControl mScaleBelow; WaterFloatControl mBlurMultiplier; - // list of all the parameters, listed by name - std::map<std::string, LLWaterParamSet> mParamList; F32 mDensitySliderValue; + /// load an individual preset into the sky + void loadPreset(const std::string & name,bool propagate=true); private: + friend class LLSingleton<LLWaterParamManager>; + /*virtual*/ void initSingleton(); + LLWaterParamManager(); + ~LLWaterParamManager(); + /// load a preset file + void loadAllPresets(const std::string & fileName); + + + LLVector4 mWaterPlane; F32 mWaterFogKS; + - // our parameter manager singleton instance - static LLWaterParamManager * sInstance; + // list of all the parameters, listed by name + std::map<std::string, LLWaterParamSet> mParamList; + + std::vector<LLGLSLShader *> mShaderList; }; inline void LLWaterParamManager::setDensitySliderValue(F32 val) diff --git a/indra/newview/llwaterparamset.cpp b/indra/newview/llwaterparamset.cpp index 3e97f9dbe..e7d59c162 100644 --- a/indra/newview/llwaterparamset.cpp +++ b/indra/newview/llwaterparamset.cpp @@ -230,3 +230,46 @@ F32 LLWaterParamSet::getFloat(const std::string& paramName, bool& error) return 0; } +// Added for interpolation effect in DEV-33645 +// Based on LLWLParamSet::mix, but written by Jacob without an intimate knowledge of how WindLight works. +// The function definition existed in the header but was never implemented. If you think there is something +// wrong with this, you're probably right. Ask Jacob, Q, or a member of the original WindLight team. +void LLWaterParamSet::mix(LLWaterParamSet& src, LLWaterParamSet& dest, F32 weight) +{ + // Setup + LLSD srcVal, destVal; // LLSD holders for get/set calls, reusable + + // Iterate through values + for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter) + { + // If param exists in both src and dest, set the holder variables, otherwise skip + if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first)) + { + srcVal = src.mParamValues[iter->first]; + destVal = dest.mParamValues[iter->first]; + } + else + { + continue; + } + + if(iter->second.isReal()) // If it's a real, interpolate directly + { + iter->second = srcVal.asReal() + ((destVal.asReal() - srcVal.asReal()) * weight); + } + else if(iter->second.isArray() && iter->second[0].isReal() // If it's an array of reals, loop through the reals and interpolate on those + && iter->second.size() == srcVal.size() && iter->second.size() == destVal.size()) + { + // Actually do interpolation: old value + (difference in values * factor) + for(int i=0; i < iter->second.size(); ++i) + { + // iter->second[i] = (1.f-weight)*(F32)srcVal[i].asReal() + weight*(F32)destVal[i].asReal(); // old way of doing it -- equivalent but one more operation + iter->second[i] = srcVal[i].asReal() + ((destVal[i].asReal() - srcVal[i].asReal()) * weight); + } + } + else // Else, skip + { + continue; + } + } +} diff --git a/indra/newview/llwaterparamset.h b/indra/newview/llwaterparamset.h index 9087843ec..9d51be652 100644 --- a/indra/newview/llwaterparamset.h +++ b/indra/newview/llwaterparamset.h @@ -40,7 +40,6 @@ #include "v4color.h" #include "llviewershadermgr.h" -class LLFloaterWater; class LLWaterParamSet; /// A class representing a set of parameter values for the Water shaders. diff --git a/indra/newview/llwearable.cpp b/indra/newview/llwearable.cpp index 72deff26d..a8adbb527 100644 --- a/indra/newview/llwearable.cpp +++ b/indra/newview/llwearable.cpp @@ -41,6 +41,7 @@ #include "llagent.h" #include "llagentcamera.h" #include "llagentwearables.h" +#include "llnotificationsutil.h" #include "llassetuploadresponders.h" #include "llviewerwindow.h" #include "llfloatercustomize.h" @@ -1021,7 +1022,7 @@ void LLWearable::saveNewAsset() LLSD args; args["NAME"] = mName; - LLNotifications::instance().add("CannotSaveWearableOutOfSpace", args); + LLNotificationsUtil::add("CannotSaveWearableOutOfSpace", args); return; } @@ -1069,7 +1070,7 @@ void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userda llwarns << buffer << " Status: " << status << llendl; LLSD args; args["NAME"] = type_name; - LLNotifications::instance().add("CannotSaveToAssetStore", args); + LLNotificationsUtil::add("CannotSaveToAssetStore", args); } // Delete temp file diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index 0ab91c58e..7b514cf04 100644 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -41,7 +41,7 @@ #include "llviewerinventory.h" //#include "llfloaterchat.h" #include "llviewerstats.h" -#include "llnotify.h" +#include "llnotificationsutil.h" // Globals LLWearableList gWearableList; // Globally constructed; be careful that there's no dependency with gAgent. @@ -191,16 +191,16 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID args["TYPE"] = LLAssetType::lookupHumanReadable(data->mAssetType); if (isNewWearable) { - LLNotifications::instance().add("InvalidWearable"); + LLNotificationsUtil::add("InvalidWearable"); } else if (data->mName.empty()) { - LLNotifications::instance().add("FailedToFindWearableUnnamed", args); + LLNotificationsUtil::add("FailedToFindWearableUnnamed", args); } else { args["DESC"] = data->mName; - LLNotifications::instance().add("FailedToFindWearable", args); + LLNotificationsUtil::add("FailedToFindWearable", args); } } // Always call callback; wearable will be NULL if we failed diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp index 82f02df3e..28bfe034a 100644 --- a/indra/newview/llweb.cpp +++ b/indra/newview/llweb.cpp @@ -36,6 +36,7 @@ #include "llweb.h" #include "llviewerwindow.h" +#include "llwindow.h" #include "llviewercontrol.h" #include "llfloatermediabrowser.h" @@ -64,7 +65,7 @@ void LLWeb::loadURL(const std::string& url) void LLWeb::loadURLExternal(const std::string& url) { std::string escaped_url = escapeURL(url); - gViewerWindow->getWindow()->spawnWebBrowser(escaped_url); + gViewerWindow->getWindow()->spawnWebBrowser(escaped_url,true); } diff --git a/indra/newview/llwind.cpp b/indra/newview/llwind.cpp index 2b0f0d969..0a2afd428 100644 --- a/indra/newview/llwind.cpp +++ b/indra/newview/llwind.cpp @@ -121,12 +121,12 @@ void LLWind::decompress(LLBitPack &bitpack, LLGroupHeader *group_headerp) set_group_of_patch_header(group_headerp); // X component - decode_patch_header(bitpack, &patch_header); + decode_patch_header(bitpack, &patch_header, FALSE); decode_patch(bitpack, buffer); decompress_patch(mVelX, buffer, &patch_header); // Y component - decode_patch_header(bitpack, &patch_header); + decode_patch_header(bitpack, &patch_header, FALSE); decode_patch(bitpack, buffer); decompress_patch(mVelY, buffer, &patch_header); diff --git a/indra/newview/llwlanimator.cpp b/indra/newview/llwlanimator.cpp index f7e40e49f..ed90c9d7c 100644 --- a/indra/newview/llwlanimator.cpp +++ b/indra/newview/llwlanimator.cpp @@ -49,7 +49,8 @@ void LLWLAnimator::update(LLWLParamSet& curParams) curTime = getDayTime(); // don't do anything if empty - if(mTimeTrack.size() == 0) { + if(mTimeTrack.size() == 0) + { return; } @@ -59,13 +60,15 @@ void LLWLAnimator::update(LLWLParamSet& curParams) mSecondIt++; // grab the two tween iterators - while(mSecondIt != mTimeTrack.end() && curTime > mSecondIt->first) { + while(mSecondIt != mTimeTrack.end() && curTime > mSecondIt->first) + { mFirstIt++; mSecondIt++; } // scroll it around when you get to the end - if(mSecondIt == mTimeTrack.end() || mFirstIt->first > curTime) { + if(mSecondIt == mTimeTrack.end() || mFirstIt->first > curTime) + { mSecondIt = mTimeTrack.begin(); mFirstIt = mTimeTrack.end(); mFirstIt--; @@ -73,56 +76,66 @@ void LLWLAnimator::update(LLWLParamSet& curParams) F32 weight = 0; - if(mFirstIt->first < mSecondIt->first) { + if(mFirstIt->first < mSecondIt->first) + { // get the delta time and the proper weight weight = F32 (curTime - mFirstIt->first) / (mSecondIt->first - mFirstIt->first); // handle the ends - } else if(mFirstIt->first > mSecondIt->first) { + } + else if(mFirstIt->first > mSecondIt->first) + { // right edge of time line - if(curTime >= mFirstIt->first) { + if(curTime >= mFirstIt->first) + { weight = F32 (curTime - mFirstIt->first) / ((1 + mSecondIt->first) - mFirstIt->first); - // left edge of time line - } else { + } + else + { weight = F32 ((1 + curTime) - mFirstIt->first) / ((1 + mSecondIt->first) - mFirstIt->first); } - // handle same as whatever the last one is - } else { + } + else + { weight = 1; } // do the interpolation and set the parameters - curParams.mix(LLWLParamManager::instance()->mParamList[mFirstIt->second], - LLWLParamManager::instance()->mParamList[mSecondIt->second], weight); + curParams.mix(LLWLParamManager::getInstance()->mParamList[mFirstIt->second], + LLWLParamManager::getInstance()->mParamList[mSecondIt->second], weight); } F64 LLWLAnimator::getDayTime() { - if(!mIsRunning) { + if(!mIsRunning) + { return mDayTime; } - if(mUseLindenTime) { - + if(mUseLindenTime) + { F32 phase = gSky.getSunPhase() / F_PI; // we're not solving the non-linear equation that determines sun phase // we're just linearly interpolating between the major points if (phase <= 5.0 / 4.0) { mDayTime = (1.0 / 3.0) * phase + (1.0 / 3.0); - } else { + } + else + { mDayTime = phase - (1.0 / 2.0); } - if(mDayTime > 1) { + if(mDayTime > 1) + { mDayTime--; } @@ -133,10 +146,12 @@ F64 LLWLAnimator::getDayTime() mDayTime = (LLTimer::getElapsedSeconds() - mStartTime) / mDayRate; // clamp it - if(mDayTime < 0) { + if(mDayTime < 0) + { mDayTime = 0; } - while(mDayTime > 1) { + while(mDayTime > 1) + { mDayTime--; } @@ -150,9 +165,12 @@ void LLWLAnimator::setDayTime(F64 dayTime) mDayTime = dayTime; // clamp it - if(mDayTime < 0) { + if(mDayTime < 0) + { mDayTime = 0; - } else if(mDayTime > 1) { + } + else if(mDayTime > 1) + { mDayTime = 1; } } diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp index 577d1edc1..abb9cd03f 100644 --- a/indra/newview/llwldaycycle.cpp +++ b/indra/newview/llwldaycycle.cpp @@ -96,13 +96,13 @@ void LLWLDayCycle::loadDayCycle(const std::string & fileName) // check each param name exists in param manager bool success; LLWLParamSet pset; - success = LLWLParamManager::instance()->getParamSet(day_data[i][1].asString(), pset); + success = LLWLParamManager::getInstance()->getParamSet(day_data[i][1].asString(), pset); if(!success) { // alert the user LLSD args; args["SKY"] = day_data[i][1].asString(); - LLNotifications::instance().add("WLMissingSky", args); + LLNotifications::instance().add("WLMissingSky", args, LLSD()); continue; } @@ -203,7 +203,7 @@ bool LLWLDayCycle::changeKeyParam(F32 time, const std::string & name) // just remove and add back // make sure param exists LLWLParamSet tmp; - bool stat = LLWLParamManager::instance()->getParamSet(name, tmp); + bool stat = LLWLParamManager::getInstance()->getParamSet(name, tmp); if(stat == false) { return stat; @@ -249,7 +249,7 @@ bool LLWLDayCycle::getKeyedParam(F32 time, LLWLParamSet& param) std::map<F32, std::string>::iterator mIt = mTimeMap.find(time); if(mIt != mTimeMap.end()) { - return LLWLParamManager::instance()->getParamSet(mIt->second, param); + return LLWLParamManager::getInstance()->getParamSet(mIt->second, param); } // return error if not found diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index d3fc32835..35ee41de8 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -61,9 +61,10 @@ #include "llfloaterdaycycle.h" #include "llfloaterenvsettings.h" -#include "curl/curl.h" +#include "llviewershadermgr.h" +#include "llglslshader.h" -LLWLParamManager * LLWLParamManager::sInstance = NULL; +#include "curl/curl.h" LLWLParamManager::LLWLParamManager() : @@ -286,6 +287,25 @@ void LLWLParamManager::updateShaderUniforms(LLGLSLShader * shader) } +void LLWLParamManager::updateShaderLinks() +{ + mShaderList.clear(); + LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; + end_shaders = LLViewerShaderMgr::instance()->endShaders(); + for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) + { + if (shaders_iter->mProgramObject != 0 + && (gPipeline.canUseWindLightShaders() || shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)) + { + if( glGetUniformLocationARB(shaders_iter->mProgramObject,"lightnorm")>=0 || + glGetUniformLocationARB(shaders_iter->mProgramObject,"camPosLocal")>=0 || + glGetUniformLocationARB(shaders_iter->mProgramObject,"scene_light_strength")>=0 || + glGetUniformLocationARB(shaders_iter->mProgramObject,"cloud_pos_density1")>=0) + mShaderList.push_back(&(*shaders_iter)); + } + } +} + void LLWLParamManager::propagateParameters(void) { LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WLPARAM); @@ -337,16 +357,10 @@ void LLWLParamManager::propagateParameters(void) mCurParams.set("lightnorm", mLightDir); // bind the variables for all shaders only if we're using WindLight - LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; - end_shaders = LLViewerShaderMgr::instance()->endShaders(); - for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) + std::vector<LLGLSLShader*>::iterator shaders_iter=mShaderList.begin(); + for(; shaders_iter != mShaderList.end(); ++shaders_iter) { - if (shaders_iter->mProgramObject != 0 - && (gPipeline.canUseWindLightShaders() - || shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)) - { - shaders_iter->mUniformsDirty = TRUE; - } + (*shaders_iter)->mUniformsDirty = TRUE; } // get the cfr version of the sun's direction @@ -400,32 +414,14 @@ void LLWLParamManager::update(LLViewerCamera * cam) lightNorm3 *= LLQuaternion(-(camYaw + camYawDelta), LLVector3(0.f, 1.f, 0.f)); mRotatedLightDir = LLVector4(lightNorm3, 0.f); - LLViewerShaderMgr::shader_iter shaders_iter, end_shaders; - end_shaders = LLViewerShaderMgr::instance()->endShaders(); - for(shaders_iter = LLViewerShaderMgr::instance()->beginShaders(); shaders_iter != end_shaders; ++shaders_iter) + std::vector<LLGLSLShader*>::iterator shaders_iter=mShaderList.begin(); + for(; shaders_iter != mShaderList.end(); ++shaders_iter) { - if (shaders_iter->mProgramObject != 0 - && (gPipeline.canUseWindLightShaders() - || shaders_iter->mShaderGroup == LLGLSLShader::SG_WATER)) - { - shaders_iter->mUniformsDirty = TRUE; - } + (*shaders_iter)->mUniformsDirty = TRUE; } } } -// static -void LLWLParamManager::initClass(void) -{ - instance(); -} - -// static -void LLWLParamManager::cleanupClass() -{ - delete sInstance; - sInstance = NULL; -} void LLWLParamManager::resetAnimator(F32 curTime, bool run) { @@ -537,27 +533,22 @@ bool LLWLParamManager::removeParamSet(const std::string& name, bool delete_from_ } -// static -LLWLParamManager * LLWLParamManager::instance() +// virtual static +void LLWLParamManager::initSingleton() { - if(NULL == sInstance) - { - sInstance = new LLWLParamManager(); - sInstance->loadPresets(LLStringUtil::null); + loadPresets(LLStringUtil::null); - // load the day - sInstance->mDay.loadDayCycle(gSavedSettings.getString("AscentActiveDayCycle")); + // load the day + mDay.loadDayCycle(gSavedSettings.getString("AscentActiveDayCycle")); - // *HACK - sets cloud scrolling to what we want... fix this better in the future - sInstance->getParamSet("Default", sInstance->mCurParams); + // *HACK - sets cloud scrolling to what we want... fix this better in the future + getParamSet("Default", mCurParams); - // set it to noon - sInstance->resetAnimator(0.5, true); + // set it to noon + resetAnimator(0.5, true); - // but use linden time sets it to what the estate is - sInstance->mAnimator.mUseLindenTime = true; - } + // but use linden time sets it to what the estate is + mAnimator.mUseLindenTime = true; - return sInstance; } diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h index a117dc1b0..e89f1ee22 100644 --- a/indra/newview/llwlparammanager.h +++ b/indra/newview/llwlparammanager.h @@ -122,15 +122,14 @@ struct WLFloatControl { }; /// WindLight parameter manager class - what controls all the wind light shaders -class LLWLParamManager +class LLWLParamManager : public LLSingleton<LLWLParamManager> { + LOG_CLASS(LLWLParamManager); + public: - LLWLParamManager(); - ~LLWLParamManager(); + void updateShaderLinks(); - /// load a preset file - void loadPresets(const std::string & fileName); /// save the preset file void savePresets(const std::string & fileName); @@ -193,8 +192,8 @@ public: /// returns true if successful bool removeParamSet(const std::string& name, bool delete_from_disk); - // singleton pattern implementation - static LLWLParamManager * instance(); + /// @return all named windlight presets. + const std::map<std::string, LLWLParamSet>& getPresets() const { return mParamList; } public: @@ -249,13 +248,22 @@ public: F32 mDomeOffset; F32 mDomeRadius; - // list of all the parameters, listed by name - std::map<std::string, LLWLParamSet> mParamList; private: - // our parameter manager singleton instance - static LLWLParamManager * sInstance; + /// load a preset file + friend class LLWLAnimator; + void loadPresets(const std::string & fileName); + + friend class LLSingleton<LLWLParamManager>; + /*virtual*/ void initSingleton(); + LLWLParamManager(); + ~LLWLParamManager(); + + // list of all the parameters, listed by name + std::map<std::string, LLWLParamSet> mParamList; + + std::vector<LLGLSLShader *> mShaderList; }; diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp index ea9c00ae8..4f62db627 100644 --- a/indra/newview/llwlparamset.cpp +++ b/indra/newview/llwlparamset.cpp @@ -266,7 +266,6 @@ void LLWLParamSet::setEastAngle(float val) void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) { // set up the iterators - LLSD::map_iterator cIt = mParamValues.beginMap(); // keep cloud positions and coverage the same /// TODO masking will do this later @@ -279,55 +278,39 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight) LLSD srcVal; LLSD destVal; - // do the interpolation for all the ones saved as vectors - // skip the weird ones - for(; cIt != mParamValues.endMap(); cIt++) { + // Iterate through values + for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter) + { - // check params to make sure they're actually there - if(src.mParamValues.has(cIt->first)) + // If param exists in both src and dest, set the holder variables, otherwise skip + if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first)) { - srcVal = src.mParamValues[cIt->first]; + srcVal = src.mParamValues[iter->first]; + destVal = dest.mParamValues[iter->first]; } else { continue; } - if(dest.mParamValues.has(cIt->first)) + if(iter->second.isReal()) // If it's a real, interpolate directly { - destVal = dest.mParamValues[cIt->first]; + iter->second = srcVal.asReal() + ((destVal.asReal() - srcVal.asReal()) * weight); } - else + else if(iter->second.isArray() && iter->second[0].isReal() // If it's an array of reals, loop through the reals and interpolate on those + && iter->second.size() == srcVal.size() && iter->second.size() == destVal.size()) + { + // Actually do interpolation: old value + (difference in values * factor) + for(int i=0; i < iter->second.size(); ++i) + { + // iter->second[i] = (1.f-weight)*(F32)srcVal[i].asReal() + weight*(F32)destVal[i].asReal(); // old way of doing it -- equivalent but one more operation + iter->second[i] = srcVal[i].asReal() + ((destVal[i].asReal() - srcVal[i].asReal()) * weight); + } + } + else // Else, skip { continue; } - - // skip if not a vector - if(!cIt->second.isArray()) - { - continue; - } - - // only Real vectors allowed - if(!cIt->second[0].isReal()) - { - continue; - } - - // make sure all the same size - if( cIt->second.size() != srcVal.size() || - cIt->second.size() != destVal.size()) - { - continue; - } - - // more error checking might be necessary; - - for(int i=0; i < cIt->second.size(); ++i) - { - cIt->second[i] = (1.0f - weight) * (F32) srcVal[i].asReal() + - weight * (F32) destVal[i].asReal(); - } } // now mix the extra parameters diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h index 21d646f3b..f403fbe23 100644 --- a/indra/newview/llwlparamset.h +++ b/indra/newview/llwlparamset.h @@ -38,10 +38,9 @@ #include "v4math.h" #include "v4color.h" -#include "llviewershadermgr.h" -class LLFloaterWindLight; class LLWLParamSet; +class LLGLSLShader; /// A class representing a set of parameter values for the WindLight shaders. class LLWLParamSet { diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index fbceaa9cc..38317f5e0 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -46,6 +46,7 @@ #include "llregionhandle.h" #include "llsurface.h" #include "llviewercamera.h" +#include "llviewertexture.h" #include "llviewertexturelist.h" #include "llviewernetwork.h" #include "llviewerobjectlist.h" @@ -78,12 +79,12 @@ const S32 WORLD_PATCH_SIZE = 16; extern LLColor4U MAX_WATER_COLOR; -const U32 LLWorld::mWidth = 256; +U32 LLWorld::mWidth = 256; // meters/point, therefore mWidth * mScale = meters per edge const F32 LLWorld::mScale = 1.f; -const F32 LLWorld::mWidthInMeters = mWidth * mScale; +F32 LLWorld::mWidthInMeters = mWidth * mScale; // // Functions @@ -138,7 +139,7 @@ void LLWorld::destroyClass() } -LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) +LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host, const U32 ®ion_size_x, const U32 ®ion_size_y) { LLMemType mt(LLMemType::MTYPE_REGIONS); llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl; @@ -171,9 +172,11 @@ LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) U32 iindex = 0; U32 jindex = 0; + mWidth = region_size_x; + mWidthInMeters = mWidth * mScale; from_region_handle(region_handle, &iindex, &jindex); - S32 x = (S32)(iindex/mWidth); - S32 y = (S32)(jindex/mWidth); + S32 x = (S32)(iindex/256); + S32 y = (S32)(jindex/256); llinfos << "Adding new region (" << x << ":" << y << ")" << llendl; llinfos << "Host: " << host << llendl; @@ -439,9 +442,9 @@ BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global) // Allow objects to go up to their radius underground. -F32 LLWorld::getMinAllowedZ(LLViewerObject* object) +F32 LLWorld::getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos) { - F32 land_height = resolveLandHeightGlobal(object->getPositionGlobal()); + F32 land_height = resolveLandHeightGlobal(global_pos); F32 radius = 0.5f * object->getScale().length(); return land_height - radius; } @@ -604,7 +607,7 @@ void LLWorld::updateVisibilities() region_list_t::iterator curiter = iter++; LLViewerRegion* regionp = *curiter; F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); - F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); + F32 radius = 0.5f*(F32) sqrt(height * height + diagonal_squared); if (!regionp->getLand().hasZData() || LLViewerCamera::getInstance()->sphereInFrustum(regionp->getCenterAgent(), radius)) { @@ -625,7 +628,7 @@ void LLWorld::updateVisibilities() } F32 height = regionp->getLand().getMaxZ() - regionp->getLand().getMinZ(); - F32 radius = 0.5f*fsqrtf(height * height + diagonal_squared); + F32 radius = 0.5f*(F32) sqrt(height * height + diagonal_squared); if (LLViewerCamera::getInstance()->sphereInFrustum(regionp->getCenterAgent(), radius)) { regionp->calculateCameraDistance(); @@ -653,8 +656,8 @@ void LLWorld::updateRegions(F32 max_update_time) BOOL did_one = FALSE; // Perform idle time updates for the regions (and associated surfaces) - for (region_list_t::iterator iter = mRegionList.begin(); - iter != mRegionList.end(); ++iter) + for (region_list_t::iterator iter = mActiveRegionList.begin()/*mRegionList.begin()*/; + iter != mActiveRegionList.end()/*mRegionList.end()*/; ++iter) { LLViewerRegion* regionp = *iter; F32 max_time = max_update_time - update_timer.getElapsedTimeF32(); @@ -823,7 +826,7 @@ F32 LLWorld::getLandFarClip() const void LLWorld::setLandFarClip(const F32 far_clip) { - static S32 const rwidth = (S32)REGION_WIDTH_U32; + static S32 const rwidth = (S32)getRegionWidthInMeters(); S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth; S32 const n2 = (llceil(far_clip) - 1) / rwidth; bool need_water_objects_update = n1 != n2; @@ -1253,9 +1256,21 @@ void process_enable_simulator(LLMessageSystem *msg, void **user_data) // which simulator should we modify? LLHost sim(ip_u32, port); + U32 region_size_x = 256; + msg->getU32Fast(_PREHASH_SimulatorInfo, _PREHASH_RegionSizeX, region_size_x); + + U32 region_size_y = 256; + msg->getU32Fast(_PREHASH_SimulatorInfo, _PREHASH_RegionSizeY, region_size_y); + + if (region_size_y == 0 || region_size_x == 0) + { + region_size_x = 256; + region_size_y = 256; + } + // Viewer trusts the simulator. msg->enableCircuit(sim, TRUE); - LLWorld::getInstance()->addRegion(handle, sim); + LLWorld::getInstance()->addRegion(handle, sim, region_size_x, region_size_y); // give the simulator a message it can use to get ip and port llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl; @@ -1411,6 +1426,8 @@ static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3 void LLWorld::getAvatars(std::vector<LLUUID>* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const { + F32 radius_squared = radius * radius; + if(avatar_ids != NULL) { avatar_ids->clear(); @@ -1419,6 +1436,33 @@ void LLWorld::getAvatars(std::vector<LLUUID>* avatar_ids, std::vector<LLVector3d { positions->clear(); } + // get the list of avatars from the character list first, so distances are correct + // when agent is above 1020m and other avatars are nearby + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; + if(!pVOAvatar->isDead() && !pVOAvatar->isSelf()) + { + LLUUID uuid = pVOAvatar->getID(); + if(!uuid.isNull()) + { + LLVector3d pos_global = pVOAvatar->getPositionGlobal(); + if(dist_vec_squared(pos_global, relative_to) <= radius_squared) + { + if(positions != NULL) + { + positions->push_back(pos_global); + } + if(avatar_ids !=NULL) + { + avatar_ids->push_back(uuid); + } + } + } + } + } + // region avatars added for situations where radius is greater than RenderFarClip for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -1428,50 +1472,16 @@ void LLWorld::getAvatars(std::vector<LLUUID>* avatar_ids, std::vector<LLVector3d for (S32 i = 0; i < count; i++) { LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global); - if(dist_vec(pos_global, relative_to) <= radius) + if(dist_vec_squared(pos_global, relative_to) <= radius_squared) { - if(positions != NULL) - { - positions->push_back(pos_global); - } - if(avatar_ids != NULL) - { - avatar_ids->push_back(regionp->mMapAvatarIDs.get(i)); - } - } - } - } - // retrieve the list of close avatars from viewer objects as well - // for when we are above 1000m, only do this when we are retrieving - // uuid's too as there could be duplicates - if(avatar_ids != NULL) - { - for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); - iter != LLCharacter::sInstances.end(); ++iter) - { - LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; - if(pVOAvatar->isDead() || pVOAvatar->isSelf()) - continue; - LLUUID uuid = pVOAvatar->getID(); - if(uuid.isNull()) - continue; - LLVector3d pos_global = pVOAvatar->getPositionGlobal(); - if(dist_vec(pos_global, relative_to) <= radius) - { - bool found = false; - uuid_vec_t::iterator sel_iter = avatar_ids->begin(); - for (; sel_iter != avatar_ids->end(); sel_iter++) - { - if(*sel_iter == uuid) - { - found = true; - break; - } - } - if(!found) + LLUUID uuid = regionp->mMapAvatarIDs.get(i); + // if this avatar doesn't already exist in the list, add it + if(uuid.notNull() && avatar_ids!=NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end()) { if(positions != NULL) + { positions->push_back(pos_global); + } avatar_ids->push_back(uuid); } } diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index ec6e45b23..d079582d1 100644 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -71,7 +71,7 @@ public: LLWorld(); void destroyClass(); - LLViewerRegion* addRegion(const U64 ®ion_handle, const LLHost &host); + LLViewerRegion* addRegion(const U64 ®ion_handle, const LLHost &host, const U32 ®ion_size_x, const U32 ®ion_size_y); // safe to call if already present, does the "right thing" if // hosts are same, or if hosts are different, etc... void removeRegion(const LLHost &host); @@ -95,7 +95,7 @@ public: // Return the lowest allowed Z point to prevent objects from being moved // underground. - F32 getMinAllowedZ(LLViewerObject* object); + F32 getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos); // takes a line segment defined by point_a and point_b, then // determines the closest (to point_a) point of intersection that is @@ -170,12 +170,12 @@ private: region_list_t mCulledRegionList; // Number of points on edge - static const U32 mWidth; + static U32 mWidth; // meters/point, therefore mWidth * mScale = meters per edge static const F32 mScale; - static const F32 mWidthInMeters; + static F32 mWidthInMeters; F32 mLandFarClip; // Far clip distance for land. LLPatchVertexArray mLandPatch; diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index d4c9c7f66..575e8120b 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -484,13 +484,15 @@ void LLWorldMapView::draw() gGL.setSceneBlendType(LLRender::BT_ALPHA); // Infohubs - if (gSavedSettings.getBOOL("MapShowInfohubs")) //(sMapScale >= sThresholdB) + static const LLCachedControl<bool> map_show_infohubs("MapShowInfohubs"); + if (map_show_infohubs) //(sMapScale >= sThresholdB) { drawGenericItems(LLWorldMap::getInstance()->mInfohubs, sInfohubImage); } // Telehubs - if (gSavedSettings.getBOOL("MapShowTelehubs")) //(sMapScale >= sThresholdB) + static const LLCachedControl<bool> map_show_telehubs("MapShowTelehubs"); + if (map_show_telehubs) //(sMapScale >= sThresholdB) { drawGenericItems(LLWorldMap::getInstance()->mTelehubs, sTelehubImage); } @@ -502,7 +504,8 @@ void LLWorldMapView::draw() drawImage(home, sHomeImage); } - if (gSavedSettings.getBOOL("MapShowLandForSale")) + static const LLCachedControl<bool> map_show_land_for_sale("MapShowLandForSale"); + if (map_show_land_for_sale) { drawGenericItems(LLWorldMap::getInstance()->mLandForSale, sForSaleImage); // for 1.23, we're showing normal land and adult land in the same UI; you don't @@ -514,12 +517,7 @@ void LLWorldMapView::draw() } } - if (gSavedSettings.getBOOL("MapShowPGEvents") || - gSavedSettings.getBOOL("MapShowMatureEvents") || - gSavedSettings.getBOOL("MapShowAdultEvents") ) - { - drawEvents(); - } + drawEvents(); // Now draw your avatar after all that other stuff. LLVector3d pos_global = gAgent.getPositionGlobal(); @@ -541,7 +539,8 @@ void LLWorldMapView::draw() // Draw icons for the avatars in each region. // Drawn after your avatar so you can see nearby people. - if (gSavedSettings.getBOOL("MapShowPeople")) + static const LLCachedControl<bool> map_show_people("MapShowPeople"); + if (map_show_people) { drawAgents(); } @@ -887,7 +886,8 @@ void LLWorldMapView::drawTiles(S32 width, S32 height) { gGL.vertex3f(right, top, 0.f); gGL.end(); - if (gSavedSettings.getBOOL("MapShowLandForSale") && overlayimage && overlayimage->hasGLTexture()) + static const LLCachedControl<bool> map_show_land_for_sale("MapShowLandForSale"); + if (map_show_land_for_sale && overlayimage && overlayimage->hasGLTexture()) { gGL.getTexUnit(0)->bind(overlayimage); gGL.color4f(1.f, 1.f, 1.f, alpha); @@ -1057,9 +1057,13 @@ void LLWorldMapView::drawEvents() bool mature_enabled = gAgent.canAccessMature(); bool adult_enabled = gAgent.canAccessAdult(); - BOOL show_pg = gSavedSettings.getBOOL("MapShowPGEvents"); - BOOL show_mature = mature_enabled && gSavedSettings.getBOOL("MapShowMatureEvents"); - BOOL show_adult = adult_enabled && gSavedSettings.getBOOL("MapShowAdultEvents"); + static const LLCachedControl<bool> map_show_pg_events("MapShowPGEvents"); + static const LLCachedControl<bool> map_show_mature_events("MapShowMatureEvents"); + static const LLCachedControl<bool> map_show_adult_events("MapShowAdultEvents"); + + BOOL show_pg = map_show_pg_events; + BOOL show_mature = mature_enabled && map_show_mature_events; + BOOL show_adult = adult_enabled && map_show_adult_events; // First the non-selected events LLWorldMap::item_info_list_t::const_iterator e; @@ -1874,8 +1878,9 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, } // Select event you clicked on - if (gSavedSettings.getBOOL("MapShowPGEvents")) - { + static const LLCachedControl<bool> map_show_pg_events("MapShowPGEvents"); + if (map_show_pg_events) + { for (it = LLWorldMap::getInstance()->mPGEvents.begin(); it != LLWorldMap::getInstance()->mPGEvents.end(); ++it) { LLItemInfo& event = *it; @@ -1889,7 +1894,8 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, } } } - if (gSavedSettings.getBOOL("MapShowMatureEvents")) + static const LLCachedControl<bool> map_show_mature_events("MapShowMatureEvents"); + if (map_show_mature_events) { for (it = LLWorldMap::getInstance()->mMatureEvents.begin(); it != LLWorldMap::getInstance()->mMatureEvents.end(); ++it) { @@ -1904,7 +1910,8 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, } } } - if (gSavedSettings.getBOOL("MapShowAdultEvents")) + static const LLCachedControl<bool> map_show_adult_events("MapShowAdultEvents"); + if (map_show_adult_events) { for (it = LLWorldMap::getInstance()->mAdultEvents.begin(); it != LLWorldMap::getInstance()->mAdultEvents.end(); ++it) { @@ -1919,8 +1926,8 @@ void LLWorldMapView::handleClick(S32 x, S32 y, MASK mask, } } } - - if (gSavedSettings.getBOOL("MapShowLandForSale")) + static const LLCachedControl<bool> map_show_land_for_sale("MapShowLandForSale"); + if (map_show_land_for_sale) { for (it = LLWorldMap::getInstance()->mLandForSale.begin(); it != LLWorldMap::getInstance()->mLandForSale.end(); ++it) { diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index c9254d740..6d18fbc66 100644 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -319,16 +319,18 @@ bool LLXMLRPCTransaction::Impl::process() } } - const F32 MAX_PROCESSING_TIME = 0.05f; - LLTimer timer; + //const F32 MAX_PROCESSING_TIME = 0.05f; + //LLTimer timer; - while (mCurlRequest->perform() > 0) + mCurlRequest->perform(); + + /*while (mCurlRequest->perform() > 0) { if (timer.getElapsedTimeF32() >= MAX_PROCESSING_TIME) { return false; } - } + }*/ while(1) { @@ -429,7 +431,7 @@ void LLXMLRPCTransaction::Impl::setStatus(Status status, mStatusMessage = "Despite our best efforts, something unexpected has gone wrong. \n" " \n" - "Please check " + gHippoGridManager->getCurrentGrid()->getGridNick() + "'s status \n" + "Please check " + gHippoGridManager->getCurrentGrid()->getGridName() + "'s status \n" "to see if there is a known problem with the service."; //mStatusURI = "http://secondlife.com/status/"; @@ -447,7 +449,7 @@ void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code) case CURLE_COULDNT_RESOLVE_HOST: message = "DNS could not resolve the host name.\n" - "Please verify that you can connect to " + gHippoGridManager->getCurrentGrid()->getGridNick() + "'s\n" + "Please verify that you can connect to " + gHippoGridManager->getCurrentGrid()->getGridName() + "'s\n" "web site. If you can, but continue to receive this error,\n" "please go to the support section and report this problem."; break; @@ -456,7 +458,7 @@ void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code) message = "The login server couldn't verify itself via SSL.\n" "If you continue to receive this error, please go\n" - "to the Support section of " + gHippoGridManager->getCurrentGrid()->getGridNick() + "'s web site\n" + "to the Support section of " + gHippoGridManager->getCurrentGrid()->getGridName() + "'s web site\n" "and report the problem."; break; @@ -468,7 +470,7 @@ void LLXMLRPCTransaction::Impl::setCurlStatus(CURLcode code) "are set correctly.\n" "\n" "If you continue to receive this error, please go\n" - "to the Support section of " + gHippoGridManager->getCurrentGrid()->getGridNick() + "'s web site\n" + "to the Support section of " + gHippoGridManager->getCurrentGrid()->getGridName() + "'s web site\n" "and report the problem."; break; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 6eb4b56b4..7ed337b59 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -52,6 +52,7 @@ #include "llui.h" #include "llglheaders.h" #include "llrender.h" +#include "llwindow.h" // newview includes #include "llagent.h" @@ -70,6 +71,9 @@ #include "llgldbg.h" #include "llhudmanager.h" #include "lllightconstants.h" +#if MESH_ENABLED +#include "llmeshrepository.h" +#endif //MESH_ENABLED #include "llresmgr.h" #include "llselectmgr.h" #include "llsky.h" @@ -82,6 +86,7 @@ #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" #include "llviewerregion.h" // for audio debugging. +#include "llviewerstats.h" #include "llviewerwindow.h" // For getSpinAxis #include "llvoavatar.h" #include "llvoground.h" @@ -157,8 +162,6 @@ static S32 sDelayedVBOEnable = 0; BOOL gAvatarBacklight = FALSE; -BOOL gRenderForSelect = FALSE; - BOOL gDebugPipeline = FALSE; LLPipeline gPipeline; const LLMatrix4* gGLLastMatrix = NULL; @@ -311,10 +314,12 @@ static const U32 gl_cube_face[] = void validate_framebuffer_object(); -void addDeferredAttachments(LLRenderTarget& target) +bool addDeferredAttachments(LLRenderTarget& target) { - target.addColorAttachment(GL_RGBA); //specular - target.addColorAttachment(GL_RGBA); //normal+z + bool ret1 = target.addColorAttachment(GL_RGBA); + bool ret2 = target.addColorAttachment(GL_RGBA); + return ret1 && //specular + ret2; //normal+z } LLPipeline::LLPipeline() : @@ -369,6 +374,7 @@ void LLPipeline::init() sDynamicLOD = gSavedSettings.getBOOL("RenderDynamicLOD"); sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO"); + LLVertexBuffer::sForceStrideMode = gSavedSettings.getU32("ShyotlRenderVBOStrideMode"); LLVertexBuffer::sOmitBlank = gSavedSettings.getBOOL("SianaRenderOmitBlankVBO"); LLVertexBuffer::sPreferStreamDraw = gSavedSettings.getBOOL("RenderPreferStreamDraw"); sRenderAttachedLights = gSavedSettings.getBOOL("RenderAttachedLights"); @@ -387,7 +393,7 @@ void LLPipeline::init() getPool(LLDrawPool::POOL_BUMP); getPool(LLDrawPool::POOL_GLOW); - mTrianglesDrawnStat.reset(); + LLViewerStats::getInstance()->mTrianglesDrawnStat.reset(); resetFrameStats(); for (U32 i = 0; i < NUM_RENDER_TYPES; ++i) @@ -527,8 +533,8 @@ void LLPipeline::resizeScreenTexture() { if (gPipeline.canUseVertexShaders() && assertInitialized()) { - GLuint resX = gViewerWindow->getWindowDisplayWidth(); - GLuint resY = gViewerWindow->getWindowDisplayHeight(); + GLuint resX = gViewerWindow->getWorldViewWidthRaw(); + GLuint resY = gViewerWindow->getWorldViewHeightRaw(); allocateScreenBuffer(resX,resY); } @@ -537,6 +543,49 @@ void LLPipeline::resizeScreenTexture() void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { U32 samples = gSavedSettings.getU32("RenderFSAASamples"); + + //try to allocate screen buffers at requested resolution and samples + // - on failure, shrink number of samples and try again + // - if not multisampled, shrink resolution and try again (favor X resolution over Y) + // Make sure to call "releaseScreenBuffers" after each failure to cleanup the partially loaded state + + if (!allocateScreenBuffer(resX, resY, samples)) + { + releaseScreenBuffers(); + //reduce number of samples + while (samples > 0) + { + samples /= 2; + if (allocateScreenBuffer(resX, resY, samples)) + { //success + return; + } + releaseScreenBuffers(); + } + + //reduce resolution + while (resY > 0 && resX > 0) + { + resY /= 2; + if (allocateScreenBuffer(resX, resY, samples)) + { + return; + } + releaseScreenBuffers(); + + resX /= 2; + if (allocateScreenBuffer(resX, resY, samples)) + { + return; + } + releaseScreenBuffers(); + } + + llwarns << "Unable to allocate screen buffer at any resolution!" << llendl; + } +} +bool LLPipeline::allocateScreenBuffer(U32 resX, U32 resY, U32 samples) +{ U32 res_mod = gSavedSettings.getU32("RenderResolutionDivisor"); if (res_mod > 1 && res_mod < resX && res_mod < resY) { @@ -554,22 +603,22 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) //allocate deferred rendering color buffers static const LLCachedControl<bool> shadow_precision("DeferredHighPrecision",true); const GLuint format = shadow_precision ? GL_RGBA : GL_RGBA16F_ARB; //TO-DO: Profile 16bit format later - mDeferredScreen.allocate(resX, resY, format, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); - addDeferredAttachments(mDeferredScreen); + if (!mDeferredScreen.allocate(resX, resY, format, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + if (!mDeferredDepth.allocate(resX, resY, 0, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; + if (!addDeferredAttachments(mDeferredScreen)) return false; - mScreen.allocate(resX, resY, format, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + if (!mScreen.allocate(resX, resY, format, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; #if LL_DARWIN // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO - mEdgeMap.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + if (!mEdgeMap.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; #else - mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + if (!mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; #endif if (shadow_detail > 0 || ssao) { //only need mDeferredLight[0] for shadows OR ssao - mDeferredLight[0].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + if (!mDeferredLight[0].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; } else { @@ -578,7 +627,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) if (ssao || gi) { //only need mDeferredLight[1] for ssao... and GI - mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + if (!mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; } else { @@ -587,14 +636,14 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) if (gi) { //only need mDeferredLight[2] and mGIMapPost for gi - mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + if (!mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; for (U32 i = 0; i < 2; i++) { #if LL_DARWIN // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO - mGIMapPost[i].allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + if (!mGIMapPost[i].allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; #else - mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + if (!mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; #endif } } @@ -622,7 +671,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { //allocate 4 sun shadow maps for (U32 i = 0; i < 4; i++) { - mShadow[i].allocate(U32(resX*scale),U32(resY*scale), shadow_fmt, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE); + if (!mShadow[i].allocate(U32(resX*scale),U32(resY*scale), shadow_fmt, TRUE, FALSE, LLTexUnit::TT_RECT_TEXTURE)) return false; } } else @@ -640,7 +689,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { //allocate two spot shadow maps for (U32 i = 4; i < 6; i++) { - mShadow[i].allocate(width, height, shadow_fmt, TRUE, FALSE); + if (!mShadow[i].allocate(width, height, shadow_fmt, TRUE, FALSE)) return false; } } else @@ -653,7 +702,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) width = nhpo2(resX)/2; height = nhpo2(resY)/2; - mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE); + if (!mLuminanceMap.allocate(width,height, GL_RGBA, FALSE, FALSE)) return false; } else { @@ -675,7 +724,7 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) mEdgeMap.release(); mLuminanceMap.release(); - mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE); + if (!mScreen.allocate(resX, resY, GL_RGBA, TRUE, TRUE, LLTexUnit::TT_RECT_TEXTURE, FALSE)) return false; } @@ -685,14 +734,14 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) { static const LLCachedControl<bool> shadow_precision("DeferredHighPrecision",true); const GLuint format = shadow_precision ? GL_RGBA : GL_RGBA16F_ARB; //TO-DO: Profile 16bit format later - mSampleBuffer.allocate(resX,resY,format,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); - addDeferredAttachments(mSampleBuffer); + if (!mSampleBuffer.allocate(resX,resY,format,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples)) return false; + if (!addDeferredAttachments(mSampleBuffer))return false; mDeferredScreen.setSampleBuffer(&mSampleBuffer); mEdgeMap.setSampleBuffer(&mSampleBuffer); } else { - mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples); + if(!mSampleBuffer.allocate(resX,resY,GL_RGBA,TRUE,TRUE,LLTexUnit::TT_RECT_TEXTURE,FALSE,samples)) return false;; } mScreen.setSampleBuffer(&mSampleBuffer); @@ -707,19 +756,20 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY) if (LLPipeline::sRenderDeferred) { //share depth buffer between deferred targets mDeferredScreen.shareDepthBuffer(mScreen); - for (U32 i = 0; i < 3; i++) + /*for (U32 i = 0; i < 3; i++) { //share stencil buffer with screen space lightmap to stencil out sky if (mDeferredLight[i].getTexture(0)) { mDeferredScreen.shareDepthBuffer(mDeferredLight[i]); } - } + }*/ } gGL.getTexUnit(0)->disable(); stop_glerror(); + return true; } //static @@ -762,6 +812,19 @@ void LLPipeline::releaseGLBuffers() mWaterRef.release(); mWaterDis.release(); + + for (U32 i = 0; i < 3; i++) + { + mGlow[i].release(); + } + + releaseScreenBuffers(); + + LLVOAvatar::resetImpostors(); +} + +void LLPipeline::releaseScreenBuffers() +{ mScreen.release(); mSampleBuffer.release(); mDeferredScreen.release(); @@ -781,13 +844,6 @@ void LLPipeline::releaseGLBuffers() { mShadow[i].release(); } - - for (U32 i = 0; i < 3; i++) - { - mGlow[i].release(); - } - - LLVOAvatar::resetImpostors(); } void LLPipeline::createGLBuffers() @@ -807,9 +863,9 @@ void LLPipeline::createGLBuffers() stop_glerror(); - GLuint resX = gViewerWindow->getWindowDisplayWidth(); - GLuint resY = gViewerWindow->getWindowDisplayHeight(); - + GLuint resX = gViewerWindow->getWorldViewWidthRaw(); + GLuint resY = gViewerWindow->getWorldViewHeightRaw(); + if (LLPipeline::sRenderGlow) { //screen space glow buffers const U32 glow_res = llmax(1, @@ -1389,7 +1445,7 @@ void LLPipeline::resetFrameStats() { assertInitialized(); - mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f); + LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f); if (mBatchCount > 0) { @@ -1566,6 +1622,31 @@ F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera return radius*radius * F_PI; } +//static +F32 LLPipeline::calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera) +{ + LLVector4a origin; + origin.load3(camera.getOrigin().mV); + + LLVector4a lookAt; + lookAt.setSub(center, origin); + F32 dist = lookAt.getLength3().getF32(); + + //ramp down distance for nearby objects + //shrink dist by dist/16. + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } + + //get area of circle around node + F32 app_angle = atanf(size.getLength3().getF32()/dist); + F32 radius = app_angle*LLDrawable::sCurPixelAngle; + return radius*radius * F_PI; +} + void LLPipeline::grabReferences(LLCullResult& result) { sCull = &result; @@ -1887,6 +1968,14 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl LLGLDepthTest depth(GL_TRUE, GL_FALSE); + bool bound_shader = false; + if (gPipeline.canUseVertexShaders() && LLGLSLShader::sCurBoundShader == 0) + { //if no shader is currently bound, use the occlusion shader instead of fixed function if we can + // (shadow render uses a special shader that clamps to clip planes) + bound_shader = true; + gOcclusionProgram.bind(); + } + for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { @@ -1914,12 +2003,16 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl } } + if (bound_shader) + { + gOcclusionProgram.unbind(); + } + camera.disableUserClipPlane(); - // Render non-windlight sky. - if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && - gSky.mVOSkyp.notNull() && - gSky.mVOSkyp->mDrawable.notNull()) + if (hasRenderType(LLPipeline::RENDER_TYPE_SKY) && + gSky.mVOSkyp.notNull() && + gSky.mVOSkyp->mDrawable.notNull()) { gSky.mVOSkyp->mDrawable->setVisible(camera); sCull->pushDrawable(gSky.mVOSkyp->mDrawable); @@ -1980,7 +2073,7 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) } if (sMinRenderSize > 0.f && - llmax(llmax(group->mBounds[1].mV[0], group->mBounds[1].mV[1]), group->mBounds[1].mV[2]) < sMinRenderSize) + llmax(llmax(group->mBounds[1][0], group->mBounds[1][1]), group->mBounds[1][2]) < sMinRenderSize) { return; } @@ -2042,7 +2135,21 @@ void LLPipeline::doOcclusion(LLCamera& camera) LLGLDepthTest depth(GL_TRUE, GL_FALSE); LLGLDisable cull(GL_CULL_FACE); + + bool bind_shader = LLGLSLShader::sNoFixedFunction && LLGLSLShader::sCurBoundShader == 0; + if (bind_shader) + { + if (LLPipeline::sShadowRender) + { + gDeferredShadowProgram.bind(); + } + else + { + gOcclusionProgram.bind(); + } + } + for (LLCullResult::sg_list_t::iterator iter = sCull->beginOcclusionGroups(); iter != sCull->endOcclusionGroups(); ++iter) { LLSpatialGroup* group = *iter; @@ -2050,6 +2157,18 @@ void LLPipeline::doOcclusion(LLCamera& camera) group->clearOcclusionState(LLSpatialGroup::ACTIVE_OCCLUSION); } + if (bind_shader) + { + if (LLPipeline::sShadowRender) + { + gDeferredShadowProgram.unbind(); + } + else + { + gOcclusionProgram.unbind(); + } + } + gGL.setColorMask(true, false); } } @@ -2083,6 +2202,9 @@ void LLPipeline::rebuildPriorityGroups() assertInitialized(); +#if MESH_ENABLED + gMeshRepo.notifyLoadedMeshes(); +#endif //MESH_ENABLED mGroupQ1Locked = true; // Iterate through all drawables on the priority build queue, @@ -2364,6 +2486,9 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) glClear(GL_DEPTH_BUFFER_BIT); gDepthDirty = TRUE; + LLVector4a offseta; + offseta.load3(offset.mV); + for (LLDrawable::drawable_vector_t::iterator iter = mShiftList.begin(); iter != mShiftList.end(); iter++) { @@ -2372,7 +2497,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) { continue; } - drawablep->shiftPos(offset); + drawablep->shiftPos(offseta); drawablep->clearState(LLDrawable::ON_SHIFT_LIST); } mShiftList.resize(0); @@ -2386,7 +2511,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) LLSpatialPartition* part = region->getSpatialPartition(i); if (part) { - part->shift(offset); + part->shift(offseta); } } } @@ -2417,7 +2542,7 @@ void LLPipeline::markGLRebuild(LLGLUpdate* glu) void LLPipeline::markPartitionMove(LLDrawable* drawable) { if (!drawable->isState(LLDrawable::PARTITION_MOVE) && - !drawable->getPositionGroup().isExactlyZero()) + !drawable->getPositionGroup().equals3(LLVector4a::getZero())) { drawable->setState(LLDrawable::PARTITION_MOVE); mPartitionQ.push_back(drawable); @@ -2985,8 +3110,10 @@ void LLPipeline::postSort(LLCamera& camera) { if (sMinRenderSize > 0.f) { - LLVector3 bounds = (*k)->mExtents[1]-(*k)->mExtents[0]; - if (llmax(llmax(bounds.mV[0], bounds.mV[1]), bounds.mV[2]) > sMinRenderSize) + LLVector4a bounds; + bounds.setSub((*k)->mExtents[1],(*k)->mExtents[0]); + + if (llmax(llmax(bounds[0], bounds[1]), bounds[2]) > sMinRenderSize) { sCull->pushDrawInfo(j->first, *k); } @@ -3168,6 +3295,13 @@ void render_hud_elements() glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); gGL.color4f(1,1,1,1); + + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.bind(); + } + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + if (!LLPipeline::sReflectionRender && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { static const LLCachedControl<U32> fsaa_samples("RenderFSAASamples",0); @@ -3194,6 +3328,10 @@ void render_hud_elements() { LLHUDText::renderAllHUD(); } + if (LLGLSLShader::sNoFixedFunction) + { + gUIProgram.unbind(); + } gGL.flush(); } @@ -3319,14 +3457,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) LLAppViewer::instance()->pingMainloopTimeout("Pipeline:ForceVBO"); - //by bao - //fake vertex buffer updating - //to guaranttee at least updating one VBO buffer every frame - //to walk around the bug caused by ATI card --> DEV-3855 - // - //if(forceVBOUpdate) - // gSky.mVOSkyp->updateDummyVertexBuffer() ; - gFrameStats.start(LLFrameStats::RENDER_GEOM); // Initialize lots of GL state to "safe" values @@ -3372,12 +3502,6 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) } } - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING)) - { - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderForSelect"); - gObjectList.renderObjectsForSelect(camera, gViewerWindow->getVirtualWindowRect()); - } - else { LLFastTimer t(LLFastTimer::FTM_POOLS); @@ -3408,6 +3532,7 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); + LLGLSLShader::bindNoShader(); doOcclusion(camera); } @@ -3440,8 +3565,8 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) check_stack_depth(stack_depth); std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i); LLGLState::checkStates(msg); - LLGLState::checkTextureChannels(msg); - LLGLState::checkClientArrays(msg); + //LLGLState::checkTextureChannels(msg); + //LLGLState::checkClientArrays(msg); } } } @@ -3473,77 +3598,81 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate) occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); + LLGLSLShader::bindNoShader(); doOcclusion(camera); } } LLVertexBuffer::unbind(); LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + //LLGLState::checkTextureChannels(); + //LLGLState::checkClientArrays(); - stop_glerror(); + //stop_glerror(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights"); - - if (!sReflectionRender) + //LLGLState::checkStates(); + //LLGLState::checkTextureChannels(); + //LLGLState::checkClientArrays(); + if (!LLPipeline::sImpostorRender) { - renderHighlights(); - } - - // Contains a list of the faces of objects that are physical or - // have touch-handlers. - mHighlightFaces.clear(); - - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug"); - renderDebug(); + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderHighlights"); - LLVertexBuffer::unbind(); - - if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred) - { - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + if (!sReflectionRender) { - // Render debugging beacons. - gObjectList.renderObjectBeacons(); - gObjectList.resetObjectBeacons(); + renderHighlights(); + } + + // Contains a list of the faces of objects that are physical or + // have touch-handlers. + mHighlightFaces.clear(); + + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderDebug"); + + renderDebug(); + + LLVertexBuffer::unbind(); + + if (!LLPipeline::sReflectionRender && !LLPipeline::sRenderDeferred) + { + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) + { + // Render debugging beacons. + gObjectList.renderObjectBeacons(); + gObjectList.resetObjectBeacons(); + } + else + { + // Make sure particle effects disappear + LLHUDObject::renderAllForTimer(); + } } else { // Make sure particle effects disappear LLHUDObject::renderAllForTimer(); } - } - else - { - // Make sure particle effects disappear - LLHUDObject::renderAllForTimer(); - } - LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd"); + LLAppViewer::instance()->pingMainloopTimeout("Pipeline:RenderGeomEnd"); - //HACK: preserve/restore matrices around HUD render - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) - { - for (U32 i = 0; i < 16; i++) + //HACK: preserve/restore matrices around HUD render + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) { - gGLModelView[i] = saved_modelview[i]; - gGLProjection[i] = saved_projection[i]; + for (U32 i = 0; i < 16; i++) + { + gGLModelView[i] = saved_modelview[i]; + gGLProjection[i] = saved_projection[i]; + } } } LLVertexBuffer::unbind(); LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + //LLGLState::checkTextureChannels(); + //LLGLState::checkClientArrays(); } void LLPipeline::renderGeomDeferred(LLCamera& camera) @@ -3625,8 +3754,8 @@ void LLPipeline::renderGeomDeferred(LLCamera& camera) llerrs << "GL matrix stack corrupted!" << llendl; } LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + //LLGLState::checkTextureChannels(); + //LLGLState::checkClientArrays(); } } } @@ -3681,6 +3810,7 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) occlude = FALSE; gGLLastMatrix = NULL; glLoadMatrixd(gGLModelView); + LLGLSLShader::bindNoShader(); doOcclusion(camera); gGL.setColorMask(true, false); } @@ -3719,8 +3849,8 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera) llerrs << "GL matrix stack corrupted!" << llendl; } LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + //LLGLState::checkTextureChannels(); + //LLGLState::checkClientArrays(); } } } @@ -3794,8 +3924,8 @@ void LLPipeline::renderGeomShadow(LLCamera& camera) LLVertexBuffer::unbind(); LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + //LLGLState::checkTextureChannels(); + //LLGLState::checkClientArrays(); } } else @@ -3849,6 +3979,8 @@ void LLPipeline::renderDebug() glLoadMatrixd(gGLModelView); gGL.setColorMask(true, false); + bool hud_only = hasRenderType(LLPipeline::RENDER_TYPE_HUD); + // Debug stuff. for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -3859,7 +3991,8 @@ void LLPipeline::renderDebug() LLSpatialPartition* part = region->getSpatialPartition(i); if (part) { - if (hasRenderType(part->mDrawableType)) + if ( hud_only && (part->mDrawableType == RENDER_TYPE_HUD || part->mDrawableType == RENDER_TYPE_HUD_PARTICLES) || + !hud_only && hasRenderType(part->mDrawableType) ) { part->renderDebug(); } @@ -4101,185 +4234,6 @@ void LLPipeline::renderDebug() gGL.flush(); } -void LLPipeline::renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect) -{ - assertInitialized(); - - gGL.setColorMask(true, false); - gPipeline.resetDrawOrders(); - - for (std::set<LLViewerObject*>::iterator iter = objects.begin(); iter != objects.end(); ++iter) - { - stateSort((*iter)->mDrawable, *LLViewerCamera::getInstance()); - } - - LLMemType mt(LLMemType::MTYPE_PIPELINE); - - - - glMatrixMode(GL_MODELVIEW); - - LLGLSDefault gls_default; - LLGLSObjectSelect gls_object_select; - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest gls_depth(GL_TRUE,GL_TRUE); - disableLights(); - - LLVertexBuffer::unbind(); - - //for each drawpool - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - U32 last_type = 0; - - // If we don't do this, we crash something on changing graphics settings - // from Medium -> Low, because we unload all the shaders and the - // draw pools aren't aware. I don't know if this has to be a separate - // loop before actual rendering. JC - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (poolp->isFacePool() && hasRenderType(poolp->getType())) - { - poolp->prerender(); - } - } - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (poolp->isFacePool() && hasRenderType(poolp->getType())) - { - LLFacePool* face_pool = (LLFacePool*) poolp; - face_pool->renderForSelect(); - LLVertexBuffer::unbind(); - gGLLastMatrix = NULL; - glLoadMatrixd(gGLModelView); - - if (poolp->getType() != last_type) - { - last_type = poolp->getType(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - } - } - } - - LLGLEnable alpha_test(GL_ALPHA_TEST); - if (render_transparent) - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER_EQUAL, 0.f); - } - else - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.2f); - } - - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_VERT_COLOR); - gGL.getTexUnit(0)->setTextureAlphaBlend(LLTexUnit::TBO_MULT, LLTexUnit::TBS_TEX_ALPHA, LLTexUnit::TBS_VERT_ALPHA); - - U32 prim_mask = LLVertexBuffer::MAP_VERTEX | - LLVertexBuffer::MAP_TEXCOORD0; - - for (std::set<LLViewerObject*>::iterator i = objects.begin(); i != objects.end(); ++i) - { - LLViewerObject* vobj = *i; - LLDrawable* drawable = vobj->mDrawable; - if (vobj->isDead() || - vobj->isHUDAttachment() || - (LLSelectMgr::getInstance()->mHideSelectedObjects && vobj->isSelected()) || - drawable->isDead() || - !hasRenderType(drawable->getRenderType())) - { - continue; - } - - for (S32 j = 0; j < drawable->getNumFaces(); ++j) - { - LLFace* facep = drawable->getFace(j); - if (!facep->getPool()) - { - facep->renderForSelect(prim_mask); - } - } - } - - // pick HUD objects - LLVOAvatar* avatarp = gAgent.getAvatarObject(); - if (avatarp && sShowHUDAttachments) - { - glh::matrix4f save_proj(glh_get_current_projection()); - glh::matrix4f save_model(glh_get_current_modelview()); - - setup_hud_matrices(screen_rect); - for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin(); - iter != avatarp->mAttachmentPoints.end(); ) - { - LLVOAvatar::attachment_map_t::iterator curiter = iter++; - LLViewerJointAttachment* attachmentp = curiter->second; - if (attachmentp->getIsHUDAttachment()) - { - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachmentp->mAttachedObjects.begin(); - attachment_iter != attachmentp->mAttachedObjects.end(); - ++attachment_iter) - { - if (LLViewerObject* objectp = (*attachment_iter)) - { - LLDrawable* drawable = objectp->mDrawable; - if (drawable->isDead()) - { - continue; - } - - for (S32 j = 0; j < drawable->getNumFaces(); ++j) - { - LLFace* facep = drawable->getFace(j); - if (!facep->getPool()) - { - facep->renderForSelect(prim_mask); - } - } - - //render child faces - LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); iter++) - { - LLViewerObject* child = *iter; - LLDrawable* child_drawable = child->mDrawable; - for (S32 l = 0; l < child_drawable->getNumFaces(); ++l) - { - LLFace* facep = child_drawable->getFace(l); - if (!facep->getPool()) - { - facep->renderForSelect(prim_mask); - } - } - } - } - } - } - } - - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(save_proj.m); - glh_set_current_projection(save_proj); - - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(save_model.m); - glh_set_current_modelview(save_model); - - - } - - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); - - LLVertexBuffer::unbind(); - - gGL.setColorMask(true, true); -} - void LLPipeline::rebuildPools() { LLMemType mt(LLMemType::MTYPE_PIPELINE); @@ -4692,7 +4646,7 @@ static F32 calc_light_dist(LLVOVolume* light, const LLVector3& cam_pos, F32 max_ { return max_dist; } - F32 dist = fsqrtf(dist2); + F32 dist = (F32) sqrt(dist2); dist *= 1.f / inten; dist -= radius; if (selected) @@ -5054,12 +5008,14 @@ void LLPipeline::enableLights(U32 mask) } if (mLightMask != mask) { + stop_glerror(); if (!mLightMask) { glEnable(GL_LIGHTING); } if (mask) { + stop_glerror(); for (S32 i=0; i<8; i++) { LLLightState* light = gGL.getLight(i); @@ -5074,14 +5030,17 @@ void LLPipeline::enableLights(U32 mask) light->setDiffuse(LLColor4::black); } } + stop_glerror(); } else { glDisable(GL_LIGHTING); } + stop_glerror(); mLightMask = mask; LLColor4 ambient = gSky.getTotalAmbientColor(); glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV); + stop_glerror(); } } @@ -5150,7 +5109,7 @@ void LLPipeline::enableLightsFullbright(const LLColor4& color) void LLPipeline::disableLights() { enableLights(0); // no lighting (full bright) - glColor4f(1.f, 1.f, 1.f, 1.f); +// glColor4f(1.f, 1.f, 1.f, 1.f); } //============================================================================ @@ -5786,6 +5745,7 @@ void LLPipeline::resetVertexBuffers() { sRenderBump = gSavedSettings.getBOOL("RenderObjectBump"); LLVertexBuffer::sUseStreamDraw = gSavedSettings.getBOOL("ShyotlRenderUseStreamVBO"); + LLVertexBuffer::sForceStrideMode = gSavedSettings.getU32("ShyotlRenderVBOStrideMode"); LLVertexBuffer::sOmitBlank = gSavedSettings.getBOOL("SianaRenderOmitBlankVBO"); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) @@ -5908,25 +5868,25 @@ void apply_cube_face_rotation(U32 face) void validate_framebuffer_object() { GLenum status; - status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); switch(status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: + case GL_FRAMEBUFFER_COMPLETE: //framebuffer OK, no error. break; - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: // frame buffer not OK: probably means unsupported depth buffer format llerrs << "Framebuffer Incomplete Missing Attachment." << llendl; break; - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: //May not work on mac. Remove/ifdef if that's the case, for now. GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS missing from glext.h. // frame buffer not OK: probably means unsupported depth buffer format llerrs << "Framebuffer Incomplete Dimensions." << llendl; break; - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: // frame buffer not OK: probably means unsupported depth buffer format llerrs << "Framebuffer Incomplete Attachment." << llendl; break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: + case GL_FRAMEBUFFER_UNSUPPORTED: /* choose different formats */ llerrs << "Framebuffer unsupported." << llendl; break; @@ -5963,16 +5923,14 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b static const LLCachedControl<U32> res_mod("RenderResolutionDivisor",1); LLVector2 tc1(0,0); - LLVector2 tc2((F32) gViewerWindow->getWindowDisplayWidth()*2, - (F32) gViewerWindow->getWindowDisplayHeight()*2); + LLVector2 tc2((F32) gViewerWindow->getWorldViewWidthRaw()*2, + (F32) gViewerWindow->getWorldViewHeightRaw()*2); if (res_mod > 1) { tc2 /= (F32) res_mod.get(); } - gGL.setColorMask(true, true); - LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM); gGL.color4f(1,1,1,1); LLGLDepthTest depth(GL_FALSE); @@ -6065,14 +6023,10 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGlowExtractProgram.uniform1f("warmthAmount", warmthAmount); LLGLEnable blend_on(GL_BLEND); LLGLEnable test(GL_ALPHA_TEST); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); gGL.setSceneBlendType(LLRender::BT_ADD_WITH_ALPHA); - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.getTexUnit(0)->disable(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_RECT_TEXTURE); - gGL.getTexUnit(0)->bind(&mScreen); - + mScreen.bindTexture(0, 0); + gGL.color4f(1,1,1,1); gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); gGL.begin(LLRender::TRIANGLE_STRIP); @@ -6087,7 +6041,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b gGL.end(); - gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->unbind(mScreen.getUsage()); mGlow[2].flush(); } @@ -6117,7 +6071,6 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b for (S32 i = 0; i < kernel; i++) { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); { LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO); mGlow[i%2].bindTarget(); @@ -6162,21 +6115,25 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b if (LLRenderTarget::sUseFBO) { LLFastTimer ftm(LLFastTimer::FTM_RENDER_BLOOM_FBO); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } - gViewerWindow->setupViewport(); + gGLViewport[0] = gViewerWindow->getWorldViewRectRaw().mLeft; + gGLViewport[1] = gViewerWindow->getWorldViewRectRaw().mBottom; + gGLViewport[2] = gViewerWindow->getWorldViewRectRaw().getWidth(); + gGLViewport[3] = gViewerWindow->getWorldViewRectRaw().getHeight(); + glViewport(gGLViewport[0], gGLViewport[1], gGLViewport[2], gGLViewport[3]); - tc2.setVec((F32) gViewerWindow->getWindowDisplayWidth(), - (F32) gViewerWindow->getWindowDisplayHeight()); + tc2.setVec((F32) gViewerWindow->getWorldViewWidthRaw(), + (F32) gViewerWindow->getWorldViewHeightRaw()); gGL.flush(); LLVertexBuffer::unbind(); - if (LLPipeline::sRenderDeferred && !LLViewerCamera::getInstance()->cameraUnderWater()) + if (LLPipeline::sRenderDeferred) { - bool dof_enabled = true; + bool dof_enabled = !LLViewerCamera::getInstance()->cameraUnderWater(); LLGLSLShader* shader = &gDeferredPostProgram; static const LLCachedControl<bool> render_dof("RenderDepthOfField",false); @@ -6185,7 +6142,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b shader = &gDeferredGIFinalProgram; dof_enabled = false; } - else if (LLToolMgr::getInstance()->inBuildMode() || !render_dof) + else if (!dof_enabled || LLToolMgr::getInstance()->inBuildMode() || !render_dof) { //squish focal length when in build mode (or if DoF is disabled) so DoF doesn't make editing objects difficult shader = &gDeferredPostNoDoFProgram; dof_enabled = false; @@ -6309,7 +6266,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b shader->uniform1f("magnification", magnification); } - S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); + S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, mScreen.getUsage()); if (channel > -1) { mScreen.bindTexture(0, channel); @@ -6371,19 +6328,20 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b LLGLDisable blend(GL_BLEND); - //tex unit 0 - gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); - - gGL.getTexUnit(0)->bind(&mGlow[1]); - gGL.getTexUnit(1)->activate(); - gGL.getTexUnit(1)->enable(LLTexUnit::TT_RECT_TEXTURE); - - - //tex unit 1 - gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); + if (LLGLSLShader::sNoFixedFunction) + { + gGlowCombineProgram.bind(); + } + else + { + //tex unit 0 + gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR); + //tex unit 1 + gGL.getTexUnit(1)->setTextureColorBlend(LLTexUnit::TBO_ADD, LLTexUnit::TBS_TEX_COLOR, LLTexUnit::TBS_PREV_COLOR); + } + gGL.getTexUnit(0)->bind(&mGlow[1]); gGL.getTexUnit(1)->bind(&mScreen); - gGL.getTexUnit(1)->activate(); static const LLCachedControl<U32> fsaa_samples("RenderFSAASamples",0); LLGLEnable multisample(fsaa_samples > 0 ? GL_MULTISAMPLE_ARB : 0); @@ -6391,11 +6349,19 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b buff->setBuffer(mask); buff->drawArrays(LLRender::TRIANGLE_STRIP, 0, 3); - gGL.getTexUnit(1)->disable(); - gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); + if (LLGLSLShader::sNoFixedFunction) + { + gGlowCombineProgram.unbind(); + } + else + { + gGL.getTexUnit(1)->disable(); + gGL.getTexUnit(1)->setTextureBlendType(LLTexUnit::TB_MULT); - gGL.getTexUnit(0)->activate(); - gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT); + } + } if (LLRenderTarget::sUseFBO) @@ -6427,25 +6393,23 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen noise_map = mNoiseMap; } - LLGLState::checkTextureChannels(); - shader.bind(); S32 channel = 0; - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage()); if (channel > -1) { mDeferredScreen.bindTexture(0,channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage()); if (channel > -1) { mDeferredScreen.bindTexture(1, channel); gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); } - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage()); if (channel > -1) { mDeferredScreen.bindTexture(2, channel); @@ -6527,14 +6491,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR); } - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - if (channel > -1) - { - has_gi = TRUE; - gi_source->bindTexture(0, channel); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); - } - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH); if (channel > -1) { @@ -6576,22 +6532,17 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen shader.uniformMatrix4fv("gi_norm_mat", 1, FALSE, mGINormalMatrix.m); } } - - /*channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); - if (channel > -1) - { - mDeferredScreen.bindTexture(3, channel); - }*/ + stop_glerror(); - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, mDeferredDepth.getUsage()); if (channel > -1) { gGL.getTexUnit(channel)->bind(&mDeferredDepth, TRUE); - gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + //gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); stop_glerror(); - glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); - glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); + //glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_TEXTURE_COMPARE_MODE_ARB, GL_NONE); + //glTexParameteri(LLTexUnit::getInternalType(mDeferredDepth.getUsage()), GL_DEPTH_TEXTURE_MODE_ARB, GL_ALPHA); stop_glerror(); @@ -6620,7 +6571,7 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen stop_glerror(); - channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, mDeferredLight[light_index].getUsage()); if (channel > -1) { mDeferredLight[light_index].bindTexture(0, channel); @@ -6640,6 +6591,13 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen mGlow[1].bindTexture(0, channel); } + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + if (channel > -1) + { + gi_source->bindTexture(0, channel); + gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + } + channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE); if (channel > -1) { @@ -6852,9 +6810,9 @@ void LLPipeline::renderDeferredLighting() } //ati doesn't seem to love actually using the stencil buffer on FBO's - LLGLEnable stencil(GL_STENCIL_TEST); - glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + LLGLDisable stencil(GL_STENCIL_TEST); + //glStencilFunc(GL_EQUAL, 1, 0xFFFFFFFF); + //glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); gGL.setColorMask(true, true); @@ -6981,7 +6939,7 @@ void LLPipeline::renderDeferredLighting() mLuminanceMap.flush(); gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mLuminanceMap.getTexture(), true); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_TRILINEAR); - glGenerateMipmapEXT(GL_TEXTURE_2D); + glGenerateMipmap(GL_TEXTURE_2D); } } @@ -7247,8 +7205,9 @@ void LLPipeline::renderDeferredLighting() } - LLVector3 center = drawablep->getPositionAgent(); - F32* c = center.mV; + LLVector4a center; + center.load3(drawablep->getPositionAgent().mV); + const F32* c = center.getF32ptr(); F32 s = volume->getLightRadius()*1.5f; LLColor3 col = volume->getLightColor(); @@ -7264,7 +7223,9 @@ void LLPipeline::renderDeferredLighting() continue; } - if (camera->AABBInFrustumNoFarClip(center, LLVector3(s,s,s)) == 0) + LLVector4a sa; + sa.splat(s); + if (camera->AABBInFrustumNoFarClip(center, sa) == 0) { continue; } @@ -7307,8 +7268,9 @@ void LLPipeline::renderDeferredLighting() LLFastTimer ftm(LLFastTimer::FTM_LOCAL_LIGHTS); glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s); glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f); - glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, - GL_UNSIGNED_BYTE, get_box_fan_indices_ptr(camera, center)); + glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8, + GL_UNSIGNED_BYTE, get_box_fan_indices_ptr(camera, center)); + stop_glerror(); } } else @@ -7341,8 +7303,9 @@ void LLPipeline::renderDeferredLighting() LLVOVolume* volume = drawablep->getVOVolume(); - LLVector3 center = drawablep->getPositionAgent(); - F32* c = center.mV; + LLVector4a center; + center.load3(drawablep->getPositionAgent().mV); + const F32* c = center.getF32ptr(); F32 s = volume->getLightRadius()*1.5f; sVisibleLightCount++; @@ -7675,33 +7638,41 @@ void LLPipeline::setupSpotLight(LLGLSLShader& shader, LLDrawable* drawablep) LLViewerTexture* img = volume->getLightTexture(); + if (img == NULL) + { + img = LLViewerFetchedTexture::sWhiteImagep; + } + S32 channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_PROJECTION); - if (channel > -1 && img) + if (channel > -1) { - gGL.getTexUnit(channel)->bind(img); + if (img) + { + gGL.getTexUnit(channel)->bind(img); - F32 lod_range = logf(img->getWidth())/logf(2.f); + F32 lod_range = logf(img->getWidth())/logf(2.f); - shader.uniform1f("proj_focus", focus); - shader.uniform1f("proj_lod", lod_range); - shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f)); + shader.uniform1f("proj_focus", focus); + shader.uniform1f("proj_lod", lod_range); + shader.uniform1f("proj_ambient_lod", llclamp((proj_range-focus)/proj_range*lod_range, 0.f, 1.f)); + } } + } void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) { stop_glerror(); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_POSITION, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_NORMAL, mDeferredScreen.getUsage()); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, mDeferredScreen.getUsage()); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_SPECULAR, mDeferredScreen.getUsage()); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, mDeferredScreen.getUsage()); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LIGHT, mDeferredLight[0].getUsage()); shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, LLTexUnit::TT_RECT_TEXTURE); - shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, LLTexUnit::TT_RECT_TEXTURE); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_EDGE, mEdgeMap.getUsage()); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_SUN_LIGHT, mDeferredLight[1].getUsage()); + shader.disableTexture(LLViewerShaderMgr::DEFERRED_LOCAL_LIGHT, mDeferredLight[2].getUsage()); shader.disableTexture(LLViewerShaderMgr::DEFERRED_LUMINANCE); shader.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); shader.disableTexture(LLViewerShaderMgr::DEFERRED_GI_MIP); @@ -7749,7 +7720,7 @@ void LLPipeline::unbindDeferredShader(LLGLSLShader &shader) gGL.getTexUnit(0)->activate(); shader.unbind(); - LLGLState::checkTextureChannels(); + //LLGLState::checkTextureChannels(); } inline float sgn(float a) @@ -7858,24 +7829,22 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) static LLCullResult ref_result; - if (LLDrawPoolWater::sNeedsDistortionUpdate) + if (LLDrawPoolWater::sNeedsReflectionUpdate) { //initial sky pass (no user clip plane) { //mask out everything but the sky gPipeline.pushRenderTypeMask(); gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::RENDER_TYPE_WL_CLOUDS, LLPipeline::END_RENDER_TYPES); + static LLCullResult result; updateCull(camera, result); stateSort(camera, result); - andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, - LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS, - LLPipeline::RENDER_TYPE_WL_CLOUDS, - LLPipeline::RENDER_TYPE_WL_SKY, - LLPipeline::END_RENDER_TYPES); renderGeom(camera, TRUE); + gPipeline.popRenderTypeMask(); } @@ -7885,7 +7854,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) gPipeline.pushRenderTypeMask(); if (detail < 4) { - clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES); + clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS, END_RENDER_TYPES); if (detail < 3) { clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES); @@ -7900,7 +7869,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_GROUND, LLPipeline::RENDER_TYPE_SKY, - LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS, LLPipeline::RENDER_TYPE_WL_CLOUDS, LLPipeline::END_RENDER_TYPES); static const LLCachedControl<bool> skip_distortion_updates("SkipReflectOcclusionUpdates",false); @@ -7909,8 +7877,11 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) LLGLDisable cull(GL_CULL_FACE); updateCull(camera, ref_result, -water_clip, &plane); stateSort(camera, ref_result); - gPipeline.grabReferences(ref_result); - renderGeom(camera); + if (LLDrawPoolWater::sNeedsDistortionUpdate) + { + gPipeline.grabReferences(ref_result); + renderGeom(camera); + } LLPipeline::sSkipUpdate = FALSE; gPipeline.popRenderTypeMask(); } @@ -7986,16 +7957,16 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in) glClear(GL_DEPTH_BUFFER_BIT); } glClearColor(0.f, 0.f, 0.f, 0.f); - - gViewerWindow->setupViewport(); + gViewerWindow->setup3DViewport(); gPipeline.popRenderTypeMask(); LLDrawPoolWater::sNeedsReflectionUpdate = FALSE; LLDrawPoolWater::sNeedsDistortionUpdate = FALSE; - LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd)); + LLPlane npnorm(-pnorm, -pd); + LLViewerCamera::getInstance()->setUserClipPlane(npnorm); LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); + //LLGLState::checkTextureChannels(); + //LLGLState::checkClientArrays(); if (agent) { @@ -8022,7 +7993,6 @@ glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up) dirN = dir; dirN.normVec(); - ret.m[ 0] = lftN[0]; ret.m[ 1] = upN[0]; @@ -8125,14 +8095,21 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera LLVertexBuffer::unbind(); { + if (!use_shader) + { //occlusion program is general purpose depth-only no-textures + gOcclusionProgram.bind(); + } LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE); - LLGLDisable test(GL_ALPHA_TEST); gGL.getTexUnit(0)->disable(); for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i) { renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); } gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + if (!use_shader) + { + gOcclusionProgram.unbind(); + } } if (use_shader) @@ -8148,12 +8125,11 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera { LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA); - LLGLEnable test(GL_ALPHA_TEST); - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f); + gDeferredShadowAlphaMaskProgram.bind(); + gDeferredShadowAlphaMaskProgram.setAlphaRange(0.6f, 1.f); renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE); glColor4f(1,1,1,1); renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE); - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } //glCullFace(GL_BACK); @@ -8244,7 +8220,8 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector const LLPlane& cp = camera.getAgentPlane(j); const LLVector3& v1 = pp[bs[i*2+0]]; const LLVector3& v2 = pp[bs[i*2+1]]; - const LLVector3 n(cp.mV); + LLVector3 n; + cp.getVector3(n); LLVector3 line = v1-v2; @@ -8258,8 +8235,8 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector LLVector3 intersect = v2+line*t; pp.push_back(intersect); } - } } + } //camera frustum line segments const U32 fs[] = @@ -8290,7 +8267,8 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector const LLVector3& v1 = pp[fs[i*2+0]+8]; const LLVector3& v2 = pp[fs[i*2+1]+8]; const LLPlane& cp = bp[j]; - const LLVector3 n(cp.mV); + LLVector3 n; + cp.getVector3(n); LLVector3 line = v1-v2; @@ -8305,7 +8283,7 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector pp.push_back(intersect); } } - } + } LLVector3 ext[] = { min-LLVector3(0.05f,0.05f,0.05f), max+LLVector3(0.05f,0.05f,0.05f) }; @@ -8560,6 +8538,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_VOIDWATER, LLPipeline::RENDER_TYPE_PASS_ALPHA_SHADOW, + LLPipeline::RENDER_TYPE_PASS_GRASS, LLPipeline::RENDER_TYPE_PASS_SIMPLE, LLPipeline::RENDER_TYPE_PASS_BUMP, LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT, @@ -8596,12 +8575,13 @@ void LLPipeline::generateSunShadow(LLCamera& camera) //F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] }; //put together a universal "near clip" plane for shadow frusta - /*LLPlane shadow_near_clip; + LLPlane shadow_near_clip; { - LLVector3 p = gAgentCamera.getCameraPositionAgent();//gAgent.getPositionAgent(); - p += mSunDir * gSavedSettings.getF32("RenderFarClip")*2.f; + LLVector3 p = gAgent.getPositionAgent();//gAgentCamera.getCameraPositionAgent(); + static const LLCachedControl<F32> render_far_clip("RenderFarClip"); + p += mSunDir * render_far_clip*2.f; shadow_near_clip.setVec(p, mSunDir); - }*/ + } LLVector3 lightDir = -mSunDir; lightDir.normVec(); @@ -8677,7 +8657,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) near_clip = -max.mV[2]; F32 far_clip = -min.mV[2]*2.f; - far_clip = llmin(far_clip, 128.f); + //far_clip = llmin(far_clip, 128.f); far_clip = llmin(far_clip, camera.getFar()); F32 range = far_clip-near_clip; @@ -8970,11 +8950,6 @@ void LLPipeline::generateSunShadow(LLCamera& camera) fovx = acos(fovx); fovz = acos(fovz); - if (fovx > cutoff || llround(fovz, 0.01f) > cutoff) - { - // llerrs << "WTF?" << llendl; - } - mShadowFOV.mV[j] = cutoff; } @@ -9040,8 +9015,8 @@ void LLPipeline::generateSunShadow(LLCamera& camera) LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE); - shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); - //shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_clip); + //shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR); + shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_clip); //translate and scale to from [-1, 1] to [0, 1] glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f, @@ -9221,6 +9196,10 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadow[i+4].flush(); } } + else + { //no spotlight shadows + mShadowSpotLight[0] = mShadowSpotLight[1] = NULL; + } static const LLCachedControl<bool> camera_offset("CameraOffset",false); if (!camera_offset) @@ -9339,7 +9318,7 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) stateSort(*LLViewerCamera::getInstance(), result); - const LLVector3* ext = avatar->mDrawable->getSpatialExtents(); + const LLVector4a* ext = avatar->mDrawable->getSpatialExtents(); LLVector3 pos(avatar->getRenderPosition()+avatar->getImpostorOffset()); LLCamera camera = *viewer_camera; @@ -9348,25 +9327,30 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) LLVector2 tdim; - LLVector3 half_height = (ext[1]-ext[0])*0.5f; - LLVector3 left = camera.getLeftAxis(); - left *= left; - left.normalize(); + LLVector4a half_height; + half_height.setSub(ext[1], ext[0]); + half_height.mul(0.5f); - LLVector3 up = camera.getUpAxis(); - up *= up; - up.normalize(); + LLVector4a left; + left.load3(camera.getLeftAxis().mV); + left.mul(left); + left.normalize3fast(); - tdim.mV[0] = fabsf(half_height * left); - tdim.mV[1] = fabsf(half_height * up); + LLVector4a up; + up.load3(camera.getUpAxis().mV); + up.mul(up); + up.normalize3fast(); + + tdim.mV[0] = fabsf(half_height.dot3(left).getF32()); + tdim.mV[1] = fabsf(half_height.dot3(up).getF32()); glMatrixMode(GL_PROJECTION); glPushMatrix(); - //glh::matrix4f ortho = gl_ortho(-tdim.mV[0], tdim.mV[0], -tdim.mV[1], tdim.mV[1], 1.0, 256.0); + F32 distance = (pos-camera.getOrigin()).length(); F32 fov = atanf(tdim.mV[1]/distance)*2.f*RAD_TO_DEG; - F32 aspect = tdim.mV[0]/tdim.mV[1]; //128.f/256.f; + F32 aspect = tdim.mV[0]/tdim.mV[1]; glh::matrix4f persp = gl_perspective(fov, aspect, 1.f, 256.f); glh_set_current_projection(persp); glLoadMatrixf(persp.m); @@ -9383,11 +9367,9 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) glClearColor(0.0f,0.0f,0.0f,0.0f); gGL.setColorMask(true, true); - glStencilMask(0xFFFFFFFF); - glClearStencil(0); - + // get the number of pixels per angle - F32 pa = gViewerWindow->getWindowDisplayHeight() / (RAD_TO_DEG * LLViewerCamera::getInstance()->getView()); + F32 pa = gViewerWindow->getWindowHeightRaw() / (RAD_TO_DEG * viewer_camera->getView()); //get resolution based on angle width and height of impostor (double desired resolution to prevent aliasing) U32 resY = llmin(nhpo2((U32) (fov*pa)), (U32) 512); @@ -9396,61 +9378,43 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) if (!avatar->mImpostor.isComplete() || resX != avatar->mImpostor.getWidth() || resY != avatar->mImpostor.getHeight()) { + static const LLCachedControl<bool> shadow_precision("DeferredHighPrecision",true); //TO-DO: Profile 16bit format later + avatar->mImpostor.allocate(resX,resY, (!LLPipeline::sRenderDeferred || shadow_precision) ? GL_RGBA : GL_RGBA16F_ARB,TRUE,TRUE); + if (LLPipeline::sRenderDeferred) { - static const LLCachedControl<bool> shadow_precision("DeferredHighPrecision",true); - const GLuint format = shadow_precision ? GL_RGBA : GL_RGBA16F_ARB; //TO-DO: Profile 16bit format later - avatar->mImpostor.allocate(resX,resY,format,TRUE,TRUE); addDeferredAttachments(avatar->mImpostor); } - else - { - avatar->mImpostor.allocate(resX,resY,GL_RGBA,TRUE,TRUE); - } + gGL.getTexUnit(0)->bind(&avatar->mImpostor); gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); } - LLGLEnable stencil(GL_STENCIL_TEST); - glStencilMask(0xFFFFFFFF); - glStencilFunc(GL_ALWAYS, 1, 0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + avatar->mImpostor.bindTarget(); - { - LLGLEnable scissor(GL_SCISSOR_TEST); - glScissor(0, 0, resX, resY); - avatar->mImpostor.bindTarget(); - avatar->mImpostor.clear(); - } - if (LLPipeline::sRenderDeferred) { - stop_glerror(); + avatar->mImpostor.clear(); renderGeomDeferred(camera); renderGeomPostDeferred(camera); } else { + LLGLEnable scissor(GL_SCISSOR_TEST); + glScissor(0, 0, resX, resY); + avatar->mImpostor.clear(); renderGeom(camera); } - glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - glStencilFunc(GL_EQUAL, 1, 0xFFFFFF); - - //if (!sRenderDeferred || muted) - { - LLVector3 left = camera.getLeftAxis()*tdim.mV[0]*2.f; - LLVector3 up = camera.getUpAxis()*tdim.mV[1]*2.f; - - //Safe?? + { //create alpha mask based on depth buffer (grey out if muted) if (LLPipeline::sRenderDeferred) { GLuint buff = GL_COLOR_ATTACHMENT0_EXT; glDrawBuffersARB(1, &buff); } - LLGLEnable blend(muted ? 0 : GL_BLEND); + LLGLDisable blend(GL_BLEND); if (muted) { @@ -9461,25 +9425,34 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar) gGL.setColorMask(false, true); } - gGL.setSceneBlendType(LLRender::BT_ADD); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest depth(GL_FALSE, GL_FALSE); + LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); + + gGL.flush(); + + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + static const F32 clip_plane = 0.99999f; - gGL.color4f(1,1,1,1); gGL.color4ub(64,64,64,255); gGL.begin(LLRender::QUADS); - gGL.vertex3fv((pos+left-up).mV); - gGL.vertex3fv((pos-left-up).mV); - gGL.vertex3fv((pos-left+up).mV); - gGL.vertex3fv((pos+left+up).mV); + gGL.vertex3f(-1, -1, clip_plane); + gGL.vertex3f(1, -1, clip_plane); + gGL.vertex3f(1, 1, clip_plane); + gGL.vertex3f(-1, 1, clip_plane); gGL.end(); gGL.flush(); - gGL.setSceneBlendType(LLRender::BT_ALPHA); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } - avatar->mImpostor.flush(); avatar->setImpostorDim(tdim); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index efafec32e..d3fea1ff2 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -91,8 +91,11 @@ public: void resetVertexBuffers(); void resizeScreenTexture(); void releaseGLBuffers(); + void releaseScreenBuffers(); void createGLBuffers(); + void allocateScreenBuffer(U32 resX, U32 resY); + bool allocateScreenBuffer(U32 resX, U32 resY, U32 samples); void resetVertexBuffers(LLDrawable* drawable); void setUseVBO(BOOL use_vbo); @@ -197,6 +200,7 @@ public: //calculate pixel area of given box from vantage point of given camera static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); + static F32 calcPixelArea(const LLVector4a& center, const LLVector4a& size, LLCamera &camera); void stateSort(LLCamera& camera, LLCullResult& result); void stateSort(LLSpatialGroup* group, LLCamera& camera); @@ -236,7 +240,6 @@ public: void renderHighlights(); void renderDebug(); - void renderForSelect(std::set<LLViewerObject*>& objects, BOOL render_transparent, const LLRect& screen_rect); void rebuildPools(); // Rebuild pools void findReferences(LLDrawable *drawablep); // Find the lists which have references to this object @@ -440,7 +443,6 @@ public: S32 mMeanBatchSize; S32 mTrianglesDrawn; S32 mNumVisibleNodes; - LLStat mTrianglesDrawnStat; S32 mVerticesRelit; S32 mLightingChanges; @@ -679,7 +681,6 @@ void render_bbox(const LLVector3 &min, const LLVector3 &max); void render_hud_elements(); extern LLPipeline gPipeline; -extern BOOL gRenderForSelect; extern BOOL gDebugPipeline; extern const LLMatrix4* gGLLastMatrix; diff --git a/indra/newview/rlvcommon.cpp b/indra/newview/rlvcommon.cpp index df409ff14..c45551516 100644 --- a/indra/newview/rlvcommon.cpp +++ b/indra/newview/rlvcommon.cpp @@ -18,6 +18,7 @@ #include "llagent.h" #include "llappviewer.h" #include "llavatarnamecache.h" +#include "llnotificationsutil.h" #include "lluictrlfactory.h" #include "llversionviewer.h" #include "llviewermenu.h" @@ -43,7 +44,7 @@ void RlvNotifications::notifyBehaviour(ERlvBehaviour eBhvr, ERlvParamType eType) { LLSD argsNotify; argsNotify["MESSAGE"] = strMsg; - LLNotifications::instance().add("SystemMessageTip", argsNotify); + LLNotificationsUtil::add("SystemMessageTip", argsNotify); } } #endif // RLV_EXTENSION_NOTIFY_BEHAVIOUR @@ -53,7 +54,7 @@ void RlvNotifications::notifyBlocked(const std::string& strRlvString) { LLSD argsNotify; argsNotify["MESSAGE"] = RlvStrings::getString(strRlvString); - LLNotifications::instance().add("SystemMessageTip", argsNotify); + LLNotificationsUtil::add("SystemMessageTip", argsNotify); } // Checked: 2009-11-11 (RLVa-1.1.0a) | Added: RLVa-1.1.0a @@ -65,7 +66,7 @@ void RlvNotifications::notifyBlockedViewXXX(const char* pstrAssetType) LLSD argsNotify; argsNotify["MESSAGE"] = strMsg; - LLNotifications::instance().add("SystemMessageTip", argsNotify); + LLNotificationsUtil::add("SystemMessageTip", argsNotify); } // Checked: 2009-11-13 (RLVa-1.1.0b) | Modified: RLVa-1.1.0b @@ -437,7 +438,7 @@ void RlvUtil::notifyFailedAssertion(const std::string& strAssert, const std::str LLSD argsNotify; argsNotify["MESSAGE"] = llformat("RLVa assertion failure: %s (%s - %d)", strAssert.c_str(), strFile.c_str(), nLine); - LLNotifications::instance().add("SystemMessageTip", argsNotify); + LLNotificationsUtil::add("SystemMessageTip", argsNotify); } // Checked: 2010-03-27 (RLVa-1.1.3a) | Modified: RLVa-1.2.0b diff --git a/indra/newview/rlvextensions.cpp b/indra/newview/rlvextensions.cpp index cc3fc6bc5..818eb9f34 100644 --- a/indra/newview/rlvextensions.cpp +++ b/indra/newview/rlvextensions.cpp @@ -307,7 +307,7 @@ std::string RlvExtGetSet::onGetEnv(std::string strSetting) LLFloaterWindLight::instance()->syncMenu(); } - LLWLParamManager* pWLParams = LLWLParamManager::instance(); + LLWLParamManager* pWLParams = LLWLParamManager::getInstance(); F32 nValue = 0.0f; if ("daytime" == strSetting) @@ -380,7 +380,7 @@ ERlvCmdRet RlvExtGetSet::onSetEnv(std::string strSetting, const std::string& str LLFloaterWindLight::instance()->syncMenu(); } - LLWLParamManager* pWLParams = LLWLParamManager::instance(); + LLWLParamManager* pWLParams = LLWLParamManager::getInstance(); WLFloatControl* pFloat = NULL; WLColorControl* pColour = NULL; diff --git a/indra/newview/rlvfloaterbehaviour.cpp b/indra/newview/rlvfloaterbehaviour.cpp index 808f35408..c8f33f5e0 100644 --- a/indra/newview/rlvfloaterbehaviour.cpp +++ b/indra/newview/rlvfloaterbehaviour.cpp @@ -165,7 +165,7 @@ void RlvFloaterBehaviour::changed(const RlvCommand& /*rlvCmd*/, bool /*fInternal void RlvFloaterBehaviour::onAvatarNameLookup(const LLUUID& uuid) { - std::map<LLUUID, boost::signals2::connection>::const_iterator itLookup = m_PendingLookup.find(uuid); + std::map<LLUUID, boost::signals2::connection>::iterator itLookup = m_PendingLookup.find(uuid); if (itLookup != m_PendingLookup.end()) { itLookup->second.disconnect(); diff --git a/indra/newview/rlvhelper.cpp b/indra/newview/rlvhelper.cpp index 57f3037ee..b7959c31b 100644 --- a/indra/newview/rlvhelper.cpp +++ b/indra/newview/rlvhelper.cpp @@ -20,6 +20,7 @@ #include "llgesturemgr.h" #include "llinventoryview.h" #include "llinventorybridge.h" +#include "llnotificationsutil.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" #include "llviewerregion.h" @@ -335,7 +336,7 @@ bool RlvForceWear::isWearingItem(const LLInventoryItem* pItem) case LLAssetType::AT_OBJECT: return (gAgent.getAvatarObject()) && (gAgent.getAvatarObject()->isWearingAttachment(pItem->getUUID())); case LLAssetType::AT_GESTURE: - return gGestureManager.isGestureActive(pItem->getUUID()); + return LLGestureMgr::instance().isGestureActive(pItem->getUUID()); case LLAssetType::AT_LINK: return isWearingItem(gInventory.getItem(pItem->getLinkedUUID())); default: @@ -351,7 +352,7 @@ void RlvForceWear::forceFolder(const LLViewerInventoryCategory* pFolder, EWearAc // [See LLWearableBridge::wearOnAvatar(): don't wear anything until initial wearables are loaded, can destroy clothing items] if (!gAgentWearables.areWearablesLoaded()) { - LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded"); + LLNotificationsUtil::add("CanNotChangeAppearanceUntilLoaded"); return; } LLVOAvatar* pAvatar = gAgent.getAvatarObject(); @@ -784,7 +785,7 @@ void RlvForceWear::done() for (S32 idxGesture = 0, cntGesture = m_remGestures.count(); idxGesture < cntGesture; idxGesture++) { LLViewerInventoryItem* pItem = m_remGestures.get(idxGesture); - gGestureManager.deactivateGesture(pItem->getUUID()); + LLGestureMgr::instance().deactivateGesture(pItem->getUUID()); gInventory.updateItem(pItem); gInventory.notifyObservers(); } @@ -877,7 +878,7 @@ void RlvForceWear::done() // Process gestures if (m_addGestures.size()) { - gGestureManager.activateGestures(m_addGestures); + LLGestureMgr::instance().activateGestures(m_addGestures); for (S32 idxGesture = 0, cntGesture = m_addGestures.count(); idxGesture < cntGesture; idxGesture++) gInventory.updateItem(m_addGestures.get(idxGesture)); gInventory.notifyObservers(); @@ -954,7 +955,7 @@ void RlvBehaviourNotifyHandler::sendNotification(const std::string& strText, con // Checked: 2009-06-03 (RLVa-0.2.0h) | Added: RLVa-0.2.0h void RlvWLSnapshot::restoreSnapshot(const RlvWLSnapshot* pWLSnapshot) { - LLWLParamManager* pWLParams = LLWLParamManager::instance(); + LLWLParamManager* pWLParams = LLWLParamManager::getInstance(); if ( (pWLSnapshot) && (pWLParams) ) { pWLParams->mAnimator.mIsRunning = pWLSnapshot->fIsRunning; @@ -975,7 +976,7 @@ RlvWLSnapshot* RlvWLSnapshot::takeSnapshot() } RlvWLSnapshot* pWLSnapshot = NULL; - LLWLParamManager* pWLParams = LLWLParamManager::instance(); + LLWLParamManager* pWLParams = LLWLParamManager::getInstance(); if (pWLParams) { pWLSnapshot = new RlvWLSnapshot(); @@ -1043,7 +1044,7 @@ bool rlvCanDeleteOrReturn() LLSD args; args["MESSAGE"] = llformat("RestrainedLove Support will be %s after you restart", (rlv_handler_t::isEnabled()) ? "disabled" : "enabled" ); - LLNotifications::instance().add("GenericAlert", args); + LLNotificationsUtil::add("GenericAlert", args); #endif } // Checked: 2009-07-08 (RLVa-1.0.0e) diff --git a/indra/newview/skins/default/xui/en-us/floater_customize.xml b/indra/newview/skins/default/xui/en-us/floater_customize.xml index 261ab3189..ac3c36b95 100644 --- a/indra/newview/skins/default/xui/en-us/floater_customize.xml +++ b/indra/newview/skins/default/xui/en-us/floater_customize.xml @@ -1326,6 +1326,8 @@ scratch and wear it. <button bottom="-273" follows="left|top" font="SansSerifSmall" halign="center" height="16" label="Advanced Parameters" label_selected="Advanced Parameters" left="8" mouse_opaque="true" name="Advanced Parameters" scale_image="true" width="82" /> + <button name="Take Off" label="Take Off" label_selected="Take Off" + follows="left|top" width="82" height="20" left="8" bottom="-375"/> <text type="string" length="1" bg_visible="false" border_drop_shadow_visible="false" border_visible="false" bottom="-24" drop_shadow_visible="true" follows="left|top|right" diff --git a/indra/newview/skins/default/xui/en-us/floater_instant_message.xml b/indra/newview/skins/default/xui/en-us/floater_instant_message.xml index 5e7b76f95..7c25a964f 100644 --- a/indra/newview/skins/default/xui/en-us/floater_instant_message.xml +++ b/indra/newview/skins/default/xui/en-us/floater_instant_message.xml @@ -39,8 +39,8 @@ </string> <button bottom="-40" follows="left|top" height="20" label="Profile" left="5" name="profile_callee_btn" width="80" /> - <!--button bottom="-40" follows="left|top" halign="center" height="20" label="Teleport" left_delta="80" - name="profile_tele_btn" width="80" /--> + <button bottom="-40" follows="left|top" halign="center" height="20" label="Teleport" left_delta="80" + name="profile_tele_btn" width="80" /> <button bottom="-40" follows="left|top" halign="center" height="20" label="History" left_delta="80" name="history_btn" visible="true" width="80" /> <check_box bottom="-40" follows="left|top" halign="center" height="20" left_delta="80" diff --git a/indra/newview/skins/default/xui/en-us/floater_object_backup.xml b/indra/newview/skins/default/xui/en-us/floater_object_backup.xml new file mode 100755 index 000000000..060c4421e --- /dev/null +++ b/indra/newview/skins/default/xui/en-us/floater_object_backup.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater can_close="true" can_drag_on_left="false" can_minimize="true" can_resize="false" + rect_control="FloaterObjectBackuptRect" + height="80" width="200" name="Import" title="Import progress" mouse_opaque="true"> + <text height="30" left="10" name="name_label" top="-20"> Progress </text> +</floater> diff --git a/indra/newview/skins/default/xui/en-us/floater_snapshot.xml b/indra/newview/skins/default/xui/en-us/floater_snapshot.xml index 5b86ce319..b48c2ca1c 100644 --- a/indra/newview/skins/default/xui/en-us/floater_snapshot.xml +++ b/indra/newview/skins/default/xui/en-us/floater_snapshot.xml @@ -151,9 +151,6 @@ <combo_item name="Depth" value="depth"> Depth </combo_item> - <combo_item name="ObjectMattes" value="objects"> - Object Mattes - </combo_item> </combo_box> <check_box bottom_delta="-20" follows="left|top" label="Show interface in snapshot" left="10" name="ui_check" /> diff --git a/indra/newview/skins/default/xui/en-us/floater_tools.xml b/indra/newview/skins/default/xui/en-us/floater_tools.xml index 295ac58c7..e490ec687 100644 --- a/indra/newview/skins/default/xui/en-us/floater_tools.xml +++ b/indra/newview/skins/default/xui/en-us/floater_tools.xml @@ -301,9 +301,7 @@ <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" bottom="-163" left="118" drop_shadow_visible="true" follows="left|top" font="SansSerifSmall" h_pad="0" halign="right" height="16" - mouse_opaque="true" name="prim_count" v_pad="0" width="143"> - primitives: [COUNT] - </text> + mouse_opaque="true" name="prim_count" v_pad="0" width="143"/> <!-- Sub-tabs --> @@ -632,7 +630,7 @@ text_enabled_color="0, 100, 40, 255" width="87" /> <spinner bottom_delta="-18" decimal_digits="3" follows="left|top" height="16" increment="0.01" initial_val="0" label="Z" label_width="10" left_delta="0" - max_val="4096" min_val="0" mouse_opaque="true" name="Pos Z" + max_val="4096" min_val="-3.5" mouse_opaque="true" name="Pos Z" text_enabled_color="0, 67, 132, 255" width="87" /> <button bottom_delta="35" follows="top|right" font="SansSerifSmall" halign="center" height="18" label="C" left_delta="90" mouse_opaque="true" name="copypos" enabled="true" @@ -1011,6 +1009,9 @@ <panel border="true" bottom="-383" follows="left|top|right|bottom" height="367" label="Features" left="1" mouse_opaque="false" name="Features" width="270"> + <string name="None">None</string> + <string name="Prim">Prim</string> + <string name="Convex Hull">Convex Hull</string> <text bg_visible="false" border_drop_shadow_visible="false" border_visible="false" bottom="-20" drop_shadow_visible="true" follows="left|top" font="SansSerifSmall" h_pad="0" halign="left" height="10" left="10" @@ -1029,35 +1030,35 @@ tool_tip="Allows object to flex about the Z axis. (Client-side only)" width="121" /> <spinner bottom_delta="-20" decimal_digits="5" follows="left|top" height="16" - increment="1" initial_val="2" label="Softness" label_width="65" left="10" + increment="1" initial_val="2" label="Softness" label_width="55" left="10" max_val="3" min_val="0" mouse_opaque="true" name="FlexNumSections" - width="128" /> + width="118" /> <spinner bottom_delta="-20" decimal_digits="5" follows="left|top" height="16" - increment="0.5" initial_val="0.3" label="Gravity" label_width="65" + increment="0.5" initial_val="0.3" label="Gravity" label_width="55" left="10" max_val="10" min_val="-10" mouse_opaque="true" name="FlexGravity" - width="128" /> + width="118" /> <spinner bottom_delta="-20" decimal_digits="5" follows="left|top" height="16" - increment="0.5" initial_val="2" label="Drag" label_width="65" left="10" + increment="0.5" initial_val="2" label="Drag" label_width="55" left="10" max_val="10" min_val="0" mouse_opaque="true" name="FlexFriction" - width="128" /> + width="118" /> <spinner bottom_delta="-20" decimal_digits="5" follows="left|top" height="16" - increment="0.5" initial_val="0" label="Wind" label_width="65" left="10" - max_val="10" min_val="0" mouse_opaque="true" name="FlexWind" width="128" /> + increment="0.5" initial_val="0" label="Wind" label_width="55" left="10" + max_val="10" min_val="0" mouse_opaque="true" name="FlexWind" width="118" /> <spinner bottom_delta="-20" decimal_digits="5" follows="left|top" height="16" - increment="0.5" initial_val="1" label="Tension" label_width="65" left="10" - max_val="10" min_val="0" mouse_opaque="true" name="FlexTension" width="128" /> + increment="0.5" initial_val="1" label="Tension" label_width="55" left="10" + max_val="10" min_val="0" mouse_opaque="true" name="FlexTension" width="118" /> <spinner bottom_delta="-20" decimal_digits="5" follows="left|top" height="16" - increment="0.01" initial_val="0" label="Force X" label_width="65" left="10" + increment="0.01" initial_val="0" label="Force X" label_width="55" left="10" max_val="10" min_val="-10" mouse_opaque="true" name="FlexForceX" - width="128" /> + width="118" /> <spinner bottom_delta="-20" decimal_digits="5" follows="left|top" height="16" - increment="0.01" initial_val="0" label="Force Y" label_width="65" left="10" + increment="0.01" initial_val="0" label="Force Y" label_width="55" left="10" max_val="10" min_val="-10" mouse_opaque="true" name="FlexForceY" - width="128" /> + width="118" /> <spinner bottom_delta="-20" decimal_digits="5" follows="left|top" height="16" - increment="0.01" initial_val="0" label="Force Z" label_width="65" left="10" + increment="0.01" initial_val="0" label="Force Z" label_width="55" left="10" max_val="10" min_val="-10" mouse_opaque="true" name="FlexForceZ" - width="128" /> + width="118" /> <check_box bottom_delta="-30" follows="left|top" font="SansSerifSmall" height="16" initial_value="false" label="Light" left="10" mouse_opaque="true" name="Light Checkbox Ctrl" tool_tip="Causes object to emit light" @@ -1123,12 +1124,102 @@ max_val="2" min_val="0" mouse_opaque="true" name="Light Falloff" width="108" /> - <spinner bottom_delta="0" decimal_digits="3" follows="left|top" height="16" + <spinner bottom_delta="0" + decimal_digits="3" + follows="left|top" + height="16" left_delta="114" - increment="0.05" initial_val="1" label="Ambiance" label_width="55" - max_val="1" min_val="0" mouse_opaque="true" - name="Light Ambiance" - width="118" /> + ncrement="0.05" + initial_val="1" + label="Ambiance" + label_width="55" + max_val="1" + min_val="0" + mouse_opaque="true" + name="Light Ambiance" + width="118" /> + <text + type="string" + length="1" + follows="left|top" + height="10" + layout="topleft" + name="label physicsshapetype" + left_delta="13" + bottom="-41" + width="121"> + Physics Shape Type: + </text> + <combo_box + height="19" + bottom_delta="-26" + layout="topleft" + follows="left|top" + name="Physics Shape Type Combo Ctrl" + tool_tip="Choose the physics shape type" + width="108"/> + <spinner + follows="left|top" + height="19" + increment="1" + initial_value="1" + label="Gravity" + label_width="55" + layout="topleft" + min_val="-1" + max_val="28" + name="Physics Gravity" + top_pad="10" + width="118" /> + + <spinner + follows="left|top" + height="19" + increment="0.1" + initial_value="0" + label="Friction" + label_width="55" + layout="topleft" + left_delta="0" + max_val="255" + min_val="0" + name="Physics Friction" + top_pad="4" + bottom_delta="-20" + width="118" /> + + <spinner + follows="left|top" + height="19" + increment="0.1" + initial_value="0" + label="Density" + label_width="55" + label_wrap="true" + layout="topleft" + left_delta="0" + max_val="22587" + min_val="1" + name="Physics Density" + top_pad="4" + bottom_delta="-20" + width="118" /> + + <spinner + follows="left|top" + height="19" + increment="0.01" + initial_value="0" + label="Restitution" + label_width="55" + layout="topleft" + left_delta="0" + max_val="1" + min_val="0" + name="Physics Restitution" + top_pad="8" + bottom_delta="-20" + width="118" /> </panel> <!-- Texture sub-tab --> @@ -1469,4 +1560,10 @@ <string name="grid_attachment_text"> Attachment </string> + <string name="status_selectprimequiv"> + , Cost: [SEL_WEIGHT] + </string> + <string name="status_selectcount"> + Primitives: [COUNT][PE_STRING] + </string> </floater> diff --git a/indra/newview/skins/default/xui/en-us/menu_viewer.xml b/indra/newview/skins/default/xui/en-us/menu_viewer.xml index afba100cc..4a49daede 100644 --- a/indra/newview/skins/default/xui/en-us/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en-us/menu_viewer.xml @@ -52,9 +52,9 @@ </menu_item_call> <menu_item_separator bottom="-121" enabled="true" height="8" label="-----------" left="0" mouse_opaque="true" name="separator2" width="243" /> - <menu_item_call bottom="-140" enabled="true" height="19" label="Save Texture As..." left="0" - mouse_opaque="true" name="Save Texture As..." width="243"> - <on_click function="File.SaveTexture" userdata="" /> + <menu_item_call bottom="-140" enabled="true" height="19" label="Save Preview As..." left="0" + mouse_opaque="true" name="Save Preview As..." width="243"> + <on_click function="File.SavePreview" userdata="" /> <on_enable function="File.EnableSaveAs" /> </menu_item_call> <menu_item_separator bottom="-148" enabled="true" height="8" label="-----------" left="0" diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml index e0d489f42..51ac59cbb 100644 --- a/indra/newview/skins/default/xui/en-us/notifications.xml +++ b/indra/newview/skins/default/xui/en-us/notifications.xml @@ -1,5 +1,13 @@ <?xml version="1.0" ?><notifications> + <global name="VIEWER_NAME"> + Singularity Viewer + </global> + + <global name="VIEWER_SITE"> + http://www.singularityviewer.org/ + </global> + <global name="skipnexttime"> Don't show me this again @@ -1887,6 +1895,15 @@ Multiple parcels selected. Try selecting a single parcel. </notification> + <notification + icon="notifytip.tga" + name="DeedToGroupFail" + type="notifytip"> + Deed to group failed. + <tag>group</tag> + <tag>fail</tag> + </notification> + <notification icon="alertmodal.tga" name="ParcelCanPlayMedia" diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_chat.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_chat.xml index 00412ca2d..7d4d31cea 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_chat.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_chat.xml @@ -272,7 +272,7 @@ To use spellcheck, right-click a misspelled word left="5" name="CmdDivisor" width="356"/> <check_box bottom_delta="-24" enabled="true" follows="left|top" font="SansSerifSmall" height="16" - label="Highlight messages if any of they contain the terms" left="5" mouse_opaque="true" + label="Highlight messages if any of them contain the terms" left="5" mouse_opaque="true" name="KeywordsOn" radio_style="false" width="270"/> <text bottom_delta="-20" follows="left|top" font="SansSerifSmall" height="20" left="12" name="keyword_txt1" width="512"> diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml index 5db045198..a34e943bf 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml @@ -13,8 +13,8 @@ width="400" /> <check_box bottom_delta="-20" control_name="AscentDisableTeleportScreens" enabled="true" follows="left|top" font="SansSerifSmall" height="16" initial_value="true" - label="Show the Teleport progress screens" left="10" - tool_tip="If turned off, the viewer will not hide your UI while teleporting, allowing you to continue to read IMs." + label="Hide the Teleport progress screens" left="10" + tool_tip="If checked, the viewer will hide the teleport progress screen, allowing you to continue to read IMs." mouse_opaque="true" name="disable_tp_screen_check" radio_style="false" width="400" /> <check_box bottom_delta="-20" control_name="OptionPlayTpSound" enabled="true" @@ -25,8 +25,8 @@ width="400" /> <check_box bottom_delta="-20" control_name="AscentDisableLogoutScreens" enabled="true" follows="left|top" font="SansSerifSmall" height="16" initial_value="true" - label="Show the Login/Logout progress screens" left="10" - tool_tip="If turned off, the viewer does not hide the UI when logging in or out." + label="Hide the Login/Logout progress screens" left="10" + tool_tip="If checked, the viewer will hide the login/logout progress screen." mouse_opaque="true" name="disable_logout_screen_check" radio_style="false" width="400" /> </panel> diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml index 786f763f3..f3195e5e7 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_grids.xml @@ -2,234 +2,241 @@ <panel enabled="true" label="Grids" name="Grids panel" height="408" width="517" left="102" follows="left|top|right|bottom" border="true" mouse_opaque="true"> - <!-- Grid Selector --> - <text type="string" length="1" enabled="true" name="grid_selector_label" + <!-- Grid Selector --> + <text type="string" length="1" enabled="true" name="grid_selector_label" height="10" width="100" left="12" bottom="-20" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" - follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" - drop_shadow_visible="true" border_drop_shadow_visible="false"> - Select a grid: - </text> - <combo_box max_chars="20" allow_text_entry="false" name="grid_selector" - height="18" width="200" left="120" bottom_delta="-4" - follows="left|top" mouse_opaque="true" /> - <button label="Default" label_selected="Default" enabled="true" name="btn_default" - height="18" width="75" left_delta="210" bottom_delta="0" - halign="center" - follows="left|top" scale_image="true" - font="SansSerifSmall" mouse_opaque="true" /> - <text type="string" length="1" enabled="true" name="default_grid" - height="10" width="200" left_delta="80" bottom_delta="5" h_pad="0" v_pad="0" halign="left" font="SansSerifSmall" follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" drop_shadow_visible="true" border_drop_shadow_visible="false"> - ([DEFAULT]) - </text> - <!-- Buttons --> - <button label="Delete" label_selected="Delete" enabled="true" name="btn_delete" + Select a grid: + </text> + <combo_box max_chars="20" allow_text_entry="false" name="grid_selector" + height="18" width="200" left="120" bottom_delta="-4" + follows="left|top" mouse_opaque="true" /> + <button label="Default" label_selected="Default" enabled="true" name="btn_default" + height="18" width="75" left_delta="210" bottom_delta="0" + halign="center" + follows="left|top" scale_image="true" + font="SansSerifSmall" mouse_opaque="true" /> + <text type="string" length="1" enabled="true" name="default_grid" + height="10" width="200" left_delta="80" bottom_delta="5" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" + follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" + drop_shadow_visible="true" border_drop_shadow_visible="false"> + ([DEFAULT]) + </text> + <!-- Buttons --> + <button label="Delete" label_selected="Delete" enabled="true" name="btn_delete" height="18" width="75" left="120" bottom_delta="-27" halign="center" follows="left|top" scale_image="true" font="SansSerifSmall" mouse_opaque="true" /> - <button label="Add" label_selected="Add" enabled="true" name="btn_add" + <button label="Add" label_selected="Add" enabled="true" name="btn_add" height="18" width="75" left_delta="78" bottom_delta="0" halign="center" follows="left|top" scale_image="true" font="SansSerifSmall" mouse_opaque="true" /> - <button label="Copy" label_selected="Copy" enabled="true" name="btn_copy" + <button label="Copy" label_selected="Copy" enabled="true" name="btn_copy" height="18" width="75" left_delta="78" bottom_delta="0" halign="center" follows="left|top" scale_image="true" font="SansSerifSmall" mouse_opaque="true" /> - <!-- Login URI --> - <text type="string" length="1" enabled="true" name="loginuri_label" + <!-- Advanced --> + <button label="Advanced" label_selected="Advanced" enabled="true" name="btn_advanced" + height="18" width="75" left_delta="78" bottom_delta="0" + halign="center" + follows="left|top" scale_image="true" + font="SansSerifSmall" mouse_opaque="true" /> + <!-- Login URI --> + <text type="string" length="1" enabled="true" name="loginuri_label" height="10" width="100" left="12" bottom_delta="-32" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" drop_shadow_visible="true" border_drop_shadow_visible="false"> - Login URI: - </text> - <line_editor max_length="254" enabled="true" name="loginuri" - handle_edit_keys_directly="true" + Login URI: + </text> + <line_editor max_length="254" enabled="true" name="loginuri" + handle_edit_keys_directly="true" height="18" left="120" right="-12" bottom_delta="-4" halign="right" font="SansSerifSmall" follows="left|top|right" border_visible="false" mouse_opaque="false" drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <button label="Get Grid Info" label_selected="Get Grid Info" enabled="true" name="btn_gridinfo" + <!--<button label="Get Grid Info" label_selected="Get Grid Info" enabled="true" name="btn_gridinfo" height="18" width="100" left="120" bottom_delta="-22" halign="center" follows="left|top" scale_image="true" - font="SansSerifSmall" mouse_opaque="true" /> - <!-- Platform --> - <text type="string" length="1" enabled="true" name="platform_label" + font="SansSerifSmall" mouse_opaque="true" />--> + <!-- Platform --> + <text type="string" length="1" enabled="true" name="platform_label" height="10" width="100" left="12" bottom_delta="-32" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" drop_shadow_visible="true" border_drop_shadow_visible="false"> - Platform: - </text> - <combo_box max_chars="20" allow_text_entry="false" name="platform" + Platform: + </text> + <combo_box max_chars="20" allow_text_entry="false" name="platform" height="18" width="200" left="120" bottom_delta="-4" follows="left|top" mouse_opaque="true" /> - <!-- Grid Nickname --> - <text type="string" length="1" enabled="true" name="gridnick_label" - height="10" width="100" left="12" bottom_delta="-22" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" - follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" - drop_shadow_visible="true" border_drop_shadow_visible="false"> - Grid Nickname: - </text> - <line_editor max_length="25" enabled="false" name="gridnick" - handle_edit_keys_directly="true" - height="18" width="175" left="120" bottom_delta="-4" - halign="right" - font="SansSerifSmall" - follows="left|top" border_visible="false" mouse_opaque="false" - drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <!-- Grid Name --> - <text type="string" length="1" enabled="true" name="gridname_label" + <!-- Grid Name --> + <text type="string" length="1" enabled="true" name="gridname_label" height="10" width="100" left="12" bottom_delta="-20" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" drop_shadow_visible="true" border_drop_shadow_visible="false"> - Grid Name: - </text> - <line_editor max_length="254" enabled="true" name="gridname" - handle_edit_keys_directly="true" + Grid Name: + </text> + <line_editor max_length="254" enabled="true" name="gridname" + handle_edit_keys_directly="true" height="18" left="120" right="-12" bottom_delta="-4" halign="right" font="SansSerifSmall" follows="left|top|right" border_visible="false" mouse_opaque="false" drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <!-- Grid Splash Page --> - <text type="string" length="1" enabled="true" name="loginpage_label" - height="10" width="100" left="12" bottom_delta="-22" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" + + <!-- Grid Message --> + <text type="string" length="1" enabled="true" name="gridmessage_label" + height="10" width="100" left="12" bottom_delta="-50" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" drop_shadow_visible="true" border_drop_shadow_visible="false"> - Splash Page: - </text> - <line_editor max_length="254" enabled="true" name="loginpage" - handle_edit_keys_directly="true" - height="18" left="120" right="-12" bottom_delta="-4" - halign="right" + Grid Info: + </text> + <text_editor type="string" length="1" bottom="-185" embedded_items="false" enabled="true" follows="left|top|right" + handle_edit_keys_directly="true" + font="SansSerifSmall" height="50" left="120" right="-12" bottom_delta="-4" max_length="512" + mouse_opaque="true" name="gridmessage" word_wrap="true" spell_check="true" /> + + <!-- Advanced settings --> + + <!-- Grid Splash Page --> + <text type="string" length="1" enabled="true" name="loginpage_label" + height="10" width="100" left="12" bottom_delta="-22" visible="false" + h_pad="0" v_pad="0" halign="left" font="SansSerifSmall" - follows="left|top|right" border_visible="false" mouse_opaque="false" - drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <!-- Helper URI --> - <text type="string" length="1" enabled="true" name="helperuri_label" - height="10" width="100" left="12" bottom_delta="-20" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" - drop_shadow_visible="true" border_drop_shadow_visible="false"> - Helper URL: - </text> - <line_editor max_length="254" enabled="true" name="helperuri" - handle_edit_keys_directly="true" + drop_shadow_visible="true" border_drop_shadow_visible="false"> + Splash Page: + </text> + <line_editor max_length="254" enabled="true" name="loginpage" + handle_edit_keys_directly="true" visible="false" height="18" left="120" right="-12" bottom_delta="-4" halign="right" font="SansSerifSmall" follows="left|top|right" border_visible="false" mouse_opaque="false" drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <!-- Web Site --> - <text type="string" length="1" enabled="true" name="website_label" - height="10" width="100" left="12" bottom_delta="-20" + <!-- Helper URI --> + <text type="string" length="1" enabled="true" name="helperuri_label" + height="10" width="100" left="12" bottom_delta="-20" visible="false" h_pad="0" v_pad="0" halign="left" font="SansSerifSmall" follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" drop_shadow_visible="true" border_drop_shadow_visible="false"> - Web Site: - </text> - <line_editor max_length="254" enabled="true" name="website" - handle_edit_keys_directly="true" + Helper URL: + </text> + <line_editor max_length="254" enabled="true" name="helperuri" + handle_edit_keys_directly="true" visible="false" height="18" left="120" right="-12" bottom_delta="-4" halign="right" font="SansSerifSmall" follows="left|top|right" border_visible="false" mouse_opaque="false" drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <!-- Support URL --> - <text type="string" length="1" enabled="true" name="support_label" - height="10" width="100" left="12" bottom_delta="-20" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" - follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" - drop_shadow_visible="true" border_drop_shadow_visible="false"> - Support URL: - </text> - <line_editor max_length="254" enabled="true" name="support" - handle_edit_keys_directly="true" - height="18" left="120" right="-12" bottom_delta="-4" - halign="right" - font="SansSerifSmall" - follows="left|top|right" border_visible="false" mouse_opaque="false" - drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <!-- Account URL --> - <text type="string" length="1" enabled="true" name="register_label" - height="10" width="100" left="12" bottom_delta="-20" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" - follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" - drop_shadow_visible="true" border_drop_shadow_visible="false"> - Account URL: - </text> - <line_editor max_length="254" enabled="true" name="register" - handle_edit_keys_directly="true" - height="18" left="120" right="-12" bottom_delta="-4" - halign="right" - font="SansSerifSmall" - follows="left|top|right" border_visible="false" mouse_opaque="false" - drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <!-- Password URL --> - <text type="string" length="1" enabled="true" name="password_label" - height="10" width="100" left="12" bottom_delta="-20" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" - follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" - drop_shadow_visible="true" border_drop_shadow_visible="false"> - Password URL: - </text> - <line_editor max_length="254" enabled="true" name="password" - handle_edit_keys_directly="true" - height="18" left="120" right="-12" bottom_delta="-4" - halign="right" - font="SansSerifSmall" - follows="left|top|right" border_visible="false" mouse_opaque="false" - drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <!-- Search URL --> - <text type="string" length="1" enabled="true" name="search_label" - height="10" width="100" left="12" bottom_delta="-20" - h_pad="0" v_pad="0" halign="left" - font="SansSerifSmall" - follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" - drop_shadow_visible="true" border_drop_shadow_visible="false"> - Search URL: - </text> - <line_editor max_length="254" enabled="true" name="search" - handle_edit_keys_directly="true" - height="18" left="120" right="-12" bottom_delta="-4" - halign="right" - font="SansSerifSmall" - follows="left|top|right" border_visible="false" mouse_opaque="false" - drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <!-- Rendering Compatibility --> - <check_box enabled="true" radio_style="false" - label="Rendering Compatibility" name="render_compat" + <!-- Web Site --> + <text type="string" length="1" enabled="true" name="website_label" + height="10" width="100" left="12" bottom_delta="-20" visible="false" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" + follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" + drop_shadow_visible="true" border_drop_shadow_visible="false"> + Web Site: + </text> + <line_editor max_length="254" enabled="true" name="website" + handle_edit_keys_directly="true" visible="false" + height="18" left="120" right="-12" bottom_delta="-4" + halign="right" + font="SansSerifSmall" + follows="left|top|right" border_visible="false" mouse_opaque="false" + drop_shadow_visible="true" border_drop_shadow_visible="false" /> + <!-- Support URL --> + <text type="string" length="1" enabled="true" name="support_label" + height="10" width="100" left="12" bottom_delta="-20" visible="false" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" + follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" + drop_shadow_visible="true" border_drop_shadow_visible="false"> + Support URL: + </text> + <line_editor max_length="254" enabled="true" name="support" + handle_edit_keys_directly="true" visible="false" + height="18" left="120" right="-12" bottom_delta="-4" + halign="right" + font="SansSerifSmall" + follows="left|top|right" border_visible="false" mouse_opaque="false" + drop_shadow_visible="true" border_drop_shadow_visible="false" /> + <!-- Account URL --> + <text type="string" length="1" enabled="true" name="register_label" + height="10" width="100" left="12" bottom_delta="-20" visible="false" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" + follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" + drop_shadow_visible="true" border_drop_shadow_visible="false"> + Account URL: + </text> + <line_editor max_length="254" enabled="true" name="register" + handle_edit_keys_directly="true" visible="false" + height="18" left="120" right="-12" bottom_delta="-4" + halign="right" + font="SansSerifSmall" + follows="left|top|right" border_visible="false" mouse_opaque="false" + drop_shadow_visible="true" border_drop_shadow_visible="false" /> + <!-- Password URL --> + <text type="string" length="1" enabled="true" name="password_label" + height="10" width="100" left="12" bottom_delta="-20" visible="false" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" + follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" + drop_shadow_visible="true" border_drop_shadow_visible="false"> + Password URL: + </text> + <line_editor max_length="254" enabled="true" name="password" + handle_edit_keys_directly="true" visible="false" + height="18" left="120" right="-12" bottom_delta="-4" + halign="right" + font="SansSerifSmall" + follows="left|top|right" border_visible="false" mouse_opaque="false" + drop_shadow_visible="true" border_drop_shadow_visible="false" /> + <!-- Search URL --> + <text type="string" length="1" enabled="true" name="search_label" + height="10" width="100" left="12" bottom_delta="-20" visible="false" + h_pad="0" v_pad="0" halign="left" + font="SansSerifSmall" + follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" + drop_shadow_visible="true" border_drop_shadow_visible="false"> + Search URL: + </text> + <line_editor max_length="254" enabled="true" name="search" + handle_edit_keys_directly="true" visible="false" + height="18" left="120" right="-12" bottom_delta="-4" + halign="right" + font="SansSerifSmall" + follows="left|top|right" border_visible="false" mouse_opaque="false" + drop_shadow_visible="true" border_drop_shadow_visible="false" /> + <!-- Rendering Compatibility --> + <check_box enabled="true" radio_style="false" + label="Rendering Compatibility" name="render_compat" visible="false" height="18" left="115" bottom_delta="-35" h_pad="0" v_pad="0" halign="left" font="SansSerifSmall" follows="left|top" bg_visible="false" border_visible="false" mouse_opaque="true" drop_shadow_visible="true" border_drop_shadow_visible="false" /> - <button label="?" label_selected="?" enabled="true" name="btn_help_render_compat" - height="18" width="18" left_delta="160" bottom_delta="1" + <button label="?" label_selected="?" enabled="true" name="btn_help_render_compat" + height="18" width="18" left_delta="160" bottom_delta="1" visible="false" halign="center" follows="left|top" font="SansSerifSmall" mouse_opaque="true" /> </panel> diff --git a/indra/newview/skins/default/xui/en-us/strings.xml b/indra/newview/skins/default/xui/en-us/strings.xml index ba0074d58..83db17102 100644 --- a/indra/newview/skins/default/xui/en-us/strings.xml +++ b/indra/newview/skins/default/xui/en-us/strings.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="utf-8" standalone="yes" ?> <!-- This file contains strings that used to be hardcoded in the source. It is only for those strings which don't belong in a floater. - For example, the strings used in avatar chat bubbles, and strings + For example, the strings used in avatar chat bubbles, and strings that are returned from one component and may appear in many places--> <strings> - + <string name="hippo_label_free">free</string> <string name="hippo_label_week">week</string> <string name="TeleportOfferMaturity"> @@ -12,7 +12,7 @@ </string> <string name="TeleportLureMaturity"> [NAME]'s teleport lure is to [DESTINATION] - </string> + </string> <!-- Login --> <string name="LoginInProgress">Logging in. [APP_NAME] may appear frozen. Please wait.</string> @@ -36,8 +36,8 @@ <!-- Disconnection --> <string name="AgentLostConnection">This region may be experiencing trouble. Please check your connection to the Internet.</string> - - + + <!-- Tooltip, llhoverview.cpp --> <string name="TooltipPerson">Person</string><!-- Object under mouse pointer is an avatar --> <string name="TooltipNoName">(no name)</string> <!-- No name on an object --> @@ -63,9 +63,9 @@ <string name="TooltipFlagGroupScripts">Group Scripts</string> <string name="TooltipFlagNoScripts">No Scripts</string> <string name="TooltipLand">Land:</string> - <string name="TooltipMustSingleDrop">Only a single item can be dragged here</string> + <string name="TooltipMustSingleDrop">Only a single item can be dragged here</string> + - <!-- Indicates that an avatar's name or other similar datum is being retrieved. General usage. --> <string name="RetrievingData">Retrieving...</string> @@ -73,21 +73,21 @@ <!-- Indicates something is being loaded. Maybe should be merged with RetrievingData --> <string name="LoadingData">Loading...</string> - - + + <!-- namecache --> <!-- Avatar name: text shown for LLUUID::null --> <string name="AvatarNameNobody">(nobody)</string> - + <!-- Avatar name: text shown while fetching name --> <string name="AvatarNameWaiting">(waiting)</string> <!-- Avatar name: text shown as an alternative to AvatarNameFetching, easter egg. --> <string name="AvatarNameHippos">(hippos)</string> - + <!-- Group name: text shown for LLUUID::null --> <string name="GroupNameNone">(none)</string> - + <!-- Asset errors. Used in llassetstorage.cpp, translation from error code to error message. --> <string name="AssetErrorNone">No error</string> <string name="AssetErrorRequestFailed">Asset request: failed</string> @@ -100,7 +100,7 @@ <string name="AssetErrorCircuitGone">Circuit gone</string> <string name="AssetErrorPriceMismatch">Viewer and server do not agree on price</string> <string name="AssetErrorUnknownStatus">Unknown status</string> - + <!-- llvoavatar. Displayed in the avatar's chat bubble --> <string name="AvatarEditingApparance">(Editing Appearance)</string> <string name="AvatarAway">Away</string> @@ -177,24 +177,24 @@ <string name="anim_express_worry">Worry</string> <string name="anim_yes_happy">Yes (Happy)</string> <string name="anim_yes_head">Yes</string> - + <string name="texture_loading">Loading...</string> <string name="worldmap_offline">Offline</string> - + <!-- Chat --> <string name="whisper">whispers:</string> <string name="shout">shouts:</string> - + <!-- Sim Access labels --> <string name="SIM_ACCESS_PG">PG</string> <string name="SIM_ACCESS_MATURE">Mature</string> <string name="SIM_ACCESS_ADULT">Adult</string> <string name="SIM_ACCESS_DOWN">Offline</string> <string name="SIM_ACCESS_MIN">Unknown</string> - + <!-- For use when we do not have land type back from the server --> <string name="land_type_unknown">(unknown)</string> - + <!-- Covenant info --> <string name="covenant_never_modified">Last Modified: (never)</string> <string name="covenant_modified">Last Modified: </string> @@ -215,7 +215,7 @@ <string name="compressed_image_files">Compressed Images</string> <string name="load_files">Load Files</string> <string name="choose_the_directory">Choose Directory</string> - + <!-- LSL Usage Hover Tips --> <string name="LSLTipSleepTime"> Sleeps script for [SLEEP_TIME] seconds. @@ -1650,8 +1650,8 @@ string llGetHTTPHeader(key request_id, string header) Returns the value for header for request_id </string> <string name="LSLTipText_llSetPrimMediaParams"> - integer llSetPrimMediaParams(integer face, list params) - Returns an integer that is a STATUS_* flag which details the success/failure of the operation(s). +integer llSetPrimMediaParams(integer face, list params) +Returns an integer that is a STATUS_* flag which details the success/failure of the operation(s). </string> <string name="LSLTipText_llGetPrimMediaParams"> list llGetPrimMediaParams(integer face, list params) @@ -1659,54 +1659,589 @@ Returns the media params for a particular face on an object, given the desired l (Returns an empty list if no media exists on the face.) </string> <string name="LSLTipText_llClearPrimMedia"> - integer llClearPrimMedia(integer face) - Returns an integer that is a STATUS_* flag which details the success/failure of the operation. +integer llClearPrimMedia(integer face) +Returns an integer that is a STATUS_* flag which details the success/failure of the operation. </string> <string name="LSLTipText_llSetLinkPrimitiveParamsFast"> - llSetLinkPrimitiveParamsFast(integer linknumber, list rules) - Set primitive parameters for linknumber based on rules with no built-in script sleep. +llSetLinkPrimitiveParamsFast(integer linknumber, list rules) +Set primitive parameters for linknumber based on rules with no built-in script sleep. </string> <string name="LSLTipText_llGetLinkPrimitiveParams"> - list llGetLinkPrimitiveParams(integer linknumber,list rules) +list llGetLinkPrimitiveParams(integer linknumber,list rules) Get primitive parameters for linknumber based on rules. </string> <string name="LSLTipText_llLinkParticleSystem"> - list llLinkParticleSystem(integer linknumber, list rules) +list llLinkParticleSystem(integer linknumber, list rules) Creates a particle system based on rules. Empty list removes particle system from object. List format is [ rule1, data1, rule2, data2 . . . rulen, datan ]. </string> <string name="LSLTipText_llSetLinkTextureAnim"> - llSetLinkTextureAnim(integer link, integer mode, integer face, integer sizex, integer sizey, float start, float length, float rate) - Animate the texture on the specified face/faces of the specified prim/prims by setting the texture scale and offset. +llSetLinkTextureAnim(integer link, integer mode, integer face, integer sizex, integer sizey, float start, float length, float rate) +Animate the texture on the specified face/faces of the specified prim/prims by setting the texture scale and offset. </string> <string name="LSLTipText_llGetLinkNumberOfSides"> - integer llGetLinkNumberOfSides(integer link) - Returns the number of sides of the specified linked prim. +integer llGetLinkNumberOfSides(integer link) +Returns the number of sides of the specified linked prim. </string> <string name="LSLTipText_llGetUsername"> - string llGetUsername(key id) - Returns the single-word username of an avatar, iff the avatar is in the current region, otherwise the empty string. +string llGetUsername(key id) +Returns the single-word username of an avatar, if the avatar is in the current region, otherwise the empty string. </string> <string name="LSLTipText_llRequestUsername"> - key llRequestUsername(key id) - Requests single-word username of an avatar. When data is available the dataserver event will be raised. +key llRequestUsername(key id) +Requests single-word username of an avatar. When data is available the dataserver event will be raised. </string> <string name="LSLTipText_llGetDisplayName"> - string llGetDisplayName(key id) - Returns the name of an avatar, iff the avatar is in the current simulator, and the name has been cached, otherwise the same as llGetUsername. Use llRequestDisplayName if you absolutely must have the display name. +string llGetDisplayName(key id) +Returns the name of an avatar, if the avatar is in the current simulator, and the name has been cached, otherwise the same as llGetUsername. Use llRequestDisplayName if you absolutely must have the display name. </string> <string name="LSLTipText_llRequestDisplayName"> - key llRequestDisplayName(key id) - Requests name of an avatar. When data is available the dataserver event will be raised. +key llRequestDisplayName(key id) +Requests name of an avatar. When data is available the dataserver event will be raised. </string> -<string name="LSLTipText_llRegionSayTo"> + <string name="LSLTipText_llRegionSayTo"> llRegionSayTo(key target, integer channel, string msg) Sends msg on channel (not DEBUG_CHANNEL) directly to prim or avatar target anywhere within the region -</string> -<string name="LSLTipText_llGetEnv"> + </string> + <string name="LSLTipText_llGetEnv"> string llGetEnv(string name) Returns a string with the requested data about the region -</string> + </string> + <string name="LSLTipText_llCastRay"> +list llCastRay( Vector start, Vector end, list options ) +Returns a list consisting of the following three values for each hit: UUID, Link number, Hit position. + </string> + <string name="LSLTipText_llGetSPMaxMemory"> +integer llGetSPMaxMemory( ) +Returns the integer of the most bytes used while llScriptProfiler was last active. + </string> + <string name="LSLTipText_llGetUsedMemory"> +integer llGetUsedMemory( ) +Returns the integer of the number of bytes of memory currently in use by the script. + </string> + <string name="LSLTipText_llGodLikeRezObject"> +llGodLikeRezObject( key inventory, vector pos ) +Rez directly off of UUID if owner has god-bit set. +(Requires god mode) + </string> + <string name="LSLTipText_llScriptProfiler"> +llScriptProfiler( integer flags ) +Enables or disables the scripts profiling state. + </string> + <string name="LSLTipText_llSetInventoryPermMask"> +llSetInventoryPermMask( string item, integer mask, integer value ) +Sets the given permission mask to the new value on the inventory item. +(Requires god mode) + </string> + <string name="LSLTipText_llSetObjectPermMask"> +llSetObjectPermMask( integer mask, integer value ) +Sets the given permission mask to the new value on the root object the task is attached to. +(Requires god mode) + </string> + +<!-- Addition of OSSL commands for use in OpenSimulator based regions, including Aurora --> + <string name="LSLTipText_osSetRegionWaterHeight"> +osSetRegionWaterHeight(float height) +Adjusts water height on region. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetRegionSunSettings"> +osSetRegionSunSettings(integer useEstateSun, integer sunFixed, float sunHour) +Changes the estate sun settings, then triggers a sun update +'sunFixed' TRUE to keep the sun stationary, FALSE to use global time +'sunHour' The sun hour that is desired, 0...24, 0 is sunrise. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetEstateSunSettings"> +osSetEstateSunSettings(integer sunFixed, float sunHour) +sunFixed = TRUE or FALSE, sunHour = 00.00 to 24.00. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetCurrentSunHour"> +float osGetCurrentSunHour() +Returns float value of current sun hour 0...24 0 is sunrise. +(OpenSim only.) + </string> + <string name="LSLTipText_osSunGetParam"> +*DEPRECATED* Use osGetSunParam instead. +(OpenSim only.) + </string> + <string name="LSLTipText_osSunSetParam"> +*DEPRECATED* Use osSetSunParam instead. +(OpenSim only.) + </string> + <string name="LSLTipText_osWindActiveModelPluginName"> +string osWindActiveModelPluginName() +Returns the current working wind module installed +These are SimpleRandomWind or ConfigurableWind. +(OpenSim only.) + </string> + <string name="LSLTipText_osParcelJoin"> +osParcelJoin(vector pos1, vector pos2)) +Joins parcels @ X,Y coordinates. +(OpenSim only.) + </string> + <string name="LSLTipText_osParcelSubdivide"> +osParcelSubdivide(vector pos1, vector pos2)) +Subdivides parcels @ X,Y coordinates. +(OpenSim only.) + </string> + <string name="LSLTipText_osParcelSetDetails"> +*DEPRECATED* Use osSetParcelDetails instead. +(OpenSim only.) + </string> + <string name="LSLTipText_osWindParamSet"> +*DEPRECATED* Use osSetWindParam instead. +(OpenSim only.) + </string> + <string name="LSLTipText_osWindParamGet"> +*DEPRECATED* Use osGetWindParam instead. +(OpenSim only.) + </string> + <string name="LSLTipText_osList2Double"> +double osList2Double(list src, integer index) +Returns double-precision value from src at index. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetDynamicTextureURL"> +osSetDynamicTextureURL(key dynamicID, string contentType, string url, string extraParams, integer timer ) +Renders a web texture on the prim containing the script, and returns the UUID of the newly created texture. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetDynamicTextureData"> +osSetDynamicTextureData(key dynamicID, string contentType, string data, string extraParams, integer timer) +Writes text and vector graphics onto a prim face. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetDynamicTextureURLBlend"> +osSetDynamicTextureURLBlend(key dynamicID, string contentType, string url, string extraParams, integer timer, integer alpha) +Allows for two dynamic textures to blend on the prim containing this script. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetDynamicTextureDataBlend"> +osSetDynamicTextureDataBlend(key dynamicID, string contentType, string data, string extraParams, integer timer, integer alpha) +Allows for two dynamic textures to blend on the prim containing this script. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetDynamicTextureURLBlendFace"> +osSetDynamicTextureURLBlendFace(key dynamicID, string contentType, string url, string extraParams, integer blend, integer disp, integer timer, integer alpha, integer face) +Loads a web texture on a prim. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetDynamicTextureDataBlendFace"> +osSetDynamicTextureDataBlendFace(key dynamicID, string contentType, string data, string extraParams, integer blend, integer disp, integer timer, integer alpha, integer face) +(OpenSim only.) + </string> + <string name="LSLTipText_osTerrainGetHeight"> +*DEPRECATED* Use osGetTerrainHeight instead. +(OpenSim only.) + </string> + <string name="LSLTipText_osTerrainSetHeight"> +*DEPRECATED* Use osSetTerrainHeight instead. +(OpenSim only.) + </string> + <string name="LSLTipText_osTerrainFlush"> +osTerrainFlush() +Updates terrain data. Call this after you are done using osTerrainSetHeight. +(OpenSim only.) + </string> + <string name="LSLTipText_osRegionRestart"> +integer osRegionRestart(float seconds) +Restart the current region in the specified number of seconds from now. +(OpenSim only.) + </string> + <string name="LSLTipText_osRegionNotice"> +osRegionNotice(string msg) +Broadcasts a notification message to all agents on the current region. +(OpenSim only.) + </string> + <string name="LSLTipText_osConsoleCommand"> +osConsoleCommand(string command) +Issues commands directly to the OpenSim server console. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetParcelMediaURL"> +osSetParcelMediaURL(string url) +Sets parcel media URL. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetParcelSIPAddress"> +osSetParcelSIPAddress(string SIPAddress) +Sets parcel SIP Address for Voice. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetPrimFloatOnWater"> +osSetPrimFloatOnWater(integer floatYN) +Make physical prims float at the water level, TRUE or FALSE. +(OpenSim only.) + </string> + <string name="LSLTipText_osTeleportAgent"> +osTeleportAgent(key agent, integer regionX, integer regionY, vector position, vector lookat) + or +osTeleportAgent(key agent, string regionName, vector position, vector lookat) + or +osTeleportAgent(key agent, vector position, vector lookat) +Teleports the specified agent to a specified location in the region, the grid, or the hypergrid. See documentation for details. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetAgentIP"> +string osGetAgentIP(key agent) +Returns the Avatars IP Address +Allows in-world tools be used to coordinate out of world network services that need access to client IP addresses. +Should *ONLY* be used by Region Server Owner. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetAgents"> +list osGetAgents() +Returns a list of all avatars in the region in which the script is running. +(OpenSim only.) + </string> + <string name="LSLTipText_osAvatarPlayAnimation"> +osAvatarPlayAnimation(key UUID, string animation) +Triggers animations contained within the same prim as the script. Does not need the target avatar's permission. +(OpenSim only.) + </string> + <string name="LSLTipText_osAvatarStopAnimation"> +osAvatarStopAnimation(key UUID, string animation) +Stops specified animation on the specified avatar. +(OpenSim only.) + </string> + <string name="LSLTipText_osMovePen"> +osMovePen(string drawList, integer x, integer y) +Moves the pen's location to the coordinates specified by the x and y parameters, without drawing anything. +(OpenSim only.) + </string> + <string name="LSLTipText_osDrawLine"> +osDrawLine(string drawList, integer startX, integer startY, integer endX, integer endY) +osDrawLine(string drawList, integer endX, integer endY) +Draws a line on a dynamic texture. +(OpenSim only.) + </string> + <string name="LSLTipText_osDrawText"> +osDrawText(string drawList, string text) +Renders text on a dynamic texture. +(OpenSim only.) + </string> + <string name="LSLTipText_osDrawEllipse"> +osDrawEllipse(string drawList, integer width, integer height) +Draws an ellipse on a dynamic texture. +(OpenSim only.) + </string> + <string name="LSLTipText_osDrawRectangle"> +osDrawRectangle(string drawList, integer width, integer height) +Draws a rectangle on a dynamic texture. +(OpenSim only.) + </string> + <string name="LSLTipText_osDrawFilledRectangle"> +osDrawFilledRectangle(string drawList, integer width, integer height) +Draws a rectangle on a dynamic texture, and fills it with the current pen color. +(OpenSim only.) + </string> + <string name="LSLTipText_osDrawPolygon"> +string osDrawPolygon (string drawList, list x, list y) +Draws a polygon on a dynamic texture. +(OpenSim only.) + </string> + <string name="LSLTipText_osDrawFilledPolygon"> +string osDrawFilledPolygon (string drawList, list x, list y) +Draws a polygon on a dynamic texture, and fills it with the current pen color. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetFontSize"> +osSetFontSize(string drawList, integer fontSize) +Sets the font size to be used in osDrawText. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetFontName"> +osSetFontName(string drawList, string fontName) +Sets current font to be used by osDrawText. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetPenSize"> +osSetPenSize(string drawList, integer penSize) +Sets the pen size (line thickness) that is to be used when drawing dynamic textures. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetPenCap"> +osSetPenCap(string drawList, string direction, string type) +Apply a shape on the end of a line. This allows using arrow, diamond, round and flat caps. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetPenColour"> +*DEPRECATED* Use osSetPenColor instead +(OpenSim only.) + </string> + <string name="LSLTipText_osDrawImage"> +osDrawImage(string drawList, integer width, integer height, string imageUrl) +Retrieves an image specified by the imageUrl parameter and draws it at the specified height and width. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetDrawStringSize"> +vector osGetDrawStringSize(string contentType, string text, string fontName, integer fontSize) +Returns a vector containing the horizontal and vertical dimensions in pixels of the specified text +(OpenSim only.) + </string> + <string name="LSLTipText_osSetStateEvents"> +osSetStateEvents(integer events) +Used in the past as a workaround for a bug with Opensim, which has long since been fixed. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetScriptEngineName"> +string osGetScriptEngineName() +Returns the name of the script engine which is currently enabled on the server. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetSimulatorVersion"> +string osGetSimulatorVersion() +Returns OpenSim server version information as a string. +(OpenSim only.) + </string> + <string name="LSLTipText_osParseJSON"> +string osParseJSON(string JSON) +Returns a hashtable containing the structured JSON contents. +(OpenSim only.) + </string> + <string name="LSLTipText_osMessageObject"> +osMessageObject(key UUID, string message) +Sends a string to the object identified by UUID. +The receiving object requires a dataserver(key queryid, string data) in a contained script(s). +The queryid passed will be the id of the calling object. +(OpenSim only.) + </string> + <string name="LSLTipText_osMakeNotecard"> +osMakeNotecard(string notecardName, list contents) +Write a Notecard contained in Prim with contents of list. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetNotecardLine"> +string osGetNotecardLine(string name, integer line) +Reads the requested notecard line and return its data as a string. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetNotecard"> +string osGetNotecard(string name) +Reads the entire notecard and return its data as a string. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetNumberOfNotecardLines"> +integer osGetNumberOfNotecardLines(string name) +Returns total number of lines in a notecard. +(OpenSim only.) + </string> + <string name="LSLTipText_osAvatarName2Key"> +key osAvatarName2Key(string firstname, string lastname) +Returns the avatar's UUID from their firstname, lastname. +(OpenSim only.) + </string> + <string name="LSLTipText_osKey2Name"> +string osKey2Name(key UUID) +Returns avatar name from their UUID key. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetGridNick"> +string osGetGridNick() +Returns the grid's nickname. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetGridName"> +string osGetGridName() +Returns the grid's name. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetGridLoginURI"> +string osGetGridLoginURI() +Returns the grid's LoginURI. +(OpenSim only.) + </string> + <string name="LSLTipText_osFormatString"> +string osFormatString(string str, list strings) +Return the string with parameters substituted into it (format comes from .NET String.Format class) +Parameters are specified positionally. +(OpenSim only.) + </string> + <string name="LSLTipText_osMatchString"> +list osMatchString(string src, string pattern, integer start) +Return a list of matches for the pattern and its components inside the source string. +The pattern is a regular expression. Each match in the result is the string that matched and its position in the source. +(OpenSim only.) + </string> + <string name="LSLTipText_osLoadedCreationDate"> +string osLoadedCreationDate() +Returns Creation Date from meta data of OAR. +(OpenSim only.) + </string> + <string name="LSLTipText_osLoadedCreationTime"> +string osLoadedCreationTime() +Returns Creation Time from meta data of OAR. +(OpenSim only.) + </string> + <string name="LSLTipText_osLoadedCreationID"> +string osLoadedCreationID() +Returns creation ID from meta data of OAR. Can not be used to identify a machine. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetLinkPrimitiveParams"> +list osGetLinkPrimitiveParams(integer linknumber, list rules) +Returns the primitive parameters for the linkset prims specified by linknumber. If using linkset constants (e.g. LINK_SET, LINK_ALL_CHILDREN, etc), the requested parameters of each relevant prim are concatenated to the end of the list. Otherwise, usage is identical to llGetPrimitiveParams(). +(OpenSim only.) + </string> + <string name="LSLTipText_osNpcCreate"> +key osNpcCreate(string firstname, string lastname, vector position, key UUID) +Creates an NPC (Non Player Character) clone named firstname lastname at position from an already existing avatar specified by UUID. +(OpenSim only.) + </string> + <string name="LSLTipText_osNpcMoveTo"> +osNpcMoveTo(key npc, vector position) +Moves an NPC to a location within the region. +(OpenSim only.) + </string> + <string name="LSLTipText_osNpcSay"> +osNpcSay(key npc, string message) +Makes an NPC say something. +(OpenSim only.) + </string> + <string name="LSLTipText_osNpcRemove"> +osNpcRemove(key npc) +Removes an NPC. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetMapTexture"> +key osGetMapTexture() +Returns the map texture UUID. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetRegionMapTexture"> +key osGetRegionMapTexture(string regionName) +Returns the map texture UUID for the regionName requested. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetRegionStats"> +list osGetRegionStats() +Returns a list of float values representing a number of region statistics (21 of the values shown in the statistics bar of LL-based clients). +(OpenSim only.) + </string> + <string name="LSLTipText_osGetSimulatorMemory"> +integer osGetSimulatorMemory() +Returns the current amount of RAM used by the current OpenSim instance. +(OpenSim only.) + </string> + <string name="LSLTipText_osKickAvatar"> +osKickAvatar(string FirstName, string LastName, string alert) +Kicks avatar from region with an alert message. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetSpeed"> +osSetSpeed(key UUID, float SpeedModifier) +Multiplies the normal running, walking, and flying speed of the specified avatar. +(OpenSim only.) + </string> + <string name="LSLTipText_osCauseDamage"> +osCauseDamage(key UUID, float damage) +Causes damage to specified avatar. +(OpenSim only.) + </string> + <string name="LSLTipText_osCauseHealing"> +osCauseHealing(key UUID, float healing) +Causes healing to specified avatar. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetPrimitiveParams"> +list osGetPrimitiveParams(key prim, list rules) +Gets the parameters of the primitive, specified by key. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetPrimitiveParams"> +osSetPrimitiveParams(key prim, list rules) +Sets primitive Params. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetProjectionParams"> +osSetProjectionParams(key prim. integer projection, key texture, float fov, float focus, float amb) +Set projection paramaters for light sources. +(OpenSim only.) + </string> + <string name="LSLTipText_osUnixTimeToTimestamp"> +string osUnixTimeToTimestamp(integer unixtime) +Converts unixtime to an llGetTimeStamp() formated string. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetPenColor"> +osSetPenColor(string drawList, string color) +Sets the pen color that is to be used when drawing dynamic textures. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetSunParam"> +float osGetSunParam(string param) +Returns current float values for param, where param = day_length, year_length, day_night_offset, update_interval. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetSunParam"> +osSetSunParam(string param, float value) +Sets region's sun parameters, where param = day_length, year_length, day_night_offset, update_interval. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetParcelDetails"> +osSetParcelDetails(vector pos, list rules) +Set parcel details. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetTerrainHeight"> +float osGetTerrainHeight(integer x, integer y) +Returns current terrain height at the given coordinates. +(OpenSim only.) + </string> + <string name="LSLTipText_osSetTerrainHeight"> +osSetTerrainHeight(integer x, integer y, float val) +Sets terrain height at the given coordinates. Use osTerrainFlush() afterwards. +(OpenSim only.) + </string> + <string name="LSLTipText_osGetAvatarList"> +list osGetAvatarList() +Returns a strided list of the UUID, position, and name of each avatar in the region, except the owner. +(OpenSim only.) + </string> + <string name="LSLTipText_osTeleportOwner"> +osTeleportOwner(integer regionX, integer regionY, vector position, vector lookat) + or +osTeleportOwner(string regionName, vector position, vector lookat) + or +osTeleportOwner(vector position, vector lookat) +Teleports the owner of the object that holds the script to a specified location in the region, the grid, or the hypergrid. See documentation for details. +(OpenSim only.) + </string> + + <!-- LightShare functions --> + <string name="LSLTipText_cmSetWindlightScene"> +integer cmSetWindlightScene(list rules) +Set the current WindLight scene. Estate managers and owners only. +(Reguires LightShare) + </string> + <string name="LSLTipText_cmSetWindlightSceneTargeted"> +integer cmSetWindlightSceneTargeted(list rules, key target) +Set the current WindLight scene directed at a specific avatar. Estate managers and owners only. +(Reguires LightShare) + </string> + <string name="LSLTipText_cmGetWindlightScene"> +list cmGetWindlightScene(list rules) +Get the current WindLight settings. +(Reguires LightShare) + </string> + <!-- LightShare functions - alternate versions --> + <!-- don't ask me why they renamed 'em, but we need to include both versions - - MC --> + <string name="LSLTipText_lsSetWindlightScene"> +integer lsSetWindlightScene(list rules) +Set the current WindLight scene. Estate managers and owners only. +(Reguires LightShare) + </string> + <string name="LSLTipText_lsSetWindlightSceneTargeted"> +integer lsSetWindlightSceneTargeted(list rules, key target) +Set the current WindLight scene directed at a specific avatar. Estate managers and owners only. +(Reguires LightShare) + </string> + <string name="LSLTipText_lsGetWindlightScene"> +list lsGetWindlightScene(list rules) +Get the current WindLight settings. +(Reguires LightShare) + </string> </strings> - diff --git a/indra/newview/statemachine/aievent.cpp b/indra/newview/statemachine/aievent.cpp index 0e7e9fa6e..ec2901932 100644 --- a/indra/newview/statemachine/aievent.cpp +++ b/indra/newview/statemachine/aievent.cpp @@ -40,7 +40,7 @@ struct AIRSData { AIRSData(bool one_shot) : mOneShot(one_shot) { } }; -// A list of all statemachines registered for a particular event, and and API to work on it. +// A list of all statemachines registered for a particular event, and an API to work on it. struct AIRegisteredStateMachines { typedef std::map<AIStateMachine*, AIRSData> rsm_type; rsm_type mRegisteredStateMachines; diff --git a/indra/newview/statemachine/aievent.h b/indra/newview/statemachine/aievent.h index a90a04aaf..34ecc4db3 100644 --- a/indra/newview/statemachine/aievent.h +++ b/indra/newview/statemachine/aievent.h @@ -56,7 +56,7 @@ class AIEvent { * * This may be called for already unregistered events. * This should be called from the destructor of a statemachine for any event it registers, - * as well as when it doesn't need the event anymore (in the case on non- one shot events). + * as well as when it doesn't need the event anymore (in the case of non- one shot events). * * @param event the event we want to no longer be notified off. * @param statemachine the statemachine. diff --git a/indra/newview/statemachine/aifetchinventoryfolder.cpp b/indra/newview/statemachine/aifetchinventoryfolder.cpp index 9b19ee155..a0af969d1 100644 --- a/indra/newview/statemachine/aifetchinventoryfolder.cpp +++ b/indra/newview/statemachine/aifetchinventoryfolder.cpp @@ -88,7 +88,10 @@ void AIFetchInventoryFolder::initialize_impl(void) mNeedNotifyObservers = false; set_state(AIFetchInventoryFolder_checkFolderExists); if (!gInventory.isInventoryUsable()) + { + // This immediately calls this->idle(), and then when the event occurs cont(). AIEvent::Register(AIEvent::LLInventoryModel_mIsAgentInvUsable_true, this); + } } void AIFetchInventoryFolder::multiplex_impl(void) diff --git a/indra/newview/statemachine/aifilepicker.cpp b/indra/newview/statemachine/aifilepicker.cpp index fdfb5a968..38cbf6996 100644 --- a/indra/newview/statemachine/aifilepicker.cpp +++ b/indra/newview/statemachine/aifilepicker.cpp @@ -82,7 +82,7 @@ std::string AIFilePicker::get_folder(std::string const& default_path, std::strin { AIAccess<context_map_type> wContextMap(sContextMap); context_map_type::iterator iter = wContextMap->find(context); - if (iter != wContextMap->end()) + if (iter != wContextMap->end() && !iter->second.empty()) { return iter->second; } @@ -91,22 +91,37 @@ std::string AIFilePicker::get_folder(std::string const& default_path, std::strin LL_DEBUGS("Plugin") << "context \"" << context << "\" not found. Returning default_path \"" << default_path << "\"." << LL_ENDL; return default_path; } - else if ((iter = wContextMap->find("savefile")) != wContextMap->end()) + else if ((iter = wContextMap->find("savefile")) != wContextMap->end() && !iter->second.empty()) { LL_DEBUGS("Plugin") << "context \"" << context << "\" not found and default_path empty. Returning context \"savefile\": \"" << iter->second << "\"." << LL_ENDL; return iter->second; } else { - LL_DEBUGS("Plugin") << "context \"" << context << "\" not found, default_path empty and context \"savefile\" not found. Returning \"$HOME\"." << LL_ENDL; // This is the last resort when all else failed. Open the file chooser in directory 'home'. - char const* home = NULL; #if LL_WINDOWS - home = getenv("HOMEPATH"); + char const* envname = "USERPROFILE"; #else - home = getenv("HOME"); + char const* envname = "HOME"; #endif - return home ? home : ""; + char const* home = getenv(envname); + if (!home || home[0] == '\0') + { +#if LL_WINDOWS + // On windows, the filepicker window won't pop up at all if we pass an empty string. + home = "C:\\"; +#else + home = "/"; +#endif + LL_DEBUGS("Plugin") << "context \"" << context << "\" not found, default_path empty, context \"savefile\" not found " + "and environment variable \"$" << envname << "\" empty! Returning \"" << home << "\"." << LL_ENDL; + } + else + { + LL_DEBUGS("Plugin") << "context \"" << context << "\" not found, default_path empty and context \"savefile\" not found. " + "Returning environment variable \"$" << envname << "\" (" << home << ")." << LL_ENDL; + } + return home; } } diff --git a/indra/newview/statemachine/aistatemachine.cpp b/indra/newview/statemachine/aistatemachine.cpp index 2eccfb53e..bdf43fcdc 100644 --- a/indra/newview/statemachine/aistatemachine.cpp +++ b/indra/newview/statemachine/aistatemachine.cpp @@ -79,7 +79,7 @@ AITHREADSAFESIMPLE(U64, AIStateMachine::sMaxCount, ); void AIStateMachine::updateSettings(void) { Dout(dc::statemachine, "Initializing AIStateMachine::sMaxCount"); - *AIAccess<U64>(sMaxCount) = LLFastTimer::countsPerSecond() * gSavedSettings.getU32("StateMachineMaxTime") / 1000; + *AIAccess<U64>(sMaxCount) = LLFastTimer::sClockResolution * gSavedSettings.getU32("StateMachineMaxTime") / 1000; } //---------------------------------------------------------------------------- @@ -319,7 +319,7 @@ void AIStateMachine::mainloop(void*) if (total_clocks >= max_count) { #ifndef LL_RELEASE_FOR_DOWNLOAD - llwarns << "AIStateMachine::mainloop did run for " << (total_clocks * 1000 / LLFastTimer::countsPerSecond()) << " ms." << llendl; + llwarns << "AIStateMachine::mainloop did run for " << (total_clocks * 1000 / LLFastTimer::sClockResolution) << " ms." << llendl; #endif std::sort(active_statemachines.begin(), active_statemachines.end(), QueueElementComp()); break; diff --git a/indra/newview/statemachine/aistatemachine.h b/indra/newview/statemachine/aistatemachine.h index 094f30031..0c905668c 100644 --- a/indra/newview/statemachine/aistatemachine.h +++ b/indra/newview/statemachine/aistatemachine.h @@ -70,14 +70,16 @@ // .-------. | | // | Run |_, | Call multiplex_impl() until idle(), abort() or finish() is called. // '-------' | -// | | | -// v | | -// Abort | | Calls abort_impl(). -// | | | -// v v | -// Finish | Calls finish_impl(). -// | | -// `---------' +// | | | +// v | | +// Abort | | Calls abort_impl(). +// | | | +// v v | +// Finish | Calls finish_impl(), which may call kill() and/or the callback +// | | | function passed to run(), if any, which may call kill() and/or run(). +// | `-------' +// v +// Killed Delete the statemachine (all statemachines must be allocated with new). // // Each state causes corresponding code to be called. // Finish cleans up whatever is done by Initialize. @@ -93,6 +95,12 @@ // abort() in case of failure, or finish() in case of success. // Respectively these set the state to Abort and Finish. // +// finish_impl may call kill() for a (default) destruction upon finish. +// Even in that case the callback (passed to run()) may call run() again, +// which overrides the request for a default kill. Or, if finish_impl +// doesn't call kill() the callback may call kill() to request the +// destruction of the state machine object. +// // State machines are run from the "idle" part of the viewer main loop. // Often a state machine has nothing to do however. In that case it can // call the method idle(). This will stop the state machine until @@ -184,7 +192,7 @@ class AIStateMachine { base_state_type mState; //!< State of the base class. bool mIdle; //!< True if this state machine is not running. bool mAborted; //!< True after calling abort() and before calling run(). - bool mQueued; //!< True when the statemachine is queued to be added back to the active list. + bool mQueued; //!< True when the statemachine is queued to be added back to the active list. S64 mSleep; //!< Non-zero while the state machine is sleeping. // Callback facilities. diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index 750c9faa5..ad9561f53 100644 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -2,83 +2,70 @@ * @file llagentaccess_test.cpp * @brief LLAgentAccess tests * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * 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. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * 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. * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ + +#include "linden_common.h" #include "../test/lltut.h" #include "../llagentaccess.h" -#include "llcontrolgroupreader.h" +#include "llcontrol.h" #include "indra_constants.h" #include <iostream> -class LLControlGroupReader_Test : public LLControlGroupReader -{ -public: - LLControlGroupReader_Test() : test_preferred_maturity(SIM_ACCESS_PG) {} - - virtual std::string getString(const std::string& name) const - { - return ""; - } - virtual std::string getText(const std::string& name) - { - return ""; - } - virtual BOOL getBOOL(const std::string& name) - { - return false; - } - virtual S32 getS32(const std::string& name) - { - return 0; - } - virtual F32 getF32(const std::string& name) - { - return 0; - } - virtual U32 getU32(const std::string& name) - { - return test_preferred_maturity; - } - - //-------------------------------------- - // Everything from here down is test code and not part of the interface - void setPreferredMaturity(U32 m) - { - test_preferred_maturity = m; - } -private: - U32 test_preferred_maturity; - -}; +//---------------------------------------------------------------------------- +// Implementation of enough of LLControlGroup to support the tests: +static U32 test_preferred_maturity = SIM_ACCESS_PG; + +LLControlGroup::LLControlGroup(const std::string& name) + : LLInstanceTracker<LLControlGroup, std::string>(name) +{ +} + +LLControlGroup::~LLControlGroup() +{ +} + +// Implementation of just the LLControlGroup methods we requre +BOOL LLControlGroup::declareU32(const std::string& name, U32 initial_val, const std::string& comment, BOOL persist) +{ + test_preferred_maturity = initial_val; + return true; +} + +void LLControlGroup::setU32(const std::string& name, U32 val) +{ + test_preferred_maturity = val; +} + +U32 LLControlGroup::getU32(const std::string& name) +{ + return test_preferred_maturity; +} +//---------------------------------------------------------------------------- + namespace tut { struct agentaccess @@ -87,25 +74,26 @@ namespace tut typedef test_group<agentaccess> agentaccess_t; typedef agentaccess_t::object agentaccess_object_t; - tut::agentaccess_t tut_agentaccess("agentaccess"); + tut::agentaccess_t tut_agentaccess("LLAgentAccess"); template<> template<> void agentaccess_object_t::test<1>() { - LLControlGroupReader_Test cgr; + LLControlGroup cgr("test"); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); LLAgentAccess aa(cgr); - cgr.setPreferredMaturity(SIM_ACCESS_PG); + cgr.setU32("PreferredMaturity", SIM_ACCESS_PG); ensure("1 prefersPG", aa.prefersPG()); ensure("1 prefersMature", !aa.prefersMature()); ensure("1 prefersAdult", !aa.prefersAdult()); - cgr.setPreferredMaturity(SIM_ACCESS_MATURE); + cgr.setU32("PreferredMaturity", SIM_ACCESS_MATURE); ensure("2 prefersPG", !aa.prefersPG()); ensure("2 prefersMature", aa.prefersMature()); ensure("2 prefersAdult", !aa.prefersAdult()); - cgr.setPreferredMaturity(SIM_ACCESS_ADULT); + cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT); ensure("3 prefersPG", !aa.prefersPG()); ensure("3 prefersMature", aa.prefersMature()); ensure("3 prefersAdult", aa.prefersAdult()); @@ -114,7 +102,8 @@ namespace tut template<> template<> void agentaccess_object_t::test<2>() { - LLControlGroupReader_Test cgr; + LLControlGroup cgr("test"); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); LLAgentAccess aa(cgr); // make sure default is PG @@ -163,7 +152,8 @@ namespace tut template<> template<> void agentaccess_object_t::test<3>() { - LLControlGroupReader_Test cgr; + LLControlGroup cgr("test"); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); LLAgentAccess aa(cgr); ensure("starts normal", !aa.isGodlike()); @@ -186,7 +176,8 @@ namespace tut template<> template<> void agentaccess_object_t::test<4>() { - LLControlGroupReader_Test cgr; + LLControlGroup cgr("test"); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); LLAgentAccess aa(cgr); ensure("1 pg to start", aa.wantsPGOnly()); @@ -211,12 +202,12 @@ namespace tut ensure("2 mature pref pg", !aa.canAccessMature()); ensure("3 mature pref pg", !aa.canAccessAdult()); - cgr.setPreferredMaturity(SIM_ACCESS_MATURE); + cgr.setU32("PreferredMaturity", SIM_ACCESS_MATURE); ensure("1 mature", !aa.wantsPGOnly()); ensure("2 mature", aa.canAccessMature()); ensure("3 mature", !aa.canAccessAdult()); - cgr.setPreferredMaturity(SIM_ACCESS_PG); + cgr.setU32("PreferredMaturity", SIM_ACCESS_PG); ensure("1 mature pref pg", aa.wantsPGOnly()); ensure("2 mature pref pg", !aa.canAccessMature()); ensure("3 mature pref pg", !aa.canAccessAdult()); @@ -226,14 +217,14 @@ namespace tut ensure("2 adult pref pg", !aa.canAccessMature()); ensure("3 adult pref pg", !aa.canAccessAdult()); - cgr.setPreferredMaturity(SIM_ACCESS_ADULT); + cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT); ensure("1 adult", !aa.wantsPGOnly()); ensure("2 adult", aa.canAccessMature()); ensure("3 adult", aa.canAccessAdult()); // make sure that even if pref is high, if access is low we block access // this shouldn't occur in real life but we want to be safe - cgr.setPreferredMaturity(SIM_ACCESS_ADULT); + cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT); aa.setMaturity('P'); ensure("1 pref adult, actual pg", aa.wantsPGOnly()); ensure("2 pref adult, actual pg", !aa.canAccessMature()); @@ -244,7 +235,8 @@ namespace tut template<> template<> void agentaccess_object_t::test<5>() { - LLControlGroupReader_Test cgr; + LLControlGroup cgr("test"); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); LLAgentAccess aa(cgr); ensure("1 transition starts false", !aa.isInTransition()); @@ -252,6 +244,22 @@ namespace tut ensure("2 transition now true", aa.isInTransition()); } + /* + template<> template<> + void agentaccess_object_t::test<6>() + { + LLControlGroup cgr("test"); + cgr.declareU32("PreferredMaturity", SIM_ACCESS_PG, "declared_for_test", FALSE); + LLAgentAccess aa(cgr); + + cgr.setU32("PreferredMaturity", SIM_ACCESS_ADULT); + aa.setMaturity('M'); + ensure("1 preferred maturity pegged to M when maturity is M", cgr.getU32("PreferredMaturity") == SIM_ACCESS_MATURE); + + aa.setMaturity('P'); + ensure("1 preferred maturity pegged to P when maturity is P", cgr.getU32("PreferredMaturity") == SIM_ACCESS_PG); + } + */ } diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index eb21b6aa4..f49799b1c 100755 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -85,9 +85,6 @@ class ViewerManifest(LLManifest): self.path("*.png") self.path("textures.xml") self.end_prefix("default/textures") - self.exclude("default/xui/en_us/mime_types_windows.xml") - self.exclude("default/xui/en_us/mime_types_mac.xml") - self.exclude("default/xui/en_us/mime_types_linux.xml") self.path("default/xui/*/*.xml") self.path("Default.xml") self.path("default/*.xml") @@ -269,9 +266,6 @@ class WindowsManifest(ViewerManifest): self.path("qtwcodecs4.dll") self.end_prefix() - # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 - self.path("skins/default/xui/en-us/mime_types_windows.xml", "skins/default/xui/en-us/mime_types.xml") - # Get llcommon and deps. If missing assume static linkage and continue. if self.prefix(src=self.args['configuration'], dst=""): try: @@ -461,10 +455,10 @@ class DarwinManifest(ViewerManifest): # copy additional libs in <bundle>/Contents/MacOS/ self.path("../../libraries/universal-darwin/lib_release/libhunspell-1.2.dylib", dst="MacOS/libhunspell-1.2.dylib") self.path("../../libraries/universal-darwin/lib_release/libndofdev.dylib", dst="MacOS/libndofdev.dylib") - self.path("../../libraries/universal-darwin/lib_release/libvorbisenc.2.dylib", dst="MacOS/libvorbisenc.2.dylib") - self.path("../../libraries/universal-darwin/lib_release/libvorbisfile.3.dylib", dst="MacOS/libvorbisfile.3.dylib") - self.path("../../libraries/universal-darwin/lib_release/libvorbis.0.dylib", dst="MacOS/libvorbis.0.dylib") - self.path("../../libraries/universal-darwin/lib_release/libogg.0.dylib", dst="MacOS/libogg.0.dylib") + #self.path("../../libraries/universal-darwin/lib_release/libvorbisenc.2.dylib", dst="MacOS/libvorbisenc.2.dylib") + #self.path("../../libraries/universal-darwin/lib_release/libvorbisfile.3.dylib", dst="MacOS/libvorbisfile.3.dylib") + #self.path("../../libraries/universal-darwin/lib_release/libvorbis.0.dylib", dst="MacOS/libvorbis.0.dylib") + #self.path("../../libraries/universal-darwin/lib_release/libogg.0.dylib", dst="MacOS/libogg.0.dylib") # most everything goes in the Resources directory if self.prefix(src="", dst="Resources"): @@ -520,8 +514,11 @@ class DarwinManifest(ViewerManifest): self.path(self.args['configuration'] + "/libfmodwrapper.dylib", "libfmodwrapper.dylib") # our apps - self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") - #self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") + try: + self.path("../mac_crash_logger/" + self.args['configuration'] + "/mac-crash-logger.app", "mac-crash-logger.app") + self.path("../mac_updater/" + self.args['configuration'] + "/mac-updater.app", "mac-updater.app") + except: + pass # plugin launcher self.path("../llplugin/slplugin/" + self.args['configuration'] + "/SLPlugin.app", "SLPlugin.app") @@ -534,14 +531,14 @@ class DarwinManifest(ViewerManifest): "libaprutil-1.0.3.8.dylib", "libexpat.0.5.0.dylib"): target_lib = os.path.join('../../..', libfile) - self.run_command("ln -sf %(target)r %(link)r" % - {'target': target_lib, - 'link' : os.path.join(mac_crash_logger_res_path, libfile)} - ) self.run_command("ln -sf %(target)r %(link)r" % {'target': target_lib, 'link' : os.path.join(slplugin_res_path, libfile)} ) + #self.run_command("ln -sf %(target)r %(link)r" % + # {'target': target_lib, + # 'link' : os.path.join(mac_crash_logger_res_path, libfile)} + # ) # plugins if self.prefix(src="", dst="llplugin"): @@ -552,9 +549,6 @@ class DarwinManifest(ViewerManifest): self.end_prefix("llplugin") - # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 - self.path("skins/default/xui/en-us/mime_types_mac.xml", "skins/default/xui/en-us/mime_types.xml") - # command line arguments for connecting to the proper grid self.put_in_file(self.flags_list(), 'arguments.txt') @@ -707,9 +701,6 @@ class LinuxManifest(ViewerManifest): self.path("../plugins/gstreamer010/libmedia_plugin_gstreamer010.so", "libmedia_plugin_gstreamer.so") self.end_prefix("bin/llplugin") - # Per platform MIME config on the cheap. See SNOW-307 / DEV-41388 - self.path("skins/default/xui/en-us/mime_types_linux.xml", "skins/default/xui/en-us/mime_types.xml") - self.path("featuretable_linux.txt") def wrapper_name(self): diff --git a/indra/newview/wlfPanel_AdvSettings.cpp b/indra/newview/wlfPanel_AdvSettings.cpp index aef9e3276..40952c1bd 100644 --- a/indra/newview/wlfPanel_AdvSettings.cpp +++ b/indra/newview/wlfPanel_AdvSettings.cpp @@ -96,8 +96,8 @@ BOOL wlfPanel_AdvSettings::postBuild() LLComboBox* comboBoxSky = getChild<LLComboBox>("WLSkyPresetsCombo"); if(comboBoxSky != NULL) { - std::map<std::string, LLWLParamSet>::iterator mIt = LLWLParamManager::instance()->mParamList.begin(); - for(; mIt != LLWLParamManager::instance()->mParamList.end(); mIt++) + std::map<std::string, LLWLParamSet>::const_iterator mIt = LLWLParamManager::getInstance()->getPresets().begin(); + for(; mIt != LLWLParamManager::getInstance()->getPresets().end(); mIt++) { if (mIt->first.length() > 0) comboBoxSky->add(mIt->first); @@ -110,8 +110,8 @@ BOOL wlfPanel_AdvSettings::postBuild() LLComboBox* comboBoxWater = getChild<LLComboBox>("WLWaterPresetsCombo"); if(comboBoxWater != NULL) { - std::map<std::string, LLWaterParamSet>::iterator mIt = LLWaterParamManager::instance()->mParamList.begin(); - for(; mIt != LLWaterParamManager::instance()->mParamList.end(); mIt++) + std::map<std::string, LLWaterParamSet>::const_iterator mIt = LLWaterParamManager::getInstance()->getPresets().begin(); + for(; mIt != LLWaterParamManager::getInstance()->getPresets().end(); mIt++) { if (mIt->first.length() > 0) comboBoxWater->add(mIt->first); @@ -155,8 +155,8 @@ void wlfPanel_AdvSettings::onClickExpandBtn(void* user_data) } void wlfPanel_AdvSettings::onChangePresetName(LLUICtrl* ctrl, void * userData) { - LLWLParamManager::instance()->mAnimator.mIsRunning = false; - LLWLParamManager::instance()->mAnimator.mUseLindenTime = false; + LLWLParamManager::getInstance()->mAnimator.mIsRunning = false; + LLWLParamManager::getInstance()->mAnimator.mUseLindenTime = false; LLComboBox * combo_box = static_cast<LLComboBox*>(ctrl); llinfos << "Combobox is " << combo_box->getControlName() << " aka " << combo_box->getName() << llendl; @@ -167,7 +167,7 @@ void wlfPanel_AdvSettings::onChangePresetName(LLUICtrl* ctrl, void * userData) return; } current_preset = combo_box->getSelectedValue().asString(); - LLWLParamManager::instance()->loadPreset(current_preset); + LLWLParamManager::getInstance()->loadPreset(current_preset); } else if (combo_box->getName() == "WLWaterPresetsCombo") { @@ -176,6 +176,6 @@ void wlfPanel_AdvSettings::onChangePresetName(LLUICtrl* ctrl, void * userData) return; } current_preset = combo_box->getSelectedValue().asString(); - LLWaterParamManager::instance()->loadPreset(current_preset); + LLWaterParamManager::getInstance()->loadPreset(current_preset); } } diff --git a/indra/plugins/filepicker/CMakeLists.txt b/indra/plugins/filepicker/CMakeLists.txt index 4b4805a4e..2070b664b 100644 --- a/indra/plugins/filepicker/CMakeLists.txt +++ b/indra/plugins/filepicker/CMakeLists.txt @@ -63,12 +63,21 @@ else (WINDOWS) set(WINDOWS_API_LIBRARIES "") endif (WINDOWS) +if (DARWIN) + include(CMakeFindFrameworks) + find_library(APPKIT_LIBRARY AppKit) + find_library(CARBON_LIBRARY Carbon) + find_library(IOKIT_LIBRARY IOKit) + set(OSX_FILE_LIBRARIES ${APPKIT_LIBRARY} ${CARBON_LIBRARY} ${IOKIT_LIBRARY}) +endif (DARWIN) + target_link_libraries(basic_plugin_filepicker ${LLPLUGIN_LIBRARIES} ${LLCOMMON_LIBRARIES} ${BASIC_PLUGIN_BASE_LIBRARIES} ${UI_LIBRARIES} ${WINDOWS_API_LIBRARIES} + ${OSX_FILE_LIBRARIES} ) add_dependencies(basic_plugin_filepicker diff --git a/indra/plugins/filepicker/lldirpicker.cpp b/indra/plugins/filepicker/lldirpicker.cpp index ae5873209..733f779f6 100644 --- a/indra/plugins/filepicker/lldirpicker.cpp +++ b/indra/plugins/filepicker/lldirpicker.cpp @@ -189,16 +189,12 @@ OSStatus LLDirPicker::doNavChooseDialog() error = NavCreateChooseFolderDialog(&mNavOptions, &doNavCallbackEvent, NULL, NULL, &navRef); - gViewerWindow->mWindow->beforeDialog(); - if (error == noErr) { PLS_FLUSH; error = NavDialogRun(navRef); } - gViewerWindow->mWindow->afterDialog(); - if (error == noErr) error = NavDialogGetReply(navRef, &navReply); @@ -232,7 +228,7 @@ BOOL LLDirPicker::getDir(std::string const& folder) BOOL success = FALSE; OSStatus error = noErr; - mFileName = folder; + mFileName = const_cast<std::string*>(&folder); // mNavOptions.saveFileName diff --git a/indra/plugins/filepicker/llfilepicker.cpp b/indra/plugins/filepicker/llfilepicker.cpp index ffad899d6..8342882c8 100644 --- a/indra/plugins/filepicker/llfilepicker.cpp +++ b/indra/plugins/filepicker/llfilepicker.cpp @@ -761,7 +761,7 @@ Boolean LLFilePickerBase::navOpenFilterProc(AEDesc *theItem, void *info, void *c } else if (filter == FFLOAD_XML) { - if (fileInfo.filetype != 'XML' && + if (fileInfo.filetype != 'XML ' && (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("xml"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) ) { @@ -785,7 +785,7 @@ Boolean LLFilePickerBase::navOpenFilterProc(AEDesc *theItem, void *info, void *c } else if (filter == FFLOAD_RAW) { - if (fileInfo.filetype != L'\?\?\?\?' && + if (fileInfo.filetype != '\?\?\?\?' && (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("raw"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) ) { @@ -952,14 +952,14 @@ OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, std::string const extension = CFSTR(".png"); break; case FFSAVE_AVI: - type = L'\?\?\?\?'; - creator = L'\?\?\?\?'; + type = '\?\?\?\?'; + creator = '\?\?\?\?'; extension = CFSTR(".mov"); break; case FFSAVE_ANIM: - type = L'\?\?\?\?'; - creator = L'\?\?\?\?'; + type = '\?\?\?\?'; + creator = '\?\?\?\?'; extension = CFSTR(".xaf"); break; @@ -971,26 +971,26 @@ OSStatus LLFilePickerBase::doNavSaveDialog(ESaveFilter filter, std::string const break; #endif case FFSAVE_RAW: - type = L'\?\?\?\?'; - creator = L'\?\?\?\?'; + type = '\?\?\?\?'; + creator = '\?\?\?\?'; extension = CFSTR(".raw"); break; case FFSAVE_J2C: - type = L'\?\?\?\?'; + type = '\?\?\?\?'; creator = 'prvw'; extension = CFSTR(".j2c"); break; case FFSAVE_ALL: default: - type = L'\?\?\?\?'; - creator = L'\?\?\?\?'; + type = '\?\?\?\?'; + creator = '\?\?\?\?'; extension = CFSTR(""); break; } - NavEventUPP eventUPP = NewNavEventUPP(navSetDefaultFolderProc); + NavEventUPP eventUPP = NewNavEventUPP(NULL); //TODO: test filepicker mFolder = folder; // Create the dialog diff --git a/indra/plugins/filepicker/llfilepicker.h b/indra/plugins/filepicker/llfilepicker.h index 9c8db8e8a..0ba7ff614 100644 --- a/indra/plugins/filepicker/llfilepicker.h +++ b/indra/plugins/filepicker/llfilepicker.h @@ -39,6 +39,7 @@ #ifndef LL_LLFILEPICKER_H #define LL_LLFILEPICKER_H +#include "basic_plugin_base.h" // For PLS_INFOS etc. #include "legacy.h" #include <vector> @@ -163,10 +164,10 @@ private: #if LL_DARWIN NavDialogCreationOptions mNavOptions; - OSStatus doNavChooseDialog(ELoadFilter filter); - OSStatus doNavSaveDialog(ESaveFilter filter, const std::string& filename); + OSStatus doNavChooseDialog(ELoadFilter filter, const std::string& folder); + OSStatus doNavSaveDialog(ESaveFilter filter, const std::string& filename, const std::string& folder); static Boolean navOpenFilterProc(AEDesc *theItem, void *info, void *callBackUD, NavFilterModes filterMode); - static pascal void LLFilePickerBase::doNavCallbackEvent(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void* callBackUD); + static pascal void doNavCallbackEvent(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void* callBackUD); ELoadFilter getLoadFilter(void) const { return mLoadFilter; } std::string const& getFolder(void) const { return mFolder; } #endif // LL_DARWIN @@ -189,6 +190,7 @@ public: #endif // LL_GTK #if !LL_WINDOWS && !(LL_GTK && LL_X11) +public: void setWindowID(unsigned long window_id) { PLS_WARNS << "Calling unimplemented LLFilePickerBase::setWindowID" << PLS_ENDL; } #endif diff --git a/indra/test/v2math_tut.cpp b/indra/test/v2math_tut.cpp index 08a091a79..8ec588ce5 100644 --- a/indra/test/v2math_tut.cpp +++ b/indra/test/v2math_tut.cpp @@ -92,7 +92,7 @@ namespace tut F32 x = 2.2345f, y = 3.5678f ; LLVector2 vec2(x,y); ensure("magVecSquared:Fail ", is_approx_equal(vec2.magVecSquared(), (x*x + y*y))); - ensure("magVec:Fail ", is_approx_equal(vec2.magVec(), fsqrtf(x*x + y*y))); + ensure("magVec:Fail ", is_approx_equal(vec2.magVec(), (F32) sqrt(x*x + y*y))); } template<> template<> @@ -414,7 +414,7 @@ namespace tut ensure_equals("dist_vec_squared values are not equal",val2, val1); val1 = dist_vec(vec2, vec3); - val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2)); + val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2)); ensure_equals("dist_vec values are not equal",val2, val1); } @@ -438,7 +438,7 @@ namespace tut LLVector2 vec2(x1, y1); F32 vecMag = vec2.normVec(); - F32 mag = fsqrtf(x1*x1 + y1*y1); + F32 mag = (F32) sqrt(x1*x1 + y1*y1); F32 oomag = 1.f / mag; val1 = x1 * oomag; diff --git a/indra/test/v3color_tut.cpp b/indra/test/v3color_tut.cpp index 26d30682a..e36301ace 100644 --- a/indra/test/v3color_tut.cpp +++ b/indra/test/v3color_tut.cpp @@ -99,7 +99,7 @@ namespace tut F32 r = 2.3436212f, g = 1231.f, b = 4.7849321232f; LLColor3 llcolor3(r,g,b); ensure("magVecSquared:Fail ", is_approx_equal(llcolor3.magVecSquared(), (r*r + g*g + b*b))); - ensure("magVec:Fail ", is_approx_equal(llcolor3.magVec(), fsqrtf(r*r + g*g + b*b))); + ensure("magVec:Fail ", is_approx_equal(llcolor3.magVec(), (F32) sqrt(r*r + g*g + b*b))); } template<> template<> @@ -109,7 +109,7 @@ namespace tut F32 val1, val2,val3; LLColor3 llcolor3(r,g,b); F32 vecMag = llcolor3.normVec(); - F32 mag = fsqrtf(r*r + g*g + b*b); + F32 mag = (F32) sqrt(r*r + g*g + b*b); F32 oomag = 1.f / mag; val1 = r * oomag; val2 = g * oomag; @@ -292,7 +292,7 @@ namespace tut F32 r1 =1.f, g1 = 2.f,b1 = 1.2f, r2 = -2.3f, g2 = 1.11f, b2 = 1234.234f; LLColor3 llcolor3(r1,g1,b1),llcolor3a(r2,g2,b2); F32 val = distVec(llcolor3,llcolor3a); - ensure("distVec failed ", is_approx_equal(fsqrtf((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val)); + ensure("distVec failed ", is_approx_equal((F32) sqrt((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val)); F32 val1 = distVec_squared(llcolor3,llcolor3a); ensure("distVec_squared failed ", is_approx_equal(((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) ,val1)); diff --git a/indra/test/v3dmath_tut.cpp b/indra/test/v3dmath_tut.cpp index 598d72aab..2b06bb552 100644 --- a/indra/test/v3dmath_tut.cpp +++ b/indra/test/v3dmath_tut.cpp @@ -409,7 +409,7 @@ namespace tut LLVector3d vec3D(x,y,z); F64 res = (x*x + y*y + z*z) - vec3D.magVecSquared(); ensure("1:magVecSquared:Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO))); - res = fsqrtf(x*x + y*y + z*z) - vec3D.magVec(); + res = (F32) sqrt(x*x + y*y + z*z) - vec3D.magVec(); ensure("2:magVec: Fail ", ((-F_APPROXIMATELY_ZERO <= res)&& (res <=F_APPROXIMATELY_ZERO))); } diff --git a/indra/test/v3math_tut.cpp b/indra/test/v3math_tut.cpp index 7cbcb2304..0ab45a6a0 100644 --- a/indra/test/v3math_tut.cpp +++ b/indra/test/v3math_tut.cpp @@ -156,7 +156,7 @@ namespace tut F32 x = 2.32f, y = 1.212f, z = -.12f; LLVector3 vec3(x,y,z); ensure("1:magVecSquared:Fail ", is_approx_equal(vec3.magVecSquared(), (x*x + y*y + z*z))); - ensure("2:magVec:Fail ", is_approx_equal(vec3.magVec(), fsqrtf(x*x + y*y + z*z))); + ensure("2:magVec:Fail ", is_approx_equal(vec3.magVec(), (F32) sqrt(x*x + y*y + z*z))); } template<> template<> @@ -516,7 +516,7 @@ namespace tut F32 val1,val2; LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2); val1 = dist_vec(vec3,vec3a); - val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); + val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); ensure_equals("1:dist_vec: Fail ",val2, val1); val1 = dist_vec_squared(vec3,vec3a); val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); diff --git a/indra/test/v4color_tut.cpp b/indra/test/v4color_tut.cpp index b9142e73f..ee95a1bae 100644 --- a/indra/test/v4color_tut.cpp +++ b/indra/test/v4color_tut.cpp @@ -161,7 +161,7 @@ namespace tut F32 r = 0x20, g = 0xFFFF, b = 0xFF; LLColor4 llcolor4(r,g,b); ensure("magVecSquared:Fail ", is_approx_equal(llcolor4.magVecSquared(), (r*r + g*g + b*b))); - ensure("magVec:Fail ", is_approx_equal(llcolor4.magVec(), fsqrtf(r*r + g*g + b*b))); + ensure("magVec:Fail ", is_approx_equal(llcolor4.magVec(), (F32) sqrt(r*r + g*g + b*b))); } template<> template<> @@ -170,7 +170,7 @@ namespace tut F32 r = 0x20, g = 0xFFFF, b = 0xFF; LLColor4 llcolor4(r,g,b); F32 vecMag = llcolor4.normVec(); - F32 mag = fsqrtf(r*r + g*g + b*b); + F32 mag = (F32) sqrt(r*r + g*g + b*b); F32 oomag = 1.f / mag; F32 val1 = r * oomag, val2 = g * oomag, val3 = b * oomag; ensure("1:normVec failed ", (is_approx_equal(val1, llcolor4.mV[0]) && is_approx_equal(val2, llcolor4.mV[1]) && is_approx_equal(val3, llcolor4.mV[2]) && is_approx_equal(vecMag, mag))); diff --git a/indra/test/v4coloru_tut.cpp b/indra/test/v4coloru_tut.cpp index 1630b4ede..4b8070e30 100644 --- a/indra/test/v4coloru_tut.cpp +++ b/indra/test/v4coloru_tut.cpp @@ -140,7 +140,7 @@ namespace tut U8 r = 0x12, g = 0xFF, b = 0xAF; LLColor4U llcolor4u(r,g,b); ensure("magVecSquared:Fail ", is_approx_equal(llcolor4u.magVecSquared(), (F32)(r*r + g*g + b*b))); - ensure("magVec:Fail ", is_approx_equal(llcolor4u.magVec(), fsqrtf(r*r + g*g + b*b))); + ensure("magVec:Fail ", is_approx_equal(llcolor4u.magVec(), (F32) sqrt(r*r + g*g + b*b))); } template<> template<> diff --git a/indra/test/v4math_tut.cpp b/indra/test/v4math_tut.cpp index cc37be356..c529b17c2 100644 --- a/indra/test/v4math_tut.cpp +++ b/indra/test/v4math_tut.cpp @@ -102,7 +102,7 @@ namespace tut { F32 x = 10.f, y = -2.3f, z = -.023f; LLVector4 vec4(x,y,z); - ensure("magVec:Fail ", is_approx_equal(vec4.magVec(), fsqrtf(x*x + y*y + z*z))); + ensure("magVec:Fail ", is_approx_equal(vec4.magVec(), (F32) sqrt(x*x + y*y + z*z))); ensure("magVecSquared:Fail ", is_approx_equal(vec4.magVecSquared(), (x*x + y*y + z*z))); } @@ -343,7 +343,7 @@ namespace tut F32 val1,val2; LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2); val1 = dist_vec(vec4,vec4a); - val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); + val2 = (F32) sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); ensure_equals("dist_vec: Fail ",val2, val1); val1 = dist_vec_squared(vec4,vec4a); val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); diff --git a/install.xml b/install.xml index 3cb7378dc..3f1347123 100644 --- a/install.xml +++ b/install.xml @@ -3,43 +3,48 @@ <map> <key>installables</key> <map> - <key>GL</key> + <key>glext</key> <map> <key>copyright</key> - <string>Copyright (c) 1991-2000 Silicon Graphics, Inc.</string> + <string>Copyright (c) 2007-2010 Khronos Group Inc.</string> <key>description</key> - <string>A standard for 3D Graphics rendering engine.</string> + <string>OpenGL Extension Header Files</string> <key>license</key> - <string>GL</string> + <string>glext</string> <key>packages</key> <map> - <key>darwin</key> - <map> - <key>md5sum</key> - <string>0bd2795a2afe09f6c563f2f888f24cc9</string> - <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/GL-darwin-20080613.tar.bz2</uri> - </map> <key>linux</key> <map> <key>md5sum</key> - <string>2ab29212a7f3acdaebf10059af816be0</string> + <string>2fc9a86782ec8dcc719ddc78026e7ba2</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/GL-linux-20080812.tar.bz2</uri> - </map> - <key>linux64</key> - <map> - <key>md5sum</key> - <string>9c3dff3817f1105f9054401fdef1fe50</string> - <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/GL-linux64-20080909.tar.bz2</uri> + <uri>https://github.com/downloads/siana/SingularityViewer/glext-68-win32-linux.tar.bz2</uri> </map> <key>windows</key> <map> <key>md5sum</key> - <string>91155239b02f576384603795d41eb971</string> + <string>2fc9a86782ec8dcc719ddc78026e7ba2</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/GL-windows-20090505.tar.bz2</uri> + <uri>https://github.com/downloads/siana/SingularityViewer/glext-68-win32-linux.tar.bz2</uri> + </map> + </map> + </map> + <key>freeglut</key> + <map> + <key>copyright</key> + <string>Copyright (c) 1999-2000 Pawel W. Olszta.</string> + <key>description</key> + <string>OpenSource alternative to OpenGL Utility Toolkit</string> + <key>license</key> + <string>freeglut</string> + <key>packages</key> + <map> + <key>windows</key> + <map> + <key>md5sum</key> + <string>fefd6b548d677a60a198e50d9326d939</string> + <key>url</key> + <uri>https://github.com/downloads/Shyotl/SingularityViewer/freeglut-2.6.0-win32.tar.bz2</uri> </map> </map> </map> @@ -403,9 +408,9 @@ <key>darwin</key> <map> <key>md5sum</key> - <string>694173293a483c01472a30cc7d895c5a</string> + <string>a9ab0e2910e1a8fe06a2a42ffdc8b7da</string> <key>url</key> - <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/freetype-2.1.5-darwin-20080812.tar.bz2</uri> + <uri>https://github.com/siana-osx/SingularityViewer/downloads/freetype-2.4.4-darwin-20110705.tar.bz2</uri> </map> <key>linux</key> <map> @@ -1330,10 +1335,61 @@ anguage Infrstructure (CLI) international standard</string> <key>url</key> <string>http://opensource-definition.org/licenses/afl-2.1.html</string> </map> - <key>GL</key> + <key>glext</key> <map> - <key>url</key> - <string>http://www.xfree86.org/4.4.0/LICENSE9.html#sgi</string> + <key>text</key> + <string>Copyright (c) 2007-2010 The Khronos Group Inc. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and/or associated documentation files (the +"Materials"), to deal in the Materials without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Materials, and to +permit persons to whom the Materials are furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Materials. + +THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + </string> + </map> + <key>freeglut</key> + <map> + <key>text</key> + <string>Freeglut Copyright +------------------ + +Freeglut code without an explicit copyright is covered by the following +copyright: + +Copyright (c) 1999-2000 Pawel W. Olszta. All Rights Reserved. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies or substantial portions of the Software. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of Pawel W. Olszta shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from Pawel W. Olszta. + </string> </map> <key>MSDTW</key> <map> diff --git a/scripts/messages/message_template.msg b/scripts/messages/message_template.msg index d56bda3f6..d3acb611e 100644 --- a/scripts/messages/message_template.msg +++ b/scripts/messages/message_template.msg @@ -2061,6 +2061,15 @@ version 2.0 { IsPhantom BOOL } { CastsShadows BOOL } } + { + ExtraPhysics Variable + { PhysicsShapeType U8 } + { Density F32 } + { Friction F32 } + { Restitution F32 } + { GravityMultiplier F32 } + + } }