summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/cmake/CMakeLists.txt1
-rw-r--r--indra/cmake/LLCommon.cmake2
-rw-r--r--indra/cmake/XmlRpcEpi.cmake11
-rw-r--r--indra/llcommon/llfile.cpp18
-rw-r--r--indra/llcommon/llfile.h2
-rw-r--r--indra/llcommon/llmemory.cpp42
-rw-r--r--indra/llcommon/llsd.cpp201
-rw-r--r--indra/llcommon/llsd.h20
-rw-r--r--indra/llcommon/llstring.cpp69
-rw-r--r--indra/llcommon/llstring.h14
-rw-r--r--indra/llmessage/CMakeLists.txt3
-rw-r--r--indra/llmessage/llfiltersd2xmlrpc.cpp778
-rw-r--r--indra/llmessage/llfiltersd2xmlrpc.h271
-rw-r--r--indra/llrender/llgltexture.cpp21
-rw-r--r--indra/llrender/llgltexture.h6
-rw-r--r--indra/llrender/llimagegl.cpp260
-rw-r--r--indra/llrender/llimagegl.h35
-rw-r--r--indra/llui/llaccordionctrl.cpp8
-rw-r--r--indra/llui/llaccordionctrltab.cpp6
-rw-r--r--indra/llui/llflatlistview.cpp49
-rw-r--r--indra/llwebrtc/llwebrtc.cpp20
-rw-r--r--indra/llwebrtc/llwebrtc.h1
-rw-r--r--indra/llwebrtc/llwebrtc_impl.h5
-rw-r--r--indra/llxml/llxmlnode.cpp39
-rw-r--r--indra/llxml/llxmlnode.h12
-rw-r--r--indra/newview/CMakeLists.txt6
-rw-r--r--indra/newview/app_settings/settings.xml24
-rw-r--r--indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl41
-rw-r--r--indra/newview/gltf/buffer_util.h10
-rw-r--r--indra/newview/gltfscenemanager.cpp5
-rw-r--r--indra/newview/llcurrencyuimanager.cpp137
-rw-r--r--indra/newview/lldebugview.cpp6
-rw-r--r--indra/newview/lldrawpoolbump.cpp388
-rw-r--r--indra/newview/lldrawpoolbump.h5
-rw-r--r--indra/newview/llfloateravatar.cpp5
-rw-r--r--indra/newview/llfloaterbuyland.cpp201
-rw-r--r--indra/newview/llfloaterchangeitemthumbnail.cpp22
-rw-r--r--indra/newview/llfloaterdestinations.cpp5
-rw-r--r--indra/newview/llfloaterfonttest.cpp5
-rw-r--r--indra/newview/llfloatergltfasseteditor.cpp527
-rw-r--r--indra/newview/llfloatergltfasseteditor.h101
-rw-r--r--indra/newview/llgltffolderitem.cpp164
-rw-r--r--indra/newview/llgltffolderitem.h128
-rw-r--r--indra/newview/llgltffoldermodel.cpp73
-rw-r--r--indra/newview/llgltffoldermodel.h91
-rw-r--r--indra/newview/llheroprobemanager.cpp7
-rw-r--r--indra/newview/llimview.cpp8
-rw-r--r--indra/newview/lllocalbitmaps.cpp1
-rw-r--r--indra/newview/lllogininstance.cpp5
-rw-r--r--indra/newview/llnetmap.cpp20
-rw-r--r--indra/newview/llslurl.cpp6
-rw-r--r--indra/newview/llsurface.cpp169
-rw-r--r--indra/newview/llsurface.h11
-rw-r--r--indra/newview/llsurfacepatch.cpp9
-rw-r--r--indra/newview/lltextureview.cpp67
-rw-r--r--indra/newview/llversioninfo.cpp22
-rw-r--r--indra/newview/llversioninfo.h26
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp65
-rw-r--r--indra/newview/llviewermenu.cpp29
-rw-r--r--indra/newview/llviewerobject.cpp4
-rwxr-xr-xindra/newview/llviewerregion.cpp6
-rw-r--r--indra/newview/llviewerregion.h2
-rw-r--r--indra/newview/llviewertexture.cpp360
-rw-r--r--indra/newview/llviewertexture.h26
-rw-r--r--indra/newview/llviewertexturelist.cpp24
-rw-r--r--indra/newview/llviewertexturelist.h18
-rw-r--r--indra/newview/llviewerwindow.cpp134
-rw-r--r--indra/newview/llviewerwindow.h9
-rw-r--r--indra/newview/llvlcomposition.cpp412
-rw-r--r--indra/newview/llvlcomposition.h2
-rw-r--r--indra/newview/llvoicechannel.cpp12
-rw-r--r--indra/newview/llvoiceclient.cpp33
-rw-r--r--indra/newview/llvoiceclient.h3
-rw-r--r--indra/newview/llvoicevivox.cpp18
-rw-r--r--indra/newview/llvoicewebrtc.cpp32
-rw-r--r--indra/newview/llvoicewebrtc.h5
-rw-r--r--indra/newview/llvovolume.cpp37
-rw-r--r--indra/newview/llvowater.cpp15
-rw-r--r--indra/newview/llvowater.h3
-rw-r--r--indra/newview/llworld.cpp2
-rw-r--r--indra/newview/llworldmipmap.cpp1
-rw-r--r--indra/newview/llworldmipmap.h6
-rw-r--r--indra/newview/llxmlrpclistener.cpp278
-rw-r--r--indra/newview/llxmlrpclistener.h3
-rw-r--r--indra/newview/llxmlrpctransaction.cpp361
-rw-r--r--indra/newview/llxmlrpctransaction.h92
-rw-r--r--indra/newview/skins/default/xui/da/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/de/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/de/menu_viewer.xml6
-rw-r--r--indra/newview/skins/default/xui/en/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_gltf_asset_editor.xml284
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml44
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml14
-rw-r--r--indra/newview/skins/default/xui/es/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/es/menu_viewer.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/it/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/it/menu_viewer.xml6
-rw-r--r--indra/newview/skins/default/xui/ja/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/ja/menu_viewer.xml1
-rw-r--r--indra/newview/skins/default/xui/pl/menu_viewer.xml5
-rw-r--r--indra/newview/skins/default/xui/pt/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/pt/menu_viewer.xml6
-rw-r--r--indra/newview/skins/default/xui/ru/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/ru/menu_viewer.xml6
-rw-r--r--indra/newview/skins/default/xui/tr/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/tr/menu_viewer.xml6
-rw-r--r--indra/newview/skins/default/xui/zh/floater_about.xml1
-rw-r--r--indra/newview/skins/default/xui/zh/menu_viewer.xml6
-rw-r--r--indra/viewer_components/login/lllogin.cpp41
111 files changed, 2792 insertions, 3833 deletions
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index 0f338931c0..c067105f68 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -63,7 +63,6 @@ set(cmake_SOURCE_FILES
VisualLeakDetector.cmake
LibVLCPlugin.cmake
WebRTC.cmake
- XmlRpcEpi.cmake
xxHash.cmake
ZLIBNG.cmake
)
diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake
index 9e3707ff17..dd43ca4916 100644
--- a/indra/cmake/LLCommon.cmake
+++ b/indra/cmake/LLCommon.cmake
@@ -6,5 +6,3 @@ include(EXPAT)
include(Tracy)
include(xxHash)
include(ZLIBNG)
-
-include(XmlRpcEpi)
diff --git a/indra/cmake/XmlRpcEpi.cmake b/indra/cmake/XmlRpcEpi.cmake
deleted file mode 100644
index 6409f9d6e2..0000000000
--- a/indra/cmake/XmlRpcEpi.cmake
+++ /dev/null
@@ -1,11 +0,0 @@
-# -*- cmake -*-
-include(Prebuilt)
-
-include_guard()
-add_library( ll::xmlrpc-epi INTERFACE IMPORTED )
-
-use_system_binary( xmlrpc-epi )
-
-use_prebuilt_binary(xmlrpc-epi)
-target_link_libraries(ll::xmlrpc-epi INTERFACE xmlrpc-epi )
-target_include_directories( ll::xmlrpc-epi SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index ddf239f306..9045324bf2 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -248,6 +248,24 @@ int LLFile::close(LLFILE * file)
return ret_value;
}
+std::string LLFile::getContents(const std::string& filename)
+{
+ LLFILE* fp = fopen(filename, "rb"); /* Flawfinder: ignore */
+ if (fp)
+ {
+ fseek(fp, 0, SEEK_END);
+ U32 length = ftell(fp);
+ fseek(fp, 0, SEEK_SET);
+
+ std::vector<char> buffer(length);
+ size_t nread = fread(buffer.data(), 1, length, fp);
+ fclose(fp);
+
+ return std::string(buffer.data(), nread);
+ }
+
+ return LLStringUtil::null;
+}
int LLFile::remove(const std::string& filename, int supress_error)
{
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 2564671b13..74110343fc 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -67,6 +67,8 @@ public:
static int close(LLFILE * file);
+ static std::string getContents(const std::string& filename);
+
// perms is a permissions mask like 0777 or 0700. In most cases it will
// be overridden by the user's umask. It is ignored on Windows.
// mkdir() considers "directory already exists" to be SUCCESS.
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 4b7d60d654..104c40f0d7 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -39,6 +39,7 @@
#elif LL_LINUX
# include <unistd.h>
# include <sys/resource.h>
+# include <sys/sysinfo.h>
#endif
#include "llmemory.h"
@@ -85,6 +86,7 @@ void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size)
void LLMemory::updateMemoryInfo()
{
LL_PROFILE_ZONE_SCOPED
+ U32Kilobytes avail_phys;
#if LL_WINDOWS
PROCESS_MEMORY_COUNTERS counters;
@@ -95,22 +97,10 @@ void LLMemory::updateMemoryInfo()
}
sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(counters.WorkingSetSize));
- sample(sAllocatedMem, sAllocatedMemInKB);
sAllocatedPageSizeInKB = U32Kilobytes::convert(U64Bytes(counters.PagefileUsage));
sample(sVirtualMem, sAllocatedPageSizeInKB);
-
- U32Kilobytes avail_phys, avail_virtual;
+ U32Kilobytes avail_virtual;
LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
- sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
-
- if(sMaxPhysicalMemInKB > sAllocatedMemInKB)
- {
- sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ;
- }
- else
- {
- sAvailPhysicalMemInKB = U32Kilobytes(0);
- }
#elif defined(LL_DARWIN)
task_vm_info info;
@@ -147,21 +137,39 @@ void LLMemory::updateMemoryInfo()
if (result == KERN_SUCCESS) {
// This is what Chrome reports as 'the "Physical Memory Free" value reported by the Memory Monitor in Instruments.'
// Note though that inactive pages are not included here and not yet free, but could become so under memory pressure.
- sAvailPhysicalMemInKB = U32Bytes(vmstat.free_count * page_size);
- sMaxPhysicalMemInKB = LLMemoryInfo::getHardwareMemSize();
- }
+ avail_phys = U32Bytes(vmstat.free_count * page_size);
+ sMaxHeapSizeInKB = LLMemoryInfo::getHardwareMemSize();
+ }
else
{
LL_WARNS() << "task_info failed" << LL_ENDL;
}
-
+#elif defined(LL_LINUX)
+ // Use sysinfo() to get the total physical memory.
+ struct sysinfo info;
+ sysinfo(&info);
+ sMaxHeapSizeInKB = U32Kilobytes::convert((U64Bytes)info.totalram); // Total RAM in system
+ avail_phys = U32Kilobytes::convert((U64Bytes)info.freeram); // Total Free RAM in system
+ sAllocatedMemInKB = U32Kilobytes::convert(U64Bytes(LLMemory::getCurrentRSS())); // represents the RAM allocated by this process only (in line with the windows implementation)
#else
//not valid for other systems for now.
+ LL_WARNS() << "LLMemory::updateMemoryInfo() not implemented for this platform." << LL_ENDL;
sAllocatedMemInKB = U64Bytes(LLMemory::getCurrentRSS());
sMaxPhysicalMemInKB = U64Bytes(U32_MAX);
sAvailPhysicalMemInKB = U64Bytes(U32_MAX);
#endif
+ sample(sAllocatedMem, sAllocatedMemInKB);
+ // sMaxPhysicalMem - max this process can use = the lesser of (what we already have + what's available) or MaxHeap
+ sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
+ if(sMaxPhysicalMemInKB > sAllocatedMemInKB)
+ {
+ sAvailPhysicalMemInKB = sMaxPhysicalMemInKB - sAllocatedMemInKB ;
+ }
+ else
+ {
+ sAvailPhysicalMemInKB = U32Kilobytes(0);
+ }
return ;
}
diff --git a/indra/llcommon/llsd.cpp b/indra/llcommon/llsd.cpp
index 663ceac22b..b36ff7d263 100644
--- a/indra/llcommon/llsd.cpp
+++ b/indra/llcommon/llsd.cpp
@@ -30,6 +30,7 @@
#include "linden_common.h"
#include "llsd.h"
+#include "llbase64.h"
#include "llerror.h"
#include "../llmath/llmath.h"
#include "llformat.h"
@@ -142,6 +143,8 @@ public:
virtual const String& asStringRef() const { static const std::string empty; return empty; }
+ virtual String asXMLRPCValue() const { return "<nil/>"; }
+
virtual bool has(const String&) const { return false; }
virtual LLSD get(const String&) const { return LLSD(); }
virtual LLSD getKeys() const { return LLSD::emptyArray(); }
@@ -222,6 +225,8 @@ namespace
virtual LLSD::Integer asInteger() const { return mValue ? 1 : 0; }
virtual LLSD::Real asReal() const { return mValue ? 1 : 0; }
virtual LLSD::String asString() const;
+
+ virtual LLSD::String asXMLRPCValue() const { return mValue ? "<boolean>1</boolean>" : "<boolean>0</boolean>"; }
};
LLSD::String ImplBoolean::asString() const
@@ -243,6 +248,8 @@ namespace
virtual LLSD::Integer asInteger() const { return mValue; }
virtual LLSD::Real asReal() const { return mValue; }
virtual LLSD::String asString() const;
+
+ virtual LLSD::String asXMLRPCValue() const { return "<int>" + std::to_string(mValue) + "</int>"; }
};
LLSD::String ImplInteger::asString() const
@@ -259,6 +266,8 @@ namespace
virtual LLSD::Integer asInteger() const;
virtual LLSD::Real asReal() const { return mValue; }
virtual LLSD::String asString() const;
+
+ virtual LLSD::String asXMLRPCValue() const { return "<double>" + std::to_string(mValue) + "</double>"; }
};
LLSD::Boolean ImplReal::asBoolean() const
@@ -286,9 +295,11 @@ namespace
virtual LLSD::URI asURI() const { return LLURI(mValue); }
virtual size_t size() const { return mValue.size(); }
virtual const LLSD::String& asStringRef() const { return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<string>" + LLStringFn::xml_encode(mValue) + "</string>"; }
};
- LLSD::Integer ImplString::asInteger() const
+ LLSD::Integer ImplString::asInteger() const
{
// This must treat "1.23" not as an error, but as a number, which is
// then truncated down to an integer. Hence, this code doesn't call
@@ -298,7 +309,7 @@ namespace
return (int)asReal();
}
- LLSD::Real ImplString::asReal() const
+ LLSD::Real ImplString::asReal() const
{
F64 v = 0.0;
std::istringstream i_stream(mValue);
@@ -323,6 +334,8 @@ namespace
virtual LLSD::String asString() const{ return mValue.asString(); }
virtual LLSD::UUID asUUID() const { return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<string>" + mValue.asString() + "</string>"; }
};
@@ -344,6 +357,8 @@ namespace
}
virtual LLSD::String asString() const{ return mValue.asString(); }
virtual LLSD::Date asDate() const { return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<dateTime.iso8601>" + mValue.toHTTPDateString("%FT%T") + "</dateTime.iso8601>"; }
};
@@ -355,6 +370,8 @@ namespace
virtual LLSD::String asString() const{ return mValue.asString(); }
virtual LLSD::URI asURI() const { return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<string>" + LLStringFn::xml_encode(mValue.asString()) + "</string>"; }
};
@@ -365,13 +382,15 @@ namespace
ImplBinary(const LLSD::Binary& v) : Base(v) { }
virtual const LLSD::Binary& asBinary() const{ return mValue; }
+
+ virtual LLSD::String asXMLRPCValue() const { return "<base64>" + LLBase64::encode(mValue.data(), mValue.size()) + "</base64>"; }
};
class ImplMap : public LLSD::Impl
{
private:
- typedef std::map<LLSD::String, LLSD> DataMap;
+ typedef std::map<LLSD::String, LLSD> DataMap;
DataMap mData;
@@ -387,6 +406,19 @@ namespace
virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
+ virtual LLSD::String asXMLRPCValue() const
+ {
+ std::ostringstream os;
+ os << "<struct>";
+ for (const auto& it : mData)
+ {
+ os << "<member><name>" << LLStringFn::xml_encode(it.first) << "</name>"
+ << it.second.asXMLRPCValue() << "</member>";
+ }
+ os << "</struct>";
+ return os.str();
+ }
+
virtual bool has(const LLSD::String&) const;
using LLSD::Impl::get; // Unhiding get(size_t)
@@ -511,7 +543,7 @@ namespace
class ImplArray : public LLSD::Impl
{
private:
- typedef std::vector<LLSD> DataVector;
+ typedef std::vector<LLSD> DataVector;
DataVector mData;
@@ -527,6 +559,18 @@ namespace
virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
+ virtual LLSD::String asXMLRPCValue() const
+ {
+ std::ostringstream os;
+ os << "<array><data>";
+ for (const auto& it : mData)
+ {
+ os << it.asXMLRPCValue();
+ }
+ os << "</data></array>";
+ return os.str();
+ }
+
using LLSD::Impl::get; // Unhiding get(LLSD::String)
using LLSD::Impl::erase; // Unhiding erase(LLSD::String)
using LLSD::Impl::ref; // Unhiding ref(LLSD::String)
@@ -872,6 +916,155 @@ const LLSD::Binary& LLSD::asBinary() const { return safe(impl).asBinary(); }
const LLSD::String& LLSD::asStringRef() const { return safe(impl).asStringRef(); }
+LLSD::String LLSD::asXMLRPCValue() const { return "<value>" + safe(impl).asXMLRPCValue() + "</value>"; }
+
+static bool inline check(bool condition, const char* warning_message)
+{
+ if (!condition)
+ {
+ LL_WARNS() << warning_message << LL_ENDL;
+ }
+
+ return condition;
+}
+
+static bool parseXMLRPCArrayValue(LLSD& target, LLSD::TreeNode* node)
+{
+ LLSD::TreeNode* data = node->getFirstChild();
+ if (!check(data, "No array inner XML element (<data> expected)") ||
+ !check(data->hasName("data"), "Invalid array inner XML element (<data> expected)") ||
+ !check(!data->getNextSibling(), "Multiple array inner XML elements (single <data> expected)"))
+ return false;
+
+ for (LLSD::TreeNode* item = data->getFirstChild(); item; item = item->getNextSibling())
+ {
+ LLSD value;
+ if (!value.fromXMLRPCValue(item))
+ return false;
+
+ target.append(value);
+ }
+
+ return true;
+}
+
+static bool parseXMLRPCStructValue(LLSD& target, LLSD::TreeNode* node)
+{
+ for (LLSD::TreeNode* item = node->getFirstChild(); item; item = item->getNextSibling())
+ {
+ if (!check(item->hasName("member"), "Invalid struct inner XML element (<member> expected)"))
+ return false;
+
+ std::string name;
+ LLSD value;
+ for (LLSD::TreeNode* subitem = item->getFirstChild(); subitem; subitem = subitem->getNextSibling())
+ {
+ if (subitem->hasName("name"))
+ {
+ name = LLStringFn::xml_decode(subitem->getTextContents());
+ }
+ else if (!value.fromXMLRPCValue(subitem))
+ {
+ return false;
+ }
+ }
+ if (!check(!name.empty(), "Empty struct member name"))
+ return false;
+
+ target.insert(name, value);
+ }
+
+ return true;
+}
+
+bool LLSD::fromXMLRPCValue(TreeNode* node)
+{
+ clear();
+
+ llassert(node);
+ if (!node)
+ return false;
+
+ if (!check(node->hasName("value"), "Invalid XML element (<value> expected)"))
+ return false;
+
+ TreeNode* inner = node->getFirstChild();
+ if (!inner)
+ {
+ check(false, "No inner XML element (value type expected)");
+ // Value with no type qualifier is treated as string
+ assign(LLStringFn::xml_decode(node->getTextContents()));
+ return true;
+ }
+
+ if (!check(!inner->getNextSibling(), "Multiple inner XML elements (single expected)"))
+ return false;
+
+ if (inner->hasName("string"))
+ {
+ assign(LLStringFn::xml_decode(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("int") || inner->hasName("i4"))
+ {
+ assign(std::stoi(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("double"))
+ {
+ assign(std::stod(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("boolean"))
+ {
+ assign(!!std::stoi(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("dateTime.iso8601"))
+ {
+ assign(Date(inner->getTextContents()));
+ return true;
+ }
+
+ if (inner->hasName("base64"))
+ {
+ std::string decoded = LLBase64::decodeAsString(inner->getTextContents());
+ Binary binary(decoded.size());
+ memcpy(binary.data(), decoded.data(), decoded.size());
+ assign(binary);
+ return true;
+ }
+
+ if (inner->hasName("array"))
+ {
+ if (!parseXMLRPCArrayValue(*this, inner))
+ {
+ clear();
+ return false;
+ }
+ return true;
+ }
+
+ if (inner->hasName("struct"))
+ {
+ if (!parseXMLRPCStructValue(*this, inner))
+ {
+ clear();
+ return false;
+ }
+ return true;
+ }
+
+ check(false, "Unknown inner XML element (known value type expected)");
+ // Value with unknown type qualifier is treated as string
+ assign(LLStringFn::xml_decode(inner->getTextContents()));
+ return true;
+}
+
// const char * helpers
LLSD::LLSD(const char* v) : impl(0) { ALLOC_LLSD_OBJECT; assign(v); }
void LLSD::assign(const char* v)
diff --git a/indra/llcommon/llsd.h b/indra/llcommon/llsd.h
index a5e735b561..5532decfc3 100644
--- a/indra/llcommon/llsd.h
+++ b/indra/llcommon/llsd.h
@@ -259,10 +259,24 @@ public:
UUID asUUID() const;
Date asDate() const;
URI asURI() const;
- const Binary& asBinary() const;
+ const Binary& asBinary() const;
// asStringRef on any non-string type will return a ref to an empty string.
- const String& asStringRef() const;
+ const String& asStringRef() const;
+
+ // Return "<value><((type))>((scalar value or recursive calls))</((type))></value>"
+ // See http://xmlrpc.com/spec.md
+ String asXMLRPCValue() const;
+
+ struct TreeNode
+ {
+ virtual bool hasName(const String& name) const = 0;
+ virtual String getTextContents() const = 0;
+ virtual TreeNode* getFirstChild() const = 0;
+ virtual TreeNode* getNextSibling() const = 0;
+ };
+
+ bool fromXMLRPCValue(TreeNode* node);
operator Boolean() const { return asBoolean(); }
operator Integer() const { return asInteger(); }
@@ -275,7 +289,7 @@ public:
// This is needed because most platforms do not automatically
// convert the boolean negation as a bool in an if statement.
- bool operator!() const {return !asBoolean();}
+ bool operator!() const { return !asBoolean(); }
//@}
/** @name Character Pointer Helpers
diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp
index 514d73b24b..6f3d193d6b 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -1208,6 +1208,75 @@ namespace LLStringFn
return output;
}
+ using literals_t = std::map<char, std::string>;
+ static const literals_t xml_elem_literals =
+ {
+ { '<', "&lt;" },
+ { '>', "&gt;" },
+ { '&', "&amp;" }
+ };
+ static const literals_t xml_attr_literals =
+ {
+ { '"', "&quot;" },
+ { '\'', "&apos;" }
+ };
+
+ static void literals_encode(std::string& text, const literals_t& literals)
+ {
+ for (const std::pair<char, std::string> it : literals)
+ {
+ std::string::size_type pos = 0;
+ while ((pos = text.find(it.first, pos)) != std::string::npos)
+ {
+ text.replace(pos, 1, it.second);
+ pos += it.second.size();
+ }
+ }
+ }
+
+ static void literals_decode(std::string& text, const literals_t& literals)
+ {
+ for (const std::pair<char, std::string> it : literals)
+ {
+ std::string::size_type pos = 0;
+ while ((pos = text.find(it.second, pos)) != std::string::npos)
+ {
+ text[pos++] = it.first;
+ text.erase(pos, it.second.size() - 1);
+ }
+ }
+ }
+
+ /**
+ * @brief Replace all characters that are not allowed in XML 1.0
+ * with corresponding literals: [ < > & ] => [ &lt; &gt; &amp; ]
+ */
+ std::string xml_encode(const std::string& input, bool for_attribute)
+ {
+ std::string result(input);
+ literals_encode(result, xml_elem_literals);
+ if (for_attribute)
+ {
+ literals_encode(result, xml_attr_literals);
+ }
+ return result;
+ }
+
+ /**
+ * @brief Replace some of XML literals that are defined in XML 1.0
+ * with corresponding characters: [ &lt; &gt; &amp; ] => [ < > & ]
+ */
+ std::string xml_decode(const std::string& input, bool for_attribute)
+ {
+ std::string result(input);
+ literals_decode(result, xml_elem_literals);
+ if (for_attribute)
+ {
+ literals_decode(result, xml_attr_literals);
+ }
+ return result;
+ }
+
/**
* @brief Replace all control characters (c < 0x20) with replacement in
* string.
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 123f4184b5..b69a068830 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -890,6 +890,20 @@ namespace LLStringFn
/**
+ * @brief Replace all characters that are not allowed in XML 1.0
+ * with corresponding literals: [ < > & ] => [ &lt; &gt; &amp; ]
+ */
+ LL_COMMON_API std::string xml_encode(const std::string& input, bool for_attribute = false);
+
+
+ /**
+ * @brief Replace some of XML literals that are defined in XML 1.0
+ * with corresponding characters: [ &lt; &gt; &amp; ] => [ < > & ]
+ */
+ LL_COMMON_API std::string xml_decode(const std::string& input, bool for_attribute = false);
+
+
+ /**
* @brief Replace all control characters (0 <= c < 0x20) with replacement in
* string. This is safe for utf-8
*
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 5322139304..b2757a7306 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -27,7 +27,6 @@ set(llmessage_SOURCE_FILES
lldatapacker.cpp
lldispatcher.cpp
llexperiencecache.cpp
- llfiltersd2xmlrpc.cpp
llgenericstreamingmessage.cpp
llhost.cpp
llhttpnode.cpp
@@ -111,7 +110,6 @@ set(llmessage_HEADER_FILES
lleventflags.h
llexperiencecache.h
llextendedstatus.h
- llfiltersd2xmlrpc.h
llfollowcamparams.h
llgenericstreamingmessage.h
llhost.h
@@ -193,7 +191,6 @@ target_link_libraries(
llfilesystem
llmath
llcorehttp
- ll::xmlrpc-epi
)
target_include_directories( llmessage INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/indra/llmessage/llfiltersd2xmlrpc.cpp b/indra/llmessage/llfiltersd2xmlrpc.cpp
deleted file mode 100644
index 84b56d54bf..0000000000
--- a/indra/llmessage/llfiltersd2xmlrpc.cpp
+++ /dev/null
@@ -1,778 +0,0 @@
-/**
- * @file llfiltersd2xmlrpc.cpp
- * @author Phoenix
- * @date 2005-04-26
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-/**
- * xml rpc request:
- * <code>
- * <?xml version="1.0"?>
- * <methodCall><methodName>examples.getStateName</methodName>
- * <params><param><value><i4>41</i4></value></param></params>
- * </methodCall>
- * </code>
- *
- * xml rpc response:
- * <code>
- * <?xml version="1.0"?>
- * <methodResponse>
- * <params><param><value><string>South Dakota</string></value></param></params>
- * </methodResponse>
- * </code>
- *
- * xml rpc fault:
- * </code>
- * <?xml version="1.0"?>
- * <methodResponse>
- * <fault><value><struct>
- * <member><name>faultCode</name><value><int>4</int></value></member>
- * <member><name>faultString</name><value><string>...</string></value></member>
- * </struct></value></fault>
- * </methodResponse>
- * </code>
- *
- * llsd rpc request:
- * <code>
- * { 'method':'...', 'parameter':...]}
- * </code>
- *
- * llsd rpc response:
- * <code>
- * { 'response':... }
- * </code>
- *
- * llsd rpc fault:
- * <code>
- * { 'fault': {'code':i..., 'description':'...'} }
- * </code>
- *
- */
-
-#include "linden_common.h"
-#include "llfiltersd2xmlrpc.h"
-
-#include <sstream>
-#include <iterator>
-
-#ifdef LL_USESYSTEMLIBS
-#include <xmlrpc.h>
-#else
-#include <xmlrpc-epi/xmlrpc.h>
-#endif
-
-#include "apr_base64.h"
-
-#include "llbuffer.h"
-#include "llbufferstream.h"
-#include "llfasttimer.h"
-#include "llmemorystream.h"
-#include "llsd.h"
-#include "llsdserialize.h"
-#include "lluuid.h"
-
-// spammy mode
-//#define LL_SPEW_STREAM_OUT_DEBUGGING 1
-
-/**
- * String constants
- */
-static const char XML_HEADER[] = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
-static const char XMLRPC_REQUEST_HEADER_1[] = "<methodCall><methodName>";
-static const char XMLRPC_REQUEST_HEADER_2[] = "</methodName><params>";
-static const char XMLRPC_REQUEST_FOOTER[] = "</params></methodCall>";
-static const char XMLRPC_METHOD_RESPONSE_HEADER[] = "<methodResponse>";
-static const char XMLRPC_METHOD_RESPONSE_FOOTER[] = "</methodResponse>";
-static const char XMLRPC_RESPONSE_HEADER[] = "<params><param>";
-static const char XMLRPC_RESPONSE_FOOTER[] = "</param></params>";
-static const char XMLRPC_FAULT_1[] = "<fault><value><struct><member><name>faultCode</name><value><int>";
-static const char XMLRPC_FAULT_2[] = "</int></value></member><member><name>faultString</name><value><string>";
-static const char XMLRPC_FAULT_3[] = "</string></value></member></struct></value></fault>";
-static const char LLSDRPC_RESPONSE_HEADER[] = "{'response':";
-static const char LLSDRPC_RESPONSE_FOOTER[] = "}";
-const char LLSDRPC_REQUEST_HEADER_1[] = "{'method':'";
-const char LLSDRPC_REQUEST_HEADER_2[] = "', 'parameter': ";
-const char LLSDRPC_REQUEST_FOOTER[] = "}";
-static const char LLSDRPC_FAULT_HADER_1[] = "{ 'fault': {'code':i";
-static const char LLSDRPC_FAULT_HADER_2[] = ", 'description':";
-static const char LLSDRPC_FAULT_FOOTER[] = "} }";
-static const S32 DEFAULT_PRECISION = 20;
-
-/**
- * LLFilterSD2XMLRPC
- */
-LLFilterSD2XMLRPC::LLFilterSD2XMLRPC()
-{
-}
-
-LLFilterSD2XMLRPC::~LLFilterSD2XMLRPC()
-{
-}
-
-std::string xml_escape_string(const std::string& in)
-{
- std::ostringstream out;
- std::string::const_iterator it = in.begin();
- std::string::const_iterator end = in.end();
- for(; it != end; ++it)
- {
- switch((*it))
- {
- case '<':
- out << "&lt;";
- break;
- case '>':
- out << "&gt;";
- break;
- case '&':
- out << "&amp;";
- break;
- case '\'':
- out << "&apos;";
- break;
- case '"':
- out << "&quot;";
- break;
- default:
- out << (*it);
- break;
- }
- }
- return out.str();
-}
-
-void LLFilterSD2XMLRPC::streamOut(std::ostream& ostr, const LLSD& sd)
-{
- ostr << "<value>";
- switch(sd.type())
- {
- case LLSD::TypeMap:
- {
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(map) BEGIN" << LL_ENDL;
-#endif
- ostr << "<struct>";
- if(ostr.fail())
- {
- LL_INFOS() << "STREAM FAILURE writing struct" << LL_ENDL;
- }
- LLSD::map_const_iterator it = sd.beginMap();
- LLSD::map_const_iterator end = sd.endMap();
- for(; it != end; ++it)
- {
- ostr << "<member><name>" << xml_escape_string((*it).first)
- << "</name>";
- streamOut(ostr, (*it).second);
- if(ostr.fail())
- {
- LL_INFOS() << "STREAM FAILURE writing '" << (*it).first
- << "' with sd type " << (*it).second.type() << LL_ENDL;
- }
- ostr << "</member>";
- }
- ostr << "</struct>";
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(map) END" << LL_ENDL;
-#endif
- break;
- }
- case LLSD::TypeArray:
- {
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(array) BEGIN" << LL_ENDL;
-#endif
- ostr << "<array><data>";
- LLSD::array_const_iterator it = sd.beginArray();
- LLSD::array_const_iterator end = sd.endArray();
- for(; it != end; ++it)
- {
- streamOut(ostr, *it);
- if(ostr.fail())
- {
- LL_INFOS() << "STREAM FAILURE writing array element sd type "
- << (*it).type() << LL_ENDL;
- }
- }
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(array) END" << LL_ENDL;
-#endif
- ostr << "</data></array>";
- break;
- }
- case LLSD::TypeUndefined:
- // treat undefined as a bool with a false value.
- case LLSD::TypeBoolean:
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(bool)" << LL_ENDL;
-#endif
- ostr << "<boolean>" << (sd.asBoolean() ? "1" : "0") << "</boolean>";
- break;
- case LLSD::TypeInteger:
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(int)" << LL_ENDL;
-#endif
- ostr << "<i4>" << sd.asInteger() << "</i4>";
- break;
- case LLSD::TypeReal:
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(real)" << LL_ENDL;
-#endif
- ostr << "<double>" << sd.asReal() << "</double>";
- break;
- case LLSD::TypeString:
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(string)" << LL_ENDL;
-#endif
- ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
- break;
- case LLSD::TypeUUID:
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(uuid)" << LL_ENDL;
-#endif
- // serialize it as a string
- ostr << "<string>" << sd.asString() << "</string>";
- break;
- case LLSD::TypeURI:
- {
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(uri)" << LL_ENDL;
-#endif
- // serialize it as a string
- ostr << "<string>" << xml_escape_string(sd.asString()) << "</string>";
- break;
- }
- case LLSD::TypeBinary:
- {
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(binary)" << LL_ENDL;
-#endif
- // this is pretty inefficient, but we'll deal with that
- // problem when it becomes one.
- ostr << "<base64>";
- LLSD::Binary buffer = sd.asBinary();
- if(!buffer.empty())
- {
- // *TODO: convert to LLBase64
- int b64_buffer_length = apr_base64_encode_len(static_cast<int>(buffer.size()));
- char* b64_buffer = new char[b64_buffer_length];
- b64_buffer_length = apr_base64_encode_binary(
- b64_buffer,
- &buffer[0],
- static_cast<int>(buffer.size()));
- ostr.write(b64_buffer, b64_buffer_length - 1);
- delete[] b64_buffer;
- }
- ostr << "</base64>";
- break;
- }
- case LLSD::TypeDate:
-#if LL_SPEW_STREAM_OUT_DEBUGGING
- LL_INFOS() << "streamOut(date)" << LL_ENDL;
-#endif
- // no need to escape this since it will be alpha-numeric.
- ostr << "<dateTime.iso8601>" << sd.asString() << "</dateTime.iso8601>";
- break;
- default:
- // unhandled type
- LL_WARNS() << "Unhandled structured data type: " << sd.type()
- << LL_ENDL;
- break;
- }
- ostr << "</value>";
-}
-
-/**
- * LLFilterSD2XMLRPCResponse
- */
-
-LLFilterSD2XMLRPCResponse::LLFilterSD2XMLRPCResponse()
-{
-}
-
-LLFilterSD2XMLRPCResponse::~LLFilterSD2XMLRPCResponse()
-{
-}
-
-
-// virtual
-LLIOPipe::EStatus LLFilterSD2XMLRPCResponse::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
-{
- LL_PROFILE_ZONE_SCOPED;
-
- PUMP_DEBUG;
- // This pipe does not work if it does not have everyting. This
- // could be addressed by making a stream parser for llsd which
- // handled partial information.
- if(!eos)
- {
- return STATUS_BREAK;
- }
-
- PUMP_DEBUG;
- // we have everyting in the buffer, so turn the structure data rpc
- // response into an xml rpc response.
- LLBufferStream stream(channels, buffer.get());
- stream << XML_HEADER << XMLRPC_METHOD_RESPONSE_HEADER;
- LLSD sd;
- LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
-
- PUMP_DEBUG;
- LLIOPipe::EStatus rv = STATUS_ERROR;
- if(sd.has("response"))
- {
- PUMP_DEBUG;
- // it is a normal response. pack it up and ship it out.
- stream.precision(DEFAULT_PRECISION);
- stream << XMLRPC_RESPONSE_HEADER;
- streamOut(stream, sd["response"]);
- stream << XMLRPC_RESPONSE_FOOTER << XMLRPC_METHOD_RESPONSE_FOOTER;
- rv = STATUS_DONE;
- }
- else if(sd.has("fault"))
- {
- PUMP_DEBUG;
- // it is a fault.
- stream << XMLRPC_FAULT_1 << sd["fault"]["code"].asInteger()
- << XMLRPC_FAULT_2
- << xml_escape_string(sd["fault"]["description"].asString())
- << XMLRPC_FAULT_3 << XMLRPC_METHOD_RESPONSE_FOOTER;
- rv = STATUS_DONE;
- }
- else
- {
- LL_WARNS() << "Unable to determine the type of LLSD response." << LL_ENDL;
- }
- PUMP_DEBUG;
- return rv;
-}
-
-/**
- * LLFilterSD2XMLRPCRequest
- */
-LLFilterSD2XMLRPCRequest::LLFilterSD2XMLRPCRequest()
-{
-}
-
-LLFilterSD2XMLRPCRequest::LLFilterSD2XMLRPCRequest(const char* method)
-{
- if(method)
- {
- mMethod.assign(method);
- }
-}
-
-LLFilterSD2XMLRPCRequest::~LLFilterSD2XMLRPCRequest()
-{
-}
-
-// virtual
-LLIOPipe::EStatus LLFilterSD2XMLRPCRequest::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
-{
- LL_PROFILE_ZONE_SCOPED;
- // This pipe does not work if it does not have everyting. This
- // could be addressed by making a stream parser for llsd which
- // handled partial information.
- PUMP_DEBUG;
- if(!eos)
- {
- LL_INFOS() << "!eos" << LL_ENDL;
- return STATUS_BREAK;
- }
-
- // See if we can parse it
- LLBufferStream stream(channels, buffer.get());
- LLSD sd;
- LLSDSerialize::fromNotation(sd, stream, buffer->count(channels.in()));
- if(stream.fail())
- {
- LL_INFOS() << "STREAM FAILURE reading structure data." << LL_ENDL;
- }
-
- PUMP_DEBUG;
- // We can get the method and parameters from either the member
- // function or passed in via the buffer. We prefer the buffer if
- // we found a parameter and a method, or fall back to using
- // mMethod and putting everyting in the buffer into the parameter.
- std::string method;
- LLSD param_sd;
- if(sd.has("method") && sd.has("parameter"))
- {
- method = sd["method"].asString();
- param_sd = sd["parameter"];
- }
- else
- {
- method = mMethod;
- param_sd = sd;
- }
- if(method.empty())
- {
- LL_WARNS() << "SD -> XML Request no method found." << LL_ENDL;
- return STATUS_ERROR;
- }
-
- PUMP_DEBUG;
- // We have a method, and some kind of parameter, so package it up
- // and send it out.
- LLBufferStream ostream(channels, buffer.get());
- ostream.precision(DEFAULT_PRECISION);
- if(ostream.fail())
- {
- LL_INFOS() << "STREAM FAILURE setting precision" << LL_ENDL;
- }
- ostream << XML_HEADER << XMLRPC_REQUEST_HEADER_1
- << xml_escape_string(method) << XMLRPC_REQUEST_HEADER_2;
- if(ostream.fail())
- {
- LL_INFOS() << "STREAM FAILURE writing method headers" << LL_ENDL;
- }
- switch(param_sd.type())
- {
- case LLSD::TypeMap:
- // If the params are a map, then we do not want to iterate
- // through them since the iterators returned will be map
- // ordered un-named values, which will lose the names, and
- // only stream the values, turning it into an array.
- ostream << "<param>";
- streamOut(ostream, param_sd);
- ostream << "</param>";
- break;
- case LLSD::TypeArray:
- {
-
- LLSD::array_iterator it = param_sd.beginArray();
- LLSD::array_iterator end = param_sd.endArray();
- for(; it != end; ++it)
- {
- ostream << "<param>";
- streamOut(ostream, *it);
- ostream << "</param>";
- }
- break;
- }
- default:
- ostream << "<param>";
- streamOut(ostream, param_sd);
- ostream << "</param>";
- break;
- }
-
- stream << XMLRPC_REQUEST_FOOTER;
- return STATUS_DONE;
-}
-
-/**
- * LLFilterXMLRPCResponse2LLSD
- */
-// this is a c function here since it's really an implementation
-// detail that requires a header file just get the definition of the
-// parameters.
-LLIOPipe::EStatus stream_out(std::ostream& ostr, XMLRPC_VALUE value)
-{
- XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(value);
- LLIOPipe::EStatus status = LLIOPipe::STATUS_OK;
- switch(type)
- {
- case xmlrpc_type_base64:
- {
- S32 len = XMLRPC_GetValueStringLen(value);
- const char* buf = XMLRPC_GetValueBase64(value);
- ostr << " b(";
- if((len > 0) && buf)
- {
- ostr << len << ")\"";
- ostr.write(buf, len);
- ostr << "\"";
- }
- else
- {
- ostr << "0)\"\"";
- }
- break;
- }
- case xmlrpc_type_boolean:
- //LL_DEBUGS() << "stream_out() bool" << LL_ENDL;
- ostr << " " << (XMLRPC_GetValueBoolean(value) ? "true" : "false");
- break;
- case xmlrpc_type_datetime:
- ostr << " d\"" << XMLRPC_GetValueDateTime_ISO8601(value) << "\"";
- break;
- case xmlrpc_type_double:
- ostr << " r" << XMLRPC_GetValueDouble(value);
- //LL_DEBUGS() << "stream_out() double" << XMLRPC_GetValueDouble(value)
- // << LL_ENDL;
- break;
- case xmlrpc_type_int:
- ostr << " i" << XMLRPC_GetValueInt(value);
- //LL_DEBUGS() << "stream_out() integer:" << XMLRPC_GetValueInt(value)
- // << LL_ENDL;
- break;
- case xmlrpc_type_string:
- //LL_DEBUGS() << "stream_out() string: " << str << LL_ENDL;
- ostr << " s(" << XMLRPC_GetValueStringLen(value) << ")'"
- << XMLRPC_GetValueString(value) << "'";
- break;
- case xmlrpc_type_array: // vector
- case xmlrpc_type_mixed: // vector
- {
- //LL_DEBUGS() << "stream_out() array" << LL_ENDL;
- ostr << " [";
- U32 needs_comma = 0;
- XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
- while(current && (LLIOPipe::STATUS_OK == status))
- {
- if(needs_comma++) ostr << ",";
- status = stream_out(ostr, current);
- current = XMLRPC_VectorNext(value);
- }
- ostr << "]";
- break;
- }
- case xmlrpc_type_struct: // still vector
- {
- //LL_DEBUGS() << "stream_out() struct" << LL_ENDL;
- ostr << " {";
- std::string name;
- U32 needs_comma = 0;
- XMLRPC_VALUE current = XMLRPC_VectorRewind(value);
- while(current && (LLIOPipe::STATUS_OK == status))
- {
- if(needs_comma++) ostr << ",";
- name.assign(XMLRPC_GetValueID(current));
- ostr << "'" << LLSDNotationFormatter::escapeString(name) << "':";
- status = stream_out(ostr, current);
- current = XMLRPC_VectorNext(value);
- }
- ostr << "}";
- break;
- }
- case xmlrpc_type_empty:
- case xmlrpc_type_none:
- default:
- status = LLIOPipe::STATUS_ERROR;
- LL_WARNS() << "Found an empty xmlrpc type.." << LL_ENDL;
- // not much we can do here...
- break;
- };
- return status;
-}
-
-LLFilterXMLRPCResponse2LLSD::LLFilterXMLRPCResponse2LLSD()
-{
-}
-
-LLFilterXMLRPCResponse2LLSD::~LLFilterXMLRPCResponse2LLSD()
-{
-}
-
-LLIOPipe::EStatus LLFilterXMLRPCResponse2LLSD::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
-{
- LL_PROFILE_ZONE_SCOPED;
-
- PUMP_DEBUG;
- if(!eos) return STATUS_BREAK;
- if(!buffer) return STATUS_ERROR;
-
- PUMP_DEBUG;
- // *FIX: This technique for reading data is far from optimal. We
- // need to have some kind of istream interface into the xml
- // parser...
- S32 bytes = buffer->countAfter(channels.in(), NULL);
- if(!bytes) return STATUS_ERROR;
- char* buf = new char[bytes + 1];
- buf[bytes] = '\0';
- buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes);
-
- //LL_DEBUGS() << "xmlrpc response: " << buf << LL_ENDL;
-
- PUMP_DEBUG;
- XMLRPC_REQUEST response = XMLRPC_REQUEST_FromXML(
- buf,
- bytes,
- NULL);
- if(!response)
- {
- LL_WARNS() << "XML -> SD Response unable to parse xml." << LL_ENDL;
- delete[] buf;
- return STATUS_ERROR;
- }
-
- PUMP_DEBUG;
- LLBufferStream stream(channels, buffer.get());
- stream.precision(DEFAULT_PRECISION);
- if(XMLRPC_ResponseIsFault(response))
- {
- PUMP_DEBUG;
- stream << LLSDRPC_FAULT_HADER_1
- << XMLRPC_GetResponseFaultCode(response)
- << LLSDRPC_FAULT_HADER_2;
- const char* fault_str = XMLRPC_GetResponseFaultString(response);
- std::string fault_string;
- if(fault_str)
- {
- fault_string.assign(fault_str);
- }
- stream << "'" << LLSDNotationFormatter::escapeString(fault_string)
- << "'" <<LLSDRPC_FAULT_FOOTER;
- }
- else
- {
- PUMP_DEBUG;
- stream << LLSDRPC_RESPONSE_HEADER;
- XMLRPC_VALUE param = XMLRPC_RequestGetData(response);
- if(param)
- {
- stream_out(stream, param);
- }
- stream << LLSDRPC_RESPONSE_FOOTER;
- }
- PUMP_DEBUG;
- XMLRPC_RequestFree(response, 1);
- delete[] buf;
- PUMP_DEBUG;
- return STATUS_DONE;
-}
-
-/**
- * LLFilterXMLRPCRequest2LLSD
- */
-LLFilterXMLRPCRequest2LLSD::LLFilterXMLRPCRequest2LLSD()
-{
-}
-
-LLFilterXMLRPCRequest2LLSD::~LLFilterXMLRPCRequest2LLSD()
-{
-}
-
-LLIOPipe::EStatus LLFilterXMLRPCRequest2LLSD::process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump)
-{
- LL_PROFILE_ZONE_SCOPED;
- PUMP_DEBUG;
- if(!eos) return STATUS_BREAK;
- if(!buffer) return STATUS_ERROR;
-
- PUMP_DEBUG;
- // *FIX: This technique for reading data is far from optimal. We
- // need to have some kind of istream interface into the xml
- // parser...
- S32 bytes = buffer->countAfter(channels.in(), NULL);
- if(!bytes) return STATUS_ERROR;
- char* buf = new char[bytes + 1];
- buf[bytes] = '\0';
- buffer->readAfter(channels.in(), NULL, (U8*)buf, bytes);
-
- //LL_DEBUGS() << "xmlrpc request: " << buf << LL_ENDL;
-
- // Check the value in the buffer. XMLRPC_REQUEST_FromXML will report a error code 4 if
- // values that are less than 0x20 are passed to it, except
- // 0x09: Horizontal tab; 0x0a: New Line; 0x0d: Carriage
- U8* cur_pBuf = (U8*)buf;
- U8 cur_char;
- for (S32 i=0; i<bytes; i++)
- {
- cur_char = *cur_pBuf;
- if ( cur_char < 0x20
- && 0x09 != cur_char
- && 0x0a != cur_char
- && 0x0d != cur_char )
- {
- *cur_pBuf = '?';
- }
- ++cur_pBuf;
- }
-
- PUMP_DEBUG;
- XMLRPC_REQUEST request = XMLRPC_REQUEST_FromXML(
- buf,
- bytes,
- NULL);
- if(!request)
- {
- LL_WARNS() << "XML -> SD Request process parse error." << LL_ENDL;
- delete[] buf;
- return STATUS_ERROR;
- }
-
- PUMP_DEBUG;
- LLBufferStream stream(channels, buffer.get());
- stream.precision(DEFAULT_PRECISION);
- const char* name = XMLRPC_RequestGetMethodName(request);
- stream << LLSDRPC_REQUEST_HEADER_1 << (name ? name : "")
- << LLSDRPC_REQUEST_HEADER_2;
- XMLRPC_VALUE param = XMLRPC_RequestGetData(request);
- if(param)
- {
- PUMP_DEBUG;
- S32 size = XMLRPC_VectorSize(param);
- if(size > 1)
- {
- // if there are multiple parameters, stuff the values into
- // an array so that the next step in the chain can read them.
- stream << "[";
- }
- XMLRPC_VALUE current = XMLRPC_VectorRewind(param);
- bool needs_comma = false;
- while(current)
- {
- if(needs_comma)
- {
- stream << ",";
- }
- needs_comma = true;
- stream_out(stream, current);
- current = XMLRPC_VectorNext(param);
- }
- if(size > 1)
- {
- // close the array
- stream << "]";
- }
- }
- stream << LLSDRPC_REQUEST_FOOTER;
- XMLRPC_RequestFree(request, 1);
- delete[] buf;
- PUMP_DEBUG;
- return STATUS_DONE;
-}
-
diff --git a/indra/llmessage/llfiltersd2xmlrpc.h b/indra/llmessage/llfiltersd2xmlrpc.h
deleted file mode 100644
index 55938d3e2b..0000000000
--- a/indra/llmessage/llfiltersd2xmlrpc.h
+++ /dev/null
@@ -1,271 +0,0 @@
-/**
- * @file llfiltersd2xmlrpc.h
- * @author Phoenix
- * @date 2005-04-26
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- *
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
- * $/LicenseInfo$
- */
-
-#ifndef LL_LLFILTERSD2XMLRPC_H
-#define LL_LLFILTERSD2XMLRPC_H
-
-/**
- * These classes implement the necessary pipes for translating between
- * xmlrpc and llsd rpc. The llsd rpcs mechanism was developed as an
- * extensible and easy to parse serialization grammer which maintains
- * a time efficient in-memory representation.
- */
-
-#include <iosfwd>
-#include "lliopipe.h"
-
-/**
- * @class LLFilterSD2XMLRPC
- * @brief Filter from serialized LLSD to an XMLRPC method call
- *
- * This clas provides common functionality for the LLFilterSD2XMLRPRC
- * request and response classes.
- */
-class LLFilterSD2XMLRPC : public LLIOPipe
-{
-public:
- LLFilterSD2XMLRPC();
- virtual ~LLFilterSD2XMLRPC();
-
-protected:
- /**
- * @brief helper method
- */
- void streamOut(std::ostream& ostr, const LLSD& sd);
-};
-
-/**
- * @class LLFilterSD2XMLRPCResponse
- * @brief Filter from serialized LLSD to an XMLRPC response
- *
- * This class filters a serialized LLSD object to an xmlrpc
- * repsonse. Since resonses are limited to a single param, the xmlrprc
- * response only serializes it as one object.
- * This class correctly handles normal llsd responses as well as llsd
- * rpc faults.
- *
- * For example, if given:
- * <code>{'response':[ i200, r3.4, {"foo":"bar"} ]}</code>
- * Would generate:
- * <code>
- * <?xml version="1.0"?>
- * <methodResponse><params><param><array><data>
- * <value><int>200</int></value>
- * <value><double>3.4</double></value>
- * <value><struct><member>
- * <name>foo</name><value><string>bar</string></value></member>
- * </struct></value>
- * </data></array></param></params></methodResponse>
- * </code>
- */
-class LLFilterSD2XMLRPCResponse : public LLFilterSD2XMLRPC
-{
-public:
- // constructor
- LLFilterSD2XMLRPCResponse();
-
- // destructor
- virtual ~LLFilterSD2XMLRPCResponse();
-
- /* @name LLIOPipe virtual implementations
- */
- //@{
-protected:
- /**
- * @brief Process the data in buffer.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
-};
-
-/**
- * @class LLFilterSD2XMLRPCRequest
- * @brief Filter from serialized LLSD to an XMLRPC method call
- *
- * This class will accept any kind of serialized LLSD object, but you
- * probably want to have an array on the outer boundary since this
- * object will interpret each element in the top level LLSD as a
- * parameter into the xmlrpc spec.
- *
- * For example, you would represent 3 params as:
- * <code>
- * {'method'='foo', 'parameter':[i200, r3.4, {"foo":"bar"}]}
- * </code>
- * To generate:
- * <code>
- * <?xml version="1.0"?>
- * <methodCall><params>
- * <param><value><int>200</int></value></param>
- * <param><value><double>3.4</double></value></param>
- * <param><value><struct><member>
- * <name>foo</name><value><string>bar</string></value></member>
- * </struct></value></param>
- * </params></methodCall>
- *
- * This class will accept 2 different kinds of encodings. The first
- * just an array of params as long as you specify the method in the
- * constructor. It will also accept a structured data in the form:
- * {'method':'$method_name', 'parameter':[...] } In the latter form, the
- * encoded 'method' will be used regardless of the construction of the
- * object, and the 'parameter' will be used as parameter to the call.
- */
-class LLFilterSD2XMLRPCRequest : public LLFilterSD2XMLRPC
-{
-public:
- // constructor
- LLFilterSD2XMLRPCRequest();
-
- // constructor
- LLFilterSD2XMLRPCRequest(const char* method);
-
- // destructor
- virtual ~LLFilterSD2XMLRPCRequest();
-
- /* @name LLIOPipe virtual implementations
- */
- //@{
-protected:
- /**
- * @brief Process the data in buffer.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
-
-protected:
- // The method name of this request.
- std::string mMethod;
-};
-
-/**
- * @class LLFilterXMLRPCResponse2LLSD
- * @brief Filter from serialized XMLRPC method response to LLSD
- *
- * The xmlrpc spec states that responses can only have one element
- * which can be of any supported type.
- * This takes in xml of the form:
- * <code>
- * <?xml version=\"1.0\"?><methodResponse><params><param>
- * <value><string>ok</string></value></param></params></methodResponse>
- * </code>
- * And processes it into:
- * <code>'ok'</code>
- *
- */
-class LLFilterXMLRPCResponse2LLSD : public LLIOPipe
-{
-public:
- // constructor
- LLFilterXMLRPCResponse2LLSD();
-
- // destructor
- virtual ~LLFilterXMLRPCResponse2LLSD();
-
- /* @name LLIOPipe virtual implementations
- */
- //@{
-protected:
- /**
- * @brief Process the data in buffer.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
-
-protected:
-};
-
-/**
- * @class LLFilterXMLRPCRequest2LLSD
- * @brief Filter from serialized XMLRPC method call to LLSD
- *
- * This takes in xml of the form:
- * <code>
- * <?xml version=\"1.0\"?><methodCall>
- * <methodName>repeat</methodName>
- * <params>
- * <param><value><i4>4</i4></value></param>
- * <param><value><string>ok</string></value></param>
- * </params></methodCall>
- * </code>
- * And processes it into:
- * <code>{ 'method':'repeat', 'params':[i4, 'ok'] }</code>
- */
-class LLFilterXMLRPCRequest2LLSD : public LLIOPipe
-{
-public:
- // constructor
- LLFilterXMLRPCRequest2LLSD();
-
- // destructor
- virtual ~LLFilterXMLRPCRequest2LLSD();
-
- /* @name LLIOPipe virtual implementations
- */
- //@{
-protected:
- /**
- * @brief Process the data in buffer.
- */
- virtual EStatus process_impl(
- const LLChannelDescriptors& channels,
- buffer_ptr_t& buffer,
- bool& eos,
- LLSD& context,
- LLPumpIO* pump);
- //@}
-
-protected:
-};
-
-/**
- * @brief This function takes string, and escapes it appropritately
- * for inclusion as xml data.
- */
-std::string xml_escape_string(const std::string& in);
-
-/**
- * @brief Externally available constants
- */
-extern const char LLSDRPC_REQUEST_HEADER_1[];
-extern const char LLSDRPC_REQUEST_HEADER_2[];
-extern const char LLSDRPC_REQUEST_FOOTER[];
-
-#endif // LL_LLFILTERSD2XMLRPC_H
diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp
index e614f45986..4dcca5a726 100644
--- a/indra/llrender/llgltexture.cpp
+++ b/indra/llrender/llgltexture.cpp
@@ -351,20 +351,6 @@ void LLGLTexture::forceUpdateBindStats(void) const
return mGLTexturep->forceUpdateBindStats() ;
}
-U32 LLGLTexture::getTexelsInAtlas() const
-{
- llassert(mGLTexturep.notNull()) ;
-
- return mGLTexturep->getTexelsInAtlas() ;
-}
-
-U32 LLGLTexture::getTexelsInGLTexture() const
-{
- llassert(mGLTexturep.notNull()) ;
-
- return mGLTexturep->getTexelsInGLTexture() ;
-}
-
bool LLGLTexture::isGLTextureCreated() const
{
llassert(mGLTexturep.notNull()) ;
@@ -372,13 +358,6 @@ bool LLGLTexture::isGLTextureCreated() const
return mGLTexturep->isGLTextureCreated() ;
}
-S32 LLGLTexture::getDiscardLevelInAtlas() const
-{
- llassert(mGLTexturep.notNull()) ;
-
- return mGLTexturep->getDiscardLevelInAtlas() ;
-}
-
void LLGLTexture::destroyGLTexture()
{
if(mGLTexturep.notNull() && mGLTexturep->getHasGLTexture())
diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h
index 0901243f8f..a7de20dc5c 100644
--- a/indra/llrender/llgltexture.h
+++ b/indra/llrender/llgltexture.h
@@ -51,10 +51,10 @@ public:
BOOST_NONE = 0,
BOOST_AVATAR ,
BOOST_AVATAR_BAKED ,
- BOOST_SCULPTED ,
BOOST_TERRAIN , // Needed for minimap generation for now. Lower than BOOST_HIGH so the texture stats don't get forced, i.e. texture stats are manually managed by minimap/terrain instead.
BOOST_HIGH = 10,
+ BOOST_SCULPTED ,
BOOST_BUMP ,
BOOST_UNUSED_1 , // Placeholder to avoid disrupting habits around texture debug
BOOST_SELECTED ,
@@ -75,7 +75,6 @@ public:
AVATAR_SCRATCH_TEX,
DYNAMIC_TEX,
MEDIA,
- ATLAS,
OTHER,
MAX_GL_IMAGE_CATEGORY
};
@@ -156,10 +155,7 @@ public:
bool isJustBound()const ;
void forceUpdateBindStats(void) const;
- U32 getTexelsInAtlas() const ;
- U32 getTexelsInGLTexture() const ;
bool isGLTextureCreated() const ;
- S32 getDiscardLevelInAtlas() const ;
LLGLTextureState getTextureState() const { return mTextureState; }
//---------------------------------------------------------------------------------------------
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 7e5cd628c1..956bcef352 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -41,6 +41,7 @@
#include "llrender.h"
#include "llwindow.h"
#include "llframetimer.h"
+#include <unordered_set>
extern LL_COMMON_API bool on_main_thread();
@@ -130,10 +131,9 @@ S32 LLImageGL::sCount = 0;
bool LLImageGL::sGlobalUseAnisotropic = false;
F32 LLImageGL::sLastFrameTime = 0.f;
-bool LLImageGL::sAllowReadBackRaw = false ;
LLImageGL* LLImageGL::sDefaultGLTexture = NULL ;
bool LLImageGL::sCompressTextures = false;
-std::set<LLImageGL*> LLImageGL::sImageList;
+std::unordered_set<LLImageGL*> LLImageGL::sImageList;
bool LLImageGLThread::sEnabledTextures = false;
@@ -150,6 +150,9 @@ S32 LLImageGL::sMaxCategories = 1 ;
//optimization for when we don't need to calculate mIsMask
bool LLImageGL::sSkipAnalyzeAlpha;
+U32 LLImageGL::sScratchPBO = 0;
+U32 LLImageGL::sScratchPBOSize = 0;
+
//------------------------
//****************************************************************************************************
@@ -159,20 +162,6 @@ bool LLImageGL::sSkipAnalyzeAlpha;
//**************************************************************************************
//below are functions for debug use
//do not delete them even though they are not currently being used.
-void check_all_images()
-{
- for (std::set<LLImageGL*>::iterator iter = LLImageGL::sImageList.begin();
- iter != LLImageGL::sImageList.end(); iter++)
- {
- LLImageGL* glimage = *iter;
- if (glimage->getTexName() && glimage->isGLTextureCreated())
- {
- gGL.getTexUnit(0)->bind(glimage) ;
- glimage->checkTexSize() ;
- gGL.getTexUnit(0)->unbind(glimage->getTarget()) ;
- }
- }
-}
void LLImageGL::checkTexSize(bool forced) const
{
@@ -252,6 +241,11 @@ void LLImageGL::initClass(LLWindow* window, S32 num_catagories, bool skip_analyz
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
sSkipAnalyzeAlpha = skip_analyze_alpha;
+ if (sScratchPBO == 0)
+ {
+ glGenBuffers(1, &sScratchPBO);
+ }
+
if (thread_texture_loads || thread_media_updates)
{
LLImageGLThread::createInstance(window);
@@ -265,6 +259,12 @@ void LLImageGL::cleanupClass()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LLImageGLThread::deleteSingleton();
+ if (sScratchPBO != 0)
+ {
+ glDeleteBuffers(1, &sScratchPBO);
+ sScratchPBO = 0;
+ sScratchPBOSize = 0;
+ }
}
@@ -360,66 +360,19 @@ void LLImageGL::updateStats(F32 current_time)
//----------------------------------------------------------------------------
//static
-void LLImageGL::destroyGL(bool save_state)
+void LLImageGL::destroyGL()
{
for (S32 stage = 0; stage < gGLManager.mNumTextureImageUnits; stage++)
{
gGL.getTexUnit(stage)->unbind(LLTexUnit::TT_TEXTURE);
}
-
- sAllowReadBackRaw = true ;
- for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
- iter != sImageList.end(); iter++)
- {
- LLImageGL* glimage = *iter;
- if (glimage->mTexName)
- {
- if (save_state && glimage->isGLTextureCreated() && glimage->mComponents)
- {
- glimage->mSaveData = new LLImageRaw;
- if(!glimage->readBackRaw(glimage->mCurrentDiscardLevel, glimage->mSaveData, false)) //necessary, keep it.
- {
- glimage->mSaveData = NULL ;
- }
- }
-
- glimage->destroyGLTexture();
- stop_glerror();
- }
- }
- sAllowReadBackRaw = false ;
-}
-
-//static
-void LLImageGL::restoreGL()
-{
- for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
- iter != sImageList.end(); iter++)
- {
- LLImageGL* glimage = *iter;
- if(glimage->getTexName())
- {
- LL_ERRS() << "tex name is not 0." << LL_ENDL ;
- }
- if (glimage->mSaveData.notNull())
- {
- if (glimage->getComponents() && glimage->mSaveData->getComponents())
- {
- glimage->createGLTexture(glimage->mCurrentDiscardLevel, glimage->mSaveData, 0, true, glimage->getCategory());
- stop_glerror();
- }
- glimage->mSaveData = NULL; // deletes data
- }
- }
}
//static
void LLImageGL::dirtyTexOptions()
{
- for (std::set<LLImageGL*>::iterator iter = sImageList.begin();
- iter != sImageList.end(); iter++)
+ for (auto& glimage : sImageList)
{
- LLImageGL* glimage = *iter;
glimage->mTexOptionsDirty = true;
stop_glerror();
}
@@ -542,10 +495,6 @@ void LLImageGL::init(bool usemipmaps)
mHeight = 0;
mCurrentDiscardLevel = -1;
- mDiscardLevelInAtlas = -1 ;
- mTexelsInAtlas = 0 ;
- mTexelsInGLTexture = 0 ;
-
mAllowCompression = true;
mTarget = GL_TEXTURE_2D;
@@ -622,9 +571,6 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve
return false;
}
- // pickmask validity depends on old image size, delete it
- freePickMask();
-
mWidth = width;
mHeight = height;
mComponents = ncomponents;
@@ -1025,98 +971,6 @@ bool LLImageGL::setImage(const U8* data_in, bool data_hasmips /* = false */, S32
return true;
}
-bool LLImageGL::preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image)
-{
- //not compatible with core GL profile
- llassert(!LLRender::sGLCoreProfile);
-
- if (gGLManager.mIsDisabled)
- {
- LL_WARNS() << "Trying to create a texture while GL is disabled!" << LL_ENDL;
- return false;
- }
- llassert(gGLManager.mInited);
- stop_glerror();
-
- if (discard_level < 0)
- {
- llassert(mCurrentDiscardLevel >= 0);
- discard_level = mCurrentDiscardLevel;
- }
-
- // Actual image width/height = raw image width/height * 2^discard_level
- S32 w = raw_image->getWidth() << discard_level;
- S32 h = raw_image->getHeight() << discard_level;
-
- // setSize may call destroyGLTexture if the size does not match
- if (!setSize(w, h, raw_image->getComponents(), discard_level))
- {
- LL_WARNS() << "Trying to create a texture with incorrect dimensions!" << LL_ENDL;
- return false;
- }
-
- if (!mHasExplicitFormat)
- {
- switch (mComponents)
- {
- case 1:
- // Use luminance alpha (for fonts)
- mFormatInternal = GL_LUMINANCE8;
- mFormatPrimary = GL_LUMINANCE;
- mFormatType = GL_UNSIGNED_BYTE;
- break;
- case 2:
- // Use luminance alpha (for fonts)
- mFormatInternal = GL_LUMINANCE8_ALPHA8;
- mFormatPrimary = GL_LUMINANCE_ALPHA;
- mFormatType = GL_UNSIGNED_BYTE;
- break;
- case 3:
- mFormatInternal = GL_RGB8;
- mFormatPrimary = GL_RGB;
- mFormatType = GL_UNSIGNED_BYTE;
- break;
- case 4:
- mFormatInternal = GL_RGBA8;
- mFormatPrimary = GL_RGBA;
- mFormatType = GL_UNSIGNED_BYTE;
- break;
- default:
- LL_ERRS() << "Bad number of components for texture: " << (U32) getComponents() << LL_ENDL;
- }
- }
-
- mCurrentDiscardLevel = discard_level;
- mDiscardLevelInAtlas = discard_level;
- mTexelsInAtlas = raw_image->getWidth() * raw_image->getHeight() ;
- mLastBindTime = sLastFrameTime;
- mGLTextureCreated = false ;
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, raw_image->getWidth());
- stop_glerror();
-
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 1);
- stop_glerror();
- }
-
- return true ;
-}
-
-void LLImageGL::postAddToAtlas()
-{
- if(mFormatSwapBytes)
- {
- glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
- stop_glerror();
- }
-
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- gGL.getTexUnit(0)->setTextureFilteringOption(mFilterOption);
- stop_glerror();
-}
-
U32 type_width_from_pixtype(U32 pixtype)
{
U32 type_width = 0;
@@ -1752,7 +1606,6 @@ bool LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, bool data_
mTextureMemory = (S64Bytes)getMipBytes(mCurrentDiscardLevel);
- mTexelsInGLTexture = getWidth() * getHeight();
// mark this as bound at this point, so we don't throw it out immediately
mLastBindTime = sLastFrameTime;
@@ -1830,8 +1683,7 @@ void LLImageGL::syncTexName(LLGLuint texname)
bool LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const
{
- llassert_always(sAllowReadBackRaw) ;
- //LL_ERRS() << "should not call this function!" << LL_ENDL ;
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (discard_level < 0)
{
@@ -2297,6 +2149,8 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
//----------------------------------------------------------------------------
U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+ freePickMask();
U32 pick_width = pWidth/2 + 1;
U32 pick_height = pHeight/2 + 1;
@@ -2314,7 +2168,6 @@ U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight)
//----------------------------------------------------------------------------
void LLImageGL::freePickMask()
{
- // pickmask validity depends on old image size, delete it
if (mPickMask != NULL)
{
delete [] mPickMask;
@@ -2352,16 +2205,16 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
return ;
}
- freePickMask();
-
if (mFormatType != GL_UNSIGNED_BYTE ||
((mFormatPrimary != GL_RGBA)
&& (mFormatPrimary != GL_SRGB_ALPHA)))
{
//cannot generate a pick mask for this texture
+ freePickMask();
return;
}
+
#ifdef SHOW_ASSERT
const U32 pickSize = createPickMask(width, height);
#else // SHOW_ASSERT
@@ -2460,6 +2313,73 @@ void LLImageGL::resetCurTexSizebar()
sCurTexSizeBar = -1 ;
sCurTexPickSize = -1 ;
}
+
+bool LLImageGL::scaleDown(S32 desired_discard)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
+
+ if (mTarget != GL_TEXTURE_2D)
+ {
+ return false;
+ }
+
+ desired_discard = llmin(desired_discard, mMaxDiscardLevel);
+
+ if (desired_discard <= mCurrentDiscardLevel)
+ {
+ return false;
+ }
+
+ S32 mip = desired_discard - mCurrentDiscardLevel;
+
+ S32 desired_width = getWidth(desired_discard);
+ S32 desired_height = getHeight(desired_discard);
+
+ U64 size = getBytes(desired_discard);
+ llassert(size <= 2048*2048*4); // we shouldn't be using this method to downscale huge textures, but it'll work
+ gGL.getTexUnit(0)->bind(this);
+
+
+ if (sScratchPBO == 0)
+ {
+ glGenBuffers(1, &sScratchPBO);
+ sScratchPBOSize = 0;
+ }
+
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, sScratchPBO);
+
+ if (size > sScratchPBOSize)
+ {
+ glBufferData(GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_COPY);
+ sScratchPBOSize = size;
+ }
+
+ glGetTexImage(mTarget, mip, mFormatPrimary, mFormatType, nullptr);
+
+ free_tex_image(mTexName);
+
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO);
+ glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+
+ alloc_tex_image(desired_width, desired_height, mFormatPrimary);
+
+ if (mHasMipMaps)
+ {
+ LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap");
+ glGenerateMipmap(mTarget);
+ }
+
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+ mCurrentDiscardLevel = desired_discard;
+
+ return true;
+}
+
+
//----------------------------------------------------------------------------
#if LL_IMAGEGL_THREAD_CHECK
void LLImageGL::checkActiveThread()
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index 5c7a5ce821..3892e9c014 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -39,6 +39,7 @@
#include "llrender.h"
#include "threadpool.h"
#include "workqueue.h"
+#include <unordered_set>
#define LL_IMAGEGL_THREAD_CHECK 0 //set to 1 to enable thread debugging for ImageGL
@@ -83,9 +84,8 @@ public:
// needs to be called every frame
static void updateStats(F32 current_time);
- // Save off / restore GL textures
- static void destroyGL(bool save_state = true);
- static void restoreGL();
+ // cleanup GL state
+ static void destroyGL();
static void dirtyTexOptions();
static bool checkSize(S32 width, S32 height);
@@ -148,6 +148,10 @@ public:
S32 getDiscardLevel() const { return mCurrentDiscardLevel; }
S32 getMaxDiscardLevel() const { return mMaxDiscardLevel; }
+ // override the current discard level
+ // should only be used for local textures where you know exactly what you're doing
+ void setDiscardLevel(S32 level) { mCurrentDiscardLevel = level; }
+
S32 getCurrentWidth() const { return mWidth ;}
S32 getCurrentHeight() const { return mHeight ;}
S32 getWidth(S32 discard_level = -1) const;
@@ -194,26 +198,26 @@ public:
void setFilteringOption(LLTexUnit::eTextureFilterOptions option);
LLTexUnit::eTextureFilterOptions getFilteringOption(void) const { return mFilterOption; }
- LLGLenum getTexTarget()const { return mTarget ;}
- S8 getDiscardLevelInAtlas()const {return mDiscardLevelInAtlas;}
- U32 getTexelsInAtlas()const { return mTexelsInAtlas ;}
- U32 getTexelsInGLTexture()const {return mTexelsInGLTexture;}
-
+ LLGLenum getTexTarget()const { return mTarget; }
void init(bool usemipmaps);
virtual void cleanup(); // Clean up the LLImageGL so it can be reinitialized. Be careful when using this in derived class destructors
void setNeedsAlphaAndPickMask(bool need_mask);
- bool preAddToAtlas(S32 discard_level, const LLImageRaw* raw_image);
- void postAddToAtlas() ;
-
#if LL_IMAGEGL_THREAD_CHECK
// thread debugging
std::thread::id mActiveThread;
void checkActiveThread();
#endif
+ // scale down to the desired discard level using GPU
+ // returns true if texture was scaled down
+ // desired discard will be clamped to max discard
+ // if desired discard is less than or equal to current discard, no scaling will occur
+ // only works for GL_TEXTURE_2D target
+ bool scaleDown(S32 desired_discard);
+
public:
// Various GL/Rendering options
S64Bytes mTextureMemory;
@@ -240,15 +244,10 @@ private:
bool mGLTextureCreated ;
LLGLuint mTexName;
- //LLGLuint mNewTexName = 0; // tex name set by background thread to be applied in main thread
U16 mWidth;
U16 mHeight;
S8 mCurrentDiscardLevel;
- S8 mDiscardLevelInAtlas;
- U32 mTexelsInAtlas ;
- U32 mTexelsInGLTexture;
-
bool mAllowCompression;
protected:
@@ -275,7 +274,7 @@ protected:
// STATICS
public:
- static std::set<LLImageGL*> sImageList;
+ static std::unordered_set<LLImageGL*> sImageList;
static S32 sCount;
static F32 sLastFrameTime;
@@ -301,6 +300,8 @@ public:
private:
static S32 sMaxCategories;
static bool sSkipAnalyzeAlpha;
+ static U32 sScratchPBO;
+ static U32 sScratchPBOSize;
//the flag to allow to call readBackRaw(...).
//can be removed if we do not use that function at all.
diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp
index 4682044d6e..06f7a20add 100644
--- a/indra/llui/llaccordionctrl.cpp
+++ b/indra/llui/llaccordionctrl.cpp
@@ -379,12 +379,10 @@ void LLAccordionCtrl::initNoTabsWidget(const LLTextBox::Params& tb_params)
void LLAccordionCtrl::updateNoTabsHelpTextVisibility()
{
- bool visible_exists = false;
- std::vector<LLAccordionCtrlTab*>::const_iterator it = mAccordionTabs.begin();
- const std::vector<LLAccordionCtrlTab*>::const_iterator it_end = mAccordionTabs.end();
- while (it < it_end)
+ bool visible_exists{ false };
+ for (auto accordion_tab : mAccordionTabs)
{
- if ((*(it++))->getVisible())
+ if (accordion_tab->getVisible())
{
visible_exists = true;
break;
diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp
index 6d58a2545c..ac66525030 100644
--- a/indra/llui/llaccordionctrltab.cpp
+++ b/indra/llui/llaccordionctrltab.cpp
@@ -602,15 +602,13 @@ void LLAccordionCtrlTab::setSelected(bool is_selected)
LLView* LLAccordionCtrlTab::findContainerView()
{
- child_list_const_iter_t it = getChildList()->begin(), it_end = getChildList()->end();
- while (it != it_end)
+ for (auto child : *getChildList())
{
- LLView* child = *(it++);
if (DD_HEADER_NAME != child->getName() && child->getVisible())
return child;
}
- return NULL;
+ return nullptr;
}
void LLAccordionCtrlTab::selectOnFocusReceived()
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index 1799968afb..53f39766c6 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -1250,17 +1250,15 @@ void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
detached_items.clear();
// Go through items and detach valid items, remove them from items panel
// and add to detached_items.
- pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end();
- while (iter != iter_end)
+ for (auto item_pair : mItemPairs)
{
- LLPanel* pItem = (*iter)->first;
+ LLPanel* pItem = item_pair->first;
if (1 == pItem->notify(action))
{
- selectItemPair((*iter), false);
+ selectItemPair(item_pair, false);
mItemsPanel->removeChild(pItem);
- detached_items.push_back(pItem);
+ detached_items.emplace_back(pItem);
}
- iter++;
}
if (!detached_items.empty())
{
@@ -1268,12 +1266,10 @@ void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
if (detached_items.size() == mItemPairs.size())
{
// This way will be faster if all items were disconnected
- pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end();
- while (iter != iter_end)
+ for (auto item_pair : mItemPairs)
{
- (*iter)->first = NULL;
- delete *iter;
- iter++;
+ item_pair->first = nullptr;
+ delete item_pair;
}
mItemPairs.clear();
// Also set items panel height to zero.
@@ -1286,26 +1282,16 @@ void LLFlatListView::detachItems(std::vector<LLPanel*>& detached_items)
}
else
{
- std::vector<LLPanel*>::const_iterator
- detached_iter = detached_items.begin(),
- detached_iter_end = detached_items.end();
- while (detached_iter < detached_iter_end)
+ for (auto detached_item : detached_items)
{
- LLPanel* pDetachedItem = *detached_iter;
- pairs_iterator_t iter = mItemPairs.begin(), iter_end = mItemPairs.end();
- while (iter != iter_end)
+ auto found_pos = std::find_if(mItemPairs.begin(), mItemPairs.end(), [detached_item](auto item_pair) { return item_pair->first == detached_item; });
+ if (found_pos != mItemPairs.end())
{
- item_pair_t* item_pair = *iter;
- if (item_pair->first == pDetachedItem)
- {
- mItemPairs.erase(iter);
- item_pair->first = NULL;
- delete item_pair;
- break;
- }
- iter++;
+ mItemPairs.erase(found_pos);
+ auto item_pair = *found_pos;
+ item_pair->first = nullptr;
+ delete item_pair;
}
- detached_iter++;
}
rearrangeItems();
}
@@ -1412,11 +1398,10 @@ void LLFlatListViewEx::filterItems(bool re_sort, bool notify_parent)
action.with("match_filter", cur_filter);
mHasMatchedItems = false;
- bool visibility_changed = false;
- pairs_const_iterator_t iter = getItemPairs().begin(), iter_end = getItemPairs().end();
- while (iter != iter_end)
+ bool visibility_changed{ false };
+ for (auto item_pair : getItemPairs())
{
- LLPanel* pItem = (*(iter++))->first;
+ LLPanel* pItem = item_pair->first;
visibility_changed |= updateItemVisibility(pItem, action);
}
diff --git a/indra/llwebrtc/llwebrtc.cpp b/indra/llwebrtc/llwebrtc.cpp
index 92a2827d73..6dc632aba4 100644
--- a/indra/llwebrtc/llwebrtc.cpp
+++ b/indra/llwebrtc/llwebrtc.cpp
@@ -35,6 +35,7 @@
#include "api/media_stream_interface.h"
#include "api/media_stream_track.h"
#include "modules/audio_processing/audio_buffer.h"
+#include "modules/audio_mixer/audio_mixer_impl.h"
namespace llwebrtc
{
@@ -88,7 +89,7 @@ void LLAudioDeviceObserver::OnRenderData(const void *audio_samples,
{
}
-LLCustomProcessor::LLCustomProcessor() : mSampleRateHz(0), mNumChannels(0), mMicrophoneEnergy(0.0)
+LLCustomProcessor::LLCustomProcessor() : mSampleRateHz(0), mNumChannels(0), mMicrophoneEnergy(0.0), mGain(1.0)
{
memset(mSumVector, 0, sizeof(mSumVector));
}
@@ -128,9 +129,13 @@ void LLCustomProcessor::Process(webrtc::AudioBuffer *audio_in)
for (size_t index = 0; index < stream_config.num_samples(); index++)
{
float sample = frame_samples[index];
+ sample = sample * mGain; // apply gain
+ frame_samples[index] = sample; // write processed sample back to buffer.
energy += sample * sample;
}
+ audio_in->CopyFrom(&frame[0], stream_config);
+
// smooth it.
size_t buffer_size = sizeof(mSumVector) / sizeof(mSumVector[0]);
float totalSum = 0;
@@ -236,9 +241,9 @@ void LLWebRTCImpl::init()
webrtc::AudioProcessing::Config apm_config;
apm_config.echo_canceller.enabled = false;
apm_config.echo_canceller.mobile_mode = false;
- apm_config.gain_controller1.enabled = true;
+ apm_config.gain_controller1.enabled = false;
apm_config.gain_controller1.mode = webrtc::AudioProcessing::Config::GainController1::kAdaptiveAnalog;
- apm_config.gain_controller2.enabled = true;
+ apm_config.gain_controller2.enabled = false;
apm_config.high_pass_filter.enabled = true;
apm_config.noise_suppression.enabled = true;
apm_config.noise_suppression.level = webrtc::AudioProcessing::Config::NoiseSuppression::kVeryHigh;
@@ -260,6 +265,7 @@ void LLWebRTCImpl::init()
mAudioProcessingModule->ApplyConfig(apm_config);
mAudioProcessingModule->Initialize(processing_config);
+
mPeerConnectionFactory = webrtc::CreatePeerConnectionFactory(mNetworkThread.get(),
mWorkerThread.get(),
mSignalingThread.get(),
@@ -336,9 +342,9 @@ void LLWebRTCImpl::setAudioConfig(LLWebRTCDeviceInterface::AudioConfig config)
webrtc::AudioProcessing::Config apm_config;
apm_config.echo_canceller.enabled = config.mEchoCancellation;
apm_config.echo_canceller.mobile_mode = false;
- apm_config.gain_controller1.enabled = true;
+ apm_config.gain_controller1.enabled = config.mAGC;
apm_config.gain_controller1.mode = webrtc::AudioProcessing::Config::GainController1::kAdaptiveAnalog;
- apm_config.gain_controller2.enabled = true;
+ apm_config.gain_controller2.enabled = false;
apm_config.high_pass_filter.enabled = true;
apm_config.transient_suppression.enabled = true;
apm_config.pipeline.multi_channel_render = true;
@@ -612,6 +618,8 @@ float LLWebRTCImpl::getTuningAudioLevel() { return -20 * log10f(mTuningAudioDevi
float LLWebRTCImpl::getPeerConnectionAudioLevel() { return -20 * log10f(mPeerCustomProcessor->getMicrophoneEnergy()); }
+void LLWebRTCImpl::setPeerConnectionGain(float gain) { mPeerCustomProcessor->setGain(gain); }
+
//
// Peer Connection Helpers
@@ -937,7 +945,7 @@ void LLWebRTCPeerConnectionImpl::setSendVolume(float volume)
{
for (auto &track : mLocalStream->GetAudioTracks())
{
- track->GetSource()->SetVolume(volume);
+ track->GetSource()->SetVolume(volume*5.0);
}
}
});
diff --git a/indra/llwebrtc/llwebrtc.h b/indra/llwebrtc/llwebrtc.h
index b0b47bacc1..54eefc8554 100644
--- a/indra/llwebrtc/llwebrtc.h
+++ b/indra/llwebrtc/llwebrtc.h
@@ -145,6 +145,7 @@ class LLWebRTCDeviceInterface
virtual void setTuningMode(bool enable) = 0;
virtual float getTuningAudioLevel() = 0; // for use during tuning
virtual float getPeerConnectionAudioLevel() = 0; // for use when not tuning
+ virtual void setPeerConnectionGain(float gain) = 0;
};
// LLWebRTCAudioInterface provides the viewer with a way
diff --git a/indra/llwebrtc/llwebrtc_impl.h b/indra/llwebrtc/llwebrtc_impl.h
index cb54e83a63..2fb5525519 100644
--- a/indra/llwebrtc/llwebrtc_impl.h
+++ b/indra/llwebrtc/llwebrtc_impl.h
@@ -121,6 +121,8 @@ class LLCustomProcessor : public webrtc::CustomProcessing
float getMicrophoneEnergy() { return mMicrophoneEnergy; }
+ void setGain(float gain) { mGain = gain; }
+
protected:
static const int NUM_PACKETS_TO_FILTER = 30; // 300 ms of smoothing
int mSampleRateHz;
@@ -128,6 +130,7 @@ class LLCustomProcessor : public webrtc::CustomProcessing
float mSumVector[NUM_PACKETS_TO_FILTER];
float mMicrophoneEnergy;
+ float mGain;
};
@@ -160,6 +163,8 @@ class LLWebRTCImpl : public LLWebRTCDeviceInterface, public webrtc::AudioDeviceS
float getTuningAudioLevel() override;
float getPeerConnectionAudioLevel() override;
+ void setPeerConnectionGain(float gain) override;
+
//
// AudioDeviceSink
//
diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp
index 0fd4516844..7f6b8093fc 100644
--- a/indra/llxml/llxmlnode.cpp
+++ b/indra/llxml/llxmlnode.cpp
@@ -653,32 +653,24 @@ bool LLXMLNode::updateNode(
// static
bool LLXMLNode::parseFile(const std::string& filename, LLXMLNodePtr& node, LLXMLNode* defaults_tree)
{
- // Read file
- LL_DEBUGS("XMLNode") << "parsing XML file: " << filename << LL_ENDL;
- LLFILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */
- if (fp == NULL)
+ std::string xml = LLFile::getContents(filename);
+ if (xml.empty())
{
- node = NULL ;
- return false;
+ LL_WARNS("XMLNode") << "no XML file: " << filename << LL_ENDL;
+ }
+ else if (parseBuffer(xml.data(), xml.size(), node, defaults_tree))
+ {
+ return true;
}
- fseek(fp, 0, SEEK_END);
- U32 length = ftell(fp);
- fseek(fp, 0, SEEK_SET);
-
- U8* buffer = new U8[length+1];
- size_t nread = fread(buffer, 1, length, fp);
- buffer[nread] = 0;
- fclose(fp);
- bool rv = parseBuffer(buffer, static_cast<U32>(nread), node, defaults_tree);
- delete [] buffer;
- return rv;
+ node = nullptr;
+ return false;
}
// static
bool LLXMLNode::parseBuffer(
- U8* buffer,
- U32 length,
+ const char* buffer,
+ U64 length,
LLXMLNodePtr& node,
LLXMLNode* defaults)
{
@@ -693,20 +685,25 @@ bool LLXMLNode::parseBuffer(
file_node->mParser = &my_parser;
- XML_SetUserData(my_parser, (void *)file_node_ptr);
+ XML_SetUserData(my_parser, file_node_ptr);
// Do the parsing
- if (XML_Parse(my_parser, (const char *)buffer, length, true) != XML_STATUS_OK)
+ bool success = XML_STATUS_OK == XML_Parse(my_parser, buffer, (int)length, true);
+ if (!success)
{
LL_WARNS() << "Error parsing xml error code: "
<< XML_ErrorString(XML_GetErrorCode(my_parser))
<< " on line " << XML_GetCurrentLineNumber(my_parser)
+ << ", column " << XML_GetCurrentColumnNumber(my_parser)
<< LL_ENDL;
}
// Deinit
XML_ParserFree(my_parser);
+ if (!success)
+ return false;
+
if (!file_node->mChildren || file_node->mChildren->map.size() != 1)
{
LL_WARNS() << "Parse failure - wrong number of top-level nodes xml."
diff --git a/indra/llxml/llxmlnode.h b/indra/llxml/llxmlnode.h
index b8e29bbfef..b8f9e1ff69 100644
--- a/indra/llxml/llxmlnode.h
+++ b/indra/llxml/llxmlnode.h
@@ -129,20 +129,20 @@ public:
void addChild(LLXMLNodePtr& new_child);
void setParent(LLXMLNodePtr& new_parent); // reparent if necessary
- // Serialization
+ // Deserialization
static bool parseFile(
const std::string& filename,
LLXMLNodePtr& node,
- LLXMLNode* defaults_tree);
+ LLXMLNode* defaults = nullptr);
static bool parseBuffer(
- U8* buffer,
- U32 length,
+ const char* buffer,
+ U64 length,
LLXMLNodePtr& node,
- LLXMLNode* defaults);
+ LLXMLNode* defaults = nullptr);
static bool parseStream(
std::istream& str,
LLXMLNodePtr& node,
- LLXMLNode* defaults);
+ LLXMLNode* defaults = nullptr);
static bool updateNode(
LLXMLNodePtr& node,
LLXMLNodePtr& update_node);
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 3aaeb426da..cbcc85cc1c 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -219,6 +219,7 @@ set(viewer_SOURCE_FILES
llfloaterfonttest.cpp
llfloaterforgetuser.cpp
llfloatergesture.cpp
+ llfloatergltfasseteditor.cpp
llfloatergodtools.cpp
llfloatergotoline.cpp
llfloatergridstatus.cpp
@@ -313,6 +314,8 @@ set(viewer_SOURCE_FILES
llgesturemgr.cpp
llgiveinventory.cpp
llglsandbox.cpp
+ llgltffolderitem.cpp
+ llgltffoldermodel.cpp
llgltfmateriallist.cpp
llgltfmaterialpreviewmgr.cpp
llgroupactions.cpp
@@ -879,6 +882,7 @@ set(viewer_HEADER_FILES
llfloaterfonttest.h
llfloaterforgetuser.h
llfloatergesture.h
+ llfloatergltfasseteditor.h
llfloatergodtools.h
llfloatergotoline.h
llfloatergridstatus.h
@@ -975,6 +979,8 @@ set(viewer_HEADER_FILES
llgesturelistener.h
llgesturemgr.h
llgiveinventory.h
+ llgltffolderitem.h
+ llgltffoldermodel.h
llgltfmateriallist.h
llgltfmaterialpreviewmgr.h
llgroupactions.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 50632a7b07..c455b6f5f1 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7716,6 +7716,28 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>RenderMinFreeMainMemoryThreshold</key>
+ <map>
+ <key>Comment</key>
+ <string>Minimum of available physical memory in MB before textures get scaled down</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>512</integer>
+ </map>
+ <key>RenderLowMemMinDiscardIncrement</key>
+ <map>
+ <key>Comment</key>
+ <string>Minimum increment of discard level if system memory gets low</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>F32</string>
+ <key>Value</key>
+ <real>0.1</real>
+ </map>
<key>RenderMaxTextureIndex</key>
<map>
<key>Comment</key>
@@ -13065,7 +13087,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>AutoDisengageMic</key>
<map>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl
index 902746366d..6d05d983f3 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/normgenF.glsl
@@ -25,24 +25,53 @@
/*[EXTRA_CODE_HERE]*/
+
+
+// generate a normal map using an approximation of the old emboss bump map "brightness/darkness" technique
+// srcMap is a source color image, output should be a normal
+
out vec4 frag_color;
-uniform sampler2D alphaMap;
+uniform sampler2D srcMap;
in vec2 vary_texcoord0;
uniform float stepX;
uniform float stepY;
uniform float norm_scale;
+uniform int bump_code;
+
+#define BE_BRIGHTNESS 1
+#define BE_DARKNESS 2
+
+// get luminance or inverse luminance depending on bump_code
+float getBumpValue(vec2 texcoord)
+{
+ vec3 c = texture(srcMap, texcoord).rgb;
+
+ vec3 WEIGHT = vec3(0.2995, 0.5875, 0.1145);
+
+ float l = dot(c, WEIGHT);
+
+ if (bump_code == BE_DARKNESS)
+ {
+ l = 1.0 - l;
+ }
+
+ return l;
+}
+
void main()
{
- float c = texture(alphaMap, vary_texcoord0).r;
+ float c = getBumpValue(vary_texcoord0).r;
+
+ float scaler = 512.0;
- vec3 right = vec3(norm_scale, 0, (texture(alphaMap, vary_texcoord0+vec2(stepX, 0)).r-c)*255);
- vec3 left = vec3(-norm_scale, 0, (texture(alphaMap, vary_texcoord0-vec2(stepX, 0)).r-c)*255);
- vec3 up = vec3(0, -norm_scale, (texture(alphaMap, vary_texcoord0-vec2(0, stepY)).r-c)*255);
- vec3 down = vec3(0, norm_scale, (texture(alphaMap, vary_texcoord0+vec2(0, stepY)).r-c)*255);
+ vec3 right = vec3(norm_scale, 0, (getBumpValue(vary_texcoord0+vec2(stepX, 0)).r-c)*scaler);
+ vec3 left = vec3(-norm_scale, 0, (getBumpValue(vary_texcoord0-vec2(stepX, 0)).r-c)*scaler);
+ vec3 up = vec3(0, -norm_scale, (getBumpValue(vary_texcoord0-vec2(0, stepY)).r-c)*scaler);
+ vec3 down = vec3(0, norm_scale, (getBumpValue(vary_texcoord0+vec2(0, stepY)).r-c)*scaler);
vec3 norm = cross(right, down) + cross(down, left) + cross(left,up) + cross(up, right);
diff --git a/indra/newview/gltf/buffer_util.h b/indra/newview/gltf/buffer_util.h
index 40f9448aaf..89cedf4a47 100644
--- a/indra/newview/gltf/buffer_util.h
+++ b/indra/newview/gltf/buffer_util.h
@@ -181,6 +181,16 @@ namespace LL
}
template<>
+ inline void copyVec4<U8, U64>(U8* src, U64& dst)
+ {
+ U8* data = (U8*)&dst;
+ data[0] = src[0];
+ data[1] = src[1];
+ data[2] = src[2];
+ data[3] = src[3];
+ }
+
+ template<>
inline void copyVec4<U16, LLColor4U>(U16* src, LLColor4U& dst)
{
dst.set(src[0], src[1], src[2], src[3]);
diff --git a/indra/newview/gltfscenemanager.cpp b/indra/newview/gltfscenemanager.cpp
index 7b2de4d6de..b161ec8492 100644
--- a/indra/newview/gltfscenemanager.cpp
+++ b/indra/newview/gltfscenemanager.cpp
@@ -42,6 +42,7 @@
#include "llviewertexturelist.h"
#include "llimagej2c.h"
#include "llfloaterperms.h"
+#include "llfloaterreg.h"
#include "llagentbenefits.h"
#include "llfilesystem.h"
#include "boost/json.hpp"
@@ -144,7 +145,7 @@ void GLTFSceneManager::uploadSelection()
}
else
{
- raw = image.mTexture->getCachedRawImage();
+ raw = image.mTexture->getRawImage();
}
if (raw.notNull())
@@ -314,6 +315,7 @@ void GLTFSceneManager::load(const std::string& filename)
{
mObjects.push_back(obj);
}
+ LLFloaterReg::showInstance("gltf_asset_editor");
}
}
else
@@ -339,6 +341,7 @@ void GLTFSceneManager::renderAlpha()
void GLTFSceneManager::addGLTFObject(LLViewerObject* obj, LLUUID gltf_id)
{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_GLTF;
llassert(obj->getVolume()->getParams().getSculptID() == gltf_id);
llassert(obj->getVolume()->getParams().getSculptType() == LL_SCULPT_TYPE_GLTF);
diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index 06c87343e2..8a4ab091a3 100644
--- a/indra/newview/llcurrencyuimanager.cpp
+++ b/indra/newview/llcurrencyuimanager.cpp
@@ -111,16 +111,17 @@ public:
bool hasEstimate() const;
std::string getLocalEstimate() const;
- void startTransaction(TransactionType type,
- const char* method, LLXMLRPCValue params);
+ void startTransaction(TransactionType type, const char* method, const LLSD& params);
+
+ // return true if update needed
bool checkTransaction();
- // return true if update needed
void setError(const std::string& message, const std::string& uri);
void clearError();
+ // return true if update needed
bool considerUpdateCurrency();
- // return true if update needed
+
void currencyKey(S32);
static void onCurrencyKey(LLLineEditor* caller, void* data);
@@ -160,32 +161,29 @@ void LLCurrencyUIManager::Impl::updateCurrencyInfo()
return;
}
- LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
- keywordArgs.appendString("agentId", gAgent.getID().asString());
- keywordArgs.appendString(
- "secureSessionId",
- gAgent.getSecureSessionID().asString());
- keywordArgs.appendString("language", LLUI::getLanguage());
- keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
- keywordArgs.appendString("viewerChannel", LLVersionInfo::instance().getChannel());
- keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::instance().getMajor());
- keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::instance().getMinor());
- keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::instance().getPatch());
+ const LLVersionInfo& vi(LLVersionInfo::instance());
+
+ LLSD params = LLSD::emptyMap();
+ params["agentId"] = gAgent.getID().asString();
+ params["secureSessionId"] = gAgent.getSecureSessionID().asString();
+ params["language"] = LLUI::getLanguage();
+ params["currencyBuy"] = mUserCurrencyBuy;
+ params["viewerChannel"] = vi.getChannel();
+ params["viewerMajorVersion"] = vi.getMajor();
+ params["viewerMinorVersion"] = vi.getMinor();
+ params["viewerPatchVersion"] = vi.getPatch();
// With GitHub builds, the build number is too big to fit in a 32-bit int,
- // and XMLRPC_VALUE doesn't deal with integers wider than int. Use string.
- keywordArgs.appendString("viewerBuildVersion", stringize(LLVersionInfo::instance().getBuild()));
-
- LLXMLRPCValue params = LLXMLRPCValue::createArray();
- params.append(keywordArgs);
+ // and XMLRPC value doesn't deal with integers wider than int. Use string.
+ params["viewerBuildVersion"] = std::to_string(vi.getBuild());
startTransaction(TransactionCurrency, "getCurrencyQuote", params);
}
void LLCurrencyUIManager::Impl::finishCurrencyInfo()
{
- LLXMLRPCValue result = mTransaction->responseValue();
+ const LLSD& result = mTransaction->response();
- bool success = result["success"].asBool();
+ bool success = result["success"].asBoolean();
if (!success)
{
setError(
@@ -195,24 +193,24 @@ void LLCurrencyUIManager::Impl::finishCurrencyInfo()
return;
}
- LLXMLRPCValue currency = result["currency"];
+ const LLSD& currency = result["currency"];
// old XML-RPC server: estimatedCost = value in US cents
- mUSDCurrencyEstimated = currency["estimatedCost"].isValid();
+ mUSDCurrencyEstimated = currency.has("estimatedCost");
if (mUSDCurrencyEstimated)
{
- mUSDCurrencyEstimatedCost = currency["estimatedCost"].asInt();
+ mUSDCurrencyEstimatedCost = currency["estimatedCost"].asInteger();
}
// newer XML-RPC server: estimatedLocalCost = local currency string
- mLocalCurrencyEstimated = currency["estimatedLocalCost"].isValid();
+ mLocalCurrencyEstimated = currency.has("estimatedLocalCost");
if (mLocalCurrencyEstimated)
{
mLocalCurrencyEstimatedCost = currency["estimatedLocalCost"].asString();
mSupportsInternationalBilling = true;
}
- S32 newCurrencyBuy = currency["currencyBuy"].asInt();
+ S32 newCurrencyBuy = currency["currencyBuy"].asInteger();
if (newCurrencyBuy != mUserCurrencyBuy)
{
mUserCurrencyBuy = newCurrencyBuy;
@@ -224,36 +222,36 @@ void LLCurrencyUIManager::Impl::finishCurrencyInfo()
void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
{
- LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
- keywordArgs.appendString("agentId", gAgent.getID().asString());
- keywordArgs.appendString(
- "secureSessionId",
- gAgent.getSecureSessionID().asString());
- keywordArgs.appendString("language", LLUI::getLanguage());
- keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
+ const LLVersionInfo& vi(LLVersionInfo::instance());
+
+ LLSD params = LLSD::emptyMap();
+ params["agentId"] = gAgent.getID().asString();
+ params["secureSessionId"] = gAgent.getSecureSessionID().asString();
+ params["language"] = LLUI::getLanguage();
+ params["currencyBuy"] = mUserCurrencyBuy;
+ params["confirm"] = mSiteConfirm;
+ params["viewerChannel"] = vi.getChannel();
+ params["viewerMajorVersion"] = vi.getMajor();
+ params["viewerMinorVersion"] = vi.getMinor();
+ params["viewerPatchVersion"] = vi.getPatch();
+ // With GitHub builds, the build number is too big to fit in a 32-bit int,
+ // and XMLRPC value doesn't deal with integers wider than int. Use string.
+ params["viewerBuildVersion"] = std::to_string(vi.getBuild());
+
if (mUSDCurrencyEstimated)
{
- keywordArgs.appendInt("estimatedCost", mUSDCurrencyEstimatedCost);
+ params["estimatedCost"] = mUSDCurrencyEstimatedCost;
}
+
if (mLocalCurrencyEstimated)
{
- keywordArgs.appendString("estimatedLocalCost", mLocalCurrencyEstimatedCost);
+ params["estimatedLocalCost"] = mLocalCurrencyEstimatedCost;
}
- keywordArgs.appendString("confirm", mSiteConfirm);
+
if (!password.empty())
{
- keywordArgs.appendString("password", password);
+ params["password"] = password;
}
- keywordArgs.appendString("viewerChannel", LLVersionInfo::instance().getChannel());
- keywordArgs.appendInt("viewerMajorVersion", LLVersionInfo::instance().getMajor());
- keywordArgs.appendInt("viewerMinorVersion", LLVersionInfo::instance().getMinor());
- keywordArgs.appendInt("viewerPatchVersion", LLVersionInfo::instance().getPatch());
- // With GitHub builds, the build number is too big to fit in a 32-bit int,
- // and XMLRPC_VALUE doesn't deal with integers wider than int. Use string.
- keywordArgs.appendString("viewerBuildVersion", stringize(LLVersionInfo::instance().getBuild()));
-
- LLXMLRPCValue params = LLXMLRPCValue::createArray();
- params.append(keywordArgs);
startTransaction(TransactionBuy, "buyCurrency", params);
@@ -263,9 +261,9 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
void LLCurrencyUIManager::Impl::finishCurrencyBuy()
{
- LLXMLRPCValue result = mTransaction->responseValue();
+ const LLSD& result = mTransaction->response();
- bool success = result["success"].asBool();
+ bool success = result["success"].asBoolean();
if (!success)
{
setError(
@@ -282,7 +280,7 @@ void LLCurrencyUIManager::Impl::finishCurrencyBuy()
}
void LLCurrencyUIManager::Impl::startTransaction(TransactionType type,
- const char* method, LLXMLRPCValue params)
+ const char* method, const LLSD& params)
{
static std::string transactionURI;
if (transactionURI.empty())
@@ -293,12 +291,7 @@ void LLCurrencyUIManager::Impl::startTransaction(TransactionType type,
delete mTransaction;
mTransactionType = type;
- mTransaction = new LLXMLRPCTransaction(
- transactionURI,
- method,
- params,
- false /* don't use gzip */
- );
+ mTransaction = new LLXMLRPCTransaction(transactionURI, method, params);
clearError();
}
@@ -352,12 +345,17 @@ bool LLCurrencyUIManager::Impl::checkTransaction()
{
setError(mTransaction->statusMessage(), mTransaction->statusURI());
}
- else {
+ else
+ {
switch (mTransactionType)
{
- case TransactionCurrency: finishCurrencyInfo(); break;
- case TransactionBuy: finishCurrencyBuy(); break;
- default: ;
+ case TransactionCurrency:
+ finishCurrencyInfo();
+ break;
+ case TransactionBuy:
+ finishCurrencyBuy();
+ break;
+ default:;
}
}
@@ -385,9 +383,8 @@ void LLCurrencyUIManager::Impl::clearError()
bool LLCurrencyUIManager::Impl::considerUpdateCurrency()
{
- if (mCurrencyChanged
- && !mTransaction
- && mCurrencyKeyTimer.getElapsedTimeF32() >= CURRENCY_ESTIMATE_FREQUENCY)
+ if (mCurrencyChanged && !mTransaction &&
+ mCurrencyKeyTimer.getElapsedTimeF32() >= CURRENCY_ESTIMATE_FREQUENCY)
{
updateCurrencyInfo();
return true;
@@ -408,7 +405,8 @@ void LLCurrencyUIManager::Impl::currencyKey(S32 value)
mUserCurrencyBuy = value;
- if (hasEstimate()) {
+ if (hasEstimate())
+ {
clearEstimate();
//cannot just simply refresh the whole UI, as the edit field will
// get reset and the cursor will change...
@@ -421,8 +419,7 @@ void LLCurrencyUIManager::Impl::currencyKey(S32 value)
}
// static
-void LLCurrencyUIManager::Impl::onCurrencyKey(
- LLLineEditor* caller, void* data)
+void LLCurrencyUIManager::Impl::onCurrencyKey(LLLineEditor* caller, void* data)
{
S32 value = atoi(caller->getText().c_str());
LLCurrencyUIManager::Impl* self = (LLCurrencyUIManager::Impl*)data;
@@ -589,14 +586,12 @@ bool LLCurrencyUIManager::inProcess()
bool LLCurrencyUIManager::canCancel()
{
- return impl.mTransactionType != Impl::TransactionBuy;
+ return !buying();
}
bool LLCurrencyUIManager::canBuy()
{
- return impl.mTransactionType == Impl::TransactionNone
- && impl.hasEstimate()
- && impl.mUserCurrencyBuy > 0;
+ return !inProcess() && impl.hasEstimate() && impl.mUserCurrencyBuy > 0;
}
bool LLCurrencyUIManager::buying()
diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp
index b88d11886a..0596a8fe7d 100644
--- a/indra/newview/lldebugview.cpp
+++ b/indra/newview/lldebugview.cpp
@@ -105,10 +105,7 @@ void LLDebugView::init()
addChild(gSceneMonitorView);
gSceneMonitorView->setRect(rect);
- r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f),
- (S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f));
-
- r.set(150, rect.getHeight() - 50, 820, 100);
+ r.set(150, rect.getHeight() - 60, 820, 110);
LLTextureView::Params tvp;
tvp.name("gTextureView");
tvp.rect(r);
@@ -116,7 +113,6 @@ void LLDebugView::init()
tvp.visible(false);
gTextureView = LLUICtrlFactory::create<LLTextureView>(tvp);
addChild(gTextureView);
- //gTextureView->reshape(r.getWidth(), r.getHeight(), true);
}
void LLDebugView::draw()
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 055f99d764..7289e95b6e 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -79,11 +79,6 @@ static S32 diffuse_channel = -1;
static S32 bump_channel = -1;
static bool shiny = false;
-// Enabled after changing LLViewerTexture::mNeedsCreateTexture to an
-// LLAtomicBool; this should work just fine, now. HB
-#define LL_BUMPLIST_MULTITHREADED 1
-
-
// static
void LLStandardBumpmap::shutdown()
{
@@ -764,24 +759,21 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText
LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
llassert( (bump_code == BE_BRIGHTNESS) || (bump_code == BE_DARKNESS) );
- LLViewerTexture* bump = NULL;
+ LLViewerTexture* bump = nullptr;
- bump_image_map_t* entries_list = NULL;
- void (*callback_func)( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata ) = NULL;
+ bump_image_map_t* entries_list = nullptr;
switch( bump_code )
{
case BE_BRIGHTNESS:
entries_list = &mBrightnessEntries;
- callback_func = LLBumpImageList::onSourceBrightnessLoaded;
break;
case BE_DARKNESS:
entries_list = &mDarknessEntries;
- callback_func = LLBumpImageList::onSourceDarknessLoaded;
break;
default:
llassert(0);
- return NULL;
+ return nullptr;
}
bump_image_map_t::iterator iter = entries_list->find(src_image->getID());
@@ -789,51 +781,18 @@ LLViewerTexture* LLBumpImageList::getBrightnessDarknessImage(LLViewerFetchedText
{
bump = iter->second;
}
- else
- {
- (*entries_list)[src_image->getID()] = LLViewerTextureManager::getLocalTexture( true );
- bump = (*entries_list)[src_image->getID()]; // In case callback was called immediately and replaced the image
- }
-
- if (!src_image->hasCallbacks())
- { //if image has no callbacks but resolutions don't match, trigger raw image loaded callback again
- if (src_image->getWidth() != bump->getWidth() ||
- src_image->getHeight() != bump->getHeight())// ||
- //(LLPipeline::sRenderDeferred && bump->getComponents() != 4))
- {
- src_image->setBoostLevel(LLGLTexture::BOOST_BUMP) ;
- src_image->setLoadedCallback( callback_func, 0, true, false, new LLUUID(src_image->getID()), NULL );
- src_image->forceToSaveRawImage(0) ;
- }
- }
-
- return bump;
-}
-
-// static
-void LLBumpImageList::onSourceBrightnessLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata )
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- LLUUID* source_asset_id = (LLUUID*)userdata;
- LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_BRIGHTNESS );
- if( final )
+ if (bump == nullptr ||
+ src_image->getWidth() != bump->getWidth() ||
+ src_image->getHeight() != bump->getHeight())
{
- delete source_asset_id;
+ onSourceUpdated(src_image, (EBumpEffect) bump_code);
}
-}
-// static
-void LLBumpImageList::onSourceDarknessLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata )
-{
- LLUUID* source_asset_id = (LLUUID*)userdata;
- LLBumpImageList::onSourceLoaded( success, src_vi, src, *source_asset_id, BE_DARKNESS );
- if( final )
- {
- delete source_asset_id;
- }
+ return (*entries_list)[src_image->getID()];
}
+
void LLBumpImageList::onSourceStandardLoaded( bool success, LLViewerFetchedTexture* src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata)
{
if (success && LLPipeline::sRenderDeferred)
@@ -909,289 +868,108 @@ void LLBumpImageList::generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nr
}
// static
-void LLBumpImageList::onSourceLoaded( bool success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump_code )
+void LLBumpImageList::onSourceUpdated(LLViewerTexture* src, EBumpEffect bump_code)
{
- LL_PROFILE_ZONE_SCOPED;
-
- if( success )
- {
- LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
-
- LLImageDataSharedLock lock(src);
-
- bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries );
- bump_image_map_t::iterator iter = entries_list.find(source_asset_id);
-
- {
- if (iter == entries_list.end() ||
- iter->second.isNull() ||
- iter->second->getWidth() != src->getWidth() ||
- iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
- { //make sure an entry exists for this image
- entries_list[src_vi->getID()] = LLViewerTextureManager::getLocalTexture(true);
- iter = entries_list.find(src_vi->getID());
- }
- }
-
- if (iter->second->getWidth() != src->getWidth() ||
- iter->second->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
- {
- LLPointer<LLImageRaw> dst_image = new LLImageRaw(src->getWidth(), src->getHeight(), 1);
- U8* dst_data = dst_image->getData();
- S32 dst_data_size = dst_image->getDataSize();
-
- const U8* src_data = src->getData();
- S32 src_data_size = src->getDataSize();
-
- S32 src_components = src->getComponents();
-
- // Convert to luminance and then scale and bias that to get ready for
- // embossed bump mapping. (0-255 maps to 127-255)
-
- // Convert to fixed point so we don't have to worry about precision/clamping.
- const S32 FIXED_PT = 8;
- const S32 R_WEIGHT = S32(0.2995f * (1<<FIXED_PT));
- const S32 G_WEIGHT = S32(0.5875f * (1<<FIXED_PT));
- const S32 B_WEIGHT = S32(0.1145f * (1<<FIXED_PT));
-
- S32 minimum = 255;
- S32 maximum = 0;
-
- switch( src_components )
- {
- case 1:
- case 2:
- {
- if( src_data_size == dst_data_size * src_components )
- {
- for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
- {
- dst_data[i] = src_data[j];
- if( dst_data[i] < minimum )
- {
- minimum = dst_data[i];
- }
- if( dst_data[i] > maximum )
- {
- maximum = dst_data[i];
- }
- }
- }
- else
- {
- llassert(0);
- dst_image->clear();
- }
- }
- break;
- case 3:
- case 4:
- {
- if( src_data_size == dst_data_size * src_components )
- {
- for( S32 i = 0, j=0; i < dst_data_size; i++, j+= src_components )
- {
- // RGB to luminance
- dst_data[i] = (R_WEIGHT * src_data[j] + G_WEIGHT * src_data[j+1] + B_WEIGHT * src_data[j+2]) >> FIXED_PT;
- //llassert( dst_data[i] <= 255 );true because it's 8bit
- if( dst_data[i] < minimum )
- {
- minimum = dst_data[i];
- }
- if( dst_data[i] > maximum )
- {
- maximum = dst_data[i];
- }
- }
- }
- else
- {
- llassert(0);
- dst_image->clear();
- }
- }
- break;
- default:
- llassert(0);
- dst_image->clear();
- break;
- }
-
- if( maximum > minimum )
- {
- U8 bias_and_scale_lut[256];
- F32 twice_one_over_range = 2.f / (maximum - minimum);
- S32 i;
-
- const F32 ARTIFICIAL_SCALE = 2.f; // Advantage: exaggerates the effect in midrange. Disadvantage: clamps at the extremes.
- if (BE_DARKNESS == bump_code)
- {
- for( i = minimum; i <= maximum; i++ )
- {
- F32 minus_one_to_one = F32(maximum - i) * twice_one_over_range - 1.f;
- bias_and_scale_lut[i] = llclampb(ll_round(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
- }
- }
- else
- {
- for( i = minimum; i <= maximum; i++ )
- {
- F32 minus_one_to_one = F32(i - minimum) * twice_one_over_range - 1.f;
- bias_and_scale_lut[i] = llclampb(ll_round(127 * minus_one_to_one * ARTIFICIAL_SCALE + 128));
- }
- }
-
- for( i = 0; i < dst_data_size; i++ )
- {
- dst_data[i] = bias_and_scale_lut[dst_data[i]];
- }
- }
-
- //---------------------------------------------------
- // immediately assign bump to a smart pointer in case some local smart pointer
- // accidentally releases it.
- LLPointer<LLViewerTexture> bump = iter->second;
-
- if (!LLPipeline::sRenderDeferred)
- {
- bump->setExplicitFormat(GL_ALPHA8, GL_ALPHA);
-
-#if LL_BUMPLIST_MULTITHREADED
- auto tex_queue = LLImageGLThread::sEnabledTextures ? sTexUpdateQueue.lock() : nullptr;
-
- if (tex_queue)
- { //dispatch creation to background thread
- LLImageRaw* dst_ptr = dst_image;
- LLViewerTexture* bump_ptr = bump;
- dst_ptr->ref();
- bump_ptr->ref();
- tex_queue->post(
- [=]()
- {
- LL_PROFILE_ZONE_NAMED("bil - create texture");
- bump_ptr->createGLTexture(0, dst_ptr);
- bump_ptr->unref();
- dst_ptr->unref();
- });
-
- }
- else
-#endif
- {
- bump->createGLTexture(0, dst_image);
- }
- }
- else
- { //convert to normal map
- LL_PROFILE_ZONE_NAMED("bil - create normal map");
- LLImageGL* img = bump->getGLTexture();
- LLImageRaw* dst_ptr = dst_image.get();
- LLGLTexture* bump_ptr = bump.get();
-
- dst_ptr->ref();
- img->ref();
- bump_ptr->ref();
- auto create_func = [=]()
- {
- img->setUseMipMaps(true);
- // upload dst_image to GPU (greyscale in red channel)
- img->setExplicitFormat(GL_RED, GL_RED);
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_DRAWPOOL;
- bump_ptr->createGLTexture(0, dst_ptr);
- dst_ptr->unref();
- };
+ const LLUUID& src_id = src->getID();
- auto generate_func = [=]()
- {
- // Allocate an empty RGBA texture at "tex_name" the same size as bump
- // Note: bump will still point at GPU copy of dst_image
- bump_ptr->setExplicitFormat(GL_RGBA, GL_RGBA);
- LLGLuint tex_name;
- img->createGLTexture(0, nullptr, false, 0, true, &tex_name);
+ bump_image_map_t& entries_list(bump_code == BE_BRIGHTNESS ? gBumpImageList.mBrightnessEntries : gBumpImageList.mDarknessEntries);
+ bump_image_map_t::iterator iter = entries_list.find(src_id);
- // point render target at empty buffer
- sRenderTarget.setColorAttachment(img, tex_name);
+ if (iter == entries_list.end())
+ { //make sure an entry exists for this image
+ entries_list[src_id] = LLViewerTextureManager::getLocalTexture(true);
+ iter = entries_list.find(src_id);
+ }
- // generate normal map in empty texture
- {
- sRenderTarget.bindTarget();
+ //---------------------------------------------------
+ // immediately assign bump to a smart pointer in case some local smart pointer
+ // accidentally releases it.
+ LLPointer<LLViewerTexture> bump = iter->second;
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable cull(GL_CULL_FACE);
- LLGLDisable blend(GL_BLEND);
- gGL.setColorMask(true, true);
+ if (bump->getWidth() != src->getWidth() ||
+ bump->getHeight() != src->getHeight()) // bump not cached yet or has changed resolution
+ {
+ //convert to normal map
+ LL_PROFILE_ZONE_NAMED("bil - create normal map");
- gNormalMapGenProgram.bind();
+ bump->setExplicitFormat(GL_RGBA, GL_RGBA);
- static LLStaticHashedString sNormScale("norm_scale");
- static LLStaticHashedString sStepX("stepX");
- static LLStaticHashedString sStepY("stepY");
+ LLImageGL* src_img = src->getGLTexture();
+ LLImageGL* dst_img = bump->getGLTexture();
+ dst_img->setSize(src->getWidth(), src->getHeight(), 4, 0);
+ dst_img->setUseMipMaps(true);
+ dst_img->setDiscardLevel(0);
+ dst_img->createGLTexture();
- gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
- gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump_ptr->getWidth());
- gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump_ptr->getHeight());
+ gGL.getTexUnit(0)->bind(bump);
- gGL.getTexUnit(0)->bind(bump_ptr);
+ LLImageGL::setManualImage(GL_TEXTURE_2D, 0, dst_img->getPrimaryFormat(), dst_img->getWidth(), dst_img->getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, nullptr, false);
- gGL.begin(LLRender::TRIANGLE_STRIP);
- gGL.texCoord2f(0, 0);
- gGL.vertex2f(0, 0);
+ LLGLuint tex_name = dst_img->getTexName();
+ // point render target at empty buffer
+ sRenderTarget.setColorAttachment(bump->getGLTexture(), tex_name);
- gGL.texCoord2f(0, 1);
- gGL.vertex2f(0, 1);
+ // generate normal map in empty texture
+ {
+ sRenderTarget.bindTarget();
- gGL.texCoord2f(1, 0);
- gGL.vertex2f(1, 0);
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable cull(GL_CULL_FACE);
+ LLGLDisable blend(GL_BLEND);
+ gGL.setColorMask(true, true);
- gGL.texCoord2f(1, 1);
- gGL.vertex2f(1, 1);
+ LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
+ gNormalMapGenProgram.bind();
- gGL.end();
+ static LLStaticHashedString sNormScale("norm_scale");
+ static LLStaticHashedString sStepX("stepX");
+ static LLStaticHashedString sStepY("stepY");
+ static LLStaticHashedString sBumpCode("bump_code");
- gGL.flush();
+ gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale"));
+ gNormalMapGenProgram.uniform1f(sStepX, 1.f / bump->getWidth());
+ gNormalMapGenProgram.uniform1f(sStepY, 1.f / bump->getHeight());
+ gNormalMapGenProgram.uniform1i(sBumpCode, bump_code);
- gNormalMapGenProgram.unbind();
+ gGL.getTexUnit(0)->bind(src);
- sRenderTarget.flush();
- sRenderTarget.releaseColorAttachment();
- }
+ gGL.begin(LLRender::TRIANGLE_STRIP);
+ gGL.texCoord2f(0, 0);
+ gGL.vertex2f(0, 0);
- // point bump at normal map and free gpu copy of dst_image
- img->syncTexName(tex_name);
+ gGL.texCoord2f(0, 1);
+ gGL.vertex2f(0, 1);
- // generate mipmap
- gGL.getTexUnit(0)->bind(img);
- glGenerateMipmap(GL_TEXTURE_2D);
- gGL.getTexUnit(0)->disable();
+ gGL.texCoord2f(1, 0);
+ gGL.vertex2f(1, 0);
- bump_ptr->unref();
- img->unref();
- };
+ gGL.texCoord2f(1, 1);
+ gGL.vertex2f(1, 1);
-#if LL_BUMPLIST_MULTITHREADED
- auto main_queue = LLImageGLThread::sEnabledTextures ? sMainQueue.lock() : nullptr;
+ gGL.end();
- if (main_queue)
- { //dispatch texture upload to background thread, issue GPU commands to generate normal map on main thread
- main_queue->postTo(
- sTexUpdateQueue,
- create_func,
- generate_func);
- }
- else
-#endif
- { // immediate upload texture and generate normal map
- create_func();
- generate_func();
- }
+ gGL.flush();
+ sRenderTarget.flush();
+ sRenderTarget.releaseColorAttachment();
+ if (shader)
+ {
+ shader->bind();
}
-
- iter->second = bump; // derefs (and deletes) old image
- //---------------------------------------------------
}
+
+ // generate mipmap
+ gGL.getTexUnit(0)->bind(bump);
+ glGenerateMipmap(GL_TEXTURE_2D);
+ gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
+
+ iter->second = bump; // derefs (and deletes) old image
+ //---------------------------------------------------
+
}
void LLDrawPoolBump::pushBumpBatches(U32 type)
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index 65cb9af015..15976884ca 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -140,14 +140,13 @@ public:
LLViewerTexture* getBrightnessDarknessImage(LLViewerFetchedTexture* src_image, U8 bump_code);
void addTextureStats(U8 bump, const LLUUID& base_image_id, F32 virtual_size);
- static void onSourceBrightnessLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata );
- static void onSourceDarknessLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata );
static void onSourceStandardLoaded( bool success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, bool final, void* userdata );
static void generateNormalMapFromAlpha(LLImageRaw* src, LLImageRaw* nrm_image);
private:
- static void onSourceLoaded( bool success, LLViewerTexture *src_vi, LLImageRaw* src, LLUUID& source_asset_id, EBumpEffect bump );
+ // should be called whenever resolution of src_vi changes compared to the current entry
+ static void onSourceUpdated( LLViewerTexture *src_vi, EBumpEffect bump );
private:
typedef std::unordered_map<LLUUID, LLPointer<LLViewerTexture> > bump_image_map_t;
diff --git a/indra/newview/llfloateravatar.cpp b/indra/newview/llfloateravatar.cpp
index 6a38d7549c..404316275d 100644
--- a/indra/newview/llfloateravatar.cpp
+++ b/indra/newview/llfloateravatar.cpp
@@ -25,11 +25,6 @@
* $/LicenseInfo$
*/
-/**
- * Floater that appears when buying an object, giving a preview
- * of its contents and their permissions.
- */
-
#include "llviewerprecompiledheaders.h"
#include "llfloateravatar.h"
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 570a223908..11505e3047 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -182,7 +182,7 @@ public:
void refreshUI();
- void startTransaction(TransactionType type, const LLXMLRPCValue& params);
+ void startTransaction(TransactionType type, const LLSD& params);
bool checkTransaction();
void tellUserError(const std::string& message, const std::string& uri);
@@ -396,11 +396,10 @@ void LLFloaterBuyLandUI::updateParcelInfo()
// Can't have more than region max tasks, regardless of parcel
// object bonus factor.
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
- if(region)
+ if (region)
{
S32 max_tasks_per_region = (S32)region->getMaxTasks();
- mParcelSupportedObjects = llmin(
- mParcelSupportedObjects, max_tasks_per_region);
+ mParcelSupportedObjects = llmin(mParcelSupportedObjects, max_tasks_per_region);
}
mParcelSoldWithObjects = parcel->getSellWithObjects();
@@ -423,7 +422,7 @@ void LLFloaterBuyLandUI::updateParcelInfo()
// checks that we can buy the land
- if(mIsForGroup && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
+ if (mIsForGroup && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED))
{
mCannotBuyReason = getString("cant_buy_for_group");
return;
@@ -492,85 +491,56 @@ void LLFloaterBuyLandUI::updateParcelInfo()
void LLFloaterBuyLandUI::updateCovenantInfo()
{
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
- if(!region) return;
+ if (!region)
+ return;
U8 sim_access = region->getSimAccess();
std::string rating = LLViewerRegion::accessToString(sim_access);
LLTextBox* region_name = getChild<LLTextBox>("region_name_text");
- if (region_name)
- {
- std::string region_name_txt = region->getName() + " ("+rating +")";
- region_name->setText(region_name_txt);
+ std::string region_name_txt = region->getName() + " ("+rating +")";
+ region_name->setText(region_name_txt);
- LLIconCtrl* rating_icon = getChild<LLIconCtrl>("rating_icon");
- LLRect rect = rating_icon->getRect();
- S32 region_name_width = llmin(region_name->getRect().getWidth(), region_name->getTextBoundingRect().getWidth());
- S32 icon_left_pad = region_name->getRect().mLeft + region_name_width + ICON_PAD;
- region_name->setToolTip(region_name->getText());
- rating_icon->setRect(rect.setOriginAndSize(icon_left_pad, rect.mBottom, rect.getWidth(), rect.getHeight()));
+ LLIconCtrl* rating_icon = getChild<LLIconCtrl>("rating_icon");
+ LLRect rect = rating_icon->getRect();
+ S32 region_name_width = llmin(region_name->getRect().getWidth(), region_name->getTextBoundingRect().getWidth());
+ S32 icon_left_pad = region_name->getRect().mLeft + region_name_width + ICON_PAD;
+ region_name->setToolTip(region_name->getText());
+ rating_icon->setRect(rect.setOriginAndSize(icon_left_pad, rect.mBottom, rect.getWidth(), rect.getHeight()));
- switch(sim_access)
- {
- case SIM_ACCESS_PG:
- rating_icon->setValue(getString("icon_PG"));
- break;
+ switch (sim_access)
+ {
+ case SIM_ACCESS_PG:
+ rating_icon->setValue(getString("icon_PG"));
+ break;
- case SIM_ACCESS_ADULT:
- rating_icon->setValue(getString("icon_R"));
- break;
+ case SIM_ACCESS_ADULT:
+ rating_icon->setValue(getString("icon_R"));
+ break;
- default:
- rating_icon->setValue(getString("icon_M"));
- }
+ default:
+ rating_icon->setValue(getString("icon_M"));
}
LLTextBox* region_type = getChild<LLTextBox>("region_type_text");
- if (region_type)
- {
- region_type->setText(region->getLocalizedSimProductName());
- region_type->setToolTip(region->getLocalizedSimProductName());
- }
+ region_type->setText(region->getLocalizedSimProductName());
+ region_type->setToolTip(region->getLocalizedSimProductName());
LLTextBox* resellable_clause = getChild<LLTextBox>("resellable_clause");
- if (resellable_clause)
- {
- if (region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL))
- {
- resellable_clause->setText(getString("can_not_resell"));
- }
- else
- {
- resellable_clause->setText(getString("can_resell"));
- }
- }
+ const char* can_resell = region->getRegionFlag(REGION_FLAGS_BLOCK_LAND_RESELL) ? "can_not_resell" : "can_resell";
+ resellable_clause->setText(getString(can_resell));
LLTextBox* changeable_clause = getChild<LLTextBox>("changeable_clause");
- if (changeable_clause)
- {
- if (region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES))
- {
- changeable_clause->setText(getString("can_change"));
- }
- else
- {
- changeable_clause->setText(getString("can_not_change"));
- }
- }
+ const char* can_change = region->getRegionFlag(REGION_FLAGS_ALLOW_PARCEL_CHANGES) ? "can_change" : "can_not_change";
+ changeable_clause->setText(getString(can_change));
LLCheckBoxCtrl* check = getChild<LLCheckBoxCtrl>("agree_covenant");
- if(check)
- {
- check->set(false);
- check->setEnabled(true);
- check->setCommitCallback(onChangeAgreeCovenant, this);
- }
+ check->set(false);
+ check->setEnabled(true);
+ check->setCommitCallback(onChangeAgreeCovenant, this);
LLTextBox* box = getChild<LLTextBox>("covenant_text");
- if(box)
- {
- box->setVisible(false);
- }
+ box->setVisible(false);
// send EstateCovenantInfo message
LLMessageSystem *msg = gMessageSystem;
@@ -584,10 +554,9 @@ void LLFloaterBuyLandUI::updateCovenantInfo()
// static
void LLFloaterBuyLandUI::onChangeAgreeCovenant(LLUICtrl* ctrl, void* user_data)
{
- LLFloaterBuyLandUI* self = (LLFloaterBuyLandUI*)user_data;
- if(self)
+ if (user_data)
{
- self->refreshUI();
+ ((LLFloaterBuyLandUI*)user_data)->refreshUI();
}
}
@@ -626,13 +595,13 @@ void LLFloaterBuyLandUI::updateFloaterEstateName(const std::string& name)
void LLFloaterBuyLandUI::updateFloaterLastModified(const std::string& text)
{
LLTextBox* editor = getChild<LLTextBox>("covenant_timestamp_text");
- if (editor) editor->setText(text);
+ editor->setText(text);
}
void LLFloaterBuyLandUI::updateFloaterEstateOwnerName(const std::string& name)
{
LLTextBox* box = getChild<LLTextBox>("estate_owner_text");
- if (box) box->setText(name);
+ box->setText(name);
}
void LLFloaterBuyLandUI::updateWebSiteInfo()
@@ -640,9 +609,10 @@ void LLFloaterBuyLandUI::updateWebSiteInfo()
S32 askBillableArea = mIsForGroup ? 0 : mParcelBillableArea;
S32 askCurrencyBuy = mCurrency.getAmount();
- if (mTransaction && mTransactionType == TransactionPreflight
- && mPreflightAskBillableArea == askBillableArea
- && mPreflightAskCurrencyBuy == askCurrencyBuy)
+ if (mTransaction &&
+ mTransactionType == TransactionPreflight &&
+ mPreflightAskBillableArea == askBillableArea &&
+ mPreflightAskCurrencyBuy == askCurrencyBuy)
{
return;
}
@@ -664,27 +634,21 @@ void LLFloaterBuyLandUI::updateWebSiteInfo()
mSiteCurrencyEstimatedCost = 0;
#endif
- LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
- keywordArgs.appendString("agentId", gAgent.getID().asString());
- keywordArgs.appendString(
- "secureSessionId",
- gAgent.getSecureSessionID().asString());
- keywordArgs.appendString("language", LLUI::getLanguage());
- keywordArgs.appendInt("billableArea", mPreflightAskBillableArea);
- keywordArgs.appendInt("currencyBuy", mPreflightAskCurrencyBuy);
-
- LLXMLRPCValue params = LLXMLRPCValue::createArray();
- params.append(keywordArgs);
+ LLSD params = LLSD::emptyMap();
+ params["agentId"] = gAgent.getID().asString();
+ params["secureSessionId"] = gAgent.getSecureSessionID().asString();
+ params["language"] = LLUI::getLanguage();
+ params["billableArea"] = mPreflightAskBillableArea;
+ params["currencyBuy"] = mPreflightAskCurrencyBuy;
startTransaction(TransactionPreflight, params);
}
void LLFloaterBuyLandUI::finishWebSiteInfo()
{
+ const LLSD& result = mTransaction->response();
- LLXMLRPCValue result = mTransaction->responseValue();
-
- mSiteValid = result["success"].asBool();
+ mSiteValid = result["success"].asBoolean();
if (!mSiteValid)
{
tellUserError(
@@ -694,31 +658,30 @@ void LLFloaterBuyLandUI::finishWebSiteInfo()
return;
}
- LLXMLRPCValue membership = result["membership"];
- mSiteMembershipUpgrade = membership["upgrade"].asBool();
+ const LLSD& membership = result["membership"];
+ mSiteMembershipUpgrade = membership["upgrade"].asBoolean();
mSiteMembershipAction = membership["action"].asString();
mSiteMembershipPlanIDs.clear();
mSiteMembershipPlanNames.clear();
- LLXMLRPCValue levels = membership["levels"];
- for (LLXMLRPCValue level = levels.rewind();
- level.isValid();
- level = levels.next())
+ const LLSD& levels = membership["levels"];
+ for (auto it = levels.beginArray(); it != levels.endArray(); ++it)
{
+ const LLSD& level = *it;
mSiteMembershipPlanIDs.push_back(level["id"].asString());
mSiteMembershipPlanNames.push_back(level["description"].asString());
}
mUserPlanChoice = 0;
- LLXMLRPCValue landUse = result["landUse"];
- mSiteLandUseUpgrade = landUse["upgrade"].asBool();
+ const LLSD& landUse = result["landUse"];
+ mSiteLandUseUpgrade = landUse["upgrade"].asBoolean();
mSiteLandUseAction = landUse["action"].asString();
- LLXMLRPCValue currency = result["currency"];
- if (currency["estimatedCost"].isValid())
+ const LLSD& currency = result["currency"];
+ if (currency.has("estimatedCost"))
{
- mCurrency.setUSDEstimate(currency["estimatedCost"].asInt());
+ mCurrency.setUSDEstimate(currency["estimatedCost"].asInteger());
}
- if (currency["estimatedLocalCost"].isValid())
+ if (currency.has("estimatedLocalCost"))
{
mCurrency.setLocalEstimate(currency["estimatedLocalCost"].asString());
}
@@ -760,35 +723,30 @@ void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password)
}
}
- LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct();
- keywordArgs.appendString("agentId", gAgent.getID().asString());
- keywordArgs.appendString(
- "secureSessionId",
- gAgent.getSecureSessionID().asString());
- keywordArgs.appendString("language", LLUI::getLanguage());
- keywordArgs.appendString("levelId", newLevel);
- keywordArgs.appendInt("billableArea",
- mIsForGroup ? 0 : mParcelBillableArea);
- keywordArgs.appendInt("currencyBuy", mCurrency.getAmount());
- keywordArgs.appendInt("estimatedCost", mCurrency.getUSDEstimate());
- keywordArgs.appendString("estimatedLocalCost", mCurrency.getLocalEstimate());
- keywordArgs.appendString("confirm", mSiteConfirm);
+ LLSD params = LLSD::emptyMap();
+ params["agentId"] = gAgent.getID().asString();
+ params["secureSessionId"] = gAgent.getSecureSessionID().asString();
+ params["language"] = LLUI::getLanguage();
+ params["levelId"] = newLevel;
+ params["billableArea"] = mIsForGroup ? 0 : mParcelBillableArea;
+ params["currencyBuy"] = mCurrency.getAmount();
+ params["estimatedCost"] = mCurrency.getUSDEstimate();
+ params["estimatedLocalCost"] = mCurrency.getLocalEstimate();
+ params["confirm"] = mSiteConfirm;
+
if (!password.empty())
{
- keywordArgs.appendString("password", password);
+ params["password"] = password;
}
- LLXMLRPCValue params = LLXMLRPCValue::createArray();
- params.append(keywordArgs);
-
startTransaction(TransactionBuy, params);
}
void LLFloaterBuyLandUI::finishWebSitePrep()
{
- LLXMLRPCValue result = mTransaction->responseValue();
+ const LLSD& result = mTransaction->response();
- bool success = result["success"].asBool();
+ bool success = result["success"].asBoolean();
if (!success)
{
tellUserError(
@@ -850,7 +808,7 @@ void LLFloaterBuyLandUI::updateGroupName(const LLUUID& id,
}
}
-void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCValue& params)
+void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLSD& params)
{
delete mTransaction;
mTransaction = NULL;
@@ -878,12 +836,7 @@ void LLFloaterBuyLandUI::startTransaction(TransactionType type, const LLXMLRPCVa
return;
}
- mTransaction = new LLXMLRPCTransaction(
- transaction_uri,
- method,
- params,
- false /* don't use gzip */
- );
+ mTransaction = new LLXMLRPCTransaction(transaction_uri, method, params);
}
bool LLFloaterBuyLandUI::checkTransaction()
diff --git a/indra/newview/llfloaterchangeitemthumbnail.cpp b/indra/newview/llfloaterchangeitemthumbnail.cpp
index 3e2e7cb7a3..fb31361fd9 100644
--- a/indra/newview/llfloaterchangeitemthumbnail.cpp
+++ b/indra/newview/llfloaterchangeitemthumbnail.cpp
@@ -951,8 +951,8 @@ void LLFloaterChangeItemThumbnail::onTexturePickerCommit()
|| texturep->getFullWidth() == 0)
{
if (texturep->isFullyLoaded()
- && (texturep->getCachedRawImageLevel() == 0 || texturep->getRawImageLevel() == 0)
- && (texturep->isCachedRawImageReady() || texturep->isRawImageValid()))
+ && (texturep->getRawImageLevel() == 0)
+ && (texturep->isRawImageValid()))
{
LLUUID task_id = mTaskId;
uuid_set_t inventory_ids = mItemList;
@@ -962,20 +962,10 @@ void LLFloaterChangeItemThumbnail::onTexturePickerCommit()
{
onUploadComplete(asset_id, task_id, inventory_ids, handle);
};
- if (texturep->isRawImageValid())
- {
- LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getRawImage(),
- *mItemList.begin(),
- mTaskId,
- callback);
- }
- else
- {
- LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getCachedRawImage(),
- *mItemList.begin(),
- mTaskId,
- callback);
- }
+ LLFloaterSimpleSnapshot::uploadThumbnail(texturep->getRawImage(),
+ *mItemList.begin(),
+ mTaskId,
+ callback);
}
else
{
diff --git a/indra/newview/llfloaterdestinations.cpp b/indra/newview/llfloaterdestinations.cpp
index 93cf02e835..fad9693e8f 100644
--- a/indra/newview/llfloaterdestinations.cpp
+++ b/indra/newview/llfloaterdestinations.cpp
@@ -25,11 +25,6 @@
* $/LicenseInfo$
*/
-/**
- * Floater that appears when buying an object, giving a preview
- * of its contents and their permissions.
- */
-
#include "llviewerprecompiledheaders.h"
#include "llfloaterdestinations.h"
diff --git a/indra/newview/llfloaterfonttest.cpp b/indra/newview/llfloaterfonttest.cpp
index 95d08cb9ce..d39b061d40 100644
--- a/indra/newview/llfloaterfonttest.cpp
+++ b/indra/newview/llfloaterfonttest.cpp
@@ -25,11 +25,6 @@
* $/LicenseInfo$
*/
-/**
- * Floater that appears when buying an object, giving a preview
- * of its contents and their permissions.
- */
-
#include "llviewerprecompiledheaders.h"
#include "llfloaterfonttest.h"
diff --git a/indra/newview/llfloatergltfasseteditor.cpp b/indra/newview/llfloatergltfasseteditor.cpp
new file mode 100644
index 0000000000..f21b8032d0
--- /dev/null
+++ b/indra/newview/llfloatergltfasseteditor.cpp
@@ -0,0 +1,527 @@
+/**
+ * @file llfloatergltfasseteditor.cpp
+ * @author Andrii Kleshchev
+ * @brief LLFloaterGltfAssetEditor class implementation
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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 "llfloatergltfasseteditor.h"
+
+#include "gltf/asset.h"
+#include "llcallbacklist.h"
+#include "llmenubutton.h"
+#include "llselectmgr.h"
+#include "llspinctrl.h"
+#include "llviewerobject.h"
+
+const LLColor4U DEFAULT_WHITE(255, 255, 255);
+
+/// LLFloaterGLTFAssetEditor
+
+LLFloaterGLTFAssetEditor::LLFloaterGLTFAssetEditor(const LLSD& key)
+ : LLFloater(key)
+ , mUIColor(LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE))
+{
+ setTitle("GLTF Asset Editor (WIP)");
+
+ mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", [this](LLUICtrl* ctrl, const LLSD& data) { onMenuDoToSelected(data); });
+ mEnableCallbackRegistrar.add("PanelObject.menuEnable", [this](LLUICtrl* ctrl, const LLSD& data) { return onMenuEnableItem(data); });
+}
+
+LLFloaterGLTFAssetEditor::~LLFloaterGLTFAssetEditor()
+{
+ gIdleCallbacks.deleteFunction(idle, this);
+
+ if (mScroller)
+ {
+ removeChild(mScroller);
+ delete mScroller;
+ mScroller = NULL;
+ }
+}
+
+bool LLFloaterGLTFAssetEditor::postBuild()
+{
+ // Position
+ mMenuClipboardPos = getChild<LLMenuButton>("clipboard_pos_btn");
+ mCtrlPosX = getChild<LLSpinCtrl>("Pos X", true);
+ mCtrlPosX->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
+ mCtrlPosY = getChild<LLSpinCtrl>("Pos Y", true);
+ mCtrlPosY->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
+ mCtrlPosZ = getChild<LLSpinCtrl>("Pos Z", true);
+ mCtrlPosZ->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
+
+ // Scale
+ mMenuClipboardScale = getChild<LLMenuButton>("clipboard_size_btn");
+ mCtrlScaleX = getChild<LLSpinCtrl>("Scale X", true);
+ mCtrlScaleX->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
+ mCtrlScaleY = getChild<LLSpinCtrl>("Scale Y", true);
+ mCtrlScaleY->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
+ mCtrlScaleZ = getChild<LLSpinCtrl>("Scale Z", true);
+ mCtrlScaleZ->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
+
+ // Rotation
+ mMenuClipboardRot = getChild<LLMenuButton>("clipboard_rot_btn");
+ mCtrlRotX = getChild<LLSpinCtrl>("Rot X", true);
+ mCtrlRotX->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
+ mCtrlRotY = getChild<LLSpinCtrl>("Rot Y", true);
+ mCtrlRotY->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
+ mCtrlRotZ = getChild<LLSpinCtrl>("Rot Z", true);
+ mCtrlPosZ->setCommitCallback([this](LLUICtrl* ctrl, const LLSD& param) { onCommitTransform(); });
+ setTransformsEnabled(false);
+ // todo: do multiple panels based on selected element.
+ mTransformsPanel = getChild<LLPanel>("transform_panel", true);
+ mTransformsPanel->setVisible(false);
+
+ mItemListPanel = getChild<LLPanel>("item_list_panel", true);
+ initFolderRoot();
+
+ return true;
+}
+
+void LLFloaterGLTFAssetEditor::initFolderRoot()
+{
+ if (mScroller || mFolderRoot)
+ {
+ LL_ERRS() << "Folder root already initialized" << LL_ENDL;
+ return;
+ }
+
+ LLRect scroller_view_rect = mItemListPanel->getRect();
+ scroller_view_rect.translate(-scroller_view_rect.mLeft, -scroller_view_rect.mBottom);
+ LLScrollContainer::Params scroller_params(LLUICtrlFactory::getDefaultParams<LLFolderViewScrollContainer>());
+ scroller_params.rect(scroller_view_rect);
+ scroller_params.name("folder_scroller");
+ mScroller = LLUICtrlFactory::create<LLFolderViewScrollContainer>(scroller_params);
+ mScroller->setFollowsAll();
+
+ // Insert that scroller into the panel widgets hierarchy
+ mItemListPanel->addChild(mScroller);
+
+ // Create the root model and view for all conversation sessions
+ LLGLTFFolderItem* base_item = new LLGLTFFolderItem(mGLTFViewModel);
+
+ LLFolderView::Params p(LLUICtrlFactory::getDefaultParams<LLFolderView>());
+ p.name = "Root";
+ p.title = "Root";
+ p.rect = LLRect(0, 0, getRect().getWidth(), 0);
+ p.parent_panel = mItemListPanel;
+ p.tool_tip = p.name;
+ p.listener = base_item;
+ p.view_model = &mGLTFViewModel;
+ p.root = NULL;
+ p.use_ellipses = true;
+ p.options_menu = "menu_gltf.xml"; // *TODO : create this or fix to be optional
+ mFolderRoot = LLUICtrlFactory::create<LLFolderView>(p);
+ mFolderRoot->setCallbackRegistrar(&mCommitCallbackRegistrar);
+ mFolderRoot->setEnableRegistrar(&mEnableCallbackRegistrar);
+ // Attach root to the scroller
+ mScroller->addChild(mFolderRoot);
+ mFolderRoot->setScrollContainer(mScroller);
+ mFolderRoot->setFollowsAll();
+ mFolderRoot->setOpen(true);
+ mFolderRoot->setSelectCallback([this](const std::deque<LLFolderViewItem*>& items, bool user_action) { onFolderSelectionChanged(items, user_action); });
+ mScroller->setVisible(true);
+
+ gIdleCallbacks.addFunction(idle, this);
+}
+
+void LLFloaterGLTFAssetEditor::onOpen(const LLSD& key)
+{
+ loadFromSelection();
+}
+
+void LLFloaterGLTFAssetEditor::idle(void* user_data)
+{
+ LLFloaterGLTFAssetEditor* floater = (LLFloaterGLTFAssetEditor*)user_data;
+
+ if (floater->mFolderRoot)
+ {
+ floater->mFolderRoot->update();
+ }
+}
+
+void LLFloaterGLTFAssetEditor::loadItem(S32 id, const std::string& name, LLGLTFFolderItem::EType type, LLFolderViewFolder* parent)
+{
+ LLGLTFFolderItem* listener = new LLGLTFFolderItem(id, name, type, mGLTFViewModel);
+
+ LLFolderViewItem::Params params;
+ params.name(name);
+ params.creation_date(0);
+ params.root(mFolderRoot);
+ params.listener(listener);
+ params.rect(LLRect());
+ params.tool_tip = params.name;
+ params.font_color = mUIColor;
+ params.font_highlight_color = mUIColor;
+ LLFolderViewItem* view = LLUICtrlFactory::create<LLFolderViewItem>(params);
+
+ view->addToFolder(parent);
+ view->setVisible(true);
+}
+
+void LLFloaterGLTFAssetEditor::loadFromNode(S32 node_id, LLFolderViewFolder* parent)
+{
+ if (mAsset->mNodes.size() <= node_id)
+ {
+ return;
+ }
+
+ LL::GLTF::Node& node = mAsset->mNodes[node_id];
+
+ std::string name = node.mName;
+ if (node.mName.empty())
+ {
+ name = getString("node_tittle");
+ }
+ else
+ {
+ name = node.mName;
+ }
+
+ LLGLTFFolderItem* listener = new LLGLTFFolderItem(node_id, name, LLGLTFFolderItem::TYPE_NODE, mGLTFViewModel);
+
+ LLFolderViewFolder::Params p;
+ p.root = mFolderRoot;
+ p.listener = listener;
+ p.name = name;
+ p.tool_tip = name;
+ p.font_color = mUIColor;
+ p.font_highlight_color = mUIColor;
+ LLFolderViewFolder* view = LLUICtrlFactory::create<LLFolderViewFolder>(p);
+
+ view->addToFolder(parent);
+ view->setVisible(true);
+ view->setOpen(true);
+
+ for (S32& node_id : node.mChildren)
+ {
+ loadFromNode(node_id, view);
+ }
+
+ if (node.mMesh != LL::GLTF::INVALID_INDEX && mAsset->mMeshes.size() > node.mMesh)
+ {
+ std::string name = mAsset->mMeshes[node.mMesh].mName;
+ if (name.empty())
+ {
+ name = getString("mesh_tittle");
+ }
+ loadItem(node.mMesh, name, LLGLTFFolderItem::TYPE_MESH, view);
+ }
+
+ if (node.mSkin != LL::GLTF::INVALID_INDEX && mAsset->mSkins.size() > node.mSkin)
+ {
+ std::string name = mAsset->mSkins[node.mSkin].mName;
+ if (name.empty())
+ {
+ name = getString("skin_tittle");
+ }
+ loadItem(node.mSkin, name, LLGLTFFolderItem::TYPE_SKIN, view);
+ }
+
+ view->setChildrenInited(true);
+}
+
+void LLFloaterGLTFAssetEditor::loadFromSelection()
+{
+ if (!mFolderRoot || LLSelectMgr::getInstance()->getSelection()->getObjectCount() != 1)
+ {
+ return;
+ }
+
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(NULL);
+ LLViewerObject* objectp = node->getObject();
+ if (!objectp)
+ {
+ return;
+ }
+
+ mAsset = objectp->mGLTFAsset;
+ if (!mAsset)
+ {
+ return;
+ }
+
+ if (node->mName.empty())
+ {
+ setTitle(getString("floater_title"));
+ }
+ else
+ {
+ setTitle(node->mName);
+ }
+
+ LLUIColor item_color = LLUIColorTable::instance().getColor("MenuItemEnabledColor", DEFAULT_WHITE);
+ for (S32 i = 0; i < mAsset->mScenes.size(); i++)
+ {
+ LL::GLTF::Scene& scene = mAsset->mScenes[i];
+ std::string name = scene.mName;
+ if (scene.mName.empty())
+ {
+ name = getString("scene_tittle");
+ }
+ else
+ {
+ name = scene.mName;
+ }
+
+ LLGLTFFolderItem* listener = new LLGLTFFolderItem(i, name, LLGLTFFolderItem::TYPE_SCENE, mGLTFViewModel);
+
+
+ LLFolderViewFolder::Params p;
+ p.name = name;
+ p.root = mFolderRoot;
+ p.listener = listener;
+ p.tool_tip = name;
+ p.font_color = mUIColor;
+ p.font_highlight_color = mUIColor;
+ LLFolderViewFolder* view = LLUICtrlFactory::create<LLFolderViewFolder>(p);
+
+ view->addToFolder(mFolderRoot);
+ view->setVisible(true);
+ view->setOpen(true);
+
+ for (S32& node_id : scene.mNodes)
+ {
+ loadFromNode(node_id, view);
+ }
+ view->setChildrenInited(true);
+ }
+
+ mGLTFViewModel.requestSortAll();
+ mFolderRoot->setChildrenInited(true);
+ mFolderRoot->arrangeAll();
+ mFolderRoot->update();
+}
+
+void LLFloaterGLTFAssetEditor::onFolderSelectionChanged(const std::deque<LLFolderViewItem*>& items, bool user_action)
+{
+ if (items.empty())
+ {
+ setTransformsEnabled(false);
+ return;
+ }
+
+ LLFolderViewItem* item = items.front();
+ LLGLTFFolderItem* vmi = static_cast<LLGLTFFolderItem*>(item->getViewModelItem());
+
+ switch (vmi->getType())
+ {
+ case LLGLTFFolderItem::TYPE_NODE:
+ {
+ setTransformsEnabled(true);
+ loadNodeTransforms(vmi->getItemId());
+ break;
+ }
+ default:
+ {
+ setTransformsEnabled(false);
+ break;
+ }
+ }
+}
+
+void LLFloaterGLTFAssetEditor::setTransformsEnabled(bool val)
+{
+ mMenuClipboardPos->setEnabled(val);
+ mCtrlPosX->setEnabled(val);
+ mCtrlPosY->setEnabled(val);
+ mCtrlPosZ->setEnabled(val);
+ mMenuClipboardScale->setEnabled(val);
+ mCtrlScaleX->setEnabled(val);
+ mCtrlScaleY->setEnabled(val);
+ mCtrlScaleZ->setEnabled(val);
+ mMenuClipboardRot->setEnabled(val);
+ mCtrlRotX->setEnabled(val);
+ mCtrlRotY->setEnabled(val);
+ mCtrlRotZ->setEnabled(val);
+}
+
+void LLFloaterGLTFAssetEditor::loadNodeTransforms(S32 node_id)
+{
+ if (node_id < 0 || node_id >= mAsset->mNodes.size())
+ {
+ LL_ERRS() << "Node id out of range: " << node_id << LL_ENDL;
+ return;
+ }
+
+ LL::GLTF::Node& node = mAsset->mNodes[node_id];
+
+ mCtrlPosX->set(node.mTranslation[0]);
+ mCtrlPosY->set(node.mTranslation[1]);
+ mCtrlPosZ->set(node.mTranslation[2]);
+
+ mCtrlScaleX->set(node.mScale[0]);
+ mCtrlScaleY->set(node.mScale[1]);
+ mCtrlScaleZ->set(node.mScale[2]);
+
+ LLQuaternion object_rot = LLQuaternion(node.mRotation[0], node.mRotation[1], node.mRotation[2], node.mRotation[3]);
+ object_rot.getEulerAngles(&(mLastEulerDegrees.mV[VX]), &(mLastEulerDegrees.mV[VY]), &(mLastEulerDegrees.mV[VZ]));
+ mLastEulerDegrees *= RAD_TO_DEG;
+ mLastEulerDegrees.mV[VX] = fmod(ll_round(mLastEulerDegrees.mV[VX], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
+ mLastEulerDegrees.mV[VY] = fmod(ll_round(mLastEulerDegrees.mV[VY], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
+ mLastEulerDegrees.mV[VZ] = fmod(ll_round(mLastEulerDegrees.mV[VZ], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
+
+ mCtrlRotX->set(mLastEulerDegrees.mV[VX]);
+ mCtrlRotY->set(mLastEulerDegrees.mV[VY]);
+ mCtrlRotZ->set(mLastEulerDegrees.mV[VZ]);
+}
+
+void LLFloaterGLTFAssetEditor::onCommitTransform()
+{
+ if (!mFolderRoot)
+ {
+ LL_ERRS() << "Folder root not initialized" << LL_ENDL;
+ return;
+ }
+
+ LLFolderViewItem* item = mFolderRoot->getCurSelectedItem();
+ if (!item)
+ {
+ LL_ERRS() << "Nothing selected" << LL_ENDL;
+ return;
+ }
+
+ LLGLTFFolderItem* vmi = static_cast<LLGLTFFolderItem*>(item->getViewModelItem());
+
+ if (!vmi || vmi->getType() != LLGLTFFolderItem::TYPE_NODE)
+ {
+ LL_ERRS() << "Only nodes implemented" << LL_ENDL;
+ return;
+ }
+ S32 node_id = vmi->getItemId();
+ LL::GLTF::Node& node = mAsset->mNodes[node_id];
+
+ LL::GLTF::vec3 tr(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
+ node.setTranslation(tr);
+
+ LL::GLTF::vec3 scale(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get());
+ node.setScale(scale);
+
+ LLVector3 new_rot(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get());
+ new_rot.mV[VX] = ll_round(new_rot.mV[VX], OBJECT_ROTATION_PRECISION);
+ new_rot.mV[VY] = ll_round(new_rot.mV[VY], OBJECT_ROTATION_PRECISION);
+ new_rot.mV[VZ] = ll_round(new_rot.mV[VZ], OBJECT_ROTATION_PRECISION);
+
+ // Note: must compare before conversion to radians, some value can go 'around' 360
+ LLVector3 delta = new_rot - mLastEulerDegrees;
+
+ if (delta.magVec() >= 0.0005f)
+ {
+ mLastEulerDegrees = new_rot;
+ new_rot *= DEG_TO_RAD;
+
+ LLQuaternion rotation;
+ rotation.setQuat(new_rot.mV[VX], new_rot.mV[VY], new_rot.mV[VZ]);
+ LL::GLTF::quat q;
+ q[0] = rotation.mQ[VX];
+ q[1] = rotation.mQ[VY];
+ q[2] = rotation.mQ[VZ];
+ q[3] = rotation.mQ[VW];
+
+ node.setRotation(q);
+ }
+
+ mAsset->updateTransforms();
+}
+
+void LLFloaterGLTFAssetEditor::onMenuDoToSelected(const LLSD& userdata)
+{
+ std::string command = userdata.asString();
+
+ if (command == "psr_paste")
+ {
+ // todo: implement
+ // onPastePos();
+ // onPasteSize();
+ // onPasteRot();
+ }
+ else if (command == "pos_paste")
+ {
+ // todo: implement
+ }
+ else if (command == "size_paste")
+ {
+ // todo: implement
+ }
+ else if (command == "rot_paste")
+ {
+ // todo: implement
+ }
+ else if (command == "psr_copy")
+ {
+ // onCopyPos();
+ // onCopySize();
+ // onCopyRot();
+ }
+ else if (command == "pos_copy")
+ {
+ // todo: implement
+ }
+ else if (command == "size_copy")
+ {
+ // todo: implement
+ }
+ else if (command == "rot_copy")
+ {
+ // todo: implement
+ }
+}
+
+bool LLFloaterGLTFAssetEditor::onMenuEnableItem(const LLSD& userdata)
+{
+ if (!mFolderRoot)
+ {
+ return false;
+ }
+
+ LLFolderViewItem* item = mFolderRoot->getCurSelectedItem();
+ if (!item)
+ {
+ return false;
+ }
+
+ LLGLTFFolderItem* vmi = static_cast<LLGLTFFolderItem*>(item->getViewModelItem());
+
+ if (!vmi || vmi->getType() != LLGLTFFolderItem::TYPE_NODE)
+ {
+ return false;
+ }
+
+ std::string command = userdata.asString();
+ if (command == "pos_paste" || command == "size_paste" || command == "rot_paste")
+ {
+ // todo: implement
+ return true;
+ }
+ if (command == "psr_copy")
+ {
+ // todo: implement
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/indra/newview/llfloatergltfasseteditor.h b/indra/newview/llfloatergltfasseteditor.h
new file mode 100644
index 0000000000..e35ed30ed0
--- /dev/null
+++ b/indra/newview/llfloatergltfasseteditor.h
@@ -0,0 +1,101 @@
+/**
+ * @file llfloatergltfasseteditor.h
+ * @author Andrii Kleshchev
+ * @brief LLFloaterGltfAssetEditor header file
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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_LLFLOATERGLTFASSETEDITOR_H
+#define LL_LLFLOATERGLTFASSETEDITOR_H
+
+#include "llfloater.h"
+
+#include "llgltffoldermodel.h"
+
+namespace LL
+{
+ namespace GLTF
+ {
+ class Asset;
+ }
+}
+
+class LLSpinCtrl;
+class LLMenuButton;
+
+class LLFloaterGLTFAssetEditor : public LLFloater
+{
+public:
+ LLFloaterGLTFAssetEditor(const LLSD& key);
+ ~LLFloaterGLTFAssetEditor();
+
+ bool postBuild() override;
+ void onOpen(const LLSD& key) override;
+ void initFolderRoot();
+
+ LLGLTFViewModel& getRootViewModel() { return mGLTFViewModel; }
+
+ static void idle(void* user_data);
+ void loadItem(S32 id, const std::string& name, LLGLTFFolderItem::EType type, LLFolderViewFolder* parent);
+ void loadFromNode(S32 node, LLFolderViewFolder* parent);
+ void loadFromSelection();
+
+protected:
+ void onFolderSelectionChanged(const std::deque<LLFolderViewItem*>& items, bool user_action);
+ void onCommitTransform();
+ void onMenuDoToSelected(const LLSD& userdata);
+ bool onMenuEnableItem(const LLSD& userdata);
+
+ void setTransformsEnabled(bool val);
+ void loadNodeTransforms(S32 id);
+
+private:
+
+ std::shared_ptr<LL::GLTF::Asset> mAsset;
+
+ // Folder view related
+ LLUIColor mUIColor;
+ LLGLTFViewModel mGLTFViewModel;
+ LLPanel* mItemListPanel = nullptr;
+ LLFolderView* mFolderRoot = nullptr;
+ LLScrollContainer* mScroller = nullptr;
+
+ // Transforms panel
+ LLVector3 mLastEulerDegrees;
+
+ LLPanel* mTransformsPanel = nullptr;
+ LLMenuButton* mMenuClipboardPos = nullptr;
+ LLSpinCtrl* mCtrlPosX = nullptr;
+ LLSpinCtrl* mCtrlPosY = nullptr;
+ LLSpinCtrl* mCtrlPosZ = nullptr;
+ LLMenuButton* mMenuClipboardScale = nullptr;
+ LLSpinCtrl* mCtrlScaleX = nullptr;
+ LLSpinCtrl* mCtrlScaleY = nullptr;
+ LLSpinCtrl* mCtrlScaleZ = nullptr;
+ LLMenuButton* mMenuClipboardRot = nullptr;
+ LLSpinCtrl* mCtrlRotX = nullptr;
+ LLSpinCtrl* mCtrlRotY = nullptr;
+ LLSpinCtrl* mCtrlRotZ = nullptr;
+};
+
+#endif
diff --git a/indra/newview/llgltffolderitem.cpp b/indra/newview/llgltffolderitem.cpp
new file mode 100644
index 0000000000..77a19c060d
--- /dev/null
+++ b/indra/newview/llgltffolderitem.cpp
@@ -0,0 +1,164 @@
+/**
+ * @file llgltffolderitem.cpp
+ * @author Andrey Kleshchev
+ * @brief LLGLTFFolderItem class implementation
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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 "llgltffolderitem.h"
+
+#include "llinventoryicon.h"
+
+/// LLGLTFItem
+
+LLGLTFFolderItem::LLGLTFFolderItem(S32 id, const std::string &display_name, EType type, LLFolderViewModelInterface& root_view_model)
+ : LLFolderViewModelItemCommon(root_view_model)
+ , mName(display_name)
+ , mItemType(type)
+ , mItemId(id)
+{
+ init();
+}
+
+LLGLTFFolderItem::LLGLTFFolderItem(LLFolderViewModelInterface& root_view_model)
+ : LLFolderViewModelItemCommon(root_view_model)
+{
+ init();
+}
+
+LLGLTFFolderItem::~LLGLTFFolderItem()
+{
+
+}
+
+void LLGLTFFolderItem::init()
+{
+ // using inventory icons as a placeholder.
+ // Todo: GLTF needs to have own icons
+ switch (mItemType)
+ {
+ case TYPE_SCENE:
+ pIcon = LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_OBJECT_MULTI);
+ break;
+ case TYPE_NODE:
+ pIcon = LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_OBJECT);
+ break;
+ case TYPE_MESH:
+ pIcon = LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_MESH);
+ break;
+ case TYPE_SKIN:
+ pIcon = LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_BODYPART_SKIN);
+ break;
+ default:
+ pIcon = LLInventoryIcon::getIcon(LLInventoryType::ICONNAME_OBJECT);
+ break;
+ }
+}
+
+
+bool LLGLTFFolderItem::filterChildItem(LLFolderViewModelItem* item, LLFolderViewFilter& filter)
+{
+ S32 filter_generation = filter.getCurrentGeneration();
+
+ bool continue_filtering = true;
+ if (item)
+ {
+ if (item->getLastFilterGeneration() < filter_generation)
+ {
+ // Recursive application of the filter for child items (CHUI-849)
+ continue_filtering = item->filter(filter);
+ }
+
+ // Update latest generation to pass filter in parent and propagate up to root
+ if (item->passedFilter())
+ {
+ LLGLTFFolderItem* view_model = this;
+
+ while (view_model && view_model->mMostFilteredDescendantGeneration < filter_generation)
+ {
+ view_model->mMostFilteredDescendantGeneration = filter_generation;
+ view_model = static_cast<LLGLTFFolderItem*>(view_model->mParent);
+ }
+ }
+ }
+ return continue_filtering;
+}
+
+bool LLGLTFFolderItem::filter(LLFolderViewFilter& filter)
+{
+ const S32 filter_generation = filter.getCurrentGeneration();
+ const S32 must_pass_generation = filter.getFirstRequiredGeneration();
+
+ if (getLastFilterGeneration() >= must_pass_generation
+ && getLastFolderFilterGeneration() >= must_pass_generation
+ && !passedFilter(must_pass_generation))
+ {
+ // failed to pass an earlier filter that was a subset of the current one
+ // go ahead and flag this item as not pass
+ setPassedFilter(false, filter_generation);
+ setPassedFolderFilter(false, filter_generation);
+ return true;
+ }
+
+ bool is_folder = true;
+ const bool passed_filter_folder = is_folder ? filter.checkFolder(this) : true;
+ setPassedFolderFilter(passed_filter_folder, filter_generation);
+
+ bool continue_filtering = true;
+
+ if (!mChildren.empty()
+ && (getLastFilterGeneration() < must_pass_generation // haven't checked descendants against minimum required generation to pass
+ || descendantsPassedFilter(must_pass_generation))) // or at least one descendant has passed the minimum requirement
+ {
+ // now query children
+ for (child_list_t::iterator iter = mChildren.begin(), end_iter = mChildren.end(); iter != end_iter; ++iter)
+ {
+ continue_filtering = filterChildItem((*iter), filter);
+ if (!continue_filtering)
+ {
+ break;
+ }
+ }
+ }
+
+ // If we didn't use all the filter time that means we filtered all of our descendants so we can filter ourselves now
+ if (continue_filtering)
+ {
+ // This is where filter check on the item done (CHUI-849)
+ const bool passed_filter = filter.check(this);
+ if (passed_filter && mChildren.empty() && is_folder) // Update the latest filter generation for empty folders
+ {
+ LLGLTFFolderItem* view_model = this;
+ while (view_model && view_model->mMostFilteredDescendantGeneration < filter_generation)
+ {
+ view_model->mMostFilteredDescendantGeneration = filter_generation;
+ view_model = static_cast<LLGLTFFolderItem*>(view_model->mParent);
+ }
+ }
+ setPassedFilter(passed_filter, filter_generation, filter.getStringMatchOffset(this), filter.getFilterStringSize());
+ continue_filtering = !filter.isTimedOut();
+ }
+ return continue_filtering;
+}
diff --git a/indra/newview/llgltffolderitem.h b/indra/newview/llgltffolderitem.h
new file mode 100644
index 0000000000..89d90c81cc
--- /dev/null
+++ b/indra/newview/llgltffolderitem.h
@@ -0,0 +1,128 @@
+/**
+ * @file llgltffolderitem.h
+ * @author Andrey Kleshchev
+ * @brief LLGLTFFolderItem header file
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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_LLGLTFFOLDERITEM_H
+#define LL_LLGLTFFOLDERITEM_H
+
+#include "llfloater.h"
+
+#include "llfolderviewmodel.h"
+
+class LLGLTFFolderItem : public LLFolderViewModelItemCommon
+{
+public:
+ enum EType
+ {
+ TYPE_ROOT,
+ TYPE_SCENE,
+ TYPE_NODE,
+ TYPE_MESH,
+ TYPE_SKIN,
+ };
+
+ LLGLTFFolderItem(S32 id, const std::string &display_name, EType type, LLFolderViewModelInterface& root_view_model);
+ LLGLTFFolderItem(LLFolderViewModelInterface& root_view_model);
+ virtual ~LLGLTFFolderItem();
+
+ void init();
+
+ const std::string& getName() const override { return mName; }
+ const std::string& getDisplayName() const override { return mName; }
+ const std::string& getSearchableName() const override { return mName; }
+
+ std::string getSearchableDescription() const override { return std::string(); }
+ std::string getSearchableCreatorName()const override { return std::string(); }
+ std::string getSearchableUUIDString() const override { return std::string(); }
+
+ LLPointer<LLUIImage> getIcon() const override { return pIcon; }
+ LLPointer<LLUIImage> getIconOpen() const override { return getIcon(); }
+ LLPointer<LLUIImage> getIconOverlay() const override { return NULL; }
+
+ LLFontGL::StyleFlags getLabelStyle() const override { return LLFontGL::NORMAL; }
+ std::string getLabelSuffix() const override { return std::string(); }
+
+ void openItem(void) override {}
+ void closeItem(void) override {}
+ void selectItem(void) override {}
+
+ void navigateToFolder(bool new_window = false, bool change_mode = false) override {}
+
+ bool isItemWearable() const override { return false; }
+
+ bool isItemRenameable() const override { return false; }
+ bool renameItem(const std::string& new_name) override { return false; }
+
+ bool isItemMovable(void) const override { return false; } // Can be moved to another folder
+ void move(LLFolderViewModelItem* parent_listener) override {}
+
+ bool isItemRemovable(bool check_worn = true) const override { return false; }
+ bool removeItem() override { return false; }
+ void removeBatch(std::vector<LLFolderViewModelItem*>& batch) override {}
+
+ bool isItemCopyable(bool can_copy_as_link = true) const override { return false; }
+ bool copyToClipboard() const override { return false; }
+ bool cutToClipboard() override { return false; }
+ bool isCutToClipboard() override { return false; }
+
+ bool isClipboardPasteable() const override { return false; }
+ void pasteFromClipboard() override {}
+ void pasteLinkFromClipboard() override {}
+
+ void buildContextMenu(LLMenuGL& menu, U32 flags) override {};
+
+ bool potentiallyVisible() override { return true; }; // is the item definitely visible or we haven't made up our minds yet?
+
+ bool hasChildren() const override { return mChildren.size() > 0; }
+
+ bool dragOrDrop(
+ MASK mask,
+ bool drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data,
+ std::string& tooltip_msg) override
+ {
+ return false;
+ }
+
+ bool filterChildItem(LLFolderViewModelItem* item, LLFolderViewFilter& filter);
+ bool filter(LLFolderViewFilter& filter) override;
+
+ EType getType() const { return mItemType; }
+ S32 getItemId() const { return mItemId; }
+
+private:
+ LLUIImagePtr pIcon;
+ std::string mName;
+ EType mItemType = TYPE_ROOT;
+
+ // mItemId can be an id in a mesh vector, node vector or any other vector.
+ // mItemId is not nessesarily unique, ex: some nodes can reuse the same
+ // mesh or skin, so mesh-items can have the same id.
+ S32 mItemId = -1;
+};
+
+#endif
diff --git a/indra/newview/llgltffoldermodel.cpp b/indra/newview/llgltffoldermodel.cpp
new file mode 100644
index 0000000000..de2510dc4a
--- /dev/null
+++ b/indra/newview/llgltffoldermodel.cpp
@@ -0,0 +1,73 @@
+/**
+ * @file llgltffoldermodel.cpp
+ * @author Andrey Kleshchev
+ * @brief gltf model's folder structure related classes
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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 "llgltffoldermodel.h"
+
+#include "llfolderviewitem.h"
+
+bool LLGLTFSort::operator()(const LLGLTFFolderItem* const& a, const LLGLTFFolderItem* const& b) const
+{
+ // Comparison operator: returns "true" is a comes before b, "false" otherwise
+ S32 compare = LLStringUtil::compareDict(a->getName(), b->getName());
+ return (compare < 0);
+}
+
+/// LLGLTFViewModel
+
+LLGLTFViewModel::LLGLTFViewModel()
+ : base_t(new LLGLTFSort(), new LLGLTFFilter())
+{}
+
+void LLGLTFViewModel::sort(LLFolderViewFolder* folder)
+{
+ base_t::sort(folder);
+}
+
+ /// LLGLTFNode
+// LLUICtrlFactory::create<LLGLTFNode>(params);
+class LLGLTFNode : public LLFolderViewItem
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLFolderViewItem::Params>
+ {
+ Params();
+ };
+ ~LLGLTFNode();
+protected:
+ LLGLTFNode(const Params& p);
+};
+
+LLGLTFNode::LLGLTFNode(const LLGLTFNode::Params& p)
+ : LLFolderViewItem(p)
+{
+}
+
+LLGLTFNode::~LLGLTFNode()
+{
+}
diff --git a/indra/newview/llgltffoldermodel.h b/indra/newview/llgltffoldermodel.h
new file mode 100644
index 0000000000..69b284aa31
--- /dev/null
+++ b/indra/newview/llgltffoldermodel.h
@@ -0,0 +1,91 @@
+/**
+ * @file llfloatergltfasseteditor.h
+ * @author Andrey Kleshchev
+ * @brief gltf model's folder structure related classes
+ *
+ * $LicenseInfo:firstyear=2024&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2024, 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_LLGLTFFOLDERMODEL_H
+#define LL_LLGLTFFOLDERMODEL_H
+
+#include "llfolderviewmodel.h"
+#include "llgltffolderitem.h"
+
+class LLGLTFSort
+{
+public:
+ LLGLTFSort() { }
+ bool operator()(const LLGLTFFolderItem* const& a, const LLGLTFFolderItem* const& b) const;
+private:
+};
+
+class LLGLTFFilter : public LLFolderViewFilter
+{
+public:
+ LLGLTFFilter() { mEmpty = ""; }
+ ~LLGLTFFilter() {}
+
+ bool check(const LLFolderViewModelItem* item) { return true; }
+ bool checkFolder(const LLFolderViewModelItem* folder) const { return true; }
+ void setEmptyLookupMessage(const std::string& message) { }
+ std::string getEmptyLookupMessage(bool is_empty_folder = false) const { return mEmpty; }
+ bool showAllResults() const { return true; }
+ std::string::size_type getStringMatchOffset(LLFolderViewModelItem* item) const { return std::string::npos; }
+ std::string::size_type getFilterStringSize() const { return 0; }
+
+ bool isActive() const { return false; }
+ bool isModified() const { return false; }
+ void clearModified() { }
+ const std::string& getName() const { return mEmpty; }
+ const std::string& getFilterText() { return mEmpty; }
+ void setModified(EFilterModified behavior = FILTER_RESTART) { }
+
+ void resetTime(S32 timeout) { }
+ bool isTimedOut() { return false; }
+
+ bool isDefault() const { return true; }
+ bool isNotDefault() const { return false; }
+ void markDefault() { }
+ void resetDefault() { }
+
+ S32 getCurrentGeneration() const { return 0; }
+ S32 getFirstSuccessGeneration() const { return 0; }
+ S32 getFirstRequiredGeneration() const { return 0; }
+private:
+ std::string mEmpty;
+};
+
+class LLGLTFViewModel
+ : public LLFolderViewModel<LLGLTFSort, LLGLTFFolderItem, LLGLTFFolderItem, LLGLTFFilter>
+{
+public:
+ typedef LLFolderViewModel< LLGLTFSort, LLGLTFFolderItem, LLGLTFFolderItem, LLGLTFFilter> base_t;
+ LLGLTFViewModel();
+
+ void sort(LLFolderViewFolder* folder);
+ bool startDrag(std::vector<LLFolderViewModelItem*>& items) { return false; }
+
+private:
+};
+
+#endif
diff --git a/indra/newview/llheroprobemanager.cpp b/indra/newview/llheroprobemanager.cpp
index 66ccdd2b32..cbe1105024 100644
--- a/indra/newview/llheroprobemanager.cpp
+++ b/indra/newview/llheroprobemanager.cpp
@@ -121,6 +121,7 @@ void LLHeroProbeManager::update()
// Find our nearest hero candidate.
float last_distance = 99999.f;
float camera_center_distance = 99999.f;
+ mNearestHero = nullptr;
for (auto vo : mHeroVOList)
{
if (vo && !vo->isDead() && vo->mDrawable.notNull() && vo->isReflectionProbe() && vo->getReflectionProbeIsBox())
@@ -194,11 +195,17 @@ void LLHeroProbeManager::update()
else
{
mNearestHero = nullptr;
+ mDefaultProbe->mViewerObject = nullptr;
}
mHeroProbeStrength = 1;
}
+ else
+ {
+ mNearestHero = nullptr;
+ mDefaultProbe->mViewerObject = nullptr;
}
+}
void LLHeroProbeManager::renderProbes()
{
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 72edbaebe1..05b1fec8e5 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -3412,11 +3412,11 @@ LLUUID LLIMMgr::addSession(
((IM_NOTHING_SPECIAL == dialog) || (IM_SESSION_P2P_INVITE == dialog) || (IM_SESSION_CONFERENCE_START == dialog)) &&
ids.size())
{
- LLIMModel::LLIMSession* ad_hoc_found = LLIMModel::getInstance()->findAdHocIMSession(ids);
- if (ad_hoc_found)
+ session = LLIMModel::getInstance()->findAdHocIMSession(ids);
+ if (session)
{
new_session = false;
- session_id = ad_hoc_found->mSessionID;
+ session_id = session->mSessionID;
}
}
@@ -3852,7 +3852,7 @@ bool LLIMMgr::startCall(const LLUUID& session_id, LLVoiceChannel::EDirection dir
{
LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
if (!voice_channel) return false;
- if (!voice_channel_info.isUndefined())
+ if (voice_channel_info.isDefined() && voice_channel_info.isMap() && voice_channel_info.size() > 0)
{
voice_channel->setChannelInfo(voice_channel_info);
}
diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp
index 6ab5e05b7d..0e2b3cb409 100644
--- a/indra/newview/lllocalbitmaps.cpp
+++ b/indra/newview/lllocalbitmaps.cpp
@@ -215,7 +215,6 @@ bool LLLocalBitmap::updateSelf(EUpdateType optional_firstupdate)
("file://"+mFilename, FTT_LOCAL_FILE, mWorldID, LL_LOCAL_USE_MIPMAPS);
texture->createGLTexture(LL_LOCAL_DISCARD_LEVEL, raw_image);
- texture->setCachedRawImage(LL_LOCAL_DISCARD_LEVEL, raw_image);
texture->ref();
gTextureList.addImage(texture, TEX_LIST_STANDARD);
diff --git a/indra/newview/lllogininstance.cpp b/indra/newview/lllogininstance.cpp
index 282a273be6..d015c0ed95 100644
--- a/indra/newview/lllogininstance.cpp
+++ b/indra/newview/lllogininstance.cpp
@@ -33,9 +33,6 @@
#include "stringize.h"
#include "llsdserialize.h"
-// llmessage (!)
-#include "llfiltersd2xmlrpc.h" // for xml_escape_string()
-
// login
#include "lllogin.h"
@@ -612,7 +609,7 @@ std::string construct_start_string()
<< position[VX] << "&"
<< position[VY] << "&"
<< position[VZ]);
- start = xml_escape_string(unescaped_start);
+ start = LLStringFn::xml_encode(unescaped_start, true);
break;
}
case LLSLURL::HOME_LOCATION:
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index 1410232a0f..fd968d9027 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -296,8 +296,6 @@ void LLNetMap::draw()
gGL.color4f(1.f, 0.5f, 0.5f, 1.f);
}
-
-
// Draw using texture.
gGL.getTexUnit(0)->bind(regionp->getLand().getSTexture());
gGL.begin(LLRender::QUADS);
@@ -311,24 +309,6 @@ void LLNetMap::draw()
gGL.vertex2f(right, top);
gGL.end();
- // Draw water
- gGL.flush();
- {
- if (regionp->getLand().getWaterTexture())
- {
- gGL.getTexUnit(0)->bind(regionp->getLand().getWaterTexture());
- gGL.begin(LLRender::QUADS);
- gGL.texCoord2f(0.f, 1.f);
- gGL.vertex2f(left, top);
- gGL.texCoord2f(0.f, 0.f);
- gGL.vertex2f(left, bottom);
- gGL.texCoord2f(1.f, 0.f);
- gGL.vertex2f(right, bottom);
- gGL.texCoord2f(1.f, 1.f);
- gGL.vertex2f(right, top);
- gGL.end();
- }
- }
gGL.flush();
}
diff --git a/indra/newview/llslurl.cpp b/indra/newview/llslurl.cpp
index 432ec3899a..d80cf2e80e 100644
--- a/indra/newview/llslurl.cpp
+++ b/indra/newview/llslurl.cpp
@@ -32,13 +32,15 @@
#include "llpanellogin.h"
#include "llviewercontrol.h"
#include "llviewernetwork.h"
-#include "llfiltersd2xmlrpc.h"
+
#include "curl/curl.h"
+
const char* LLSLURL::SLURL_HTTP_SCHEME = "http";
const char* LLSLURL::SLURL_HTTPS_SCHEME = "https";
const char* LLSLURL::SLURL_SECONDLIFE_SCHEME = "secondlife";
const char* LLSLURL::SLURL_SECONDLIFE_PATH = "secondlife";
const char* LLSLURL::SLURL_COM = "slurl.com";
+
// For DnD - even though www.slurl.com redirects to slurl.com in a browser, you can copy and drag
// text with www.slurl.com or a link explicitly pointing at www.slurl.com so testing for this
// version is required also.
@@ -437,7 +439,7 @@ std::string LLSLURL::getLoginString() const
LL_WARNS("AppInit") << "Unexpected SLURL type (" << (int)mType << ")for login string" << LL_ENDL;
break;
}
- return xml_escape_string(unescaped_start.str());
+ return LLStringFn::xml_encode(unescaped_start.str(), true);
}
bool LLSLURL::operator ==(const LLSLURL& rhs)
diff --git a/indra/newview/llsurface.cpp b/indra/newview/llsurface.cpp
index e6bced5c92..1826885069 100644
--- a/indra/newview/llsurface.cpp
+++ b/indra/newview/llsurface.cpp
@@ -54,6 +54,7 @@
#include "llglheaders.h"
#include "lldrawpoolterrain.h"
#include "lldrawable.h"
+#include "llworldmipmap.h"
extern LLPipeline gPipeline;
extern bool gShiftFrame;
@@ -74,7 +75,6 @@ LLSurface::LLSurface(U32 type, LLViewerRegion *regionp) :
mDetailTextureScale(0.f),
mOriginGlobal(0.0, 0.0, 0.0),
mSTexturep(NULL),
- mWaterTexturep(NULL),
mGridsPerPatchEdge(0),
mMetersPerGrid(1.0f),
mMetersPerEdge(1.0f),
@@ -129,14 +129,7 @@ LLSurface::~LLSurface()
{
gPipeline.removePool(poolp);
// Don't enable this until we blitz the draw pool for it as well. -- djs
- if (mSTexturep)
- {
- mSTexturep = NULL;
- }
- if (mWaterTexturep)
- {
- mWaterTexturep = NULL;
- }
+ mSTexturep = NULL;
}
else
{
@@ -216,62 +209,17 @@ LLViewerTexture* LLSurface::getSTexture()
return mSTexturep;
}
-LLViewerTexture* LLSurface::getWaterTexture()
-{
- if (mWaterTexturep.notNull() && !mWaterTexturep->hasGLTexture())
- {
- createWaterTexture();
- }
- return mWaterTexturep;
-}
-
void LLSurface::createSTexture()
{
if (!mSTexturep)
{
- // Fill with dummy gray data.
- // GL NOT ACTIVE HERE
- LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize, sTextureSize, 3);
- U8 *default_texture = raw->getData();
- for (S32 i = 0; i < sTextureSize; i++)
- {
- for (S32 j = 0; j < sTextureSize; j++)
- {
- *(default_texture + (i*sTextureSize + j)*3) = 128;
- *(default_texture + (i*sTextureSize + j)*3 + 1) = 128;
- *(default_texture + (i*sTextureSize + j)*3 + 2) = 128;
- }
- }
+ U64 handle = mRegionp->getHandle();
- mSTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), false);
- mSTexturep->dontDiscard();
- gGL.getTexUnit(0)->bind(mSTexturep);
- mSTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
- }
-}
+ U32 grid_x, grid_y;
-void LLSurface::createWaterTexture()
-{
- if (!mWaterTexturep)
- {
- // Create the water texture
- LLPointer<LLImageRaw> raw = new LLImageRaw(sTextureSize/2, sTextureSize/2, 4);
- U8 *default_texture = raw->getData();
- for (S32 i = 0; i < sTextureSize/2; i++)
- {
- for (S32 j = 0; j < sTextureSize/2; j++)
- {
- *(default_texture + (i*sTextureSize/2 + j)*4) = MAX_WATER_COLOR.mV[0];
- *(default_texture + (i*sTextureSize/2 + j)*4 + 1) = MAX_WATER_COLOR.mV[1];
- *(default_texture + (i*sTextureSize/2 + j)*4 + 2) = MAX_WATER_COLOR.mV[2];
- *(default_texture + (i*sTextureSize/2 + j)*4 + 3) = MAX_WATER_COLOR.mV[3];
- }
- }
+ grid_from_region_handle(handle, &grid_x, &grid_y);
- mWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), false);
- mWaterTexturep->dontDiscard();
- gGL.getTexUnit(0)->bind(mWaterTexturep);
- mWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
+ mSTexturep = LLWorldMipmap::loadObjectsTile(grid_x, grid_y, 1);
}
}
@@ -285,11 +233,10 @@ void LLSurface::initTextures()
///////////////////////
//
- // Water texture
+ // Water object
//
if (gSavedSettings.getBOOL("RenderWater") )
{
- createWaterTexture();
mWaterObjp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, mRegionp);
gPipeline.createObject(mWaterObjp);
LLVector3d water_pos_global = from_region_handle(mRegionp->getHandle());
@@ -683,11 +630,8 @@ bool LLSurface::idleUpdate(F32 max_update_time)
}
}
- if (did_update)
- {
- // some patches changed, update region reflection probes
- mRegionp->updateReflectionProbes();
- }
+ // some patches changed, update region reflection probes
+ mRegionp->updateReflectionProbes(did_update);
return did_update;
}
@@ -1221,98 +1165,3 @@ F32 LLSurface::getWaterHeight() const
}
}
-
-bool LLSurface::generateWaterTexture(const F32 x, const F32 y,
- const F32 width, const F32 height)
-{
- LL_PROFILE_ZONE_SCOPED
- if (!getWaterTexture())
- {
- return false;
- }
-
- S32 tex_width = mWaterTexturep->getWidth();
- S32 tex_height = mWaterTexturep->getHeight();
- S32 tex_comps = mWaterTexturep->getComponents();
- S32 tex_stride = tex_width * tex_comps;
- LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
- U8 *rawp = raw->getData();
-
- F32 scale = 256.f * getMetersPerGrid() / (F32)tex_width;
- F32 scale_inv = 1.f / scale;
-
- S32 x_begin, y_begin, x_end, y_end;
-
- x_begin = ll_round(x * scale_inv);
- y_begin = ll_round(y * scale_inv);
- x_end = ll_round((x + width) * scale_inv);
- y_end = ll_round((y + width) * scale_inv);
-
- if (x_end > tex_width)
- {
- x_end = tex_width;
- }
- if (y_end > tex_width)
- {
- y_end = tex_width;
- }
-
- // OK, for now, just have the composition value equal the height at the point.
- LLVector3 location;
- LLColor4U coloru;
-
- const F32 WATER_HEIGHT = getWaterHeight();
-
- S32 i, j, offset;
- for (j = y_begin; j < y_end; j++)
- {
- for (i = x_begin; i < x_end; i++)
- {
- //F32 nv[2];
- //nv[0] = i/256.f;
- //nv[1] = j/256.f;
- // const S32 modulation = noise2(nv)*40;
- offset = j*tex_stride + i*tex_comps;
- location.mV[VX] = i*scale;
- location.mV[VY] = j*scale;
-
- // Sample multiple points
- const F32 height = resolveHeightRegion(location);
-
- if (height > WATER_HEIGHT)
- {
- // Above water...
- coloru = MAX_WATER_COLOR;
- coloru.mV[3] = ABOVE_WATERLINE_ALPHA;
- *(rawp + offset++) = coloru.mV[0];
- *(rawp + offset++) = coloru.mV[1];
- *(rawp + offset++) = coloru.mV[2];
- *(rawp + offset++) = coloru.mV[3];
- }
- else
- {
- // Want non-linear curve for transparency gradient
- coloru = MAX_WATER_COLOR;
- const F32 frac = 1.f - 2.f/(2.f - (height - WATER_HEIGHT));
- S32 alpha = 64 + ll_round((255-64)*frac);
-
- alpha = llmin(ll_round((F32)MAX_WATER_COLOR.mV[3]), alpha);
- alpha = llmax(64, alpha);
-
- coloru.mV[3] = alpha;
- *(rawp + offset++) = coloru.mV[0];
- *(rawp + offset++) = coloru.mV[1];
- *(rawp + offset++) = coloru.mV[2];
- *(rawp + offset++) = coloru.mV[3];
- }
- }
- }
-
- if (!mWaterTexturep->hasGLTexture())
- {
- mWaterTexturep->createGLTexture(0, raw);
- }
-
- mWaterTexturep->setSubImage(raw, x_begin, y_begin, x_end - x_begin, y_end - y_begin);
- return true;
-}
diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h
index 324296a4d3..68295225b6 100644
--- a/indra/newview/llsurface.h
+++ b/indra/newview/llsurface.h
@@ -128,7 +128,7 @@ public:
F32 getWaterHeight() const;
LLViewerTexture *getSTexture();
- LLViewerTexture *getWaterTexture();
+
bool hasZData() const { return mHasZData; }
void dirtyAllPatches(); // Use this to dirty all patches when changing terrain parameters
@@ -171,19 +171,11 @@ public:
protected:
void createSTexture();
- void createWaterTexture();
void initTextures();
- void initWater();
-
void createPatchData(); // Allocates memory for patches.
void destroyPatchData(); // Deallocates memory for patches.
- bool generateWaterTexture(const F32 x, const F32 y,
- const F32 width, const F32 height); // Generate texture from composition values.
-
- //F32 updateTexture(LLSurfacePatch *ppatch);
-
LLSurfacePatch *getPatch(const S32 x, const S32 y) const;
protected:
@@ -201,7 +193,6 @@ protected:
// The textures should never be directly initialized - use the setter methods!
LLPointer<LLViewerTexture> mSTexturep; // Texture for surface
- LLPointer<LLViewerTexture> mWaterTexturep; // Water texture
LLPointer<LLVOWater> mWaterObjp;
diff --git a/indra/newview/llsurfacepatch.cpp b/indra/newview/llsurfacepatch.cpp
index 042d770550..2a21170b07 100644
--- a/indra/newview/llsurfacepatch.cpp
+++ b/indra/newview/llsurfacepatch.cpp
@@ -906,15 +906,8 @@ void LLSurfacePatch::updateGL()
updateCompositionStats();
F32 tex_patch_size = meters_per_grid*grids_per_patch_edge;
- if (comp->generateMinimapTileLand((F32)origin_region[VX], (F32)origin_region[VY],
- tex_patch_size, tex_patch_size))
- {
- mSTexUpdate = false;
- // Also generate the water texture
- mSurfacep->generateWaterTexture((F32)origin_region.mdV[VX], (F32)origin_region.mdV[VY],
- tex_patch_size, tex_patch_size);
- }
+ mSTexUpdate = false;
}
void LLSurfacePatch::dirtyZ()
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index f521293b96..9d7319d5b8 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -59,8 +59,6 @@
#include "llvoavatarself.h"
#include "lltexlayer.h"
-extern F32 texmem_lower_bound_scale;
-
LLTextureView *gTextureView = NULL;
#define HIGH_PRIORITY 100000000.f
@@ -463,7 +461,7 @@ public:
: texture_view("texture_view")
{
S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
- changeDefault(rect, LLRect(0,0,100,line_height * 4));
+ changeDefault(rect, LLRect(0,0,0,line_height * 7));
}
};
@@ -494,19 +492,51 @@ void LLGLTexMemBar::draw()
U32 total_objects = gObjectList.getNumObjects();
F32 x_right = 0.0;
+ U32 image_count = gTextureList.getNumImages();
+ U32 raw_image_count = 0;
+ U64 raw_image_bytes = 0;
+
+ U32 saved_raw_image_count = 0;
+ U64 saved_raw_image_bytes = 0;
+
+ U32 aux_raw_image_count = 0;
+ U64 aux_raw_image_bytes = 0;
+
+ for (auto& image : gTextureList)
+ {
+ const LLImageRaw* raw_image = image->getRawImage();
+
+ if (raw_image)
+ {
+ raw_image_count++;
+ raw_image_bytes += raw_image->getDataSize();
+ }
+
+ raw_image = image->getSavedRawImage();
+ if (raw_image)
+ {
+ saved_raw_image_count++;
+ saved_raw_image_bytes += raw_image->getDataSize();
+ }
+
+ raw_image = image->getAuxRawImage();
+ if (raw_image)
+ {
+ aux_raw_image_count++;
+ aux_raw_image_bytes += raw_image->getDataSize();
+ }
+ }
+
+ F64 raw_image_bytes_MB = raw_image_bytes / (1024.0 * 1024.0);
+ F64 saved_raw_image_bytes_MB = saved_raw_image_bytes / (1024.0 * 1024.0);
+ F64 aux_raw_image_bytes_MB = aux_raw_image_bytes / (1024.0 * 1024.0);
+
//----------------------------------------------------------------------------
LLGLSUIDefault gls_ui;
LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
LLColor4 color;
- // Gray background using completely magic numbers
- gGL.color4f(0.f, 0.f, 0.f, 0.25f);
- // const LLRect & rect(getRect());
- // gl_rect_2d(-4, v_offset, rect.mRight - rect.mLeft + 2, v_offset + line_height*4);
-
std::string text = "";
- LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6,
- text_color, LLFontGL::LEFT, LLFontGL::TOP);
LLTrace::Recording& recording = LLViewerStats::instance().getRecording();
@@ -527,6 +557,10 @@ void LLGLTexMemBar::draw()
U32 texFetchLatMed = U32(recording.getMean(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
U32 texFetchLatMax = U32(recording.getMax(LLTextureFetch::sTexFetchLatency).value() * 1000.0f);
+ // draw a background above first line.... no idea where the rest of the background comes from for the below text
+ gGL.color4f(0.f, 0.f, 0.f, 0.25f);
+ gl_rect_2d(-10, getRect().getHeight() + line_height + 1, getRect().getWidth()+2, getRect().getHeight()+2);
+
text = llformat("Est. Free: %d MB Sys Free: %d MB FBO: %d MB Bias: %.2f Cache: %.1f/%.1f MB",
(S32)LLViewerTexture::sFreeVRAMMegabytes,
LLMemory::getAvailableMemKB()/1024,
@@ -534,11 +568,15 @@ void LLGLTexMemBar::draw()
discard_bias,
cache_usage,
cache_max_usage);
- //, cache_entries, cache_max_entries
-
- LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*6,
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*7,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
+ text = llformat("Images: %d Raw: %d (%.2f MB) Saved: %d (%.2f MB) Aux: %d (%.2f MB)", image_count, raw_image_count, raw_image_bytes_MB,
+ saved_raw_image_count, saved_raw_image_bytes_MB,
+ aux_raw_image_count, aux_raw_image_bytes_MB);
+ LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height * 6,
+ text_color, LLFontGL::LEFT, LLFontGL::TOP);
+
U32 cache_read(0U), cache_write(0U), res_wait(0U);
LLAppViewer::getTextureFetch()->getStateStats(&cache_read, &cache_write, &res_wait);
@@ -551,7 +589,6 @@ void LLGLTexMemBar::draw()
cache_read,
cache_write,
res_wait);
-
LLFontGL::getFontMonospace()->renderUTF8(text, 0, 0, v_offset + line_height*5,
text_color, LLFontGL::LEFT, LLFontGL::TOP);
@@ -791,7 +828,7 @@ void LLTextureView::draw()
LL_INFOS() << "ID\tMEM\tBOOST\tPRI\tWIDTH\tHEIGHT\tDISCARD" << LL_ENDL;
}
- for (LLViewerTextureList::image_priority_list_t::iterator iter = gTextureList.mImageList.begin();
+ for (LLViewerTextureList::image_list_t::iterator iter = gTextureList.mImageList.begin();
iter != gTextureList.mImageList.end(); )
{
LLPointer<LLViewerFetchedTexture> imagep = *iter++;
diff --git a/indra/newview/llversioninfo.cpp b/indra/newview/llversioninfo.cpp
index a571b5544b..4e8320b72a 100644
--- a/indra/newview/llversioninfo.cpp
+++ b/indra/newview/llversioninfo.cpp
@@ -76,37 +76,37 @@ LLVersionInfo::~LLVersionInfo()
{
}
-S32 LLVersionInfo::getMajor()
+S32 LLVersionInfo::getMajor() const
{
return LL_VIEWER_VERSION_MAJOR;
}
-S32 LLVersionInfo::getMinor()
+S32 LLVersionInfo::getMinor() const
{
return LL_VIEWER_VERSION_MINOR;
}
-S32 LLVersionInfo::getPatch()
+S32 LLVersionInfo::getPatch() const
{
return LL_VIEWER_VERSION_PATCH;
}
-U64 LLVersionInfo::getBuild()
+U64 LLVersionInfo::getBuild() const
{
return LL_VIEWER_VERSION_BUILD;
}
-std::string LLVersionInfo::getVersion()
+std::string LLVersionInfo::getVersion() const
{
return version;
}
-std::string LLVersionInfo::getShortVersion()
+std::string LLVersionInfo::getShortVersion() const
{
return short_version;
}
-std::string LLVersionInfo::getChannelAndVersion()
+std::string LLVersionInfo::getChannelAndVersion() const
{
if (mVersionChannel.empty())
{
@@ -117,7 +117,7 @@ std::string LLVersionInfo::getChannelAndVersion()
return mVersionChannel;
}
-std::string LLVersionInfo::getChannel()
+std::string LLVersionInfo::getChannel() const
{
return mWorkingChannelName;
}
@@ -128,7 +128,7 @@ void LLVersionInfo::resetChannel(const std::string& channel)
mVersionChannel.clear(); // Reset version and channel string til next use.
}
-LLVersionInfo::ViewerMaturity LLVersionInfo::getViewerMaturity()
+LLVersionInfo::ViewerMaturity LLVersionInfo::getViewerMaturity() const
{
ViewerMaturity maturity;
@@ -166,12 +166,12 @@ LLVersionInfo::ViewerMaturity LLVersionInfo::getViewerMaturity()
}
-std::string LLVersionInfo::getBuildConfig()
+std::string LLVersionInfo::getBuildConfig() const
{
return build_configuration;
}
-std::string LLVersionInfo::getReleaseNotes()
+std::string LLVersionInfo::getReleaseNotes() const
{
return mReleaseNotes;
}
diff --git a/indra/newview/llversioninfo.h b/indra/newview/llversioninfo.h
index aed43263a6..237b37a084 100644
--- a/indra/newview/llversioninfo.h
+++ b/indra/newview/llversioninfo.h
@@ -52,38 +52,38 @@ public:
~LLVersionInfo();
/// return the major version number as an integer
- S32 getMajor();
+ S32 getMajor() const;
/// return the minor version number as an integer
- S32 getMinor();
+ S32 getMinor() const;
/// return the patch version number as an integer
- S32 getPatch();
+ S32 getPatch() const;
/// return the build number as an integer
- U64 getBuild();
+ U64 getBuild() const;
/// return the full viewer version as a string like "2.0.0.200030"
- std::string getVersion();
+ std::string getVersion() const;
/// return the viewer version as a string like "2.0.0"
- std::string getShortVersion();
+ std::string getShortVersion() const;
/// return the viewer version and channel as a string
/// like "Second Life Release 2.0.0.200030"
- std::string getChannelAndVersion();
+ std::string getChannelAndVersion() const;
/// return the channel name, e.g. "Second Life"
- std::string getChannel();
+ std::string getChannel() const;
/// return the CMake build type
- std::string getBuildConfig();
+ std::string getBuildConfig() const;
/// reset the channel name used by the viewer.
void resetChannel(const std::string& channel);
/// return the bit width of an address
- S32 getAddressSize() { return ADDRESS_SIZE; }
+ S32 getAddressSize() const { return ADDRESS_SIZE; }
typedef enum
{
@@ -92,11 +92,11 @@ public:
BETA_VIEWER,
RELEASE_VIEWER
} ViewerMaturity;
- ViewerMaturity getViewerMaturity();
+ ViewerMaturity getViewerMaturity() const;
/// get the release-notes URL, once it becomes available -- until then,
/// return empty string
- std::string getReleaseNotes();
+ std::string getReleaseNotes() const;
private:
std::string version;
@@ -107,7 +107,7 @@ private:
std::string mWorkingChannelName;
// Storage for the "version and channel" string.
// This will get reset too.
- std::string mVersionChannel;
+ mutable std::string mVersionChannel;
std::string build_configuration;
std::string mReleaseNotes;
// Store unique_ptrs to the next couple things so we don't have to explain
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index ceda2675d5..3e1705b8a1 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -76,6 +76,7 @@
#include "llfloaterfonttest.h"
#include "llfloaterforgetuser.h"
#include "llfloatergesture.h"
+#include "llfloatergltfasseteditor.h"
#include "llfloatergodtools.h"
#include "llfloatergridstatus.h"
#include "llfloatergroups.h"
@@ -372,6 +373,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("forget_username", "floater_forget_user.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterForgetUser>);
LLFloaterReg::add("gestures", "floater_gesture.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGesture>);
+ LLFloaterReg::add("gltf_asset_editor", "floater_gltf_asset_editor.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGLTFAssetEditor>);
LLFloaterReg::add("god_tools", "floater_god_tools.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGodTools>);
LLFloaterReg::add("grid_status", "floater_grid_status.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGridStatus>);
LLFloaterReg::add("group_picker", "floater_choose_group.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterGroupPicker>);
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 23931ecf03..f62d929e9a 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -1253,41 +1253,46 @@ void LLViewerMedia::getOpenIDCookieCoro(std::string url)
hostEnd = authority.size();
}
- LLViewerMedia* inst = getInstance();
if (url.length())
{
- LLMediaCtrl* media_instance = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents");
- if (media_instance)
- {
- std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart);
- std::string cookie_name = "";
- std::string cookie_value = "";
- std::string cookie_path = "";
- bool httponly = true;
- bool secure = true;
- if (inst->parseRawCookie(inst->mOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) &&
- media_instance->getMediaPlugin())
+ LLAppViewer::instance()->postToMainCoro([=]()
{
- // MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the
- // url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked.
- // For now, we use the URL for the OpenID POST request since it will have the same authority
- // as the domain field.
- // (Feels like there must be a less dirty way to construct a URL from component LLURL parts)
- // MAINT-6392 - Rider: Do not change, however, the original URI requested, since it is used further
- // 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);
-
- // 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);
- }
- }
+ LLMediaCtrl* media_instance = LLFloaterReg::getInstance("destinations")->getChild<LLMediaCtrl>("destination_guide_contents");
+ if (media_instance)
+ {
+ LLViewerMedia* inst = getInstance();
+ std::string cookie_host = authority.substr(hostStart, hostEnd - hostStart);
+ std::string cookie_name = "";
+ std::string cookie_value = "";
+ std::string cookie_path = "";
+ bool httponly = true;
+ bool secure = true;
+ if (inst->parseRawCookie(inst->mOpenIDCookie, cookie_name, cookie_value, cookie_path, httponly, secure) &&
+ media_instance->getMediaPlugin())
+ {
+ // MAINT-5711 - inexplicably, the CEF setCookie function will no longer set the cookie if the
+ // url and domain are not the same. This used to be my.sl.com and id.sl.com respectively and worked.
+ // For now, we use the URL for the OpenID POST request since it will have the same authority
+ // as the domain field.
+ // (Feels like there must be a less dirty way to construct a URL from component LLURL parts)
+ // MAINT-6392 - Rider: Do not change, however, the original URI requested, since it is used further
+ // 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);
+
+ // 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);
+ }
+ }
+ });
}
+ LLViewerMedia* inst = getInstance();
+
// Note: Rider: MAINT-6392 - Some viewer code requires access to the my.sl.com openid cookie for such
// actions as posting snapshots to the feed. This is handled through HTTPCore rather than CEF and so
// we must learn to SHARE the cookies.
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 7e58a604f6..2687938b35 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -8139,6 +8139,15 @@ class LLAdvancedClickGLTFUpload: public view_listener_t
}
};
+class LLAdvancedClickGLTFEdit : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterReg::showInstance("gltf_asset_editor");
+ return true;
+ }
+};
+
class LLAdvancedClickResizeWindow : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -9481,15 +9490,6 @@ class LLUpdateMembershipLabel : public view_listener_t
}
};
-void handle_voice_morphing_subscribe()
-{
- LLWeb::loadURL(LLTrans::getString("voice_morphing_url"));
-}
-
-void handle_premium_voice_morphing_subscribe()
-{
- LLWeb::loadURL(LLTrans::getString("premium_voice_morphing_url"));
-}
class LLToggleUIHints : public view_listener_t
{
@@ -9690,16 +9690,6 @@ void initialize_menus()
//Communicate Nearby chat
view_listener_t::addMenu(new LLCommunicateNearbyChat(), "Communicate.NearbyChat");
- // Communicate > Voice morphing > Subscribe...
- commit.add("Communicate.VoiceMorphing.Subscribe", boost::bind(&handle_voice_morphing_subscribe));
- // Communicate > Voice morphing > Premium perk...
- commit.add("Communicate.VoiceMorphing.PremiumPerk", boost::bind(&handle_premium_voice_morphing_subscribe));
- LLVivoxVoiceClient * voice_clientp = LLVivoxVoiceClient::getInstance();
- enable.add("Communicate.VoiceMorphing.NoVoiceMorphing.Check"
- , boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, voice_clientp, "NoVoiceMorphing"));
- commit.add("Communicate.VoiceMorphing.NoVoiceMorphing.Click"
- , boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, voice_clientp, "NoVoiceMorphing"));
-
// World menu
view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun");
view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark");
@@ -9813,6 +9803,7 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedClickGLTFOpen(), "Advanced.ClickGLTFOpen");
view_listener_t::addMenu(new LLAdvancedClickGLTFSaveAs(), "Advanced.ClickGLTFSaveAs");
view_listener_t::addMenu(new LLAdvancedClickGLTFUpload(), "Advanced.ClickGLTFUpload");
+ view_listener_t::addMenu(new LLAdvancedClickGLTFEdit(), "Advanced.ClickGLTFEdit");
view_listener_t::addMenu(new LLAdvancedClickResizeWindow(), "Advanced.ClickResizeWindow");
view_listener_t::addMenu(new LLAdvancedPurgeShaderCache(), "Advanced.ClearShaderCache");
view_listener_t::addMenu(new LLAdvancedRebuildTerrain(), "Advanced.RebuildTerrain");
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 8af0057c88..232b020d3d 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -3676,7 +3676,9 @@ bool LLViewerObject::updateLOD()
bool LLViewerObject::updateGeometry(LLDrawable *drawable)
{
- return false;
+ // return true means "update complete", return false means "try again next frame"
+ // default should be return true
+ return true;
}
void LLViewerObject::updateGL()
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index 19a1990665..39244c8246 100755
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1269,8 +1269,12 @@ U32 LLViewerRegion::getNumOfVisibleGroups() const
return mImpl ? static_cast<U32>(mImpl->mVisibleGroups.size()) : 0;
}
-void LLViewerRegion::updateReflectionProbes()
+void LLViewerRegion::updateReflectionProbes(bool full_update)
{
+ if (!full_update && mReflectionMaps.empty())
+ {
+ return;
+ }
LL_PROFILE_ZONE_SCOPED_CATEGORY_DISPLAY;
const F32 probe_spacing = 32.f;
const F32 probe_radius = sqrtf((probe_spacing * 0.5f) * (probe_spacing * 0.5f) * 3.f);
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index 68247dc18e..d0ec1fe877 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -428,7 +428,7 @@ public:
static bool isNewObjectCreationThrottleDisabled() {return sNewObjectCreationThrottle < 0;}
// rebuild reflection probe list
- void updateReflectionProbes();
+ void updateReflectionProbes(bool full_update);
private:
void addToVOCacheTree(LLVOCacheEntry* entry);
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index c1062b9a01..b2ed86707c 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -101,6 +101,7 @@ U32 LLViewerTexture::sMaxSmallImageSize = MAX_CACHED_RAW_IMAGE_AREA;
bool LLViewerTexture::sFreezeImageUpdates = false;
F32 LLViewerTexture::sCurrentTime = 0.0f;
+constexpr F32 MEMORY_CHECK_WAIT_TIME = 1.0f;
constexpr F32 MIN_VRAM_BUDGET = 768.f;
F32 LLViewerTexture::sFreeVRAMMegabytes = MIN_VRAM_BUDGET;
@@ -413,8 +414,6 @@ void LLViewerTextureManager::init()
}
}
imagep->createGLTexture(0, image_raw);
- //cache the raw image
- imagep->setCachedRawImage(0, image_raw);
image_raw = NULL;
#else
LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, true, LLGLTexture::BOOST_UI);
@@ -484,10 +483,6 @@ void LLViewerTexture::initClass()
LLImageGL::sDefaultGLTexture = LLViewerFetchedTexture::sDefaultImagep->getGLTexture();
}
-// non-const (used externally
-F32 texmem_lower_bound_scale = 0.85f;
-F32 texmem_middle_bound_scale = 0.925f;
-
//static
void LLViewerTexture::updateClass()
{
@@ -519,14 +514,49 @@ void LLViewerTexture::updateClass()
sFreeVRAMMegabytes = target - used;
F32 over_pct = llmax((used-target) / target, 0.f);
- sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.f + over_pct);
- if (sDesiredDiscardBias > 1.f)
+ if (isSystemMemoryLow())
+ {
+ // System RAM is low -> ramp up discard bias over time to free memory
+ if (sEvaluationTimer.getElapsedTimeF32() > MEMORY_CHECK_WAIT_TIME)
+ {
+ static LLCachedControl<F32> low_mem_min_discard_increment(gSavedSettings, "RenderLowMemMinDiscardIncrement", .1f);
+ sDesiredDiscardBias += llmax(low_mem_min_discard_increment, over_pct);
+ sEvaluationTimer.reset();
+ }
+ }
+ else
+ {
+ sDesiredDiscardBias = llmax(sDesiredDiscardBias, 1.f + over_pct);
+
+ if (sDesiredDiscardBias > 1.f)
+ {
+ sDesiredDiscardBias -= gFrameIntervalSeconds * 0.01;
+ }
+ }
+
+ LLViewerTexture::sFreezeImageUpdates = false;
+}
+
+//static
+bool LLViewerTexture::isSystemMemoryLow()
+{
+ static LLFrameTimer timer;
+ static U32Megabytes physical_res = U32Megabytes(U32_MAX);
+
+ static LLCachedControl<U32> min_free_main_memory(gSavedSettings, "RenderMinFreeMainMemoryThreshold", 512);
+ const U32Megabytes MIN_FREE_MAIN_MEMORY(min_free_main_memory);
+
+ if (timer.getElapsedTimeF32() < MEMORY_CHECK_WAIT_TIME) //call this once per second.
{
- sDesiredDiscardBias -= gFrameIntervalSeconds * 0.01;
+ return physical_res < MIN_FREE_MAIN_MEMORY;
}
- LLViewerTexture::sFreezeImageUpdates = false; // sDesiredDiscardBias > (desired_discard_bias_max - 1.0f);
+ timer.reset();
+
+ LLMemory::updateMemoryInfo();
+ physical_res = LLMemory::getAvailableMemKB();
+ return physical_res < MIN_FREE_MAIN_MEMORY;
}
//end of static functions
@@ -696,9 +726,6 @@ bool LLViewerTexture::bindDefaultImage(S32 stage)
}
stop_glerror();
- //check if there is cached raw image and switch to it if possible
- switchToCachedImage();
-
LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
if (tester)
{
@@ -899,18 +926,6 @@ void LLViewerTexture::reorganizeVolumeList()
}
}
-//virtual
-void LLViewerTexture::switchToCachedImage()
-{
- //nothing here.
-}
-
-//virtual
-void LLViewerTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw)
-{
- //nothing here.
-}
-
bool LLViewerTexture::isLargeImage()
{
return (S32)mTexelsPerImage > LLViewerTexture::sMinLargeImageSize;
@@ -1045,10 +1060,6 @@ void LLViewerFetchedTexture::init(bool firstinit)
mIsFetched = false;
mInFastCacheList = false;
- mCachedRawImage = NULL;
- mCachedRawDiscardLevel = -1;
- mCachedRawImageReady = false;
-
mSavedRawImage = NULL;
mForceToSaveRawImage = false;
mSaveRawImage = false;
@@ -1106,9 +1117,6 @@ void LLViewerFetchedTexture::cleanup()
// Clean up image data
destroyRawImage();
- mCachedRawImage = NULL;
- mCachedRawDiscardLevel = -1;
- mCachedRawImageReady = false;
mSavedRawImage = NULL;
mSavedRawDiscardLevel = -1;
}
@@ -1188,13 +1196,17 @@ void LLViewerFetchedTexture::setForSculpt()
{
static const S32 MAX_INTERVAL = 8; //frames
+ forceToSaveRawImage(0, F32_MAX);
+
+ setBoostLevel(llmax((S32)getBoostLevel(),
+ (S32)LLGLTexture::BOOST_SCULPTED));
+
mForSculpt = true;
if(isForSculptOnly() && hasGLTexture() && !getBoundRecently())
{
destroyGLTexture(); //sculpt image does not need gl texture.
mTextureState = ACTIVE;
}
- checkCachedRawSculptImage();
setMaxVirtualSizeResetInterval(MAX_INTERVAL);
}
@@ -1307,10 +1319,6 @@ void LLViewerFetchedTexture::addToCreateTexture()
}
}
- //discard the cached raw image and the saved raw image
- mCachedRawImageReady = false;
- mCachedRawDiscardLevel = -1;
- mCachedRawImage = NULL;
mSavedRawDiscardLevel = -1;
mSavedRawImage = NULL;
}
@@ -2011,13 +2019,6 @@ bool LLViewerFetchedTexture::updateFetch()
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("vftuf - current < min");
make_request = false;
}
- else if(mCachedRawImage.notNull() // can be empty
- && mCachedRawImageReady
- && (current_discard < 0 || current_discard > mCachedRawDiscardLevel))
- {
- make_request = false;
- switchToCachedImage(); //use the cached raw data first
- }
if (make_request)
{
@@ -2511,20 +2512,6 @@ bool LLViewerFetchedTexture::doLoadedCallbacks()
}
//
- // Do a readback if required, OR start off a texture decode
- //
- if (need_readback && (getMaxDiscardLevel() > gl_discard))
- {
- // Do a readback to get the GL data into the raw image
- // We have GL data.
-
- destroyRawImage();
- reloadRawImage(mLoadedCallbackDesiredDiscardLevel);
- llassert(mRawImage.notNull());
- llassert(!mNeedsAux || mAuxRawImage.notNull());
- }
-
- //
// Run raw/auxiliary data callbacks
//
if (run_raw_callbacks && mIsRawImageValid && (mRawDiscardLevel <= getMaxDiscardLevel()))
@@ -2631,61 +2618,6 @@ void LLViewerFetchedTexture::forceImmediateUpdate()
return;
}
-LLImageRaw* LLViewerFetchedTexture::reloadRawImage(S8 discard_level)
-{
- llassert(mGLTexturep.notNull());
- llassert(discard_level >= 0);
- llassert(mComponents > 0);
-
- if (mRawImage.notNull())
- {
- //mRawImage is in use by somebody else, do not delete it.
- return NULL;
- }
-
- if(mSavedRawDiscardLevel >= 0 && mSavedRawDiscardLevel <= discard_level)
- {
- if (mSavedRawDiscardLevel != discard_level
- && mBoostLevel != BOOST_ICON
- && mBoostLevel != BOOST_THUMBNAIL)
- {
- mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents());
- mRawImage->copy(getSavedRawImage());
- }
- else
- {
- mRawImage = getSavedRawImage();
- }
- mRawDiscardLevel = discard_level;
- }
- else
- {
- //force to fetch raw image again if cached raw image is not good enough.
- if(mCachedRawDiscardLevel > discard_level)
- {
- mRawImage = mCachedRawImage;
- mRawDiscardLevel = mCachedRawDiscardLevel;
- }
- else //cached raw image is good enough, copy it.
- {
- if(mCachedRawDiscardLevel != discard_level)
- {
- mRawImage = new LLImageRaw(getWidth(discard_level), getHeight(discard_level), getComponents());
- mRawImage->copy(mCachedRawImage);
- }
- else
- {
- mRawImage = mCachedRawImage;
- }
- mRawDiscardLevel = discard_level;
- }
- }
- mIsRawImageValid = true;
- sRawCount++;
-
- return mRawImage;
-}
-
bool LLViewerFetchedTexture::needsToSaveRawImage()
{
return mForceToSaveRawImage || mSaveRawImage;
@@ -2710,7 +2642,6 @@ void LLViewerFetchedTexture::destroyRawImage()
{
saveRawImage();
}
- setCachedRawImage();
}
mRawImage = NULL;
@@ -2720,151 +2651,6 @@ void LLViewerFetchedTexture::destroyRawImage()
}
}
-//use the mCachedRawImage to (re)generate the gl texture.
-//virtual
-void LLViewerFetchedTexture::switchToCachedImage()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- if(mCachedRawImage.notNull() &&
- !mNeedsCreateTexture) // <--- texture creation is pending, don't step on it
- {
- mRawImage = mCachedRawImage;
-
- if (getComponents() != mRawImage->getComponents())
- {
- // We've changed the number of components, so we need to move any
- // objects using this pool to a different pool.
- mComponents = mRawImage->getComponents();
- mGLTexturep->setComponents(mComponents);
- gTextureList.dirtyImage(this);
- }
-
- mIsRawImageValid = true;
- mRawDiscardLevel = mCachedRawDiscardLevel;
-
- scheduleCreateTexture();
- }
-}
-
-//cache the imageraw forcefully.
-//virtual
-void LLViewerFetchedTexture::setCachedRawImage(S32 discard_level, LLImageRaw* imageraw)
-{
- if(imageraw != mRawImage.get())
- {
- if (mBoostLevel == LLGLTexture::BOOST_ICON)
- {
- S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_ICON_DIMENSIONS;
- S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_ICON_DIMENSIONS;
- if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
- {
- mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents());
- mCachedRawImage->copyScaled(imageraw);
- }
- else
- {
- mCachedRawImage = imageraw;
- }
- }
- else if (mBoostLevel == LLGLTexture::BOOST_THUMBNAIL)
- {
- S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : DEFAULT_THUMBNAIL_DIMENSIONS;
- S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : DEFAULT_THUMBNAIL_DIMENSIONS;
- if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
- {
- mCachedRawImage = new LLImageRaw(expected_width, expected_height, imageraw->getComponents());
- mCachedRawImage->copyScaled(imageraw);
- }
- else
- {
- mCachedRawImage = imageraw;
- }
- }
- else
- {
- mCachedRawImage = imageraw;
- }
- mCachedRawDiscardLevel = discard_level;
- mCachedRawImageReady = true;
- }
-}
-
-void LLViewerFetchedTexture::setCachedRawImage()
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- if(mRawImage == mCachedRawImage)
- {
- return;
- }
- if(!mIsRawImageValid)
- {
- return;
- }
-
- if(mCachedRawImageReady)
- {
- return;
- }
-
- if(mCachedRawDiscardLevel < 0 || mCachedRawDiscardLevel > mRawDiscardLevel)
- {
- S32 i = 0;
- S32 w = mRawImage->getWidth();
- S32 h = mRawImage->getHeight();
-
- S32 max_size = MAX_CACHED_RAW_IMAGE_AREA;
- if(LLGLTexture::BOOST_TERRAIN == mBoostLevel)
- {
- max_size = MAX_CACHED_RAW_TERRAIN_IMAGE_AREA;
- }
- if(mForSculpt)
- {
- max_size = MAX_CACHED_RAW_SCULPT_IMAGE_AREA;
- mCachedRawImageReady = !mRawDiscardLevel;
- }
- else
- {
- mCachedRawImageReady = (!mRawDiscardLevel || ((w * h) >= max_size));
- }
-
- while(((w >> i) * (h >> i)) > max_size)
- {
- ++i;
- }
-
- if(i)
- {
- if(!(w >> i) || !(h >> i))
- {
- --i;
- }
-
- {
- //make a duplicate in case somebody else is using this raw image
- mRawImage = mRawImage->scaled(w >> i, h >> i);
- }
- }
- mCachedRawImage = mRawImage;
- mRawDiscardLevel += i;
- mCachedRawDiscardLevel = mRawDiscardLevel;
- }
-}
-
-void LLViewerFetchedTexture::checkCachedRawSculptImage()
-{
- if(mCachedRawImageReady && mCachedRawDiscardLevel > 0)
- {
- if(getDiscardLevel() != 0)
- {
- mCachedRawImageReady = false;
- }
- else if(isForSculptOnly())
- {
- resetTextureStats(); //do not update this image any more.
- }
- }
-}
-
void LLViewerFetchedTexture::saveRawImage()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
@@ -2904,6 +2690,20 @@ void LLViewerFetchedTexture::saveRawImage()
mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents());
}
}
+ else if (mBoostLevel == LLGLTexture::BOOST_SCULPTED)
+ {
+ S32 expected_width = mKnownDrawWidth > 0 ? mKnownDrawWidth : sMaxSculptRez;
+ S32 expected_height = mKnownDrawHeight > 0 ? mKnownDrawHeight : sMaxSculptRez;
+ if (mRawImage->getWidth() > expected_width || mRawImage->getHeight() > expected_height)
+ {
+ mSavedRawImage = new LLImageRaw(expected_width, expected_height, mRawImage->getComponents());
+ mSavedRawImage->copyScaled(mRawImage);
+ }
+ else
+ {
+ mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents());
+ }
+ }
else
{
mSavedRawImage = new LLImageRaw(mRawImage->getData(), mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents());
@@ -2949,20 +2749,23 @@ void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_t
{
mForceToSaveRawImage = true;
mDesiredSavedRawDiscardLevel = desired_discard;
+ }
+}
- //copy from the cached raw image if exists.
- if(mCachedRawImage.notNull() && mRawImage.isNull() )
- {
- mRawImage = mCachedRawImage;
- mRawDiscardLevel = mCachedRawDiscardLevel;
-
- saveRawImage();
+void LLViewerFetchedTexture::readbackRawImage()
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
- mRawImage = NULL;
- mRawDiscardLevel = INVALID_DISCARD_LEVEL;
+ if (mGLTexturep.notNull() && mGLTexturep->getTexName() != 0 && mRawImage.isNull())
+ {
+ mRawImage = new LLImageRaw();
+ if (!mGLTexturep->readBackRaw(-1, mRawImage, false))
+ {
+ mRawImage = nullptr;
}
}
}
+
void LLViewerFetchedTexture::destroySavedRawImage()
{
if(mLastReferencedSavedRawImageTime < mKeptSavedRawImageTime)
@@ -2997,6 +2800,11 @@ LLImageRaw* LLViewerFetchedTexture::getSavedRawImage()
return mSavedRawImage;
}
+const LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() const
+{
+ return mSavedRawImage;
+}
+
bool LLViewerFetchedTexture::hasSavedRawImage() const
{
return mSavedRawImage.notNull();
@@ -3173,20 +2981,14 @@ void LLViewerLODTexture::processTextureStats()
bool LLViewerLODTexture::scaleDown()
{
- if(hasGLTexture() && mCachedRawDiscardLevel > getDiscardLevel())
+ if (mGLTexturep.isNull())
{
- switchToCachedImage();
-
- LLTexturePipelineTester* tester = (LLTexturePipelineTester*)LLMetricPerformanceTesterBasic::getTester(sTesterName);
- if (tester)
- {
- tester->setStablizingTime();
- }
-
- return true;
+ return false;
}
- return false;
+
+ return mGLTexturep->scaleDown(mDesiredDiscardLevel);
}
+
//----------------------------------------------------------------------------------------------
//end of LLViewerLODTexture
//----------------------------------------------------------------------------------------------
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index dc9182bf1b..b1e0494a30 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -117,6 +117,7 @@ protected:
public:
static void initClass();
static void updateClass();
+ static bool isSystemMemoryLow();
LLViewerTexture(bool usemipmaps = true);
LLViewerTexture(const LLUUID& id, bool usemipmaps) ;
@@ -165,8 +166,6 @@ public:
S32 getNumVolumes(U32 channel) const;
const ll_volume_list_t* getVolumeList(U32 channel) const { return &mVolumeList[channel]; }
-
- virtual void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ;
bool isLargeImage() ;
void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;}
@@ -184,8 +183,6 @@ private:
friend class LLBumpImageList;
friend class LLUIImageList;
- virtual void switchToCachedImage();
-
protected:
friend class LLViewerTextureList;
LLUUID mID;
@@ -370,7 +367,6 @@ public:
U32 getFetchPriority() const { return mFetchPriority ;}
F32 getDownloadProgress() const {return mDownloadProgress ;}
- LLImageRaw* reloadRawImage(S8 discard_level) ;
void destroyRawImage();
bool needsToSaveRawImage();
@@ -389,17 +385,20 @@ public:
bool isForSculptOnly() const;
//raw image management
- void checkCachedRawSculptImage() ;
LLImageRaw* getRawImage()const { return mRawImage ;}
S32 getRawImageLevel() const {return mRawDiscardLevel;}
- LLImageRaw* getCachedRawImage() const { return mCachedRawImage ;}
- S32 getCachedRawImageLevel() const {return mCachedRawDiscardLevel;}
- bool isCachedRawImageReady() const {return mCachedRawImageReady ;}
bool isRawImageValid()const { return mIsRawImageValid ; }
void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ;
- /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) override;
+
+ // readback the raw image from OpenGL if mRawImage is not valid
+ void readbackRawImage();
+
void destroySavedRawImage() ;
LLImageRaw* getSavedRawImage() ;
+ S32 getSavedRawImageLevel() const {return mSavedRawDiscardLevel; }
+
+ const LLImageRaw* getSavedRawImage() const;
+ const LLImageRaw* getAuxRawImage() const { return mAuxRawImage; }
bool hasSavedRawImage() const ;
F32 getElapsedLastReferencedSavedRawImageTime() const ;
bool isFullyLoaded() const;
@@ -416,7 +415,6 @@ public:
/*virtual*/bool isActiveFetching() override; //is actively in fetching by the fetching pipeline.
protected:
- /*virtual*/ void switchToCachedImage() override;
S32 getCurrentDiscardLevelForFetching() ;
void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f);
@@ -425,7 +423,6 @@ private:
void cleanup() ;
void saveRawImage() ;
- void setCachedRawImage() ;
//for atlas
void resetFaceAtlas() ;
@@ -497,11 +494,6 @@ protected:
F32 mLastReferencedSavedRawImageTime ;
F32 mKeptSavedRawImageTime ;
- //a small version of the copy of the raw image (<= 64 * 64)
- LLPointer<LLImageRaw> mCachedRawImage;
- S32 mCachedRawDiscardLevel;
- bool mCachedRawImageReady; //the rez of the mCachedRawImage reaches the upper limit.
-
LLHost mTargetHost; // if invalid, just request from agent's simulator
// Timers
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index b90c1868fc..4d8fd8ddd5 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -296,7 +296,7 @@ void LLViewerTextureList::shutdown()
// Write out list of currently loaded textures for precaching on startup
typedef std::set<std::pair<S32,LLViewerFetchedTexture*> > image_area_list_t;
image_area_list_t image_area_list;
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); ++iter)
{
LLViewerFetchedTexture* image = *iter;
@@ -367,7 +367,7 @@ void LLViewerTextureList::dump()
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
LL_INFOS() << "LLViewerTextureList::dump()" << LL_ENDL;
- for (image_priority_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it)
+ for (image_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it)
{
LLViewerFetchedTexture* image = *it;
@@ -381,15 +381,9 @@ void LLViewerTextureList::dump()
}
}
-void LLViewerTextureList::destroyGL(bool save_state)
+void LLViewerTextureList::destroyGL()
{
- LLImageGL::destroyGL(save_state);
-}
-
-void LLViewerTextureList::restoreGL()
-{
- llassert_always(mInitialized) ;
- LLImageGL::restoreGL();
+ LLImageGL::destroyGL();
}
/* Vertical tab container button image IDs
@@ -895,7 +889,7 @@ void LLViewerTextureList::clearFetchingRequests()
LLAppViewer::getTextureFetch()->deleteAllRequests();
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); ++iter)
{
LLViewerFetchedTexture* imagep = *iter;
@@ -1208,7 +1202,7 @@ void LLViewerTextureList::updateImagesUpdateStats()
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
if (mForceResetTextureStats)
{
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@@ -1228,7 +1222,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
// Update texture stats and priorities
std::vector<LLPointer<LLViewerFetchedTexture> > image_list;
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@@ -1248,7 +1242,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
image_list.clear();
// Update fetch (decode)
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
@@ -1275,7 +1269,7 @@ void LLViewerTextureList::decodeAllImages(F32 max_time)
}
}
// Update fetch again
- for (image_priority_list_t::iterator iter = mImageList.begin();
+ for (image_list_t::iterator iter = mImageList.begin();
iter != mImageList.end(); )
{
LLViewerFetchedTexture* imagep = *iter++;
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index e4ebb7b0e8..2779ad9f91 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -33,7 +33,7 @@
#include "llviewertexture.h"
#include "llui.h"
#include <list>
-#include <set>
+#include <unordered_set>
#include "lluiimage.h"
const U32 LL_IMAGE_REZ_LOSSLESS_CUTOFF = 128;
@@ -115,8 +115,7 @@ public:
void init();
void shutdown();
void dump();
- void destroyGL(bool save_state = true);
- void restoreGL();
+ void destroyGL();
bool isInitialized() const {return mInitialized;}
void findTexturesByID(const LLUUID &image_id, std::vector<LLViewerFetchedTexture*> &output);
@@ -188,7 +187,7 @@ private:
LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation.
S8 texture_type = LLViewerTexture::FETCHED_TEXTURE,
LLGLint internal_format = 0,
- LLGLenum primary_format = 0,
+ LLGLenum primary_format = 0,
const LLUUID& force_id = LLUUID::null
);
@@ -211,7 +210,7 @@ private:
{ return getImage(image_id, f_type, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); }
public:
- typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t;
+ typedef std::unordered_set<LLPointer<LLViewerFetchedTexture> > image_list_t;
image_list_t mLoadingStreamList;
image_list_t mCreateTextureList;
image_list_t mCallbackList;
@@ -222,16 +221,19 @@ public:
bool mForceResetTextureStats;
+ // to make "for (auto& imagep : gTextureList)" work
+ const image_list_t::iterator begin() const { return mImageList.begin(); }
+ const image_list_t::iterator end() const { return mImageList.end(); }
+
private:
typedef std::map< LLTextureKey, LLPointer<LLViewerFetchedTexture> > uuid_map_t;
uuid_map_t mUUIDMap;
LLTextureKey mLastUpdateKey;
- typedef std::set < LLPointer<LLViewerFetchedTexture> > image_priority_list_t;
- image_priority_list_t mImageList;
+ image_list_t mImageList;
// simply holds on to LLViewerFetchedTexture references to stop them from being purged too soon
- std::set<LLPointer<LLViewerFetchedTexture> > mImagePreloads;
+ std::unordered_set<LLPointer<LLViewerFetchedTexture> > mImagePreloads;
bool mInitialized ;
LLFrameTimer mForceDecodeTimer;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index cfa12bf178..ef85d57416 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1827,10 +1827,8 @@ LLViewerWindow::LLViewerWindow(const Params& p)
mToolStored( NULL ),
mHideCursorPermanent( false ),
mCursorHidden(false),
- mIgnoreActivate( false ),
mResDirty(false),
mStatesDirty(false),
- mCurrResolutionIndex(0),
mProgressView(NULL)
{
// gKeyboard is still NULL, so it doesn't do LLWindowListener any good to
@@ -2402,7 +2400,7 @@ void LLViewerWindow::shutdownGL()
LLSelectMgr::getInstance()->cleanup();
LL_INFOS() << "Stopping GL during shutdown" << LL_ENDL;
- stopGL(false);
+ stopGL();
stop_glerror();
gGL.shutdown();
@@ -5715,7 +5713,7 @@ void LLViewerWindow::dumpState()
<< LL_ENDL;
}
-void LLViewerWindow::stopGL(bool save_state)
+void LLViewerWindow::stopGL()
{
//Note: --bao
//if not necessary, do not change the order of the function calls in this function.
@@ -5761,7 +5759,7 @@ void LLViewerWindow::stopGL(bool save_state)
gPostProcess->invalidate();
}
- gTextureList.destroyGL(save_state);
+ gTextureList.destroyGL();
stop_glerror();
gGLManager.mIsDisabled = true;
@@ -5778,6 +5776,14 @@ void LLViewerWindow::stopGL(bool save_state)
void LLViewerWindow::restoreGL(const std::string& progress_message)
{
+ llassert(false);
+ // DEPRECATED -- this is left over from when we would completely destroy and restore a GL context
+ // when switching from windowed to fullscreen. None of this machinery has been exercised in years
+ // and is unreliable. If we ever *do* have another use case where completely unloading and reloading
+ // everthing is necessary, requiring a viewer restart for that operation is a fine thing to do.
+ // -- davep
+
+
//Note: --bao
//if not necessary, do not change the order of the function calls in this function.
//if change something, make sure it will not break anything.
@@ -5790,8 +5796,6 @@ void LLViewerWindow::restoreGL(const std::string& progress_message)
initGLDefaults();
LLGLState::restoreGL();
- gTextureList.restoreGL();
-
// for future support of non-square pixels, and fonts that are properly stretched
//LLFontGL::destroyDefaultFonts();
initFonts();
@@ -5867,122 +5871,6 @@ void LLViewerWindow::checkSettings()
}
}
-void LLViewerWindow::restartDisplay(bool show_progress_bar)
-{
- LL_INFOS() << "Restaring GL" << LL_ENDL;
- stopGL();
- if (show_progress_bar)
- {
- restoreGL(LLTrans::getString("ProgressChangingResolution"));
- }
- else
- {
- restoreGL();
- }
-}
-
-bool LLViewerWindow::changeDisplaySettings(LLCoordScreen size, bool enable_vsync, bool show_progress_bar)
-{
- //bool was_maximized = gSavedSettings.getBOOL("WindowMaximized");
-
- //gResizeScreenTexture = true;
-
-
- //U32 fsaa = gSavedSettings.getU32("RenderFSAASamples");
- //U32 old_fsaa = mWindow->getFSAASamples();
-
- // if not maximized, use the request size
- if (!mWindow->getMaximized())
- {
- mWindow->setSize(size);
- }
-
- //if (fsaa == old_fsaa)
- {
- return true;
- }
-
-/*
-
- // Close floaters that don't handle settings change
- LLFloaterReg::hideInstance("snapshot");
-
- bool result_first_try = false;
- bool result_second_try = false;
-
- LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
- send_agent_pause();
- LL_INFOS() << "Stopping GL during changeDisplaySettings" << LL_ENDL;
- stopGL();
- mIgnoreActivate = true;
- LLCoordScreen old_size;
- LLCoordScreen old_pos;
- mWindow->getSize(&old_size);
-
- //mWindow->setFSAASamples(fsaa);
-
- result_first_try = mWindow->switchContext(false, size, disable_vsync);
- if (!result_first_try)
- {
- // try to switch back
- //mWindow->setFSAASamples(old_fsaa);
- result_second_try = mWindow->switchContext(false, old_size, disable_vsync);
-
- if (!result_second_try)
- {
- // we are stuck...try once again with a minimal resolution?
- send_agent_resume();
- mIgnoreActivate = false;
- return false;
- }
- }
- send_agent_resume();
-
- LL_INFOS() << "Restoring GL during resolution change" << LL_ENDL;
- if (show_progress_bar)
- {
- restoreGL(LLTrans::getString("ProgressChangingResolution"));
- }
- else
- {
- restoreGL();
- }
-
- if (!result_first_try)
- {
- LLSD args;
- args["RESX"] = llformat("%d",size.mX);
- args["RESY"] = llformat("%d",size.mY);
- LLNotificationsUtil::add("ResolutionSwitchFail", args);
- size = old_size; // for reshape below
- }
-
- bool success = result_first_try || result_second_try;
-
- if (success)
- {
- // maximize window if was maximized, else reposition
- if (was_maximized)
- {
- mWindow->maximize();
- }
- else
- {
- S32 windowX = gSavedSettings.getS32("WindowX");
- S32 windowY = gSavedSettings.getS32("WindowY");
-
- mWindow->setPosition(LLCoordScreen ( windowX, windowY ) );
- }
- }
-
- mIgnoreActivate = false;
- gFocusMgr.setKeyboardFocus(keyboard_focus);
-
- return success;
-
- */
-}
-
F32 LLViewerWindow::getWorldViewAspectRatio() const
{
F32 world_aspect = (F32)mWorldViewRectRaw.getWidth() / (F32)mWorldViewRectRaw.getHeight();
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 4a6b901b33..ba59ce4141 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -455,9 +455,7 @@ public:
// handle shutting down GL and bringing it back up
void requestResolutionUpdate();
void checkSettings();
- void restartDisplay(bool show_progress_bar);
- bool changeDisplaySettings(LLCoordScreen size, bool enable_vsync, bool show_progress_bar);
- bool getIgnoreDestroyWindow() { return mIgnoreActivate; }
+
F32 getWorldViewAspectRatio() const;
const LLVector2& getDisplayScale() const { return mDisplayScale; }
void calcDisplayScale();
@@ -471,7 +469,7 @@ private:
void switchToolByMask(MASK mask);
void destroyWindow();
void drawMouselookInstructions();
- void stopGL(bool save_state = true);
+ void stopGL();
void restoreGL(const std::string& progress_message = LLStringUtil::null);
void initFonts(F32 zoom_factor = 1.f);
void schedulePick(LLPickInfo& pick_info);
@@ -528,8 +526,6 @@ private:
std::string mOverlayTitle; // Used for special titles such as "Second Life - Special E3 2003 Beta"
- bool mIgnoreActivate;
-
std::string mInitAlert; // Window / GL initialization requires an alert
LLHandle<LLView> mWorldViewPlaceholder; // widget that spans the portion of screen dedicated to rendering the 3d world
@@ -542,7 +538,6 @@ private:
bool mResDirty;
bool mStatesDirty;
- U32 mCurrResolutionIndex;
std::unique_ptr<LLWindowListener> mWindowListener;
std::unique_ptr<LLViewerWindowListener> mViewerWindowListener;
diff --git a/indra/newview/llvlcomposition.cpp b/indra/newview/llvlcomposition.cpp
index ba255f2b24..f5f058a080 100644
--- a/indra/newview/llvlcomposition.cpp
+++ b/indra/newview/llvlcomposition.cpp
@@ -317,7 +317,7 @@ bool LLTerrainMaterials::makeMaterialsReady(bool boost, bool strict)
// static
bool LLTerrainMaterials::makeTextureReady(LLPointer<LLViewerFetchedTexture>& tex, bool boost)
{
- llassert(tex);
+ //llassert(tex); ??? maybe ok ???
if (!tex) { return false; }
if (tex->getDiscardLevel() < 0)
@@ -571,416 +571,6 @@ bool LLVLComposition::generateComposition()
return LLTerrainMaterials::generateMaterials();
}
-namespace
-{
- void prepare_fallback_image(LLImageRaw* raw_image)
- {
- raw_image->resize(BASE_SIZE, BASE_SIZE, 4);
- raw_image->fill(LLColor4U::white);
- }
-
- // Check if the raw image is loaded for this texture at a discard
- // level the minimap can use, and if not then try to get it loaded.
- bool prepare_raw_image(LLPointer<LLImageRaw>& raw_image, bool emissive, LLViewerFetchedTexture* tex, bool& delete_raw_post)
- {
- if (!tex)
- {
- if (!emissive)
- {
- prepare_fallback_image(raw_image);
- }
- else
- {
- llassert(!raw_image);
- raw_image = nullptr;
- }
- return true;
- }
- if (raw_image)
- {
- // Callback already initiated
- if (raw_image->getDataSize() > 0)
- {
- // Callback finished
- delete_raw_post = true;
- return true;
- }
- else
- {
- return false;
- }
- }
-
- raw_image = new LLImageRaw();
-
- S32 ddiscard = 0;
- {
- S32 min_dim = llmin(tex->getFullWidth(), tex->getFullHeight());
- while (min_dim > BASE_SIZE && ddiscard < MAX_DISCARD_LEVEL)
- {
- ddiscard++;
- min_dim /= 2;
- }
- }
-
- struct PendingImage
- {
- LLImageRaw* mRawImage;
- S32 mDesiredDiscard;
- LLUUID mTextureId;
- PendingImage(LLImageRaw* raw_image, S32 ddiscard, const LLUUID& texture_id)
- : mRawImage(raw_image)
- , mDesiredDiscard(ddiscard)
- , mTextureId(texture_id)
- {
- mRawImage->ref();
- }
- ~PendingImage()
- {
- mRawImage->unref();
- }
- };
- PendingImage* pending_image = new PendingImage(raw_image, ddiscard, tex->getID());
-
- loaded_callback_func cb = [](bool success, LLViewerFetchedTexture * src_vi, LLImageRaw * src, LLImageRaw * src_aux, S32 discard_level, bool is_final, void* userdata) {
- PendingImage* pending = (PendingImage*)userdata;
- // Owning LLVLComposition still exists
-
- // Assume mRawImage only used by single LLVLComposition for now
- const bool in_use_by_composition = pending->mRawImage->getNumRefs() > 1;
- llassert(pending->mRawImage->getNumRefs());
- llassert(pending->mRawImage->getNumRefs() <= 2);
- const bool needs_data = !pending->mRawImage->getDataSize();
- if (in_use_by_composition && needs_data)
- {
- if (success && pending->mDesiredDiscard == discard_level)
- {
- pending->mRawImage->resize(BASE_SIZE, BASE_SIZE, src->getComponents());
- pending->mRawImage->copyScaled(src);
- }
- else if (is_final)
- {
- prepare_fallback_image(pending->mRawImage);
- }
- }
-
- if (is_final) { delete pending; }
- };
- tex->setLoadedCallback(cb, ddiscard, true, false, pending_image, nullptr);
- tex->forceToSaveRawImage(ddiscard);
-
- return false;
- }
-};
-
-bool LLVLComposition::generateMinimapTileLand(const F32 x, const F32 y,
- const F32 width, const F32 height)
-{
- LL_PROFILE_ZONE_SCOPED
- llassert(mSurfacep);
- llassert(x >= 0.f);
- llassert(y >= 0.f);
-
- ///////////////////////////
- //
- // Generate raw data arrays for surface textures
- //
- //
-
- // These have already been validated by generateComposition.
- U8* st_data[ASSET_COUNT];
- S32 st_data_size[ASSET_COUNT]; // for debugging
-
- const bool use_textures = getMaterialType() != LLTerrainMaterials::Type::PBR;
- if (use_textures)
- {
- if (!makeTexturesReady(true, true)) { return false; }
- }
- else
- {
- if (!makeMaterialsReady(true, true)) { return false; }
- }
-
- for (S32 i = 0; i < ASSET_COUNT; i++)
- {
- if (mRawImages[i].isNull())
- {
- // Read back a raw image for this discard level, if it exists
- LLViewerFetchedTexture* tex;
- LLViewerFetchedTexture* tex_emissive; // Can be null
- bool has_base_color_factor;
- bool has_emissive_factor;
- bool has_alpha;
- LLColor3 base_color_factor;
- LLColor3 emissive_factor;
- if (use_textures)
- {
- tex = mDetailTextures[i];
- tex_emissive = nullptr;
- has_base_color_factor = false;
- has_emissive_factor = false;
- has_alpha = false;
- llassert(tex);
- }
- else
- {
- LLPointer<LLFetchedGLTFMaterial>& mat = mDetailRenderMaterials[i];
- tex = mat->mBaseColorTexture;
- tex_emissive = mat->mEmissiveTexture;
- base_color_factor = LLColor3(mat->mBaseColor);
- // *HACK: Treat alpha as black
- base_color_factor *= (mat->mBaseColor.mV[VW]);
- emissive_factor = mat->mEmissiveColor;
- has_base_color_factor = (base_color_factor.mV[VX] != 1.f ||
- base_color_factor.mV[VY] != 1.f ||
- base_color_factor.mV[VZ] != 1.f);
- has_emissive_factor = (emissive_factor.mV[VX] != 1.f ||
- emissive_factor.mV[VY] != 1.f ||
- emissive_factor.mV[VZ] != 1.f);
- has_alpha = mat->mAlphaMode != LLGLTFMaterial::ALPHA_MODE_OPAQUE;
- }
-
- if (!tex) { tex = LLViewerFetchedTexture::sWhiteImagep; }
-
- bool delete_raw_post = false;
- bool delete_raw_post_emissive = false;
- if (!prepare_raw_image(mRawImagesBaseColor[i], false, tex, delete_raw_post)) { return false; }
- if (tex_emissive && !prepare_raw_image(mRawImagesEmissive[i], true, tex_emissive, delete_raw_post_emissive)) { return false; }
- // tex_emissive can be null, and then will be ignored
-
- // In the simplest case, the minimap image is just the base color.
- // This will be replaced if we need to do any tinting/compositing.
- mRawImages[i] = mRawImagesBaseColor[i];
-
- // *TODO: This isn't quite right for PBR:
- // 1) It does not convert the color images from SRGB to linear
- // before mixing (which will always require copying the image).
- // 2) It mixes emissive and base color before mixing terrain
- // materials, but it should be the other way around
- // Long-term, we should consider a method that is more
- // maintainable. Shaders, perhaps? Bake shaders to textures?
- LLPointer<LLImageRaw> raw_emissive;
- if (tex_emissive)
- {
- raw_emissive = mRawImagesEmissive[i];
- if (has_emissive_factor ||
- tex_emissive->getWidth(tex_emissive->getRawImageLevel()) != BASE_SIZE ||
- tex_emissive->getHeight(tex_emissive->getRawImageLevel()) != BASE_SIZE ||
- tex_emissive->getComponents() != 4)
- {
- LLPointer<LLImageRaw> newraw_emissive = new LLImageRaw(BASE_SIZE, BASE_SIZE, 4);
- // Copy RGB, leave alpha alone (set to opaque by default)
- newraw_emissive->copy(mRawImagesEmissive[i]);
- if (has_emissive_factor)
- {
- newraw_emissive->tint(emissive_factor);
- }
- raw_emissive = newraw_emissive;
- }
- }
- if (has_base_color_factor ||
- raw_emissive ||
- has_alpha ||
- tex->getWidth(tex->getRawImageLevel()) != BASE_SIZE ||
- tex->getHeight(tex->getRawImageLevel()) != BASE_SIZE ||
- tex->getComponents() != 3)
- {
- LLPointer<LLImageRaw> newraw = new LLImageRaw(BASE_SIZE, BASE_SIZE, 3);
- if (has_alpha)
- {
- // Approximate the water underneath terrain alpha with solid water color
- newraw->clear(
- MAX_WATER_COLOR.mV[VX],
- MAX_WATER_COLOR.mV[VY],
- MAX_WATER_COLOR.mV[VZ],
- 255);
- }
- newraw->composite(mRawImagesBaseColor[i]);
- if (has_base_color_factor)
- {
- newraw->tint(base_color_factor);
- }
- // Apply emissive texture
- if (raw_emissive)
- {
- newraw->addEmissive(raw_emissive);
- }
-
- mRawImages[i] = newraw; // deletes old
- }
-
- if (delete_raw_post)
- {
- tex->destroyRawImage();
- }
- if (delete_raw_post_emissive)
- {
- tex_emissive->destroyRawImage();
- }
-
- // Remove intermediary image references
- mRawImagesBaseColor[i] = nullptr;
- mRawImagesEmissive[i] = nullptr;
- }
- st_data[i] = mRawImages[i]->getData();
- st_data_size[i] = mRawImages[i]->getDataSize();
- }
-
- ///////////////////////////////////////
- //
- // Generate and clamp x/y bounding box.
- //
- //
-
- S32 x_begin, y_begin, x_end, y_end;
- x_begin = (S32)(x * mScaleInv);
- y_begin = (S32)(y * mScaleInv);
- x_end = ll_round( (x + width) * mScaleInv );
- y_end = ll_round( (y + width) * mScaleInv );
-
- if (x_end > mWidth)
- {
- llassert(false);
- x_end = mWidth;
- }
- if (y_end > mWidth)
- {
- llassert(false);
- y_end = mWidth;
- }
-
-
- ///////////////////////////////////////////
- //
- // Generate target texture information, stride ratios.
- //
- //
-
- LLViewerTexture *texturep;
- U32 tex_width, tex_height, tex_comps;
- U32 tex_stride;
- F32 tex_x_scalef, tex_y_scalef;
- S32 tex_x_begin, tex_y_begin, tex_x_end, tex_y_end;
- F32 tex_x_ratiof, tex_y_ratiof;
-
- texturep = mSurfacep->getSTexture();
- tex_width = texturep->getWidth();
- tex_height = texturep->getHeight();
- tex_comps = texturep->getComponents();
- tex_stride = tex_width * tex_comps;
-
- U32 st_comps = 3;
- U32 st_width = BASE_SIZE;
- U32 st_height = BASE_SIZE;
-
- if (tex_comps != st_comps)
- {
- llassert(false);
- return false;
- }
-
- tex_x_scalef = (F32)tex_width / (F32)mWidth;
- tex_y_scalef = (F32)tex_height / (F32)mWidth;
- tex_x_begin = (S32)((F32)x_begin * tex_x_scalef);
- tex_y_begin = (S32)((F32)y_begin * tex_y_scalef);
- tex_x_end = (S32)((F32)x_end * tex_x_scalef);
- tex_y_end = (S32)((F32)y_end * tex_y_scalef);
-
- tex_x_ratiof = (F32)mWidth*mScale / (F32)tex_width;
- tex_y_ratiof = (F32)mWidth*mScale / (F32)tex_height;
-
- LLPointer<LLImageRaw> raw = new LLImageRaw(tex_width, tex_height, tex_comps);
- U8 *rawp = raw->getData();
-
- F32 st_x_stride, st_y_stride;
- st_x_stride = ((F32)st_width / (F32)mTexScaleX)*((F32)mWidth / (F32)tex_width);
- st_y_stride = ((F32)st_height / (F32)mTexScaleY)*((F32)mWidth / (F32)tex_height);
-
- llassert(st_x_stride > 0.f);
- llassert(st_y_stride > 0.f);
- ////////////////////////////////
- //
- // Iterate through the target texture, striding through the
- // subtextures and interpolating appropriately.
- //
- //
-
- F32 sti, stj;
- S32 st_offset;
- sti = (tex_x_begin * st_x_stride) - st_width*(llfloor((tex_x_begin * st_x_stride)/st_width));
- stj = (tex_y_begin * st_y_stride) - st_height*(llfloor((tex_y_begin * st_y_stride)/st_height));
-
- st_offset = (llfloor(stj * st_width) + llfloor(sti)) * st_comps;
- for (S32 j = tex_y_begin; j < tex_y_end; j++)
- {
- U32 offset = j * tex_stride + tex_x_begin * tex_comps;
- sti = (tex_x_begin * st_x_stride) - st_width*((U32)(tex_x_begin * st_x_stride)/st_width);
- for (S32 i = tex_x_begin; i < tex_x_end; i++)
- {
- S32 tex0, tex1;
- F32 composition = getValueScaled(i*tex_x_ratiof, j*tex_y_ratiof);
-
- tex0 = llfloor( composition );
- tex0 = llclamp(tex0, 0, 3);
- composition -= tex0;
- tex1 = tex0 + 1;
- tex1 = llclamp(tex1, 0, 3);
-
- st_offset = (lltrunc(sti) + lltrunc(stj)*st_width) * st_comps;
- for (U32 k = 0; k < tex_comps; k++)
- {
- // Linearly interpolate based on composition.
- if (st_offset >= st_data_size[tex0] || st_offset >= st_data_size[tex1])
- {
- // SJB: This shouldn't be happening, but does... Rounding error?
- //LL_WARNS() << "offset 0 [" << tex0 << "] =" << st_offset << " >= size=" << st_data_size[tex0] << LL_ENDL;
- //LL_WARNS() << "offset 1 [" << tex1 << "] =" << st_offset << " >= size=" << st_data_size[tex1] << LL_ENDL;
- }
- else
- {
- F32 a = *(st_data[tex0] + st_offset);
- F32 b = *(st_data[tex1] + st_offset);
- rawp[ offset ] = (U8)lltrunc( a + composition * (b - a) );
- }
- offset++;
- st_offset++;
- }
-
- sti += st_x_stride;
- if (sti >= st_width)
- {
- sti -= st_width;
- }
- }
-
- stj += st_y_stride;
- if (stj >= st_height)
- {
- stj -= st_height;
- }
- }
-
- if (!texturep->hasGLTexture())
- {
- texturep->createGLTexture(0, raw);
- }
- texturep->setSubImage(raw, tex_x_begin, tex_y_begin, tex_x_end - tex_x_begin, tex_y_end - tex_y_begin);
-
- // Un-boost detail textures (will get re-boosted if rendering in high detail)
- for (S32 i = 0; i < ASSET_COUNT; i++)
- {
- unboost_minimap_texture(mDetailTextures[i]);
- }
-
- // Un-boost textures for each detail material (will get re-boosted if rendering in high detail)
- for (S32 i = 0; i < ASSET_COUNT; i++)
- {
- unboost_minimap_material(mDetailMaterials[i]);
- }
-
- return true;
-}
-
F32 LLVLComposition::getStartHeight(S32 corner)
{
return mStartHeight[corner];
diff --git a/indra/newview/llvlcomposition.h b/indra/newview/llvlcomposition.h
index 61c35ade28..2637d77183 100644
--- a/indra/newview/llvlcomposition.h
+++ b/indra/newview/llvlcomposition.h
@@ -114,8 +114,6 @@ public:
// Viewer side hack to generate composition values
bool generateHeights(const F32 x, const F32 y, const F32 width, const F32 height);
bool generateComposition();
- // Generate texture from composition values.
- bool generateMinimapTileLand(const F32 x, const F32 y, const F32 width, const F32 height);
// Use these as indeces ito the get/setters below that use 'corner'
enum ECorner
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
index b665eb69a2..b95e43da8d 100644
--- a/indra/newview/llvoicechannel.cpp
+++ b/indra/newview/llvoicechannel.cpp
@@ -96,7 +96,7 @@ void LLVoiceChannel::setChannelInfo(const LLSD &channelInfo)
if (mState == STATE_NO_CHANNEL_INFO)
{
- if (mChannelInfo.isUndefined())
+ if (mChannelInfo.isUndefined() || !mChannelInfo.isMap() || mChannelInfo.size() == 0)
{
LLNotificationsUtil::add("VoiceChannelJoinFailed", mNotifyArgs);
LL_WARNS("Voice") << "Received empty channel info for channel " << mSessionName << LL_ENDL;
@@ -122,7 +122,7 @@ void LLVoiceChannel::onChange(EStatusType type, const LLSD& channelInfo, bool pr
{
LL_DEBUGS("Voice") << "Incoming channel info: " << channelInfo << LL_ENDL;
LL_DEBUGS("Voice") << "Current channel info: " << mChannelInfo << LL_ENDL;
- if (mChannelInfo.isUndefined())
+ if (mChannelInfo.isUndefined() || (mChannelInfo.isMap() && mChannelInfo.size() == 0))
{
mChannelInfo = channelInfo;
}
@@ -477,7 +477,7 @@ void LLVoiceChannelGroup::setChannelInfo(const LLSD& channelInfo)
if (mState == STATE_NO_CHANNEL_INFO)
{
- if(!mChannelInfo.isUndefined())
+ if(mChannelInfo.isDefined() && mChannelInfo.isMap())
{
setState(STATE_READY);
@@ -676,9 +676,9 @@ void LLVoiceChannelProximal::activate()
// we're connected to a non-spatial channel, so disconnect.
LLVoiceClient::getInstance()->leaveNonSpatialChannel();
}
+
LLVoiceClient::getInstance()->activateSpatialChannel(true);
LLVoiceChannel::activate();
-
}
void LLVoiceChannelProximal::onChange(EStatusType type, const LLSD& channelInfo, bool proximal)
@@ -751,7 +751,7 @@ void LLVoiceChannelProximal::deactivate()
{
setState(STATE_HUNG_UP);
}
-
+ LLVoiceClient::getInstance()->removeObserver(this);
LLVoiceClient::getInstance()->activateSpatialChannel(false);
}
@@ -907,7 +907,7 @@ void LLVoiceChannelP2P::setChannelInfo(const LLSD& channel_info)
}
mReceivedCall = true;
- if (!channel_info.isUndefined())
+ if (channel_info.isDefined() && channel_info.isMap())
{
mIncomingCallInterface = LLVoiceClient::getInstance()->getIncomingCallInterface(channel_info);
}
diff --git a/indra/newview/llvoiceclient.cpp b/indra/newview/llvoiceclient.cpp
index 74c6d611a8..67f41b2733 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -137,8 +137,9 @@ LLVoiceClient::LLVoiceClient(LLPumpIO *pump)
mSpatialVoiceModule(NULL),
mNonSpatialVoiceModule(NULL),
m_servicePump(NULL),
- mVoiceEffectEnabled(LLCachedControl<bool>(gSavedSettings, "VoiceMorphingEnabled", true)),
+ mVoiceEffectEnabled(LLCachedControl<bool>(gSavedSettings, "VoiceMorphingEnabled", false)),
mVoiceEffectDefault(LLCachedControl<std::string>(gSavedPerAccountSettings, "VoiceEffectDefault", "00000000-0000-0000-0000-000000000000")),
+ mVoiceEffectSupportNotified(false),
mPTTDirty(true),
mPTT(true),
mUsePTT(true),
@@ -569,11 +570,37 @@ void LLVoiceClient::setMicGain(F32 gain)
//------------------------------------------
// enable/disable voice features
+// static
+bool LLVoiceClient::onVoiceEffectsNotSupported(const LLSD &notification, const LLSD &response)
+{
+ S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
+ switch (option)
+ {
+ case 0: // "Okay"
+ gSavedSettings.setBOOL("VoiceMorphingEnabled", FALSE);
+ break;
+
+ case 1: // "Cancel"
+ break;
+
+ default:
+ llassert(0);
+ break;
+ }
+ return false;
+}
+
bool LLVoiceClient::voiceEnabled()
{
static LLCachedControl<bool> enable_voice_chat(gSavedSettings, "EnableVoiceChat");
static LLCachedControl<bool> cmd_line_disable_voice(gSavedSettings, "CmdLineDisableVoice");
- return enable_voice_chat && !cmd_line_disable_voice && !gNonInteractive;
+ bool enabled = enable_voice_chat && !cmd_line_disable_voice && !gNonInteractive;
+ if (enabled && !mVoiceEffectSupportNotified && getVoiceEffectEnabled() && !getVoiceEffectDefault().isNull())
+ {
+ LLNotificationsUtil::add("VoiceEffectsNotSupported", LLSD(), LLSD(), &LLVoiceClient::onVoiceEffectsNotSupported);
+ mVoiceEffectSupportNotified = true;
+ }
+ return enabled;
}
void LLVoiceClient::setVoiceEnabled(bool enabled)
@@ -812,7 +839,7 @@ std::string LLVoiceClient::sipURIFromID(const LLUUID &id)
LLVoiceEffectInterface* LLVoiceClient::getVoiceEffectInterface() const
{
- return getVoiceEffectEnabled() ? dynamic_cast<LLVoiceEffectInterface*>(mSpatialVoiceModule) : NULL;
+ return NULL;
}
///////////////////
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index 7411df1693..9ae18b315c 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -508,6 +508,8 @@ public:
protected:
+ static bool onVoiceEffectsNotSupported(const LLSD &notification, const LLSD &response);
+
LLVoiceModuleInterface* mSpatialVoiceModule;
LLVoiceModuleInterface* mNonSpatialVoiceModule;
LLSD mSpatialCredentials; // used to store spatial credentials for vivox
@@ -519,6 +521,7 @@ protected:
LLCachedControl<bool> mVoiceEffectEnabled;
LLCachedControl<std::string> mVoiceEffectDefault;
+ bool mVoiceEffectSupportNotified;
bool mPTTDirty;
bool mPTT;
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index 17fd85f280..371b0df860 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -5107,25 +5107,31 @@ void LLVivoxVoiceClient::processChannels(bool process)
bool LLVivoxVoiceClient::isCurrentChannel(const LLSD &channelInfo)
{
- if (!mProcessChannels || (channelInfo["voice_server_type"].asString() != VIVOX_VOICE_SERVER_TYPE))
+ if (!mProcessChannels || (channelInfo.has("voice_server_type") && channelInfo["voice_server_type"].asString() != VIVOX_VOICE_SERVER_TYPE))
{
return false;
}
- if (mAudioSession)
+ // favor the next audio session, as that's the one we're bringing up.
+ sessionStatePtr_t session = mNextAudioSession;
+ if (!session)
+ {
+ session = mAudioSession;
+ }
+ if (session)
{
if (!channelInfo["session_handle"].asString().empty())
{
- return mAudioSession->mHandle == channelInfo["session_handle"].asString();
+ return session->mHandle == channelInfo["session_handle"].asString();
}
- return channelInfo["channel_uri"].asString() == mAudioSession->mSIPURI;
+ return channelInfo["channel_uri"].asString() == session->mSIPURI;
}
return false;
}
bool LLVivoxVoiceClient::compareChannels(const LLSD& channelInfo1, const LLSD& channelInfo2)
{
- return (channelInfo1["voice_server_type"] == VIVOX_VOICE_SERVER_TYPE) &&
- (channelInfo1["voice_server_type"] == channelInfo2["voice_server_type"]) &&
+ return (!channelInfo1.has("voice_server_type") || (channelInfo1["voice_server_type"] == VIVOX_VOICE_SERVER_TYPE)) &&
+ (!channelInfo2.has("voice_server_type") || (channelInfo2["voice_server_type"] == VIVOX_VOICE_SERVER_TYPE)) &&
(channelInfo1["channel_uri"] == channelInfo2["channel_uri"]);
}
diff --git a/indra/newview/llvoicewebrtc.cpp b/indra/newview/llvoicewebrtc.cpp
index 661b4f7ef1..8049bb7a73 100644
--- a/indra/newview/llvoicewebrtc.cpp
+++ b/indra/newview/llvoicewebrtc.cpp
@@ -24,7 +24,6 @@
* $/LicenseInfo$
*/
#include <algorithm>
-#include <format>
#include "llvoicewebrtc.h"
#include "llsdutil.h"
@@ -86,7 +85,7 @@ namespace {
const F32 VOLUME_SCALE_WEBRTC = 0.01f;
const F32 LEVEL_SCALE_WEBRTC = 0.008f;
- const F32 SPEAKING_AUDIO_LEVEL = 0.35;
+ const F32 SPEAKING_AUDIO_LEVEL = 0.30;
static const std::string REPORTED_VOICE_SERVER_TYPE = "Secondlife WebRTC Gateway";
@@ -1486,14 +1485,10 @@ void LLWebRTCVoiceClient::setMicGain(F32 gain)
if (gain != mMicGain)
{
mMicGain = gain;
- sessionState::for_each(boost::bind(predSetMicGain, _1, gain));
+ mWebRTCDeviceInterface->setPeerConnectionGain(gain);
}
}
-void LLWebRTCVoiceClient::predSetMicGain(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 gain)
-{
- session->setMicGain(gain);
-}
void LLWebRTCVoiceClient::setVoiceEnabled(bool enabled)
{
@@ -1692,7 +1687,6 @@ std::map<std::string, LLWebRTCVoiceClient::sessionState::ptr_t> LLWebRTCVoiceCli
LLWebRTCVoiceClient::sessionState::sessionState() :
mHangupOnLastLeave(false),
mNotifyOnFirstJoin(false),
- mMicGain(1.0),
mMuted(false),
mSpeakerVolume(1.0),
mShuttingDown(false)
@@ -1737,15 +1731,6 @@ void LLWebRTCVoiceClient::sessionState::setMuteMic(bool muted)
}
}
-void LLWebRTCVoiceClient::sessionState::setMicGain(F32 gain)
-{
- mMicGain = gain;
- for (auto &connection : mWebRTCConnections)
- {
- connection->setMicGain(gain);
- }
-}
-
void LLWebRTCVoiceClient::sessionState::setSpeakerVolume(F32 volume)
{
mSpeakerVolume = volume;
@@ -1850,7 +1835,6 @@ LLWebRTCVoiceClient::sessionStatePtr_t LLWebRTCVoiceClient::addSession(const std
LL_DEBUGS("Voice") << "adding new session with channel: " << channel_id << LL_ENDL;
session->setMuteMic(mMuteMic);
- session->setMicGain(mMicGain);
session->setSpeakerVolume(mSpeakerVolume);
sessionState::addSession(channel_id, session);
@@ -1976,7 +1960,6 @@ bool LLWebRTCVoiceClient::estateSessionState::processConnectionStates()
connectionPtr_t connection(new LLVoiceWebRTCSpatialConnection(neighbor, INVALID_PARCEL_ID, mChannelID));
mWebRTCConnections.push_back(connection);
- connection->setMicGain(mMicGain);
connection->setMuteMic(mMuted);
connection->setSpeakerVolume(mSpeakerVolume);
}
@@ -2106,7 +2089,6 @@ LLVoiceWebRTCConnection::LLVoiceWebRTCConnection(const LLUUID &regionID, const s
mShutDown(false),
mIceCompleted(false),
mSpeakerVolume(0.0),
- mMicGain(0.0),
mOutstandingRequests(0),
mChannelID(channelID),
mRegionID(regionID),
@@ -2369,15 +2351,6 @@ void LLVoiceWebRTCConnection::setMuteMic(bool muted)
}
}
-void LLVoiceWebRTCConnection::setMicGain(F32 gain)
-{
- mMicGain = gain;
- if (mWebRTCAudioInterface)
- {
- mWebRTCAudioInterface->setSendVolume(gain);
- }
-}
-
void LLVoiceWebRTCConnection::setSpeakerVolume(F32 volume)
{
mSpeakerVolume = volume;
@@ -2677,7 +2650,6 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
// this connection.
mWebRTCAudioInterface->setMute(mMuted);
mWebRTCAudioInterface->setReceiveVolume(mSpeakerVolume);
- mWebRTCAudioInterface->setSendVolume(mMicGain);
LLWebRTCVoiceClient::getInstance()->OnConnectionEstablished(mChannelID, mRegionID);
setVoiceConnectionState(VOICE_STATE_WAIT_FOR_DATA_CHANNEL);
break;
diff --git a/indra/newview/llvoicewebrtc.h b/indra/newview/llvoicewebrtc.h
index c341ea6c94..480a7897cd 100644
--- a/indra/newview/llvoicewebrtc.h
+++ b/indra/newview/llvoicewebrtc.h
@@ -282,7 +282,6 @@ public:
virtual void sendData(const std::string &data);
void setMuteMic(bool muted);
- void setMicGain(F32 volume);
void setSpeakerVolume(F32 volume);
void setUserVolume(const LLUUID& id, F32 volume);
@@ -303,7 +302,6 @@ public:
std::string mName;
bool mMuted; // this session is muted.
- F32 mMicGain; // gain for this session.
F32 mSpeakerVolume; // volume for this session.
bool mShuttingDown;
@@ -382,7 +380,6 @@ public:
static void predSendData(const LLWebRTCVoiceClient::sessionStatePtr_t &session, const std::string& spatial_data);
static void predUpdateOwnVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 audio_level);
static void predSetMuteMic(const LLWebRTCVoiceClient::sessionStatePtr_t &session, bool mute);
- static void predSetMicGain(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 volume);
static void predSetSpeakerVolume(const LLWebRTCVoiceClient::sessionStatePtr_t &session, F32 volume);
static void predShutdownSession(const LLWebRTCVoiceClient::sessionStatePtr_t &session);
static void predSetUserMute(const LLWebRTCVoiceClient::sessionStatePtr_t &session, const LLUUID& id, bool mute);
@@ -607,7 +604,6 @@ class LLVoiceWebRTCConnection :
void processIceUpdatesCoro();
virtual void setMuteMic(bool muted);
- virtual void setMicGain(F32 volume);
virtual void setSpeakerVolume(F32 volume);
void setUserVolume(const LLUUID& id, F32 volume);
@@ -686,7 +682,6 @@ class LLVoiceWebRTCConnection :
std::string mRemoteChannelSDP;
bool mMuted;
- F32 mMicGain;
F32 mSpeakerVolume;
bool mShutDown;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index de62256134..7ca3fbd1ad 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -851,19 +851,9 @@ void LLVOVolume::updateTextureVirtualSize(bool forced)
if (mSculptTexture.notNull())
{
- mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(),
- (S32)LLGLTexture::BOOST_SCULPTED));
mSculptTexture->setForSculpt() ;
- if(!mSculptTexture->isCachedRawImageReady())
- {
- S32 lod = llmin(mLOD, 3);
- F32 lodf = ((F32)(lod + 1.0f)/4.f);
- F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ;
- mSculptTexture->addTextureStats(2.f * tex_size * tex_size, false);
- }
-
- S32 texture_discard = mSculptTexture->getCachedRawImageLevel(); //try to match the texture
+ S32 texture_discard = mSculptTexture->getRawImageLevel(); //try to match the texture
S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ;
if (texture_discard >= 0 && //texture has some data available
@@ -1159,7 +1149,9 @@ void LLVOVolume::updateSculptTexture()
LLUUID id = sculpt_params->getSculptTexture();
if (id.notNull())
{
- mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+ mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true, LLGLTexture::BOOST_SCULPTED, LLViewerTexture::LOD_TEXTURE);
+ mSculptTexture->forceToSaveRawImage(0, F32_MAX);
+ mSculptTexture->addTextureStats(256.f*256.f);
}
mSkinInfoUnavaliable = false;
@@ -1252,8 +1244,22 @@ void LLVOVolume::sculpt()
S8 sculpt_components = 0;
const U8* sculpt_data = NULL;
- S32 discard_level = mSculptTexture->getCachedRawImageLevel() ;
- LLImageRaw* raw_image = mSculptTexture->getCachedRawImage() ;
+ S32 discard_level = mSculptTexture->getRawImageLevel() ;
+ LLImageRaw* raw_image = mSculptTexture->getRawImage() ;
+
+ if (!raw_image)
+ {
+ raw_image = mSculptTexture->getSavedRawImage();
+ S32 discard_level = mSculptTexture->getSavedRawImageLevel();
+ }
+
+ if (!raw_image)
+ {
+ // last resort, read back from GL
+ mSculptTexture->readbackRawImage();
+ raw_image = mSculptTexture->getRawImage();
+ discard_level = mSculptTexture->getRawImageLevel();
+ }
S32 max_discard = mSculptTexture->getMaxDiscardLevel();
if (discard_level > max_discard)
@@ -1310,8 +1316,6 @@ void LLVOVolume::sculpt()
if(!raw_image)
{
- llassert(discard_level < 0) ;
-
sculpt_width = 0;
sculpt_height = 0;
sculpt_data = NULL ;
@@ -2039,6 +2043,7 @@ bool LLVOVolume::updateGeometry(LLDrawable *drawable)
if (mDrawable->isState(LLDrawable::REBUILD_RIGGED))
{
+ LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("rebuild rigged");
updateRiggedVolume(false);
genBBoxes(false);
mDrawable->clearState(LLDrawable::REBUILD_RIGGED);
diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp
index 34040e1aca..2bc849a74f 100644
--- a/indra/newview/llvowater.cpp
+++ b/indra/newview/llvowater.cpp
@@ -59,7 +59,6 @@ LLVOWater::LLVOWater(const LLUUID &id,
mbCanSelect = false;
setScale(LLVector3(256.f, 256.f, 0.f)); // Hack for setting scale for bounding boxes/visibility.
- mUseTexture = true;
mIsEdgePatch = false;
}
@@ -101,14 +100,7 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline)
LLDrawPoolWater *pool = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER);
- if (mUseTexture)
- {
- mDrawable->setNumFaces(1, pool, mRegionp->getLand().getWaterTexture());
- }
- else
- {
- mDrawable->setNumFaces(1, pool, LLWorld::getInstance()->getDefaultWaterTexture());
- }
+ mDrawable->setNumFaces(1, pool, LLWorld::getInstance()->getDefaultWaterTexture());
return mDrawable;
}
@@ -249,11 +241,6 @@ void setVecZ(LLVector3& v)
v.mV[VZ] = 1;
}
-void LLVOWater::setUseTexture(const bool use_texture)
-{
- mUseTexture = use_texture;
-}
-
void LLVOWater::setIsEdgePatch(const bool edge_patch)
{
mIsEdgePatch = edge_patch;
diff --git a/indra/newview/llvowater.h b/indra/newview/llvowater.h
index adae86691a..ba3da510c4 100644
--- a/indra/newview/llvowater.h
+++ b/indra/newview/llvowater.h
@@ -70,13 +70,10 @@ public:
/*virtual*/ bool isActive() const; // Whether this object needs to do an idleUpdate.
- void setUseTexture(const bool use_texture);
void setIsEdgePatch(const bool edge_patch);
- bool getUseTexture() const { return mUseTexture; }
bool getIsEdgePatch() const { return mIsEdgePatch; }
protected:
- bool mUseTexture;
bool mIsEdgePatch;
S32 mRenderType;
};
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 2eadea20ef..6470c81aaa 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -961,7 +961,6 @@ void LLWorld::updateWaterObjects()
if (!getRegionFromHandle(region_handle))
{ // No region at that area, so make water
LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion());
- waterp->setUseTexture(false);
waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
y + rwidth/2,
256.f + water_height));
@@ -1015,7 +1014,6 @@ void LLWorld::updateWaterObjects()
mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER,
gAgent.getRegion());
waterp = mEdgeWaterObjects[dir];
- waterp->setUseTexture(false);
waterp->setIsEdgePatch(true);
gPipeline.createObject(waterp);
}
diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp
index e226fd4748..d8ea2b884f 100644
--- a/indra/newview/llworldmipmap.cpp
+++ b/indra/newview/llworldmipmap.cpp
@@ -178,6 +178,7 @@ LLPointer<LLViewerFetchedTexture> LLWorldMipmap::getObjectsTile(U32 grid_x, U32
}
}
+//static
LLPointer<LLViewerFetchedTexture> LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 grid_y, S32 level)
{
// Get the grid coordinates
diff --git a/indra/newview/llworldmipmap.h b/indra/newview/llworldmipmap.h
index ab98b55b72..907f24d1e7 100644
--- a/indra/newview/llworldmipmap.h
+++ b/indra/newview/llworldmipmap.h
@@ -74,11 +74,13 @@ public:
// Convert world coordinates to mipmap grid coordinates at a given level
static void globalToMipmap(F64 global_x, F64 global_y, S32 level, U32* grid_x, U32* grid_y);
+ // Load the relevant tile from S3
+ static LLPointer<LLViewerFetchedTexture> loadObjectsTile(U32 grid_x, U32 grid_y, S32 level);
+
private:
// Get a handle (key) from grid coordinates
U64 convertGridToHandle(U32 grid_x, U32 grid_y) { return to_region_handle(grid_x * REGION_WIDTH_UNITS, grid_y * REGION_WIDTH_UNITS); }
- // Load the relevant tile from S3
- LLPointer<LLViewerFetchedTexture> loadObjectsTile(U32 grid_x, U32 grid_y, S32 level);
+
// Clear a level from its "missing" tiles
void cleanMissedTilesFromLevel(S32 level);
diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp
index 1148e81fd5..7c7bd98bcd 100644
--- a/indra/newview/llxmlrpclistener.cpp
+++ b/indra/newview/llxmlrpclistener.cpp
@@ -39,12 +39,6 @@
#include <boost/scoped_ptr.hpp>
#include <boost/range.hpp> // boost::begin(), boost::end()
-#ifdef LL_USESYSTEMLIBS
-#include <xmlrpc.h>
-#else
-#include <xmlrpc-epi/xmlrpc.h>
-#endif
-
#include "curl/curl.h"
// other Linden headers
@@ -178,13 +172,6 @@ public:
static const CURLcodeMapper sCURLcodeMapper;
-LLXMLRPCListener::LLXMLRPCListener(const std::string& pumpname):
- mBoundListener(LLEventPumps::instance().
- obtain(pumpname).
- listen("LLXMLRPCListener", boost::bind(&LLXMLRPCListener::process, this, _1)))
-{
-}
-
/**
* Capture an outstanding LLXMLRPCTransaction and poll it periodically until
* done.
@@ -213,38 +200,20 @@ public:
mMethod(command["method"]),
mReplyPump(command["reply"])
{
- // LL_ERRS if any of these are missing
- const char* required[] = { "uri", "method", "reply" };
- // optional: "options" (array of string)
- // Validate the request
- std::set<std::string> missing;
- for (const char** ri = boost::begin(required); ri != boost::end(required); ++ri)
+ // LL_ERRS if any of these keys are missing or empty
+ if (mUri.empty() || mMethod.empty() || mReplyPump.empty())
{
- // If the command does not contain this required entry, add it to 'missing'.
- if (! command.has(*ri))
- {
- missing.insert(*ri);
- }
- }
- if (! missing.empty())
- {
- LL_ERRS("LLXMLRPCListener") << mMethod << " request missing params: ";
- const char* separator = "";
- for (std::set<std::string>::const_iterator mi(missing.begin()), mend(missing.end());
- mi != mend; ++mi)
- {
- LL_CONT << separator << *mi;
- separator = ", ";
- }
- LL_CONT << LL_ENDL;
+ LL_ERRS("LLXMLRPCListener")
+ << "Some params are missing: "
+ << "reply: '" << mReplyPump << "', "
+ << "method: '" << mMethod << "', "
+ << "uri: '" << mUri << "'"
+ << LL_ENDL;
}
- // Build the XMLRPC request.
- XMLRPC_REQUEST request = XMLRPC_RequestNew();
- XMLRPC_RequestSetMethodName(request, mMethod.c_str());
- XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
- XMLRPC_VALUE xparams = XMLRPC_CreateVector(NULL, xmlrpc_vector_struct);
- LLSD params(command["params"]);
+ LLSD request_params = LLSD::emptyMap();
+
+ LLSD params = command.get("params");
if (params.isMap())
{
for (LLSD::map_const_iterator pi(params.beginMap()), pend(params.endMap());
@@ -252,44 +221,33 @@ public:
{
std::string name(pi->first);
LLSD param(pi->second);
- if (param.isString())
+ switch (param.type())
{
- XMLRPC_VectorAppendString(xparams, name.c_str(), param.asString().c_str(), 0);
- }
- else if (param.isInteger() || param.isBoolean())
- {
- XMLRPC_VectorAppendInt(xparams, name.c_str(), param.asInteger());
- }
- else if (param.isReal())
- {
- XMLRPC_VectorAppendDouble(xparams, name.c_str(), param.asReal());
- }
- else
- {
- LL_ERRS("LLXMLRPCListener") << mMethod << " request param "
- << name << " has unknown type: " << param << LL_ENDL;
+ case LLSD::TypeString:
+ case LLSD::TypeInteger:
+ case LLSD::TypeReal:
+ request_params.insert(name, param);
+ break;
+ case LLSD::TypeBoolean:
+ request_params.insert(name, param.asInteger());
+ break;
+ default:
+ LL_ERRS("LLXMLRPCListener") << mMethod
+ << " request param '" << name << "' has unknown type: " << param << LL_ENDL;
}
}
}
- LLSD options(command["options"]);
+
+ LLSD options = command.get("options");
if (options.isArray())
{
- XMLRPC_VALUE xoptions = XMLRPC_CreateVector("options", xmlrpc_vector_array);
- for (LLSD::array_const_iterator oi(options.beginArray()), oend(options.endArray());
- oi != oend; ++oi)
- {
- XMLRPC_VectorAppendString(xoptions, NULL, oi->asString().c_str(), 0);
- }
- XMLRPC_AddValueToVector(xparams, xoptions);
+ request_params.insert("options", options);
}
- XMLRPC_RequestSetData(request, xparams);
- mTransaction.reset(new LLXMLRPCTransaction(mUri, request, true, command.has("http_params")? LLSD(command["http_params"]) : LLSD()));
+ LLSD http_params = command.get("http_params");
+ mTransaction.reset(new LLXMLRPCTransaction(mUri, mMethod, request_params, http_params));
mPreviousStatus = mTransaction->status(NULL);
- // Free the XMLRPC_REQUEST object and the attached data values.
- XMLRPC_RequestFree(request, 1);
-
// Now ensure that we get regular callbacks to poll for completion.
mBoundListener =
LLEventPumps::instance().
@@ -323,7 +281,7 @@ public:
data["error"] = "";
data["transfer_rate"] = 0.0;
LLEventPump& replyPump(LLEventPumps::instance().obtain(mReplyPump));
- if (! done)
+ if (!done)
{
// Not done yet, carry on.
if (status == LLXMLRPCTransaction::StatusDownloading
@@ -367,10 +325,8 @@ public:
// Given 'message', need we care?
if (status == LLXMLRPCTransaction::StatusComplete)
{
- // Success! Parse data.
- std::string status_string(data["status"]);
- data["responses"] = parseResponse(status_string);
- data["status"] = status_string;
+ // Success! Retrieve response data.
+ data["responses"] = mTransaction->response();
}
// whether successful or not, send reply on requested LLEventPump
@@ -388,159 +344,6 @@ public:
}
private:
- /// Derived from LLUserAuth::parseResponse() and parseOptionInto()
- LLSD parseResponse(std::string& status_string)
- {
- // Extract every member into data["responses"] (a map of string
- // values).
- XMLRPC_REQUEST response = mTransaction->response();
- if (! response)
- {
- LL_DEBUGS("LLXMLRPCListener") << "No response" << LL_ENDL;
- return LLSD();
- }
-
- XMLRPC_VALUE param = XMLRPC_RequestGetData(response);
- if (! param)
- {
- LL_DEBUGS("LLXMLRPCListener") << "Response contains no data" << LL_ENDL;
- return LLSD();
- }
-
- // Now, parse everything
- return parseValues(status_string, "", param);
- }
-
- LLSD parseValue(std::string& status_string, const std::string& key, const std::string& key_pfx, XMLRPC_VALUE param)
- {
- LLSD response;
-
- XMLRPC_VALUE_TYPE_EASY type = XMLRPC_GetValueTypeEasy(param);
- switch (type)
- {
- case xmlrpc_type_empty:
- LL_INFOS("LLXMLRPCListener") << "Empty result for key " << key_pfx << key << LL_ENDL;
- break;
- case xmlrpc_type_base64:
- {
- S32 len = XMLRPC_GetValueStringLen(param);
- const char* buf = XMLRPC_GetValueBase64(param);
- if ((len > 0) && buf)
- {
- // During implementation this code was not tested
- // If you encounter this, please make sure this is correct,
- // then remove llassert
- llassert(0);
-
- LLSD::Binary data;
- data.resize(len);
- memcpy((void*)&data[0], (void*)buf, len);
- response = data;
- }
- else
- {
- LL_WARNS("LLXMLRPCListener") << "Potentially malformed xmlrpc_type_base64 for key "
- << key_pfx << key << LL_ENDL;
- }
- break;
- }
- case xmlrpc_type_boolean:
- {
- response = LLSD::Boolean(XMLRPC_GetValueBoolean(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
- break;
- }
- case xmlrpc_type_datetime:
- {
- std::string iso8601_date(XMLRPC_GetValueDateTime_ISO8601(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << iso8601_date << LL_ENDL;
- response = LLSD::Date(iso8601_date);
- break;
- }
- case xmlrpc_type_double:
- {
- response = LLSD::Real(XMLRPC_GetValueDouble(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
- break;
- }
- case xmlrpc_type_int:
- {
- response = LLSD::Integer(XMLRPC_GetValueInt(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
- break;
- }
- case xmlrpc_type_string:
- {
- response = LLSD::String(XMLRPC_GetValueString(param));
- LL_DEBUGS("LLXMLRPCListener") << "val: " << response << LL_ENDL;
- break;
- }
- case xmlrpc_type_mixed:
- case xmlrpc_type_array:
- {
- // We expect this to be an array of submaps. Walk the array,
- // recursively parsing each submap and collecting them.
- LLSD array;
- int i = 0; // for descriptive purposes
- for (XMLRPC_VALUE row = XMLRPC_VectorRewind(param); row;
- row = XMLRPC_VectorNext(param), ++i)
- {
- // Recursive call. For the lower-level key_pfx, if 'key'
- // is "foo", pass "foo[0]:", then "foo[1]:", etc. In the
- // nested call, a subkey "bar" will then be logged as
- // "foo[0]:bar", and so forth.
- // Parse the scalar subkey/value pairs from this array
- // entry into a temp submap. Collect such submaps in 'array'.
-
- array.append(parseValue(status_string, "",
- STRINGIZE(key_pfx << key << '[' << i << "]:"),
- row));
- }
- // Having collected an 'array' of 'submap's, insert that whole
- // 'array' as the value of this 'key'.
- response = array;
- break;
- }
- case xmlrpc_type_struct:
- {
- response = parseValues(status_string,
- STRINGIZE(key_pfx << key << ':'),
- param);
- break;
- }
- case xmlrpc_type_none: // Not expected
- default:
- // whoops - unrecognized type
- LL_WARNS("LLXMLRPCListener") << "Unhandled xmlrpc type " << type << " for key "
- << key_pfx << key << LL_ENDL;
- response = STRINGIZE("<bad XMLRPC type " << type << '>');
- status_string = "BadType";
- }
- return response;
- }
-
- /**
- * Parse key/value pairs from a given XMLRPC_VALUE into an LLSD map.
- * @param key_pfx Used to describe a given key in log messages. At top
- * level, pass "". When parsing an options array, pass the top-level key
- * name of the array plus the index of the array entry; to this we'll
- * append the subkey of interest.
- * @param param XMLRPC_VALUE iterator. At top level, pass
- * XMLRPC_RequestGetData(XMLRPC_REQUEST).
- */
- LLSD parseValues(std::string& status_string, const std::string& key_pfx, XMLRPC_VALUE param)
- {
- LLSD responses;
- for (XMLRPC_VALUE current = XMLRPC_VectorRewind(param); current;
- current = XMLRPC_VectorNext(param))
- {
- std::string key(XMLRPC_GetValueID(current));
- LL_DEBUGS("LLXMLRPCListener") << "key: " << key_pfx << key << LL_ENDL;
- responses.insert(key, parseValue(status_string, key, key_pfx, current));
- }
- return responses;
- }
-
const LLReqID mReqID;
const std::string mUri;
const std::string mMethod;
@@ -550,11 +353,18 @@ private:
LLXMLRPCTransaction::EStatus mPreviousStatus; // To detect state changes.
};
-bool LLXMLRPCListener::process(const LLSD& command)
+LLXMLRPCListener::LLXMLRPCListener(const std::string& pumpname)
+: mBoundListener(LLEventPumps::instance().obtain(pumpname).listen
+(
+ "LLXMLRPCListener",
+ [&](const LLSD& command) -> bool
+ {
+ // Allocate a new heap Poller, but do not save a pointer to it. Poller
+ // will check its own status and free itself on completion of the request.
+ (new Poller(command));
+ // Conventional event listener return
+ return false;
+ }
+))
{
- // Allocate a new heap Poller, but do not save a pointer to it. Poller
- // will check its own status and free itself on completion of the request.
- (new Poller(command));
- // conventional event listener return
- return false;
}
diff --git a/indra/newview/llxmlrpclistener.h b/indra/newview/llxmlrpclistener.h
index aaed98eec5..fd75acb8b1 100644
--- a/indra/newview/llxmlrpclistener.h
+++ b/indra/newview/llxmlrpclistener.h
@@ -42,9 +42,6 @@ public:
/// Specify the pump name on which to listen
LLXMLRPCListener(const std::string& pumpname);
- /// Handle request events on the event pump specified at construction time
- bool process(const LLSD& command);
-
private:
LLTempBoundListener mBoundListener;
};
diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp
index ec6e22cd7a..55622fb6b7 100644
--- a/indra/newview/llxmlrpctransaction.cpp
+++ b/indra/newview/llxmlrpctransaction.cpp
@@ -42,22 +42,11 @@
#include "bufferarray.h"
#include "llversioninfo.h"
#include "llviewercontrol.h"
+#include "llxmlnode.h"
#include "stringize.h"
// Have to include these last to avoid queue redefinition!
-#ifdef LL_USESYSTEMLIBS
-#include <xmlrpc.h>
-#else
-#include <xmlrpc-epi/xmlrpc.h>
-#endif
-// <xmlrpc-epi/queue.h> contains a harmful #define queue xmlrpc_queue. This
-// breaks any use of std::queue. Ditch that #define: if any of our code wants
-// to reference xmlrpc_queue, let it reference it directly.
-#if defined(queue)
-#undef queue
-#endif
-
#include "llappviewer.h"
#include "lltrans.h"
@@ -75,111 +64,6 @@ namespace boost
// nothing.
static LLXMLRPCListener listener("LLXMLRPCTransaction");
-LLXMLRPCValue LLXMLRPCValue::operator[](const char* id) const
-{
- return LLXMLRPCValue(XMLRPC_VectorGetValueWithID(mV, id));
-}
-
-std::string LLXMLRPCValue::asString() const
-{
- const char* s = XMLRPC_GetValueString(mV);
- return s ? s : "";
-}
-
-int LLXMLRPCValue::asInt() const { return XMLRPC_GetValueInt(mV); }
-bool LLXMLRPCValue::asBool() const { return XMLRPC_GetValueBoolean(mV) != 0; }
-double LLXMLRPCValue::asDouble() const { return XMLRPC_GetValueDouble(mV); }
-
-LLXMLRPCValue LLXMLRPCValue::rewind()
-{
- return LLXMLRPCValue(XMLRPC_VectorRewind(mV));
-}
-
-LLXMLRPCValue LLXMLRPCValue::next()
-{
- return LLXMLRPCValue(XMLRPC_VectorNext(mV));
-}
-
-bool LLXMLRPCValue::isValid() const
-{
- return mV != NULL;
-}
-
-LLXMLRPCValue LLXMLRPCValue::createArray()
-{
- return LLXMLRPCValue(XMLRPC_CreateVector(NULL, xmlrpc_vector_array));
-}
-
-LLXMLRPCValue LLXMLRPCValue::createStruct()
-{
- return LLXMLRPCValue(XMLRPC_CreateVector(NULL, xmlrpc_vector_struct));
-}
-
-
-void LLXMLRPCValue::append(LLXMLRPCValue& v)
-{
- XMLRPC_AddValueToVector(mV, v.mV);
-}
-
-void LLXMLRPCValue::appendString(const std::string& v)
-{
- XMLRPC_AddValueToVector(mV, XMLRPC_CreateValueString(NULL, v.c_str(), 0));
-}
-
-void LLXMLRPCValue::appendInt(int v)
-{
- XMLRPC_AddValueToVector(mV, XMLRPC_CreateValueInt(NULL, v));
-}
-
-void LLXMLRPCValue::appendBool(bool v)
-{
- XMLRPC_AddValueToVector(mV, XMLRPC_CreateValueBoolean(NULL, v));
-}
-
-void LLXMLRPCValue::appendDouble(double v)
-{
- XMLRPC_AddValueToVector(mV, XMLRPC_CreateValueDouble(NULL, v));
-}
-
-
-void LLXMLRPCValue::append(const char* id, LLXMLRPCValue& v)
-{
- XMLRPC_SetValueID(v.mV, id, 0);
- XMLRPC_AddValueToVector(mV, v.mV);
-}
-
-void LLXMLRPCValue::appendString(const char* id, const std::string& v)
-{
- XMLRPC_AddValueToVector(mV, XMLRPC_CreateValueString(id, v.c_str(), 0));
-}
-
-void LLXMLRPCValue::appendInt(const char* id, int v)
-{
- XMLRPC_AddValueToVector(mV, XMLRPC_CreateValueInt(id, v));
-}
-
-void LLXMLRPCValue::appendBool(const char* id, bool v)
-{
- XMLRPC_AddValueToVector(mV, XMLRPC_CreateValueBoolean(id, v));
-}
-
-void LLXMLRPCValue::appendDouble(const char* id, double v)
-{
- XMLRPC_AddValueToVector(mV, XMLRPC_CreateValueDouble(id, v));
-}
-
-void LLXMLRPCValue::cleanup()
-{
- XMLRPC_CleanupValue(mV);
- mV = NULL;
-}
-
-XMLRPC_VALUE LLXMLRPCValue::getValue() const
-{
- return mV;
-}
-
-
class LLXMLRPCTransaction::Handler : public LLCore::HttpHandler
{
public:
@@ -192,6 +76,9 @@ public:
private:
+ bool parseResponse(LLXMLNodePtr root);
+ bool parseValue(LLSD& target, LLXMLNodePtr source);
+
LLXMLRPCTransaction::Impl *mImpl;
LLCore::HttpRequest::ptr_t mRequest;
};
@@ -213,26 +100,26 @@ public:
LLCore::HttpHandle mPostH;
std::string mURI;
-
std::string mProxyAddress;
std::string mResponseText;
- XMLRPC_REQUEST mResponse;
+ LLSD mResponseData;
+
std::string mCertStore;
- LLSD mErrorCertData;
+ LLSD mErrorCertData;
- Impl(const std::string& uri, XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams);
- Impl(const std::string& uri,
- const std::string& method, LLXMLRPCValue params, bool useGzip);
- ~Impl();
+ Impl
+ (
+ const std::string& uri,
+ const std::string& method,
+ const LLSD& params,
+ const LLSD& httpParams
+ );
bool process();
void setStatus(EStatus code, const std::string& message = "", const std::string& uri = "");
void setHttpStatus(const LLCore::HttpStatus &status);
-
-private:
- void init(XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams);
};
LLXMLRPCTransaction::Handler::Handler(LLCore::HttpRequest::ptr_t &request,
@@ -275,89 +162,113 @@ void LLXMLRPCTransaction::Handler::onCompleted(LLCore::HttpHandle handle,
mImpl->setStatus(LLXMLRPCTransaction::StatusComplete);
mImpl->mTransferStats = response->getTransferStats();
- // the contents of a buffer array are potentially noncontiguous, so we
+ // The contents of a buffer array are potentially noncontiguous, so we
// will need to copy them into an contiguous block of memory for XMLRPC.
LLCore::BufferArray *body = response->getBody();
- char * bodydata = new char[body->size()];
+ mImpl->mResponseText.resize(body->size());
- body->read(0, bodydata, body->size());
+ body->read(0, mImpl->mResponseText.data(), body->size());
- mImpl->mResponse = XMLRPC_REQUEST_FromXML(bodydata, static_cast<int>(body->size()), 0);
+ LLXMLNodePtr root;
+ if (!LLXMLNode::parseBuffer(mImpl->mResponseText.data(), body->size(), root, nullptr))
+ {
+ LL_WARNS() << "Failed parsing XML response; request URI: " << mImpl->mURI << LL_ENDL;
+ return;
+ }
- delete[] bodydata;
+ if (!parseResponse(root))
+ return;
- bool hasError = false;
- bool hasFault = false;
- int faultCode = 0;
- std::string faultString;
+ LL_INFOS() << "XML response parsed successfully; request URI: " << mImpl->mURI << LL_ENDL;
+}
- LLXMLRPCValue error(XMLRPC_RequestGetError(mImpl->mResponse));
- if (error.isValid())
+struct XMLTreeNode final : public LLSD::TreeNode
+{
+ XMLTreeNode(const LLXMLNodePtr impl)
+ : mImpl(impl)
+ , mFirstChild(impl ? create(impl->getFirstChild()) : nullptr)
+ , mNextSibling(impl ? create(impl->getNextSibling()) : nullptr)
{
- hasError = true;
- faultCode = error["faultCode"].asInt();
- faultString = error["faultString"].asString();
}
- else if (XMLRPC_ResponseIsFault(mImpl->mResponse))
+
+ static XMLTreeNode* create(LLXMLNodePtr node) { return node ? new XMLTreeNode(node) : nullptr; }
+
+ virtual bool hasName(const LLSD::String& name) const override { return mImpl && mImpl->hasName(name); }
+ virtual LLSD::String getTextContents() const override { return mImpl ? mImpl->getTextContents() : LLStringUtil::null; }
+ virtual TreeNode* getFirstChild() const override { return mFirstChild.get(); }
+ virtual TreeNode* getNextSibling() const override { return mNextSibling.get(); }
+
+private:
+ const LLXMLNodePtr mImpl;
+ const std::shared_ptr<XMLTreeNode> mFirstChild;
+ const std::shared_ptr<XMLTreeNode> mNextSibling;
+};
+
+bool LLXMLRPCTransaction::Handler::parseResponse(LLXMLNodePtr root)
+{
+ // We have alreasy checked in LLXMLNode::parseBuffer()
+ // that root contains exactly one child
+ if (!root->hasName("methodResponse"))
{
- hasFault = true;
- faultCode = XMLRPC_GetResponseFaultCode(mImpl->mResponse);
- faultString = XMLRPC_GetResponseFaultString(mImpl->mResponse);
+ LL_WARNS() << "Invalid root element in XML response; request URI: " << mImpl->mURI << LL_ENDL;
+ return false;
}
- if (hasError || hasFault)
+ LLXMLNodePtr first = root->getFirstChild();
+ LLXMLNodePtr second = first->getFirstChild();
+ if (!first->getNextSibling() && second && !second->getNextSibling())
{
- mImpl->setStatus(LLXMLRPCTransaction::StatusXMLRPCError);
-
- LL_WARNS() << "LLXMLRPCTransaction XMLRPC "
- << (hasError ? "error " : "fault ")
- << faultCode << ": "
- << faultString << LL_ENDL;
- LL_WARNS() << "LLXMLRPCTransaction request URI: "
- << mImpl->mURI << LL_ENDL;
+ if (first->hasName("fault"))
+ {
+ LLSD fault;
+ if (parseValue(fault, second) &&
+ fault.isMap() && fault.has("faultCode") && fault.has("faultString"))
+ {
+ LL_WARNS() << "Request failed;"
+ << " faultCode: '" << fault.get("faultCode").asString() << "',"
+ << " faultString: '" << fault.get("faultString").asString() << "',"
+ << " request URI: " << mImpl->mURI << LL_ENDL;
+ return false;
+ }
+ }
+ else if (first->hasName("params") &&
+ second->hasName("param") && !second->getNextSibling())
+ {
+ LLXMLNodePtr third = second->getFirstChild();
+ if (third && !third->getNextSibling() && parseValue(mImpl->mResponseData, third))
+ {
+ return true;
+ }
+ }
}
-}
-
-//=========================================================================
+ LL_WARNS() << "Invalid response format; request URI: " << mImpl->mURI << LL_ENDL;
-LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
- XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams)
- : mHttpRequest(),
- mStatus(LLXMLRPCTransaction::StatusNotStarted),
- mURI(uri),
- mResponse(0)
-{
- init(request, useGzip, httpParams);
+ return false;
}
-
-LLXMLRPCTransaction::Impl::Impl(const std::string& uri,
- const std::string& method, LLXMLRPCValue params, bool useGzip)
- : mHttpRequest(),
- mStatus(LLXMLRPCTransaction::StatusNotStarted),
- mURI(uri),
- mResponse(0)
+bool LLXMLRPCTransaction::Handler::parseValue(LLSD& target, LLXMLNodePtr source)
{
- XMLRPC_REQUEST request = XMLRPC_RequestNew();
- XMLRPC_RequestSetMethodName(request, method.c_str());
- XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
- XMLRPC_RequestSetData(request, params.getValue());
-
- init(request, useGzip, LLSD());
- // DEV-28398: without this XMLRPC_RequestFree() call, it looks as though
- // the 'request' object is simply leaked. It's less clear to me whether we
- // should also ask to free request value data (second param 1), since the
- // data come from 'params'.
- XMLRPC_RequestFree(request, 1);
+ XMLTreeNode tn(source);
+ return target.fromXMLRPCValue(&tn);
}
-void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams)
+//=========================================================================
+
+LLXMLRPCTransaction::Impl::Impl
+(
+ const std::string& uri,
+ const std::string& method,
+ const LLSD& params,
+ const LLSD& http_params
+)
+ : mHttpRequest()
+ , mStatus(LLXMLRPCTransaction::StatusNotStarted)
+ , mURI(uri)
{
LLCore::HttpOptions::ptr_t httpOpts;
LLCore::HttpHeaders::ptr_t httpHeaders;
-
if (!mHttpRequest)
{
mHttpRequest = LLCore::HttpRequest::ptr_t(new LLCore::HttpRequest);
@@ -366,37 +277,34 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const
// LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer
httpOpts = LLCore::HttpOptions::ptr_t(new LLCore::HttpOptions());
- // delay between repeats will start from 5 sec and grow to 20 sec with each repeat
+ // Delay between repeats will start from 5 sec and grow to 20 sec with each repeat
httpOpts->setMinBackoff(5E6L);
httpOpts->setMaxBackoff(20E6L);
- httpOpts->setTimeout(httpParams.has("timeout") ? httpParams["timeout"].asInteger() : 40L);
- if (httpParams.has("retries"))
+ httpOpts->setTimeout(http_params.has("timeout") ? http_params["timeout"].asInteger() : 40L);
+ if (http_params.has("retries"))
{
- httpOpts->setRetries(httpParams["retries"].asInteger());
+ httpOpts->setRetries(http_params["retries"].asInteger());
}
- if (httpParams.has("DNSCacheTimeout"))
+ if (http_params.has("DNSCacheTimeout"))
{
- httpOpts->setDNSCacheTimeout(httpParams["DNSCacheTimeout"].asInteger());
+ httpOpts->setDNSCacheTimeout(http_params["DNSCacheTimeout"].asInteger());
}
bool vefifySSLCert = !gSavedSettings.getBOOL("NoVerifySSLCert");
mCertStore = gSavedSettings.getString("CertStore");
- httpOpts->setSSLVerifyPeer( vefifySSLCert );
- httpOpts->setSSLVerifyHost( vefifySSLCert ? 2 : 0);
+ httpOpts->setSSLVerifyPeer(vefifySSLCert);
+ httpOpts->setSSLVerifyHost(vefifySSLCert ? 2 : 0);
// LLRefCounted starts with a 1 ref, so don't add a ref in the smart pointer
httpHeaders = LLCore::HttpHeaders::ptr_t(new LLCore::HttpHeaders());
httpHeaders->append(HTTP_OUT_HEADER_CONTENT_TYPE, HTTP_CONTENT_TEXT_XML);
- std::string user_agent = stringize(
- LLVersionInfo::instance().getChannel(), ' ',
- LLVersionInfo::instance().getMajor(), '.',
- LLVersionInfo::instance().getMinor(), '.',
- LLVersionInfo::instance().getPatch(), " (",
- LLVersionInfo::instance().getBuild(), ')');
+ const LLVersionInfo& vi(LLVersionInfo::instance());
+ std::string user_agent = vi.getChannel() + llformat(" %d.%d.%d (%llu)",
+ vi.getMajor(), vi.getMinor(), vi.getPatch(), vi.getBuild());
httpHeaders->append(HTTP_OUT_HEADER_USER_AGENT, user_agent);
@@ -404,31 +312,19 @@ void LLXMLRPCTransaction::Impl::init(XMLRPC_REQUEST request, bool useGzip, const
//This might help with bug #503 */
//httpOpts->setDNSCacheTimeout(-1);
- LLCore::BufferArray::ptr_t body = LLCore::BufferArray::ptr_t(new LLCore::BufferArray());
+ std::string request =
+ "<?xml version=\"1.0\"?><methodCall><methodName>" + method +
+ "</methodName><params><param>" + params.asXMLRPCValue() +
+ "</param></params></methodCall>";
- // TODO: See if there is a way to serialize to a preallocated buffer I'm
- // not fond of the copy here.
- int requestSize(0);
- char * requestText = XMLRPC_REQUEST_ToXML(request, &requestSize);
-
- body->append(requestText, requestSize);
+ LLCore::BufferArray::ptr_t body = LLCore::BufferArray::ptr_t(new LLCore::BufferArray());
- XMLRPC_Free(requestText);
+ body->append(request.c_str(), request.size());
- mHandler = LLXMLRPCTransaction::Handler::ptr_t(new Handler( mHttpRequest, this ));
+ mHandler = LLXMLRPCTransaction::Handler::ptr_t(new Handler(mHttpRequest, this));
mPostH = mHttpRequest->requestPost(LLCore::HttpRequest::DEFAULT_POLICY_ID,
mURI, body.get(), httpOpts, httpHeaders, mHandler);
-
-}
-
-
-LLXMLRPCTransaction::Impl::~Impl()
-{
- if (mResponse)
- {
- XMLRPC_RequestFree(mResponse, 1);
- }
}
bool LLXMLRPCTransaction::Impl::process()
@@ -539,18 +435,16 @@ void LLXMLRPCTransaction::Impl::setHttpStatus(const LLCore::HttpStatus &status)
}
-
-LLXMLRPCTransaction::LLXMLRPCTransaction(
- const std::string& uri, XMLRPC_REQUEST request, bool useGzip, const LLSD& httpParams)
-: impl(* new Impl(uri, request, useGzip, httpParams))
-{ }
-
-
-LLXMLRPCTransaction::LLXMLRPCTransaction(
+LLXMLRPCTransaction::LLXMLRPCTransaction
+(
const std::string& uri,
- const std::string& method, LLXMLRPCValue params, bool useGzip)
-: impl(* new Impl(uri, method, params, useGzip))
-{ }
+ const std::string& method,
+ const LLSD& params,
+ const LLSD& http_params
+)
+: impl(*new Impl(uri, method, params, http_params))
+{
+}
LLXMLRPCTransaction::~LLXMLRPCTransaction()
{
@@ -590,14 +484,9 @@ std::string LLXMLRPCTransaction::statusURI()
return impl.mStatusURI;
}
-XMLRPC_REQUEST LLXMLRPCTransaction::response()
-{
- return impl.mResponse;
-}
-
-LLXMLRPCValue LLXMLRPCTransaction::responseValue()
+const LLSD& LLXMLRPCTransaction::response()
{
- return LLXMLRPCValue(XMLRPC_RequestGetData(impl.mResponse));
+ return impl.mResponseData;
}
diff --git a/indra/newview/llxmlrpctransaction.h b/indra/newview/llxmlrpctransaction.h
index 4c8796f936..f7a38f5f90 100644
--- a/indra/newview/llxmlrpctransaction.h
+++ b/indra/newview/llxmlrpctransaction.h
@@ -29,73 +29,22 @@
#include <string>
-typedef struct _xmlrpc_request* XMLRPC_REQUEST;
-typedef struct _xmlrpc_value* XMLRPC_VALUE;
- // foward decl of types from xmlrpc.h (this usage is type safe)
-class LLCertificate;
-
-class LLXMLRPCValue
- // a c++ wrapper around XMLRPC_VALUE
-{
-public:
- LLXMLRPCValue() : mV(NULL) { }
- LLXMLRPCValue(XMLRPC_VALUE value) : mV(value) { }
-
- bool isValid() const;
-
- std::string asString() const;
- int asInt() const;
- bool asBool() const;
- double asDouble() const;
-
- LLXMLRPCValue operator[](const char*) const;
-
- LLXMLRPCValue rewind();
- LLXMLRPCValue next();
-
- static LLXMLRPCValue createArray();
- static LLXMLRPCValue createStruct();
-
- void append(LLXMLRPCValue&);
- void appendString(const std::string&);
- void appendInt(int);
- void appendBool(bool);
- void appendDouble(double);
- void appendValue(LLXMLRPCValue&);
-
- void append(const char*, LLXMLRPCValue&);
- void appendString(const char*, const std::string&);
- void appendInt(const char*, int);
- void appendBool(const char*, bool);
- void appendDouble(const char*, double);
- void appendValue(const char*, LLXMLRPCValue&);
-
- void cleanup();
- // only call this on the top level created value
-
- XMLRPC_VALUE getValue() const;
-
-private:
- XMLRPC_VALUE mV;
-};
-
-
+/// An asynchronous request and responses via XML-RPC
class LLXMLRPCTransaction
- // an asynchronous request and responses via XML-RPC
{
public:
- LLXMLRPCTransaction(const std::string& uri,
- XMLRPC_REQUEST request, bool useGzip = true, const LLSD& httpParams = LLSD());
- // does not take ownership of the request object
- // request can be freed as soon as the transaction is constructed
-
- LLXMLRPCTransaction(const std::string& uri,
- const std::string& method, LLXMLRPCValue params, bool useGzip = true);
- // *does* take control of the request value, you must not free it
+ LLXMLRPCTransaction
+ (
+ const std::string& uri,
+ const std::string& method,
+ const LLSD& params,
+ const LLSD& http_params = LLSD()
+ );
~LLXMLRPCTransaction();
- typedef enum e_status {
+ typedef enum e_status
+ {
StatusNotStarted,
StatusStarted,
StatusDownloading,
@@ -105,26 +54,25 @@ public:
StatusOtherError
} EStatus;
+ /// Run the request a little, returns true when done
bool process();
- // run the request a little, returns true when done
+ /// Return a status, and extended CURL code, if code isn't null
EStatus status(int* curlCode);
- // return status, and extended CURL code, if code isn't null
LLSD getErrorCertData();
+
+ /// Return a message string, suitable for showing the user
std::string statusMessage();
- // return a message string, suitable for showing the user
+
+ /// Return a URI for the user with more information (can be empty)
std::string statusURI();
- // return a URI for the user with more information
- // can be empty
- XMLRPC_REQUEST response();
- LLXMLRPCValue responseValue();
- // only valid if StatusComplete, otherwise NULL
- // retains ownership of the result object, don't free it
+ /// Only non-empty if StatusComplete, otherwise Undefined
+ const LLSD& response();
+ /// Only valid if StsatusComplete, otherwise 0.0
F64 transferRate();
- // only valid if StsatusComplete, otherwise 0.0
private:
class Handler;
@@ -133,6 +81,4 @@ private:
Impl& impl;
};
-
-
#endif // LLXMLRPCTRANSACTION_H
diff --git a/indra/newview/skins/default/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml
index 7bcae69779..604eb7c58f 100644
--- a/indra/newview/skins/default/xui/da/floater_about.xml
+++ b/indra/newview/skins/default/xui/da/floater_about.xml
@@ -69,7 +69,6 @@ OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
PCRE Copyright (c) 1997-2008 University of Cambridge
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
-xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler.
google-perftools Copyright (c) 2005, Google Inc.
diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml
index 10ccf0d5da..320db7f654 100644
--- a/indra/newview/skins/default/xui/de/floater_about.xml
+++ b/indra/newview/skins/default/xui/de/floater_about.xml
@@ -28,7 +28,6 @@ mit Open-Source-Beiträgen von:</text>
PCRE Copyright (c) 1997-2012 University of Cambridge.
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga.
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com).
- xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Copyright (C) 1995-2012 Jean-loup Gailly und Mark Adler.
diff --git a/indra/newview/skins/default/xui/de/menu_viewer.xml b/indra/newview/skins/default/xui/de/menu_viewer.xml
index f6724d4993..8c446c1975 100644
--- a/indra/newview/skins/default/xui/de/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/de/menu_viewer.xml
@@ -42,12 +42,6 @@
<menu_item_call label="Facebook..." name="Facebook"/>
<menu_item_call label="Twitter..." name="Twitter"/>
<menu_item_call label="Flickr..." name="Flickr"/>
- <menu label="Voice-Morphing" name="VoiceMorphing">
- <menu_item_check label="Kein Voice-Morphing" name="NoVoiceMorphing"/>
- <menu_item_check label="Vorschau..." name="Preview"/>
- <menu_item_call label="Abonnieren..." name="Subscribe"/>
- <menu_item_call label="Premium-Vorteil..." name="PremiumPerk"/>
- </menu>
<menu_item_check label="Gesten..." name="Gestures"/>
<menu_item_check label="Freunde" name="My Friends"/>
<menu_item_check label="Gruppen" name="My Groups"/>
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index ff2fa93cbb..126cd84d56 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -111,7 +111,6 @@ Dummy Name replaced at run time
PCRE Copyright (c) 1997-2012 University of Cambridge
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
diff --git a/indra/newview/skins/default/xui/en/floater_gltf_asset_editor.xml b/indra/newview/skins/default/xui/en/floater_gltf_asset_editor.xml
new file mode 100644
index 0000000000..b17d0aa5b6
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_gltf_asset_editor.xml
@@ -0,0 +1,284 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ default_tab_group="1"
+ height="530"
+ width="256"
+ min_height="400"
+ min_width="200"
+ layout="topleft"
+ name="gltf asset editor"
+ title="[OBJECT_NAME]">
+ <floater.string name="floater_title" value="GLTF Scene Editor"/>
+ <floater.string name="scene_tittle" value="Scene"/>
+ <floater.string name="node_tittle" value="Node"/>
+ <floater.string name="mesh_tittle" value="Mesh"/>
+ <floater.string name="skin_tittle" value="Skin"/>
+
+ <layout_stack
+ name="main_layout"
+ orientation="vertical"
+ follows="all"
+ bottom="-1"
+ top="16"
+ left="5"
+ right="-1"
+ border_size="0">
+
+ <layout_panel
+ name="top_lp"
+ border="true"
+ bevel_style="in"
+ auto_resize="false"
+ user_resize="true"
+ visible="true"
+ height="200">
+ <panel
+ follows="all"
+ layout="topleft"
+ name="item_list_panel"
+ visible="true"
+ bottom="-1"
+ top="1"
+ left="5"
+ right="-1"/>
+ </layout_panel>
+
+ <layout_panel
+ name="transforms_panel"
+ border="true"
+ bevel_style="in"
+ auto_resize="true"
+ user_resize="true"
+ visible="true"
+ height="150">
+ <menu_button
+ menu_filename="menu_copy_paste_pos.xml"
+ follows="top|left"
+ height="11"
+ image_disabled="ClipboardSmallMenu_Disabled"
+ image_selected="ClipboardSmallMenu_Press"
+ image_unselected="ClipboardSmallMenu_Off"
+ layout="topleft"
+ left="4"
+ top="10"
+ name="clipboard_pos_btn"
+ tool_tip="Paste options"
+ width="19"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ name="label position"
+ tool_tip="Position (meters)"
+ left_pad="8"
+ top_delta="0"
+ width="121">
+ Position (m)
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="-27"
+ max_val="512"
+ min_val="-256"
+ name="Pos X"
+ text_enabled_color="1 0 0.3 .7"
+ top_pad="8"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="512"
+ min_val="-256"
+ name="Pos Y"
+ text_enabled_color="EmphasisColor"
+ top_pad="3"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Z"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="4096"
+ min_val="-32"
+ name="Pos Z"
+ text_enabled_color="0 0.8 1 .65"
+ top_pad="3"
+ width="87" />
+ <menu_button
+ menu_filename="menu_copy_paste_size.xml"
+ follows="top|left"
+ height="11"
+ image_disabled="ClipboardSmallMenu_Disabled"
+ image_selected="ClipboardSmallMenu_Press"
+ image_unselected="ClipboardSmallMenu_Off"
+ layout="topleft"
+ left_delta="0"
+ top_pad="13"
+ name="clipboard_size_btn"
+ tool_tip="Paste options"
+ width="19"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="8"
+ top_delta="0"
+ name="label size"
+ tool_tip="Size (meters)"
+ width="121">
+ Size (m)
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="-27"
+ max_val="64"
+ min_val="0.01"
+ name="Scale X"
+ text_enabled_color="1 1 1 1"
+ top_pad="8"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="64"
+ min_val="0.01"
+ name="Scale Y"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Z"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="64"
+ min_val="0.01"
+ name="Scale Z"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <menu_button
+ menu_filename="menu_copy_paste_rot.xml"
+ follows="top|left"
+ height="11"
+ image_disabled="ClipboardSmallMenu_Disabled"
+ image_selected="ClipboardSmallMenu_Press"
+ image_unselected="ClipboardSmallMenu_Off"
+ layout="topleft"
+ left_delta="0"
+ top_pad="13"
+ name="clipboard_rot_btn"
+ tool_tip="Paste options"
+ width="19"/>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="8"
+ top_delta="0"
+ name="label rotation"
+ tool_tip="Rotation (degrees)"
+ width="121">
+ Rotation (°)
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="-27"
+ max_val="9999"
+ min_val="-9999"
+ name="Rot X"
+ text_enabled_color="1 1 1 1"
+ top_pad="8"
+ width="87" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="9999"
+ min_val="-9999"
+ name="Rot Y"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="Z"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="9999"
+ min_val="-9999"
+ name="Rot Z"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ </layout_panel>
+
+ <layout_panel
+ name="blank_panel"
+ border="true"
+ bevel_style="in"
+ auto_resize="true"
+ user_resize="true"
+ visible="false"
+ height="150">
+ </layout_panel>
+ </layout_stack>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 4a043bbbc9..347638249b 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -561,42 +561,6 @@
parameter="conversation" />
</menu_item_check>
<menu_item_separator/>
- <menu
- label="Voice morphing"
- name="VoiceMorphing"
- visibility_control="VoiceMorphingEnabled">
- <menu_item_check
- label="No voice morphing"
- name="NoVoiceMorphing">
- <menu_item_check.on_check
- function="Communicate.VoiceMorphing.NoVoiceMorphing.Check" />
- <menu_item_check.on_click
- function="Communicate.VoiceMorphing.NoVoiceMorphing.Click" />
- </menu_item_check>
- <menu_item_separator/>
- <menu_item_check
- label="Preview..."
- name="Preview">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="voice_effect" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="voice_effect" />
- </menu_item_check>
- <menu_item_call
- label="Subscribe..."
- name="Subscribe">
- <menu_item_call.on_click
- function="Communicate.VoiceMorphing.Subscribe" />
- </menu_item_call>
- <menu_item_call
- label="Premium perk..."
- name="PremiumPerk">
- <menu_item_call.on_click
- function="Communicate.VoiceMorphing.PremiumPerk" />
- </menu_item_call>
- </menu>
<menu_item_check
label="Gestures..."
name="Gestures"
@@ -2887,6 +2851,14 @@ function="World.EnvPreset"
<menu_item_call.on_click
function="Advanced.ClickGLTFUpload" />
</menu_item_call>
+ <menu_item_call
+ label="Edit..."
+ name="Edit...">
+ <menu_item_call.on_enable
+ function="EnableGLTFUpload"/>
+ <menu_item_call.on_click
+ function="Advanced.ClickGLTFEdit" />
+ </menu_item_call>
</menu>
<menu
create_jump_keys="true"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 1584de6880..f86b297395 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -8842,6 +8842,20 @@ New Voice Morphs are available!
</notification>
<notification
+ icon="alertmodal.tga"
+ name="VoiceEffectsNotSupported"
+ sound="UISndAlert"
+ persist="true"
+ type="alertmodal">
+Voice Morphs are not supported by this viewer.
+ <usetemplate
+ notext="Cancel"
+ name="okcancelbuttons"
+ yestext="Disable Voice Morphing"/>
+ <tag>voice</tag>
+ </notification>
+
+ <notification
icon="notifytip.tga"
name="Cannot enter parcel: not a group member"
type="notifytip">
diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml
index e14ba32f69..8103a95376 100644
--- a/indra/newview/skins/default/xui/es/floater_about.xml
+++ b/indra/newview/skins/default/xui/es/floater_about.xml
@@ -28,7 +28,6 @@ con contribuciones de código abierto de:</text>
PCRE Copyright (c) 1997-2012 University of Cambridge
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Copyright (C) 1995-2012 Jean-loup Gailly y Mark Adler.
diff --git a/indra/newview/skins/default/xui/es/menu_viewer.xml b/indra/newview/skins/default/xui/es/menu_viewer.xml
index c22311f882..04e43f01da 100644
--- a/indra/newview/skins/default/xui/es/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/es/menu_viewer.xml
@@ -42,12 +42,6 @@
<menu_item_call label="Facebook..." name="Facebook"/>
<menu_item_call label="Twitter..." name="Twitter"/>
<menu_item_call label="Flickr..." name="Flickr"/>
- <menu label="Transformación de voz" name="VoiceMorphing">
- <menu_item_check label="Sin transformación de voz" name="NoVoiceMorphing"/>
- <menu_item_check label="Probar..." name="Preview"/>
- <menu_item_call label="Suscribir..." name="Subscribe"/>
- <menu_item_call label="Ventaja Premium..." name="PremiumPerk"/>
- </menu>
<menu_item_check label="Gestos..." name="Gestures"/>
<menu_item_check label="Amigos" name="My Friends"/>
<menu_item_check label="Grupos" name="My Groups"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_about.xml b/indra/newview/skins/default/xui/fr/floater_about.xml
index 09da1fb5fd..b6ea621177 100644
--- a/indra/newview/skins/default/xui/fr/floater_about.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about.xml
@@ -28,7 +28,6 @@ avec les contributions Open Source de :</text>
PCRE Copyright (c) 1997-2012 University of Cambridge
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Copyright (C) 1995-2012 Jean-Loup Gailly et Mark Adler.
diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml
index 7e195d3ca9..77be47d749 100644
--- a/indra/newview/skins/default/xui/it/floater_about.xml
+++ b/indra/newview/skins/default/xui/it/floater_about.xml
@@ -28,7 +28,6 @@ con contributi open source da:</text>
PCRE Copyright (c) 1997-2012 University of Cambridge
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Copyright (C) 1995-2012 Jean-loup Gailly e Mark Adler.
diff --git a/indra/newview/skins/default/xui/it/menu_viewer.xml b/indra/newview/skins/default/xui/it/menu_viewer.xml
index 043fd28ddb..85999ccbe0 100644
--- a/indra/newview/skins/default/xui/it/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/it/menu_viewer.xml
@@ -42,12 +42,6 @@
<menu_item_call label="Facebook..." name="Facebook"/>
<menu_item_call label="Twitter..." name="Twitter"/>
<menu_item_call label="Flickr..." name="Flickr"/>
- <menu label="Manipolazione voce" name="VoiceMorphing">
- <menu_item_check label="Nessuna manipolazione voce" name="NoVoiceMorphing"/>
- <menu_item_check label="Anteprima..." name="Preview"/>
- <menu_item_call label="Abbonati..." name="Subscribe"/>
- <menu_item_call label="Vantaggio Premium..." name="PremiumPerk"/>
- </menu>
<menu_item_check label="Gesture..." name="Gestures"/>
<menu_item_check label="Amici" name="My Friends"/>
<menu_item_check label="Gruppi" name="My Groups"/>
diff --git a/indra/newview/skins/default/xui/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml
index 12d763be37..6cd22f6a31 100644
--- a/indra/newview/skins/default/xui/ja/floater_about.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about.xml
@@ -33,7 +33,6 @@ OpenSSL Copyright (C) 1998-2008 The OpenSSL Project.
PCRE Copyright (c) 1997-2012 University of Cambridge
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
-xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
diff --git a/indra/newview/skins/default/xui/ja/menu_viewer.xml b/indra/newview/skins/default/xui/ja/menu_viewer.xml
index a1f3980df4..f6b10bb121 100644
--- a/indra/newview/skins/default/xui/ja/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ja/menu_viewer.xml
@@ -74,7 +74,6 @@
<menu_item_check label="ボイスチャット" name="Speak"/>
<menu_item_check name="Conversation Log..." label="会話ログ…"/>
<menu_item_separator/>
- <menu label="ボイスモーフィング" name="VoiceMorphing"/>
<menu_item_check label="ジェスチャー…" name="Gestures"/>
<menu_item_separator/>
<menu_item_check label="フレンド" name="My Friends"/>
diff --git a/indra/newview/skins/default/xui/pl/menu_viewer.xml b/indra/newview/skins/default/xui/pl/menu_viewer.xml
index 4d03e7c780..ee162addd2 100644
--- a/indra/newview/skins/default/xui/pl/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pl/menu_viewer.xml
@@ -35,11 +35,6 @@
<menu_item_check label="Czat lokalny..." name="Nearby Chat" />
<menu_item_check label="Mowa" name="Speak" />
<menu_item_check name="Conversation Log..." label="Dziennik rozmów..." />
- <menu label="Przekształcanie głosu" name="VoiceMorphing">
- <menu_item_check label="Bez przekształcania" name="NoVoiceMorphing" />
- <menu_item_check label="Podgląd..." name="Preview" />
- <menu_item_call label="Subskrybuj..." name="Subscribe" />
- </menu>
<menu_item_check label="Gesty..." name="Gestures" />
<menu_item_check label="Znajomi" name="My Friends" />
<menu_item_check label="Grupy" name="My Groups" />
diff --git a/indra/newview/skins/default/xui/pt/floater_about.xml b/indra/newview/skins/default/xui/pt/floater_about.xml
index aaed728f84..0e95c53109 100644
--- a/indra/newview/skins/default/xui/pt/floater_about.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about.xml
@@ -28,7 +28,6 @@ com contribuições de código aberto de:</text>
PCRE Copyright (c) 1997-2012 University of Cambridge
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
diff --git a/indra/newview/skins/default/xui/pt/menu_viewer.xml b/indra/newview/skins/default/xui/pt/menu_viewer.xml
index b70adc3ad2..0f4873d11c 100644
--- a/indra/newview/skins/default/xui/pt/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/pt/menu_viewer.xml
@@ -42,12 +42,6 @@
<menu_item_call label="Facebook..." name="Facebook"/>
<menu_item_call label="Twitter..." name="Twitter"/>
<menu_item_call label="Flickr..." name="Flickr"/>
- <menu label="Distorção de voz" name="VoiceMorphing">
- <menu_item_check label="Não distorcer voz" name="NoVoiceMorphing"/>
- <menu_item_check label="Visualizar..." name="Preview"/>
- <menu_item_call label="Assinar..." name="Subscribe"/>
- <menu_item_call label="Benefício Premium..." name="PremiumPerk"/>
- </menu>
<menu_item_check label="Gestos..." name="Gestures"/>
<menu_item_check label="Amigos" name="My Friends"/>
<menu_item_check label="Grupos" name="My Groups"/>
diff --git a/indra/newview/skins/default/xui/ru/floater_about.xml b/indra/newview/skins/default/xui/ru/floater_about.xml
index a65a979ccd..22827bc397 100644
--- a/indra/newview/skins/default/xui/ru/floater_about.xml
+++ b/indra/newview/skins/default/xui/ru/floater_about.xml
@@ -28,7 +28,6 @@
PCRE (c) 1997-2012, Кембриджский университет
SDL (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- xmlrpc-epi (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib (C) 1995-2012 Jean-loup Gailly и Mark Adler.
diff --git a/indra/newview/skins/default/xui/ru/menu_viewer.xml b/indra/newview/skins/default/xui/ru/menu_viewer.xml
index 8361464f4c..4a6390329d 100644
--- a/indra/newview/skins/default/xui/ru/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/ru/menu_viewer.xml
@@ -40,12 +40,6 @@
<menu_item_call label="Facebook..." name="Facebook"/>
<menu_item_call label="Twitter..." name="Twitter"/>
<menu_item_call label="Flickr..." name="Flickr"/>
- <menu label="Изменение голоса" name="VoiceMorphing">
- <menu_item_check label="Без изменения голоса" name="NoVoiceMorphing"/>
- <menu_item_check label="Просмотр..." name="Preview"/>
- <menu_item_call label="Подписаться..." name="Subscribe"/>
- <menu_item_call label="Премиум-бонус..." name="PremiumPerk"/>
- </menu>
<menu_item_check label="Жесты..." name="Gestures"/>
<menu_item_check label="Друзья" name="My Friends"/>
<menu_item_check label="Группы" name="My Groups"/>
diff --git a/indra/newview/skins/default/xui/tr/floater_about.xml b/indra/newview/skins/default/xui/tr/floater_about.xml
index 40ca3707c3..ca21bee464 100644
--- a/indra/newview/skins/default/xui/tr/floater_about.xml
+++ b/indra/newview/skins/default/xui/tr/floater_about.xml
@@ -28,7 +28,6 @@ açık kaynak kod katkısında bulunanlar şunlardır:</text>
PCRE Telif Hakkı (c) 1997-2012 University of Cambridge
SDL Telif Hakkı (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Telif Hakkı (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- xmlrpc-epi Telif Hakkı (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Telif Hakkı (C) 1995-2012 Jean-loup Gailly ve Mark Adler.
diff --git a/indra/newview/skins/default/xui/tr/menu_viewer.xml b/indra/newview/skins/default/xui/tr/menu_viewer.xml
index 1c977ba5ce..fb6111248c 100644
--- a/indra/newview/skins/default/xui/tr/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/tr/menu_viewer.xml
@@ -40,12 +40,6 @@
<menu_item_call label="Facebook..." name="Facebook"/>
<menu_item_call label="Twitter..." name="Twitter"/>
<menu_item_call label="Flickr..." name="Flickr"/>
- <menu label="Ses şekillendirme" name="VoiceMorphing">
- <menu_item_check label="Ses şekillendirme yok" name="NoVoiceMorphing"/>
- <menu_item_check label="Önizleme..." name="Preview"/>
- <menu_item_call label="Abone ol..." name="Subscribe"/>
- <menu_item_call label="Özel üye avantajı..." name="PremiumPerk"/>
- </menu>
<menu_item_check label="Mimikler..." name="Gestures"/>
<menu_item_check label="Arkadaşlar" name="My Friends"/>
<menu_item_check label="Gruplar" name="My Groups"/>
diff --git a/indra/newview/skins/default/xui/zh/floater_about.xml b/indra/newview/skins/default/xui/zh/floater_about.xml
index a56ae753d1..727f598894 100644
--- a/indra/newview/skins/default/xui/zh/floater_about.xml
+++ b/indra/newview/skins/default/xui/zh/floater_about.xml
@@ -28,7 +28,6 @@
PCRE Copyright (c) 1997-2012 University of Cambridge
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- xmlrpc-epi Copyright (C) 2000 Epinions, Inc.
xxHash Copyright (C) 2012-2020 Yann Collet.
zlib Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler.
diff --git a/indra/newview/skins/default/xui/zh/menu_viewer.xml b/indra/newview/skins/default/xui/zh/menu_viewer.xml
index 972434dfc5..a048af7b68 100644
--- a/indra/newview/skins/default/xui/zh/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/zh/menu_viewer.xml
@@ -40,12 +40,6 @@
<menu_item_call label="臉書…" name="Facebook"/>
<menu_item_call label="推特…" name="Twitter"/>
<menu_item_call label="Flickr…" name="Flickr"/>
- <menu label="語音變聲" name="VoiceMorphing">
- <menu_item_check label="沒有變聲效果" name="NoVoiceMorphing"/>
- <menu_item_check label="預覽……" name="Preview"/>
- <menu_item_call label="訂閱……" name="Subscribe"/>
- <menu_item_call label="付費會員獨享…" name="PremiumPerk"/>
- </menu>
<menu_item_check label="姿勢…" name="Gestures"/>
<menu_item_check label="朋友" name="My Friends"/>
<menu_item_check label="群組" name="My Groups"/>
diff --git a/indra/viewer_components/login/lllogin.cpp b/indra/viewer_components/login/lllogin.cpp
index 2a0468f3ad..48fecb4f22 100644
--- a/indra/viewer_components/login/lllogin.cpp
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -66,6 +66,16 @@ public:
LLEventPump& getEventPump() { return mPump; }
private:
+ LLSD hidePasswd(const LLSD& data)
+ {
+ LLSD result(data);
+ if (result.has("params") && result["params"].has("passwd"))
+ {
+ result["params"]["passwd"] = "*******";
+ }
+ return result;
+ }
+
LLSD getProgressEventLLSD(const std::string& state, const std::string& change,
const LLSD& data = LLSD())
{
@@ -74,15 +84,16 @@ private:
status_data["change"] = change;
status_data["progress"] = 0.0f;
- if(mAuthResponse.has("transfer_rate"))
+ if (mAuthResponse.has("transfer_rate"))
{
status_data["transfer_rate"] = mAuthResponse["transfer_rate"];
}
- if(data.isDefined())
+ if (data.isDefined())
{
status_data["data"] = data;
}
+
return status_data;
}
@@ -119,17 +130,18 @@ private:
void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)
{
- LL_DEBUGS("LLLogin") << " connect with uri '" << uri << "', login_params " << login_params << LL_ENDL;
+ LL_DEBUGS("LLLogin") << " connect with uri '" << uri << "', login_params " << login_params << LL_ENDL;
// Launch a coroutine with our login_() method. Run the coroutine until
// its first wait; at that point, return here.
std::string coroname =
- LLCoros::instance().launch("LLLogin::Impl::login_",
- boost::bind(&Impl::loginCoro, this, uri, login_params));
- LL_DEBUGS("LLLogin") << " connected with uri '" << uri << "', login_params " << login_params << LL_ENDL;
+ LLCoros::instance().launch("LLLogin::Impl::login_", [&]() { loginCoro(uri, login_params); });
+
+ LL_DEBUGS("LLLogin") << " connected with uri '" << uri << "', login_params " << login_params << LL_ENDL;
}
-namespace {
+namespace
+{
// Instantiate this rendezvous point at namespace scope so it's already
// present no matter how early the updater might post to it.
// Use an LLEventMailDrop, which has future-like semantics: regardless of the
@@ -140,12 +152,8 @@ static LLEventMailDrop sSyncPoint("LoginSync");
void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
{
- LLSD printable_params = login_params;
- if (printable_params.has("params")
- && printable_params["params"].has("passwd"))
- {
- printable_params["params"]["passwd"] = "*******";
- }
+ LLSD printable_params = hidePasswd(login_params);
+
try
{
LL_DEBUGS("LLLogin") << "Entering coroutine " << LLCoros::getName()
@@ -171,12 +179,7 @@ void LLLogin::Impl::loginCoro(std::string uri, LLSD login_params)
++attempts;
LLSD progress_data;
progress_data["attempt"] = attempts;
- progress_data["request"] = request;
- if (progress_data["request"].has("params")
- && progress_data["request"]["params"].has("passwd"))
- {
- progress_data["request"]["params"]["passwd"] = "*******";
- }
+ progress_data["request"] = hidePasswd(request);
sendProgressEvent("offline", "authenticating", progress_data);
// We expect zero or more "Downloading" status events, followed by