summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/00-Common.cmake13
-rw-r--r--indra/cmake/Variables.cmake2
-rw-r--r--indra/llappearance/llviewervisualparam.cpp2
-rw-r--r--indra/llappearance/llwearable.cpp6
-rw-r--r--indra/llappearance/llwearabledata.cpp5
-rw-r--r--indra/llappearance/llwearabletype.cpp119
-rw-r--r--indra/llappearance/llwearabletype.h56
-rw-r--r--indra/llcommon/CMakeLists.txt5
-rw-r--r--indra/llcommon/llcoros.cpp9
-rw-r--r--indra/llcommon/llcoros.h2
-rw-r--r--indra/llcommon/llerror.cpp290
-rw-r--r--indra/llcommon/llevents.cpp19
-rw-r--r--indra/llcommon/llevents.h14
-rw-r--r--indra/llcommon/llregex.h89
-rw-r--r--indra/llcommon/llsingleton.h14
-rw-r--r--indra/llcommon/llsys.cpp39
-rw-r--r--indra/llcommon/llthreadsafequeue.h19
-rw-r--r--indra/llcommon/tests/threadsafeschedule_test.cpp4
-rw-r--r--indra/llcommon/tests/workqueue_test.cpp72
-rw-r--r--indra/llcommon/timing.cpp25
-rw-r--r--indra/llcommon/workqueue.cpp30
-rw-r--r--indra/llcommon/workqueue.h197
-rw-r--r--indra/llimage/llimage.cpp7
-rw-r--r--indra/llinventory/llsettingsbase.cpp22
-rw-r--r--indra/llinventory/llsettingsbase.h20
-rw-r--r--indra/llinventory/llsettingsdaycycle.cpp28
-rw-r--r--indra/llinventory/llsettingssky.cpp128
-rw-r--r--indra/llinventory/llsettingswater.cpp22
-rw-r--r--indra/llmath/llmatrix4a.h9
-rw-r--r--indra/llmessage/lldatapacker.cpp164
-rw-r--r--indra/llmessage/lldatapacker.h17
-rw-r--r--indra/llmessage/message_prehash.cpp8
-rw-r--r--indra/llmessage/message_prehash.h8
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp60
-rw-r--r--indra/llplugin/llpluginclassmedia.h14
-rw-r--r--indra/llprimitive/llmaterialtable.cpp17
-rw-r--r--indra/llprimitive/llmaterialtable.h2
-rw-r--r--indra/llprimitive/llmediaentry.cpp5
-rw-r--r--indra/llprimitive/llmodel.cpp35
-rw-r--r--indra/llprimitive/llmodel.h3
-rw-r--r--indra/llprimitive/llprimitive.cpp348
-rw-r--r--indra/llprimitive/llprimitive.h5
-rw-r--r--indra/llrender/llgl.cpp3
-rw-r--r--indra/llrender/llglslshader.cpp13
-rw-r--r--indra/llrender/llglslshader.h8
-rw-r--r--indra/llrender/llimagegl.cpp89
-rw-r--r--indra/llrender/llimagegl.h27
-rw-r--r--indra/llrender/llrender.cpp2
-rw-r--r--indra/llrender/llshadermgr.cpp5
-rw-r--r--indra/llrender/llshadermgr.h2
-rw-r--r--indra/llrender/llvertexbuffer.cpp54
-rw-r--r--indra/llrender/llvertexbuffer.h22
-rw-r--r--indra/llui/llcombobox.cpp37
-rw-r--r--indra/llui/llcombobox.h7
-rw-r--r--indra/llui/llnotifications.h13
-rw-r--r--indra/llui/llnotificationslistener.h3
-rw-r--r--indra/llui/llnotificationtemplate.h2
-rw-r--r--indra/llui/lltextbase.cpp6
-rw-r--r--indra/llui/lltextbase.h2
-rw-r--r--indra/llui/lltextbox.cpp4
-rw-r--r--indra/llui/llurlentry.cpp51
-rw-r--r--indra/llui/llurlentry.h2
-rw-r--r--indra/llui/llurlregistry.cpp12
-rw-r--r--indra/llvfs/lldir.cpp10
-rw-r--r--indra/llvfs/lldir.h3
-rw-r--r--indra/llvfs/lldiriterator.cpp4
-rw-r--r--indra/llwindow/llappdelegate-objc.h1
-rw-r--r--indra/llwindow/llopenglview-objc.mm5
-rw-r--r--indra/llwindow/llwindow.h2
-rw-r--r--indra/llwindow/llwindowheadless.h6
-rw-r--r--indra/llwindow/llwindowmacosx-objc.h2
-rw-r--r--indra/llwindow/llwindowmacosx.cpp38
-rw-r--r--indra/llwindow/llwindowmacosx.h2
-rw-r--r--indra/llwindow/llwindowwin32.cpp323
-rw-r--r--indra/llwindow/llwindowwin32.h36
-rw-r--r--indra/llxml/llcontrol.h1
-rw-r--r--indra/media_plugins/cef/CMakeLists.txt3
-rw-r--r--indra/media_plugins/cef/media_plugin_cef.cpp5
-rw-r--r--indra/media_plugins/libvlc/media_plugin_libvlc.cpp41
-rw-r--r--indra/newview/CMakeLists.txt7
-rw-r--r--indra/newview/Info-SecondLife.plist2
-rw-r--r--indra/newview/VIEWER_VERSION.txt2
-rw-r--r--indra/newview/app_settings/settings.xml89
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl14
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl64
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl22
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl18
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/materialF.glsl12
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl (renamed from indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl)45
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl (renamed from indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl)41
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl (renamed from indra/newview/app_settings/shaders/class1/objects/emissiveSkinnedV.glsl)31
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/debugSkinnedV.glsl41
-rw-r--r--indra/newview/app_settings/shaders/class1/interface/occlusionSkinnedV.glsl (renamed from indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl)25
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl6
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl1
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl4
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/bumpV.glsl13
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl71
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl17
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl66
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/shinyV.glsl20
-rw-r--r--indra/newview/app_settings/shaders/class1/objects/simpleV.glsl18
-rw-r--r--indra/newview/app_settings/toolbars.xml1
-rw-r--r--indra/newview/featuretable.txt4
-rw-r--r--indra/newview/installers/windows/lang_pl.nsibin12080 -> 12082 bytes
-rw-r--r--indra/newview/licenses-linux.txt2
-rw-r--r--indra/newview/licenses-mac.txt2
-rw-r--r--indra/newview/licenses-win32.txt8
-rw-r--r--indra/newview/llagentwearables.cpp9
-rw-r--r--indra/newview/llappcorehttp.cpp34
-rw-r--r--indra/newview/llappdelegate-objc.mm12
-rw-r--r--indra/newview/llappearancemgr.cpp99
-rw-r--r--indra/newview/llappviewer.cpp197
-rw-r--r--indra/newview/llappviewermacosx-for-objc.h2
-rw-r--r--indra/newview/llappviewermacosx.cpp27
-rw-r--r--indra/newview/llappviewerwin32.cpp16
-rw-r--r--indra/newview/llcofwearables.cpp2
-rw-r--r--indra/newview/lldrawable.cpp15
-rw-r--r--indra/newview/lldrawpool.cpp119
-rw-r--r--indra/newview/lldrawpool.h41
-rw-r--r--indra/newview/lldrawpoolalpha.cpp391
-rw-r--r--indra/newview/lldrawpoolalpha.h22
-rw-r--r--indra/newview/lldrawpoolavatar.cpp1785
-rw-r--r--indra/newview/lldrawpoolavatar.h202
-rw-r--r--indra/newview/lldrawpoolbump.cpp309
-rw-r--r--indra/newview/lldrawpoolbump.h35
-rw-r--r--indra/newview/lldrawpoolmaterials.cpp66
-rw-r--r--indra/newview/lldrawpoolmaterials.h18
-rw-r--r--indra/newview/lldrawpoolsimple.cpp511
-rw-r--r--indra/newview/lldrawpoolsimple.h35
-rw-r--r--indra/newview/lldrawpoolwater.cpp472
-rw-r--r--indra/newview/lldrawpoolwater.h3
-rw-r--r--indra/newview/llenvironment.cpp20
-rw-r--r--indra/newview/lleventpoll.cpp4
-rw-r--r--indra/newview/lleventpoll.h2
-rw-r--r--indra/newview/llface.cpp133
-rw-r--r--indra/newview/llface.h10
-rw-r--r--indra/newview/llfavoritesbar.cpp58
-rw-r--r--indra/newview/llfavoritesbar.h2
-rw-r--r--indra/newview/llfloaterbuyland.cpp3
-rw-r--r--indra/newview/llfloatereditextdaycycle.cpp18
-rw-r--r--indra/newview/llfloatergodtools.cpp23
-rw-r--r--indra/newview/llfloaterimsessiontab.cpp7
-rw-r--r--indra/newview/llfloaterlinkreplace.cpp2
-rw-r--r--indra/newview/llfloaterpreference.cpp52
-rw-r--r--indra/newview/llfloaterpreference.h2
-rw-r--r--indra/newview/llfloaterregioninfo.cpp23
-rw-r--r--indra/newview/llfloaterwindowsize.cpp6
-rw-r--r--indra/newview/llhasheduniqueid.cpp4
-rw-r--r--indra/newview/llimprocessing.cpp4
-rw-r--r--indra/newview/llinventorybridge.cpp38
-rw-r--r--indra/newview/llinventorybridge.h3
-rw-r--r--indra/newview/llinventoryfilter.cpp5
-rw-r--r--indra/newview/llinventoryfunctions.cpp40
-rw-r--r--indra/newview/llinventoryfunctions.h2
-rw-r--r--indra/newview/llinventoryicon.cpp2
-rw-r--r--indra/newview/llinventorymodel.cpp321
-rw-r--r--indra/newview/llinventorymodel.h4
-rw-r--r--indra/newview/llinventorypanel.cpp3
-rw-r--r--indra/newview/lllogchat.cpp12
-rw-r--r--indra/newview/llmachineid.cpp557
-rw-r--r--indra/newview/llmachineid.h2
-rw-r--r--indra/newview/llmainlooprepeater.cpp88
-rw-r--r--indra/newview/llmainlooprepeater.h64
-rw-r--r--indra/newview/llmaniprotate.cpp5
-rw-r--r--indra/newview/llmanipscale.cpp5
-rw-r--r--indra/newview/llmaniptranslate.cpp5
-rw-r--r--indra/newview/llmeshrepository.cpp2
-rw-r--r--indra/newview/llnotificationmanager.cpp2
-rw-r--r--indra/newview/llnotificationmanager.h4
-rw-r--r--indra/newview/lloutfitgallery.cpp2
-rw-r--r--indra/newview/lloutfitslist.cpp2
-rw-r--r--indra/newview/llpaneleditwearable.cpp2
-rw-r--r--indra/newview/llpanelexperiencepicker.cpp4
-rw-r--r--indra/newview/llpanelface.cpp4
-rw-r--r--indra/newview/llpanelgroupcreate.cpp2
-rw-r--r--indra/newview/llpanelmaininventory.cpp39
-rw-r--r--indra/newview/llpanelmaininventory.h2
-rw-r--r--indra/newview/llpanelobject.cpp2
-rw-r--r--indra/newview/llpaneloutfitedit.cpp11
-rw-r--r--indra/newview/llpanelsnapshotpostcard.cpp3
-rw-r--r--indra/newview/llpanelvolume.cpp26
-rw-r--r--indra/newview/llpanelvolume.h3
-rw-r--r--indra/newview/llpreviewnotecard.cpp38
-rw-r--r--indra/newview/llpreviewnotecard.h8
-rw-r--r--indra/newview/llpreviewtexture.cpp39
-rw-r--r--indra/newview/llpreviewtexture.h1
-rw-r--r--indra/newview/llregioninfomodel.cpp23
-rw-r--r--indra/newview/llsecapi.h4
-rw-r--r--indra/newview/llsechandler_basic.cpp32
-rw-r--r--indra/newview/llsechandler_basic.h6
-rw-r--r--indra/newview/llselectmgr.cpp43
-rw-r--r--indra/newview/llselectmgr.h4
-rw-r--r--indra/newview/llsetkeybinddialog.h2
-rw-r--r--indra/newview/llsidepanelappearance.cpp2
-rw-r--r--indra/newview/llspatialpartition.cpp25
-rw-r--r--indra/newview/llspatialpartition.h21
-rw-r--r--indra/newview/llstartup.cpp8
-rw-r--r--indra/newview/lltoolpie.cpp41
-rw-r--r--indra/newview/lltranslate.cpp22
-rw-r--r--indra/newview/llversioninfo.cpp10
-rw-r--r--indra/newview/llviewerassetstorage.cpp6
-rw-r--r--indra/newview/llviewerassetupload.cpp2
-rw-r--r--indra/newview/llvieweraudio.cpp2
-rw-r--r--indra/newview/llvieweraudio.h5
-rw-r--r--indra/newview/llviewercontrol.cpp26
-rw-r--r--indra/newview/llviewerdisplay.cpp7
-rw-r--r--indra/newview/llviewerinput.cpp201
-rw-r--r--indra/newview/llviewerinput.h14
-rw-r--r--indra/newview/llviewerinventory.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp9
-rw-r--r--indra/newview/llviewermenu.cpp34
-rw-r--r--indra/newview/llviewermessage.cpp6
-rw-r--r--indra/newview/llvieweroctree.cpp293
-rw-r--r--indra/newview/llviewerparcelmgr.cpp42
-rw-r--r--indra/newview/llviewerparcelmgr.h2
-rw-r--r--indra/newview/llviewerregion.cpp24
-rw-r--r--indra/newview/llviewershadermgr.cpp1247
-rw-r--r--indra/newview/llviewershadermgr.h25
-rw-r--r--indra/newview/llviewertexture.cpp55
-rw-r--r--indra/newview/llviewertexture.h4
-rw-r--r--indra/newview/llviewerwearable.cpp4
-rw-r--r--indra/newview/llviewerwindow.cpp12
-rw-r--r--indra/newview/llvoavatar.cpp54
-rw-r--r--indra/newview/llvoavatar.h23
-rw-r--r--indra/newview/llvoavatarself.cpp9
-rw-r--r--indra/newview/llvoicevivox.cpp476
-rw-r--r--indra/newview/llvoicevivox.h2
-rw-r--r--indra/newview/llvovolume.cpp526
-rw-r--r--indra/newview/llwearableitemslist.cpp4
-rw-r--r--indra/newview/llwearablelist.cpp3
-rw-r--r--indra/newview/llweb.cpp7
-rw-r--r--indra/newview/llworld.cpp6
-rw-r--r--indra/newview/pipeline.cpp494
-rw-r--r--indra/newview/pipeline.h35
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_move.xml9
-rw-r--r--indra/newview/slplugin.entitlements8
-rw-r--r--indra/newview/tests/gpus_results.txt14
-rw-r--r--indra/newview/tests/gpus_seen.txt16
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp4
-rw-r--r--indra/newview/tests/llsechandler_basic_test.cpp4
-rwxr-xr-xindra/newview/viewer_manifest.py8
251 files changed, 6998 insertions, 6655 deletions
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 8aea50e02b..bf54b655c2 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -42,8 +42,8 @@ if(NON_RELEASE_CRASH_REPORTING)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DLL_SEND_CRASH_REPORTS=1")
endif()
-# Don't bother with a MinSizeRel build.
-set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release;Debug" CACHE STRING
+# Don't bother with MinSizeRel or Debug builds.
+set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release" CACHE STRING
"Supported build types." FORCE)
@@ -70,13 +70,18 @@ if (WINDOWS)
if( ADDRESS_SIZE EQUAL 32 )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /p:PreferredToolArchitecture=x64")
endif()
+
+ # Preserve first-pass-through versions (ie no FORCE overwrite). Prevents recursive addition of /Zo (04/2021)
+ set(OG_CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE} CACHE STRING "OG_CXX_FLAGS_RELEASE")
+ set(OG_CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} CACHE STRING "OG_CXX_FLAGS_RELWITHDEBINFO")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
- "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Zo"
+ "${OG_CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Zo"
CACHE STRING "C++ compiler release-with-debug options" FORCE)
set(CMAKE_CXX_FLAGS_RELEASE
- "${CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /Zo"
+ "${OG_CMAKE_CXX_FLAGS_RELEASE} ${LL_CXX_FLAGS} /Zo"
CACHE STRING "C++ compiler release options" FORCE)
+
# zlib has assembly-language object files incompatible with SAFESEH
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE /SAFESEH:NO /NODEFAULTLIB:LIBCMT /IGNORE:4099")
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index c81b22e572..e72475cbc4 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -60,7 +60,7 @@ if (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake)
set(INSTALL_PROPRIETARY ON CACHE BOOL "Install proprietary binaries")
endif (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake)
set(TEMPLATE_VERIFIER_OPTIONS "" CACHE STRING "Options for scripts/template_verifier.py")
-set(TEMPLATE_VERIFIER_MASTER_URL "http://bitbucket.org/lindenlab/master-message-template/raw/tip/message_template.msg" CACHE STRING "Location of the master message template")
+set(TEMPLATE_VERIFIER_MASTER_URL "https://bitbucket.org/lindenlab/master-message-template-git/raw/master/message_template.msg" CACHE STRING "Location of the master message template")
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
diff --git a/indra/llappearance/llviewervisualparam.cpp b/indra/llappearance/llviewervisualparam.cpp
index af8394b60c..fb0d12f0af 100644
--- a/indra/llappearance/llviewervisualparam.cpp
+++ b/indra/llappearance/llviewervisualparam.cpp
@@ -70,7 +70,7 @@ BOOL LLViewerVisualParamInfo::parseXml(LLXmlTreeNode *node)
static LLStdStringHandle wearable_string = LLXmlTree::addAttributeString("wearable");
if( node->getFastAttributeString( wearable_string, wearable) )
{
- mWearableType = LLWearableType::typeNameToType( wearable );
+ mWearableType = LLWearableType::getInstance()->typeNameToType( wearable );
}
static LLStdStringHandle edit_group_string = LLXmlTree::addAttributeString("edit_group");
diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
index 28a36e6e41..e4bc8ff427 100644
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -73,17 +73,17 @@ LLWearable::~LLWearable()
const std::string& LLWearable::getTypeLabel() const
{
- return LLWearableType::getTypeLabel(mType);
+ return LLWearableType::getInstance()->getTypeLabel(mType);
}
const std::string& LLWearable::getTypeName() const
{
- return LLWearableType::getTypeName(mType);
+ return LLWearableType::getInstance()->getTypeName(mType);
}
LLAssetType::EType LLWearable::getAssetType() const
{
- return LLWearableType::getAssetType(mType);
+ return LLWearableType::getInstance()->getAssetType(mType);
}
BOOL LLWearable::exportFile(const std::string& filename) const
diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp
index 66cc4f3766..0eaeedb6ee 100644
--- a/indra/llappearance/llwearabledata.cpp
+++ b/indra/llappearance/llwearabledata.cpp
@@ -231,10 +231,11 @@ BOOL LLWearableData::getWearableIndex(const LLWearable *wearable, U32& index_fou
U32 LLWearableData::getClothingLayerCount() const
{
U32 count = 0;
+ LLWearableType *wr_inst = LLWearableType::getInstance();
for (S32 i = 0; i < LLWearableType::WT_COUNT; i++)
{
LLWearableType::EType type = (LLWearableType::EType)i;
- if (LLWearableType::getAssetType(type)==LLAssetType::AT_CLOTHING)
+ if (wr_inst->getAssetType(type)==LLAssetType::AT_CLOTHING)
{
count += getWearableCount(type);
}
@@ -244,7 +245,7 @@ U32 LLWearableData::getClothingLayerCount() const
BOOL LLWearableData::canAddWearable(const LLWearableType::EType type) const
{
- LLAssetType::EType a_type = LLWearableType::getAssetType(type);
+ LLAssetType::EType a_type = LLWearableType::getInstance()->getAssetType(type);
if (a_type==LLAssetType::AT_CLOTHING)
{
return (getClothingLayerCount() < MAX_CLOTHING_LAYERS);
diff --git a/indra/llappearance/llwearabletype.cpp b/indra/llappearance/llwearabletype.cpp
index 281060d01d..4ac611b1de 100644
--- a/indra/llappearance/llwearabletype.cpp
+++ b/indra/llappearance/llwearabletype.cpp
@@ -30,153 +30,98 @@
#include "llinventorydefines.h"
-struct WearableEntry : public LLDictionaryEntry
+LLWearableType::LLWearableDictionary::LLWearableDictionary(LLTranslationBridge::ptr_t& trans)
{
- WearableEntry(LLWearableType& wtype,
- const std::string &name,
- const std::string& default_new_name,
- LLAssetType::EType assetType,
- LLInventoryType::EIconName iconName,
- BOOL disable_camera_switch = FALSE,
- BOOL allow_multiwear = TRUE) :
- LLDictionaryEntry(name),
- mAssetType(assetType),
- mDefaultNewName(default_new_name),
- mLabel(wtype.mTrans->getString(name)),
- mIconName(iconName),
- mDisableCameraSwitch(disable_camera_switch),
- mAllowMultiwear(allow_multiwear)
- {
-
- }
- const LLAssetType::EType mAssetType;
- const std::string mLabel;
- const std::string mDefaultNewName; //keep mLabel for backward compatibility
- LLInventoryType::EIconName mIconName;
- BOOL mDisableCameraSwitch;
- BOOL mAllowMultiwear;
-};
-
-class LLWearableDictionary : public LLParamSingleton<LLWearableDictionary>,
- public LLDictionary<LLWearableType::EType, WearableEntry>
-{
- LLSINGLETON(LLWearableDictionary, LLWearableType&);
-};
-
-LLWearableDictionary::LLWearableDictionary(LLWearableType& wtype)
-{
- addEntry(LLWearableType::WT_SHAPE, new WearableEntry(wtype, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE));
- addEntry(LLWearableType::WT_SKIN, new WearableEntry(wtype, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE));
- addEntry(LLWearableType::WT_HAIR, new WearableEntry(wtype, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE));
- addEntry(LLWearableType::WT_EYES, new WearableEntry(wtype, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE));
- addEntry(LLWearableType::WT_SHIRT, new WearableEntry(wtype, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE));
- addEntry(LLWearableType::WT_PANTS, new WearableEntry(wtype, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE));
- addEntry(LLWearableType::WT_SHOES, new WearableEntry(wtype, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE));
- addEntry(LLWearableType::WT_SOCKS, new WearableEntry(wtype, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE));
- addEntry(LLWearableType::WT_JACKET, new WearableEntry(wtype, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE));
- addEntry(LLWearableType::WT_GLOVES, new WearableEntry(wtype, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE));
- addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(wtype, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE));
- addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(wtype, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE));
- addEntry(LLWearableType::WT_SKIRT, new WearableEntry(wtype, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE));
- addEntry(LLWearableType::WT_ALPHA, new WearableEntry(wtype, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE));
- addEntry(LLWearableType::WT_TATTOO, new WearableEntry(wtype, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE));
- addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(wtype, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE));
-
- addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(wtype, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE));
-
- addEntry(LLWearableType::WT_INVALID, new WearableEntry(wtype, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE));
- addEntry(LLWearableType::WT_NONE, new WearableEntry(wtype, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
+ addEntry(LLWearableType::WT_SHAPE, new WearableEntry(trans, "shape", "New Shape", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SHAPE, FALSE, FALSE));
+ addEntry(LLWearableType::WT_SKIN, new WearableEntry(trans, "skin", "New Skin", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_SKIN, FALSE, FALSE));
+ addEntry(LLWearableType::WT_HAIR, new WearableEntry(trans, "hair", "New Hair", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_HAIR, FALSE, FALSE));
+ addEntry(LLWearableType::WT_EYES, new WearableEntry(trans, "eyes", "New Eyes", LLAssetType::AT_BODYPART, LLInventoryType::ICONNAME_BODYPART_EYES, FALSE, FALSE));
+ addEntry(LLWearableType::WT_SHIRT, new WearableEntry(trans, "shirt", "New Shirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHIRT, FALSE, TRUE));
+ addEntry(LLWearableType::WT_PANTS, new WearableEntry(trans, "pants", "New Pants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PANTS, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SHOES, new WearableEntry(trans, "shoes", "New Shoes", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SHOES, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SOCKS, new WearableEntry(trans, "socks", "New Socks", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SOCKS, FALSE, TRUE));
+ addEntry(LLWearableType::WT_JACKET, new WearableEntry(trans, "jacket", "New Jacket", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_JACKET, FALSE, TRUE));
+ addEntry(LLWearableType::WT_GLOVES, new WearableEntry(trans, "gloves", "New Gloves", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_GLOVES, FALSE, TRUE));
+ addEntry(LLWearableType::WT_UNDERSHIRT, new WearableEntry(trans, "undershirt", "New Undershirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERSHIRT, FALSE, TRUE));
+ addEntry(LLWearableType::WT_UNDERPANTS, new WearableEntry(trans, "underpants", "New Underpants", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNDERPANTS, FALSE, TRUE));
+ addEntry(LLWearableType::WT_SKIRT, new WearableEntry(trans, "skirt", "New Skirt", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_SKIRT, FALSE, TRUE));
+ addEntry(LLWearableType::WT_ALPHA, new WearableEntry(trans, "alpha", "New Alpha", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_ALPHA, FALSE, TRUE));
+ addEntry(LLWearableType::WT_TATTOO, new WearableEntry(trans, "tattoo", "New Tattoo", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_TATTOO, FALSE, TRUE));
+ addEntry(LLWearableType::WT_UNIVERSAL, new WearableEntry(trans, "universal", "New Universal", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_UNIVERSAL, FALSE, TRUE));
+
+ addEntry(LLWearableType::WT_PHYSICS, new WearableEntry(trans, "physics", "New Physics", LLAssetType::AT_CLOTHING, LLInventoryType::ICONNAME_CLOTHING_PHYSICS, TRUE, TRUE));
+
+ addEntry(LLWearableType::WT_INVALID, new WearableEntry(trans, "invalid", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_UNKNOWN, FALSE, FALSE));
+ addEntry(LLWearableType::WT_NONE, new WearableEntry(trans, "none", "Invalid Wearable", LLAssetType::AT_NONE, LLInventoryType::ICONNAME_NONE, FALSE, FALSE));
}
// class LLWearableType
-LLWearableType::LLWearableType(LLTranslationBridge* trans)
+LLWearableType::LLWearableType(LLTranslationBridge::ptr_t &trans)
+: mDictionary(trans)
{
- // LLTranslationBridge exists, but is not ready at this point in time since strings.xml is not yet loaded
- mTrans = trans;
}
LLWearableType::~LLWearableType()
{
- delete mTrans;
}
void LLWearableType::initSingleton()
{
- // To make sure all wrapping functions will crash without initing LLWearableType;
- LLWearableDictionary::initParamSingleton(*this);
-
- // Todo: consider merging LLWearableType and LLWearableDictionary
}
-// static
LLWearableType::EType LLWearableType::typeNameToType(const std::string& type_name)
{
- const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
- const LLWearableType::EType wearable = dict->lookup(type_name);
+ const LLWearableType::EType wearable = mDictionary.lookup(type_name);
return wearable;
}
-// static
const std::string& LLWearableType::getTypeName(LLWearableType::EType type)
{
- const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
- const WearableEntry *entry = dict->lookup(type);
+ const WearableEntry *entry = mDictionary.lookup(type);
if (!entry) return getTypeName(WT_INVALID);
return entry->mName;
}
-//static
const std::string& LLWearableType::getTypeDefaultNewName(LLWearableType::EType type)
{
- const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
- const WearableEntry *entry = dict->lookup(type);
+ const WearableEntry *entry = mDictionary.lookup(type);
if (!entry) return getTypeDefaultNewName(WT_INVALID);
return entry->mDefaultNewName;
}
-// static
const std::string& LLWearableType::getTypeLabel(LLWearableType::EType type)
{
- const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
- const WearableEntry *entry = dict->lookup(type);
+ const WearableEntry *entry = mDictionary.lookup(type);
if (!entry) return getTypeLabel(WT_INVALID);
return entry->mLabel;
}
-// static
LLAssetType::EType LLWearableType::getAssetType(LLWearableType::EType type)
{
- const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
- const WearableEntry *entry = dict->lookup(type);
+ const WearableEntry *entry = mDictionary.lookup(type);
if (!entry) return getAssetType(WT_INVALID);
return entry->mAssetType;
}
-// static
LLInventoryType::EIconName LLWearableType::getIconName(LLWearableType::EType type)
{
- const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
- const WearableEntry *entry = dict->lookup(type);
+ const WearableEntry *entry = mDictionary.lookup(type);
if (!entry) return getIconName(WT_INVALID);
return entry->mIconName;
}
-// static
BOOL LLWearableType::getDisableCameraSwitch(LLWearableType::EType type)
{
- const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
- const WearableEntry *entry = dict->lookup(type);
+ const WearableEntry *entry = mDictionary.lookup(type);
if (!entry) return FALSE;
return entry->mDisableCameraSwitch;
}
-// static
BOOL LLWearableType::getAllowMultiwear(LLWearableType::EType type)
{
- const LLWearableDictionary *dict = LLWearableDictionary::getInstance();
- const WearableEntry *entry = dict->lookup(type);
+ const WearableEntry *entry = mDictionary.lookup(type);
if (!entry) return FALSE;
return entry->mAllowMultiwear;
}
diff --git a/indra/llappearance/llwearabletype.h b/indra/llappearance/llwearabletype.h
index 57f3ef160d..793a33cc87 100644
--- a/indra/llappearance/llwearabletype.h
+++ b/indra/llappearance/llwearabletype.h
@@ -35,10 +35,9 @@
class LLWearableType : public LLParamSingleton<LLWearableType>
{
- LLSINGLETON(LLWearableType, LLTranslationBridge* trans);
+ LLSINGLETON(LLWearableType, LLTranslationBridge::ptr_t &trans);
~LLWearableType();
void initSingleton();
- friend struct WearableEntry;
public:
enum EType
{
@@ -67,20 +66,53 @@ public:
// Most methods are wrappers for dictionary, but if LLWearableType is not initialized,
// they will crash. Whole LLWearableType is just wrapper for convinient calls.
- static const std::string& getTypeName(EType type);
- static const std::string& getTypeDefaultNewName(EType type);
- static const std::string& getTypeLabel(EType type);
- static LLAssetType::EType getAssetType(EType type);
- static EType typeNameToType(const std::string& type_name);
- static LLInventoryType::EIconName getIconName(EType type);
- static BOOL getDisableCameraSwitch(EType type);
- static BOOL getAllowMultiwear(EType type);
+ const std::string& getTypeName(EType type);
+ const std::string& getTypeDefaultNewName(EType type);
+ const std::string& getTypeLabel(EType type);
+ LLAssetType::EType getAssetType(EType type);
+ EType typeNameToType(const std::string& type_name);
+ LLInventoryType::EIconName getIconName(EType type);
+ BOOL getDisableCameraSwitch(EType type);
+ BOOL getAllowMultiwear(EType type);
static EType inventoryFlagsToWearableType(U32 flags);
-protected:
+private:
+ struct WearableEntry : public LLDictionaryEntry
+ {
+ WearableEntry(LLTranslationBridge::ptr_t& trans,
+ const std::string &name,
+ const std::string& default_new_name,
+ LLAssetType::EType assetType,
+ LLInventoryType::EIconName iconName,
+ BOOL disable_camera_switch = FALSE,
+ BOOL allow_multiwear = TRUE) :
+ LLDictionaryEntry(name),
+ mAssetType(assetType),
+ mDefaultNewName(default_new_name),
+ mLabel(trans->getString(name)),
+ mIconName(iconName),
+ mDisableCameraSwitch(disable_camera_switch),
+ mAllowMultiwear(allow_multiwear)
+ {
- LLTranslationBridge* mTrans;
+ }
+ const LLAssetType::EType mAssetType;
+ const std::string mLabel;
+ const std::string mDefaultNewName;
+ LLInventoryType::EIconName mIconName;
+ BOOL mDisableCameraSwitch;
+ BOOL mAllowMultiwear;
+ };
+
+ class LLWearableDictionary : public LLDictionary<LLWearableType::EType, WearableEntry>
+ {
+ public:
+ LLWearableDictionary(LLTranslationBridge::ptr_t& trans);
+ ~LLWearableDictionary() {}
+ };
+
+ LLWearableDictionary mDictionary;
};
#endif // LL_LLWEARABLETYPE_H
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index 78d6ea3090..9defa6b6c1 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -119,8 +119,8 @@ set(llcommon_SOURCE_FILES
lluriparser.cpp
lluuid.cpp
llworkerthread.cpp
+ timing.cpp
u64.cpp
- threadpool.cpp
workqueue.cpp
StackWalker.cpp
)
@@ -213,9 +213,9 @@ set(llcommon_HEADER_FILES
llqueuedthread.h
llrand.h
llrefcount.h
+ llregex.h
llregistry.h
llrun.h
- llrefcount.h
llsafehandle.h
llsd.h
llsdjson.h
@@ -256,7 +256,6 @@ set(llcommon_HEADER_FILES
lockstatic.h
stdtypes.h
stringize.h
- threadpool.h
threadsafeschedule.h
timer.h
tuple.h
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 111c50af93..75fc0fec99 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -135,6 +135,13 @@ LLCoros::LLCoros():
LLCoros::~LLCoros()
{
+}
+
+void LLCoros::cleanupSingleton()
+{
+ // Some of the coroutines (like voice) will depend onto
+ // origin singletons, so clean coros before deleting those
+
printActiveCoroutines("at entry to ~LLCoros()");
// Other LLApp status-change listeners do things like close
// work queues and inject the Stop exception into pending
@@ -150,6 +157,8 @@ LLCoros::~LLCoros()
{
// don't use llcoro::suspend() because that module depends
// on this one
+ // This will yield current(main) thread and will let active
+ // corutines run once
boost::this_fiber::yield();
}
printActiveCoroutines("after pumping");
diff --git a/indra/llcommon/llcoros.h b/indra/llcommon/llcoros.h
index 6c0bec3ef9..a94cfca19f 100644
--- a/indra/llcommon/llcoros.h
+++ b/indra/llcommon/llcoros.h
@@ -89,6 +89,8 @@ class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
{
LLSINGLETON(LLCoros);
~LLCoros();
+
+ void cleanupSingleton();
public:
/// The viewer's use of the term "coroutine" became deeply embedded before
/// the industry term "fiber" emerged to distinguish userland threads from
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index f7af181927..a4a5cb2d24 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -442,6 +442,62 @@ namespace
typedef std::vector<LLError::RecorderPtr> Recorders;
typedef std::vector<LLError::CallSite*> CallSiteVector;
+ class SettingsConfig : public LLRefCount
+ {
+ friend class Globals;
+
+ public:
+ virtual ~SettingsConfig();
+
+ LLError::ELevel mDefaultLevel;
+
+ bool mLogAlwaysFlush;
+
+ U32 mEnabledLogTypesMask;
+
+ LevelMap mFunctionLevelMap;
+ LevelMap mClassLevelMap;
+ LevelMap mFileLevelMap;
+ LevelMap mTagLevelMap;
+ std::map<std::string, unsigned int> mUniqueLogMessages;
+
+ LLError::FatalFunction mCrashFunction;
+ LLError::TimeFunction mTimeFunction;
+
+ Recorders mRecorders;
+ LLMutex mRecorderMutex;
+
+ int mShouldLogCallCounter;
+
+ private:
+ SettingsConfig();
+ };
+
+ typedef LLPointer<SettingsConfig> SettingsConfigPtr;
+
+ SettingsConfig::SettingsConfig()
+ : LLRefCount(),
+ mDefaultLevel(LLError::LEVEL_DEBUG),
+ mLogAlwaysFlush(true),
+ mEnabledLogTypesMask(255),
+ mFunctionLevelMap(),
+ mClassLevelMap(),
+ mFileLevelMap(),
+ mTagLevelMap(),
+ mUniqueLogMessages(),
+ mCrashFunction(NULL),
+ mTimeFunction(NULL),
+ mRecorders(),
+ mRecorderMutex(),
+ mShouldLogCallCounter(0)
+ {
+ }
+
+ SettingsConfig::~SettingsConfig()
+ {
+ mRecorders.clear();
+ }
+
class Globals
{
public:
@@ -449,16 +505,31 @@ namespace
protected:
Globals();
public:
+ std::ostringstream messageStream;
+ bool messageStreamInUse;
std::string mFatalMessage;
void addCallSite(LLError::CallSite&);
void invalidateCallSites();
+ SettingsConfigPtr getSettingsConfig();
+
+ void resetSettingsConfig();
+ LLError::SettingsStoragePtr saveAndResetSettingsConfig();
+ void restore(LLError::SettingsStoragePtr pSettingsStorage);
private:
CallSiteVector callSites;
+ SettingsConfigPtr mSettingsConfig;
};
- Globals::Globals() {}
+ Globals::Globals()
+ : messageStream(),
+ messageStreamInUse(false),
+ callSites(),
+ mSettingsConfig(new SettingsConfig())
+ {
+ }
+
Globals* Globals::getInstance()
{
@@ -486,120 +557,31 @@ namespace
callSites.clear();
}
-}
-namespace LLError
-{
- class SettingsConfig : public LLRefCount
- {
- friend class Settings;
-
- public:
- virtual ~SettingsConfig();
-
- LLError::ELevel mDefaultLevel;
-
- bool mLogAlwaysFlush;
-
- U32 mEnabledLogTypesMask;
-
- LevelMap mFunctionLevelMap;
- LevelMap mClassLevelMap;
- LevelMap mFileLevelMap;
- LevelMap mTagLevelMap;
- std::map<std::string, unsigned int> mUniqueLogMessages;
-
- LLError::FatalFunction mCrashFunction;
- LLError::TimeFunction mTimeFunction;
-
- Recorders mRecorders;
-
- int mShouldLogCallCounter;
-
- private:
- SettingsConfig();
- };
-
- typedef LLPointer<SettingsConfig> SettingsConfigPtr;
-
- class Settings
- {
- public:
- static Settings* getInstance();
- protected:
- Settings();
- public:
- SettingsConfigPtr getSettingsConfig();
-
- void reset();
- SettingsStoragePtr saveAndReset();
- void restore(SettingsStoragePtr pSettingsStorage);
-
- private:
- SettingsConfigPtr mSettingsConfig;
- };
-
- SettingsConfig::SettingsConfig()
- : LLRefCount(),
- mDefaultLevel(LLError::LEVEL_DEBUG),
- mLogAlwaysFlush(true),
- mEnabledLogTypesMask(255),
- mFunctionLevelMap(),
- mClassLevelMap(),
- mFileLevelMap(),
- mTagLevelMap(),
- mUniqueLogMessages(),
- mCrashFunction([](const std::string&){}),
- mTimeFunction(NULL),
- mRecorders(),
- mShouldLogCallCounter(0)
- {
- }
-
- SettingsConfig::~SettingsConfig()
- {
- mRecorders.clear();
- }
-
- Settings::Settings():
- mSettingsConfig(new SettingsConfig())
- {
- }
-
- Settings* Settings::getInstance()
+ SettingsConfigPtr Globals::getSettingsConfig()
{
- // According to C++11 Function-Local Initialization
- // of static variables is supposed to be thread safe
- // without risk of deadlocks.
- static Settings inst;
-
- return &inst;
+ return mSettingsConfig;
}
- SettingsConfigPtr Settings::getSettingsConfig()
- {
- return mSettingsConfig;
- }
-
- void Settings::reset()
- {
- Globals::getInstance()->invalidateCallSites();
- mSettingsConfig = new SettingsConfig();
- }
+ void Globals::resetSettingsConfig()
+ {
+ invalidateCallSites();
+ mSettingsConfig = new SettingsConfig();
+ }
- SettingsStoragePtr Settings::saveAndReset()
- {
- SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());
- reset();
- return oldSettingsConfig;
- }
+ LLError::SettingsStoragePtr Globals::saveAndResetSettingsConfig()
+ {
+ LLError::SettingsStoragePtr oldSettingsConfig(mSettingsConfig.get());
+ resetSettingsConfig();
+ return oldSettingsConfig;
+ }
- void Settings::restore(SettingsStoragePtr pSettingsStorage)
- {
- Globals::getInstance()->invalidateCallSites();
- SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
- mSettingsConfig = newSettingsConfig;
- }
+ void Globals::restore(LLError::SettingsStoragePtr pSettingsStorage)
+ {
+ invalidateCallSites();
+ SettingsConfigPtr newSettingsConfig(dynamic_cast<SettingsConfig *>(pSettingsStorage.get()));
+ mSettingsConfig = newSettingsConfig;
+ }
}
namespace LLError
@@ -723,7 +705,7 @@ namespace
void commonInit(const std::string& user_dir, const std::string& app_dir, bool log_to_stderr = true)
{
- LLError::Settings::getInstance()->reset();
+ Globals::getInstance()->resetSettingsConfig();
LLError::setDefaultLevel(LLError::LEVEL_INFO);
LLError::setAlwaysFlush(true);
@@ -764,13 +746,13 @@ namespace LLError
void setFatalFunction(const FatalFunction& f)
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
s->mCrashFunction = f;
}
FatalFunction getFatalFunction()
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
return s->mCrashFunction;
}
@@ -781,72 +763,77 @@ namespace LLError
void setTimeFunction(TimeFunction f)
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
s->mTimeFunction = f;
}
void setDefaultLevel(ELevel level)
{
- Globals::getInstance()->invalidateCallSites();
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
s->mDefaultLevel = level;
}
ELevel getDefaultLevel()
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
return s->mDefaultLevel;
}
void setAlwaysFlush(bool flush)
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
s->mLogAlwaysFlush = flush;
}
bool getAlwaysFlush()
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
return s->mLogAlwaysFlush;
}
void setEnabledLogTypesMask(U32 mask)
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
s->mEnabledLogTypesMask = mask;
}
U32 getEnabledLogTypesMask()
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
return s->mEnabledLogTypesMask;
}
void setFunctionLevel(const std::string& function_name, ELevel level)
{
- Globals::getInstance()->invalidateCallSites();
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
s->mFunctionLevelMap[function_name] = level;
}
void setClassLevel(const std::string& class_name, ELevel level)
{
- Globals::getInstance()->invalidateCallSites();
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
s->mClassLevelMap[class_name] = level;
}
void setFileLevel(const std::string& file_name, ELevel level)
{
- Globals::getInstance()->invalidateCallSites();
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
s->mFileLevelMap[file_name] = level;
}
void setTagLevel(const std::string& tag_name, ELevel level)
{
- Globals::getInstance()->invalidateCallSites();
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
s->mTagLevelMap[tag_name] = level;
}
@@ -891,8 +878,9 @@ namespace LLError
{
void configure(const LLSD& config)
{
- Globals::getInstance()->invalidateCallSites();
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ Globals *g = Globals::getInstance();
+ g->invalidateCallSites();
+ SettingsConfigPtr s = g->getSettingsConfig();
s->mFunctionLevelMap.clear();
s->mClassLevelMap.clear();
@@ -1019,7 +1007,8 @@ namespace LLError
{
return;
}
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ LLMutexLock lock(&s->mRecorderMutex);
s->mRecorders.push_back(recorder);
}
@@ -1029,7 +1018,8 @@ namespace LLError
{
return;
}
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ LLMutexLock lock(&s->mRecorderMutex);
s->mRecorders.erase(std::remove(s->mRecorders.begin(), s->mRecorders.end(), recorder),
s->mRecorders.end());
}
@@ -1041,11 +1031,12 @@ namespace LLError
// with a Recorders::iterator indicating the position of that entry in
// mRecorders. The shared_ptr might be empty (operator!() returns true) if
// there was no such RECORDER subclass instance in mRecorders.
+ //
+ // NOTE!!! Requires external mutex lock!!!
template <typename RECORDER>
std::pair<boost::shared_ptr<RECORDER>, Recorders::iterator>
- findRecorderPos()
+ findRecorderPos(SettingsConfigPtr &s)
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
// Since we promise to return an iterator, use a classic iterator
// loop.
auto end{s->mRecorders.end()};
@@ -1076,7 +1067,9 @@ namespace LLError
template <typename RECORDER>
boost::shared_ptr<RECORDER> findRecorder()
{
- return findRecorderPos<RECORDER>().first;
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ LLMutexLock lock(&s->mRecorderMutex);
+ return findRecorderPos<RECORDER>(s).first;
}
// Remove an entry from SettingsConfig::mRecorders whose RecorderPtr
@@ -1085,10 +1078,11 @@ namespace LLError
template <typename RECORDER>
bool removeRecorder()
{
- auto found = findRecorderPos<RECORDER>();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
+ LLMutexLock lock(&s->mRecorderMutex);
+ auto found = findRecorderPos<RECORDER>(s);
if (found.first)
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
s->mRecorders.erase(found.second);
}
return bool(found.first);
@@ -1187,10 +1181,11 @@ namespace
{
LL_PROFILE_ZONE_SCOPED
LLError::ELevel level = site.mLevel;
- LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
std::string escaped_message;
-
+
+ LLMutexLock lock(&s->mRecorderMutex);
for (Recorders::const_iterator i = s->mRecorders.begin();
i != s->mRecorders.end();
++i)
@@ -1326,7 +1321,8 @@ namespace LLError
return false;
}
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ Globals *g = Globals::getInstance();
+ SettingsConfigPtr s = g->getSettingsConfig();
s->mShouldLogCallCounter++;
@@ -1356,7 +1352,7 @@ namespace LLError
: false);
site.mCached = true;
- Globals::getInstance()->addCallSite(site);
+ g->addCallSite(site);
return site.mShouldLog = site.mLevel >= compareLevel;
}
@@ -1371,7 +1367,7 @@ namespace LLError
}
Globals* g = Globals::getInstance();
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = g->getSettingsConfig();
std::string message = out.str();
@@ -1416,12 +1412,12 @@ namespace LLError
{
SettingsStoragePtr saveAndResetSettings()
{
- return Settings::getInstance()->saveAndReset();
+ return Globals::getInstance()->saveAndResetSettingsConfig();
}
void restoreSettings(SettingsStoragePtr pSettingsStorage)
{
- return Settings::getInstance()->restore(pSettingsStorage);
+ return Globals::getInstance()->restore(pSettingsStorage);
}
std::string removePrefix(std::string& s, const std::string& p)
@@ -1467,7 +1463,7 @@ namespace LLError
int shouldLogCallCount()
{
- SettingsConfigPtr s = Settings::getInstance()->getSettingsConfig();
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
return s->mShouldLogCallCounter;
}
@@ -1579,8 +1575,8 @@ bool debugLoggingEnabled(const std::string& tag)
{
return false;
}
-
- LLError::SettingsConfigPtr s = LLError::Settings::getInstance()->getSettingsConfig();
+
+ SettingsConfigPtr s = Globals::getInstance()->getSettingsConfig();
LLError::ELevel level = LLError::LEVEL_DEBUG;
bool res = checkLevelMap(s->mTagLevelMap, tag, level);
return res;
diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp
index 64fb985951..0a213bddef 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -45,7 +45,6 @@
#include <cctype>
// external library headers
#include <boost/range/iterator_range.hpp>
-#include <boost/make_shared.hpp>
#if LL_WINDOWS
#pragma warning (push)
#pragma warning (disable : 4701) // compiler thinks might use uninitialized var, but no
@@ -285,7 +284,7 @@ LLEventPump::LLEventPump(const std::string& name, bool tweak):
// Register every new instance with LLEventPumps
mRegistry(LLEventPumps::instance().getHandle()),
mName(mRegistry.get()->registerNew(*this, name, tweak)),
- mSignal(boost::make_shared<LLStandardSignal>()),
+ mSignal(std::make_shared<LLStandardSignal>()),
mEnabled(true)
{}
@@ -317,14 +316,24 @@ void LLEventPump::clear()
{
// Destroy the original LLStandardSignal instance, replacing it with a
// whole new one.
- mSignal = boost::make_shared<LLStandardSignal>();
+ mSignal = std::make_shared<LLStandardSignal>();
mConnections.clear();
}
void LLEventPump::reset()
{
- mSignal.reset();
+ // Resetting mSignal is supposed to disconnect everything on its own
+ // But due to crash on 'reset' added explicit cleanup to get more data
+ ConnectionMap::const_iterator iter = mConnections.begin();
+ ConnectionMap::const_iterator end = mConnections.end();
+ while (iter!=end)
+ {
+ iter->second.disconnect();
+ iter++;
+ }
mConnections.clear();
+
+ mSignal.reset();
//mDeps.clear();
}
@@ -543,7 +552,7 @@ bool LLEventStream::post(const LLSD& event)
// *stack* instance of the shared_ptr, ensuring that our heap
// LLStandardSignal object will live at least until post() returns, even
// if 'this' gets destroyed during the call.
- boost::shared_ptr<LLStandardSignal> signal(mSignal);
+ std::shared_ptr<LLStandardSignal> signal(mSignal);
// Let caller know if any one listener handled the event. This is mostly
// useful when using LLEventStream as a listener for an upstream
// LLEventPump.
diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h
index e380c108f4..ae6e5aabc9 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -49,8 +49,6 @@
#endif
#include <boost/bind.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/enable_shared_from_this.hpp>
#include <boost/utility.hpp> // noncopyable
#include <boost/optional/optional.hpp>
#include <boost/visit_each.hpp>
@@ -571,7 +569,7 @@ protected:
const NameList& before);
/// implement the dispatching
- boost::shared_ptr<LLStandardSignal> mSignal;
+ std::shared_ptr<LLStandardSignal> mSignal;
/// valve open?
bool mEnabled;
@@ -745,14 +743,4 @@ private:
LL_COMMON_API bool sendReply(const LLSD& reply, const LLSD& request,
const std::string& replyKey="reply");
-// Somewhat to my surprise, passing boost::bind(...boost::weak_ptr<T>...) to
-// listen() fails in Boost code trying to instantiate LLEventListener (i.e.
-// LLStandardSignal::slot_type) because the boost::get_pointer() utility function isn't
-// specialized for boost::weak_ptr. This remedies that omission.
-namespace boost
-{
- template <typename T>
- T* get_pointer(const weak_ptr<T>& ptr) { return shared_ptr<T>(ptr).get(); }
-}
-
#endif /* ! defined(LL_LLEVENTS_H) */
diff --git a/indra/llcommon/llregex.h b/indra/llcommon/llregex.h
new file mode 100644
index 0000000000..2b7f5e47c2
--- /dev/null
+++ b/indra/llcommon/llregex.h
@@ -0,0 +1,89 @@
+/**
+ * @file llregex.h
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2021, 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 LLREGEX_H
+#define LLREGEX_H
+#include <boost/regex.hpp>
+
+template <typename S, typename M, typename R>
+LL_COMMON_API bool ll_regex_match(const S& string, M& match, const R& regex)
+{
+ try
+ {
+ return boost::regex_match(string, match, regex);
+ }
+ catch (const std::runtime_error& e)
+ {
+ LL_WARNS() << "error matching with '" << regex.str() << "': "
+ << e.what() << ":\n'" << string << "'" << LL_ENDL;
+ return false;
+ }
+}
+
+template <typename S, typename R>
+LL_COMMON_API bool ll_regex_match(const S& string, const R& regex)
+{
+ try
+ {
+ return boost::regex_match(string, regex);
+ }
+ catch (const std::runtime_error& e)
+ {
+ LL_WARNS() << "error matching with '" << regex.str() << "': "
+ << e.what() << ":\n'" << string << "'" << LL_ENDL;
+ return false;
+ }
+}
+
+template <typename S, typename M, typename R>
+bool ll_regex_search(const S& string, M& match, const R& regex)
+{
+ try
+ {
+ return boost::regex_search(string, match, regex);
+ }
+ catch (const std::runtime_error& e)
+ {
+ LL_WARNS() << "error searching with '" << regex.str() << "': "
+ << e.what() << ":\n'" << string << "'" << LL_ENDL;
+ return false;
+ }
+}
+
+template <typename S, typename R>
+bool ll_regex_search(const S& string, const R& regex)
+{
+ try
+ {
+ return boost::regex_search(string, regex);
+ }
+ catch (const std::runtime_error& e)
+ {
+ LL_WARNS() << "error searching with '" << regex.str() << "': "
+ << e.what() << ":\n'" << string << "'" << LL_ENDL;
+ return false;
+ }
+}
+#endif // LLREGEX_H
diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h
index 6042c0906c..f85f961287 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -847,13 +847,14 @@ template<class T>
class LLSimpleton
{
public:
- template <typename... ARGS>
- static void createInstance(ARGS&&... args)
- {
+ static T* sInstance;
+
+ static void createInstance()
+ {
llassert(sInstance == nullptr);
- sInstance = new T(std::forward<ARGS>(args)...);
+ sInstance = new T();
}
-
+
static inline T* getInstance() { return sInstance; }
static inline T& instance() { return *getInstance(); }
static inline bool instanceExists() { return sInstance != nullptr; }
@@ -863,9 +864,6 @@ public:
delete sInstance;
sInstance = nullptr;
}
-
-private:
- static T* sInstance;
};
template <class T>
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 306ef05b6d..18f4684b49 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -43,12 +43,12 @@
#include "llerrorcontrol.h"
#include "llevents.h"
#include "llformat.h"
+#include "llregex.h"
#include "lltimer.h"
#include "llsdserialize.h"
#include "llsdutil.h"
#include <boost/bind.hpp>
#include <boost/circular_buffer.hpp>
-#include <boost/regex.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/range.hpp>
@@ -101,39 +101,6 @@ static const F32 MEM_INFO_THROTTLE = 20;
// dropped below the login framerate, we'd have very little additional data.
static const F32 MEM_INFO_WINDOW = 10*60;
-// Wrap boost::regex_match() with a function that doesn't throw.
-template <typename S, typename M, typename R>
-static bool regex_match_no_exc(const S& string, M& match, const R& regex)
-{
- try
- {
- return boost::regex_match(string, match, regex);
- }
- catch (const std::runtime_error& e)
- {
- LL_WARNS("LLMemoryInfo") << "error matching with '" << regex.str() << "': "
- << e.what() << ":\n'" << string << "'" << LL_ENDL;
- return false;
- }
-}
-
-// Wrap boost::regex_search() with a function that doesn't throw.
-template <typename S, typename M, typename R>
-static bool regex_search_no_exc(const S& string, M& match, const R& regex)
-{
- try
- {
- return boost::regex_search(string, match, regex);
- }
- catch (const std::runtime_error& e)
- {
- LL_WARNS("LLMemoryInfo") << "error searching with '" << regex.str() << "': "
- << e.what() << ":\n'" << string << "'" << LL_ENDL;
- return false;
- }
-}
-
-
LLOSInfo::LLOSInfo() :
mMajorVer(0), mMinorVer(0), mBuild(0), mOSVersionString("")
{
@@ -377,7 +344,7 @@ LLOSInfo::LLOSInfo() :
boost::smatch matched;
std::string glibc_version(gnu_get_libc_version());
- if ( regex_match_no_exc(glibc_version, matched, os_version_parse) )
+ if ( ll_regex_match(glibc_version, matched, os_version_parse) )
{
LL_INFOS("AppInit") << "Using glibc version '" << glibc_version << "' as OS version" << LL_ENDL;
@@ -1044,7 +1011,7 @@ LLSD LLMemoryInfo::loadStatsMap()
while (std::getline(meminfo, line))
{
LL_DEBUGS("LLMemoryInfo") << line << LL_ENDL;
- if (regex_match_no_exc(line, matched, stat_rx))
+ if (ll_regex_match(line, matched, stat_rx))
{
// e.g. "MemTotal: 4108424 kB"
LLSD::String key(matched[1].first, matched[1].second);
diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
index 2806506550..a588175074 100644
--- a/indra/llcommon/llthreadsafequeue.h
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -85,8 +85,8 @@ public:
LLThreadSafeQueue(U32 capacity = 1024);
virtual ~LLThreadSafeQueue() {}
- // Add an element to the queue (will block if the queue has reached
- // capacity).
+ // Add an element to the queue (will block if the queue has
+ // reached capacity).
//
// This call will raise an interrupt error if the queue is closed while
// the caller is blocked.
@@ -95,11 +95,6 @@ public:
// legacy name
void pushFront(ElementT const & element) { return push(element); }
- // Add an element to the queue (will block if the queue has reached
- // capacity). Return false if the queue is closed before push is possible.
- template <typename T>
- bool pushIfOpen(T&& element);
-
// Try to add an element to the queue without blocking. Returns
// true only if the element was actually added.
template <typename T>
@@ -319,8 +314,8 @@ bool LLThreadSafeQueue<ElementT, QueueT>::push_(lock_t& lock, T&& element)
template <typename ElementT, typename QueueT>
-template <typename T>
-bool LLThreadSafeQueue<ElementT, QueueT>::pushIfOpen(T&& element)
+template<typename T>
+void LLThreadSafeQueue<ElementT, QueueT>::push(T&& element)
{
LL_PROFILE_ZONE_SCOPED;
lock_t lock1(mLock);
@@ -330,10 +325,12 @@ bool LLThreadSafeQueue<ElementT, QueueT>::pushIfOpen(T&& element)
// drained or not: the moment either end calls close(), further push()
// operations will fail.
if (mClosed)
- return false;
+ {
+ LLTHROW(LLThreadSafeQueueInterrupt());
+ }
if (push_(lock1, std::forward<T>(element)))
- return true;
+ return;
// Storage Full. Wait for signal.
mCapacityCond.wait(lock1);
diff --git a/indra/llcommon/tests/threadsafeschedule_test.cpp b/indra/llcommon/tests/threadsafeschedule_test.cpp
index c421cc7b1c..af67b9f492 100644
--- a/indra/llcommon/tests/threadsafeschedule_test.cpp
+++ b/indra/llcommon/tests/threadsafeschedule_test.cpp
@@ -46,11 +46,11 @@ namespace tut
// the real time required for each push() call. Explicitly increment
// the timestamp for each one -- but since we're passing explicit
// timestamps, make the queue reorder them.
- queue.push(Queue::TimeTuple(Queue::Clock::now() + 200ms, "ghi"));
+ queue.push(Queue::TimeTuple(Queue::Clock::now() + 20ms, "ghi"));
// Given the various push() overloads, you have to match the type
// exactly: conversions are ambiguous.
queue.push("abc"s);
- queue.push(Queue::Clock::now() + 100ms, "def");
+ queue.push(Queue::Clock::now() + 10ms, "def");
queue.close();
auto entry = queue.pop();
ensure_equals("failed to pop first", std::get<0>(entry), "abc"s);
diff --git a/indra/llcommon/tests/workqueue_test.cpp b/indra/llcommon/tests/workqueue_test.cpp
index bea3ad911b..d5405400fd 100644
--- a/indra/llcommon/tests/workqueue_test.cpp
+++ b/indra/llcommon/tests/workqueue_test.cpp
@@ -20,10 +20,7 @@
// external library headers
// other Linden headers
#include "../test/lltut.h"
-#include "../test/catch_and_store_what_in.h"
#include "llcond.h"
-#include "llcoros.h"
-#include "lleventcoro.h"
#include "llstring.h"
#include "stringize.h"
@@ -141,8 +138,7 @@ namespace tut
[](){ return 17; },
// Note that a postTo() *callback* can safely bind a reference to
// a variable on the invoking thread, because the callback is run
- // on the invoking thread. (Of course the bound variable must
- // survive until the callback is called.)
+ // on the invoking thread.
[&result](int i){ result = i; });
// this should post the callback to main
qptr->runOne();
@@ -160,70 +156,4 @@ namespace tut
main.runPending();
ensure_equals("failed to run string callback", alpha, "abc");
}
-
- template<> template<>
- void object::test<5>()
- {
- set_test_name("postTo with void return");
- WorkQueue main("main");
- auto qptr = WorkQueue::getInstance("queue");
- std::string observe;
- main.postTo(
- qptr,
- // The ONLY reason we can get away with binding a reference to
- // 'observe' in our work callable is because we're directly
- // calling qptr->runOne() on this same thread. It would be a
- // mistake to do that if some other thread were servicing 'queue'.
- [&observe](){ observe = "queue"; },
- [&observe](){ observe.append(";main"); });
- qptr->runOne();
- main.runOne();
- ensure_equals("failed to run both lambdas", observe, "queue;main");
- }
-
- template<> template<>
- void object::test<6>()
- {
- set_test_name("waitForResult");
- std::string stored;
- // Try to call waitForResult() on this thread's main coroutine. It
- // should throw because the main coroutine must service the queue.
- auto what{ catch_what<WorkQueue::Error>(
- [this, &stored](){ stored = queue.waitForResult(
- [](){ return "should throw"; }); }) };
- ensure("lambda should not have run", stored.empty());
- ensure_not("waitForResult() should have thrown", what.empty());
- ensure(STRINGIZE("should mention waitForResult: " << what),
- what.find("waitForResult") != std::string::npos);
-
- // Call waitForResult() on a coroutine, with a string result.
- LLCoros::instance().launch(
- "waitForResult string",
- [this, &stored]()
- { stored = queue.waitForResult(
- [](){ return "string result"; }); });
- llcoro::suspend();
- // Nothing will have happened yet because, even if the coroutine did
- // run immediately, all it did was to queue the inner lambda on
- // 'queue'. Service it.
- queue.runOne();
- llcoro::suspend();
- ensure_equals("bad waitForResult return", stored, "string result");
-
- // Call waitForResult() on a coroutine, with a void callable.
- stored.clear();
- bool done = false;
- LLCoros::instance().launch(
- "waitForResult void",
- [this, &stored, &done]()
- {
- queue.waitForResult([&stored](){ stored = "ran"; });
- done = true;
- });
- llcoro::suspend();
- queue.runOne();
- llcoro::suspend();
- ensure_equals("didn't run coroutine", stored, "ran");
- ensure("void waitForResult() didn't return", done);
- }
} // namespace tut
diff --git a/indra/llcommon/timing.cpp b/indra/llcommon/timing.cpp
new file mode 100644
index 0000000000..c2dc695ef3
--- /dev/null
+++ b/indra/llcommon/timing.cpp
@@ -0,0 +1,25 @@
+/**
+ * @file timing.cpp
+ * @brief This file will be deprecated in the future.
+ *
+ * $LicenseInfo:firstyear=2000&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$
+ */
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index fbdbea2051..1e89d87cff 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -26,9 +26,8 @@
using Mutex = LLCoros::Mutex;
using Lock = LLCoros::LockType;
-LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity):
- super(makeName(name)),
- mQueue(capacity)
+LL::WorkQueue::WorkQueue(const std::string& name):
+ super(makeName(name))
{
// TODO: register for "LLApp" events so we can implicitly close() on
// viewer shutdown.
@@ -39,21 +38,6 @@ void LL::WorkQueue::close()
mQueue.close();
}
-size_t LL::WorkQueue::size()
-{
- return mQueue.size();
-}
-
-bool LL::WorkQueue::isClosed()
-{
- return mQueue.isClosed();
-}
-
-bool LL::WorkQueue::done()
-{
- return mQueue.done();
-}
-
void LL::WorkQueue::runUntilClose()
{
try
@@ -146,13 +130,3 @@ void LL::WorkQueue::error(const std::string& msg)
{
LL_ERRS("WorkQueue") << msg << LL_ENDL;
}
-
-void LL::WorkQueue::checkCoroutine(const std::string& method)
-{
- // By convention, the default coroutine on each thread has an empty name
- // string. See also LLCoros::logname().
- if (LLCoros::getName().empty())
- {
- LLTHROW(Error("Do not call " + method + " from a thread's default coroutine"));
- }
-}
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index 96574a18b9..8e4b38c2f3 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -12,14 +12,14 @@
#if ! defined(LL_WORKQUEUE_H)
#define LL_WORKQUEUE_H
-#include "llcoros.h"
-#include "llexception.h"
#include "llinstancetracker.h"
#include "threadsafeschedule.h"
#include <chrono>
-#include <exception> // std::current_exception
#include <functional> // std::function
+#include <queue>
#include <string>
+#include <utility> // std::pair
+#include <vector>
namespace LL
{
@@ -45,16 +45,11 @@ namespace LL
using TimedWork = Queue::TimeTuple;
using Closed = Queue::Closed;
- struct Error: public LLException
- {
- Error(const std::string& what): LLException(what) {}
- };
-
/**
* You may omit the WorkQueue name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkQueue(const std::string& name = std::string(), size_t capacity=1024);
+ WorkQueue(const std::string& name = std::string());
/**
* Since the point of WorkQueue is to pass work to some other worker
@@ -64,36 +59,15 @@ namespace LL
*/
void close();
- /**
- * WorkQueue supports multiple producers and multiple consumers. In
- * the general case it's misleading to test size(), since any other
- * thread might change it the nanosecond the lock is released. On that
- * basis, some might argue against publishing a size() method at all.
- *
- * But there are two specific cases in which a test based on size()
- * might be reasonable:
- *
- * * If you're the only producer, noticing that size() == 0 is
- * meaningful.
- * * If you're the only consumer, noticing that size() > 0 is
- * meaningful.
- */
- size_t size();
- /// producer end: are we prevented from pushing any additional items?
- bool isClosed();
- /// consumer end: are we done, is the queue entirely drained?
- bool done();
-
/*---------------------- fire and forget API -----------------------*/
/// fire-and-forget, but at a particular (future?) time
template <typename CALLABLE>
void post(const TimePoint& time, CALLABLE&& callable)
{
- // Defer reifying an arbitrary CALLABLE until we hit this or
- // postIfOpen(). All other methods should accept CALLABLEs of
- // arbitrary type to avoid multiple levels of std::function
- // indirection.
+ // Defer reifying an arbitrary CALLABLE until we hit this method.
+ // All other methods should accept CALLABLEs of arbitrary type to
+ // avoid multiple levels of std::function indirection.
mQueue.push(TimedWork(time, std::move(callable)));
}
@@ -109,47 +83,6 @@ namespace LL
}
/**
- * post work for a particular time, unless the queue is closed before
- * we can post
- */
- template <typename CALLABLE>
- bool postIfOpen(const TimePoint& time, CALLABLE&& callable)
- {
- // Defer reifying an arbitrary CALLABLE until we hit this or
- // post(). All other methods should accept CALLABLEs of arbitrary
- // type to avoid multiple levels of std::function indirection.
- return mQueue.pushIfOpen(TimedWork(time, std::move(callable)));
- }
-
- /**
- * post work, unless the queue is closed before we can post
- */
- template <typename CALLABLE>
- bool postIfOpen(CALLABLE&& callable)
- {
- return postIfOpen(TimePoint::clock::now(), std::move(callable));
- }
-
- /**
- * Post work to be run at a specified time to another WorkQueue, which
- * may or may not still exist and be open. Return true if we were able
- * to post.
- */
- template <typename CALLABLE>
- static bool postMaybe(weak_t target, const TimePoint& time, CALLABLE&& callable);
-
- /**
- * Post work to another WorkQueue, which may or may not still exist
- * and be open. Return true if we were able to post.
- */
- template <typename CALLABLE>
- static bool postMaybe(weak_t target, CALLABLE&& callable)
- {
- return postMaybe(target, TimePoint::clock::now(),
- std::forward<CALLABLE>(callable));
- }
-
- /**
* Launch a callable returning bool that will trigger repeatedly at
* specified interval, until the callable returns false.
*
@@ -182,8 +115,63 @@ namespace LL
// Studio compile errors that seem utterly unrelated to this source
// code.
template <typename CALLABLE, typename FOLLOWUP>
- bool postTo(weak_t target,
- const TimePoint& time, CALLABLE&& callable, FOLLOWUP&& callback);
+ bool postTo(WorkQueue::weak_t target,
+ const TimePoint& time, CALLABLE&& callable, FOLLOWUP&& callback)
+ {
+ // We're being asked to post to the WorkQueue at target.
+ // target is a weak_ptr: have to lock it to check it.
+ auto tptr = target.lock();
+ if (! tptr)
+ // can't post() if the target WorkQueue has been destroyed
+ return false;
+
+ // Here we believe target WorkQueue still exists. Post to it a
+ // lambda that packages our callable, our callback and a weak_ptr
+ // to this originating WorkQueue.
+ tptr->post(
+ time,
+ [reply = super::getWeak(),
+ callable = std::move(callable),
+ callback = std::move(callback)]
+ ()
+ {
+ // Call the callable in any case -- but to minimize
+ // copying the result, immediately bind it into a reply
+ // lambda. The reply lambda also binds the original
+ // callback, so that when we, the originating WorkQueue,
+ // finally receive and process the reply lambda, we'll
+ // call the bound callback with the bound result -- on the
+ // same thread that originally called postTo().
+ auto rlambda =
+ [result = callable(),
+ callback = std::move(callback)]
+ ()
+ { callback(std::move(result)); };
+ // Check if this originating WorkQueue still exists.
+ // Remember, the outer lambda is now running on a thread
+ // servicing the target WorkQueue, and real time has
+ // elapsed since postTo()'s tptr->post() call.
+ // reply is a weak_ptr: have to lock it to check it.
+ auto rptr = reply.lock();
+ if (rptr)
+ {
+ // Only post reply lambda if the originating WorkQueue
+ // still exists. If not -- who would we tell? Log it?
+ try
+ {
+ rptr->post(std::move(rlambda));
+ }
+ catch (const Closed&)
+ {
+ // Originating WorkQueue might still exist, but
+ // might be Closed. Same thing: just discard the
+ // callback.
+ }
+ }
+ });
+ // looks like we were able to post()
+ return true;
+ }
/**
* Post work to another WorkQueue, requesting a specific callback to
@@ -193,36 +181,10 @@ namespace LL
* inaccessible.
*/
template <typename CALLABLE, typename FOLLOWUP>
- bool postTo(weak_t target, CALLABLE&& callable, FOLLOWUP&& callback)
- {
- return postTo(target, TimePoint::clock::now(),
- std::move(callable), std::move(callback));
- }
-
- /**
- * Post work to another WorkQueue to be run at a specified time,
- * blocking the calling coroutine until then, returning the result to
- * caller on completion.
- *
- * In general, we assume that each thread's default coroutine is busy
- * servicing its WorkQueue or whatever. To try to prevent mistakes, we
- * forbid calling waitForResult() from a thread's default coroutine.
- */
- template <typename CALLABLE>
- auto waitForResult(const TimePoint& time, CALLABLE&& callable);
-
- /**
- * Post work to another WorkQueue, blocking the calling coroutine
- * until then, returning the result to caller on completion.
- *
- * In general, we assume that each thread's default coroutine is busy
- * servicing its WorkQueue or whatever. To try to prevent mistakes, we
- * forbid calling waitForResult() from a thread's default coroutine.
- */
- template <typename CALLABLE>
- auto waitForResult(CALLABLE&& callable)
+ bool postTo(WorkQueue::weak_t target,
+ CALLABLE&& callable, FOLLOWUP&& callback)
{
- return waitForResult(TimePoint::clock::now(), std::move(callable));
+ return postTo(target, TimePoint::clock::now(), std::move(callable), std::move(callback));
}
/*--------------------------- worker API ---------------------------*/
@@ -271,23 +233,6 @@ namespace LL
bool runUntil(const TimePoint& until);
private:
- template <typename CALLABLE, typename FOLLOWUP>
- static auto makeReplyLambda(CALLABLE&& callable, FOLLOWUP&& callback);
- /// general case: arbitrary C++ return type
- template <typename CALLABLE, typename FOLLOWUP, typename RETURNTYPE>
- struct MakeReplyLambda;
- /// specialize for CALLABLE returning void
- template <typename CALLABLE, typename FOLLOWUP>
- struct MakeReplyLambda<CALLABLE, FOLLOWUP, void>;
-
- /// general case: arbitrary C++ return type
- template <typename CALLABLE, typename RETURNTYPE>
- struct WaitForResult;
- /// specialize for CALLABLE returning void
- template <typename CALLABLE>
- struct WaitForResult<CALLABLE, void>;
-
- static void checkCoroutine(const std::string& method);
static void error(const std::string& msg);
static std::string makeName(const std::string& name);
void callWork(const Queue::DataTuple& work);
@@ -309,8 +254,8 @@ namespace LL
{
public:
// bind the desired data
- BackJack(weak_t target,
- const TimePoint& start,
+ BackJack(WorkQueue::weak_t target,
+ const WorkQueue::TimePoint& start,
const std::chrono::duration<Rep, Period>& interval,
CALLABLE&& callable):
mTarget(target),
@@ -357,8 +302,8 @@ namespace LL
}
private:
- weak_t mTarget;
- TimePoint mStart;
+ WorkQueue::weak_t mTarget;
+ WorkQueue::TimePoint mStart;
std::chrono::duration<Rep, Period> mInterval;
CALLABLE mCallable;
};
diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 5c49ec02ea..2bf5f5492e 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -1451,7 +1451,7 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
setDataAndSize(new_data, new_width, new_height, components);
}
}
- else
+ else try
{
// copy out existing image data
S32 temp_data_size = old_width * old_height * components;
@@ -1485,6 +1485,11 @@ bool LLImageRaw::scale( S32 new_width, S32 new_height, bool scale_image_data )
}
}
}
+ catch (std::bad_alloc&) // for temp_buffer
+ {
+ LL_WARNS() << "Failed to allocate temporary image buffer" << LL_ENDL;
+ return false;
+ }
return true ;
}
diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp
index 89a4eebf26..aed972b150 100644
--- a/indra/llinventory/llsettingsbase.cpp
+++ b/indra/llinventory/llsettingsbase.cpp
@@ -395,7 +395,7 @@ bool LLSettingsBase::validate()
LLSD LLSettingsBase::settingValidation(LLSD &settings, validation_list_t &validations, bool partial)
{
- static Validator validateName(SETTING_NAME, false, LLSD::TypeString, boost::bind(&Validator::verifyStringLength, _1, 63));
+ static Validator validateName(SETTING_NAME, false, LLSD::TypeString, boost::bind(&Validator::verifyStringLength, _1, _2, 63));
static Validator validateId(SETTING_ID, false, LLSD::TypeUUID);
static Validator validateHash(SETTING_HASH, false, LLSD::TypeInteger);
static Validator validateType(SETTING_TYPE, false, LLSD::TypeString);
@@ -534,7 +534,7 @@ bool LLSettingsBase::Validator::verify(LLSD &data, U32 flags)
return false;
}
- if (!mVerify.empty() && !mVerify(data[mName]))
+ if (!mVerify.empty() && !mVerify(data[mName], flags))
{
LL_WARNS("SETTINGS") << "Setting '" << mName << "' fails validation." << LL_ENDL;
return false;
@@ -543,17 +543,17 @@ bool LLSettingsBase::Validator::verify(LLSD &data, U32 flags)
return true;
}
-bool LLSettingsBase::Validator::verifyColor(LLSD &value)
+bool LLSettingsBase::Validator::verifyColor(LLSD &value, U32)
{
return (value.size() == 3 || value.size() == 4);
}
-bool LLSettingsBase::Validator::verifyVector(LLSD &value, S32 length)
+bool LLSettingsBase::Validator::verifyVector(LLSD &value, U32, S32 length)
{
return (value.size() == length);
}
-bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD &value, S32 length)
+bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD &value, U32, S32 length)
{
if (value.size() != length)
return false;
@@ -596,7 +596,7 @@ bool LLSettingsBase::Validator::verifyVectorNormalized(LLSD &value, S32 length)
return true;
}
-bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals)
+bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD &value, U32, LLSD minvals, LLSD maxvals)
{
for (S32 index = 0; index < value.size(); ++index)
{
@@ -619,12 +619,12 @@ bool LLSettingsBase::Validator::verifyVectorMinMax(LLSD &value, LLSD minvals, LL
return true;
}
-bool LLSettingsBase::Validator::verifyQuaternion(LLSD &value)
+bool LLSettingsBase::Validator::verifyQuaternion(LLSD &value, U32)
{
return (value.size() == 4);
}
-bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD &value)
+bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD &value, U32)
{
if (value.size() != 4)
return false;
@@ -642,7 +642,7 @@ bool LLSettingsBase::Validator::verifyQuaternionNormal(LLSD &value)
return true;
}
-bool LLSettingsBase::Validator::verifyFloatRange(LLSD &value, LLSD range)
+bool LLSettingsBase::Validator::verifyFloatRange(LLSD &value, U32, LLSD range)
{
F64 real = value.asReal();
@@ -655,7 +655,7 @@ bool LLSettingsBase::Validator::verifyFloatRange(LLSD &value, LLSD range)
return true;
}
-bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, LLSD range)
+bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, U32, LLSD range)
{
S32 ival = value.asInteger();
@@ -668,7 +668,7 @@ bool LLSettingsBase::Validator::verifyIntegerRange(LLSD &value, LLSD range)
return true;
}
-bool LLSettingsBase::Validator::verifyStringLength(LLSD &value, S32 length)
+bool LLSettingsBase::Validator::verifyStringLength(LLSD &value, U32, S32 length)
{
std::string sval = value.asString();
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
index f7a9d5b7cd..1f0589f571 100644
--- a/indra/llinventory/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -270,7 +270,7 @@ public:
public:
static const U32 VALIDATION_PARTIAL;
- typedef boost::function<bool(LLSD &)> verify_pr;
+ typedef boost::function<bool(LLSD &, U32)> verify_pr;
Validator(std::string name, bool required, LLSD::Type type, verify_pr verify = verify_pr(), LLSD defval = LLSD()) :
mName(name),
@@ -287,15 +287,15 @@ public:
bool verify(LLSD &data, U32 flags);
// Some basic verifications
- static bool verifyColor(LLSD &value);
- static bool verifyVector(LLSD &value, S32 length);
- static bool verifyVectorMinMax(LLSD &value, LLSD minvals, LLSD maxvals);
- static bool verifyVectorNormalized(LLSD &value, S32 length);
- static bool verifyQuaternion(LLSD &value);
- static bool verifyQuaternionNormal(LLSD &value);
- static bool verifyFloatRange(LLSD &value, LLSD range);
- static bool verifyIntegerRange(LLSD &value, LLSD range);
- static bool verifyStringLength(LLSD &value, S32 length);
+ static bool verifyColor(LLSD &value, U32 flags);
+ static bool verifyVector(LLSD &value, U32 flags, S32 length);
+ static bool verifyVectorMinMax(LLSD &value, U32 flags, LLSD minvals, LLSD maxvals);
+ static bool verifyVectorNormalized(LLSD &value, U32 flags, S32 length);
+ static bool verifyQuaternion(LLSD &value, U32 flags);
+ static bool verifyQuaternionNormal(LLSD &value, U32 flags);
+ static bool verifyFloatRange(LLSD &value, U32 flags, LLSD range);
+ static bool verifyIntegerRange(LLSD &value, U32 flags, LLSD range);
+ static bool verifyStringLength(LLSD &value, U32 flags, S32 length);
private:
std::string mName;
diff --git a/indra/llinventory/llsettingsdaycycle.cpp b/indra/llinventory/llsettingsdaycycle.cpp
index b390ea5b1e..241826604f 100644
--- a/indra/llinventory/llsettingsdaycycle.cpp
+++ b/indra/llinventory/llsettingsdaycycle.cpp
@@ -457,7 +457,7 @@ void LLSettingsDay::blend(const LLSettingsBase::ptr_t &other, F64 mix)
namespace
{
- bool validateDayCycleTrack(LLSD &value)
+ bool validateDayCycleTrack(LLSD &value, U32 flags)
{
// Trim extra tracks.
while (value.size() > LLSettingsDay::TRACK_MAX)
@@ -528,7 +528,7 @@ namespace
return true;
}
- bool validateDayCycleFrames(LLSD &value)
+ bool validateDayCycleFrames(LLSD &value, U32 flags)
{
bool hasSky(false);
bool hasWater(false);
@@ -541,7 +541,7 @@ namespace
if (ftype == "sky")
{
LLSettingsSky::validation_list_t valid_sky = LLSettingsSky::validationList();
- LLSD res_sky = LLSettingsBase::settingValidation(frame, valid_sky);
+ LLSD res_sky = LLSettingsBase::settingValidation(frame, valid_sky, flags);
if (res_sky["success"].asInteger() == 0)
{
@@ -554,7 +554,7 @@ namespace
else if (ftype == "water")
{
LLSettingsWater::validation_list_t valid_h2o = LLSettingsWater::validationList();
- LLSD res_h2o = LLSettingsBase::settingValidation(frame, valid_h2o);
+ LLSD res_h2o = LLSettingsBase::settingValidation(frame, valid_h2o, flags);
if (res_h2o["success"].asInteger() == 0)
{
LL_WARNS("SETTINGS") << "Water setting named '" << (*itf).first << "' validation failed!: " << res_h2o << LL_ENDL;
@@ -570,18 +570,20 @@ namespace
}
}
- if (!hasSky)
+ if ((flags & LLSettingsBase::Validator::VALIDATION_PARTIAL) == 0)
{
- LL_WARNS("SETTINGS") << "No skies defined." << LL_ENDL;
- return false;
- }
+ if (!hasSky)
+ {
+ LL_WARNS("SETTINGS") << "No skies defined." << LL_ENDL;
+ return false;
+ }
- if (!hasWater)
- {
- LL_WARNS("SETTINGS") << "No waters defined." << LL_ENDL;
- return false;
+ if (!hasWater)
+ {
+ LL_WARNS("SETTINGS") << "No waters defined." << LL_ENDL;
+ return false;
+ }
}
-
return true;
}
}
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index 0ada97ad3f..979a284744 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -151,25 +151,25 @@ LLSettingsSky::validation_list_t legacyHazeValidationList()
if (legacyHazeValidation.empty())
{
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_AMBIENT, false, LLSD::TypeArray,
- boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1,
+ boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_DENSITY, false, LLSD::TypeArray,
- boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1,
+ boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_BLUE_HORIZON, false, LLSD::TypeArray,
- boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1,
+ boost::bind(&LLSettingsBase::Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_DENSITY, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(5.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(5.0f)))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_HAZE_HORIZON, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(5.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(5.0f)))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_MULTIPLIER, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0001f)(2.0f)))));
legacyHazeValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DISTANCE_MULTIPLIER, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0001f)(1000.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0001f)(1000.0f)))));
}
return legacyHazeValidation;
}
@@ -180,19 +180,19 @@ LLSettingsSky::validation_list_t rayleighValidationList()
if (rayleighValidation.empty())
{
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(32768.0f)))));
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-1.0f)(1.0f)))));
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
rayleighValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
}
return rayleighValidation;
}
@@ -203,19 +203,19 @@ LLSettingsSky::validation_list_t absorptionValidationList()
if (absorptionValidation.empty())
{
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(32768.0f)))));
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-1.0f)(1.0f)))));
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
absorptionValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
}
return absorptionValidation;
}
@@ -226,31 +226,31 @@ LLSettingsSky::validation_list_t mieValidationList()
if (mieValidation.empty())
{
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_WIDTH, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(32768.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(32768.0f)))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_EXP_SCALE_FACTOR, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(-1.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-1.0f)(1.0f)))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_LINEAR_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(2.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(2.0f)))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_DENSITY_PROFILE_CONSTANT_TERM, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
mieValidation.push_back(LLSettingsBase::Validator(LLSettingsSky::SETTING_MIE_ANISOTROPY_FACTOR, false, LLSD::TypeReal,
- boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&LLSettingsBase::Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
}
return mieValidation;
}
-bool validateLegacyHaze(LLSD &value)
+bool validateLegacyHaze(LLSD &value, U32 flags)
{
LLSettingsSky::validation_list_t legacyHazeValidations = legacyHazeValidationList();
llassert(value.type() == LLSD::TypeMap);
- LLSD result = LLSettingsBase::settingValidation(value, legacyHazeValidations);
+ LLSD result = LLSettingsBase::settingValidation(value, legacyHazeValidations, flags);
if (result["errors"].size() > 0)
{
LL_WARNS("SETTINGS") << "Legacy Haze Config Validation errors: " << result["errors"] << LL_ENDL;
@@ -264,7 +264,7 @@ bool validateLegacyHaze(LLSD &value)
return true;
}
-bool validateRayleighLayers(LLSD &value)
+bool validateRayleighLayers(LLSD &value, U32 flags)
{
LLSettingsSky::validation_list_t rayleighValidations = rayleighValidationList();
if (value.isArray())
@@ -275,24 +275,24 @@ bool validateRayleighLayers(LLSD &value)
LLSD& layerConfig = (*itf);
if (layerConfig.type() == LLSD::TypeMap)
{
- if (!validateRayleighLayers(layerConfig))
+ if (!validateRayleighLayers(layerConfig, flags))
{
allGood = false;
}
}
else if (layerConfig.type() == LLSD::TypeArray)
{
- return validateRayleighLayers(layerConfig);
+ return validateRayleighLayers(layerConfig, flags);
}
else
{
- return LLSettingsBase::settingValidation(value, rayleighValidations);
+ return LLSettingsBase::settingValidation(value, rayleighValidations, flags);
}
}
return allGood;
}
llassert(value.type() == LLSD::TypeMap);
- LLSD result = LLSettingsBase::settingValidation(value, rayleighValidations);
+ LLSD result = LLSettingsBase::settingValidation(value, rayleighValidations, flags);
if (result["errors"].size() > 0)
{
LL_WARNS("SETTINGS") << "Rayleigh Config Validation errors: " << result["errors"] << LL_ENDL;
@@ -306,7 +306,7 @@ bool validateRayleighLayers(LLSD &value)
return true;
}
-bool validateAbsorptionLayers(LLSD &value)
+bool validateAbsorptionLayers(LLSD &value, U32 flags)
{
LLSettingsBase::validation_list_t absorptionValidations = absorptionValidationList();
if (value.isArray())
@@ -317,24 +317,24 @@ bool validateAbsorptionLayers(LLSD &value)
LLSD& layerConfig = (*itf);
if (layerConfig.type() == LLSD::TypeMap)
{
- if (!validateAbsorptionLayers(layerConfig))
+ if (!validateAbsorptionLayers(layerConfig, flags))
{
allGood = false;
}
}
else if (layerConfig.type() == LLSD::TypeArray)
{
- return validateAbsorptionLayers(layerConfig);
+ return validateAbsorptionLayers(layerConfig, flags);
}
else
{
- return LLSettingsBase::settingValidation(value, absorptionValidations);
+ return LLSettingsBase::settingValidation(value, absorptionValidations, flags);
}
}
return allGood;
}
llassert(value.type() == LLSD::TypeMap);
- LLSD result = LLSettingsBase::settingValidation(value, absorptionValidations);
+ LLSD result = LLSettingsBase::settingValidation(value, absorptionValidations, flags);
if (result["errors"].size() > 0)
{
LL_WARNS("SETTINGS") << "Absorption Config Validation errors: " << result["errors"] << LL_ENDL;
@@ -348,7 +348,7 @@ bool validateAbsorptionLayers(LLSD &value)
return true;
}
-bool validateMieLayers(LLSD &value)
+bool validateMieLayers(LLSD &value, U32 flags)
{
LLSettingsBase::validation_list_t mieValidations = mieValidationList();
if (value.isArray())
@@ -359,23 +359,23 @@ bool validateMieLayers(LLSD &value)
LLSD& layerConfig = (*itf);
if (layerConfig.type() == LLSD::TypeMap)
{
- if (!validateMieLayers(layerConfig))
+ if (!validateMieLayers(layerConfig, flags))
{
allGood = false;
}
}
else if (layerConfig.type() == LLSD::TypeArray)
{
- return validateMieLayers(layerConfig);
+ return validateMieLayers(layerConfig, flags);
}
else
{
- return LLSettingsBase::settingValidation(value, mieValidations);
+ return LLSettingsBase::settingValidation(value, mieValidations, flags);
}
}
return allGood;
}
- LLSD result = LLSettingsBase::settingValidation(value, mieValidations);
+ LLSD result = LLSettingsBase::settingValidation(value, mieValidations, flags);
if (result["errors"].size() > 0)
{
LL_WARNS("SETTINGS") << "Mie Config Validation errors: " << result["errors"] << LL_ENDL;
@@ -555,80 +555,80 @@ LLSettingsSky::validation_list_t LLSettingsSky::validationList()
validation.push_back(Validator(SETTING_HALO_TEXTUREID, false, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_CLOUD_COLOR, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*")))));
validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY1, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
LLSD(LLSDArray(1.0f)(1.0f)(3.0f)("*")))));
validation.push_back(Validator(SETTING_CLOUD_POS_DENSITY2, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
LLSD(LLSDArray(1.0f)(1.0f)(1.0f)("*")))));
validation.push_back(Validator(SETTING_CLOUD_SCALE, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.001f)(3.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.001f)(3.0f)))));
validation.push_back(Validator(SETTING_CLOUD_SCROLL_RATE, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(-50.0f)(-50.0f)),
LLSD(LLSDArray(50.0f)(50.0f)))));
validation.push_back(Validator(SETTING_CLOUD_SHADOW, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
validation.push_back(Validator(SETTING_CLOUD_TEXTUREID, false, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_CLOUD_VARIANCE, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
validation.push_back(Validator(SETTING_DOME_OFFSET, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
validation.push_back(Validator(SETTING_DOME_RADIUS, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(2000.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(2000.0f)))));
validation.push_back(Validator(SETTING_GAMMA, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(20.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(20.0f)))));
validation.push_back(Validator(SETTING_GLOW, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.2f)("*")(-10.0f)("*")),
LLSD(LLSDArray(40.0f)("*")(10.0f)("*")))));
validation.push_back(Validator(SETTING_MAX_Y, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(10000.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(10000.0f)))));
validation.push_back(Validator(SETTING_MOON_ROTATION, true, LLSD::TypeArray, &Validator::verifyQuaternionNormal));
validation.push_back(Validator(SETTING_MOON_SCALE, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
validation.push_back(Validator(SETTING_MOON_TEXTUREID, false, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_MOON_BRIGHTNESS, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
validation.push_back(Validator(SETTING_STAR_BRIGHTNESS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(500.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(500.0f)))));
validation.push_back(Validator(SETTING_SUNLIGHT_COLOR, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)("*")),
LLSD(LLSDArray(3.0f)(3.0f)(3.0f)("*")))));
validation.push_back(Validator(SETTING_SUN_ROTATION, true, LLSD::TypeArray, &Validator::verifyQuaternionNormal));
validation.push_back(Validator(SETTING_SUN_SCALE, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.25f)(20.0f))), LLSD::Real(1.0)));
validation.push_back(Validator(SETTING_SUN_TEXTUREID, false, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_PLANET_RADIUS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(32768.0f)))));
validation.push_back(Validator(SETTING_SKY_BOTTOM_RADIUS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(32768.0f)))));
validation.push_back(Validator(SETTING_SKY_TOP_RADIUS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(1000.0f)(32768.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(1000.0f)(32768.0f)))));
validation.push_back(Validator(SETTING_SUN_ARC_RADIANS, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(0.1f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(0.1f)))));
validation.push_back(Validator(SETTING_SKY_MOISTURE_LEVEL, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
validation.push_back(Validator(SETTING_SKY_DROPLET_RADIUS, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(5.0f)(1000.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(5.0f)(1000.0f)))));
validation.push_back(Validator(SETTING_SKY_ICE_LEVEL, false, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
validation.push_back(Validator(SETTING_RAYLEIGH_CONFIG, true, LLSD::TypeArray, &validateRayleighLayers));
validation.push_back(Validator(SETTING_ABSORPTION_CONFIG, true, LLSD::TypeArray, &validateAbsorptionLayers));
diff --git a/indra/llinventory/llsettingswater.cpp b/indra/llinventory/llsettingswater.cpp
index 16cd3343e4..90f99e8198 100644
--- a/indra/llinventory/llsettingswater.cpp
+++ b/indra/llinventory/llsettingswater.cpp
@@ -228,34 +228,34 @@ LLSettingsWater::validation_list_t LLSettingsWater::validationList()
// in deeply nested arrays like this [[[[[[[[[[v1,v2,v3]]]]]]]]]]
validation.push_back(Validator(SETTING_BLUR_MULTIPLIER, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-0.5f)(0.5f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-0.5f)(0.5f)))));
validation.push_back(Validator(SETTING_FOG_COLOR, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)(1.0f)),
LLSD(LLSDArray(1.0f)(1.0f)(1.0f)(1.0f)))));
validation.push_back(Validator(SETTING_FOG_DENSITY, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(-10.0f)(10.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(-10.0f)(10.0f)))));
validation.push_back(Validator(SETTING_FOG_MOD, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(20.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(20.0f)))));
validation.push_back(Validator(SETTING_FRESNEL_OFFSET, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
validation.push_back(Validator(SETTING_FRESNEL_SCALE, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(1.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(1.0f)))));
validation.push_back(Validator(SETTING_NORMAL_MAP, true, LLSD::TypeUUID));
validation.push_back(Validator(SETTING_NORMAL_SCALE, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(0.0f)(0.0f)(0.0f)),
LLSD(LLSDArray(10.0f)(10.0f)(10.0f)))));
validation.push_back(Validator(SETTING_SCALE_ABOVE, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(3.0f)))));
validation.push_back(Validator(SETTING_SCALE_BELOW, true, LLSD::TypeReal,
- boost::bind(&Validator::verifyFloatRange, _1, LLSD(LLSDArray(0.0f)(3.0f)))));
+ boost::bind(&Validator::verifyFloatRange, _1, _2, LLSD(LLSDArray(0.0f)(3.0f)))));
validation.push_back(Validator(SETTING_WAVE1_DIR, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(-20.0f)(-20.0f)),
LLSD(LLSDArray(20.0f)(20.0f)))));
validation.push_back(Validator(SETTING_WAVE2_DIR, true, LLSD::TypeArray,
- boost::bind(&Validator::verifyVectorMinMax, _1,
+ boost::bind(&Validator::verifyVectorMinMax, _1, _2,
LLSD(LLSDArray(-20.0f)(-20.0f)),
LLSD(LLSDArray(20.0f)(20.0f)))));
}
diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h
index 5291a05607..2cf50e9cd2 100644
--- a/indra/llmath/llmatrix4a.h
+++ b/indra/llmath/llmatrix4a.h
@@ -78,8 +78,15 @@ public:
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 F32* src)
+ {
+ mMatrix[0] = _mm_loadu_ps(src);
+ mMatrix[1] = _mm_loadu_ps(src+4);
+ mMatrix[2] = _mm_loadu_ps(src+8);
+ mMatrix[3] = _mm_loadu_ps(src+12);
+ }
inline void loadu(const LLMatrix3& src)
{
diff --git a/indra/llmessage/lldatapacker.cpp b/indra/llmessage/lldatapacker.cpp
index 6cf6af6437..96c1297e0d 100644
--- a/indra/llmessage/lldatapacker.cpp
+++ b/indra/llmessage/lldatapacker.cpp
@@ -173,6 +173,71 @@ BOOL LLDataPacker::unpackFixed(F32 &value, const char *name,
return ok;
}
+BOOL LLDataPacker::unpackU16s(U16 *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackU16(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading Unsigned 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOL LLDataPacker::unpackS16s(S16 *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackS16(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading Signed 16s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOL LLDataPacker::unpackF32s(F32 *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackF32(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOL LLDataPacker::unpackColor4Us(LLColor4U *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackColor4U(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading Float 32s \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+BOOL LLDataPacker::unpackUUIDs(LLUUID *values, S32 count, const char *name)
+{
+ for (S32 idx = 0; idx < count; ++idx)
+ {
+ if (!unpackUUID(values[idx], name))
+ {
+ LL_WARNS("DATAPACKER") << "Buffer overflow reading UUIDs \"" << name << "\" at index " << idx << "!" << LL_ENDL;
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
//---------------------------------------------------------------------------
// LLDataPackerBinaryBuffer implementation
//---------------------------------------------------------------------------
@@ -319,6 +384,29 @@ BOOL LLDataPackerBinaryBuffer::unpackU16(U16 &value, const char *name)
return success;
}
+BOOL LLDataPackerBinaryBuffer::packS16(const S16 value, const char *name)
+{
+ BOOL success = verifyLength(sizeof(S16), name);
+
+ if (mWriteEnabled && success)
+ {
+ htolememcpy(mCurBufferp, &value, MVT_S16, 2);
+ }
+ mCurBufferp += 2;
+ return success;
+}
+
+BOOL LLDataPackerBinaryBuffer::unpackS16(S16 &value, const char *name)
+{
+ BOOL success = verifyLength(sizeof(S16), name);
+
+ if (success)
+ {
+ htolememcpy(&value, mCurBufferp, MVT_S16, 2);
+ }
+ mCurBufferp += 2;
+ return success;
+}
BOOL LLDataPackerBinaryBuffer::packU32(const U32 value, const char *name)
{
@@ -884,6 +972,52 @@ BOOL LLDataPackerAsciiBuffer::unpackU16(U16 &value, const char *name)
return success;
}
+BOOL LLDataPackerAsciiBuffer::packS16(const S16 value, const char *name)
+{
+ BOOL success = TRUE;
+ writeIndentedName(name);
+ int numCopied = 0;
+ if (mWriteEnabled)
+ {
+ numCopied = snprintf(mCurBufferp, getBufferSize() - getCurrentSize(), "%d\n", value); /* Flawfinder: ignore */
+ }
+ else
+ {
+ numCopied = snprintf(DUMMY_BUFFER, sizeof(DUMMY_BUFFER), "%d\n", value); /* Flawfinder: ignore */
+ }
+
+ // snprintf returns number of bytes that would have been written
+ // had the output not being truncated. In that case, it will
+ // return either -1 or value >= passed in size value . So a check needs to be added
+ // to detect truncation, and if there is any, only account for the
+ // actual number of bytes written..and not what could have been
+ // written.
+ if(numCopied < 0 || numCopied > getBufferSize() - getCurrentSize())
+ {
+ numCopied = getBufferSize() - getCurrentSize();
+ LL_WARNS() << "LLDataPackerAsciiBuffer::packS16: val truncated: " << LL_ENDL;
+ }
+
+ mCurBufferp += numCopied;
+
+ return success;
+}
+
+
+BOOL LLDataPackerAsciiBuffer::unpackS16(S16 &value, const char *name)
+{
+ BOOL success = TRUE;
+ char valuestr[DP_BUFSIZE]; /* Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return FALSE;
+ }
+
+ S32 in_val;
+ sscanf(valuestr, "%d", &in_val);
+ value = in_val;
+ return success;
+}
BOOL LLDataPackerAsciiBuffer::packU32(const U32 value, const char *name)
{
@@ -1587,6 +1721,36 @@ BOOL LLDataPackerAsciiFile::unpackU16(U16 &value, const char *name)
return success;
}
+BOOL LLDataPackerAsciiFile::packS16(const S16 value, const char *name)
+{
+ BOOL success = TRUE;
+ writeIndentedName(name);
+ if (mFP)
+ {
+ fprintf(mFP, "%d\n", value);
+ }
+ else if (mOutputStream)
+ {
+ *mOutputStream << "" << value << "\n";
+ }
+ return success;
+}
+
+
+BOOL LLDataPackerAsciiFile::unpackS16(S16 &value, const char *name)
+{
+ BOOL success = TRUE;
+ char valuestr[DP_BUFSIZE]; /*Flawfinder: ignore */
+ if (!getValueStr(name, valuestr, DP_BUFSIZE))
+ {
+ return FALSE;
+ }
+
+ S32 in_val;
+ sscanf(valuestr, "%d", &in_val);
+ value = in_val;
+ return success;
+}
BOOL LLDataPackerAsciiFile::packU32(const U32 value, const char *name)
{
diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h
index 5140f56c01..ac28cadbce 100644
--- a/indra/llmessage/lldatapacker.h
+++ b/indra/llmessage/lldatapacker.h
@@ -60,6 +60,11 @@ public:
virtual BOOL packU16(const U16 value, const char *name) = 0;
virtual BOOL unpackU16(U16 &value, const char *name) = 0;
+ BOOL unpackU16s(U16 *value, S32 count, const char *name);
+
+ virtual BOOL packS16(const S16 value, const char *name) = 0;
+ virtual BOOL unpackS16(S16 &value, const char *name) = 0;
+ BOOL unpackS16s(S16 *value, S32 count, const char *name);
virtual BOOL packU32(const U32 value, const char *name) = 0;
virtual BOOL unpackU32(U32 &value, const char *name) = 0;
@@ -69,6 +74,7 @@ public:
virtual BOOL packF32(const F32 value, const char *name) = 0;
virtual BOOL unpackF32(F32 &value, const char *name) = 0;
+ BOOL unpackF32s(F32 *values, S32 count, const char *name);
// Packs a float into an integer, using the given size
// and picks the right U* data type to pack into.
@@ -82,6 +88,7 @@ public:
virtual BOOL packColor4U(const LLColor4U &value, const char *name) = 0;
virtual BOOL unpackColor4U(LLColor4U &value, const char *name) = 0;
+ BOOL unpackColor4Us(LLColor4U *values, S32 count, const char *name);
virtual BOOL packVector2(const LLVector2 &value, const char *name) = 0;
virtual BOOL unpackVector2(LLVector2 &value, const char *name) = 0;
@@ -94,6 +101,7 @@ public:
virtual BOOL packUUID(const LLUUID &value, const char *name) = 0;
virtual BOOL unpackUUID(LLUUID &value, const char *name) = 0;
+ BOOL unpackUUIDs(LLUUID *values, S32 count, const char *name);
U32 getPassFlags() const { return mPassFlags; }
void setPassFlags(U32 flags) { mPassFlags = flags; }
protected:
@@ -139,6 +147,9 @@ public:
/*virtual*/ BOOL packU16(const U16 value, const char *name);
/*virtual*/ BOOL unpackU16(U16 &value, const char *name);
+ /*virtual*/ BOOL packS16(const S16 value, const char *name);
+ /*virtual*/ BOOL unpackS16(S16 &value, const char *name);
+
/*virtual*/ BOOL packU32(const U32 value, const char *name);
/*virtual*/ BOOL unpackU32(U32 &value, const char *name);
@@ -247,6 +258,9 @@ public:
/*virtual*/ BOOL packU16(const U16 value, const char *name);
/*virtual*/ BOOL unpackU16(U16 &value, const char *name);
+ /*virtual*/ BOOL packS16(const S16 value, const char *name);
+ /*virtual*/ BOOL unpackS16(S16 &value, const char *name);
+
/*virtual*/ BOOL packU32(const U32 value, const char *name);
/*virtual*/ BOOL unpackU32(U32 &value, const char *name);
@@ -375,6 +389,9 @@ public:
/*virtual*/ BOOL packU16(const U16 value, const char *name);
/*virtual*/ BOOL unpackU16(U16 &value, const char *name);
+ /*virtual*/ BOOL packS16(const S16 value, const char *name);
+ /*virtual*/ BOOL unpackS16(S16 &value, const char *name);
+
/*virtual*/ BOOL packU32(const U32 value, const char *name);
/*virtual*/ BOOL unpackU32(U32 &value, const char *name);
diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp
index fba5b7453d..219b1855d2 100644
--- a/indra/llmessage/message_prehash.cpp
+++ b/indra/llmessage/message_prehash.cpp
@@ -281,6 +281,13 @@ char const* const _PREHASH_PricePerMeter = LLMessageStringTable::getInstance()->
char const* const _PREHASH_RegionFlags = LLMessageStringTable::getInstance()->getString("RegionFlags");
char const* const _PREHASH_RegionFlagsExtended = LLMessageStringTable::getInstance()->getString("RegionFlagsExtended");
char const* const _PREHASH_RegionProtocols = LLMessageStringTable::getInstance()->getString("RegionProtocols");
+char const* const _PREHASH_ChatWhisperRange = LLMessageStringTable::getInstance()->getString("ChatWhisperRange");
+char const* const _PREHASH_ChatNormalRange = LLMessageStringTable::getInstance()->getString("ChatNormalRange");
+char const* const _PREHASH_ChatShoutRange = LLMessageStringTable::getInstance()->getString("ChatShoutRange");
+char const* const _PREHASH_ChatWhisperOffset = LLMessageStringTable::getInstance()->getString("ChatWhisperOffset");
+char const* const _PREHASH_ChatNormalOffset = LLMessageStringTable::getInstance()->getString("ChatNormalOffset");
+char const* const _PREHASH_ChatShoutOffset = LLMessageStringTable::getInstance()->getString("ChatShoutOffset");
+char const* const _PREHASH_ChatFlags = LLMessageStringTable::getInstance()->getString("ChatFlags");
char const* const _PREHASH_VoteResult = LLMessageStringTable::getInstance()->getString("VoteResult");
char const* const _PREHASH_ParcelDirFeeEstimate = LLMessageStringTable::getInstance()->getString("ParcelDirFeeEstimate");
char const* const _PREHASH_ModifyBlock = LLMessageStringTable::getInstance()->getString("ModifyBlock");
@@ -309,6 +316,7 @@ char const* const _PREHASH_DuplicateFlags = LLMessageStringTable::getInstance()-
char const* const _PREHASH_RegionInfo2 = LLMessageStringTable::getInstance()->getString("RegionInfo2");
char const* const _PREHASH_RegionInfo3 = LLMessageStringTable::getInstance()->getString("RegionInfo3");
char const* const _PREHASH_RegionInfo4 = LLMessageStringTable::getInstance()->getString("RegionInfo4");
+char const* const _PREHASH_RegionInfo5 = LLMessageStringTable::getInstance()->getString("RegionInfo5");
char const* const _PREHASH_TextColor = LLMessageStringTable::getInstance()->getString("TextColor");
char const* const _PREHASH_SlaveID = LLMessageStringTable::getInstance()->getString("SlaveID");
char const* const _PREHASH_Charter = LLMessageStringTable::getInstance()->getString("Charter");
diff --git a/indra/llmessage/message_prehash.h b/indra/llmessage/message_prehash.h
index 4f72c01ddf..8f6ee5a327 100644
--- a/indra/llmessage/message_prehash.h
+++ b/indra/llmessage/message_prehash.h
@@ -281,6 +281,13 @@ extern char const* const _PREHASH_PricePerMeter;
extern char const* const _PREHASH_RegionFlags;
extern char const* const _PREHASH_RegionFlagsExtended;
extern char const* const _PREHASH_RegionProtocols;
+extern char const* const _PREHASH_ChatWhisperRange;
+extern char const* const _PREHASH_ChatNormalRange;
+extern char const* const _PREHASH_ChatShoutRange;
+extern char const* const _PREHASH_ChatWhisperOffset;
+extern char const* const _PREHASH_ChatNormalOffset;
+extern char const* const _PREHASH_ChatShoutOffset;
+extern char const* const _PREHASH_ChatFlags;
extern char const* const _PREHASH_VoteResult;
extern char const* const _PREHASH_ParcelDirFeeEstimate;
extern char const* const _PREHASH_ModifyBlock;
@@ -309,6 +316,7 @@ extern char const* const _PREHASH_DuplicateFlags;
extern char const* const _PREHASH_RegionInfo2;
extern char const* const _PREHASH_RegionInfo3;
extern char const* const _PREHASH_RegionInfo4;
+extern char const* const _PREHASH_RegionInfo5;
extern char const* const _PREHASH_TextColor;
extern char const* const _PREHASH_SlaveID;
extern char const* const _PREHASH_Charter;
diff --git a/indra/llplugin/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 6d51adc685..a436452461 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -690,6 +690,66 @@ bool LLPluginClassMedia::textInput(const std::string &text, MASK modifiers, LLSD
return true;
}
+// This function injects a previously stored OpenID cookie into
+// each new media instance - see SL-15867 for details. It appears
+// that the way we use the cache, shared between multiple CEF
+// instances means that sometimes the OpenID cookie cannot be read
+// even though it appears to be there. The long term solution to
+// this is to create a separate cache directory for each instance
+// but that has its own set of problems. This short term approach
+// "forces" each new media instance to have a copy of the cookie
+// so that a page that needs it - e.g. Profiles - finds it and
+// can log in successfully.
+void LLPluginClassMedia::injectOpenIDCookie()
+{
+ // can be called before we know who the user is at login
+ // and there is no OpenID cookie at that point so no
+ // need to try to set it (these values will all be empty)
+ if (sOIDcookieName.length() && sOIDcookieValue.length())
+ {
+ setCookie(sOIDcookieUrl, sOIDcookieName,
+ sOIDcookieValue, sOIDcookieHost, sOIDcookiePath, sOIDcookieHttpOnly, sOIDcookieSecure);
+ }
+}
+
+// We store each component of the OpenI cookie individuality here
+// because previously, there was some significant parsing to
+// break up the raw string into these components and we do not
+// want to have to do that again here. Stored as statics because
+// we want to share their value between all instances of this
+// class - the ones that receive it at login and any others
+// that open afterwards (e.g. the Profiles floater)
+std::string LLPluginClassMedia::sOIDcookieUrl = std::string();
+std::string LLPluginClassMedia::sOIDcookieName = std::string();
+std::string LLPluginClassMedia::sOIDcookieValue = std::string();
+std::string LLPluginClassMedia::sOIDcookieHost = std::string();
+std::string LLPluginClassMedia::sOIDcookiePath = std::string();
+bool LLPluginClassMedia::sOIDcookieHttpOnly = false;
+bool LLPluginClassMedia::sOIDcookieSecure = false;
+
+// Once we receive the OpenID cookie, it is parsed/processed
+// in llViewerMedia::parseRawCookie() and then the component
+// values are stored here so that next time a new media
+// instance is created, we can use injectOpenIDCookie()
+// to "insist" that the cookie store remember its value.
+// One might ask why we need to go via LLViewerMedia (which
+// makes this call) - this is because the raw cookie arrives
+// here in this file but undergoes non-trivial processing
+// in LLViewerMedia.
+void LLPluginClassMedia::storeOpenIDCookie(const std::string url,
+ const std::string name, const std::string value,
+ const std::string host, const std::string path,
+ bool httponly, bool secure)
+{
+ sOIDcookieUrl = url;
+ sOIDcookieName = name;
+ sOIDcookieValue = value;
+ sOIDcookieHost = host;
+ sOIDcookiePath = path;
+ sOIDcookieHttpOnly = httponly;
+ sOIDcookieSecure = secure;
+}
+
void LLPluginClassMedia::setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure)
{
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_cookie");
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 382f891e0c..a09145cf50 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -135,6 +135,20 @@ public:
// Text may be unicode (utf8 encoded)
bool textInput(const std::string &text, MASK modifiers, LLSD native_key_data);
+ static std::string sOIDcookieUrl;
+ static std::string sOIDcookieName;
+ static std::string sOIDcookieValue;
+ static std::string sOIDcookieHost;
+ static std::string sOIDcookiePath;
+ static bool sOIDcookieHttpOnly;
+ static bool sOIDcookieSecure;
+ void storeOpenIDCookie(const std::string url,
+ const std::string name, const std::string value,
+ const std::string host, const std::string path,
+ bool httponly, bool secure);
+
+ void injectOpenIDCookie();
+
void setCookie(std::string uri, std::string name, std::string value, std::string domain, std::string path, bool httponly, bool secure);
void loadURI(const std::string &uri);
diff --git a/indra/llprimitive/llmaterialtable.cpp b/indra/llprimitive/llmaterialtable.cpp
index 37c718b4c6..58b2d00d44 100644
--- a/indra/llprimitive/llmaterialtable.cpp
+++ b/indra/llprimitive/llmaterialtable.cpp
@@ -559,6 +559,23 @@ LLUUID LLMaterialTable::getCollisionSoundUUID(U8 mcode, U8 mcode2)
}
}
+bool LLMaterialTable::isCollisionSound(const LLUUID &uuid)
+{
+ for (U8 i = 0; i < LL_MCODE_END; i++)
+ {
+ for (U8 j = 0; j < LL_MCODE_END; j++)
+ {
+ i &= LL_MCODE_MASK;
+ j &= LL_MCODE_MASK;
+ if (mCollisionSoundMatrix[i * LL_MCODE_END + j] == uuid)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
LLUUID LLMaterialTable::getSlidingSoundUUID(U8 mcode, U8 mcode2)
{
mcode &= LL_MCODE_MASK;
diff --git a/indra/llprimitive/llmaterialtable.h b/indra/llprimitive/llmaterialtable.h
index a17e0103ff..0cf5e626ef 100644
--- a/indra/llprimitive/llmaterialtable.h
+++ b/indra/llprimitive/llmaterialtable.h
@@ -128,6 +128,8 @@ public:
F32 getDamageMod(U8 mcode);
F32 getEPMod(U8 mcode);
+ bool isCollisionSound(const LLUUID &uuid);
+
LLUUID getCollisionSoundUUID(U8 mcode, U8 mcode2);
LLUUID getSlidingSoundUUID(U8 mcode, U8 mcode2);
LLUUID getRollingSoundUUID(U8 mcode, U8 mcode2);
diff --git a/indra/llprimitive/llmediaentry.cpp b/indra/llprimitive/llmediaentry.cpp
index 02aba2bd83..53e9555c6a 100644
--- a/indra/llprimitive/llmediaentry.cpp
+++ b/indra/llprimitive/llmediaentry.cpp
@@ -27,8 +27,7 @@
#include "linden_common.h"
#include "llmediaentry.h"
#include "lllslconstants.h"
-
-#include <boost/regex.hpp>
+#include "llregex.h"
// LLSD key defines
// DO NOT REORDER OR REMOVE THESE!
@@ -456,7 +455,7 @@ static bool pattern_match(const std::string &candidate_str, const std::string &p
// case-insensitive matching:
boost::regex regexp(expression, boost::regex::perl|boost::regex::icase);
- return boost::regex_match(candidate_str, regexp);
+ return ll_regex_match(candidate_str, regexp);
}
bool LLMediaEntry::checkCandidateUrl(const std::string& url) const
diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp
index a23b991f1d..dd37b8ce0b 100644
--- a/indra/llprimitive/llmodel.cpp
+++ b/indra/llprimitive/llmodel.cpp
@@ -31,6 +31,7 @@
#include "llconvexdecomposition.h"
#include "llsdserialize.h"
#include "llvector4a.h"
+#include "llmd5.h"
#ifdef LL_USESYSTEMLIBS
# include <zlib.h>
@@ -1451,6 +1452,8 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
{
mLockScaleIfJointPosition = false;
}
+
+ updateHash();
}
LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_position) const
@@ -1502,6 +1505,38 @@ LLSD LLMeshSkinInfo::asLLSD(bool include_joints, bool lock_scale_if_joint_positi
return ret;
}
+void LLMeshSkinInfo::updateHash()
+{
+ // get hash of data relevant to render batches
+ LLMD5 hash;
+
+ //mJointNames
+ for (auto& name : mJointNames)
+ {
+ hash.update(name);
+ }
+
+ //mJointNums
+ hash.update((U8*)&(mJointNums[0]), sizeof(S32) * mJointNums.size());
+
+ //mInvBindMatrix
+ F32* src = mInvBindMatrix[0].getF32ptr();
+
+ for (int i = 0; i < mInvBindMatrix.size() * 16; ++i)
+ {
+ S32 t = llround(src[i] * 10000.f);
+ hash.update((U8*)&t, sizeof(S32));
+ }
+ //hash.update((U8*)&(mInvBindMatrix[0]), sizeof(LLMatrix4a) * mInvBindMatrix.size());
+
+ hash.finalize();
+
+ U64 digest[2];
+ hash.raw_digest((U8*) digest);
+
+ mHash = digest[0];
+}
+
LLModel::Decomposition::Decomposition(LLSD& data)
{
fromLLSD(data);
diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h
index cd2b6c6728..2d27592bc8 100644
--- a/indra/llprimitive/llmodel.h
+++ b/indra/llprimitive/llmodel.h
@@ -49,6 +49,7 @@ public:
LLMeshSkinInfo(LLSD& data);
void fromLLSD(LLSD& data);
LLSD asLLSD(bool include_joints, bool lock_scale_if_joint_position) const;
+ void updateHash();
LLUUID mMeshID;
std::vector<std::string> mJointNames;
@@ -58,10 +59,12 @@ public:
matrix_list_t mAlternateBindMatrix;
LL_ALIGN_16(LLMatrix4a mBindShapeMatrix);
+
float mPelvisOffset;
bool mLockScaleIfJointPosition;
bool mInvalidJointsScrubbed;
bool mJointNumsInitialized;
+ U64 mHash = 0;
} LL_ALIGN_POSTFIX(16);
LL_ALIGN_PREFIX(16)
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index 53b83a40d7..67c225d25d 100644
--- a/indra/llprimitive/llprimitive.cpp
+++ b/indra/llprimitive/llprimitive.cpp
@@ -114,6 +114,35 @@ const char *SCULPT_DEFAULT_TEXTURE = "be293869-d0d9-0a69-5989-ad27f1946fd4"; //
// can't be divided by 2. See DEV-19108
const F32 TEXTURE_ROTATION_PACK_FACTOR = ((F32) 0x08000);
+struct material_id_type // originally from llrendermaterialtable
+{
+ material_id_type()
+ {
+ memset((void*)m_value, 0, sizeof(m_value));
+ }
+
+ bool operator==(const material_id_type& other) const
+ {
+ return (memcmp(m_value, other.m_value, sizeof(m_value)) == 0);
+ }
+
+ bool operator!=(const material_id_type& other) const
+ {
+ return !operator==(other);
+ }
+
+ bool isNull() const
+ {
+ return (memcmp(m_value, s_null_id, sizeof(m_value)) == 0);
+ }
+
+ U8 m_value[MATERIAL_ID_SIZE]; // server side this is MD5RAW_BYTES
+
+ static const U8 s_null_id[MATERIAL_ID_SIZE];
+};
+
+const U8 material_id_type::s_null_id[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+
//static
// LEGACY: by default we use the LLVolumeMgr::gVolumeMgr global
// TODO -- eliminate this global from the codebase!
@@ -1079,50 +1108,85 @@ S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_fa
return (S32)(cur_ptr - start_loc);
}
-S32 LLPrimitive::unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type)
-{
- U8 *start_loc = cur_ptr;
- U64 i;
- htolememcpy(data_ptr,cur_ptr, type,data_size);
- cur_ptr += data_size;
-
- for (i = 1; i < face_count; i++)
- {
- // Already unswizzled, don't need to unswizzle it again!
- memcpy(data_ptr+(i*data_size),data_ptr,data_size); /* Flawfinder: ignore */
- }
-
- while ((cur_ptr < buffer_end) && (*cur_ptr != 0))
- {
- LL_DEBUGS("TEFieldDecode") << "TE exception" << LL_ENDL;
- i = 0;
- while (*cur_ptr & 0x80)
- {
- i |= ((*cur_ptr++) & 0x7F);
- i = i << 7;
- }
-
- i |= *cur_ptr++;
-
- for (S32 j = 0; j < face_count; j++)
- {
- if (i & 0x01)
- {
- htolememcpy(data_ptr+(j*data_size),cur_ptr,type,data_size);
- LL_DEBUGS("TEFieldDecode") << "Assigning " ;
- char foo[64];
- sprintf(foo,"%x %x",*(data_ptr+(j*data_size)), *(data_ptr+(j*data_size)+1));
- LL_CONT << foo << " to face " << j << LL_ENDL;
- }
- i = i >> 1;
- }
- cur_ptr += data_size;
- }
- llassert(cur_ptr <= buffer_end); // buffer underrun
- return (S32)(cur_ptr - start_loc);
+namespace
+{
+ template< typename T >
+ bool unpack_TEField(T dest[], U8 dest_count, U8 * &source, U8 *source_end, EMsgVariableType type)
+ {
+ const size_t size(sizeof(T));
+
+ LL_DEBUGS("TEXTUREENTRY") << "Request to read items of size " << size << " with swizzle " << type << " froum buffer sized " << (source_end - source) << LL_ENDL;
+
+ if ((source + size + 1) > source_end)
+ {
+ // we add 1 above to take into account the byte that we know must follow the value.
+ LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Requires " << size << " + 1 bytes for default, " << (source_end - source) << " bytes remaning." << LL_ENDL;
+ source = source_end;
+ return false;
+ }
+
+ // Extract the default value and fill the array.
+ htolememcpy(dest, source, type, size);
+ source += size;
+ for (S32 idx = 1; idx < dest_count; ++idx)
+ {
+ dest[idx] = dest[0];
+ }
+
+ while (source < source_end)
+ {
+ U64 index_flags(0);
+ U8 sbit(0);
+
+ // Unpack the variable length bitfield. Each bit represents whether the following
+ // value will be placed at the corresponding array index.
+ do
+ {
+ if (source >= source_end)
+ {
+ LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Reading index flags." << LL_ENDL;
+ source = source_end;
+ return false;
+ }
+
+ sbit = *source++;
+ index_flags <<= 7; // original code had this after?
+ index_flags |= (sbit & 0x7F);
+ } while (sbit & 0x80);
+
+ if (!index_flags)
+ { // We've hit the terminating 0 byte.
+ break;
+ }
+
+ if ((source + size + 1) > source_end)
+ {
+ // we add 1 above to take into account the byte that we know must follow the value.
+ LL_WARNS("TEXTUREENTRY") << "Buffer exhausted! Requires " << size << " + 1 bytes for default, " << (source_end - source) << " bytes remaning." << LL_ENDL;
+ source = source_end;
+ return false;
+ }
+
+ // get the value for the indexs.
+ T value;
+ htolememcpy(&value, source, type, size);
+ source += size;
+
+ for (S32 idx = 0; idx < dest_count; idx++)
+ {
+ if (index_flags & 1ULL << idx)
+ {
+ dest[idx] = value;
+ }
+ }
+
+ }
+ return true;
+ }
}
+
// Pack information about all texture entries into container:
// { TextureEntry Variable 2 }
// Includes information about image ID, color, scale S,T, offset S,T and rotation
@@ -1298,9 +1362,9 @@ BOOL LLPrimitive::packTEMessage(LLDataPacker &dp) const
S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num, LLTEContents& tec)
{
S32 retval = 0;
- // temp buffer for material ID processing
- // data will end up in tec.material_id[]
- U8 material_data[LLTEContents::MAX_TES*16];
+ // temp buffer for material ID processing
+ // data will end up in tec.material_id[]
+ material_id_type material_data[LLTEContents::MAX_TES];
if (block_num < 0)
{
@@ -1316,54 +1380,49 @@ S32 LLPrimitive::parseTEMessage(LLMessageSystem* mesgsys, char const* block_name
tec.face_count = 0;
return retval;
}
+ else if (tec.size >= LLTEContents::MAX_TE_BUFFER)
+ {
+ LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL;
+ tec.size = LLTEContents::MAX_TE_BUFFER - 1;
+ }
- if (block_num < 0)
- {
- mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, 0, LLTEContents::MAX_TE_BUFFER);
- }
- else
- {
- mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, block_num, LLTEContents::MAX_TE_BUFFER);
- }
+ // if block_num < 0 ask for block 0
+ mesgsys->getBinaryDataFast(block_name, _PREHASH_TextureEntry, tec.packed_buffer, 0, std::max(block_num, 0), LLTEContents::MAX_TE_BUFFER - 1);
-
+ // The last field is not zero terminated.
+ // Rather than special case the upack functions. Just make it 0x00 terminated.
+ tec.packed_buffer[tec.size] = 0x00;
+ ++tec.size;
tec.face_count = llmin((U32)getNumTEs(),(U32)LLTEContents::MAX_TES);
U8 *cur_ptr = tec.packed_buffer;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_data, 16, tec.face_count, MVT_LLUUID);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.colors, 4, tec.face_count, MVT_U8);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_s, 4, tec.face_count, MVT_F32);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.scale_t, 4, tec.face_count, MVT_F32);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_s, 2, tec.face_count, MVT_S16Array);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.offset_t, 2, tec.face_count, MVT_S16Array);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.image_rot, 2, tec.face_count, MVT_S16Array);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.bump, 1, tec.face_count, MVT_U8);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.media_flags, 1, tec.face_count, MVT_U8);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)tec.glow, 1, tec.face_count, MVT_U8);
-
- if (cur_ptr < tec.packed_buffer + tec.size)
- {
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, tec.packed_buffer+tec.size, (U8 *)material_data, 16, tec.face_count, MVT_LLUUID);
- }
- else
- {
- memset(material_data, 0, sizeof(material_data));
+ LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffere sized: " << tec.size << LL_ENDL;
+ U8 *buffer_end = tec.packed_buffer + tec.size;
+
+ if (!( unpack_TEField<LLUUID>(tec.image_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID) &&
+ unpack_TEField<LLColor4U>(tec.colors, tec.face_count, cur_ptr, buffer_end, MVT_U8) &&
+ unpack_TEField<F32>(tec.scale_s, tec.face_count, cur_ptr, buffer_end, MVT_F32) &&
+ unpack_TEField<F32>(tec.scale_t, tec.face_count, cur_ptr, buffer_end, MVT_F32) &&
+ unpack_TEField<S16>(tec.offset_s, tec.face_count, cur_ptr, buffer_end, MVT_S16) &&
+ unpack_TEField<S16>(tec.offset_t, tec.face_count, cur_ptr, buffer_end, MVT_S16) &&
+ unpack_TEField<S16>(tec.image_rot, tec.face_count, cur_ptr, buffer_end, MVT_S16) &&
+ unpack_TEField<U8>(tec.bump, tec.face_count, cur_ptr, buffer_end, MVT_U8) &&
+ unpack_TEField<U8>(tec.media_flags, tec.face_count, cur_ptr, buffer_end, MVT_U8) &&
+ unpack_TEField<U8>(tec.glow, tec.face_count, cur_ptr, buffer_end, MVT_U8)))
+ {
+ LL_WARNS("TEXTUREENTRY") << "Failure parsing Texture Entry Message due to malformed TE Field! Dropping changes on the floor. " << LL_ENDL;
+ return 0;
+ }
+
+ if (cur_ptr >= buffer_end || !unpack_TEField<material_id_type>(material_data, tec.face_count, cur_ptr, buffer_end, MVT_LLUUID))
+ {
+ memset((void*)material_data, 0, sizeof(material_data));
}
for (U32 i = 0; i < tec.face_count; i++)
{
- tec.material_ids[i].set(&material_data[i * 16]);
+ tec.material_ids[i].set(&(material_data[i]));
}
retval = 1;
@@ -1375,7 +1434,6 @@ S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec)
S32 retval = 0;
LLColor4 color;
- LLColor4U coloru;
for (U32 i = 0; i < tec.face_count; i++)
{
LLUUID& req_id = ((LLUUID*)tec.image_data)[i];
@@ -1388,20 +1446,15 @@ S32 LLPrimitive::applyParsedTEMessage(LLTEContents& tec)
retval |= setTEGlow(i, (F32)tec.glow[i] / (F32)0xFF);
retval |= setTEMaterialID(i, tec.material_ids[i]);
- coloru = LLColor4U(tec.colors + 4*i);
-
// Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
// as all zeros. However, the subtraction and addition must be done in unsigned
// byte space, not in float space, otherwise off-by-one errors occur. JC
- color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f;
- color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f;
- color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f;
- color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f;
+ color.mV[VRED] = F32(255 - tec.colors[i].mV[VRED]) / 255.f;
+ color.mV[VGREEN] = F32(255 - tec.colors[i].mV[VGREEN]) / 255.f;
+ color.mV[VBLUE] = F32(255 - tec.colors[i].mV[VBLUE]) / 255.f;
+ color.mV[VALPHA] = F32(255 - tec.colors[i].mV[VALPHA]) / 255.f;
retval |= setTEColor(i, color);
-
-
-
}
return retval;
@@ -1423,24 +1476,32 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
const U32 MAX_TES = 45;
// Avoid construction of 32 UUIDs per call
- static LLUUID image_ids[MAX_TES];
static LLMaterialID material_ids[MAX_TES];
- U8 image_data[MAX_TES*16];
- U8 colors[MAX_TES*4];
- F32 scale_s[MAX_TES];
- F32 scale_t[MAX_TES];
- S16 offset_s[MAX_TES];
- S16 offset_t[MAX_TES];
- S16 image_rot[MAX_TES];
- U8 bump[MAX_TES];
- U8 media_flags[MAX_TES];
- U8 glow[MAX_TES];
- U8 material_data[MAX_TES*16];
-
- const U32 MAX_TE_BUFFER = 4096;
- U8 packed_buffer[MAX_TE_BUFFER];
- U8 *cur_ptr = packed_buffer;
+ const U32 MAX_TE_BUFFER = 4096;
+ U8 packed_buffer[MAX_TE_BUFFER];
+ memset((void*)packed_buffer, 0, MAX_TE_BUFFER);
+
+ LLUUID image_data[MAX_TES];
+ LLColor4U colors[MAX_TES];
+ F32 scale_s[MAX_TES];
+ F32 scale_t[MAX_TES];
+ S16 offset_s[MAX_TES];
+ S16 offset_t[MAX_TES];
+ S16 image_rot[MAX_TES];
+ U8 bump[MAX_TES];
+ U8 media_flags[MAX_TES];
+ U8 glow[MAX_TES];
+ material_id_type material_data[MAX_TES];
+
+ memset((void*)scale_s, 0, sizeof(scale_s));
+ memset((void*)scale_t, 0, sizeof(scale_t));
+ memset((void*)offset_s, 0, sizeof(offset_s));
+ memset((void*)offset_t, 0, sizeof(offset_t));
+ memset((void*)image_rot, 0, sizeof(image_rot));
+ memset((void*)bump, 0, sizeof(bump));
+ memset((void*)media_flags, 0, sizeof(media_flags));
+ memset((void*)glow, 0, sizeof(glow));
S32 size;
U32 face_count = 0;
@@ -1456,50 +1517,52 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
{
return retval;
}
+ else if (size >= MAX_TE_BUFFER)
+ {
+ LL_WARNS("TEXTUREENTRY") << "Excessive buffer size detected in Texture Entry! Truncating." << LL_ENDL;
+ size = MAX_TE_BUFFER - 1;
+ }
+ // The last field is not zero terminated.
+ // Rather than special case the upack functions. Just make it 0x00 terminated.
+ packed_buffer[size] = 0x00;
+ ++size;
face_count = llmin((U32) getNumTEs(), MAX_TES);
U32 i;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_data, 16, face_count, MVT_LLUUID);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)colors, 4, face_count, MVT_U8);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_s, 4, face_count, MVT_F32);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)scale_t, 4, face_count, MVT_F32);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_s, 2, face_count, MVT_S16Array);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)offset_t, 2, face_count, MVT_S16Array);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)image_rot, 2, face_count, MVT_S16Array);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)bump, 1, face_count, MVT_U8);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)media_flags, 1, face_count, MVT_U8);
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)glow, 1, face_count, MVT_U8);
- if (cur_ptr < packed_buffer + size)
- {
- cur_ptr++;
- cur_ptr += unpackTEField(cur_ptr, packed_buffer+size, (U8 *)material_data, 16, face_count, MVT_LLUUID);
- }
- else
+ U8 *cur_ptr = packed_buffer;
+ LL_DEBUGS("TEXTUREENTRY") << "Texture Entry with buffer sized: " << size << LL_ENDL;
+ U8 *buffer_end = packed_buffer + size;
+
+ if (!( unpack_TEField<LLUUID>(image_data, face_count, cur_ptr, buffer_end, MVT_LLUUID) &&
+ unpack_TEField<LLColor4U>(colors, face_count, cur_ptr, buffer_end, MVT_U8) &&
+ unpack_TEField<F32>(scale_s, face_count, cur_ptr, buffer_end, MVT_F32) &&
+ unpack_TEField<F32>(scale_t, face_count, cur_ptr, buffer_end, MVT_F32) &&
+ unpack_TEField<S16>(offset_s, face_count, cur_ptr, buffer_end, MVT_S16) &&
+ unpack_TEField<S16>(offset_t, face_count, cur_ptr, buffer_end, MVT_S16) &&
+ unpack_TEField<S16>(image_rot, face_count, cur_ptr, buffer_end, MVT_S16) &&
+ unpack_TEField<U8>(bump, face_count, cur_ptr, buffer_end, MVT_U8) &&
+ unpack_TEField<U8>(media_flags, face_count, cur_ptr, buffer_end, MVT_U8) &&
+ unpack_TEField<U8>(glow, face_count, cur_ptr, buffer_end, MVT_U8)))
+ {
+ LL_WARNS("TEXTUREENTRY") << "Failure parsing Texture Entry Message due to malformed TE Field! Dropping changes on the floor. " << LL_ENDL;
+ return 0;
+ }
+
+ if (cur_ptr >= buffer_end || !unpack_TEField<material_id_type>(material_data, face_count, cur_ptr, buffer_end, MVT_LLUUID))
{
- memset(material_data, 0, sizeof(material_data));
+ memset((void*)material_data, 0, sizeof(material_data));
}
for (i = 0; i < face_count; i++)
{
- memcpy(image_ids[i].mData,&image_data[i*16],16); /* Flawfinder: ignore */
- material_ids[i].set(&material_data[i * 16]);
+ material_ids[i].set(&(material_data[i]));
}
LLColor4 color;
- LLColor4U coloru;
for (i = 0; i < face_count; i++)
{
- retval |= setTETexture(i, image_ids[i]);
+ retval |= setTETexture(i, ((LLUUID*)image_data)[i]);
retval |= setTEScale(i, scale_s[i], scale_t[i]);
retval |= setTEOffset(i, (F32)offset_s[i] / (F32)0x7FFF, (F32) offset_t[i] / (F32) 0x7FFF);
retval |= setTERotation(i, ((F32)image_rot[i] / TEXTURE_ROTATION_PACK_FACTOR) * F_TWO_PI);
@@ -1507,15 +1570,14 @@ S32 LLPrimitive::unpackTEMessage(LLDataPacker &dp)
retval |= setTEMediaTexGen(i, media_flags[i]);
retval |= setTEGlow(i, (F32)glow[i] / (F32)0xFF);
retval |= setTEMaterialID(i, material_ids[i]);
- coloru = LLColor4U(colors + 4*i);
// Note: This is an optimization to send common colors (1.f, 1.f, 1.f, 1.f)
// as all zeros. However, the subtraction and addition must be done in unsigned
// byte space, not in float space, otherwise off-by-one errors occur. JC
- color.mV[VRED] = F32(255 - coloru.mV[VRED]) / 255.f;
- color.mV[VGREEN] = F32(255 - coloru.mV[VGREEN]) / 255.f;
- color.mV[VBLUE] = F32(255 - coloru.mV[VBLUE]) / 255.f;
- color.mV[VALPHA] = F32(255 - coloru.mV[VALPHA]) / 255.f;
+ color.mV[VRED] = F32(255 - colors[i].mV[VRED]) / 255.f;
+ color.mV[VGREEN] = F32(255 - colors[i].mV[VGREEN]) / 255.f;
+ color.mV[VBLUE] = F32(255 - colors[i].mV[VBLUE]) / 255.f;
+ color.mV[VALPHA] = F32(255 - colors[i].mV[VALPHA]) / 255.f;
retval |= setTEColor(i, color);
}
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index b1f8112223..309b18faa9 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -330,8 +330,8 @@ struct LLTEContents
{
static const U32 MAX_TES = 45;
- U8 image_data[MAX_TES*16];
- U8 colors[MAX_TES*4];
+ LLUUID image_data[MAX_TES];
+ LLColor4U colors[MAX_TES];
F32 scale_s[MAX_TES];
F32 scale_t[MAX_TES];
S16 offset_s[MAX_TES];
@@ -423,7 +423,6 @@ public:
void copyTEs(const LLPrimitive *primitive);
S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const;
- S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type);
BOOL packTEMessage(LLMessageSystem *mesgsys) const;
BOOL packTEMessage(LLDataPacker &dp) const;
S32 unpackTEMessage(LLMessageSystem* mesgsys, char const* block_name, const S32 block_num); // Variable num of blocks
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index c7f85aec21..b49b14615f 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -1095,8 +1095,7 @@ void LLGLManager::initExtensions()
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);
- mHasDepthClamp = FALSE;
+ 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
mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts);
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 08c9dd8769..2f1ce0eec9 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -970,6 +970,19 @@ void LLGLSLShader::bind()
}
}
+void LLGLSLShader::bind(bool rigged)
+{
+ if (rigged)
+ {
+ llassert(mRiggedVariant);
+ mRiggedVariant->bind();
+ }
+ else
+ {
+ bind();
+ }
+}
+
void LLGLSLShader::unbind()
{
LL_PROFILE_ZONE_SCOPED;
diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h
index 3b23cf1b28..6fdb789087 100644
--- a/indra/llrender/llglslshader.h
+++ b/indra/llrender/llglslshader.h
@@ -230,6 +230,8 @@ public:
BOOL link(BOOL suppress_errors = FALSE);
void bind();
+ //helper to conditionally bind mRiggedVariant instead of this
+ void bind(bool rigged);
void unbind();
// Unbinds any previously bound shader by explicitly binding no shader.
@@ -267,7 +269,8 @@ public:
LLShaderFeatures mFeatures;
std::vector< std::pair< std::string, GLenum > > mShaderFiles;
std::string mName;
- boost::unordered_map<std::string, std::string> mDefines;
+ typedef std::unordered_map<std::string, std::string> defines_map_t;
+ defines_map_t mDefines;
//statistcis for profiling shader performance
U32 mTimerQuery;
@@ -285,6 +288,9 @@ public:
std::vector<U32> mTextureMagFilter;
std::vector<U32> mTextureMinFilter;
+ // this pointer should be set to whichever shader represents this shader's rigged variant
+ LLGLSLShader* mRiggedVariant = nullptr;
+
private:
void unloadInternal();
};
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 894eb8c773..ed0e3fb345 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -172,19 +172,31 @@ BOOL is_little_endian()
return (*c == 0x78) ;
}
+LLImageGLThread* LLImageGLThread::sInstance = nullptr;
+
//static
void LLImageGL::initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha /* = false */)
{
LL_PROFILE_ZONE_SCOPED;
sSkipAnalyzeAlpha = skip_analyze_alpha;
- LLImageGLThread::createInstance(window);
+ LLImageGLThread::sInstance = new LLImageGLThread(window);
+ LLImageGLThread::sInstance->start();
+}
+
+//static
+void LLImageGL::updateClass()
+{
+ LL_PROFILE_ZONE_SCOPED;
+ LLImageGLThread::sInstance->executeCallbacks();
}
//static
void LLImageGL::cleanupClass()
{
LL_PROFILE_ZONE_SCOPED;
- LLImageGLThread::deleteSingleton();
+ LLImageGLThread::sInstance->mFunctionQueue.close();
+ delete LLImageGLThread::sInstance;
+ LLImageGLThread::sInstance = nullptr;
}
//static
@@ -492,9 +504,6 @@ void LLImageGL::init(BOOL usemipmaps)
#endif
mCategory = -1;
-
- // Sometimes we have to post work for the main thread.
- mMainQueue = LL::WorkQueue::getInstance("mainloop");
}
void LLImageGL::cleanup()
@@ -1527,7 +1536,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
}
//if we're on the image loading thread, be sure to delete old_texname and update mTexName on the main thread
- if (! on_main_thread())
+ if (LLImageGLThread::sInstance != nullptr &&
+ LLThread::currentID() == LLImageGLThread::sInstance->getID())
{
{
LL_PROFILE_ZONE_NAMED("cglt - sync");
@@ -1544,9 +1554,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
}
ref();
- LL::WorkQueue::postMaybe(
- mMainQueue,
- [=]()
+ LLImageGLThread::sInstance->postCallback([=]()
{
LL_PROFILE_ZONE_NAMED("cglt - delete callback");
if (old_texname != 0)
@@ -2251,11 +2259,7 @@ void LLImageGL::resetCurTexSizebar()
*/
LLImageGLThread::LLImageGLThread(LLWindow* window)
- // We want exactly one thread, but a very large capacity: we never want
- // anyone, especially inner-loop render code, to have to block on post()
- // because we're full.
- : ThreadPool("LLImageGL", 1, 1024*1024)
- , mWindow(window)
+ : LLThread("LLImageGL"), mWindow(window)
{
LL_PROFILE_ZONE_SCOPED;
mFinished = false;
@@ -2264,6 +2268,61 @@ LLImageGLThread::LLImageGLThread(LLWindow* window)
ThreadPool::start();
}
+// post a function to be executed on the LLImageGL background thread
+
+bool LLImageGLThread::post(const std::function<void()>& func)
+{
+ try
+ {
+ mFunctionQueue.post(func);
+ }
+ catch (LLThreadSafeQueueInterrupt e)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//post a callback to be executed on the main thread
+
+bool LLImageGLThread::postCallback(const std::function<void()>& callback)
+{
+ try
+ {
+ if (!mCallbackQueue.tryPost(callback))
+ {
+ mPendingCallbackQ.push(callback);
+ }
+ }
+ catch (LLThreadSafeQueueInterrupt e)
+ {
+ //thread is closing, drop request
+ return false;
+ }
+
+ return true;
+}
+
+void LLImageGLThread::executeCallbacks()
+{
+ LL_PROFILE_ZONE_SCOPED;
+ //executed from main thread
+ mCallbackQueue.runPending();
+
+ while (!mPendingCallbackQ.empty())
+ {
+ if (mCallbackQueue.tryPost(mPendingCallbackQ.front()))
+ {
+ mPendingCallbackQ.pop();
+ }
+ else
+ {
+ break;
+ }
+ }
+}
+
void LLImageGLThread::run()
{
LL_PROFILE_ZONE_SCOPED;
@@ -2271,7 +2330,7 @@ void LLImageGLThread::run()
// WorkQueue, likewise cleanup afterwards.
mWindow->makeContextCurrent(mContext);
gGL.init();
- ThreadPool::run();
+ mFunctionQueue.runUntilClose();
gGL.shutdown();
mWindow->destroySharedContext(mContext);
}
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index ae773bb362..bb46dbc639 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -37,7 +37,6 @@
#include "llunits.h"
#include "llthreadsafequeue.h"
#include "llrender.h"
-#include "threadpool.h"
#include "workqueue.h"
class LLTextureAtlas ;
@@ -199,7 +198,6 @@ private:
void freePickMask();
LLPointer<LLImageRaw> mSaveData; // used for destroyGL/restoreGL
- LL::WorkQueue::weak_t mMainQueue;
U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel
U16 mPickMaskWidth;
U16 mPickMaskHeight;
@@ -273,6 +271,7 @@ public:
public:
static void initClass(LLWindow* window, S32 num_catagories, BOOL skip_analyze_alpha = false);
+ static void updateClass();
static void cleanupClass() ;
private:
@@ -308,24 +307,34 @@ public:
};
-class LLImageGLThread : public LLSimpleton<LLImageGLThread>, LL::ThreadPool
+class LLImageGLThread : public LLThread
{
public:
LLImageGLThread(LLWindow* window);
// post a function to be executed on the LLImageGL background thread
- template <typename CALLABLE>
- bool post(CALLABLE&& func)
- {
- return getQueue().postIfOpen(std::forward<CALLABLE>(func));
- }
+ bool post(const std::function<void()>& func);
+
+ //post a callback to be executed on the main thread
+ bool postCallback(const std::function<void()>& callback);
+
+ void executeCallbacks();
void run() override;
-private:
+ // Work Queue for background thread
+ LL::WorkQueue mFunctionQueue;
+
+ // Work Queue for main thread (run from updateClass)
+ LL::WorkQueue mCallbackQueue;
+
LLWindow* mWindow;
void* mContext = nullptr;
LLAtomicBool mFinished;
+
+ std::queue<std::function<void()>> mPendingCallbackQ;
+
+ static LLImageGLThread* sInstance;
};
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index aad04beea2..0c180ed50d 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -1283,7 +1283,7 @@ void LLRender::syncLightState()
void LLRender::syncMatrices()
{
- static const U32 name[] =
+ static const U32 name[] =
{
LLShaderMgr::MODELVIEW_MATRIX,
LLShaderMgr::PROJECTION_MATRIX,
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index e8c6295930..a9a4314afa 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -165,6 +165,7 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
if (features->hasObjectSkinning)
{
+ shader->mRiggedVariant = shader;
if (!shader->attachVertexObject("avatar/objectSkinV.glsl"))
{
return FALSE;
@@ -599,7 +600,7 @@ void LLShaderMgr::dumpObjectLog(GLhandleARB ret, BOOL warns, const std::string&
}
}
-GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines, S32 texture_index_channels)
+GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines, S32 texture_index_channels)
{
// endsure work-around for missing GLSL funcs gets propogated to feature shader files (e.g. srgbF.glsl)
@@ -774,7 +775,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
if (defines)
{
- for (boost::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter)
+ for (std::unordered_map<std::string,std::string>::iterator iter = defines->begin(); iter != defines->end(); ++iter)
{
std::string define = "#define " + iter->first + " " + iter->second + "\n";
extra_code_text[extra_code_count++] = (GLcharARB *) strdup(define.c_str());
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 3908efd4ec..67c0d6ab10 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -264,7 +264,7 @@ public:
void dumpShaderSource(U32 shader_code_count, GLcharARB** shader_code_text);
BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE);
BOOL validateProgramObject(GLhandleARB obj);
- GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, boost::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
+ GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::unordered_map<std::string, std::string>* defines = NULL, S32 texture_index_channels = -1);
// Implemented in the application to actually point to the shader directory.
virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual
diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp
index 5ea07ddcb1..46654cc5b9 100644
--- a/indra/llrender/llvertexbuffer.cpp
+++ b/indra/llrender/llvertexbuffer.cpp
@@ -157,12 +157,12 @@ LLVBOPool::LLVBOPool(U32 vboUsage, U32 vboType)
std::fill(mMissCount.begin(), mMissCount.end(), 0);
}
-volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
+U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
{
LL_PROFILE_ZONE_SCOPED
llassert(vbo_block_size(size) == size);
- volatile U8* ret = NULL;
+ U8* ret = NULL;
U32 i = vbo_block_index(size);
@@ -256,7 +256,7 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
return ret;
}
-void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
+void LLVBOPool::release(U32 name, U8* buffer, U32 size)
{
llassert(vbo_block_size(size) == size);
@@ -749,7 +749,7 @@ void LLVertexBuffer::drawRangeFast(U32 mode, U32 start, U32 end, U32 count, U32
mMappable = false;
gGL.syncMatrices();
- U16* idx = ((U16*)(U8*)mAlignedIndexOffset) + indices_offset;
+ U16* idx = ((U16*)getIndicesPointer()) + indices_offset;
LL_PROFILER_GPU_ZONEC("gl.DrawRangeElements", 0xFFFF00)
glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT,
@@ -1539,7 +1539,7 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count)
// Map for data access
-volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
+U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)
{
LL_PROFILE_ZONE_SCOPED;
bindGLBuffer(true);
@@ -1601,7 +1601,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
}
else
{
- volatile U8* src = NULL;
+ U8* src = NULL;
waitFence();
if (gGLManager.mHasMapBufferRange)
{
@@ -1660,7 +1660,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
llassert(src != NULL);
- mMappedData = LL_NEXT_ALIGNED_ADDRESS<volatile U8>(src);
+ mMappedData = LL_NEXT_ALIGNED_ADDRESS<U8>(src);
mAlignedOffset = mMappedData - src;
stop_glerror();
@@ -1716,7 +1716,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo
}
-volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
+U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)
{
LL_PROFILE_ZONE_SCOPED;
bindGLIndices(true);
@@ -1786,7 +1786,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range
}
else
{
- volatile U8* src = NULL;
+ U8* src = NULL;
waitFence();
if (gGLManager.mHasMapBufferRange)
{
@@ -2068,7 +2068,7 @@ template <class T,S32 type> struct VertexBufferStrider
{
if (type == LLVertexBuffer::TYPE_INDEX)
{
- volatile U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
+ U8* ptr = vbo.mapIndexBuffer(index, count, map_range);
if (ptr == NULL)
{
@@ -2084,7 +2084,7 @@ template <class T,S32 type> struct VertexBufferStrider
{
S32 stride = LLVertexBuffer::sTypeSize[type];
- volatile U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
+ U8* ptr = vbo.mapVertexBuffer(type, index, count, map_range);
if (ptr == NULL)
{
@@ -2454,29 +2454,37 @@ void LLVertexBuffer::setBuffer(U32 data_mask)
void LLVertexBuffer::setBufferFast(U32 data_mask)
{
- //set up pointers if the data mask is different ...
- bool setup = (sLastMask != data_mask);
+ if (useVBOs())
+ {
+ //set up pointers if the data mask is different ...
+ bool setup = (sLastMask != data_mask);
-
- const bool bindBuffer = bindGLBufferFast();
- const bool bindIndices = bindGLIndicesFast();
+ const bool bindBuffer = bindGLBufferFast();
+ const bool bindIndices = bindGLIndicesFast();
- setup = setup || bindBuffer || bindIndices;
+ setup = setup || bindBuffer || bindIndices;
+
+ setupClientArrays(data_mask);
- setupClientArrays(data_mask);
-
- if (data_mask && setup)
+ if (data_mask && setup)
+ {
+ setupVertexBufferFast(data_mask);
+ sSetCount++;
+ }
+ }
+ else
{
- setupVertexBufferFast(data_mask);
- sSetCount++;
+ //fallback to slow path when not using VBOs
+ setBuffer(data_mask);
}
}
+
// virtual (default)
void LLVertexBuffer::setupVertexBuffer(U32 data_mask)
{
stop_glerror();
- volatile U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
+ U8* base = useVBOs() ? (U8*) mAlignedOffset : mMappedData;
if (gDebugGL && ((data_mask & mTypeMask) != data_mask))
{
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 1b400b3aad..baf8407fc6 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -64,10 +64,10 @@ public:
const U32 mType;
//size MUST be a power of 2
- volatile U8* allocate(U32& name, U32 size, bool for_seed = false);
+ U8* allocate(U32& name, U32 size, bool for_seed = false);
//size MUST be the size provided to allocate that returned the given name
- void release(U32 name, volatile U8* buffer, U32 size);
+ void release(U32 name, U8* buffer, U32 size);
//batch allocate buffers to be provided to the application on demand
void seedPool();
@@ -82,7 +82,7 @@ public:
{
public:
U32 mGLName;
- volatile U8* mClientData;
+ U8* mClientData;
};
typedef std::list<Record> record_list_t;
@@ -234,8 +234,8 @@ public:
LLVertexBuffer(U32 typemask, S32 usage);
// map for data access
- volatile U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
- volatile U8* mapIndexBuffer(S32 index, S32 count, bool map_range);
+ U8* mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range);
+ U8* mapIndexBuffer(S32 index, S32 count, bool map_range);
void bindForFeedback(U32 channel, U32 type, U32 index, U32 count);
@@ -278,14 +278,14 @@ public:
S32 getNumVerts() const { return mNumVerts; }
S32 getNumIndices() const { return mNumIndices; }
- volatile U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
- volatile U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
+ U8* getIndicesPointer() const { return useVBOs() ? (U8*) mAlignedIndexOffset : mMappedIndexData; }
+ U8* getVerticesPointer() const { return useVBOs() ? (U8*) mAlignedOffset : mMappedData; }
U32 getTypeMask() const { return mTypeMask; }
bool hasDataType(S32 type) const { return ((1 << type) & getTypeMask()); }
S32 getSize() const;
S32 getIndicesSize() const { return mIndicesSize; }
- volatile U8* getMappedData() const { return mMappedData; }
- volatile U8* getMappedIndices() const { return mMappedIndexData; }
+ U8* getMappedData() const { return mMappedData; }
+ U8* getMappedIndices() const { return mMappedIndexData; }
S32 getOffset(S32 type) const { return mOffsets[type]; }
S32 getUsage() const { return mUsage; }
bool isWriteable() const { return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? true : false; }
@@ -318,8 +318,8 @@ protected:
U32 mGLIndices; // GL IBO handle
U32 mGLArray; // GL VAO handle
- volatile U8* mMappedData; // pointer to currently mapped data (NULL if unmapped)
- volatile U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped)
+ U8* mMappedData; // pointer to currently mapped data (NULL if unmapped)
+ U8* mMappedIndexData; // pointer to currently mapped indices (NULL if unmapped)
U32 mMappedDataUsingVBOs : 1;
U32 mMappedIndexDataUsingVBOs : 1;
diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp
index 52dc908655..bcc653a602 100644
--- a/indra/llui/llcombobox.cpp
+++ b/indra/llui/llcombobox.cpp
@@ -1037,6 +1037,43 @@ void LLComboBox::prearrangeList(std::string filter)
}
}
+
+//============================================================================
+// ll::ui::SearchableControl functions
+
+//virtual
+std::string LLComboBox::_getSearchText() const
+{
+ std::string res;
+ if (mList)
+ {
+ // getAllData returns a full copy of content, might be a
+ // better option to implement an mList->getSearchText(column)
+ std::vector<LLScrollListItem*> data = mList->getAllData();
+ std::vector<LLScrollListItem*>::iterator iter = data.begin();
+ while (iter != data.end())
+ {
+ LLScrollListCell* cell = (*iter)->getColumn(0);
+ if (cell)
+ {
+ std::string whitelist_url = cell->getValue().asString();
+ res += cell->getValue().asString();
+ }
+ iter++;
+ }
+ }
+ return res + getToolTip();
+}
+
+//virtual
+void LLComboBox::onSetHighlight() const
+{
+ if (mButton)
+ {
+ mButton->ll::ui::SearchableControl::setHighlighted(ll::ui::SearchableControl::getHighlighted());
+ }
+}
+
//============================================================================
// LLCtrlListInterface functions
diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h
index 4af3313162..e17d6cdfb4 100644
--- a/indra/llui/llcombobox.h
+++ b/indra/llui/llcombobox.h
@@ -44,7 +44,9 @@ class LLFontGL;
class LLViewBorder;
class LLComboBox
-: public LLUICtrl, public LLCtrlListInterface
+: public LLUICtrl
+, public LLCtrlListInterface
+, public ll::ui::SearchableControl
{
public:
typedef enum e_preferred_position
@@ -100,6 +102,9 @@ protected:
void initFromParams(const Params&);
void prearrangeList(std::string filter = "");
+ virtual std::string _getSearchText() const;
+ virtual void onSetHighlight() const;
+
public:
// LLView interface
virtual void onFocusLost();
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index b1123d27e5..1c4860aa99 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -84,7 +84,6 @@
#include <sstream>
#include <boost/utility.hpp>
-#include <boost/shared_ptr.hpp>
#include <boost/type_traits.hpp>
#include <boost/signals2.hpp>
#include <boost/range.hpp>
@@ -131,7 +130,7 @@ public:
typedef boost::function<void (const LLSD&, const LLSD&)> LLNotificationResponder;
-typedef boost::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr;
+typedef std::shared_ptr<LLNotificationResponderInterface> LLNotificationResponderPtr;
typedef LLFunctorRegistry<LLNotificationResponder> LLNotificationFunctorRegistry;
typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegistration;
@@ -276,19 +275,19 @@ private:
bool mInvertSetting;
};
-typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
+typedef std::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
struct LLNotificationTemplate;
// we want to keep a map of these by name, and it's best to manage them
// with smart pointers
-typedef boost::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr;
+typedef std::shared_ptr<LLNotificationTemplate> LLNotificationTemplatePtr;
struct LLNotificationVisibilityRule;
-typedef boost::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRulePtr;
+typedef std::shared_ptr<LLNotificationVisibilityRule> LLNotificationVisibilityRulePtr;
/**
* @class LLNotification
@@ -745,6 +744,10 @@ public:
{}
virtual ~LLNotificationChannelBase()
{
+ // explicit cleanup for easier issue detection
+ mChanged.disconnect_all_slots();
+ mPassedFilter.disconnect_all_slots();
+ mFailedFilter.disconnect_all_slots();
mItems.clear();
}
// you can also connect to a Channel, so you can be notified of
diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h
index f9f7641de6..4bab377626 100644
--- a/indra/llui/llnotificationslistener.h
+++ b/indra/llui/llnotificationslistener.h
@@ -31,7 +31,6 @@
#include "lleventapi.h"
#include "llnotificationptr.h"
-#include <boost/shared_ptr.hpp>
#include <map>
#include <string>
@@ -61,7 +60,7 @@ private:
static LLSD asLLSD(LLNotificationPtr);
class Forwarder;
- typedef std::map<std::string, boost::shared_ptr<Forwarder> > ForwarderMap;
+ typedef std::map<std::string, std::shared_ptr<Forwarder> > ForwarderMap;
ForwarderMap mForwarders;
LLNotifications & mNotifications;
};
diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h
index 20cbc89ede..a8902486e4 100644
--- a/indra/llui/llnotificationtemplate.h
+++ b/indra/llui/llnotificationtemplate.h
@@ -31,7 +31,7 @@
#include "llinitparam.h"
#include "llnotifications.h"
-typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
+typedef std::shared_ptr<LLNotificationForm> LLNotificationFormPtr;
// This is the class of object read from the XML file (notifications.xml,
// from the appropriate local language directory).
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index 4274c81645..3b0789892f 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -184,6 +184,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
mFontShadow(p.font_shadow),
mPopupMenuHandle(),
mReadOnly(p.read_only),
+ mSkipTripleClick(false),
mSkipLinkUnderline(p.skip_link_underline),
mSpellCheck(p.spellcheck),
mSpellCheckStart(-1),
@@ -1017,6 +1018,11 @@ BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask)
// handle triple click
if (!mTripleClickTimer.hasExpired())
{
+ if (mSkipTripleClick)
+ {
+ return TRUE;
+ }
+
S32 real_line = getLineNumFromDocIndex(mCursorPos, false);
S32 line_start = -1;
S32 line_end = -1;
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 4e966b7cef..2e2e1b9833 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -699,7 +699,7 @@ protected:
bool mPlainText; // didn't use Image or Icon segments
bool mAutoIndent;
S32 mMaxTextByteLength; // Maximum length mText is allowed to be in bytes
-
+ bool mSkipTripleClick;
bool mSkipLinkUnderline;
// support widgets
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 134afc005b..c567451973 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -45,7 +45,9 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p)
: LLTextBase(p),
mClickedCallback(NULL),
mShowCursorHand(true)
-{}
+{
+ mSkipTripleClick = true;
+}
LLTextBox::~LLTextBox()
{}
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index e43c52c0c2..38495e1e0b 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -35,6 +35,7 @@
#include "llavatarnamecache.h"
#include "llcachename.h"
+#include "llregex.h"
#include "lltrans.h"
#include "lluicolortable.h"
#include "message.h"
@@ -181,11 +182,51 @@ bool LLUrlEntryBase::isLinkDisabled() const
return globally_disabled;
}
-bool LLUrlEntryBase::isWikiLinkCorrect(std::string url)
+bool LLUrlEntryBase::isWikiLinkCorrect(const std::string &labeled_url) const
{
- LLWString label = utf8str_to_wstring(getLabelFromWikiLink(url));
- label.erase(std::remove(label.begin(), label.end(), L'\u200B'), label.end());
- return (LLUrlRegistry::instance().hasUrl(wstring_to_utf8str(label))) ? false : true;
+ LLWString wlabel = utf8str_to_wstring(getLabelFromWikiLink(labeled_url));
+ wlabel.erase(std::remove(wlabel.begin(), wlabel.end(), L'\u200B'), wlabel.end());
+
+ // Unicode URL validation, see SL-15243
+ std::replace_if(wlabel.begin(),
+ wlabel.end(),
+ [](const llwchar &chr)
+ {
+ return (chr == L'\u2024') // "One Dot Leader"
+ || (chr == L'\uFE52') // "Small Full Stop"
+ || (chr == L'\uFF0E') // "Fullwidth Full Stop"
+ // Not a decomposition, but suficiently similar
+ || (chr == L'\u05C5'); // "Hebrew Mark Lower Dot"
+ },
+ L'\u002E'); // Dot "Full Stop"
+
+ std::replace_if(wlabel.begin(),
+ wlabel.end(),
+ [](const llwchar &chr)
+ {
+ return (chr == L'\u02D0') // "Modifier Letter Colon"
+ || (chr == L'\uFF1A') // "Fullwidth Colon"
+ || (chr == L'\uFE55'); // "Small Colon"
+ },
+ L'\u003A'); // Colon
+
+ std::replace_if(wlabel.begin(),
+ wlabel.end(),
+ [](const llwchar &chr)
+ {
+ return (chr == L'\uFF0F'); // "Fullwidth Solidus"
+ },
+ L'\u002F'); // Solidus
+
+ std::string label = wstring_to_utf8str(wlabel);
+ if ((label.find(".com") != std::string::npos
+ || label.find("www.") != std::string::npos)
+ && label.find("://") == std::string::npos)
+ {
+ label = "http://" + label;
+ }
+
+ return (LLUrlRegistry::instance().hasUrl(label)) ? false : true;
}
std::string LLUrlEntryBase::urlToLabelWithGreyQuery(const std::string &url) const
@@ -1416,7 +1457,7 @@ std::string LLUrlEntryIcon::getIcon(const std::string &url)
// Grep icon info between <icon>...</icon> tags
// matches[1] contains the icon name/path
boost::match_results<std::string::const_iterator> matches;
- mIcon = (boost::regex_match(url, matches, mPattern) && matches[1].matched)
+ mIcon = (ll_regex_match(url, matches, mPattern) && matches[1].matched)
? matches[1]
: LLStringUtil::null;
LLStringUtil::trim(mIcon);
diff --git a/indra/llui/llurlentry.h b/indra/llui/llurlentry.h
index 4af1ab5096..102e0a4fd9 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -105,7 +105,7 @@ public:
bool isLinkDisabled() const;
- bool isWikiLinkCorrect(std::string url);
+ bool isWikiLinkCorrect(const std::string &url) const;
virtual bool isSLURLvalid(const std::string &url) const { return TRUE; };
diff --git a/indra/llui/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 321a0ec5b9..bfcd970529 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -26,10 +26,10 @@
*/
#include "linden_common.h"
+#include "llregex.h"
#include "llurlregistry.h"
#include "lluriparser.h"
-#include <boost/regex.hpp>
// default dummy callback that ignores any label updates from the server
void LLUrlRegistryNullCallback(const std::string &url, const std::string &label, const std::string& icon)
@@ -108,15 +108,7 @@ static bool matchRegex(const char *text, boost::regex regex, U32 &start, U32 &en
boost::cmatch result;
bool found;
- // regex_search can potentially throw an exception, so check for it
- try
- {
- found = boost::regex_search(text, result, regex);
- }
- catch (std::runtime_error &)
- {
- return false;
- }
+ found = ll_regex_search(text, result, regex);
if (! found)
{
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index 9e9abbadff..69b23f9cf8 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -337,6 +337,11 @@ const std::string &LLDir::getDumpDir() const
return LLDir::sDumpDir;
}
+bool LLDir::dumpDirExists() const
+{
+ return !sDumpDir.empty();
+}
+
const std::string &LLDir::getPerAccountChatLogsDir() const
{
return mPerAccountChatLogsDir;
@@ -888,6 +893,11 @@ std::string LLDir::getScrubbedFileName(const std::string uncleanFileName)
return name;
}
+std::string LLDir::getDumpLogsDirPath(const std::string &file_name)
+{
+ return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "dump_logs", file_name);
+}
+
// static
std::string LLDir::getForbiddenFileChars()
{
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index 4988b9c6e3..b9a046ba33 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -90,6 +90,7 @@ class LLDir
const std::string &getLindenUserDir() const; // Location of the Linden user dir.
const std::string &getChatLogsDir() const; // Location of the chat logs dir.
const std::string &getDumpDir() const; // Location of the per-run dump dir.
+ bool dumpDirExists() const;
const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir.
const std::string &getTempDir() const; // Common temporary directory
const std::string getCacheDir(bool get_default = false) const; // Location of the cache.
@@ -174,6 +175,8 @@ class LLDir
// random filename in common temporary directory
std::string getTempFilename() const;
+ static std::string getDumpLogsDirPath(const std::string &file_name = "");
+
// For producing safe download file names from potentially unsafe ones
static std::string getScrubbedFileName(const std::string uncleanFileName);
static std::string getForbiddenFileChars();
diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp
index 3eb64e69d9..f57bf4ebc6 100644
--- a/indra/llvfs/lldiriterator.cpp
+++ b/indra/llvfs/lldiriterator.cpp
@@ -27,8 +27,8 @@
#include "lldiriterator.h"
#include "fix_macros.h"
+#include "llregex.h"
#include <boost/filesystem.hpp>
-#include <boost/regex.hpp>
namespace fs = boost::filesystem;
@@ -131,7 +131,7 @@ bool LLDirIterator::Impl::next(std::string &fname)
{
boost::smatch match;
std::string name = mIter->path().filename().string();
- found = boost::regex_match(name, match, mFilterExp);
+ found = ll_regex_match(name, match, mFilterExp);
if (found)
{
fname = name;
diff --git a/indra/llwindow/llappdelegate-objc.h b/indra/llwindow/llappdelegate-objc.h
index 0b38647b4a..ceda7ff74c 100644
--- a/indra/llwindow/llappdelegate-objc.h
+++ b/indra/llwindow/llappdelegate-objc.h
@@ -33,6 +33,7 @@
LLNonInlineTextView *inputView;
NSTimer *frameTimer;
NSString *currentInputLanguage;
+ std::string secondLogPath;
}
@property (assign) IBOutlet LLNSWindow *window;
diff --git a/indra/llwindow/llopenglview-objc.mm b/indra/llwindow/llopenglview-objc.mm
index b647085b7e..fd20f2ad15 100644
--- a/indra/llwindow/llopenglview-objc.mm
+++ b/indra/llwindow/llopenglview-objc.mm
@@ -495,7 +495,8 @@ attributedStringInfo getSegments(NSAttributedString *str)
// e.g. OS Window for upload something or Input Window...
// mModifiers instance variable is for insertText: or insertText:replacementRange: (by Pell Smit)
mModifiers = [theEvent modifierFlags];
- bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers);
+
+ bool acceptsText = mHasMarkedText ? false : callKeyDown(&eventData, keycode, mModifiers, [[theEvent characters] characterAtIndex:0]);
unichar ch;
if (acceptsText &&
!mMarkedTextAllowed &&
@@ -538,7 +539,7 @@ attributedStringInfo getSegments(NSAttributedString *str)
if (mModifiers & mask)
{
eventData.mKeyEvent = NativeKeyEventData::KEYDOWN;
- callKeyDown(&eventData, [theEvent keyCode], 0);
+ callKeyDown(&eventData, [theEvent keyCode], 0, [[theEvent characters] characterAtIndex:0]);
}
else
{
diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h
index 43d81e4d59..0edf39f6ef 100644
--- a/indra/llwindow/llwindow.h
+++ b/indra/llwindow/llwindow.h
@@ -88,11 +88,11 @@ public:
//Must be called on the same thread that called createSharedContext()
virtual void destroySharedContext(void* context) = 0;
+ virtual void toggleVSync(bool enable_vsync) = 0;
virtual BOOL setCursorPosition(LLCoordWindow position) = 0;
virtual BOOL getCursorPosition(LLCoordWindow *position) = 0;
#if LL_WINDOWS
- virtual void toggleVSync(bool enable_vsync) = 0;
virtual BOOL getCursorDelta(LLCoordCommon* delta) = 0;
#endif
virtual void showCursor() = 0;
diff --git a/indra/llwindow/llwindowheadless.h b/indra/llwindow/llwindowheadless.h
index 78c5e4bae4..410da79623 100644
--- a/indra/llwindow/llwindowheadless.h
+++ b/indra/llwindow/llwindowheadless.h
@@ -52,10 +52,10 @@ public:
void* createSharedContext() { return nullptr; }
void makeContextCurrent(void*) {}
void destroySharedContext(void*) {}
- /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;};
- /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;};
+ /*virtual*/ void toggleVSync(bool enable_vsync) { }
+ /*virtual*/ BOOL setCursorPosition(LLCoordWindow position) {return FALSE;};
+ /*virtual*/ BOOL getCursorPosition(LLCoordWindow *position) {return FALSE;};
#if LL_WINDOWS
- /*virtual*/ virtual void toggleVSync(bool enable_vsync) { }
/*virtual*/ BOOL getCursorDelta(LLCoordCommon* delta) { return FALSE; }
#endif
/*virtual*/ void showCursor() {};
diff --git a/indra/llwindow/llwindowmacosx-objc.h b/indra/llwindow/llwindowmacosx-objc.h
index 44fd4127ce..43edc0110d 100644
--- a/indra/llwindow/llwindowmacosx-objc.h
+++ b/indra/llwindow/llwindowmacosx-objc.h
@@ -131,7 +131,7 @@ void setupInputWindow(NSWindowRef window, GLViewRef view);
// These are all implemented in llwindowmacosx.cpp.
// This is largely for easier interop between Obj-C and C++ (at least in the viewer's case due to the BOOL vs. BOOL conflict)
bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask);
-bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask);
+bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wchar_t character);
void callResetKeys();
bool callUnicodeCallback(wchar_t character, unsigned int mask);
void callRightMouseDown(float *pos, unsigned int mask);
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index a74fa78388..0e37e82091 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -208,8 +208,17 @@ bool callKeyUp(NSKeyEventRef event, unsigned short key, unsigned int mask)
return retVal;
}
-bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask)
+bool callKeyDown(NSKeyEventRef event, unsigned short key, unsigned int mask, wchar_t character)
{
+ if((key == gKeyboard->inverseTranslateKey('Z')) && (character == 'y'))
+ {
+ key = gKeyboard->inverseTranslateKey('Y');
+ }
+ else if ((key == gKeyboard->inverseTranslateKey('Y')) && (character == 'z'))
+ {
+ key = gKeyboard->inverseTranslateKey('Z');
+ }
+
mRawKeyEvent = event;
bool retVal = gKeyboard->handleKeyDown(key, mask);
mRawKeyEvent = NULL;
@@ -652,17 +661,7 @@ BOOL LLWindowMacOSX::createContext(int x, int y, int width, int height, int bits
}
// Disable vertical sync for swap
- GLint frames_per_swap = 0;
- if (!enable_vsync)
- {
- frames_per_swap = 0;
- }
- else
- {
- frames_per_swap = 1;
- }
-
- CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap);
+ toggleVSync(enable_vsync);
//enable multi-threaded OpenGL
if (sUseMultGL)
@@ -1935,6 +1934,21 @@ void LLWindowMacOSX::destroySharedContext(void* context)
delete sc;
}
+void LLWindowMacOSX::toggleVSync(bool enable_vsync)
+{
+ GLint frames_per_swap = 0;
+ if (!enable_vsync)
+ {
+ frames_per_swap = 0;
+ }
+ else
+ {
+ frames_per_swap = 1;
+ }
+
+ CGLSetParameter(mContext, kCGLCPSwapInterval, &frames_per_swap);
+}
+
void LLWindowMacOSX::interruptLanguageTextInput()
{
commitCurrentPreedit(mGLView);
diff --git a/indra/llwindow/llwindowmacosx.h b/indra/llwindow/llwindowmacosx.h
index 18fa86930f..b0f339e1db 100644
--- a/indra/llwindow/llwindowmacosx.h
+++ b/indra/llwindow/llwindowmacosx.h
@@ -140,6 +140,8 @@ public:
//Must be called on the same thread that called createSharedContext()
void destroySharedContext(void* context) override;
+ void toggleVSync(bool enable_vsync) override;
+
protected:
LLWindowMacOSX(LLWindowCallbacks* callbacks,
const std::string& title, const std::string& name, int x, int y, int width, int height, U32 flags,
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index 7f8f88a749..149a92ffff 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -183,19 +183,23 @@ DWORD LLWindowWin32::sWinIMESentenceMode = IME_SMODE_AUTOMATIC;
LLCoordWindow LLWindowWin32::sWinIMEWindowPosition(-1,-1);
// The following class LLWinImm delegates Windows IMM APIs.
-// It was originally introduced to support US Windows XP, on which we needed
-// to dynamically load IMM32.DLL and use GetProcAddress to resolve its entry
-// points. Now that that's moot, we retain this wrapper only for hooks for
-// metrics.
+// We need this because some language versions of Windows,
+// e.g., US version of Windows XP, doesn't install IMM32.DLL
+// as a default, and we can't link against imm32.lib statically.
+// I believe DLL loading of this type is best suited to do
+// in a static initialization of a class. What I'm not sure is
+// whether it follows the Linden Conding Standard...
+// See http://wiki.secondlife.com/wiki/Coding_standards#Static_Members
class LLWinImm
{
public:
- static bool isAvailable() { return true; }
+ static bool isAvailable() { return sTheInstance.mHImmDll != NULL; }
public:
// Wrappers for IMM API.
static BOOL isIME(HKL hkl);
+ static HWND getDefaultIMEWnd(HWND hwnd);
static HIMC getContext(HWND hwnd);
static BOOL releaseContext(HWND hwnd, HIMC himc);
static BOOL getOpenStatus(HIMC himc);
@@ -209,96 +213,236 @@ public:
static BOOL setCompositionFont(HIMC himc, LPLOGFONTW logfont);
static BOOL setCandidateWindow(HIMC himc, LPCANDIDATEFORM candidate_form);
static BOOL notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value);
+
+private:
+ LLWinImm();
+ ~LLWinImm();
+
+private:
+ // Pointers to IMM API.
+ BOOL (WINAPI *mImmIsIME)(HKL);
+ HWND (WINAPI *mImmGetDefaultIMEWnd)(HWND);
+ HIMC (WINAPI *mImmGetContext)(HWND);
+ BOOL (WINAPI *mImmReleaseContext)(HWND, HIMC);
+ BOOL (WINAPI *mImmGetOpenStatus)(HIMC);
+ BOOL (WINAPI *mImmSetOpenStatus)(HIMC, BOOL);
+ BOOL (WINAPI *mImmGetConversionStatus)(HIMC, LPDWORD, LPDWORD);
+ BOOL (WINAPI *mImmSetConversionStatus)(HIMC, DWORD, DWORD);
+ BOOL (WINAPI *mImmGetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
+ BOOL (WINAPI *mImmSetCompostitionWindow)(HIMC, LPCOMPOSITIONFORM);
+ LONG (WINAPI *mImmGetCompositionString)(HIMC, DWORD, LPVOID, DWORD);
+ BOOL (WINAPI *mImmSetCompositionString)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD);
+ BOOL (WINAPI *mImmSetCompositionFont)(HIMC, LPLOGFONTW);
+ BOOL (WINAPI *mImmSetCandidateWindow)(HIMC, LPCANDIDATEFORM);
+ BOOL (WINAPI *mImmNotifyIME)(HIMC, DWORD, DWORD, DWORD);
+
+private:
+ HMODULE mHImmDll;
+ static LLWinImm sTheInstance;
};
+LLWinImm LLWinImm::sTheInstance;
+
+LLWinImm::LLWinImm() : mHImmDll(NULL)
+{
+ // Check system metrics
+ if ( !GetSystemMetrics( SM_IMMENABLED ) )
+ return;
+
+ mHImmDll = LoadLibraryA("Imm32");
+ if (mHImmDll != NULL)
+ {
+ mImmIsIME = (BOOL (WINAPI *)(HKL)) GetProcAddress(mHImmDll, "ImmIsIME");
+ mImmGetDefaultIMEWnd = (HWND (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetDefaultIMEWnd");
+ mImmGetContext = (HIMC (WINAPI *)(HWND)) GetProcAddress(mHImmDll, "ImmGetContext");
+ mImmReleaseContext = (BOOL (WINAPI *)(HWND, HIMC)) GetProcAddress(mHImmDll, "ImmReleaseContext");
+ mImmGetOpenStatus = (BOOL (WINAPI *)(HIMC)) GetProcAddress(mHImmDll, "ImmGetOpenStatus");
+ mImmSetOpenStatus = (BOOL (WINAPI *)(HIMC, BOOL)) GetProcAddress(mHImmDll, "ImmSetOpenStatus");
+ mImmGetConversionStatus = (BOOL (WINAPI *)(HIMC, LPDWORD, LPDWORD)) GetProcAddress(mHImmDll, "ImmGetConversionStatus");
+ mImmSetConversionStatus = (BOOL (WINAPI *)(HIMC, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmSetConversionStatus");
+ mImmGetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmGetCompositionWindow");
+ mImmSetCompostitionWindow = (BOOL (WINAPI *)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(mHImmDll, "ImmSetCompositionWindow");
+ mImmGetCompositionString= (LONG (WINAPI *)(HIMC, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmGetCompositionStringW");
+ mImmSetCompositionString= (BOOL (WINAPI *)(HIMC, DWORD, LPVOID, DWORD, LPVOID, DWORD)) GetProcAddress(mHImmDll, "ImmSetCompositionStringW");
+ mImmSetCompositionFont = (BOOL (WINAPI *)(HIMC, LPLOGFONTW)) GetProcAddress(mHImmDll, "ImmSetCompositionFontW");
+ mImmSetCandidateWindow = (BOOL (WINAPI *)(HIMC, LPCANDIDATEFORM)) GetProcAddress(mHImmDll, "ImmSetCandidateWindow");
+ mImmNotifyIME = (BOOL (WINAPI *)(HIMC, DWORD, DWORD, DWORD)) GetProcAddress(mHImmDll, "ImmNotifyIME");
+
+ if (mImmIsIME == NULL ||
+ mImmGetDefaultIMEWnd == NULL ||
+ mImmGetContext == NULL ||
+ mImmReleaseContext == NULL ||
+ mImmGetOpenStatus == NULL ||
+ mImmSetOpenStatus == NULL ||
+ mImmGetConversionStatus == NULL ||
+ mImmSetConversionStatus == NULL ||
+ mImmGetCompostitionWindow == NULL ||
+ mImmSetCompostitionWindow == NULL ||
+ mImmGetCompositionString == NULL ||
+ mImmSetCompositionString == NULL ||
+ mImmSetCompositionFont == NULL ||
+ mImmSetCandidateWindow == NULL ||
+ mImmNotifyIME == NULL)
+ {
+ // If any of the above API entires are not found, we can't use IMM API.
+ // So, turn off the IMM support. We should log some warning message in
+ // the case, since it is very unusual; these APIs are available from
+ // the beginning, and all versions of IMM32.DLL should have them all.
+ // Unfortunately, this code may be executed before initialization of
+ // the logging channel (LL_WARNS()), and we can't do it here... Yes, this
+ // is one of disadvantages to use static constraction to DLL loading.
+ FreeLibrary(mHImmDll);
+ mHImmDll = NULL;
+
+ // If we unload the library, make sure all the function pointers are cleared
+ mImmIsIME = NULL;
+ mImmGetDefaultIMEWnd = NULL;
+ mImmGetContext = NULL;
+ mImmReleaseContext = NULL;
+ mImmGetOpenStatus = NULL;
+ mImmSetOpenStatus = NULL;
+ mImmGetConversionStatus = NULL;
+ mImmSetConversionStatus = NULL;
+ mImmGetCompostitionWindow = NULL;
+ mImmSetCompostitionWindow = NULL;
+ mImmGetCompositionString = NULL;
+ mImmSetCompositionString = NULL;
+ mImmSetCompositionFont = NULL;
+ mImmSetCandidateWindow = NULL;
+ mImmNotifyIME = NULL;
+ }
+ }
+}
+
+
// static
BOOL LLWinImm::isIME(HKL hkl)
{
- return ImmIsIME(hkl);
+ if ( sTheInstance.mImmIsIME )
+ return sTheInstance.mImmIsIME(hkl);
+ return FALSE;
}
// static
HIMC LLWinImm::getContext(HWND hwnd)
{
- return ImmGetContext(hwnd);
+ if ( sTheInstance.mImmGetContext )
+ return sTheInstance.mImmGetContext(hwnd);
+ return 0;
}
//static
BOOL LLWinImm::releaseContext(HWND hwnd, HIMC himc)
{
- return ImmReleaseContext(hwnd, himc);
+ if ( sTheInstance.mImmIsIME )
+ return sTheInstance.mImmReleaseContext(hwnd, himc);
+ return FALSE;
}
// static
BOOL LLWinImm::getOpenStatus(HIMC himc)
{
- return ImmGetOpenStatus(himc);
+ if ( sTheInstance.mImmGetOpenStatus )
+ return sTheInstance.mImmGetOpenStatus(himc);
+ return FALSE;
}
// static
BOOL LLWinImm::setOpenStatus(HIMC himc, BOOL status)
{
- return ImmSetOpenStatus(himc, status);
+ if ( sTheInstance.mImmSetOpenStatus )
+ return sTheInstance.mImmSetOpenStatus(himc, status);
+ return FALSE;
}
// static
BOOL LLWinImm::getConversionStatus(HIMC himc, LPDWORD conversion, LPDWORD sentence)
{
- return ImmGetConversionStatus(himc, conversion, sentence);
+ if ( sTheInstance.mImmGetConversionStatus )
+ return sTheInstance.mImmGetConversionStatus(himc, conversion, sentence);
+ return FALSE;
}
// static
BOOL LLWinImm::setConversionStatus(HIMC himc, DWORD conversion, DWORD sentence)
{
- return ImmSetConversionStatus(himc, conversion, sentence);
+ if ( sTheInstance.mImmSetConversionStatus )
+ return sTheInstance.mImmSetConversionStatus(himc, conversion, sentence);
+ return FALSE;
}
// static
BOOL LLWinImm::getCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
{
- return ImmGetCompositionWindow(himc, form);
+ if ( sTheInstance.mImmGetCompostitionWindow )
+ return sTheInstance.mImmGetCompostitionWindow(himc, form);
+ return FALSE;
}
// static
BOOL LLWinImm::setCompositionWindow(HIMC himc, LPCOMPOSITIONFORM form)
{
- return ImmSetCompositionWindow(himc, form);
+ if ( sTheInstance.mImmSetCompostitionWindow )
+ return sTheInstance.mImmSetCompostitionWindow(himc, form);
+ return FALSE;
}
// static
LONG LLWinImm::getCompositionString(HIMC himc, DWORD index, LPVOID data, DWORD length)
{
- return ImmGetCompositionString(himc, index, data, length);
+ if ( sTheInstance.mImmGetCompositionString )
+ return sTheInstance.mImmGetCompositionString(himc, index, data, length);
+ return FALSE;
}
// static
BOOL LLWinImm::setCompositionString(HIMC himc, DWORD index, LPVOID pComp, DWORD compLength, LPVOID pRead, DWORD readLength)
{
- return ImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);
+ if ( sTheInstance.mImmSetCompositionString )
+ return sTheInstance.mImmSetCompositionString(himc, index, pComp, compLength, pRead, readLength);
+ return FALSE;
}
// static
BOOL LLWinImm::setCompositionFont(HIMC himc, LPLOGFONTW pFont)
{
- return ImmSetCompositionFont(himc, pFont);
+ if ( sTheInstance.mImmSetCompositionFont )
+ return sTheInstance.mImmSetCompositionFont(himc, pFont);
+ return FALSE;
}
// static
BOOL LLWinImm::setCandidateWindow(HIMC himc, LPCANDIDATEFORM form)
{
- return ImmSetCandidateWindow(himc, form);
+ if ( sTheInstance.mImmSetCandidateWindow )
+ return sTheInstance.mImmSetCandidateWindow(himc, form);
+ return FALSE;
}
// static
BOOL LLWinImm::notifyIME(HIMC himc, DWORD action, DWORD index, DWORD value)
{
- return ImmNotifyIME(himc, action, index, value);
+ if ( sTheInstance.mImmNotifyIME )
+ return sTheInstance.mImmNotifyIME(himc, action, index, value);
+ return FALSE;
}
+
+// ----------------------------------------------------------------------------------------
+LLWinImm::~LLWinImm()
+{
+ if (mHImmDll != NULL)
+ {
+ FreeLibrary(mHImmDll);
+ mHImmDll = NULL;
+ }
+}
+
+
class LLMonitorInfo
{
public:
@@ -408,7 +552,8 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
: LLWindow(callbacks, fullscreen, flags)
{
sMainThreadId = LLThread::currentID();
- mWindowThread = new LLWindowWin32Thread();
+ mWindowThread = new LLWindowWin32Thread(this);
+ mWindowThread->start();
//MAINT-516 -- force a load of opengl32.dll just in case windows went sideways
LoadLibrary(L"opengl32.dll");
@@ -479,6 +624,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
// Make an instance of our window then define the window class
mhInstance = GetModuleHandle(NULL);
+ mWndProc = NULL;
// Init Direct Input - needed for joystick / Spacemouse
@@ -902,13 +1048,17 @@ void LLWindowWin32::close()
// Something killed the window while we were busy destroying gl or handle somehow got broken
LL_WARNS("Window") << "Failed to destroy Window, invalid handle!" << LL_ENDL;
}
+ mWindowHandle = NULL;
+ mWindowThread->mFinished = true;
});
- // Even though the above lambda might not yet have run, we've already
- // bound mWindowHandle into it by value, which should suffice for the
- // operations we're asking. That's the last time WE should touch it.
- mWindowHandle = NULL;
- mWindowThread->close();
+
+ while (!mWindowThread->isStopped())
+ {
+ //nudge window thread
+ PostMessage(mWindowHandle, WM_USER + 0x0017, 0xB0B0, 0x1337);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
}
BOOL LLWindowWin32::isValid()
@@ -1201,7 +1351,51 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen& size, BO
<< " Fullscreen: " << mFullscreen
<< LL_ENDL;
- recreateWindow(window_rect, dw_ex_style, dw_style);
+ auto oldHandle = mWindowHandle;
+
+ //zero out mWindowHandle and mhDC before destroying window so window thread falls back to peekmessage
+ mWindowHandle = 0;
+ mhDC = 0;
+
+ if (oldHandle && !destroy_window_handler(oldHandle))
+ {
+ LL_WARNS("Window") << "Failed to properly close window before recreating it!" << LL_ENDL;
+ }
+
+ mWindowHandle = NULL;
+ mhDC = 0;
+
+ mWindowThread->post(
+ [this, window_rect, dw_ex_style, dw_style]()
+ {
+ mWindowHandle = CreateWindowEx(dw_ex_style,
+ mWindowClassName,
+ mWindowTitle,
+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
+ window_rect.left, // x pos
+ window_rect.top, // y pos
+ window_rect.right - window_rect.left, // width
+ window_rect.bottom - window_rect.top, // height
+ NULL,
+ NULL,
+ mhInstance,
+ NULL);
+
+ if (mWindowHandle)
+ {
+ mhDC = GetDC(mWindowHandle);
+ }
+ }
+ );
+
+ // HACK wait for above handle to become populated
+ // TODO: use a future
+ int count = 1024;
+ while (!mhDC && count > 0)
+ {
+ Sleep(10);
+ --count;
+ }
if (mWindowHandle)
{
@@ -1529,7 +1723,48 @@ const S32 max_format = (S32)num_formats - 1;
mhDC = 0; // Zero The Device Context
}
- recreateWindow(window_rect, dw_ex_style, dw_style);
+ auto oldHandle = mWindowHandle;
+ mWindowHandle = NULL;
+ mhDC = 0;
+
+ // Destroy The Window
+ if (oldHandle && !destroy_window_handler(oldHandle))
+ {
+ LL_WARNS("Window") << "Failed to properly close window!" << LL_ENDL;
+ }
+
+ mWindowThread->post(
+ [this, window_rect, dw_ex_style, dw_style]()
+ {
+ mWindowHandle = CreateWindowEx(dw_ex_style,
+ mWindowClassName,
+ mWindowTitle,
+ WS_CLIPSIBLINGS | WS_CLIPCHILDREN | dw_style,
+ window_rect.left, // x pos
+ window_rect.top, // y pos
+ window_rect.right - window_rect.left, // width
+ window_rect.bottom - window_rect.top, // height
+ NULL,
+ NULL,
+ mhInstance,
+ NULL);
+
+ if (mWindowHandle)
+ {
+ mhDC = GetDC(mWindowHandle);
+ }
+ }
+ );
+
+ // HACK wait for above handle to become populated
+ // TODO: use a future
+ int count = 1024;
+ while (!mhDC && count > 0)
+ {
+ PostMessage(oldHandle, WM_USER + 8, 0x1717, 0x3b3b);
+ Sleep(10);
+ --count;
+ }
if (mWindowHandle)
{
@@ -1764,7 +1999,7 @@ void* LLWindowWin32::createSharedContext()
S32 attribs[] =
{
WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
- WGL_CONTEXT_MINOR_VERSION_ARB, 2,
+ WGL_CONTEXT_MINOR_VERSION_ARB, 6,
WGL_CONTEXT_PROFILE_MASK_ARB, LLRender::sGLCoreProfile ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
WGL_CONTEXT_FLAGS_ARB, gDebugGL ? WGL_CONTEXT_DEBUG_BIT_ARB : 0,
0
@@ -2112,7 +2347,7 @@ void LLWindowWin32::gatherInput()
}
- if (mWindowThread->getQueue().size())
+ if (mWindowThread->mFunctionQueue.size() > 0)
{
LL_PROFILE_ZONE_NAMED("gi - PostMessage");
kickWindowThread();
@@ -2220,6 +2455,17 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
if (NULL != window_imp)
{
+ // Has user provided their own window callback?
+ if (NULL != window_imp->mWndProc)
+ {
+ LL_PROFILE_ZONE_NAMED("mwp - WndProc");
+ if (!window_imp->mWndProc(h_wnd, u_msg, w_param, l_param))
+ {
+ // user has handled window message
+ return 0;
+ }
+ }
+
// Juggle to make sure we can get negative positions for when
// mouse is outside window.
LLCoordWindow window_coord((S32)(S16)LOWORD(l_param), (S32)(S16)HIWORD(l_param));
@@ -4500,8 +4746,10 @@ std::vector<std::string> LLWindowWin32::getDynamicFallbackFontList()
#endif // LL_WINDOWS
-inline LLWindowWin32::LLWindowWin32Thread::LLWindowWin32Thread()
- : ThreadPool("Window Thread", 1, MAX_QUEUE_SIZE)
+inline LLWindowWin32Thread::LLWindowWin32Thread(LLWindowWin32* window)
+ : LLThread("Window Thread"),
+ mWindow(window),
+ mFunctionQueue(MAX_QUEUE_SIZE)
{
ThreadPool::start();
}
@@ -4565,7 +4813,7 @@ void LLWindowWin32::LLWindowWin32Thread::run()
{
MSG msg;
BOOL status;
- if (mhDC == 0)
+ if (mWindow->mhDC == 0)
{
LL_PROFILE_ZONE_NAMED("w32t - PeekMessage");
logger.onChange("PeekMessage(", std::hex, mWindowHandle, ")");
@@ -4592,7 +4840,11 @@ void LLWindowWin32::LLWindowWin32Thread::run()
LL_PROFILE_ZONE_NAMED("w32t - Function Queue");
logger.onChange("runPending()");
//process any pending functions
- getQueue().runPending();
+ std::function<void()> curFunc;
+ while (mFunctionQueue.tryPopBack(curFunc))
+ {
+ curFunc();
+ }
}
#if 0
@@ -4605,6 +4857,11 @@ void LLWindowWin32::LLWindowWin32Thread::run()
}
}
+void LLWindowWin32Thread::post(const std::function<void()>& func)
+{
+ mFunctionQueue.pushFront(func);
+}
+
void LLWindowWin32::post(const std::function<void()>& func)
{
mFunctionQueue.pushFront(func);
diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h
index b02815e990..8d0193abc8 100644
--- a/indra/llwindow/llwindowwin32.h
+++ b/indra/llwindow/llwindowwin32.h
@@ -36,12 +36,44 @@
#include "llthread.h"
#include "llthreadsafequeue.h"
#include "llmutex.h"
-#include "workqueue.h"
// Hack for async host by name
#define LL_WM_HOST_RESOLVED (WM_APP + 1)
typedef void (*LLW32MsgCallback)(const MSG &msg);
+class LLWindowWin32;
+
+// Thread that owns the Window Handle
+class LLWindowWin32Thread : public LLThread
+{
+public:
+ class Message
+ {
+ public:
+ LRESULT mMsg;
+ };
+
+ static const int MAX_QUEUE_SIZE = 2048;
+
+ LLThreadSafeQueue<MSG> mMessageQueue;
+ LLThreadSafeQueue<std::function<void()>> mFunctionQueue;
+
+ bool mFinished = false;
+
+ LLWindowWin32Thread(LLWindowWin32* window);
+
+ void run() override;
+
+ void post(const std::function<void()>& func);
+
+private:
+
+ // call PeekMessage and pull enqueue messages for later processing
+ void gatherInput();
+ LLWindowWin32* mWindow = nullptr;
+
+};
+
class LLWindowWin32 : public LLWindow
{
public:
@@ -186,6 +218,7 @@ protected:
HGLRC mhRC = 0; // OpenGL rendering context
HDC mhDC = 0; // Windows Device context handle
HINSTANCE mhInstance; // handle to application instance
+ WNDPROC mWndProc; // user-installable window proc
RECT mOldMouseClip; // Screen rect to which the mouse cursor was globally constrained before we changed it in clipMouse()
WPARAM mLastSizeWParam;
F32 mOverrideAspectRatio;
@@ -247,6 +280,7 @@ protected:
void kickWindowThread(HWND windowHandle=0);
friend class LLWindowManager;
+ friend class LLWindowWin32Thread;
};
class LLSplashScreenWin32 : public LLSplashScreen
diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h
index 5da13f5010..088502c017 100644
--- a/indra/llxml/llcontrol.h
+++ b/indra/llxml/llcontrol.h
@@ -247,6 +247,7 @@ public:
// generic getter
template<typename T> T get(const std::string& name)
{
+ LL_PROFILE_ZONE_SCOPED;
LLControlVariable* control = getControl(name);
LLSD value;
eControlType type = TYPE_COUNT;
diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt
index 76d398576c..2acce03d08 100644
--- a/indra/media_plugins/cef/CMakeLists.txt
+++ b/indra/media_plugins/cef/CMakeLists.txt
@@ -5,7 +5,6 @@ project(media_plugin_cef)
include(Boost)
include(00-Common)
include(LLCommon)
-include(LLImage)
include(LLPlugin)
include(LLMath)
include(LLRender)
@@ -13,7 +12,6 @@ include(LLWindow)
include(Linking)
include(PluginAPI)
include(MediaPluginBase)
-include(OpenGL)
include(CEFPlugin)
@@ -22,7 +20,6 @@ include_directories(
${MEDIA_PLUGIN_BASE_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${LLMATH_INCLUDE_DIRS}
- ${LLIMAGE_INCLUDE_DIRS}
${LLRENDER_INCLUDE_DIRS}
${LLWINDOW_INCLUDE_DIRS}
${CEF_INCLUDE_DIR}
diff --git a/indra/media_plugins/cef/media_plugin_cef.cpp b/indra/media_plugins/cef/media_plugin_cef.cpp
index 8465285d2b..11dec63cd3 100644
--- a/indra/media_plugins/cef/media_plugin_cef.cpp
+++ b/indra/media_plugins/cef/media_plugin_cef.cpp
@@ -29,7 +29,7 @@
#include "linden_common.h"
#include "indra_constants.h" // for indra keyboard codes
-#include "llgl.h"
+#include "llglheaders.h" // for GL_* constants
#include "llsdutil.h"
#include "llplugininstance.h"
#include "llpluginmessage.h"
@@ -37,9 +37,6 @@
#include "volume_catcher.h"
#include "media_plugin_base.h"
-#include <functional>
-#include <chrono>
-
#include "dullahan.h"
////////////////////////////////////////////////////////////////////////////////
diff --git a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
index 5d4a488e64..1afe25e9a1 100644
--- a/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
+++ b/indra/media_plugins/libvlc/media_plugin_libvlc.cpp
@@ -283,35 +283,16 @@ void MediaPluginLibVLC::playMedia()
return;
}
+ // A new call to play the media is received after the initial one. Typically
+ // this is due to a size change request either as the media naturally resizes
+ // to the size of the prim container, or else, as a 2D window is resized by the
+ // user. Stopping the media, helps avoid a race condition where the media pixel
+ // buffer size is out of sync with the declared size (width/height) for a frame
+ // or two and the plugin crashes as VLC tries to decode a frame into unallocated
+ // memory.
if (mLibVLCMediaPlayer)
{
- // stop listening to events while we reset things
- libvlc_event_manager_t* em = libvlc_media_player_event_manager(mLibVLCMediaPlayer);
- if (em)
- {
- libvlc_event_detach(em, libvlc_MediaPlayerOpening, eventCallbacks, NULL);
- libvlc_event_detach(em, libvlc_MediaPlayerPlaying, eventCallbacks, NULL);
- libvlc_event_detach(em, libvlc_MediaPlayerPaused, eventCallbacks, NULL);
- libvlc_event_detach(em, libvlc_MediaPlayerStopped, eventCallbacks, NULL);
- libvlc_event_detach(em, libvlc_MediaPlayerEndReached, eventCallbacks, NULL);
- libvlc_event_detach(em, libvlc_MediaPlayerEncounteredError, eventCallbacks, NULL);
- libvlc_event_detach(em, libvlc_MediaPlayerTimeChanged, eventCallbacks, NULL);
- libvlc_event_detach(em, libvlc_MediaPlayerPositionChanged, eventCallbacks, NULL);
- libvlc_event_detach(em, libvlc_MediaPlayerLengthChanged, eventCallbacks, NULL);
- libvlc_event_detach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, NULL);
- };
-
libvlc_media_player_stop(mLibVLCMediaPlayer);
- libvlc_media_player_release(mLibVLCMediaPlayer);
-
- mLibVLCMediaPlayer = 0;
- }
-
- if (mLibVLCMedia)
- {
- libvlc_media_release(mLibVLCMedia);
-
- mLibVLCMedia = 0;
}
mLibVLCMedia = libvlc_media_new_location(mLibVLC, mURL.c_str());
@@ -345,6 +326,9 @@ void MediaPluginLibVLC::playMedia()
libvlc_event_attach(em, libvlc_MediaPlayerTitleChanged, eventCallbacks, this);
}
+ libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext);
+ libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth);
+
mLibVLCCallbackContext.parent = this;
mLibVLCCallbackContext.texture_pixels = mPixels;
mLibVLCCallbackContext.mp = mLibVLCMediaPlayer;
@@ -366,14 +350,11 @@ void MediaPluginLibVLC::playMedia()
setStatus(STATUS_LOADED);
- libvlc_video_set_callbacks(mLibVLCMediaPlayer, lock, unlock, display, &mLibVLCCallbackContext);
- libvlc_video_set_format(mLibVLCMediaPlayer, "RV32", mWidth, mHeight, mWidth * mDepth);
-
// note this relies on the "set_loop" message arriving before the "start" (play) one
// but that appears to always be the case
if (mIsLooping)
{
- libvlc_media_add_option(mLibVLCMedia, "input-repeat=-1");
+ libvlc_media_add_option(mLibVLCMedia, "input-repeat=65535");
}
libvlc_media_player_play(mLibVLCMediaPlayer);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 6d090be33a..9b636e5e5d 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -393,6 +393,7 @@ set(viewer_SOURCE_FILES
llloginhandler.cpp
lllogininstance.cpp
llmachineid.cpp
+ llmainlooprepeater.cpp
llmanip.cpp
llmaniprotate.cpp
llmanipscale.cpp
@@ -1031,6 +1032,7 @@ set(viewer_HEADER_FILES
llloginhandler.h
lllogininstance.h
llmachineid.h
+ llmainlooprepeater.h
llmanip.h
llmaniprotate.h
llmanipscale.h
@@ -1602,7 +1604,6 @@ if (WINDOWS)
${WINDOWS_LIBRARIES}
comdlg32
dxguid
- imm32
kernel32
odbc32
odbccp32
@@ -2184,8 +2185,8 @@ if (DARWIN)
# SIGH, as of 2018-05-24 (cmake 3.11.1) the INSTALL_RPATH property simply
# does not work. Try this:
LINK_FLAGS "-rpath @loader_path/../Frameworks"
- MACOSX_BUNDLE_INFO_PLIST
- "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist"
+ MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info-SecondLife.plist"
+ XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${MACOSX_BUNDLE_GUI_IDENTIFIER}"
)
set(VIEWER_APP_BUNDLE "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${product}.app")
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index cfe9d991c5..09b0e1ec1b 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -11,7 +11,7 @@
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
- <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index f186cd8874..a194c18e86 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.4.24
+6.5.1
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 607e531e62..2d821b7451 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -1573,10 +1573,11 @@
<key>Value</key>
<real>1.0</real>
</map>
- <key>CameraPreset</key> <!-- deprecated (see SL-12429) -->
+ <key>CameraPreset</key>
+ <!-- deprecated (see SL-12429) -->
<map>
<key>Comment</key>
- <string>Preset camera position - view (0 - rear, 1 - front, 2 - group)</string>
+ <string>(Deprecated) Preset camera position - view (0 - rear, 1 - front, 2 - group)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -2483,10 +2484,11 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>DEPRECATED: DebugShowPrivateMem</key> <!-- deprecated (see MAINT-8091) -->
+ <key>DebugShowPrivateMem</key>
+ <!-- deprecated (see MAINT-8091) -->
<map>
<key>Comment</key>
- <string>Show Private Mem Info</string>
+ <string>(Deprecated) Show Private Mem Info</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -3726,6 +3728,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>EnableCollisionSounds</key>
+ <map>
+ <key>Comment</key>
+ <string>Play sounds on collision</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>EnableMouselook</key>
<map>
<key>Comment</key>
@@ -3858,17 +3871,6 @@
<key>Value</key>
<integer>1</integer>
</map>
- <key>MainWorkTime</key>
- <map>
- <key>Comment</key>
- <string>Max time per frame devoted to mainloop work queue (in milliseconds)</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>F32</string>
- <key>Value</key>
- <real>0.1</real>
- </map>
<key>QueueInventoryFetchTimeout</key>
<map>
<key>Comment</key>
@@ -5797,7 +5799,7 @@
<key>LoginSRVPump</key>
<map>
<key>Comment</key>
- <string>Name of the message pump that handles SRV request (deprecated)</string>
+ <string>(Deprecated) Name of the message pump that handles SRV request)</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
@@ -6608,10 +6610,11 @@
<key>Value</key>
<real>600.0</real>
</map>
- <key>MemoryPrivatePoolEnabled</key> <!-- deprecated (see MAINT-8091) -->
+ <key>MemoryPrivatePoolEnabled</key>
+ <!-- deprecated (see MAINT-8091) -->
<map>
<key>Comment</key>
- <string>DEPRECATED: Enable the private memory pool management</string>
+ <string>(Deprecated) Enable the private memory pool management</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -6619,10 +6622,11 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>MemoryPrivatePoolSize</key> <!-- deprecated (see MAINT-8091) -->
+ <key>MemoryPrivatePoolSize</key>
+ <!-- deprecated (see MAINT-8091) -->
<map>
<key>Comment</key>
- <string>DEPRECATED: Size of the private memory pool in MB (min. value is 256)</string>
+ <string>(Deprecated) Size of the private memory pool in MB (min. value is 256)</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -8326,7 +8330,7 @@
<key>QAModeEventHostPort</key>
<map>
<key>Comment</key>
- <string>DEPRECATED: Port on which lleventhost should listen</string>
+ <string>(Deprecated) Port on which lleventhost should listen</string>
<key>Persist</key>
<integer>0</integer>
<key>Type</key>
@@ -8645,28 +8649,6 @@
</array>
</map>
- <key>RenderAlphaBatchFullbrights</key>
- <map>
- <key>Comment</key>
- <string>Render fullbright alpha content more efficiently, but with possible visual differences from prev viewers.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>0</integer>
- </map>
- <key>RenderAlphaBatchEmissives</key>
- <map>
- <key>Comment</key>
- <string>Render emissive alpha content more efficiently, but with possible visual differences from prev viewers.</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>Boolean</string>
- <key>Value</key>
- <integer>1</integer>
- </map>
<key>RenderAnisotropic</key>
<map>
<key>Comment</key>
@@ -10141,7 +10123,7 @@
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <integer>512</integer>
+ <integer>4096</integer>
</map>
<key>RenderNameFadeDuration</key>
<map>
@@ -12674,19 +12656,16 @@
<key>Value</key>
<integer>50</integer>
</map>
- <key>ThreadPoolSizes</key>
+ <key>TextureSaveLocation</key>
<map>
<key>Comment</key>
- <string>Map of size overrides for specific thread pools.</string>
+ <string>Current location for bulk saving textures to disk</string>
<key>Persist</key>
- <integer>1</integer>
+ <integer>0</integer>
<key>Type</key>
- <string>LLSD</string>
+ <string>String</string>
<key>Value</key>
- <map>
- <key>General</key>
- <integer>4</integer>
- </map>
+ <string />
</map>
<key>ThrottleBandwidthKBPS</key>
<map>
@@ -14074,10 +14053,11 @@
<key>Value</key>
<string>Default</string>
</map>
- <key>UseExternalBrowser</key> <!-- deprecated (see MAINT-4127) -->
+ <key>UseExternalBrowser</key>
+ <!-- deprecated (see MAINT-4127) -->
<map>
<key>Comment</key>
- <string>Use default browser when opening web pages instead of in-world browser.</string>
+ <string>(Deprecated) Use default browser when opening web pages instead of in-world browser.</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -14472,6 +14452,7 @@
<integer>0</integer>
</map>
<key>VoiceCallsFriendsOnly</key>
+ <!-- deprecated (see SL-12871) -->
<map>
<key>Comment</key>
<string>(Deprecated) Only accept voice calls from residents on your friends list</string>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
index dc484317e9..d3a05c34c0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaF.glsl
@@ -86,6 +86,14 @@ float getAmbientClamp();
vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, float ambiance)
{
+ // SL-14895 inverted attenuation work-around
+ // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct
+ // that previous value now that the inversion is corrected, we reverse the calculations in LLPipeline::setupHWLights()
+ // to recover the `adjusted_radius` value previously being sent as la.
+ float falloff_factor = (12.0 * fa) - 9.0;
+ float inverted_la = falloff_factor / la;
+ // Yes, it makes me want to cry as well. DJH
+
vec3 col = vec3(0);
//get light vector
@@ -95,7 +103,7 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec
float dist = length(lv);
float da = 1.0;
- /*if (dist > la)
+ /*if (dist > inverted_la)
{
return col;
}
@@ -113,9 +121,9 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 diffuse, vec3 v, vec3 n, vec
return col;
}*/
- if (dist > 0.0 && la > 0.0)
+ if (dist > 0.0 && inverted_la > 0.0)
{
- dist /= la;
+ dist /= inverted_la;
//normalize light vector
lv = normalize(lv);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
index 506118d381..6a93bc2fd2 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl
@@ -105,9 +105,9 @@ void main()
vec4 vert = vec4(position.xyz, 1.0);
pos = (modelview_matrix * vert);
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
-#endif
+#endif //IS_AVATAR_SKIN
-#endif
+#endif // HAS_SKIN
#ifdef USE_INDEXED_TEX
passTextureIndex();
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl
deleted file mode 100644
index 10144f3e16..0000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpSkinnedV.glsl
+++ /dev/null
@@ -1,64 +0,0 @@
-/**
- * @file bumpV.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-uniform mat4 projection_matrix;
-uniform mat4 texture_matrix0;
-uniform mat4 modelview_matrix;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec3 normal;
-ATTRIBUTE vec2 texcoord0;
-ATTRIBUTE vec4 tangent;
-
-VARYING vec3 vary_mat0;
-VARYING vec3 vary_mat1;
-VARYING vec3 vary_mat2;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-mat4 getObjectSkinnedTransform();
-
-void main()
-{
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
- mat4 mat = getObjectSkinnedTransform();
-
- mat = modelview_matrix * mat;
-
- vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
-
-
- vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz);
- vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz);
- vec3 b = cross(n, t) * tangent.w;
-
- 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 = projection_matrix*vec4(pos, 1.0);
- vertex_color = diffuse_color;
-}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
index 9f9749394e..d90891aa20 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/bumpV.glsl
@@ -39,16 +39,32 @@ VARYING vec3 vary_mat2;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+uniform mat4 modelview_matrix;
+#endif
+
void main()
{
//transform vertex
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
+ gl_Position = projection_matrix*vec4(pos, 1.0);
+
+ vec3 n = normalize((mat * vec4(normal.xyz+position.xyz, 1.0)).xyz-pos.xyz);
+ vec3 t = normalize((mat * vec4(tangent.xyz+position.xyz, 1.0)).xyz-pos.xyz);
+#else
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
vec3 n = normalize(normal_matrix * normal);
vec3 t = normalize(normal_matrix * tangent.xyz);
+#endif
+
vec3 b = cross(n, t) * tangent.w;
-
+ vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+
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);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
index 3c026796c8..d64bcefade 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/diffuseV.glsl
@@ -39,14 +39,28 @@ VARYING vec2 vary_texcoord0;
void passTextureIndex();
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+uniform mat4 modelview_matrix;
+#endif
+
void main()
{
- //transform vertex
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec4 pos = mat * vec4(position.xyz, 1.0);
+ gl_Position = projection_matrix * pos;
+ vary_normal = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
+#else
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vary_normal = normalize(normal_matrix * normal);
+#endif
+
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
passTextureIndex();
- vary_normal = normalize(normal_matrix * normal);
-
+
vertex_color = diffuse_color;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
index 8f6eb79668..2c139430e7 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyV.glsl
@@ -25,7 +25,6 @@
uniform mat3 normal_matrix;
uniform mat4 texture_matrix0;
-uniform mat4 texture_matrix1;
uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix;
@@ -47,19 +46,32 @@ VARYING vec2 vary_texcoord0;
VARYING vec3 vary_texcoord1;
VARYING vec4 vary_position;
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+#endif
+
void main()
{
//transform vertex
vec4 vert = vec4(position.xyz,1.0);
passTextureIndex();
+
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec4 pos = mat * vert;
+ vary_position = gl_Position = projection_matrix * pos;
+ vec3 norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
+#else
vec4 pos = (modelview_matrix * vert);
vary_position = gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
-
vec3 norm = normalize(normal_matrix * normal);
+#endif
vec3 ref = reflect(pos.xyz, -norm);
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz;
+ vary_texcoord1 = transpose(normal_matrix) * ref.xyz;
calcAtmospherics(pos.xyz);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
index bdf3546aa5..e71636f2c9 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightV.glsl
@@ -45,15 +45,26 @@ VARYING vec3 vary_position;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+#endif
void main()
{
//transform vertex
vec4 vert = vec4(position.xyz, 1.0);
- vec4 pos = (modelview_matrix * vert);
passTextureIndex();
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec4 pos = mat * vert;
+ gl_Position = projection_matrix * pos;
+#else
+ vec4 pos = (modelview_matrix * vert);
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
+#endif
#ifdef WATER_FOG
vary_position = pos.xyz;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index e1f7031af6..02d83925ea 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -91,6 +91,14 @@ float getAmbientClamp();
vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spec, vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight, inout float glare, float ambiance)
{
+ // SL-14895 inverted attenuation work-around
+ // This routine is tweaked to match deferred lighting, but previously used an inverted la value. To reconstruct
+ // that previous value now that the inversion is corrected, we reverse the calculations in LLPipeline::setupHWLights()
+ // to recover the `adjusted_radius` value previously being sent as la.
+ float falloff_factor = (12.0 * fa) - 9.0;
+ float inverted_la = falloff_factor / la;
+ // Yes, it makes me want to cry as well. DJH
+
vec3 col = vec3(0);
//get light vector
@@ -100,9 +108,9 @@ vec3 calcPointLightOrSpotLight(vec3 light_col, vec3 npos, vec3 diffuse, vec4 spe
float dist = length(lv);
float da = 1.0;
- dist /= la;
+ dist /= inverted_la;
- if (dist > 0.0 && la > 0.0)
+ if (dist > 0.0 && inverted_la > 0.0)
{
//normalize light vector
lv = normalize(lv);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl
index 2487110624..2b17aea75a 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/diffuseSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowAlphaMaskSkinnedV.glsl
@@ -1,8 +1,9 @@
/**
- * @file diffuseSkinnedV.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * @file shadowAlphaMaskSkinnedV.glsl
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
+ * 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
@@ -22,38 +23,48 @@
* $/LicenseInfo$
*/
-uniform mat4 projection_matrix;
uniform mat4 texture_matrix0;
uniform mat4 modelview_matrix;
+uniform mat4 projection_matrix;
+uniform float shadow_target_width;
ATTRIBUTE vec3 position;
ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec3 normal;
ATTRIBUTE vec2 texcoord0;
-VARYING vec3 vary_normal;
+VARYING vec4 post_pos;
+VARYING float target_pos_x;
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
+void passTextureIndex();
+
mat4 getObjectSkinnedTransform();
void main()
{
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
+ //transform vertex
+ vec4 pre_pos = vec4(position.xyz, 1.0);
+
mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat;
- vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
- vec4 norm = vec4(position.xyz, 1.0);
- norm.xyz += normal.xyz;
- norm.xyz = (mat*norm).xyz;
- norm.xyz = normalize(norm.xyz-pos.xyz);
+ vec4 pos = mat * pre_pos;
+ pos = projection_matrix * pos;
- vary_normal = norm.xyz;
-
- vertex_color = diffuse_color;
+ target_pos_x = 0.5 * (shadow_target_width - 1.0) * pos.x;
+
+ post_pos = pos;
+
+#if !defined(DEPTH_CLAMP)
+ gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+ gl_Position = pos;
+#endif
- gl_Position = projection_matrix*vec4(pos, 1.0);
+ passTextureIndex();
+
+ vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
+ vertex_color = diffuse_color;
}
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl
index df31b5a79f..bdf8e0854d 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/shadowSkinnedV.glsl
@@ -1,6 +1,7 @@
/**
- * @file simpleSkinnedV.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * @file shadowSkinnedV.glsl
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
@@ -22,44 +23,30 @@
* $/LicenseInfo$
*/
-uniform mat4 texture_matrix0;
uniform mat4 modelview_matrix;
uniform mat4 projection_matrix;
ATTRIBUTE vec3 position;
-ATTRIBUTE vec3 normal;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
+VARYING vec4 post_pos;
-
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
-void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
void main()
{
//transform vertex
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat;
- vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
-
- vec4 norm = vec4(position.xyz, 1.0);
- norm.xyz += normal.xyz;
- norm.xyz = (mat*norm).xyz;
- norm.xyz = normalize(norm.xyz-pos.xyz);
-
- calcAtmospherics(pos.xyz);
+ vec4 pos = (mat*vec4(position.xyz, 1.0));
+ pos = projection_matrix*pos;
+
+ post_pos = pos;
+
+#if !defined(DEPTH_CLAMP)
+ gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+#else
+ gl_Position = pos;
+#endif
- vec4 color = calcLighting(pos.xyz, norm.xyz, diffuse_color);
- vertex_color = color;
-
- gl_Position = projection_matrix*vec4(pos, 1.0);
-
-
}
diff --git a/indra/newview/app_settings/shaders/class1/objects/emissiveSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl
index 9064904191..d9ca6d3a46 100644
--- a/indra/newview/app_settings/shaders/class1/objects/emissiveSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/treeShadowSkinnedV.glsl
@@ -1,7 +1,7 @@
/**
- * @file emissiveSkinnedV.glsl
+ * @file treeShadowV.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * $LicenseInfo:firstyear=2007&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
@@ -23,34 +23,31 @@
* $/LicenseInfo$
*/
-uniform mat4 projection_matrix;
uniform mat4 texture_matrix0;
uniform mat4 modelview_matrix;
-
+uniform mat4 projection_matrix;
+
ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 emissive;
ATTRIBUTE vec2 texcoord0;
-VARYING vec4 vertex_color;
+VARYING vec4 post_pos;
VARYING vec2 vary_texcoord0;
-
-void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
void main()
{
//transform vertex
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
- mat4 mat = getObjectSkinnedTransform();
+ mat4 mat = getObjectSkinnedTransform();
mat = modelview_matrix * mat;
- vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
- vertex_color = emissive;
-
- calcAtmospherics(pos.xyz);
-
- gl_Position = projection_matrix*vec4(pos, 1.0);
+ vec4 pos = mat * vec4(position.xyz, 1.0);
+ pos = projection_matrix * pos;
+
+ post_pos = pos;
+
+ gl_Position = vec4(pos.x, pos.y, pos.w*0.5, pos.w);
+
+ vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
}
diff --git a/indra/newview/app_settings/shaders/class1/interface/debugSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/interface/debugSkinnedV.glsl
new file mode 100644
index 0000000000..74f22aec4f
--- /dev/null
+++ b/indra/newview/app_settings/shaders/class1/interface/debugSkinnedV.glsl
@@ -0,0 +1,41 @@
+/**
+ * @file debugSkinnedV.glsl
+ *
+ * $LicenseInfo:firstyear=2021&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$
+ */
+
+uniform mat4 projection_matrix;
+uniform mat4 modelview_matrix;
+
+mat4 getObjectSkinnedTransform();
+
+ATTRIBUTE vec3 position;
+
+void main()
+{
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
+
+ gl_Position = projection_matrix*vec4(pos, 1.0);
+}
+
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/interface/occlusionSkinnedV.glsl
index eff75435a9..7305065a05 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightSkinnedV.glsl
+++ b/indra/newview/app_settings/shaders/class1/interface/occlusionSkinnedV.glsl
@@ -1,6 +1,7 @@
/**
- * @file fullbrightSkinnedV.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
+ * @file occlusionSkinnedV.glsl
+ *
+ * $LicenseInfo:firstyear=2021&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2007, Linden Research, Inc.
*
@@ -23,35 +24,17 @@
*/
uniform mat4 projection_matrix;
-uniform mat4 texture_matrix0;
uniform mat4 modelview_matrix;
ATTRIBUTE vec3 position;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-void calcAtmospherics(vec3 inPositionEye);
mat4 getObjectSkinnedTransform();
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-
-
void main()
{
- //transform vertex
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
-
mat4 mat = getObjectSkinnedTransform();
-
mat = modelview_matrix * mat;
vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
-
- calcAtmospherics(pos.xyz);
-
- vertex_color = diffuse_color;
-
gl_Position = projection_matrix*vec4(pos, 1.0);
-
-
}
+
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl
index b768d609f4..d87403c78f 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightAlphaMaskNonIndexedF.glsl
@@ -43,13 +43,13 @@ void default_lighting()
{
vec4 color = texture2D(diffuseMap,vary_texcoord0.xy);
- color *= vertex_color;
-
if (color.a < minimum_alpha)
{
discard;
}
-
+
+ color *= vertex_color;
+
color.rgb = atmosLighting(color.rgb);
color.rgb = scaleSoftClip(color.rgb);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
index 5fcdf3107c..89be8195f0 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightF.glsl
@@ -56,5 +56,6 @@ void fullbright_lighting()
color.rgb = pow(color.rgb, vec3(1.0/texture_gamma));
frag_color = color;
+
}
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl
index d04cd79f4b..37cac5f437 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterAlphaMaskF.glsl
@@ -43,13 +43,13 @@ void fullbright_lighting_water()
{
vec4 color = diffuseLookup(vary_texcoord0.xy);
- color.rgb *= vertex_color.rgb;
-
if (color.a < minimum_alpha)
{
discard;
}
+ color.rgb *= vertex_color.rgb;
+
color.rgb = fullbrightAtmosTransport(color.rgb);
frag_color = applyWaterFog(color);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl
index 3b9c04b22b..c98db4795c 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightWaterNonIndexedAlphaMaskF.glsl
@@ -41,13 +41,15 @@ VARYING vec2 vary_texcoord0;
void fullbright_lighting_water()
{
- vec4 color = texture2D(diffuseMap, vary_texcoord0.xy) * vertex_color;
+ vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
if (color.a < minimum_alpha)
{
discard;
}
+ color.rgb *= vertex_color.rgb;
+
color.rgb = fullbrightAtmosTransport(color.rgb);
frag_color = applyWaterFog(color);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl
index 0916797259..9c89c09573 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskF.glsl
@@ -41,13 +41,13 @@ void default_lighting_water()
{
vec4 color = diffuseLookup(vary_texcoord0.xy);
- color.rgb *= vertex_color.rgb;
-
if (color.a < minimum_alpha)
{
discard;
}
+ color.rgb *= vertex_color.rgb;
+
color.rgb = atmosLighting(color.rgb);
frag_color = applyWaterFog(color);
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl
index f2a84f1d42..9de7a03180 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightWaterAlphaMaskNonIndexedF.glsl
@@ -43,13 +43,13 @@ void default_lighting_water()
{
vec4 color = texture2D(diffuseMap,vary_texcoord0.xy);
- color.rgb *= vertex_color.rgb;
-
if (color.a < minimum_alpha)
{
discard;
}
+ color.rgb *= vertex_color.rgb;
+
color.rgb = atmosLighting(color.rgb);
color = applyWaterFog(color);
diff --git a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl
index a7738087dc..ee9970bc70 100644
--- a/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/bumpV.glsl
@@ -33,10 +33,23 @@ ATTRIBUTE vec2 texcoord1;
VARYING vec2 vary_texcoord0;
VARYING vec2 vary_texcoord1;
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+uniform mat4 modelview_matrix;
+#endif
+
void main()
{
//transform vertex
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec4 pos = mat * vec4(position.xyz, 1.0);
+ gl_Position = projection_matrix * pos;
+#else
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
+#endif
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
vary_texcoord1 = (texture_matrix0 * vec4(texcoord1,0,1)).xy;
}
diff --git a/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl b/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl
index e984deb0c8..d762239e51 100644
--- a/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/emissiveV.glsl
@@ -37,20 +37,30 @@ VARYING vec2 vary_texcoord0;
void calcAtmospherics(vec3 inPositionEye);
-
-
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+#endif
void main()
{
//transform vertex
passTextureIndex();
+
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+
+ vec4 pos = mat * vec4(position.xyz, 1.0);
+ gl_Position = projection_matrix * pos;
+#else
gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+ vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0));
+#endif
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0));
+
calcAtmospherics(pos.xyz);
vertex_color = emissive;
-
-
}
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
deleted file mode 100644
index 1e244d9dfd..0000000000
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinySkinnedV.glsl
+++ /dev/null
@@ -1,71 +0,0 @@
-/**
- * @file shinySimpleSkinnedV.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-uniform mat4 texture_matrix0;
-uniform mat4 texture_matrix1;
-uniform mat4 modelview_matrix;
-uniform mat4 projection_matrix;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec3 normal;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-VARYING vec3 vary_texcoord1;
-VARYING vec4 vary_position;
-
-
-void calcAtmospherics(vec3 inPositionEye);
-mat4 getObjectSkinnedTransform();
-
-void main()
-{
- mat4 mat = getObjectSkinnedTransform();
-
- mat = modelview_matrix * mat;
- vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
-
- mat4 mvp = modelview_matrix * projection_matrix;
- vary_position = mvp * vec4(position, 1.0);
-
- vec4 norm = vec4(position.xyz, 1.0);
- norm.xyz += normal.xyz;
- norm.xyz = (mat*norm).xyz;
- norm.xyz = normalize(norm.xyz-pos.xyz);
-
- vec3 ref = reflect(pos.xyz, -norm.xyz);
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz;
-
- calcAtmospherics(pos.xyz);
-
- vertex_color = diffuse_color;
-
- gl_Position = projection_matrix*vec4(pos, 1.0);
-
-
-}
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl
index 34bd8d445a..ace2574ac2 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightShinyV.glsl
@@ -25,7 +25,6 @@
uniform mat3 normal_matrix;
uniform mat4 texture_matrix0;
-uniform mat4 texture_matrix1;
uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix;
@@ -46,20 +45,32 @@ VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
VARYING vec3 vary_texcoord1;
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+#endif
void main()
{
//transform vertex
vec4 vert = vec4(position.xyz,1.0);
passTextureIndex();
+
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec4 pos = mat * vert;
+ gl_Position = projection_matrix * pos;
+ vec3 norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
+#else
vec4 pos = (modelview_matrix * vert);
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
-
vec3 norm = normalize(normal_matrix * normal);
+#endif
vec3 ref = reflect(pos.xyz, -norm);
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz;
+ vary_texcoord1 = transpose(normal_matrix) * ref;
calcAtmospherics(pos.xyz);
diff --git a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl
index fc20d3270e..5af42f1fcf 100644
--- a/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/fullbrightV.glsl
@@ -33,26 +33,33 @@ ATTRIBUTE vec2 texcoord0;
ATTRIBUTE vec3 normal;
ATTRIBUTE vec4 diffuse_color;
-
void calcAtmospherics(vec3 inPositionEye);
-
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+#endif
void main()
{
//transform vertex
vec4 vert = vec4(position.xyz,1.0);
passTextureIndex();
- vec4 pos = (modelview_matrix * vert);
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec4 pos = mat * vert;
+ gl_Position = projection_matrix * pos;
+#else
+ vec4 pos = (modelview_matrix * vert);
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
+#endif
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
calcAtmospherics(pos.xyz);
vertex_color = diffuse_color;
-
-
}
diff --git a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
deleted file mode 100644
index 727bae19c0..0000000000
--- a/indra/newview/app_settings/shaders/class1/objects/shinySimpleSkinnedV.glsl
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- * @file shinySimpleSkinnedV.glsl
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-uniform mat4 projection_matrix;
-uniform mat4 texture_matrix0;
-uniform mat4 texture_matrix1;
-uniform mat4 modelview_matrix;
-
-ATTRIBUTE vec3 position;
-ATTRIBUTE vec3 normal;
-ATTRIBUTE vec4 diffuse_color;
-ATTRIBUTE vec2 texcoord0;
-
-VARYING vec4 vertex_color;
-VARYING vec2 vary_texcoord0;
-VARYING vec3 vary_texcoord1;
-
-vec4 calcLighting(vec3 pos, vec3 norm, vec4 color);
-void calcAtmospherics(vec3 inPositionEye);
-mat4 getObjectSkinnedTransform();
-
-void main()
-{
- mat4 mat = getObjectSkinnedTransform();
-
- mat = modelview_matrix * mat;
- vec3 pos = (mat*vec4(position.xyz, 1.0)).xyz;
-
- vec4 norm = vec4(position.xyz, 1.0);
- norm.xyz += normal.xyz;
- norm.xyz = (mat*norm).xyz;
- norm.xyz = normalize(norm.xyz-pos.xyz);
-
- vec3 ref = reflect(pos.xyz, -norm.xyz);
-
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz;
-
- calcAtmospherics(pos.xyz);
-
- vec4 color = calcLighting(pos.xyz, norm.xyz, diffuse_color);
- vertex_color = color;
-
- gl_Position = projection_matrix*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 4ba8194d03..097e42d233 100644
--- a/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl
@@ -25,7 +25,6 @@
uniform mat3 normal_matrix;
uniform mat4 texture_matrix0;
-uniform mat4 texture_matrix1;
uniform mat4 modelview_matrix;
uniform mat4 modelview_projection_matrix;
@@ -45,19 +44,32 @@ void calcAtmospherics(vec3 inPositionEye);
uniform vec4 origin;
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+#endif
+
void main()
{
//transform vertex
vec4 vert = vec4(position.xyz,1.0);
passTextureIndex();
+
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+ vec4 pos = mat * vert;
+ gl_Position = projection_matrix * pos;
+ vec3 norm = normalize((mat*vec4(normal.xyz+position.xyz,1.0)).xyz-pos.xyz);
+#else
vec4 pos = (modelview_matrix * vert);
gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
-
vec3 norm = normalize(normal_matrix * normal);
+#endif
vec3 ref = reflect(pos.xyz, -norm);
- vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy;
- vary_texcoord1 = (texture_matrix1*vec4(ref,1.0)).xyz;
+ vary_texcoord0 = (texture_matrix0*vec4(texcoord0,0,1)).xy;
+ vary_texcoord1 = transpose(normal_matrix) * ref;
calcAtmospherics(pos.xyz);
diff --git a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
index 9ef7704b70..2025174f7d 100644
--- a/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
+++ b/indra/newview/app_settings/shaders/class1/objects/simpleV.glsl
@@ -44,12 +44,16 @@ void calcAtmospherics(vec3 inPositionEye);
VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0;
+#ifdef HAS_SKIN
+mat4 getObjectSkinnedTransform();
+uniform mat4 projection_matrix;
+#endif
+
void main()
{
//transform vertex
vec4 vert = vec4(position.xyz,1.0);
- gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
passTextureIndex();
vary_texcoord0 = (texture_matrix0 * vec4(texcoord0, 0, 1)).xy;
@@ -58,11 +62,23 @@ void main()
if (no_atmo == 1)
{
vertex_color = diffuse_color;
+ gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
}
else
{
+#ifdef HAS_SKIN
+ mat4 mat = getObjectSkinnedTransform();
+ mat = modelview_matrix * mat;
+
+ vec4 pos = mat * vert;
+ vec3 norm = normalize((mat*vec4(normal.xyz+vert.xyz,1.0)).xyz-pos.xyz);
+
+ gl_Position = projection_matrix * pos;
+#else
vec4 pos = (modelview_matrix * vert);
vec3 norm = normalize(normal_matrix * normal);
+ gl_Position = modelview_projection_matrix*vec4(position.xyz, 1.0);
+#endif
calcAtmospherics(pos.xyz);
diff --git a/indra/newview/app_settings/toolbars.xml b/indra/newview/app_settings/toolbars.xml
index eec0d81e8b..f3a23edc58 100644
--- a/indra/newview/app_settings/toolbars.xml
+++ b/indra/newview/app_settings/toolbars.xml
@@ -7,6 +7,7 @@
<command name="destinations"/>
<command name="people"/>
<command name="profile"/>
+ <command name="map"/>
<command name="move"/>
<command name="view"/>
<command name="howto"/>
diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt
index f1bf8d76c2..bd66641db9 100644
--- a/indra/newview/featuretable.txt
+++ b/indra/newview/featuretable.txt
@@ -70,6 +70,7 @@ RenderShadowDetail 1 2
RenderUseStreamVBO 1 1
RenderFSAASamples 1 16
RenderMaxTextureIndex 1 16
+RenderGLCoreProfile 1 1
//
// Low Graphics Settings (fixed function)
@@ -619,9 +620,10 @@ RenderAvatarCloth 0 0
RenderVBOEnable 1 0
// ATI cards generally perform better when not using VBOs for streaming data
-
+// ATI cards also prefer an OpenGL Compatibility Profile Context
list ATI
RenderUseStreamVBO 1 0
+RenderGLCoreProfile 1 0
// Disable vertex buffer objects by default for ATI cards with little video memory
list ATIVramLT256
diff --git a/indra/newview/installers/windows/lang_pl.nsi b/indra/newview/installers/windows/lang_pl.nsi
index 05977847b9..865e8bdeee 100644
--- a/indra/newview/installers/windows/lang_pl.nsi
+++ b/indra/newview/installers/windows/lang_pl.nsi
Binary files differ
diff --git a/indra/newview/licenses-linux.txt b/indra/newview/licenses-linux.txt
index b43c402e64..e53ba94a36 100644
--- a/indra/newview/licenses-linux.txt
+++ b/indra/newview/licenses-linux.txt
@@ -638,7 +638,7 @@ Vivox SDK License
RSA Data Security, Inc. MD5 Message-Digest Algorithm
-Audio coding: Polycom¨ Siren14TM (ITU-T Rec. G.722.1 Annex C)
+Audio coding: Polycom(R) Siren14TM (ITU-T Rec. G.722.1 Annex C)
Open Source Software Licensing
Each open source software component utilized by this product is subject to its own copyright and licensing terms, as listed below.
diff --git a/indra/newview/licenses-mac.txt b/indra/newview/licenses-mac.txt
index af80bff5d9..d0747ccd03 100644
--- a/indra/newview/licenses-mac.txt
+++ b/indra/newview/licenses-mac.txt
@@ -522,7 +522,7 @@ Vivox SDK License
RSA Data Security, Inc. MD5 Message-Digest Algorithm
-Audio coding: Polycom¨ Siren14TM (ITU-T Rec. G.722.1 Annex C)
+Audio coding: Polycom(R) Siren14TM (ITU-T Rec. G.722.1 Annex C)
Open Source Software Licensing
Each open source software component utilized by this product is subject to its own copyright and licensing terms, as listed below.
diff --git a/indra/newview/licenses-win32.txt b/indra/newview/licenses-win32.txt
index 8736626907..98edd35bea 100644
--- a/indra/newview/licenses-win32.txt
+++ b/indra/newview/licenses-win32.txt
@@ -4,7 +4,7 @@ Logitech License
End-User License Agreement for Logitech LCD SDK
-This End-User License Agreement for Logitech LCD SDK ( “Agreement”) is a legal agreement between you, either an individual or legal entity (“You” or “you”) and Logitech Inc. (“Logitech”) for use of the Logitech LCD software development kit, which includes computer software and related media and documentation (hereinafter “LCD SDK”). By using this LCD SDK, you are agreeing to be bound by the terms and conditions of this Agreement. If you do not agree to the terms and conditions of this Agreement, promptly return the LCD SDK and other items that are part of this product in their original package with your sales receipt to your point of purchase for a full refund, or if you have downloaded this software from a Logitech web site, then you must stop using the software and destroy any copies of the software in your possession or control.
+This End-User License Agreement for Logitech LCD SDK ( "Agreement") is a legal agreement between you, either an individual or legal entity ("You" or "you") and Logitech Inc. ("Logitech") for use of the Logitech LCD software development kit, which includes computer software and related media and documentation (hereinafter "LCD SDK"). By using this LCD SDK, you are agreeing to be bound by the terms and conditions of this Agreement. If you do not agree to the terms and conditions of this Agreement, promptly return the LCD SDK and other items that are part of this product in their original package with your sales receipt to your point of purchase for a full refund, or if you have downloaded this software from a Logitech web site, then you must stop using the software and destroy any copies of the software in your possession or control.
1 Grant of License and Restrictions.
This Agreement grants You the following rights provided that You comply with all terms and conditions of this Agreement.
@@ -14,7 +14,7 @@ This Agreement grants You the following rights provided that You comply with all
(d) In the event Logitech, in its sole discretion, elects to provide copies of the LCD SDK to more than one individual employed by You (if You are not a single individual), each such individual shall be entitled to exercise the rights granted in this Agreement and shall be bound by the terms and conditions herein.
2 Updates.
-Logitech is not obligated to provide technical support or updates to You for the LCD SDK provided to You pursuant to this Agreement. However, Logitech may, in its sole discretion, provide further pre-release versions, technical support, updates and/or supplements (“Updates”) to You, in which case such Updates shall be deemed to be included in the “LCD SDK” and shall be governed by this Agreement, unless other terms of use are provided in writing by Logitech with such Updates.
+Logitech is not obligated to provide technical support or updates to You for the LCD SDK provided to You pursuant to this Agreement. However, Logitech may, in its sole discretion, provide further pre-release versions, technical support, updates and/or supplements ("Updates") to You, in which case such Updates shall be deemed to be included in the "LCD SDK" and shall be governed by this Agreement, unless other terms of use are provided in writing by Logitech with such Updates.
3 Intellectual Property Rights.
The LCD SDK is licensed, not sold, to You for use only under the terms and conditions of this Agreement. Logitech and its suppliers retain title to the LCD SDK and all intellectual property rights therein. The LCD SDK is protected by intellectual property laws and international treaties, including U.S. copyright law and international copyright treaties. All rights not expressly granted by Logitech are reserved.
@@ -23,7 +23,7 @@ The LCD SDK is licensed, not sold, to You for use only under the terms and condi
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, LOGITECH AND ITS SUPPLIERS PROVIDE THE LCD SDK AND OTHER LOGITECH PRODUCTS AND SERVICES (IF ANY) AS IS AND WITHOUT WARRANTY OF ANY KIND. LOGITECH AND ITS SUPPLIERS EXPRESSLY DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD-PARTY RIGHTS WITH RESPECT TO THE LCD SDK AND ANY WARRANTIES OF NON-INTERFERENCE OR ACCURACY OF INFORMATIONAL CONTENT. NO LOGITECH DEALER, AGENT, OR EMPLOYEE IS AUTHORIZED TO MAKE ANY MODIFICATION, EXTENSION, OR ADDITION TO THIS WARRANTY. Some jurisdictions do not allow limitations on how long an implied warranty lasts, so the above limitation may not apply to you.
5 Limitation of Liability.
-IN NO EVENT WILL LOGITECH OR ITS SUPPLIERS BE LIABLE FOR ANY COSTS OF PROCUREMENT OF SUBSTITUTE PRODUCTS OR SERVICES, LOST PROFITS, LOSS OF INFORMATION OR DATA, OR ANY OTHER SPECIAL, INDIRECT, CONSEQUENTIAL, OR INCIDENTAL DAMAGES ARISING IN ANY WAY OUT OF THE SALE OF, USE OF, OR INABILITY TO USE THE LCD SDK OR ANY LOGITECH PRODUCT OR SERVICE, EVEN IF LOGITECH HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN NO CASE SHALL LOGITECH'S AND ITS SUPPLIERS’ TOTAL LIABILITY EXCEED THE ACTUAL MONEY PAID FOR THE LOGITECH PRODUCT OR SERVICE GIVING RISE TO THE LIABILITY. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so the above limitation or exclusion may not apply to you. The above limitations will not apply in case of personal injury where and to the extent that applicable law requires such liability.
+IN NO EVENT WILL LOGITECH OR ITS SUPPLIERS BE LIABLE FOR ANY COSTS OF PROCUREMENT OF SUBSTITUTE PRODUCTS OR SERVICES, LOST PROFITS, LOSS OF INFORMATION OR DATA, OR ANY OTHER SPECIAL, INDIRECT, CONSEQUENTIAL, OR INCIDENTAL DAMAGES ARISING IN ANY WAY OUT OF THE SALE OF, USE OF, OR INABILITY TO USE THE LCD SDK OR ANY LOGITECH PRODUCT OR SERVICE, EVEN IF LOGITECH HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN NO CASE SHALL LOGITECH'S AND ITS SUPPLIERS' TOTAL LIABILITY EXCEED THE ACTUAL MONEY PAID FOR THE LOGITECH PRODUCT OR SERVICE GIVING RISE TO THE LIABILITY. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so the above limitation or exclusion may not apply to you. The above limitations will not apply in case of personal injury where and to the extent that applicable law requires such liability.
6 U.S. Government Rights.
Use, duplication, or disclosure of the software contained in the LCD SDK by the U.S. Government is subject to restrictions set forth in this Agreement and as provided in DFARS 227.7202-1(a) and 227.7202-3(a) (1995), DFARS 252.227-7013(c)(1)(ii) (OCT 1988) FAR 12.212(a) (1995), FAR 52.227-19, or FAR 52.227-14 (ALT III), as applicable. Logitech Inc. 6505 Kaiser Drive, Fremont, CA 94555.
@@ -564,7 +564,7 @@ Vivox SDK License
RSA Data Security, Inc. MD5 Message-Digest Algorithm
-Audio coding: Polycom¨ Siren14TM (ITU-T Rec. G.722.1 Annex C)
+Audio coding: Polycom(R) Siren14TM (ITU-T Rec. G.722.1 Annex C)
Open Source Software Licensing
Each open source software component utilized by this product is subject to its own copyright and licensing terms, as listed below.
diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp
index 7f18ea6fe2..be168ff5dd 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -1049,13 +1049,14 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
}
// updating inventory
+ LLWearableType* wearable_type_inst = LLWearableType::getInstance();
// TODO: Removed check for ensuring that teens don't remove undershirt and underwear. Handle later
// note: shirt is the first non-body part wearable item. Update if wearable order changes.
// This loop should remove all clothing, but not any body parts
for (S32 j = 0; j < (S32)LLWearableType::WT_COUNT; j++)
{
- if (LLWearableType::getAssetType((LLWearableType::EType)j) == LLAssetType::AT_CLOTHING)
+ if (wearable_type_inst->getAssetType((LLWearableType::EType)j) == LLAssetType::AT_CLOTHING)
{
removeWearable((LLWearableType::EType)j, true, 0);
}
@@ -1075,7 +1076,7 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
new_wearable->setName(new_item->getName());
new_wearable->setItemID(new_item->getUUID());
- if (LLWearableType::getAssetType(type) == LLAssetType::AT_BODYPART)
+ if (wearable_type_inst->getAssetType(type) == LLAssetType::AT_BODYPART)
{
// exactly one wearable per body part
setWearable(type,0,new_wearable);
@@ -1162,7 +1163,7 @@ void LLAgentWearables::setWearableItem(LLInventoryItem* new_item, LLViewerWearab
if ((old_wearable->getAssetID() == new_wearable->getAssetID()) &&
(old_item_id == new_item->getUUID()))
{
- LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getTypeName(type) << LL_ENDL;
+ LL_DEBUGS() << "No change to wearable asset and item: " << LLWearableType::getInstance()->getTypeName(type) << LL_ENDL;
return;
}
@@ -1594,7 +1595,7 @@ void LLAgentWearables::editWearable(const LLUUID& item_id)
return;
}
- const BOOL disable_camera_switch = LLWearableType::getDisableCameraSwitch(wearable->getType());
+ const BOOL disable_camera_switch = LLWearableType::getInstance()->getDisableCameraSwitch(wearable->getType());
LLPanel* panel = LLFloaterSidePanelContainer::getPanel("appearance");
LLSidepanelAppearance::editWearable(wearable, panel, disable_camera_switch);
}
diff --git a/indra/newview/llappcorehttp.cpp b/indra/newview/llappcorehttp.cpp
index 3da87e657c..ef56478106 100644
--- a/indra/newview/llappcorehttp.cpp
+++ b/indra/newview/llappcorehttp.cpp
@@ -271,20 +271,13 @@ void LLAppCoreHttp::init()
<< LL_ENDL;
}
- // Signal for global pipelining preference from settings
+ // Global pipelining setting
static const std::string http_pipelining("HttpPipelining");
if (gSavedSettings.controlExists(http_pipelining))
{
- LLPointer<LLControlVariable> cntrl_ptr = gSavedSettings.getControl(http_pipelining);
- if (cntrl_ptr.isNull())
- {
- LL_WARNS("Init") << "Unable to set signal on global setting '" << http_pipelining
- << "'" << LL_ENDL;
- }
- else
- {
- mPipelinedSignal = cntrl_ptr->getCommitSignal()->connect(boost::bind(&setting_changed));
- }
+ // Default to true (in ctor) if absent.
+ mPipelined = gSavedSettings.getBOOL(http_pipelining);
+ LL_INFOS("Init") << "HTTP Pipelining " << (mPipelined ? "enabled" : "disabled") << "!" << LL_ENDL;
}
// Register signals for settings and state changes
@@ -398,21 +391,6 @@ void LLAppCoreHttp::refreshSettings(bool initial)
{
LLCore::HttpStatus status;
- // Global pipelining setting
- bool pipeline_changed(false);
- static const std::string http_pipelining("HttpPipelining");
- if (gSavedSettings.controlExists(http_pipelining))
- {
- // Default to true (in ctor) if absent.
- bool pipelined(gSavedSettings.getBOOL(http_pipelining));
- if (pipelined != mPipelined)
- {
- mPipelined = pipelined;
- pipeline_changed = true;
- }
- LL_INFOS("Init") << "HTTP Pipelining " << (mPipelined ? "enabled" : "disabled") << "!" << LL_ENDL;
- }
-
for (int i(0); i < LL_ARRAY_SIZE(init_data); ++i)
{
const EAppPolicy app_policy(static_cast<EAppPolicy>(i));
@@ -441,7 +419,7 @@ void LLAppCoreHttp::refreshSettings(bool initial)
// Init- or run-time settings. Must use the queued request API.
// Pipelining changes
- if (initial || pipeline_changed)
+ if (initial)
{
const bool to_pipeline(mPipelined && init_data[i].mPipelined);
if (to_pipeline != mHttpClasses[app_policy].mPipelined)
@@ -484,7 +462,7 @@ void LLAppCoreHttp::refreshSettings(bool initial)
}
}
- if (initial || setting != mHttpClasses[app_policy].mConnLimit || pipeline_changed)
+ if (initial || setting != mHttpClasses[app_policy].mConnLimit)
{
// Set it and report. Strategies depend on pipelining:
//
diff --git a/indra/newview/llappdelegate-objc.mm b/indra/newview/llappdelegate-objc.mm
index aeb3294f53..5214f4b838 100644
--- a/indra/newview/llappdelegate-objc.mm
+++ b/indra/newview/llappdelegate-objc.mm
@@ -301,6 +301,12 @@ struct AttachmentInfo
AttachmentInfo(metadata.staticDebugPathname, "text/xml")
};
+ secondLogPath = metadata.secondLogFilePathname;
+ if(!secondLogPath.empty())
+ {
+ info.push_back(AttachmentInfo(secondLogPath, "text/xml"));
+ }
+
// We "happen to know" that info[0].basename is "SecondLife.old" -- due to
// the fact that BugsplatMac only notices a crash during the viewer run
// following the crash.
@@ -339,6 +345,12 @@ struct AttachmentInfo
- (void)bugsplatStartupManagerDidFinishSendingCrashReport:(BugsplatStartupManager *)bugsplatStartupManager
{
infos("Sent crash report to BugSplat");
+
+ if(!secondLogPath.empty())
+ {
+ boost::filesystem::remove(secondLogPath);
+ }
+ clearDumpLogsDir();
}
- (void)bugsplatStartupManager:(BugsplatStartupManager *)bugsplatStartupManager didFailWithError:(NSError *)error
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index 9fc2e9ead8..39c9fa1bca 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -957,7 +957,7 @@ void recovered_item_link_cb(const LLUUID& item_id, LLWearableType::EType type, L
// runway skip here?
}
- LL_INFOS() << "HP " << holder->index() << " recovered item link for type " << type << LL_ENDL;
+ LL_INFOS("Avatar") << "HP " << holder->index() << " recovered item link for type " << type << LL_ENDL;
holder->eraseTypeToLink(type);
// Add wearable to FoundData for actual wearing
LLViewerInventoryItem *item = gInventory.getItem(item_id);
@@ -1021,8 +1021,8 @@ void LLWearableHoldingPattern::recoverMissingWearable(LLWearableType::EType type
// Try to recover by replacing missing wearable with a new one.
LLNotificationsUtil::add("ReplacedMissingWearable");
- LL_DEBUGS() << "Wearable " << LLWearableType::getTypeLabel(type)
- << " could not be downloaded. Replaced inventory item with default wearable." << LL_ENDL;
+ LL_DEBUGS("Avatar") << "Wearable of type '" << LLWearableType::getInstance()->getTypeName(type)
+ << "' could not be downloaded. Replaced inventory item with default wearable." << LL_ENDL;
LLViewerWearable* wearable = LLWearableList::instance().createNewWearable(type, gAgentAvatarp);
// Add a new one in the lost and found folder.
@@ -2347,6 +2347,52 @@ void LLAppearanceMgr::enforceCOFItemRestrictions(LLPointer<LLInventoryCallback>
}
}
+bool sort_by_linked_uuid(const LLViewerInventoryItem* item1, const LLViewerInventoryItem* item2)
+{
+ if (!item1 || !item2)
+ {
+ LL_WARNS() << "item1, item2 cannot be null, something is very wrong" << LL_ENDL;
+ return true;
+ }
+
+ return item1->getLinkedUUID() < item2->getLinkedUUID();
+}
+
+void get_sorted_base_and_cof_items(LLInventoryModel::item_array_t& cof_item_array, LLInventoryModel::item_array_t& outfit_item_array)
+{
+ LLUUID base_outfit_id = LLAppearanceMgr::instance().getBaseOutfitUUID();
+
+ if (base_outfit_id.notNull())
+ {
+ LLIsValidItemLink collector;
+ LLInventoryModel::cat_array_t sub_cat_array;
+
+ gInventory.collectDescendents(base_outfit_id,
+ sub_cat_array,
+ outfit_item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+
+ LLInventoryModel::cat_array_t cof_cats;
+
+ gInventory.collectDescendentsIf(LLAppearanceMgr::instance().getCOF(), cof_cats, cof_item_array,
+ LLInventoryModel::EXCLUDE_TRASH, collector);
+
+ for (U32 i = 0; i < outfit_item_array.size(); ++i)
+ {
+ LLViewerInventoryItem* linked_item = outfit_item_array.at(i)->getLinkedItem();
+ if (linked_item != NULL && linked_item->getActualType() == LLAssetType::AT_TEXTURE)
+ {
+ outfit_item_array.erase(outfit_item_array.begin() + i);
+ break;
+ }
+ }
+
+ std::sort(cof_item_array.begin(), cof_item_array.end(), sort_by_linked_uuid);
+ std::sort(outfit_item_array.begin(), outfit_item_array.end(), sort_by_linked_uuid);
+ }
+}
+
+
void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
bool enforce_ordering,
nullary_func_t post_update_func)
@@ -2388,7 +2434,30 @@ void LLAppearanceMgr::updateAppearanceFromCOF(bool enforce_item_restrictions,
if (!validateClothingOrderingInfo())
{
- LL_WARNS() << "Clothing ordering error" << LL_ENDL;
+
+ LLInventoryModel::item_array_t outfit_item_array;
+ LLInventoryModel::item_array_t cof_item_array;
+ get_sorted_base_and_cof_items(cof_item_array, outfit_item_array);
+
+ if (outfit_item_array.size() == cof_item_array.size())
+ {
+ for (U32 i = 0; i < cof_item_array.size(); ++i)
+ {
+ LLViewerInventoryItem *cof_it = cof_item_array.at(i);
+ LLViewerInventoryItem *base_it = outfit_item_array.at(i);
+
+ if (cof_it->getActualDescription() != base_it->getActualDescription())
+ {
+ if (cof_it->getLinkedUUID() == base_it->getLinkedUUID())
+ {
+ cof_it->setDescription(base_it->getActualDescription());
+ gInventory.updateItem(cof_it);
+ }
+ }
+ }
+ LLAppearanceMgr::getInstance()->updateIsDirty();
+ }
+
}
BoolSetter setIsInUpdateAppearanceFromCOF(mIsInUpdateAppearanceFromCOF);
@@ -3017,17 +3086,6 @@ void LLAppearanceMgr::removeCOFLinksOfType(LLWearableType::EType type, LLPointer
}
}
-bool sort_by_linked_uuid(const LLViewerInventoryItem* item1, const LLViewerInventoryItem* item2)
-{
- if (!item1 || !item2)
- {
- LL_WARNS() << "item1, item2 cannot be null, something is very wrong" << LL_ENDL;
- return true;
- }
-
- return item1->getLinkedUUID() < item2->getLinkedUUID();
-}
-
void LLAppearanceMgr::updateIsDirty()
{
LLUUID cof = getCOF();
@@ -4267,6 +4325,17 @@ public:
}
virtual void done()
{
+ if (mComplete.size() <= 0)
+ {
+ // Ex: timeout
+ LL_WARNS() << "Failed to load data. Removing observer " << LL_ENDL;
+ gInventory.removeObserver(this);
+ doOnIdleOneTime(mCallable);
+
+ delete this;
+ return;
+ }
+
// What we do here is get the complete information on the
// items in the requested category, and set up an observer
// that will wait for that to happen.
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index e7f104d6fd..5b3cbff9b8 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -233,12 +233,11 @@
#include "llavatariconctrl.h"
#include "llgroupiconctrl.h"
#include "llviewerassetstats.h"
-#include "workqueue.h"
-using namespace LL;
// Include for security api initialization
#include "llsecapi.h"
#include "llmachineid.h"
+#include "llmainlooprepeater.h"
#include "llcleanup.h"
#include "llcoproceduremanager.h"
@@ -367,10 +366,6 @@ BOOL gLogoutInProgress = FALSE;
BOOL gSimulateMemLeak = FALSE;
-// We don't want anyone, especially threads working on the graphics pipeline,
-// to have to block due to this WorkQueue being full.
-WorkQueue gMainloopWork("mainloop", 1024*1024);
-
////////////////////////////////////////////////////////////
// Internal globals... that should be removed.
static std::string gArgs;
@@ -386,6 +381,42 @@ static std::string gLaunchFileOnQuit;
// Used on Win32 for other apps to identify our window (eg, win_setup)
const char* const VIEWER_WINDOW_CLASSNAME = "Second Life";
+//-- LLDeferredTaskList ------------------------------------------------------
+
+/**
+ * A list of deferred tasks.
+ *
+ * We sometimes need to defer execution of some code until the viewer gets idle,
+ * e.g. removing an inventory item from within notifyObservers() may not work out.
+ *
+ * Tasks added to this list will be executed in the next LLAppViewer::idle() iteration.
+ * All tasks are executed only once.
+ */
+class LLDeferredTaskList: public LLSingleton<LLDeferredTaskList>
+{
+ LLSINGLETON_EMPTY_CTOR(LLDeferredTaskList);
+ LOG_CLASS(LLDeferredTaskList);
+
+ friend class LLAppViewer;
+ typedef boost::signals2::signal<void()> signal_t;
+
+ void addTask(const signal_t::slot_type& cb)
+ {
+ mSignal.connect(cb);
+ }
+
+ void run()
+ {
+ if (!mSignal.empty())
+ {
+ mSignal();
+ mSignal.disconnect_all_slots();
+ }
+ }
+
+ signal_t mSignal;
+};
+
//----------------------------------------------------------------------------
// List of entries from strings.xml to always replace
@@ -582,7 +613,7 @@ static void settings_modify()
LLPipeline::sRenderDeferred = LLPipeline::sRenderBump && gSavedSettings.getBOOL("RenderDeferred");
LLVOSurfacePatch::sLODFactor = gSavedSettings.getF32("RenderTerrainLODFactor");
LLVOSurfacePatch::sLODFactor *= LLVOSurfacePatch::sLODFactor; //square lod factor to get exponential range of [1,4]
- gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
+ gDebugGL = gSavedSettings.getBOOL("RenderDebugGL") || gDebugSession;
gDebugPipeline = gSavedSettings.getBOOL("RenderDebugPipeline");
}
@@ -684,8 +715,6 @@ LLAppViewer::LLAppViewer()
gLoggedInTime.stop();
- initLoggingAndGetLastDuration();
-
processMarkerFiles();
//
// OK to write stuff to logs now, we've now crash reported if necessary
@@ -738,10 +767,6 @@ bool LLAppViewer::init()
// Start of the application
//
- // initialize LLWearableType translation bridge.
- // Memory will be cleaned up in ::cleanupClass()
- LLWearableType::initParamSingleton(new LLUITranslationBridge());
-
// initialize the LLSettingsType translation bridge.
LLTranslationBridge::ptr_t trans = std::make_shared<LLUITranslationBridge>();
LLSettingsType::initParamSingleton(trans);
@@ -763,6 +788,7 @@ bool LLAppViewer::init()
//
init_default_trans_args();
+ // inits from settings.xml and from strings.xml
if (!initConfiguration())
return false;
@@ -829,6 +855,10 @@ bool LLAppViewer::init()
// Setup LLTrans after LLUI::initClass has been called.
initStrings();
+ // initialize LLWearableType translation bridge.
+ // Will immediately use LLTranslationBridge to init LLWearableDictionary
+ LLWearableType::initParamSingleton(trans);
+
// Setup notifications after LLUI::initClass() has been called.
LLNotifications::instance();
LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ;
@@ -943,6 +973,9 @@ bool LLAppViewer::init()
}
LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ;
+ // Initialize the repeater service.
+ LLMainLoopRepeater::instance().start();
+
// Initialize event recorder
LLViewerEventRecorder::createInstance();
@@ -1064,8 +1097,15 @@ bool LLAppViewer::init()
if (count > 0 && v1 <= 10)
{
LL_INFOS("AppInit") << "Detected obsolete intel driver: " << driver << LL_ENDL;
+
+ if (!gViewerWindow->getInitAlert().empty() // graphic initialization crashed on last run
+ || LLVersionInfo::getInstance()->getChannelAndVersion() != gLastRunVersion // viewer was updated
+ || mNumSessions % 20 == 0 //periodically remind user to update driver
+ )
+ {
LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedIntelDriver");
std::string gpu_name = ll_safe_string((const char *)glGetString(GL_RENDERER));
+ LL_INFOS("AppInit") << "Notifying user about obsolete intel driver for " << gpu_name << LL_ENDL;
details.setArg("[VERSION]", driver);
details.setArg("[GPUNAME]", gpu_name);
S32 button = OSMessageBox(details.getString(),
@@ -1082,6 +1122,7 @@ bool LLAppViewer::init()
}
}
}
+ }
#endif
// Obsolete? mExpectedGLVersion is always zero
@@ -1292,6 +1333,13 @@ bool LLAppViewer::init()
LLSelectMgr::createInstance();
LLViewerCamera::createInstance();
+#if LL_WINDOWS
+ if (!mSecondInstance)
+ {
+ gDirUtilp->deleteDirAndContents(gDirUtilp->getDumpLogsDirPath());
+ }
+#endif
+
return true;
}
@@ -1382,6 +1430,11 @@ bool LLAppViewer::doFrame()
{
LL_RECORD_BLOCK_TIME(FTM_FRAME);
+ if (!LLWorld::instanceExists())
+ {
+ LLWorld::createInstance();
+ }
+
LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop"));
LLSD newFrame;
@@ -1389,11 +1442,11 @@ bool LLAppViewer::doFrame()
LL_PROFILE_ZONE_NAMED("df LLTrace");
if (LLFloaterReg::instanceVisible("block_timers"))
{
- LLTrace::BlockTimer::processTimes();
+ LLTrace::BlockTimer::processTimes();
}
- LLTrace::get_frame_recording().nextPeriod();
- LLTrace::BlockTimer::logStats();
+ LLTrace::get_frame_recording().nextPeriod();
+ LLTrace::BlockTimer::logStats();
}
LLTrace::get_thread_recorder()->pullFromChildren();
@@ -1413,7 +1466,7 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED( "df gatherInput" )
- pingMainloopTimeout("Main:GatherInput");
+ pingMainloopTimeout("Main:GatherInput");
}
if (gViewerWindow)
@@ -1440,14 +1493,14 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED( "df mainloop" )
- // canonical per-frame event
- mainloop.post(newFrame);
+ // canonical per-frame event
+ mainloop.post(newFrame);
}
{
LL_PROFILE_ZONE_NAMED( "df suspend" )
- // give listeners a chance to run
- llcoro::suspend();
+ // give listeners a chance to run
+ llcoro::suspend();
}
if (!LLApp::isExiting())
@@ -1475,7 +1528,7 @@ bool LLAppViewer::doFrame()
{
{
LL_PROFILE_ZONE_NAMED( "df pauseMainloopTimeout" )
- pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
+ pauseMainloopTimeout(); // *TODO: Remove. Messages shouldn't be stalling for 20+ seconds!
}
LL_RECORD_BLOCK_TIME(FTM_IDLE);
@@ -1483,14 +1536,20 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED( "df resumeMainloopTimeout" )
- resumeMainloopTimeout();
- }
+ resumeMainloopTimeout();
+ }
}
if (gDoDisconnect && (LLStartUp::getStartupState() == STATE_STARTED))
{
pauseMainloopTimeout();
saveFinalSnapshot();
+
+ if (LLVoiceClient::instanceExists())
+ {
+ LLVoiceClient::getInstance()->terminate();
+ }
+
disconnectViewer();
resumeMainloopTimeout();
}
@@ -1507,19 +1566,19 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED( "df Snapshot" )
- pingMainloopTimeout("Main:Snapshot");
- LLFloaterSnapshot::update(); // take snapshots
+ pingMainloopTimeout("Main:Snapshot");
+ LLFloaterSnapshot::update(); // take snapshots
LLFloaterOutfitSnapshot::update();
- gGLActive = FALSE;
- }
+ gGLActive = FALSE;
}
}
+ }
{
LL_PROFILE_ZONE_NAMED( "df pauseMainloopTimeout" )
- pingMainloopTimeout("Main:Sleep");
+ pingMainloopTimeout("Main:Sleep");
- pauseMainloopTimeout();
+ pauseMainloopTimeout();
}
// Sleep and run background threads
@@ -1606,7 +1665,7 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED( "df gMeshRepo" )
- gMeshRepo.update() ;
+ gMeshRepo.update() ;
}
if(!total_work_pending) //pause texture fetching threads if nothing to process.
@@ -1637,7 +1696,7 @@ bool LLAppViewer::doFrame()
{
LL_PROFILE_ZONE_NAMED( "df resumeMainloopTimeout" )
- resumeMainloopTimeout();
+ resumeMainloopTimeout();
}
pingMainloopTimeout("Main:End");
}
@@ -2158,6 +2217,8 @@ bool LLAppViewer::cleanup()
SUBSYSTEM_CLEANUP(LLProxy);
LLCore::LLHttp::cleanup();
+ LLMainLoopRepeater::instance().stop();
+
ll_close_fail_log();
LLError::LLCallStacks::cleanup();
@@ -2250,6 +2311,17 @@ void LLAppViewer::initLoggingAndGetLastDuration()
LLError::addGenericRecorder(&errorCallback);
//LLError::setTimeFunction(getRuntime);
+
+ if (mSecondInstance)
+ {
+ LLFile::mkdir(gDirUtilp->getDumpLogsDirPath());
+
+ LLUUID uid;
+ uid.generate();
+ LLError::logToFile(gDirUtilp->getDumpLogsDirPath(uid.asString() + ".log"));
+ }
+ else
+ {
// Remove the last ".old" log file.
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,
"SecondLife.old");
@@ -2269,12 +2341,12 @@ void LLAppViewer::initLoggingAndGetLastDuration()
std::ostringstream duration_log_stream; // can't log yet, so save any message for when we can below
int start_stat_result = LLFile::stat(start_marker_file_name, &start_marker_stat);
int log_stat_result = LLFile::stat(log_file, &log_file_stat);
- if ( 0 == start_stat_result && 0 == log_stat_result )
+ if (0 == start_stat_result && 0 == log_stat_result)
{
int elapsed_seconds = log_file_stat.st_ctime - start_marker_stat.st_ctime;
// only report a last run time if the last viewer was the same version
// because this stat will be counted against this version
- if ( markerIsSameVersion(start_marker_file_name) )
+ if (markerIsSameVersion(start_marker_file_name))
{
gLastExecDuration = elapsed_seconds;
}
@@ -2287,13 +2359,13 @@ void LLAppViewer::initLoggingAndGetLastDuration()
else
{
// at least one of the LLFile::stat calls failed, so we can't compute the run time
- duration_log_stream << "duration stat failure; start: "<< start_stat_result << " log: " << log_stat_result;
+ duration_log_stream << "duration stat failure; start: " << start_stat_result << " log: " << log_stat_result;
gLastExecDuration = -1; // unknown
}
std::string duration_log_msg(duration_log_stream.str());
// Create a new start marker file for comparison with log file time for the next run
- LLAPRFile start_marker_file ;
+ LLAPRFile start_marker_file;
start_marker_file.open(start_marker_file_name, LL_APR_WB);
if (start_marker_file.getFileHandle())
{
@@ -2310,6 +2382,7 @@ void LLAppViewer::initLoggingAndGetLastDuration()
{
LL_WARNS("MarkerFile") << duration_log_msg << LL_ENDL;
}
+ }
}
bool LLAppViewer::loadSettingsFromDirectory(const std::string& location_key,
@@ -2658,7 +2731,7 @@ bool LLAppViewer::initConfiguration()
const std::string& value = *(++itr);
if (!tempSetControl(name,value))
{
- LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL;
+ LL_WARNS() << "Failed --set " << name << ": setting name unknown." << LL_ENDL;
}
}
}
@@ -3114,6 +3187,15 @@ bool LLAppViewer::initWindow()
void LLAppViewer::writeDebugInfo(bool isStatic)
{
+#if LL_WINDOWS && LL_BUGSPLAT
+ // bugsplat does not create dump folder and debug logs are written directly
+ // to logs folder, so it conflicts with main instance
+ if (mSecondInstance)
+ {
+ return;
+ }
+#endif
+
//Try to do the minimum when writing data during a crash.
std::string* debug_filename;
debug_filename = ( isStatic
@@ -3442,7 +3524,7 @@ void LLAppViewer::writeSystemInfo()
if (! gDebugInfo.has("Dynamic") )
gDebugInfo["Dynamic"] = LLSD::emptyMap();
-#if LL_WINDOWS
+#if LL_WINDOWS && !LL_BUGSPLAT
gDebugInfo["SLLog"] = gDirUtilp->getExpandedFilename(LL_PATH_DUMP,"SecondLife.log");
#else
//Not ideal but sufficient for good reporting.
@@ -3524,14 +3606,14 @@ void LLAppViewer::writeSystemInfo()
gDebugInfo["FirstLogin"] = LLSD::Boolean(gAgent.isFirstLogin());
gDebugInfo["FirstRunThisInstall"] = gSavedSettings.getBOOL("FirstRunThisInstall");
gDebugInfo["StartupState"] = LLStartUp::getStartupStateString();
-
+
if (gViewerWindow)
{
- std::vector<std::string> resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList();
- for (auto res_iter : resolutions)
- {
- gDebugInfo["DisplayInfo"].append(res_iter);
- }
+ std::vector<std::string> resolutions = gViewerWindow->getWindow()->getDisplaysResolutionList();
+ for (auto res_iter : resolutions)
+ {
+ gDebugInfo["DisplayInfo"].append(res_iter);
+ }
}
writeDebugInfo(); // Save out debug_info.log early, in case of crash.
@@ -3786,6 +3868,7 @@ void LLAppViewer::processMarkerFiles()
// - Other Crash (SecondLife.error_marker present)
// These checks should also remove these files for the last 2 cases if they currently exist
+ std::ostringstream marker_log_stream;
bool marker_is_same_version = true;
// first, look for the marker created at startup and deleted on a clean exit
mMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,MARKER_FILE_NAME);
@@ -3796,12 +3879,12 @@ void LLAppViewer::processMarkerFiles()
marker_is_same_version = markerIsSameVersion(mMarkerFileName);
// now test to see if this file is locked by a running process (try to open for write)
- LL_DEBUGS("MarkerFile") << "Checking exec marker file for lock..." << LL_ENDL;
+ marker_log_stream << "Checking exec marker file for lock...";
mMarkerFile.open(mMarkerFileName, LL_APR_WB);
apr_file_t* fMarker = mMarkerFile.getFileHandle() ;
if (!fMarker)
{
- LL_INFOS("MarkerFile") << "Exec marker file open failed - assume it is locked." << LL_ENDL;
+ marker_log_stream << "Exec marker file open failed - assume it is locked.";
mSecondInstance = true; // lock means that instance is running.
}
else
@@ -3809,16 +3892,20 @@ void LLAppViewer::processMarkerFiles()
// We were able to open it, now try to lock it ourselves...
if (apr_file_lock(fMarker, APR_FLOCK_NONBLOCK | APR_FLOCK_EXCLUSIVE) != APR_SUCCESS)
{
- LL_WARNS_ONCE("MarkerFile") << "Locking exec marker failed." << LL_ENDL;
+ marker_log_stream << "Locking exec marker failed.";
mSecondInstance = true; // lost a race? be conservative
}
else
{
// No other instances; we've locked this file now, so record our version; delete on quit.
recordMarkerVersion(mMarkerFile);
- LL_DEBUGS("MarkerFile") << "Exec marker file existed but was not locked; rewritten." << LL_ENDL;
+ marker_log_stream << "Exec marker file existed but was not locked; rewritten.";
}
}
+ initLoggingAndGetLastDuration();
+
+ std::string marker_log_msg(marker_log_stream.str());
+ LL_INFOS("MarkerFile") << marker_log_msg << LL_ENDL;
if (mSecondInstance)
{
@@ -3837,6 +3924,7 @@ void LLAppViewer::processMarkerFiles()
}
else // marker did not exist... last exec (if any) did not freeze
{
+ initLoggingAndGetLastDuration();
// Create the marker file for this execution & lock it; it will be deleted on a clean exit
apr_status_t s;
s = mMarkerFile.open(mMarkerFileName, LL_APR_WB, TRUE);
@@ -3962,8 +4050,18 @@ void LLAppViewer::removeDumpDir()
{
//Call this routine only on clean exit. Crash reporter will clean up
//its locking table for us.
+ if (gDirUtilp->dumpDirExists()) // Check if dump dir was created this run
+ {
std::string dump_dir = gDirUtilp->getExpandedFilename(LL_PATH_DUMP, "");
gDirUtilp->deleteDirAndContents(dump_dir);
+ }
+
+ if (mSecondInstance && !isError())
+ {
+ std::string log_filename = LLError::logFileName();
+ LLError::logToFile("");
+ LLFile::remove(log_filename);
+ }
}
void LLAppViewer::forceQuit()
@@ -4452,7 +4550,7 @@ bool LLAppViewer::initCache()
void LLAppViewer::addOnIdleCallback(const boost::function<void()>& cb)
{
- gMainloopWork.post(cb);
+ LLDeferredTaskList::instance().addTask(cb);
}
void LLAppViewer::loadKeyBindings()
@@ -4850,6 +4948,7 @@ void LLAppViewer::idle()
LLNotificationsUI::LLToast::updateClass();
LLSmoothInterpolation::updateInterpolants();
LLMortician::updateClass();
+ LLImageGL::updateClass();
LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify()
LLDirPickerThread::clearDead();
F32 dt_raw = idle_timer.getElapsedTimeAndResetF32();
diff --git a/indra/newview/llappviewermacosx-for-objc.h b/indra/newview/llappviewermacosx-for-objc.h
index 79c3efff91..94bfa2491b 100644
--- a/indra/newview/llappviewermacosx-for-objc.h
+++ b/indra/newview/llappviewermacosx-for-objc.h
@@ -31,6 +31,7 @@ bool pumpMainLoop();
void handleQuit();
void cleanupViewer();
void infos(const std::string& message);
+void clearDumpLogsDir();
// This struct is malleable; it only serves as a way to convey a number of
// fields from llappviewermacosx.cpp's CrashMetadata_instance() function to the
@@ -47,6 +48,7 @@ struct CrashMetadata
std::string agentFullname;
std::string regionName;
std::string fatalMessage;
+ std::string secondLogFilePathname;
};
CrashMetadata& CrashMetadata_instance();
diff --git a/indra/newview/llappviewermacosx.cpp b/indra/newview/llappviewermacosx.cpp
index aa932f9c89..cb5cac6f2d 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -57,6 +57,7 @@
#include <fstream>
#include "lldir.h"
+#include "lldiriterator.h"
#include <signal.h>
#include <CoreAudio/CoreAudio.h> // for systemwide mute
class LLMediaCtrl; // for LLURLDispatcher
@@ -136,6 +137,14 @@ void cleanupViewer()
gViewerAppPtr = NULL;
}
+void clearDumpLogsDir()
+{
+ if (!LLAppViewer::instance()->isSecondInstance())
+ {
+ gDirUtilp->deleteDirAndContents(gDirUtilp->getDumpLogsDirPath());
+ }
+}
+
// The BugsplatMac API is structured as a number of different method
// overrides, each returning a different piece of metadata. But since we
// obtain such metadata by opening and parsing a file, it seems ridiculous to
@@ -190,6 +199,24 @@ CrashMetadataSingleton::CrashMetadataSingleton()
LLStringUtil::replaceChar(agentFullname, '_', ' ');
regionName = get_metadata(info, "CurrentRegion");
fatalMessage = get_metadata(info, "FatalMessage");
+
+ if (gDirUtilp->fileExists(gDirUtilp->getDumpLogsDirPath()))
+ {
+ LLDirIterator file_iter(gDirUtilp->getDumpLogsDirPath(), "*.log");
+ std::string file_name;
+ bool found = true;
+ while(found)
+ {
+ if((found = file_iter.next(file_name)))
+ {
+ std::string log_filename = gDirUtilp->getDumpLogsDirPath(file_name);
+ if(LLError::logFileName() != log_filename)
+ {
+ secondLogFilePathname = log_filename;
+ }
+ }
+ }
+ }
}
}
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 9074e6a6cf..8b14ed3ccf 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -118,16 +118,22 @@ namespace
{
if (nCode == MDSCB_EXCEPTIONCODE)
{
- // send the main viewer log file
+ // send the main viewer log file, one per instance
// widen to wstring, convert to __wchar_t, then pass c_str()
sBugSplatSender->sendAdditionalFile(
- WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log")));
+ WCSTR(LLError::logFileName()));
- sBugSplatSender->sendAdditionalFile(
- WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml")));
+ // second instance does not have some log files
+ // TODO: This needs fixing, if each instance now has individual logs,
+ // same should be made true for static debug files
+ if (!LLAppViewer::instance()->isSecondInstance())
+ {
+ sBugSplatSender->sendAdditionalFile(
+ WCSTR(*LLAppViewer::instance()->getStaticDebugFile()));
+ }
sBugSplatSender->sendAdditionalFile(
- WCSTR(*LLAppViewer::instance()->getStaticDebugFile()));
+ WCSTR(gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "settings.xml")));
// We don't have an email address for any user. Hijack this
// metadata field for the platform identifier.
diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp
index b31981b235..aa2ba752b7 100644
--- a/indra/newview/llcofwearables.cpp
+++ b/indra/newview/llcofwearables.cpp
@@ -74,7 +74,7 @@ protected:
}
// Set proper label for the "Create new <WEARABLE_TYPE>" menu item.
- std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type));
+ std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getInstance()->getTypeName(w_type));
menu_item->setLabel(new_label);
}
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 502ebbd4b1..7e99b99284 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -149,21 +149,6 @@ void LLDrawable::unload()
{
LLVOVolume *pVVol = getVOVolume();
pVVol->setNoLOD();
-
- for (S32 i = 0; i < getNumFaces(); i++)
- {
- LLFace* facep = getFace(i);
- if (facep->isState(LLFace::RIGGED))
- {
- LLDrawPoolAvatar* pool = (LLDrawPoolAvatar*)facep->getPool();
- if (pool) {
- pool->removeRiggedFace(facep);
- }
- facep->setVertexBuffer(NULL);
- }
- facep->clearState(LLFace::RIGGED);
- }
-
pVVol->markForUpdate(TRUE);
}
diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 3e4f97e494..92a9bed504 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -50,6 +50,9 @@
#include "lldrawpoolwlsky.h"
#include "llglslshader.h"
#include "llglcommonfunc.h"
+#include "llvoavatar.h"
+#include "llviewershadermgr.h"
+
S32 LLDrawPool::sNumDrawPools = 0;
@@ -385,21 +388,43 @@ LLRenderPass::~LLRenderPass()
}
void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture)
-{
+{
+ LL_PROFILE_ZONE_SCOPED;
LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
{
LLDrawInfo *pparams = *k;
- if (pparams) {
+ if (pparams)
+ {
pushBatch(*pparams, mask, texture);
}
}
}
-void LLRenderPass::renderTexture(U32 type, U32 mask, BOOL batch_textures)
+void LLRenderPass::renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture)
{
- pushBatches(type, mask, true, batch_textures);
+ LL_PROFILE_ZONE_SCOPED;
+ LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[type];
+ LLVOAvatar* lastAvatar = nullptr;
+ U64 lastMeshId = 0;
+ mask |= LLVertexBuffer::MAP_WEIGHT4;
+
+ for (LLSpatialGroup::drawmap_elem_t::iterator k = draw_info.begin(); k != draw_info.end(); ++k)
+ {
+ LLDrawInfo* pparams = *k;
+ if (pparams)
+ {
+ if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
+ {
+ uploadMatrixPalette(*pparams);
+ lastAvatar = pparams->mAvatar;
+ lastMeshId = pparams->mSkinInfo->mHash;
+ }
+
+ pushBatch(*pparams, mask, texture);
+ }
+ }
}
void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
@@ -415,27 +440,74 @@ void LLRenderPass::pushBatches(U32 type, U32 mask, BOOL texture, BOOL batch_text
}
}
+void LLRenderPass::pushRiggedBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ LLVOAvatar* lastAvatar = nullptr;
+ U64 lastMeshId = 0;
+ mask |= LLVertexBuffer::MAP_WEIGHT4;
+ for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
+ {
+ LLDrawInfo* pparams = *i;
+ if (pparams)
+ {
+ if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
+ {
+ uploadMatrixPalette(*pparams);
+ lastAvatar = pparams->mAvatar;
+ lastMeshId = pparams->mSkinInfo->mHash;
+ }
+
+ pushBatch(*pparams, mask, texture, batch_textures);
+ }
+ }
+}
+
void LLRenderPass::pushMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
{
+ LL_PROFILE_ZONE_SCOPED;
for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
{
LLDrawInfo* pparams = *i;
if (pparams)
{
- if (LLGLSLShader::sCurBoundShaderPtr)
- {
- LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
- }
- else
- {
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, pparams->mAlphaMaskCutoff);
- }
-
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
pushBatch(*pparams, mask, texture, batch_textures);
}
}
}
+void LLRenderPass::pushRiggedMaskBatches(U32 type, U32 mask, BOOL texture, BOOL batch_textures)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ LLVOAvatar* lastAvatar = nullptr;
+ U64 lastMeshId = 0;
+ for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
+ {
+ LLDrawInfo* pparams = *i;
+ if (pparams)
+ {
+ if (LLGLSLShader::sCurBoundShaderPtr)
+ {
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(pparams->mAlphaMaskCutoff);
+ }
+ else
+ {
+ gGL.setAlphaRejectSettings(LLRender::CF_GREATER, pparams->mAlphaMaskCutoff);
+ }
+
+ if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
+ {
+ uploadMatrixPalette(*pparams);
+ lastAvatar = pparams->mAvatar;
+ lastMeshId = pparams->mSkinInfo->mHash;
+ }
+
+ pushBatch(*pparams, mask | LLVertexBuffer::MAP_WEIGHT4, texture, batch_textures);
+ }
+ }
+}
+
void LLRenderPass::applyModelMatrix(const LLDrawInfo& params)
{
if (params.mModelMatrix != gGLLastMatrix)
@@ -514,7 +586,24 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba
}
}
-void LLRenderPass::renderGroups(U32 type, U32 mask, BOOL texture)
+// static
+bool LLRenderPass::uploadMatrixPalette(LLDrawInfo& params)
{
- gPipeline.renderGroups(this, type, mask, texture);
+ // upload matrix palette to shader
+ const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo);
+ U32 count = mpc.mMatrixPalette.size();
+
+ if (count == 0)
+ {
+ //skin info not loaded yet, don't render
+ return false;
+ }
+
+ LLGLSLShader::sCurBoundShaderPtr->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX,
+ count,
+ FALSE,
+ (GLfloat*)&(mpc.mGLMp[0]));
+
+ return true;
}
+
diff --git a/indra/newview/lldrawpool.h b/indra/newview/lldrawpool.h
index ecd9bd034f..6d49b0254b 100644
--- a/indra/newview/lldrawpool.h
+++ b/indra/newview/lldrawpool.h
@@ -125,38 +125,68 @@ protected:
class LLRenderPass : public LLDrawPool
{
public:
+ // list of possible LLRenderPass types to assign a render batch to
+ // NOTE: "rigged" variant MUST be non-rigged variant + 1
enum
{
PASS_SIMPLE = NUM_POOL_TYPES,
+ PASS_SIMPLE_RIGGED,
PASS_GRASS,
PASS_FULLBRIGHT,
+ PASS_FULLBRIGHT_RIGGED,
PASS_INVISIBLE,
- PASS_INVISI_SHINY,
+ PASS_INVISIBLE_RIGGED,
+ PASS_INVISI_SHINY,
+ PASS_INVISI_SHINY_RIGGED,
PASS_FULLBRIGHT_SHINY,
+ PASS_FULLBRIGHT_SHINY_RIGGED,
PASS_SHINY,
+ PASS_SHINY_RIGGED,
PASS_BUMP,
+ PASS_BUMP_RIGGED,
PASS_POST_BUMP,
+ PASS_POST_BUMP_RIGGED,
PASS_MATERIAL,
+ PASS_MATERIAL_RIGGED,
PASS_MATERIAL_ALPHA,
+ PASS_MATERIAL_ALPHA_RIGGED,
PASS_MATERIAL_ALPHA_MASK, // Diffuse texture used as alpha mask
+ PASS_MATERIAL_ALPHA_MASK_RIGGED,
PASS_MATERIAL_ALPHA_EMISSIVE,
+ PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED,
PASS_SPECMAP,
+ PASS_SPECMAP_RIGGED,
PASS_SPECMAP_BLEND,
+ PASS_SPECMAP_BLEND_RIGGED,
PASS_SPECMAP_MASK, // Diffuse texture used as alpha mask and specular texture(map)
+ PASS_SPECMAP_MASK_RIGGED,
PASS_SPECMAP_EMISSIVE,
+ PASS_SPECMAP_EMISSIVE_RIGGED,
PASS_NORMMAP,
+ PASS_NORMMAP_RIGGED,
PASS_NORMMAP_BLEND,
+ PASS_NORMMAP_BLEND_RIGGED,
PASS_NORMMAP_MASK, // Diffuse texture used as alpha mask and normal map
+ PASS_NORMMAP_MASK_RIGGED,
PASS_NORMMAP_EMISSIVE,
+ PASS_NORMMAP_EMISSIVE_RIGGED,
PASS_NORMSPEC,
- PASS_NORMSPEC_BLEND,
+ PASS_NORMSPEC_RIGGED,
+ PASS_NORMSPEC_BLEND,
+ PASS_NORMSPEC_BLEND_RIGGED,
PASS_NORMSPEC_MASK, // Diffuse texture used as alpha mask with normal and specular map
+ PASS_NORMSPEC_MASK_RIGGED,
PASS_NORMSPEC_EMISSIVE,
+ PASS_NORMSPEC_EMISSIVE_RIGGED,
PASS_GLOW,
+ PASS_GLOW_RIGGED,
PASS_ALPHA,
PASS_ALPHA_MASK,
+ PASS_ALPHA_MASK_RIGGED,
PASS_FULLBRIGHT_ALPHA_MASK, // Diffuse texture used as alpha mask and fullbright
+ PASS_FULLBRIGHT_ALPHA_MASK_RIGGED,
PASS_ALPHA_INVISIBLE,
+ PASS_ALPHA_INVISIBLE_RIGGED,
NUM_RENDER_TYPES,
};
@@ -169,12 +199,13 @@ public:
static void applyModelMatrix(const LLDrawInfo& params);
virtual void pushBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
+ virtual void pushRiggedBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
virtual void pushMaskBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
+ virtual void pushRiggedMaskBatches(U32 type, U32 mask, BOOL texture = TRUE, BOOL batch_textures = FALSE);
virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE);
+ static bool uploadMatrixPalette(LLDrawInfo& params);
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, BOOL batch_textures = TRUE);
-
+ virtual void renderRiggedGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
};
class LLFacePool : public LLDrawPool
diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp
index 34f9bfe35d..9b298b120a 100644
--- a/indra/newview/lldrawpoolalpha.cpp
+++ b/indra/newview/lldrawpoolalpha.cpp
@@ -48,18 +48,20 @@
#include "lldrawpoolwater.h"
#include "llspatialpartition.h"
#include "llglcommonfunc.h"
+#include "llvoavatar.h"
BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE;
+#define current_shader (LLGLSLShader::sCurBoundShaderPtr)
+
static BOOL deferred_render = FALSE;
LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) :
- LLRenderPass(type), current_shader(NULL), target_shader(NULL),
- simple_shader(NULL), fullbright_shader(NULL), emissive_shader(NULL),
+ LLRenderPass(type), target_shader(NULL),
mColorSFactor(LLRender::BF_UNDEF), mColorDFactor(LLRender::BF_UNDEF),
mAlphaSFactor(LLRender::BF_UNDEF), mAlphaDFactor(LLRender::BF_UNDEF)
{
-
+
}
LLDrawPoolAlpha::~LLDrawPoolAlpha()
@@ -98,33 +100,43 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
- emissive_shader = (LLPipeline::sRenderDeferred) ? &gDeferredEmissiveProgram :
- (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
+ emissive_shader[0] = (LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
+ emissive_shader[1] = emissive_shader[0]->mRiggedVariant;
- emissive_shader->bind();
- emissive_shader->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0);
- emissive_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
- emissive_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
+ for (int i = 0; i < 2; ++i)
+ {
+ emissive_shader[i]->bind();
+ emissive_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, (LLPipeline::sRenderingHUDs) ? 1 : 0);
+ emissive_shader[i]->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+ emissive_shader[i]->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
+ }
if (pass == 0)
{
- fullbright_shader = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram :
- (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram;
-
- fullbright_shader->bind();
- fullbright_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
- fullbright_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
- fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
- fullbright_shader->unbind();
+ fullbright_shader[0] = (LLPipeline::sImpostorRender) ? &gDeferredFullbrightProgram :
+ (LLPipeline::sUnderWaterRender) ? &gDeferredFullbrightWaterProgram : &gDeferredFullbrightProgram;
+ fullbright_shader[1] = fullbright_shader[0]->mRiggedVariant;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ fullbright_shader[i]->bind();
+ fullbright_shader[i]->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+ fullbright_shader[i]->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
+ fullbright_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
+ fullbright_shader[i]->unbind();
+ }
- simple_shader = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram :
- (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram;
+ simple_shader[0] = (LLPipeline::sImpostorRender) ? &gDeferredAlphaImpostorProgram :
+ (LLPipeline::sUnderWaterRender) ? &gDeferredAlphaWaterProgram : &gDeferredAlphaProgram;
+ simple_shader[1] = simple_shader[0]->mRiggedVariant;
//prime simple shader (loads shadow relevant uniforms)
- gPipeline.bindDeferredShader(*simple_shader);
-
- simple_shader->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
+ for (int i = 0; i < 2; ++i)
+ {
+ gPipeline.bindDeferredShader(*simple_shader[i]);
+ simple_shader[i]->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f / 2.2f));
+ simple_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
+ }
}
else if (!LLPipeline::sImpostorRender)
{
@@ -133,16 +145,21 @@ void LLDrawPoolAlpha::beginPostDeferredPass(S32 pass)
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 = fullbright_shader = &gObjectFullbrightAlphaMaskProgram;
- gObjectFullbrightAlphaMaskProgram.bind();
- gObjectFullbrightAlphaMaskProgram.setMinimumAlpha(0.33f);
+ simple_shader[0] = fullbright_shader[0] = &gObjectFullbrightAlphaMaskProgram;
+ simple_shader[1] = fullbright_shader[1] = simple_shader[0]->mRiggedVariant;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ simple_shader[i]->bind();
+ simple_shader[i]->setMinimumAlpha(0.33f);
+ }
}
deferred_render = TRUE;
if (mShaderLevel > 0)
{
// Start out with no shaders.
- current_shader = target_shader = NULL;
+ target_shader = NULL;
}
gPipeline.enableLightsDynamic();
}
@@ -155,7 +172,7 @@ void LLDrawPoolAlpha::endPostDeferredPass(S32 pass)
{
gPipeline.mDeferredDepth.flush();
gPipeline.mScreen.bindTarget();
- gObjectFullbrightAlphaMaskProgram.unbind();
+ LLGLSLShader::sCurBoundShaderPtr->unbind();
}
deferred_render = FALSE;
@@ -172,51 +189,46 @@ void LLDrawPoolAlpha::beginRenderPass(S32 pass)
{
LL_PROFILE_ZONE_SCOPED;
- simple_shader = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram :
+ simple_shader[0] = (LLPipeline::sImpostorRender) ? &gObjectSimpleImpostorProgram :
(LLPipeline::sUnderWaterRender) ? &gObjectSimpleWaterProgram : &gObjectSimpleProgram;
- fullbright_shader = (LLPipeline::sImpostorRender) ? &gObjectFullbrightProgram :
+ fullbright_shader[0] = (LLPipeline::sImpostorRender) ? &gObjectFullbrightProgram :
(LLPipeline::sUnderWaterRender) ? &gObjectFullbrightWaterProgram : &gObjectFullbrightProgram;
- emissive_shader = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram :
+ emissive_shader[0] = (LLPipeline::sImpostorRender) ? &gObjectEmissiveProgram :
(LLPipeline::sUnderWaterRender) ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
+ simple_shader[1] = simple_shader[0]->mRiggedVariant;
+ fullbright_shader[1] = fullbright_shader[0]->mRiggedVariant;
+ emissive_shader[1] = emissive_shader[0]->mRiggedVariant;
+
if (LLPipeline::sImpostorRender)
{
- if (mShaderLevel > 0)
- {
- fullbright_shader->bind();
- fullbright_shader->setMinimumAlpha(0.5f);
- fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
- simple_shader->bind();
- simple_shader->setMinimumAlpha(0.5f);
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
- }
- else
+ for (int i = 0; i < 2; ++i)
{
- gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); //OK
+ fullbright_shader[i]->bind();
+ fullbright_shader[i]->setMinimumAlpha(0.5f);
+ fullbright_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
+ simple_shader[i]->bind();
+ simple_shader[i]->setMinimumAlpha(0.5f);
+ simple_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
}
}
else
{
- if (mShaderLevel > 0)
- {
- fullbright_shader->bind();
- fullbright_shader->setMinimumAlpha(0.f);
- fullbright_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
- simple_shader->bind();
- simple_shader->setMinimumAlpha(0.f);
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
- }
- else
+ for (int i = 0; i < 2; ++i)
{
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK
+ fullbright_shader[i]->bind();
+ fullbright_shader[i]->setMinimumAlpha(0.f);
+ fullbright_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
+ simple_shader[i]->bind();
+ simple_shader[i]->setMinimumAlpha(0.f);
+ simple_shader[i]->uniform1i(LLShaderMgr::NO_ATMO, LLPipeline::sRenderingHUDs ? 1 : 0);
}
}
gPipeline.enableLightsDynamic();
LLGLSLShader::bindNoShader();
- current_shader = NULL;
}
void LLDrawPoolAlpha::endRenderPass( S32 pass )
@@ -266,14 +278,7 @@ void LLDrawPoolAlpha::render(S32 pass)
gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
}
- if (mShaderLevel > 0)
- {
- renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, pass);
- }
- else
- {
- renderAlpha(getVertexDataMask(), pass);
- }
+ renderAlpha(getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2, pass);
gGL.setColorMask(true, false);
@@ -284,16 +289,8 @@ void LLDrawPoolAlpha::render(S32 pass)
if (sShowDebugAlpha)
{
- BOOL shaders = gPipeline.canUseVertexShaders();
- if(shaders)
- {
- gHighlightProgram.bind();
- }
- else
- {
- gPipeline.enableLightsFullbright();
- }
-
+ gHighlightProgram.bind();
+
gGL.diffuseColor4f(1,0,0,1);
LLViewerFetchedTexture::sSmokeImagep->addTextureStats(1024.f*1024.f);
@@ -315,10 +312,23 @@ void LLDrawPoolAlpha::render(S32 pass)
gGL.diffuseColor4f(0, 1, 0, 1);
pushBatches(LLRenderPass::PASS_INVISIBLE, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
- if(shaders)
- {
- gHighlightProgram.unbind();
- }
+ gHighlightProgram.mRiggedVariant->bind();
+ gGL.diffuseColor4f(1, 0, 0, 1);
+
+ pushRiggedBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_ALPHA_INVISIBLE_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+
+ // Material alpha mask
+ gGL.diffuseColor4f(0, 0, 1, 1);
+ pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+
+ gGL.diffuseColor4f(0, 1, 0, 1);
+ pushRiggedBatches(LLRenderPass::PASS_INVISIBLE_RIGGED, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, FALSE);
+ LLGLSLShader::sCurBoundShaderPtr->unbind();
}
}
@@ -375,7 +385,7 @@ inline void Draw(LLDrawInfo* draw, U32 mask)
draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
}
-bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material, LLGLSLShader* current_shader)
+bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material)
{
bool tex_setup = false;
@@ -393,7 +403,7 @@ bool LLDrawPoolAlpha::TexSetup(LLDrawInfo* draw, bool use_material, LLGLSLShader
current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, draw->mSpecularMap);
}
}
- else if (current_shader == simple_shader)
+ else if (current_shader == simple_shader[0] || current_shader == simple_shader[1])
{
current_shader->bindTexture(LLShaderMgr::BUMP_MAP, LLViewerFetchedTexture::sFlatNormalImagep);
current_shader->bindTexture(LLShaderMgr::SPECULAR_MAP, LLViewerFetchedTexture::sWhiteImagep);
@@ -450,81 +460,86 @@ void LLDrawPoolAlpha::RestoreTexSetup(bool tex_setup)
}
}
-void LLDrawPoolAlpha::renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights)
-{
- gPipeline.enableLightsFullbright();
- fullbright_shader->bind();
- fullbright_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.0f);
-
- for (LLDrawInfo* draw : fullbrights)
- {
- bool tex_setup = TexSetup(draw, false, fullbright_shader);
-
- LLGLEnableFunc stencil_test(GL_STENCIL_TEST, draw->mSelected, &LLGLCommonFunc::selected_stencil_test);
- gGL.blendFunc((LLRender::eBlendFactor) draw->mBlendFuncSrc, (LLRender::eBlendFactor) draw->mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
-
- Draw(draw, mask & ~(LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2));
- RestoreTexSetup(tex_setup);
- }
- fullbright_shader->unbind();
-}
-
void LLDrawPoolAlpha::drawEmissive(U32 mask, LLDrawInfo* draw)
{
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
draw->mVertexBuffer->setBufferFast((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE);
draw->mVertexBuffer->drawRangeFast(draw->mDrawMode, draw->mStart, draw->mEnd, draw->mCount, draw->mOffset);
}
-void LLDrawPoolAlpha::drawEmissiveInline(U32 mask, LLDrawInfo* draw)
+
+void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives)
{
+ emissive_shader[0]->bind();
+ emissive_shader[0]->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
+
+ gPipeline.enableLightsDynamic();
+
// install glow-accumulating blend mode
- gGL.blendFunc(
- LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color
- LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow)
+ // don't touch color, add to alpha (glow)
+ gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE);
- emissive_shader->bind();
-
- drawEmissive(mask, draw);
+ for (LLDrawInfo* draw : emissives)
+ {
+ bool tex_setup = TexSetup(draw, false);
+ drawEmissive(mask, draw);
+ RestoreTexSetup(tex_setup);
+ }
- // restore our alpha blend mode
- gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
+ // restore our alpha blend mode
+ gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
- current_shader->bind();
+ emissive_shader[0]->unbind();
}
-void LLDrawPoolAlpha::renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives)
+void LLDrawPoolAlpha::renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives)
{
- emissive_shader->bind();
- emissive_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
+ emissive_shader[1]->bind();
+ emissive_shader[1]->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, 1.f);
gPipeline.enableLightsDynamic();
+ mask |= LLVertexBuffer::MAP_WEIGHT4;
// install glow-accumulating blend mode
// don't touch color, add to alpha (glow)
- gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE);
-
+ gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, LLRender::BF_ONE, LLRender::BF_ONE);
+
+ LLVOAvatar* lastAvatar = nullptr;
+ U64 lastMeshId = 0;
+
for (LLDrawInfo* draw : emissives)
{
- bool tex_setup = TexSetup(draw, false, emissive_shader);
+ bool tex_setup = TexSetup(draw, false);
+ if (lastAvatar != draw->mAvatar || lastMeshId != draw->mSkinInfo->mHash)
+ {
+ if (!uploadMatrixPalette(*draw))
+ { // failed to upload matrix palette, skip rendering
+ continue;
+ }
+ lastAvatar = draw->mAvatar;
+ lastMeshId = draw->mSkinInfo->mHash;
+ }
drawEmissive(mask, draw);
RestoreTexSetup(tex_setup);
}
// restore our alpha blend mode
- gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
+ gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor);
- emissive_shader->unbind();
+ emissive_shader[1]->unbind();
}
void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
{
LL_PROFILE_ZONE_SCOPED;
- BOOL batch_fullbrights = gSavedSettings.getBOOL("RenderAlphaBatchFullbrights");
- BOOL batch_emissives = gSavedSettings.getBOOL("RenderAlphaBatchEmissives");
- BOOL initialized_lighting = FALSE;
+ BOOL initialized_lighting = FALSE;
BOOL light_enabled = TRUE;
-
- for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
+
+ LLVOAvatar* lastAvatar = nullptr;
+ U64 lastMeshId = 0;
+ LLGLSLShader* lastAvatarShader = nullptr;
+
+ for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i)
{
LL_PROFILE_ZONE_NAMED("renderAlpha - group");
LLSpatialGroup* group = *i;
@@ -535,9 +550,9 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
!group->isDead())
{
static std::vector<LLDrawInfo*> emissives;
- static std::vector<LLDrawInfo*> fullbrights;
+ static std::vector<LLDrawInfo*> rigged_emissives;
emissives.resize(0);
- fullbrights.resize(0);
+ rigged_emissives.resize(0);
bool is_particle_or_hud_particle = group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_PARTICLE
|| group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE;
@@ -579,12 +594,6 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
}
}
- if (params.mFullbright && batch_fullbrights)
- {
- fullbrights.push_back(&params);
- continue;
- }
-
LLRenderPass::applyModelMatrix(params);
LLMaterial* mat = NULL;
@@ -600,7 +609,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
if (light_enabled || !initialized_lighting)
{
initialized_lighting = TRUE;
- target_shader = fullbright_shader;
+ target_shader = fullbright_shader[0];
light_enabled = FALSE;
}
@@ -609,7 +618,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
else if (!light_enabled || !initialized_lighting)
{
initialized_lighting = TRUE;
- target_shader = simple_shader;
+ target_shader = simple_shader[0];
light_enabled = TRUE;
}
@@ -625,27 +634,36 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
target_shader = &(gDeferredMaterialWaterProgram[mask]);
}
+ if (params.mAvatar != nullptr)
+ {
+ llassert(target_shader->mRiggedVariant != nullptr);
+ target_shader = target_shader->mRiggedVariant;
+ }
+
if (current_shader != target_shader)
{
gPipeline.bindDeferredShader(*target_shader);
- current_shader = target_shader;
}
}
else if (!params.mFullbright)
{
- target_shader = simple_shader;
+ target_shader = simple_shader[0];
}
else
{
- target_shader = fullbright_shader;
+ target_shader = fullbright_shader[0];
}
- if(current_shader != target_shader)
- {// If we need shaders, and we're not ALREADY using the proper shader, then bind it
- // (this way we won't rebind shaders unnecessarily).
- current_shader = target_shader;
- current_shader->bind();
- }
+ if (params.mAvatar != nullptr)
+ {
+ target_shader = target_shader->mRiggedVariant;
+ }
+
+ if (current_shader != target_shader)
+ {// If we need shaders, and we're not ALREADY using the proper shader, then bind it
+ // (this way we won't rebind shaders unnecessarily).
+ target_shader->bind();
+ }
LLVector4 spec_color(1, 1, 1, 1);
F32 env_intensity = 0.0f;
@@ -661,7 +679,7 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
if (current_shader)
{
- current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[0], spec_color.mV[1], spec_color.mV[2], spec_color.mV[3]);
+ current_shader->uniform4f(LLShaderMgr::SPECULAR_COLOR, spec_color.mV[0], spec_color.mV[1], spec_color.mV[2], spec_color.mV[3]);
current_shader->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env_intensity);
current_shader->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, brightness);
}
@@ -671,32 +689,54 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
params.mGroup->rebuildMesh();
}
- bool tex_setup = TexSetup(&params, (mat != nullptr), current_shader);
+ if (params.mAvatar != nullptr)
+ {
+ if (lastAvatar != params.mAvatar ||
+ lastMeshId != params.mSkinInfo->mHash ||
+ lastAvatarShader != LLGLSLShader::sCurBoundShaderPtr)
+ {
+ if (!uploadMatrixPalette(params))
+ {
+ continue;
+ }
+ lastAvatar = params.mAvatar;
+ lastMeshId = params.mSkinInfo->mHash;
+ lastAvatarShader = LLGLSLShader::sCurBoundShaderPtr;
+ }
+ }
+
+ bool tex_setup = TexSetup(&params, (mat != nullptr));
{
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor);
- params.mVertexBuffer->setBufferFast(mask & ~(params.mFullbright ? (LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2) : 0));
-
+ U32 drawMask = mask;
+ if (params.mFullbright)
{
- params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
+ drawMask &= ~(LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_TEXCOORD1 | LLVertexBuffer::MAP_TEXCOORD2);
}
+ if (params.mAvatar != nullptr)
+ {
+ drawMask |= LLVertexBuffer::MAP_WEIGHT4;
+ }
+
+ params.mVertexBuffer->setBufferFast(drawMask);
+ params.mVertexBuffer->drawRangeFast(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);
}
// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow). Interleaving these state-changing calls is expensive, but glow must be drawn Z-sorted with alpha.
- if (current_shader &&
- draw_glow_for_this_partition &&
+ if (draw_glow_for_this_partition &&
params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE))
{
- if (batch_emissives)
+ if (params.mAvatar != nullptr)
{
- emissives.push_back(&params);
+ rigged_emissives.push_back(&params);
}
else
{
- drawEmissiveInline(mask, &params);
- }
+ emissives.push_back(&params);
+ }
}
if (tex_setup)
@@ -708,41 +748,56 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask, S32 pass)
}
}
-
- bool rebind = false;
- if (batch_fullbrights)
{
- if (!fullbrights.empty())
+ bool rebind = false;
+ LLGLSLShader* lastShader = current_shader;
+ if (!emissives.empty())
{
- light_enabled = false;
- renderFullbrights(mask, fullbrights);
+ light_enabled = true;
+ renderEmissives(mask, emissives);
rebind = true;
}
- }
- if (batch_emissives)
- {
- if (!emissives.empty())
+ if (!rigged_emissives.empty())
{
light_enabled = true;
- renderEmissives(mask, emissives);
+ renderRiggedEmissives(mask, rigged_emissives);
rebind = true;
}
- }
- if (current_shader && rebind)
- {
- current_shader->bind();
+ if (lastShader && rebind)
+ {
+ lastShader->bind();
+ }
}
- }
+ }
}
gGL.setSceneBlendType(LLRender::BT_ALPHA);
- LLVertexBuffer::unbind();
-
+ LLVertexBuffer::unbind();
+
if (!light_enabled)
{
gPipeline.enableLightsDynamic();
}
}
+
+bool LLDrawPoolAlpha::uploadMatrixPalette(const LLDrawInfo& params)
+{
+ const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo);
+ U32 count = mpc.mMatrixPalette.size();
+
+ if (count == 0)
+ {
+ //skin info not loaded yet, don't render
+ return false;
+ }
+
+ LLGLSLShader::sCurBoundShaderPtr->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX,
+ count,
+ FALSE,
+ (GLfloat*)&(mpc.mGLMp[0]));
+
+ return true;
+}
diff --git a/indra/newview/lldrawpoolalpha.h b/indra/newview/lldrawpoolalpha.h
index a50b1d929e..64c17c3fef 100644
--- a/indra/newview/lldrawpoolalpha.h
+++ b/indra/newview/lldrawpoolalpha.h
@@ -65,23 +65,22 @@ public:
void renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE);
void renderAlpha(U32 mask, S32 pass);
void renderAlphaHighlight(U32 mask);
-
+ bool uploadMatrixPalette(const LLDrawInfo& params);
+
static BOOL sShowDebugAlpha;
private:
- LLGLSLShader* current_shader;
LLGLSLShader* target_shader;
- LLGLSLShader* simple_shader;
- LLGLSLShader* fullbright_shader;
- LLGLSLShader* emissive_shader;
- void renderFullbrights(U32 mask, std::vector<LLDrawInfo*>& fullbrights);
- void renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives);
+ // setup by beginFooPass, [0] is static variant, [1] is rigged variant
+ LLGLSLShader* simple_shader[2] = { nullptr };
+ LLGLSLShader* fullbright_shader[2] = { nullptr };
+ LLGLSLShader* emissive_shader[2] = { nullptr };
void drawEmissive(U32 mask, LLDrawInfo* draw);
- void drawEmissiveInline(U32 mask, LLDrawInfo* draw);
-
- bool TexSetup(LLDrawInfo* draw, bool use_material, LLGLSLShader* current_shader);
+ void renderEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives);
+ void renderRiggedEmissives(U32 mask, std::vector<LLDrawInfo*>& emissives);
+ bool TexSetup(LLDrawInfo* draw, bool use_material);
void RestoreTexSetup(bool tex_setup);
// our 'normal' alpha blend function for this pass
@@ -89,6 +88,9 @@ private:
LLRender::eBlendFactor mColorDFactor;
LLRender::eBlendFactor mAlphaSFactor;
LLRender::eBlendFactor mAlphaDFactor;
+
+ // if true, we're executing a rigged render pass
+ bool mRigged = false;
};
class LLDrawPoolAlphaPostWater : public LLDrawPoolAlpha
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 5b51e9db24..125cd3fd5b 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -126,13 +126,6 @@ BOOL LLDrawPoolAvatar::isDead()
return FALSE;
}
- for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i)
- {
- if (mRiggedFace[i].size() > 0)
- {
- return FALSE;
- }
- }
return TRUE;
}
@@ -159,17 +152,6 @@ void LLDrawPoolAvatar::prerender()
{
sBufferUsage = GL_STREAM_DRAW_ARB;
}
-
- if (!mDrawFace.empty())
- {
- const LLFace *facep = mDrawFace[0];
- if (facep && facep->getDrawable())
- {
- LLVOAvatar* avatarp = (LLVOAvatar *)facep->getDrawable()->getVObj().get();
- updateRiggedVertexBuffers(avatarp);
- updateSkinInfoMatrixPalettes(avatarp);
- }
- }
}
LLMatrix4& LLDrawPoolAvatar::getModelView()
@@ -215,15 +197,6 @@ void LLDrawPoolAvatar::beginDeferredPass(S32 pass)
case 2:
beginDeferredSkinned();
break;
- case 3:
- beginDeferredRiggedSimple();
- break;
- case 4:
- beginDeferredRiggedBump();
- break;
- default:
- beginDeferredRiggedMaterial(pass-5);
- break;
}
}
@@ -250,15 +223,6 @@ void LLDrawPoolAvatar::endDeferredPass(S32 pass)
case 2:
endDeferredSkinned();
break;
- case 3:
- endDeferredRiggedSimple();
- break;
- case 4:
- endDeferredRiggedBump();
- break;
- default:
- endDeferredRiggedMaterial(pass-5);
- break;
}
}
@@ -271,176 +235,51 @@ void LLDrawPoolAvatar::renderDeferred(S32 pass)
S32 LLDrawPoolAvatar::getNumPostDeferredPasses()
{
- return 10;
+ return 1;
}
void LLDrawPoolAvatar::beginPostDeferredPass(S32 pass)
{
LL_PROFILE_ZONE_SCOPED
- switch (pass)
- {
- case 0:
- beginPostDeferredAlpha();
- break;
- case 1:
- beginRiggedFullbright();
- break;
- case 2:
- beginRiggedFullbrightShiny();
- break;
- case 3:
- beginDeferredRiggedAlpha();
- break;
- case 4:
- beginRiggedFullbrightAlpha();
- break;
- case 9:
- beginRiggedGlow();
- break;
- default:
- beginDeferredRiggedMaterialAlpha(pass-5);
- break;
- }
-}
-
-void LLDrawPoolAvatar::beginPostDeferredAlpha()
-{
- LL_PROFILE_ZONE_SCOPED
-
- sSkipOpaque = TRUE;
- sShaderLevel = mShaderLevel;
- sVertexProgram = &gDeferredAvatarAlphaProgram;
- sRenderingSkinned = TRUE;
+ sSkipOpaque = TRUE;
+ sShaderLevel = mShaderLevel;
+ sVertexProgram = &gDeferredAvatarAlphaProgram;
+ sRenderingSkinned = TRUE;
- gPipeline.bindDeferredShader(*sVertexProgram);
+ gPipeline.bindDeferredShader(*sVertexProgram);
- sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
-
- sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
-}
-
-void LLDrawPoolAvatar::beginDeferredRiggedAlpha()
-{
- LL_PROFILE_ZONE_SCOPED
+ sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);
- sVertexProgram = &gDeferredSkinnedAlphaProgram;
- gPipeline.bindDeferredShader(*sVertexProgram);
- sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- gPipeline.enableLightsDynamic();
-}
-
-void LLDrawPoolAvatar::beginDeferredRiggedMaterialAlpha(S32 pass)
-{
- LL_PROFILE_ZONE_SCOPED
-
- switch (pass)
- {
- case 0: pass = 1; break;
- case 1: pass = 5; break;
- case 2: pass = 9; break;
- default: pass = 13; break;
- }
-
- pass += LLMaterial::SHADER_COUNT;
-
- sVertexProgram = &gDeferredMaterialProgram[pass];
-
- if (LLPipeline::sUnderWaterRender)
- {
- sVertexProgram = &(gDeferredMaterialWaterProgram[pass]);
- }
-
- gPipeline.bindDeferredShader(*sVertexProgram);
- sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
- specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
- gPipeline.enableLightsDynamic();
-}
-
-void LLDrawPoolAvatar::endDeferredRiggedAlpha()
-{
- LL_PROFILE_ZONE_SCOPED
-
- LLVertexBuffer::unbind();
- gPipeline.unbindDeferredShader(*sVertexProgram);
- sDiffuseChannel = 0;
- normal_channel = -1;
- specular_channel = -1;
- sVertexProgram = NULL;
+ sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
}
void LLDrawPoolAvatar::endPostDeferredPass(S32 pass)
{
LL_PROFILE_ZONE_SCOPED
+ // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
+ sRenderingSkinned = FALSE;
+ sSkipOpaque = FALSE;
- switch (pass)
- {
- case 0:
- endPostDeferredAlpha();
- break;
- case 1:
- endRiggedFullbright();
- break;
- case 2:
- endRiggedFullbrightShiny();
- break;
- case 3:
- endDeferredRiggedAlpha();
- break;
- case 4:
- endRiggedFullbrightAlpha();
- break;
- case 5:
- endRiggedGlow();
- break;
- default:
- endDeferredRiggedAlpha();
- break;
- }
-}
-
-void LLDrawPoolAvatar::endPostDeferredAlpha()
-{
- LL_PROFILE_ZONE_SCOPED
-
- // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done
- sRenderingSkinned = FALSE;
- sSkipOpaque = FALSE;
-
- gPipeline.unbindDeferredShader(*sVertexProgram);
- sDiffuseChannel = 0;
- sShaderLevel = mShaderLevel;
+ gPipeline.unbindDeferredShader(*sVertexProgram);
+ sDiffuseChannel = 0;
+ sShaderLevel = mShaderLevel;
}
void LLDrawPoolAvatar::renderPostDeferred(S32 pass)
{
LL_PROFILE_ZONE_SCOPED
- static 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 material alpha 1
- 10,//rigged material alpha 2
- 11,//rigged material alpha 3
- 12,//rigged material alpha 4
- 13, //rigged glow
- };
-
- S32 p = actual_pass[pass];
-
+ is_post_deferred_render = true;
if (LLPipeline::sImpostorRender)
{ //HACK for impostors so actual pass ends up being proper pass
- p -= 2;
+ render(0);
}
-
- is_post_deferred_render = true;
- render(p);
- is_post_deferred_render = false;
+ else
+ {
+ render(2);
+ }
+ is_post_deferred_render = false;
}
@@ -506,68 +345,12 @@ void LLDrawPoolAvatar::beginShadowPass(S32 pass)
gGL.diffuseColor4f(1, 1, 1, 1);
}
- else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND)
- {
- sVertexProgram = &gDeferredAttachmentAlphaShadowProgram;
-
- // bind diffuse tex so we can reference the alpha channel...
- S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP);
- sDiffuseChannel = 0;
- if (loc != -1)
- {
- sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- }
-
- if ((sShaderLevel > 0)) // for hardware blending
- {
- sRenderingSkinned = TRUE;
- sVertexProgram->bind();
- }
-
- gGL.diffuseColor4f(1, 1, 1, 1);
- }
- else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK)
- {
- sVertexProgram = &gDeferredAttachmentAlphaMaskShadowProgram;
-
- // bind diffuse tex so we can reference the alpha channel...
- S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP);
- sDiffuseChannel = 0;
- if (loc != -1)
- {
- sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- }
-
- if ((sShaderLevel > 0)) // for hardware blending
- {
- sRenderingSkinned = TRUE;
- sVertexProgram->bind();
- }
-
- gGL.diffuseColor4f(1, 1, 1, 1);
- }
- else // SHADOW_PASS_ATTACHMENT_OPAQUE
- {
- sVertexProgram = &gDeferredAttachmentShadowProgram;
- S32 loc = sVertexProgram->getUniformLocation(LLViewerShaderMgr::DIFFUSE_MAP);
- sDiffuseChannel = 0;
- if (loc != -1)
- {
- sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- }
- sVertexProgram->bind();
- }
}
void LLDrawPoolAvatar::endShadowPass(S32 pass)
{
LL_PROFILE_ZONE_SCOPED;
- if (pass == SHADOW_PASS_ATTACHMENT_OPAQUE)
- {
- LLVertexBuffer::unbind();
- }
-
if (sShaderLevel > 0)
{
sVertexProgram->unbind();
@@ -625,77 +408,17 @@ void LLDrawPoolAvatar::renderShadow(S32 pass)
avatarp->renderSkinned();
LLDrawPoolAvatar::sSkipOpaque = false;
}
- else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_BLEND) // rigged alpha
- {
- LLDrawPoolAvatar::sSkipOpaque = true;
- renderRigged(avatarp, RIGGED_MATERIAL_ALPHA);
- renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE);
- renderRigged(avatarp, RIGGED_ALPHA);
- renderRigged(avatarp, RIGGED_FULLBRIGHT_ALPHA);
- renderRigged(avatarp, RIGGED_GLOW);
- renderRigged(avatarp, RIGGED_SPECMAP_BLEND);
- renderRigged(avatarp, RIGGED_NORMMAP_BLEND);
- renderRigged(avatarp, RIGGED_NORMSPEC_BLEND);
- LLDrawPoolAvatar::sSkipOpaque = false;
- }
- else if (pass == SHADOW_PASS_ATTACHMENT_ALPHA_MASK) // rigged alpha mask
- {
- LLDrawPoolAvatar::sSkipOpaque = true;
- renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK);
- renderRigged(avatarp, RIGGED_NORMMAP_MASK);
- renderRigged(avatarp, RIGGED_SPECMAP_MASK);
- renderRigged(avatarp, RIGGED_NORMSPEC_MASK);
- renderRigged(avatarp, RIGGED_GLOW);
- LLDrawPoolAvatar::sSkipOpaque = false;
- }
- else // rigged opaque (SHADOW_PASS_ATTACHMENT_OPAQUE
- {
- LLDrawPoolAvatar::sSkipTransparent = true;
- renderRigged(avatarp, RIGGED_MATERIAL);
- renderRigged(avatarp, RIGGED_SPECMAP);
- renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE);
- renderRigged(avatarp, RIGGED_NORMMAP);
- renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);
- renderRigged(avatarp, RIGGED_NORMSPEC);
- renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE);
- renderRigged(avatarp, RIGGED_SIMPLE);
- renderRigged(avatarp, RIGGED_FULLBRIGHT);
- renderRigged(avatarp, RIGGED_SHINY);
- renderRigged(avatarp, RIGGED_FULLBRIGHT_SHINY);
- renderRigged(avatarp, RIGGED_GLOW);
- renderRigged(avatarp, RIGGED_DEFERRED_BUMP);
- renderRigged(avatarp, RIGGED_DEFERRED_SIMPLE);
- LLDrawPoolAvatar::sSkipTransparent = false;
- }
}
S32 LLDrawPoolAvatar::getNumPasses()
{
- LL_PROFILE_ZONE_SCOPED
-
- if (LLPipeline::sImpostorRender)
- {
- return 8;
- }
- else
- {
- return 10;
- }
+ return 3;
}
S32 LLDrawPoolAvatar::getNumDeferredPasses()
{
- LL_PROFILE_ZONE_SCOPED
-
- if (LLPipeline::sImpostorRender)
- {
- return 19;
- }
- else
- {
- return 21;
- }
+ return 3;
}
@@ -733,27 +456,6 @@ void LLDrawPoolAvatar::beginRenderPass(S32 pass)
case 2:
beginSkinned();
break;
- 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;
}
if (pass == 0)
@@ -782,27 +484,6 @@ void LLDrawPoolAvatar::endRenderPass(S32 pass)
case 2:
endSkinned();
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;
}
}
@@ -1037,462 +718,6 @@ void LLDrawPoolAvatar::endSkinned()
gGL.getTexUnit(0)->activate();
}
-void LLDrawPoolAvatar::beginRiggedSimple()
-{
- LL_PROFILE_ZONE_SCOPED
-
- 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();
- if (LLPipeline::sRenderingHUDs)
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
- }
-}
-
-void LLDrawPoolAvatar::endRiggedSimple()
-{
- LL_PROFILE_ZONE_SCOPED
-
- LLVertexBuffer::unbind();
- if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
- {
- sVertexProgram->unbind();
- sVertexProgram = NULL;
- }
-}
-
-void LLDrawPoolAvatar::beginRiggedAlpha()
-{
- LL_PROFILE_ZONE_SCOPED
-
- beginRiggedSimple();
-}
-
-void LLDrawPoolAvatar::endRiggedAlpha()
-{
- LL_PROFILE_ZONE_SCOPED
-
- endRiggedSimple();
-}
-
-
-void LLDrawPoolAvatar::beginRiggedFullbrightAlpha()
-{
- LL_PROFILE_ZONE_SCOPED
-
- beginRiggedFullbright();
-}
-
-void LLDrawPoolAvatar::endRiggedFullbrightAlpha()
-{
- LL_PROFILE_ZONE_SCOPED
-
- endRiggedFullbright();
-}
-
-void LLDrawPoolAvatar::beginRiggedGlow()
-{
- LL_PROFILE_ZONE_SCOPED
-
- if (sShaderLevel > 0)
- {
- if (LLPipeline::sUnderWaterRender)
- {
- sVertexProgram = &gSkinnedObjectEmissiveWaterProgram;
- }
- else
- {
- sVertexProgram = &gSkinnedObjectEmissiveProgram;
- }
- }
- else
- {
- if (LLPipeline::sUnderWaterRender)
- {
- sVertexProgram = &gObjectEmissiveNonIndexedWaterProgram;
- }
- else
- {
- sVertexProgram = &gObjectEmissiveNonIndexedProgram;
- }
- }
-
- if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
- {
- sDiffuseChannel = 0;
- sVertexProgram->bind();
-
- sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, LLPipeline::sRenderDeferred ? 2.2f : 1.1f);
-
- if (LLPipeline::sRenderingHUDs)
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
-
- F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
- sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
- }
-}
-
-void LLDrawPoolAvatar::endRiggedGlow()
-{
- LL_PROFILE_ZONE_SCOPED
-
- endRiggedFullbright();
-}
-
-void LLDrawPoolAvatar::beginRiggedFullbright()
-{
- LL_PROFILE_ZONE_SCOPED
-
- if (sShaderLevel > 0)
- {
- if (LLPipeline::sUnderWaterRender)
- {
- sVertexProgram = &gSkinnedObjectFullbrightWaterProgram;
- }
- else
- {
- if (LLPipeline::sRenderDeferred)
- {
- sVertexProgram = &gDeferredSkinnedFullbrightProgram;
- }
- else
- {
- sVertexProgram = &gSkinnedObjectFullbrightProgram;
- }
- }
- }
- else
- {
- if (LLPipeline::sUnderWaterRender)
- {
- sVertexProgram = &gObjectFullbrightNonIndexedWaterProgram;
- }
- else
- {
- sVertexProgram = &gObjectFullbrightNonIndexedProgram;
- }
- }
-
- if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
- {
- sDiffuseChannel = 0;
- sVertexProgram->bind();
-
- if (LLPipeline::sRenderingHUDs)
- {
- sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else if (LLPipeline::sRenderDeferred)
- {
- sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
- sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
- }
- else
- {
- sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
- }
-}
-
-void LLDrawPoolAvatar::endRiggedFullbright()
-{
- LL_PROFILE_ZONE_SCOPED
-
- LLVertexBuffer::unbind();
- if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
- {
- sVertexProgram->unbind();
- sVertexProgram = NULL;
- }
-}
-
-void LLDrawPoolAvatar::beginRiggedShinySimple()
-{
- LL_PROFILE_ZONE_SCOPED
-
- 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();
- if (LLPipeline::sRenderingHUDs)
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
- LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
- }
-}
-
-void LLDrawPoolAvatar::endRiggedShinySimple()
-{
- LL_PROFILE_ZONE_SCOPED
-
- LLVertexBuffer::unbind();
- if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
- {
- LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
- sVertexProgram->unbind();
- sVertexProgram = NULL;
- }
-}
-
-void LLDrawPoolAvatar::beginRiggedFullbrightShiny()
-{
- LL_PROFILE_ZONE_SCOPED
-
- if (sShaderLevel > 0)
- {
- if (LLPipeline::sUnderWaterRender)
- {
- sVertexProgram = &gSkinnedObjectFullbrightShinyWaterProgram;
- }
- else
- {
- if (LLPipeline::sRenderDeferred)
- {
- sVertexProgram = &gDeferredSkinnedFullbrightShinyProgram;
- }
- else
- {
- sVertexProgram = &gSkinnedObjectFullbrightShinyProgram;
- }
- }
- }
- else
- {
- if (LLPipeline::sUnderWaterRender)
- {
- sVertexProgram = &gObjectFullbrightShinyNonIndexedWaterProgram;
- }
- else
- {
- sVertexProgram = &gObjectFullbrightShinyNonIndexedProgram;
- }
- }
-
- if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
- {
- sVertexProgram->bind();
- if (LLPipeline::sRenderingHUDs)
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
- LLDrawPoolBump::bindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
-
- if (LLPipeline::sRenderingHUDs)
- {
- sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else if (LLPipeline::sRenderDeferred)
- {
- sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
- F32 gamma = gSavedSettings.getF32("RenderDeferredDisplayGamma");
- sVertexProgram->uniform1f(LLShaderMgr::DISPLAY_GAMMA, (gamma > 0.1f) ? 1.0f / gamma : (1.0f/2.2f));
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
- else
- {
- sVertexProgram->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
- }
-}
-
-void LLDrawPoolAvatar::endRiggedFullbrightShiny()
-{
- LL_PROFILE_ZONE_SCOPED
-
- LLVertexBuffer::unbind();
- if (sShaderLevel > 0 || gPipeline.canUseVertexShaders())
- {
- LLDrawPoolBump::unbindCubeMap(sVertexProgram, 2, sDiffuseChannel, cube_channel, false);
- sVertexProgram->unbind();
- sVertexProgram = NULL;
- }
-}
-
-
-void LLDrawPoolAvatar::beginDeferredRiggedSimple()
-{
- LL_PROFILE_ZONE_SCOPED
-
- sVertexProgram = &gDeferredSkinnedDiffuseProgram;
- sDiffuseChannel = 0;
- sVertexProgram->bind();
- if (LLPipeline::sRenderingHUDs)
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
-}
-
-void LLDrawPoolAvatar::endDeferredRiggedSimple()
-{
- LL_PROFILE_ZONE_SCOPED
-
- LLVertexBuffer::unbind();
- sVertexProgram->unbind();
- sVertexProgram = NULL;
-}
-
-void LLDrawPoolAvatar::beginDeferredRiggedBump()
-{
- LL_PROFILE_ZONE_SCOPED
-
- sVertexProgram = &gDeferredSkinnedBumpProgram;
- sVertexProgram->bind();
- if (LLPipeline::sRenderingHUDs)
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
- normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
- sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
-}
-
-void LLDrawPoolAvatar::endDeferredRiggedBump()
-{
- LL_PROFILE_ZONE_SCOPED
-
- LLVertexBuffer::unbind();
- sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP);
- sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- sVertexProgram->unbind();
- normal_channel = -1;
- sDiffuseChannel = 0;
- sVertexProgram = NULL;
-}
-
-void LLDrawPoolAvatar::beginDeferredRiggedMaterial(S32 pass)
-{
- LL_PROFILE_ZONE_SCOPED
-
- if (pass == 1 ||
- pass == 5 ||
- pass == 9 ||
- pass == 13)
- { //skip alpha passes
- return;
- }
- sVertexProgram = &gDeferredMaterialProgram[pass+LLMaterial::SHADER_COUNT];
-
- if (LLPipeline::sUnderWaterRender)
- {
- sVertexProgram = &(gDeferredMaterialWaterProgram[pass+LLMaterial::SHADER_COUNT]);
- }
-
- sVertexProgram->bind();
- if (LLPipeline::sRenderingHUDs)
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- sVertexProgram->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
- normal_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::BUMP_MAP);
- specular_channel = sVertexProgram->enableTexture(LLViewerShaderMgr::SPECULAR_MAP);
- sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
-}
-
-void LLDrawPoolAvatar::endDeferredRiggedMaterial(S32 pass)
-{
- LL_PROFILE_ZONE_SCOPED
-
- if (pass == 1 ||
- pass == 5 ||
- pass == 9 ||
- pass == 13)
- {
- return;
- }
-
- LLVertexBuffer::unbind();
- sVertexProgram->disableTexture(LLViewerShaderMgr::BUMP_MAP);
- sVertexProgram->disableTexture(LLViewerShaderMgr::SPECULAR_MAP);
- sVertexProgram->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- sVertexProgram->unbind();
- normal_channel = -1;
- sDiffuseChannel = 0;
- sVertexProgram = NULL;
-}
-
void LLDrawPoolAvatar::beginDeferredSkinned()
{
LL_PROFILE_ZONE_SCOPED
@@ -1654,142 +879,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
return;
}
- if (pass == 3)
- {
- if (is_deferred_render)
- {
- renderDeferredRiggedSimple(avatarp);
- }
- else
- {
- renderRiggedSimple(avatarp);
-
- if (LLPipeline::sRenderDeferred)
- { //render "simple" materials
- renderRigged(avatarp, RIGGED_MATERIAL);
- renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_MASK);
- renderRigged(avatarp, RIGGED_MATERIAL_ALPHA_EMISSIVE);
- renderRigged(avatarp, RIGGED_NORMMAP);
- renderRigged(avatarp, RIGGED_NORMMAP_MASK);
- renderRigged(avatarp, RIGGED_NORMMAP_EMISSIVE);
- renderRigged(avatarp, RIGGED_SPECMAP);
- renderRigged(avatarp, RIGGED_SPECMAP_MASK);
- renderRigged(avatarp, RIGGED_SPECMAP_EMISSIVE);
- renderRigged(avatarp, RIGGED_NORMSPEC);
- renderRigged(avatarp, RIGGED_NORMSPEC_MASK);
- renderRigged(avatarp, RIGGED_NORMSPEC_EMISSIVE);
- }
- }
- return;
- }
-
- if (pass == 4)
- {
- if (is_deferred_render)
- {
- renderDeferredRiggedBump(avatarp);
- }
- else
- {
- renderRiggedFullbright(avatarp);
- }
-
- return;
- }
-
- if (is_deferred_render && pass >= 5 && pass <= 21)
- {
- S32 p = pass-5;
-
- if (p != 1 &&
- p != 5 &&
- p != 9 &&
- p != 13)
- {
- renderDeferredRiggedMaterial(avatarp, p);
- }
- return;
- }
-
-
-
-
- if (pass == 5)
- {
- renderRiggedShinySimple(avatarp);
-
- return;
- }
-
- if (pass == 6)
- {
- renderRiggedFullbrightShiny(avatarp);
- return;
- }
-
- if (pass >= 7 && pass < 13)
- {
- if (pass == 7)
- {
- renderRiggedAlpha(avatarp);
-
- if (LLPipeline::sRenderDeferred && !is_post_deferred_render)
- { //render transparent materials under water
- 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);
-
- renderRigged(avatarp, RIGGED_MATERIAL_ALPHA);
- renderRigged(avatarp, RIGGED_SPECMAP_BLEND);
- renderRigged(avatarp, RIGGED_NORMMAP_BLEND);
- renderRigged(avatarp, RIGGED_NORMSPEC_BLEND);
-
- gGL.setColorMask(true, false);
- }
- return;
- }
-
- if (pass == 8)
- {
- renderRiggedFullbrightAlpha(avatarp);
- return;
- }
-
- if (LLPipeline::sRenderDeferred && is_post_deferred_render)
- {
- S32 p = 0;
- switch (pass)
- {
- case 9: p = 1; break;
- case 10: p = 5; break;
- case 11: p = 9; break;
- case 12: p = 13; break;
- }
-
- {
- LLGLEnable blend(GL_BLEND);
- renderDeferredRiggedMaterial(avatarp, p);
- }
- return;
- }
- else if (pass == 9)
- {
- renderRiggedGlow(avatarp);
- return;
- }
- }
-
- if (pass == 13)
- {
- renderRiggedGlow(avatarp);
-
- return;
- }
-
if ((sShaderLevel >= SHADER_LEVEL_CLOTH))
{
LLMatrix4 rot_mat;
@@ -1821,776 +910,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)
}
}
-void LLDrawPoolAvatar::getRiggedGeometry(
- LLFace* face,
- LLPointer<LLVertexBuffer>& buffer,
- U32 data_mask,
- const LLMeshSkinInfo* skin,
- LLVolume* volume,
- const LLVolumeFace& vol_face)
-{
- LL_PROFILE_ZONE_SCOPED
-
- face->setGeomIndex(0);
- face->setIndicesIndex(0);
-
- if (face->getTextureIndex() != FACE_DO_NOT_BATCH_TEXTURES)
- {
- face->setDrawInfo(NULL);
- }
-
- //rigged faces do not batch textures
- face->setTextureIndex(FACE_DO_NOT_BATCH_TEXTURES);
-
- if (buffer.isNull() || buffer->getTypeMask() != data_mask || !buffer->isWriteable())
- {
- // 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);
- }
-
- if (!buffer->allocateBuffer(vol_face.mNumVertices, vol_face.mNumIndices, true))
- {
- LL_WARNS("LLDrawPoolAvatar") << "Failed to allocate Vertex Buffer to "
- << vol_face.mNumVertices << " vertices and "
- << vol_face.mNumIndices << " indices" << LL_ENDL;
- // allocate dummy triangle
- buffer->allocateBuffer(1, 3, true);
- memset((U8*)buffer->getMappedData(), 0, buffer->getSize());
- memset((U8*)buffer->getMappedIndices(), 0, buffer->getIndicesSize());
- }
- }
- else
- {
- //resize existing buffer
- if(!buffer->resizeBuffer(vol_face.mNumVertices, vol_face.mNumIndices))
- {
- LL_WARNS("LLDrawPoolAvatar") << "Failed to resize Vertex Buffer to "
- << vol_face.mNumVertices << " vertices and "
- << vol_face.mNumIndices << " indices" << LL_ENDL;
- // allocate dummy triangle
- buffer->resizeBuffer(1, 3);
- memset((U8*)buffer->getMappedData(), 0, buffer->getSize());
- memset((U8*)buffer->getMappedIndices(), 0, buffer->getIndicesSize());
- }
- }
-
- face->setSize(buffer->getNumVerts(), buffer->getNumIndices());
- face->setVertexBuffer(buffer);
-
- U16 offset = 0;
-
- LLMatrix4 mat_vert = LLMatrix4(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);
-
- //let getGeometryVolume know if alpha should override shiny
- U32 type = gPipeline.getPoolTypeFromTE(face->getTextureEntry(), face->getTexture());
-
- if (type == LLDrawPool::POOL_ALPHA)
- {
- face->setPoolType(LLDrawPool::POOL_ALPHA);
- }
- else
- {
- face->setPoolType(mType); // either POOL_AVATAR or POOL_CONTROL_AV
- }
-
- //LL_INFOS() << "Rebuilt face " << face->getTEOffset() << " of " << face->getDrawable() << " at " << gFrameTimeSeconds << LL_ENDL;
-
- // Let getGeometryVolume know if a texture matrix is in play
- if (face->mTextureMatrix)
- {
- face->setState(LLFace::TEXTURE_ANIM);
- }
- else
- {
- face->clearState(LLFace::TEXTURE_ANIM);
- }
- face->getGeometryVolume(*volume, face->getTEOffset(), mat_vert, mat_normal, offset, true);
-
- buffer->flush();
-}
-
-void LLDrawPoolAvatar::updateRiggedFaceVertexBuffer(
- LLVOAvatar* avatar,
- LLFace* face,
- const LLVOVolume* vobj,
- LLVolume* volume,
- LLVolumeFace& vol_face)
-{
- LL_PROFILE_ZONE_SCOPED;
-
- LLVector4a* weights = vol_face.mWeights;
- if (!weights)
- {
- return;
- }
-
- if (!vobj || vobj->isNoLOD())
- {
- return;
- }
-
- LLPointer<LLVertexBuffer> buffer = face->getVertexBuffer();
- LLDrawable* drawable = face->getDrawable();
-
- const U32 max_joints = LLSkinningUtil::getMaxJointCount();
-
-#if USE_SEPARATE_JOINT_INDICES_AND_WEIGHTS
- #define CONDITION_WEIGHT(f) ((U8)llclamp((S32)f, (S32)0, (S32)max_joints-1))
- LLVector4a* just_weights = vol_face.mJustWeights;
- // we need to calculate the separated indices and store just the matrix weights for this vol...
- if (!vol_face.mJointIndices)
- {
- // not very consty after all...
- vol_face.allocateJointIndices(vol_face.mNumVertices);
- just_weights = vol_face.mJustWeights;
-
- U8* joint_indices_cursor = vol_face.mJointIndices;
- for (int i = 0; i < vol_face.mNumVertices; i++)
- {
- F32* w = weights[i].getF32ptr();
- F32* w_ = just_weights[i].getF32ptr();
-
- F32 w0 = floorf(w[0]);
- F32 w1 = floorf(w[1]);
- F32 w2 = floorf(w[2]);
- F32 w3 = floorf(w[3]);
-
- joint_indices_cursor[0] = CONDITION_WEIGHT(w0);
- joint_indices_cursor[1] = CONDITION_WEIGHT(w1);
- joint_indices_cursor[2] = CONDITION_WEIGHT(w2);
- joint_indices_cursor[3] = CONDITION_WEIGHT(w3);
-
- // remove joint portion of combined weight
- w_[0] = w[0] - w0;
- w_[1] = w[1] - w1;
- w_[2] = w[2] - w2;
- w_[3] = w[3] - w3;
-
- joint_indices_cursor += 4;
- }
- }
-#endif
-
- U32 data_mask = face->getRiggedVertexBufferDataMask();
- const LLMeshSkinInfo* skin = nullptr;
-
- if (buffer.isNull() ||
- buffer->getTypeMask() != data_mask ||
- buffer->getNumVerts() != vol_face.mNumVertices ||
- buffer->getNumIndices() != vol_face.mNumIndices ||
- (drawable && drawable->isState(LLDrawable::REBUILD_ALL)))
- {
- LL_PROFILE_ZONE_NAMED("Rigged VBO Rebuild");
- skin = vobj->getSkinInfo();
- // FIXME ugly const cast
- LLSkinningUtil::scrubInvalidJoints(avatar, const_cast<LLMeshSkinInfo*>(skin));
-
- if (!vol_face.mWeightsScrubbed)
- {
- LLSkinningUtil::scrubSkinWeights(weights, vol_face.mNumVertices, skin);
- vol_face.mWeightsScrubbed = TRUE;
- }
-
- if (drawable && drawable->isState(LLDrawable::REBUILD_ALL))
- {
- //rebuild EVERY face in the drawable, not just this one, to avoid missing drawable wide rebuild issues
- for (S32 i = 0; i < drawable->getNumFaces(); ++i)
- {
- LLFace* facep = drawable->getFace(i);
- U32 face_data_mask = facep->getRiggedVertexBufferDataMask();
- if (face_data_mask)
- {
- LLPointer<LLVertexBuffer> cur_buffer = facep->getVertexBuffer();
- const LLVolumeFace& cur_vol_face = volume->getVolumeFace(i);
- getRiggedGeometry(facep, cur_buffer, face_data_mask, skin, volume, cur_vol_face);
- }
- }
- drawable->clearState(LLDrawable::REBUILD_ALL);
-
- buffer = face->getVertexBuffer();
- }
- else
- {
- //just rebuild this face
- getRiggedGeometry(face, buffer, data_mask, skin, volume, vol_face);
- }
- }
-
- if (sShaderLevel <= 0 &&
- face->mLastSkinTime < avatar->getLastSkinTime() &&
- !buffer.isNull() &&
- buffer->getNumVerts() == vol_face.mNumVertices &&
- buffer->getNumIndices() == vol_face.mNumIndices)
- {
- LL_PROFILE_ZONE_NAMED("Software Skinning");
- //perform software vertex skinning for this face
- LLStrider<LLVector3> position;
- LLStrider<LLVector3> normal;
-
- 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;
-
- const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, vobj->getMeshID());
- const LLMatrix4a* mat = &(mpc.mMatrixPalette[0]);
- const LLMatrix4a& bind_shape_matrix = mpc.mBindShapeMatrix;
-
- if (!mpc.mMatrixPalette.empty())
- {
- for (U32 j = 0; j < buffer->getNumVerts(); ++j)
- {
- LLMatrix4a final_mat;
- LLSkinningUtil::getPerVertexSkinMatrix(weights[j].getF32ptr(), mat, false, final_mat, max_joints);
-
- LLVector4a& v = vol_face.mPositions[j];
- LLVector4a t;
- LLVector4a dst;
- bind_shape_matrix.affineTransform(v, t);
- final_mat.affineTransform(t, dst);
- pos[j] = dst;
-
- if (norm)
- {
- LLVector4a& n = vol_face.mNormals[j];
- bind_shape_matrix.rotate(n, t);
- final_mat.rotate(t, dst);
- //dst.normalize3fast();
- norm[j] = dst;
- }
- }
- }
- }
-}
-
-void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
-{
- LL_PROFILE_ZONE_SCOPED
-
- if (!avatar->shouldRenderRigged())
- {
- return;
- }
-
- LLUUID lastMeshId;
-
- for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
- {
- LL_PROFILE_ZONE_NAMED("Render Rigged Face");
- LLFace* face = mRiggedFace[type][i];
-
- S32 offset = face->getIndicesStart();
- U32 count = face->getIndicesCount();
-
- U16 start = face->getGeomStart();
- U16 end = start + face->getGeomCount()-1;
-
- 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;
- }
-
- U32 data_mask = LLFace::getRiggedDataMask(type);
-
- LLVertexBuffer* buff = face->getVertexBuffer();
-
- const LLTextureEntry* tex_entry = face->getTextureEntry();
- LLMaterial* mat = tex_entry ? tex_entry->getMaterialParams().get() : nullptr;
-
- if (LLDrawPoolAvatar::sShadowPass >= 0)
- {
- bool is_alpha_blend = false;
- bool is_alpha_mask = false;
-
- LLViewerTexture* tex = face->getTexture(LLRender::DIFFUSE_MAP);
- if (tex)
- {
- if (tex->getIsAlphaMask())
- {
- is_alpha_mask = true;
- }
- }
-
- if (tex)
- {
- LLGLenum image_format = tex->getPrimaryFormat();
- if (!is_alpha_mask && (image_format == GL_RGBA || image_format == GL_ALPHA))
- {
- is_alpha_blend = true;
- }
- }
-
- if (tex_entry)
- {
- if (tex_entry->getAlpha() <= 0.99f)
- {
- is_alpha_blend = true;
- }
- }
-
- if (mat)
- {
- switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaMode()))
- {
- case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
- {
- is_alpha_mask = true;
- is_alpha_blend = false;
- }
- break;
-
- case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
- {
- is_alpha_blend = true;
- is_alpha_mask = false;
- }
- break;
-
- case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
- case LLMaterial::DIFFUSE_ALPHA_MODE_DEFAULT:
- case LLMaterial::DIFFUSE_ALPHA_MODE_NONE:
- default:
- is_alpha_blend = false;
- is_alpha_mask = false;
- break;
- }
- }
-
- // if this is alpha mask content and we're doing opaques or a non-alpha-mask shadow pass...
- if (is_alpha_mask && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_MASK))
- {
- return;
- }
-
- // if this is alpha blend content and we're doing opaques or a non-alpha-blend shadow pass...
- if (is_alpha_blend && (LLDrawPoolAvatar::sSkipTransparent || LLDrawPoolAvatar::sShadowPass != SHADOW_PASS_ATTACHMENT_ALPHA_BLEND))
- {
- return;
- }
-
- // if this is opaque content and we're skipping opaques...
- if (!is_alpha_mask && !is_alpha_blend && LLDrawPoolAvatar::sSkipOpaque)
- {
- return;
- }
- }
-
- if (buff)
- {
- if (sShaderLevel > 0)
- {
- auto& meshId = vobj->getMeshID();
-
- if (lastMeshId != meshId) // <== only upload matrix palette to GL if the skininfo changed
- {
- // upload matrix palette to shader
- const MatrixPaletteCache& mpc = updateSkinInfoMatrixPalette(avatar, meshId);
- U32 count = mpc.mMatrixPalette.size();
-
- if (count == 0)
- {
- //skin info not loaded yet, don't render
- continue;
- }
-
- LLDrawPoolAvatar::sVertexProgram->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX,
- count,
- FALSE,
- (GLfloat*) &(mpc.mGLMp[0]));
- }
-
- lastMeshId = meshId;
- }
- else
- {
- data_mask &= ~LLVertexBuffer::MAP_WEIGHT4;
- }
-
- if (mat)
- {
- //order is important here LLRender::DIFFUSE_MAP should be last, becouse it change
- //(gGL).mCurrTextureUnitIndex
- LLViewerTexture* specular = NULL;
- if (LLPipeline::sImpostorRender)
- {
- specular = LLViewerTextureManager::findFetchedTexture(gBlackSquareID, TEX_LIST_STANDARD);
- llassert(NULL != specular);
- }
- else
- {
- specular = face->getTexture(LLRender::SPECULAR_MAP);
- }
- if (specular && specular_channel >= 0)
- {
- gGL.getTexUnit(specular_channel)->bindFast(specular);
- }
-
- if (normal_channel >= 0)
- {
- auto* texture = face->getTexture(LLRender::NORMAL_MAP);
- if (texture)
- {
- gGL.getTexUnit(normal_channel)->bindFast(texture);
- }
- //else
- //{
- // TODO handle missing normal map
- //}
- }
-
- gGL.getTexUnit(sDiffuseChannel)->bindFast(face->getTexture(LLRender::DIFFUSE_MAP));
-
-
- LLColor4 col = mat->getSpecularLightColor();
- F32 spec = mat->getSpecularLightExponent()/255.f;
-
- F32 env = mat->getEnvironmentIntensity()/255.f;
-
- if (mat->getSpecularID().isNull())
- {
- env = tex_entry->getShiny()*0.25f;
- col.set(env,env,env,0);
- spec = env;
- }
-
- BOOL fullbright = tex_entry->getFullbright();
-
- sVertexProgram->uniform1f(LLShaderMgr::EMISSIVE_BRIGHTNESS, fullbright ? 1.f : 0.f);
- sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec);
- sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env);
-
- if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
- {
- F32 cutoff = mat->getAlphaMaskCutoff()/255.f;
- sVertexProgram->setMinimumAlpha(cutoff);
- }
- else
- {
- sVertexProgram->setMinimumAlpha(0.f);
- }
-
- if (!LLPipeline::sShadowRender && !LLPipeline::sReflectionRender)
- {
- for (U32 i = 0; i < LLRender::NUM_TEXTURE_CHANNELS; ++i)
- {
- LLViewerTexture* tex = face->getTexture(i);
- if (tex)
- {
- tex->addTextureStats(avatar->getPixelArea());
- }
- }
- }
- }
- else
- {
- sVertexProgram->setMinimumAlpha(0.f);
- if (normal_channel > -1)
- {
- LLDrawPoolBump::bindBumpMap(face, normal_channel);
- }
-
- gGL.getTexUnit(sDiffuseChannel)->bindFast(face->getTexture());
-
- }
-
- if (face->mTextureMatrix && vobj->mTexAnimMode)
- {
- U32 tex_index = gGL.getCurrentTexUnitIndex();
-
- if (tex_index <= 1)
- {
- gGL.matrixMode(LLRender::eMatrixMode(LLRender::MM_TEXTURE0 + tex_index));
- gGL.pushMatrix();
- gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix);
- }
-
- buff->setBufferFast(data_mask);
- buff->drawRangeFast(LLRender::TRIANGLES, start, end, count, offset);
-
- if (tex_index <= 1)
- {
- gGL.matrixMode(LLRender::eMatrixMode(LLRender::MM_TEXTURE0 + tex_index));
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- }
- }
- else
- {
- buff->setBufferFast(data_mask);
- buff->drawRangeFast(LLRender::TRIANGLES, start, end, count, offset);
- }
- }
- }
-}
-
-void LLDrawPoolAvatar::renderDeferredRiggedSimple(LLVOAvatar* avatar)
-{
- LL_PROFILE_ZONE_SCOPED
-
- renderRigged(avatar, RIGGED_DEFERRED_SIMPLE);
-}
-
-void LLDrawPoolAvatar::renderDeferredRiggedBump(LLVOAvatar* avatar)
-{
- LL_PROFILE_ZONE_SCOPED
-
- renderRigged(avatar, RIGGED_DEFERRED_BUMP);
-}
-
-void LLDrawPoolAvatar::renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass)
-{
- LL_PROFILE_ZONE_SCOPED
-
- renderRigged(avatar, pass);
-}
-
static LLTrace::BlockTimerStatHandle FTM_RIGGED_VBO("Rigged VBO");
-void LLDrawPoolAvatar::updateRiggedVertexBuffers(LLVOAvatar* avatar)
-{
- LL_RECORD_BLOCK_TIME(FTM_RIGGED_VBO);
-
- //update rigged vertex buffers
- for (U32 type = 0; type < NUM_RIGGED_PASSES; ++type)
- {
- LL_PROFILE_ZONE_NAMED("Pass");
- for (U32 i = 0; i < mRiggedFace[type].size(); ++i)
- {
- LL_PROFILE_ZONE_NAMED("Face");
- LLFace* face = mRiggedFace[type][i];
- LLDrawable* drawable = face->getDrawable();
- if (!drawable)
- {
- continue;
- }
-
- LLVOVolume* vobj = drawable->getVOVolume();
-
- if (!vobj || vobj->isNoLOD())
- {
- continue;
- }
-
- LLVolume* volume = vobj->getVolume();
- S32 te = face->getTEOffset();
-
- if (!volume || volume->getNumVolumeFaces() <= te)
- {
- continue;
- }
-
- LLVolumeFace& vol_face = volume->getVolumeFace(te);
- updateRiggedFaceVertexBuffer(avatar, face, vobj, volume, vol_face);
- }
- }
-}
-
-void LLDrawPoolAvatar::updateSkinInfoMatrixPalettes(LLVOAvatar* avatarp)
-{
- LL_PROFILE_ZONE_SCOPED;
- //evict matrix palettes from the cache that haven't been updated in 10 frames
- for (matrix_palette_cache_t::iterator iter = mMatrixPaletteCache.begin(); iter != mMatrixPaletteCache.end(); )
- {
- if (gFrameCount - iter->second.mFrame > 10)
- {
- iter = mMatrixPaletteCache.erase(iter);
- }
- else
- {
- ++iter;
- }
- }
-}
-
-const LLDrawPoolAvatar::MatrixPaletteCache& LLDrawPoolAvatar::updateSkinInfoMatrixPalette(LLVOAvatar * avatarp, const LLUUID& meshId)
-{
- MatrixPaletteCache& entry = mMatrixPaletteCache[meshId];
-
- if (entry.mFrame != gFrameCount)
- {
- LL_PROFILE_ZONE_SCOPED;
-
- const LLMeshSkinInfo* skin = gMeshRepo.getSkinInfo(meshId);
- entry.mFrame = gFrameCount;
-
- if (skin != nullptr)
- {
- entry.mBindShapeMatrix = skin->mBindShapeMatrix;
-
- //build matrix palette
- U32 count = LLSkinningUtil::getMeshJointCount(skin);
- entry.mMatrixPalette.resize(count);
- LLSkinningUtil::initSkinningMatrixPalette(&(entry.mMatrixPalette[0]), count, skin, avatarp);
-
- const LLMatrix4a* mat = &(entry.mMatrixPalette[0]);
-
- entry.mGLMp.resize(count * 12);
-
- F32* mp = &(entry.mGLMp[0]);
-
- for (U32 i = 0; i < count; ++i)
- {
- F32* m = (F32*)mat[i].mMatrix[0].getF32ptr();
-
- U32 idx = i * 12;
-
- mp[idx + 0] = m[0];
- mp[idx + 1] = m[1];
- mp[idx + 2] = m[2];
- mp[idx + 3] = m[12];
-
- mp[idx + 4] = m[4];
- mp[idx + 5] = m[5];
- mp[idx + 6] = m[6];
- mp[idx + 7] = m[13];
-
- mp[idx + 8] = m[8];
- mp[idx + 9] = m[9];
- mp[idx + 10] = m[10];
- mp[idx + 11] = m[14];
- }
- }
- else
- {
- entry.mMatrixPalette.resize(0);
- entry.mGLMp.resize(0);
- }
- }
-
- return entry;
-}
-
-void LLDrawPoolAvatar::renderRiggedSimple(LLVOAvatar* avatar)
-{
- LL_PROFILE_ZONE_SCOPED
-
- renderRigged(avatar, RIGGED_SIMPLE);
-}
-
-void LLDrawPoolAvatar::renderRiggedFullbright(LLVOAvatar* avatar)
-{
- LL_PROFILE_ZONE_SCOPED
-
- renderRigged(avatar, RIGGED_FULLBRIGHT);
-}
-
-
-void LLDrawPoolAvatar::renderRiggedShinySimple(LLVOAvatar* avatar)
-{
- LL_PROFILE_ZONE_SCOPED
-
- renderRigged(avatar, RIGGED_SHINY);
-}
-
-void LLDrawPoolAvatar::renderRiggedFullbrightShiny(LLVOAvatar* avatar)
-{
- LL_PROFILE_ZONE_SCOPED
-
- renderRigged(avatar, RIGGED_FULLBRIGHT_SHINY);
-}
-
-void LLDrawPoolAvatar::renderRiggedAlpha(LLVOAvatar* avatar)
-{
- LL_PROFILE_ZONE_SCOPED
-
- if (!mRiggedFace[RIGGED_ALPHA].empty())
- {
- 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);
-
- renderRigged(avatar, RIGGED_ALPHA);
- gGL.setColorMask(true, false);
- }
-}
-
-void LLDrawPoolAvatar::renderRiggedFullbrightAlpha(LLVOAvatar* avatar)
-{
- LL_PROFILE_ZONE_SCOPED
-
- if (!mRiggedFace[RIGGED_FULLBRIGHT_ALPHA].empty())
- {
- 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);
-
- renderRigged(avatar, RIGGED_FULLBRIGHT_ALPHA);
- gGL.setColorMask(true, false);
- }
-}
-
-void LLDrawPoolAvatar::renderRiggedGlow(LLVOAvatar* avatar)
-{
- LL_PROFILE_ZONE_SCOPED
-
- if (!mRiggedFace[RIGGED_GLOW].empty())
- {
- 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);
-
- renderRigged(avatar, RIGGED_GLOW, true);
-
- gGL.setColorMask(true, false);
- gGL.setSceneBlendType(LLRender::BT_ALPHA);
- }
-}
-
-
-
//-----------------------------------------------------------------------------
// getDebugTexture()
//-----------------------------------------------------------------------------
@@ -2619,66 +940,6 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const
return LLColor3(0.f, 1.f, 0.f);
}
-void LLDrawPoolAvatar::addRiggedFace(LLFace* facep, U32 type)
-{
- LL_PROFILE_ZONE_SCOPED
-
- llassert (facep->isState(LLFace::RIGGED));
- llassert(getType() == LLDrawPool::POOL_AVATAR || getType() == LLDrawPool::POOL_CONTROL_AV);
- if (facep->getPool() && facep->getPool() != this)
- {
- LL_ERRS() << "adding rigged face that's already in another pool" << LL_ENDL;
- }
- if (type >= NUM_RIGGED_PASSES)
- {
- LL_ERRS() << "Invalid rigged face type." << LL_ENDL;
- }
- if (facep->getRiggedIndex(type) != -1)
- {
- LL_ERRS() << "Tried to add a rigged face that's referenced elsewhere." << LL_ENDL;
- }
-
- facep->setRiggedIndex(type, mRiggedFace[type].size());
- facep->setPool(this);
- mRiggedFace[type].push_back(facep);
-}
-
-void LLDrawPoolAvatar::removeRiggedFace(LLFace* facep)
-{
- LL_PROFILE_ZONE_SCOPED
-
- llassert (facep->isState(LLFace::RIGGED));
- llassert(getType() == LLDrawPool::POOL_AVATAR || getType() == LLDrawPool::POOL_CONTROL_AV);
- if (facep->getPool() != this)
- {
- LL_ERRS() << "Tried to remove a rigged face from the wrong pool" << LL_ENDL;
- }
- facep->setPool(NULL);
-
- for (U32 i = 0; i < NUM_RIGGED_PASSES; ++i)
- {
- S32 index = facep->getRiggedIndex(i);
-
- if (index > -1)
- {
- if (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
- {
- LL_ERRS() << "Face reference data corrupt for rigged type " << i
- << ((mRiggedFace[i].size() <= index) ? "; wrong index (out of bounds)" : (mRiggedFace[i][index] != facep) ? "; wrong face pointer" : "")
- << LL_ENDL;
- }
- }
- }
-}
LLVertexBufferAvatar::LLVertexBufferAvatar()
: LLVertexBuffer(sDataMask,
diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h
index 800bbc5f62..21add39b21 100644
--- a/indra/newview/lldrawpoolavatar.h
+++ b/indra/newview/lldrawpoolavatar.h
@@ -62,119 +62,11 @@ public:
~LLDrawPoolAvatar();
/*virtual*/ BOOL isDead();
- typedef enum
- {
- RIGGED_MATERIAL=0,
- RIGGED_MATERIAL_ALPHA,
- RIGGED_MATERIAL_ALPHA_MASK,
- RIGGED_MATERIAL_ALPHA_EMISSIVE,
- RIGGED_SPECMAP,
- RIGGED_SPECMAP_BLEND,
- RIGGED_SPECMAP_MASK,
- RIGGED_SPECMAP_EMISSIVE,
- RIGGED_NORMMAP,
- RIGGED_NORMMAP_BLEND,
- RIGGED_NORMMAP_MASK,
- RIGGED_NORMMAP_EMISSIVE,
- RIGGED_NORMSPEC,
- RIGGED_NORMSPEC_BLEND,
- RIGGED_NORMSPEC_MASK,
- RIGGED_NORMSPEC_EMISSIVE,
- RIGGED_SIMPLE,
- RIGGED_FULLBRIGHT,
- RIGGED_SHINY,
- RIGGED_FULLBRIGHT_SHINY,
- RIGGED_GLOW,
- RIGGED_ALPHA,
- RIGGED_FULLBRIGHT_ALPHA,
- RIGGED_DEFERRED_BUMP,
- RIGGED_DEFERRED_SIMPLE,
- NUM_RIGGED_PASSES,
- RIGGED_UNKNOWN,
- } eRiggedPass;
-
- typedef enum
- {
- RIGGED_MATERIAL_MASK =
- LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_NORMAL |
- LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_COLOR |
- LLVertexBuffer::MAP_WEIGHT4,
- RIGGED_MATERIAL_ALPHA_VMASK = RIGGED_MATERIAL_MASK,
- RIGGED_MATERIAL_ALPHA_MASK_MASK = RIGGED_MATERIAL_MASK,
- RIGGED_MATERIAL_ALPHA_EMISSIVE_MASK = RIGGED_MATERIAL_MASK,
- RIGGED_SPECMAP_VMASK =
- LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_NORMAL |
- LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_TEXCOORD2 |
- LLVertexBuffer::MAP_COLOR |
- LLVertexBuffer::MAP_WEIGHT4,
- RIGGED_SPECMAP_BLEND_MASK = RIGGED_SPECMAP_VMASK,
- RIGGED_SPECMAP_MASK_MASK = RIGGED_SPECMAP_VMASK,
- RIGGED_SPECMAP_EMISSIVE_MASK = RIGGED_SPECMAP_VMASK,
- RIGGED_NORMMAP_VMASK =
- LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_NORMAL |
- LLVertexBuffer::MAP_TANGENT |
- LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_TEXCOORD1 |
- LLVertexBuffer::MAP_COLOR |
- LLVertexBuffer::MAP_WEIGHT4,
- RIGGED_NORMMAP_BLEND_MASK = RIGGED_NORMMAP_VMASK,
- RIGGED_NORMMAP_MASK_MASK = RIGGED_NORMMAP_VMASK,
- RIGGED_NORMMAP_EMISSIVE_MASK = RIGGED_NORMMAP_VMASK,
- RIGGED_NORMSPEC_VMASK =
- LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_NORMAL |
- LLVertexBuffer::MAP_TANGENT |
- LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_TEXCOORD1 |
- LLVertexBuffer::MAP_TEXCOORD2 |
- LLVertexBuffer::MAP_COLOR |
- LLVertexBuffer::MAP_WEIGHT4,
- RIGGED_NORMSPEC_BLEND_MASK = RIGGED_NORMSPEC_VMASK,
- RIGGED_NORMSPEC_MASK_MASK = RIGGED_NORMSPEC_VMASK,
- RIGGED_NORMSPEC_EMISSIVE_MASK = RIGGED_NORMSPEC_VMASK,
- 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_EMISSIVE |
- 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_TANGENT |
- 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;
-
typedef enum
{
SHADOW_PASS_AVATAR_OPAQUE,
SHADOW_PASS_AVATAR_ALPHA_BLEND,
SHADOW_PASS_AVATAR_ALPHA_MASK,
- SHADOW_PASS_ATTACHMENT_ALPHA_BLEND,
- SHADOW_PASS_ATTACHMENT_ALPHA_MASK,
- SHADOW_PASS_ATTACHMENT_OPAQUE,
NUM_SHADOW_PASSES
} eShadowPass;
@@ -215,101 +107,19 @@ typedef enum
void endImpostor();
void endSkinned();
- void beginDeferredImpostor();
- void beginDeferredRigid();
- void beginDeferredSkinned();
-
- void endDeferredImpostor();
- void endDeferredRigid();
- void endDeferredSkinned();
-
- void beginPostDeferredAlpha();
- void endPostDeferredAlpha();
-
- void beginRiggedSimple();
- void beginRiggedFullbright();
- void beginRiggedFullbrightShiny();
- void beginRiggedShinySimple();
- void beginRiggedAlpha();
- void beginRiggedFullbrightAlpha();
- void beginRiggedGlow();
- void beginDeferredRiggedAlpha();
- void beginDeferredRiggedMaterial(S32 pass);
- void beginDeferredRiggedMaterialAlpha(S32 pass);
-
- void endRiggedSimple();
- void endRiggedFullbright();
- void endRiggedFullbrightShiny();
- void endRiggedShinySimple();
- void endRiggedAlpha();
- void endRiggedFullbrightAlpha();
- void endRiggedGlow();
- void endDeferredRiggedAlpha();
- void endDeferredRiggedMaterial(S32 pass);
- void endDeferredRiggedMaterialAlpha(S32 pass);
-
- void beginDeferredRiggedSimple();
- void beginDeferredRiggedBump();
-
- void endDeferredRiggedSimple();
- void endDeferredRiggedBump();
-
- void getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face);
- void updateRiggedFaceVertexBuffer(LLVOAvatar* avatar,
- LLFace* facep,
- const LLVOVolume* vobj,
- LLVolume* volume,
- LLVolumeFace& vol_face);
- void updateRiggedVertexBuffers(LLVOAvatar* avatar);
+ void beginDeferredRigid();
+ void beginDeferredImpostor();
+ void beginDeferredSkinned();
- void updateSkinInfoMatrixPalettes(LLVOAvatar* avatarp);
-
- 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);
- void renderDeferredRiggedMaterial(LLVOAvatar* avatar, S32 pass);
-
-
-
- void addRiggedFace(LLFace* facep, U32 type);
- void removeRiggedFace(LLFace* facep);
-
- std::vector<LLFace*> mRiggedFace[NUM_RIGGED_PASSES];
-
- LL_ALIGN_PREFIX(16)
- class MatrixPaletteCache
- {
- public:
- U32 mFrame;
- LLMeshSkinInfo::matrix_list_t mMatrixPalette;
- LL_ALIGN_16(LLMatrix4a mBindShapeMatrix);
- // Float array ready to be sent to GL
- std::vector<F32> mGLMp;
-
- MatrixPaletteCache() :
- mFrame(gFrameCount-1)
- {
- }
- } LL_ALIGN_POSTFIX(16);
-
- const MatrixPaletteCache& updateSkinInfoMatrixPalette(LLVOAvatar* avatarp, const LLUUID& meshId);
-
- typedef std::unordered_map<LLUUID, MatrixPaletteCache> matrix_palette_cache_t;
- matrix_palette_cache_t mMatrixPaletteCache;
+ void endDeferredRigid();
+ void endDeferredImpostor();
+ void endDeferredSkinned();
/*virtual*/ LLViewerTexture *getDebugTexture();
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null.
-
static BOOL sSkipOpaque;
static BOOL sSkipTransparent;
static S32 sShadowPass;
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 8f3b0c99b4..af8b194f38 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -47,6 +47,7 @@
#include "pipeline.h"
#include "llspatialpartition.h"
#include "llviewershadermgr.h"
+#include "llmodel.h"
//#include "llimagebmp.h"
//#include "../tools/imdebug/imdebug.h"
@@ -203,22 +204,11 @@ S32 LLDrawPoolBump::numBumpPasses()
{
if (mShaderLevel > 1)
{
- if (LLPipeline::sImpostorRender)
- {
- return 2;
- }
- else
- {
- return 3;
- }
- }
- else if (LLPipeline::sImpostorRender)
- {
- return 1;
+ return 6;
}
else
{
- return 2;
+ return 4;
}
}
else
@@ -235,6 +225,8 @@ S32 LLDrawPoolBump::getNumPasses()
void LLDrawPoolBump::beginRenderPass(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
+ mRigged = ((pass % 2) == 1);
+ pass /= 2;
switch( pass )
{
case 0:
@@ -267,7 +259,7 @@ void LLDrawPoolBump::render(S32 pass)
{
return;
}
-
+ pass /= 2;
switch( pass )
{
case 0:
@@ -295,6 +287,7 @@ void LLDrawPoolBump::render(S32 pass)
void LLDrawPoolBump::endRenderPass(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
+ pass /= 2;
switch( pass )
{
case 0:
@@ -326,12 +319,7 @@ void LLDrawPoolBump::endRenderPass(S32 pass)
void LLDrawPoolBump::beginShiny(bool invisible)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
- if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))||
- (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
- {
- return;
- }
-
+
mShiny = TRUE;
sVertexMask = VERTEX_MASK_SHINY;
// Second pass: environment map
@@ -340,31 +328,31 @@ void LLDrawPoolBump::beginShiny(bool invisible)
sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
}
- if (getShaderLevel() > 0)
+ if (LLPipeline::sUnderWaterRender)
{
- if (LLPipeline::sUnderWaterRender)
- {
- shader = &gObjectShinyWaterProgram;
- }
- else
- {
- shader = &gObjectShinyProgram;
- }
- shader->bind();
- if (LLPipeline::sRenderingHUDs)
- {
- shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
+ shader = &gObjectShinyWaterProgram;
}
else
{
- shader = NULL;
+ shader = &gObjectShinyProgram;
}
+ if (mRigged)
+ {
+ llassert(shader->mRiggedVariant);
+ shader = shader->mRiggedVariant;
+ }
+
+ shader->bind();
+ if (LLPipeline::sRenderingHUDs)
+ {
+ shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+ }
+ else
+ {
+ shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+ }
+
bindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible);
if (mShaderLevel > 1)
@@ -391,7 +379,6 @@ void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& di
shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
if (shader_level > 1)
{
- cube_map->setMatrix(1);
// Make sure that texture coord generation happens for tex unit 1, as that's the one we use for
// the cube map in the one pass shiny shaders
cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
@@ -403,7 +390,6 @@ void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& di
{
cube_channel = shader->enableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
diffuse_channel = -1;
- cube_map->setMatrix(0);
cube_map->enable(cube_channel);
}
gGL.getTexUnit(cube_channel)->bind(cube_map);
@@ -415,7 +401,6 @@ void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& di
diffuse_channel = -1;
gGL.getTexUnit(0)->disable();
cube_map->enable(0);
- cube_map->setMatrix(0);
gGL.getTexUnit(0)->bind(cube_map);
gGL.getTexUnit(0)->setTextureColorBlend(LLTexUnit::TBO_REPLACE, LLTexUnit::TBS_TEX_COLOR);
@@ -427,27 +412,32 @@ void LLDrawPoolBump::bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& di
void LLDrawPoolBump::renderShiny(bool invisible)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
- if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))||
- (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
- {
- return;
- }
-
+
if( gSky.mVOSkyp->getCubeMap() )
{
LLGLEnable blend_enable(GL_BLEND);
if (!invisible && mShaderLevel > 1)
{
- LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ if (mRigged)
+ {
+ LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_SHINY_RIGGED, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
+ else
+ {
+ LLRenderPass::pushBatches(LLRenderPass::PASS_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
}
else if (!invisible)
{
- renderGroups(LLRenderPass::PASS_SHINY, sVertexMask);
+ if (mRigged)
+ {
+ gPipeline.renderRiggedGroups(this, LLRenderPass::PASS_SHINY_RIGGED, sVertexMask, TRUE);
+ }
+ else
+ {
+ gPipeline.renderGroups(this, LLRenderPass::PASS_SHINY, sVertexMask, TRUE);
+ }
}
- //else // invisible (deprecated)
- //{
- //renderGroups(LLRenderPass::PASS_INVISI_SHINY, sVertexMask);
- //}
}
}
@@ -472,27 +462,12 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32&
// Moved below shader->disableTexture call to avoid false alarms from auto-re-enable of textures on stage 0
// MAINT-755
cube_map->disable();
- cube_map->restoreMatrix();
- }
-
- 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)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
- if ((!invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_SHINY))||
- (invisible && !gPipeline.hasRenderBatches(LLRenderPass::PASS_INVISI_SHINY)))
- {
- return;
- }
unbindCubeMap(shader, mShaderLevel, diffuse_channel, cube_channel, invisible);
if (shader)
@@ -508,11 +483,7 @@ void LLDrawPoolBump::endShiny(bool invisible)
void LLDrawPoolBump::beginFullbrightShiny()
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
- if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
- {
- return;
- }
-
+
sVertexMask = VERTEX_MASK_SHINY | LLVertexBuffer::MAP_TEXCOORD0;
// Second pass: environment map
@@ -533,6 +504,12 @@ void LLDrawPoolBump::beginFullbrightShiny()
}
}
+ if (mRigged)
+ {
+ llassert(shader->mRiggedVariant);
+ shader = shader->mRiggedVariant;
+ }
+
LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
if( cube_map )
{
@@ -553,9 +530,8 @@ void LLDrawPoolBump::beginFullbrightShiny()
LLVector3 vec = LLVector3(gShinyOrigin) * mat;
LLVector4 vec4(vec, gShinyOrigin.mV[3]);
- shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
+ shader->uniform4fv(LLViewerShaderMgr::SHINY_ORIGIN, 1, vec4.mV);
- cube_map->setMatrix(1);
// Make sure that texture coord generation happens for tex unit 1, as that's the one we use for
// the cube map in the one pass shiny shaders
gGL.getTexUnit(1)->disable();
@@ -579,10 +555,6 @@ void LLDrawPoolBump::beginFullbrightShiny()
void LLDrawPoolBump::renderFullbrightShiny()
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
- if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
- {
- return;
- }
if( gSky.mVOSkyp->getCubeMap() )
{
@@ -590,11 +562,25 @@ void LLDrawPoolBump::renderFullbrightShiny()
if (mShaderLevel > 1)
{
- LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ if (mRigged)
+ {
+ LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
+ else
+ {
+ LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
}
else
{
- LLRenderPass::renderTexture(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
+ if (mRigged)
+ {
+ LLRenderPass::pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED, sVertexMask);
+ }
+ else
+ {
+ LLRenderPass::pushBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY, sVertexMask);
+ }
}
}
}
@@ -602,18 +588,13 @@ void LLDrawPoolBump::renderFullbrightShiny()
void LLDrawPoolBump::endFullbrightShiny()
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_SHINY);
- if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_FULLBRIGHT_SHINY))
- {
- return;
- }
LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;
if( cube_map )
{
cube_map->disable();
- cube_map->restoreMatrix();
- /*if (diffuse_channel != 0)
+ /*if (diffuse_channel != 0)
{
shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
}
@@ -726,53 +707,22 @@ BOOL LLDrawPoolBump::bindBumpMap(U8 bump_code, LLViewerTexture* texture, F32 vsi
}
//static
-void LLDrawPoolBump::beginBump(U32 pass)
+void LLDrawPoolBump::beginBump()
{
- if (!gPipeline.hasRenderBatches(pass))
- {
- return;
- }
-
sVertexMask = VERTEX_MASK_BUMP;
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
// Optional second pass: emboss bump map
stop_glerror();
- 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);
+ shader = &gObjectBumpProgram;
- // TEXTURE UNIT 1
- gGL.getTexUnit(1)->activate();
-
- 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);
-
- // src = tex0 + (1 - tex1) - 0.5
- // = (bump0/2 + 0.5) + (1 - (bump1/2 + 0.5)) - 0.5
- // = (1 + bump0 - bump1) / 2
+ if (mRigged)
+ {
+ llassert(shader->mRiggedVariant);
+ shader = shader->mRiggedVariant;
+ }
-
- // 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);
- }
+ shader->bind();
gGL.setSceneBlendType(LLRender::BT_MULT_X2);
stop_glerror();
@@ -781,11 +731,6 @@ void LLDrawPoolBump::beginBump(U32 pass)
//static
void LLDrawPoolBump::renderBump(U32 pass)
{
- if (!gPipeline.hasRenderBatches(pass))
- {
- return;
- }
-
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
LLGLDisable fog(GL_FOG);
LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LEQUAL);
@@ -800,11 +745,6 @@ void LLDrawPoolBump::renderBump(U32 pass)
//static
void LLDrawPoolBump::endBump(U32 pass)
{
- if (!gPipeline.hasRenderBatches(pass))
- {
- return;
- }
-
if (LLGLSLShader::sNoFixedFunction)
{
gObjectBumpProgram.unbind();
@@ -828,7 +768,7 @@ S32 LLDrawPoolBump::getNumDeferredPasses()
{
if (gSavedSettings.getBOOL("RenderObjectBump"))
{
- return 1;
+ return 2;
}
else
{
@@ -838,66 +778,86 @@ S32 LLDrawPoolBump::getNumDeferredPasses()
void LLDrawPoolBump::beginDeferredPass(S32 pass)
{
- if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
+ if (!gPipeline.hasRenderBatches( pass == 0 ? LLRenderPass::PASS_BUMP : LLRenderPass::PASS_BUMP_RIGGED))
{
return;
}
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
mShiny = TRUE;
- gDeferredBumpProgram.bind();
- diffuse_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- bump_channel = gDeferredBumpProgram.enableTexture(LLViewerShaderMgr::BUMP_MAP);
+ gDeferredBumpProgram.bind(pass == 1);
+ diffuse_channel = LLGLSLShader::sCurBoundShaderPtr->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+ bump_channel = LLGLSLShader::sCurBoundShaderPtr->enableTexture(LLViewerShaderMgr::BUMP_MAP);
gGL.getTexUnit(diffuse_channel)->unbind(LLTexUnit::TT_TEXTURE);
gGL.getTexUnit(bump_channel)->unbind(LLTexUnit::TT_TEXTURE);
}
void LLDrawPoolBump::endDeferredPass(S32 pass)
{
- if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
+ if (!gPipeline.hasRenderBatches(pass == 0 ? LLRenderPass::PASS_BUMP : LLRenderPass::PASS_BUMP_RIGGED))
{
return;
}
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
mShiny = FALSE;
- gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
- gDeferredBumpProgram.disableTexture(LLViewerShaderMgr::BUMP_MAP);
- gDeferredBumpProgram.unbind();
+ LLGLSLShader::sCurBoundShaderPtr->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP);
+ LLGLSLShader::sCurBoundShaderPtr->disableTexture(LLViewerShaderMgr::BUMP_MAP);
+ LLGLSLShader::sCurBoundShaderPtr->unbind();
gGL.getTexUnit(0)->activate();
}
void LLDrawPoolBump::renderDeferred(S32 pass)
{
- if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
+ if (!gPipeline.hasRenderBatches(pass == 0 ? LLRenderPass::PASS_BUMP : LLRenderPass::PASS_BUMP_RIGGED))
{
return;
}
LL_RECORD_BLOCK_TIME(FTM_RENDER_BUMP);
- U32 type = LLRenderPass::PASS_BUMP;
- LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
- LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
+ bool rigged = pass == 1;
+ U32 type = rigged ? LLRenderPass::PASS_BUMP_RIGGED : LLRenderPass::PASS_BUMP;
+ LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
+ LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
- U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
-
- for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
- {
- LLDrawInfo& params = **i;
+ U32 mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_TANGENT | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR;
- gDeferredBumpProgram.setMinimumAlpha(params.mAlphaMaskCutoff);
- LLDrawPoolBump::bindBumpMap(params, bump_channel);
- pushBatch(params, mask, TRUE);
- }
+ LLVOAvatar* avatar = nullptr;
+ U64 skin = 0;
+
+ for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
+ {
+ LLDrawInfo& params = **i;
+
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(params.mAlphaMaskCutoff);
+ LLDrawPoolBump::bindBumpMap(params, bump_channel);
+
+ if (rigged)
+ {
+ if (avatar != params.mAvatar || skin != params.mSkinInfo->mHash)
+ {
+ uploadMatrixPalette(params);
+ avatar = params.mAvatar;
+ skin = params.mSkinInfo->mHash;
+ }
+ pushBatch(params, mask | LLVertexBuffer::MAP_WEIGHT4, TRUE, FALSE);
+ }
+ else
+ {
+ pushBatch(params, mask, TRUE, FALSE);
+ }
+ }
}
void LLDrawPoolBump::beginPostDeferredPass(S32 pass)
{
+ mRigged = ((pass % 2) == 1);
+ pass /= 2;
switch (pass)
{
case 0:
beginFullbrightShiny();
break;
case 1:
- beginBump(LLRenderPass::PASS_POST_BUMP);
+ beginBump();
break;
}
}
@@ -920,6 +880,7 @@ void LLDrawPoolBump::endPostDeferredPass(S32 pass)
void LLDrawPoolBump::renderPostDeferred(S32 pass)
{
+ pass /= 2;
switch (pass)
{
case 0:
@@ -1462,8 +1423,17 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI
void LLDrawPoolBump::renderBump(U32 type, U32 mask)
{
- LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
- LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
+ LLVOAvatar* avatar = nullptr;
+ U64 skin = 0;
+
+ if (mRigged)
+ { // nudge type enum and include skinweights for rigged pass
+ type += 1;
+ mask |= LLVertexBuffer::MAP_WEIGHT4;
+ }
+
+ LLCullResult::drawinfo_iterator begin = gPipeline.beginRenderMap(type);
+ LLCullResult::drawinfo_iterator end = gPipeline.endRenderMap(type);
for (LLCullResult::drawinfo_iterator i = begin; i != end; ++i)
{
@@ -1471,6 +1441,21 @@ void LLDrawPoolBump::renderBump(U32 type, U32 mask)
if (LLDrawPoolBump::bindBumpMap(params))
{
+ if (mRigged)
+ {
+ if (avatar != params.mAvatar || skin != params.mSkinInfo->mHash)
+ {
+ if (uploadMatrixPalette(params))
+ {
+ avatar = params.mAvatar;
+ skin = params.mSkinInfo->mHash;
+ }
+ else
+ {
+ continue;
+ }
+ }
+ }
pushBatch(params, mask, FALSE);
}
}
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index bab160c34d..624dbe3034 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -48,19 +48,19 @@ public:
static U32 sVertexMask;
BOOL mShiny;
- virtual U32 getVertexDataMask() { return sVertexMask; }
+ virtual U32 getVertexDataMask() override { return sVertexMask; }
LLDrawPoolBump();
- virtual void render(S32 pass = 0);
- virtual void beginRenderPass( S32 pass );
- virtual void endRenderPass( S32 pass );
- virtual S32 getNumPasses();
- /*virtual*/ void prerender();
- /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE);
+ virtual void render(S32 pass = 0) override;
+ virtual void beginRenderPass( S32 pass ) override;
+ virtual void endRenderPass( S32 pass ) override;
+ virtual S32 getNumPasses() override;
+ /*virtual*/ void prerender() override;
+ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL batch_textures = FALSE) override;
void renderBump(U32 type, U32 mask);
- void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture);
+ void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) override;
S32 numBumpPasses();
@@ -72,28 +72,29 @@ public:
void renderFullbrightShiny();
void endFullbrightShiny();
- void beginBump(U32 pass = LLRenderPass::PASS_BUMP);
+ void beginBump();
void renderBump(U32 pass = LLRenderPass::PASS_BUMP);
void endBump(U32 pass = LLRenderPass::PASS_BUMP);
static void bindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible);
static void unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32& diffuse_channel, S32& cube_channel, bool invisible);
- virtual S32 getNumDeferredPasses();
- /*virtual*/ void beginDeferredPass(S32 pass);
- /*virtual*/ void endDeferredPass(S32 pass);
- /*virtual*/ void renderDeferred(S32 pass);
+ virtual S32 getNumDeferredPasses() override;
+ /*virtual*/ void beginDeferredPass(S32 pass) override;
+ /*virtual*/ void endDeferredPass(S32 pass) override;
+ /*virtual*/ void renderDeferred(S32 pass) override;
- virtual S32 getNumPostDeferredPasses() { return 2; }
- /*virtual*/ void beginPostDeferredPass(S32 pass);
- /*virtual*/ void endPostDeferredPass(S32 pass);
- /*virtual*/ void renderPostDeferred(S32 pass);
+ virtual S32 getNumPostDeferredPasses() override { return 4; }
+ /*virtual*/ void beginPostDeferredPass(S32 pass) override;
+ /*virtual*/ void endPostDeferredPass(S32 pass) override;
+ /*virtual*/ void renderPostDeferred(S32 pass) override;
static BOOL bindBumpMap(LLDrawInfo& params, S32 channel = -2);
static BOOL bindBumpMap(LLFace* face, S32 channel = -2);
private:
static BOOL bindBumpMap(U8 bump_code, LLViewerTexture* tex, F32 vsize, S32 channel);
+ bool mRigged = false; // if true, doing a rigged pass
};
diff --git a/indra/newview/lldrawpoolmaterials.cpp b/indra/newview/lldrawpoolmaterials.cpp
index d2a8757379..fd5850084b 100644
--- a/indra/newview/lldrawpoolmaterials.cpp
+++ b/indra/newview/lldrawpoolmaterials.cpp
@@ -31,6 +31,7 @@
#include "llviewershadermgr.h"
#include "pipeline.h"
#include "llglcommonfunc.h"
+#include "llvoavatar.h"
S32 diffuse_channel = -1;
@@ -47,11 +48,18 @@ void LLDrawPoolMaterials::prerender()
S32 LLDrawPoolMaterials::getNumDeferredPasses()
{
- return 12;
+ // 12 render passes times 2 (one for each rigged and non rigged)
+ return 12*2;
}
void LLDrawPoolMaterials::beginDeferredPass(S32 pass)
{
+ bool rigged = false;
+ if (pass >= 12)
+ {
+ rigged = true;
+ pass -= 12;
+ }
U32 shader_idx[] =
{
0, //LLRenderPass::PASS_MATERIAL,
@@ -72,13 +80,22 @@ void LLDrawPoolMaterials::beginDeferredPass(S32 pass)
15, //LLRenderPass::PASS_NORMSPEC_GLOW,
};
- mShader = &(gDeferredMaterialProgram[shader_idx[pass]]);
-
- if (LLPipeline::sUnderWaterRender)
- {
- mShader = &(gDeferredMaterialWaterProgram[shader_idx[pass]]);
- }
-
+ U32 idx = shader_idx[pass];
+
+ if (LLPipeline::sUnderWaterRender)
+ {
+ mShader = &(gDeferredMaterialWaterProgram[idx]);
+ }
+ else
+ {
+ mShader = &(gDeferredMaterialProgram[idx]);
+ }
+
+ if (rigged)
+ {
+ llassert(mShader->mRiggedVariant != nullptr);
+ mShader = mShader->mRiggedVariant;
+ }
mShader->bind();
if (LLPipeline::sRenderingHUDs)
@@ -127,9 +144,20 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
LLRenderPass::PASS_NORMSPEC_EMISSIVE,
};
+ bool rigged = false;
+ if (pass >= 12)
+ {
+ rigged = true;
+ pass -= 12;
+ }
+
llassert(pass < sizeof(type_list)/sizeof(U32));
U32 type = type_list[pass];
+ if (rigged)
+ {
+ type += 1;
+ }
U32 mask = mShader->mAttributeMask;
@@ -160,7 +188,7 @@ void LLDrawPoolMaterials::renderDeferred(S32 pass)
{
LL_PROFILE_ZONE_SCOPED;
- pushMaterialsBatch(params, mask);
+ pushMaterialsBatch(params, mask, rigged);
}
}
}
@@ -175,7 +203,7 @@ void LLDrawPoolMaterials::bindNormalMap(LLViewerTexture* tex)
mShader->bindTexture(LLShaderMgr::BUMP_MAP, tex);
}
-void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask)
+void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask, bool rigged)
{
LL_PROFILE_ZONE_SCOPED;
applyModelMatrix(params);
@@ -214,6 +242,24 @@ void LLDrawPoolMaterials::pushMaterialsBatch(LLDrawInfo& params, U32 mask)
params.mGroup->rebuildMesh();
}
+ // upload matrix palette to shader
+ if (rigged)
+ {
+ const LLVOAvatar::MatrixPaletteCache& mpc = params.mAvatar->updateSkinInfoMatrixPalette(params.mSkinInfo);
+ U32 count = mpc.mMatrixPalette.size();
+
+ if (count == 0)
+ {
+ //skin info not loaded yet, don't render
+ return;
+ }
+
+ mShader->uniformMatrix3x4fv(LLViewerShaderMgr::AVATAR_MATRIX,
+ count,
+ FALSE,
+ (GLfloat*)&(mpc.mGLMp[0]));
+ }
+
LLGLEnableFunc stencil_test(GL_STENCIL_TEST, params.mSelected, &LLGLCommonFunc::selected_stencil_test);
params.mVertexBuffer->setBufferFast(mask);
diff --git a/indra/newview/lldrawpoolmaterials.h b/indra/newview/lldrawpoolmaterials.h
index 6e39821b07..8a3ad923df 100644
--- a/indra/newview/lldrawpoolmaterials.h
+++ b/indra/newview/lldrawpoolmaterials.h
@@ -55,21 +55,21 @@ public:
LLVertexBuffer::MAP_TANGENT
};
- /*virtual*/ U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+ U32 getVertexDataMask() override { return VERTEX_DATA_MASK; }
- /*virtual*/ void render(S32 pass = 0) { }
- /*virtual*/ S32 getNumPasses() {return 0;}
- /*virtual*/ void prerender();
+ void render(S32 pass = 0) override { }
+ S32 getNumPasses() override {return 0;}
+ void prerender() override;
- /*virtual*/ S32 getNumDeferredPasses();
- /*virtual*/ void beginDeferredPass(S32 pass);
- /*virtual*/ void endDeferredPass(S32 pass);
- /*virtual*/ void renderDeferred(S32 pass);
+ S32 getNumDeferredPasses() override;
+ void beginDeferredPass(S32 pass) override;
+ void endDeferredPass(S32 pass) override;
+ void renderDeferred(S32 pass) override;
void bindSpecularMap(LLViewerTexture* tex);
void bindNormalMap(LLViewerTexture* tex);
- /*virtual*/ void pushMaterialsBatch(LLDrawInfo& params, U32 mask);
+ void pushMaterialsBatch(LLDrawInfo& params, U32 mask, bool rigged);
};
#endif //LL_LLDRAWPOOLMATERIALS_H
diff --git a/indra/newview/lldrawpoolsimple.cpp b/indra/newview/lldrawpoolsimple.cpp
index 320160d10d..ca4e20ae9b 100644
--- a/indra/newview/lldrawpoolsimple.cpp
+++ b/indra/newview/lldrawpoolsimple.cpp
@@ -45,15 +45,24 @@ static LLTrace::BlockTimerStatHandle FTM_RENDER_GRASS_DEFERRED("Deferred Grass")
void LLDrawPoolGlow::beginPostDeferredPass(S32 pass)
{
- gDeferredEmissiveProgram.bind();
- gDeferredEmissiveProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+ if (pass == 0)
+ {
+ gDeferredEmissiveProgram.bind();
+ }
+ else
+ {
+ llassert(gDeferredEmissiveProgram.mRiggedVariant);
+ gDeferredEmissiveProgram.mRiggedVariant->bind();
+ }
+
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
if (LLPipeline::sRenderingHUDs)
{
- gDeferredEmissiveProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
}
else
{
- gDeferredEmissiveProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
}
}
@@ -71,7 +80,14 @@ void LLDrawPoolGlow::renderPostDeferred(S32 pass)
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
gGL.setColorMask(false, true);
- pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ if (pass == 0)
+ {
+ pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
+ else
+ {
+ pushRiggedBatches(LLRenderPass::PASS_GLOW_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
gGL.setColorMask(true, false);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
@@ -79,7 +95,8 @@ void LLDrawPoolGlow::renderPostDeferred(S32 pass)
void LLDrawPoolGlow::endPostDeferredPass(S32 pass)
{
- gDeferredEmissiveProgram.unbind();
+ LLGLSLShader::sCurBoundShaderPtr->unbind();
+
LLRenderPass::endRenderPass(pass);
}
@@ -87,7 +104,7 @@ S32 LLDrawPoolGlow::getNumPasses()
{
if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 0)
{
- return 1;
+ return 2;
}
else
{
@@ -112,6 +129,11 @@ void LLDrawPoolGlow::render(S32 pass)
llassert(shader_level > 0);
LLGLSLShader* shader = LLPipeline::sUnderWaterRender ? &gObjectEmissiveWaterProgram : &gObjectEmissiveProgram;
+ if (pass == 1)
+ {
+ llassert(shader->mRiggedVariant);
+ shader = shader->mRiggedVariant;
+ }
shader->bind();
if (LLPipeline::sRenderDeferred)
{
@@ -120,7 +142,7 @@ void LLDrawPoolGlow::render(S32 pass)
else
{
shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.f);
- }
+ }
if (LLPipeline::sRenderingHUDs)
{
@@ -134,7 +156,14 @@ void LLDrawPoolGlow::render(S32 pass)
LLGLDepthTest depth(GL_TRUE, GL_FALSE);
gGL.setColorMask(false, true);
- pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ if (pass == 0)
+ {
+ pushBatches(LLRenderPass::PASS_GLOW, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
+ else
+ {
+ pushRiggedBatches(LLRenderPass::PASS_GLOW_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
gGL.setColorMask(true, false);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
@@ -155,39 +184,43 @@ void LLDrawPoolSimple::prerender()
mShaderLevel = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT);
}
+S32 LLDrawPoolSimple::getNumPasses()
+{
+ return 2;
+}
+
void LLDrawPoolSimple::beginRenderPass(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
- if (LLPipeline::sImpostorRender)
- {
- simple_shader = &gObjectSimpleImpostorProgram;
- }
- else if (LLPipeline::sUnderWaterRender)
- {
- simple_shader = &gObjectSimpleWaterProgram;
- }
- else
- {
- simple_shader = &gObjectSimpleProgram;
- }
+ if (LLPipeline::sImpostorRender)
+ {
+ simple_shader = &gObjectSimpleImpostorProgram;
+ }
+ else if (LLPipeline::sUnderWaterRender)
+ {
+ simple_shader = &gObjectSimpleWaterProgram;
+ }
+ else
+ {
+ simple_shader = &gObjectSimpleProgram;
+ }
+
+ if (pass == 1)
+ {
+ llassert(simple_shader->mRiggedVariant);
+ simple_shader = simple_shader->mRiggedVariant;
+ }
- if (mShaderLevel > 0)
- {
- simple_shader->bind();
+ simple_shader->bind();
- if (LLPipeline::sRenderingHUDs)
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
+ if (LLPipeline::sRenderingHUDs)
+ {
+ simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
}
- else
+ else
{
- LLGLSLShader::bindNoShader();
+ simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
}
}
@@ -197,10 +230,7 @@ void LLDrawPoolSimple::endRenderPass(S32 pass)
stop_glerror();
LLRenderPass::endRenderPass(pass);
stop_glerror();
- if (mShaderLevel > 0)
- {
- simple_shader->unbind();
- }
+ simple_shader->unbind();
}
void LLDrawPoolSimple::render(S32 pass)
@@ -211,35 +241,38 @@ void LLDrawPoolSimple::render(S32 pass)
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE);
gPipeline.enableLightsDynamic();
- if (mShaderLevel > 0)
- {
- 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);
- pushBatches(LLRenderPass::PASS_MATERIAL, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_SPECMAP, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_NORMMAP, mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_NORMSPEC, mask, TRUE, TRUE);
- }
- }
- else
- {
- LLGLDisable alpha_test(GL_ALPHA_TEST);
- renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask());
- }
-
- }
-}
-
-
+ U32 mask = getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX;
+ if (pass == 0)
+ {
+ 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);
+ pushBatches(LLRenderPass::PASS_MATERIAL, mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_SPECMAP, mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_NORMMAP, mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_NORMSPEC, mask, TRUE, TRUE);
+ }
+ }
+ else
+ {
+ pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, 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
+ pushRiggedBatches(LLRenderPass::PASS_BUMP_RIGGED, mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_MATERIAL_RIGGED, mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_SPECMAP_RIGGED, mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_NORMMAP_RIGGED, mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_RIGGED, mask, TRUE, TRUE);
+ }
+ }
+ }
+}
@@ -261,32 +294,31 @@ void LLDrawPoolAlphaMask::beginRenderPass(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
- if (LLPipeline::sUnderWaterRender)
- {
- simple_shader = &gObjectSimpleWaterAlphaMaskProgram;
- }
- else
- {
- simple_shader = &gObjectSimpleAlphaMaskProgram;
- }
+ if (LLPipeline::sUnderWaterRender)
+ {
+ simple_shader = &gObjectSimpleWaterAlphaMaskProgram;
+ }
+ else
+ {
+ simple_shader = &gObjectSimpleAlphaMaskProgram;
+ }
- if (mShaderLevel > 0)
- {
- simple_shader->bind();
+ if (pass == 1)
+ {
+ llassert(simple_shader->mRiggedVariant);
+ simple_shader = simple_shader->mRiggedVariant;
+ }
- if (LLPipeline::sRenderingHUDs)
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
- }
- else
- {
- LLGLSLShader::bindNoShader();
- }
+ simple_shader->bind();
+
+ if (LLPipeline::sRenderingHUDs)
+ {
+ simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+ }
+ else
+ {
+ simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+ }
}
void LLDrawPoolAlphaMask::endRenderPass(S32 pass)
@@ -306,20 +338,22 @@ void LLDrawPoolAlphaMask::render(S32 pass)
LLGLDisable blend(GL_BLEND);
LL_PROFILE_ZONE_SCOPED;
- if (mShaderLevel > 0)
- {
- simple_shader->bind();
- simple_shader->setMinimumAlpha(0.33f);
+
- if (LLPipeline::sRenderingHUDs)
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
+ simple_shader->bind();
+ simple_shader->setMinimumAlpha(0.33f);
+
+ if (LLPipeline::sRenderingHUDs)
+ {
+ simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
+ }
+ else
+ {
+ simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
+ }
+ if (pass == 0)
+ {
pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
pushMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
pushMaskBatches(LLRenderPass::PASS_SPECMAP_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
@@ -328,9 +362,11 @@ void LLDrawPoolAlphaMask::render(S32 pass)
}
else
{
- LLGLEnable test(GL_ALPHA_TEST);
- pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask(), TRUE, FALSE);
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK
+ pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushRiggedMaskBatches(LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushRiggedMaskBatches(LLRenderPass::PASS_SPECMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushRiggedMaskBatches(LLRenderPass::PASS_NORMMAP_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ pushRiggedMaskBatches(LLRenderPass::PASS_NORMSPEC_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
}
}
@@ -348,31 +384,32 @@ void LLDrawPoolFullbrightAlphaMask::beginRenderPass(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
+ bool rigged = (pass == 1);
if (LLPipeline::sUnderWaterRender)
{
- simple_shader = &gObjectFullbrightWaterAlphaMaskProgram;
+ gObjectFullbrightWaterAlphaMaskProgram.bind(rigged);
}
else
{
- simple_shader = &gObjectFullbrightAlphaMaskProgram;
+ gObjectFullbrightAlphaMaskProgram.bind(rigged);
}
- if (mShaderLevel > 0)
+ if (LLPipeline::sRenderingHUDs)
{
- simple_shader->bind();
-
- if (LLPipeline::sRenderingHUDs)
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
- }
- else
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
- }
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.f);
}
- else
+ else
{
- LLGLSLShader::bindNoShader();
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
+ if (LLPipeline::sRenderDeferred)
+ {
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+ }
+ else
+ {
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+ }
}
}
@@ -382,70 +419,61 @@ void LLDrawPoolFullbrightAlphaMask::endRenderPass(S32 pass)
stop_glerror();
LLRenderPass::endRenderPass(pass);
stop_glerror();
- if (mShaderLevel > 0)
- {
- simple_shader->unbind();
- }
+ LLGLSLShader::sCurBoundShaderPtr->unbind();
}
void LLDrawPoolFullbrightAlphaMask::render(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK);
- if (mShaderLevel > 0)
- {
- if (simple_shader)
- {
- simple_shader->bind();
- simple_shader->setMinimumAlpha(0.33f);
-
- if (LLPipeline::sRenderingHUDs)
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 1);
- simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
- }
- else
- {
- simple_shader->uniform1i(LLShaderMgr::NO_ATMO, 0);
- if (LLPipeline::sRenderDeferred)
- {
- simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
- }
- else
- {
- simple_shader->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
- }
- }
- }
- pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- //LLGLSLShader::bindNoShader();
- }
- else
- {
- LLGLEnable test(GL_ALPHA_TEST);
- gPipeline.enableLightsFullbright();
- pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask(), TRUE, FALSE);
- gPipeline.enableLightsDynamic();
- gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); //OK
- }
+ if (pass == 0)
+ {
+ pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
+ else
+ {
+ pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
+
}
//===============================
//DEFERRED IMPLEMENTATION
//===============================
+S32 LLDrawPoolSimple::getNumDeferredPasses()
+{
+ if (LLPipeline::sRenderingHUDs)
+ {
+ return 1;
+ }
+ else
+ {
+ return 2;
+ }
+}
void LLDrawPoolSimple::beginDeferredPass(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED);
- gDeferredDiffuseProgram.bind();
+
+ mShader = &gDeferredDiffuseProgram;
+
+ if (pass == 1)
+ {
+ llassert(mShader->mRiggedVariant != nullptr);
+ mShader = mShader->mRiggedVariant;
+ }
+
+
+ mShader->bind();
if (LLPipeline::sRenderingHUDs)
{
- gDeferredDiffuseProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+ mShader->uniform1i(LLShaderMgr::NO_ATMO, 1);
}
else
{
- gDeferredDiffuseProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+ mShader->uniform1i(LLShaderMgr::NO_ATMO, 0);
}
}
@@ -454,7 +482,7 @@ void LLDrawPoolSimple::endDeferredPass(S32 pass)
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED);
LLRenderPass::endRenderPass(pass);
- gDeferredDiffuseProgram.unbind();
+ mShader->unbind();
}
void LLDrawPoolSimple::renderDeferred(S32 pass)
@@ -463,41 +491,61 @@ void LLDrawPoolSimple::renderDeferred(S32 pass)
LLGLDisable blend(GL_BLEND);
LLGLDisable alpha_test(GL_ALPHA_TEST);
+ if (pass == 0)
{ //render simple
LL_RECORD_BLOCK_TIME(FTM_RENDER_SIMPLE_DEFERRED);
pushBatches(LLRenderPass::PASS_SIMPLE, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
}
+ else
+ {
+ //render simple rigged
+ pushRiggedBatches(LLRenderPass::PASS_SIMPLE_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
}
static LLTrace::BlockTimerStatHandle FTM_RENDER_ALPHA_MASK_DEFERRED("Deferred Alpha Mask");
void LLDrawPoolAlphaMask::beginDeferredPass(S32 pass)
{
-
+ if (pass == 0)
+ {
+ gDeferredDiffuseAlphaMaskProgram.bind();
+ }
+ else
+ {
+ llassert(gDeferredDiffuseAlphaMaskProgram.mRiggedVariant);
+ gDeferredDiffuseAlphaMaskProgram.mRiggedVariant->bind();
+ }
+
}
void LLDrawPoolAlphaMask::endDeferredPass(S32 pass)
{
-
+ LLGLSLShader::sCurBoundShaderPtr->unbind();
}
void LLDrawPoolAlphaMask::renderDeferred(S32 pass)
{
LL_RECORD_BLOCK_TIME(FTM_RENDER_ALPHA_MASK_DEFERRED);
- gDeferredDiffuseAlphaMaskProgram.bind();
- gDeferredDiffuseAlphaMaskProgram.setMinimumAlpha(0.33f);
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.33f);
if (LLPipeline::sRenderingHUDs)
{
- gDeferredDiffuseAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
}
else
{
- gDeferredDiffuseAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
}
- pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
- gDeferredDiffuseAlphaMaskProgram.unbind();
+ if (pass == 0)
+ {
+ pushMaskBatches(LLRenderPass::PASS_ALPHA_MASK, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
+ else
+ {
+ pushRiggedMaskBatches(LLRenderPass::PASS_ALPHA_MASK_RIGGED, getVertexDataMask() | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, TRUE);
+ }
}
@@ -572,7 +620,7 @@ void LLDrawPoolGrass::render(S32 pass)
LLGLEnable test(GL_ALPHA_TEST);
gGL.setSceneBlendType(LLRender::BT_ALPHA);
//render grass
- LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask());
+ LLRenderPass::pushBatches(LLRenderPass::PASS_GRASS, getVertexDataMask());
}
}
@@ -603,7 +651,7 @@ void LLDrawPoolGrass::renderDeferred(S32 pass)
}
//render grass
- LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask());
+ LLRenderPass::pushBatches(LLRenderPass::PASS_GRASS, getVertexDataMask());
}
}
@@ -621,24 +669,24 @@ void LLDrawPoolFullbright::prerender()
void LLDrawPoolFullbright::beginPostDeferredPass(S32 pass)
{
+ bool rigged = (pass == 1);
if (LLPipeline::sUnderWaterRender)
{
- gDeferredFullbrightWaterProgram.bind();
+ gDeferredFullbrightWaterProgram.bind(rigged);
}
else
{
- gDeferredFullbrightProgram.bind();
+ gDeferredFullbrightProgram.bind(rigged);
if (LLPipeline::sRenderingHUDs)
{
- gDeferredFullbrightProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
}
else
{
- gDeferredFullbrightProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
}
}
-
}
void LLDrawPoolFullbright::renderPostDeferred(S32 pass)
@@ -647,19 +695,19 @@ void LLDrawPoolFullbright::renderPostDeferred(S32 pass)
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);
+ if (pass == 0)
+ {
+ pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
+ }
+ else
+ {
+ pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, fullbright_mask, TRUE, TRUE);
+ }
}
void LLDrawPoolFullbright::endPostDeferredPass(S32 pass)
{
- if (LLPipeline::sUnderWaterRender)
- {
- gDeferredFullbrightWaterProgram.unbind();
- }
- else
- {
- gDeferredFullbrightProgram.unbind();
- }
+ LLGLSLShader::sCurBoundShaderPtr->unbind();
LLRenderPass::endRenderPass(pass);
}
@@ -675,6 +723,12 @@ void LLDrawPoolFullbright::beginRenderPass(S32 pass)
{
fullbright_shader = &gObjectFullbrightProgram;
}
+
+ if (pass == 1)
+ {
+ llassert(fullbright_shader->mRiggedVariant);
+ fullbright_shader = fullbright_shader->mRiggedVariant;
+ }
}
void LLDrawPoolFullbright::endRenderPass(S32 pass)
@@ -715,21 +769,23 @@ void LLDrawPoolFullbright::render(S32 pass)
}
U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
- pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, fullbright_mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, fullbright_mask, TRUE, TRUE);
- pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, fullbright_mask, TRUE, TRUE);
- }
- else
- {
- gPipeline.enableLightsFullbright();
- U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR;
- renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask);
- pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask);
- pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, fullbright_mask);
- pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, fullbright_mask);
- pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, fullbright_mask);
+
+ if (pass == 0)
+ {
+ pushBatches(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE, fullbright_mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE, fullbright_mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE, fullbright_mask, TRUE, TRUE);
+ pushBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE, fullbright_mask, TRUE, TRUE);
+ }
+ else
+ {
+ pushRiggedBatches(LLRenderPass::PASS_FULLBRIGHT_RIGGED, fullbright_mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED, fullbright_mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_SPECMAP_EMISSIVE_RIGGED, fullbright_mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_NORMMAP_EMISSIVE_RIGGED, fullbright_mask, TRUE, TRUE);
+ pushRiggedBatches(LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED, fullbright_mask, TRUE, TRUE);
+ }
}
stop_glerror();
@@ -737,39 +793,39 @@ void LLDrawPoolFullbright::render(S32 pass)
S32 LLDrawPoolFullbright::getNumPasses()
{
- return 1;
+ return 2;
}
void LLDrawPoolFullbrightAlphaMask::beginPostDeferredPass(S32 pass)
{
-
+ bool rigged = (pass == 1);
if (LLPipeline::sRenderingHUDs)
{
- gObjectFullbrightAlphaMaskProgram.bind();
- gObjectFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
- gObjectFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+ gObjectFullbrightAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
}
else if (LLPipeline::sRenderDeferred)
{
if (LLPipeline::sUnderWaterRender)
{
- gDeferredFullbrightAlphaMaskWaterProgram.bind();
- gDeferredFullbrightAlphaMaskWaterProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
- gDeferredFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 1);
+ gDeferredFullbrightAlphaMaskWaterProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 1);
}
else
{
- gDeferredFullbrightAlphaMaskProgram.bind();
- gDeferredFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
- gDeferredFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+ gDeferredFullbrightAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 2.2f);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
}
}
else
{
- gObjectFullbrightAlphaMaskProgram.bind();
- gObjectFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
- gObjectFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::NO_ATMO, 0);
+ gObjectFullbrightAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::TEXTURE_GAMMA, 1.0f);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::NO_ATMO, 0);
}
}
@@ -778,26 +834,19 @@ void LLDrawPoolFullbrightAlphaMask::renderPostDeferred(S32 pass)
LL_RECORD_BLOCK_TIME(FTM_RENDER_FULLBRIGHT);
LLGLDisable blend(GL_BLEND);
U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXTURE_INDEX;
- pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, fullbright_mask, TRUE, TRUE);
+ if (pass == 0)
+ {
+ pushMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, fullbright_mask, TRUE, TRUE);
+ }
+ else
+ {
+ pushRiggedMaskBatches(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED, fullbright_mask, TRUE, TRUE);
+ }
}
void LLDrawPoolFullbrightAlphaMask::endPostDeferredPass(S32 pass)
{
- if (LLPipeline::sRenderingHUDs || !LLPipeline::sRenderDeferred)
- {
- gObjectFullbrightAlphaMaskProgram.unbind();
- }
- else
- {
- if (LLPipeline::sUnderWaterRender)
- {
- gDeferredFullbrightAlphaMaskWaterProgram.unbind();
- }
- else
- {
- gDeferredFullbrightAlphaMaskProgram.unbind();
- }
- }
+ LLGLSLShader::sCurBoundShaderPtr->unbind();
LLRenderPass::endRenderPass(pass);
}
diff --git a/indra/newview/lldrawpoolsimple.h b/indra/newview/lldrawpoolsimple.h
index b27cc4babc..d6fecdd23c 100644
--- a/indra/newview/lldrawpoolsimple.h
+++ b/indra/newview/lldrawpoolsimple.h
@@ -29,6 +29,8 @@
#include "lldrawpool.h"
+class LLGLSLShader;
+
class LLDrawPoolSimple : public LLRenderPass
{
public:
@@ -39,22 +41,23 @@ public:
LLVertexBuffer::MAP_TEXCOORD0 |
LLVertexBuffer::MAP_COLOR
};
- virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; }
+ virtual U32 getVertexDataMask() override { return VERTEX_DATA_MASK; }
LLDrawPoolSimple();
- /*virtual*/ S32 getNumDeferredPasses() { return 1; }
- /*virtual*/ void beginDeferredPass(S32 pass);
- /*virtual*/ void endDeferredPass(S32 pass);
- /*virtual*/ void renderDeferred(S32 pass);
+ S32 getNumDeferredPasses() override;
+ void beginDeferredPass(S32 pass) override;
+ void endDeferredPass(S32 pass) override;
+ void renderDeferred(S32 pass) override;
- /*virtual*/ void beginRenderPass(S32 pass);
- /*virtual*/ void endRenderPass(S32 pass);
+ void beginRenderPass(S32 pass) override;
+ void endRenderPass(S32 pass) override;
/// We need two passes so we can handle emissive materials separately.
- /*virtual*/ S32 getNumPasses() { return 1; }
- /*virtual*/ void render(S32 pass = 0);
- /*virtual*/ void prerender();
+ S32 getNumPasses() override;
+ void render(S32 pass = 0) override;
+ void prerender() override;
+ LLGLSLShader* mShader = nullptr;
};
class LLDrawPoolGrass : public LLRenderPass
@@ -98,12 +101,12 @@ public:
LLDrawPoolAlphaMask();
- /*virtual*/ S32 getNumDeferredPasses() { return 1; }
+ /*virtual*/ S32 getNumDeferredPasses() { return 2; }
/*virtual*/ void beginDeferredPass(S32 pass);
/*virtual*/ void endDeferredPass(S32 pass);
/*virtual*/ void renderDeferred(S32 pass);
- /*virtual*/ S32 getNumPasses() { return 1; }
+ /*virtual*/ S32 getNumPasses() { return 2; }
/*virtual*/ void beginRenderPass(S32 pass);
/*virtual*/ void endRenderPass(S32 pass);
/*virtual*/ void render(S32 pass = 0);
@@ -124,12 +127,12 @@ public:
LLDrawPoolFullbrightAlphaMask();
- /*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
+ /*virtual*/ S32 getNumPostDeferredPasses() { return 2; }
/*virtual*/ void beginPostDeferredPass(S32 pass);
/*virtual*/ void endPostDeferredPass(S32 pass);
/*virtual*/ void renderPostDeferred(S32 pass);
- /*virtual*/ S32 getNumPasses() { return 1; }
+ /*virtual*/ S32 getNumPasses() { return 2; }
/*virtual*/ void beginRenderPass(S32 pass);
/*virtual*/ void endRenderPass(S32 pass);
/*virtual*/ void render(S32 pass = 0);
@@ -150,7 +153,7 @@ public:
LLDrawPoolFullbright();
- /*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
+ /*virtual*/ S32 getNumPostDeferredPasses() { return 2; }
/*virtual*/ void beginPostDeferredPass(S32 pass);
/*virtual*/ void endPostDeferredPass(S32 pass);
/*virtual*/ void renderPostDeferred(S32 pass);
@@ -179,7 +182,7 @@ public:
virtual void prerender() { }
- /*virtual*/ S32 getNumPostDeferredPasses() { return 1; }
+ /*virtual*/ S32 getNumPostDeferredPasses() { return 2; }
/*virtual*/ void beginPostDeferredPass(S32 pass);
/*virtual*/ void endPostDeferredPass(S32 pass);
/*virtual*/ void renderPostDeferred(S32 pass);
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 2f3c52ecd2..e2d3f67e46 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -50,8 +50,6 @@
#include "llsettingssky.h"
#include "llsettingswater.h"
-static float sTime;
-
BOOL deferred_render = FALSE;
BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE;
@@ -146,7 +144,7 @@ void LLDrawPoolWater::renderDeferred(S32 pass)
}
deferred_render = TRUE;
- shade();
+ renderWater();
deferred_render = FALSE;
}
@@ -182,7 +180,7 @@ void LLDrawPoolWater::render(S32 pass)
if ((mShaderLevel > 0) && !sSkipScreenCopy)
{
- shade();
+ renderWater();
return;
}
@@ -485,332 +483,246 @@ void LLDrawPoolWater::renderReflection(LLFace* face)
face->renderIndexed();
}
-void LLDrawPoolWater::shade2(bool edge, LLGLSLShader* shader, const LLColor3& light_diffuse, const LLVector3& light_dir, F32 light_exp)
+void LLDrawPoolWater::renderWater()
{
LL_PROFILE_ZONE_SCOPED;
- F32 water_height = LLEnvironment::instance().getWaterHeight();
- F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2];
- F32 eyedepth = camera_height - water_height;
- bool underwater = eyedepth <= 0.0f;
-
- LLEnvironment& environment = LLEnvironment::instance();
- LLSettingsWater::ptr_t pwater = environment.getCurrentWater();
- LLSettingsSky::ptr_t psky = environment.getCurrentSky();
-
- shader->bind();
-
-// bind textures for water rendering
- if (deferred_render)
- {
- if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0)
- {
- glh::matrix4f norm_mat = get_current_modelview().inverse().transpose();
- shader->uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m);
- }
- }
-
- LLColor4 specular(psky->getIsSunUp() ? psky->getSunlightColor() : psky->getMoonlightColor());
- shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV);
-
- sTime = (F32)LLFrameTimer::getElapsedSeconds() * 0.5f;
-
- S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX);
-
- if (reftex > -1)
- {
- gGL.getTexUnit(reftex)->activate();
- gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef);
- gGL.getTexUnit(0)->activate();
- }
+ if (!deferred_render)
+ {
+ gGL.setColorMask(true, true);
+ }
- //bind normal map
- S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
- S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2);
+ LLGLDisable blend(GL_BLEND);
- LLViewerTexture* tex_a = mWaterNormp[0];
- LLViewerTexture* tex_b = mWaterNormp[1];
+ LLColor3 light_diffuse(0, 0, 0);
+ F32 light_exp = 0.0f;
- F32 blend_factor = LLEnvironment::instance().getCurrentWater()->getBlendFactor();
-
- gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
+ LLEnvironment & environment = LLEnvironment::instance();
+ LLSettingsWater::ptr_t pwater = environment.getCurrentWater();
+ LLSettingsSky::ptr_t psky = environment.getCurrentSky();
+ LLVector3 light_dir = environment.getLightDirection();
+ bool sun_up = environment.getIsSunUp();
+ bool moon_up = environment.getIsMoonUp();
+ bool has_normal_mips = gSavedSettings.getBOOL("RenderWaterMipNormal");
+ bool underwater = LLViewerCamera::getInstance()->cameraUnderWater();
- if (tex_a && (!tex_b || (tex_a == tex_b)))
- {
- gGL.getTexUnit(bumpTex)->bind(tex_a);
- blend_factor = 0; // only one tex provided, no blending
- }
- else if (tex_b && !tex_a)
+ if (sun_up)
{
- gGL.getTexUnit(bumpTex)->bind(tex_b);
- blend_factor = 0; // only one tex provided, no blending
+ light_diffuse += psky->getSunlightColor();
}
- else if (tex_b != tex_a)
+ // moonlight is several orders of magnitude less bright than sunlight,
+ // so only use this color when the moon alone is showing
+ else if (moon_up)
{
- gGL.getTexUnit(bumpTex)->bind(tex_a);
- gGL.getTexUnit(bumpTex2)->bind(tex_b);
+ light_diffuse += psky->getMoonlightColor();
}
-
- // bind reflection texture from RenderTarget
- S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
- F32 screenRes[] =
- {
- 1.f/gGLViewport[2],
- 1.f/gGLViewport[3]
- };
-
- S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
- stop_glerror();
-
-// set uniforms for water rendering
- shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes);
- shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
-
- LLColor4 fog_color(pwater->getWaterFogColor(), 0.0f);
- F32 fog_density = pwater->getModifiedWaterFogDensity(underwater);
- if (screentex > -1)
- {
- shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density);
- gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);
- }
-
- if (mShaderLevel == 1)
- {
- //F32 fog_density_slider_value = param_mgr->mDensitySliderValue;
- //sWaterFogColor.mV[3] = fog_density_slider_value;
- fog_color.mV[VW] = log(fog_density) / log(2);
- }
-
- shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
-
- //shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix);
- shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth);
- shader->uniform1f(LLShaderMgr::WATER_TIME, sTime);
- shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
- shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
- shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp);
- if (LLEnvironment::instance().isCloudScrollPaused())
+ // Apply magic numbers translating light direction into intensities
+ light_dir.normalize();
+ F32 ground_proj_sq = light_dir.mV[0] * light_dir.mV[0] + light_dir.mV[1] * light_dir.mV[1];
+ light_exp = llmax(32.f, 256.f * powf(ground_proj_sq, 16.0f));
+ if (0.f < light_diffuse.normalize()) // Normalizing a color? Puzzling...
{
- static const std::array<F32, 2> zerowave{ {0.0f, 0.0f} };
-
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data());
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data());
+ light_diffuse *= (1.5f + (6.f * ground_proj_sq));
}
- else
+
+ // set up normal maps filtering
+ for (auto norm_map : mWaterNormp)
{
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
- shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
+ if (norm_map) norm_map->setFilteringOption(has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
}
- shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
- shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV);
- shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale());
- shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset());
- shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier());
+ LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor());
+ F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f;
+ bool edge = false;
+ LLGLSLShader *shader = nullptr;
+ do // twice through, once with normal shader bound & once with edge shader bound
+ {
+ // select shader
+ if (underwater && LLPipeline::sWaterReflections)
+ {
+ shader = deferred_render ? &gDeferredUnderWaterProgram : &gUnderWaterProgram;
+ }
+ else
+ {
+ if (edge && !deferred_render)
+ {
+ shader = &gWaterEdgeProgram;
+ }
+ else
+ {
+ shader = deferred_render ? &gDeferredWaterProgram : &gWaterProgram;
+ }
+ }
+ shader->bind();
- F32 sunAngle = llmax(0.f, light_dir.mV[1]);
- F32 scaledAngle = 1.f - sunAngle;
+ // bind textures for water rendering
+ S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX);
+ if (reftex > -1)
+ {
+ gGL.getTexUnit(reftex)->activate();
+ gGL.getTexUnit(reftex)->bind(&gPipeline.mWaterRef);
+ gGL.getTexUnit(0)->activate();
+ }
- shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle);
- shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle);
- shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f*sunAngle);
- shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0);
+ // bind normal map
+ S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
+ S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2);
- LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm();
- shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV);
- shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
+ LLViewerTexture *tex_a = mWaterNormp[0];
+ LLViewerTexture *tex_b = mWaterNormp[1];
- if (LLViewerCamera::getInstance()->cameraUnderWater())
- {
- shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow());
- }
- else
- {
- shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove());
- }
+ F32 blend_factor = pwater->getBlendFactor();
- {
- LLGLDisable cullface(GL_CULL_FACE);
+ gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
- if (edge)
+ if (tex_a && (!tex_b || (tex_a == tex_b)))
{
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++)
- {
- LLFace *face = *iter;
- if (face)
- {
- LLVOWater* water = (LLVOWater*) face->getViewerObject();
- gGL.getTexUnit(diffTex)->bind(face->getTexture());
-
- if (water)
- {
- bool edge_patch = water->getIsEdgePatch();
- if (edge_patch)
- {
- //sNeedsReflectionUpdate = TRUE;
- face->renderIndexed();
- }
- }
- }
- }
+ gGL.getTexUnit(bumpTex)->bind(tex_a);
+ blend_factor = 0; // only one tex provided, no blending
}
- else
+ else if (tex_b && !tex_a)
{
- for (std::vector<LLFace*>::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++)
- {
- LLFace *face = *iter;
- if (face)
- {
- LLVOWater* water = (LLVOWater*) face->getViewerObject();
- gGL.getTexUnit(diffTex)->bind(face->getTexture());
-
- if (water)
- {
- bool edge_patch = water->getIsEdgePatch();
- if (!edge_patch)
- {
- sNeedsReflectionUpdate = TRUE;
- sNeedsDistortionUpdate = TRUE;
- face->renderIndexed();
- }
- }
- }
- }
+ gGL.getTexUnit(bumpTex)->bind(tex_b);
+ blend_factor = 0; // only one tex provided, no blending
+ }
+ else if (tex_b != tex_a)
+ {
+ gGL.getTexUnit(bumpTex)->bind(tex_a);
+ gGL.getTexUnit(bumpTex2)->bind(tex_b);
}
- }
- gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
- gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
+ // bind reflection texture from RenderTarget
+ S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
+ F32 screenRes[] = {1.f / gGLViewport[2], 1.f / gGLViewport[3]};
- shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
- shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);
- shader->disableTexture(LLShaderMgr::BUMP_MAP);
- shader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
- shader->disableTexture(LLShaderMgr::WATER_REFTEX);
- shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH);
+ S32 diffTex = shader->enableTexture(LLShaderMgr::DIFFUSE_MAP);
- shader->unbind();
-}
+ // set uniforms for shader
+ if (deferred_render)
+ {
+ if (shader->getUniformLocation(LLShaderMgr::DEFERRED_NORM_MATRIX) >= 0)
+ {
+ glh::matrix4f norm_mat = get_current_modelview().inverse().transpose();
+ shader->uniformMatrix4fv(LLShaderMgr::DEFERRED_NORM_MATRIX, 1, FALSE, norm_mat.m);
+ }
+ }
-void LLDrawPoolWater::shade()
-{
- LL_PROFILE_ZONE_SCOPED;
- if (!deferred_render)
- {
- gGL.setColorMask(true, true);
- }
+ shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes);
+ shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
- LLVOSky *voskyp = gSky.mVOSkyp;
+ LLColor4 fog_color(pwater->getWaterFogColor(), 0.0f);
+ F32 fog_density = pwater->getModifiedWaterFogDensity(underwater);
- if(voskyp == NULL)
- {
- return;
- }
+ if (screentex > -1)
+ {
+ shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density);
+ gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);
+ }
- LLGLDisable blend(GL_BLEND);
+ if (mShaderLevel == 1)
+ {
+ fog_color.mV[VW] = log(fog_density) / log(2);
+ }
- LLColor3 light_diffuse(0,0,0);
- F32 light_exp = 0.0f;
- LLVector3 light_dir;
+ F32 water_height = environment.getWaterHeight();
+ F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2];
+ shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height);
+ shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time);
+ shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
- LLEnvironment& environment = LLEnvironment::instance();
- LLSettingsWater::ptr_t pwater = environment.getCurrentWater();
- LLSettingsSky::ptr_t psky = environment.getCurrentSky();
+ shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV);
+ shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
- light_dir = environment.getLightDirection();
- light_dir.normalize();
+ shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
+ shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp);
+ if (LLEnvironment::instance().isCloudScrollPaused())
+ {
+ static const std::array<F32, 2> zerowave {{0.0f, 0.0f}};
- bool sun_up = environment.getIsSunUp();
- bool moon_up = environment.getIsMoonUp();
+ shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, zerowave.data());
+ shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, zerowave.data());
+ }
+ else
+ {
+ shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
+ shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
+ }
+ shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
- if (sun_up)
- {
- light_diffuse += voskyp->getSun().getColorCached();
- }
- // moonlight is several orders of magnitude less bright than sunlight,
- // so only use this color when the moon alone is showing
- else if (moon_up)
- {
- light_diffuse += psky->getMoonDiffuse();
- }
+ shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV);
+ shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale());
+ shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset());
+ shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier());
- light_exp = light_dir * LLVector3(light_dir.mV[0], light_dir.mV[1], 0.f);
+ F32 sunAngle = llmax(0.f, light_dir.mV[1]);
+ F32 scaledAngle = 1.f - sunAngle;
- light_diffuse.normalize();
- light_diffuse *= (light_exp + 0.25f);
+ shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0);
+ shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle);
+ shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle);
+ shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f * sunAngle);
+ shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0);
- light_exp *= light_exp;
- light_exp *= light_exp;
- light_exp *= light_exp;
- light_exp *= light_exp;
- light_exp *= 256.f;
- light_exp = light_exp > 32.f ? light_exp : 32.f;
+ LLVector4 rotated_light_direction = LLEnvironment::instance().getRotatedLightNorm();
+ shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV);
+ shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
- light_diffuse *= 6.f;
+ if (LLViewerCamera::getInstance()->cameraUnderWater())
+ {
+ shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow());
+ }
+ else
+ {
+ shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove());
+ }
- LLGLSLShader* shader = nullptr;
- LLGLSLShader* edge_shader = nullptr;
+ LLGLDisable cullface(GL_CULL_FACE);
- F32 eyedepth = LLViewerCamera::getInstance()->getOrigin().mV[2] - LLEnvironment::instance().getWaterHeight();
-
- if (eyedepth < 0.f && LLPipeline::sWaterReflections)
- {
- if (deferred_render)
- {
- shader = &gDeferredUnderWaterProgram;
- }
- else
+ LLVOWater *water = nullptr;
+ for (LLFace *const &face : mDrawFace)
{
- shader = &gUnderWaterProgram;
- }
- }
- else if (deferred_render)
- {
- shader = &gDeferredWaterProgram;
- edge_shader = nullptr;
- }
- else
- {
- shader = &gWaterProgram;
- edge_shader = &gWaterEdgeProgram;
- }
+ if (!face) continue;
+ water = static_cast<LLVOWater *>(face->getViewerObject());
+ if (!water) continue;
- if (mWaterNormp[0])
- {
- if (gSavedSettings.getBOOL("RenderWaterMipNormal"))
- {
- mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- }
- else
- {
- mWaterNormp[0]->setFilteringOption(LLTexUnit::TFO_POINT);
- }
- }
+ gGL.getTexUnit(diffTex)->bind(face->getTexture());
- if (mWaterNormp[1])
- {
- if (gSavedSettings.getBOOL("RenderWaterMipNormal"))
- {
- mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_ANISOTROPIC);
- }
- else
- {
- mWaterNormp[1]->setFilteringOption(LLTexUnit::TFO_POINT);
- }
- }
+ if (edge == (bool) water->getIsEdgePatch())
+ {
+ face->renderIndexed();
- shade2(false, shader, light_diffuse, light_dir, light_exp);
- shade2(true, edge_shader ? edge_shader : shader, light_diffuse, light_dir, light_exp);
+ // If not occlusion culling, record non-void water being drawn
+ // (If occlusion is enabled, these are set within LLOcclusionCullingGroup::checkOcclusion() )
+ if (!edge && !LLPipeline::sUseOcclusion)
+ {
+ sNeedsReflectionUpdate = TRUE;
+ sNeedsDistortionUpdate = TRUE;
+ }
+ }
+ }
- gGL.getTexUnit(0)->activate();
- gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
- if (!deferred_render)
- {
- gGL.setColorMask(true, false);
- }
+ shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
+ shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);
+ shader->disableTexture(LLShaderMgr::BUMP_MAP);
+ shader->disableTexture(LLShaderMgr::DIFFUSE_MAP);
+ shader->disableTexture(LLShaderMgr::WATER_REFTEX);
+ shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH);
+
+ // clean up
+ shader->unbind();
+ gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
+ gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
+
+ edge = !edge;
+ } while (!edge);
+ gGL.getTexUnit(0)->activate();
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ if (!deferred_render)
+ {
+ gGL.setColorMask(true, false);
+ }
}
LLViewerTexture *LLDrawPoolWater::getDebugTexture()
diff --git a/indra/newview/lldrawpoolwater.h b/indra/newview/lldrawpoolwater.h
index a5d163e0d7..6f2fc3271d 100644
--- a/indra/newview/lldrawpoolwater.h
+++ b/indra/newview/lldrawpoolwater.h
@@ -78,8 +78,7 @@ public:
/*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display
void renderReflection(LLFace* face);
- void shade();
- void shade2(bool edge, LLGLSLShader* shader, const LLColor3& light_diffuse, const LLVector3& light_dir, F32 light_exp);
+ void renderWater();
void setTransparentTextures(const LLUUID& transparentTextureId, const LLUUID& nextTransparentTextureId);
void setOpaqueTexture(const LLUUID& opaqueTextureId);
diff --git a/indra/newview/llenvironment.cpp b/indra/newview/llenvironment.cpp
index 1a66f10b8f..4bec7fa111 100644
--- a/indra/newview/llenvironment.cpp
+++ b/indra/newview/llenvironment.cpp
@@ -2102,7 +2102,15 @@ void LLEnvironment::coroUpdateEnvironment(S32 parcel_id, S32 track_no, UpdateInf
LL_WARNS("ENVIRONMENT") << "Couldn't update Windlight settings for " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL;
notify = LLSD::emptyMap();
- notify["FAIL_REASON"] = result["message"].asString();
+ std::string reason = result["message"].asString();
+ if (reason.empty())
+ {
+ notify["FAIL_REASON"] = status.toString();
+ }
+ else
+ {
+ notify["FAIL_REASON"] = reason;
+ }
}
else if (LLApp::isExiting())
{
@@ -2168,7 +2176,15 @@ void LLEnvironment::coroResetEnvironment(S32 parcel_id, S32 track_no, environmen
LL_WARNS("ENVIRONMENT") << "Couldn't reset Windlight settings in " << ((parcel_id == INVALID_PARCEL_ID) ? ("region!") : ("parcel!")) << LL_ENDL;
notify = LLSD::emptyMap();
- notify["FAIL_REASON"] = result["message"].asString();
+ std::string reason = result["message"].asString();
+ if (reason.empty())
+ {
+ notify["FAIL_REASON"] = status.toString();
+ }
+ else
+ {
+ notify["FAIL_REASON"] = reason;
+ }
}
else if (LLApp::isExiting())
{
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index 4b5fd8a758..6f3f6e9166 100644
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -47,7 +47,7 @@ namespace LLEventPolling
namespace Details
{
- class LLEventPollImpl: public boost::enable_shared_from_this<LLEventPollImpl>
+ class LLEventPollImpl: public std::enable_shared_from_this<LLEventPollImpl>
{
public:
LLEventPollImpl(const LLHost &sender);
@@ -284,7 +284,7 @@ namespace Details
LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender):
mImpl()
{
- mImpl = boost::make_shared<LLEventPolling::Details::LLEventPollImpl>(sender);
+ mImpl = std::make_shared<LLEventPolling::Details::LLEventPollImpl>(sender);
mImpl->start(poll_url);
}
diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h
index 65766dbb2a..d6da04b281 100644
--- a/indra/newview/lleventpoll.h
+++ b/indra/newview/lleventpoll.h
@@ -51,7 +51,7 @@ public:
private:
- boost::shared_ptr<LLEventPolling::Details::LLEventPollImpl> mImpl;
+ std::shared_ptr<LLEventPolling::Details::LLEventPollImpl> mImpl;
};
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 88b958d24a..39ca7961d8 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -56,6 +56,7 @@
#include "llviewertexture.h"
#include "llvoavatar.h"
#include "llsculptidsize.h"
+#include "llmeshrepository.h"
#if LL_LINUX
// Work-around spurious used before init warning on Vector4a
@@ -71,6 +72,7 @@ static LLStaticHashedString sColorIn("color_in");
BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE
+
#define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2])
/*
@@ -197,14 +199,7 @@ void LLFace::destroy()
if (mDrawPoolp)
{
- if (this->isState(LLFace::RIGGED) && (mDrawPoolp->getType() == LLDrawPool::POOL_CONTROL_AV || mDrawPoolp->getType() == LLDrawPool::POOL_AVATAR))
- {
- ((LLDrawPoolAvatar*) mDrawPoolp)->removeRiggedFace(this);
- }
- else
- {
- mDrawPoolp->removeFace(this);
- }
+ mDrawPoolp->removeFace(this);
mDrawPoolp = NULL;
}
@@ -1286,7 +1281,9 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
return FALSE;
}
- const LLVolumeFace &vf = volume.getVolumeFace(f);
+ bool rigged = isState(RIGGED);
+
+ const LLVolumeFace &vf = volume.getVolumeFace(f);
S32 num_vertices = (S32)vf.mNumVertices;
S32 num_indices = (S32) vf.mNumIndices;
@@ -1450,9 +1447,6 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
- LLMatrix4a mat_normal;
- mat_normal.loadu(mat_norm_in);
-
F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0;
bool do_xform = false;
if (rebuild_tcoord)
@@ -1487,6 +1481,45 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
+ const LLMeshSkinInfo* skin = nullptr;
+ LLMatrix4a mat_vert;
+ LLMatrix4a mat_normal;
+
+ // prepare mat_vert
+ if (rebuild_pos)
+ {
+ if (rigged)
+ { //override with bind shape matrix if rigged
+ skin = mSkinInfo;
+ mat_vert = skin->mBindShapeMatrix;
+ }
+ else
+ {
+ mat_vert.loadu(mat_vert_in);
+ }
+ }
+
+ if (rebuild_normal || rebuild_tangent)
+ { //override mat_normal with inverse of skin->mBindShapeMatrix
+ LL_PROFILE_ZONE_NAMED("getGeometryVolume - norm mat override");
+ if (rigged)
+ {
+ if (skin == nullptr)
+ {
+ skin = mSkinInfo;
+ }
+
+ //TODO -- cache this (check profile marker above)?
+ glh::matrix4f m((F32*) skin->mBindShapeMatrix.getF32ptr());
+ m = m.inverse().transpose();
+ mat_normal.loadu(m.m);
+ }
+ else
+ {
+ mat_normal.loadu(mat_norm_in);
+ }
+ }
+
static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback", false);
#ifdef GL_TRANSFORM_FEEDBACK_BUFFER
@@ -1740,7 +1773,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
do_xform = false;
}
- if (getVirtualSize() >= MIN_TEX_ANIM_SIZE || isState(LLFace::RIGGED))
+ if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) // || isState(LLFace::RIGGED))
{ //don't override texture transform during tc bake
tex_mode = 0;
}
@@ -2036,9 +2069,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range);
- LLMatrix4a mat_vert;
- mat_vert.loadu(mat_vert_in);
-
+
F32* dst = (F32*) vert.get();
F32* end_f32 = dst+mGeomCount*4;
@@ -2089,10 +2120,10 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
}
}
-
if (rebuild_normal)
{
- //LL_RECORD_TIME_BLOCK(FTM_FACE_GEOM_NORMAL);
+ LL_PROFILE_ZONE_NAMED("getGeometryVolume - normal");
+
mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range);
F32* normals = (F32*) norm.get();
LLVector4a* src = vf.mNormals;
@@ -2714,56 +2745,6 @@ void LLFace::clearVertexBuffer()
mVertexBuffer = NULL;
}
-//static
-U32 LLFace::getRiggedDataMask(U32 type)
-{
- static const U32 rigged_data_mask[] = {
- LLDrawPoolAvatar::RIGGED_MATERIAL_MASK,
- LLDrawPoolAvatar::RIGGED_MATERIAL_ALPHA_VMASK,
- LLDrawPoolAvatar::RIGGED_MATERIAL_ALPHA_MASK_MASK,
- LLDrawPoolAvatar::RIGGED_MATERIAL_ALPHA_EMISSIVE_MASK,
- LLDrawPoolAvatar::RIGGED_SPECMAP_VMASK,
- LLDrawPoolAvatar::RIGGED_SPECMAP_BLEND_MASK,
- LLDrawPoolAvatar::RIGGED_SPECMAP_MASK_MASK,
- LLDrawPoolAvatar::RIGGED_SPECMAP_EMISSIVE_MASK,
- LLDrawPoolAvatar::RIGGED_NORMMAP_VMASK,
- LLDrawPoolAvatar::RIGGED_NORMMAP_BLEND_MASK,
- LLDrawPoolAvatar::RIGGED_NORMMAP_MASK_MASK,
- LLDrawPoolAvatar::RIGGED_NORMMAP_EMISSIVE_MASK,
- LLDrawPoolAvatar::RIGGED_NORMSPEC_VMASK,
- LLDrawPoolAvatar::RIGGED_NORMSPEC_BLEND_MASK,
- LLDrawPoolAvatar::RIGGED_NORMSPEC_MASK_MASK,
- LLDrawPoolAvatar::RIGGED_NORMSPEC_EMISSIVE_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_DEFERRED_BUMP_MASK,
- LLDrawPoolAvatar::RIGGED_DEFERRED_SIMPLE_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())
@@ -2776,19 +2757,7 @@ S32 LLFace::getRiggedIndex(U32 type) const
return mRiggedIndex[type];
}
-void LLFace::setRiggedIndex(U32 type, S32 index)
+U64 LLFace::getSkinHash()
{
- 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;
+ return mSkinInfo ? mSkinInfo->mHash : 0;
}
-
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index 2e76c974fa..c533edede4 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -49,6 +49,7 @@ class LLViewerTexture;
class LLGeometryManager;
class LLTextureAtlasSlot;
class LLDrawInfo;
+class LLMeshSkinInfo;
const F32 MIN_ALPHA_SIZE = 1024.f;
const F32 MIN_TEX_ANIM_SIZE = 512.f;
@@ -228,11 +229,7 @@ public:
void setVertexBuffer(LLVertexBuffer* buffer);
void clearVertexBuffer(); //sets mVertexBuffer to NULL
LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; }
- U32 getRiggedVertexBufferDataMask() const;
S32 getRiggedIndex(U32 type) const;
- void setRiggedIndex(U32 type, S32 index);
-
- static U32 getRiggedDataMask(U32 type);
void notifyAboutCreatingTexture(LLViewerTexture *texture);
void notifyAboutMissingAsset(LLViewerTexture *texture);
@@ -261,6 +258,11 @@ public:
LLMatrix4* mSpecMapMatrix;
LLMatrix4* mNormalMapMatrix;
LLDrawInfo* mDrawInfo;
+ LLVOAvatar* mAvatar = nullptr;
+ LLMeshSkinInfo* mSkinInfo = nullptr;
+
+ // return mSkinInfo->mHash or 0 if mSkinInfo is null
+ U64 getSkinHash();
private:
LLPointer<LLVertexBuffer> mVertexBuffer;
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 83b5bf3f25..cca6b9ce32 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -682,8 +682,12 @@ void LLFavoritesBarCtrl::changed(U32 mask)
//virtual
void LLFavoritesBarCtrl::reshape(S32 width, S32 height, BOOL called_from_parent)
{
+ S32 delta_width = width - getRect().getWidth();
+ S32 delta_height = height - getRect().getHeight();
+
+ bool force_update = delta_width || delta_height || sForceReshape;
LLUICtrl::reshape(width, height, called_from_parent);
- updateButtons();
+ updateButtons(force_update);
}
void LLFavoritesBarCtrl::draw()
@@ -746,8 +750,13 @@ const LLButton::Params& LLFavoritesBarCtrl::getButtonParams()
return button_params;
}
-void LLFavoritesBarCtrl::updateButtons()
+void LLFavoritesBarCtrl::updateButtons(bool force_update)
{
+ if (LLApp::isExiting())
+ {
+ return;
+ }
+
mItems.clear();
if (!collectFavoriteItems(mItems))
@@ -778,28 +787,29 @@ void LLFavoritesBarCtrl::updateButtons()
const child_list_t* childs = getChildList();
child_list_const_iter_t child_it = childs->begin();
int first_changed_item_index = 0;
- int rightest_point = getRect().mRight - mMoreTextBox->getRect().getWidth();
- //lets find first changed button
- while (child_it != childs->end() && first_changed_item_index < mItems.size())
- {
- LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (*child_it);
- if (button)
- {
- const LLViewerInventoryItem *item = mItems[first_changed_item_index].get();
- if (item)
- {
- // an child's order and mItems should be same
- if (button->getLandmarkId() != item->getUUID() // sort order has been changed
- || button->getLabelSelected() != item->getName() // favorite's name has been changed
- || button->getRect().mRight < rightest_point) // favbar's width has been changed
- {
- break;
- }
- }
- first_changed_item_index++;
- }
- child_it++;
- }
+ if (!force_update)
+ {
+ //lets find first changed button
+ while (child_it != childs->end() && first_changed_item_index < mItems.size())
+ {
+ LLFavoriteLandmarkButton* button = dynamic_cast<LLFavoriteLandmarkButton*> (*child_it);
+ if (button)
+ {
+ const LLViewerInventoryItem *item = mItems[first_changed_item_index].get();
+ if (item)
+ {
+ // an child's order and mItems should be same
+ if (button->getLandmarkId() != item->getUUID() // sort order has been changed
+ || button->getLabelSelected() != item->getName()) // favorite's name has been changed
+ {
+ break;
+ }
+ }
+ first_changed_item_index++;
+ }
+ child_it++;
+ }
+ }
// now first_changed_item_index should contains a number of button that need to change
if (first_changed_item_index <= mItems.size())
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index 3bb940948b..2d7ba9df67 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -75,7 +75,7 @@ public:
void setLandingTab(LLUICtrl* tab) { mLandingTab = tab; }
protected:
- void updateButtons();
+ void updateButtons(bool force_update = false);
LLButton* createButton(const LLPointer<LLViewerInventoryItem> item, const LLButton::Params& button_params, S32 x_offset );
const LLButton::Params& getButtonParams();
BOOL collectFavoriteItems(LLInventoryModel::item_array_t &items);
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 0a0e5ffc06..464e7ff4a2 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -996,7 +996,8 @@ void LLFloaterBuyLandUI::draw()
// virtual
BOOL LLFloaterBuyLandUI::canClose()
{
- bool can_close = (mTransaction ? FALSE : TRUE) && mCurrency.canCancel();
+ // mTransactionType check for pre-buy estimation stage and mCurrency to allow exit after transaction
+ bool can_close = !mTransaction && (mTransactionType != TransactionBuy || mCurrency.canCancel());
if (!can_close)
{
// explain to user why they can't do this, see DEV-9605
diff --git a/indra/newview/llfloatereditextdaycycle.cpp b/indra/newview/llfloatereditextdaycycle.cpp
index 0501c287ad..281d4f68f5 100644
--- a/indra/newview/llfloatereditextdaycycle.cpp
+++ b/indra/newview/llfloatereditextdaycycle.cpp
@@ -1457,14 +1457,22 @@ void LLFloaterEditExtDayCycle::reblendSettings()
{
F64 position = mTimeSlider->getCurSliderValue();
- if ((mSkyBlender->getTrack() != mCurrentTrack) && (mCurrentTrack != LLSettingsDay::TRACK_WATER))
+ if (mSkyBlender)
{
- mSkyBlender->switchTrack(mCurrentTrack, position);
+ if ((mSkyBlender->getTrack() != mCurrentTrack) && (mCurrentTrack != LLSettingsDay::TRACK_WATER))
+ {
+ mSkyBlender->switchTrack(mCurrentTrack, position);
+ }
+ else
+ {
+ mSkyBlender->setPosition(position);
+ }
}
- else
- mSkyBlender->setPosition(position);
- mWaterBlender->setPosition(position);
+ if (mWaterBlender)
+ {
+ mWaterBlender->setPosition(position);
+ }
}
void LLFloaterEditExtDayCycle::doApplyCommit(LLSettingsDay::ptr_t day)
diff --git a/indra/newview/llfloatergodtools.cpp b/indra/newview/llfloatergodtools.cpp
index adc7f71586..4b22f7427b 100644
--- a/indra/newview/llfloatergodtools.cpp
+++ b/indra/newview/llfloatergodtools.cpp
@@ -248,6 +248,29 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg)
region_flags = flags;
}
+ if (msg->has(_PREHASH_RegionInfo5))
+ {
+ F32 chat_whisper_range;
+ F32 chat_normal_range;
+ F32 chat_shout_range;
+ F32 chat_whisper_offset;
+ F32 chat_normal_offset;
+ F32 chat_shout_offset;
+ U32 chat_flags;
+
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperRange, chat_whisper_range);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalRange, chat_normal_range);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutRange, chat_shout_range);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperOffset, chat_whisper_offset);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalOffset, chat_normal_offset);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutOffset, chat_shout_offset);
+ msg->getU32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatFlags, chat_flags);
+
+ LL_INFOS() << "Whisper range: " << chat_whisper_range << " normal range: " << chat_normal_range << " shout range: " << chat_shout_range
+ << " whisper offset: " << chat_whisper_offset << " normal offset: " << chat_normal_offset << " shout offset: " << chat_shout_offset
+ << " chat flags: " << chat_flags << LL_ENDL;
+ }
+
if (host != gAgent.getRegionHost())
{
// Update is for a different region than the one we're in.
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index 7541bb5efe..441979389e 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -518,9 +518,12 @@ void LLFloaterIMSessionTab::addConversationViewParticipant(LLConversationItem* p
LLFolderViewItem* widget = get_ptr_in_map(mConversationsWidgets,uuid);
// If not already present, create the participant view and attach it to the root, otherwise, just refresh it
- if (widget && update_view)
+ if (widget)
{
- updateConversationViewParticipant(uuid); // overkill?
+ if (update_view)
+ {
+ updateConversationViewParticipant(uuid); // overkill?
+ }
}
else
{
diff --git a/indra/newview/llfloaterlinkreplace.cpp b/indra/newview/llfloaterlinkreplace.cpp
index 595d584799..8ee7a72055 100644
--- a/indra/newview/llfloaterlinkreplace.cpp
+++ b/indra/newview/llfloaterlinkreplace.cpp
@@ -162,7 +162,7 @@ void LLFloaterLinkReplace::onStartClicked()
else
{
LLSD args;
- args["TYPE"] = LLWearableType::getTypeName(source_item->getWearableType());
+ args["TYPE"] = LLWearableType::getInstance()->getTypeName(source_item->getWearableType());
params.substitutions(args);
LLNotifications::instance().add(params);
}
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index 92e64d0b95..12b4d6a1cd 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -263,7 +263,8 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mGotPersonalInfo(false),
mOriginalIMViaEmail(false),
mLanguageChanged(false),
- mAvatarDataInitialized(false)
+ mAvatarDataInitialized(false),
+ mSearchDataDirty(true)
{
LLConversationLog::instance().addObserver(this);
@@ -2144,6 +2145,11 @@ void LLFloaterPreference::updateClickActionViews()
getChild<LLComboBox>("double_click_action_combo")->setValue(dbl_click_to_teleport ? 2 : (int)dbl_click_to_walk);
}
+void LLFloaterPreference::updateSearchableItems()
+{
+ mSearchDataDirty = true;
+}
+
void LLFloaterPreference::applyUIColor(LLUICtrl* ctrl, const LLSD& param)
{
LLUIColorTable::instance().setColor(param.asString(), LLColor4(ctrl->getValue()));
@@ -2326,7 +2332,7 @@ BOOL LLPanelPreference::postBuild()
}
//////////////////////PanelSetup ///////////////////
- if (hasChild("max_bandwidth"), TRUE)
+ if (hasChild("max_bandwidth", TRUE))
{
mBandWidthUpdater = new LLPanelPreference::Updater(boost::bind(&handleBandwidthChanged, _1), BANDWIDTH_UPDATER_TIMEOUT);
gSavedSettings.getControl("ThrottleBandwidthKBPS")->getSignal()->connect(boost::bind(&LLPanelPreference::Updater::update, mBandWidthUpdater, _2));
@@ -2900,10 +2906,19 @@ void LLPanelPreferenceControls::populateControlTable()
filename = "control_table_contents_columns_basic.xml";
break;
default:
- // Either unknown mode or MODE_SAVED_SETTINGS
- // It doesn't have UI or actual settings yet
- LL_INFOS() << "Unimplemented mode" << LL_ENDL;
- return;
+ {
+ // Either unknown mode or MODE_SAVED_SETTINGS
+ // It doesn't have UI or actual settings yet
+ LL_WARNS() << "Unimplemented mode" << LL_ENDL;
+
+ // Searchable columns were removed, mark searchables for an update
+ LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
+ if (instance)
+ {
+ instance->updateSearchableItems();
+ }
+ return;
+ }
}
addControlTableColumns(filename);
@@ -2934,8 +2949,15 @@ void LLPanelPreferenceControls::populateControlTable()
}
else
{
- LL_INFOS() << "Unimplemented mode" << LL_ENDL;
- return;
+ LL_WARNS() << "Unimplemented mode" << LL_ENDL;
+ }
+
+ // Searchable columns were removed and readded, mark searchables for an update
+ // Note: at the moment tables/lists lack proper llsearchableui support
+ LLFloaterPreference* instance = LLFloaterReg::findTypedInstance<LLFloaterPreference>("preferences");
+ if (instance)
+ {
+ instance->updateSearchableItems();
}
}
@@ -3178,7 +3200,12 @@ void LLPanelPreferenceControls::setKeyBind(const std::string &control, EMouseCli
break;
}
}
- mConflictHandler[mode].registerControl(control, index, click, key, mask, true);
+ // At the moment 'ignore_mask' mask is mostly ignored, a placeholder
+ // Todo: implement it since it's preferable for things like teleport to match
+ // mask exactly but for things like running to ignore additional masks
+ // Ideally this needs representation in keybindings UI
+ bool ignore_mask = true;
+ mConflictHandler[mode].registerControl(control, index, click, key, mask, ignore_mask);
}
else if (!set)
{
@@ -3553,6 +3580,12 @@ void LLFloaterPreference::onUpdateFilterTerm(bool force)
if( !mSearchData || (mSearchData->mLastFilter == seachValue && !force))
return;
+ if (mSearchDataDirty)
+ {
+ // Data exists, but is obsolete, regenerate
+ collectSearchableItems();
+ }
+
mSearchData->mLastFilter = seachValue;
if( !mSearchData->mRootTab )
@@ -3650,4 +3683,5 @@ void LLFloaterPreference::collectSearchableItems()
collectChildren( this, ll::prefs::PanelDataPtr(), pRootTabcontainer );
}
+ mSearchDataDirty = false;
}
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 1268935712..e9e19e9acb 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -108,6 +108,7 @@ public:
void getControlNames(std::vector<std::string>& names);
// updates click/double-click action controls depending on values from settings.xml
void updateClickActionViews();
+ void updateSearchableItems();
protected:
void onBtnOK(const LLSD& userdata);
@@ -220,6 +221,7 @@ private:
LLSearchEditor *mFilterEdit;
std::unique_ptr< ll::prefs::SearchData > mSearchData;
+ bool mSearchDataDirty;
void onUpdateFilterTerm( bool force = false );
void collectSearchableItems();
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index ec1909d02a..17e55b5f2c 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -470,6 +470,29 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg)
region_flags = flags;
}
+ if (msg->has(_PREHASH_RegionInfo5))
+ {
+ F32 chat_whisper_range;
+ F32 chat_normal_range;
+ F32 chat_shout_range;
+ F32 chat_whisper_offset;
+ F32 chat_normal_offset;
+ F32 chat_shout_offset;
+ U32 chat_flags;
+
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperRange, chat_whisper_range);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalRange, chat_normal_range);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutRange, chat_shout_range);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperOffset, chat_whisper_offset);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalOffset, chat_normal_offset);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutOffset, chat_shout_offset);
+ msg->getU32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatFlags, chat_flags);
+
+ LL_INFOS() << "Whisper range: " << chat_whisper_range << " normal range: " << chat_normal_range << " shout range: " << chat_shout_range
+ << " whisper offset: " << chat_whisper_offset << " normal offset: " << chat_normal_offset << " shout offset: " << chat_shout_offset
+ << " chat flags: " << chat_flags << LL_ENDL;
+ }
+
// GENERAL PANEL
panel = tab->getChild<LLPanel>("General");
panel->getChild<LLUICtrl>("region_text")->setValue(LLSD(sim_name));
diff --git a/indra/newview/llfloaterwindowsize.cpp b/indra/newview/llfloaterwindowsize.cpp
index ec161018b8..863b7cbb12 100644
--- a/indra/newview/llfloaterwindowsize.cpp
+++ b/indra/newview/llfloaterwindowsize.cpp
@@ -34,18 +34,16 @@
#include "llcombobox.h"
#include "llfloater.h"
#include "llfloaterreg.h"
+#include "llregex.h"
#include "lluictrl.h"
-// System libraries
-#include <boost/regex.hpp>
-
// Extract from strings of the form "<width> x <height>", e.g. "640 x 480".
bool extractWindowSizeFromString(const std::string& instr, U32 *width, U32 *height)
{
boost::cmatch what;
// matches (any number)(any non-number)(any number)
const boost::regex expression("([0-9]+)[^0-9]+([0-9]+)");
- if (boost::regex_match(instr.c_str(), what, expression))
+ if (ll_regex_match(instr.c_str(), what, expression))
{
*width = atoi(what[1].first);
*height = atoi(what[2].first);
diff --git a/indra/newview/llhasheduniqueid.cpp b/indra/newview/llhasheduniqueid.cpp
index 03192d3e61..38dafc167f 100644
--- a/indra/newview/llhasheduniqueid.cpp
+++ b/indra/newview/llhasheduniqueid.cpp
@@ -35,8 +35,8 @@ bool llHashedUniqueID(unsigned char id[MD5HEX_STR_SIZE])
bool idIsUnique = true;
LLMD5 hashed_unique_id;
unsigned char unique_id[MAC_ADDRESS_BYTES];
- if ( LLUUID::getNodeID(unique_id)
- || LLMachineID::getUniqueID(unique_id, sizeof(unique_id))
+ if ( LLMachineID::getUniqueID(unique_id, sizeof(unique_id))
+ || LLUUID::getNodeID(unique_id)
)
{
hashed_unique_id.update(unique_id, MAC_ADDRESS_BYTES);
diff --git a/indra/newview/llimprocessing.cpp b/indra/newview/llimprocessing.cpp
index 1e43e4ea3a..0524313a5c 100644
--- a/indra/newview/llimprocessing.cpp
+++ b/indra/newview/llimprocessing.cpp
@@ -42,6 +42,7 @@
#include "llnotificationsutil.h"
#include "llnotificationmanager.h"
#include "llpanelgroup.h"
+#include "llregex.h"
#include "llregionhandle.h"
#include "llsdserialize.h"
#include "llslurl.h"
@@ -55,7 +56,6 @@
#include "llviewerregion.h"
#include "llvoavatarself.h"
-#include <boost/regex.hpp>
#include "boost/lexical_cast.hpp"
#if LL_MSVC
// disable boost::lexical_cast warning
@@ -122,7 +122,7 @@ static std::string clean_name_from_task_im(const std::string& msg,
boost::smatch match;
static const boost::regex returned_exp(
"(.*been returned to your inventory lost and found folder by )(.+)( (from|near).*)");
- if (boost::regex_match(msg, match, returned_exp))
+ if (ll_regex_match(msg, match, returned_exp))
{
// match objects are 1-based for groups
std::string final = match[1].str();
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 844d544e16..3609c5e457 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -5465,11 +5465,20 @@ void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
getClipboardEntries(true, items, disabled_items, flags);
items.push_back(std::string("Texture Separator"));
- items.push_back(std::string("Save As"));
- if (!canSaveTexture())
- {
- disabled_items.push_back(std::string("Save As"));
- }
+
+ if ((flags & ITEM_IN_MULTI_SELECTION) != 0)
+ {
+ items.push_back(std::string("Save Selected As"));
+ }
+ else
+ {
+ items.push_back(std::string("Save As"));
+ if (!canSaveTexture())
+ {
+ disabled_items.push_back(std::string("Save As"));
+ }
+ }
+
}
addLinkReplaceMenuOption(items, disabled_items);
hide_context_entries(menu, items, disabled_items);
@@ -5487,6 +5496,23 @@ void LLTextureBridge::performAction(LLInventoryModel* model, std::string action)
preview_texture->saveAs();
}
}
+ else if ("save_selected_as" == action)
+ {
+ openItem();
+ if (canSaveTexture())
+ {
+ LLPreviewTexture* preview_texture = LLFloaterReg::getTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
+ if (preview_texture)
+ {
+ preview_texture->saveMultipleToFile(mFileName);
+ }
+ }
+ else
+ {
+ LL_WARNS() << "You don't have permission to save " << getName() << " to disk." << LL_ENDL;
+ }
+
+ }
else LLItemBridge::performAction(model, action);
}
@@ -6817,7 +6843,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
disabled_items.push_back(std::string("Wearable Edit"));
}
- if (LLWearableType::getAllowMultiwear(mWearableType))
+ if (LLWearableType::getInstance()->getAllowMultiwear(mWearableType))
{
items.push_back(std::string("Wearable Add"));
if (!gAgentWearables.canAddWearable(mWearableType))
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 9af8664388..c21bfbd02d 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -403,6 +403,9 @@ public:
virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
virtual void performAction(LLInventoryModel* model, std::string action);
bool canSaveTexture(void);
+ void setFileName(const std::string& file_name) { mFileName = file_name; }
+protected:
+ std::string mFileName;
};
class LLSoundBridge : public LLItemBridge
diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp
index 84018655d0..707ff2b7b6 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -36,13 +36,14 @@
#include "llinventorymodelbackgroundfetch.h"
#include "llinventoryfunctions.h"
#include "llmarketplacefunctions.h"
+#include "llregex.h"
#include "llviewercontrol.h"
#include "llfolderview.h"
#include "llinventorybridge.h"
#include "llviewerfoldertype.h"
#include "llradiogroup.h"
#include "llstartup.h"
-#include <boost/regex.hpp>
+
// linden library includes
#include "llclipboard.h"
#include "lltrans.h"
@@ -877,7 +878,7 @@ void LLInventoryFilter::setFilterSubString(const std::string& string)
boost::regex mPattern = boost::regex("\"\\s*([^<]*)?\\s*\"",
boost::regex::perl | boost::regex::icase);
boost::match_results<std::string::const_iterator> matches;
- mExactToken = (boost::regex_match(filter_sub_string_new, matches, mPattern) && matches[1].matched)
+ mExactToken = (ll_regex_match(filter_sub_string_new, matches, mPattern) && matches[1].matched)
? matches[1]
: LLStringUtil::null;
if ((old_token.empty() && !mExactToken.empty())
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
index f2e06d19f3..9cc67766ca 100644
--- a/indra/newview/llinventoryfunctions.cpp
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -47,6 +47,7 @@
#include "llappviewer.h"
#include "llavataractions.h"
#include "llclipboard.h"
+#include "lldirpicker.h"
#include "lldonotdisturbnotificationstorage.h"
#include "llfloatersidepanelcontainer.h"
#include "llfocusmgr.h"
@@ -2517,6 +2518,10 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
{
LLAppearanceMgr::instance().removeItemsFromAvatar(ids);
}
+ else if ("save_selected_as" == action)
+ {
+ (new LLDirPickerThread(boost::bind(&LLInventoryAction::saveMultipleTextures, _1, selected_items, model), std::string()))->getFile();
+ }
else
{
std::set<LLFolderViewItem*>::iterator set_iter;
@@ -2544,6 +2549,41 @@ void LLInventoryAction::doToSelected(LLInventoryModel* model, LLFolderView* root
}
}
+void LLInventoryAction::saveMultipleTextures(const std::vector<std::string>& filenames, std::set<LLFolderViewItem*> selected_items, LLInventoryModel* model)
+{
+ gSavedSettings.setString("TextureSaveLocation", filenames[0]);
+
+ LLMultiPreview* multi_previewp = new LLMultiPreview();
+ gFloaterView->addChild(multi_previewp);
+
+ LLFloater::setFloaterHost(multi_previewp);
+
+ std::map<std::string, S32> tex_names_map;
+ std::set<LLFolderViewItem*>::iterator set_iter;
+
+ for (set_iter = selected_items.begin(); set_iter != selected_items.end(); ++set_iter)
+ {
+ LLFolderViewItem* folder_item = *set_iter;
+ if(!folder_item) continue;
+ LLTextureBridge* bridge = (LLTextureBridge*)folder_item->getViewModelItem();
+ if(!bridge) continue;
+
+ std::string tex_name = bridge->getName();
+ if(!tex_names_map.insert(std::pair<std::string, S32>(tex_name, 0)).second)
+ {
+ tex_names_map[tex_name]++;
+ bridge->setFileName(tex_name + llformat("_%.3d", tex_names_map[tex_name]));
+ }
+ bridge->performAction(model, "save_selected_as");
+ }
+
+ LLFloater::setFloaterHost(NULL);
+ if (multi_previewp)
+ {
+ multi_previewp->openFloater(LLSD());
+ }
+}
+
void LLInventoryAction::removeItemFromDND(LLFolderView* root)
{
if(gAgent.isDoNotDisturb())
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
index 37c3c47336..2cb2b1e877 100644
--- a/indra/newview/llinventoryfunctions.h
+++ b/indra/newview/llinventoryfunctions.h
@@ -468,6 +468,8 @@ struct LLInventoryAction
static void onItemsRemovalConfirmation(const LLSD& notification, const LLSD& response, LLHandle<LLFolderView> root);
static void removeItemFromDND(LLFolderView* root);
+ static void saveMultipleTextures(const std::vector<std::string>& filenames, std::set<LLFolderViewItem*> selected_items, LLInventoryModel* model);
+
static const int sConfirmOnDeleteItemsNumber;
private:
diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp
index 81c001b8bd..44e493fdf4 100644
--- a/indra/newview/llinventoryicon.cpp
+++ b/indra/newview/llinventoryicon.cpp
@@ -196,7 +196,7 @@ const std::string& LLInventoryIcon::getIconName(LLInventoryType::EIconName idx)
LLInventoryType::EIconName LLInventoryIcon::assignWearableIcon(U32 misc_flag)
{
const LLWearableType::EType wearable_type = LLWearableType::inventoryFlagsToWearableType(misc_flag);
- return LLWearableType::getIconName(wearable_type);
+ return LLWearableType::getInstance()->getIconName(wearable_type);
}
LLInventoryType::EIconName LLInventoryIcon::assignSettingsIcon(U32 misc_flag)
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 28db6a5808..ba453471c6 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -487,7 +487,8 @@ const LLUUID LLInventoryModel::findCategoryUUIDForTypeInRoot(
S32 count = cats->size();
for(S32 i = 0; i < count; ++i)
{
- if(cats->at(i)->getPreferredType() == preferred_type)
+ LLViewerInventoryCategory* p_cat = cats->at(i);
+ if(p_cat && p_cat->getPreferredType() == preferred_type)
{
const LLUUID& folder_id = cats->at(i)->getUUID();
if (rv.isNull() || folder_id < rv)
@@ -1659,9 +1660,18 @@ void LLInventoryModel::notifyObservers()
iter = mObservers.upper_bound(observer);
}
- mModifyMask = LLInventoryObserver::NONE;
+ // If there were any changes that arrived during notifyObservers,
+ // shedule them for next loop
+ mModifyMask = mModifyMaskBacklog;
mChangedItemIDs.clear();
+ mChangedItemIDs.insert(mChangedItemIDsBacklog.begin(), mChangedItemIDsBacklog.end());
mAddedItemIDs.clear();
+ mAddedItemIDs.insert(mAddedItemIDsBacklog.begin(), mAddedItemIDsBacklog.end());
+
+ mModifyMaskBacklog = LLInventoryObserver::NONE;
+ mChangedItemIDsBacklog.clear();
+ mAddedItemIDsBacklog.clear();
+
mIsNotifyObservers = FALSE;
}
@@ -1673,8 +1683,10 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
{
// Something marked an item for change within a call to notifyObservers
// (which is in the process of processing the list of items marked for change).
- // This means the change may fail to be processed.
- LL_WARNS(LOG_INV) << "Adding changed mask within notify observers! Change will likely be lost." << LL_ENDL;
+ // This means the change will have to be processed later.
+ // It's preferable for this not to happen, but it's not an issue unless code
+ // specifically wants to notifyObservers immediately (changes won't happen untill later)
+ LL_WARNS(LOG_INV) << "Adding changed mask within notify observers! Change's processing will be performed on idle." << LL_ENDL;
LLViewerInventoryItem *item = getItem(referent);
if (item)
{
@@ -1689,17 +1701,40 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
}
}
}
-
- mModifyMask |= mask;
+
+ if (mIsNotifyObservers)
+ {
+ mModifyMaskBacklog |= mask;
+ }
+ else
+ {
+ mModifyMask |= mask;
+ }
+
if (referent.notNull() && (mChangedItemIDs.find(referent) == mChangedItemIDs.end()))
{
- mChangedItemIDs.insert(referent);
+ if (mIsNotifyObservers)
+ {
+ mChangedItemIDsBacklog.insert(referent);
+ }
+ else
+ {
+ mChangedItemIDs.insert(referent);
+ }
+
update_marketplace_category(referent, false);
- if (mask & LLInventoryObserver::ADD)
- {
- mAddedItemIDs.insert(referent);
- }
+ if (mask & LLInventoryObserver::ADD)
+ {
+ if (mIsNotifyObservers)
+ {
+ mAddedItemIDsBacklog.insert(referent);
+ }
+ else
+ {
+ mAddedItemIDs.insert(referent);
+ }
+ }
// Update all linked items. Starting with just LABEL because I'm
// not sure what else might need to be accounted for this.
@@ -2660,7 +2695,10 @@ void LLInventoryModel::createCommonSystemCategories()
gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD,true);
gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS,true);
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, true);
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK, true); // folder should exist before user tries to 'landmark this'
gInventory.findCategoryUUIDForType(LLFolderType::FT_SETTINGS, true);
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX, true);
}
struct LLUUIDAndName
@@ -3705,17 +3743,18 @@ void LLInventoryModel::dumpInventory() const
// returning an overall good/bad flag.
bool LLInventoryModel::validate() const
{
- bool valid = true;
+ const S32 MAX_VERBOSE_ERRORS = 40; // too many errors can cause disconect or freeze
+ S32 error_count = 0;
if (getRootFolderID().isNull())
{
LL_WARNS() << "no root folder id" << LL_ENDL;
- valid = false;
+ error_count++;
}
if (getLibraryRootFolderID().isNull())
{
LL_WARNS() << "no root folder id" << LL_ENDL;
- valid = false;
+ error_count++;
}
if (mCategoryMap.size() + 1 != mParentChildCategoryTree.size())
@@ -3723,7 +3762,7 @@ bool LLInventoryModel::validate() const
// ParentChild should be one larger because of the special entry for null uuid.
LL_INFOS() << "unexpected sizes: cat map size " << mCategoryMap.size()
<< " parent/child " << mParentChildCategoryTree.size() << LL_ENDL;
- valid = false;
+ error_count++;
}
S32 cat_lock = 0;
S32 item_lock = 0;
@@ -3735,23 +3774,32 @@ bool LLInventoryModel::validate() const
const LLViewerInventoryCategory *cat = cit->second;
if (!cat)
{
- LL_WARNS() << "invalid cat" << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "invalid cat" << LL_ENDL;
+ }
+ error_count++;
continue;
}
if (cat_id != cat->getUUID())
{
- LL_WARNS() << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "cat id/index mismatch " << cat_id << " " << cat->getUUID() << LL_ENDL;
+ }
+ error_count++;
}
if (cat->getParentUUID().isNull())
{
if (cat_id != getRootFolderID() && cat_id != getLibraryRootFolderID())
{
- LL_WARNS() << "cat " << cat_id << " has no parent, but is not root ("
- << getRootFolderID() << ") or library root ("
- << getLibraryRootFolderID() << ")" << LL_ENDL;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "cat " << cat_id << " has no parent, but is not root ("
+ << getRootFolderID() << ") or library root ("
+ << getLibraryRootFolderID() << ")" << LL_ENDL;
+ }
}
}
cat_array_t* cats;
@@ -3759,8 +3807,11 @@ bool LLInventoryModel::validate() const
getDirectDescendentsOf(cat_id,cats,items);
if (!cats || !items)
{
- LL_WARNS() << "invalid direct descendents for " << cat_id << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "invalid direct descendents for " << cat_id << LL_ENDL;
+ }
+ error_count++;
continue;
}
if (cat->getDescendentCount() == LLViewerInventoryCategory::DESCENDENT_COUNT_UNKNOWN)
@@ -3769,12 +3820,15 @@ bool LLInventoryModel::validate() const
}
else if (cats->size() + items->size() != cat->getDescendentCount())
{
- LL_WARNS() << "invalid desc count for " << cat_id << " name [" << cat->getName()
- << "] parent " << cat->getParentUUID()
- << " cached " << cat->getDescendentCount()
- << " expected " << cats->size() << "+" << items->size()
- << "=" << cats->size() +items->size() << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "invalid desc count for " << cat_id << " name [" << cat->getName()
+ << "] parent " << cat->getParentUUID()
+ << " cached " << cat->getDescendentCount()
+ << " expected " << cats->size() << "+" << items->size()
+ << "=" << cats->size() + items->size() << LL_ENDL;
+ }
+ error_count++;
}
if (cat->getVersion() == LLViewerInventoryCategory::VERSION_UNKNOWN)
{
@@ -3794,8 +3848,11 @@ bool LLInventoryModel::validate() const
if (!item)
{
- LL_WARNS() << "null item at index " << i << " for cat " << cat_id << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "null item at index " << i << " for cat " << cat_id << LL_ENDL;
+ }
+ error_count++;
continue;
}
@@ -3803,10 +3860,13 @@ bool LLInventoryModel::validate() const
if (item->getParentUUID() != cat_id)
{
- LL_WARNS() << "wrong parent for " << item_id << " found "
- << item->getParentUUID() << " expected " << cat_id
- << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "wrong parent for " << item_id << " found "
+ << item->getParentUUID() << " expected " << cat_id
+ << LL_ENDL;
+ }
+ error_count++;
}
@@ -3814,17 +3874,24 @@ bool LLInventoryModel::validate() const
item_map_t::const_iterator it = mItemMap.find(item_id);
if (it == mItemMap.end())
{
- LL_WARNS() << "item " << item_id << " found as child of "
- << cat_id << " but not in top level mItemMap" << LL_ENDL;
- valid = false;
+
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "item " << item_id << " found as child of "
+ << cat_id << " but not in top level mItemMap" << LL_ENDL;
+ }
+ error_count++;
}
else
{
LLViewerInventoryItem *top_item = it->second;
if (top_item != item)
{
- LL_WARNS() << "item mismatch, item_id " << item_id
- << " top level entry is different, uuid " << top_item->getUUID() << LL_ENDL;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "item mismatch, item_id " << item_id
+ << " top level entry is different, uuid " << top_item->getUUID() << LL_ENDL;
+ }
}
}
@@ -3833,19 +3900,25 @@ bool LLInventoryModel::validate() const
bool found = getObjectTopmostAncestor(item_id, topmost_ancestor_id);
if (!found)
{
- LL_WARNS() << "unable to find topmost ancestor for " << item_id << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "unable to find topmost ancestor for " << item_id << LL_ENDL;
+ }
+ error_count++;
}
else
{
if (topmost_ancestor_id != getRootFolderID() &&
topmost_ancestor_id != getLibraryRootFolderID())
{
- LL_WARNS() << "unrecognized top level ancestor for " << item_id
- << " got " << topmost_ancestor_id
- << " expected " << getRootFolderID()
- << " or " << getLibraryRootFolderID() << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "unrecognized top level ancestor for " << item_id
+ << " got " << topmost_ancestor_id
+ << " expected " << getRootFolderID()
+ << " or " << getLibraryRootFolderID() << LL_ENDL;
+ }
+ error_count++;
}
}
}
@@ -3859,9 +3932,12 @@ bool LLInventoryModel::validate() const
getDirectDescendentsOf(parent_id,cats,items);
if (!cats)
{
- LL_WARNS() << "cat " << cat_id << " name [" << cat->getName()
- << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "cat " << cat_id << " name [" << cat->getName()
+ << "] orphaned - no child cat array for alleged parent " << parent_id << LL_ENDL;
+ }
+ error_count++;
}
else
{
@@ -3877,8 +3953,11 @@ bool LLInventoryModel::validate() const
}
if (!found)
{
- LL_WARNS() << "cat " << cat_id << " name [" << cat->getName()
- << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "cat " << cat_id << " name [" << cat->getName()
+ << "] orphaned - not found in child cat array of alleged parent " << parent_id << LL_ENDL;
+ }
}
}
}
@@ -3890,24 +3969,33 @@ bool LLInventoryModel::validate() const
LLViewerInventoryItem *item = iit->second;
if (item->getUUID() != item_id)
{
- LL_WARNS() << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL;
- valid = false;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "item_id " << item_id << " does not match " << item->getUUID() << LL_ENDL;
+ }
+ error_count++;
}
const LLUUID& parent_id = item->getParentUUID();
if (parent_id.isNull())
{
- LL_WARNS() << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "item " << item_id << " name [" << item->getName() << "] has null parent id!" << LL_ENDL;
+ }
}
- else
+ else if (error_count < MAX_VERBOSE_ERRORS)
{
cat_array_t* cats;
item_array_t* items;
getDirectDescendentsOf(parent_id,cats,items);
if (!items)
{
- LL_WARNS() << "item " << item_id << " name [" << item->getName()
- << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "item " << item_id << " name [" << item->getName()
+ << "] orphaned - alleged parent has no child items list " << parent_id << LL_ENDL;
+ }
}
else
{
@@ -3922,63 +4010,70 @@ bool LLInventoryModel::validate() const
}
if (!found)
{
- LL_WARNS() << "item " << item_id << " name [" << item->getName()
- << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ LL_WARNS() << "item " << item_id << " name [" << item->getName()
+ << "] orphaned - not found as child of alleged parent " << parent_id << LL_ENDL;
+ }
}
}
}
- // Link checking
- if (item->getIsLinkType())
- {
- const LLUUID& link_id = item->getUUID();
- const LLUUID& target_id = item->getLinkedUUID();
- LLViewerInventoryItem *target_item = getItem(target_id);
- LLViewerInventoryCategory *target_cat = getCategory(target_id);
- // Linked-to UUID should have back reference to this link.
- if (!hasBacklinkInfo(link_id, target_id))
- {
- LL_WARNS() << "link " << item->getUUID() << " type " << item->getActualType()
- << " missing backlink info at target_id " << target_id
- << LL_ENDL;
- }
- // Links should have referents.
- if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
- {
- LL_WARNS() << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
- }
- else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
- {
- LL_WARNS() << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
- }
- if (target_item && target_item->getIsLinkType())
- {
- LL_WARNS() << "link " << item->getName() << " references a link item "
- << target_item->getName() << " " << target_item->getUUID() << LL_ENDL;
- }
- // Links should not have backlinks.
- std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(link_id);
- if (range.first != range.second)
- {
- LL_WARNS() << "Link item " << item->getName() << " has backlinks!" << LL_ENDL;
- }
- }
- else
- {
- // Check the backlinks of a non-link item.
- const LLUUID& target_id = item->getUUID();
- std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(target_id);
- for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
- {
- const LLUUID& link_id = it->second;
- LLViewerInventoryItem *link_item = getItem(link_id);
- if (!link_item || !link_item->getIsLinkType())
- {
- LL_WARNS() << "invalid backlink from target " << item->getName() << " to " << link_id << LL_ENDL;
- }
- }
- }
+ // Link checking
+ if (error_count < MAX_VERBOSE_ERRORS)
+ {
+ if (item->getIsLinkType())
+ {
+ const LLUUID& link_id = item->getUUID();
+ const LLUUID& target_id = item->getLinkedUUID();
+ LLViewerInventoryItem *target_item = getItem(target_id);
+ LLViewerInventoryCategory *target_cat = getCategory(target_id);
+ // Linked-to UUID should have back reference to this link.
+ if (!hasBacklinkInfo(link_id, target_id))
+ {
+ LL_WARNS() << "link " << item->getUUID() << " type " << item->getActualType()
+ << " missing backlink info at target_id " << target_id
+ << LL_ENDL;
+ }
+ // Links should have referents.
+ if (item->getActualType() == LLAssetType::AT_LINK && !target_item)
+ {
+ LL_WARNS() << "broken item link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+ }
+ else if (item->getActualType() == LLAssetType::AT_LINK_FOLDER && !target_cat)
+ {
+ LL_WARNS() << "broken folder link " << item->getName() << " id " << item->getUUID() << LL_ENDL;
+ }
+ if (target_item && target_item->getIsLinkType())
+ {
+ LL_WARNS() << "link " << item->getName() << " references a link item "
+ << target_item->getName() << " " << target_item->getUUID() << LL_ENDL;
+ }
+
+ // Links should not have backlinks.
+ std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(link_id);
+ if (range.first != range.second)
+ {
+ LL_WARNS() << "Link item " << item->getName() << " has backlinks!" << LL_ENDL;
+ }
+ }
+ else
+ {
+ // Check the backlinks of a non-link item.
+ const LLUUID& target_id = item->getUUID();
+ std::pair<backlink_mmap_t::const_iterator, backlink_mmap_t::const_iterator> range = mBacklinkMMap.equal_range(target_id);
+ for (backlink_mmap_t::const_iterator it = range.first; it != range.second; ++it)
+ {
+ const LLUUID& link_id = it->second;
+ LLViewerInventoryItem *link_item = getItem(link_id);
+ if (!link_item || !link_item->getIsLinkType())
+ {
+ LL_WARNS() << "invalid backlink from target " << item->getName() << " to " << link_id << LL_ENDL;
+ }
+ }
+ }
+ }
}
if (cat_lock > 0 || item_lock > 0)
@@ -3995,9 +4090,9 @@ bool LLInventoryModel::validate() const
LL_INFOS() << "Found " << version_unknown_count << " cats with unknown version" << LL_ENDL;
}
- LL_INFOS() << "Validate done, valid = " << (U32) valid << LL_ENDL;
+ LL_INFOS() << "Validate done, found " << error_count << " errors" << LL_ENDL;
- return valid;
+ return error_count == 0;
}
///----------------------------------------------------------------------------
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index a4326aaeed..4dcd9332be 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -538,6 +538,10 @@ private:
U32 mModifyMask;
changed_items_t mChangedItemIDs;
changed_items_t mAddedItemIDs;
+ // Fallback when notifyObservers is in progress
+ U32 mModifyMaskBacklog;
+ changed_items_t mChangedItemIDsBacklog;
+ changed_items_t mAddedItemIDsBacklog;
//--------------------------------------------------------------------
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
index 9b7e0c7824..7c241c3283 100644
--- a/indra/newview/llinventorypanel.cpp
+++ b/indra/newview/llinventorypanel.cpp
@@ -44,6 +44,7 @@
#include "llinventoryfunctions.h"
#include "llinventorymodelbackgroundfetch.h"
#include "llnotificationsutil.h"
+#include "llpanelmaininventory.h"
#include "llpreview.h"
#include "llsidepanelinventory.h"
#include "llstartup.h"
@@ -1613,7 +1614,7 @@ void LLInventoryPanel::openInventoryPanelAndSetSelection(BOOL auto_open, const L
bool in_inbox = (gInventory.isObjectDescendentOf(obj_id, gInventory.findCategoryUUIDForType(LLFolderType::FT_INBOX)));
- if (main_panel && !in_inbox)
+ if (!in_inbox && (main_panel || !sidepanel_inventory->getMainInventoryPanel()->isRecentItemsPanelSelected()))
{
sidepanel_inventory->selectAllItemsPanel();
}
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index eebc2486a2..fb9885b454 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -30,6 +30,7 @@
#include "llagentui.h"
#include "llavatarnamecache.h"
#include "lllogchat.h"
+#include "llregex.h"
#include "lltrans.h"
#include "llviewercontrol.h"
@@ -40,7 +41,6 @@
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/replace.hpp>
-#include <boost/regex.hpp>
#include <boost/regex/v4/match_results.hpp>
#include <boost/foreach.hpp>
@@ -250,8 +250,8 @@ std::string LLLogChat::makeLogFileName(std::string filename)
**/
boost::match_results<std::string::const_iterator> matches;
- bool inboundConf = boost::regex_match(filename, matches, INBOUND_CONFERENCE);
- bool outboundConf = boost::regex_match(filename, matches, OUTBOUND_CONFERENCE);
+ bool inboundConf = ll_regex_match(filename, matches, INBOUND_CONFERENCE);
+ bool outboundConf = ll_regex_match(filename, matches, OUTBOUND_CONFERENCE);
if (!(inboundConf || outboundConf))
{
if( gSavedPerAccountSettings.getBOOL("LogFileNamewithDate") )
@@ -837,7 +837,7 @@ bool LLLogChat::isTranscriptFileFound(std::string fullname)
{
//matching a timestamp
boost::match_results<std::string::const_iterator> matches;
- if (boost::regex_match(remove_utf8_bom(buffer), matches, TIMESTAMP))
+ if (ll_regex_match(remove_utf8_bom(buffer), matches, TIMESTAMP))
{
result = true;
}
@@ -917,7 +917,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
//matching a timestamp
boost::match_results<std::string::const_iterator> matches;
- if (!boost::regex_match(raw, matches, TIMESTAMP_AND_STUFF)) return false;
+ if (!ll_regex_match(raw, matches, TIMESTAMP_AND_STUFF)) return false;
bool has_timestamp = matches[IDX_TIMESTAMP].matched;
if (has_timestamp)
@@ -950,7 +950,7 @@ bool LLChatLogParser::parse(std::string& raw, LLSD& im, const LLSD& parse_params
//matching a name and a text
std::string stuff = matches[IDX_STUFF];
boost::match_results<std::string::const_iterator> name_and_text;
- if (!boost::regex_match(stuff, name_and_text, NAME_AND_TEXT)) return false;
+ if (!ll_regex_match(stuff, name_and_text, NAME_AND_TEXT)) return false;
bool has_name = name_and_text[IDX_NAME].matched;
std::string name = LLURI::unescape(name_and_text[IDX_NAME]);
diff --git a/indra/newview/llmachineid.cpp b/indra/newview/llmachineid.cpp
index 57a6ecb604..89eb941106 100644
--- a/indra/newview/llmachineid.cpp
+++ b/indra/newview/llmachineid.cpp
@@ -30,240 +30,447 @@
#if LL_WINDOWS
#define _WIN32_DCOM
#include <iostream>
-using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
+#elif LL_DARWIN
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
#endif
unsigned char static_unique_id[] = {0,0,0,0,0,0};
+unsigned char static_legacy_id[] = {0,0,0,0,0,0};
bool static has_static_unique_id = false;
+bool static has_static_legacy_id = false;
#if LL_WINDOWS
-class LLComInitialize
+class LLWMIMethods
{
- HRESULT mHR;
public:
- LLComInitialize()
+ LLWMIMethods()
+ : pLoc(NULL),
+ pSvc(NULL)
{
- mHR = CoInitializeEx(0, COINIT_MULTITHREADED);
- if (FAILED(mHR))
- LL_DEBUGS("AppInit") << "Failed to initialize COM library. Error code = 0x" << hex << mHR << LL_ENDL;
+ initCOMObjects();
}
- ~LLComInitialize()
+ ~LLWMIMethods()
{
- if (SUCCEEDED(mHR))
- CoUninitialize();
+ if (isInitialized())
+ {
+ cleanCOMObjects();
+ }
}
-};
-#endif //LL_WINDOWS
+ bool isInitialized() { return SUCCEEDED(mHR); }
+ bool getWindowsProductNumber(unsigned char *unique_id, size_t len);
+ bool getDiskDriveSerialNumber(unsigned char *unique_id, size_t len);
+ bool getProcessorSerialNumber(unsigned char *unique_id, size_t len);
+ bool getMotherboardSerialNumber(unsigned char *unique_id, size_t len);
+ bool getComputerSystemProductUUID(unsigned char *unique_id, size_t len);
+ bool getGenericSerialNumber(const BSTR &select, const LPCWSTR &variable, unsigned char *unique_id, size_t len, bool validate_as_uuid = false);
-// get an unique machine id.
-// NOT THREAD SAFE - do before setting up threads.
-// MAC Address doesn't work for Windows 7 since the first returned hardware MAC address changes with each reboot, Go figure??
+private:
+ void initCOMObjects();
+ void cleanCOMObjects();
-S32 LLMachineID::init()
+ HRESULT mHR;
+ IWbemLocator *pLoc;
+ IWbemServices *pSvc;
+};
+
+
+void LLWMIMethods::initCOMObjects()
{
- size_t len = sizeof(static_unique_id);
- memset(static_unique_id, 0, len);
- S32 ret_code = 0;
-#if LL_WINDOWS
# pragma comment(lib, "wbemuuid.lib")
+ // Step 1: --------------------------------------------------
+ // Initialize COM. ------------------------------------------
- // algorithm to detect BIOS serial number found at:
- // http://msdn.microsoft.com/en-us/library/aa394077%28VS.85%29.aspx
- // we can't use the MAC address since on Windows 7, the first returned MAC address changes with every reboot.
+ mHR = CoInitializeEx(0, COINIT_MULTITHREADED);
+ if (FAILED(mHR))
+ {
+ LL_DEBUGS("AppInit") << "Failed to initialize COM library. Error code = 0x" << std::hex << mHR << LL_ENDL;
+ return;
+ }
+ // Step 2: --------------------------------------------------
+ // Set general COM security levels --------------------------
+ // Note: If you are using Windows 2000, you need to specify -
+ // the default authentication credentials for a user by using
+ // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
+ // parameter of CoInitializeSecurity ------------------------
+
+ mHR = CoInitializeSecurity(
+ NULL,
+ -1, // COM authentication
+ NULL, // Authentication services
+ NULL, // Reserved
+ RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
+ RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
+ NULL, // Authentication info
+ EOAC_NONE, // Additional capabilities
+ NULL // Reserved
+ );
+
+ if (FAILED(mHR))
+ {
+ LL_WARNS("AppInit") << "Failed to initialize security. Error code = 0x" << std::hex << mHR << LL_ENDL;
+ CoUninitialize();
+ return; // Program has failed.
+ }
- HRESULT hres;
+ // Step 3: ---------------------------------------------------
+ // Obtain the initial locator to WMI -------------------------
- // Step 1: --------------------------------------------------
- // Initialize COM. ------------------------------------------
+ mHR = CoCreateInstance(
+ CLSID_WbemLocator,
+ 0,
+ CLSCTX_INPROC_SERVER,
+ IID_IWbemLocator, (LPVOID *)&pLoc);
- LLComInitialize comInit;
+ if (FAILED(mHR))
+ {
+ LL_WARNS("AppInit") << "Failed to create IWbemLocator object." << " Err code = 0x" << std::hex << mHR << LL_ENDL;
+ CoUninitialize();
+ return; // Program has failed.
+ }
- // Step 2: --------------------------------------------------
- // Set general COM security levels --------------------------
- // Note: If you are using Windows 2000, you need to specify -
- // the default authentication credentials for a user by using
- // a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
- // parameter of CoInitializeSecurity ------------------------
+ // Step 4: -----------------------------------------------------
+ // Connect to WMI through the IWbemLocator::ConnectServer method
+
+ // Connect to the root\cimv2 namespace with
+ // the current user and obtain pointer pSvc
+ // to make IWbemServices calls.
+ mHR = pLoc->ConnectServer(
+ _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
+ NULL, // User name. NULL = current user
+ NULL, // User password. NULL = current
+ 0, // Locale. NULL indicates current
+ NULL, // Security flags.
+ 0, // Authority (e.g. Kerberos)
+ 0, // Context object
+ &pSvc // pointer to IWbemServices proxy
+ );
+
+ if (FAILED(mHR))
+ {
+ LL_WARNS("AppInit") << "Could not connect. Error code = 0x" << std::hex << mHR << LL_ENDL;
+ pLoc->Release();
+ CoUninitialize();
+ return; // Program has failed.
+ }
- hres = CoInitializeSecurity(
- NULL,
- -1, // COM authentication
- NULL, // Authentication services
- NULL, // Reserved
- RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
- RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
- NULL, // Authentication info
- EOAC_NONE, // Additional capabilities
- NULL // Reserved
- );
+ LL_DEBUGS("AppInit") << "Connected to ROOT\\CIMV2 WMI namespace" << LL_ENDL;
-
- if (FAILED(hres))
- {
- LL_WARNS("AppInit") << "Failed to initialize security. Error code = 0x" << hex << hres << LL_ENDL;
- return 1; // Program has failed.
- }
-
- // Step 3: ---------------------------------------------------
- // Obtain the initial locator to WMI -------------------------
-
- IWbemLocator *pLoc = NULL;
-
- hres = CoCreateInstance(
- CLSID_WbemLocator,
- 0,
- CLSCTX_INPROC_SERVER,
- IID_IWbemLocator, (LPVOID *) &pLoc);
-
- if (FAILED(hres))
- {
- LL_WARNS("AppInit") << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << LL_ENDL;
- return 1; // Program has failed.
- }
+ // Step 5: --------------------------------------------------
+ // Set security levels on the proxy -------------------------
- // Step 4: -----------------------------------------------------
- // Connect to WMI through the IWbemLocator::ConnectServer method
-
- IWbemServices *pSvc = NULL;
-
- // Connect to the root\cimv2 namespace with
- // the current user and obtain pointer pSvc
- // to make IWbemServices calls.
- hres = pLoc->ConnectServer(
- _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
- NULL, // User name. NULL = current user
- NULL, // User password. NULL = current
- 0, // Locale. NULL indicates current
- NULL, // Security flags.
- 0, // Authority (e.g. Kerberos)
- 0, // Context object
- &pSvc // pointer to IWbemServices proxy
- );
-
- if (FAILED(hres))
- {
- LL_WARNS("AppInit") << "Could not connect. Error code = 0x" << hex << hres << LL_ENDL;
- pLoc->Release();
- return 1; // Program has failed.
- }
+ mHR = CoSetProxyBlanket(
+ pSvc, // Indicates the proxy to set
+ RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
+ RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
+ NULL, // Server principal name
+ RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
+ RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
+ NULL, // client identity
+ EOAC_NONE // proxy capabilities
+ );
+
+ if (FAILED(mHR))
+ {
+ LL_WARNS("AppInit") << "Could not set proxy blanket. Error code = 0x" << std::hex << mHR << LL_ENDL;
+ cleanCOMObjects();
+ return; // Program has failed.
+ }
+}
+
+
+void LLWMIMethods::cleanCOMObjects()
+{
+ pSvc->Release();
+ pLoc->Release();
+ CoUninitialize();
+}
+
+bool LLWMIMethods::getWindowsProductNumber(unsigned char *unique_id, size_t len)
+{
+ // wmic path Win32_ComputerSystemProduct get UUID
+ return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_OperatingSystem"), L"SerialNumber", unique_id, len);
+}
+
+bool LLWMIMethods::getDiskDriveSerialNumber(unsigned char *unique_id, size_t len)
+{
+ // wmic path Win32_DiskDrive get DeviceID,SerialNumber
+ return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_DiskDrive"), L"SerialNumber", unique_id, len);
+}
+
+bool LLWMIMethods::getProcessorSerialNumber(unsigned char *unique_id, size_t len)
+{
+ // wmic path Win32_Processor get DeviceID,ProcessorId
+ return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_Processor"), L"ProcessorId", unique_id, len);
+}
- LL_DEBUGS("AppInit") << "Connected to ROOT\\CIMV2 WMI namespace" << LL_ENDL;
+bool LLWMIMethods::getMotherboardSerialNumber(unsigned char *unique_id, size_t len)
+{
+ // wmic path Win32_Processor get DeviceID,ProcessorId
+ return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_BaseBoard"), L"SerialNumber", unique_id, len);
+}
+
+bool LLWMIMethods::getComputerSystemProductUUID(unsigned char *unique_id, size_t len)
+{
+ // UUID from Win32_ComputerSystemProduct is motherboard's uuid and is identical to csproduct's uuid
+ // wmic csproduct get name,identifyingnumber,uuid
+ // wmic path Win32_ComputerSystemProduct get UUID
+ return getGenericSerialNumber(bstr_t("SELECT * FROM Win32_ComputerSystemProduct"), L"UUID", unique_id, len, true);
+}
+bool LLWMIMethods::getGenericSerialNumber(const BSTR &select, const LPCWSTR &variable, unsigned char *unique_id, size_t len, bool validate_as_uuid)
+{
+ if (!isInitialized())
+ {
+ return false;
+ }
- // Step 5: --------------------------------------------------
- // Set security levels on the proxy -------------------------
+ HRESULT hres;
- hres = CoSetProxyBlanket(
- pSvc, // Indicates the proxy to set
- RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
- RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
- NULL, // Server principal name
- RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
- RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
- NULL, // client identity
- EOAC_NONE // proxy capabilities
- );
+ // Step 6: --------------------------------------------------
+ // Use the IWbemServices pointer to make requests of WMI ----
- if (FAILED(hres))
+ // For example, get the name of the operating system
+ IEnumWbemClassObject* pEnumerator = NULL;
+ hres = pSvc->ExecQuery(
+ bstr_t("WQL"),
+ select,
+ WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
+ NULL,
+ &pEnumerator);
+
+ if (FAILED(hres))
+ {
+ LL_WARNS("AppInit") << "Query for operating system name failed." << " Error code = 0x" << std::hex << hres << LL_ENDL;
+ return false; // Program has failed.
+ }
+
+ // Step 7: -------------------------------------------------
+ // Get the data from the query in step 6 -------------------
+
+ IWbemClassObject *pclsObj = NULL;
+ ULONG uReturn = 0;
+ bool found = false;
+
+ while (pEnumerator)
+ {
+ HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
+ &pclsObj, &uReturn);
+
+ if (0 == uReturn)
{
- LL_WARNS("AppInit") << "Could not set proxy blanket. Error code = 0x" << hex << hres << LL_ENDL;
- pSvc->Release();
- pLoc->Release();
- return 1; // Program has failed.
+ break;
}
- // Step 6: --------------------------------------------------
- // Use the IWbemServices pointer to make requests of WMI ----
-
- // For example, get the name of the operating system
- IEnumWbemClassObject* pEnumerator = NULL;
- hres = pSvc->ExecQuery(
- bstr_t("WQL"),
- bstr_t("SELECT * FROM Win32_OperatingSystem"),
- WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
- NULL,
- &pEnumerator);
-
- if (FAILED(hres))
+ VARIANT vtProp;
+
+ // Get the value of the Name property
+ hr = pclsObj->Get(variable, 0, &vtProp, 0, 0);
+ if (FAILED(hr))
{
- LL_WARNS("AppInit") << "Query for operating system name failed." << " Error code = 0x" << hex << hres << LL_ENDL;
- pSvc->Release();
- pLoc->Release();
- return 1; // Program has failed.
+ LL_WARNS() << "Failed to get SerialNumber. Error code = 0x" << std::hex << hres << LL_ENDL;
+ pclsObj->Release();
+ pclsObj = NULL;
+ continue;
}
- // Step 7: -------------------------------------------------
- // Get the data from the query in step 6 -------------------
-
- IWbemClassObject *pclsObj = NULL;
- ULONG uReturn = 0;
-
- while (pEnumerator)
+ // use characters in the returned Serial Number to create a byte array of size len
+ BSTR serialNumber(vtProp.bstrVal);
+ unsigned int serial_size = SysStringLen(serialNumber);
+ if (serial_size < 1) // < len?
{
- HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
- &pclsObj, &uReturn);
+ VariantClear(&vtProp);
+ pclsObj->Release();
+ pclsObj = NULL;
+ continue;
+ }
- if(0 == uReturn)
+ if (validate_as_uuid)
+ {
+ std::wstring ws(serialNumber, serial_size);
+ std::string str(ws.begin(), ws.end());
+
+ if (!LLUUID::validate(str))
{
- break;
+ VariantClear(&vtProp);
+ pclsObj->Release();
+ pclsObj = NULL;
+ continue;
}
- VARIANT vtProp;
+ static const LLUUID f_uuid("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF");
+ LLUUID id(str);
- // Get the value of the Name property
- hr = pclsObj->Get(L"SerialNumber", 0, &vtProp, 0, 0);
- if (FAILED(hr))
+ if (id.isNull() || id == f_uuid)
{
- LL_WARNS() << "Failed to get SerialNumber. Error code = 0x" << hex << hres << LL_ENDL;
+ // Not unique id
+ VariantClear(&vtProp);
pclsObj->Release();
pclsObj = NULL;
continue;
}
- LL_INFOS("AppInit") << " Serial Number : " << vtProp.bstrVal << LL_ENDL;
+ }
+ LL_INFOS("AppInit") << " Serial Number : " << vtProp.bstrVal << LL_ENDL;
- // use characters in the returned Serial Number to create a byte array of size len
- BSTR serialNumber ( vtProp.bstrVal);
- unsigned int serial_size = SysStringLen(serialNumber);
- unsigned int j = 0;
+ unsigned int j = 0;
- while (j < serial_size && vtProp.bstrVal[j] != 0)
+ while (j < serial_size && vtProp.bstrVal[j] != 0)
+ {
+ for (unsigned int i = 0; i < len; i++)
{
- for (unsigned int i = 0; i < len; i++)
+ if (j >= serial_size || vtProp.bstrVal[j] == 0)
+ break;
+
+ unique_id[i] = (unsigned int)(unique_id[i] + serialNumber[j]);
+ j++;
+ }
+ }
+ VariantClear(&vtProp);
+
+ pclsObj->Release();
+ pclsObj = NULL;
+ found = true;
+ break;
+ }
+
+ // Cleanup
+ // ========
+
+ if (pEnumerator)
+ pEnumerator->Release();
+
+ return found;
+}
+#elif LL_DARWIN
+bool getSerialNumber(unsigned char *unique_id, size_t len)
+{
+ CFStringRef serial_cf_str = NULL;
+ io_service_t platformExpert = IOServiceGetMatchingService(kIOMasterPortDefault,
+ IOServiceMatching("IOPlatformExpertDevice"));
+ if (platformExpert)
+ {
+ serial_cf_str = (CFStringRef) IORegistryEntryCreateCFProperty(platformExpert,
+ CFSTR(kIOPlatformSerialNumberKey),
+ kCFAllocatorDefault, 0);
+ IOObjectRelease(platformExpert);
+ }
+
+ if (serial_cf_str)
+ {
+ char buffer[64] = {0};
+ std::string serial_str("");
+ if (CFStringGetCString(serial_cf_str, buffer, 64, kCFStringEncodingUTF8))
+ {
+ serial_str = buffer;
+ }
+
+ S32 serial_size = serial_str.size();
+
+ if(serial_str.size() > 0)
+ {
+ S32 j = 0;
+ while (j < serial_size)
+ {
+ for (S32 i = 0; i < len; i++)
{
- if (j >= serial_size || vtProp.bstrVal[j] == 0)
+ if (j >= serial_size)
break;
-
- static_unique_id[i] = (unsigned int)(static_unique_id[i] + serialNumber[j]);
+
+ unique_id[i] = (unsigned int)(unique_id[i] + serial_str[j]);
j++;
}
}
- VariantClear(&vtProp);
+ return true;
+ }
+ }
+ return false;
+}
+#endif
- pclsObj->Release();
- pclsObj = NULL;
- break;
+// get an unique machine id.
+// NOT THREAD SAFE - do before setting up threads.
+// MAC Address doesn't work for Windows 7 since the first returned hardware MAC address changes with each reboot, Go figure??
+
+S32 LLMachineID::init()
+{
+ size_t len = sizeof(static_unique_id);
+ memset(static_unique_id, 0, len);
+ S32 ret_code = 0;
+#if LL_WINDOWS
+
+ LLWMIMethods comInit;
+
+ if (comInit.getWindowsProductNumber(static_legacy_id, len))
+ {
+ // Bios id can change on windows update, so it is not the best id to use
+ // but since old viewer already use them, we might need this id to decode
+ // passwords
+ has_static_legacy_id = true;
+ }
+
+ // Try motherboard/bios id, if it is present it is supposed to be sufficiently unique
+ if (comInit.getComputerSystemProductUUID(static_unique_id, len))
+ {
+ has_static_unique_id = true;
+ LL_DEBUGS("AppInit") << "Using product uuid as unique id" << LL_ENDL;
+ }
+
+ // Fallback to legacy
+ if (!has_static_unique_id)
+ {
+ if (has_static_legacy_id)
+ {
+ memcpy(static_unique_id, &static_legacy_id, len);
+ // Since ids are identical, mark legacy as not present
+ // to not cause retry's in sechandler
+ has_static_legacy_id = false;
+ has_static_unique_id = true;
+ LL_DEBUGS("AppInit") << "Using legacy serial" << LL_ENDL;
+ }
+ else
+ {
+ return 1; // Program has failed.
}
+ }
- // Cleanup
- // ========
-
- if (pSvc)
- pSvc->Release();
- if (pLoc)
- pLoc->Release();
- if (pEnumerator)
- pEnumerator->Release();
- ret_code=0;
-#else
- unsigned char * staticPtr = (unsigned char *)(&static_unique_id[0]);
+ ret_code=0;
+#elif LL_DARWIN
+ if (getSerialNumber(static_unique_id, len))
+ {
+ has_static_unique_id = true;
+ LL_DEBUGS("AppInit") << "Using Serial number as unique id" << LL_ENDL;
+ }
+
+ {
+ unsigned char * staticPtr = (unsigned char *)(&static_legacy_id[0]);
ret_code = LLUUID::getNodeID(staticPtr);
+ has_static_legacy_id = true;
+ }
+
+ // Fallback to legacy
+ if (!has_static_unique_id)
+ {
+ if (has_static_legacy_id)
+ {
+ memcpy(static_unique_id, &static_legacy_id, len);
+ // Since ids are identical, mark legacy as not present
+ // to not cause retry's in sechandler
+ has_static_legacy_id = false;
+ has_static_unique_id = true;
+ LL_DEBUGS("AppInit") << "Using legacy serial" << LL_ENDL;
+ }
+ }
+#else
+ unsigned char * staticPtr = (unsigned char *)(&static_legacy_id[0]);
+ ret_code = LLUUID::getNodeID(staticPtr);
+ has_static_unique_id = true;
+ has_static_legacy_id = false;
#endif
- has_static_unique_id = true;
LL_INFOS("AppInit") << "UniqueID: 0x";
// Code between here and LL_ENDL is not executed unless the LL_DEBUGS
@@ -292,3 +499,13 @@ S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)
}
return 0;
}
+
+S32 LLMachineID::getLegacyID(unsigned char *unique_id, size_t len)
+{
+ if (has_static_legacy_id)
+ {
+ memcpy(unique_id, &static_legacy_id, len);
+ return 1;
+ }
+ return 0;
+}
diff --git a/indra/newview/llmachineid.h b/indra/newview/llmachineid.h
index 6ef8c36fdb..ec1e855031 100644
--- a/indra/newview/llmachineid.h
+++ b/indra/newview/llmachineid.h
@@ -34,6 +34,8 @@ public:
LLMachineID();
virtual ~LLMachineID();
static S32 getUniqueID(unsigned char *unique_id, size_t len);
+ // fallback id for windows
+ static S32 getLegacyID(unsigned char *unique_id, size_t len);
static S32 init();
protected:
diff --git a/indra/newview/llmainlooprepeater.cpp b/indra/newview/llmainlooprepeater.cpp
new file mode 100644
index 0000000000..6736e9a950
--- /dev/null
+++ b/indra/newview/llmainlooprepeater.cpp
@@ -0,0 +1,88 @@
+/**
+ * @file llmachineid.cpp
+ * @brief retrieves unique machine ids
+ *
+ * $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 "llapr.h"
+#include "llevents.h"
+#include "llmainlooprepeater.h"
+
+
+
+// LLMainLoopRepeater
+//-----------------------------------------------------------------------------
+
+
+LLMainLoopRepeater::LLMainLoopRepeater(void):
+ mQueue(0)
+{
+ ; // No op.
+}
+
+
+void LLMainLoopRepeater::start(void)
+{
+ if(mQueue != 0) return;
+
+ mQueue = new LLThreadSafeQueue<LLSD>(1024);
+ mMainLoopConnection = LLEventPumps::instance().
+ obtain("mainloop").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMainLoop, this, _1));
+ mRepeaterConnection = LLEventPumps::instance().
+ obtain("mainlooprepeater").listen(LLEventPump::inventName(), boost::bind(&LLMainLoopRepeater::onMessage, this, _1));
+}
+
+
+void LLMainLoopRepeater::stop(void)
+{
+ mMainLoopConnection.release();
+ mRepeaterConnection.release();
+
+ delete mQueue;
+ mQueue = 0;
+}
+
+
+bool LLMainLoopRepeater::onMainLoop(LLSD const &)
+{
+ LLSD message;
+ while(mQueue->tryPopBack(message)) {
+ std::string pump = message["pump"].asString();
+ if(pump.length() == 0 ) continue; // No pump.
+ LLEventPumps::instance().obtain(pump).post(message["payload"]);
+ }
+ return false;
+}
+
+
+bool LLMainLoopRepeater::onMessage(LLSD const & event)
+{
+ try {
+ mQueue->pushFront(event);
+ } catch(LLThreadSafeQueueError & e) {
+ LL_WARNS() << "could not repeat message (" << e.what() << ")" <<
+ event.asString() << LL_ENDL;
+ }
+ return false;
+}
diff --git a/indra/newview/llmainlooprepeater.h b/indra/newview/llmainlooprepeater.h
new file mode 100644
index 0000000000..2ec3a74e4a
--- /dev/null
+++ b/indra/newview/llmainlooprepeater.h
@@ -0,0 +1,64 @@
+/**
+ * @file llmainlooprepeater.h
+ * @brief a service for repeating messages on the main loop.
+ *
+ * $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_LLMAINLOOPREPEATER_H
+#define LL_LLMAINLOOPREPEATER_H
+
+
+#include "llsd.h"
+#include "llthreadsafequeue.h"
+
+
+//
+// A service which creates the pump 'mainlooprepeater' to which any thread can
+// post a message that will be re-posted on the main loop.
+//
+// The posted message should contain two map elements: pump and payload. The
+// pump value is a string naming the pump to which the message should be
+// re-posted. The payload value is what will be posted to the designated pump.
+//
+class LLMainLoopRepeater:
+ public LLSingleton<LLMainLoopRepeater>
+{
+ LLSINGLETON(LLMainLoopRepeater);
+public:
+ // Start the repeater service.
+ void start(void);
+
+ // Stop the repeater service.
+ void stop(void);
+
+private:
+ LLTempBoundListener mMainLoopConnection;
+ LLTempBoundListener mRepeaterConnection;
+ LLThreadSafeQueue<LLSD> * mQueue;
+
+ bool onMainLoop(LLSD const &);
+ bool onMessage(LLSD const & event);
+};
+
+
+#endif
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index c3e39429a2..7c942e8b53 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -105,7 +105,10 @@ void LLManipRotate::handleSelect()
{
// *FIX: put this in mouseDown?
LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- gFloaterTools->setStatusText("rotate");
+ if (gFloaterTools)
+ {
+ gFloaterTools->setStatusText("rotate");
+ }
LLManip::handleSelect();
}
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index 9a8222d941..e74fd1241b 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -170,7 +170,10 @@ void LLManipScale::handleSelect()
LLBBox bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
updateSnapGuides(bbox);
LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- gFloaterTools->setStatusText("scale");
+ if (gFloaterTools)
+ {
+ gFloaterTools->setStatusText("scale");
+ }
LLManip::handleSelect();
}
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index 9248c160c6..8736d3b51f 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -287,7 +287,10 @@ LLManipTranslate::~LLManipTranslate()
void LLManipTranslate::handleSelect()
{
LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- gFloaterTools->setStatusText("move");
+ if (gFloaterTools)
+ {
+ gFloaterTools->setStatusText("move");
+ }
LLManip::handleSelect();
}
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index a19d6d0b19..c5a3ff44b3 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -1956,7 +1956,7 @@ bool LLMeshRepoThread::skinInfoReceived(const LLUUID& mesh_id, U8* data, S32 dat
LLMeshSkinInfo info(skin);
info.mMeshID = mesh_id;
- // LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL;
+ // LL_DEBUGS(LOG_MESH) << "info pelvis offset" << info.mPelvisOffset << LL_ENDL;
{
LLMutexLock lock(mMutex);
mSkinInfoQ.push_back(info);
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
index a6f20a9f27..b06131cf38 100644
--- a/indra/newview/llnotificationmanager.cpp
+++ b/indra/newview/llnotificationmanager.cpp
@@ -63,7 +63,7 @@ void LLNotificationManager::init()
mChannels.push_back(new LLBrowserNotification());
mChannels.push_back(new LLIMHandler());
- mChatHandler = boost::shared_ptr<LLFloaterIMNearbyChatHandler>(new LLFloaterIMNearbyChatHandler());
+ mChatHandler = std::shared_ptr<LLFloaterIMNearbyChatHandler>(new LLFloaterIMNearbyChatHandler());
}
//--------------------------------------------------------------------------
diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h
index 52c79cc689..cf987ff4e9 100644
--- a/indra/newview/llnotificationmanager.h
+++ b/indra/newview/llnotificationmanager.h
@@ -35,8 +35,6 @@
#include <map>
#include <string>
-#include <boost/shared_ptr.hpp>
-
namespace LLNotificationsUI {
class LLToast;
@@ -60,7 +58,7 @@ public:
void onChat(const LLChat& msg, const LLSD &args);
private:
- boost::shared_ptr<class LLFloaterIMNearbyChatHandler> mChatHandler;
+ std::shared_ptr<class LLFloaterIMNearbyChatHandler> mChatHandler;
std::vector<LLNotificationChannelPtr> mChannels;
};
diff --git a/indra/newview/lloutfitgallery.cpp b/indra/newview/lloutfitgallery.cpp
index c1b622ffff..6a1597fad5 100644
--- a/indra/newview/lloutfitgallery.cpp
+++ b/indra/newview/lloutfitgallery.cpp
@@ -900,7 +900,7 @@ void LLOutfitGalleryContextMenu::onOutfitsRemovalConfirmation(const LLSD& notifi
void LLOutfitGalleryContextMenu::onCreate(const LLSD& data)
{
- LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
+ LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(data.asString());
if (type == LLWearableType::WT_NONE)
{
LL_WARNS() << "Invalid wearable type" << LL_ENDL;
diff --git a/indra/newview/lloutfitslist.cpp b/indra/newview/lloutfitslist.cpp
index 423e57978a..7270580032 100644
--- a/indra/newview/lloutfitslist.cpp
+++ b/indra/newview/lloutfitslist.cpp
@@ -1207,7 +1207,7 @@ void LLOutfitListGearMenuBase::onRename()
void LLOutfitListGearMenuBase::onCreate(const LLSD& data)
{
- LLWearableType::EType type = LLWearableType::typeNameToType(data.asString());
+ LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(data.asString());
if (type == LLWearableType::WT_NONE)
{
LL_WARNS() << "Invalid wearable type" << LL_ENDL;
diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp
index c601a6c210..be11a4a9f3 100644
--- a/indra/newview/llpaneleditwearable.cpp
+++ b/indra/newview/llpaneleditwearable.cpp
@@ -1276,7 +1276,7 @@ void LLPanelEditWearable::changeCamera(U8 subpart)
{
// Don't change the camera if this type doesn't have a camera switch.
// Useful for wearables like physics that don't have an associated physical body part.
- if (LLWearableType::getDisableCameraSwitch(mWearablePtr->getType()))
+ if (LLWearableType::getInstance()->getDisableCameraSwitch(mWearablePtr->getType()))
{
return;
}
diff --git a/indra/newview/llpanelexperiencepicker.cpp b/indra/newview/llpanelexperiencepicker.cpp
index 80aeee6da1..6dfdbaf63f 100644
--- a/indra/newview/llpanelexperiencepicker.cpp
+++ b/indra/newview/llpanelexperiencepicker.cpp
@@ -41,8 +41,8 @@
#include "llcombobox.h"
#include "llviewercontrol.h"
#include "llfloater.h"
+#include "llregex.h"
#include "lltrans.h"
-#include <boost/regex.hpp>
#define BTN_FIND "find"
#define BTN_OK "ok_btn"
@@ -116,7 +116,7 @@ void LLPanelExperiencePicker::onBtnFind()
boost::cmatch what;
std::string text = getChild<LLUICtrl>(TEXT_EDIT)->getValue().asString();
const boost::regex expression("secondlife:///app/experience/[\\da-f-]+/profile");
- if (boost::regex_match(text.c_str(), what, expression))
+ if (ll_regex_match(text.c_str(), what, expression))
{
LLURI uri(text);
LLSD path_array = uri.pathArray();
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 23394b26f2..71657239a6 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -361,7 +361,7 @@ void LLPanelFace::sendBump(U32 bumpiness)
//
LLSelectedTEMaterial::setNormalID(this, current_normal_map);
- LLSelectMgr::getInstance()->selectionSetBumpmap( bump );
+ LLSelectMgr::getInstance()->selectionSetBumpmap( bump, bumpytexture_ctrl->getImageItemID() );
}
void LLPanelFace::sendTexGen()
@@ -390,7 +390,7 @@ void LLPanelFace::sendShiny(U32 shininess)
LLSelectedTEMaterial::setSpecularID(this, specmap);
- LLSelectMgr::getInstance()->selectionSetShiny( shiny );
+ LLSelectMgr::getInstance()->selectionSetShiny( shiny, texture_ctrl->getImageItemID() );
updateShinyControls(!specmap.isNull(), true);
diff --git a/indra/newview/llpanelgroupcreate.cpp b/indra/newview/llpanelgroupcreate.cpp
index 052212dc27..52be75072c 100644
--- a/indra/newview/llpanelgroupcreate.cpp
+++ b/indra/newview/llpanelgroupcreate.cpp
@@ -45,6 +45,7 @@
#include "llfloaterreg.h"
#include "llfloater.h"
#include "llgroupmgr.h"
+#include "llstatusbar.h" // to re-request balance
#include "lltrans.h"
#include "llnotificationsutil.h"
#include "lluicolortable.h"
@@ -117,6 +118,7 @@ void LLPanelGroupCreate::refreshCreatedGroup(const LLUUID& group_id)
params["group_id"] = group_id;
params["open_tab_name"] = "panel_group_info_sidetray";
LLFloaterSidePanelContainer::showPanel("people", "panel_group_info_sidetray", params);
+ LLStatusBar::sendMoneyBalanceRequest();
}
void LLPanelGroupCreate::addMembershipRow(const std::string &name)
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
index e9c9c451a2..1a1792fb60 100644
--- a/indra/newview/llpanelmaininventory.cpp
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -62,15 +62,11 @@
const std::string FILTERS_FILENAME("filters.xml");
-static LLPanelInjector<LLPanelMainInventory> t_inventory("panel_main_inventory");
+const std::string ALL_ITEMS("All Items");
+const std::string RECENT_ITEMS("Recent Items");
+const std::string WORN_ITEMS("Worn Items");
-void on_file_loaded_for_save(BOOL success,
- LLViewerFetchedTexture *src_vi,
- LLImageRaw* src,
- LLImageRaw* aux_src,
- S32 discard_level,
- BOOL final,
- void* userdata);
+static LLPanelInjector<LLPanelMainInventory> t_inventory("panel_main_inventory");
///----------------------------------------------------------------------------
/// LLFloaterInventoryFinder
@@ -149,7 +145,7 @@ BOOL LLPanelMainInventory::postBuild()
//panel->getFilter().markDefault();
// Set up the default inv. panel/filter settings.
- mActivePanel = getChild<LLInventoryPanel>("All Items");
+ mActivePanel = getChild<LLInventoryPanel>(ALL_ITEMS);
if (mActivePanel)
{
// "All Items" is the previous only view, so it gets the InventorySortOrder
@@ -159,7 +155,7 @@ BOOL LLPanelMainInventory::postBuild()
mActivePanel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, mActivePanel, _1, _2));
mResortActivePanel = true;
}
- LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>("Recent Items");
+ LLInventoryPanel* recent_items_panel = getChild<LLInventoryPanel>(RECENT_ITEMS);
if (recent_items_panel)
{
// assign default values until we will be sure that we have setting to restore
@@ -174,7 +170,7 @@ BOOL LLPanelMainInventory::postBuild()
recent_items_panel->setSelectCallback(boost::bind(&LLPanelMainInventory::onSelectionChange, this, recent_items_panel, _1, _2));
}
- mWornItemsPanel = getChild<LLInventoryPanel>("Worn Items");
+ mWornItemsPanel = getChild<LLInventoryPanel>(WORN_ITEMS);
if (mWornItemsPanel)
{
U32 filter_types = 0x0;
@@ -271,7 +267,7 @@ LLPanelMainInventory::~LLPanelMainInventory( void )
// for example, LLParamSDParser doesn't know about U64,
// so some FilterOps params should be revised.
LLSD filterRoot;
- LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>("All Items");
+ LLInventoryPanel* all_items_panel = getChild<LLInventoryPanel>(ALL_ITEMS);
if (all_items_panel)
{
LLSD filterState;
@@ -285,7 +281,7 @@ LLPanelMainInventory::~LLPanelMainInventory( void )
}
}
- LLInventoryPanel* panel = findChild<LLInventoryPanel>("Recent Items");
+ LLInventoryPanel* panel = findChild<LLInventoryPanel>(RECENT_ITEMS);
if (panel)
{
LLSD filterState;
@@ -316,7 +312,7 @@ LLPanelMainInventory::~LLPanelMainInventory( void )
LLInventoryPanel* LLPanelMainInventory::getAllItemsPanel()
{
- return getChild<LLInventoryPanel>("All Items");
+ return getChild<LLInventoryPanel>(ALL_ITEMS);
}
void LLPanelMainInventory::selectAllItemsPanel()
@@ -324,6 +320,11 @@ void LLPanelMainInventory::selectAllItemsPanel()
mFilterTabs->selectFirstTab();
}
+bool LLPanelMainInventory::isRecentItemsPanelSelected()
+{
+ return (RECENT_ITEMS == getActivePanel()->getName());
+}
+
void LLPanelMainInventory::startSearch()
{
// this forces focus to line editor portion of search editor
@@ -439,7 +440,7 @@ void LLPanelMainInventory::setSortBy(const LLSD& userdata)
}
getActivePanel()->setSortOrder(sort_order_mask);
- if ("Recent Items" == getActivePanel()->getName())
+ if (isRecentItemsPanelSelected())
{
gSavedSettings.setU32("RecentItemsSortOrder", sort_order_mask);
}
@@ -801,8 +802,8 @@ void LLPanelMainInventory::toggleFindOptions()
void LLPanelMainInventory::setSelectCallback(const LLFolderView::signal_t::slot_type& cb)
{
- getChild<LLInventoryPanel>("All Items")->setSelectCallback(cb);
- getChild<LLInventoryPanel>("Recent Items")->setSelectCallback(cb);
+ getChild<LLInventoryPanel>(ALL_ITEMS)->setSelectCallback(cb);
+ getChild<LLInventoryPanel>(RECENT_ITEMS)->setSelectCallback(cb);
}
void LLPanelMainInventory::onSelectionChange(LLInventoryPanel *panel, const std::deque<LLFolderViewItem*>& items, BOOL user_action)
@@ -1200,11 +1201,11 @@ void LLPanelMainInventory::onAddButtonClick()
{
// Gray out the "New Folder" option when the Recent tab is active as new folders will not be displayed
// unless "Always show folders" is checked in the filter options.
- bool recent_active = ("Recent Items" == mActivePanel->getName());
+
LLMenuGL* menu = (LLMenuGL*)mMenuAddHandle.get();
if (menu)
{
- menu->getChild<LLMenuItemGL>("New Folder")->setEnabled(!recent_active);
+ menu->getChild<LLMenuItemGL>("New Folder")->setEnabled(!isRecentItemsPanelSelected());
setUploadCostIfNeeded();
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
index dfb8db9d12..257bce930c 100644
--- a/indra/newview/llpanelmaininventory.h
+++ b/indra/newview/llpanelmaininventory.h
@@ -81,6 +81,8 @@ public:
void selectAllItemsPanel();
const LLInventoryPanel* getActivePanel() const { return mActivePanel; }
+ bool isRecentItemsPanelSelected();
+
const std::string& getFilterText() const { return mFilterText; }
void setSelectCallback(const LLFolderView::signal_t::slot_type& cb);
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 6bff95ab36..831c89b005 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -896,7 +896,7 @@ void LLPanelObject::getState( )
mSpinScaleY->setMaxValue(OBJECT_MAX_HOLE_SIZE_Y);
break;
default:
- if (editable)
+ if (editable && single_volume)
{
mSpinScaleX->set( 1.f - scale_x );
mSpinScaleY->set( 1.f - scale_y );
diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp
index 5be9ab6095..35582d2967 100644
--- a/indra/newview/llpaneloutfitedit.cpp
+++ b/indra/newview/llpaneloutfitedit.cpp
@@ -98,7 +98,7 @@ std::string LLShopURLDispatcher::resolveURL(LLWearableType::EType wearable_type,
{
const std::string prefix = "MarketplaceURL";
const std::string sex_str = (sex == SEX_MALE) ? "Male" : "Female";
- const std::string type_str = LLWearableType::getTypeName(wearable_type);
+ const std::string type_str = LLWearableType::getInstance()->getTypeName(wearable_type);
std::string setting_name = prefix;
@@ -174,7 +174,7 @@ public:
private:
static void onCreate(const LLSD& param)
{
- LLWearableType::EType type = LLWearableType::typeNameToType(param.asString());
+ LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(param.asString());
if (type == LLWearableType::WT_NONE)
{
LL_WARNS() << "Invalid wearable type" << LL_ENDL;
@@ -189,19 +189,20 @@ private:
{
LLView* menu_clothes = gMenuHolder->getChildView("COF.Gear.New_Clothes", FALSE);
LLView* menu_bp = gMenuHolder->getChildView("COF.Gear.New_Body_Parts", FALSE);
+ LLWearableType * wearable_type_inst = LLWearableType::getInstance();
for (U8 i = LLWearableType::WT_SHAPE; i != (U8) LLWearableType::WT_COUNT; ++i)
{
LLWearableType::EType type = (LLWearableType::EType) i;
- const std::string& type_name = LLWearableType::getTypeName(type);
+ const std::string& type_name = wearable_type_inst->getTypeName(type);
LLMenuItemCallGL::Params p;
p.name = type_name;
- p.label = LLTrans::getString(LLWearableType::getTypeDefaultNewName(type));
+ p.label = LLTrans::getString(wearable_type_inst->getTypeDefaultNewName(type));
p.on_click.function_name = "Wearable.Create";
p.on_click.parameter = LLSD(type_name);
- LLView* parent = LLWearableType::getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp;
+ LLView* parent = wearable_type_inst->getAssetType(type) == LLAssetType::AT_CLOTHING ? menu_clothes : menu_bp;
LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
}
}
diff --git a/indra/newview/llpanelsnapshotpostcard.cpp b/indra/newview/llpanelsnapshotpostcard.cpp
index b8aa976657..05fa2b58b1 100644
--- a/indra/newview/llpanelsnapshotpostcard.cpp
+++ b/indra/newview/llpanelsnapshotpostcard.cpp
@@ -38,6 +38,7 @@
#include "llfloatersnapshot.h" // FIXME: replace with a snapshot storage model
#include "llpanelsnapshot.h"
#include "llpostcard.h"
+#include "llregex.h"
#include "llsnapshotlivepreview.h"
#include "llviewercontrol.h" // gSavedSettings
#include "llviewerwindow.h"
@@ -229,7 +230,7 @@ void LLPanelSnapshotPostcard::onSend()
boost::regex email_format("[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}(,[ \t]*[A-Za-z0-9.%+-_]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,})*");
- if (to.empty() || !boost::regex_match(to, email_format))
+ if (to.empty() || !ll_regex_match(to, email_format))
{
LLNotificationsUtil::add("PromptRecipientEmail");
return;
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 05d9346f89..89c558e4f8 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -50,6 +50,7 @@
//#include "llfirstuse.h"
#include "llfocusmgr.h"
#include "llmanipscale.h"
+#include "llinventorymodel.h"
#include "llpreviewscript.h"
#include "llresmgr.h"
#include "llselectmgr.h"
@@ -57,6 +58,7 @@
#include "lltextbox.h"
#include "lltool.h"
#include "lltoolcomp.h"
+#include "lltooldraganddrop.h"
#include "lltoolmgr.h"
#include "lltrans.h"
#include "llui.h"
@@ -780,7 +782,7 @@ void LLPanelVolume::onLightCancelTexture(const LLSD& data)
// selection of "None" texture.
LLUUID tex_id = LightTextureCtrl->getImageAssetID();
bool is_spotlight = volobjp->isLightSpotlight();
- volobjp->setLightTextureID(tex_id); //updates spotlight
+ setLightTextureID(tex_id, LightTextureCtrl->getImageItemID(), volobjp); //updates spotlight
if (!is_spotlight && tex_id.notNull())
{
@@ -825,7 +827,7 @@ void LLPanelVolume::onLightSelectTexture(const LLSD& data)
if(LightTextureCtrl)
{
LLUUID id = LightTextureCtrl->getImageAssetID();
- volobjp->setLightTextureID(id);
+ setLightTextureID(id, LightTextureCtrl->getImageItemID(), volobjp);
}
}
@@ -888,11 +890,12 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
if(LightTextureCtrl)
{
LLUUID id = LightTextureCtrl->getImageAssetID();
+ LLUUID item_id = LightTextureCtrl->getImageItemID();
if (id.notNull())
{
if (!volobjp->isLightSpotlight())
{ //this commit is making this a spot light, set UI to default params
- volobjp->setLightTextureID(id);
+ setLightTextureID(id, item_id, volobjp);
LLVector3 spot_params = volobjp->getSpotLightParams();
self->getChild<LLUICtrl>("Light FOV")->setValue(spot_params.mV[0]);
self->getChild<LLUICtrl>("Light Focus")->setValue(spot_params.mV[1]);
@@ -902,7 +905,7 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
{ //modifying existing params, this time volobjp won't change params on its own.
if (volobjp->getLightTextureID() != id)
{
- volobjp->setLightTextureID(id);
+ setLightTextureID(id, item_id, volobjp);
}
LLVector3 spot_params;
@@ -914,7 +917,7 @@ void LLPanelVolume::onCommitLight( LLUICtrl* ctrl, void* userdata )
}
else if (volobjp->isLightSpotlight())
{ //no longer a spot light
- volobjp->setLightTextureID(id);
+ setLightTextureID(id, item_id, volobjp);
//self->getChildView("Light FOV")->setEnabled(FALSE);
//self->getChildView("Light Focus")->setEnabled(FALSE);
//self->getChildView("Light Ambiance")->setEnabled(FALSE);
@@ -931,6 +934,19 @@ void LLPanelVolume::onCommitIsLight( LLUICtrl* ctrl, void* userdata )
self->sendIsLight();
}
+// static
+void LLPanelVolume::setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp)
+{
+ if (volobjp)
+ {
+ LLViewerInventoryItem* item = gInventory.getItem(item_id);
+ if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
+ {
+ LLToolDragAndDrop::handleDropTextureProtections(volobjp, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ }
+ volobjp->setLightTextureID(asset_id);
+ }
+}
//----------------------------------------------------------------------------
// static
diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h
index 66117316cf..6e49ccb742 100644
--- a/indra/newview/llpanelvolume.h
+++ b/indra/newview/llpanelvolume.h
@@ -40,6 +40,7 @@ class LLButton;
class LLViewerObject;
class LLComboBox;
class LLColorSwatchCtrl;
+class LLVOVolume;
class LLPanelVolume : public LLPanel
{
@@ -73,6 +74,8 @@ public:
void onLightCancelTexture(const LLSD& data);
void onLightSelectTexture(const LLSD& data);
+ static void setLightTextureID(const LLUUID &asset_id, const LLUUID &item_id, LLVOVolume* volobjp);
+
protected:
void getState();
diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp
index 1b60610668..59be35fe92 100644
--- a/indra/newview/llpreviewnotecard.cpp
+++ b/indra/newview/llpreviewnotecard.cpp
@@ -232,6 +232,7 @@ void LLPreviewNotecard::loadAsset()
if (!editor)
return;
+ bool fail = false;
if(item)
{
@@ -315,7 +316,31 @@ void LLPreviewNotecard::loadAsset()
getChildView("Delete")->setEnabled(TRUE);
}
}
- else
+ else if (mObjectUUID.notNull() && mItemUUID.notNull())
+ {
+ LLViewerObject* objectp = gObjectList.findObject(mObjectUUID);
+ if (objectp && (objectp->isInventoryPending() || objectp->isInventoryDirty()))
+ {
+ // It's a notecard in object's inventory and we failed to get it because inventory is not up to date.
+ // Subscribe for callback and retry at inventoryChanged()
+ registerVOInventoryListener(objectp, NULL); //removes previous listener
+
+ if (objectp->isInventoryDirty())
+ {
+ objectp->requestInventory();
+ }
+ }
+ else
+ {
+ fail = true;
+ }
+ }
+ else
+ {
+ fail = true;
+ }
+
+ if (fail)
{
editor->setText(LLStringUtil::null);
editor->makePristine();
@@ -600,6 +625,17 @@ void LLPreviewNotecard::syncExternal()
}
}
+/*virtual*/
+void LLPreviewNotecard::inventoryChanged(LLViewerObject* object,
+ LLInventoryObject::object_list_t* inventory,
+ S32 serial_num,
+ void* user_data)
+{
+ removeVOInventoryListener();
+ loadAsset();
+}
+
+
void LLPreviewNotecard::deleteNotecard()
{
LLNotificationsUtil::add("DeleteNotecard", LLSD(), LLSD(), boost::bind(&LLPreviewNotecard::handleConfirmDeleteDialog,this, _1, _2));
diff --git a/indra/newview/llpreviewnotecard.h b/indra/newview/llpreviewnotecard.h
index d9c14815c1..3a706b8645 100644
--- a/indra/newview/llpreviewnotecard.h
+++ b/indra/newview/llpreviewnotecard.h
@@ -31,6 +31,7 @@
#include "llassetstorage.h"
#include "llpreviewscript.h"
#include "lliconctrl.h"
+#include "llvoinventorylistener.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLPreviewNotecard
@@ -41,7 +42,7 @@
class LLViewerTextEditor;
class LLButton;
-class LLPreviewNotecard : public LLPreview
+class LLPreviewNotecard : public LLPreview, public LLVOInventoryListener
{
public:
LLPreviewNotecard(const LLSD& key);
@@ -75,6 +76,11 @@ public:
void syncExternal();
+ void inventoryChanged(LLViewerObject* object,
+ LLInventoryObject::object_list_t* inventory,
+ S32 serial_num,
+ void* user_data) override;
+
protected:
void updateTitleButtons() override;
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 1e91da529c..cd7b93aba7 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -50,6 +50,7 @@
#include "llviewertexture.h"
#include "llviewertexturelist.h"
#include "lluictrlfactory.h"
+#include "llviewercontrol.h"
#include "llviewerwindow.h"
#include "lllineeditor.h"
@@ -317,6 +318,44 @@ void LLPreviewTexture::saveTextureToFile(const std::vector<std::string>& filenam
0, TRUE, FALSE, new LLUUID(mItemUUID), &mCallbackTextureList);
}
+
+void LLPreviewTexture::saveMultipleToFile(const std::string& file_name)
+{
+ std::string texture_location(gSavedSettings.getString("TextureSaveLocation"));
+ std::string texture_name = file_name.empty() ? getItem()->getName() : file_name;
+
+ std::string filepath;
+ S32 i = 0;
+ S32 err = 0;
+ std::string extension(".png");
+ do
+ {
+ filepath = texture_location;
+ filepath += gDirUtilp->getDirDelimiter();
+ filepath += texture_name;
+
+ if (i != 0)
+ {
+ filepath += llformat("_%.3d", i);
+ }
+
+ filepath += extension;
+
+ llstat stat_info;
+ err = LLFile::stat( filepath, &stat_info );
+ i++;
+ } while (-1 != err); // Search until the file is not found (i.e., stat() gives an error).
+
+
+ mSaveFileName = filepath;
+ mLoadingFullImage = TRUE;
+ getWindow()->incBusyCount();
+
+ mImage->forceToSaveRawImage(0);//re-fetch the raw image if the old one is removed.
+ mImage->setLoadedCallback(LLPreviewTexture::onFileLoadedForSave,
+ 0, TRUE, FALSE, new LLUUID(mItemUUID), &mCallbackTextureList);
+}
+
// virtual
void LLPreviewTexture::reshape(S32 width, S32 height, BOOL called_from_parent)
{
diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h
index ad77d9e118..9b6a843875 100644
--- a/indra/newview/llpreviewtexture.h
+++ b/indra/newview/llpreviewtexture.h
@@ -63,6 +63,7 @@ public:
void openToSave();
void saveTextureToFile(const std::vector<std::string>& filenames);
+ void saveMultipleToFile(const std::string& file_name = "");
static void onSaveAsBtn(void* data);
diff --git a/indra/newview/llregioninfomodel.cpp b/indra/newview/llregioninfomodel.cpp
index 7daaa7ef8e..6caec6ec4a 100644
--- a/indra/newview/llregioninfomodel.cpp
+++ b/indra/newview/llregioninfomodel.cpp
@@ -173,6 +173,29 @@ void LLRegionInfoModel::update(LLMessageSystem* msg)
mRegionFlags = flags;
}
+ if (msg->has(_PREHASH_RegionInfo5))
+ {
+ F32 chat_whisper_range;
+ F32 chat_normal_range;
+ F32 chat_shout_range;
+ F32 chat_whisper_offset;
+ F32 chat_normal_offset;
+ F32 chat_shout_offset;
+ U32 chat_flags;
+
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperRange, chat_whisper_range);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalRange, chat_normal_range);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutRange, chat_shout_range);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatWhisperOffset, chat_whisper_offset);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatNormalOffset, chat_normal_offset);
+ msg->getF32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatShoutOffset, chat_shout_offset);
+ msg->getU32Fast(_PREHASH_RegionInfo5, _PREHASH_ChatFlags, chat_flags);
+
+ LL_INFOS() << "Whisper range: " << chat_whisper_range << " normal range: " << chat_normal_range << " shout range: " << chat_shout_range
+ << " whisper offset: " << chat_whisper_offset << " normal offset: " << chat_normal_offset << " shout offset: " << chat_shout_offset
+ << " chat flags: " << chat_flags << LL_ENDL;
+ }
+
// the only reasonable way to decide if we actually have any data is to
// check to see if any of these fields have nonzero sizes
if (msg->getSize(_PREHASH_RegionInfo2, _PREHASH_ProductSKU) > 0 ||
diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h
index 410737b27f..e1320375ab 100644
--- a/indra/newview/llsecapi.h
+++ b/indra/newview/llsecapi.h
@@ -264,7 +264,9 @@ public:
virtual void validate(int validation_policy,
LLPointer<LLCertificateChain> cert_chain,
const LLSD& validation_params) =0;
-
+
+ // Clear cache if any
+ virtual void clearSertCache()=0;
};
diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp
index b4853d270a..6b06abaf99 100644
--- a/indra/newview/llsechandler_basic.cpp
+++ b/indra/newview/llsechandler_basic.cpp
@@ -1310,8 +1310,8 @@ LLSecAPIBasicHandler::~LLSecAPIBasicHandler()
_writeProtectedData();
}
-void LLSecAPIBasicHandler::_readProtectedData()
-{
+void LLSecAPIBasicHandler::_readProtectedData(unsigned char *unique_id, U32 id_len)
+{
// attempt to load the file into our map
LLPointer<LLSDParser> parser = new LLSDXMLParser();
llifstream protected_data_stream(mProtectedDataFilename.c_str(),
@@ -1322,9 +1322,7 @@ void LLSecAPIBasicHandler::_readProtectedData()
U8 buffer[BUFFER_READ_SIZE];
U8 decrypted_buffer[BUFFER_READ_SIZE];
int decrypted_length;
- unsigned char unique_id[MAC_ADDRESS_BYTES];
- LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
- LLXORCipher cipher(unique_id, sizeof(unique_id));
+ LLXORCipher cipher(unique_id, id_len);
// read in the salt and key
protected_data_stream.read((char *)salt, STORE_SALT_SIZE);
@@ -1376,6 +1374,30 @@ void LLSecAPIBasicHandler::_readProtectedData()
}
}
+void LLSecAPIBasicHandler::_readProtectedData()
+{
+ unsigned char unique_id[MAC_ADDRESS_BYTES];
+ try
+ {
+ // try default id
+ LLMachineID::getUniqueID(unique_id, sizeof(unique_id));
+ _readProtectedData(unique_id, sizeof(unique_id));
+ }
+ catch(LLProtectedDataException&)
+ {
+ // try with legacy id, it will return false if it is identical to getUniqueID
+ // or if it is not assigned/not in use
+ if (LLMachineID::getLegacyID(unique_id, sizeof(unique_id)))
+ {
+ _readProtectedData(unique_id, sizeof(unique_id));
+ }
+ else
+ {
+ throw;
+ }
+ }
+}
+
void LLSecAPIBasicHandler::_writeProtectedData()
{
std::ostringstream formatted_data_ostream;
diff --git a/indra/newview/llsechandler_basic.h b/indra/newview/llsechandler_basic.h
index 82670f9083..17e9f72f07 100644
--- a/indra/newview/llsechandler_basic.h
+++ b/indra/newview/llsechandler_basic.h
@@ -177,7 +177,10 @@ public:
virtual void validate(int validation_policy,
LLPointer<LLCertificateChain> ca_chain,
const LLSD& validation_params);
-
+
+ // Clears cache of certs validated agains store
+ virtual void clearSertCache() { mTrustedCertCache.clear(); }
+
protected:
std::vector<LLPointer<LLCertificate> > mCerts;
@@ -326,6 +329,7 @@ public:
protected:
+ void _readProtectedData(unsigned char *unique_id, U32 id_len);
void _readProtectedData();
void _writeProtectedData();
std::string _legacyLoadPassword();
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index bc00c518e9..6f136e50e0 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -1366,11 +1366,8 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 &
}
break;
case SELECT_TYPE_HUD:
- // use HUD-scaled grid
- mGridScale = LLVector3(0.25f, 0.25f, 0.25f);
- break;
case SELECT_TYPE_WORLD:
- mGridScale = LLVector3(1.f, 1.f, 1.f) * gSavedSettings.getF32("GridResolution");
+ mGridScale = LLVector3(1.f, 1.f, 1.f) * llmin(gSavedSettings.getF32("GridResolution"), 0.5f);
break;
}
}
@@ -1937,7 +1934,7 @@ BOOL LLSelectMgr::selectionRevertTextures()
return revert_successful;
}
-void LLSelectMgr::selectionSetBumpmap(U8 bumpmap)
+void LLSelectMgr::selectionSetBumpmap(U8 bumpmap, const LLUUID &image_id)
{
struct f : public LLSelectedTEFunctor
{
@@ -1953,7 +1950,22 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap)
return true;
}
} setfunc(bumpmap);
- getSelection()->applyToTEs(&setfunc);
+
+ LLViewerInventoryItem* item = gInventory.getItem(image_id);
+ if(item
+ && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())
+ && (mSelectedObjects->getNumNodes() > 1) )
+ {
+ LL_WARNS() << "Attempted to apply no-copy texture to multiple objects" << LL_ENDL;
+ return;
+ }
+ if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
+ {
+ LLViewerObject *object = mSelectedObjects->getFirstRootObject();
+ if (!object) return;
+ LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ }
+ getSelection()->applyToTEs(&setfunc);
LLSelectMgrSendFunctor sendfunc;
getSelection()->applyToObjects(&sendfunc);
@@ -1982,7 +1994,7 @@ void LLSelectMgr::selectionSetTexGen(U8 texgen)
}
-void LLSelectMgr::selectionSetShiny(U8 shiny)
+void LLSelectMgr::selectionSetShiny(U8 shiny, const LLUUID &image_id)
{
struct f : public LLSelectedTEFunctor
{
@@ -1998,7 +2010,22 @@ void LLSelectMgr::selectionSetShiny(U8 shiny)
return true;
}
} setfunc(shiny);
- getSelection()->applyToTEs(&setfunc);
+
+ LLViewerInventoryItem* item = gInventory.getItem(image_id);
+ if(item
+ && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())
+ && (mSelectedObjects->getNumNodes() > 1) )
+ {
+ LL_WARNS() << "Attempted to apply no-copy texture to multiple objects" << LL_ENDL;
+ return;
+ }
+ if (item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()))
+ {
+ LLViewerObject *object = mSelectedObjects->getFirstRootObject();
+ if (!object) return;
+ LLToolDragAndDrop::handleDropTextureProtections(object, item, LLToolDragAndDrop::SOURCE_AGENT, LLUUID::null);
+ }
+ getSelection()->applyToTEs(&setfunc);
LLSelectMgrSendFunctor sendfunc;
getSelection()->applyToObjects(&sendfunc);
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 0fd2e74090..ce0316e610 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -609,9 +609,9 @@ public:
void selectionRevertColors();
void selectionRevertShinyColors();
BOOL selectionRevertTextures();
- void selectionSetBumpmap( U8 bumpmap );
+ void selectionSetBumpmap( U8 bumpmap, const LLUUID &image_id );
void selectionSetTexGen( U8 texgen );
- void selectionSetShiny( U8 shiny );
+ void selectionSetShiny( U8 shiny, const LLUUID &image_id );
void selectionSetFullbright( U8 fullbright );
void selectionSetMedia( U8 media_type, const LLSD &media_data );
void selectionSetClickAction(U8 action);
diff --git a/indra/newview/llsetkeybinddialog.h b/indra/newview/llsetkeybinddialog.h
index a34b952233..24dfa1dbfd 100644
--- a/indra/newview/llsetkeybinddialog.h
+++ b/indra/newview/llsetkeybinddialog.h
@@ -76,6 +76,8 @@ public:
static void onDefault(void* user_data);
static void onClickTimeout(void* user_data, MASK mask);
+ static bool isRecording() { return sRecordKeys; }
+
class Updater;
private:
diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp
index 6dfe40c29a..aed9dba7ef 100644
--- a/indra/newview/llsidepanelappearance.cpp
+++ b/indra/newview/llsidepanelappearance.cpp
@@ -210,7 +210,7 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility)
// when editing its physics.
if (!gAgentCamera.cameraCustomizeAvatar())
{
- LLVOAvatarSelf::onCustomizeStart(LLWearableType::getDisableCameraSwitch(wearable_ptr->getType()));
+ LLVOAvatarSelf::onCustomizeStart(LLWearableType::getInstance()->getDisableCameraSwitch(wearable_ptr->getType()));
}
if (is_wearable_edit_visible)
{
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 30b7124550..332fa73944 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -2901,8 +2901,24 @@ void renderBatchSize(LLDrawInfo* params)
{
LLGLEnable offset(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(-1.f, 1.f);
- gGL.diffuseColor4ubv((GLubyte*) &(params->mDebugColor));
- pushVerts(params, LLVertexBuffer::MAP_VERTEX);
+ LLGLSLShader* old_shader = LLGLSLShader::sCurBoundShaderPtr;
+ U32 mask = LLVertexBuffer::MAP_VERTEX;
+ bool bind = false;
+ if (params->mAvatar)
+ {
+ bind = true;
+ old_shader->mRiggedVariant->bind();
+ LLRenderPass::uploadMatrixPalette(*params);
+ mask |= LLVertexBuffer::MAP_WEIGHT4;
+ }
+
+ gGL.diffuseColor4ubv((GLubyte*)&(params->mDebugColor));
+ pushVerts(params, mask);
+
+ if (bind)
+ {
+ old_shader->bind();
+ }
}
void renderShadowFrusta(LLDrawInfo* params)
@@ -4085,6 +4101,11 @@ void LLDrawInfo::validate()
mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset);
}
+U64 LLDrawInfo::getSkinHash()
+{
+ return mSkinInfo ? mSkinInfo->mHash : 0;
+}
+
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 8cc50e71b1..5fca516f19 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -82,6 +82,9 @@ public:
void validate();
+ // return mSkinHash->mHash, or 0 if mSkinHash is null
+ U64 getSkinHash();
+
LLVector4a mExtents[2];
LLPointer<LLVertexBuffer> mVertexBuffer;
@@ -120,6 +123,8 @@ public:
F32 mAlphaMaskCutoff;
U8 mDiffuseAlphaMode;
bool mSelected;
+ LLVOAvatar* mAvatar = nullptr;
+ LLMeshSkinInfo* mSkinInfo = nullptr;
struct CompareTexture
@@ -647,7 +652,7 @@ class LLVolumeGeometryManager: public LLGeometryManager
virtual void rebuildGeom(LLSpatialGroup* group);
virtual void rebuildMesh(LLSpatialGroup* group);
virtual void getGeometry(LLSpatialGroup* group);
- U32 genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL no_materials = FALSE);
+ U32 genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE, BOOL rigged = FALSE);
void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);
private:
@@ -655,13 +660,13 @@ private:
void freeFaces();
static int32_t sInstanceCount;
- static LLFace** sFullbrightFaces;
- static LLFace** sBumpFaces;
- static LLFace** sSimpleFaces;
- static LLFace** sNormFaces;
- static LLFace** sSpecFaces;
- static LLFace** sNormSpecFaces;
- static LLFace** sAlphaFaces;
+ static LLFace** sFullbrightFaces[2];
+ static LLFace** sBumpFaces[2];
+ static LLFace** sSimpleFaces[2];
+ static LLFace** sNormFaces[2];
+ static LLFace** sSpecFaces[2];
+ static LLFace** sNormSpecFaces[2];
+ static LLFace** sAlphaFaces[2];
};
//spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp)
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 2b94ab76ba..8d21b04511 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -206,9 +206,6 @@
#include "llstacktrace.h"
-#include "threadpool.h"
-
-
#if LL_WINDOWS
#include "lldxhardware.h"
#endif
@@ -2830,6 +2827,11 @@ void reset_login()
// Hide any other stuff
LLFloaterReg::hideVisibleInstances();
LLStartUp::setStartupState( STATE_BROWSER_INIT );
+
+ // Clear any verified certs and verify them again on next login
+ // to ensure cert matches server instead of just getting reused
+ LLPointer<LLCertificateStore> store = gSecAPIHandler->getCertificateStore("");
+ store->clearSertCache();
}
//---------------------------------------------------------------------------
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index 75a5fabdc2..54ff7d295e 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -460,8 +460,9 @@ BOOL LLToolPie::useClickAction(MASK mask,
&& object
&& !object->isAttachment()
&& LLPrimitive::isPrimitive(object->getPCode())
- && (object->getClickAction()
- || parent->getClickAction());
+ // useClickAction does not handle Touch (0) or Disabled action
+ && ((object->getClickAction() && object->getClickAction() != CLICK_ACTION_DISABLED)
+ || (parent && parent->getClickAction() && parent->getClickAction() != CLICK_ACTION_DISABLED));
}
@@ -472,18 +473,18 @@ U8 final_click_action(LLViewerObject* obj)
U8 click_action = CLICK_ACTION_TOUCH;
LLViewerObject* parent = obj->getRootEdit();
- if (obj->getClickAction()
- || (parent && parent->getClickAction()))
- {
- if (obj->getClickAction())
- {
- click_action = obj->getClickAction();
- }
- else if (parent && parent->getClickAction())
- {
- click_action = parent->getClickAction();
- }
- }
+ U8 object_action = obj->getClickAction();
+ U8 parent_action = parent ? parent->getClickAction() : CLICK_ACTION_TOUCH;
+ if (parent_action == CLICK_ACTION_DISABLED || object_action)
+ {
+ // CLICK_ACTION_DISABLED ("None" in UI) is intended for child action to
+ // override parent's action when assigned to parent or to child
+ click_action = object_action;
+ }
+ else if (parent_action)
+ {
+ click_action = parent_action;
+ }
return click_action;
}
@@ -657,9 +658,10 @@ bool LLToolPie::teleportToClickedLocation()
bool is_land = mHoverPick.mPickType == LLPickInfo::PICK_LAND;
bool pos_non_zero = !mHoverPick.mPosGlobal.isExactlyZero();
bool has_touch_handler = (objp && objp->flagHandleTouch()) || (parentp && parentp->flagHandleTouch());
- bool has_click_action = final_click_action(objp);
+ U8 click_action = final_click_action(objp); // default action: 0 - touch
+ bool has_click_action = (click_action || has_touch_handler) && click_action != CLICK_ACTION_DISABLED;
- if (pos_non_zero && (is_land || (is_in_world && !has_touch_handler && !has_click_action)))
+ if (pos_non_zero && (is_land || (is_in_world && !has_click_action)))
{
LLVector3d pos = mHoverPick.mPosGlobal;
pos.mdV[VZ] += gAgentAvatarp->getPelvisToFoot();
@@ -790,7 +792,8 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
LL_DEBUGS("UserInput") << "hover handled by LLToolPie (inactive)" << LL_ENDL;
}
else if ((!object || !object->isAttachment() || object->getClickAction() != CLICK_ACTION_DISABLED)
- && ((object && object->flagHandleTouch()) || (parent && parent->flagHandleTouch())))
+ && ((object && object->flagHandleTouch()) || (parent && parent->flagHandleTouch()))
+ && (!object || !object->isAvatar()))
{
show_highlight = true;
gViewerWindow->setCursor(UI_CURSOR_HAND);
@@ -1094,8 +1097,6 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l
final_name = LLTrans::getString("TooltipPerson");;
}
- // *HACK: We may select this object, so pretend it was clicked
- mPick = mHoverPick;
LLInspector::Params p;
p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
p.message(final_name);
@@ -1207,8 +1208,6 @@ BOOL LLToolPie::handleTooltipObject( LLViewerObject* hover_object, std::string l
if (show_all_object_tips || needs_tip)
{
- // We may select this object, so pretend it was clicked
- mPick = mHoverPick;
LLInspector::Params p;
p.fillFrom(LLUICtrlFactory::instance().getDefaultParams<LLInspector>());
p.message(tooltip_msg);
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
index 553a3cd086..a2c696c762 100644
--- a/indra/newview/lltranslate.cpp
+++ b/indra/newview/lltranslate.cpp
@@ -197,6 +197,11 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s
LLSD result = httpAdapter->getRawAndSuspend(httpRequest, url, httpOpts, httpHeaders);
+ if (LLApp::isQuitting())
+ {
+ return;
+ }
+
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -207,7 +212,22 @@ void LLTranslationAPIHandler::translateMessageCoro(LanguagePair_t fromTo, std::s
const LLSD::Binary &rawBody = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS_RAW].asBinary();
std::string body(rawBody.begin(), rawBody.end());
- if (this->parseResponse(parseResult, body, translation, detected_lang, err_msg))
+ bool res = false;
+
+ try
+ {
+ res = this->parseResponse(parseResult, body, translation, detected_lang, err_msg);
+ }
+ catch (std::out_of_range&)
+ {
+ LL_WARNS() << "Out of range exception on string " << body << LL_ENDL;
+ }
+ catch (...)
+ {
+ LOG_UNHANDLED_EXCEPTION( "Exception on string " + body );
+ }
+
+ if (res)
{
// Fix up the response
LLStringUtil::replaceString(translation, "&lt;", "<");
diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp
index 4720a989b0..376a7fce76 100644
--- a/indra/newview/llversioninfo.cpp
+++ b/indra/newview/llversioninfo.cpp
@@ -28,9 +28,9 @@
#include "llviewerprecompiledheaders.h"
#include "llevents.h"
#include "lleventfilter.h"
+#include "llregex.h"
#include "llversioninfo.h"
#include "stringize.h"
-#include <boost/regex.hpp>
#if ! defined(LL_VIEWER_CHANNEL) \
|| ! defined(LL_VIEWER_VERSION_MAJOR) \
@@ -139,19 +139,19 @@ LLVersionInfo::ViewerMaturity LLVersionInfo::getViewerMaturity()
static const boost::regex is_project_channel("\\bProject\\b");
static const boost::regex is_release_channel("\\bRelease\\b");
- if (boost::regex_search(channel, is_release_channel))
+ if (ll_regex_search(channel, is_release_channel))
{
maturity = RELEASE_VIEWER;
}
- else if (boost::regex_search(channel, is_beta_channel))
+ else if (ll_regex_search(channel, is_beta_channel))
{
maturity = BETA_VIEWER;
}
- else if (boost::regex_search(channel, is_project_channel))
+ else if (ll_regex_search(channel, is_project_channel))
{
maturity = PROJECT_VIEWER;
}
- else if (boost::regex_search(channel, is_test_channel))
+ else if (ll_regex_search(channel, is_test_channel))
{
maturity = TEST_VIEWER;
}
diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp
index c1b129750a..64d9ce62c5 100644
--- a/indra/newview/llviewerassetstorage.cpp
+++ b/indra/newview/llviewerassetstorage.cpp
@@ -520,6 +520,12 @@ void LLViewerAssetStorage::assetRequestCoro(
boost::bind(&LLViewerAssetStorage::capsRecvForRegion, this, _1, capsRecv.getName()));
llcoro::suspendUntilEventOn(capsRecv);
+
+ if (LLApp::isExiting() || !gAssetStorage)
+ {
+ return;
+ }
+
LL_WARNS_ONCE("ViewerAsset") << "capsRecv got event" << LL_ENDL;
LL_WARNS_ONCE("ViewerAsset") << "region " << gAgent.getRegion() << " mViewerAssetUrl " << mViewerAssetUrl << LL_ENDL;
}
diff --git a/indra/newview/llviewerassetupload.cpp b/indra/newview/llviewerassetupload.cpp
index bc07821ccd..0df6811f6a 100644
--- a/indra/newview/llviewerassetupload.cpp
+++ b/indra/newview/llviewerassetupload.cpp
@@ -793,7 +793,7 @@ void LLViewerAssetUpload::AssetInventoryUploadCoproc(LLCoreHttpUtil::HttpCorouti
// Show the preview panel for textures and sounds to let
// user know that the image (or snapshot) arrived intact.
LLInventoryPanel* panel = LLInventoryPanel::getActiveInventoryPanel(FALSE);
- LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, serverInventoryItem, TRUE, TAKE_FOCUS_NO, (panel == NULL));
+ LLInventoryPanel::openInventoryPanelAndSetSelection(TRUE, serverInventoryItem, FALSE, TAKE_FOCUS_NO, (panel == NULL));
// restore keyboard focus
gFocusMgr.setKeyboardFocus(focus);
diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp
index cb20801756..f97ba0930e 100644
--- a/indra/newview/llvieweraudio.cpp
+++ b/indra/newview/llvieweraudio.cpp
@@ -81,7 +81,7 @@ void LLViewerAudio::registerIdleListener()
}
}
-void LLViewerAudio::startInternetStreamWithAutoFade(std::string streamURI)
+void LLViewerAudio::startInternetStreamWithAutoFade(const std::string &streamURI)
{
// Old and new stream are identical
if (mNextStreamURI == streamURI)
diff --git a/indra/newview/llvieweraudio.h b/indra/newview/llvieweraudio.h
index 16f9b63113..782285ce36 100644
--- a/indra/newview/llvieweraudio.h
+++ b/indra/newview/llvieweraudio.h
@@ -55,7 +55,7 @@ public:
FADE_OUT,
};
- void startInternetStreamWithAutoFade(std::string streamURI);
+ void startInternetStreamWithAutoFade(const std::string &streamURI);
void stopInternetStreamWithAutoFade();
bool onIdleUpdate();
@@ -65,7 +65,8 @@ public:
F32 getFadeVolume();
bool getForcedTeleportFade() { return mForcedTeleportFade; };
void setForcedTeleportFade(bool fade) { mForcedTeleportFade = fade;} ;
- void setNextStreamURI(std::string stream) { mNextStreamURI = stream; } ;
+ std::string getNextStreamURI() { return mNextStreamURI; };
+ void setNextStreamURI(const std::string &stream) { mNextStreamURI = stream; } ;
void setWasPlaying(bool playing) { mWasPlaying = playing;} ;
private:
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index e5ebbcb9ab..9f76543647 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -107,10 +107,14 @@ static bool handleRenderAvatarMouselookChanged(const LLSD& newvalue)
static bool handleRenderFarClipChanged(const LLSD& newvalue)
{
- F32 draw_distance = (F32) newvalue.asReal();
- gAgentCamera.mDrawDistance = draw_distance;
- LLWorld::getInstance()->setLandFarClip(draw_distance);
- return true;
+ if (LLStartUp::getStartupState() >= STATE_STARTED)
+ {
+ F32 draw_distance = (F32)newvalue.asReal();
+ gAgentCamera.mDrawDistance = draw_distance;
+ LLWorld::getInstance()->setLandFarClip(draw_distance);
+ return true;
+ }
+ return false;
}
static bool handleTerrainDetailChanged(const LLSD& newvalue)
@@ -143,6 +147,20 @@ static bool handleSetShaderChanged(const LLSD& newvalue)
gBumpImageList.destroyGL();
gBumpImageList.restoreGL();
+ if (gPipeline.isInit())
+ {
+ // ALM depends onto atmospheric shaders, state might have changed
+ bool old_state = LLPipeline::sRenderDeferred;
+ LLPipeline::refreshCachedSettings();
+ gPipeline.updateRenderDeferred();
+ if (old_state != LLPipeline::sRenderDeferred)
+ {
+ gPipeline.releaseGLBuffers();
+ gPipeline.createGLBuffers();
+ gPipeline.resetVertexBuffers();
+ }
+ }
+
// else, leave terrain detail as is
LLViewerShaderMgr::instance()->setShaders();
return true;
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 6368286f6e..38ac4275cf 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -578,8 +578,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
//
LLAppViewer::instance()->pingMainloopTimeout("Display:Camera");
- LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield);
- LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
+ if (LLViewerCamera::instanceExists())
+ {
+ LLViewerCamera::getInstance()->setZoomParameters(zoom_factor, subfield);
+ LLViewerCamera::getInstance()->setNear(MIN_NEAR_PLANE);
+ }
//////////////////////////
//
diff --git a/indra/newview/llviewerinput.cpp b/indra/newview/llviewerinput.cpp
index c0eaa88f54..94ec534732 100644
--- a/indra/newview/llviewerinput.cpp
+++ b/indra/newview/llviewerinput.cpp
@@ -38,6 +38,7 @@
#include "llkeybind.h" // LLKeyData
#include "llmorphview.h"
#include "llmoveview.h"
+#include "llsetkeybinddialog.h"
#include "lltoolfocus.h"
#include "lltoolpie.h"
#include "llviewercontrol.h"
@@ -60,8 +61,21 @@ const F32 ORBIT_NUDGE_RATE = 0.05f; // fraction of normal speed
const LLKeyData agent_control_lbutton(CLICK_LEFT, KEY_NONE, MASK_NONE, true);
+struct LLKeybindFunctionData
+{
+ LLKeybindFunctionData(boost::function<bool(EKeystate keystate)> function, bool global)
+ :
+ mFunction(function),
+ mIsGlobal(global)
+ {
+ }
+ boost::function<bool(EKeystate keystate)> mFunction;
+ // todo: might be good idea to make this into enum, like: global/inworld/menu
+ bool mIsGlobal;
+};
+
struct LLKeyboardActionRegistry
-: public LLRegistrySingleton<std::string, boost::function<bool (EKeystate keystate)>, LLKeyboardActionRegistry>
+: public LLRegistrySingleton<const std::string, LLKeybindFunctionData, LLKeyboardActionRegistry>
{
LLSINGLETON_EMPTY_CTOR(LLKeyboardActionRegistry);
};
@@ -852,7 +866,10 @@ bool agen_control_lbutton_handle(EKeystate s)
return true;
}
-#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, ACTION);
+// In-world keybindings, like walking or camera
+#define REGISTER_KEYBOARD_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, LLKeybindFunctionData(ACTION, false));
+// Global keybindings that should work even with floaters focused, like voice
+#define REGISTER_KEYBOARD_GLOBAL_ACTION(KEY, ACTION) LLREGISTER_STATIC(LLKeyboardActionRegistry, KEY, LLKeybindFunctionData(ACTION, true));
REGISTER_KEYBOARD_ACTION("jump", agent_jump);
REGISTER_KEYBOARD_ACTION("push_down", agent_push_down);
REGISTER_KEYBOARD_ACTION("push_forward", agent_push_forward);
@@ -903,8 +920,8 @@ REGISTER_KEYBOARD_ACTION("toggle_pause_media", toggle_pause_media);
REGISTER_KEYBOARD_ACTION("toggle_enable_media", toggle_enable_media);
REGISTER_KEYBOARD_ACTION("teleport_to", teleport_to);
REGISTER_KEYBOARD_ACTION("walk_to", walk_to);
-REGISTER_KEYBOARD_ACTION("toggle_voice", toggle_voice);
-REGISTER_KEYBOARD_ACTION("voice_follow_key", voice_follow_key);
+REGISTER_KEYBOARD_GLOBAL_ACTION("toggle_voice", toggle_voice);
+REGISTER_KEYBOARD_GLOBAL_ACTION("voice_follow_key", voice_follow_key);
#undef REGISTER_KEYBOARD_ACTION
LLViewerInput::LLViewerInput()
@@ -1034,6 +1051,53 @@ BOOL LLViewerInput::handleKeyUp(KEY translated_key, MASK translated_mask)
return gViewerWindow->handleKeyUp(translated_key, translated_mask);
}
+bool LLViewerInput::handleGlobalBindsKeyDown(KEY key, MASK mask)
+{
+ if (LLSetKeyBindDialog::isRecording())
+ {
+ // handleGlobalBindsKeyDown happens before view handling, so can't
+ // be interupted by LLSetKeyBindDialog, check manually
+ return false;
+ }
+ S32 mode = getMode();
+ return scanKey(mGlobalKeyBindings[mode], mGlobalKeyBindings[mode].size(), key, mask, TRUE, FALSE, FALSE, FALSE);
+}
+
+bool LLViewerInput::handleGlobalBindsKeyUp(KEY key, MASK mask)
+{
+ if (LLSetKeyBindDialog::isRecording())
+ {
+ // handleGlobalBindsKeyUp happens before view handling, so can't
+ // be interupted by LLSetKeyBindDialog, check manually
+ return false;
+ }
+
+ S32 mode = getMode();
+ return scanKey(mGlobalKeyBindings[mode], mGlobalKeyBindings[mode].size(), key, mask, FALSE, TRUE, FALSE, FALSE);
+}
+
+bool LLViewerInput::handleGlobalBindsMouse(EMouseClickType clicktype, MASK mask, bool down)
+{
+ if (LLSetKeyBindDialog::isRecording())
+ {
+ // handleGlobalBindsMouse happens before view handling, so can't
+ // be interupted by LLSetKeyBindDialog, check manually
+ return false;
+ }
+
+ bool res = false;
+ S32 mode = getMode();
+ if (down)
+ {
+ res = scanMouse(mGlobalMouseBindings[mode], mGlobalMouseBindings[mode].size(), clicktype, mask, MOUSE_STATE_DOWN, true);
+ }
+ else
+ {
+ res = scanMouse(mGlobalMouseBindings[mode], mGlobalMouseBindings[mode].size(), clicktype, mask, MOUSE_STATE_UP, true);
+ }
+ return res;
+}
+
BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name)
{
S32 index;
@@ -1061,39 +1125,64 @@ BOOL LLViewerInput::bindKey(const S32 mode, const KEY key, const MASK mask, cons
}
// Not remapped, look for a function
-
- function_t* result = LLKeyboardActionRegistry::getValue(function_name);
+
+ LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name);
if (result)
{
- function = *result;
+ function = result->mFunction;
}
if (!function)
{
- LL_ERRS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL;
+ LL_WARNS_ONCE() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL;
return FALSE;
}
- // check for duplicate first and overwrite
- S32 size = mKeyBindings[mode].size();
- for (index = 0; index < size; index++)
+ if (mode >= MODE_COUNT)
{
- if (key == mKeyBindings[mode][index].mKey && mask == mKeyBindings[mode][index].mMask)
- break;
+ LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
+ return FALSE;
}
- if (mode >= MODE_COUNT)
- {
- LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
- return FALSE;
- }
+ // check for duplicate first and overwrite
+ if (result->mIsGlobal)
+ {
+ S32 size = mGlobalKeyBindings[mode].size();
+ for (index = 0; index < size; index++)
+ {
+ if (key == mGlobalKeyBindings[mode][index].mKey && mask == mGlobalKeyBindings[mode][index].mMask)
+ {
+ mGlobalKeyBindings[mode][index].mFunction = function;
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ S32 size = mKeyBindings[mode].size();
+ for (index = 0; index < size; index++)
+ {
+ if (key == mKeyBindings[mode][index].mKey && mask == mKeyBindings[mode][index].mMask)
+ {
+ mKeyBindings[mode][index].mFunction = function;
+ return TRUE;
+ }
+ }
+ }
LLKeyboardBinding bind;
bind.mKey = key;
bind.mMask = mask;
bind.mFunction = function;
- mKeyBindings[mode].push_back(bind);
+ if (result->mIsGlobal)
+ {
+ mGlobalKeyBindings[mode].push_back(bind);
+ }
+ else
+ {
+ mKeyBindings[mode].push_back(bind);
+ }
return TRUE;
}
@@ -1104,38 +1193,63 @@ BOOL LLViewerInput::bindMouse(const S32 mode, const EMouseClickType mouse, const
typedef boost::function<bool(EKeystate)> function_t;
function_t function = NULL;
- function_t* result = LLKeyboardActionRegistry::getValue(function_name);
+ LLKeybindFunctionData* result = LLKeyboardActionRegistry::getValue(function_name);
if (result)
{
- function = *result;
+ function = result->mFunction;
}
if (!function)
{
- LL_ERRS() << "Can't bind key to function " << function_name << ", no function with this name found" << LL_ENDL;
+ LL_WARNS_ONCE() << "Can't bind mouse key to function " << function_name << ", no function with this name found" << LL_ENDL;
return FALSE;
}
- // check for duplicate first and overwrite
- S32 size = mMouseBindings[mode].size();
- for (index = 0; index < size; index++)
- {
- if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask)
- break;
- }
-
if (mode >= MODE_COUNT)
{
LL_ERRS() << "LLKeyboard::bindKey() - unknown mode passed" << mode << LL_ENDL;
return FALSE;
}
+ // check for duplicate first and overwrite
+ if (result->mIsGlobal)
+ {
+ S32 size = mGlobalMouseBindings[mode].size();
+ for (index = 0; index < size; index++)
+ {
+ if (mouse == mGlobalMouseBindings[mode][index].mMouse && mask == mGlobalMouseBindings[mode][index].mMask)
+ {
+ mGlobalMouseBindings[mode][index].mFunction = function;
+ return true;
+ }
+ }
+ }
+ else
+ {
+ S32 size = mMouseBindings[mode].size();
+ for (index = 0; index < size; index++)
+ {
+ if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask)
+ {
+ mMouseBindings[mode][index].mFunction = function;
+ return true;
+ }
+ }
+ }
+
LLMouseBinding bind;
bind.mMouse = mouse;
bind.mMask = mask;
bind.mFunction = function;
- mMouseBindings[mode].push_back(bind);
+ if (result->mIsGlobal)
+ {
+ mGlobalMouseBindings[mode].push_back(bind);
+ }
+ else
+ {
+ mMouseBindings[mode].push_back(bind);
+ }
return TRUE;
}
@@ -1162,6 +1276,8 @@ void LLViewerInput::resetBindings()
{
for (S32 i = 0; i < MODE_COUNT; i++)
{
+ mGlobalKeyBindings[i].clear();
+ mGlobalMouseBindings[i].clear();
mKeyBindings[i].clear();
mMouseBindings[i].clear();
}
@@ -1439,11 +1555,18 @@ BOOL LLViewerInput::handleMouse(LLWindow *window_impl, LLCoordGL pos, MASK mask,
return handled;
}
-bool LLViewerInput::scanMouse(const std::vector<LLMouseBinding> &binding, S32 binding_count, EMouseClickType mouse, MASK mask, EMouseState state) const
+bool LLViewerInput::scanMouse(
+ const std::vector<LLMouseBinding> &binding,
+ S32 binding_count,
+ EMouseClickType mouse,
+ MASK mask,
+ EMouseState state,
+ bool ignore_additional_masks
+) const
{
for (S32 i = 0; i < binding_count; i++)
{
- if (binding[i].mMouse == mouse && (binding[i].mMask & mask) == binding[i].mMask)
+ if (binding[i].mMouse == mouse && (ignore_additional_masks ? (binding[i].mMask & mask) == binding[i].mMask : binding[i].mMask == mask))
{
bool res = false;
switch (state)
@@ -1480,7 +1603,11 @@ bool LLViewerInput::scanMouse(EMouseClickType click, EMouseState state) const
bool res = false;
S32 mode = getMode();
MASK mask = gKeyboard->currentMask(TRUE);
- res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state);
+
+ // By default mouse clicks require exact mask
+ // Todo: support for mIgnoreMasks because some functions like teleports
+ // expect to be canceled, but for voice it's prefered to ignore mask.
+ res = scanMouse(mMouseBindings[mode], mMouseBindings[mode].size(), click, mask, state, false);
// no user defined actions found or those actions can't handle the key/button, handle control if nessesary
if (!res && agent_control_lbutton.canHandle(click, KEY_NONE, mask))
{
@@ -1536,5 +1663,11 @@ bool LLViewerInput::isMouseBindUsed(const EMouseClickType mouse, const MASK mask
if (mouse == mMouseBindings[mode][index].mMouse && mask == mMouseBindings[mode][index].mMask)
return true;
}
+ size = mGlobalMouseBindings[mode].size();
+ for (S32 index = 0; index < size; index++)
+ {
+ if (mouse == mGlobalMouseBindings[mode][index].mMouse && mask == mGlobalMouseBindings[mode][index].mMask)
+ return true;
+ }
return false;
}
diff --git a/indra/newview/llviewerinput.h b/indra/newview/llviewerinput.h
index 281a209896..ca70ac76bf 100644
--- a/indra/newview/llviewerinput.h
+++ b/indra/newview/llviewerinput.h
@@ -109,6 +109,13 @@ public:
BOOL handleKey(KEY key, MASK mask, BOOL repeated);
BOOL handleKeyUp(KEY key, MASK mask);
+ // Handle 'global' keybindings that do not consume event,
+ // yet need to be processed early
+ // Example: we want voice to toggle even if some floater is focused
+ bool handleGlobalBindsKeyDown(KEY key, MASK mask);
+ bool handleGlobalBindsKeyUp(KEY key, MASK mask);
+ bool handleGlobalBindsMouse(EMouseClickType clicktype, MASK mask, bool down);
+
S32 loadBindingsXML(const std::string& filename); // returns number bound, 0 on error
EKeyboardMode getMode() const;
@@ -149,7 +156,8 @@ private:
S32 binding_count,
EMouseClickType mouse,
MASK mask,
- EMouseState state) const;
+ EMouseState state,
+ bool ignore_additional_masks) const;
S32 loadBindingMode(const LLViewerInput::KeyMode& keymode, S32 mode);
BOOL bindKey(const S32 mode, const KEY key, const MASK mask, const std::string& function_name);
@@ -164,6 +172,10 @@ private:
std::vector<LLKeyboardBinding> mKeyBindings[MODE_COUNT];
std::vector<LLMouseBinding> mMouseBindings[MODE_COUNT];
+ // keybindings that do not consume event and are handled earlier, before floaters
+ std::vector<LLKeyboardBinding> mGlobalKeyBindings[MODE_COUNT];
+ std::vector<LLMouseBinding> mGlobalMouseBindings[MODE_COUNT];
+
typedef std::map<U32, U32> key_remap_t;
key_remap_t mRemapKeys[MODE_COUNT];
std::set<KEY> mKeysSkippedByUI;
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index bbed741a33..55ac817479 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -1756,7 +1756,7 @@ void menu_create_inventory_item(LLInventoryPanel* panel, LLFolderBridge *bridge,
else
{
// Use for all clothing and body parts. Adding new wearable types requires updating LLWearableDictionary.
- LLWearableType::EType wearable_type = LLWearableType::typeNameToType(type_name);
+ LLWearableType::EType wearable_type = LLWearableType::getInstance()->typeNameToType(type_name);
if (wearable_type >= LLWearableType::WT_SHAPE && wearable_type < LLWearableType::WT_COUNT)
{
const LLUUID parent_id = bridge ? bridge->getUUID() : LLUUID::null;
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index c347e0eb76..af8db76add 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1290,7 +1290,13 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
// down.
std::string cefUrl(std::string(inst->mOpenIDURL.mURI) + "://" + std::string(inst->mOpenIDURL.mAuthority));
- media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host, cookie_path, httponly, secure);
+ media_instance->getMediaPlugin()->setCookie(cefUrl, cookie_name, cookie_value, cookie_host,
+ cookie_path, httponly, secure);
+
+ // Now that we have parsed the raw cookie, we must store it so that each new media instance
+ // can also get a copy and faciliate logging into internal SL sites.
+ media_instance->getMediaPlugin()->storeOpenIDCookie(cefUrl, cookie_name, cookie_value,
+ cookie_host, cookie_path, httponly, secure);
}
}
}
@@ -1830,6 +1836,7 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
if (media_source)
{
+ media_source->injectOpenIDCookie();
media_source->setDisableTimeout(gSavedSettings.getBOOL("DebugPluginDisableTimeout"));
media_source->setLoop(mMediaLoop);
media_source->setAutoScale(mMediaAutoScale);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 534c03d581..3f8398d93a 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -360,11 +360,21 @@ LLMenuParcelObserver::~LLMenuParcelObserver()
void LLMenuParcelObserver::changed()
{
LLParcel *parcel = LLViewerParcelMgr::getInstance()->getParcelSelection()->getParcel();
- gMenuHolder->childSetEnabled("Land Buy Pass", LLPanelLandGeneral::enableBuyPass(NULL) && !(parcel->getOwnerID()== gAgent.getID()));
-
- BOOL buyable = enable_buy_land(NULL);
- gMenuHolder->childSetEnabled("Land Buy", buyable);
- gMenuHolder->childSetEnabled("Buy Land...", buyable);
+ if (gMenuLand && parcel)
+ {
+ LLView* child = gMenuLand->findChild<LLView>("Land Buy Pass");
+ if (child)
+ {
+ child->setEnabled(LLPanelLandGeneral::enableBuyPass(NULL) && !(parcel->getOwnerID() == gAgent.getID()));
+ }
+
+ child = gMenuLand->findChild<LLView>("Land Buy");
+ if (child)
+ {
+ BOOL buyable = enable_buy_land(NULL);
+ child->setEnabled(buyable);
+ }
+ }
}
@@ -7280,7 +7290,7 @@ namespace
};
}
-void queue_actions(LLFloaterScriptQueue* q, const std::string& msg)
+bool queue_actions(LLFloaterScriptQueue* q, const std::string& msg)
{
QueueObjects func(q);
LLSelectMgr *mgr = LLSelectMgr::getInstance();
@@ -7302,6 +7312,7 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& msg)
{
LL_ERRS() << "Bad logic." << LL_ENDL;
}
+ q->closeFloater();
}
else
{
@@ -7310,6 +7321,7 @@ void queue_actions(LLFloaterScriptQueue* q, const std::string& msg)
LL_WARNS() << "Unexpected script compile failure." << LL_ENDL;
}
}
+ return !fail;
}
class LLToolsSelectedScriptAction : public view_listener_t
@@ -7357,8 +7369,10 @@ class LLToolsSelectedScriptAction : public view_listener_t
if (queue)
{
queue->setMono(mono);
- queue_actions(queue, msg);
- queue->setTitle(title);
+ if (queue_actions(queue, msg))
+ {
+ queue->setTitle(title);
+ }
}
else
{
@@ -8553,7 +8567,7 @@ class LLEditEnableTakeOff : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
std::string clothing = userdata.asString();
- LLWearableType::EType type = LLWearableType::typeNameToType(clothing);
+ LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing);
if (type >= LLWearableType::WT_SHAPE && type < LLWearableType::WT_COUNT)
return LLAgentWearables::selfHasWearable(type);
return false;
@@ -8569,7 +8583,7 @@ class LLEditTakeOff : public view_listener_t
LLAppearanceMgr::instance().removeAllClothesFromAvatar();
else
{
- LLWearableType::EType type = LLWearableType::typeNameToType(clothing);
+ LLWearableType::EType type = LLWearableType::getInstance()->typeNameToType(clothing);
if (type >= LLWearableType::WT_SHAPE
&& type < LLWearableType::WT_COUNT
&& (gAgentWearables.getWearableCount(type) > 0))
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 52a65abf9b..e5d81032c5 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -38,6 +38,7 @@
#include "llfollowcamparams.h"
#include "llinventorydefines.h"
#include "lllslconstants.h"
+#include "llmaterialtable.h"
#include "llregionhandle.h"
#include "llsd.h"
#include "llsdserialize.h"
@@ -3853,6 +3854,11 @@ void process_sound_trigger(LLMessageSystem *msg, void **)
return;
}
+ if (LLMaterialTable::basic.isCollisionSound(sound_id) && !gSavedSettings.getBOOL("EnableCollisionSounds"))
+ {
+ return;
+ }
+
gAudiop->triggerSound(sound_id, owner_id, gain, LLAudioEngine::AUDIO_TYPE_SFX, pos_global);
}
diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp
index 868cf75d11..b7d0e06116 100644
--- a/indra/newview/llvieweroctree.cpp
+++ b/indra/newview/llvieweroctree.cpp
@@ -32,6 +32,7 @@
#include "llappviewer.h"
#include "llglslshader.h"
#include "llviewershadermgr.h"
+#include "lldrawpoolwater.h"
//-----------------------------------------------------------------------------------
//static variables definitions
@@ -931,47 +932,53 @@ void LLOcclusionCullingGroup::releaseOcclusionQueryObjectNames()
}
}
-void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode)
-{
- if (mode > STATE_MODE_SINGLE)
- {
- if (mode == STATE_MODE_DIFF)
- {
- LLSpatialSetOcclusionStateDiff setter(state);
- setter.traverse(mOctreeNode);
- }
- else if (mode == STATE_MODE_BRANCH)
- {
- LLSpatialSetOcclusionState setter(state);
- setter.traverse(mOctreeNode);
- }
- else
- {
- for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
- {
- mOcclusionState[i] |= state;
-
- if ((state & DISCARD_QUERY) && mOcclusionQuery[i])
- {
- releaseOcclusionQueryObjectName(mOcclusionQuery[i]);
- mOcclusionQuery[i] = 0;
- }
- }
- }
- }
- else
- {
- if (state & OCCLUDED)
- {
- add(sNumObjectsOccluded, 1);
- }
- mOcclusionState[LLViewerCamera::sCurCameraID] |= state;
- if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
- {
- releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
- mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
- }
- }
+void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode /* = STATE_MODE_SINGLE */ )
+{
+ switch (mode)
+ {
+ case STATE_MODE_SINGLE:
+ if (state & OCCLUDED)
+ {
+ add(sNumObjectsOccluded, 1);
+ }
+ mOcclusionState[LLViewerCamera::sCurCameraID] |= state;
+ if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
+ {
+ releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
+ mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
+ }
+ break;
+
+ case STATE_MODE_DIFF:
+ {
+ LLSpatialSetOcclusionStateDiff setter(state);
+ setter.traverse(mOctreeNode);
+ }
+ break;
+
+ case STATE_MODE_BRANCH:
+ {
+ LLSpatialSetOcclusionState setter(state);
+ setter.traverse(mOctreeNode);
+ }
+ break;
+
+ case STATE_MODE_ALL_CAMERAS:
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionState[i] |= state;
+
+ if ((state & DISCARD_QUERY) && mOcclusionQuery[i])
+ {
+ releaseOcclusionQueryObjectName(mOcclusionQuery[i]);
+ mOcclusionQuery[i] = 0;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
}
class LLSpatialClearOcclusionState : public OctreeTraveler
@@ -1006,36 +1013,42 @@ public:
}
};
-void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode)
-{
- if (mode > STATE_MODE_SINGLE)
- {
- if (mode == STATE_MODE_DIFF)
- {
- LLSpatialClearOcclusionStateDiff clearer(state);
- clearer.traverse(mOctreeNode);
- }
- else if (mode == STATE_MODE_BRANCH)
- {
- LLSpatialClearOcclusionState clearer(state);
- clearer.traverse(mOctreeNode);
- }
- else
- {
- for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
- {
- mOcclusionState[i] &= ~state;
- }
- }
- }
- else
- {
- if (state & OCCLUDED)
- {
- add(sNumObjectsUnoccluded, 1);
- }
- mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state;
- }
+void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode /* = STATE_MODE_SINGLE */)
+{
+ switch (mode)
+ {
+ case STATE_MODE_SINGLE:
+ if (state & OCCLUDED)
+ {
+ add(sNumObjectsUnoccluded, 1);
+ }
+ mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state;
+ break;
+
+ case STATE_MODE_DIFF:
+ {
+ LLSpatialClearOcclusionStateDiff clearer(state);
+ clearer.traverse(mOctreeNode);
+ }
+ break;
+
+ case STATE_MODE_BRANCH:
+ {
+ LLSpatialClearOcclusionState clearer(state);
+ clearer.traverse(mOctreeNode);
+ }
+ break;
+
+ case STATE_MODE_ALL_CAMERAS:
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
+ {
+ mOcclusionState[i] &= ~state;
+ }
+ break;
+
+ default:
+ break;
+ }
}
BOOL LLOcclusionCullingGroup::earlyFail(LLCamera* camera, const LLVector4a* bounds)
@@ -1089,75 +1102,73 @@ U32 LLOcclusionCullingGroup::getLastOcclusionIssuedTime()
void LLOcclusionCullingGroup::checkOcclusion()
{
- if (LLPipeline::sUseOcclusion > 1)
- {
- LL_PROFILE_ZONE_SCOPED;
- LLOcclusionCullingGroup* parent = (LLOcclusionCullingGroup*)getParent();
- if (parent && parent->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
- { //if the parent has been marked as occluded, the child is implicitly occluded
- clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
- }
- else if (isOcclusionState(QUERY_PENDING))
- { //otherwise, if a query is pending, read it back
+ if (LLPipeline::sUseOcclusion < 2) return; // 0 - NoOcclusion, 1 = ReadOnly, 2 = ModifyOcclusionState TODO: DJH 11-2021 ENUM this
- GLuint available = 0;
- if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
- {
- LL_PROFILE_ZONE_NAMED("co - query available")
- glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
- }
- else
- {
- available = 1;
- }
-
- if (available)
- { //result is available, read it back, otherwise wait until next frame
- GLuint res = 1;
- if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
- {
- LL_PROFILE_ZONE_NAMED("co - query result")
- glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res);
+ LL_PROFILE_ZONE_SCOPED;
+ LLOcclusionCullingGroup* parent = (LLOcclusionCullingGroup*)getParent();
+ if (parent && parent->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
+ { //if the parent has been marked as occluded, the child is implicitly occluded
+ clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
+ return;
+ }
+
+ if (mOcclusionQuery[LLViewerCamera::sCurCameraID] && isOcclusionState(QUERY_PENDING))
+ {
+ if (isOcclusionState(DISCARD_QUERY))
+ { // delete the query to avoid holding onto hundreds of pending queries
+ releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
+ mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
+ // mark non-occluded
+ clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
+ clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
+ }
+ else
+ {
+ GLuint available;
+ {
+ LL_PROFILE_ZONE_NAMED("co - query available");
+ glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+ }
+
+ if (available)
+ {
+ GLuint query_result; // Will be # samples drawn, or a boolean depending on mHasOcclusionQuery2 (both are type GLuint)
+ {
+ LL_PROFILE_ZONE_NAMED("co - query result");
+ glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &query_result);
+ }
#if LL_TRACK_PENDING_OCCLUSION_QUERIES
- sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
+ sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
#endif
- }
- else if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
- { //delete the query to avoid holding onto hundreds of pending queries
- releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
- mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
- }
-
- if (isOcclusionState(DISCARD_QUERY))
- {
- res = 2;
- }
-
- if (res > 0)
- {
- assert_states_valid(this);
- clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
- assert_states_valid(this);
- }
- else
- {
- assert_states_valid(this);
-
- setOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
-
- assert_states_valid(this);
- }
-
- clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
- }
- }
- else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
- { //check occlusion has been issued for occluded node that has not had a query issued
- assert_states_valid(this);
- clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
- assert_states_valid(this);
- }
- }
+ if (LLPipeline::RENDER_TYPE_WATER == mSpatialPartition->mDrawableType)
+ {
+ // Note any unoccluded water, for deciding on reflection/distortion passes
+ // (If occlusion is disabled, these are set within LLDrawPoolWater::render)
+ if (query_result > 0)
+ {
+ LLDrawPoolWater::sNeedsReflectionUpdate = TRUE;
+ LLDrawPoolWater::sNeedsDistortionUpdate = TRUE;
+ }
+ }
+
+ if (query_result > 0)
+ {
+ clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
+ }
+ else
+ {
+ setOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
+ }
+ clearOcclusionState(QUERY_PENDING);
+ }
+ }
+ }
+ else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLOcclusionCullingGroup::OCCLUDED))
+ { //check occlusion has been issued for occluded node that has not had a query issued
+ assert_states_valid(this);
+ clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF);
+ assert_states_valid(this);
+ }
}
void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* shift)
@@ -1175,7 +1186,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
}
F32 OCCLUSION_FUDGE_Z = SG_OCCLUSION_FUDGE; //<-- #Solution #2
- if (LLDrawPool::POOL_WATER == mSpatialPartition->mDrawableType)
+ if (LLPipeline::RENDER_TYPE_VOIDWATER == mSpatialPartition->mDrawableType)
{
OCCLUSION_FUDGE_Z = 1.;
}
@@ -1205,8 +1216,8 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
// behind the far clip plane, and in the case of edge water to avoid
// it being culled while still visible.
bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
- (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER ||
- mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER);
+ (mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_WATER ||
+ mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_VOIDWATER);
LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0);
@@ -1237,7 +1248,7 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh
bounds[1][1]+SG_OCCLUSION_FUDGE,
bounds[1][2]+OCCLUSION_FUDGE_Z);
- if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER)
+ if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_VOIDWATER)
{
LL_PROFILE_ZONE_NAMED("doOcclusion - draw water");
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 06172e366d..56370df751 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -1888,7 +1888,8 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
if (parcel)
{
// Only update stream if parcel changed (recreated) or music is playing (enabled)
- if (!agent_parcel_update || gSavedSettings.getBOOL("MediaTentativeAutoPlay"))
+ static LLCachedControl<bool> already_playing(gSavedSettings, "MediaTentativeAutoPlay", true);
+ if (!agent_parcel_update || already_playing)
{
LLViewerParcelAskPlay::getInstance()->cancelNotification();
std::string music_url_raw = parcel->getMusicURL();
@@ -1906,7 +1907,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use
LLViewerRegion *region = LLWorld::getInstance()->getRegion(msg->getSender());
if (region)
{
- optionally_start_music(music_url, parcel->mLocalID, region->getRegionID());
+ optionallyStartMusic(music_url, parcel->mLocalID, region->getRegionID(), !agent_parcel_update);
}
}
else
@@ -1943,9 +1944,13 @@ void LLViewerParcelMgr::onStartMusicResponse(const LLUUID &region_id, const S32
LL_INFOS("ParcelMgr") << "Starting parcel music " << url << LL_ENDL;
LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(url);
}
+ else
+ {
+ LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null);
+ }
}
-void LLViewerParcelMgr::optionally_start_music(const std::string &music_url, const S32 &local_id, const LLUUID &region_id)
+void LLViewerParcelMgr::optionallyStartMusic(const std::string &music_url, const S32 &local_id, const LLUUID &region_id, bool switched_parcel)
{
static LLCachedControl<bool> streaming_music(gSavedSettings, "AudioStreamingMusic", true);
if (streaming_music)
@@ -1955,25 +1960,35 @@ void LLViewerParcelMgr::optionally_start_music(const std::string &music_url, con
// only play music when you enter a new parcel if the UI control for this
// was not *explicitly* stopped by the user. (part of SL-4878)
LLPanelNearByMedia* nearby_media_panel = gStatusBar->getNearbyMediaPanel();
+ LLViewerAudio* viewer_audio = LLViewerAudio::getInstance();
// ask mode //todo constants
if (autoplay_mode == 2)
{
- // stop previous stream
- LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null);
-
// if user set media to play - ask
if ((nearby_media_panel && nearby_media_panel->getParcelAudioAutoStart())
|| (!nearby_media_panel && tentative_autoplay))
{
- LLViewerParcelAskPlay::getInstance()->askToPlay(region_id,
- local_id,
- music_url,
- onStartMusicResponse);
+ // user did not stop audio
+ if (switched_parcel || music_url != viewer_audio->getNextStreamURI())
+ {
+ viewer_audio->startInternetStreamWithAutoFade(LLStringUtil::null);
+
+ LLViewerParcelAskPlay::getInstance()->askToPlay(region_id,
+ local_id,
+ music_url,
+ onStartMusicResponse);
+ }
+ // else do nothing:
+ // Parcel properties changed, but not url.
+ // We are already playing this url and asked about it when agent entered parcel
+ // or user started audio manually at some point
}
else
{
+ // stopped by the user, do not autoplay
LLViewerParcelAskPlay::getInstance()->cancelNotification();
+ viewer_audio->startInternetStreamWithAutoFade(LLStringUtil::null);
}
}
// autoplay
@@ -1985,11 +2000,12 @@ void LLViewerParcelMgr::optionally_start_music(const std::string &music_url, con
&& tentative_autoplay))
{
LL_INFOS("ParcelMgr") << "Starting parcel music " << music_url << LL_ENDL;
- LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(music_url);
+ viewer_audio->startInternetStreamWithAutoFade(music_url);
}
- else
+ // autoplay off
+ else if(switched_parcel || music_url != viewer_audio->getNextStreamURI())
{
- LLViewerAudio::getInstance()->startInternetStreamWithAutoFade(LLStringUtil::null);
+ viewer_audio->startInternetStreamWithAutoFade(LLStringUtil::null);
}
}
}
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 508a63c398..6ce389ab88 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -271,7 +271,7 @@ public:
//void makeLandmarkAtSelection();
static void onStartMusicResponse(const LLUUID &region_id, const S32 &parcel_id, const std::string &url, const bool &play);
- static void optionally_start_music(const std::string &music_url, const S32 &local_id, const LLUUID &region_id);
+ static void optionallyStartMusic(const std::string &music_url, const S32 &local_id, const LLUUID &region_id, bool switched_parcel);
static void processParcelOverlay(LLMessageSystem *msg, void **user_data);
static void processParcelProperties(LLMessageSystem *msg, void **user_data);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 7628a6c7ef..198fe1563c 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -187,7 +187,7 @@ public:
mLandp(NULL)
{}
- void buildCapabilityNames(LLSD& capabilityNames);
+ static void buildCapabilityNames(LLSD& capabilityNames);
// The surfaces and other layers
LLSurface* mLandp;
@@ -260,6 +260,12 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
// This loop is used for retrying a capabilities request.
do
{
+ if (STATE_WORLD_INIT > LLStartUp::getStartupState())
+ {
+ LL_INFOS("AppInit", "Capabilities") << "Aborting capabilities request, reason: returned to login screen" << LL_ENDL;
+ return;
+ }
+
regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
@@ -308,13 +314,19 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCoro(U64 regionHandle)
regionp = NULL;
result = httpAdapter->postAndSuspend(httpRequest, url, capabilityNames);
- ++mSeedCapAttempts;
+ if (STATE_WORLD_INIT > LLStartUp::getStartupState())
+ {
+ LL_INFOS("AppInit", "Capabilities") << "Aborting capabilities request, reason: returned to login screen" << LL_ENDL;
+ return;
+ }
- if (LLApp::isExiting())
+ if (LLApp::isExiting() || gDisconnected)
{
return;
}
+ ++mSeedCapAttempts;
+
regionp = LLWorld::getInstance()->getRegionFromHandle(regionHandle);
if (!regionp) //region was removed
{
@@ -429,7 +441,7 @@ void LLViewerRegionImpl::requestBaseCapabilitiesCompleteCoro(U64 regionHandle)
break; // no retry
}
- if (LLApp::isExiting())
+ if (LLApp::isExiting() || gDisconnected)
{
break;
}
@@ -537,7 +549,7 @@ void LLViewerRegionImpl::requestSimulatorFeatureCoro(std::string url, U64 region
continue;
}
- if (LLApp::isExiting())
+ if (LLApp::isExiting() || gDisconnected)
{
break;
}
@@ -2816,7 +2828,6 @@ void LLViewerRegion::unpackRegionHandshake()
mProductName = productName;
}
-
mCentralBakeVersion = region_protocols & 1; // was (S32)gSavedSettings.getBOOL("UseServerTextureBaking");
LLVLComposition *compp = getComposition();
if (compp)
@@ -2925,6 +2936,7 @@ void LLViewerRegion::unpackRegionHandshake()
mRegionTimer.reset(); //reset region timer.
}
+// static
void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)
{
capabilityNames.append("AbuseCategories");
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 1b6d8210c3..a1f532dd35 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -77,6 +77,7 @@ LLGLSLShader gTransformTangentProgram;
//utility shaders
LLGLSLShader gOcclusionProgram;
+LLGLSLShader gSkinnedOcclusionProgram;
LLGLSLShader gOcclusionCubeProgram;
LLGLSLShader gCustomAlphaProgram;
LLGLSLShader gGlowCombineProgram;
@@ -87,6 +88,7 @@ LLGLSLShader gTwoTextureCompareProgram;
LLGLSLShader gOneTextureFilterProgram;
LLGLSLShader gOneTextureNoColorProgram;
LLGLSLShader gDebugProgram;
+LLGLSLShader gSkinnedDebugProgram;
LLGLSLShader gClipProgram;
LLGLSLShader gDownsampleDepthProgram;
LLGLSLShader gDownsampleDepthRectProgram;
@@ -96,56 +98,49 @@ LLGLSLShader gBenchmarkProgram;
//object shaders
LLGLSLShader gObjectSimpleProgram;
+LLGLSLShader gSkinnedObjectSimpleProgram;
LLGLSLShader gObjectSimpleImpostorProgram;
+LLGLSLShader gSkinnedObjectSimpleImpostorProgram;
LLGLSLShader gObjectPreviewProgram;
LLGLSLShader gObjectSimpleWaterProgram;
+LLGLSLShader gSkinnedObjectSimpleWaterProgram;
LLGLSLShader gObjectSimpleAlphaMaskProgram;
+LLGLSLShader gSkinnedObjectSimpleAlphaMaskProgram;
LLGLSLShader gObjectSimpleWaterAlphaMaskProgram;
+LLGLSLShader gSkinnedObjectSimpleWaterAlphaMaskProgram;
LLGLSLShader gObjectFullbrightProgram;
+LLGLSLShader gSkinnedObjectFullbrightProgram;
LLGLSLShader gObjectFullbrightWaterProgram;
+LLGLSLShader gSkinnedObjectFullbrightWaterProgram;
LLGLSLShader gObjectEmissiveProgram;
+LLGLSLShader gSkinnedObjectEmissiveProgram;
LLGLSLShader gObjectEmissiveWaterProgram;
+LLGLSLShader gSkinnedObjectEmissiveWaterProgram;
LLGLSLShader gObjectFullbrightAlphaMaskProgram;
+LLGLSLShader gSkinnedObjectFullbrightAlphaMaskProgram;
LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram;
+LLGLSLShader gSkinnedObjectFullbrightWaterAlphaMaskProgram;
LLGLSLShader gObjectFullbrightShinyProgram;
+LLGLSLShader gSkinnedObjectFullbrightShinyProgram;
LLGLSLShader gObjectFullbrightShinyWaterProgram;
+LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram;
LLGLSLShader gObjectShinyProgram;
+LLGLSLShader gSkinnedObjectShinyProgram;
LLGLSLShader gObjectShinyWaterProgram;
+LLGLSLShader gSkinnedObjectShinyWaterProgram;
LLGLSLShader gObjectBumpProgram;
+LLGLSLShader gSkinnedObjectBumpProgram;
LLGLSLShader gTreeProgram;
LLGLSLShader gTreeWaterProgram;
LLGLSLShader gObjectFullbrightNoColorProgram;
LLGLSLShader gObjectFullbrightNoColorWaterProgram;
-LLGLSLShader gObjectSimpleNonIndexedProgram;
LLGLSLShader gObjectSimpleNonIndexedTexGenProgram;
LLGLSLShader gObjectSimpleNonIndexedTexGenWaterProgram;
-LLGLSLShader gObjectSimpleNonIndexedWaterProgram;
LLGLSLShader gObjectAlphaMaskNonIndexedProgram;
LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram;
LLGLSLShader gObjectAlphaMaskNoColorProgram;
LLGLSLShader gObjectAlphaMaskNoColorWaterProgram;
-LLGLSLShader gObjectFullbrightNonIndexedProgram;
-LLGLSLShader gObjectFullbrightNonIndexedWaterProgram;
-LLGLSLShader gObjectEmissiveNonIndexedProgram;
-LLGLSLShader gObjectEmissiveNonIndexedWaterProgram;
-LLGLSLShader gObjectFullbrightShinyNonIndexedProgram;
-LLGLSLShader gObjectFullbrightShinyNonIndexedWaterProgram;
-LLGLSLShader gObjectShinyNonIndexedProgram;
-LLGLSLShader gObjectShinyNonIndexedWaterProgram;
-
-//object hardware skinning shaders
-LLGLSLShader gSkinnedObjectSimpleProgram;
-LLGLSLShader gSkinnedObjectFullbrightProgram;
-LLGLSLShader gSkinnedObjectEmissiveProgram;
-LLGLSLShader gSkinnedObjectFullbrightShinyProgram;
-LLGLSLShader gSkinnedObjectShinySimpleProgram;
-
-LLGLSLShader gSkinnedObjectSimpleWaterProgram;
-LLGLSLShader gSkinnedObjectFullbrightWaterProgram;
-LLGLSLShader gSkinnedObjectEmissiveWaterProgram;
-LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram;
-LLGLSLShader gSkinnedObjectShinySimpleWaterProgram;
//environment shaders
LLGLSLShader gTerrainProgram;
@@ -191,17 +186,18 @@ LLGLSLShader gDeferredWaterProgram;
LLGLSLShader gDeferredUnderWaterProgram;
LLGLSLShader gDeferredDiffuseProgram;
LLGLSLShader gDeferredDiffuseAlphaMaskProgram;
+LLGLSLShader gDeferredSkinnedDiffuseAlphaMaskProgram;
LLGLSLShader gDeferredNonIndexedDiffuseProgram;
LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram;
LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram;
LLGLSLShader gDeferredSkinnedDiffuseProgram;
LLGLSLShader gDeferredSkinnedBumpProgram;
-LLGLSLShader gDeferredSkinnedAlphaProgram;
LLGLSLShader gDeferredBumpProgram;
LLGLSLShader gDeferredTerrainProgram;
LLGLSLShader gDeferredTerrainWaterProgram;
LLGLSLShader gDeferredTreeProgram;
LLGLSLShader gDeferredTreeShadowProgram;
+LLGLSLShader gDeferredSkinnedTreeShadowProgram;
LLGLSLShader gDeferredAvatarProgram;
LLGLSLShader gDeferredAvatarAlphaProgram;
LLGLSLShader gDeferredLightProgram;
@@ -213,9 +209,12 @@ LLGLSLShader gDeferredBlurLightProgram;
LLGLSLShader gDeferredSoftenProgram;
LLGLSLShader gDeferredSoftenWaterProgram;
LLGLSLShader gDeferredShadowProgram;
+LLGLSLShader gDeferredSkinnedShadowProgram;
LLGLSLShader gDeferredShadowCubeProgram;
LLGLSLShader gDeferredShadowAlphaMaskProgram;
+LLGLSLShader gDeferredSkinnedShadowAlphaMaskProgram;
LLGLSLShader gDeferredShadowFullbrightAlphaMaskProgram;
+LLGLSLShader gDeferredSkinnedShadowFullbrightAlphaMaskProgram;
LLGLSLShader gDeferredAvatarShadowProgram;
LLGLSLShader gDeferredAvatarAlphaShadowProgram;
LLGLSLShader gDeferredAvatarAlphaMaskShadowProgram;
@@ -223,14 +222,20 @@ LLGLSLShader gDeferredAttachmentShadowProgram;
LLGLSLShader gDeferredAttachmentAlphaShadowProgram;
LLGLSLShader gDeferredAttachmentAlphaMaskShadowProgram;
LLGLSLShader gDeferredAlphaProgram;
+LLGLSLShader gDeferredSkinnedAlphaProgram;
LLGLSLShader gDeferredAlphaImpostorProgram;
+LLGLSLShader gDeferredSkinnedAlphaImpostorProgram;
LLGLSLShader gDeferredAlphaWaterProgram;
+LLGLSLShader gDeferredSkinnedAlphaWaterProgram;
LLGLSLShader gDeferredAvatarEyesProgram;
LLGLSLShader gDeferredFullbrightProgram;
LLGLSLShader gDeferredFullbrightAlphaMaskProgram;
LLGLSLShader gDeferredFullbrightWaterProgram;
+LLGLSLShader gDeferredSkinnedFullbrightWaterProgram;
LLGLSLShader gDeferredFullbrightAlphaMaskWaterProgram;
+LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskWaterProgram;
LLGLSLShader gDeferredEmissiveProgram;
+LLGLSLShader gDeferredSkinnedEmissiveProgram;
LLGLSLShader gDeferredPostProgram;
LLGLSLShader gDeferredCoFProgram;
LLGLSLShader gDeferredDoFCombineProgram;
@@ -243,14 +248,29 @@ LLGLSLShader gDeferredWLSunProgram;
LLGLSLShader gDeferredWLMoonProgram;
LLGLSLShader gDeferredStarProgram;
LLGLSLShader gDeferredFullbrightShinyProgram;
-LLGLSLShader gDeferredSkinnedFullbrightShinyProgram;
+LLGLSLShader gDeferredSkinnedFullbrightShinyProgram;
LLGLSLShader gDeferredSkinnedFullbrightProgram;
+LLGLSLShader gDeferredSkinnedFullbrightAlphaMaskProgram;
LLGLSLShader gNormalMapGenProgram;
// Deferred materials shaders
LLGLSLShader gDeferredMaterialProgram[LLMaterial::SHADER_COUNT*2];
LLGLSLShader gDeferredMaterialWaterProgram[LLMaterial::SHADER_COUNT*2];
+//helper for making a rigged variant of a given shader
+bool make_rigged_variant(LLGLSLShader& shader, LLGLSLShader& riggedShader)
+{
+ riggedShader.mName = llformat("Skinned %s", shader.mName.c_str());
+ riggedShader.mFeatures = shader.mFeatures;
+ riggedShader.mFeatures.hasObjectSkinning = true;
+ riggedShader.addPermutation("HAS_SKIN", "1");
+ riggedShader.mShaderFiles = shader.mShaderFiles;
+ riggedShader.mShaderLevel = shader.mShaderLevel;
+ riggedShader.mShaderGroup = shader.mShaderGroup;
+ shader.mRiggedVariant = &riggedShader;
+ return riggedShader.createShader(NULL, NULL);
+}
+
LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderLevel(SHADER_COUNT, 0),
mMaxAvatarShaderLevel(0)
@@ -263,75 +283,77 @@ LLViewerShaderMgr::LLViewerShaderMgr() :
mShaderList.push_back(&gWLMoonProgram);
mShaderList.push_back(&gAvatarProgram);
mShaderList.push_back(&gObjectShinyProgram);
- mShaderList.push_back(&gObjectShinyNonIndexedProgram);
+ mShaderList.push_back(&gSkinnedObjectShinyProgram);
mShaderList.push_back(&gWaterProgram);
mShaderList.push_back(&gWaterEdgeProgram);
mShaderList.push_back(&gAvatarEyeballProgram);
mShaderList.push_back(&gObjectSimpleProgram);
+ mShaderList.push_back(&gSkinnedObjectSimpleProgram);
mShaderList.push_back(&gObjectSimpleImpostorProgram);
+ mShaderList.push_back(&gSkinnedObjectSimpleImpostorProgram);
mShaderList.push_back(&gObjectPreviewProgram);
mShaderList.push_back(&gImpostorProgram);
mShaderList.push_back(&gObjectFullbrightNoColorProgram);
mShaderList.push_back(&gObjectFullbrightNoColorWaterProgram);
mShaderList.push_back(&gObjectSimpleAlphaMaskProgram);
+ mShaderList.push_back(&gSkinnedObjectSimpleAlphaMaskProgram);
mShaderList.push_back(&gObjectBumpProgram);
+ mShaderList.push_back(&gSkinnedObjectBumpProgram);
mShaderList.push_back(&gObjectEmissiveProgram);
+ mShaderList.push_back(&gSkinnedObjectEmissiveProgram);
mShaderList.push_back(&gObjectEmissiveWaterProgram);
+ mShaderList.push_back(&gSkinnedObjectEmissiveWaterProgram);
mShaderList.push_back(&gObjectFullbrightProgram);
+ mShaderList.push_back(&gSkinnedObjectFullbrightProgram);
mShaderList.push_back(&gObjectFullbrightAlphaMaskProgram);
+ mShaderList.push_back(&gSkinnedObjectFullbrightAlphaMaskProgram);
mShaderList.push_back(&gObjectFullbrightShinyProgram);
+ mShaderList.push_back(&gSkinnedObjectFullbrightShinyProgram);
mShaderList.push_back(&gObjectFullbrightShinyWaterProgram);
- mShaderList.push_back(&gObjectSimpleNonIndexedProgram);
+ mShaderList.push_back(&gSkinnedObjectFullbrightShinyWaterProgram);
mShaderList.push_back(&gObjectSimpleNonIndexedTexGenProgram);
mShaderList.push_back(&gObjectSimpleNonIndexedTexGenWaterProgram);
- mShaderList.push_back(&gObjectSimpleNonIndexedWaterProgram);
mShaderList.push_back(&gObjectAlphaMaskNonIndexedProgram);
mShaderList.push_back(&gObjectAlphaMaskNonIndexedWaterProgram);
mShaderList.push_back(&gObjectAlphaMaskNoColorProgram);
mShaderList.push_back(&gObjectAlphaMaskNoColorWaterProgram);
mShaderList.push_back(&gTreeProgram);
mShaderList.push_back(&gTreeWaterProgram);
- mShaderList.push_back(&gObjectFullbrightNonIndexedProgram);
- mShaderList.push_back(&gObjectFullbrightNonIndexedWaterProgram);
- mShaderList.push_back(&gObjectEmissiveNonIndexedProgram);
- mShaderList.push_back(&gObjectEmissiveNonIndexedWaterProgram);
- mShaderList.push_back(&gObjectFullbrightShinyNonIndexedProgram);
- mShaderList.push_back(&gObjectFullbrightShinyNonIndexedWaterProgram);
- mShaderList.push_back(&gSkinnedObjectSimpleProgram);
- mShaderList.push_back(&gSkinnedObjectFullbrightProgram);
- mShaderList.push_back(&gSkinnedObjectEmissiveProgram);
- mShaderList.push_back(&gSkinnedObjectFullbrightShinyProgram);
- mShaderList.push_back(&gSkinnedObjectShinySimpleProgram);
- mShaderList.push_back(&gSkinnedObjectSimpleWaterProgram);
- mShaderList.push_back(&gSkinnedObjectFullbrightWaterProgram);
- mShaderList.push_back(&gSkinnedObjectEmissiveWaterProgram);
- mShaderList.push_back(&gSkinnedObjectFullbrightShinyWaterProgram);
- mShaderList.push_back(&gSkinnedObjectShinySimpleWaterProgram);
mShaderList.push_back(&gTerrainProgram);
mShaderList.push_back(&gTerrainWaterProgram);
mShaderList.push_back(&gObjectSimpleWaterProgram);
+ mShaderList.push_back(&gSkinnedObjectSimpleWaterProgram);
mShaderList.push_back(&gObjectFullbrightWaterProgram);
+ mShaderList.push_back(&gSkinnedObjectFullbrightWaterProgram);
mShaderList.push_back(&gObjectSimpleWaterAlphaMaskProgram);
+ mShaderList.push_back(&gSkinnedObjectSimpleWaterAlphaMaskProgram);
mShaderList.push_back(&gObjectFullbrightWaterAlphaMaskProgram);
+ mShaderList.push_back(&gSkinnedObjectFullbrightWaterAlphaMaskProgram);
mShaderList.push_back(&gAvatarWaterProgram);
mShaderList.push_back(&gObjectShinyWaterProgram);
- mShaderList.push_back(&gObjectShinyNonIndexedWaterProgram);
+ mShaderList.push_back(&gSkinnedObjectShinyWaterProgram);
mShaderList.push_back(&gUnderWaterProgram);
mShaderList.push_back(&gDeferredSunProgram);
mShaderList.push_back(&gDeferredSoftenProgram);
mShaderList.push_back(&gDeferredSoftenWaterProgram);
mShaderList.push_back(&gDeferredAlphaProgram);
+ mShaderList.push_back(&gDeferredSkinnedAlphaProgram);
mShaderList.push_back(&gDeferredAlphaImpostorProgram);
+ mShaderList.push_back(&gDeferredSkinnedAlphaImpostorProgram);
mShaderList.push_back(&gDeferredAlphaWaterProgram);
- mShaderList.push_back(&gDeferredSkinnedAlphaProgram);
+ mShaderList.push_back(&gDeferredSkinnedAlphaWaterProgram);
mShaderList.push_back(&gDeferredFullbrightProgram);
mShaderList.push_back(&gDeferredFullbrightAlphaMaskProgram);
mShaderList.push_back(&gDeferredFullbrightWaterProgram);
- mShaderList.push_back(&gDeferredFullbrightAlphaMaskWaterProgram);
+ mShaderList.push_back(&gDeferredSkinnedFullbrightWaterProgram);
+ mShaderList.push_back(&gDeferredFullbrightAlphaMaskWaterProgram);
+ mShaderList.push_back(&gDeferredSkinnedFullbrightAlphaMaskWaterProgram);
mShaderList.push_back(&gDeferredFullbrightShinyProgram);
- mShaderList.push_back(&gDeferredSkinnedFullbrightShinyProgram);
+ mShaderList.push_back(&gDeferredSkinnedFullbrightShinyProgram);
mShaderList.push_back(&gDeferredSkinnedFullbrightProgram);
+ mShaderList.push_back(&gDeferredSkinnedFullbrightAlphaMaskProgram);
mShaderList.push_back(&gDeferredEmissiveProgram);
+ mShaderList.push_back(&gDeferredSkinnedEmissiveProgram);
mShaderList.push_back(&gDeferredAvatarEyesProgram);
mShaderList.push_back(&gDeferredWaterProgram);
mShaderList.push_back(&gDeferredUnderWaterProgram);
@@ -457,8 +479,8 @@ void LLViewerShaderMgr::setShaders()
bool canRenderDeferred = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred");
bool hasWindLightShaders = LLFeatureManager::getInstance()->isFeatureAvailable("WindLightUseAtmosShaders");
S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail");
- bool useRenderDeferred = canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP");
bool doingWindLight = hasWindLightShaders && gSavedSettings.getBOOL("WindLightUseAtmosShaders");
+ bool useRenderDeferred = doingWindLight && canRenderDeferred && gSavedSettings.getBOOL("RenderDeferred") && gSavedSettings.getBOOL("RenderAvatarVP");
//using shaders, disable fixed function
LLGLSLShader::sNoFixedFunction = true;
@@ -732,8 +754,10 @@ void LLViewerShaderMgr::setShaders()
void LLViewerShaderMgr::unloadShaders()
{
gOcclusionProgram.unload();
+ gSkinnedOcclusionProgram.unload();
gOcclusionCubeProgram.unload();
gDebugProgram.unload();
+ gSkinnedDebugProgram.unload();
gClipProgram.unload();
gDownsampleDepthProgram.unload();
gDownsampleDepthRectProgram.unload();
@@ -755,58 +779,50 @@ void LLViewerShaderMgr::unloadShaders()
gObjectFullbrightNoColorProgram.unload();
gObjectFullbrightNoColorWaterProgram.unload();
gObjectSimpleProgram.unload();
+ gSkinnedObjectSimpleProgram.unload();
gObjectSimpleImpostorProgram.unload();
+ gSkinnedObjectSimpleImpostorProgram.unload();
gObjectPreviewProgram.unload();
gImpostorProgram.unload();
gObjectSimpleAlphaMaskProgram.unload();
+ gSkinnedObjectSimpleAlphaMaskProgram.unload();
gObjectBumpProgram.unload();
+ gSkinnedObjectBumpProgram.unload();
gObjectSimpleWaterProgram.unload();
+ gSkinnedObjectSimpleWaterProgram.unload();
gObjectSimpleWaterAlphaMaskProgram.unload();
+ gSkinnedObjectSimpleWaterAlphaMaskProgram.unload();
gObjectFullbrightProgram.unload();
+ gSkinnedObjectFullbrightProgram.unload();
gObjectFullbrightWaterProgram.unload();
+ gSkinnedObjectFullbrightWaterProgram.unload();
gObjectEmissiveProgram.unload();
+ gSkinnedObjectEmissiveProgram.unload();
gObjectEmissiveWaterProgram.unload();
+ gSkinnedObjectEmissiveWaterProgram.unload();
gObjectFullbrightAlphaMaskProgram.unload();
+ gSkinnedObjectFullbrightAlphaMaskProgram.unload();
gObjectFullbrightWaterAlphaMaskProgram.unload();
+ gSkinnedObjectFullbrightWaterAlphaMaskProgram.unload();
gObjectShinyProgram.unload();
+ gSkinnedObjectShinyProgram.unload();
gObjectFullbrightShinyProgram.unload();
+ gSkinnedObjectFullbrightShinyProgram.unload();
gObjectFullbrightShinyWaterProgram.unload();
+ gSkinnedObjectFullbrightShinyWaterProgram.unload();
gObjectShinyWaterProgram.unload();
+ gSkinnedObjectShinyWaterProgram.unload();
- gObjectSimpleNonIndexedProgram.unload();
gObjectSimpleNonIndexedTexGenProgram.unload();
gObjectSimpleNonIndexedTexGenWaterProgram.unload();
- gObjectSimpleNonIndexedWaterProgram.unload();
gObjectAlphaMaskNonIndexedProgram.unload();
gObjectAlphaMaskNonIndexedWaterProgram.unload();
gObjectAlphaMaskNoColorProgram.unload();
gObjectAlphaMaskNoColorWaterProgram.unload();
- gObjectFullbrightNonIndexedProgram.unload();
- gObjectFullbrightNonIndexedWaterProgram.unload();
- gObjectEmissiveNonIndexedProgram.unload();
- gObjectEmissiveNonIndexedWaterProgram.unload();
gTreeProgram.unload();
gTreeWaterProgram.unload();
- gObjectShinyNonIndexedProgram.unload();
- gObjectFullbrightShinyNonIndexedProgram.unload();
- gObjectFullbrightShinyNonIndexedWaterProgram.unload();
- gObjectShinyNonIndexedWaterProgram.unload();
-
- gSkinnedObjectSimpleProgram.unload();
- gSkinnedObjectFullbrightProgram.unload();
- gSkinnedObjectEmissiveProgram.unload();
- gSkinnedObjectFullbrightShinyProgram.unload();
- gSkinnedObjectShinySimpleProgram.unload();
-
- gSkinnedObjectSimpleWaterProgram.unload();
- gSkinnedObjectFullbrightWaterProgram.unload();
- gSkinnedObjectEmissiveWaterProgram.unload();
- gSkinnedObjectFullbrightShinyWaterProgram.unload();
- gSkinnedObjectShinySimpleWaterProgram.unload();
-
-
gWaterProgram.unload();
gWaterEdgeProgram.unload();
gUnderWaterProgram.unload();
@@ -832,13 +848,13 @@ void LLViewerShaderMgr::unloadShaders()
gDeferredDiffuseProgram.unload();
gDeferredDiffuseAlphaMaskProgram.unload();
+ gDeferredSkinnedDiffuseAlphaMaskProgram.unload();
gDeferredNonIndexedDiffuseAlphaMaskProgram.unload();
gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload();
gDeferredNonIndexedDiffuseProgram.unload();
gDeferredSkinnedDiffuseProgram.unload();
gDeferredSkinnedBumpProgram.unload();
- gDeferredSkinnedAlphaProgram.unload();
-
+
gTransformPositionProgram.unload();
gTransformTexCoordProgram.unload();
gTransformNormalProgram.unload();
@@ -915,7 +931,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()
}
shaders.push_back( make_pair( "objects/nonindexedTextureV.glsl", 1 ) );
- boost::unordered_map<std::string, std::string> attribs;
+ std::unordered_map<std::string, std::string> attribs;
attribs["MAX_JOINTS_PER_MESH_OBJECT"] =
boost::lexical_cast<std::string>(LLSkinningUtil::getMaxJointCount());
@@ -1227,14 +1243,15 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredTreeProgram.unload();
gDeferredTreeShadowProgram.unload();
+ gDeferredSkinnedTreeShadowProgram.unload();
gDeferredDiffuseProgram.unload();
gDeferredDiffuseAlphaMaskProgram.unload();
+ gDeferredSkinnedDiffuseAlphaMaskProgram.unload();
gDeferredNonIndexedDiffuseAlphaMaskProgram.unload();
gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram.unload();
gDeferredNonIndexedDiffuseProgram.unload();
gDeferredSkinnedDiffuseProgram.unload();
gDeferredSkinnedBumpProgram.unload();
- gDeferredSkinnedAlphaProgram.unload();
gDeferredBumpProgram.unload();
gDeferredImpostorProgram.unload();
gDeferredTerrainProgram.unload();
@@ -1251,9 +1268,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredSoftenProgram.unload();
gDeferredSoftenWaterProgram.unload();
gDeferredShadowProgram.unload();
+ gDeferredSkinnedShadowProgram.unload();
gDeferredShadowCubeProgram.unload();
gDeferredShadowAlphaMaskProgram.unload();
+ gDeferredSkinnedShadowAlphaMaskProgram.unload();
gDeferredShadowFullbrightAlphaMaskProgram.unload();
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.unload();
gDeferredAvatarShadowProgram.unload();
gDeferredAvatarAlphaShadowProgram.unload();
gDeferredAvatarAlphaMaskShadowProgram.unload();
@@ -1263,12 +1283,17 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarProgram.unload();
gDeferredAvatarAlphaProgram.unload();
gDeferredAlphaProgram.unload();
+ gDeferredSkinnedAlphaProgram.unload();
gDeferredAlphaWaterProgram.unload();
+ gDeferredSkinnedAlphaWaterProgram.unload();
gDeferredFullbrightProgram.unload();
gDeferredFullbrightAlphaMaskProgram.unload();
gDeferredFullbrightWaterProgram.unload();
+ gDeferredSkinnedFullbrightWaterProgram.unload();
gDeferredFullbrightAlphaMaskWaterProgram.unload();
+ gDeferredSkinnedFullbrightAlphaMaskWaterProgram.unload();
gDeferredEmissiveProgram.unload();
+ gDeferredSkinnedEmissiveProgram.unload();
gDeferredAvatarEyesProgram.unload();
gDeferredPostProgram.unload();
gDeferredCoFProgram.unload();
@@ -1283,8 +1308,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredWLMoonProgram.unload();
gDeferredStarProgram.unload();
gDeferredFullbrightShinyProgram.unload();
- gDeferredSkinnedFullbrightShinyProgram.unload();
+ gDeferredSkinnedFullbrightShinyProgram.unload();
gDeferredSkinnedFullbrightProgram.unload();
+ gDeferredSkinnedFullbrightAlphaMaskProgram.unload();
gDeferredHighlightProgram.unload();
gDeferredHighlightNormalProgram.unload();
@@ -1341,7 +1367,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredDiffuseProgram.mShaderFiles.push_back(make_pair("deferred/diffuseIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredDiffuseProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredDiffuseProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredDiffuseProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gDeferredDiffuseProgram, gDeferredSkinnedDiffuseProgram);
+ success = success && gDeferredDiffuseProgram.createShader(NULL, NULL);
}
if (success)
@@ -1353,7 +1380,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredDiffuseAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/diffuseAlphaMaskIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredDiffuseAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
gDeferredDiffuseAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gDeferredDiffuseAlphaMaskProgram, gDeferredSkinnedDiffuseAlphaMaskProgram);
+ success = success && gDeferredDiffuseAlphaMaskProgram.createShader(NULL, NULL);
}
if (success)
@@ -1395,94 +1423,14 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
- gDeferredSkinnedDiffuseProgram.mName = "Deferred Skinned Diffuse Shader";
- gDeferredSkinnedDiffuseProgram.mFeatures.hasObjectSkinning = true;
- gDeferredSkinnedDiffuseProgram.mFeatures.encodesNormal = true;
- gDeferredSkinnedDiffuseProgram.mFeatures.hasSrgb = 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 = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredSkinnedDiffuseProgram.createShader(NULL, NULL);
- llassert(success);
- }
-
- if (success)
- {
- gDeferredSkinnedBumpProgram.mName = "Deferred Skinned Bump Shader";
- gDeferredSkinnedBumpProgram.mFeatures.hasObjectSkinning = true;
- gDeferredSkinnedBumpProgram.mFeatures.encodesNormal = 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 = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredSkinnedBumpProgram.createShader(NULL, NULL);
- llassert(success);
- }
-
- if (success)
- {
- gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader";
- gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true;
- gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = false;
- gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = false;
- gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true;
- gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true;
- gDeferredSkinnedAlphaProgram.mFeatures.hasSrgb = true;
- gDeferredSkinnedAlphaProgram.mFeatures.encodesNormal = true;
- gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;
- gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true;
- gDeferredSkinnedAlphaProgram.mFeatures.hasTransport = true;
- gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;
- gDeferredSkinnedAlphaProgram.mFeatures.hasShadows = true;
-
- gDeferredSkinnedAlphaProgram.mShaderFiles.clear();
- gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
- gDeferredSkinnedAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
-
- gDeferredSkinnedAlphaProgram.clearPermutations();
- gDeferredSkinnedAlphaProgram.addPermutation("USE_DIFFUSE_TEX", "1");
- gDeferredSkinnedAlphaProgram.addPermutation("HAS_SKIN", "1");
- gDeferredSkinnedAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
-
- if (use_sun_shadow)
- {
- gDeferredSkinnedAlphaProgram.addPermutation("HAS_SHADOW", "1");
- }
-
- if (ambient_kill)
- {
- gDeferredSkinnedAlphaProgram.addPermutation("AMBIENT_KILL", "1");
- }
-
- if (sunlight_kill)
- {
- gDeferredSkinnedAlphaProgram.addPermutation("SUNLIGHT_KILL", "1");
- }
-
- if (local_light_kill)
- {
- gDeferredSkinnedAlphaProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
- }
-
- success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL);
- llassert(success);
-
- // Hack to include uniforms for lighting without linking in lighting file
- gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true;
- gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;
- }
-
- if (success)
- {
gDeferredBumpProgram.mName = "Deferred Bump Shader";
gDeferredBumpProgram.mFeatures.encodesNormal = true;
gDeferredBumpProgram.mShaderFiles.clear();
gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredBumpProgram.mShaderFiles.push_back(make_pair("deferred/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredBumpProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredBumpProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gDeferredBumpProgram, gDeferredSkinnedBumpProgram);
+ success = success && gDeferredBumpProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -1570,6 +1518,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredMaterialProgram[i].addPermutation("HAS_SKIN", "1");
gDeferredMaterialProgram[i].mFeatures.hasObjectSkinning = true;
}
+ else
+ {
+ gDeferredMaterialProgram[i].mRiggedVariant = &gDeferredMaterialProgram[i + 0x10];
+ }
success = gDeferredMaterialProgram[i].createShader(NULL, NULL);
llassert(success);
@@ -1615,6 +1567,10 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredMaterialWaterProgram[i].addPermutation("HAS_SKIN", "1");
}
+ else
+ {
+ gDeferredMaterialWaterProgram[i].mRiggedVariant = &(gDeferredMaterialWaterProgram[i + 0x10]);
+ }
gDeferredMaterialWaterProgram[i].addPermutation("WATER_FOG","1");
if (ambient_kill)
@@ -1691,10 +1647,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ gDeferredTreeShadowProgram.mRiggedVariant = &gDeferredSkinnedTreeShadowProgram;
success = gDeferredTreeShadowProgram.createShader(NULL, NULL);
llassert(success);
}
+ if (success)
+ {
+ gDeferredSkinnedTreeShadowProgram.mName = "Deferred Skinned Tree Shadow Shader";
+ gDeferredSkinnedTreeShadowProgram.mShaderFiles.clear();
+ gDeferredSkinnedTreeShadowProgram.mFeatures.isDeferred = true;
+ gDeferredSkinnedTreeShadowProgram.mFeatures.hasShadows = true;
+ gDeferredSkinnedTreeShadowProgram.mFeatures.hasObjectSkinning = true;
+ gDeferredSkinnedTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredSkinnedTreeShadowProgram.mShaderFiles.push_back(make_pair("deferred/treeShadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSkinnedTreeShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ success = gDeferredSkinnedTreeShadowProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
+
if (success)
{
gDeferredImpostorProgram.mName = "Deferred Impostor Shader";
@@ -1883,172 +1854,235 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
- gDeferredAlphaProgram.mName = "Deferred Alpha Shader";
-
- gDeferredAlphaProgram.mFeatures.calculatesLighting = false;
- gDeferredAlphaProgram.mFeatures.hasLighting = false;
- gDeferredAlphaProgram.mFeatures.isAlphaLighting = true;
- gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
- gDeferredAlphaProgram.mFeatures.hasSrgb = true;
- gDeferredAlphaProgram.mFeatures.encodesNormal = true;
- gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true;
- gDeferredAlphaProgram.mFeatures.hasAtmospherics = true;
- gDeferredAlphaProgram.mFeatures.hasGamma = true;
- gDeferredAlphaProgram.mFeatures.hasTransport = true;
- gDeferredAlphaProgram.mFeatures.hasShadows = use_sun_shadow;
-
- if (mShaderLevel[SHADER_DEFERRED] < 1)
+ for (int i = 0; i < 2 && success; ++i)
{
- gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
- }
- else
- { //shave off some texture units for shadow maps
- gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
- }
-
- 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));
-
- gDeferredAlphaProgram.clearPermutations();
- gDeferredAlphaProgram.addPermutation("USE_VERTEX_COLOR", "1");
- gDeferredAlphaProgram.addPermutation("USE_INDEXED_TEX", "1");
- if (use_sun_shadow)
- {
- gDeferredAlphaProgram.addPermutation("HAS_SHADOW", "1");
- }
+ LLGLSLShader* shader = nullptr;
+ bool rigged = i == 1;
+ if (!rigged)
+ {
+ shader = &gDeferredAlphaProgram;
+ shader->mName = "Deferred Alpha Shader";
+ shader->mRiggedVariant = &gDeferredSkinnedAlphaProgram;
+ }
+ else
+ {
+ shader = &gDeferredSkinnedAlphaProgram;
+ shader->mName = "Skinned Deferred Alpha Shader";
+ shader->mFeatures.hasObjectSkinning = true;
+ }
- if (ambient_kill)
- {
- gDeferredAlphaProgram.addPermutation("AMBIENT_KILL", "1");
- }
+ shader->mFeatures.calculatesLighting = false;
+ shader->mFeatures.hasLighting = false;
+ shader->mFeatures.isAlphaLighting = true;
+ shader->mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
+ shader->mFeatures.hasSrgb = true;
+ shader->mFeatures.encodesNormal = true;
+ shader->mFeatures.calculatesAtmospherics = true;
+ shader->mFeatures.hasAtmospherics = true;
+ shader->mFeatures.hasGamma = true;
+ shader->mFeatures.hasTransport = true;
+ shader->mFeatures.hasShadows = use_sun_shadow;
+
+ if (mShaderLevel[SHADER_DEFERRED] < 1)
+ {
+ shader->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+ }
+ else
+ { //shave off some texture units for shadow maps
+ shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
+ }
- if (sunlight_kill)
- {
- gDeferredAlphaProgram.addPermutation("SUNLIGHT_KILL", "1");
- }
+ shader->mShaderFiles.clear();
+ shader->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
+ shader->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
- if (local_light_kill)
- {
- gDeferredAlphaProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
- }
+ shader->clearPermutations();
+ shader->addPermutation("USE_VERTEX_COLOR", "1");
+ shader->addPermutation("USE_INDEXED_TEX", "1");
+ if (use_sun_shadow)
+ {
+ shader->addPermutation("HAS_SHADOW", "1");
+ }
- gDeferredAlphaProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ if (ambient_kill)
+ {
+ shader->addPermutation("AMBIENT_KILL", "1");
+ }
- success = gDeferredAlphaProgram.createShader(NULL, NULL);
- llassert(success);
+ if (sunlight_kill)
+ {
+ shader->addPermutation("SUNLIGHT_KILL", "1");
+ }
- // Hack
- gDeferredAlphaProgram.mFeatures.calculatesLighting = true;
- gDeferredAlphaProgram.mFeatures.hasLighting = true;
+ if (local_light_kill)
+ {
+ shader->addPermutation("LOCAL_LIGHT_KILL", "1");
+ }
+
+ if (rigged)
+ {
+ shader->addPermutation("HAS_SKIN", "1");
+ }
+
+ shader->mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+ success = shader->createShader(NULL, NULL);
+ llassert(success);
+
+ // Hack
+ shader->mFeatures.calculatesLighting = true;
+ shader->mFeatures.hasLighting = true;
+ }
}
if (success)
{
- gDeferredAlphaImpostorProgram.mName = "Deferred Alpha Impostor Shader";
+ LLGLSLShader* shaders[] = {
+ &gDeferredAlphaImpostorProgram,
+ &gDeferredSkinnedAlphaImpostorProgram
+ };
-// Begin Hack
- gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = false;
- gDeferredAlphaImpostorProgram.mFeatures.hasLighting = false;
+ for (int i = 0; i < 2 && success; ++i)
+ {
+ bool rigged = i == 1;
+ LLGLSLShader* shader = shaders[i];
- gDeferredAlphaImpostorProgram.mFeatures.hasSrgb = true;
- gDeferredAlphaImpostorProgram.mFeatures.isAlphaLighting = true;
- gDeferredAlphaImpostorProgram.mFeatures.encodesNormal = true;
- gDeferredAlphaImpostorProgram.mFeatures.hasShadows = use_sun_shadow;
+ shader->mName = rigged ? "Skinned Deferred Alpha Impostor Shader" : "Deferred Alpha Impostor Shader";
- if (mShaderLevel[SHADER_DEFERRED] < 1)
- {
- gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
- }
- else
- { //shave off some texture units for shadow maps
- gDeferredAlphaImpostorProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
- }
+ // Begin Hack
+ shader->mFeatures.calculatesLighting = false;
+ shader->mFeatures.hasLighting = false;
- gDeferredAlphaImpostorProgram.mShaderFiles.clear();
- gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAlphaImpostorProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ shader->mFeatures.hasSrgb = true;
+ shader->mFeatures.isAlphaLighting = true;
+ shader->mFeatures.encodesNormal = true;
+ shader->mFeatures.hasShadows = use_sun_shadow;
- gDeferredAlphaImpostorProgram.clearPermutations();
- gDeferredAlphaImpostorProgram.addPermutation("USE_INDEXED_TEX", "1");
- gDeferredAlphaImpostorProgram.addPermutation("FOR_IMPOSTOR", "1");
- gDeferredAlphaImpostorProgram.addPermutation("USE_VERTEX_COLOR", "1");
+ if (mShaderLevel[SHADER_DEFERRED] < 1)
+ {
+ shader->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+ }
+ else
+ { //shave off some texture units for shadow maps
+ shader->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
+ }
- if (use_sun_shadow)
- {
- gDeferredAlphaImpostorProgram.addPermutation("HAS_SHADOW", "1");
- }
+ shader->mShaderFiles.clear();
+ shader->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
+ shader->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+
+ shader->clearPermutations();
+ shader->addPermutation("USE_INDEXED_TEX", "1");
+ shader->addPermutation("FOR_IMPOSTOR", "1");
+ shader->addPermutation("USE_VERTEX_COLOR", "1");
+ if (rigged)
+ {
+ shader->mFeatures.hasObjectSkinning = true;
+ shader->addPermutation("HAS_SKIN", "1");
+ }
- gDeferredAlphaImpostorProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ if (use_sun_shadow)
+ {
+ shader->addPermutation("HAS_SHADOW", "1");
+ }
- success = gDeferredAlphaImpostorProgram.createShader(NULL, NULL);
- llassert(success);
+ shader->mRiggedVariant = &gDeferredSkinnedAlphaImpostorProgram;
+ shader->mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ if (!rigged)
+ {
+ shader->mRiggedVariant = shaders[1];
+ }
+ success = shader->createShader(NULL, NULL);
+ llassert(success);
-// End Hack
- gDeferredAlphaImpostorProgram.mFeatures.calculatesLighting = true;
- gDeferredAlphaImpostorProgram.mFeatures.hasLighting = true;
+ // End Hack
+ shader->mFeatures.calculatesLighting = true;
+ shader->mFeatures.hasLighting = true;
+ }
}
- if (success)
- {
- gDeferredAlphaWaterProgram.mName = "Deferred Alpha Underwater Shader";
- gDeferredAlphaWaterProgram.mFeatures.calculatesLighting = false;
- gDeferredAlphaWaterProgram.mFeatures.hasLighting = false;
- gDeferredAlphaWaterProgram.mFeatures.isAlphaLighting = true;
- gDeferredAlphaWaterProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
- gDeferredAlphaWaterProgram.mFeatures.hasWaterFog = true;
- gDeferredAlphaWaterProgram.mFeatures.hasSrgb = true;
- gDeferredAlphaWaterProgram.mFeatures.encodesNormal = true;
- gDeferredAlphaWaterProgram.mFeatures.calculatesAtmospherics = true;
- gDeferredAlphaWaterProgram.mFeatures.hasAtmospherics = true;
- gDeferredAlphaWaterProgram.mFeatures.hasGamma = true;
- gDeferredAlphaWaterProgram.mFeatures.hasTransport = true;
- gDeferredAlphaWaterProgram.mFeatures.hasShadows = use_sun_shadow;
-
- if (mShaderLevel[SHADER_DEFERRED] < 1)
- {
- gDeferredAlphaWaterProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
- }
- else
- { //shave off some texture units for shadow maps
- gDeferredAlphaWaterProgram.mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
- }
- gDeferredAlphaWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- gDeferredAlphaWaterProgram.mShaderFiles.clear();
- gDeferredAlphaWaterProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAlphaWaterProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
-
- gDeferredAlphaWaterProgram.clearPermutations();
- gDeferredAlphaWaterProgram.addPermutation("USE_INDEXED_TEX", "1");
- gDeferredAlphaWaterProgram.addPermutation("WATER_FOG", "1");
- gDeferredAlphaWaterProgram.addPermutation("USE_VERTEX_COLOR", "1");
- if (use_sun_shadow)
- {
- gDeferredAlphaWaterProgram.addPermutation("HAS_SHADOW", "1");
- }
+ if (success)
+ {
+ LLGLSLShader* shader[] = {
+ &gDeferredAlphaWaterProgram,
+ &gDeferredSkinnedAlphaWaterProgram
+ };
+
+ gDeferredAlphaWaterProgram.mRiggedVariant = &gDeferredSkinnedAlphaWaterProgram;
+
+ gDeferredAlphaWaterProgram.mName = "Deferred Alpha Underwater Shader";
+ gDeferredSkinnedAlphaWaterProgram.mName = "Deferred Skinned Alpha Underwater Shader";
- if (ambient_kill)
+ for (int i = 0; i < 2 && success; ++i)
{
- gDeferredAlphaWaterProgram.addPermutation("AMBIENT_KILL", "1");
- }
+ shader[i]->mFeatures.calculatesLighting = false;
+ shader[i]->mFeatures.hasLighting = false;
+ shader[i]->mFeatures.isAlphaLighting = true;
+ shader[i]->mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels
+ shader[i]->mFeatures.hasWaterFog = true;
+ shader[i]->mFeatures.hasSrgb = true;
+ shader[i]->mFeatures.encodesNormal = true;
+ shader[i]->mFeatures.calculatesAtmospherics = true;
+ shader[i]->mFeatures.hasAtmospherics = true;
+ shader[i]->mFeatures.hasGamma = true;
+ shader[i]->mFeatures.hasTransport = true;
+ shader[i]->mFeatures.hasShadows = use_sun_shadow;
+
+ if (mShaderLevel[SHADER_DEFERRED] < 1)
+ {
+ shader[i]->mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+ }
+ else
+ { //shave off some texture units for shadow maps
+ shader[i]->mFeatures.mIndexedTextureChannels = llmax(LLGLSLShader::sIndexedTextureChannels - 6, 1);
+ }
+ shader[i]->mShaderGroup = LLGLSLShader::SG_WATER;
+ shader[i]->mShaderFiles.clear();
+ shader[i]->mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));
+ shader[i]->mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+
+ shader[i]->clearPermutations();
+ shader[i]->addPermutation("USE_INDEXED_TEX", "1");
+ shader[i]->addPermutation("WATER_FOG", "1");
+ shader[i]->addPermutation("USE_VERTEX_COLOR", "1");
+ if (use_sun_shadow)
+ {
+ shader[i]->addPermutation("HAS_SHADOW", "1");
+ }
- if (sunlight_kill)
- {
- gDeferredAlphaWaterProgram.addPermutation("SUNLIGHT_KILL", "1");
- }
+ if (ambient_kill)
+ {
+ shader[i]->addPermutation("AMBIENT_KILL", "1");
+ }
- if (local_light_kill)
- {
- gDeferredAlphaWaterProgram.addPermutation("LOCAL_LIGHT_KILL", "1");
- }
- gDeferredAlphaWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ if (sunlight_kill)
+ {
+ shader[i]->addPermutation("SUNLIGHT_KILL", "1");
+ }
- success = gDeferredAlphaWaterProgram.createShader(NULL, NULL);
- llassert(success);
+ if (local_light_kill)
+ {
+ shader[i]->addPermutation("LOCAL_LIGHT_KILL", "1");
+ }
- // Hack
- gDeferredAlphaWaterProgram.mFeatures.calculatesLighting = true;
- gDeferredAlphaWaterProgram.mFeatures.hasLighting = true;
+ if (i == 1)
+ { // rigged variant
+ shader[i]->mFeatures.hasObjectSkinning = true;
+ shader[i]->addPermutation("HAS_SKIN", "1");
+ }
+ else
+ {
+ shader[i]->mRiggedVariant = shader[1];
+ }
+ shader[i]->mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+
+ success = shader[i]->createShader(NULL, NULL);
+ llassert(success);
+
+ // Hack
+ shader[i]->mFeatures.calculatesLighting = true;
+ shader[i]->mFeatures.hasLighting = true;
+ }
}
if (success)
@@ -2082,6 +2116,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
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));
gDeferredFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ success = make_rigged_variant(gDeferredFullbrightProgram, gDeferredSkinnedFullbrightProgram);
success = gDeferredFullbrightProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -2099,7 +2134,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredFullbrightAlphaMaskProgram.addPermutation("HAS_ALPHA_MASK","1");
gDeferredFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gDeferredFullbrightAlphaMaskProgram, gDeferredSkinnedFullbrightAlphaMaskProgram);
+ success = success && gDeferredFullbrightAlphaMaskProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -2118,10 +2154,11 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
gDeferredFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gDeferredFullbrightWaterProgram.addPermutation("WATER_FOG","1");
- success = gDeferredFullbrightWaterProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gDeferredFullbrightWaterProgram, gDeferredSkinnedFullbrightWaterProgram);
+ success = success && gDeferredFullbrightWaterProgram.createShader(NULL, NULL);
llassert(success);
}
-
+
if (success)
{
gDeferredFullbrightAlphaMaskWaterProgram.mName = "Deferred Fullbright Underwater Alpha Masking Shader";
@@ -2138,7 +2175,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightAlphaMaskWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("HAS_ALPHA_MASK","1");
gDeferredFullbrightAlphaMaskWaterProgram.addPermutation("WATER_FOG","1");
- success = gDeferredFullbrightAlphaMaskWaterProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gDeferredFullbrightAlphaMaskWaterProgram, gDeferredSkinnedFullbrightAlphaMaskWaterProgram);
+ success = success && gDeferredFullbrightAlphaMaskWaterProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -2155,43 +2193,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredFullbrightShinyProgram.createShader(NULL, NULL);
- llassert(success);
- }
-
- if (success)
- {
- gDeferredSkinnedFullbrightProgram.mName = "Skinned Fullbright Shader";
- gDeferredSkinnedFullbrightProgram.mFeatures.calculatesAtmospherics = true;
- gDeferredSkinnedFullbrightProgram.mFeatures.hasAtmospherics = true;
- gDeferredSkinnedFullbrightProgram.mFeatures.hasGamma = true;
- gDeferredSkinnedFullbrightProgram.mFeatures.hasTransport = true;
- gDeferredSkinnedFullbrightProgram.mFeatures.hasObjectSkinning = true;
- gDeferredSkinnedFullbrightProgram.mFeatures.disableTextureIndex = true;
- gDeferredSkinnedFullbrightProgram.mFeatures.hasSrgb = true;
- gDeferredSkinnedFullbrightProgram.mShaderFiles.clear();
- gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("objects/fullbrightSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSkinnedFullbrightProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
- gDeferredSkinnedFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = gDeferredSkinnedFullbrightProgram.createShader(NULL, NULL);
- llassert(success);
- }
-
- if (success)
- {
- gDeferredSkinnedFullbrightShinyProgram.mName = "Skinned Fullbright Shiny Shader";
- gDeferredSkinnedFullbrightShinyProgram.mFeatures.calculatesAtmospherics = true;
- gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasAtmospherics = true;
- gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasGamma = true;
- gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasTransport = true;
- gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasObjectSkinning = true;
- gDeferredSkinnedFullbrightShinyProgram.mFeatures.disableTextureIndex = true;
- gDeferredSkinnedFullbrightShinyProgram.mFeatures.hasSrgb = true;
- gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.clear();
- gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSkinnedFullbrightShinyProgram.mShaderFiles.push_back(make_pair("deferred/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));
- gDeferredSkinnedFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = gDeferredSkinnedFullbrightShinyProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gDeferredFullbrightShinyProgram, gDeferredSkinnedFullbrightShinyProgram);
+ success = success && gDeferredFullbrightShinyProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -2206,7 +2209,8 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredEmissiveProgram.mShaderFiles.push_back(make_pair("deferred/emissiveF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
- success = gDeferredEmissiveProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gDeferredEmissiveProgram, gDeferredSkinnedEmissiveProgram);
+ success = success && gDeferredEmissiveProgram.createShader(NULL, NULL);
llassert(success);
}
@@ -2349,10 +2353,29 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredShadowProgram.addPermutation("DEPTH_CLAMP", "1");
}
+ gDeferredShadowProgram.mRiggedVariant = &gDeferredSkinnedShadowProgram;
success = gDeferredShadowProgram.createShader(NULL, NULL);
llassert(success);
}
+ if (success)
+ {
+ gDeferredSkinnedShadowProgram.mName = "Deferred Skinned Shadow Shader";
+ gDeferredSkinnedShadowProgram.mFeatures.isDeferred = true;
+ gDeferredSkinnedShadowProgram.mFeatures.hasShadows = true;
+ gDeferredSkinnedShadowProgram.mFeatures.hasObjectSkinning = true;
+ gDeferredSkinnedShadowProgram.mShaderFiles.clear();
+ gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredSkinnedShadowProgram.mShaderFiles.push_back(make_pair("deferred/shadowF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSkinnedShadowProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ if (gGLManager.mHasDepthClamp)
+ {
+ gDeferredSkinnedShadowProgram.addPermutation("DEPTH_CLAMP", "1");
+ }
+ success = gDeferredSkinnedShadowProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
+
if (success)
{
gDeferredShadowCubeProgram.mName = "Deferred Shadow Cube Shader";
@@ -2386,11 +2409,32 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
}
gDeferredShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1");
gDeferredShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ gDeferredShadowFullbrightAlphaMaskProgram.mRiggedVariant = &gDeferredSkinnedShadowFullbrightAlphaMaskProgram;
success = gDeferredShadowFullbrightAlphaMaskProgram.createShader(NULL, NULL);
llassert(success);
}
if (success)
+ {
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mName = "Deferred Skinned Shadow Fullbright Alpha Mask Shader";
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mFeatures.hasObjectSkinning = true;
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.clear();
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
+
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.clearPermutations();
+ if (gGLManager.mHasDepthClamp)
+ {
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
+ }
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.addPermutation("IS_FULLBRIGHT", "1");
+ gDeferredSkinnedShadowFullbrightAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ success = gDeferredSkinnedShadowFullbrightAlphaMaskProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
+
+ if (success)
{
gDeferredShadowAlphaMaskProgram.mName = "Deferred Shadow Alpha Mask Shader";
gDeferredShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
@@ -2403,10 +2447,28 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
}
gDeferredShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ gDeferredShadowAlphaMaskProgram.mRiggedVariant = &gDeferredSkinnedShadowAlphaMaskProgram;
success = gDeferredShadowAlphaMaskProgram.createShader(NULL, NULL);
llassert(success);
}
+ if (success)
+ {
+ gDeferredSkinnedShadowAlphaMaskProgram.mName = "Deferred Skinned Shadow Alpha Mask Shader";
+ gDeferredSkinnedShadowAlphaMaskProgram.mFeatures.mIndexedTextureChannels = LLGLSLShader::sIndexedTextureChannels;
+ gDeferredSkinnedShadowAlphaMaskProgram.mFeatures.hasObjectSkinning = true;
+ gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.clear();
+ gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredSkinnedShadowAlphaMaskProgram.mShaderFiles.push_back(make_pair("deferred/shadowAlphaMaskF.glsl", GL_FRAGMENT_SHADER_ARB));
+ if (gGLManager.mHasDepthClamp)
+ {
+ gDeferredSkinnedShadowAlphaMaskProgram.addPermutation("DEPTH_CLAMP", "1");
+ }
+ gDeferredSkinnedShadowAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_DEFERRED];
+ success = gDeferredSkinnedShadowAlphaMaskProgram.createShader(NULL, NULL);
+ llassert(success);
+ }
+
if (success)
{
gDeferredAvatarShadowProgram.mName = "Deferred Avatar Shadow Shader";
@@ -2782,79 +2844,9 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
BOOL LLViewerShaderMgr::loadShadersObject()
{
BOOL success = TRUE;
-
- if (mShaderLevel[SHADER_OBJECT] == 0)
- {
- gObjectShinyProgram.unload();
- gObjectFullbrightShinyProgram.unload();
- gObjectFullbrightShinyWaterProgram.unload();
- gObjectShinyWaterProgram.unload();
- gObjectFullbrightNoColorProgram.unload();
- gObjectFullbrightNoColorWaterProgram.unload();
- gObjectSimpleProgram.unload();
- gObjectSimpleImpostorProgram.unload();
- gObjectPreviewProgram.unload();
- gImpostorProgram.unload();
- gObjectSimpleAlphaMaskProgram.unload();
- gObjectBumpProgram.unload();
- gObjectSimpleWaterProgram.unload();
- gObjectSimpleWaterAlphaMaskProgram.unload();
- gObjectEmissiveProgram.unload();
- gObjectEmissiveWaterProgram.unload();
- gObjectFullbrightProgram.unload();
- gObjectFullbrightAlphaMaskProgram.unload();
- gObjectFullbrightWaterProgram.unload();
- gObjectFullbrightWaterAlphaMaskProgram.unload();
- gObjectShinyNonIndexedProgram.unload();
- gObjectFullbrightShinyNonIndexedProgram.unload();
- gObjectFullbrightShinyNonIndexedWaterProgram.unload();
- gObjectShinyNonIndexedWaterProgram.unload();
- gObjectSimpleNonIndexedTexGenProgram.unload();
- gObjectSimpleNonIndexedTexGenWaterProgram.unload();
- gObjectSimpleNonIndexedWaterProgram.unload();
- gObjectAlphaMaskNonIndexedProgram.unload();
- gObjectAlphaMaskNonIndexedWaterProgram.unload();
- gObjectAlphaMaskNoColorProgram.unload();
- gObjectAlphaMaskNoColorWaterProgram.unload();
- gObjectFullbrightNonIndexedProgram.unload();
- gObjectFullbrightNonIndexedWaterProgram.unload();
- gObjectEmissiveNonIndexedProgram.unload();
- gObjectEmissiveNonIndexedWaterProgram.unload();
- gSkinnedObjectSimpleProgram.unload();
- gSkinnedObjectFullbrightProgram.unload();
- gSkinnedObjectEmissiveProgram.unload();
- gSkinnedObjectFullbrightShinyProgram.unload();
- gSkinnedObjectShinySimpleProgram.unload();
- gSkinnedObjectSimpleWaterProgram.unload();
- gSkinnedObjectFullbrightWaterProgram.unload();
- gSkinnedObjectEmissiveWaterProgram.unload();
- gSkinnedObjectFullbrightShinyWaterProgram.unload();
- gSkinnedObjectShinySimpleWaterProgram.unload();
- gTreeProgram.unload();
- gTreeWaterProgram.unload();
-
- 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.hasAlphaMask = true; // Fix for MAINT-8836
- 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 = mShaderLevel[SHADER_OBJECT];
- success = gObjectSimpleNonIndexedProgram.createShader(NULL, NULL);
- }
-
- if (success)
- {
gObjectSimpleNonIndexedTexGenProgram.mName = "Non indexed tex-gen Shader";
gObjectSimpleNonIndexedTexGenProgram.mFeatures.calculatesLighting = true;
gObjectSimpleNonIndexedTexGenProgram.mFeatures.calculatesAtmospherics = true;
@@ -2869,24 +2861,6 @@ BOOL LLViewerShaderMgr::loadShadersObject()
success = gObjectSimpleNonIndexedTexGenProgram.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 = mShaderLevel[SHADER_OBJECT];
- gObjectSimpleNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectSimpleNonIndexedWaterProgram.createShader(NULL, NULL);
- }
-
if (success)
{
gObjectSimpleNonIndexedTexGenWaterProgram.mName = "Non indexed tex-gen Water Shader";
@@ -3011,70 +2985,6 @@ BOOL LLViewerShaderMgr::loadShadersObject()
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 = mShaderLevel[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.mFeatures.hasSrgb = 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 = mShaderLevel[SHADER_OBJECT];
- gObjectFullbrightNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectFullbrightNonIndexedWaterProgram.createShader(NULL, NULL);
- }
-
- if (success)
- {
- gObjectEmissiveNonIndexedProgram.mName = "Non Indexed Emissive Shader";
- gObjectEmissiveNonIndexedProgram.mFeatures.calculatesAtmospherics = true;
- gObjectEmissiveNonIndexedProgram.mFeatures.hasGamma = true;
- gObjectEmissiveNonIndexedProgram.mFeatures.hasTransport = true;
- gObjectEmissiveNonIndexedProgram.mFeatures.isFullbright = true;
- gObjectEmissiveNonIndexedProgram.mFeatures.disableTextureIndex = true;
- gObjectEmissiveNonIndexedProgram.mFeatures.hasSrgb = true;
- gObjectEmissiveNonIndexedProgram.mShaderFiles.clear();
- gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectEmissiveNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
- gObjectEmissiveNonIndexedProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = gObjectEmissiveNonIndexedProgram.createShader(NULL, NULL);
- }
-
- if (success)
- {
- gObjectEmissiveNonIndexedWaterProgram.mName = "Non Indexed Emissive Water Shader";
- gObjectEmissiveNonIndexedWaterProgram.mFeatures.calculatesAtmospherics = true;
- gObjectEmissiveNonIndexedWaterProgram.mFeatures.isFullbright = true;
- gObjectEmissiveNonIndexedWaterProgram.mFeatures.hasWaterFog = true;
- gObjectEmissiveNonIndexedWaterProgram.mFeatures.hasTransport = true;
- gObjectEmissiveNonIndexedWaterProgram.mFeatures.disableTextureIndex = true;
- gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.clear();
- gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
- gObjectEmissiveNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
- gObjectEmissiveNonIndexedWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- gObjectEmissiveNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectEmissiveNonIndexedWaterProgram.createShader(NULL, NULL);
- }
-
- if (success)
- {
gObjectFullbrightNoColorProgram.mName = "Non Indexed no color Fullbright Shader";
gObjectFullbrightNoColorProgram.mFeatures.calculatesAtmospherics = true;
gObjectFullbrightNoColorProgram.mFeatures.hasGamma = true;
@@ -3107,73 +3017,6 @@ BOOL LLViewerShaderMgr::loadShadersObject()
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 = mShaderLevel[SHADER_OBJECT];
- success = gObjectShinyNonIndexedProgram.createShader(NULL, NULL);
- }
-
- 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 = mShaderLevel[SHADER_OBJECT];
- gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, NULL);
- }
-
- 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 = mShaderLevel[SHADER_OBJECT];
- success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, NULL);
- }
-
- 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 = mShaderLevel[SHADER_OBJECT];
- gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, NULL);
- }
-
- if (success)
- {
gImpostorProgram.mName = "Impostor Shader";
gImpostorProgram.mFeatures.disableTextureIndex = true;
gImpostorProgram.mFeatures.hasSrgb = true;
@@ -3215,7 +3058,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
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 = mShaderLevel[SHADER_OBJECT];
- success = gObjectSimpleProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectSimpleProgram, gSkinnedObjectSimpleProgram);
+ success = success && gObjectSimpleProgram.createShader(NULL, NULL);
}
if (success)
@@ -3235,8 +3079,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleV.glsl", GL_VERTEX_SHADER_ARB));
gObjectSimpleImpostorProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB));
gObjectSimpleImpostorProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
-
- success = gObjectSimpleImpostorProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectSimpleImpostorProgram, gSkinnedObjectSimpleImpostorProgram);
+ success = success && gObjectSimpleImpostorProgram.createShader(NULL, NULL);
}
if (success)
@@ -3253,30 +3097,30 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gObjectSimpleWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectSimpleWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
+ make_rigged_variant(gObjectSimpleWaterProgram, gSkinnedObjectSimpleWaterProgram);
success = gObjectSimpleWaterProgram.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.mFeatures.encodesNormal = true;
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 = mShaderLevel[SHADER_OBJECT];
- success = gObjectBumpProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectBumpProgram, gSkinnedObjectBumpProgram);
+ success = success && gObjectBumpProgram.createShader(NULL, NULL);
if (success)
{ //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1
- gObjectBumpProgram.bind();
- gObjectBumpProgram.uniform1i(sTexture0, 0);
- gObjectBumpProgram.uniform1i(sTexture1, 1);
- gObjectBumpProgram.unbind();
+ LLGLSLShader* shader[] = { &gObjectBumpProgram, &gSkinnedObjectBumpProgram };
+ for (int i = 0; i < 2; ++i)
+ {
+ shader[i]->bind();
+ shader[i]->uniform1i(sTexture0, 0);
+ shader[i]->uniform1i(sTexture1, 1);
+ shader[i]->unbind();
+ }
}
}
@@ -3295,7 +3139,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
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 = mShaderLevel[SHADER_OBJECT];
- success = gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectSimpleAlphaMaskProgram, gSkinnedObjectSimpleAlphaMaskProgram);
+ success = success && gObjectSimpleAlphaMaskProgram.createShader(NULL, NULL);
}
if (success)
@@ -3313,7 +3158,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectSimpleWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/simpleWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gObjectSimpleWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectSimpleWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectSimpleWaterAlphaMaskProgram, gSkinnedObjectSimpleWaterAlphaMaskProgram);
+ success = success && gObjectSimpleWaterAlphaMaskProgram.createShader(NULL, NULL);
}
if (success)
@@ -3329,7 +3175,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
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));
gObjectFullbrightProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = gObjectFullbrightProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectFullbrightProgram, gSkinnedObjectFullbrightProgram);
+ success = success && gObjectFullbrightProgram.createShader(NULL, NULL);
}
if (success)
@@ -3337,7 +3184,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightWaterProgram.mName = "Fullbright Water Shader";
gObjectFullbrightWaterProgram.mFeatures.calculatesAtmospherics = true;
gObjectFullbrightWaterProgram.mFeatures.isFullbright = true;
- gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true;
+ gObjectFullbrightWaterProgram.mFeatures.hasWaterFog = true;
gObjectFullbrightWaterProgram.mFeatures.hasTransport = true;
gObjectFullbrightWaterProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectFullbrightWaterProgram.mShaderFiles.clear();
@@ -3345,7 +3192,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gObjectFullbrightWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectFullbrightWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectFullbrightWaterProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectFullbrightWaterProgram, gSkinnedObjectFullbrightWaterProgram);
+ success = success && gObjectFullbrightWaterProgram.createShader(NULL, NULL);
}
if (success)
@@ -3361,7 +3209,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveV.glsl", GL_VERTEX_SHADER_ARB));
gObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
gObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = gObjectEmissiveProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectEmissiveProgram, gSkinnedObjectEmissiveProgram);
+ success = success && gObjectEmissiveProgram.createShader(NULL, NULL);
}
if (success)
@@ -3377,7 +3226,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectEmissiveWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectEmissiveWaterProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectEmissiveWaterProgram, gSkinnedObjectEmissiveWaterProgram);
+ success = success && gObjectEmissiveWaterProgram.createShader(NULL, NULL);
}
if (success)
@@ -3394,12 +3244,13 @@ BOOL LLViewerShaderMgr::loadShadersObject()
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 = mShaderLevel[SHADER_OBJECT];
- success = gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectFullbrightAlphaMaskProgram, gSkinnedObjectFullbrightAlphaMaskProgram);
+ success = success && gObjectFullbrightAlphaMaskProgram.createShader(NULL, NULL);
}
if (success)
{
- gObjectFullbrightWaterAlphaMaskProgram.mName = "Fullbright Water Shader";
+ gObjectFullbrightWaterAlphaMaskProgram.mName = "Fullbright Water Alpha Mask Shader";
gObjectFullbrightWaterAlphaMaskProgram.mFeatures.calculatesAtmospherics = true;
gObjectFullbrightWaterAlphaMaskProgram.mFeatures.isFullbright = true;
gObjectFullbrightWaterAlphaMaskProgram.mFeatures.hasWaterFog = true;
@@ -3411,7 +3262,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightWaterAlphaMaskProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gObjectFullbrightWaterAlphaMaskProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectFullbrightWaterAlphaMaskProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectFullbrightWaterAlphaMaskProgram, gSkinnedObjectFullbrightWaterAlphaMaskProgram);
+ success = success && gObjectFullbrightWaterAlphaMaskProgram.createShader(NULL, NULL);
}
if (success)
@@ -3427,7 +3279,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
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));
gObjectShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = gObjectShinyProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectShinyProgram, gSkinnedObjectShinyProgram);
+ success = success && gObjectShinyProgram.createShader(NULL, NULL);
}
if (success)
@@ -3444,7 +3297,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));
gObjectShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectShinyWaterProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectShinyWaterProgram, gSkinnedObjectShinyWaterProgram);
+ success = success && gObjectShinyWaterProgram.createShader(NULL, NULL);
}
if (success)
@@ -3460,7 +3314,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
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));
gObjectFullbrightShinyProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = gObjectFullbrightShinyProgram.createShader(NULL, NULL);
+ success = make_rigged_variant(gObjectFullbrightShinyProgram, gSkinnedObjectFullbrightShinyProgram);
+ success = success && gObjectFullbrightShinyProgram.createShader(NULL, NULL);
}
if (success)
@@ -3478,196 +3333,8 @@ BOOL LLViewerShaderMgr::loadShadersObject()
gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
gObjectFullbrightShinyWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;
- success = gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);
- }
-
- if (mShaderLevel[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.hasAlphaMask = 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 = mShaderLevel[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.hasAlphaMask = true;
- gSkinnedObjectFullbrightProgram.mFeatures.disableTextureIndex = true;
- gSkinnedObjectFullbrightProgram.mFeatures.hasSrgb = 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 = mShaderLevel[SHADER_OBJECT];
- success = gSkinnedObjectFullbrightProgram.createShader(NULL, NULL);
- }
-
- if (success)
- {
- gSkinnedObjectEmissiveProgram.mName = "Skinned Emissive Shader";
- gSkinnedObjectEmissiveProgram.mFeatures.calculatesAtmospherics = true;
- gSkinnedObjectEmissiveProgram.mFeatures.hasGamma = true;
- gSkinnedObjectEmissiveProgram.mFeatures.hasTransport = true;
- gSkinnedObjectEmissiveProgram.mFeatures.isFullbright = true;
- gSkinnedObjectEmissiveProgram.mFeatures.hasObjectSkinning = true;
- gSkinnedObjectEmissiveProgram.mFeatures.disableTextureIndex = true;
- gSkinnedObjectEmissiveProgram.mFeatures.hasSrgb = true;
- gSkinnedObjectEmissiveProgram.mShaderFiles.clear();
- gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
- gSkinnedObjectEmissiveProgram.mShaderFiles.push_back(make_pair("objects/fullbrightF.glsl", GL_FRAGMENT_SHADER_ARB));
- gSkinnedObjectEmissiveProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = gSkinnedObjectEmissiveProgram.createShader(NULL, NULL);
- }
-
- if (success)
- {
- gSkinnedObjectEmissiveWaterProgram.mName = "Skinned Emissive Water Shader";
- gSkinnedObjectEmissiveWaterProgram.mFeatures.calculatesAtmospherics = true;
- gSkinnedObjectEmissiveWaterProgram.mFeatures.hasGamma = true;
- gSkinnedObjectEmissiveWaterProgram.mFeatures.hasTransport = true;
- gSkinnedObjectEmissiveWaterProgram.mFeatures.isFullbright = true;
- gSkinnedObjectEmissiveWaterProgram.mFeatures.hasObjectSkinning = true;
- gSkinnedObjectEmissiveWaterProgram.mFeatures.disableTextureIndex = true;
- gSkinnedObjectEmissiveWaterProgram.mFeatures.hasWaterFog = true;
- gSkinnedObjectEmissiveWaterProgram.mShaderFiles.clear();
- gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/emissiveSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
- gSkinnedObjectEmissiveWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightWaterF.glsl", GL_FRAGMENT_SHADER_ARB));
- gSkinnedObjectEmissiveWaterProgram.mShaderLevel = mShaderLevel[SHADER_OBJECT];
- success = gSkinnedObjectEmissiveWaterProgram.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.hasAlphaMask = 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 = mShaderLevel[SHADER_OBJECT];
- success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, NULL);
- }
-
- 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.hasAlphaMask = 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 = mShaderLevel[SHADER_OBJECT];
- success = gSkinnedObjectShinySimpleProgram.createShader(NULL, NULL);
- }
-
- 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.mFeatures.hasAlphaMask = 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 = mShaderLevel[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.hasAlphaMask = 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 = mShaderLevel[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.hasAlphaMask = 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 = mShaderLevel[SHADER_OBJECT];
- success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);
- }
-
- 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.hasAlphaMask = 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 = mShaderLevel[SHADER_OBJECT];
- success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, NULL);
- }
+ success = make_rigged_variant(gObjectFullbrightShinyWaterProgram, gSkinnedObjectFullbrightShinyWaterProgram);
+ success = success && gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);
}
if( !success )
@@ -3995,9 +3662,21 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
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 = mShaderLevel[SHADER_INTERFACE];
+ gOcclusionProgram.mRiggedVariant = &gSkinnedOcclusionProgram;
success = gOcclusionProgram.createShader(NULL, NULL);
}
+ if (success)
+ {
+ gSkinnedOcclusionProgram.mName = "Skinned Occlusion Shader";
+ gSkinnedOcclusionProgram.mFeatures.hasObjectSkinning = true;
+ gSkinnedOcclusionProgram.mShaderFiles.clear();
+ gSkinnedOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
+ gSkinnedOcclusionProgram.mShaderFiles.push_back(make_pair("interface/occlusionF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gSkinnedOcclusionProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gSkinnedOcclusionProgram.createShader(NULL, NULL);
+ }
+
if (success)
{
gOcclusionCubeProgram.mName = "Occlusion Cube Shader";
@@ -4014,10 +3693,22 @@ BOOL LLViewerShaderMgr::loadShadersInterface()
gDebugProgram.mShaderFiles.clear();
gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugV.glsl", GL_VERTEX_SHADER_ARB));
gDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDebugProgram.mRiggedVariant = &gSkinnedDebugProgram;
gDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
success = gDebugProgram.createShader(NULL, NULL);
}
+ if (success)
+ {
+ gSkinnedDebugProgram.mName = "Skinned Debug Shader";
+ gSkinnedDebugProgram.mFeatures.hasObjectSkinning = true;
+ gSkinnedDebugProgram.mShaderFiles.clear();
+ gSkinnedDebugProgram.mShaderFiles.push_back(make_pair("interface/debugSkinnedV.glsl", GL_VERTEX_SHADER_ARB));
+ gSkinnedDebugProgram.mShaderFiles.push_back(make_pair("interface/debugF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gSkinnedDebugProgram.mShaderLevel = mShaderLevel[SHADER_INTERFACE];
+ success = gSkinnedDebugProgram.createShader(NULL, NULL);
+ }
+
if (success)
{
gClipProgram.mName = "Clip Shader";
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 081221f15b..297cfb6e68 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -184,10 +184,8 @@ extern LLGLSLShader gObjectPreviewProgram;
extern LLGLSLShader gObjectSimpleAlphaMaskProgram;
extern LLGLSLShader gObjectSimpleWaterProgram;
extern LLGLSLShader gObjectSimpleWaterAlphaMaskProgram;
-extern LLGLSLShader gObjectSimpleNonIndexedProgram;
extern LLGLSLShader gObjectSimpleNonIndexedTexGenProgram;
extern LLGLSLShader gObjectSimpleNonIndexedTexGenWaterProgram;
-extern LLGLSLShader gObjectSimpleNonIndexedWaterProgram;
extern LLGLSLShader gObjectAlphaMaskNonIndexedProgram;
extern LLGLSLShader gObjectAlphaMaskNonIndexedWaterProgram;
extern LLGLSLShader gObjectAlphaMaskNoColorProgram;
@@ -200,8 +198,6 @@ extern LLGLSLShader gObjectEmissiveProgram;
extern LLGLSLShader gObjectEmissiveWaterProgram;
extern LLGLSLShader gObjectFullbrightAlphaMaskProgram;
extern LLGLSLShader gObjectFullbrightWaterAlphaMaskProgram;
-extern LLGLSLShader gObjectFullbrightNonIndexedProgram;
-extern LLGLSLShader gObjectFullbrightNonIndexedWaterProgram;
extern LLGLSLShader gObjectEmissiveNonIndexedProgram;
extern LLGLSLShader gObjectEmissiveNonIndexedWaterProgram;
extern LLGLSLShader gObjectBumpProgram;
@@ -213,25 +209,9 @@ 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;
-
-extern LLGLSLShader gSkinnedObjectSimpleProgram;
-extern LLGLSLShader gSkinnedObjectFullbrightProgram;
-extern LLGLSLShader gSkinnedObjectEmissiveProgram;
-extern LLGLSLShader gSkinnedObjectFullbrightShinyProgram;
-extern LLGLSLShader gSkinnedObjectShinySimpleProgram;
-
-extern LLGLSLShader gSkinnedObjectSimpleWaterProgram;
-extern LLGLSLShader gSkinnedObjectFullbrightWaterProgram;
-extern LLGLSLShader gSkinnedObjectEmissiveWaterProgram;
-extern LLGLSLShader gSkinnedObjectFullbrightShinyWaterProgram;
-extern LLGLSLShader gSkinnedObjectShinySimpleWaterProgram;
//environment shaders
extern LLGLSLShader gTerrainProgram;
@@ -281,9 +261,6 @@ extern LLGLSLShader gDeferredDiffuseAlphaMaskProgram;
extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskProgram;
extern LLGLSLShader gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram;
extern LLGLSLShader gDeferredNonIndexedDiffuseProgram;
-extern LLGLSLShader gDeferredSkinnedDiffuseProgram;
-extern LLGLSLShader gDeferredSkinnedBumpProgram;
-extern LLGLSLShader gDeferredSkinnedAlphaProgram;
extern LLGLSLShader gDeferredBumpProgram;
extern LLGLSLShader gDeferredTerrainProgram;
extern LLGLSLShader gDeferredTerrainWaterProgram;
@@ -330,8 +307,6 @@ extern LLGLSLShader gDeferredWLSunProgram;
extern LLGLSLShader gDeferredWLMoonProgram;
extern LLGLSLShader gDeferredStarProgram;
extern LLGLSLShader gDeferredFullbrightShinyProgram;
-extern LLGLSLShader gDeferredSkinnedFullbrightShinyProgram;
-extern LLGLSLShader gDeferredSkinnedFullbrightProgram;
extern LLGLSLShader gNormalMapGenProgram;
// Deferred materials shaders
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 498e4ef8bc..e6ac701644 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -679,9 +679,6 @@ void LLViewerTexture::init(bool firstinit)
mVolumeList[LLRender::LIGHT_TEX].clear();
mVolumeList[LLRender::SCULPT_TEX].clear();
-
- mMainQueue = LL::WorkQueue::getInstance("mainloop");
- mImageQueue = LL::WorkQueue::getInstance("LLImageGL");
}
//virtual
@@ -1625,26 +1622,17 @@ void LLViewerFetchedTexture::scheduleCreateTexture()
{
mNeedsCreateTexture = TRUE;
#if LL_WINDOWS //flip to 0 to revert to single-threaded OpenGL texture uploads
- auto mainq = mMainQueue.lock();
- if (mainq)
- {
- mainq->postTo(
- mImageQueue,
- // work to be done on LLImageGL worker thread
- [this]()
- {
- //actually create the texture on a background thread
- createTexture();
- },
- // callback to be run on main thread
- [this]()
- {
- //finalize on main thread
- postCreateTexture();
- unref();
- });
- }
- else
+ if (!LLImageGLThread::sInstance->post([this]()
+ {
+ //actually create the texture on a background thread
+ createTexture();
+ LLImageGLThread::sInstance->postCallback([this]()
+ {
+ //finalize on main thread
+ postCreateTexture();
+ unref();
+ });
+ }))
#endif
{
gTextureList.mCreateTextureList.insert(this);
@@ -3598,11 +3586,22 @@ BOOL LLViewerMediaTexture::findFaces()
for(; iter != obj_list->end(); ++iter)
{
LLVOVolume* obj = *iter;
- if(obj->mDrawable.isNull())
- {
- ret = FALSE;
- continue;
- }
+ if (obj->isDead())
+ {
+ // Isn't supposed to happen, objects are supposed to detach
+ // themselves on markDead()
+ // If this happens, viewer is likely to crash
+ llassert(0);
+ LL_WARNS() << "Dead object in mMediaImplp's object list" << LL_ENDL;
+ ret = FALSE;
+ continue;
+ }
+
+ if (obj->mDrawable.isNull() || obj->mDrawable->isDead())
+ {
+ ret = FALSE;
+ continue;
+ }
S32 face_id = -1;
S32 num_faces = obj->mDrawable->getNumFaces();
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 4cd4c7cd39..f9f1bfef44 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -35,7 +35,6 @@
#include "llrender.h"
#include "llmetricperformancetester.h"
#include "httpcommon.h"
-#include "workqueue.h"
#include <map>
#include <list>
@@ -214,9 +213,6 @@ protected:
//do not use LLPointer here.
LLViewerMediaTexture* mParcelMedia ;
- LL::WorkQueue::weak_t mMainQueue;
- LL::WorkQueue::weak_t mImageQueue;
-
static F32 sTexelPixelRatio;
public:
static const U32 sCurrentFileVersion;
diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp
index 9c4dfd1ca2..c80cf27bda 100644
--- a/indra/newview/llviewerwearable.cpp
+++ b/indra/newview/llviewerwearable.cpp
@@ -562,7 +562,7 @@ void LLViewerWearable::saveNewAsset() const
void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userdata, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)
{
LLWearableSaveData* data = (LLWearableSaveData*)userdata;
- const std::string& type_name = LLWearableType::getTypeName(data->mType);
+ const std::string& type_name = LLWearableType::getInstance()->getTypeName(data->mType);
if(0 == status)
{
// Success
@@ -588,7 +588,7 @@ void LLViewerWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void*
std::ostream& operator<<(std::ostream &s, const LLViewerWearable &w)
{
- s << "wearable " << LLWearableType::getTypeName(w.mType) << "\n";
+ s << "wearable " << LLWearableType::getInstance()->getTypeName(w.mType) << "\n";
s << " Name: " << w.mName << "\n";
s << " Desc: " << w.mDescription << "\n";
//w.mPermissions
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index a35ad55cf7..198007aaa1 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -54,7 +54,6 @@
#include "llslurl.h"
#include "llrender.h"
-#include "llvoiceclient.h" // for push-to-talk button handling
#include "stringize.h"
//
@@ -1057,6 +1056,9 @@ BOOL LLViewerWindow::handleAnyMouseClick(LLWindow *window, LLCoordGL pos, MASK m
x = ll_round((F32)x / mDisplayScale.mV[VX]);
y = ll_round((F32)y / mDisplayScale.mV[VY]);
+ // Handle non-consuming global keybindings, like voice
+ gViewerInput.handleGlobalBindsMouse(clicktype, mask, down);
+
// only send mouse clicks to UI if UI is visible
if(gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
{
@@ -1584,6 +1586,10 @@ void LLViewerWindow::handleFocusLost(LLWindow *window)
BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated)
{
+ // Handle non-consuming global keybindings, like voice
+ // Never affects event processing.
+ gViewerInput.handleGlobalBindsKeyDown(key, mask);
+
if (gAwayTimer.getElapsedTimeF32() > LLAgent::MIN_AFK_TIME)
{
gAgent.clearAFK();
@@ -1608,6 +1614,10 @@ BOOL LLViewerWindow::handleTranslatedKeyDown(KEY key, MASK mask, BOOL repeated)
BOOL LLViewerWindow::handleTranslatedKeyUp(KEY key, MASK mask)
{
+ // Handle non-consuming global keybindings, like voice
+ // Never affects event processing.
+ gViewerInput.handleGlobalBindsKeyUp(key, mask);
+
// Let the inspect tool code check for ALT key to set LLToolSelectRect active instead LLToolCamera
LLToolCompInspect * tool_inspectp = LLToolCompInspect::getInstance();
if (LLToolMgr::getInstance()->getCurrentTool() == tool_inspectp)
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 04356e6507..84bb67a03d 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -111,6 +111,7 @@
#include "llsdserialize.h"
#include "llcallstack.h"
#include "llrendersphere.h"
+#include "llskinningutil.h"
#include <boost/lexical_cast.hpp>
@@ -8976,7 +8977,7 @@ void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value)
S32 u8_value = F32_to_U8(value,viewer_param->getMinWeight(),viewer_param->getMaxWeight());
apr_file_printf(file, "\t\t<param id=\"%d\" name=\"%s\" display=\"%s\" value=\"%.3f\" u8=\"%d\" type=\"%s\" wearable=\"%s\" group=\"%d\"/>\n",
viewer_param->getID(), viewer_param->getName().c_str(), viewer_param->getDisplayName().c_str(), value, u8_value, type_string.c_str(),
- LLWearableType::getTypeName(LLWearableType::EType(wtype)).c_str(),
+ LLWearableType::getInstance()->getTypeName(LLWearableType::EType(wtype)).c_str(),
viewer_param->getGroup());
}
@@ -9445,6 +9446,54 @@ LLViewerTexture* LLVOAvatar::getBakedTexture(const U8 te)
}
+const LLVOAvatar::MatrixPaletteCache& LLVOAvatar::updateSkinInfoMatrixPalette(const LLMeshSkinInfo* skin, LLVOVolume* requesting_obj)
+{
+ U64 hash = skin->mHash;
+ MatrixPaletteCache& entry = mMatrixPaletteCache[hash];
+
+ if (entry.mFrame != gFrameCount)
+ {
+ LL_PROFILE_ZONE_SCOPED;
+
+ entry.mFrame = gFrameCount;
+
+ //build matrix palette
+ U32 count = LLSkinningUtil::getMeshJointCount(skin);
+ entry.mMatrixPalette.resize(count);
+ LLSkinningUtil::initSkinningMatrixPalette(&(entry.mMatrixPalette[0]), count, skin, this);
+
+ const LLMatrix4a* mat = &(entry.mMatrixPalette[0]);
+
+ entry.mGLMp.resize(count * 12);
+
+ F32* mp = &(entry.mGLMp[0]);
+
+ for (U32 i = 0; i < count; ++i)
+ {
+ F32* m = (F32*)mat[i].mMatrix[0].getF32ptr();
+
+ U32 idx = i * 12;
+
+ mp[idx + 0] = m[0];
+ mp[idx + 1] = m[1];
+ mp[idx + 2] = m[2];
+ mp[idx + 3] = m[12];
+
+ mp[idx + 4] = m[4];
+ mp[idx + 5] = m[5];
+ mp[idx + 6] = m[6];
+ mp[idx + 7] = m[13];
+
+ mp[idx + 8] = m[8];
+ mp[idx + 9] = m[9];
+ mp[idx + 10] = m[10];
+ mp[idx + 11] = m[14];
+ }
+ }
+
+ return entry;
+}
+
// static
void LLVOAvatar::getAnimLabels( std::vector<std::string>* labels )
{
@@ -9754,6 +9803,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara
std::string outfilename = get_sequential_numbered_file_name(outprefix,".xml");
LLAPRFile outfile;
+ LLWearableType *wr_inst = LLWearableType::getInstance();
std::string fullpath = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,outfilename);
if (APR_SUCCESS == outfile.open(fullpath, LL_APR_WB ))
{
@@ -9770,7 +9820,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara
{
for (S32 type = LLWearableType::WT_SHAPE; type < LLWearableType::WT_COUNT; type++)
{
- const std::string& wearable_name = LLWearableType::getTypeName((LLWearableType::EType)type);
+ const std::string& wearable_name = wr_inst->getTypeName((LLWearableType::EType)type);
apr_file_printf( file, "\n\t\t<!-- wearable: %s -->\n", wearable_name.c_str() );
for (LLVisualParam* param = getFirstVisualParam(); param; param = getNextVisualParam())
diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h
index aeac23ad92..b85400866e 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -53,6 +53,8 @@
#include "llviewerstats.h"
#include "llvovolume.h"
#include "llavatarrendernotifier.h"
+#include "llmodel.h"
+
extern const LLUUID ANIM_AGENT_BODY_NOISE;
extern const LLUUID ANIM_AGENT_BREATHE_ROT;
@@ -77,6 +79,7 @@ class LLViewerJointMesh;
const F32 MAX_AVATAR_LOD_FACTOR = 1.0f;
+extern U32 gFrameCount;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLVOAvatar
@@ -746,6 +749,26 @@ public:
void updateMeshVisibility();
LLViewerTexture* getBakedTexture(const U8 te);
+ class alignas(16) MatrixPaletteCache
+ {
+ public:
+ U32 mFrame;
+ LLMeshSkinInfo::matrix_list_t mMatrixPalette;
+
+ // Float array ready to be sent to GL
+ std::vector<F32> mGLMp;
+
+ MatrixPaletteCache() :
+ mFrame(gFrameCount - 1)
+ {
+ }
+ };
+
+ const MatrixPaletteCache& updateSkinInfoMatrixPalette(const LLMeshSkinInfo* skinInfo, LLVOVolume* requesting_obj = nullptr);
+
+ typedef std::unordered_map<U64, MatrixPaletteCache> matrix_palette_cache_t;
+ matrix_palette_cache_t mMatrixPaletteCache;
+
protected:
void releaseMeshData();
virtual void restoreMeshData();
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 7faca2ee5b..60a69a4ac4 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -2036,6 +2036,7 @@ void LLVOAvatarSelf::debugBakedTextureUpload(EBakedTextureIndex index, BOOL fini
const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const
{
std::ostringstream outbuf;
+ LLWearableType *wr_inst = LLWearableType::getInstance();
for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter =
sAvatarDictionary->getBakedTextures().begin();
baked_iter != sAvatarDictionary->getBakedTextures().end();
@@ -2059,7 +2060,7 @@ const std::string LLVOAvatarSelf::verboseDebugDumpLocalTextureDataInfo(const LLV
{
for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)
{
- outbuf << " " << LLWearableType::getTypeName(wearable_type) << " " << wearable_index << ":";
+ outbuf << " " << wr_inst->getTypeName(wearable_type) << " " << wearable_index << ":";
const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(tex_index, wearable_index);
if (local_tex_obj)
{
@@ -2114,6 +2115,7 @@ void LLVOAvatarSelf::dumpAllTextures() const
const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTexLayerSet* layerset) const
{
std::string text="";
+ LLWearableType *wr_inst = LLWearableType::getInstance();
text = llformat("[Final:%d Avail:%d] ",isLocalTextureDataFinal(layerset), isLocalTextureDataAvailable(layerset));
@@ -2137,7 +2139,7 @@ const std::string LLVOAvatarSelf::debugDumpLocalTextureDataInfo(const LLViewerTe
const U32 wearable_count = gAgentWearables.getWearableCount(wearable_type);
if (wearable_count > 0)
{
- text += LLWearableType::getTypeName(wearable_type) + ":";
+ text += wr_inst->getTypeName(wearable_type) + ":";
for (U32 wearable_index = 0; wearable_index < wearable_count; wearable_index++)
{
const U32 discard_level = getLocalDiscardLevel(tex_index, wearable_index);
@@ -2844,9 +2846,10 @@ void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile)
apr_file_printf( file, "\n<wearable_info>\n" );
LLWearableData *wd = getWearableData();
+ LLWearableType *wr_inst = LLWearableType::getInstance();
for (S32 type = 0; type < LLWearableType::WT_COUNT; type++)
{
- const std::string& type_name = LLWearableType::getTypeName((LLWearableType::EType)type);
+ const std::string& type_name = wr_inst->getTypeName((LLWearableType::EType)type);
for (U32 j=0; j< wd->getWearableCount((LLWearableType::EType)type); j++)
{
LLViewerWearable *wearable = gAgentWearables.getViewerWearable((LLWearableType::EType)type,j);
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 86fe7c19bd..3d503638e0 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -400,6 +400,11 @@ void LLVivoxVoiceClient::init(LLPumpIO *pump)
void LLVivoxVoiceClient::terminate()
{
+ if (sShuttingDown)
+ {
+ return;
+ }
+
// needs to be done manually here since we will not get another pass in
// coroutines... that mechanism is long since gone.
if (mIsLoggedIn)
@@ -658,120 +663,205 @@ void LLVivoxVoiceClient::idle(void* user_data)
// of a coroutine.
//
//
+
+typedef enum e_voice_control_coro_state
+{
+ VOICE_STATE_ERROR = -1,
+ VOICE_STATE_DONE = 0,
+ VOICE_STATE_TP_WAIT, // entry point
+ VOICE_STATE_START_DAEMON,
+ VOICE_STATE_PROVISION_ACCOUNT,
+ VOICE_STATE_START_SESSION,
+ VOICE_STATE_SESSION_RETRY,
+ VOICE_STATE_SESSION_ESTABLISHED,
+ VOICE_STATE_WAIT_FOR_CHANNEL,
+ VOICE_STATE_DISCONNECT,
+ VOICE_STATE_WAIT_FOR_EXIT,
+} EVoiceControlCoroState;
+
void LLVivoxVoiceClient::voiceControlCoro()
{
+ int state = 0;
+ try
+ {
+ // state is passed as a reference instead of being
+ // a member due to unresolved issues with coroutine
+ // surviving longer than LLVivoxVoiceClient
+ voiceControlStateMachine(state);
+ }
+ catch (const LLContinueError&)
+ {
+ LOG_UNHANDLED_EXCEPTION("LLVivoxVoiceClient");
+ }
+ catch (...)
+ {
+ // Ideally for Windows need to log SEH exception instead or to set SEH
+ // handlers but bugsplat shows local variables for windows, which should
+ // be enough
+ LL_WARNS("Voice") << "voiceControlStateMachine crashed in state " << state << LL_ENDL;
+ throw;
+ }
+}
+
+void LLVivoxVoiceClient::voiceControlStateMachine(S32 &coro_state)
+{
LL_DEBUGS("Voice") << "starting" << LL_ENDL;
mIsCoroutineActive = true;
LLCoros::set_consuming(true);
U32 retry = 0;
- while (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE && !sShuttingDown)
- {
- LL_DEBUGS("Voice") << "Suspending voiceControlCoro() momentarily for teleport. Tuning: " << mTuningMode << ". Relog: " << mRelogRequested << LL_ENDL;
- llcoro::suspendUntilTimeout(1.0);
- }
-
- if (sShuttingDown)
- {
- mIsCoroutineActive = false;
- return;
- }
+ coro_state = VOICE_STATE_TP_WAIT;
do
{
- bool success = startAndConnectSession();
- if (success)
+ if (sShuttingDown)
{
- // enable/disable the automatic VAD and explicitly set the initial values of
- // the VAD variables ourselves when it is off - see SL-15072 for more details
- // note: we set the other parameters too even if the auto VAD is on which is ok
- unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
- unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
- unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
- unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
- setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
-
- // watch for changes to the VAD settings via Debug Settings UI and act on them accordingly
- gSavedSettings.getControl("VivoxVadAuto")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
- gSavedSettings.getControl("VivoxVadHangover")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
- gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
- gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+ // Vivox singleton performed the exit, logged out,
+ // cleaned sockets, gateway and no longer cares
+ // about state of coroutine, so just stop
+ return;
+ }
- if (mTuningMode && !sShuttingDown)
+ switch (coro_state)
+ {
+ case VOICE_STATE_TP_WAIT:
+ // starting point for voice
+ if (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE)
{
- performMicTuning();
+ LL_DEBUGS("Voice") << "Suspending voiceControlCoro() momentarily for teleport. Tuning: " << mTuningMode << ". Relog: " << mRelogRequested << LL_ENDL;
+ llcoro::suspendUntilTimeout(1.0);
+ }
+ else
+ {
+ coro_state = VOICE_STATE_START_DAEMON;
}
+ break;
- if (!sShuttingDown)
+ case VOICE_STATE_START_DAEMON:
+ LL_DEBUGS("Voice") << "Launching daemon" << LL_ENDL;
+ LLVoiceVivoxStats::getInstance()->reset();
+ if (startAndLaunchDaemon())
{
- waitForChannel(); // this doesn't normally return unless relog is needed or shutting down
+ coro_state = VOICE_STATE_PROVISION_ACCOUNT;
}
-
- LL_DEBUGS("Voice") << "lost channel RelogRequested=" << mRelogRequested << LL_ENDL;
- endAndDisconnectSession();
- retry = 0;
- }
-
- // if we hit this and mRelogRequested is true, that indicates
- // that we attempted to relog into Vivox and were rejected.
- // Rather than just quit out of voice, we will tear it down (above)
- // and then reconstruct the voice connecion from scratch.
- LL_DEBUGS("Voice")
- << "disconnected"
- << " RelogRequested=" << mRelogRequested
- << LL_ENDL;
- if (mRelogRequested && !sShuttingDown)
- {
- if (!success)
+ else
+ {
+ coro_state = VOICE_STATE_SESSION_RETRY;
+ }
+ break;
+
+ case VOICE_STATE_PROVISION_ACCOUNT:
+ if (provisionVoiceAccount())
+ {
+ coro_state = VOICE_STATE_START_SESSION;
+ }
+ else
+ {
+ coro_state = VOICE_STATE_SESSION_RETRY;
+ }
+ break;
+
+ case VOICE_STATE_START_SESSION:
+ if (establishVoiceConnection())
+ {
+ coro_state = VOICE_STATE_SESSION_ESTABLISHED;
+ }
+ else
+ {
+ coro_state = VOICE_STATE_SESSION_RETRY;
+ }
+ break;
+
+ case VOICE_STATE_SESSION_RETRY:
+ giveUp(); // cleans sockets and session
+ if (mRelogRequested)
{
// We failed to connect, give it a bit time before retrying.
retry++;
- F32 delay = llmin(5.f * (F32)retry, 60.f);
- llcoro::suspendUntilTimeout(delay);
- LL_INFOS("Voice") << "Voice failed to establish session after " << retry << " tries. Will attempt to reconnect." << LL_ENDL;
+ F32 full_delay = llmin(5.f * (F32)retry, 60.f);
+ F32 current_delay = 0.f;
+ LL_INFOS("Voice") << "Voice failed to establish session after " << retry
+ << " tries. Will attempt to reconnect in " << full_delay
+ << " seconds" << LL_ENDL;
+ while (current_delay < full_delay && !sShuttingDown)
+ {
+ // Assuming that a second has passed is not accurate,
+ // but we don't need accurancy here, just to make sure
+ // that some time passed and not to outlive voice itself
+ current_delay++;
+ llcoro::suspendUntilTimeout(1.f);
+ }
+ coro_state = VOICE_STATE_WAIT_FOR_EXIT;
}
else
{
- LL_INFOS("Voice") << "will attempt to reconnect to voice" << LL_ENDL;
+ coro_state = VOICE_STATE_DONE;
}
+ break;
- while (isGatewayRunning() || (gAgent.getTeleportState() != LLAgent::TELEPORT_NONE && !sShuttingDown))
+ case VOICE_STATE_SESSION_ESTABLISHED:
{
- LL_INFOS("Voice") << "waiting for SLVoice to exit" << LL_ENDL;
- llcoro::suspendUntilTimeout(1.0);
+ // enable/disable the automatic VAD and explicitly set the initial values of
+ // the VAD variables ourselves when it is off - see SL-15072 for more details
+ // note: we set the other parameters too even if the auto VAD is on which is ok
+ unsigned int vad_auto = gSavedSettings.getU32("VivoxVadAuto");
+ unsigned int vad_hangover = gSavedSettings.getU32("VivoxVadHangover");
+ unsigned int vad_noise_floor = gSavedSettings.getU32("VivoxVadNoiseFloor");
+ unsigned int vad_sensitivity = gSavedSettings.getU32("VivoxVadSensitivity");
+ setupVADParams(vad_auto, vad_hangover, vad_noise_floor, vad_sensitivity);
+
+ // watch for changes to the VAD settings via Debug Settings UI and act on them accordingly
+ gSavedSettings.getControl("VivoxVadAuto")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+ gSavedSettings.getControl("VivoxVadHangover")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+ gSavedSettings.getControl("VivoxVadNoiseFloor")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+ gSavedSettings.getControl("VivoxVadSensitivity")->getSignal()->connect(boost::bind(&LLVivoxVoiceClient::onVADSettingsChange, this));
+
+ if (mTuningMode)
+ {
+ performMicTuning();
+ }
+
+ coro_state = VOICE_STATE_WAIT_FOR_CHANNEL;
}
- }
- }
- while (mVoiceEnabled && mRelogRequested && !sShuttingDown);
- mIsCoroutineActive = false;
- LL_INFOS("Voice") << "exiting" << LL_ENDL;
-}
+ break;
-bool LLVivoxVoiceClient::startAndConnectSession()
-{
- bool ok = false;
- LL_DEBUGS("Voice") << LL_ENDL;
+ case VOICE_STATE_WAIT_FOR_CHANNEL:
+ waitForChannel(); // todo: split into more states like login/fonts
+ coro_state = VOICE_STATE_DISCONNECT;
+ break;
- LLVoiceVivoxStats::getInstance()->reset();
+ case VOICE_STATE_DISCONNECT:
+ LL_DEBUGS("Voice") << "lost channel RelogRequested=" << mRelogRequested << LL_ENDL;
+ endAndDisconnectSession();
+ retry = 0; // Connected without issues
+ coro_state = VOICE_STATE_WAIT_FOR_EXIT;
+ break;
- if (startAndLaunchDaemon())
- {
- if (provisionVoiceAccount())
- {
- if (establishVoiceConnection())
+ case VOICE_STATE_WAIT_FOR_EXIT:
+ if (isGatewayRunning())
{
- ok = true;
+ LL_INFOS("Voice") << "waiting for SLVoice to exit" << LL_ENDL;
+ llcoro::suspendUntilTimeout(1.0);
}
- }
- }
+ else if (mRelogRequested && mVoiceEnabled)
+ {
+ LL_INFOS("Voice") << "will attempt to reconnect to voice" << LL_ENDL;
+ coro_state = VOICE_STATE_TP_WAIT;
+ }
+ else
+ {
+ coro_state = VOICE_STATE_DONE;
+ }
+ break;
- if (!ok)
- {
- giveUp();
- }
+ case VOICE_STATE_DONE:
+ break;
+ }
+ } while (coro_state > 0);
- return ok;
+ mIsCoroutineActive = false;
+ LL_INFOS("Voice") << "exiting" << LL_ENDL;
}
bool LLVivoxVoiceClient::endAndDisconnectSession()
@@ -1041,21 +1131,24 @@ bool LLVivoxVoiceClient::provisionVoiceAccount()
LLVoiceVivoxStats::getInstance()->provisionAttemptStart();
result = httpAdapter->postAndSuspend(httpRequest, url, LLSD(), httpOpts);
+ if (sShuttingDown)
+ {
+ return false;
+ }
+
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
if (status == LLCore::HttpStatus(404))
{
F32 timeout = pow(PROVISION_RETRY_TIMEOUT, static_cast<float>(retryCount));
- LL_WARNS("Voice") << "Provision CAP 404. Retrying in " << timeout << " seconds." << LL_ENDL;
+ LL_WARNS("Voice") << "Provision CAP 404. Retrying in " << timeout << " seconds. Retries: " << (S32)retryCount << LL_ENDL;
+ llcoro::suspendUntilTimeout(timeout);
+
if (sShuttingDown)
{
return false;
}
- else
- {
- llcoro::suspendUntilTimeout(timeout);
- }
}
else if (!status)
{
@@ -1430,6 +1523,11 @@ bool LLVivoxVoiceClient::requestParcelVoiceInfo()
LLSD result = httpAdapter->postAndSuspend(httpRequest, url, LLSD());
+ if (sShuttingDown)
+ {
+ return false;
+ }
+
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
@@ -1535,6 +1633,11 @@ bool LLVivoxVoiceClient::addAndJoinSession(const sessionStatePtr_t &nextSession)
llcoro::suspend();
+ if (sShuttingDown)
+ {
+ return false;
+ }
+
LLSD result;
if (mSpatialJoiningNum == MAX_NORMAL_JOINING_SPATIAL_NUM)
@@ -1600,7 +1703,6 @@ bool LLVivoxVoiceClient::addAndJoinSession(const sessionStatePtr_t &nextSession)
if (sShuttingDown)
{
- mIsJoiningSession = false;
return false;
}
@@ -1723,6 +1825,11 @@ bool LLVivoxVoiceClient::terminateAudioSession(bool wait)
result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, LOGOUT_ATTEMPT_TIMEOUT, timeoutResult);
+ if (sShuttingDown)
+ {
+ return false;
+ }
+
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
if (result.has("session"))
{
@@ -1785,50 +1892,76 @@ bool LLVivoxVoiceClient::terminateAudioSession(bool wait)
return status;
}
+
+typedef enum e_voice_wait_for_channel_state
+{
+ VOICE_CHANNEL_STATE_LOGIN = 0, // entry point
+ VOICE_CHANNEL_STATE_CHECK_EFFECTS,
+ VOICE_CHANNEL_STATE_START_CHANNEL_PROCESSING,
+ VOICE_CHANNEL_STATE_PROCESS_CHANNEL,
+ VOICE_CHANNEL_STATE_NEXT_CHANNEL_DELAY,
+ VOICE_CHANNEL_STATE_NEXT_CHANNEL_CHECK,
+ VOICE_CHANNEL_STATE_LOGOUT,
+ VOICE_CHANNEL_STATE_RELOG,
+ VOICE_CHANNEL_STATE_DONE,
+} EVoiceWaitForChannelState;
+
bool LLVivoxVoiceClient::waitForChannel()
{
LL_INFOS("Voice") << "Waiting for channel" << LL_ENDL;
+ EVoiceWaitForChannelState state = VOICE_CHANNEL_STATE_LOGIN;
+
do
{
- if (!loginToVivox())
- {
- return false;
- }
-
if (sShuttingDown)
{
- logoutOfVivox(false);
+ // terminate() forcefully disconects voice, no need for cleanup
return false;
}
- if (LLVoiceClient::instance().getVoiceEffectEnabled())
+ switch (state)
{
- retrieveVoiceFonts();
+ case VOICE_CHANNEL_STATE_LOGIN:
+ if (!loginToVivox())
+ {
+ return false;
+ }
+ state = VOICE_CHANNEL_STATE_CHECK_EFFECTS;
+ break;
- // Request the set of available voice fonts.
- refreshVoiceEffectLists(false);
- }
+ case VOICE_CHANNEL_STATE_CHECK_EFFECTS:
+ if (LLVoiceClient::instance().getVoiceEffectEnabled())
+ {
+ retrieveVoiceFonts();
+
+ if (sShuttingDown)
+ {
+ return false;
+ }
-#if USE_SESSION_GROUPS
- // Rider: This code is completely unchanged from the original state machine
- // It does not seem to be in active use... but I'd rather not rip it out.
- // create the main session group
- setState(stateCreatingSessionGroup);
- sessionGroupCreateSendMessage();
+ // Request the set of available voice fonts.
+ refreshVoiceEffectLists(false);
+ }
+
+#if USE_SESSION_GROUPS
+ // Rider: This code is completely unchanged from the original state machine
+ // It does not seem to be in active use... but I'd rather not rip it out.
+ // create the main session group
+ setState(stateCreatingSessionGroup);
+ sessionGroupCreateSendMessage();
#endif
- do
- {
+ state = VOICE_CHANNEL_STATE_START_CHANNEL_PROCESSING;
+ break;
+
+ case VOICE_CHANNEL_STATE_START_CHANNEL_PROCESSING:
mIsProcessingChannels = true;
llcoro::suspend();
+ state = VOICE_CHANNEL_STATE_PROCESS_CHANNEL;
+ break;
- if (sShuttingDown)
- {
- mRelogRequested = false;
- break;
- }
-
+ case VOICE_CHANNEL_STATE_PROCESS_CHANNEL:
if (mTuningMode)
{
performMicTuning();
@@ -1869,54 +2002,91 @@ bool LLVivoxVoiceClient::waitForChannel()
}
}
- if (!mNextAudioSession && !sShuttingDown)
+ state = VOICE_CHANNEL_STATE_NEXT_CHANNEL_DELAY;
+ break;
+
+ case VOICE_CHANNEL_STATE_NEXT_CHANNEL_DELAY:
+ if (!mNextAudioSession)
{
llcoro::suspendUntilTimeout(1.0);
}
+ state = VOICE_CHANNEL_STATE_NEXT_CHANNEL_CHECK;
+ break;
- if (sShuttingDown)
+ case VOICE_CHANNEL_STATE_NEXT_CHANNEL_CHECK:
+ if (mVoiceEnabled && !mRelogRequested)
{
- mRelogRequested = false;
+ state = VOICE_CHANNEL_STATE_START_CHANNEL_PROCESSING;
+ break;
+ }
+ else
+ {
+ mIsProcessingChannels = false;
+ LL_DEBUGS("Voice")
+ << "leaving inner waitForChannel loop"
+ << " RelogRequested=" << mRelogRequested
+ << " VoiceEnabled=" << mVoiceEnabled
+ << LL_ENDL;
+ state = VOICE_CHANNEL_STATE_LOGOUT;
break;
}
- } while (mVoiceEnabled && !mRelogRequested && !sShuttingDown);
-
- LL_DEBUGS("Voice")
- << "leaving inner waitForChannel loop"
- << " RelogRequested=" << mRelogRequested
- << " VoiceEnabled=" << mVoiceEnabled
- << LL_ENDL;
-
- mIsProcessingChannels = false;
-
- logoutOfVivox(!sShuttingDown /*bool wait*/);
+ case VOICE_CHANNEL_STATE_LOGOUT:
+ logoutOfVivox(true /*bool wait*/);
+ if (mRelogRequested)
+ {
+ state = VOICE_CHANNEL_STATE_RELOG;
+ }
+ else
+ {
+ state = VOICE_CHANNEL_STATE_DONE;
+ }
+ break;
- if (mRelogRequested && !sShuttingDown)
- {
+ case VOICE_CHANNEL_STATE_RELOG:
LL_DEBUGS("Voice") << "Relog Requested, restarting provisioning" << LL_ENDL;
if (!provisionVoiceAccount())
{
+ if (sShuttingDown)
+ {
+ return false;
+ }
LL_WARNS("Voice") << "provisioning voice failed; giving up" << LL_ENDL;
giveUp();
return false;
}
+ if (mVoiceEnabled && mRelogRequested && isGatewayRunning())
+ {
+ state = VOICE_CHANNEL_STATE_LOGIN;
+ }
+ else
+ {
+ state = VOICE_CHANNEL_STATE_DONE;
+ }
+ break;
+ case VOICE_CHANNEL_STATE_DONE:
+ LL_DEBUGS("Voice")
+ << "exiting"
+ << " RelogRequested=" << mRelogRequested
+ << " VoiceEnabled=" << mVoiceEnabled
+ << LL_ENDL;
+ return !sShuttingDown;
}
- } while (mVoiceEnabled && mRelogRequested && isGatewayRunning() && !sShuttingDown);
-
- LL_DEBUGS("Voice")
- << "exiting"
- << " RelogRequested=" << mRelogRequested
- << " VoiceEnabled=" << mVoiceEnabled
- << LL_ENDL;
- return !sShuttingDown;
+ } while (true);
}
bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
{
LL_INFOS("Voice") << "running new voice session " << session->mHandle << LL_ENDL;
- if (!addAndJoinSession(session))
+ bool joined_session = addAndJoinSession(session);
+
+ if (sShuttingDown)
+ {
+ return false;
+ }
+
+ if (!joined_session)
{
notifyStatusObservers(LLVoiceClientStatusObserver::ERROR_UNKNOWN);
@@ -1940,9 +2110,19 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
mIsInChannel = true;
mMuteMicDirty = true;
- while (mVoiceEnabled && isGatewayRunning() && !mSessionTerminateRequested && !mTuningMode)
+ while (!sShuttingDown
+ && mVoiceEnabled
+ && isGatewayRunning()
+ && !mSessionTerminateRequested
+ && !mTuningMode)
{
sendCaptureAndRenderDevices(); // suspends
+
+ if (sShuttingDown)
+ {
+ return false;
+ }
+
if (mSessionTerminateRequested)
{
break;
@@ -1972,10 +2152,15 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
// cap for the parcel voice info. If we can't request it
// then we don't have the cap URL so we do nothing and will
// recheck next time around
- if (requestParcelVoiceInfo())
+ if (requestParcelVoiceInfo()) // suspends
{ // The parcel voice URI has changed.. break out and reconnect.
break;
}
+
+ if (sShuttingDown)
+ {
+ return false;
+ }
}
// Do the calculation that enforces the listener<->speaker tether (and also updates the real camera position)
enforceTether();
@@ -1994,6 +2179,12 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
mIsInitialized = true;
LLSD result = llcoro::suspendUntilEventOnWithTimeout(mVivoxPump, UPDATE_THROTTLE_SECONDS, timeoutEvent);
+
+ if (sShuttingDown)
+ {
+ return false;
+ }
+
if (!result.has("timeout")) // logging the timeout event spams the log
{
LL_DEBUGS("Voice") << "event=" << ll_stream_notation_sd(result) << LL_ENDL;
@@ -2036,6 +2227,11 @@ bool LLVivoxVoiceClient::runSession(const sessionStatePtr_t &session)
}
}
+ if (sShuttingDown)
+ {
+ return false;
+ }
+
mIsInChannel = false;
LL_DEBUGS("Voice") << "terminating at end of runSession" << LL_ENDL;
terminateAudioSession(true);
@@ -4718,6 +4914,12 @@ bool LLVivoxVoiceClient::switchChannel(
// The old session may now need to be deleted.
reapSession(oldSession);
+ // If voice was on, turn it off
+ if (LLVoiceClient::getInstance()->getUserPTTState())
+ {
+ LLVoiceClient::getInstance()->setUserPTTState(false);
+ }
+
notifyStatusObservers(LLVoiceClientStatusObserver::STATUS_VOICE_DISABLED);
}
else
diff --git a/indra/newview/llvoicevivox.h b/indra/newview/llvoicevivox.h
index 75ff5429f3..cf30a4e86a 100644
--- a/indra/newview/llvoicevivox.h
+++ b/indra/newview/llvoicevivox.h
@@ -626,8 +626,8 @@ private:
// Coroutine support methods
//---
void voiceControlCoro();
+ void voiceControlStateMachine(S32 &coro_state);
- bool startAndConnectSession();
bool endAndDisconnectSession();
bool callbackEndDaemon(const LLSD& data);
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 893c5f4fac..464e6efd2e 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -373,6 +373,18 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
{
delete mTextureAnimp;
mTextureAnimp = NULL;
+
+ for (S32 i = 0; i < getNumTEs(); i++)
+ {
+ LLFace* facep = mDrawable->getFace(i);
+ if (facep && facep->mTextureMatrix)
+ {
+ // delete or reset
+ delete facep->mTextureMatrix;
+ facep->mTextureMatrix = NULL;
+ }
+ }
+
gPipeline.markTextured(mDrawable);
mFaceMappingChanged = TRUE;
mTexAnimMode = 0;
@@ -472,6 +484,18 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
{
delete mTextureAnimp;
mTextureAnimp = NULL;
+
+ for (S32 i = 0; i < getNumTEs(); i++)
+ {
+ LLFace* facep = mDrawable->getFace(i);
+ if (facep && facep->mTextureMatrix)
+ {
+ // delete or reset
+ delete facep->mTextureMatrix;
+ facep->mTextureMatrix = NULL;
+ }
+ }
+
gPipeline.markTextured(mDrawable);
mFaceMappingChanged = TRUE;
mTexAnimMode = 0;
@@ -1716,7 +1740,17 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
}
}
- if (any_valid_boxes)
+ if (isRiggedMesh())
+ {
+ min.set(-1, -1, -1, 0);
+ max.set(1, 1, 1, 0);
+
+ mDrawable->setSpatialExtents(min, max);
+ mDrawable->setPositionGroup(LLVector4a(0, 0, 0));
+ updateRadius();
+ mDrawable->movePartition();
+ }
+ else if (any_valid_boxes)
{
if (rebuild)
{
@@ -4793,6 +4827,7 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
LLMatrix4a mat[kMaxJoints];
U32 maxJoints = LLSkinningUtil::getMeshJointCount(skin);
LLSkinningUtil::initSkinningMatrixPalette(mat, maxJoints, skin, avatar);
+ const LLMatrix4a bind_shape_matrix = skin->mBindShapeMatrix;
S32 rigged_vert_count = 0;
S32 rigged_face_count = 0;
@@ -4808,7 +4843,6 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons
if ( weight )
{
LLSkinningUtil::checkSkinWeights(weight, dst_face.mNumVertices, skin);
- const LLMatrix4a& bind_shape_matrix = skin->mBindShapeMatrix;
LLVector4a* pos = dst_face.mPositions;
@@ -4986,13 +5020,13 @@ bool can_batch_texture(LLFace* facep)
const static U32 MAX_FACE_COUNT = 4096U;
int32_t LLVolumeGeometryManager::sInstanceCount = 0;
-LLFace** LLVolumeGeometryManager::sFullbrightFaces = NULL;
-LLFace** LLVolumeGeometryManager::sBumpFaces = NULL;
-LLFace** LLVolumeGeometryManager::sSimpleFaces = NULL;
-LLFace** LLVolumeGeometryManager::sNormFaces = NULL;
-LLFace** LLVolumeGeometryManager::sSpecFaces = NULL;
-LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL;
-LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL;
+LLFace** LLVolumeGeometryManager::sFullbrightFaces[2] = { NULL };
+LLFace** LLVolumeGeometryManager::sBumpFaces[2] = { NULL };
+LLFace** LLVolumeGeometryManager::sSimpleFaces[2] = { NULL };
+LLFace** LLVolumeGeometryManager::sNormFaces[2] = { NULL };
+LLFace** LLVolumeGeometryManager::sSpecFaces[2] = { NULL };
+LLFace** LLVolumeGeometryManager::sNormSpecFaces[2] = { NULL };
+LLFace** LLVolumeGeometryManager::sAlphaFaces[2] = { NULL };
LLVolumeGeometryManager::LLVolumeGeometryManager()
: LLGeometryManager()
@@ -5020,32 +5054,38 @@ LLVolumeGeometryManager::~LLVolumeGeometryManager()
void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount)
{
- sFullbrightFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
- sBumpFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
- sSimpleFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
- sNormFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
- sSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
- sNormSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
- sAlphaFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
+ for (int i = 0; i < 2; ++i)
+ {
+ sFullbrightFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
+ sBumpFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
+ sSimpleFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
+ sNormFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
+ sSpecFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
+ sNormSpecFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
+ sAlphaFaces[i] = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount * sizeof(LLFace*)));
+ }
}
void LLVolumeGeometryManager::freeFaces()
{
- ll_aligned_free<64>(sFullbrightFaces);
- ll_aligned_free<64>(sBumpFaces);
- ll_aligned_free<64>(sSimpleFaces);
- ll_aligned_free<64>(sNormFaces);
- ll_aligned_free<64>(sSpecFaces);
- ll_aligned_free<64>(sNormSpecFaces);
- ll_aligned_free<64>(sAlphaFaces);
-
- sFullbrightFaces = NULL;
- sBumpFaces = NULL;
- sSimpleFaces = NULL;
- sNormFaces = NULL;
- sSpecFaces = NULL;
- sNormSpecFaces = NULL;
- sAlphaFaces = NULL;
+ for (int i = 0; i < 2; ++i)
+ {
+ ll_aligned_free<64>(sFullbrightFaces[i]);
+ ll_aligned_free<64>(sBumpFaces[i]);
+ ll_aligned_free<64>(sSimpleFaces[i]);
+ ll_aligned_free<64>(sNormFaces[i]);
+ ll_aligned_free<64>(sSpecFaces[i]);
+ ll_aligned_free<64>(sNormSpecFaces[i]);
+ ll_aligned_free<64>(sAlphaFaces[i]);
+
+ sFullbrightFaces[i] = NULL;
+ sBumpFaces[i] = NULL;
+ sSimpleFaces[i] = NULL;
+ sNormFaces[i] = NULL;
+ sSpecFaces[i] = NULL;
+ sNormSpecFaces[i] = NULL;
+ sAlphaFaces[i] = NULL;
+ }
}
void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
@@ -5066,8 +5106,18 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
return;
}
+ U32 passType = type;
+
+ bool rigged = facep->isState(LLFace::RIGGED);
+
+ if (rigged && type != LLRenderPass::PASS_ALPHA)
+ {
+ // hacky, should probably clean up -- if this face is rigged, put it in "type + 1"
+ // See LLRenderPass PASS_foo enum
+ passType += 1;
+ }
//add face to drawmap
- LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[type];
+ LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[passType];
S32 idx = draw_vec.size()-1;
@@ -5093,7 +5143,12 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
LLDrawable* drawable = facep->getDrawable();
- if (drawable->isState(LLDrawable::ANIMATED_CHILD))
+ if (rigged)
+ {
+ // rigged meshes ignore their model matrix
+ model_mat = nullptr;
+ }
+ else if (drawable->isState(LLDrawable::ANIMATED_CHILD))
{
model_mat = &drawable->getWorldMatrix();
}
@@ -5167,7 +5222,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange &&
draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange &&
#endif
- draw_vec[idx]->mMaterial == mat &&
+ //draw_vec[idx]->mMaterial == mat &&
draw_vec[idx]->mMaterialID == mat_id &&
draw_vec[idx]->mFullbright == fullbright &&
draw_vec[idx]->mBump == bump &&
@@ -5175,7 +5230,9 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_vec[idx]->mTextureMatrix == tex_mat &&
draw_vec[idx]->mModelMatrix == model_mat &&
draw_vec[idx]->mShaderMask == shader_mask &&
- draw_vec[idx]->mSelected == selected)
+ draw_vec[idx]->mSelected == selected &&
+ draw_vec[idx]->mAvatar == facep->mAvatar &&
+ draw_vec[idx]->getSkinHash() == facep->getSkinHash())
{
draw_vec[idx]->mCount += facep->getIndicesCount();
draw_vec[idx]->mEnd += facep->getGeomCount();
@@ -5221,6 +5278,8 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
draw_info->mSpecularMap = NULL;
draw_info->mMaterial = mat;
draw_info->mShaderMask = shader_mask;
+ draw_info->mAvatar = facep->mAvatar;
+ draw_info->mSkinInfo = facep->mSkinInfo;
if (mat)
{
@@ -5282,34 +5341,6 @@ void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group)
}
-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
- || drawpool->getType() == LLDrawPool::POOL_CONTROL_AV)
- {
- return (LLDrawPoolAvatar*) drawpool;
- }
- }
- }
- }
- }
-
- return NULL;
-}
-
void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value)
{
static LLCachedControl<U32> render_auto_mute_byte_limit(gSavedSettings, "RenderAutoMuteByteLimit", 0U);
@@ -5387,11 +5418,21 @@ void handleRenderAutoMuteByteLimitChanged(const LLSD& new_value)
// add a face pointer to a list of face pointers without going over MAX_COUNT faces
template<typename T>
-static inline void add_face(T** list, U32& count, T* face)
+static inline void add_face(T*** list, U32* count, T* face)
{
- if (count < MAX_FACE_COUNT)
+ if (face->isState(LLFace::RIGGED))
+ {
+ if (count[1] < MAX_FACE_COUNT)
+ {
+ list[1][count[1]++] = face;
+ }
+ }
+ else
{
- list[count++] = face;
+ if (count[0] < MAX_FACE_COUNT)
+ {
+ list[0][count[0]++] = face;
+ }
}
}
@@ -5441,14 +5482,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
mFaceList.clear();
- U32 fullbright_count = 0;
- U32 bump_count = 0;
- U32 simple_count = 0;
- U32 alpha_count = 0;
- U32 norm_count = 0;
- U32 spec_count = 0;
- U32 normspec_count = 0;
-
+ U32 fullbright_count[2] = { 0 };
+ U32 bump_count[2] = { 0 };
+ U32 simple_count[2] = { 0 };
+ U32 alpha_count[2] = { 0 };
+ U32 norm_count[2] = { 0 };
+ U32 spec_count[2] = { 0 };
+ U32 normspec_count[2] = { 0 };
U32 useage = group->getSpatialPartition()->mBufferUsage;
@@ -5497,7 +5537,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
std::string vobj_name = llformat("Vol%p", vobj);
- if (vobj->isMesh() &&
+ bool is_mesh = vobj->isMesh();
+ if (is_mesh &&
((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled()))
{
continue;
@@ -5510,7 +5551,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
group->mSurfaceArea += volume->getSurfaceArea() * llmax(llmax(scale.mV[0], scale.mV[1]), scale.mV[2]);
}
- bool is_mesh = vobj->isMesh();
+
F32 est_tris = vobj->getEstTrianglesMax();
vobj->updateControlAvatar();
@@ -5534,15 +5575,32 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
drawablep->clearState(LLDrawable::HAS_ALPHA);
- if (vobj->isRiggedMesh() &&
- ((vobj->isAnimatedObject() && vobj->getControlAvatar()) ||
- (!vobj->isAnimatedObject() && vobj->getAvatar())))
+ LLVOAvatar* avatar = nullptr;
+ const LLMeshSkinInfo* skinInfo = nullptr;
+ if (is_mesh)
{
- vobj->getAvatar()->addAttachmentOverridesForObject(vobj, NULL, false);
+ skinInfo = vobj->getSkinInfo();
+ }
+
+ if (skinInfo)
+ {
+ if (vobj->isAnimatedObject())
+ {
+ avatar = vobj->getControlAvatar();
+ }
+ else
+ {
+ avatar = vobj->getAvatar();
+ }
+ }
+
+ if (avatar != nullptr)
+ {
+ avatar->addAttachmentOverridesForObject(vobj, NULL, false);
}
// Standard rigged mesh attachments:
- bool rigged = !vobj->isAnimatedObject() && vobj->isRiggedMesh() && vobj->isAttachment();
+ bool rigged = !vobj->isAnimatedObject() && skinInfo && vobj->isAttachment();
// Animated objects. Have to check for isRiggedMesh() to
// exclude static objects in animated object linksets.
rigged = rigged || (vobj->isAnimatedObject() && vobj->isRiggedMesh() &&
@@ -5566,183 +5624,19 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
//sum up face verts and indices
drawablep->updateFaceSize(i);
-
- if (rigged)
- {
- if (!facep->isState(LLFace::RIGGED))
- { //completely reset vertex buffer
- facep->clearVertexBuffer();
- }
-
- facep->setState(LLFace::RIGGED);
- any_rigged_face = true;
-
- //get drawpool of avatar with rigged face
- LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj);
-
- 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 || old_pool->getType() == LLDrawPool::POOL_CONTROL_AV))
- {
- ((LLDrawPoolAvatar*) old_pool)->removeRiggedFace(facep);
- }
-
- //add face to new pool
- LLViewerTexture* tex = facep->getTexture();
- U32 type = gPipeline.getPoolTypeFromTE(te, tex);
-
- F32 te_alpha = te->getColor().mV[3];
-
- if (te->getGlow())
- {
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_GLOW);
- }
-
- LLMaterial* mat = te->getMaterialParams().get();
- bool fullbright = te->getFullbright();
-
- if (mat && LLPipeline::sRenderDeferred)
- {
- U8 alpha_mode = mat->getDiffuseAlphaMode();
-
- bool is_alpha = type == LLDrawPool::POOL_ALPHA &&
- (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND ||
- te_alpha < 0.999f);
-
- if (is_alpha)
- { //this face needs alpha blending, override alpha mode
- alpha_mode = LLMaterial::DIFFUSE_ALPHA_MODE_BLEND;
- }
-
- if (fullbright && (alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE))
- {
- pool->addRiggedFace(facep, LLDrawPoolAvatar::RIGGED_FULLBRIGHT);
- }
- else if (!is_alpha || te_alpha > 0.f) // //only add the face if it will actually be visible
- {
- U32 mask = mat->getShaderMask(alpha_mode);
- pool->addRiggedFace(facep, mask);
- }
-
- if(vobj->isAnimatedObject() && vobj->isRiggedMesh())
- {
- pool->updateRiggedVertexBuffers(vobj->getAvatar());
- }
- }
- else if (mat)
- {
- bool is_alpha = type == LLDrawPool::POOL_ALPHA;
- U8 mode = mat->getDiffuseAlphaMode();
- bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
- mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
-
- if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_MASK && te->getColor().mV[3] >= 0.999f)
- {
- pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE);
- }
- else if (is_alpha || (te->getColor().mV[3] < 0.999f))
- {
- if (te->getColor().mV[3] > 0.f)
- {
- pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_ALPHA : LLDrawPoolAvatar::RIGGED_ALPHA);
- }
- }
- else if (gPipeline.canUseVertexShaders()
- && LLPipeline::sRenderBump
- && te->getShiny()
- && can_be_shiny)
- {
- pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT_SHINY : LLDrawPoolAvatar::RIGGED_SHINY);
- }
- else
- {
- pool->addRiggedFace(facep, fullbright ? LLDrawPoolAvatar::RIGGED_FULLBRIGHT : LLDrawPoolAvatar::RIGGED_SIMPLE);
- }
- }
- else
- {
- if (type == LLDrawPool::POOL_ALPHA)
- {
- if (te->getColor().mV[3] > 0.f)
- {
- 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 (rigged)
+ {
+ if (!facep->isState(LLFace::RIGGED))
+ { //completely reset vertex buffer
+ facep->clearVertexBuffer();
+ }
- 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);
- }
- }
-
+ facep->setState(LLFace::RIGGED);
+ facep->mSkinInfo = (LLMeshSkinInfo*) skinInfo; // TODO -- fix ugly de-consting here
+ facep->mAvatar = avatar;
+ any_rigged_face = true;
+ }
if (cur_total > max_total || facep->getIndicesCount() <= 0 || facep->getGeomCount() <= 0)
{
@@ -5752,7 +5646,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
cur_total += facep->getGeomCount();
- if (facep->hasGeometry() && facep->getPixelArea() > FORCE_CULL_AREA)
+ if (facep->hasGeometry() &&
+ (rigged || // <-- HACK FIXME -- getPixelArea might be incorrect for rigged objects
+ facep->getPixelArea() > FORCE_CULL_AREA)) // <-- don't render tiny faces
{
const LLTextureEntry* te = facep->getTextureEntry();
LLViewerTexture* tex = facep->getTexture();
@@ -5815,7 +5711,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
}
else
{
- if (te->getColor().mV[3] > 0.f)
+ if (te->getColor().mV[3] > 0.f || te->getGlow() > 0.f)
{ //only treat as alpha in the pipeline if < 100% transparent
drawablep->setState(LLDrawable::HAS_ALPHA);
add_face(sAlphaFaces, alpha_count, facep);
@@ -5942,6 +5838,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
BOOL batch_textures = LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_OBJECT) > 1;
+ // add extra vertex data for deferred rendering (not necessarily for batching textures)
if (batch_textures)
{
bump_mask = bump_mask | LLVertexBuffer::MAP_TANGENT;
@@ -5954,13 +5851,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
U32 geometryBytes = 0;
- geometryBytes += genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSimpleFaces, simple_count, FALSE, batch_textures, FALSE);
- geometryBytes += genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sFullbrightFaces, fullbright_count, FALSE, batch_textures);
- geometryBytes += genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sAlphaFaces, alpha_count, TRUE, batch_textures);
- geometryBytes += genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sBumpFaces, bump_count, FALSE, FALSE);
- geometryBytes += genDrawInfo(group, norm_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormFaces, norm_count, FALSE, FALSE);
- geometryBytes += genDrawInfo(group, spec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sSpecFaces, spec_count, FALSE, FALSE);
- geometryBytes += genDrawInfo(group, normspec_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, sNormSpecFaces, normspec_count, FALSE, FALSE);
+ U32 extra_mask = LLVertexBuffer::MAP_TEXTURE_INDEX;
+ geometryBytes += genDrawInfo(group, simple_mask | extra_mask, sSimpleFaces[0], simple_count[0], FALSE, batch_textures);
+ geometryBytes += genDrawInfo(group, fullbright_mask | extra_mask, sFullbrightFaces[0], fullbright_count[0], FALSE, batch_textures);
+ geometryBytes += genDrawInfo(group, alpha_mask | extra_mask, sAlphaFaces[0], alpha_count[0], TRUE, batch_textures);
+ geometryBytes += genDrawInfo(group, bump_mask | extra_mask, sBumpFaces[0], bump_count[0], FALSE, FALSE);
+ geometryBytes += genDrawInfo(group, norm_mask | extra_mask, sNormFaces[0], norm_count[0], FALSE, FALSE);
+ geometryBytes += genDrawInfo(group, spec_mask | extra_mask, sSpecFaces[0], spec_count[0], FALSE, FALSE);
+ geometryBytes += genDrawInfo(group, normspec_mask | extra_mask, sNormSpecFaces[0], normspec_count[0], FALSE, FALSE);
+
+ extra_mask |= LLVertexBuffer::MAP_WEIGHT4;
+ geometryBytes += genDrawInfo(group, simple_mask | extra_mask, sSimpleFaces[1], simple_count[1], FALSE, batch_textures, TRUE);
+ geometryBytes += genDrawInfo(group, fullbright_mask | extra_mask, sFullbrightFaces[1], fullbright_count[1], FALSE, batch_textures, TRUE);
+ geometryBytes += genDrawInfo(group, alpha_mask | extra_mask, sAlphaFaces[1], alpha_count[1], TRUE, batch_textures, TRUE);
+ geometryBytes += genDrawInfo(group, bump_mask | extra_mask, sBumpFaces[1], bump_count[1], FALSE, TRUE);
+ geometryBytes += genDrawInfo(group, norm_mask | extra_mask, sNormFaces[1], norm_count[1], FALSE, TRUE);
+ geometryBytes += genDrawInfo(group, spec_mask | extra_mask, sSpecFaces[1], spec_count[1], FALSE, TRUE);
+ geometryBytes += genDrawInfo(group, normspec_mask | extra_mask, sNormSpecFaces[1], normspec_count[1], FALSE, TRUE);
group->mGeometryBytes = geometryBytes;
@@ -6122,7 +6029,7 @@ struct CompareBatchBreakerModified
const LLTextureEntry* lte = lhs->getTextureEntry();
const LLTextureEntry* rte = rhs->getTextureEntry();
- if (lte->getBumpmap() != rte->getBumpmap())
+ if (lte->getBumpmap() != rte->getBumpmap())
{
return lte->getBumpmap() < rte->getBumpmap();
}
@@ -6145,8 +6052,43 @@ struct CompareBatchBreakerModified
}
};
+struct CompareBatchBreakerRigged
+{
+ bool operator()(const LLFace* const& lhs, const LLFace* const& rhs)
+ {
+ const LLTextureEntry* lte = lhs->getTextureEntry();
+ const LLTextureEntry* rte = rhs->getTextureEntry();
+
+ if (lhs->mAvatar != rhs->mAvatar)
+ {
+ return lhs->mAvatar < rhs->mAvatar;
+ }
+ else if (lhs->mSkinInfo->mHash != rhs->mSkinInfo->mHash)
+ {
+ return lhs->mSkinInfo->mHash < rhs->mSkinInfo->mHash;
+ }
+ else if (lhs->getTexture() != rhs->getTexture())
+ {
+ return lhs->getTexture() < rhs->getTexture();
+ }
+ else if (lte->getBumpmap() != rte->getBumpmap())
+ {
+ return lte->getBumpmap() < rte->getBumpmap();
+ }
+ else if (LLPipeline::sRenderDeferred && lte->getMaterialID() != rte->getMaterialID())
+ {
+ return lte->getMaterialID() < rte->getMaterialID();
+ }
+ else // if (LLPipeline::sRenderDeferred && (lte->getMaterialParams() == rte->getMaterialParams()) && (lte->getShiny() != rte->getShiny()))
+ {
+ return lte->getShiny() < rte->getShiny();
+ }
+
+ }
+};
+
-U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL no_materials)
+U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures, BOOL rigged)
{
LL_PROFILE_ZONE_SCOPED;
@@ -6181,11 +6123,17 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
{
LL_PROFILE_ZONE_NAMED("genDrawInfo - sort");
- if (!distance_sort)
- {
- //sort faces by things that break batches
- std::sort(faces, faces+face_count, CompareBatchBreakerModified());
- }
+
+ if (rigged)
+ {
+ //sort faces by things that break batches, including avatar and mesh id
+ std::sort(faces, faces + face_count, CompareBatchBreakerRigged());
+ }
+ else if (!distance_sort)
+ {
+ //sort faces by things that break batches, not including avatar and mesh id
+ std::sort(faces, faces + face_count, CompareBatchBreakerModified());
+ }
else
{
//sort faces by distance
@@ -6202,11 +6150,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
LLViewerTexture* last_tex = NULL;
S32 buffer_index = 0;
- if (distance_sort)
- {
- buffer_index = -1;
- }
-
S32 texture_index_channels = 1;
if (gGLManager.mGLSLVersionMajor > 1 || gGLManager.mGLSLVersionMinor >= 30)
@@ -6218,6 +6161,16 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
{
texture_index_channels = gDeferredAlphaProgram.mFeatures.mIndexedTextureChannels;
}
+
+ if (rigged)
+ { //don't attempt distance sorting on rigged meshes, not likely to succeed and breaks batches
+ distance_sort = FALSE;
+ }
+
+ if (distance_sort)
+ {
+ buffer_index = -1;
+ }
static LLCachedControl<U32> max_texture_index(gSavedSettings, "RenderMaxTextureIndex", 16);
texture_index_channels = llmin(texture_index_channels, (S32) max_texture_index);
@@ -6232,7 +6185,9 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
//pull off next face
LLFace* facep = *face_iter;
LLViewerTexture* tex = facep->getTexture();
- LLMaterialPtr mat = facep->getTextureEntry()->getMaterialParams();
+ const LLTextureEntry* te = facep->getTextureEntry();
+ LLMaterialPtr mat = te->getMaterialParams();
+ LLMaterialID matId = te->getMaterialID();
if (distance_sort)
{
@@ -6355,11 +6310,14 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
while (i != end_faces &&
(LLPipeline::sTextureBindTest ||
(distance_sort ||
- ((*i)->getTexture() == tex &&
- ((*i)->getTextureEntry()->getMaterialParams() == mat)))))
+ ((*i)->getTexture() == tex))))
{
facep = *i;
-
+ const LLTextureEntry* nextTe = facep->getTextureEntry();
+ if (nextTe->getMaterialID() != matId)
+ {
+ break;
+ }
//face has no texture index
facep->mDrawInfo = NULL;
@@ -6449,8 +6407,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
U32 te_idx = facep->getTEOffset();
- llassert(!facep->isState(LLFace::RIGGED));
-
if (!facep->getGeometryVolume(*volume, te_idx,
vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset,true))
{
@@ -6547,10 +6503,6 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
}
}
}
- else if (no_materials)
- {
- registerFace(group, facep, LLRenderPass::PASS_SIMPLE);
- }
else if (transparent)
{
registerFace(group, facep, LLRenderPass::PASS_ALPHA);
diff --git a/indra/newview/llwearableitemslist.cpp b/indra/newview/llwearableitemslist.cpp
index 9acc0f8d2f..bf4db81475 100644
--- a/indra/newview/llwearableitemslist.cpp
+++ b/indra/newview/llwearableitemslist.cpp
@@ -820,7 +820,7 @@ void LLWearableItemsList::ContextMenu::show(LLView* spawning_view, LLWearableTyp
setMenuItemVisible(menup, "wearable_attach_to", false);
setMenuItemVisible(menup, "wearable_attach_to_hud", false);
- std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type));
+ std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getInstance()->getTypeName(w_type));
LLMenuItemGL* menu_item = menup->getChild<LLMenuItemGL>("create_new");
menu_item->setLabel(new_label);
@@ -1005,7 +1005,7 @@ void LLWearableItemsList::ContextMenu::updateItemsLabels(LLContextMenu* menu)
if (!item || !item->isWearableType()) return;
LLWearableType::EType w_type = item->getWearableType();
- std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getTypeName(w_type));
+ std::string new_label = LLTrans::getString("create_new_" + LLWearableType::getInstance()->getTypeName(w_type));
LLMenuItemGL* menu_item = menu->getChild<LLMenuItemGL>("create_new");
menu_item->setLabel(new_label);
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index b61fbbd073..de01fbb73d 100644
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -241,7 +241,8 @@ LLViewerWearable* LLWearableList::createNewWearable( LLWearableType::EType type,
LLViewerWearable *wearable = generateNewWearable();
wearable->setType( type, avatarp );
- std::string name = LLTrans::getString( LLWearableType::getTypeDefaultNewName(wearable->getType()) );
+ // LLWearableType has pre-translated getTypeLabel(), but it returns 'name', not 'New Name'.
+ std::string name = LLTrans::getString( LLWearableType::getInstance()->getTypeDefaultNewName(wearable->getType()) );
wearable->setName( name );
LLPermissions perm;
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index d019b400e8..b8f1ec35f6 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -38,6 +38,7 @@
#include "llfloaterreg.h"
#include "lllogininstance.h"
#include "llparcel.h"
+#include "llregex.h"
#include "llsd.h"
#include "llui.h"
#include "lluri.h"
@@ -51,8 +52,6 @@
#include "lluriparser.h"
#include "uriparser/Uri.h"
-#include <boost/regex.hpp>
-
bool on_load_url_external_response(const LLSD& notification, const LLSD& response, bool async );
@@ -239,13 +238,13 @@ bool LLWeb::useExternalBrowser(const std::string &url)
boost::regex pattern = boost::regex("\\b(lindenlab.com|secondlife.com|secondlife.io)$", boost::regex::perl|boost::regex::icase);
boost::match_results<std::string::const_iterator> matches;
- return !(boost::regex_search(uri_string, matches, pattern));
+ return !(ll_regex_search(uri_string, matches, pattern));
}
else
{
boost::regex pattern = boost::regex("^mailto:", boost::regex::perl | boost::regex::icase);
boost::match_results<std::string::const_iterator> matches;
- return boost::regex_search(url, matches, pattern);
+ return ll_regex_search(url, matches, pattern);
}
#endif
}
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 5f62908009..d7f16713d2 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -885,6 +885,7 @@ void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_heigh
void LLWorld::precullWaterObjects(LLCamera& camera, LLCullResult* cull, bool include_void_water)
{
+ LL_PROFILE_ZONE_SCOPED;
if (!gAgent.getRegion())
{
return;
@@ -1194,6 +1195,11 @@ public:
virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
{
+ if (LLApp::isExiting())
+ {
+ return;
+ }
+
if (!input["body"].has("agent-id") ||
!input["body"].has("sim-ip-and-port") ||
!input["body"].has("seed-capability"))
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index de95eb1a87..d9d97ac1e5 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -2348,6 +2348,15 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
LL_RECORD_BLOCK_TIME(FTM_CULL);
+ if (planep != nullptr)
+ {
+ camera.setUserClipPlane(*planep);
+ }
+ else
+ {
+ camera.disableUserClipPlane();
+ }
+
grabReferences(result);
sCull->clear();
@@ -2402,11 +2411,6 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl
mCubeVB->setBuffer(LLVertexBuffer::MAP_VERTEX);
}
- if (!sReflectionRender)
- {
- camera.disableUserClipPlane();
- }
-
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
{
@@ -6349,21 +6353,19 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
continue;
}
- LLVector3 light_pos(light->getRenderPosition());
- LLVector4 light_pos_gl(light_pos, 1.0f);
-
- F32 light_radius = llmax(light->getLightRadius(), 0.001f);
- F32 size = light_radius * (sRenderDeferred ? 1.5f : 1.0f);
+ LLVector3 light_pos(light->getRenderPosition());
+ LLVector4 light_pos_gl(light_pos, 1.0f);
- if (size <= 0.001f)
+ F32 adjusted_radius = light->getLightRadius() * (sRenderDeferred ? 1.5f : 1.0f);
+ if (adjusted_radius <= 0.001f)
{
continue;
}
- F32 x = (3.f * (1.f + (light->getLightFalloff() * 2.0f))); // why this magic? probably trying to match a historic behavior.
- F32 linatten = x / (light_radius); // % of brightness at radius
+ F32 x = (3.f * (1.f + (light->getLightFalloff() * 2.0f))); // why this magic? probably trying to match a historic behavior.
+ F32 linatten = x / adjusted_radius; // % of brightness at radius
- mHWLightColors[cur_light] = light_color;
+ mHWLightColors[cur_light] = light_color;
LLLightState* light_state = gGL.getLight(cur_light);
light_state->setPosition(light_pos_gl);
@@ -6372,7 +6374,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
light_state->setConstantAttenuation(0.f);
if (sRenderDeferred)
{
- light_state->setLinearAttenuation(size);
+ light_state->setLinearAttenuation(linatten);
light_state->setQuadraticAttenuation(light->getLightFalloff(DEFERRED_LIGHT_FALLOFF) + 1.f); // get falloff to match for forward deferred rendering lights
}
else
@@ -7410,32 +7412,91 @@ void LLPipeline::doResetVertexBuffers(bool forced)
LLVOPartGroup::restoreGL();
}
-void LLPipeline::renderObjects(U32 type, U32 mask, bool texture, bool batch_texture)
+void LLPipeline::renderObjects(U32 type, U32 mask, bool texture, bool batch_texture, bool rigged)
{
assertInitialized();
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
- mSimplePool->pushBatches(type, mask, texture, batch_texture);
+ if (rigged)
+ {
+ mSimplePool->pushRiggedBatches(type + 1, mask, texture, batch_texture);
+ }
+ else
+ {
+ mSimplePool->pushBatches(type, mask, texture, batch_texture);
+ }
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
}
-void LLPipeline::renderMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture)
+void LLPipeline::renderAlphaObjects(U32 mask, bool texture, bool batch_texture, bool rigged)
+{
+ LL_PROFILE_ZONE_SCOPED;
+ assertInitialized();
+ gGL.loadMatrix(gGLModelView);
+ gGLLastMatrix = NULL;
+ U32 type = LLRenderPass::PASS_ALPHA;
+ LLVOAvatar* lastAvatar = nullptr;
+ U64 lastMeshId = 0;
+ for (LLCullResult::drawinfo_iterator i = gPipeline.beginRenderMap(type); i != gPipeline.endRenderMap(type); ++i)
+ {
+ LLDrawInfo* pparams = *i;
+ if (pparams)
+ {
+ if (rigged)
+ {
+ if (pparams->mAvatar != nullptr)
+ {
+ if (lastAvatar != pparams->mAvatar || lastMeshId != pparams->mSkinInfo->mHash)
+ {
+ mSimplePool->uploadMatrixPalette(*pparams);
+ lastAvatar = pparams->mAvatar;
+ lastMeshId = pparams->mSkinInfo->mHash;
+ }
+
+ mSimplePool->pushBatch(*pparams, mask | LLVertexBuffer::MAP_WEIGHT4, texture, batch_texture);
+ }
+ }
+ else if (pparams->mAvatar == nullptr)
+ {
+ mSimplePool->pushBatch(*pparams, mask, texture, batch_texture);
+ }
+ }
+ }
+ gGL.loadMatrix(gGLModelView);
+ gGLLastMatrix = NULL;
+}
+
+void LLPipeline::renderMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture, bool rigged)
{
assertInitialized();
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
- mAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture);
+ if (rigged)
+ {
+ mAlphaMaskPool->pushRiggedMaskBatches(type+1, mask, texture, batch_texture);
+ }
+ else
+ {
+ mAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture);
+ }
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
}
-void LLPipeline::renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture)
+void LLPipeline::renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture, bool batch_texture, bool rigged)
{
assertInitialized();
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
- mFullbrightAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture);
+ if (rigged)
+ {
+ mFullbrightAlphaMaskPool->pushRiggedMaskBatches(type+1, mask, texture, batch_texture);
+ }
+ else
+ {
+ mFullbrightAlphaMaskPool->pushMaskBatches(type, mask, texture, batch_texture);
+ }
gGL.loadMatrix(gGLModelView);
gGLLastMatrix = NULL;
}
@@ -9589,198 +9650,207 @@ static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_TREE("Alpha Tree");
static LLTrace::BlockTimerStatHandle FTM_SHADOW_ALPHA_GRASS("Alpha Grass");
static LLTrace::BlockTimerStatHandle FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED("Fullbright Alpha Masked");
-void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult &result, bool use_shader, bool use_occlusion, U32 target_width)
+void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera& shadow_cam, LLCullResult& result, bool use_shader, bool use_occlusion, U32 target_width)
{
- LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER);
+ LL_RECORD_BLOCK_TIME(FTM_SHADOW_RENDER);
- //clip out geometry on the same side of water as the camera
- S32 occlude = LLPipeline::sUseOcclusion;
- if (!use_occlusion)
- {
- LLPipeline::sUseOcclusion = 0;
- }
- LLPipeline::sShadowRender = true;
-
- static const U32 types[] = {
- LLRenderPass::PASS_SIMPLE,
- LLRenderPass::PASS_FULLBRIGHT,
- LLRenderPass::PASS_SHINY,
- LLRenderPass::PASS_BUMP,
- LLRenderPass::PASS_FULLBRIGHT_SHINY ,
- LLRenderPass::PASS_MATERIAL,
- LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE,
- LLRenderPass::PASS_SPECMAP,
- LLRenderPass::PASS_SPECMAP_EMISSIVE,
- LLRenderPass::PASS_NORMMAP,
- LLRenderPass::PASS_NORMMAP_EMISSIVE,
- LLRenderPass::PASS_NORMSPEC,
- LLRenderPass::PASS_NORMSPEC_EMISSIVE,
- };
+ //clip out geometry on the same side of water as the camera
+ S32 occlude = LLPipeline::sUseOcclusion;
+ if (!use_occlusion)
+ {
+ LLPipeline::sUseOcclusion = 0;
+ }
+ LLPipeline::sShadowRender = true;
+
+ static const U32 types[] = {
+ LLRenderPass::PASS_SIMPLE,
+ LLRenderPass::PASS_FULLBRIGHT,
+ LLRenderPass::PASS_SHINY,
+ LLRenderPass::PASS_BUMP,
+ LLRenderPass::PASS_FULLBRIGHT_SHINY ,
+ LLRenderPass::PASS_MATERIAL,
+ LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE,
+ LLRenderPass::PASS_SPECMAP,
+ LLRenderPass::PASS_SPECMAP_EMISSIVE,
+ LLRenderPass::PASS_NORMMAP,
+ LLRenderPass::PASS_NORMMAP_EMISSIVE,
+ LLRenderPass::PASS_NORMSPEC,
+ LLRenderPass::PASS_NORMSPEC_EMISSIVE,
+ };
+
+ LLGLEnable cull(GL_CULL_FACE);
+
+ //enable depth clamping if available
+ LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0);
+
+ if (use_shader)
+ {
+ gDeferredShadowCubeProgram.bind();
+ }
- LLGLEnable cull(GL_CULL_FACE);
+ LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID - 1];
- //enable depth clamping if available
- LLGLEnable depth_clamp(gGLManager.mHasDepthClamp ? GL_DEPTH_CLAMP : 0);
+ occlusion_target.bindTarget();
+ updateCull(shadow_cam, result);
+ occlusion_target.flush();
- if (use_shader)
- {
- gDeferredShadowCubeProgram.bind();
- }
+ stateSort(shadow_cam, result);
- LLRenderTarget& occlusion_target = mShadowOcclusion[LLViewerCamera::sCurCameraID-1];
- occlusion_target.bindTarget();
- updateCull(shadow_cam, result);
- occlusion_target.flush();
+ //generate shadow map
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.pushMatrix();
+ gGL.loadMatrix(proj.m);
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.pushMatrix();
+ gGL.loadMatrix(view.m);
- stateSort(shadow_cam, result);
-
-
- //generate shadow map
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.pushMatrix();
- gGL.loadMatrix(proj.m);
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- gGL.loadMatrix(view.m);
+ stop_glerror();
+ gGLLastMatrix = NULL;
- stop_glerror();
- gGLLastMatrix = NULL;
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ stop_glerror();
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- stop_glerror();
-
LLEnvironment& environment = LLEnvironment::instance();
- LLVertexBuffer::unbind();
+ LLVertexBuffer::unbind();
- {
- if (!use_shader)
- { //occlusion program is general purpose depth-only no-textures
- gOcclusionProgram.bind();
- }
- else
- {
- gDeferredShadowProgram.bind();
- gDeferredShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- }
+ for (int j = 0; j < 2; ++j) // 0 -- static, 1 -- rigged
+ {
+ bool rigged = j == 1;
+ if (!use_shader)
+ { //occlusion program is general purpose depth-only no-textures
+ gOcclusionProgram.bind(rigged);
+ }
+ else
+ {
+ gDeferredShadowProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
+ }
- gGL.diffuseColor4f(1,1,1,1);
+ gGL.diffuseColor4f(1, 1, 1, 1);
S32 shadow_detail = gSavedSettings.getS32("RenderShadowDetail");
// if not using VSM, disable color writes
if (shadow_detail <= 2)
{
- gGL.setColorMask(false, false);
+ gGL.setColorMask(false, false);
}
-
- LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE);
-
- 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)
- {
+
+ LL_RECORD_BLOCK_TIME(FTM_SHADOW_SIMPLE);
+
+ gGL.getTexUnit(0)->disable();
+ for (U32 i = 0; i < sizeof(types) / sizeof(U32); ++i)
+ {
+ renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE, FALSE, rigged);
+ }
+ gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
+ if (!use_shader)
+ {
+ gOcclusionProgram.unbind();
+ }
+
+
+ }
+
+ if (use_shader)
+ {
LL_RECORD_BLOCK_TIME(FTM_SHADOW_GEOM);
- gDeferredShadowProgram.unbind();
- renderGeomShadow(shadow_cam);
- gDeferredShadowProgram.bind();
+ gDeferredShadowProgram.unbind();
+ renderGeomShadow(shadow_cam);
+ gDeferredShadowProgram.bind();
gDeferredShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- }
- else
- {
+ }
+ else
+ {
LL_RECORD_BLOCK_TIME(FTM_SHADOW_GEOM);
- renderGeomShadow(shadow_cam);
- }
+ renderGeomShadow(shadow_cam);
+ }
- {
- LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA);
+ {
+ LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA);
- gDeferredShadowAlphaMaskProgram.bind();
- gDeferredShadowAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
- gDeferredShadowAlphaMaskProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
+ for (int i = 0; i < 2; ++i)
+ {
+ bool rigged = i == 1;
- U32 mask = LLVertexBuffer::MAP_VERTEX |
- LLVertexBuffer::MAP_TEXCOORD0 |
- LLVertexBuffer::MAP_COLOR |
- LLVertexBuffer::MAP_TEXTURE_INDEX;
+ gDeferredShadowAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- {
- LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_MASKED);
- renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE);
- }
+ U32 mask = LLVertexBuffer::MAP_VERTEX |
+ LLVertexBuffer::MAP_TEXCOORD0 |
+ LLVertexBuffer::MAP_COLOR |
+ LLVertexBuffer::MAP_TEXTURE_INDEX;
- {
- LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_BLEND);
- gDeferredShadowAlphaMaskProgram.setMinimumAlpha(0.598f);
- renderObjects(LLRenderPass::PASS_ALPHA, mask, TRUE, TRUE);
- }
+ {
+ LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_MASKED);
+ renderMaskedObjects(LLRenderPass::PASS_ALPHA_MASK, mask, TRUE, TRUE, rigged);
+ }
- {
- LL_RECORD_BLOCK_TIME(FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED);
- gDeferredShadowFullbrightAlphaMaskProgram.bind();
- gDeferredShadowFullbrightAlphaMaskProgram.uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
- gDeferredShadowFullbrightAlphaMaskProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE);
- }
+ {
+ LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_BLEND);
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.598f);
+ renderAlphaObjects(mask, TRUE, TRUE, rigged);
+ }
- mask = mask & ~LLVertexBuffer::MAP_TEXTURE_INDEX;
- {
- LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_TREE);
- gDeferredTreeShadowProgram.bind();
- gDeferredTreeShadowProgram.uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
- renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, mask);
- renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, mask);
- renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, mask);
- renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, mask);
+ {
+ LL_RECORD_BLOCK_TIME(FTM_SHADOW_FULLBRIGHT_ALPHA_MASKED);
+ gDeferredShadowFullbrightAlphaMaskProgram.bind(rigged);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1f(LLShaderMgr::DEFERRED_SHADOW_TARGET_WIDTH, (float)target_width);
+ LLGLSLShader::sCurBoundShaderPtr->uniform1i(LLShaderMgr::SUN_UP_FACTOR, environment.getIsSunUp() ? 1 : 0);
+ renderFullbrightMaskedObjects(LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK, mask, TRUE, TRUE, rigged);
+ }
+
+
+ {
+ LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_GRASS);
+ gDeferredTreeShadowProgram.bind(rigged);
+ if (i == 0)
+ {
+ LLGLSLShader::sCurBoundShaderPtr->setMinimumAlpha(0.598f);
+ renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
+ }
+
+ U32 no_idx_mask = mask & ~LLVertexBuffer::MAP_TEXTURE_INDEX;
+ renderMaskedObjects(LLRenderPass::PASS_NORMSPEC_MASK, no_idx_mask, true, false, rigged);
+ renderMaskedObjects(LLRenderPass::PASS_MATERIAL_ALPHA_MASK, no_idx_mask, true, false, rigged);
+ renderMaskedObjects(LLRenderPass::PASS_SPECMAP_MASK, no_idx_mask, true, false, rigged);
+ renderMaskedObjects(LLRenderPass::PASS_NORMMAP_MASK, no_idx_mask, true, false, rigged);
+ }
}
-
- {
- LL_RECORD_BLOCK_TIME(FTM_SHADOW_ALPHA_GRASS);
- gDeferredTreeShadowProgram.setMinimumAlpha(0.598f);
- renderObjects(LLRenderPass::PASS_GRASS, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0, TRUE);
- }
}
- //glCullFace(GL_BACK);
+ //glCullFace(GL_BACK);
- gDeferredShadowCubeProgram.bind();
- gGLLastMatrix = NULL;
- gGL.loadMatrix(gGLModelView);
+ gDeferredShadowCubeProgram.bind();
+ gGLLastMatrix = NULL;
+ gGL.loadMatrix(gGLModelView);
- LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID-1];
+ LLRenderTarget& occlusion_source = mShadow[LLViewerCamera::sCurCameraID - 1];
- doOcclusion(shadow_cam, occlusion_source, occlusion_target);
+ doOcclusion(shadow_cam, occlusion_source, occlusion_target);
- if (use_shader)
- {
- gDeferredShadowProgram.unbind();
- }
-
- gGL.setColorMask(true, true);
-
- gGL.matrixMode(LLRender::MM_PROJECTION);
- gGL.popMatrix();
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.popMatrix();
- gGLLastMatrix = NULL;
+ if (use_shader)
+ {
+ gDeferredShadowProgram.unbind();
+ }
+
+ gGL.setColorMask(true, true);
- LLPipeline::sUseOcclusion = occlude;
- LLPipeline::sShadowRender = false;
+ gGL.matrixMode(LLRender::MM_PROJECTION);
+ gGL.popMatrix();
+ gGL.matrixMode(LLRender::MM_MODELVIEW);
+ gGL.popMatrix();
+ gGLLastMatrix = NULL;
+
+ LLPipeline::sUseOcclusion = occlude;
+ LLPipeline::sShadowRender = false;
}
bool LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector<LLVector3>& fp, LLVector3 light_dir)
@@ -10111,6 +10181,29 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND,
LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK,
LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE,
+ LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_SIMPLE_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_BUMP_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_SHINY_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_MATERIAL_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_SPECMAP_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_SPECMAP_BLEND_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_SPECMAP_MASK_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_SPECMAP_EMISSIVE_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_NORMMAP_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_NORMMAP_BLEND_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_NORMMAP_MASK_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_NORMMAP_EMISSIVE_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_NORMSPEC_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_NORMSPEC_BLEND_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED,
+ LLPipeline::RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED,
END_RENDER_TYPES);
gGL.setColorMask(false, false);
@@ -10837,6 +10930,21 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool textu
}
}
+void LLPipeline::renderRiggedGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture)
+{
+ for (LLCullResult::sg_iterator i = sCull->beginVisibleGroups(); i != sCull->endVisibleGroups(); ++i)
+ {
+ LLSpatialGroup* group = *i;
+ if (!group->isDead() &&
+ (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) &&
+ gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) &&
+ group->mDrawMap.find(type) != group->mDrawMap.end())
+ {
+ pass->renderRiggedGroup(group, type, mask, texture);
+ }
+ }
+}
+
static LLTrace::BlockTimerStatHandle FTM_GENERATE_IMPOSTOR("Generate Impostor");
void LLPipeline::generateImpostor(LLVOAvatar* avatar)
@@ -10872,37 +10980,31 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)
if (visually_muted || too_complex)
{
+ // only show jelly doll geometry
andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR,
LLPipeline::RENDER_TYPE_CONTROL_AV,
END_RENDER_TYPES);
}
else
{
- andRenderTypeMask(LLPipeline::RENDER_TYPE_ALPHA,
- LLPipeline::RENDER_TYPE_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_VOLUME,
- LLPipeline::RENDER_TYPE_GLOW,
- LLPipeline::RENDER_TYPE_BUMP,
- LLPipeline::RENDER_TYPE_PASS_SIMPLE,
- LLPipeline::RENDER_TYPE_PASS_ALPHA,
- LLPipeline::RENDER_TYPE_PASS_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_BUMP,
- LLPipeline::RENDER_TYPE_PASS_POST_BUMP,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_PASS_FULLBRIGHT_SHINY,
- LLPipeline::RENDER_TYPE_PASS_GLOW,
- LLPipeline::RENDER_TYPE_PASS_GRASS,
- LLPipeline::RENDER_TYPE_PASS_SHINY,
- LLPipeline::RENDER_TYPE_PASS_INVISIBLE,
- LLPipeline::RENDER_TYPE_PASS_INVISI_SHINY,
- LLPipeline::RENDER_TYPE_AVATAR,
- LLPipeline::RENDER_TYPE_CONTROL_AV,
- LLPipeline::RENDER_TYPE_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_FULLBRIGHT_ALPHA_MASK,
- LLPipeline::RENDER_TYPE_INVISIBLE,
- LLPipeline::RENDER_TYPE_SIMPLE,
- END_RENDER_TYPES);
+ //hide world geometry
+ clearRenderTypeMask(
+ RENDER_TYPE_SKY,
+ RENDER_TYPE_WL_SKY,
+ RENDER_TYPE_GROUND,
+ RENDER_TYPE_TERRAIN,
+ RENDER_TYPE_GRASS,
+ RENDER_TYPE_CONTROL_AV, // Animesh
+ RENDER_TYPE_TREE,
+ RENDER_TYPE_VOIDWATER,
+ RENDER_TYPE_WATER,
+ RENDER_TYPE_PASS_GRASS,
+ RENDER_TYPE_HUD,
+ RENDER_TYPE_PARTICLES,
+ RENDER_TYPE_CLOUDS,
+ RENDER_TYPE_HUD_PARTICLES,
+ END_RENDER_TYPES
+ );
}
S32 occlusion = sUseOcclusion;
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index b87a726647..110df8c979 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -266,11 +266,13 @@ public:
void touchTextures(LLDrawInfo* info);
void forAllVisibleDrawables(void (*func)(LLDrawable*));
- void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false);
- void renderMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false);
- void renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false);
+ void renderObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);
+ void renderAlphaObjects(U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);
+ void renderMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);
+ void renderFullbrightMaskedObjects(U32 type, U32 mask, bool texture = true, bool batch_texture = false, bool rigged = false);
void renderGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture);
+ void renderRiggedGroups(LLRenderPass* pass, U32 type, U32 mask, bool texture);
void grabReferences(LLCullResult& result);
void clearReferences();
@@ -457,34 +459,61 @@ public:
RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA,
RENDER_TYPE_GLOW = LLDrawPool::POOL_GLOW,
RENDER_TYPE_PASS_SIMPLE = LLRenderPass::PASS_SIMPLE,
+ RENDER_TYPE_PASS_SIMPLE_RIGGED = LLRenderPass::PASS_SIMPLE_RIGGED,
RENDER_TYPE_PASS_GRASS = LLRenderPass::PASS_GRASS,
RENDER_TYPE_PASS_FULLBRIGHT = LLRenderPass::PASS_FULLBRIGHT,
+ RENDER_TYPE_PASS_FULLBRIGHT_RIGGED = LLRenderPass::PASS_FULLBRIGHT,
RENDER_TYPE_PASS_INVISIBLE = LLRenderPass::PASS_INVISIBLE,
+ RENDER_TYPE_PASS_INVISIBLE_RIGGED = LLRenderPass::PASS_INVISIBLE_RIGGED,
RENDER_TYPE_PASS_INVISI_SHINY = LLRenderPass::PASS_INVISI_SHINY,
+ RENDER_TYPE_PASS_INVISI_SHINY_RIGGED = LLRenderPass::PASS_INVISI_SHINY_RIGGED,
RENDER_TYPE_PASS_FULLBRIGHT_SHINY = LLRenderPass::PASS_FULLBRIGHT_SHINY,
+ RENDER_TYPE_PASS_FULLBRIGHT_SHINY_RIGGED = LLRenderPass::PASS_FULLBRIGHT_SHINY_RIGGED,
RENDER_TYPE_PASS_SHINY = LLRenderPass::PASS_SHINY,
+ RENDER_TYPE_PASS_SHINY_RIGGED = LLRenderPass::PASS_SHINY_RIGGED,
RENDER_TYPE_PASS_BUMP = LLRenderPass::PASS_BUMP,
+ RENDER_TYPE_PASS_BUMP_RIGGED = LLRenderPass::PASS_BUMP_RIGGED,
RENDER_TYPE_PASS_POST_BUMP = LLRenderPass::PASS_POST_BUMP,
+ RENDER_TYPE_PASS_POST_BUMP_RIGGED = LLRenderPass::PASS_POST_BUMP_RIGGED,
RENDER_TYPE_PASS_GLOW = LLRenderPass::PASS_GLOW,
+ RENDER_TYPE_PASS_GLOW_RIGGED = LLRenderPass::PASS_GLOW_RIGGED,
RENDER_TYPE_PASS_ALPHA = LLRenderPass::PASS_ALPHA,
RENDER_TYPE_PASS_ALPHA_MASK = LLRenderPass::PASS_ALPHA_MASK,
+ RENDER_TYPE_PASS_ALPHA_MASK_RIGGED = LLRenderPass::PASS_ALPHA_MASK_RIGGED,
RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK,
+ RENDER_TYPE_PASS_FULLBRIGHT_ALPHA_MASK_RIGGED = LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK_RIGGED,
RENDER_TYPE_PASS_MATERIAL = LLRenderPass::PASS_MATERIAL,
+ RENDER_TYPE_PASS_MATERIAL_RIGGED = LLRenderPass::PASS_MATERIAL_RIGGED,
RENDER_TYPE_PASS_MATERIAL_ALPHA = LLRenderPass::PASS_MATERIAL_ALPHA,
+ RENDER_TYPE_PASS_MATERIAL_ALPHA_RIGGED = LLRenderPass::PASS_MATERIAL_ALPHA_RIGGED,
RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK = LLRenderPass::PASS_MATERIAL_ALPHA_MASK,
+ RENDER_TYPE_PASS_MATERIAL_ALPHA_MASK_RIGGED = LLRenderPass::PASS_MATERIAL_ALPHA_MASK_RIGGED,
RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE= LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE,
+ RENDER_TYPE_PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED = LLRenderPass::PASS_MATERIAL_ALPHA_EMISSIVE_RIGGED,
RENDER_TYPE_PASS_SPECMAP = LLRenderPass::PASS_SPECMAP,
+ RENDER_TYPE_PASS_SPECMAP_RIGGED = LLRenderPass::PASS_SPECMAP_RIGGED,
RENDER_TYPE_PASS_SPECMAP_BLEND = LLRenderPass::PASS_SPECMAP_BLEND,
+ RENDER_TYPE_PASS_SPECMAP_BLEND_RIGGED = LLRenderPass::PASS_SPECMAP_BLEND_RIGGED,
RENDER_TYPE_PASS_SPECMAP_MASK = LLRenderPass::PASS_SPECMAP_MASK,
+ RENDER_TYPE_PASS_SPECMAP_MASK_RIGGED = LLRenderPass::PASS_SPECMAP_MASK_RIGGED,
RENDER_TYPE_PASS_SPECMAP_EMISSIVE = LLRenderPass::PASS_SPECMAP_EMISSIVE,
+ RENDER_TYPE_PASS_SPECMAP_EMISSIVE_RIGGED = LLRenderPass::PASS_SPECMAP_EMISSIVE_RIGGED,
RENDER_TYPE_PASS_NORMMAP = LLRenderPass::PASS_NORMMAP,
+ RENDER_TYPE_PASS_NORMMAP_RIGGED = LLRenderPass::PASS_NORMMAP_RIGGED,
RENDER_TYPE_PASS_NORMMAP_BLEND = LLRenderPass::PASS_NORMMAP_BLEND,
+ RENDER_TYPE_PASS_NORMMAP_BLEND_RIGGED = LLRenderPass::PASS_NORMMAP_BLEND_RIGGED,
RENDER_TYPE_PASS_NORMMAP_MASK = LLRenderPass::PASS_NORMMAP_MASK,
+ RENDER_TYPE_PASS_NORMMAP_MASK_RIGGED = LLRenderPass::PASS_NORMMAP_MASK_RIGGED,
RENDER_TYPE_PASS_NORMMAP_EMISSIVE = LLRenderPass::PASS_NORMMAP_EMISSIVE,
+ RENDER_TYPE_PASS_NORMMAP_EMISSIVE_RIGGED = LLRenderPass::PASS_NORMMAP_EMISSIVE_RIGGED,
RENDER_TYPE_PASS_NORMSPEC = LLRenderPass::PASS_NORMSPEC,
+ RENDER_TYPE_PASS_NORMSPEC_RIGGED = LLRenderPass::PASS_NORMSPEC_RIGGED,
RENDER_TYPE_PASS_NORMSPEC_BLEND = LLRenderPass::PASS_NORMSPEC_BLEND,
+ RENDER_TYPE_PASS_NORMSPEC_BLEND_RIGGED = LLRenderPass::PASS_NORMSPEC_BLEND_RIGGED,
RENDER_TYPE_PASS_NORMSPEC_MASK = LLRenderPass::PASS_NORMSPEC_MASK,
+ RENDER_TYPE_PASS_NORMSPEC_MASK_RIGGED = LLRenderPass::PASS_NORMSPEC_MASK_RIGGED,
RENDER_TYPE_PASS_NORMSPEC_EMISSIVE = LLRenderPass::PASS_NORMSPEC_EMISSIVE,
+ RENDER_TYPE_PASS_NORMSPEC_EMISSIVE_RIGGED = LLRenderPass::PASS_NORMSPEC_EMISSIVE_RIGGED,
// Following are object types (only used in drawable mRenderType)
RENDER_TYPE_HUD = LLRenderPass::NUM_RENDER_TYPES,
RENDER_TYPE_VOLUME,
diff --git a/indra/newview/skins/default/xui/en/menu_inventory.xml b/indra/newview/skins/default/xui/en/menu_inventory.xml
index 5a35bbf121..78ca170813 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -815,6 +815,14 @@
function="Inventory.DoToSelected"
parameter="save_as" />
</menu_item_call>
+ <menu_item_call
+ label="Save Selected As"
+ layout="topleft"
+ name="Save Selected As">
+ <menu_item_call.on_click
+ function="Inventory.DoToSelected"
+ parameter="save_selected_as" />
+ </menu_item_call>
<menu_item_separator
layout="topleft"
name="Wearable And Object Separator"/>
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_move.xml b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
index 8794e3bf95..864223e616 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_move.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_move.xml
@@ -259,6 +259,15 @@
<combo_box.commit_callback
function="Pref.ClickActionChange"/>
</combo_box>
+ <check_box
+ control_name="EnableCollisionSounds"
+ height="20"
+ label="Play sound on collisions"
+ layout="topleft"
+ left="83"
+ name="sound_on_collisions"
+ top_pad="10"
+ width="200" />
<button
height="23"
label="Other Devices"
diff --git a/indra/newview/slplugin.entitlements b/indra/newview/slplugin.entitlements
index a1c430a57a..a72c6bc82c 100644
--- a/indra/newview/slplugin.entitlements
+++ b/indra/newview/slplugin.entitlements
@@ -4,5 +4,13 @@
<dict>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
+ <key>com.apple.security.automation.apple-events</key>
+ <true/>
+ <key>com.apple.security.cs.allow-jit</key>
+ <true/>
+ <key>com.apple.security.cs.disable-library-validation</key>
+ <true/>
+ <key>com.apple.security.cs.allow-dyld-environment-variables</key>
+ <true/>
</dict>
</plist>
diff --git a/indra/newview/tests/gpus_results.txt b/indra/newview/tests/gpus_results.txt
index 106593afd5..3b3fb1aeb6 100644
--- a/indra/newview/tests/gpus_results.txt
+++ b/indra/newview/tests/gpus_results.txt
@@ -1487,8 +1487,8 @@ Intel Open Source Technology Center Mesa DRI Intel(R) Sandybridge Desktop
Intel Open Source Technology Center Mesa DRI Intel(R) Sandybridge Desktop x86/MMX/SSE2 unsupported 1 1 3 Mesa
Intel Open Source Technology Center Mesa DRI Intel(R) Sandybridge Mobile unsupported 1 1 3 Mesa
Intel Open Source Technology Center Mesa DRI Intel(R) Sandybridge Mobile x86/MMX/SSE2 unsupported 1 1 3 Mesa
-Intel Open Source Technology Center Mesa DRI Mobile Intelå¨ GM45 Express Chipset unsupported 1 1 3 Mesa
-Intel Open Source Technology Center Mesa DRI Mobile Intelå¨ GM45 Express Chipset x86/MMX/SSE2 unsupported 1 1 3 Mesa
+Intel Open Source Technology Center Mesa DRI Mobile Intel(R) GM45 Express Chipset unsupported 1 1 3 Mesa
+Intel Open Source Technology Center Mesa DRI Mobile Intel(R) GM45 Express Chipset x86/MMX/SSE2 unsupported 1 1 3 Mesa
Intel Pineview supported 0 1 1.4 Intel Pineview
Intel Q45/Q43 supported 1 1 2.1 Intel Q45/Q43
Intel Royal BNA Driver unsupported 0 0 0 Intel Royal BNA
@@ -3012,11 +3012,11 @@ Tungsten Graphics, Inc Mesa DRI Intel(R) Sandybridge Mobile x86/MMX/SSE2
Tungsten Graphics, Inc Mesa DRI Intel(R) Sandybridge Mobile GEM 20100330 DEVELOPMENT x86/MMX/SSE2 unsupported 1 1 3 Mesa
Tungsten Graphics, Inc Mesa DRI Intel(R) Sandybridge Mobile x86/MMX/SSE2 unsupported 1 1 3 Mesa
Tungsten Graphics, Inc Mesa DRI Intel(R) Sandybridge Server unsupported 1 1 3 Mesa
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset unsupported 1 1 3 Mesa
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset GEM 20091221 2009Q4 supported 1 1 2.1 Intel Q45/Q43
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset GEM 20091221 2009Q4 x86/MMX/SSE2 supported 1 1 2.1 Intel Q45/Q43
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset GEM 20100330 DEVELOPMENT x86/MMX unsupported 1 1 3 Mesa
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset x86/MMX/SSE2 unsupported 1 1 3 Mesa
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset unsupported 1 1 3 Mesa
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset GEM 20091221 2009Q4 supported 1 1 2.1 Intel Q45/Q43
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset GEM 20091221 2009Q4 x86/MMX/SSE2 supported 1 1 2.1 Intel Q45/Q43
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset GEM 20100330 DEVELOPMENT x86/MMX unsupported 1 1 3 Mesa
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset x86/MMX/SSE2 unsupported 1 1 3 Mesa
Tungsten Graphics, Inc. Mesa DRI R100 (RS200 4437) x86/MMX/SSE2 NO-TCL DRI2 unsupported 1 1 3 Mesa
Tungsten Graphics, Inc. Mesa DRI R100 (RV200 4C57) TCL DRI2 unsupported 1 1 3 Mesa
Tungsten Graphics, Inc. Mesa DRI R100 (RV200 4C57) x86/MMX/SSE2 TCL DRI2 unsupported 1 1 3 Mesa
diff --git a/indra/newview/tests/gpus_seen.txt b/indra/newview/tests/gpus_seen.txt
index a417cb3761..66cbeece97 100644
--- a/indra/newview/tests/gpus_seen.txt
+++ b/indra/newview/tests/gpus_seen.txt
@@ -1954,8 +1954,8 @@ Intel Open Source Technology Center Mesa DRI Intel(R) Sandybridge Desktop x86/MM
Intel Open Source Technology Center Mesa DRI Intel(R) Sandybridge Mobile
Intel Open Source Technology Center Mesa DRI Intel(R) Sandybridge Mobile x86/MMX/SSE2
Intel Open Source Technology Center Mesa DRI Intel(R) Sandybridge Mobile x86/MMX/SSE2
-Intel Open Source Technology Center Mesa DRI Mobile Intelå¨ GM45 Express Chipset
-Intel Open Source Technology Center Mesa DRI Mobile Intelå¨ GM45 Express Chipset x86/MMX/SSE2
+Intel Open Source Technology Center Mesa DRI Mobile Intel(R) GM45 Express Chipset
+Intel Open Source Technology Center Mesa DRI Mobile Intel(R) GM45 Express Chipset x86/MMX/SSE2
Intel Pineview
Intel Q45/Q43
Intel Royal BNA Driver
@@ -4079,12 +4079,12 @@ Tungsten Graphics, Inc Mesa DRI Intel(R) Sandybridge Mobile GEM 20100330 DEVELOP
Tungsten Graphics, Inc Mesa DRI Intel(R) Sandybridge Mobile x86/MMX/SSE2
Tungsten Graphics, Inc Mesa DRI Intel(R) Sandybridge Mobile x86/MMX/SSE2
Tungsten Graphics, Inc Mesa DRI Intel(R) Sandybridge Server
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset GEM 20091221 2009Q4
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset GEM 20091221 2009Q4 x86/MMX/SSE2
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset GEM 20100330 DEVELOPMENT x86/MMX/SSE2
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset x86/MMX/SSE2
-Tungsten Graphics, Inc Mesa DRI Mobile Intelå¨ GM45 Express Chipset x86/MMX/SSE2
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset GEM 20091221 2009Q4
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset GEM 20091221 2009Q4 x86/MMX/SSE2
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset GEM 20100330 DEVELOPMENT x86/MMX/SSE2
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset x86/MMX/SSE2
+Tungsten Graphics, Inc Mesa DRI Mobile Intel(R) GM45 Express Chipset x86/MMX/SSE2
Tungsten Graphics, Inc. Mesa DRI R100 (RS200 4437) x86/MMX/SSE2 NO-TCL DRI2
Tungsten Graphics, Inc. Mesa DRI R100 (RV200 4C57) TCL DRI2
Tungsten Graphics, Inc. Mesa DRI R100 (RV200 4C57) x86/MMX/SSE2 TCL DRI2
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
index f9abc8b25d..8d1956957c 100644
--- a/indra/newview/tests/lllogininstance_test.cpp
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -308,6 +308,10 @@ S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)
memcpy(unique_id, gMACAddress, len);
return 1;
}
+S32 LLMachineID::getLegacyID(unsigned char *unique_id, size_t len)
+{
+ return 0;
+}
//-----------------------------------------------------------------------------
// misc
std::string xml_escape_string(const std::string& in)
diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp
index 4c8d6c51b0..da742370fc 100644
--- a/indra/newview/tests/llsechandler_basic_test.cpp
+++ b/indra/newview/tests/llsechandler_basic_test.cpp
@@ -121,6 +121,10 @@ S32 LLMachineID::getUniqueID(unsigned char *unique_id, size_t len)
memcpy(unique_id, gMACAddress, len);
return 1;
}
+S32 LLMachineID::getLegacyID(unsigned char *unique_id, size_t len)
+{
+ return 0;
+}
S32 LLMachineID::init() { return 1; }
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index b932f43141..6fcd1e84e8 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -1176,8 +1176,10 @@ class DarwinManifest(ViewerManifest):
[newpath, self.dst_path_of(dylibexecutable)])
# copy LibVLC plugin itself
- self.path2basename("../media_plugins/libvlc/" + self.args['configuration'],
- "media_plugin_libvlc.dylib")
+ dylibexecutable = 'media_plugin_libvlc.dylib'
+ self.path2basename("../media_plugins/libvlc/" + self.args['configuration'], dylibexecutable)
+ # add @rpath for the correct LibVLC subfolder
+ self.run_command(['install_name_tool', '-add_rpath', '@loader_path/lib', self.dst_path_of(dylibexecutable)])
# copy LibVLC dynamic libraries
with self.prefix(src=relpkgdir, dst="lib"):
@@ -1309,7 +1311,7 @@ class DarwinManifest(ViewerManifest):
self.run_command(['codesign', '--force', '--timestamp', '--keychain', viewer_keychain, '--sign', identity, cef_path])
self.run_command(['codesign', '--force', '--timestamp', '--keychain', viewer_keychain, '--sign', identity, greenlet_path])
self.run_command(['codesign', '--verbose', '--deep', '--force', '--entitlements', self.src_path_of("slplugin.entitlements"), '--options', 'runtime', '--keychain', viewer_keychain, '--sign', identity, slplugin_path])
- self.run_command(['codesign', '--verbose', '--deep', '--force', '--options', 'runtime', '--keychain', viewer_keychain, '--sign', identity, app_in_dmg])
+ self.run_command(['codesign', '--verbose', '--deep', '--force', '--entitlements', self.src_path_of("slplugin.entitlements"), '--options', 'runtime', '--keychain', viewer_keychain, '--sign', identity, app_in_dmg])
signed=True # if no exception was raised, the codesign worked
except ManifestError as err:
if sign_attempts: