Merge branch 'FirestormViewer:master' into FIRE-34884
commit
f885734ed5
|
|
@ -2,7 +2,7 @@
|
|||
# clang-format version 10.0.0+
|
||||
Language: Cpp
|
||||
# BasedOnStyle: Microsoft
|
||||
AccessModifierOffset: -2
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveMacros: true
|
||||
AlignConsecutiveAssignments: true
|
||||
|
|
@ -15,14 +15,14 @@ AllowAllConstructorInitializersOnNextLine: false
|
|||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: All
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||
AllowShortLambdasOnASingleLine: Inline
|
||||
AllowShortIfStatementsOnASingleLine: Never
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: MultiLine
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: true
|
||||
BinPackParameters: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
|
|
@ -67,7 +67,7 @@ IndentCaseLabels: true
|
|||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
IndentWrappedFunctionNames: true
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
|
|
@ -91,9 +91,9 @@ PointerAlignment: Left
|
|||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SortUsingDeclarations: true
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAfterTemplateKeyword: false
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
|
|
@ -102,8 +102,8 @@ SpaceBeforeParens: ControlStatements
|
|||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 2
|
||||
SpacesInAngles: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInParentheses: false
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@
|
|||
a0b3021bdcf76859054fda8e30abb3ed47749e83
|
||||
8444cd9562a6a7b755fcb075864e205122354192
|
||||
863c541ce0b2e3e1e566cc88423d3e87aaedb6ca
|
||||
743a1a6d8eabf069d95777c96e5b657cb8702593
|
||||
4a00da1ada89af6f313cee30f5177634b0b180a9
|
||||
# Wrong line endings
|
||||
1b67dd855c41f5a0cda7ec2a68d98071986ca703
|
||||
6cc7dd09d5e69cf57e6de7fb568a0ad2693f9c9a
|
||||
e2e37cced861b98de8c1a7c9c0d3a50d2d90e433
|
||||
# multiple problems
|
||||
5370a6d323e14d7b4e32a3f41ef78f7744e361c5
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
needs: setup
|
||||
strategy:
|
||||
matrix:
|
||||
runner: [windows-large, macos-12-xl]
|
||||
runner: [windows-large, macos-12-large]
|
||||
configuration: ${{ fromJSON(needs.setup.outputs.configurations) }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
outputs:
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ jobs:
|
|||
steps:
|
||||
- name: CLA Assistant
|
||||
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
|
||||
uses: secondlife-3p/contributor-assistant@v2
|
||||
uses: secondlife-3p/contributor-assistant@v2.6.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PERSONAL_ACCESS_TOKEN: ${{ secrets.SHARED_CLA_TOKEN }}
|
||||
|
|
|
|||
|
|
@ -2386,11 +2386,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>c16deaf773cb2a5d001732122ee3ec74db1dceeb</string>
|
||||
<string>76444e37be0cfccdbb5921370ba150ded2bf3c59</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.0.ea12248/openjpeg-2.5.0.ea12248-darwin64-ea12248.tar.zst</string>
|
||||
<string>https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.2-r1/openjpeg-2.5.2.10604495243-darwin64-10604495243.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
|
|
@ -2400,11 +2400,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>8c277dde6076fb682cb07264dd70f6f2298b633f</string>
|
||||
<string>6bd289a9c4564b80369ce40ecbb24a213c2732ff</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.0.ea12248/openjpeg-2.5.0.ea12248-linux64-ea12248.tar.zst</string>
|
||||
<string>https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.2-r1/openjpeg-2.5.2.10604495243-linux64-10604495243.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
|
|
@ -2414,11 +2414,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>2abf9535adf21ebdf2295f8a680300432abe6280</string>
|
||||
<string>5e6e0180adc01e07438cb98daec96543b5d85019</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.0.ea12248/openjpeg-2.5.0.ea12248-windows64-ea12248.tar.zst</string>
|
||||
<string>https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.2-r1/openjpeg-2.5.2.10604495243-windows64-10604495243.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
|
|
@ -2497,6 +2497,68 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors</string>
|
|||
<key>description</key>
|
||||
<string>Secure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) Library</string>
|
||||
</map>
|
||||
<key>openxr</key>
|
||||
<map>
|
||||
<key>platforms</key>
|
||||
<map>
|
||||
<key>windows64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>3cccc3e3f3137066c286270b35abc00ee0c0bb0c</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-openxr/releases/download/v1.1.40-r1/openxr-1.1.40-r1-windows64-10710818432.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows64</string>
|
||||
</map>
|
||||
<key>linux64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>f0ad0418a98fb8cb6e158fca3902c15ac1de9d2a</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-openxr/releases/download/v1.1.40-r1/openxr-1.1.40-r1-linux64-10710818432.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>linux64</string>
|
||||
</map>
|
||||
<key>darwin64</key>
|
||||
<map>
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>a9bfabec63a987bd34bcfdc295b928bd0696e1d7</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>sha1</string>
|
||||
<key>url</key>
|
||||
<string>https://github.com/secondlife/3p-openxr/releases/download/v1.1.40-r1/openxr-1.1.40-r1-darwin64-10710818432.tar.zst</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>darwin64</string>
|
||||
</map>
|
||||
</map>
|
||||
<key>license</key>
|
||||
<string>Apache 2.0</string>
|
||||
<key>license_file</key>
|
||||
<string>LICENSES/openxr.txt</string>
|
||||
<key>copyright</key>
|
||||
<string>Copyright 2017-2024, The Khronos Group Inc.</string>
|
||||
<key>version</key>
|
||||
<string>1.1.40-r1</string>
|
||||
<key>name</key>
|
||||
<string>openxr</string>
|
||||
<key>canonical_repo</key>
|
||||
<string>https://github.com/secondlife/3p-openxr</string>
|
||||
<key>description</key>
|
||||
<string>Generated headers and sources for OpenXR loader.</string>
|
||||
</map>
|
||||
<key>pcre</key>
|
||||
<map>
|
||||
<key>platforms</key>
|
||||
|
|
|
|||
9
build.sh
9
build.sh
|
|
@ -514,15 +514,6 @@ then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Some of the uploads takes a long time to finish in the codeticket backend,
|
||||
# causing the next codeticket upload attempt to fail.
|
||||
# Inserting this after each potentially large upload may prevent those errors.
|
||||
# JJ is making changes to Codeticket that we hope will eliminate this failure, then this can be removed
|
||||
wait_for_codeticket()
|
||||
{
|
||||
sleep $(( 60 * 6 ))
|
||||
}
|
||||
|
||||
# check status and upload results to S3
|
||||
if $succeeded
|
||||
then
|
||||
|
|
|
|||
|
|
@ -1216,6 +1216,7 @@ PanteraPolnocy
|
|||
SL-18937
|
||||
SL-19207
|
||||
SL-19681
|
||||
secondlife/viewer#2483
|
||||
Parvati Silverweb
|
||||
Patric Mills
|
||||
VWR-2645
|
||||
|
|
|
|||
|
|
@ -84,9 +84,12 @@ if (WINDOWS)
|
|||
/NODEFAULTLIB:LIBCMT
|
||||
/IGNORE:4099)
|
||||
|
||||
add_definitions(
|
||||
-DNOMINMAX
|
||||
# /DDOM_DYNAMIC # For shared library colladadom
|
||||
add_compile_definitions(
|
||||
WIN32_LEAN_AND_MEAN
|
||||
NOMINMAX
|
||||
# DOM_DYNAMIC # For shared library colladadom
|
||||
_CRT_SECURE_NO_WARNINGS # Allow use of sprintf etc
|
||||
_WINSOCK_DEPRECATED_NO_WARNINGS # Disable deprecated WinSock API warnings
|
||||
)
|
||||
add_compile_options(
|
||||
/Zo
|
||||
|
|
@ -132,9 +135,6 @@ if (WINDOWS)
|
|||
string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
endif()
|
||||
|
||||
# Allow use of sprintf etc
|
||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||
endif (WINDOWS)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ set(cmake_SOURCE_FILES
|
|||
FreeType.cmake
|
||||
GLEXT.cmake
|
||||
GLH.cmake
|
||||
GLM.cmake
|
||||
GLOD.cmake # <FS:Ansariel> Bring back GLOD
|
||||
Havok.cmake
|
||||
Hunspell.cmake
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
# -*- cmake -*-
|
||||
|
||||
include(Prebuilt)
|
||||
|
||||
include_guard()
|
||||
add_library( ll::openxr INTERFACE IMPORTED )
|
||||
|
||||
if(USE_CONAN )
|
||||
target_link_libraries( ll::openxr INTERFACE CONAN_PKG::openxr )
|
||||
return()
|
||||
endif()
|
||||
|
||||
use_prebuilt_binary(openxr)
|
||||
if (WINDOWS)
|
||||
target_link_libraries( ll::openxr INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/openxr_loader.lib )
|
||||
else()
|
||||
target_link_libraries( ll::openxr INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libopenxr_loader.a )
|
||||
endif (WINDOWS)
|
||||
|
||||
if( NOT LINUX )
|
||||
target_include_directories( ll::openxr SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
|
||||
endif()
|
||||
|
|
@ -6,7 +6,7 @@ add_library( ll::tracy INTERFACE IMPORTED )
|
|||
|
||||
# default Tracy profiling on for test builds, but off for all others
|
||||
string(TOLOWER ${VIEWER_CHANNEL} channel_lower)
|
||||
if(WINDOWS AND channel_lower MATCHES "^second life test")
|
||||
if(channel_lower MATCHES "^second life test")
|
||||
option(USE_TRACY "Use Tracy profiler." ON)
|
||||
else()
|
||||
option(USE_TRACY "Use Tracy profiler." OFF)
|
||||
|
|
@ -30,6 +30,11 @@ if (USE_TRACY)
|
|||
target_compile_definitions(ll::tracy INTERFACE -DTRACY_NO_BROADCAST=1 -DTRACY_ONLY_LOCALHOST=1)
|
||||
endif ()
|
||||
|
||||
# GHA runners don't always provide invariant TSC support, but always build with LL_TESTS enabled
|
||||
if (DARWIN AND LL_TESTS)
|
||||
target_compile_definitions(ll::tracy INTERFACE -DTRACY_TIMER_FALLBACK=1)
|
||||
endif ()
|
||||
|
||||
# See: indra/llcommon/llprofiler.h
|
||||
add_compile_definitions(LL_PROFILER_CONFIGURATION=3)
|
||||
endif (USE_TRACY)
|
||||
|
|
|
|||
|
|
@ -656,7 +656,7 @@ class LLManifest(object, metaclass=LLManifestRegistry):
|
|||
'vers':'_'.join(self.args['version'])}
|
||||
print("Creating unpacked file:", unpacked_file_name)
|
||||
# could add a gz here but that doubles the time it takes to do this step
|
||||
tf = tarfile.open(self.src_path_of(unpacked_file_name), 'w:')
|
||||
tf = tarfile.open(self.build_path_of(unpacked_file_name), 'w:')
|
||||
# add the entire installation package, at the very top level
|
||||
tf.add(self.get_dst_prefix(), "")
|
||||
tf.close()
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@
|
|||
#include "llavatarappearancedefines.h"
|
||||
#include "indra_constants.h"
|
||||
|
||||
const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH = 1024;
|
||||
const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT = 1024;
|
||||
const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_WIDTH = 2048;
|
||||
const S32 LLAvatarAppearanceDefines::SCRATCH_TEX_HEIGHT = 2048;
|
||||
|
||||
using namespace LLAvatarAppearanceDefines;
|
||||
|
||||
|
|
|
|||
|
|
@ -2429,9 +2429,15 @@ void LLKeyframeMotion::onLoadComplete(const LLUUID& asset_uuid,
|
|||
LLCharacter* character = *char_iter;
|
||||
|
||||
// look for an existing instance of this motion
|
||||
LLKeyframeMotion* motionp = static_cast<LLKeyframeMotion*> (character->findMotion(asset_uuid));
|
||||
if (motionp)
|
||||
if (LLMotion* asset = character->findMotion(asset_uuid))
|
||||
{
|
||||
LLKeyframeMotion* motionp = dynamic_cast<LLKeyframeMotion*>(asset);
|
||||
if (!motionp)
|
||||
{
|
||||
// This motion is not LLKeyframeMotion (e.g., LLEmote)
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 == status)
|
||||
{
|
||||
if (motionp->mAssetStatus == ASSET_LOADED)
|
||||
|
|
|
|||
|
|
@ -119,6 +119,7 @@ set(llcommon_HEADER_FILES
|
|||
commoncontrol.h
|
||||
ctype_workaround.h
|
||||
fix_macros.h
|
||||
fsyspath.h
|
||||
function_types.h
|
||||
indra_constants.h
|
||||
lazyeventapi.h
|
||||
|
|
@ -240,7 +241,6 @@ set(llcommon_HEADER_FILES
|
|||
lluriparser.h
|
||||
lluuid.h
|
||||
llwin32headers.h
|
||||
llwin32headerslean.h
|
||||
llworkerthread.h
|
||||
hbxxh.h
|
||||
lockstatic.h
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* @file fsyspath.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2024-04-03
|
||||
* @brief Adapt our UTF-8 std::strings for std::filesystem::path
|
||||
*
|
||||
* $LicenseInfo:firstyear=2024&license=viewerlgpl$
|
||||
* Copyright (c) 2024, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_FSYSPATH_H)
|
||||
#define LL_FSYSPATH_H
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
// While std::filesystem::path can be directly constructed from std::string on
|
||||
// both Posix and Windows, that's not what we want on Windows. Per
|
||||
// https://en.cppreference.com/w/cpp/filesystem/path/path:
|
||||
|
||||
// ... the method of conversion to the native character set depends on the
|
||||
// character type used by source.
|
||||
//
|
||||
// * If the source character type is char, the encoding of the source is
|
||||
// assumed to be the native narrow encoding (so no conversion takes place on
|
||||
// POSIX systems).
|
||||
// * If the source character type is char8_t, conversion from UTF-8 to native
|
||||
// filesystem encoding is used. (since C++20)
|
||||
// * If the source character type is wchar_t, the input is assumed to be the
|
||||
// native wide encoding (so no conversion takes places on Windows).
|
||||
|
||||
// The trouble is that on Windows, from std::string ("source character type is
|
||||
// char"), the "native narrow encoding" isn't UTF-8, so file paths containing
|
||||
// non-ASCII characters get mangled.
|
||||
//
|
||||
// Once we're building with C++20, we could pass a UTF-8 std::string through a
|
||||
// vector<char8_t> to engage std::filesystem::path's own UTF-8 conversion. But
|
||||
// sigh, as of 2024-04-03 we're not yet there.
|
||||
//
|
||||
// Anyway, encapsulating the important UTF-8 conversions in our own subclass
|
||||
// allows us to migrate forward to C++20 conventions without changing
|
||||
// referencing code.
|
||||
|
||||
class fsyspath: public std::filesystem::path
|
||||
{
|
||||
using super = std::filesystem::path;
|
||||
|
||||
public:
|
||||
// default
|
||||
fsyspath() {}
|
||||
// construct from UTF-8 encoded std::string
|
||||
fsyspath(const std::string& path): super(std::filesystem::u8path(path)) {}
|
||||
// construct from UTF-8 encoded const char*
|
||||
fsyspath(const char* path): super(std::filesystem::u8path(path)) {}
|
||||
// construct from existing path
|
||||
fsyspath(const super& path): super(path) {}
|
||||
|
||||
fsyspath& operator=(const super& p) { super::operator=(p); return *this; }
|
||||
fsyspath& operator=(const std::string& p)
|
||||
{
|
||||
super::operator=(std::filesystem::u8path(p));
|
||||
return *this;
|
||||
}
|
||||
fsyspath& operator=(const char* p)
|
||||
{
|
||||
super::operator=(std::filesystem::u8path(p));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// shadow base-class string() method with UTF-8 aware method
|
||||
std::string string() const { return super::u8string(); }
|
||||
// On Posix systems, where value_type is already char, this operator
|
||||
// std::string() method shadows the base class operator string_type()
|
||||
// method. But on Windows, where value_type is wchar_t, the base class
|
||||
// doesn't have operator std::string(). Provide it.
|
||||
operator std::string() const { return string(); }
|
||||
};
|
||||
|
||||
#endif /* ! defined(LL_FSYSPATH_H) */
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
/**
|
||||
* @file hexdump.h
|
||||
* @author Nat Goodspeed
|
||||
* @date 2023-10-03
|
||||
* @brief iostream manipulators to stream hex, or string with nonprinting chars
|
||||
*
|
||||
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
|
||||
* Copyright (c) 2023, Linden Research, Inc.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#if ! defined(LL_HEXDUMP_H)
|
||||
#define LL_HEXDUMP_H
|
||||
|
||||
#include <cctype>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string_view>
|
||||
|
||||
namespace LL
|
||||
{
|
||||
|
||||
// Format a given byte string as 2-digit hex values, no separators
|
||||
// Usage: std::cout << hexdump(somestring) << ...
|
||||
class hexdump
|
||||
{
|
||||
public:
|
||||
hexdump(const std::string_view& data):
|
||||
hexdump(data.data(), data.length())
|
||||
{}
|
||||
|
||||
hexdump(const char* data, size_t len):
|
||||
hexdump(reinterpret_cast<const unsigned char*>(data), len)
|
||||
{}
|
||||
|
||||
hexdump(const std::vector<unsigned char>& data):
|
||||
hexdump(data.data(), data.size())
|
||||
{}
|
||||
|
||||
hexdump(const unsigned char* data, size_t len):
|
||||
mData(data, data + len)
|
||||
{}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, const hexdump& self)
|
||||
{
|
||||
auto oldfmt{ out.flags() };
|
||||
auto oldfill{ out.fill() };
|
||||
out.setf(std::ios_base::hex, std::ios_base::basefield);
|
||||
out.fill('0');
|
||||
for (auto c : self.mData)
|
||||
{
|
||||
out << std::setw(2) << unsigned(c);
|
||||
}
|
||||
out.setf(oldfmt, std::ios_base::basefield);
|
||||
out.fill(oldfill);
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<unsigned char> mData;
|
||||
};
|
||||
|
||||
// Format a given byte string as a mix of printable characters and, for each
|
||||
// non-printable character, "\xnn"
|
||||
// Usage: std::cout << hexmix(somestring) << ...
|
||||
class hexmix
|
||||
{
|
||||
public:
|
||||
hexmix(const std::string_view& data):
|
||||
mData(data)
|
||||
{}
|
||||
|
||||
hexmix(const char* data, size_t len):
|
||||
mData(data, len)
|
||||
{}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& out, const hexmix& self)
|
||||
{
|
||||
auto oldfmt{ out.flags() };
|
||||
auto oldfill{ out.fill() };
|
||||
out.setf(std::ios_base::hex, std::ios_base::basefield);
|
||||
out.fill('0');
|
||||
for (auto c : self.mData)
|
||||
{
|
||||
// std::isprint() must be passed an unsigned char!
|
||||
if (std::isprint(static_cast<unsigned char>(c)))
|
||||
{
|
||||
out << c;
|
||||
}
|
||||
else
|
||||
{
|
||||
out << "\\x" << std::setw(2) << unsigned(c);
|
||||
}
|
||||
}
|
||||
out.setf(oldfmt, std::ios_base::basefield);
|
||||
out.fill(oldfill);
|
||||
return out;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string mData;
|
||||
};
|
||||
|
||||
} // namespace LL
|
||||
|
||||
#endif /* ! defined(LL_HEXDUMP_H) */
|
||||
|
|
@ -88,10 +88,6 @@ LLApp* LLApp::sApplication = NULL;
|
|||
// and disables crashlogger
|
||||
bool LLApp::sDisableCrashlogger = false;
|
||||
|
||||
// Local flag for whether or not to do logging in signal handlers.
|
||||
//static
|
||||
bool LLApp::sLogInSignal = true;
|
||||
|
||||
// static
|
||||
// Keeps track of application status
|
||||
LLScalarCond<LLApp::EAppStatus> LLApp::sStatus{LLApp::APP_STATUS_STOPPED};
|
||||
|
|
@ -226,7 +222,7 @@ bool LLApp::parseCommandOptions(int argc, wchar_t** wargv)
|
|||
if(wargv[ii][0] != '-')
|
||||
{
|
||||
LL_INFOS() << "Did not find option identifier while parsing token: "
|
||||
<< wargv[ii] << LL_ENDL;
|
||||
<< (intptr_t)wargv[ii] << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
int offset = 1;
|
||||
|
|
@ -602,6 +598,10 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)
|
|||
// We do the somewhat sketchy operation of blocking in here until the error handler
|
||||
// has gracefully stopped the app.
|
||||
|
||||
// FIXME(brad) - we are using this handler for asynchronous signals as well, so sLogInSignal is currently
|
||||
// disabled for safety. we need to find a way to selectively reenable it when it is safe.
|
||||
// see issue secondlife/viewer#2566
|
||||
|
||||
if (LLApp::sLogInSignal)
|
||||
{
|
||||
LL_INFOS() << "Signal handler - Got signal " << signum << " - " << apr_signal_description_get(signum) << LL_ENDL;
|
||||
|
|
|
|||
|
|
@ -339,8 +339,12 @@ private:
|
|||
friend void default_unix_signal_handler(int signum, siginfo_t *info, void *);
|
||||
#endif
|
||||
|
||||
public:
|
||||
static bool sLogInSignal;
|
||||
private:
|
||||
#ifdef LL_RELEASE_FOR_DOWNLOAD
|
||||
static constexpr bool sLogInSignal = false;
|
||||
#else
|
||||
static constexpr bool sLogInSignal = true;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // LL_LLAPP_H
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#endif
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llwin32headers.h"
|
||||
#include "apr_thread_proc.h"
|
||||
#include "apr_getopt.h"
|
||||
#include "apr_signal.h"
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ void* ll_tracy_new(size_t size)
|
|||
{
|
||||
throw std::bad_alloc();
|
||||
}
|
||||
TracyAlloc(ptr, size);
|
||||
LL_PROFILE_ALLOC(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +71,7 @@ void* operator new[](std::size_t count)
|
|||
|
||||
void ll_tracy_delete(void* ptr)
|
||||
{
|
||||
TracyFree(ptr);
|
||||
LL_PROFILE_FREE(ptr);
|
||||
if (gProfilerEnabled)
|
||||
{
|
||||
//LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
|
||||
|
|
@ -103,13 +103,13 @@ void operator delete[](void* ptr) noexcept
|
|||
void *tracy_aligned_malloc(size_t size, size_t alignment)
|
||||
{
|
||||
auto ptr = ll_aligned_malloc_fallback(size, alignment);
|
||||
if (ptr) TracyAlloc(ptr, size);
|
||||
if (ptr) LL_PROFILE_ALLOC(ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void tracy_aligned_free(void *memblock)
|
||||
{
|
||||
TracyFree(memblock);
|
||||
LL_PROFILE_FREE(memblock);
|
||||
ll_aligned_free_fallback(memblock);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ namespace {
|
|||
virtual void recordMessage(LLError::ELevel level,
|
||||
const std::string& message) override
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_LOGGING;
|
||||
int syslogPriority = LOG_CRIT;
|
||||
switch (level) {
|
||||
case LLError::LEVEL_DEBUG: syslogPriority = LOG_DEBUG; break;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include "stringize.h"
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llwin32headers.h"
|
||||
#include <stdlib.h> // Windows errno
|
||||
#include <vector>
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -89,10 +89,10 @@ private:
|
|||
}
|
||||
// Given arbitrary CALLABLE, which might be a lambda, how are we
|
||||
// supposed to obtain its signature for std::packaged_task? It seems
|
||||
// redundant to have to add an argument list to engage result_of, then
|
||||
// redundant to have to add an argument list to engage invoke_result_t, then
|
||||
// add the argument list again to complete the signature. At least we
|
||||
// only support a nullary CALLABLE.
|
||||
std::packaged_task<typename std::result_of<CALLABLE()>::type()> mTask;
|
||||
std::packaged_task<std::invoke_result_t<CALLABLE>()> mTask;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -68,10 +68,6 @@ documentation and/or software.
|
|||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llmd5.h"
|
||||
|
|
@ -81,232 +77,203 @@ documentation and/or software.
|
|||
// how many bytes to grab at a time when checking files
|
||||
const int LLMD5::BLOCK_LEN = 4096;
|
||||
|
||||
|
||||
// LLMD5 simple initialization method
|
||||
|
||||
LLMD5::LLMD5()
|
||||
{
|
||||
init();
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// MD5 block update operation. Continues an MD5 message-digest
|
||||
// operation, processing another message block, and updating the
|
||||
// context.
|
||||
void LLMD5::update(const uint8_t* input, const size_t input_length)
|
||||
{
|
||||
size_t input_index, buffer_index;
|
||||
size_t buffer_space; // how much space is left in buffer
|
||||
|
||||
void LLMD5::update (const uint8_t *input, const size_t input_length) {
|
||||
if (finalized)
|
||||
{ // so we can't update!
|
||||
std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t input_index, buffer_index;
|
||||
size_t buffer_space; // how much space is left in buffer
|
||||
// Compute number of bytes mod 64
|
||||
buffer_index = size_t((count >> 3) & 0x3F);
|
||||
|
||||
if (finalized){ // so we can't update!
|
||||
std::cerr << "LLMD5::update: Can't update a finalized digest!" << std::endl;
|
||||
return;
|
||||
}
|
||||
// Update number of bits
|
||||
count += input_length << 3;
|
||||
|
||||
// Compute number of bytes mod 64
|
||||
buffer_index = size_t((count >> 3) & 0x3F);
|
||||
buffer_space = 64 - buffer_index; // how much space is left in buffer
|
||||
|
||||
// Update number of bits
|
||||
count += input_length << 3;
|
||||
// now, transform each 64-byte piece of the input, bypassing the buffer
|
||||
if (input == NULL || input_length == 0)
|
||||
{
|
||||
std::cerr << "LLMD5::update: Invalid input!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
buffer_space = 64 - buffer_index; // how much space is left in buffer
|
||||
// Transform as many times as possible.
|
||||
if (input_length >= buffer_space) // ie. we have enough to fill the buffer
|
||||
{
|
||||
// fill the rest of the buffer and transform
|
||||
memcpy(/* Flawfinder: ignore */
|
||||
buffer + buffer_index,
|
||||
input,
|
||||
buffer_space);
|
||||
transform(buffer);
|
||||
|
||||
// now, transform each 64-byte piece of the input, bypassing the buffer
|
||||
if (input == NULL || input_length == 0){
|
||||
std::cerr << "LLMD5::update: Invalid input!" << std::endl;
|
||||
return;
|
||||
}
|
||||
for (input_index = buffer_space; input_index + 63 < input_length; input_index += 64)
|
||||
transform(input + input_index);
|
||||
|
||||
// Transform as many times as possible.
|
||||
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
|
||||
// fill the rest of the buffer and transform
|
||||
memcpy( /* Flawfinder: ignore */
|
||||
buffer + buffer_index,
|
||||
input,
|
||||
buffer_space);
|
||||
transform (buffer);
|
||||
buffer_index = 0; // so we can buffer remaining
|
||||
}
|
||||
else
|
||||
input_index = 0; // so we can buffer the whole input
|
||||
|
||||
for (input_index = buffer_space; input_index + 63 < input_length;
|
||||
input_index += 64)
|
||||
transform (input+input_index);
|
||||
|
||||
buffer_index = 0; // so we can buffer remaining
|
||||
}
|
||||
else
|
||||
input_index=0; // so we can buffer the whole input
|
||||
|
||||
|
||||
// and here we do the buffering:
|
||||
memcpy(buffer+buffer_index, input+input_index, input_length-input_index); /* Flawfinder: ignore */
|
||||
// and here we do the buffering:
|
||||
memcpy(buffer + buffer_index, input + input_index, input_length - input_index); /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MD5 update for files.
|
||||
// Like above, except that it works on files (and uses above as a primitive.)
|
||||
void LLMD5::update(FILE* file)
|
||||
{
|
||||
unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
|
||||
int len;
|
||||
|
||||
void LLMD5::update(FILE* file){
|
||||
|
||||
unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
|
||||
int len;
|
||||
|
||||
while ( (len=(int)fread(buffer, 1, BLOCK_LEN, file)) )
|
||||
update(buffer, len);
|
||||
|
||||
fclose (file);
|
||||
while ((len = (int)fread(buffer, 1, BLOCK_LEN, file)))
|
||||
update(buffer, len);
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// MD5 update for istreams.
|
||||
// Like update for files; see above.
|
||||
void LLMD5::update(std::istream& stream)
|
||||
{
|
||||
unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
|
||||
int len;
|
||||
|
||||
void LLMD5::update(std::istream& stream){
|
||||
|
||||
unsigned char buffer[BLOCK_LEN]; /* Flawfinder: ignore */
|
||||
int len;
|
||||
|
||||
while (stream.good()){
|
||||
stream.read( (char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable.
|
||||
len=(int)stream.gcount();
|
||||
update(buffer, len);
|
||||
}
|
||||
|
||||
while (stream.good())
|
||||
{
|
||||
stream.read((char*)buffer, BLOCK_LEN); /* Flawfinder: ignore */ // note that return value of read is unusable.
|
||||
len = (int)stream.gcount();
|
||||
update(buffer, len);
|
||||
}
|
||||
}
|
||||
|
||||
void LLMD5::update(const std::string& s)
|
||||
void LLMD5::update(const std::string& s)
|
||||
{
|
||||
update((unsigned char *)s.c_str(),s.length());
|
||||
update((unsigned char*)s.c_str(), s.length());
|
||||
}
|
||||
|
||||
// MD5 finalization. Ends an MD5 message-digest operation, writing the
|
||||
// the message digest and zeroizing the context.
|
||||
|
||||
|
||||
void LLMD5::finalize (){
|
||||
|
||||
unsigned char bits[8]; /* Flawfinder: ignore */
|
||||
size_t index, padLen;
|
||||
static uint8_t PADDING[64]={
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
void LLMD5::finalize()
|
||||
{
|
||||
unsigned char bits[8]; /* Flawfinder: ignore */
|
||||
size_t index, padLen;
|
||||
static uint8_t PADDING[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
if (finalized){
|
||||
std::cerr << "LLMD5::finalize: Already finalized this digest!" << std::endl;
|
||||
return;
|
||||
}
|
||||
if (finalized)
|
||||
{
|
||||
std::cerr << "LLMD5::finalize: Already finalized this digest!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Save number of bits.
|
||||
// Treat count, a uint64_t, as uint32_t[2].
|
||||
encode (bits, reinterpret_cast<uint32_t*>(&count), 8);
|
||||
// Save number of bits.
|
||||
// Treat count, a uint64_t, as uint32_t[2].
|
||||
encode(bits, reinterpret_cast<uint32_t*>(&count), 8);
|
||||
|
||||
// Pad out to 56 mod 64.
|
||||
index = size_t((count >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
update (PADDING, padLen);
|
||||
// Pad out to 56 mod 64.
|
||||
index = size_t((count >> 3) & 0x3f);
|
||||
padLen = (index < 56) ? (56 - index) : (120 - index);
|
||||
update(PADDING, padLen);
|
||||
|
||||
// Append length (before padding)
|
||||
update (bits, 8);
|
||||
// Append length (before padding)
|
||||
update(bits, 8);
|
||||
|
||||
// Store state in digest
|
||||
encode (digest, state, 16);
|
||||
// Store state in digest
|
||||
encode(digest, state, 16);
|
||||
|
||||
// Zeroize sensitive information
|
||||
memset (buffer, 0, sizeof(*buffer));
|
||||
|
||||
finalized=1;
|
||||
// Zeroize sensitive information
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
finalized = true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LLMD5::LLMD5(FILE *file){
|
||||
|
||||
init(); // must be called be all constructors
|
||||
update(file);
|
||||
finalize ();
|
||||
LLMD5::LLMD5(FILE* file)
|
||||
{
|
||||
init(); // must be called be all constructors
|
||||
update(file);
|
||||
finalize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
LLMD5::LLMD5(std::istream& stream){
|
||||
|
||||
init(); // must called by all constructors
|
||||
update (stream);
|
||||
finalize();
|
||||
LLMD5::LLMD5(std::istream& stream)
|
||||
{
|
||||
init(); // must called by all constructors
|
||||
update(stream);
|
||||
finalize();
|
||||
}
|
||||
|
||||
// Digest a string of the format ("%s:%i" % (s, number))
|
||||
LLMD5::LLMD5(const unsigned char *string, const unsigned int number)
|
||||
LLMD5::LLMD5(const unsigned char* string, const unsigned int number)
|
||||
{
|
||||
const char *colon = ":";
|
||||
char tbuf[16]; /* Flawfinder: ignore */
|
||||
const char* colon = ":";
|
||||
char tbuf[16]; /* Flawfinder: ignore */
|
||||
init();
|
||||
update(string, (U32)strlen((const char *) string)); /* Flawfinder: ignore */
|
||||
update((const unsigned char *) colon, (U32)strlen(colon)); /* Flawfinder: ignore */
|
||||
snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */
|
||||
update((const unsigned char *) tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */
|
||||
update(string, (U32)strlen((const char*)string)); /* Flawfinder: ignore */
|
||||
update((const unsigned char*)colon, (U32)strlen(colon)); /* Flawfinder: ignore */
|
||||
snprintf(tbuf, sizeof(tbuf), "%i", number); /* Flawfinder: ignore */
|
||||
update((const unsigned char*)tbuf, (U32)strlen(tbuf)); /* Flawfinder: ignore */
|
||||
finalize();
|
||||
}
|
||||
|
||||
// Digest a string
|
||||
LLMD5::LLMD5(const unsigned char *s)
|
||||
LLMD5::LLMD5(const unsigned char* s)
|
||||
{
|
||||
init();
|
||||
update(s, (U32)strlen((const char *) s)); /* Flawfinder: ignore */
|
||||
update(s, (U32)strlen((const char*)s)); /* Flawfinder: ignore */
|
||||
finalize();
|
||||
}
|
||||
|
||||
void LLMD5::raw_digest(unsigned char *s) const
|
||||
void LLMD5::raw_digest(unsigned char* s) const
|
||||
{
|
||||
if (!finalized)
|
||||
{
|
||||
std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't "<<
|
||||
"finalized the digest!" << std::endl;
|
||||
std::cerr << "LLMD5::raw_digest: Can't get digest if you haven't "
|
||||
<< "finalized the digest!" << std::endl;
|
||||
s[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(s, digest, 16); /* Flawfinder: ignore */
|
||||
return;
|
||||
memcpy(s, digest, 16); /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LLMD5::hex_digest(char *s) const
|
||||
void LLMD5::hex_digest(char* s) const
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!finalized)
|
||||
{
|
||||
std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't "<<
|
||||
"finalized the digest!" <<std::endl;
|
||||
std::cerr << "LLMD5::hex_digest: Can't get digest if you haven't "
|
||||
<< "finalized the digest!" << std::endl;
|
||||
s[0] = '\0';
|
||||
return;
|
||||
}
|
||||
|
||||
for (i=0; i<16; i++)
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
sprintf(s+i*2, "%02x", digest[i]); /* Flawfinder: ignore */
|
||||
sprintf(s + i * 2, "%02x", digest[i]); /* Flawfinder: ignore */
|
||||
}
|
||||
|
||||
s[32]='\0';
|
||||
|
||||
return;
|
||||
s[32] = '\0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream &stream, LLMD5 context)
|
||||
std::ostream& operator<<(std::ostream& stream, const LLMD5& context)
|
||||
{
|
||||
char s[33]; /* Flawfinder: ignore */
|
||||
context.hex_digest(s);
|
||||
|
|
@ -320,7 +287,7 @@ bool operator==(const LLMD5& a, const LLMD5& b)
|
|||
unsigned char b_guts[16];
|
||||
a.raw_digest(a_guts);
|
||||
b.raw_digest(b_guts);
|
||||
if (memcmp(a_guts,b_guts,16)==0)
|
||||
if (memcmp(a_guts, b_guts, 16) == 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
|
|
@ -328,30 +295,27 @@ bool operator==(const LLMD5& a, const LLMD5& b)
|
|||
|
||||
bool operator!=(const LLMD5& a, const LLMD5& b)
|
||||
{
|
||||
return !(a==b);
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
// PRIVATE METHODS:
|
||||
void LLMD5::init()
|
||||
{
|
||||
finalized = false; // we just started!
|
||||
|
||||
void LLMD5::init(){
|
||||
finalized=0; // we just started!
|
||||
// Nothing counted, so count=0
|
||||
count = 0;
|
||||
|
||||
// Nothing counted, so count=0
|
||||
count = 0;
|
||||
|
||||
// Load magic initialization constants.
|
||||
state[0] = 0x67452301;
|
||||
state[1] = 0xefcdab89;
|
||||
state[2] = 0x98badcfe;
|
||||
state[3] = 0x10325476;
|
||||
// Load magic initialization constants.
|
||||
state[0] = 0x67452301;
|
||||
state[1] = 0xefcdab89;
|
||||
state[2] = 0x98badcfe;
|
||||
state[3] = 0x10325476;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Constants for MD5Transform routine.
|
||||
// Although we could use C++ style constants, defines are actually better,
|
||||
// since they let us easily evade scope clashes.
|
||||
|
||||
#define S11 7
|
||||
#define S12 12
|
||||
#define S13 17
|
||||
|
|
@ -381,153 +345,144 @@ void LLMD5::init(){
|
|||
|
||||
/* ROTATE_LEFT rotates x left n bits.
|
||||
*/
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
|
||||
Rotation is separate from addition to prevent recomputation.
|
||||
*/
|
||||
#define FF(a, b, c, d, x, s, ac) { \
|
||||
(a) += F ((b), (c), (d)) + (x) + (U32)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) { \
|
||||
(a) += G ((b), (c), (d)) + (x) + (U32)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) { \
|
||||
(a) += H ((b), (c), (d)) + (x) + (U32)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) { \
|
||||
(a) += I ((b), (c), (d)) + (x) + (U32)(ac); \
|
||||
(a) = ROTATE_LEFT ((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
|
||||
#define FF(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += F((b), (c), (d)) + (x) + (U32)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define GG(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += G((b), (c), (d)) + (x) + (U32)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define HH(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += H((b), (c), (d)) + (x) + (U32)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
#define II(a, b, c, d, x, s, ac) \
|
||||
{ \
|
||||
(a) += I((b), (c), (d)) + (x) + (U32)(ac); \
|
||||
(a) = ROTATE_LEFT((a), (s)); \
|
||||
(a) += (b); \
|
||||
}
|
||||
|
||||
// LLMD5 basic transformation. Transforms state based on block.
|
||||
void LLMD5::transform (const U8 block[64]){
|
||||
void LLMD5::transform(const U8 block[64])
|
||||
{
|
||||
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
|
||||
uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
|
||||
decode(x, block, 64);
|
||||
|
||||
decode (x, block, 64);
|
||||
assert(!finalized); // not just a user error, since the method is private
|
||||
|
||||
assert(!finalized); // not just a user error, since the method is private
|
||||
/* Round 1 */
|
||||
FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
|
||||
FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
|
||||
FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
|
||||
FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
|
||||
FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
|
||||
FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
|
||||
FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
|
||||
FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
|
||||
FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
|
||||
FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
|
||||
FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
|
||||
/* Round 1 */
|
||||
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
|
||||
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
|
||||
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
|
||||
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
|
||||
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
|
||||
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
|
||||
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
|
||||
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
|
||||
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
|
||||
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
|
||||
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
|
||||
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
|
||||
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
|
||||
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
|
||||
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
|
||||
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
|
||||
/* Round 2 */
|
||||
GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
|
||||
GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
|
||||
GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
|
||||
GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
|
||||
GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
|
||||
GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
|
||||
GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
|
||||
GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
|
||||
/* Round 2 */
|
||||
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
|
||||
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
|
||||
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
|
||||
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
|
||||
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
|
||||
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
|
||||
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
|
||||
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
|
||||
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
|
||||
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
|
||||
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
|
||||
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
|
||||
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
|
||||
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
|
||||
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
|
||||
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
|
||||
/* Round 3 */
|
||||
HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
|
||||
HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
|
||||
HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
|
||||
HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
|
||||
HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
|
||||
HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
|
||||
HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
|
||||
HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
|
||||
|
||||
/* Round 3 */
|
||||
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
|
||||
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
|
||||
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
|
||||
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
|
||||
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
|
||||
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
|
||||
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
|
||||
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
|
||||
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
|
||||
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
|
||||
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
|
||||
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
|
||||
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
|
||||
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
|
||||
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
|
||||
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
|
||||
/* Round 4 */
|
||||
II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
|
||||
II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
|
||||
II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
|
||||
II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
|
||||
II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
|
||||
II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
|
||||
II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
|
||||
II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
|
||||
II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
/* Round 4 */
|
||||
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
|
||||
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
|
||||
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
|
||||
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
|
||||
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
|
||||
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
|
||||
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
|
||||
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
|
||||
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
|
||||
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
|
||||
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
|
||||
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
|
||||
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
|
||||
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
|
||||
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
|
||||
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
|
||||
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
// Zeroize sensitive information.
|
||||
memset ( (uint8_t *) x, 0, sizeof(x));
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
|
||||
// Zeroize sensitive information.
|
||||
memset(x, 0, sizeof(x));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Encodes input (uint32_t) into output (unsigned char). Assumes len is
|
||||
// a multiple of 4.
|
||||
void LLMD5::encode (uint8_t *output, const uint32_t *input, const size_t len) {
|
||||
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4) {
|
||||
output[j] = (uint8_t) (input[i] & 0xff);
|
||||
output[j+1] = (uint8_t) ((input[i] >> 8) & 0xff);
|
||||
output[j+2] = (uint8_t) ((input[i] >> 16) & 0xff);
|
||||
output[j+3] = (uint8_t) ((input[i] >> 24) & 0xff);
|
||||
}
|
||||
void LLMD5::encode(uint8_t* output, const uint32_t* input, const size_t len)
|
||||
{
|
||||
for (size_t i = 0, j = 0; j < len; i++, j += 4)
|
||||
{
|
||||
output[j] = (uint8_t)(input[i] & 0xff);
|
||||
output[j + 1] = (uint8_t)((input[i] >> 8) & 0xff);
|
||||
output[j + 2] = (uint8_t)((input[i] >> 16) & 0xff);
|
||||
output[j + 3] = (uint8_t)((input[i] >> 24) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Decodes input (unsigned char) into output (uint32_t). Assumes len is
|
||||
// a multiple of 4.
|
||||
void LLMD5::decode (uint32_t *output, const uint8_t *input, const size_t len){
|
||||
|
||||
size_t i, j;
|
||||
|
||||
for (i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
|
||||
(((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
|
||||
void LLMD5::decode(uint32_t* output, const uint8_t* input, const size_t len)
|
||||
{
|
||||
for (size_t i = 0, j = 0; j < len; i++, j += 4)
|
||||
output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) |
|
||||
(((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -67,59 +67,57 @@ documentation and/or software.
|
|||
|
||||
*/
|
||||
|
||||
#include <cstdint> // uint32_t et al.
|
||||
#include <cstdint> // uint32_t et al.
|
||||
|
||||
// use for the raw digest output
|
||||
const int MD5RAW_BYTES = 16;
|
||||
|
||||
// use for outputting hex digests
|
||||
const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null
|
||||
const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null
|
||||
const int MD5HEX_STR_BYTES = 32; // message system fixed size
|
||||
|
||||
class LL_COMMON_API LLMD5 {
|
||||
// how many bytes to grab at a time when checking files
|
||||
static const int BLOCK_LEN;
|
||||
class LL_COMMON_API LLMD5
|
||||
{
|
||||
// how many bytes to grab at a time when checking files
|
||||
static const int BLOCK_LEN;
|
||||
|
||||
public:
|
||||
// methods for controlled operation:
|
||||
LLMD5 (); // simple initializer
|
||||
void update (const uint8_t *input, const size_t input_length);
|
||||
void update (std::istream& stream);
|
||||
void update (FILE *file);
|
||||
void update (const std::string& str);
|
||||
void finalize ();
|
||||
// methods for controlled operation:
|
||||
LLMD5(); // simple initializer
|
||||
void update(const uint8_t* input, const size_t input_length);
|
||||
void update(std::istream& stream);
|
||||
void update(FILE* file);
|
||||
void update(const std::string& str);
|
||||
void finalize();
|
||||
|
||||
// constructors for special circumstances. All these constructors finalize
|
||||
// the MD5 context.
|
||||
LLMD5 (const unsigned char *string); // digest string, finalize
|
||||
LLMD5 (std::istream& stream); // digest stream, finalize
|
||||
LLMD5 (FILE *file); // digest file, close, finalize
|
||||
LLMD5 (const unsigned char *string, const unsigned int number);
|
||||
// constructors for special circumstances. All these constructors finalize
|
||||
// the MD5 context.
|
||||
LLMD5(const unsigned char* string); // digest string, finalize
|
||||
LLMD5(std::istream& stream); // digest stream, finalize
|
||||
LLMD5(FILE* file); // digest file, close, finalize
|
||||
LLMD5(const unsigned char* string, const unsigned int number);
|
||||
|
||||
// methods to acquire finalized result
|
||||
void raw_digest(unsigned char *array) const; // provide 16-byte array for binary data
|
||||
void hex_digest(char *string) const; // provide 33-byte array for ascii-hex string
|
||||
// methods to acquire finalized result
|
||||
void raw_digest(unsigned char* array) const; // provide 16-byte array for binary data
|
||||
void hex_digest(char* string) const; // provide 33-byte array for ascii-hex string
|
||||
|
||||
friend LL_COMMON_API std::ostream& operator<< (std::ostream&, LLMD5 context);
|
||||
friend LL_COMMON_API std::ostream& operator<<(std::ostream&, const LLMD5& context);
|
||||
|
||||
private:
|
||||
// next, the private data:
|
||||
uint32_t state[4];
|
||||
uint64_t count; // number of *bits*, mod 2^64
|
||||
uint8_t buffer[64]; // input buffer
|
||||
uint8_t digest[16];
|
||||
bool finalized;
|
||||
|
||||
// last, the private methods, mostly static:
|
||||
void init(); // called by all constructors
|
||||
void transform(const uint8_t* buffer); // does the real update work. Note
|
||||
// that length is implied to be 64.
|
||||
|
||||
// next, the private data:
|
||||
uint32_t state[4];
|
||||
uint64_t count; // number of *bits*, mod 2^64
|
||||
uint8_t buffer[64]; // input buffer
|
||||
uint8_t digest[16];
|
||||
uint8_t finalized;
|
||||
|
||||
// last, the private methods, mostly static:
|
||||
void init (); // called by all constructors
|
||||
void transform (const uint8_t *buffer); // does the real update work. Note
|
||||
// that length is implied to be 64.
|
||||
|
||||
static void encode (uint8_t *dest, const uint32_t *src, const size_t length);
|
||||
static void decode (uint32_t *dest, const uint8_t *src, const size_t length);
|
||||
|
||||
static void encode(uint8_t* dest, const uint32_t* src, const size_t length);
|
||||
static void decode(uint32_t* dest, const uint8_t* src, const size_t length);
|
||||
};
|
||||
|
||||
LL_COMMON_API bool operator==(const LLMD5& a, const LLMD5& b);
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ inline void* ll_aligned_realloc_16(void* ptr, size_t size, size_t old_size) // r
|
|||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
#endif
|
||||
LL_PROFILE_ALLOC(ptr, size);
|
||||
LL_PROFILE_ALLOC(ret, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -194,6 +194,18 @@ public:
|
|||
mSharedMutex->unlock<SHARED>();
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
if (mSharedMutex)
|
||||
mSharedMutex->lock<SHARED>();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
if (mSharedMutex)
|
||||
mSharedMutex->unlock<SHARED>();
|
||||
}
|
||||
|
||||
private:
|
||||
LLSharedMutex* mSharedMutex;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -418,6 +418,17 @@ private:
|
|||
bool mStayUnique;
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
bool operator!=(Type* lhs, const LLPointer<Type>& rhs)
|
||||
{
|
||||
return (lhs != rhs.get());
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
bool operator==(Type* lhs, const LLPointer<Type>& rhs)
|
||||
{
|
||||
return (lhs == rhs.get());
|
||||
}
|
||||
|
||||
// boost hash adapter
|
||||
template <class Type>
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ namespace LLPredicate
|
|||
Rule()
|
||||
{}
|
||||
|
||||
void require(ENUM e, bool match)
|
||||
void mandate(ENUM e, bool match)
|
||||
{
|
||||
mRule.set(e, match);
|
||||
}
|
||||
|
|
@ -154,7 +154,7 @@ namespace LLPredicate
|
|||
return (mRule && value).someSet();
|
||||
}
|
||||
|
||||
bool requires(const Value<ENUM> value) const
|
||||
bool mandates(const Value<ENUM> value) const
|
||||
{
|
||||
return (mRule && value).someSet() && (!mRule && value).noneSet();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,15 +114,6 @@
|
|||
# define LL_THREAD_LOCAL __thread
|
||||
#endif
|
||||
|
||||
// Static linking with apr on windows needs to be declared.
|
||||
#if LL_WINDOWS && !LL_COMMON_LINK_SHARED
|
||||
#ifndef APR_DECLARE_STATIC
|
||||
#define APR_DECLARE_STATIC // For APR on Windows
|
||||
#endif
|
||||
#ifndef APU_DECLARE_STATIC
|
||||
#define APU_DECLARE_STATIC // For APR util on Windows
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
#define BOOST_REGEX_NO_LIB 1
|
||||
|
|
@ -135,13 +126,6 @@
|
|||
|
||||
// Deal with VC++ problems
|
||||
#if LL_MSVC
|
||||
#ifndef _CRT_SECURE_NO_WARNINGS
|
||||
#define _CRT_SECURE_NO_WARNINGS // disable warnings for methods considered unsafe
|
||||
#endif
|
||||
#ifndef _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS // disable deprecated WinSock API warnings
|
||||
#endif
|
||||
|
||||
// level 4 warnings that we need to disable:
|
||||
#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class
|
||||
#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#include "llinitparam.h"
|
||||
#include "llsdparam.h"
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llexception.h"
|
||||
#include "apr_thread_proc.h"
|
||||
#include <boost/ptr_container/ptr_vector.hpp>
|
||||
|
|
@ -38,7 +37,7 @@
|
|||
#include <iosfwd> // std::ostream
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "llwin32headerslean.h" // for HANDLE
|
||||
#include "llwin32headers.h" // for HANDLE
|
||||
#elif LL_LINUX
|
||||
#if defined(Status)
|
||||
#undef Status
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
//#include <memory>
|
||||
|
||||
#if LL_WINDOWS
|
||||
# include "llwin32headerslean.h"
|
||||
# include "llwin32headers.h"
|
||||
# define _interlockedbittestandset _renamed_interlockedbittestandset
|
||||
# define _interlockedbittestandreset _renamed_interlockedbittestandreset
|
||||
# include <intrin.h>
|
||||
|
|
@ -692,7 +692,8 @@ private:
|
|||
memset(cpu_vendor, 0, len);
|
||||
sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0);
|
||||
cpu_vendor[0x1f] = 0;
|
||||
setInfo(eVendor, cpu_vendor);
|
||||
// M series CPUs don't provide this field so if empty, just fall back to Apple.
|
||||
setInfo(eVendor, (cpu_vendor[0] != '\0') ? cpu_vendor : "Apple");
|
||||
|
||||
setInfo(eStepping, getSysctlInt("machdep.cpu.stepping"));
|
||||
setInfo(eModel, getSysctlInt("machdep.cpu.model"));
|
||||
|
|
|
|||
|
|
@ -61,12 +61,21 @@ LLSD LlsdFromJson(const boost::json::value& val)
|
|||
result = LLSD(val.as_bool());
|
||||
break;
|
||||
case boost::json::kind::array:
|
||||
{
|
||||
result = LLSD::emptyArray();
|
||||
for (const auto &element : val.as_array())
|
||||
const boost::json::array& array = val.as_array();
|
||||
size_t size = array.size();
|
||||
// allocate elements 0 .. (size() - 1) to avoid incremental allocation
|
||||
if (! array.empty())
|
||||
{
|
||||
result.append(LlsdFromJson(element));
|
||||
result[size - 1] = LLSD();
|
||||
}
|
||||
for (size_t i = 0; i < size; i++)
|
||||
{
|
||||
result[i] = (LlsdFromJson(array[i]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case boost::json::kind::object:
|
||||
result = LLSD::emptyMap();
|
||||
for (const auto& element : val.as_object())
|
||||
|
|
@ -106,6 +115,7 @@ boost::json::value LlsdToJson(const LLSD &val)
|
|||
case LLSD::TypeMap:
|
||||
{
|
||||
boost::json::object& obj = result.emplace_object();
|
||||
obj.reserve(val.size());
|
||||
for (const auto& llsd_dat : llsd::inMap(val))
|
||||
{
|
||||
obj[llsd_dat.first] = LlsdToJson(llsd_dat.second);
|
||||
|
|
@ -115,6 +125,7 @@ boost::json::value LlsdToJson(const LLSD &val)
|
|||
case LLSD::TypeArray:
|
||||
{
|
||||
boost::json::array& json_array = result.emplace_array();
|
||||
json_array.reserve(val.size());
|
||||
for (const auto& llsd_dat : llsd::inArray(val))
|
||||
{
|
||||
json_array.push_back(LlsdToJson(llsd_dat));
|
||||
|
|
@ -123,7 +134,8 @@ boost::json::value LlsdToJson(const LLSD &val)
|
|||
}
|
||||
case LLSD::TypeBinary:
|
||||
default:
|
||||
LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type (" << val.type() << ")." << LL_ENDL;
|
||||
LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type ("
|
||||
<< val.type() << ")." << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,7 @@
|
|||
#include <sstream>
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h> // for htonl
|
||||
# include "llwin32headers.h" // for htonl
|
||||
#elif LL_LINUX
|
||||
# include <netinet/in.h>
|
||||
#elif LL_DARWIN
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llwin32headers.h"
|
||||
#include <dbghelp.h>
|
||||
|
||||
typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
|
||||
|
|
|
|||
|
|
@ -41,6 +41,13 @@ public:
|
|||
LLStrider(Object* first) { mObjectp = first; mSkip = sizeof(Object); }
|
||||
~LLStrider() { }
|
||||
|
||||
const LLStrider<Object>& operator=(const LLStrider<Object>& rhs)
|
||||
{
|
||||
mBytep = rhs.mBytep;
|
||||
mSkip = rhs.mSkip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const LLStrider<Object>& operator = (Object *first) { mObjectp = first; return *this;}
|
||||
void setStride (S32 skipBytes) { mSkip = (skipBytes ? skipBytes : sizeof(Object));}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,8 +33,7 @@
|
|||
#include <vector>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "llwin32headerslean.h"
|
||||
#include <winnls.h> // for WideCharToMultiByte
|
||||
#include "llwin32headers.h"
|
||||
#endif
|
||||
|
||||
std::string ll_safe_string(const char* in)
|
||||
|
|
@ -1482,6 +1481,14 @@ bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token
|
|||
template<>
|
||||
void LLStringUtil::setLocale(std::string inLocale)
|
||||
{
|
||||
if(startsWith(inLocale, "MissingString"))
|
||||
{
|
||||
// it seems this hasn't been working for some time, and I'm not sure how it is intentded to
|
||||
// properly discover the correct locale. early out now to avoid failures later in
|
||||
// formatNumber()
|
||||
LL_WARNS() << "Failed attempting to set invalid locale: " << inLocale << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
sLocale = inLocale;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
using namespace llsd;
|
||||
|
||||
#if LL_WINDOWS
|
||||
# include "llwin32headerslean.h"
|
||||
# include "llwin32headers.h"
|
||||
# include <psapi.h> // GetPerformanceInfo() et al.
|
||||
# include <VersionHelpers.h>
|
||||
#elif LL_DARWIN
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
#include <thread>
|
||||
|
||||
#if LL_WINDOWS
|
||||
# include "llwin32headerslean.h"
|
||||
# include "llwin32headers.h"
|
||||
#elif LL_LINUX || LL_DARWIN
|
||||
# include <errno.h>
|
||||
# include <sys/time.h>
|
||||
|
|
|
|||
|
|
@ -25,11 +25,8 @@
|
|||
|
||||
#include "linden_common.h"
|
||||
|
||||
// We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
|
||||
#if LL_WINDOWS
|
||||
#include "llwin32headers.h"
|
||||
// ugh, this is ugly. We need to straighten out our linking for this library
|
||||
#pragma comment(lib, "IPHLPAPI.lib")
|
||||
#include <iphlpapi.h>
|
||||
#include <nb30.h>
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,15 +28,8 @@
|
|||
#define LL_LLWINDOWS_H
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
// reset to default, which is lean
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#undef NOMINMAX
|
||||
#include <windows.h> // Does not include winsock.h because WIN32_LEAN_AND_MEAN is defined
|
||||
#include <winsock2.h> // Requires windows.h
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1085,7 +1085,27 @@ namespace tut
|
|||
return false;
|
||||
}
|
||||
|
||||
std::list<LLSD> mHistory;
|
||||
template <typename CALLABLE>
|
||||
void checkHistory(CALLABLE&& code)
|
||||
{
|
||||
try
|
||||
{
|
||||
// we expect this lambda to contain tut::ensure() calls
|
||||
std::forward<CALLABLE>(code)(mHistory);
|
||||
}
|
||||
catch (const failure&)
|
||||
{
|
||||
LL_INFOS() << "event history:" << LL_ENDL;
|
||||
for (const LLSD& item : mHistory)
|
||||
{
|
||||
LL_INFOS() << item << LL_ENDL;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
using Listory = std::list<LLSD>;
|
||||
Listory mHistory;
|
||||
LLTempBoundListener mConnection;
|
||||
};
|
||||
|
||||
|
|
@ -1136,23 +1156,26 @@ namespace tut
|
|||
// finish out the run
|
||||
waitfor(*py.mPy);
|
||||
// now verify history
|
||||
std::list<LLSD>::const_iterator li(listener.mHistory.begin()),
|
||||
lend(listener.mHistory.end());
|
||||
ensure("no events", li != lend);
|
||||
ensure_equals("history[0]", (*li)["data"].asString(), "abc");
|
||||
ensure_equals("history[0] len", (*li)["len"].asInteger(), 3);
|
||||
++li;
|
||||
ensure("only 1 event", li != lend);
|
||||
ensure_equals("history[1]", (*li)["data"].asString(), "abcdef");
|
||||
ensure_equals("history[0] len", (*li)["len"].asInteger(), 6);
|
||||
++li;
|
||||
ensure("only 2 events", li != lend);
|
||||
ensure_equals("history[2]", (*li)["data"].asString(), "abcdefghi" EOL);
|
||||
ensure_equals("history[0] len", (*li)["len"].asInteger(), 9 + sizeof(EOL) - 1);
|
||||
++li;
|
||||
// We DO NOT expect a whole new event for the second line because we
|
||||
// disconnected.
|
||||
ensure("more than 3 events", li == lend);
|
||||
listener.checkHistory(
|
||||
[](const EventListener::Listory& history)
|
||||
{
|
||||
auto li(history.begin()), lend(history.end());
|
||||
ensure("no events", li != lend);
|
||||
ensure_equals("history[0]", (*li)["data"].asString(), "abc");
|
||||
ensure_equals("history[0] len", (*li)["len"].asInteger(), 3);
|
||||
++li;
|
||||
ensure("only 1 event", li != lend);
|
||||
ensure_equals("history[1]", (*li)["data"].asString(), "abcdef");
|
||||
ensure_equals("history[0] len", (*li)["len"].asInteger(), 6);
|
||||
++li;
|
||||
ensure("only 2 events", li != lend);
|
||||
ensure_equals("history[2]", (*li)["data"].asString(), "abcdefghi" EOL);
|
||||
ensure_equals("history[0] len", (*li)["len"].asInteger(), 9 + sizeof(EOL) - 1);
|
||||
++li;
|
||||
// We DO NOT expect a whole new event for the second line because we
|
||||
// disconnected.
|
||||
ensure("more than 3 events", li == lend);
|
||||
});
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
|
|
@ -1172,14 +1195,17 @@ namespace tut
|
|||
// (or any other intervening layer) does crazy buffering. What we want
|
||||
// to ensure is that there was exactly ONE event with "eof" true, and
|
||||
// that it was the LAST event.
|
||||
std::list<LLSD>::const_reverse_iterator rli(listener.mHistory.rbegin()),
|
||||
rlend(listener.mHistory.rend());
|
||||
ensure("no events", rli != rlend);
|
||||
ensure("last event not \"eof\"", (*rli)["eof"].asBoolean());
|
||||
while (++rli != rlend)
|
||||
{
|
||||
ensure("\"eof\" event not last", ! (*rli)["eof"].asBoolean());
|
||||
}
|
||||
listener.checkHistory(
|
||||
[](const EventListener::Listory& history)
|
||||
{
|
||||
auto rli(history.rbegin()), rlend(history.rend());
|
||||
ensure("no events", rli != rlend);
|
||||
ensure("last event not \"eof\"", (*rli)["eof"].asBoolean());
|
||||
while (++rli != rlend)
|
||||
{
|
||||
ensure("\"eof\" event not last", ! (*rli)["eof"].asBoolean());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
|
|
@ -1202,13 +1228,17 @@ namespace tut
|
|||
ensure_equals("getLimit() after setlimit(10)", childout.getLimit(), 10);
|
||||
// okay, pump I/O to pick up output from child
|
||||
waitfor(*py.mPy);
|
||||
ensure("no events", ! listener.mHistory.empty());
|
||||
// For all we know, that data could have arrived in several different
|
||||
// bursts... probably not, but anyway, only check the last one.
|
||||
ensure_equals("event[\"len\"]",
|
||||
listener.mHistory.back()["len"].asInteger(), abc.length());
|
||||
ensure_equals("length of setLimit(10) data",
|
||||
listener.mHistory.back()["data"].asString().length(), 10);
|
||||
listener.checkHistory(
|
||||
[abc](const EventListener::Listory& history)
|
||||
{
|
||||
ensure("no events", ! history.empty());
|
||||
// For all we know, that data could have arrived in several different
|
||||
// bursts... probably not, but anyway, only check the last one.
|
||||
ensure_equals("event[\"len\"]",
|
||||
history.back()["len"].asInteger(), abc.length());
|
||||
ensure_equals("length of setLimit(10) data",
|
||||
history.back()["data"].asString().length(), 10);
|
||||
});
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
|
|
@ -1275,18 +1305,22 @@ namespace tut
|
|||
params.postend = pumpname;
|
||||
LLProcessPtr child = LLProcess::create(params);
|
||||
ensure("shouldn't have launched", ! child);
|
||||
ensure_equals("number of postend events", listener.mHistory.size(), 1);
|
||||
LLSD postend(listener.mHistory.front());
|
||||
ensure("has id", ! postend.has("id"));
|
||||
ensure_equals("desc", postend["desc"].asString(), std::string(params.desc));
|
||||
ensure_equals("state", postend["state"].asInteger(), LLProcess::UNSTARTED);
|
||||
ensure("has data", ! postend.has("data"));
|
||||
std::string error(postend["string"]);
|
||||
// All we get from canned parameter validation is a bool, so the
|
||||
// "validation failed" message we ourselves generate can't mention
|
||||
// "executable" by name. Just check that it's nonempty.
|
||||
//ensure_contains("error", error, "executable");
|
||||
ensure("string", ! error.empty());
|
||||
listener.checkHistory(
|
||||
[¶ms](const EventListener::Listory& history)
|
||||
{
|
||||
ensure_equals("number of postend events", history.size(), 1);
|
||||
LLSD postend(history.front());
|
||||
ensure("has id", ! postend.has("id"));
|
||||
ensure_equals("desc", postend["desc"].asString(), std::string(params.desc));
|
||||
ensure_equals("state", postend["state"].asInteger(), LLProcess::UNSTARTED);
|
||||
ensure("has data", ! postend.has("data"));
|
||||
std::string error(postend["string"]);
|
||||
// All we get from canned parameter validation is a bool, so the
|
||||
// "validation failed" message we ourselves generate can't mention
|
||||
// "executable" by name. Just check that it's nonempty.
|
||||
//ensure_contains("error", error, "executable");
|
||||
ensure("string", ! error.empty());
|
||||
});
|
||||
}
|
||||
|
||||
template<> template<>
|
||||
|
|
@ -1308,16 +1342,20 @@ namespace tut
|
|||
{
|
||||
yield();
|
||||
}
|
||||
ensure("no postend event", i < timeout);
|
||||
ensure_equals("number of postend events", listener.mHistory.size(), 1);
|
||||
LLSD postend(listener.mHistory.front());
|
||||
ensure_equals("id", postend["id"].asInteger(), childid);
|
||||
ensure("desc empty", ! postend["desc"].asString().empty());
|
||||
ensure_equals("state", postend["state"].asInteger(), LLProcess::EXITED);
|
||||
ensure_equals("data", postend["data"].asInteger(), 35);
|
||||
std::string str(postend["string"]);
|
||||
ensure_contains("string", str, "exited");
|
||||
ensure_contains("string", str, "35");
|
||||
listener.checkHistory(
|
||||
[i, timeout, childid](const EventListener::Listory& history)
|
||||
{
|
||||
ensure("no postend event", i < timeout);
|
||||
ensure_equals("number of postend events", history.size(), 1);
|
||||
LLSD postend(history.front());
|
||||
ensure_equals("id", postend["id"].asInteger(), childid);
|
||||
ensure("desc empty", ! postend["desc"].asString().empty());
|
||||
ensure_equals("state", postend["state"].asInteger(), LLProcess::EXITED);
|
||||
ensure_equals("data", postend["data"].asInteger(), 35);
|
||||
std::string str(postend["string"]);
|
||||
ensure_contains("string", str, "exited");
|
||||
ensure_contains("string", str, "35");
|
||||
});
|
||||
}
|
||||
|
||||
struct PostendListener
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ namespace tut
|
|||
op->setReplyPath(LLCore::HttpOperation::HttpReplyQueuePtr_t(), h1);
|
||||
|
||||
// Check ref count
|
||||
ensure(op.unique() == 1);
|
||||
ensure(op.use_count() == 1);
|
||||
|
||||
// release the reference, releasing the operation but
|
||||
// not the handlers.
|
||||
|
|
|
|||
|
|
@ -786,6 +786,8 @@ std::vector<std::string> LLDir::findSkinnedFilenames(const std::string& subdir,
|
|||
const std::string& filename,
|
||||
ESkinConstraint constraint) const
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
|
||||
|
||||
// Recognize subdirs that have no localization.
|
||||
static const std::set<std::string> sUnlocalized = list_of
|
||||
("") // top-level directory not localized
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ private:
|
|||
|
||||
public:
|
||||
template<bool SHARED>
|
||||
class DataLock : LLSharedMutexLockTemplate<SHARED>
|
||||
class DataLock : public LLSharedMutexLockTemplate<SHARED>
|
||||
{
|
||||
public:
|
||||
DataLock(const LLImageBase* image)
|
||||
|
|
|
|||
|
|
@ -276,16 +276,20 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r
|
|||
// Estimate the number of layers. This is consistent with what's done for j2c encoding in LLImageJ2CKDU::encodeImpl().
|
||||
constexpr S32 precision = 8; // assumed bitrate per component channel, might change in future for HDR support
|
||||
constexpr S32 max_components = 4; // assumed the file has four components; three color and alpha
|
||||
S32 nb_layers = 1;
|
||||
const S32 surface = w*h;
|
||||
S32 s = 64*64;
|
||||
S32 totalbytes = (S32)(s * max_components * precision * rate); // first level computed before loop
|
||||
while (surface > s)
|
||||
// Use MAX_IMAGE_SIZE_DEFAULT (currently 2048) if either dimension is unknown (zero)
|
||||
S32 width = (w > 0) ? w : 2048;
|
||||
S32 height = (h > 0) ? h : 2048;
|
||||
S32 max_dimension = llmax(width, height); // Find largest dimension
|
||||
S32 block_area = MAX_BLOCK_SIZE * MAX_BLOCK_SIZE; // Calculated initial block area from established max block size (currently 64)
|
||||
block_area *= llmax((max_dimension / MAX_BLOCK_SIZE / max_components), 1); // Adjust initial block area by ratio of largest dimension to block size per component
|
||||
S32 totalbytes = (S32) (block_area * max_components * precision); // First block layer computed before loop without compression rate
|
||||
S32 block_layers = 1; // Start at layer 1 since first block layer is computed outside loop
|
||||
while (block_layers < 6) // Walk five layers for the five discards in JPEG2000
|
||||
{
|
||||
if (nb_layers <= (5 - discard_level))
|
||||
totalbytes += (S32)(s * max_components * precision * rate);
|
||||
nb_layers++;
|
||||
s *= 4;
|
||||
if (block_layers <= (5 - discard_level)) // Walk backwards from discard 5 to required discard layer.
|
||||
totalbytes += (S32) (block_area * max_components * precision * rate); // Add each block layer reduced by assumed compression rate
|
||||
block_layers++; // Move to next layer
|
||||
block_area *= 4; // Increase block area by power of four
|
||||
}
|
||||
|
||||
totalbytes /= 8; // to bytes
|
||||
|
|
|
|||
|
|
@ -37,52 +37,52 @@ typedef U32 PermissionBit;
|
|||
// Do you have permission to transfer ownership of the object or
|
||||
// item. Fair use rules dictate that if you cannot copy, you can
|
||||
// always transfer.
|
||||
const PermissionBit PERM_TRANSFER = (1 << 13); // 0x00002000
|
||||
constexpr PermissionBit PERM_TRANSFER = (1 << 13); // 0x00002000
|
||||
|
||||
// objects, scale or change textures
|
||||
// parcels, allow building on it
|
||||
const PermissionBit PERM_MODIFY = (1 << 14); // 0x00004000
|
||||
constexpr PermissionBit PERM_MODIFY = (1 << 14); // 0x00004000
|
||||
|
||||
// objects, allow copy
|
||||
const PermissionBit PERM_COPY = (1 << 15); // 0x00008000
|
||||
constexpr PermissionBit PERM_COPY = (1 << 15); // 0x00008000
|
||||
|
||||
// <FS:CR> OpenSim export permission
|
||||
const PermissionBit PERM_EXPORT = (1 << 16); // 0x00010000
|
||||
// </FS:CR>
|
||||
|
||||
// parcels, allow entry, deprecated
|
||||
//const PermissionBit PERM_ENTER = (1 << 16); // 0x00010000
|
||||
//constexpr PermissionBit PERM_ENTER = (1 << 16); // 0x00010000
|
||||
|
||||
// parcels, allow terraform, deprecated
|
||||
//const PermissionBit PERM_TERRAFORM = (1 << 17); // 0x00020000
|
||||
//constexpr PermissionBit PERM_TERRAFORM = (1 << 17); // 0x00020000
|
||||
|
||||
// NOTA BENE: This flag is NO LONGER USED!!! However, it is possible that some
|
||||
// objects in the universe have it set so DON"T USE IT going forward.
|
||||
//const PermissionBit PERM_OWNER_DEBIT = (1 << 18); // 0x00040000
|
||||
//constexpr PermissionBit PERM_OWNER_DEBIT = (1 << 18); // 0x00040000
|
||||
|
||||
// objects, can grab/translate/rotate
|
||||
const PermissionBit PERM_MOVE = (1 << 19); // 0x00080000
|
||||
constexpr PermissionBit PERM_MOVE = (1 << 19); // 0x00080000
|
||||
|
||||
// parcels, avatars take damage, deprecated
|
||||
//const PermissionBit PERM_DAMAGE = (1 << 20); // 0x00100000
|
||||
|
||||
// don't use bit 31 -- printf/scanf with "%x" assume signed numbers
|
||||
const PermissionBit PERM_RESERVED = ((U32)1) << 31;
|
||||
constexpr PermissionBit PERM_RESERVED = ((U32)1) << 31;
|
||||
|
||||
const PermissionMask PERM_NONE = 0x00000000;
|
||||
const PermissionMask PERM_ALL = 0x7FFFFFFF;
|
||||
//const PermissionMask PERM_ALL_PARCEL = PERM_MODIFY | PERM_ENTER | PERM_TERRAFORM | PERM_DAMAGE;
|
||||
const PermissionMask PERM_ITEM_UNRESTRICTED = PERM_MODIFY | PERM_COPY | PERM_TRANSFER;
|
||||
constexpr PermissionMask PERM_NONE = 0x00000000;
|
||||
constexpr PermissionMask PERM_ALL = 0x7FFFFFFF;
|
||||
//constexpr PermissionMask PERM_ALL_PARCEL = PERM_MODIFY | PERM_ENTER | PERM_TERRAFORM | PERM_DAMAGE;
|
||||
constexpr PermissionMask PERM_ITEM_UNRESTRICTED = PERM_MODIFY | PERM_COPY | PERM_TRANSFER;
|
||||
|
||||
|
||||
// Useful stuff for transmission.
|
||||
// Which permissions field are we trying to change?
|
||||
const U8 PERM_BASE = 0x01;
|
||||
constexpr U8 PERM_BASE = 0x01;
|
||||
// TODO: Add another PERM_OWNER operation type for allowOperationBy DK 04/03/06
|
||||
const U8 PERM_OWNER = 0x02;
|
||||
const U8 PERM_GROUP = 0x04;
|
||||
const U8 PERM_EVERYONE = 0x08;
|
||||
const U8 PERM_NEXT_OWNER = 0x10;
|
||||
constexpr U8 PERM_OWNER = 0x02;
|
||||
constexpr U8 PERM_GROUP = 0x04;
|
||||
constexpr U8 PERM_EVERYONE = 0x08;
|
||||
constexpr U8 PERM_NEXT_OWNER = 0x10;
|
||||
|
||||
// This is just a quickie debugging key
|
||||
// no modify: PERM_ALL & ~PERM_MODIFY = 0x7fffbfff
|
||||
|
|
|
|||
|
|
@ -69,25 +69,99 @@ const U32 LLSettingsBase::Validator::VALIDATION_PARTIAL(0x01 << 0);
|
|||
LLSettingsBase::LLSettingsBase():
|
||||
mSettings(LLSD::emptyMap()),
|
||||
mDirty(true),
|
||||
mBlendedFactor(0.0)
|
||||
mLLSDDirty(true),
|
||||
mReplaced(false),
|
||||
mBlendedFactor(0.0),
|
||||
mSettingFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
LLSettingsBase::LLSettingsBase(const LLSD setting) :
|
||||
mSettings(setting),
|
||||
mLLSDDirty(true),
|
||||
mDirty(true),
|
||||
mBlendedFactor(0.0)
|
||||
mReplaced(false),
|
||||
mBlendedFactor(0.0),
|
||||
mSettingFlags(0)
|
||||
{
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLSettingsBase::loadValuesFromLLSD()
|
||||
{
|
||||
mLLSDDirty = false;
|
||||
|
||||
mAssetId = mSettings[SETTING_ASSETID].asUUID();
|
||||
mSettingId = getValue(SETTING_ID).asUUID();
|
||||
mSettingName = getValue(SETTING_NAME).asString();
|
||||
if (mSettings.has(SETTING_FLAGS))
|
||||
{
|
||||
mSettingFlags = (U32)mSettings[SETTING_FLAGS].asInteger();
|
||||
}
|
||||
else
|
||||
{
|
||||
mSettingFlags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//virtual
|
||||
void LLSettingsBase::saveValuesToLLSD()
|
||||
{
|
||||
mLLSDDirty = false;
|
||||
|
||||
mSettings[SETTING_NAME] = mSettingName;
|
||||
if (mAssetId.isNull())
|
||||
{
|
||||
mSettings.erase(SETTING_ASSETID);
|
||||
}
|
||||
else
|
||||
{
|
||||
mSettings[SETTING_ASSETID] = mAssetId;
|
||||
}
|
||||
mSettings[SETTING_FLAGS] = LLSD::Integer(mSettingFlags);
|
||||
}
|
||||
|
||||
void LLSettingsBase::saveValuesIfNeeded()
|
||||
{
|
||||
if (mLLSDDirty)
|
||||
{
|
||||
saveValuesToLLSD();
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void LLSettingsBase::lerpSettings(const LLSettingsBase &other, F64 mix)
|
||||
void LLSettingsBase::lerpSettings(LLSettingsBase &other, F64 mix)
|
||||
{
|
||||
mSettings = interpolateSDMap(mSettings, other.mSettings, other.getParameterMap(), mix);
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
|
||||
saveValuesIfNeeded();
|
||||
stringset_t skip = getSkipInterpolateKeys();
|
||||
stringset_t slerps = getSlerpKeys();
|
||||
mSettings = interpolateSDMap(mSettings, other.getSettings(), other.getParameterMap(), mix, skip, slerps);
|
||||
setDirtyFlag(true);
|
||||
loadValuesFromLLSD();
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::combineSDMaps(const LLSD &settings, const LLSD &other) const
|
||||
void LLSettingsBase::lerpVector2(LLVector2& a, const LLVector2& b, F32 mix)
|
||||
{
|
||||
a.mV[0] = lerp(a.mV[0], b.mV[0], mix);
|
||||
a.mV[1] = lerp(a.mV[1], b.mV[1], mix);
|
||||
}
|
||||
|
||||
void LLSettingsBase::lerpVector3(LLVector3& a, const LLVector3& b, F32 mix)
|
||||
{
|
||||
a.mV[0] = lerp(a.mV[0], b.mV[0], mix);
|
||||
a.mV[1] = lerp(a.mV[1], b.mV[1], mix);
|
||||
a.mV[2] = lerp(a.mV[2], b.mV[2], mix);
|
||||
}
|
||||
|
||||
void LLSettingsBase::lerpColor(LLColor3& a, const LLColor3& b, F32 mix)
|
||||
{
|
||||
a.mV[0] = lerp(a.mV[0], b.mV[0], mix);
|
||||
a.mV[1] = lerp(a.mV[1], b.mV[1], mix);
|
||||
a.mV[2] = lerp(a.mV[2], b.mV[2], mix);
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::combineSDMaps(const LLSD &settings, const LLSD &other)
|
||||
{
|
||||
LLSD newSettings;
|
||||
|
||||
|
|
@ -161,13 +235,10 @@ LLSD LLSettingsBase::combineSDMaps(const LLSD &settings, const LLSD &other) cons
|
|||
return newSettings;
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, F64 mix) const
|
||||
LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, F64 mix, const stringset_t& skip, const stringset_t& slerps)
|
||||
{
|
||||
LLSD newSettings;
|
||||
|
||||
stringset_t skip = getSkipInterpolateKeys();
|
||||
stringset_t slerps = getSlerpKeys();
|
||||
|
||||
llassert(mix >= 0.0f && mix <= 1.0f);
|
||||
|
||||
for (LLSD::map_const_iterator it = settings.beginMap(); it != settings.endMap(); ++it)
|
||||
|
|
@ -204,7 +275,7 @@ LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, c
|
|||
}
|
||||
}
|
||||
|
||||
newSettings[key_name] = interpolateSDValue(key_name, value, other_value, defaults, mix, slerps);
|
||||
newSettings[key_name] = interpolateSDValue(key_name, value, other_value, defaults, mix, skip, slerps);
|
||||
}
|
||||
|
||||
// Special handling cases
|
||||
|
|
@ -233,12 +304,12 @@ LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, c
|
|||
if (def_iter != defaults.end())
|
||||
{
|
||||
// Blend against default value
|
||||
newSettings[key_name] = interpolateSDValue(key_name, def_iter->second.getDefaultValue(), (*it).second, defaults, mix, slerps);
|
||||
newSettings[key_name] = interpolateSDValue(key_name, def_iter->second.getDefaultValue(), (*it).second, defaults, mix, skip, slerps);
|
||||
}
|
||||
else if ((*it).second.type() == LLSD::TypeMap)
|
||||
{
|
||||
// interpolate in case there are defaults inside (part of legacy)
|
||||
newSettings[key_name] = interpolateSDValue(key_name, LLSDMap(), (*it).second, defaults, mix, slerps);
|
||||
newSettings[key_name] = interpolateSDValue(key_name, LLSDMap(), (*it).second, defaults, mix, skip, slerps);
|
||||
}
|
||||
// else do nothing when no known defaults
|
||||
// TODO: Should I blend this out instead?
|
||||
|
|
@ -260,7 +331,7 @@ LLSD LLSettingsBase::interpolateSDMap(const LLSD &settings, const LLSD &other, c
|
|||
return newSettings;
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD &value, const LLSD &other_value, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const
|
||||
LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD &value, const LLSD &other_value, const parammapping_t& defaults, BlendFactor mix, const stringset_t& skip, const stringset_t& slerps)
|
||||
{
|
||||
LLSD new_value;
|
||||
|
||||
|
|
@ -286,7 +357,7 @@ LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD
|
|||
break;
|
||||
case LLSD::TypeMap:
|
||||
// deep copy.
|
||||
new_value = interpolateSDMap(value, other_value, defaults, mix);
|
||||
new_value = interpolateSDMap(value, other_value, defaults, mix, skip, slerps);
|
||||
break;
|
||||
|
||||
case LLSD::TypeArray:
|
||||
|
|
@ -348,21 +419,24 @@ LLSettingsBase::stringset_t LLSettingsBase::getSkipInterpolateKeys() const
|
|||
return skipSet;
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::getSettings() const
|
||||
LLSD& LLSettingsBase::getSettings()
|
||||
{
|
||||
saveValuesIfNeeded();
|
||||
return mSettings;
|
||||
}
|
||||
|
||||
LLSD LLSettingsBase::cloneSettings() const
|
||||
LLSD LLSettingsBase::cloneSettings()
|
||||
{
|
||||
U32 flags = getFlags();
|
||||
LLSD settings (combineSDMaps(getSettings(), LLSD()));
|
||||
if (flags)
|
||||
saveValuesIfNeeded();
|
||||
LLSD settings(combineSDMaps(getSettings(), LLSD()));
|
||||
if (U32 flags = getFlags())
|
||||
{
|
||||
settings[SETTING_FLAGS] = LLSD::Integer(flags);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
size_t LLSettingsBase::getHash() const
|
||||
size_t LLSettingsBase::getHash()
|
||||
{ // get a shallow copy of the LLSD filtering out values to not include in the hash
|
||||
LLSD hash_settings = llsd_shallow(getSettings(),
|
||||
LLSDMap(SETTING_NAME, false)(SETTING_ID, false)(SETTING_HASH, false)("*", true));
|
||||
|
|
@ -380,7 +454,9 @@ bool LLSettingsBase::validate()
|
|||
mSettings[SETTING_TYPE] = getSettingsType();
|
||||
}
|
||||
|
||||
saveValuesIfNeeded();
|
||||
LLSD result = LLSettingsBase::settingValidation(mSettings, validations);
|
||||
loadValuesFromLLSD();
|
||||
|
||||
if (result["errors"].size() > 0)
|
||||
{
|
||||
|
|
@ -710,7 +786,7 @@ F64 LLSettingsBlender::setBlendFactor(const LLSettingsBase::BlendFactor& blendf_
|
|||
|
||||
if (mTarget)
|
||||
{
|
||||
mTarget->replaceSettings(mInitial->getSettings());
|
||||
mTarget->replaceSettings(mInitial);
|
||||
mTarget->blend(mFinal, blendf);
|
||||
}
|
||||
else
|
||||
|
|
@ -725,7 +801,7 @@ void LLSettingsBlender::triggerComplete()
|
|||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
|
||||
if (mTarget)
|
||||
mTarget->replaceSettings(mFinal->getSettings());
|
||||
mTarget->replaceSettings(mFinal);
|
||||
LLSettingsBlender::ptr_t hold = shared_from_this(); // prevents this from deleting too soon
|
||||
mTarget->update();
|
||||
mOnFinished(shared_from_this());
|
||||
|
|
|
|||
|
|
@ -109,72 +109,59 @@ public:
|
|||
virtual bool isDirty() const { return mDirty; }
|
||||
virtual bool isVeryDirty() const { return mReplaced; }
|
||||
inline void setDirtyFlag(bool dirty) { mDirty = dirty; clearAssetId(); }
|
||||
inline void setReplaced() { mReplaced = true; }
|
||||
|
||||
size_t getHash() const; // Hash will not include Name, ID or a previously stored Hash
|
||||
size_t getHash(); // Hash will not include Name, ID or a previously stored Hash
|
||||
|
||||
inline LLUUID getId() const
|
||||
{
|
||||
return getValue(SETTING_ID).asUUID();
|
||||
return mSettingId;
|
||||
}
|
||||
|
||||
inline std::string getName() const
|
||||
{
|
||||
return getValue(SETTING_NAME).asString();
|
||||
return mSettingName;
|
||||
}
|
||||
|
||||
inline void setName(std::string val)
|
||||
{
|
||||
setValue(SETTING_NAME, val);
|
||||
mSettingName = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
inline LLUUID getAssetId() const
|
||||
{
|
||||
if (mSettings.has(SETTING_ASSETID))
|
||||
return mSettings[SETTING_ASSETID].asUUID();
|
||||
return LLUUID();
|
||||
return mAssetId;
|
||||
}
|
||||
|
||||
inline U32 getFlags() const
|
||||
{
|
||||
if (mSettings.has(SETTING_FLAGS))
|
||||
return static_cast<U32>(mSettings[SETTING_FLAGS].asInteger());
|
||||
return 0;
|
||||
return mSettingFlags;
|
||||
}
|
||||
|
||||
inline void setFlags(U32 value)
|
||||
{
|
||||
setLLSD(SETTING_FLAGS, LLSD::Integer(value));
|
||||
mSettingFlags = value;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
inline bool getFlag(U32 flag) const
|
||||
{
|
||||
if (mSettings.has(SETTING_FLAGS))
|
||||
return ((U32)mSettings[SETTING_FLAGS].asInteger() & flag) == flag;
|
||||
return false;
|
||||
return (mSettingFlags & flag) == flag;
|
||||
}
|
||||
|
||||
inline void setFlag(U32 flag)
|
||||
{
|
||||
U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0);
|
||||
|
||||
flags |= flag;
|
||||
|
||||
if (flags)
|
||||
mSettings[SETTING_FLAGS] = LLSD::Integer(flags);
|
||||
else
|
||||
mSettings.erase(SETTING_FLAGS);
|
||||
mSettingFlags |= flag;
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
inline void clearFlag(U32 flag)
|
||||
{
|
||||
U32 flags((mSettings.has(SETTING_FLAGS)) ? (U32)mSettings[SETTING_FLAGS].asInteger() : 0);
|
||||
|
||||
flags &= ~flag;
|
||||
|
||||
if (flags)
|
||||
mSettings[SETTING_FLAGS] = LLSD::Integer(flags);
|
||||
else
|
||||
mSettings.erase(SETTING_FLAGS);
|
||||
mSettingFlags &= ~flag;
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
virtual void replaceSettings(LLSD settings)
|
||||
|
|
@ -183,14 +170,41 @@ public:
|
|||
setDirtyFlag(true);
|
||||
mReplaced = true;
|
||||
mSettings = settings;
|
||||
loadValuesFromLLSD();
|
||||
}
|
||||
|
||||
virtual LLSD getSettings() const;
|
||||
virtual void replaceSettings(const ptr_t& other)
|
||||
{
|
||||
mBlendedFactor = 0.0;
|
||||
setDirtyFlag(true);
|
||||
mReplaced = true;
|
||||
mSettingFlags = other->getFlags();
|
||||
mSettingName = other->getName();
|
||||
mSettingId = other->getId();
|
||||
mAssetId = other->getAssetId();
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
void setSettings(LLSD settings)
|
||||
{
|
||||
setDirtyFlag(true);
|
||||
mSettings = settings;
|
||||
loadValuesFromLLSD();
|
||||
}
|
||||
|
||||
// if you are using getSettings to edit them, call setSettings(settings),
|
||||
// replaceSettings(settings) or loadValuesFromLLSD() afterwards
|
||||
virtual LLSD& getSettings();
|
||||
virtual void setLLSDDirty()
|
||||
{
|
||||
mLLSDDirty = true;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
inline void setLLSD(const std::string &name, const LLSD &value)
|
||||
{
|
||||
saveValuesIfNeeded();
|
||||
mSettings[name] = value;
|
||||
mDirty = true;
|
||||
if (name != SETTING_ASSETID)
|
||||
|
|
@ -202,8 +216,9 @@ public:
|
|||
setLLSD(name, value);
|
||||
}
|
||||
|
||||
inline LLSD getValue(const std::string &name, const LLSD &deflt = LLSD()) const
|
||||
inline LLSD getValue(const std::string &name, const LLSD &deflt = LLSD())
|
||||
{
|
||||
saveValuesIfNeeded();
|
||||
if (!mSettings.has(name))
|
||||
return deflt;
|
||||
return mSettings[name];
|
||||
|
|
@ -259,11 +274,11 @@ public:
|
|||
(const_cast<LLSettingsBase *>(this))->updateSettings();
|
||||
}
|
||||
|
||||
virtual void blend(const ptr_t &end, BlendFactor blendf) = 0;
|
||||
virtual void blend(ptr_t &end, BlendFactor blendf) = 0;
|
||||
|
||||
virtual bool validate();
|
||||
|
||||
virtual ptr_t buildDerivedClone() const = 0;
|
||||
virtual ptr_t buildDerivedClone() = 0;
|
||||
|
||||
class Validator
|
||||
{
|
||||
|
|
@ -310,17 +325,24 @@ public:
|
|||
|
||||
inline void setAssetId(LLUUID value)
|
||||
{ // note that this skips setLLSD
|
||||
mSettings[SETTING_ASSETID] = value;
|
||||
mAssetId = value;
|
||||
mLLSDDirty = true;
|
||||
}
|
||||
|
||||
inline void clearAssetId()
|
||||
{
|
||||
if (mSettings.has(SETTING_ASSETID))
|
||||
mSettings.erase(SETTING_ASSETID);
|
||||
mAssetId.setNull();
|
||||
mLLSDDirty = true;
|
||||
}
|
||||
|
||||
// Calculate any custom settings that may need to be cached.
|
||||
virtual void updateSettings() { mDirty = false; mReplaced = false; }
|
||||
LLSD cloneSettings();
|
||||
|
||||
static void lerpVector2(LLVector2& a, const LLVector2& b, F32 mix);
|
||||
static void lerpVector3(LLVector3& a, const LLVector3& b, F32 mix);
|
||||
static void lerpColor(LLColor3& a, const LLColor3& b, F32 mix);
|
||||
|
||||
protected:
|
||||
|
||||
LLSettingsBase();
|
||||
|
|
@ -331,7 +353,7 @@ protected:
|
|||
typedef std::set<std::string> stringset_t;
|
||||
|
||||
// combining settings objects. Customize for specific setting types
|
||||
virtual void lerpSettings(const LLSettingsBase &other, BlendFactor mix);
|
||||
virtual void lerpSettings(LLSettingsBase &other, BlendFactor mix);
|
||||
|
||||
// combining settings maps where it can based on mix rate
|
||||
// @settings initial value (mix==0)
|
||||
|
|
@ -339,8 +361,8 @@ protected:
|
|||
// @defaults list of default values for legacy fields and (re)setting shaders
|
||||
// @mix from 0 to 1, ratio or rate of transition from initial 'settings' to 'other'
|
||||
// return interpolated and combined LLSD map
|
||||
LLSD interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, BlendFactor mix) const;
|
||||
LLSD interpolateSDValue(const std::string& name, const LLSD &value, const LLSD &other, const parammapping_t& defaults, BlendFactor mix, const stringset_t& slerps) const;
|
||||
static LLSD interpolateSDMap(const LLSD &settings, const LLSD &other, const parammapping_t& defaults, BlendFactor mix, const stringset_t& skip, const stringset_t& slerps);
|
||||
static LLSD interpolateSDValue(const std::string& name, const LLSD &value, const LLSD &other, const parammapping_t& defaults, BlendFactor mix, const stringset_t& skip, const stringset_t& slerps);
|
||||
|
||||
/// when lerping between settings, some may require special handling.
|
||||
/// Get a list of these key to be skipped by the default settings lerp.
|
||||
|
|
@ -353,32 +375,40 @@ protected:
|
|||
|
||||
virtual validation_list_t getValidationList() const = 0;
|
||||
|
||||
// Apply any settings that need special handling.
|
||||
virtual void applySpecial(void *, bool force = false) { };
|
||||
// Apply settings.
|
||||
virtual void applyToUniforms(void *) { };
|
||||
virtual void applySpecial(void*, bool force = false) { };
|
||||
|
||||
virtual parammapping_t getParameterMap() const { return parammapping_t(); }
|
||||
|
||||
LLSD mSettings;
|
||||
|
||||
LLSD cloneSettings() const;
|
||||
|
||||
inline void setBlendFactor(BlendFactor blendfactor)
|
||||
{
|
||||
mBlendedFactor = blendfactor;
|
||||
}
|
||||
|
||||
void replaceWith(LLSettingsBase::ptr_t other)
|
||||
virtual void replaceWith(const LLSettingsBase::ptr_t other)
|
||||
{
|
||||
replaceSettings(other->cloneSettings());
|
||||
replaceSettings(other);
|
||||
setBlendFactor(other->getBlendFactor());
|
||||
}
|
||||
|
||||
virtual void loadValuesFromLLSD();
|
||||
virtual void saveValuesToLLSD();
|
||||
void saveValuesIfNeeded();
|
||||
|
||||
LLUUID mAssetId;
|
||||
LLUUID mSettingId;
|
||||
std::string mSettingName;
|
||||
U32 mSettingFlags;
|
||||
|
||||
private:
|
||||
bool mLLSDDirty;
|
||||
bool mDirty;
|
||||
bool mReplaced; // super dirty!
|
||||
|
||||
LLSD combineSDMaps(const LLSD &first, const LLSD &other) const;
|
||||
static LLSD combineSDMaps(const LLSD &first, const LLSD &other);
|
||||
|
||||
LLSD mSettings;
|
||||
BlendFactor mBlendedFactor;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -125,33 +125,38 @@ static const F32 DEFAULT_MULTISLIDER_INCREMENT(0.005f);
|
|||
//=========================================================================
|
||||
LLSettingsDay::LLSettingsDay(const LLSD &data) :
|
||||
LLSettingsBase(data),
|
||||
mInitialized(false)
|
||||
mInitialized(false),
|
||||
mDaySettings(LLSD::emptyMap())
|
||||
{
|
||||
mDayTracks.resize(TRACK_MAX);
|
||||
loadValuesFromLLSD();
|
||||
}
|
||||
|
||||
LLSettingsDay::LLSettingsDay() :
|
||||
LLSettingsBase(),
|
||||
mInitialized(false)
|
||||
mInitialized(false),
|
||||
mDaySettings(LLSD::emptyMap())
|
||||
{
|
||||
mDayTracks.resize(TRACK_MAX);
|
||||
replaceSettings(defaults());
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
LLSD LLSettingsDay::getSettings() const
|
||||
LLSD& LLSettingsDay::getSettings()
|
||||
{
|
||||
LLSD settings(LLSD::emptyMap());
|
||||
mDaySettings = LLSD::emptyMap();
|
||||
LLSD& settings = LLSettingsBase::getSettings();
|
||||
|
||||
if (mSettings.has(SETTING_NAME))
|
||||
settings[SETTING_NAME] = mSettings[SETTING_NAME];
|
||||
if (settings.has(SETTING_NAME))
|
||||
mDaySettings[SETTING_NAME] = settings[SETTING_NAME];
|
||||
|
||||
if (mSettings.has(SETTING_ID))
|
||||
settings[SETTING_ID] = mSettings[SETTING_ID];
|
||||
if (settings.has(SETTING_ID))
|
||||
mDaySettings[SETTING_ID] = settings[SETTING_ID];
|
||||
|
||||
if (mSettings.has(SETTING_ASSETID))
|
||||
settings[SETTING_ASSETID] = mSettings[SETTING_ASSETID];
|
||||
if (settings.has(SETTING_ASSETID))
|
||||
mDaySettings[SETTING_ASSETID] = settings[SETTING_ASSETID];
|
||||
|
||||
settings[SETTING_TYPE] = getSettingsType();
|
||||
mDaySettings[SETTING_TYPE] = getSettingsType();
|
||||
|
||||
std::map<std::string, LLSettingsBase::ptr_t> in_use;
|
||||
|
||||
|
|
@ -175,7 +180,7 @@ LLSD LLSettingsDay::getSettings() const
|
|||
}
|
||||
tracks.append(trackout);
|
||||
}
|
||||
settings[SETTING_TRACKS] = tracks;
|
||||
mDaySettings[SETTING_TRACKS] = tracks;
|
||||
|
||||
LLSD frames(LLSD::emptyMap());
|
||||
for (std::map<std::string, LLSettingsBase::ptr_t>::iterator itFrame = in_use.begin(); itFrame != in_use.end(); ++itFrame)
|
||||
|
|
@ -185,9 +190,15 @@ LLSD LLSettingsDay::getSettings() const
|
|||
|
||||
frames[(*itFrame).first] = framesettings;
|
||||
}
|
||||
settings[SETTING_FRAMES] = frames;
|
||||
mDaySettings[SETTING_FRAMES] = frames;
|
||||
|
||||
return settings;
|
||||
return mDaySettings;
|
||||
}
|
||||
|
||||
void LLSettingsDay::setLLSDDirty()
|
||||
{
|
||||
mDaySettings = LLSD::emptyMap();
|
||||
LLSettingsBase::setLLSDDirty();
|
||||
}
|
||||
|
||||
bool LLSettingsDay::initialize(bool validate_frames)
|
||||
|
|
@ -393,6 +404,8 @@ bool LLSettingsDay::initialize(bool validate_frames)
|
|||
mSettings[SETTING_ASSETID] = assetid;
|
||||
}
|
||||
|
||||
loadValuesFromLLSD();
|
||||
|
||||
mInitialized = true;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -450,7 +463,7 @@ LLSD LLSettingsDay::defaults()
|
|||
return dfltsetting;
|
||||
}
|
||||
|
||||
void LLSettingsDay::blend(const LLSettingsBase::ptr_t &other, F64 mix)
|
||||
void LLSettingsDay::blend(LLSettingsBase::ptr_t &other, F64 mix)
|
||||
{
|
||||
LL_ERRS("DAYCYCLE") << "Day cycles are not blendable!" << LL_ENDL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,9 +82,10 @@ public:
|
|||
|
||||
bool initialize(bool validate_frames = false);
|
||||
|
||||
virtual ptr_t buildClone() const = 0;
|
||||
virtual ptr_t buildDeepCloneAndUncompress() const = 0;
|
||||
virtual LLSD getSettings() const SETTINGS_OVERRIDE;
|
||||
virtual ptr_t buildClone() = 0;
|
||||
virtual ptr_t buildDeepCloneAndUncompress() = 0;
|
||||
virtual LLSD& getSettings() SETTINGS_OVERRIDE;
|
||||
virtual void setLLSDDirty() override;
|
||||
virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_DAYCYCLE; }
|
||||
|
||||
|
||||
|
|
@ -92,7 +93,7 @@ public:
|
|||
virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("daycycle"); }
|
||||
|
||||
// Settings status
|
||||
virtual void blend(const LLSettingsBase::ptr_t &other, F64 mix) SETTINGS_OVERRIDE;
|
||||
virtual void blend(LLSettingsBase::ptr_t &other, F64 mix) SETTINGS_OVERRIDE;
|
||||
|
||||
static LLSD defaults();
|
||||
|
||||
|
|
@ -128,7 +129,7 @@ public:
|
|||
virtual validation_list_t getValidationList() const SETTINGS_OVERRIDE;
|
||||
static validation_list_t validationList();
|
||||
|
||||
virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
|
||||
virtual LLSettingsBase::ptr_t buildDerivedClone() SETTINGS_OVERRIDE { return buildClone(); }
|
||||
|
||||
LLSettingsBase::TrackPosition getUpperBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe);
|
||||
LLSettingsBase::TrackPosition getLowerBoundFrame(S32 track, const LLSettingsBase::TrackPosition& keyframe);
|
||||
|
|
@ -144,6 +145,7 @@ protected:
|
|||
|
||||
private:
|
||||
CycleList_t mDayTracks;
|
||||
LLSD mDaySettings;
|
||||
|
||||
LLSettingsBase::Seconds mLastUpdateTime;
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -111,20 +111,24 @@ public:
|
|||
LLSettingsSky(const LLSD &data);
|
||||
virtual ~LLSettingsSky() { };
|
||||
|
||||
virtual ptr_t buildClone() const = 0;
|
||||
virtual ptr_t buildClone() = 0;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("sky"); }
|
||||
virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_SKY; }
|
||||
|
||||
// Settings status
|
||||
virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE;
|
||||
virtual void blend(LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE;
|
||||
|
||||
virtual void replaceSettings(LLSD settings) SETTINGS_OVERRIDE;
|
||||
virtual void replaceSettings(const LLSettingsBase::ptr_t& other_sky) override;
|
||||
|
||||
void replaceWithSky(LLSettingsSky::ptr_t pother);
|
||||
void replaceWithSky(const LLSettingsSky::ptr_t& pother);
|
||||
static LLSD defaults(const LLSettingsBase::TrackPosition& position = 0.0f);
|
||||
|
||||
void loadValuesFromLLSD() override;
|
||||
void saveValuesToLLSD() override;
|
||||
|
||||
F32 getPlanetRadius() const;
|
||||
F32 getSkyBottomRadius() const;
|
||||
F32 getSkyTopRadius() const;
|
||||
|
|
@ -205,6 +209,12 @@ public:
|
|||
|
||||
F32 getGamma() const;
|
||||
|
||||
F32 getHDRMin() const;
|
||||
F32 getHDRMax() const;
|
||||
F32 getHDROffset() const;
|
||||
F32 getTonemapMix() const;
|
||||
void setTonemapMix(F32 mix);
|
||||
|
||||
void setGamma(F32 val);
|
||||
|
||||
LLColor3 getGlow() const;
|
||||
|
|
@ -306,7 +316,7 @@ public:
|
|||
LLColor3 getSunlightColorClamped() const;
|
||||
LLColor3 getAmbientColorClamped() const;
|
||||
|
||||
virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
|
||||
virtual LLSettingsBase::ptr_t buildDerivedClone() SETTINGS_OVERRIDE { return buildClone(); }
|
||||
|
||||
static LLUUID GetDefaultAssetId();
|
||||
static LLUUID GetDefaultSunTextureId();
|
||||
|
|
@ -348,6 +358,12 @@ protected:
|
|||
virtual stringset_t getSlerpKeys() const SETTINGS_OVERRIDE;
|
||||
virtual stringset_t getSkipInterpolateKeys() const SETTINGS_OVERRIDE;
|
||||
|
||||
LLUUID mSunTextureId;
|
||||
LLUUID mMoonTextureId;
|
||||
LLUUID mCloudTextureId;
|
||||
LLUUID mBloomTextureId;
|
||||
LLUUID mRainbowTextureId;
|
||||
LLUUID mHaloTextureId;
|
||||
LLUUID mNextSunTextureId;
|
||||
LLUUID mNextMoonTextureId;
|
||||
LLUUID mNextCloudTextureId;
|
||||
|
|
@ -355,17 +371,68 @@ protected:
|
|||
LLUUID mNextRainbowTextureId;
|
||||
LLUUID mNextHaloTextureId;
|
||||
|
||||
bool mCanAutoAdjust;
|
||||
LLQuaternion mSunRotation;
|
||||
LLQuaternion mMoonRotation;
|
||||
LLColor3 mSunlightColor;
|
||||
LLColor3 mGlow;
|
||||
F32 mReflectionProbeAmbiance;
|
||||
F32 mSunScale;
|
||||
F32 mStarBrightness;
|
||||
F32 mMoonBrightness;
|
||||
F32 mMoonScale;
|
||||
F32 mMaxY;
|
||||
F32 mGamma;
|
||||
F32 mCloudVariance;
|
||||
F32 mCloudShadow;
|
||||
F32 mCloudScale;
|
||||
F32 mTonemapMix;
|
||||
F32 mHDROffset;
|
||||
F32 mHDRMax;
|
||||
F32 mHDRMin;
|
||||
LLVector2 mScrollRate;
|
||||
LLColor3 mCloudPosDensity1;
|
||||
LLColor3 mCloudPosDensity2;
|
||||
LLColor3 mCloudColor;
|
||||
LLSD mAbsorptionConfigs;
|
||||
LLSD mMieConfigs;
|
||||
LLSD mRayleighConfigs;
|
||||
F32 mSunArcRadians;
|
||||
F32 mSkyTopRadius;
|
||||
F32 mSkyBottomRadius;
|
||||
F32 mSkyMoistureLevel;
|
||||
F32 mSkyDropletRadius;
|
||||
F32 mSkyIceLevel;
|
||||
F32 mPlanetRadius;
|
||||
|
||||
F32 mHazeHorizon;
|
||||
F32 mHazeDensity;
|
||||
F32 mDistanceMultiplier;
|
||||
F32 mDensityMultiplier;
|
||||
LLColor3 mBlueHorizon;
|
||||
LLColor3 mBlueDensity;
|
||||
LLColor3 mAmbientColor;
|
||||
|
||||
bool mHasLegacyHaze;
|
||||
bool mLegacyHazeHorizon;
|
||||
bool mLegacyHazeDensity;
|
||||
bool mLegacyDistanceMultiplier;
|
||||
bool mLegacyDensityMultiplier;
|
||||
bool mLegacyBlueHorizon;
|
||||
bool mLegacyBlueDensity;
|
||||
bool mLegacyAmbientColor;
|
||||
|
||||
private:
|
||||
static LLSD rayleighConfigDefault();
|
||||
static LLSD absorptionConfigDefault();
|
||||
static LLSD mieConfigDefault();
|
||||
|
||||
LLColor3 getColor(const std::string& key, const LLColor3& default_value) const;
|
||||
F32 getFloat(const std::string& key, F32 default_value) const;
|
||||
LLColor3 getColor(const std::string& key, const LLColor3& default_value);
|
||||
F32 getFloat(const std::string& key, F32 default_value);
|
||||
|
||||
void calculateHeavenlyBodyPositions() const;
|
||||
void calculateLightSettings() const;
|
||||
void clampColor(LLColor3& color, F32 gamma, const F32 scale = 1.0f) const;
|
||||
static void clampColor(LLColor3& color, F32 gamma, const F32 scale = 1.0f);
|
||||
|
||||
mutable LLVector3 mSunDirection;
|
||||
mutable LLVector3 mMoonDirection;
|
||||
|
|
|
|||
|
|
@ -68,14 +68,18 @@ static const LLUUID DEFAULT_OPAQUE_WATER_TEXTURE("43c32285-d658-1793-c123-bf8631
|
|||
//=========================================================================
|
||||
LLSettingsWater::LLSettingsWater(const LLSD &data) :
|
||||
LLSettingsBase(data),
|
||||
mNextNormalMapID()
|
||||
mNextNormalMapID(),
|
||||
mNextTransparentTextureID()
|
||||
{
|
||||
loadValuesFromLLSD();
|
||||
}
|
||||
|
||||
LLSettingsWater::LLSettingsWater() :
|
||||
LLSettingsBase(),
|
||||
mNextNormalMapID()
|
||||
mNextNormalMapID(),
|
||||
mNextTransparentTextureID()
|
||||
{
|
||||
replaceSettings(defaults());
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
|
|
@ -109,6 +113,53 @@ LLSD LLSettingsWater::defaults(const LLSettingsBase::TrackPosition& position)
|
|||
return dfltsetting;
|
||||
}
|
||||
|
||||
void LLSettingsWater::loadValuesFromLLSD()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
|
||||
|
||||
LLSettingsBase::loadValuesFromLLSD();
|
||||
|
||||
LLSD& settings = getSettings();
|
||||
|
||||
mBlurMultiplier = (F32)settings[SETTING_BLUR_MULTIPLIER].asReal();
|
||||
mWaterFogColor = LLColor3(settings[SETTING_FOG_COLOR]);
|
||||
mWaterFogDensity = (F32)settings[SETTING_FOG_DENSITY].asReal();
|
||||
mFogMod = (F32)settings[SETTING_FOG_MOD].asReal();
|
||||
mFresnelOffset = (F32)settings[SETTING_FRESNEL_OFFSET].asReal();
|
||||
mFresnelScale = (F32)settings[SETTING_FRESNEL_SCALE].asReal();
|
||||
mNormalScale = LLVector3(settings[SETTING_NORMAL_SCALE]);
|
||||
mScaleAbove = (F32)settings[SETTING_SCALE_ABOVE].asReal();
|
||||
mScaleBelow = (F32)settings[SETTING_SCALE_BELOW].asReal();
|
||||
mWave1Dir = LLVector2(settings[SETTING_WAVE1_DIR]);
|
||||
mWave2Dir = LLVector2(settings[SETTING_WAVE2_DIR]);
|
||||
|
||||
mNormalMapID = settings[SETTING_NORMAL_MAP].asUUID();
|
||||
mTransparentTextureID = settings[SETTING_TRANSPARENT_TEXTURE].asUUID();
|
||||
}
|
||||
|
||||
void LLSettingsWater::saveValuesToLLSD()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
|
||||
|
||||
LLSettingsBase::saveValuesToLLSD();
|
||||
|
||||
LLSD & settings = getSettings();
|
||||
settings[SETTING_BLUR_MULTIPLIER] = LLSD::Real(mBlurMultiplier);
|
||||
settings[SETTING_FOG_COLOR] = mWaterFogColor.getValue();
|
||||
settings[SETTING_FOG_DENSITY] = LLSD::Real(mWaterFogDensity);
|
||||
settings[SETTING_FOG_MOD] = LLSD::Real(mFogMod);
|
||||
settings[SETTING_FRESNEL_OFFSET] = LLSD::Real(mFresnelOffset);
|
||||
settings[SETTING_FRESNEL_SCALE] = LLSD::Real(mFresnelScale);
|
||||
settings[SETTING_NORMAL_SCALE] = mNormalScale.getValue();
|
||||
settings[SETTING_SCALE_ABOVE] = LLSD::Real(mScaleAbove);
|
||||
settings[SETTING_SCALE_BELOW] = LLSD::Real(mScaleBelow);
|
||||
settings[SETTING_WAVE1_DIR] = mWave1Dir.getValue();
|
||||
settings[SETTING_WAVE2_DIR] = mWave2Dir.getValue();
|
||||
|
||||
settings[SETTING_NORMAL_MAP] = mNormalMapID;
|
||||
settings[SETTING_TRANSPARENT_TEXTURE] = mTransparentTextureID;
|
||||
}
|
||||
|
||||
LLSD LLSettingsWater::translateLegacySettings(LLSD legacy)
|
||||
{
|
||||
bool converted_something(false);
|
||||
|
|
@ -180,13 +231,30 @@ LLSD LLSettingsWater::translateLegacySettings(LLSD legacy)
|
|||
return newsettings;
|
||||
}
|
||||
|
||||
void LLSettingsWater::blend(const LLSettingsBase::ptr_t &end, F64 blendf)
|
||||
void LLSettingsWater::blend(LLSettingsBase::ptr_t &end, F64 blendf)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
|
||||
LLSettingsWater::ptr_t other = PTR_NAMESPACE::static_pointer_cast<LLSettingsWater>(end);
|
||||
if (other)
|
||||
{
|
||||
LLSD blenddata = interpolateSDMap(mSettings, other->mSettings, other->getParameterMap(), blendf);
|
||||
replaceSettings(blenddata);
|
||||
mSettingFlags |= other->mSettingFlags;
|
||||
|
||||
mBlurMultiplier = lerp(mBlurMultiplier, other->mBlurMultiplier, (F32)blendf);
|
||||
lerpColor(mWaterFogColor, other->mWaterFogColor, (F32)blendf);
|
||||
mWaterFogDensity = lerp(mWaterFogDensity, other->mWaterFogDensity, (F32)blendf);
|
||||
mFogMod = lerp(mFogMod, other->mFogMod, (F32)blendf);
|
||||
mFresnelOffset = lerp(mFresnelOffset, other->mFresnelOffset, (F32)blendf);
|
||||
mFresnelScale = lerp(mFresnelScale, other->mFresnelScale, (F32)blendf);
|
||||
lerpVector3(mNormalScale, other->mNormalScale, (F32)blendf);
|
||||
mScaleAbove = lerp(mScaleAbove, other->mScaleAbove, (F32)blendf);
|
||||
mScaleBelow = lerp(mScaleBelow, other->mScaleBelow, (F32)blendf);
|
||||
lerpVector2(mWave1Dir, other->mWave1Dir, (F32)blendf);
|
||||
lerpVector2(mWave2Dir, other->mWave2Dir, (F32)blendf);
|
||||
|
||||
setDirtyFlag(true);
|
||||
setReplaced();
|
||||
setLLSDDirty();
|
||||
|
||||
mNextNormalMapID = other->getNormalMapID();
|
||||
mNextTransparentTextureID = other->getTransparentTextureID();
|
||||
}
|
||||
|
|
@ -204,7 +272,34 @@ void LLSettingsWater::replaceSettings(LLSD settings)
|
|||
mNextTransparentTextureID.setNull();
|
||||
}
|
||||
|
||||
void LLSettingsWater::replaceWithWater(LLSettingsWater::ptr_t other)
|
||||
void LLSettingsWater::replaceSettings(const LLSettingsBase::ptr_t& other_water)
|
||||
{
|
||||
LLSettingsBase::replaceSettings(other_water);
|
||||
|
||||
llassert(getSettingsType() == other_water->getSettingsType());
|
||||
|
||||
LLSettingsWater::ptr_t other = PTR_NAMESPACE::dynamic_pointer_cast<LLSettingsWater>(other_water);
|
||||
|
||||
mBlurMultiplier = other->mBlurMultiplier;
|
||||
mWaterFogColor = other->mWaterFogColor;
|
||||
mWaterFogDensity = other->mWaterFogDensity;
|
||||
mFogMod = other->mFogMod;
|
||||
mFresnelOffset = other->mFresnelOffset;
|
||||
mFresnelScale = other->mFresnelScale;
|
||||
mNormalScale = other->mNormalScale;
|
||||
mScaleAbove = other->mScaleAbove;
|
||||
mScaleBelow = other->mScaleBelow;
|
||||
mWave1Dir = other->mWave1Dir;
|
||||
mWave2Dir = other->mWave2Dir;
|
||||
|
||||
mNormalMapID = other->mNormalMapID;
|
||||
mTransparentTextureID = other->mTransparentTextureID;
|
||||
|
||||
mNextNormalMapID.setNull();
|
||||
mNextTransparentTextureID.setNull();
|
||||
}
|
||||
|
||||
void LLSettingsWater::replaceWithWater(const LLSettingsWater::ptr_t& other)
|
||||
{
|
||||
replaceWith(other);
|
||||
|
||||
|
|
|
|||
|
|
@ -55,151 +55,181 @@ public:
|
|||
LLSettingsWater(const LLSD &data);
|
||||
virtual ~LLSettingsWater() { };
|
||||
|
||||
virtual ptr_t buildClone() const = 0;
|
||||
virtual ptr_t buildClone() = 0;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
virtual std::string getSettingsType() const SETTINGS_OVERRIDE { return std::string("water"); }
|
||||
virtual LLSettingsType::type_e getSettingsTypeValue() const SETTINGS_OVERRIDE { return LLSettingsType::ST_WATER; }
|
||||
|
||||
// Settings status
|
||||
virtual void blend(const LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE;
|
||||
virtual void blend(LLSettingsBase::ptr_t &end, F64 blendf) SETTINGS_OVERRIDE;
|
||||
|
||||
virtual void replaceSettings(LLSD settings) SETTINGS_OVERRIDE;
|
||||
void replaceWithWater(LLSettingsWater::ptr_t other);
|
||||
virtual void replaceSettings(const LLSettingsBase::ptr_t& other_water) override;
|
||||
void replaceWithWater(const LLSettingsWater::ptr_t& other);
|
||||
|
||||
static LLSD defaults(const LLSettingsBase::TrackPosition& position = 0.0f);
|
||||
|
||||
void loadValuesFromLLSD() override;
|
||||
void saveValuesToLLSD() override;
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
F32 getBlurMultiplier() const
|
||||
{
|
||||
return (F32)mSettings[SETTING_BLUR_MULTIPLIER].asReal();
|
||||
return mBlurMultiplier;
|
||||
}
|
||||
|
||||
void setBlurMultiplier(F32 val)
|
||||
{
|
||||
setValue(SETTING_BLUR_MULTIPLIER, val);
|
||||
mBlurMultiplier = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
LLColor3 getWaterFogColor() const
|
||||
{
|
||||
return LLColor3(mSettings[SETTING_FOG_COLOR]);
|
||||
return mWaterFogColor;
|
||||
}
|
||||
|
||||
void setWaterFogColor(LLColor3 val)
|
||||
{
|
||||
setValue(SETTING_FOG_COLOR, val);
|
||||
mWaterFogColor = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
F32 getWaterFogDensity() const
|
||||
{
|
||||
return (F32)mSettings[SETTING_FOG_DENSITY].asReal();
|
||||
return mWaterFogDensity;
|
||||
}
|
||||
|
||||
F32 getModifiedWaterFogDensity(bool underwater) const;
|
||||
|
||||
void setWaterFogDensity(F32 val)
|
||||
{
|
||||
setValue(SETTING_FOG_DENSITY, val);
|
||||
mWaterFogDensity = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
F32 getFogMod() const
|
||||
{
|
||||
return (F32)mSettings[SETTING_FOG_MOD].asReal();
|
||||
return mFogMod;
|
||||
}
|
||||
|
||||
void setFogMod(F32 val)
|
||||
{
|
||||
setValue(SETTING_FOG_MOD, val);
|
||||
mFogMod = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
F32 getFresnelOffset() const
|
||||
{
|
||||
return (F32)mSettings[SETTING_FRESNEL_OFFSET].asReal();
|
||||
return mFresnelOffset;
|
||||
}
|
||||
|
||||
void setFresnelOffset(F32 val)
|
||||
{
|
||||
setValue(SETTING_FRESNEL_OFFSET, val);
|
||||
mFresnelOffset = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
F32 getFresnelScale() const
|
||||
{
|
||||
return (F32)mSettings[SETTING_FRESNEL_SCALE].asReal();
|
||||
return mFresnelScale;
|
||||
}
|
||||
|
||||
void setFresnelScale(F32 val)
|
||||
{
|
||||
setValue(SETTING_FRESNEL_SCALE, val);
|
||||
mFresnelScale = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
LLUUID getTransparentTextureID() const
|
||||
{
|
||||
return mSettings[SETTING_TRANSPARENT_TEXTURE].asUUID();
|
||||
return mTransparentTextureID;
|
||||
}
|
||||
|
||||
void setTransparentTextureID(LLUUID val)
|
||||
{
|
||||
setValue(SETTING_TRANSPARENT_TEXTURE, val);
|
||||
mTransparentTextureID = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
LLUUID getNormalMapID() const
|
||||
{
|
||||
return mSettings[SETTING_NORMAL_MAP].asUUID();
|
||||
return mNormalMapID;
|
||||
}
|
||||
|
||||
void setNormalMapID(LLUUID val)
|
||||
{
|
||||
setValue(SETTING_NORMAL_MAP, val);
|
||||
mNormalMapID = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
LLVector3 getNormalScale() const
|
||||
{
|
||||
return LLVector3(mSettings[SETTING_NORMAL_SCALE]);
|
||||
return mNormalScale;
|
||||
}
|
||||
|
||||
void setNormalScale(LLVector3 val)
|
||||
{
|
||||
setValue(SETTING_NORMAL_SCALE, val);
|
||||
mNormalScale = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
F32 getScaleAbove() const
|
||||
{
|
||||
return (F32)mSettings[SETTING_SCALE_ABOVE].asReal();
|
||||
return mScaleAbove;
|
||||
}
|
||||
|
||||
void setScaleAbove(F32 val)
|
||||
{
|
||||
setValue(SETTING_SCALE_ABOVE, val);
|
||||
mScaleAbove = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
F32 getScaleBelow() const
|
||||
{
|
||||
return (F32)mSettings[SETTING_SCALE_BELOW].asReal();
|
||||
return mScaleBelow;
|
||||
}
|
||||
|
||||
void setScaleBelow(F32 val)
|
||||
{
|
||||
setValue(SETTING_SCALE_BELOW, val);
|
||||
mScaleBelow = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
LLVector2 getWave1Dir() const
|
||||
{
|
||||
return LLVector2(mSettings[SETTING_WAVE1_DIR]);
|
||||
return mWave1Dir;
|
||||
}
|
||||
|
||||
void setWave1Dir(LLVector2 val)
|
||||
{
|
||||
setValue(SETTING_WAVE1_DIR, val);
|
||||
mWave1Dir = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
LLVector2 getWave2Dir() const
|
||||
{
|
||||
return LLVector2(mSettings[SETTING_WAVE2_DIR]);
|
||||
return mWave2Dir;
|
||||
}
|
||||
|
||||
void setWave2Dir(LLVector2 val)
|
||||
{
|
||||
setValue(SETTING_WAVE2_DIR, val);
|
||||
mWave2Dir = val;
|
||||
setDirtyFlag(true);
|
||||
setLLSDDirty();
|
||||
}
|
||||
|
||||
//-------------------------------------------
|
||||
|
|
@ -218,7 +248,7 @@ public:
|
|||
|
||||
static LLSD translateLegacySettings(LLSD legacy);
|
||||
|
||||
virtual LLSettingsBase::ptr_t buildDerivedClone() const SETTINGS_OVERRIDE { return buildClone(); }
|
||||
virtual LLSettingsBase::ptr_t buildDerivedClone() SETTINGS_OVERRIDE { return buildClone(); }
|
||||
|
||||
static LLUUID GetDefaultAssetId();
|
||||
static LLUUID GetDefaultWaterNormalAssetId();
|
||||
|
|
@ -241,9 +271,22 @@ protected:
|
|||
|
||||
LLSettingsWater();
|
||||
|
||||
LLUUID mTransparentTextureID;
|
||||
LLUUID mNormalMapID;
|
||||
LLUUID mNextTransparentTextureID;
|
||||
LLUUID mNextNormalMapID;
|
||||
|
||||
F32 mBlurMultiplier;
|
||||
LLColor3 mWaterFogColor;
|
||||
F32 mWaterFogDensity;
|
||||
F32 mFogMod;
|
||||
F32 mFresnelOffset;
|
||||
F32 mFresnelScale;
|
||||
LLVector3 mNormalScale;
|
||||
F32 mScaleAbove;
|
||||
F32 mScaleBelow;
|
||||
LLVector2 mWave1Dir;
|
||||
LLVector2 mWave2Dir;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ public:
|
|||
const LLJointRiggingInfo& operator[](S32 i) const { return mRigInfoPtr[i]; };
|
||||
bool needsUpdate() { return mNeedsUpdate; }
|
||||
void setNeedsUpdate(bool val) { mNeedsUpdate = val; }
|
||||
|
||||
LLJointRiggingInfo* begin() { return mRigInfoPtr; }
|
||||
LLJointRiggingInfo* end() { return mRigInfoPtr + mSize; }
|
||||
|
||||
private:
|
||||
// Not implemented
|
||||
LLJointRiggingInfoTab& operator=(const LLJointRiggingInfoTab& src);
|
||||
|
|
|
|||
|
|
@ -38,8 +38,7 @@
|
|||
#include "v4color.h"
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h> // for htonl
|
||||
# include "llwin32headers.h" // for htonl
|
||||
#elif LL_LINUX
|
||||
# include <netinet/in.h>
|
||||
#elif LL_DARWIN
|
||||
|
|
|
|||
|
|
@ -2730,7 +2730,7 @@ bool LLVolume::unpackVolumeFacesInternal(const LLSD& mdl)
|
|||
}
|
||||
|
||||
|
||||
bool LLVolume::isMeshAssetLoaded()
|
||||
bool LLVolume::isMeshAssetLoaded() const
|
||||
{
|
||||
return mIsMeshAssetLoaded;
|
||||
}
|
||||
|
|
@ -2753,7 +2753,7 @@ void LLVolume::setMeshAssetUnavaliable(bool unavaliable)
|
|||
}
|
||||
}
|
||||
|
||||
bool LLVolume::isMeshAssetUnavaliable()
|
||||
bool LLVolume::isMeshAssetUnavaliable() const
|
||||
{
|
||||
return mIsMeshAssetUnavaliable;
|
||||
}
|
||||
|
|
@ -3779,6 +3779,207 @@ S32 LLVolume::getNumTriangles(S32* vcount) const
|
|||
return triangle_count;
|
||||
}
|
||||
|
||||
void LLVolumeFace::generateSilhouetteEdge(const LLVolume* volume, std::vector<S32>& edge) const
|
||||
{
|
||||
llassert(edge.empty()); // edge is supposed to be a scratch array
|
||||
|
||||
if (volume->isMeshAssetLoaded()) { return; }
|
||||
|
||||
if (mTypeMask & CAP_MASK)
|
||||
{
|
||||
// Logic copied from LLVolumeFace::createCap - indicates a face created via
|
||||
// createUnCutCubeCap.
|
||||
if (!(mTypeMask & HOLLOW_MASK) &&
|
||||
!(mTypeMask & OPEN_MASK) &&
|
||||
((volume->getParams().getPathParams().getBegin()==0.0f)&&
|
||||
(volume->getParams().getPathParams().getEnd()==1.0f))&&
|
||||
(volume->getParams().getProfileParams().getCurveType()==LL_PCODE_PROFILE_SQUARE &&
|
||||
volume->getParams().getPathParams().getCurveType()==LL_PCODE_PATH_LINE)
|
||||
)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfgse - CAP_MASK");
|
||||
|
||||
const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile;
|
||||
S32 grid_size = (profile.size()-1)/4;
|
||||
edge.resize(mNumIndices);
|
||||
llassert(edge.size() == 6*grid_size*grid_size);
|
||||
|
||||
S32 cur_edge = 0;
|
||||
for(S32 gx = 0;gx<grid_size;gx++)
|
||||
{
|
||||
for(S32 gy = 0;gy<grid_size;gy++)
|
||||
{
|
||||
if (mTypeMask & TOP_MASK)
|
||||
{
|
||||
|
||||
S32 edge_value = grid_size * 2 * gy + gx * 2;
|
||||
|
||||
if (gx > 0)
|
||||
{
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge[cur_edge++] = -1; // Mark face to higlight it
|
||||
}
|
||||
|
||||
if (gy < grid_size - 1)
|
||||
{
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
edge[cur_edge++] = edge_value;
|
||||
|
||||
if (gx < grid_size - 1)
|
||||
{
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
if (gy > 0)
|
||||
{
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
S32 edge_value = grid_size * 2 * gy + gx * 2;
|
||||
|
||||
if (gy > 0)
|
||||
{
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
if (gx < grid_size - 1)
|
||||
{
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
edge[cur_edge++] = edge_value;
|
||||
|
||||
if (gy < grid_size - 1)
|
||||
{
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
if (gx > 0)
|
||||
{
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
edge[cur_edge++] = edge_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK))
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfgse - END_MASK or SIDE_MASK");
|
||||
|
||||
edge.resize(mNumIndices);
|
||||
llassert(edge.size() == 6*(mNumS-1)*(mNumT-1));
|
||||
|
||||
S32 cur_edge = 0;
|
||||
const bool flat_face = mTypeMask & FLAT_MASK;
|
||||
for (S32 t = 0; t < (mNumT-1); t++)
|
||||
{
|
||||
for (S32 s = 0; s < (mNumS-1); s++)
|
||||
{
|
||||
// bottom left/top right neighbor face
|
||||
edge[cur_edge++] = (mNumS-1)*2*t+s*2+1;
|
||||
|
||||
if (t < mNumT-2)
|
||||
{ // top right/top left neighbor face
|
||||
edge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1;
|
||||
}
|
||||
else if (mNumT <= 3 || volume->getPath().isOpen())
|
||||
{ // no neighbor
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
else
|
||||
{ // wrap on T
|
||||
edge[cur_edge++] = s*2+1;
|
||||
}
|
||||
|
||||
if (s > 0)
|
||||
{ // top left/bottom left neighbor face
|
||||
edge[cur_edge++] = (mNumS-1)*2*t+s*2-1;
|
||||
}
|
||||
else if (flat_face || volume->getProfile().isOpen())
|
||||
{ // no neighbor
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
else
|
||||
{ // wrap on S
|
||||
edge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1;
|
||||
}
|
||||
|
||||
if (t > 0)
|
||||
{ // bottom left/bottom right neighbor face
|
||||
edge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2;
|
||||
}
|
||||
else if (mNumT <= 3 || volume->getPath().isOpen())
|
||||
{ // no neighbor
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
else
|
||||
{ // wrap on T
|
||||
edge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2;
|
||||
}
|
||||
|
||||
if (s < mNumS-2)
|
||||
{ // bottom right/top right neighbor face
|
||||
edge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2;
|
||||
}
|
||||
else if (flat_face || volume->getProfile().isOpen())
|
||||
{ // no neighbor
|
||||
edge[cur_edge++] = -1;
|
||||
}
|
||||
else
|
||||
{ // wrap on S
|
||||
edge[cur_edge++] = (mNumS-1)*2*t;
|
||||
}
|
||||
|
||||
// top right/bottom left neighbor face
|
||||
edge[cur_edge++] = (mNumS-1)*2*t+s*2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_ERRS() << "Unknown/uninitialized face type!" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// generateSilhouetteVertices()
|
||||
|
|
@ -3810,6 +4011,13 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
|||
}
|
||||
|
||||
S32 cur_index = 0;
|
||||
// Scratch array for per-face silhouette edge information. This also has a
|
||||
// lot of dev-only debug information that we might not care about anymore.
|
||||
// (see DEBUG_SILHOUETTE_EDGE_MAP)
|
||||
// *TODO: Consider removing the debug associated with
|
||||
// DEBUG_SILHOUETTE_EDGE_MAP, and remove its associated computational
|
||||
// overhead in generateSilhouetteEdge.
|
||||
std::vector<S32> edge;
|
||||
//for each face
|
||||
for (face_list_t::iterator iter = mVolumeFaces.begin();
|
||||
iter != mVolumeFaces.end(); ++iter)
|
||||
|
|
@ -3817,7 +4025,16 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
|||
LLVolumeFace& face = *iter;
|
||||
|
||||
if (!(face_mask & (0x1 << cur_index++)) ||
|
||||
face.mNumIndices == 0 || face.mEdge.empty())
|
||||
face.mNumIndices == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Attempt to generate "edge" info for this silhouette, which is used
|
||||
// for some prims. If the edge array remains empty, then this
|
||||
// silhouette generation method is not supported for this face.
|
||||
edge.clear();
|
||||
face.generateSilhouetteEdge(this, edge);
|
||||
if (edge.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
@ -3831,7 +4048,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
|||
{
|
||||
for (S32 k = 0; k < 3; k++)
|
||||
{
|
||||
S32 index = face.mEdge[j * 3 + k];
|
||||
S32 index = edge[j * 3 + k];
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
|
|
@ -3883,7 +4100,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
|||
|
||||
//for each edge
|
||||
for (S32 k = 0; k < 3; k++) {
|
||||
S32 nIndex = face.mEdge[j*3+k];
|
||||
S32 nIndex = edge[j*3+k];
|
||||
if (nIndex <= -1) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -3998,7 +4215,7 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
|||
// *FIX IF NEEDED: this does not deal with neighboring degenerate faces
|
||||
for (S32 k = 0; k < 3; k++)
|
||||
{
|
||||
S32 index = face.mEdge[j*3+k];
|
||||
S32 index = edge[j*3+k];
|
||||
if (index != -1)
|
||||
{
|
||||
fFacing[j] = fFacing[index];
|
||||
|
|
@ -4010,10 +4227,10 @@ void LLVolume::generateSilhouetteVertices(std::vector<LLVector3> &vertices,
|
|||
|
||||
//for each edge
|
||||
for (S32 k = 0; k < 3; k++) {
|
||||
S32 index = face.mEdge[j*3+k];
|
||||
S32 index = edge[j*3+k];
|
||||
if (index != -1 && fFacing[index] == (AWAY | TOWARDS)) {
|
||||
//our neighbor is degenerate, make him face our direction
|
||||
fFacing[face.mEdge[j*3+k]] = fFacing[j];
|
||||
fFacing[edge[j*3+k]] = fFacing[j];
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -4991,7 +5208,10 @@ bool LLVolumeFace::VertexMapData::ComparePosition::operator()(const LLVector3& a
|
|||
void LLVolumeFace::remap()
|
||||
{
|
||||
// Generate a remap buffer
|
||||
std::vector<unsigned int> remap(mNumVertices);
|
||||
// Documentation for meshopt_generateVertexRemapMulti claims that remap should use vertice count
|
||||
// but all examples use indice count. There are out of bounds crashes when using vertice count.
|
||||
// To be on the safe side use bigger of the two.
|
||||
std::vector<unsigned int> remap(llmax(mNumIndices, mNumVertices));
|
||||
S32 remap_vertices_count = static_cast<S32>(LLMeshOptimizer::generateRemapMultiU16(&remap[0],
|
||||
mIndices,
|
||||
mNumIndices,
|
||||
|
|
@ -5833,30 +6053,16 @@ bool LLVolumeFace::createUnCutCubeCap(LLVolume* volume, bool partial_build)
|
|||
|
||||
if (!partial_build)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfcuccm - generate indices");
|
||||
|
||||
resizeIndices(grid_size*grid_size*6);
|
||||
if (!volume->isMeshAssetLoaded())
|
||||
{
|
||||
S32 size = grid_size * grid_size * 6;
|
||||
try
|
||||
{
|
||||
mEdge.resize(size);
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LL_WARNS("LLVOLUME") << "Resize of mEdge to " << size << " failed" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
U16* out = mIndices;
|
||||
|
||||
S32 idxs[] = {0,1,(grid_size+1)+1,(grid_size+1)+1,(grid_size+1),0};
|
||||
|
||||
int cur_edge = 0;
|
||||
|
||||
for(S32 gx = 0;gx<grid_size;gx++)
|
||||
{
|
||||
|
||||
for(S32 gy = 0;gy<grid_size;gy++)
|
||||
{
|
||||
if (mTypeMask & TOP_MASK)
|
||||
|
|
@ -5866,47 +6072,6 @@ bool LLVolumeFace::createUnCutCubeCap(LLVolume* volume, bool partial_build)
|
|||
*out++ = ((gy*(grid_size+1))+gx+idxs[i]);
|
||||
}
|
||||
|
||||
S32 edge_value = grid_size * 2 * gy + gx * 2;
|
||||
|
||||
if (gx > 0)
|
||||
{
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEdge[cur_edge++] = -1; // Mark face to higlight it
|
||||
}
|
||||
|
||||
if (gy < grid_size - 1)
|
||||
{
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
|
||||
if (gx < grid_size - 1)
|
||||
{
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
if (gy > 0)
|
||||
{
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -5914,48 +6079,6 @@ bool LLVolumeFace::createUnCutCubeCap(LLVolume* volume, bool partial_build)
|
|||
{
|
||||
*out++ = ((gy*(grid_size+1))+gx+idxs[i]);
|
||||
}
|
||||
|
||||
S32 edge_value = grid_size * 2 * gy + gx * 2;
|
||||
|
||||
if (gy > 0)
|
||||
{
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
if (gx < grid_size - 1)
|
||||
{
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
|
||||
if (gy < grid_size - 1)
|
||||
{
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
if (gx > 0)
|
||||
{
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
|
||||
mEdge[cur_edge++] = edge_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6435,6 +6558,8 @@ void LLVolumeFace::createTangents()
|
|||
|
||||
void LLVolumeFace::resizeVertices(S32 num_verts)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
|
||||
|
||||
ll_aligned_free<64>(mPositions);
|
||||
//DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||
ll_aligned_free_16(mTangents);
|
||||
|
|
@ -6557,6 +6682,8 @@ void LLVolumeFace::allocateJointIndices(S32 num_verts)
|
|||
|
||||
void LLVolumeFace::resizeIndices(S32 num_indices)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VOLUME;
|
||||
|
||||
ll_aligned_free_16(mIndices);
|
||||
llassert(num_indices % 3 == 0);
|
||||
|
||||
|
|
@ -6649,19 +6776,6 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build)
|
|||
{
|
||||
resizeVertices(num_vertices);
|
||||
resizeIndices(num_indices);
|
||||
|
||||
if (!volume->isMeshAssetLoaded())
|
||||
{
|
||||
try
|
||||
{
|
||||
mEdge.resize(num_indices);
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LL_WARNS("LLVOLUME") << "Resize of mEdge to " << num_indices << " failed" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LL_CHECK_MEMORY
|
||||
|
|
@ -6676,6 +6790,7 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build)
|
|||
bool test = (mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2;
|
||||
|
||||
// Copy the vertices into the array
|
||||
{ LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfcs - copy verts");
|
||||
for (t = mBeginT; t < end_t; t++)
|
||||
{
|
||||
tt = path_data[t].mTexT;
|
||||
|
|
@ -6760,6 +6875,7 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build)
|
|||
cur_vertex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
LL_CHECK_MEMORY
|
||||
|
||||
mCenter->clear();
|
||||
|
|
@ -6813,11 +6929,11 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build)
|
|||
mCenter->mul(0.5f);
|
||||
|
||||
S32 cur_index = 0;
|
||||
S32 cur_edge = 0;
|
||||
bool flat_face = mTypeMask & FLAT_MASK;
|
||||
|
||||
if (!partial_build)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VOLUME("llvfcs - generate indices");
|
||||
|
||||
// Now we generate the indices.
|
||||
for (t = 0; t < (mNumT-1); t++)
|
||||
{
|
||||
|
|
@ -6829,64 +6945,6 @@ bool LLVolumeFace::createSide(LLVolume* volume, bool partial_build)
|
|||
mIndices[cur_index++] = s + mNumS*t; //bottom left
|
||||
mIndices[cur_index++] = s+1 + mNumS*t; //bottom right
|
||||
mIndices[cur_index++] = s+1 + mNumS*(t+1); //top right
|
||||
|
||||
// bottom left/top right neighbor face
|
||||
mEdge[cur_edge++] = (mNumS-1)*2*t+s*2+1;
|
||||
|
||||
if (t < mNumT-2)
|
||||
{ // top right/top left neighbor face
|
||||
mEdge[cur_edge++] = (mNumS-1)*2*(t+1)+s*2+1;
|
||||
}
|
||||
else if (mNumT <= 3 || volume->getPath().isOpen())
|
||||
{ // no neighbor
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
else
|
||||
{ // wrap on T
|
||||
mEdge[cur_edge++] = s*2+1;
|
||||
}
|
||||
|
||||
if (s > 0)
|
||||
{ // top left/bottom left neighbor face
|
||||
mEdge[cur_edge++] = (mNumS-1)*2*t+s*2-1;
|
||||
}
|
||||
else if (flat_face || volume->getProfile().isOpen())
|
||||
{ // no neighbor
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
else
|
||||
{ // wrap on S
|
||||
mEdge[cur_edge++] = (mNumS-1)*2*t+(mNumS-2)*2+1;
|
||||
}
|
||||
|
||||
if (t > 0)
|
||||
{ // bottom left/bottom right neighbor face
|
||||
mEdge[cur_edge++] = (mNumS-1)*2*(t-1)+s*2;
|
||||
}
|
||||
else if (mNumT <= 3 || volume->getPath().isOpen())
|
||||
{ // no neighbor
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
else
|
||||
{ // wrap on T
|
||||
mEdge[cur_edge++] = (mNumS-1)*2*(mNumT-2)+s*2;
|
||||
}
|
||||
|
||||
if (s < mNumS-2)
|
||||
{ // bottom right/top right neighbor face
|
||||
mEdge[cur_edge++] = (mNumS-1)*2*t+(s+1)*2;
|
||||
}
|
||||
else if (flat_face || volume->getProfile().isOpen())
|
||||
{ // no neighbor
|
||||
mEdge[cur_edge++] = -1;
|
||||
}
|
||||
else
|
||||
{ // wrap on S
|
||||
mEdge[cur_edge++] = (mNumS-1)*2*t;
|
||||
}
|
||||
|
||||
// top right/bottom left neighbor face
|
||||
mEdge[cur_edge++] = (mNumS-1)*2*t+s*2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -921,6 +921,15 @@ public:
|
|||
// Get a reference to the octree, which may be null
|
||||
const LLVolumeOctree* getOctree() const;
|
||||
|
||||
// Part of silhouette generation (used by selection outlines)
|
||||
// Populates the provided edge array with numbers corresponding to
|
||||
// *partial* logic of whether a particular index should be rendered
|
||||
// as a silhouette edge. -1 indicates the index should be rendered as a
|
||||
// silhouette edge. See generateSilhouetteVertices for the full logic.
|
||||
// Silhouette edges can only be generated for some types of prims. If a
|
||||
// silhouette edge cannot be generated, the edge array will be left empty.
|
||||
void generateSilhouetteEdge(const LLVolume* volume, std::vector<S32>& edge) const;
|
||||
|
||||
enum
|
||||
{
|
||||
SINGLE_MASK = 0x0001,
|
||||
|
|
@ -966,8 +975,6 @@ public:
|
|||
// indexes for mPositions/mNormals/mTexCoords
|
||||
U16* mIndices;
|
||||
|
||||
std::vector<S32> mEdge;
|
||||
|
||||
//list of skin weights for rigged volumes
|
||||
// format is mWeights[vertex_index].mV[influence] = <joint_index>.<weight>
|
||||
// mWeights.size() should be empty or match mVertices.size()
|
||||
|
|
@ -1125,9 +1132,9 @@ private:
|
|||
|
||||
public:
|
||||
virtual void setMeshAssetLoaded(bool loaded);
|
||||
virtual bool isMeshAssetLoaded();
|
||||
virtual bool isMeshAssetLoaded() const;
|
||||
virtual void setMeshAssetUnavaliable(bool unavaliable);
|
||||
virtual bool isMeshAssetUnavaliable();
|
||||
virtual bool isMeshAssetUnavaliable() const;
|
||||
|
||||
protected:
|
||||
bool mUnique;
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@
|
|||
#include "llerror.h"
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <llwin32headers.h>
|
||||
#else
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h> // ntonl()
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#define LL_LLIOPIPE_H
|
||||
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llwin32headers.h"
|
||||
#include "apr_poll.h"
|
||||
|
||||
#include "llsd.h"
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
*/
|
||||
|
||||
#include "lliopipe.h"
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llwin32headers.h"
|
||||
#include "apr_pools.h"
|
||||
#include "apr_network_io.h"
|
||||
#include "llchainio.h"
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "llmail.h"
|
||||
|
||||
// APR on Windows needs full windows headers
|
||||
#include "llwin32headers.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include <stdexcept>
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llwin32headers.h"
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ LLPluginProcessParentOwner::~LLPluginProcessParentOwner()
|
|||
bool LLPluginProcessParent::sUseReadThread = false;
|
||||
apr_pollset_t *LLPluginProcessParent::sPollSet = NULL;
|
||||
bool LLPluginProcessParent::sPollsetNeedsRebuild = false;
|
||||
LLCoros::Mutex *LLPluginProcessParent::sInstancesMutex;
|
||||
LLCoros::Mutex *LLPluginProcessParent::sInstancesMutex = nullptr;
|
||||
LLPluginProcessParent::mapInstances_t LLPluginProcessParent::sInstances;
|
||||
LLThread *LLPluginProcessParent::sReadThread = NULL;
|
||||
|
||||
|
|
@ -157,18 +157,14 @@ LLPluginProcessParent::ptr_t LLPluginProcessParent::create(LLPluginProcessParent
|
|||
/*static*/
|
||||
void LLPluginProcessParent::shutdown()
|
||||
{
|
||||
// <FS:Beq> FIRE-34497 - lock maybe be null during shutdown due to fiber shutdown race condition
|
||||
// LLCoros::LockType lock(*sInstancesMutex);
|
||||
std::unique_ptr<LLCoros::LockType> lock;
|
||||
if (sInstancesMutex)
|
||||
if (!sInstancesMutex)
|
||||
{
|
||||
lock = std::make_unique<LLCoros::LockType>(*sInstancesMutex);
|
||||
// setup was not complete, skip shutdown
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS("Plugin") << "shutdown called but no instances mutex available" << LL_ENDL;
|
||||
}
|
||||
// </FS:Beq>
|
||||
|
||||
LLCoros::LockType lock(*sInstancesMutex);
|
||||
|
||||
mapInstances_t::iterator it;
|
||||
for (it = sInstances.begin(); it != sInstances.end(); ++it)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ include(LLCommon)
|
|||
include(LLCoreHttp)
|
||||
include(LLPhysicsExtensions)
|
||||
include(LLPrimitive)
|
||||
include(GLH)
|
||||
include(GLM)
|
||||
include(TinyGLTF)
|
||||
include(ColladaDom)
|
||||
|
|
@ -71,7 +70,7 @@ target_link_libraries(llprimitive
|
|||
llrender
|
||||
llphysicsextensions_impl
|
||||
ll::colladadom
|
||||
ll::glh_linear
|
||||
ll::glm
|
||||
)
|
||||
|
||||
if(LINUX)
|
||||
|
|
|
|||
|
|
@ -53,20 +53,10 @@
|
|||
#include "llsdserialize.h"
|
||||
#include "lljoint.h"
|
||||
|
||||
#if LL_LINUX && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) >= 70000
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
|
||||
#endif
|
||||
|
||||
#include "glh/glh_linear.h"
|
||||
|
||||
#if LL_LINUX && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) >= 70000
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
|
||||
#include "glm/mat4x4.hpp"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
#include "llmatrix4a.h"
|
||||
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
|
||||
|
|
@ -1178,19 +1168,17 @@ bool LLDAELoader::OpenFile(const std::string& filename)
|
|||
|
||||
if (skin)
|
||||
{
|
||||
domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement());
|
||||
|
||||
if (geom)
|
||||
if (domGeometry* geom = daeSafeCast<domGeometry>(skin->getSource().getElement()))
|
||||
{
|
||||
domMesh* mesh = geom->getMesh();
|
||||
if (mesh)
|
||||
if (domMesh* mesh = geom->getMesh())
|
||||
{
|
||||
std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin();
|
||||
while (i != mModelsMap[mesh].end())
|
||||
dae_model_map::const_iterator it = mModelsMap.find(mesh);
|
||||
if (it != mModelsMap.end())
|
||||
{
|
||||
LLPointer<LLModel> mdl = *i;
|
||||
LLDAELoader::processDomModel(mdl, &dae, root, mesh, skin);
|
||||
i++;
|
||||
for (const LLPointer<LLModel>& model : it->second)
|
||||
{
|
||||
LLDAELoader::processDomModel(model, &dae, root, mesh, skin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1282,9 +1270,9 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
|||
mesh_scale *= normalized_transformation;
|
||||
normalized_transformation = mesh_scale;
|
||||
|
||||
glh::matrix4f inv_mat((F32*) normalized_transformation.mMatrix);
|
||||
inv_mat = inv_mat.inverse();
|
||||
LLMatrix4 inverse_normalized_transformation(inv_mat.m);
|
||||
glm::mat4 inv_mat = glm::make_mat4((F32*)normalized_transformation.mMatrix);
|
||||
inv_mat = glm::inverse(inv_mat);
|
||||
LLMatrix4 inverse_normalized_transformation(glm::value_ptr(inv_mat));
|
||||
|
||||
domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix();
|
||||
|
||||
|
|
@ -1360,6 +1348,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
|||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Has one or more skeletons
|
||||
for (std::vector<domInstance_controller::domSkeleton*>::iterator skel_it = skeletons.begin();
|
||||
skel_it != skeletons.end(); ++skel_it)
|
||||
|
|
@ -1444,6 +1433,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
|||
}
|
||||
}//got skeleton?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
domSkin::domJoints* joints = skin->getJoints();
|
||||
|
|
@ -1760,7 +1750,7 @@ void LLDAELoader::processDomModel(LLModel* model, DAE* dae, daeElement* root, do
|
|||
materials[model->mMaterialList[i]] = LLImportMaterial();
|
||||
}
|
||||
mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials));
|
||||
stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
|
||||
stretch_extents(model, transformation);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2153,102 +2143,99 @@ void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* da
|
|||
mTransform.condition();
|
||||
}
|
||||
|
||||
domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element);
|
||||
if (instance_geo)
|
||||
if (domInstance_geometry* instance_geo = daeSafeCast<domInstance_geometry>(element))
|
||||
{
|
||||
domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement());
|
||||
if (geo)
|
||||
if (domGeometry* geo = daeSafeCast<domGeometry>(instance_geo->getUrl().getElement()))
|
||||
{
|
||||
domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID())));
|
||||
if (mesh)
|
||||
if (domMesh* mesh = daeSafeCast<domMesh>(geo->getDescendant(daeElement::matchType(domMesh::ID()))))
|
||||
{
|
||||
|
||||
std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin();
|
||||
while (i != mModelsMap[mesh].end())
|
||||
dae_model_map::iterator it = mModelsMap.find(mesh);
|
||||
if (it != mModelsMap.end())
|
||||
{
|
||||
LLModel* model = *i;
|
||||
|
||||
LLMatrix4 transformation = mTransform;
|
||||
|
||||
if (mTransform.determinant() < 0)
|
||||
{ //negative scales are not supported
|
||||
LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL;
|
||||
LLSD args;
|
||||
args["Message"] = "NegativeScaleTrans";
|
||||
args["LABEL"] = getElementLabel(instance_geo);
|
||||
mWarningsArray.append(args);
|
||||
|
||||
badElement = true;
|
||||
}
|
||||
|
||||
LLModelLoader::material_map materials = getMaterials(model, instance_geo, dae);
|
||||
|
||||
// adjust the transformation to compensate for mesh normalization
|
||||
LLVector3 mesh_scale_vector;
|
||||
LLVector3 mesh_translation_vector;
|
||||
model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
|
||||
|
||||
LLMatrix4 mesh_translation;
|
||||
mesh_translation.setTranslation(mesh_translation_vector);
|
||||
mesh_translation *= transformation;
|
||||
transformation = mesh_translation;
|
||||
|
||||
LLMatrix4 mesh_scale;
|
||||
mesh_scale.initScale(mesh_scale_vector);
|
||||
mesh_scale *= transformation;
|
||||
transformation = mesh_scale;
|
||||
|
||||
if (transformation.determinant() < 0)
|
||||
{ //negative scales are not supported
|
||||
LL_INFOS() << "Negative scale detected, unsupported post-normalization transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL;
|
||||
LLSD args;
|
||||
args["Message"] = "NegativeScaleNormTrans";
|
||||
args["LABEL"] = getElementLabel(instance_geo);
|
||||
mWarningsArray.append(args);
|
||||
badElement = true;
|
||||
}
|
||||
|
||||
std::string label;
|
||||
|
||||
if (model->mLabel.empty())
|
||||
for (LLModel* model : it->second)
|
||||
{
|
||||
label = getLodlessLabel(instance_geo);
|
||||
LLMatrix4 transformation = mTransform;
|
||||
|
||||
llassert(!label.empty());
|
||||
if (mTransform.determinant() < 0)
|
||||
{ //negative scales are not supported
|
||||
LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL;
|
||||
LLSD args;
|
||||
args["Message"] = "NegativeScaleTrans";
|
||||
args["LABEL"] = getElementLabel(instance_geo);
|
||||
mWarningsArray.append(args);
|
||||
|
||||
if (model->mSubmodelID)
|
||||
{
|
||||
label += (char)((int)'a' + model->mSubmodelID);
|
||||
badElement = true;
|
||||
}
|
||||
// <FS:Beq> Support altenate LOD naming conventions
|
||||
// model->mLabel = label + sLODSuffix[mLod];
|
||||
if ( sLODSuffix[mLod].size() > 0 )
|
||||
|
||||
LLModelLoader::material_map materials = getMaterials(model, instance_geo, dae);
|
||||
|
||||
// adjust the transformation to compensate for mesh normalization
|
||||
LLVector3 mesh_scale_vector;
|
||||
LLVector3 mesh_translation_vector;
|
||||
model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector);
|
||||
|
||||
LLMatrix4 mesh_translation;
|
||||
mesh_translation.setTranslation(mesh_translation_vector);
|
||||
mesh_translation *= transformation;
|
||||
transformation = mesh_translation;
|
||||
|
||||
LLMatrix4 mesh_scale;
|
||||
mesh_scale.initScale(mesh_scale_vector);
|
||||
mesh_scale *= transformation;
|
||||
transformation = mesh_scale;
|
||||
|
||||
if (transformation.determinant() < 0)
|
||||
{ //negative scales are not supported
|
||||
LL_INFOS() << "Negative scale detected, unsupported post-normalization transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL;
|
||||
LLSD args;
|
||||
args["Message"] = "NegativeScaleNormTrans";
|
||||
args["LABEL"] = getElementLabel(instance_geo);
|
||||
mWarningsArray.append(args);
|
||||
badElement = true;
|
||||
}
|
||||
|
||||
std::string label;
|
||||
|
||||
if (model->mLabel.empty())
|
||||
{
|
||||
model->mLabel = label + '_' + sLODSuffix[mLod];
|
||||
label = getLodlessLabel(instance_geo);
|
||||
|
||||
llassert(!label.empty());
|
||||
|
||||
if (model->mSubmodelID)
|
||||
{
|
||||
label += (char)((int)'a' + model->mSubmodelID);
|
||||
}
|
||||
|
||||
// <FS:Beq> Support altenate LOD naming conventions
|
||||
//model->mLabel = label + lod_suffix[mLod];
|
||||
if (sLODSuffix[mLod].size() > 0)
|
||||
{
|
||||
model->mLabel = label + '_' + sLODSuffix[mLod];
|
||||
}
|
||||
else
|
||||
{
|
||||
model->mLabel = label;
|
||||
}
|
||||
// </FS:Beq>
|
||||
}
|
||||
else
|
||||
{
|
||||
model->mLabel = label;
|
||||
// Don't change model's name if possible, it will play havoc with scenes that already use said model.
|
||||
size_t ext_pos = getSuffixPosition(model->mLabel);
|
||||
if (ext_pos != -1)
|
||||
{
|
||||
label = model->mLabel.substr(0, ext_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
label = model->mLabel;
|
||||
}
|
||||
}
|
||||
// </FS:Beq>
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't change model's name if possible, it will play havoc with scenes that already use said model.
|
||||
size_t ext_pos = getSuffixPosition(model->mLabel);
|
||||
if (ext_pos != -1)
|
||||
{
|
||||
label = model->mLabel.substr(0, ext_pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
label = model->mLabel;
|
||||
}
|
||||
}
|
||||
|
||||
mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials));
|
||||
stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform);
|
||||
i++;
|
||||
mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials));
|
||||
stretch_extents(model, transformation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@
|
|||
#include "llsdserialize.h"
|
||||
#include "lljoint.h"
|
||||
|
||||
#include "glh/glh_linear.h"
|
||||
#include "llmatrix4a.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
|
|
|
|||
|
|
@ -94,19 +94,15 @@ std::string LLModel::getStatusString(U32 status)
|
|||
}
|
||||
|
||||
|
||||
void LLModel::offsetMesh( const LLVector3& pivotPoint )
|
||||
void LLModel::offsetMesh(const LLVector3& pivotPoint)
|
||||
{
|
||||
LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] );
|
||||
LLVector4a pivot(pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ]);
|
||||
|
||||
for (std::vector<LLVolumeFace>::iterator faceIt = mVolumeFaces.begin(); faceIt != mVolumeFaces.end(); )
|
||||
for (LLVolumeFace& face : mVolumeFaces)
|
||||
{
|
||||
std::vector<LLVolumeFace>:: iterator currentFaceIt = faceIt++;
|
||||
LLVolumeFace& face = *currentFaceIt;
|
||||
LLVector4a *pos = (LLVector4a*) face.mPositions;
|
||||
|
||||
for (S32 i=0; i<face.mNumVertices; ++i )
|
||||
for (S32 i = 0; i < face.mNumVertices; ++i)
|
||||
{
|
||||
pos[i].add( pivot );
|
||||
face.mPositions[i].add(pivot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -350,7 +346,7 @@ void LLModel::normalizeVolumeFaces()
|
|||
}
|
||||
}
|
||||
|
||||
void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out)
|
||||
void LLModel::getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) const
|
||||
{
|
||||
scale_out = mNormalizedScale;
|
||||
translation_out = mNormalizedTranslation;
|
||||
|
|
@ -1577,6 +1573,13 @@ void LLMeshSkinInfo::fromLLSD(LLSD& skin)
|
|||
mLockScaleIfJointPosition = false;
|
||||
}
|
||||
|
||||
// combine mBindShapeMatrix and mInvBindMatrix into mBindPoseMatrix
|
||||
mBindPoseMatrix.resize(mInvBindMatrix.size());
|
||||
for (U32 i = 0; i < mInvBindMatrix.size(); ++i)
|
||||
{
|
||||
matMul(mBindShapeMatrix, mInvBindMatrix[i], mBindPoseMatrix[i]);
|
||||
}
|
||||
|
||||
updateHash();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,12 +61,15 @@ public:
|
|||
std::vector< JointKey > mJointNames;
|
||||
// </FS:ND>
|
||||
mutable std::vector<S32> mJointNums;
|
||||
typedef std::vector<LLMatrix4a, boost::alignment::aligned_allocator<LLMatrix4a, 16>> matrix_list_t;
|
||||
typedef std::vector<LLMatrix4a> matrix_list_t;
|
||||
matrix_list_t mInvBindMatrix;
|
||||
|
||||
// bones/joints position overrides
|
||||
matrix_list_t mAlternateBindMatrix;
|
||||
|
||||
// cached multiply of mBindShapeMatrix and mInvBindMatrix
|
||||
matrix_list_t mBindPoseMatrix;
|
||||
|
||||
LL_ALIGN_16(LLMatrix4a mBindShapeMatrix);
|
||||
|
||||
float mPelvisOffset;
|
||||
|
|
@ -208,7 +211,7 @@ public:
|
|||
void remapVolumeFaces();
|
||||
void optimizeVolumeFaces();
|
||||
void offsetMesh( const LLVector3& pivotPoint );
|
||||
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
|
||||
void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out) const;
|
||||
LLVector3 getTransformedCenter(const LLMatrix4& mat);
|
||||
|
||||
//reorder face list based on mMaterialList in this and reference so
|
||||
|
|
|
|||
|
|
@ -31,17 +31,6 @@
|
|||
#include "lljoint.h"
|
||||
#include "llcallbacklist.h"
|
||||
|
||||
#if LL_LINUX && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) >= 70000
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
|
||||
#endif
|
||||
|
||||
#include "glh/glh_linear.h"
|
||||
|
||||
#if LL_LINUX && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) >= 70000
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
|
||||
#include "llmatrix4a.h"
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
|
|
@ -49,7 +38,7 @@
|
|||
|
||||
std::list<LLModelLoader*> LLModelLoader::sActiveLoaderList;
|
||||
|
||||
void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, bool& first_transform)
|
||||
static void stretch_extents(const LLModel* model, const LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, bool& first_transform)
|
||||
{
|
||||
LLVector4a box[] =
|
||||
{
|
||||
|
|
@ -97,19 +86,19 @@ void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4
|
|||
}
|
||||
}
|
||||
|
||||
void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, bool& first_transform)
|
||||
void LLModelLoader::stretch_extents(const LLModel* model, const LLMatrix4& mat)
|
||||
{
|
||||
LLVector4a mina, maxa;
|
||||
LLMatrix4a mata;
|
||||
|
||||
mata.loadu(mat);
|
||||
mina.load3(min.mV);
|
||||
maxa.load3(max.mV);
|
||||
mina.load3(mExtents[0].mV);
|
||||
maxa.load3(mExtents[1].mV);
|
||||
|
||||
stretch_extents(model, mata, mina, maxa, first_transform);
|
||||
::stretch_extents(model, mata, mina, maxa, mFirstTransform);
|
||||
|
||||
min.set(mina.getF32ptr());
|
||||
max.set(maxa.getF32ptr());
|
||||
mExtents[0].set(mina.getF32ptr());
|
||||
mExtents[1].set(maxa.getF32ptr());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -307,14 +296,7 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
|
|||
{
|
||||
if (idx >= model[lod].size())
|
||||
{
|
||||
if (model[lod].size())
|
||||
{
|
||||
instance_list[i].mLOD[lod] = model[lod][0];
|
||||
}
|
||||
else
|
||||
{
|
||||
instance_list[i].mLOD[lod] = NULL;
|
||||
}
|
||||
instance_list[i].mLOD[lod] = model[lod].front();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -360,7 +342,7 @@ bool LLModelLoader::loadFromSLM(const std::string& filename)
|
|||
{
|
||||
LLModelInstance& cur_instance = instance_list[i];
|
||||
mScene[cur_instance.mTransform].push_back(cur_instance);
|
||||
stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform);
|
||||
stretch_extents(cur_instance.mModel, cur_instance.mTransform);
|
||||
}
|
||||
|
||||
setLoadState( DONE );
|
||||
|
|
|
|||
|
|
@ -34,13 +34,13 @@
|
|||
|
||||
class LLJoint;
|
||||
|
||||
typedef std::map<std::string, LLMatrix4> JointTransformMap;
|
||||
typedef std::map<std::string, LLMatrix4>::iterator JointTransformMapIt;
|
||||
typedef std::map<std::string, std::string> JointMap;
|
||||
typedef std::deque<std::string> JointNameSet;
|
||||
typedef std::map<std::string, LLMatrix4> JointTransformMap;
|
||||
typedef std::map<std::string, LLMatrix4>::iterator JointTransformMapIt;
|
||||
typedef std::map<std::string, std::string> JointMap;
|
||||
typedef std::deque<std::string> JointNameSet;
|
||||
|
||||
const S32 SLM_SUPPORTED_VERSION = 3;
|
||||
const S32 NUM_LOD = 4;
|
||||
const S32 NUM_LOD = 4;
|
||||
|
||||
const U32 LEGACY_RIG_OK = 0;
|
||||
const U32 LEGACY_RIG_FLAG_TOO_MANY_JOINTS = 1;
|
||||
|
|
@ -50,32 +50,32 @@ class LLModelLoader : public LLThread
|
|||
{
|
||||
public:
|
||||
|
||||
typedef std::map<std::string, LLImportMaterial> material_map;
|
||||
typedef std::vector<LLPointer<LLModel > > model_list;
|
||||
typedef std::vector<LLModelInstance> model_instance_list;
|
||||
typedef std::map<LLMatrix4, model_instance_list > scene;
|
||||
typedef std::map<std::string, LLImportMaterial> material_map;
|
||||
typedef std::vector<LLPointer<LLModel>> model_list;
|
||||
typedef std::vector<LLModelInstance> model_instance_list;
|
||||
typedef std::map<LLMatrix4, model_instance_list> scene;
|
||||
|
||||
// Callback with loaded model data and loaded LoD
|
||||
//
|
||||
typedef boost::function<void (scene&,model_list&,S32,void*) > load_callback_t;
|
||||
typedef boost::function<void (scene&, model_list&, S32, void*)> load_callback_t;
|
||||
|
||||
// Function to provide joint lookup by name
|
||||
// (within preview avi skeleton, for example)
|
||||
//
|
||||
typedef boost::function<LLJoint* (const std::string&,void*) > joint_lookup_func_t;
|
||||
typedef boost::function<LLJoint* (const std::string&, void*)> joint_lookup_func_t;
|
||||
|
||||
// Func to load and associate material with all it's textures,
|
||||
// returned value is the number of textures loaded
|
||||
// intentionally non-const so func can modify material to
|
||||
// store platform-specific data
|
||||
//
|
||||
typedef boost::function<U32 (LLImportMaterial&,void*) > texture_load_func_t;
|
||||
typedef boost::function<U32 (LLImportMaterial&, void*)> texture_load_func_t;
|
||||
|
||||
// Callback to inform client of state changes
|
||||
// during loading process (errors will be reported
|
||||
// as state changes here as well)
|
||||
//
|
||||
typedef boost::function<void (U32,void*) > state_callback_t;
|
||||
typedef boost::function<void (U32, void*)> state_callback_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
@ -138,7 +138,7 @@ public:
|
|||
JointNameSet& jointsFromNodes,
|
||||
JointMap& legalJointNamesMap,
|
||||
U32 maxJointsPerMesh);
|
||||
virtual ~LLModelLoader() ;
|
||||
virtual ~LLModelLoader();
|
||||
|
||||
virtual void setNoNormalize() { mNoNormalize = true; }
|
||||
virtual void setNoOptimize() { mNoOptimize = true; }
|
||||
|
|
@ -158,13 +158,13 @@ public:
|
|||
bool loadFromSLM(const std::string& filename);
|
||||
|
||||
void loadModelCallback();
|
||||
void loadTextures() ; //called in the main thread.
|
||||
void loadTextures() ; // called in the main thread.
|
||||
void setLoadState(U32 state);
|
||||
|
||||
void stretch_extents(const LLModel* model, const LLMatrix4& mat);
|
||||
|
||||
|
||||
S32 mNumOfFetchingTextures ; //updated in the main thread
|
||||
bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread.
|
||||
S32 mNumOfFetchingTextures ; // updated in the main thread
|
||||
bool areTexturesReady() { return !mNumOfFetchingTextures; } // called in the main thread.
|
||||
|
||||
bool verifyCount( int expected, int result );
|
||||
|
||||
|
|
@ -225,10 +225,7 @@ protected:
|
|||
LLSD mWarningsArray; // preview floater will pull logs from here
|
||||
|
||||
static std::list<LLModelLoader*> sActiveLoaderList;
|
||||
static bool isAlive(LLModelLoader* loader) ;
|
||||
static bool isAlive(LLModelLoader* loader);
|
||||
};
|
||||
class LLMatrix4a;
|
||||
void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, bool& first_transform);
|
||||
void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, bool& first_transform);
|
||||
|
||||
#endif // LL_LLMODELLOADER_H
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ set(llrender_SOURCE_FILES
|
|||
llfontfreetype.cpp
|
||||
llfontfreetypesvg.cpp
|
||||
llfontgl.cpp
|
||||
llfontvertexbuffer.cpp
|
||||
llfontregistry.cpp
|
||||
llgl.cpp
|
||||
llglslshader.cpp
|
||||
|
|
@ -43,6 +44,7 @@ set(llrender_HEADER_FILES
|
|||
llcubemap.h
|
||||
llcubemaparray.h
|
||||
llfontgl.h
|
||||
llfontvertexbuffer.h
|
||||
llfontfreetype.h
|
||||
llfontfreetypesvg.h
|
||||
llfontbitmapcache.h
|
||||
|
|
|
|||
|
|
@ -125,27 +125,25 @@ void LLCubeMapArray::allocate(U32 resolution, U32 components, U32 count, bool us
|
|||
mImage->setHasMipMaps(use_mips);
|
||||
|
||||
bind(0);
|
||||
|
||||
U32 format = components == 4 ? GL_RGBA16F : GL_RGB16F;
|
||||
|
||||
U32 mip = 0;
|
||||
|
||||
free_cur_tex_image();
|
||||
|
||||
while (resolution >= 1)
|
||||
U32 format = components == 4 ? GL_RGBA16F : GL_RGB16F;
|
||||
U32 mip = 0;
|
||||
U32 mip_resolution = resolution;
|
||||
while (mip_resolution >= 1)
|
||||
{
|
||||
glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, format, resolution, resolution, count * 6, 0,
|
||||
glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, mip, format, mip_resolution, mip_resolution, count * 6, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
if (!use_mips)
|
||||
{
|
||||
break;
|
||||
}
|
||||
resolution /= 2;
|
||||
mip_resolution /= 2;
|
||||
++mip;
|
||||
}
|
||||
|
||||
alloc_tex_image(resolution * 6, resolution, format);
|
||||
alloc_tex_image(resolution, resolution, format, count * 6);
|
||||
|
||||
mImage->setAddressMode(LLTexUnit::TAM_CLAMP);
|
||||
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp
|
|||
}
|
||||
|
||||
// Make corresponding GL image.
|
||||
mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false));
|
||||
mImageGLVec[bitmap_idx].push_back(new LLImageGL(image_raw, false, false));
|
||||
LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);
|
||||
|
||||
// Start at beginning of the new image.
|
||||
|
|
|
|||
|
|
@ -270,15 +270,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
|
||||
const LLFontGlyphInfo* next_glyph = NULL;
|
||||
|
||||
const S32 GLYPH_BATCH_SIZE = 30;
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//LLVector3 vertices[GLYPH_BATCH_SIZE * 4];
|
||||
//LLVector2 uvs[GLYPH_BATCH_SIZE * 4];
|
||||
//LLColor4U colors[GLYPH_BATCH_SIZE * 4];
|
||||
LLVector3 vertices[GLYPH_BATCH_SIZE * 6];
|
||||
LLVector2 uvs[GLYPH_BATCH_SIZE * 6];
|
||||
LLColor4U colors[GLYPH_BATCH_SIZE * 6];
|
||||
// </FS:Ansariel>
|
||||
static constexpr S32 GLYPH_BATCH_SIZE = 30;
|
||||
static thread_local LLVector4a vertices[GLYPH_BATCH_SIZE * 6];
|
||||
static thread_local LLVector2 uvs[GLYPH_BATCH_SIZE * 6];
|
||||
static thread_local LLColor4U colors[GLYPH_BATCH_SIZE * 6];
|
||||
|
||||
LLColor4U text_color(color);
|
||||
// Preserve the transparency to render fading emojis in fading text (e.g.
|
||||
|
|
@ -310,12 +305,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
// otherwise the queued glyphs will be taken from wrong textures.
|
||||
if (glyph_count > 0)
|
||||
{
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//gGL.begin(LLRender::QUADS);
|
||||
//{
|
||||
// gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
|
||||
//}
|
||||
//gGL.end();
|
||||
gGL.begin(LLRender::TRIANGLES);
|
||||
{
|
||||
gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6);
|
||||
|
|
@ -350,18 +339,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
|
||||
if (glyph_count >= GLYPH_BATCH_SIZE)
|
||||
{
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//gGL.begin(LLRender::QUADS);
|
||||
//{
|
||||
// gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
|
||||
//}
|
||||
//gGL.end();
|
||||
gGL.begin(LLRender::TRIANGLES);
|
||||
{
|
||||
gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6);
|
||||
}
|
||||
gGL.end();
|
||||
// </FS:Ansariel>
|
||||
|
||||
glyph_count = 0;
|
||||
}
|
||||
|
|
@ -395,18 +377,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
cur_render_y = cur_y;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//gGL.begin(LLRender::QUADS);
|
||||
//{
|
||||
// gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 4);
|
||||
//}
|
||||
//gGL.end();
|
||||
gGL.begin(LLRender::TRIANGLES);
|
||||
{
|
||||
gGL.vertexBatchPreTransformed(vertices, uvs, colors, glyph_count * 6);
|
||||
}
|
||||
gGL.end();
|
||||
// </FS:Ansariel>
|
||||
|
||||
|
||||
if (right_x)
|
||||
|
|
@ -428,10 +403,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
|
||||
if (draw_ellipses)
|
||||
{
|
||||
|
||||
// recursively render ellipses at end of string
|
||||
// we've already reserved enough room
|
||||
gGL.pushUIMatrix();
|
||||
static LLWString elipses_wstr(utf8string_to_wstring(std::string("...")));
|
||||
render(elipses_wstr,
|
||||
0,
|
||||
|
|
@ -444,7 +417,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
right_x,
|
||||
false,
|
||||
use_color);
|
||||
gGL.popUIMatrix();
|
||||
}
|
||||
|
||||
gGL.popUIMatrix();
|
||||
|
|
@ -530,6 +502,7 @@ F32 LLFontGL::getWidthF32(const std::string& utf8text, S32 begin_offset, S32 max
|
|||
|
||||
F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars, bool no_padding) const
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_UI;
|
||||
const S32 LAST_CHARACTER = LLFontFreetype::LAST_CHAR_FULL;
|
||||
|
||||
F32 cur_x = 0;
|
||||
|
|
@ -1359,67 +1332,42 @@ LLFontGL &LLFontGL::operator=(const LLFontGL &source)
|
|||
return *this;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const
|
||||
//{
|
||||
// S32 index = 0;
|
||||
//
|
||||
// vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);
|
||||
// uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
|
||||
// colors_out[index] = color;
|
||||
// index++;
|
||||
//
|
||||
// vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f);
|
||||
// uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
|
||||
// colors_out[index] = color;
|
||||
// index++;
|
||||
//
|
||||
// vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f);
|
||||
// uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
|
||||
// colors_out[index] = color;
|
||||
// index++;
|
||||
//
|
||||
// vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f);
|
||||
// uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
|
||||
// colors_out[index] = color;
|
||||
//}
|
||||
void LLFontGL::renderTriangle(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const
|
||||
void LLFontGL::renderTriangle(LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const
|
||||
{
|
||||
S32 index = 0;
|
||||
|
||||
vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);
|
||||
uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
|
||||
vertex_out[index].set(screen_rect.mRight, screen_rect.mTop, 0.f);
|
||||
uv_out[index].set(uv_rect.mRight, uv_rect.mTop);
|
||||
colors_out[index] = color;
|
||||
index++;
|
||||
|
||||
vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f);
|
||||
uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
|
||||
vertex_out[index].set(screen_rect.mLeft, screen_rect.mTop, 0.f);
|
||||
uv_out[index].set(uv_rect.mLeft, uv_rect.mTop);
|
||||
colors_out[index] = color;
|
||||
index++;
|
||||
|
||||
vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f);
|
||||
uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
|
||||
vertex_out[index].set(screen_rect.mLeft, screen_rect.mBottom, 0.f);
|
||||
uv_out[index].set(uv_rect.mLeft, uv_rect.mBottom);
|
||||
colors_out[index] = color;
|
||||
index++;
|
||||
|
||||
|
||||
vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);
|
||||
uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
|
||||
vertex_out[index].set(screen_rect.mRight, screen_rect.mTop, 0.f);
|
||||
uv_out[index].set(uv_rect.mRight, uv_rect.mTop);
|
||||
colors_out[index] = color;
|
||||
index++;
|
||||
|
||||
vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f);
|
||||
uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
|
||||
vertex_out[index].set(screen_rect.mLeft, screen_rect.mBottom, 0.f);
|
||||
uv_out[index].set(uv_rect.mLeft, uv_rect.mBottom);
|
||||
colors_out[index] = color;
|
||||
index++;
|
||||
|
||||
vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f);
|
||||
uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
|
||||
vertex_out[index].set(screen_rect.mRight, screen_rect.mBottom, 0.f);
|
||||
uv_out[index].set(uv_rect.mRight, uv_rect.mBottom);
|
||||
colors_out[index] = color;
|
||||
}
|
||||
// </FS:Ansariel>
|
||||
|
||||
void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
|
||||
void LLFontGL::drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const
|
||||
{
|
||||
F32 slant_offset;
|
||||
slant_offset = ((style & ITALIC) ? ( -mFontFreetype->getAscenderHeight() * 0.2f) : 0.f);
|
||||
|
|
@ -1433,10 +1381,7 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_
|
|||
LLRectf screen_rect_offset = screen_rect;
|
||||
|
||||
screen_rect_offset.translate((F32)(pass * BOLD_OFFSET), 0.f);
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, color, slant_offset);
|
||||
renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect_offset, uv_rect, color, slant_offset);
|
||||
// </FS:Ansariel>
|
||||
glyph_count++;
|
||||
}
|
||||
}
|
||||
|
|
@ -1467,16 +1412,10 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_
|
|||
break;
|
||||
}
|
||||
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_offset, uv_rect, shadow_color, slant_offset);
|
||||
renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect_offset, uv_rect, shadow_color, slant_offset);
|
||||
// </FS:Ansariel>
|
||||
glyph_count++;
|
||||
}
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
|
||||
renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect, uv_rect, color, slant_offset);
|
||||
// </FS:Ansariel>
|
||||
glyph_count++;
|
||||
}
|
||||
else if (shadow == DROP_SHADOW)
|
||||
|
|
@ -1485,22 +1424,14 @@ void LLFontGL::drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_
|
|||
shadow_color.mV[VALPHA] = U8(color.mV[VALPHA] * drop_shadow_strength);
|
||||
LLRectf screen_rect_shadow = screen_rect;
|
||||
screen_rect_shadow.translate(1.f, -1.f);
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect_shadow, uv_rect, shadow_color, slant_offset);
|
||||
//glyph_count++;
|
||||
//renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
|
||||
renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect_shadow, uv_rect, shadow_color, slant_offset);
|
||||
glyph_count++;
|
||||
renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect, uv_rect, color, slant_offset);
|
||||
// </FS:Ansariel>
|
||||
glyph_count++;
|
||||
}
|
||||
else // normal rendering
|
||||
{
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//renderQuad(&vertex_out[glyph_count * 4], &uv_out[glyph_count * 4], &colors_out[glyph_count * 4], screen_rect, uv_rect, color, slant_offset);
|
||||
renderTriangle(&vertex_out[glyph_count * 6], &uv_out[glyph_count * 6], &colors_out[glyph_count * 6], screen_rect, uv_rect, color, slant_offset);
|
||||
// </FS:Ansariel>
|
||||
glyph_count++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -249,11 +249,8 @@ private:
|
|||
LLFontDescriptor mFontDescriptor;
|
||||
LLPointer<LLFontFreetype> mFontFreetype;
|
||||
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//void renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const;
|
||||
void renderTriangle(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const;
|
||||
// </FS:Ansariel>
|
||||
void drawGlyph(S32& glyph_count, LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;
|
||||
void renderTriangle(LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, F32 slant_amt) const;
|
||||
void drawGlyph(S32& glyph_count, LLVector4a* vertex_out, LLVector2* uv_out, LLColor4U* colors_out, const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4U& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const;
|
||||
|
||||
// Registry holds all instantiated fonts.
|
||||
static LLFontRegistry* sFontRegistry;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
* @file llfontvertexbuffer.cpp
|
||||
* @brief Buffer storage for font rendering.
|
||||
*
|
||||
* $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 "linden_common.h"
|
||||
|
||||
#include "llfontvertexbuffer.h"
|
||||
|
||||
#include "llvertexbuffer.h"
|
||||
|
||||
|
||||
bool LLFontVertexBuffer::sEnableBufferCollection = true;
|
||||
|
||||
LLFontVertexBuffer::LLFontVertexBuffer()
|
||||
{
|
||||
}
|
||||
|
||||
LLFontVertexBuffer::~LLFontVertexBuffer()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void LLFontVertexBuffer::reset()
|
||||
{
|
||||
// Todo: some form of debug only frequecy check&assert to see if this is happening too often.
|
||||
// Regenerating this list is expensive
|
||||
mBufferList.clear();
|
||||
}
|
||||
|
||||
S32 LLFontVertexBuffer::render(
|
||||
const LLFontGL* fontp,
|
||||
const LLWString& text,
|
||||
S32 begin_offset,
|
||||
LLRect rect,
|
||||
const LLColor4& color,
|
||||
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
|
||||
U8 style,
|
||||
LLFontGL::ShadowType shadow,
|
||||
S32 max_chars, S32 max_pixels,
|
||||
F32* right_x,
|
||||
bool use_ellipses,
|
||||
bool use_color)
|
||||
{
|
||||
LLRectf rect_float((F32)rect.mLeft, (F32)rect.mTop, (F32)rect.mRight, (F32)rect.mBottom);
|
||||
return render(fontp, text, begin_offset, rect_float, color, halign, valign, style, shadow, max_chars, right_x, use_ellipses, use_color);
|
||||
}
|
||||
|
||||
S32 LLFontVertexBuffer::render(
|
||||
const LLFontGL* fontp,
|
||||
const LLWString& text,
|
||||
S32 begin_offset,
|
||||
LLRectf rect,
|
||||
const LLColor4& color,
|
||||
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
|
||||
U8 style,
|
||||
LLFontGL::ShadowType shadow,
|
||||
S32 max_chars,
|
||||
F32* right_x,
|
||||
bool use_ellipses,
|
||||
bool use_color)
|
||||
{
|
||||
F32 x = rect.mLeft;
|
||||
F32 y = 0.f;
|
||||
|
||||
switch (valign)
|
||||
{
|
||||
case LLFontGL::TOP:
|
||||
y = rect.mTop;
|
||||
break;
|
||||
case LLFontGL::VCENTER:
|
||||
y = rect.getCenterY();
|
||||
break;
|
||||
case LLFontGL::BASELINE:
|
||||
case LLFontGL::BOTTOM:
|
||||
y = rect.mBottom;
|
||||
break;
|
||||
default:
|
||||
y = rect.mBottom;
|
||||
break;
|
||||
}
|
||||
return render(fontp, text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, (S32)rect.getWidth(), right_x, use_ellipses, use_color);
|
||||
}
|
||||
|
||||
S32 LLFontVertexBuffer::render(
|
||||
const LLFontGL* fontp,
|
||||
const LLWString& text,
|
||||
S32 begin_offset,
|
||||
F32 x, F32 y,
|
||||
const LLColor4& color,
|
||||
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
|
||||
U8 style,
|
||||
LLFontGL::ShadowType shadow,
|
||||
S32 max_chars , S32 max_pixels,
|
||||
F32* right_x,
|
||||
bool use_ellipses,
|
||||
bool use_color )
|
||||
{
|
||||
if (!LLFontGL::sDisplayFont) //do not display texts
|
||||
{
|
||||
return static_cast<S32>(text.length());
|
||||
}
|
||||
if (!sEnableBufferCollection)
|
||||
{
|
||||
// For debug purposes and performance testing
|
||||
return fontp->render(text, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
|
||||
}
|
||||
if (mBufferList.empty())
|
||||
{
|
||||
genBuffers(fontp, text, begin_offset, x, y, color, halign, valign,
|
||||
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
|
||||
}
|
||||
else if (mLastX != x
|
||||
|| mLastY != y
|
||||
|| mLastFont != fontp
|
||||
|| mLastColor != color // alphas change often
|
||||
|| mLastHalign != halign
|
||||
|| mLastValign != valign
|
||||
|| mLastOffset != begin_offset
|
||||
|| mLastMaxChars != max_chars
|
||||
|| mLastMaxPixels != max_pixels
|
||||
|| mLastStyle != style
|
||||
|| mLastShadow != shadow // ex: buttons change shadow state
|
||||
|| mLastScaleX != LLFontGL::sScaleX
|
||||
|| mLastScaleY != LLFontGL::sScaleY
|
||||
|| mLastVertDPI != LLFontGL::sVertDPI
|
||||
|| mLastHorizDPI != LLFontGL::sHorizDPI
|
||||
|| mLastOrigin != LLFontGL::sCurOrigin)
|
||||
{
|
||||
genBuffers(fontp, text, begin_offset, x, y, color, halign, valign,
|
||||
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderBuffers();
|
||||
|
||||
if (right_x)
|
||||
{
|
||||
*right_x = mLastRightX;
|
||||
}
|
||||
}
|
||||
return mChars;
|
||||
}
|
||||
|
||||
void LLFontVertexBuffer::genBuffers(
|
||||
const LLFontGL* fontp,
|
||||
const LLWString& text,
|
||||
S32 begin_offset,
|
||||
F32 x, F32 y,
|
||||
const LLColor4& color,
|
||||
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
|
||||
U8 style, LLFontGL::ShadowType shadow,
|
||||
S32 max_chars, S32 max_pixels,
|
||||
F32* right_x,
|
||||
bool use_ellipses,
|
||||
bool use_color)
|
||||
{
|
||||
// todo: add a debug build assert if this triggers too often for to long?
|
||||
mBufferList.clear();
|
||||
|
||||
gGL.beginList(&mBufferList);
|
||||
mChars = fontp->render(text, begin_offset, x, y, color, halign, valign,
|
||||
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
|
||||
gGL.endList();
|
||||
|
||||
mLastFont = fontp;
|
||||
mLastOffset = begin_offset;
|
||||
mLastMaxChars = max_chars;
|
||||
mLastMaxPixels = max_pixels;
|
||||
mLastX = x;
|
||||
mLastY = y;
|
||||
mLastColor = color;
|
||||
mLastHalign = halign;
|
||||
mLastValign = valign;
|
||||
mLastStyle = style;
|
||||
mLastShadow = shadow;
|
||||
|
||||
mLastScaleX = LLFontGL::sScaleX;
|
||||
mLastScaleY = LLFontGL::sScaleY;
|
||||
mLastVertDPI = LLFontGL::sVertDPI;
|
||||
mLastHorizDPI = LLFontGL::sHorizDPI;
|
||||
mLastOrigin = LLFontGL::sCurOrigin;
|
||||
|
||||
if (right_x)
|
||||
{
|
||||
mLastRightX = *right_x;
|
||||
}
|
||||
}
|
||||
|
||||
void LLFontVertexBuffer::renderBuffers()
|
||||
{
|
||||
gGL.flush(); // deliberately empty pending verts
|
||||
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
|
||||
gGL.pushUIMatrix();
|
||||
|
||||
gGL.loadUIIdentity();
|
||||
|
||||
// Depth translation, so that floating text appears 'in-world'
|
||||
// and is correctly occluded.
|
||||
gGL.translatef(0.f, 0.f, LLFontGL::sCurDepth);
|
||||
gGL.setSceneBlendType(LLRender::BT_ALPHA);
|
||||
|
||||
// Note: ellipses should technically be covered by push/load/translate of their own
|
||||
// but it's more complexity, values do not change, skipping doesn't appear to break
|
||||
// anything, so we can skip that until it proves to cause issues.
|
||||
for (LLVertexBufferData& buffer : mBufferList)
|
||||
{
|
||||
buffer.draw();
|
||||
}
|
||||
gGL.popUIMatrix();
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/**
|
||||
* @file llfontgl.h
|
||||
* @author Andrii Kleshchev
|
||||
* @brief Buffer storage for font rendering.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLFONTVERTEXBUFFER_H
|
||||
#define LL_LLFONTVERTEXBUFFER_H
|
||||
|
||||
#include "llfontgl.h"
|
||||
|
||||
class LLVertexBufferData;
|
||||
|
||||
class LLFontVertexBuffer
|
||||
{
|
||||
public:
|
||||
LLFontVertexBuffer();
|
||||
~LLFontVertexBuffer();
|
||||
|
||||
void reset();
|
||||
|
||||
S32 render(const LLFontGL* fontp,
|
||||
const LLWString& text,
|
||||
S32 begin_offset,
|
||||
LLRect rect,
|
||||
const LLColor4& color,
|
||||
LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE,
|
||||
U8 style = LLFontGL::NORMAL,
|
||||
LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW,
|
||||
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
|
||||
F32* right_x = NULL,
|
||||
bool use_ellipses = false,
|
||||
bool use_color = true);
|
||||
|
||||
S32 render(const LLFontGL* fontp,
|
||||
const LLWString& text,
|
||||
S32 begin_offset,
|
||||
LLRectf rect,
|
||||
const LLColor4& color,
|
||||
LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE,
|
||||
U8 style = LLFontGL::NORMAL,
|
||||
LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW,
|
||||
S32 max_chars = S32_MAX,
|
||||
F32* right_x = NULL,
|
||||
bool use_ellipses = false,
|
||||
bool use_color = true);
|
||||
|
||||
S32 render(const LLFontGL* fontp,
|
||||
const LLWString& text,
|
||||
S32 begin_offset,
|
||||
F32 x, F32 y,
|
||||
const LLColor4& color,
|
||||
LLFontGL::HAlign halign = LLFontGL::LEFT, LLFontGL::VAlign valign = LLFontGL::BASELINE,
|
||||
U8 style = LLFontGL::NORMAL,
|
||||
LLFontGL::ShadowType shadow = LLFontGL::NO_SHADOW,
|
||||
S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX,
|
||||
F32* right_x = NULL,
|
||||
bool use_ellipses = false,
|
||||
bool use_color = true);
|
||||
|
||||
static void enableBufferCollection(bool enable) { sEnableBufferCollection = enable; }
|
||||
private:
|
||||
|
||||
void genBuffers(const LLFontGL* fontp,
|
||||
const LLWString& text,
|
||||
S32 begin_offset,
|
||||
F32 x, F32 y,
|
||||
const LLColor4& color,
|
||||
LLFontGL::HAlign halign, LLFontGL::VAlign valign,
|
||||
U8 style,
|
||||
LLFontGL::ShadowType shadow,
|
||||
S32 max_chars, S32 max_pixels,
|
||||
F32* right_x,
|
||||
bool use_ellipses,
|
||||
bool use_color);
|
||||
|
||||
void renderBuffers();
|
||||
|
||||
std::list<LLVertexBufferData> mBufferList;
|
||||
S32 mChars = 0;
|
||||
const LLFontGL *mLastFont = nullptr;
|
||||
S32 mLastOffset = 0;
|
||||
S32 mLastMaxChars = 0;
|
||||
S32 mLastMaxPixels = 0;
|
||||
F32 mLastX = 0.f;
|
||||
F32 mLastY = 0.f;
|
||||
LLColor4 mLastColor;
|
||||
LLFontGL::HAlign mLastHalign = LLFontGL::LEFT;
|
||||
LLFontGL::VAlign mLastValign = LLFontGL::BASELINE;
|
||||
U8 mLastStyle = LLFontGL::NORMAL;
|
||||
LLFontGL::ShadowType mLastShadow = LLFontGL::NO_SHADOW;
|
||||
F32 mLastRightX = 0.f;
|
||||
|
||||
// LLFontGL's statics
|
||||
F32 mLastScaleX = 1.f;
|
||||
F32 mLastScaleY = 1.f;
|
||||
F32 mLastVertDPI = 0.f;
|
||||
F32 mLastHorizDPI = 0.f;
|
||||
LLCoordGL mLastOrigin;
|
||||
|
||||
static bool sEnableBufferCollection;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -50,6 +50,10 @@
|
|||
#include "llglheaders.h"
|
||||
#include "llglslshader.h"
|
||||
|
||||
#include "glm/glm.hpp"
|
||||
#include <glm/gtc/matrix_access.hpp>
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include "lldxhardware.h"
|
||||
#endif
|
||||
|
|
@ -1176,6 +1180,11 @@ bool LLGLManager::initGL()
|
|||
mGLVendorShort = "INTEL";
|
||||
mIsIntel = true;
|
||||
}
|
||||
else if (mGLVendor.find("APPLE") != std::string::npos)
|
||||
{
|
||||
mGLVendorShort = "APPLE";
|
||||
mIsApple = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
mGLVendorShort = "MISC";
|
||||
|
|
@ -1315,6 +1324,7 @@ bool LLGLManager::initGL()
|
|||
glGetIntegerv(GL_MAX_INTEGER_SAMPLES, &mMaxIntegerSamples);
|
||||
glGetIntegerv(GL_MAX_SAMPLE_MASK_WORDS, &mMaxSampleMaskWords);
|
||||
glGetIntegerv(GL_MAX_SAMPLES, &mMaxSamples);
|
||||
glGetIntegerv(GL_MAX_VARYING_VECTORS, &mMaxVaryingVectors);
|
||||
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &mMaxUniformBlockSize);
|
||||
|
||||
// sanity clamp max uniform block size to 64k just in case
|
||||
|
|
@ -2772,7 +2782,7 @@ void parse_glsl_version(S32& major, S32& minor)
|
|||
LLStringUtil::convertToS32(minor_str, minor);
|
||||
}
|
||||
|
||||
LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply)
|
||||
LLGLUserClipPlane::LLGLUserClipPlane(const LLPlane& p, const glm::mat4& modelview, const glm::mat4& projection, bool apply)
|
||||
{
|
||||
mApply = apply;
|
||||
|
||||
|
|
@ -2799,13 +2809,12 @@ void LLGLUserClipPlane::disable()
|
|||
|
||||
void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
|
||||
{
|
||||
glh::matrix4f& P = mProjection;
|
||||
glh::matrix4f& M = mModelview;
|
||||
const glm::mat4& P = mProjection;
|
||||
const glm::mat4& M = mModelview;
|
||||
|
||||
glh::matrix4f invtrans_MVP = (P * M).inverse().transpose();
|
||||
glh::vec4f oplane(a,b,c,d);
|
||||
glh::vec4f cplane;
|
||||
invtrans_MVP.mult_matrix_vec(oplane, cplane);
|
||||
glm::mat4 invtrans_MVP = glm::transpose(glm::inverse(P*M));
|
||||
glm::vec4 oplane(a,b,c,d);
|
||||
glm::vec4 cplane = invtrans_MVP * oplane;
|
||||
|
||||
cplane /= fabs(cplane[2]); // normalize such that depth is not scaled
|
||||
cplane[3] -= 1;
|
||||
|
|
@ -2813,13 +2822,13 @@ void LLGLUserClipPlane::setPlane(F32 a, F32 b, F32 c, F32 d)
|
|||
if(cplane[2] < 0)
|
||||
cplane *= -1;
|
||||
|
||||
glh::matrix4f suffix;
|
||||
suffix.set_row(2, cplane);
|
||||
glh::matrix4f newP = suffix * P;
|
||||
glm::mat4 suffix;
|
||||
suffix = glm::row(suffix, 2, cplane);
|
||||
glm::mat4 newP = suffix * P;
|
||||
gGL.matrixMode(LLRender::MM_PROJECTION);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadMatrix(newP.m);
|
||||
gGLObliqueProjectionInverse = LLMatrix4(newP.inverse().transpose().m);
|
||||
gGL.loadMatrix(glm::value_ptr(newP));
|
||||
gGLObliqueProjectionInverse = LLMatrix4(glm::value_ptr(glm::transpose(glm::inverse(newP))));
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
}
|
||||
|
||||
|
|
@ -2832,7 +2841,7 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G
|
|||
: mPrevDepthEnabled(sDepthEnabled), mPrevDepthFunc(sDepthFunc), mPrevWriteEnabled(sWriteEnabled)
|
||||
{
|
||||
stop_glerror();
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
|
||||
checkState();
|
||||
|
||||
if (!depth_enabled)
|
||||
|
|
@ -2865,6 +2874,7 @@ LLGLDepthTest::LLGLDepthTest(GLboolean depth_enabled, GLboolean write_enabled, G
|
|||
|
||||
LLGLDepthTest::~LLGLDepthTest()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_PIPELINE;
|
||||
checkState();
|
||||
if (sDepthEnabled != mPrevDepthEnabled )
|
||||
{
|
||||
|
|
@ -2915,31 +2925,27 @@ void LLGLDepthTest::checkState()
|
|||
|
||||
LLGLSquashToFarClip::LLGLSquashToFarClip()
|
||||
{
|
||||
glh::matrix4f proj = get_current_projection();
|
||||
glm::mat4 proj = get_current_projection();
|
||||
setProjectionMatrix(proj, 0);
|
||||
}
|
||||
|
||||
LLGLSquashToFarClip::LLGLSquashToFarClip(glh::matrix4f& P, U32 layer)
|
||||
LLGLSquashToFarClip::LLGLSquashToFarClip(const glm::mat4& P, U32 layer)
|
||||
{
|
||||
setProjectionMatrix(P, layer);
|
||||
}
|
||||
|
||||
|
||||
void LLGLSquashToFarClip::setProjectionMatrix(glh::matrix4f& projection, U32 layer)
|
||||
void LLGLSquashToFarClip::setProjectionMatrix(glm::mat4 projection, U32 layer)
|
||||
{
|
||||
|
||||
F32 depth = 0.99999f - 0.0001f * layer;
|
||||
|
||||
for (U32 i = 0; i < 4; i++)
|
||||
{
|
||||
projection.element(2, i) = projection.element(3, i) * depth;
|
||||
}
|
||||
glm::vec4 P_row_3 = glm::row(projection, 3) * depth;
|
||||
projection = glm::row(projection, 2, P_row_3);
|
||||
|
||||
LLRender::eMatrixMode last_matrix_mode = gGL.getMatrixMode();
|
||||
|
||||
gGL.matrixMode(LLRender::MM_PROJECTION);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadMatrix(projection.m);
|
||||
gGL.loadMatrix(glm::value_ptr(projection));
|
||||
|
||||
gGL.matrixMode(last_matrix_mode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,17 +43,7 @@
|
|||
#include "llinstancetracker.h"
|
||||
|
||||
#include "llglheaders.h"
|
||||
|
||||
#if LL_LINUX && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) >= 70000
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
|
||||
#endif
|
||||
|
||||
#include "glh/glh_linear.h"
|
||||
|
||||
#if LL_LINUX && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) >= 70000
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#include "glm/mat4x4.hpp"
|
||||
|
||||
extern bool gDebugGL;
|
||||
extern bool gDebugSession;
|
||||
|
|
@ -100,6 +90,7 @@ public:
|
|||
S32 mGLMaxTextureSize;
|
||||
F32 mMaxAnisotropy = 0.f;
|
||||
S32 mMaxUniformBlockSize = 0;
|
||||
S32 mMaxVaryingVectors = 0;
|
||||
|
||||
// GL 4.x capabilities
|
||||
bool mHasCubeMapArray = false;
|
||||
|
|
@ -115,6 +106,7 @@ public:
|
|||
bool mIsAMD;
|
||||
bool mIsNVIDIA;
|
||||
bool mIsIntel;
|
||||
bool mIsApple = false;
|
||||
|
||||
// hints to the render pipe
|
||||
U32 mDownScaleMethod = 0; // see settings.xml RenderDownScaleMethod
|
||||
|
|
@ -330,7 +322,7 @@ class LLGLUserClipPlane
|
|||
{
|
||||
public:
|
||||
|
||||
LLGLUserClipPlane(const LLPlane& plane, const glh::matrix4f& modelview, const glh::matrix4f& projection, bool apply = true);
|
||||
LLGLUserClipPlane(const LLPlane& plane, const glm::mat4& modelview, const glm::mat4& projection, bool apply = true);
|
||||
~LLGLUserClipPlane();
|
||||
|
||||
void setPlane(F32 a, F32 b, F32 c, F32 d);
|
||||
|
|
@ -339,8 +331,8 @@ public:
|
|||
private:
|
||||
bool mApply;
|
||||
|
||||
glh::matrix4f mProjection;
|
||||
glh::matrix4f mModelview;
|
||||
glm::mat4 mProjection;
|
||||
glm::mat4 mModelview;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
@ -354,9 +346,9 @@ class LLGLSquashToFarClip
|
|||
{
|
||||
public:
|
||||
LLGLSquashToFarClip();
|
||||
LLGLSquashToFarClip(glh::matrix4f& projection, U32 layer = 0);
|
||||
LLGLSquashToFarClip(const glm::mat4& projection, U32 layer = 0);
|
||||
|
||||
void setProjectionMatrix(glh::matrix4f& projection, U32 layer);
|
||||
void setProjectionMatrix(glm::mat4 projection, U32 layer);
|
||||
|
||||
~LLGLSquashToFarClip();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
// LL_WINDOWS
|
||||
|
||||
// windows gl headers depend on things like APIENTRY, so include windows.
|
||||
#include "llwin32headerslean.h"
|
||||
#include "llwin32headers.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#include <GL/gl.h>
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ U64 LLGLSLShader::sTotalTimeElapsed = 0;
|
|||
U32 LLGLSLShader::sTotalTrianglesDrawn = 0;
|
||||
U64 LLGLSLShader::sTotalSamplesDrawn = 0;
|
||||
U32 LLGLSLShader::sTotalBinds = 0;
|
||||
boost::json::value LLGLSLShader::sDefaultStats;
|
||||
|
||||
//UI shader -- declared here so llui_libtest will link properly
|
||||
LLGLSLShader gUIProgram;
|
||||
|
|
@ -101,9 +102,9 @@ void LLGLSLShader::initProfile()
|
|||
sTotalSamplesDrawn = 0;
|
||||
sTotalBinds = 0;
|
||||
|
||||
for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
|
||||
for (auto ptr : sInstances)
|
||||
{
|
||||
(*iter)->clearStats();
|
||||
ptr->clearStats();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -117,45 +118,57 @@ struct LLGLSLShaderCompareTimeElapsed
|
|||
};
|
||||
|
||||
//static
|
||||
void LLGLSLShader::finishProfile(bool emit_report)
|
||||
void LLGLSLShader::finishProfile(boost::json::value& statsv)
|
||||
{
|
||||
sProfileEnabled = false;
|
||||
|
||||
if (emit_report)
|
||||
if (! statsv.is_null())
|
||||
{
|
||||
std::vector<LLGLSLShader*> sorted;
|
||||
|
||||
for (std::set<LLGLSLShader*>::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter)
|
||||
{
|
||||
sorted.push_back(*iter);
|
||||
}
|
||||
|
||||
std::vector<LLGLSLShader*> sorted(sInstances.begin(), sInstances.end());
|
||||
std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed());
|
||||
|
||||
auto& stats = statsv.as_object();
|
||||
auto shadersit = stats.emplace("shaders", boost::json::array_kind).first;
|
||||
auto& shaders = shadersit->value().as_array();
|
||||
bool unbound = false;
|
||||
for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter)
|
||||
for (auto ptr : sorted)
|
||||
{
|
||||
(*iter)->dumpStats();
|
||||
if ((*iter)->mBinds == 0)
|
||||
if (ptr->mBinds == 0)
|
||||
{
|
||||
unbound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& shaderit = shaders.emplace_back(boost::json::object_kind);
|
||||
ptr->dumpStats(shaderit.as_object());
|
||||
}
|
||||
}
|
||||
|
||||
constexpr float mega = 1'000'000.f;
|
||||
float totalTimeMs = sTotalTimeElapsed / mega;
|
||||
LL_INFOS() << "-----------------------------------" << LL_ENDL;
|
||||
LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed / 1000000.f) << LL_ENDL;
|
||||
LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn / 1000000.f) << LL_ENDL;
|
||||
LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn / 1000000.f) << LL_ENDL;
|
||||
LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", totalTimeMs) << LL_ENDL;
|
||||
LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn / mega) << LL_ENDL;
|
||||
LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn / mega) << LL_ENDL;
|
||||
LL_INFOS() << "-----------------------------------" << LL_ENDL;
|
||||
auto totalsit = stats.emplace("totals", boost::json::object_kind).first;
|
||||
auto& totals = totalsit->value().as_object();
|
||||
totals.emplace("time", totalTimeMs / 1000.0);
|
||||
totals.emplace("binds", sTotalBinds);
|
||||
totals.emplace("samples", sTotalSamplesDrawn);
|
||||
totals.emplace("triangles", sTotalTrianglesDrawn);
|
||||
|
||||
auto unusedit = stats.emplace("unused", boost::json::array_kind).first;
|
||||
auto& unused = unusedit->value().as_array();
|
||||
if (unbound)
|
||||
{
|
||||
LL_INFOS() << "The following shaders were unused: " << LL_ENDL;
|
||||
for (std::vector<LLGLSLShader*>::iterator iter = sorted.begin(); iter != sorted.end(); ++iter)
|
||||
for (auto ptr : sorted)
|
||||
{
|
||||
if ((*iter)->mBinds == 0)
|
||||
if (ptr->mBinds == 0)
|
||||
{
|
||||
LL_INFOS() << (*iter)->mName << LL_ENDL;
|
||||
LL_INFOS() << ptr->mName << LL_ENDL;
|
||||
unused.emplace_back(ptr->mName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -170,36 +183,43 @@ void LLGLSLShader::clearStats()
|
|||
mBinds = 0;
|
||||
}
|
||||
|
||||
void LLGLSLShader::dumpStats()
|
||||
void LLGLSLShader::dumpStats(boost::json::object& stats)
|
||||
{
|
||||
if (mBinds > 0)
|
||||
stats.emplace("name", mName);
|
||||
auto filesit = stats.emplace("files", boost::json::array_kind).first;
|
||||
auto& files = filesit->value().as_array();
|
||||
LL_INFOS() << "=============================================" << LL_ENDL;
|
||||
LL_INFOS() << mName << LL_ENDL;
|
||||
for (U32 i = 0; i < mShaderFiles.size(); ++i)
|
||||
{
|
||||
LL_INFOS() << "=============================================" << LL_ENDL;
|
||||
LL_INFOS() << mName << LL_ENDL;
|
||||
for (U32 i = 0; i < mShaderFiles.size(); ++i)
|
||||
{
|
||||
LL_INFOS() << mShaderFiles[i].first << LL_ENDL;
|
||||
}
|
||||
LL_INFOS() << "=============================================" << LL_ENDL;
|
||||
|
||||
F32 ms = mTimeElapsed / 1000000.f;
|
||||
F32 seconds = ms / 1000.f;
|
||||
|
||||
F32 pct_tris = (F32)mTrianglesDrawn / (F32)sTotalTrianglesDrawn * 100.f;
|
||||
F32 tris_sec = (F32)(mTrianglesDrawn / 1000000.0);
|
||||
tris_sec /= seconds;
|
||||
|
||||
F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f;
|
||||
F32 samples_sec = (F32)(mSamplesDrawn / 1000000000.0);
|
||||
samples_sec /= seconds;
|
||||
|
||||
F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f;
|
||||
|
||||
LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec) << LL_ENDL;
|
||||
LL_INFOS() << "Binds: " << mBinds << " " << llformat("(%.2f pct of total)", pct_binds) << LL_ENDL;
|
||||
LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL;
|
||||
LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32)((F64)mTimeElapsed / (F64)sTotalTimeElapsed) * 100.f, ms) << LL_ENDL;
|
||||
LL_INFOS() << mShaderFiles[i].first << LL_ENDL;
|
||||
files.emplace_back(mShaderFiles[i].first);
|
||||
}
|
||||
LL_INFOS() << "=============================================" << LL_ENDL;
|
||||
|
||||
constexpr float mega = 1'000'000.f;
|
||||
constexpr double giga = 1'000'000'000.0;
|
||||
F32 ms = mTimeElapsed / mega;
|
||||
F32 seconds = ms / 1000.f;
|
||||
|
||||
F32 pct_tris = (F32)mTrianglesDrawn / (F32)sTotalTrianglesDrawn * 100.f;
|
||||
F32 tris_sec = (F32)(mTrianglesDrawn / mega);
|
||||
tris_sec /= seconds;
|
||||
|
||||
F32 pct_samples = (F32)((F64)mSamplesDrawn / (F64)sTotalSamplesDrawn) * 100.f;
|
||||
F32 samples_sec = (F32)(mSamplesDrawn / giga);
|
||||
samples_sec /= seconds;
|
||||
|
||||
F32 pct_binds = (F32)mBinds / (F32)sTotalBinds * 100.f;
|
||||
|
||||
LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec) << LL_ENDL;
|
||||
LL_INFOS() << "Binds: " << mBinds << " " << llformat("(%.2f pct of total)", pct_binds) << LL_ENDL;
|
||||
LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL;
|
||||
LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32)((F64)mTimeElapsed / (F64)sTotalTimeElapsed) * 100.f, ms) << LL_ENDL;
|
||||
stats.emplace("time", seconds);
|
||||
stats.emplace("binds", mBinds);
|
||||
stats.emplace("samples", mSamplesDrawn);
|
||||
stats.emplace("triangles", mTrianglesDrawn);
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
@ -1026,7 +1046,7 @@ void LLGLSLShader::bind()
|
|||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
llassert(mProgramObject != 0);
|
||||
llassert_always(mProgramObject != 0);
|
||||
|
||||
gGL.flush();
|
||||
|
||||
|
|
@ -1049,6 +1069,9 @@ void LLGLSLShader::bind()
|
|||
LLShaderMgr::instance()->updateShaderUniforms(this);
|
||||
mUniformsDirty = false;
|
||||
}
|
||||
|
||||
llassert_always(sCurBoundShaderPtr != nullptr);
|
||||
llassert_always(sCurBoundShader == mProgramObject);
|
||||
}
|
||||
|
||||
void LLGLSLShader::bind(U8 variant)
|
||||
|
|
@ -1087,17 +1110,17 @@ void LLGLSLShader::unbind(void)
|
|||
sCurBoundShaderPtr = NULL;
|
||||
}
|
||||
|
||||
S32 LLGLSLShader::bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
|
||||
S32 LLGLSLShader::bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
S32 channel = 0;
|
||||
channel = getUniformLocation(uniform);
|
||||
|
||||
return bindTexture(channel, texture, mode, colorspace);
|
||||
return bindTexture(channel, texture, mode);
|
||||
}
|
||||
|
||||
S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace colorspace)
|
||||
S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
|
|
@ -1113,7 +1136,6 @@ S32 LLGLSLShader::bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextu
|
|||
if (uniform > -1)
|
||||
{
|
||||
gGL.getTexUnit(uniform)->bindFast(texture);
|
||||
gGL.getTexUnit(uniform)->setTextureColorSpace(colorspace);
|
||||
}
|
||||
|
||||
return uniform;
|
||||
|
|
@ -1194,7 +1216,7 @@ S32 LLGLSLShader::getTextureChannel(S32 uniform) const
|
|||
return mTexture[uniform];
|
||||
}
|
||||
|
||||
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
|
||||
S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
|
|
@ -1211,12 +1233,11 @@ S32 LLGLSLShader::enableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTex
|
|||
{
|
||||
gGL.getTexUnit(index)->activate();
|
||||
gGL.getTexUnit(index)->enable(mode);
|
||||
gGL.getTexUnit(index)->setTextureColorSpace(space);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTexUnit::eTextureColorSpace space)
|
||||
S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
||||
|
|
@ -1229,7 +1250,7 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode, LLTe
|
|||
S32 index = mTexture[uniform];
|
||||
if (index != -1 && gGL.getTexUnit(index)->getCurrType() != LLTexUnit::TT_NONE)
|
||||
{
|
||||
if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode && gGL.getTexUnit(index)->getCurrColorSpace() != space)
|
||||
if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode)
|
||||
{
|
||||
if (gDebugSession)
|
||||
{
|
||||
|
|
@ -1552,6 +1573,34 @@ void LLGLSLShader::uniform4fv(U32 index, U32 count, const GLfloat* v)
|
|||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::uniform4uiv(U32 index, U32 count, const GLuint* v)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
llassert(sCurBoundShaderPtr == this);
|
||||
|
||||
if (mProgramObject)
|
||||
{
|
||||
if (mUniform.size() <= index)
|
||||
{
|
||||
LL_WARNS_ONCE("Shader") << "Uniform index out of bounds. Size: " << (S32)mUniform.size() << " index: " << index << LL_ENDL;
|
||||
llassert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mUniform[index] >= 0)
|
||||
{
|
||||
const auto& iter = mValue.find(mUniform[index]);
|
||||
LLVector4 vec((F32)v[0], (F32)v[1], (F32)v[2], (F32)v[3]);
|
||||
if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
glUniform4uiv(mUniform[index], count, v);
|
||||
mValue[mUniform[index]] = vec;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
|
@ -1817,6 +1866,23 @@ void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLf
|
|||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::uniform4f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
GLint location = getUniformLocation(uniform);
|
||||
|
||||
if (location >= 0)
|
||||
{
|
||||
const auto& iter = mValue.find(location);
|
||||
LLVector4 vec(x, y, z, w);
|
||||
if (iter == mValue.end() || shouldChange(iter->second, vec))
|
||||
{
|
||||
glUniform4f(location, x, y, z, w);
|
||||
mValue[location] = vec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
|
@ -1886,6 +1952,24 @@ void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, co
|
|||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::uniform4uiv(const LLStaticHashedString& uniform, U32 count, const GLuint* v)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
GLint location = getUniformLocation(uniform);
|
||||
|
||||
if (location >= 0)
|
||||
{
|
||||
LLVector4 vec((F32)v[0], (F32)v[1], (F32)v[2], (F32)v[3]);
|
||||
const auto& iter = mValue.find(location);
|
||||
if (iter == mValue.end() || shouldChange(iter->second, vec) || count != 1)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
glUniform4uiv(location, count, v);
|
||||
mValue[location] = vec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_SHADER;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "llgl.h"
|
||||
#include "llrender.h"
|
||||
#include "llstaticstringtable.h"
|
||||
#include <boost/json.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
class LLShaderFeatures
|
||||
|
|
@ -51,6 +52,7 @@ public:
|
|||
bool hasAmbientOcclusion = false;
|
||||
bool hasSrgb = false;
|
||||
bool isDeferred = false;
|
||||
bool hasFullGBuffer = false;
|
||||
bool hasScreenSpaceReflections = false;
|
||||
bool hasAlphaMask = false;
|
||||
bool hasReflectionProbes = false;
|
||||
|
|
@ -169,14 +171,14 @@ public:
|
|||
static U32 sMaxGLTFNodes;
|
||||
|
||||
static void initProfile();
|
||||
static void finishProfile(bool emit_report = true);
|
||||
static void finishProfile(boost::json::value& stats=sDefaultStats);
|
||||
|
||||
static void startProfile();
|
||||
static void stopProfile();
|
||||
|
||||
void unload();
|
||||
void clearStats();
|
||||
void dumpStats();
|
||||
void dumpStats(boost::json::object& stats);
|
||||
|
||||
// place query objects for profiling if profiling is enabled
|
||||
// if for_runtime is true, will place timer query only whether or not profiling is enabled
|
||||
|
|
@ -208,6 +210,7 @@ public:
|
|||
void uniform2fv(U32 index, U32 count, const GLfloat* v);
|
||||
void uniform3fv(U32 index, U32 count, const GLfloat* v);
|
||||
void uniform4fv(U32 index, U32 count, const GLfloat* v);
|
||||
void uniform4uiv(U32 index, U32 count, const GLuint* v);
|
||||
void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
|
||||
void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
|
||||
void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat* v);
|
||||
|
|
@ -219,10 +222,12 @@ public:
|
|||
void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
|
||||
void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
|
||||
void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
|
||||
void uniform4f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
|
||||
void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
|
||||
void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
|
||||
void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
|
||||
void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
|
||||
void uniform4uiv(const LLStaticHashedString& uniform, U32 count, const GLuint* v);
|
||||
void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v);
|
||||
|
||||
void setMinimumAlpha(F32 minimum);
|
||||
|
|
@ -239,6 +244,10 @@ public:
|
|||
|
||||
void clearPermutations();
|
||||
void addPermutation(std::string name, std::string value);
|
||||
void addPermutations(const std::map<std::string, std::string>& defines)
|
||||
{
|
||||
mDefines.insert(defines.begin(), defines.end());
|
||||
}
|
||||
void removePermutation(std::string name);
|
||||
|
||||
void addConstant(const LLGLSLShader::eShaderConsts shader_const);
|
||||
|
|
@ -247,16 +256,16 @@ public:
|
|||
//if given texture uniform is active in the shader,
|
||||
//the corresponding channel will be active upon return
|
||||
//returns channel texture is enabled in from [0-MAX)
|
||||
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
|
||||
S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
|
||||
S32 enableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
S32 disableTexture(S32 uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
|
||||
// get the texture channel of the given uniform, or -1 if uniform is not used as a texture
|
||||
S32 getTextureChannel(S32 uniform) const;
|
||||
|
||||
// bindTexture returns the texture unit we've bound the texture to.
|
||||
// You can reuse the return value to unbind a texture when required.
|
||||
S32 bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
|
||||
S32 bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE, LLTexUnit::eTextureColorSpace space = LLTexUnit::TCS_LINEAR);
|
||||
S32 bindTexture(const std::string& uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
S32 bindTexture(S32 uniform, LLTexture* texture, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
S32 bindTexture(const std::string& uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR);
|
||||
S32 bindTexture(S32 uniform, LLRenderTarget* texture, bool depth = false, LLTexUnit::eTextureFilterOptions mode = LLTexUnit::TFO_BILINEAR, U32 index = 0);
|
||||
S32 unbindTexture(const std::string& uniform, LLTexUnit::eTextureType mode = LLTexUnit::TT_TEXTURE);
|
||||
|
|
@ -357,6 +366,11 @@ public:
|
|||
|
||||
private:
|
||||
void unloadInternal();
|
||||
// This must be static because finishProfile() is called at least once
|
||||
// within a __try block. If we default its stats parameter to a temporary
|
||||
// json::value, that temporary must be destroyed when the stack is
|
||||
// unwound, which __try forbids.
|
||||
static boost::json::value sDefaultStats;
|
||||
};
|
||||
|
||||
//UI shader (declared here so llui_libtest will link properly)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ extern LL_COMMON_API bool on_main_thread();
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
const F32 MIN_TEXTURE_LIFETIME = 10.f;
|
||||
const F32 CONVERSION_SCRATCH_BUFFER_GL_VERSION = 3.29f;
|
||||
|
||||
//which power of 2 is i?
|
||||
//assumes i is a power of 2 > 0
|
||||
|
|
@ -67,12 +68,13 @@ static U64 sTextureBytes = 0;
|
|||
|
||||
// track a texture alloc on the currently bound texture.
|
||||
// asserts that no currently tracked alloc exists
|
||||
void LLImageGLMemory::alloc_tex_image(U32 width, U32 height, U32 pixformat)
|
||||
void LLImageGLMemory::alloc_tex_image(U32 width, U32 height, U32 intformat, U32 count)
|
||||
{
|
||||
U32 texUnit = gGL.getCurrentTexUnitIndex();
|
||||
llassert(texUnit == 0); // allocations should always be done on tex unit 0
|
||||
U32 texName = gGL.getTexUnit(texUnit)->getCurrTexture();
|
||||
U64 size = LLImageGL::dataFormatBytes(pixformat, width, height);
|
||||
U64 size = LLImageGL::dataFormatBytes(intformat, width, height);
|
||||
size *= count;
|
||||
|
||||
llassert(size >= 0);
|
||||
|
||||
|
|
@ -159,6 +161,7 @@ S32 LLImageGL::sMaxCategories = 1 ;
|
|||
bool LLImageGL::sSkipAnalyzeAlpha;
|
||||
U32 LLImageGL::sScratchPBO = 0;
|
||||
U32 LLImageGL::sScratchPBOSize = 0;
|
||||
U32* LLImageGL::sManualScratch = nullptr;
|
||||
|
||||
|
||||
//------------------------
|
||||
|
|
@ -256,8 +259,24 @@ void LLImageGL::initClass(LLWindow* window, S32 num_catagories, bool skip_analyz
|
|||
if (thread_texture_loads || thread_media_updates)
|
||||
{
|
||||
LLImageGLThread::createInstance(window);
|
||||
LLImageGLThread::sEnabledTextures = thread_texture_loads;
|
||||
LLImageGLThread::sEnabledMedia = thread_media_updates;
|
||||
LLImageGLThread::sEnabledTextures = gGLManager.mGLVersion > 3.95f ? thread_texture_loads : false;
|
||||
LLImageGLThread::sEnabledMedia = gGLManager.mGLVersion > 3.95f ? thread_media_updates : false;
|
||||
}
|
||||
}
|
||||
|
||||
void LLImageGL::allocateConversionBuffer()
|
||||
{
|
||||
if (gGLManager.mGLVersion < CONVERSION_SCRATCH_BUFFER_GL_VERSION)
|
||||
{
|
||||
try
|
||||
{
|
||||
sManualScratch = new U32[MAX_IMAGE_AREA];
|
||||
}
|
||||
catch (std::bad_alloc&)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
LL_ERRS() << "Failed to allocate sManualScratch" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -272,6 +291,8 @@ void LLImageGL::cleanupClass()
|
|||
sScratchPBO = 0;
|
||||
sScratchPBOSize = 0;
|
||||
}
|
||||
|
||||
delete[] sManualScratch;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -280,6 +301,15 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
|
|||
{
|
||||
switch (dataformat)
|
||||
{
|
||||
case GL_COMPRESSED_RED: return 8;
|
||||
case GL_COMPRESSED_RG: return 16;
|
||||
case GL_COMPRESSED_RGB: return 24;
|
||||
case GL_COMPRESSED_SRGB: return 32;
|
||||
case GL_COMPRESSED_RGBA: return 32;
|
||||
case GL_COMPRESSED_SRGB_ALPHA: return 32;
|
||||
case GL_COMPRESSED_LUMINANCE: return 8;
|
||||
case GL_COMPRESSED_LUMINANCE_ALPHA: return 16;
|
||||
case GL_COMPRESSED_ALPHA: return 8;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return 4;
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: return 4;
|
||||
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return 8;
|
||||
|
|
@ -287,21 +317,36 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
|
|||
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8;
|
||||
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8;
|
||||
case GL_LUMINANCE: return 8;
|
||||
case GL_LUMINANCE8: return 8;
|
||||
case GL_ALPHA: return 8;
|
||||
case GL_ALPHA8: return 8;
|
||||
case GL_RED: return 8;
|
||||
case GL_R8: return 8;
|
||||
case GL_COLOR_INDEX: return 8;
|
||||
case GL_LUMINANCE_ALPHA: return 16;
|
||||
case GL_LUMINANCE8_ALPHA8: return 16;
|
||||
case GL_RG: return 16;
|
||||
case GL_RG8: return 16;
|
||||
case GL_RGB: return 24;
|
||||
case GL_SRGB: return 24;
|
||||
case GL_RGB8: return 24;
|
||||
case GL_RGBA: return 32;
|
||||
case GL_RGBA8: return 32;
|
||||
case GL_RGB10_A2: return 32;
|
||||
case GL_SRGB_ALPHA: return 32;
|
||||
case GL_BGRA: return 32; // Used for QuickTime media textures on the Mac
|
||||
case GL_DEPTH_COMPONENT: return 24;
|
||||
case GL_DEPTH_COMPONENT24: return 24;
|
||||
case GL_R16F: return 16;
|
||||
case GL_RG16F: return 32;
|
||||
case GL_RGB16F: return 48;
|
||||
case GL_RGBA16F: return 64;
|
||||
case GL_R32F: return 32;
|
||||
case GL_RG32F: return 64;
|
||||
case GL_RGB32F: return 96;
|
||||
case GL_RGBA32F: return 128;
|
||||
default:
|
||||
LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
|
||||
LL_ERRS() << "LLImageGL::Unknown format: " << std::hex << dataformat << std::dec << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -344,13 +389,14 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
|
|||
case GL_RED: return 1;
|
||||
case GL_COLOR_INDEX: return 1;
|
||||
case GL_LUMINANCE_ALPHA: return 2;
|
||||
case GL_RG: return 2;
|
||||
case GL_RGB: return 3;
|
||||
case GL_SRGB: return 3;
|
||||
case GL_RGBA: return 4;
|
||||
case GL_SRGB_ALPHA: return 4;
|
||||
case GL_BGRA: return 4; // Used for QuickTime media textures on the Mac
|
||||
default:
|
||||
LL_ERRS() << "LLImageGL::Unknown format: " << dataformat << LL_ENDL;
|
||||
LL_ERRS() << "LLImageGL::Unknown format: " << std::hex << dataformat << std::dec << LL_ENDL;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -411,29 +457,29 @@ bool LLImageGL::create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, b
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
LLImageGL::LLImageGL(bool usemipmaps)
|
||||
LLImageGL::LLImageGL(bool usemipmaps/* = true*/, bool allow_compression/* = true*/)
|
||||
: mSaveData(0), mExternalTexture(false)
|
||||
{
|
||||
init(usemipmaps);
|
||||
init(usemipmaps, allow_compression);
|
||||
setSize(0, 0, 0);
|
||||
sImageList.insert(this);
|
||||
sCount++;
|
||||
}
|
||||
|
||||
LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps)
|
||||
LLImageGL::LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps/* = true*/, bool allow_compression/* = true*/)
|
||||
: mSaveData(0), mExternalTexture(false)
|
||||
{
|
||||
llassert( components <= 4 );
|
||||
init(usemipmaps);
|
||||
init(usemipmaps, allow_compression);
|
||||
setSize(width, height, components);
|
||||
sImageList.insert(this);
|
||||
sCount++;
|
||||
}
|
||||
|
||||
LLImageGL::LLImageGL(const LLImageRaw* imageraw, bool usemipmaps)
|
||||
LLImageGL::LLImageGL(const LLImageRaw* imageraw, bool usemipmaps/* = true*/, bool allow_compression/* = true*/)
|
||||
: mSaveData(0), mExternalTexture(false)
|
||||
{
|
||||
init(usemipmaps);
|
||||
init(usemipmaps, allow_compression);
|
||||
setSize(0, 0, 0);
|
||||
sImageList.insert(this);
|
||||
sCount++;
|
||||
|
|
@ -450,7 +496,7 @@ LLImageGL::LLImageGL(
|
|||
LLGLenum formatType,
|
||||
LLTexUnit::eTextureAddressMode addressMode)
|
||||
{
|
||||
init(false);
|
||||
init(false, true);
|
||||
mTexName = texName;
|
||||
mTarget = target;
|
||||
mComponents = components;
|
||||
|
|
@ -472,7 +518,7 @@ LLImageGL::~LLImageGL()
|
|||
}
|
||||
}
|
||||
|
||||
void LLImageGL::init(bool usemipmaps)
|
||||
void LLImageGL::init(bool usemipmaps, bool allow_compression)
|
||||
{
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
mActiveThread = LLThread::currentID();
|
||||
|
|
@ -502,7 +548,7 @@ void LLImageGL::init(bool usemipmaps)
|
|||
mHeight = 0;
|
||||
mCurrentDiscardLevel = -1;
|
||||
|
||||
mAllowCompression = true;
|
||||
mAllowCompression = allow_compression;
|
||||
|
||||
mTarget = GL_TEXTURE_2D;
|
||||
mBindTarget = LLTexUnit::TT_TEXTURE;
|
||||
|
|
@ -1006,7 +1052,7 @@ U32 type_width_from_pixtype(U32 pixtype)
|
|||
bool should_stagger_image_set(bool compressed)
|
||||
{
|
||||
#if LL_DARWIN
|
||||
return false;
|
||||
return !compressed && on_main_thread() && gGLManager.mIsAMD;
|
||||
#else
|
||||
// glTexSubImage2D doesn't work with compressed textures on select tested Nvidia GPUs on Windows 10 -Cosmic,2023-03-08
|
||||
// Setting media textures off-thread seems faster when not using sub_image_lines (Nvidia/Windows 10) -Cosmic,2023-03-31
|
||||
|
|
@ -1020,15 +1066,47 @@ void sub_image_lines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 w
|
|||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
|
||||
LL_PROFILE_ZONE_NUM(width);
|
||||
LL_PROFILE_ZONE_NUM(height);
|
||||
|
||||
U32 components = LLImageGL::dataFormatComponents(pixformat);
|
||||
U32 type_width = type_width_from_pixtype(pixtype);
|
||||
|
||||
const U32 line_width = data_width * components * type_width;
|
||||
const U32 y_offset_end = y_offset + height;
|
||||
for (U32 y_pos = y_offset; y_pos < y_offset_end; ++y_pos)
|
||||
|
||||
if (width == data_width && height % 32 == 0)
|
||||
{
|
||||
glTexSubImage2D(target, miplevel, x_offset, y_pos, width, 1, pixformat, pixtype, src);
|
||||
src += line_width;
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("subimage - batched lines");
|
||||
|
||||
// full width, batch multiple lines at a time
|
||||
// set batch size based on width
|
||||
U32 batch_size = 32;
|
||||
|
||||
if (width > 1024)
|
||||
{
|
||||
batch_size = 8;
|
||||
}
|
||||
else if (width > 512)
|
||||
{
|
||||
batch_size = 16;
|
||||
}
|
||||
|
||||
// full width texture, do 32 lines at a time
|
||||
for (U32 y_pos = y_offset; y_pos < y_offset_end; y_pos += batch_size)
|
||||
{
|
||||
glTexSubImage2D(target, miplevel, x_offset, y_pos, width, batch_size, pixformat, pixtype, src);
|
||||
src += line_width * batch_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// partial width or strange height
|
||||
for (U32 y_pos = y_offset; y_pos < y_offset_end; y_pos += 1)
|
||||
{
|
||||
glTexSubImage2D(target, miplevel, x_offset, y_pos, width, 1, pixformat, pixtype, src);
|
||||
src += line_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1192,37 +1270,37 @@ void LLImageGL::generateTextures(S32 numTextures, U32 *textures)
|
|||
}
|
||||
}
|
||||
|
||||
constexpr int DELETE_DELAY = 3; // number of frames to wait before deleting textures
|
||||
static std::vector<U32> sFreeList[DELETE_DELAY+1];
|
||||
|
||||
// static
|
||||
void LLImageGL::updateClass()
|
||||
{
|
||||
sFrameCount++;
|
||||
|
||||
// wait a few frames before actually deleting the textures to avoid
|
||||
// synchronization issues with the GPU
|
||||
U32 idx = (sFrameCount+DELETE_DELAY) % (DELETE_DELAY+1);
|
||||
|
||||
if (!sFreeList[idx].empty())
|
||||
{
|
||||
free_tex_images((GLsizei) sFreeList[idx].size(), sFreeList[idx].data());
|
||||
glDeleteTextures((GLsizei)sFreeList[idx].size(), sFreeList[idx].data());
|
||||
sFreeList[idx].resize(0);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)
|
||||
{
|
||||
// wait a few frames before actually deleting the textures to avoid
|
||||
// synchronization issues with the GPU
|
||||
static std::vector<U32> sFreeList[4];
|
||||
|
||||
if (gGLManager.mInited)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
U32 idx = sFrameCount % 4;
|
||||
|
||||
U32 idx = sFrameCount % (DELETE_DELAY+1);
|
||||
for (S32 i = 0; i < numTextures; ++i)
|
||||
{
|
||||
sFreeList[idx].push_back(textures[i]);
|
||||
}
|
||||
|
||||
idx = (sFrameCount + 3) % 4;
|
||||
|
||||
if (!sFreeList[idx].empty())
|
||||
{
|
||||
free_tex_images((GLsizei) sFreeList[idx].size(), sFreeList[idx].data());
|
||||
glDeleteTextures((GLsizei)sFreeList[idx].size(), sFreeList[idx].data());
|
||||
sFreeList[idx].resize(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1230,100 +1308,97 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)
|
|||
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void* pixels, bool allow_compression)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
bool use_scratch = false;
|
||||
U32* scratch = NULL;
|
||||
if (LLRender::sGLCoreProfile)
|
||||
{
|
||||
if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_ALPHA is deprecated, convert to RGBA
|
||||
if (pixels != nullptr)
|
||||
{
|
||||
use_scratch = true;
|
||||
scratch = new(std::nothrow) U32[width * height];
|
||||
if (!scratch)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
// <FS:Beq> FIRE-34374 - OOM Crash 80% of which are in render debug text
|
||||
// LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
|
||||
// << " bytes for a manual image W" << width << " H" << height << LL_ENDL;
|
||||
LL_WARNS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
|
||||
<< " bytes for a manual image W" << width << " H" << height << LL_ENDL;
|
||||
return;
|
||||
// </FS:Beq>
|
||||
}
|
||||
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8* pix = (U8*)&scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = 0;
|
||||
pix[3] = ((U8*)pixels)[i];
|
||||
}
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
if (gGLManager.mGLVersion >= CONVERSION_SCRATCH_BUFFER_GL_VERSION)
|
||||
{
|
||||
if (pixformat == GL_ALPHA)
|
||||
{ //GL_ALPHA is deprecated, convert to RGBA
|
||||
const GLint mask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask);
|
||||
pixformat = GL_RED;
|
||||
intformat = GL_R8;
|
||||
}
|
||||
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGBA8;
|
||||
if (pixformat == GL_LUMINANCE)
|
||||
{ //GL_LUMINANCE is deprecated, convert to GL_RGBA
|
||||
const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_ONE };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask);
|
||||
pixformat = GL_RED;
|
||||
intformat = GL_R8;
|
||||
}
|
||||
|
||||
if (pixformat == GL_LUMINANCE_ALPHA)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
|
||||
const GLint mask[] = { GL_RED, GL_RED, GL_RED, GL_GREEN };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, mask);
|
||||
pixformat = GL_RG;
|
||||
intformat = GL_RG8;
|
||||
}
|
||||
}
|
||||
|
||||
if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
|
||||
if (pixels != nullptr)
|
||||
{
|
||||
use_scratch = true;
|
||||
scratch = new(std::nothrow) U32[width * height];
|
||||
if (!scratch)
|
||||
else
|
||||
{
|
||||
if (pixformat == GL_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_ALPHA is deprecated, convert to RGBA
|
||||
if (pixels != nullptr)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
// <FS:Beq> FIRE-34374 - OOM Crash 80% of which are in render debug text
|
||||
// LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
|
||||
// << " bytes for a manual image W" << width << " H" << height << LL_ENDL;
|
||||
LL_WARNS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
|
||||
<< " bytes for a manual image W" << width << " H" << height << LL_ENDL;
|
||||
return;
|
||||
// </FS:Beq>
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8* pix = (U8*)&sManualScratch[i];
|
||||
pix[0] = pix[1] = pix[2] = 0;
|
||||
pix[3] = ((U8*)pixels)[i];
|
||||
}
|
||||
|
||||
pixels = sManualScratch;
|
||||
}
|
||||
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8 lum = ((U8*)pixels)[i * 2 + 0];
|
||||
U8 alpha = ((U8*)pixels)[i * 2 + 1];
|
||||
|
||||
U8* pix = (U8*)&scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = alpha;
|
||||
}
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGBA8;
|
||||
}
|
||||
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGBA8;
|
||||
}
|
||||
|
||||
if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
|
||||
if (pixels != nullptr)
|
||||
{
|
||||
use_scratch = true;
|
||||
scratch = new(std::nothrow) U32[width * height];
|
||||
if (!scratch)
|
||||
if (pixformat == GL_LUMINANCE_ALPHA && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGBA
|
||||
if (pixels != nullptr)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
LL_ERRS() << "Failed to allocate " << (U32)(width * height * sizeof(U32))
|
||||
<< " bytes for a manual image W" << width << " H" << height << LL_ENDL;
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8 lum = ((U8*)pixels)[i * 2 + 0];
|
||||
U8 alpha = ((U8*)pixels)[i * 2 + 1];
|
||||
|
||||
U8* pix = (U8*)&sManualScratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = alpha;
|
||||
}
|
||||
|
||||
pixels = sManualScratch;
|
||||
}
|
||||
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8 lum = ((U8*)pixels)[i];
|
||||
|
||||
U8* pix = (U8*)&scratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = 255;
|
||||
}
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGBA8;
|
||||
}
|
||||
|
||||
if (pixformat == GL_LUMINANCE && pixtype == GL_UNSIGNED_BYTE)
|
||||
{ //GL_LUMINANCE_ALPHA is deprecated, convert to RGB
|
||||
if (pixels != nullptr)
|
||||
{
|
||||
U32 pixel_count = (U32)(width * height);
|
||||
for (U32 i = 0; i < pixel_count; i++)
|
||||
{
|
||||
U8 lum = ((U8*)pixels)[i];
|
||||
|
||||
U8* pix = (U8*)&sManualScratch[i];
|
||||
pix[0] = pix[1] = pix[2] = lum;
|
||||
pix[3] = 255;
|
||||
}
|
||||
|
||||
pixels = sManualScratch;
|
||||
}
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGB8;
|
||||
}
|
||||
pixformat = GL_RGBA;
|
||||
intformat = GL_RGB8;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1332,6 +1407,14 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
{
|
||||
switch (intformat)
|
||||
{
|
||||
case GL_RED:
|
||||
case GL_R8:
|
||||
intformat = GL_COMPRESSED_RED;
|
||||
break;
|
||||
case GL_RG:
|
||||
case GL_RG8:
|
||||
intformat = GL_COMPRESSED_RG;
|
||||
break;
|
||||
case GL_RGB:
|
||||
case GL_RGB8:
|
||||
intformat = GL_COMPRESSED_RGB;
|
||||
|
|
@ -1360,12 +1443,8 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
case GL_ALPHA8:
|
||||
intformat = GL_COMPRESSED_ALPHA;
|
||||
break;
|
||||
case GL_RED:
|
||||
case GL_R8:
|
||||
intformat = GL_COMPRESSED_RED;
|
||||
break;
|
||||
default:
|
||||
LL_WARNS() << "Could not compress format: " << std::hex << intformat << LL_ENDL;
|
||||
LL_WARNS() << "Could not compress format: " << std::hex << intformat << std::dec << LL_ENDL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1381,7 +1460,7 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
if (!use_sub_image)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("glTexImage2D alloc + copy");
|
||||
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, use_scratch ? scratch : pixels);
|
||||
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, pixels);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1391,21 +1470,16 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
|
|||
glTexImage2D(target, miplevel, intformat, width, height, 0, pixformat, pixtype, nullptr);
|
||||
}
|
||||
|
||||
U8* src = (U8*)(use_scratch ? scratch : pixels);
|
||||
U8* src = (U8*)(pixels);
|
||||
if (src)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED("glTexImage2D copy");
|
||||
sub_image_lines(target, miplevel, 0, 0, width, height, pixformat, pixtype, src, width);
|
||||
}
|
||||
}
|
||||
alloc_tex_image(width, height, pixformat);
|
||||
alloc_tex_image(width, height, intformat, 1);
|
||||
}
|
||||
stop_glerror();
|
||||
|
||||
if (use_scratch)
|
||||
{
|
||||
delete[] scratch;
|
||||
}
|
||||
}
|
||||
|
||||
//create an empty GL texture: just create a texture name
|
||||
|
|
@ -2093,6 +2167,8 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
|
|||
return ;
|
||||
}
|
||||
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
|
||||
U32 length = w * h;
|
||||
U32 alphatotal = 0;
|
||||
|
||||
|
|
@ -2106,13 +2182,13 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
|
|||
// suffer the worst from aliasing when used as alpha masks.
|
||||
if (w >= 2 && h >= 2)
|
||||
{
|
||||
llassert(w%2 == 0);
|
||||
llassert(h%2 == 0);
|
||||
llassert(w % 2 == 0);
|
||||
llassert(h % 2 == 0);
|
||||
const GLubyte* rowstart = ((const GLubyte*) data_in) + mAlphaOffset;
|
||||
for (U32 y = 0; y < h; y+=2)
|
||||
for (U32 y = 0; y < h; y += 2)
|
||||
{
|
||||
const GLubyte* current = rowstart;
|
||||
for (U32 x = 0; x < w; x+=2)
|
||||
for (U32 x = 0; x < w; x += 2)
|
||||
{
|
||||
const U32 s1 = current[0];
|
||||
alphatotal += s1;
|
||||
|
|
@ -2135,7 +2211,6 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h)
|
|||
sample[asum/(16*4)] += 4;
|
||||
}
|
||||
|
||||
|
||||
rowstart += 2 * w * mAlphaStride;
|
||||
}
|
||||
length *= 2; // we sampled everything twice, essentially
|
||||
|
|
@ -2362,7 +2437,9 @@ bool LLImageGL::scaleDown(S32 desired_discard)
|
|||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_TEXTURE;
|
||||
|
||||
if (mTarget != GL_TEXTURE_2D)
|
||||
if (mTarget != GL_TEXTURE_2D
|
||||
|| mFormatInternal == -1 // not initialized
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -2381,41 +2458,32 @@ bool LLImageGL::scaleDown(S32 desired_discard)
|
|||
|
||||
if (gGLManager.mDownScaleMethod == 0)
|
||||
{ // use an FBO to downscale the texture
|
||||
// allocate new texture
|
||||
U32 temp_texname = 0;
|
||||
generateTextures(1, &temp_texname);
|
||||
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, temp_texname, true);
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glTexImage2D");
|
||||
glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, NULL);
|
||||
}
|
||||
|
||||
// account for new texture getting created
|
||||
alloc_tex_image(desired_width, desired_height, mFormatPrimary);
|
||||
|
||||
// Use render-to-texture to scale down the texture
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glFramebufferTexture2D");
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTarget, temp_texname, 0);
|
||||
}
|
||||
|
||||
glViewport(0, 0, desired_width, desired_height);
|
||||
|
||||
// draw a full screen triangle
|
||||
gGL.getTexUnit(0)->bind(this);
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
if (gGL.getTexUnit(0)->bind(this, true, true))
|
||||
{
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
|
||||
// delete old texture and assign new texture name
|
||||
deleteTextures(1, &mTexName);
|
||||
mTexName = temp_texname;
|
||||
free_tex_image(mTexName);
|
||||
glTexImage2D(mTarget, 0, mFormatInternal, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr);
|
||||
glCopyTexSubImage2D(mTarget, 0, 0, 0, 0, 0, desired_width, desired_height);
|
||||
alloc_tex_image(desired_width, desired_height, mFormatInternal, 1);
|
||||
|
||||
if (mHasMipMaps)
|
||||
{ // generate mipmaps if needed
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap");
|
||||
gGL.getTexUnit(0)->bind(this);
|
||||
glGenerateMipmap(mTarget);
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
mTexOptionsDirty = true;
|
||||
|
||||
if (mHasMipMaps)
|
||||
{ // generate mipmaps if needed
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("scaleDown - glGenerateMipmap");
|
||||
gGL.getTexUnit(0)->bind(this);
|
||||
glGenerateMipmap(mTarget);
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS_ONCE("LLImageGL") << "Failed to bind texture for downscaling." << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -2445,10 +2513,10 @@ bool LLImageGL::scaleDown(S32 desired_discard)
|
|||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, sScratchPBO);
|
||||
glTexImage2D(mTarget, 0, mFormatPrimary, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr);
|
||||
glTexImage2D(mTarget, 0, mFormatInternal, desired_width, desired_height, 0, mFormatPrimary, mFormatType, nullptr);
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
|
||||
alloc_tex_image(desired_width, desired_height, mFormatPrimary);
|
||||
alloc_tex_image(desired_width, desired_height, mFormatInternal, 1);
|
||||
|
||||
if (mHasMipMaps)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class LLWindow;
|
|||
|
||||
namespace LLImageGLMemory
|
||||
{
|
||||
void alloc_tex_image(U32 width, U32 height, U32 pixformat);
|
||||
void alloc_tex_image(U32 width, U32 height, U32 intformat, U32 count);
|
||||
void free_tex_image(U32 texName);
|
||||
void free_tex_images(U32 count, const U32* texNames);
|
||||
void free_cur_tex_image();
|
||||
|
|
@ -101,9 +101,9 @@ public:
|
|||
static bool create(LLPointer<LLImageGL>& dest, const LLImageRaw* imageraw, bool usemipmaps = true);
|
||||
|
||||
public:
|
||||
LLImageGL(bool usemipmaps = true);
|
||||
LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps = true);
|
||||
LLImageGL(const LLImageRaw* imageraw, bool usemipmaps = true);
|
||||
LLImageGL(bool usemipmaps = true, bool allow_compression = true);
|
||||
LLImageGL(U32 width, U32 height, U8 components, bool usemipmaps = true, bool allow_compression = true);
|
||||
LLImageGL(const LLImageRaw* imageraw, bool usemipmaps = true, bool allow_compression = true);
|
||||
|
||||
// For wrapping textures created via GL elsewhere with our API only. Use with caution.
|
||||
LLImageGL(LLGLuint mTexName, U32 components, LLGLenum target, LLGLint formatInternal, LLGLenum formatPrimary, LLGLenum formatType, LLTexUnit::eTextureAddressMode addressMode);
|
||||
|
|
@ -206,7 +206,7 @@ public:
|
|||
|
||||
LLGLenum getTexTarget()const { return mTarget; }
|
||||
|
||||
void init(bool usemipmaps);
|
||||
void init(bool usemipmaps, bool allow_compression);
|
||||
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);
|
||||
|
|
@ -301,6 +301,7 @@ public:
|
|||
|
||||
public:
|
||||
static void initClass(LLWindow* window, S32 num_catagories, bool skip_analyze_alpha = false, bool thread_texture_loads = false, bool thread_media_updates = false);
|
||||
static void allocateConversionBuffer();
|
||||
static void cleanupClass() ;
|
||||
|
||||
private:
|
||||
|
|
@ -308,6 +309,7 @@ private:
|
|||
static bool sSkipAnalyzeAlpha;
|
||||
static U32 sScratchPBO;
|
||||
static U32 sScratchPBOSize;
|
||||
static U32* sManualScratch;
|
||||
|
||||
//the flag to allow to call readBackRaw(...).
|
||||
//can be removed if we do not use that function at all.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -42,25 +42,17 @@
|
|||
#include "llpointer.h"
|
||||
#include "llglheaders.h"
|
||||
#include "llmatrix4a.h"
|
||||
|
||||
#if LL_LINUX && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) >= 70000
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
|
||||
#endif
|
||||
|
||||
#include "glh/glh_linear.h"
|
||||
|
||||
#if LL_LINUX && (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ ) >= 70000
|
||||
#pragma GCC diagnostic push
|
||||
#endif
|
||||
#include "glm/mat4x4.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <list>
|
||||
|
||||
class LLVertexBuffer;
|
||||
class LLCubeMap;
|
||||
class LLImageGL;
|
||||
class LLRenderTarget;
|
||||
class LLTexture ;
|
||||
class LLTexture;
|
||||
class LLVertexBufferData;
|
||||
|
||||
#define LL_MATRIX_STACK_DEPTH 32
|
||||
|
||||
|
|
@ -229,17 +221,12 @@ public:
|
|||
|
||||
void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; }
|
||||
|
||||
void setTextureColorSpace(eTextureColorSpace space);
|
||||
|
||||
eTextureColorSpace getCurrColorSpace() { return mTexColorSpace; }
|
||||
|
||||
protected:
|
||||
friend class LLRender;
|
||||
|
||||
S32 mIndex;
|
||||
U32 mCurrTexture;
|
||||
eTextureType mCurrTexType;
|
||||
eTextureColorSpace mTexColorSpace;
|
||||
S32 mCurrColorScale;
|
||||
S32 mCurrAlphaScale;
|
||||
bool mHasMipMaps;
|
||||
|
|
@ -332,8 +319,6 @@ public:
|
|||
POINTS,
|
||||
LINES,
|
||||
LINE_STRIP,
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//QUADS,
|
||||
LINE_LOOP,
|
||||
NUM_MODES
|
||||
};
|
||||
|
|
@ -415,8 +400,8 @@ public:
|
|||
void matrixMode(eMatrixMode mode);
|
||||
eMatrixMode getMatrixMode();
|
||||
|
||||
const glh::matrix4f& getModelviewMatrix();
|
||||
const glh::matrix4f& getProjectionMatrix();
|
||||
const glm::mat4& getModelviewMatrix();
|
||||
const glm::mat4& getProjectionMatrix();
|
||||
|
||||
void syncMatrices();
|
||||
void syncLightState();
|
||||
|
|
@ -431,8 +416,15 @@ public:
|
|||
|
||||
void flush();
|
||||
|
||||
// if list is set, will store buffers in list for later use, if list isn't set, will use cache
|
||||
void beginList(std::list<LLVertexBufferData> *list);
|
||||
void endList();
|
||||
|
||||
void begin(const GLuint& mode);
|
||||
void end();
|
||||
|
||||
U8 getMode() const { return mMode; }
|
||||
|
||||
void vertex2i(const GLint& x, const GLint& y);
|
||||
void vertex2f(const GLfloat& x, const GLfloat& y);
|
||||
void vertex3f(const GLfloat& x, const GLfloat& y, const GLfloat& z);
|
||||
|
|
@ -457,9 +449,9 @@ public:
|
|||
void diffuseColor4ubv(const U8* c);
|
||||
void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a);
|
||||
|
||||
void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count);
|
||||
void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count);
|
||||
void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, LLColor4U*, S32 vert_count);
|
||||
void vertexBatchPreTransformed(LLVector4a* verts, S32 vert_count);
|
||||
void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, S32 vert_count);
|
||||
void vertexBatchPreTransformed(LLVector4a* verts, LLVector2* uvs, LLColor4U*, S32 vert_count);
|
||||
|
||||
void setColorMask(bool writeColor, bool writeAlpha);
|
||||
void setColorMask(bool writeColorR, bool writeColorG, bool writeColorB, bool writeAlpha);
|
||||
|
|
@ -499,21 +491,25 @@ public:
|
|||
static bool sGLCoreProfile;
|
||||
static bool sNsightDebugSupport;
|
||||
static LLVector2 sUIGLScaleFactor;
|
||||
static bool sClassicMode; // classic sky mode active
|
||||
|
||||
private:
|
||||
friend class LLLightState;
|
||||
|
||||
LLVertexBuffer* bufferfromCache(U32 attribute_mask, U32 count);
|
||||
LLVertexBuffer* genBuffer(U32 attribute_mask, S32 count);
|
||||
void drawBuffer(LLVertexBuffer* vb, U32 mode, S32 count);
|
||||
void resetStriders(S32 count);
|
||||
|
||||
eMatrixMode mMatrixMode;
|
||||
U32 mMatIdx[NUM_MATRIX_MODES];
|
||||
U32 mMatHash[NUM_MATRIX_MODES];
|
||||
glh::matrix4f mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH];
|
||||
glm::mat4 mMatrix[NUM_MATRIX_MODES][LL_MATRIX_STACK_DEPTH];
|
||||
U32 mCurMatHash[NUM_MATRIX_MODES];
|
||||
U32 mLightHash;
|
||||
LLColor4 mAmbientLightColor;
|
||||
|
||||
bool mDirty;
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//U32 mQuadCycle;
|
||||
U32 mCount;
|
||||
U32 mMode;
|
||||
U32 mCurrTextureUnitIndex;
|
||||
|
|
@ -525,7 +521,7 @@ private:
|
|||
// </FS:Ansariel>
|
||||
|
||||
LLPointer<LLVertexBuffer> mBuffer;
|
||||
LLStrider<LLVector3> mVerticesp;
|
||||
LLStrider<LLVector4a> mVerticesp;
|
||||
LLStrider<LLVector2> mTexcoordsp;
|
||||
LLStrider<LLColor4U> mColorsp;
|
||||
std::array<LLTexUnit, LL_NUM_TEXTURE_LAYERS> mTexUnits;
|
||||
|
|
@ -539,7 +535,6 @@ private:
|
|||
|
||||
std::vector<LLVector3> mUIOffset;
|
||||
std::vector<LLVector3> mUIScale;
|
||||
|
||||
};
|
||||
|
||||
extern F32 gGLModelView[16];
|
||||
|
|
@ -547,8 +542,8 @@ extern F32 gGLLastModelView[16];
|
|||
extern F32 gGLLastProjection[16];
|
||||
extern F32 gGLProjection[16];
|
||||
extern S32 gGLViewport[4];
|
||||
extern F32 gGLDeltaModelView[16];
|
||||
extern F32 gGLInverseDeltaModelView[16];
|
||||
extern glm::mat4 gGLDeltaModelView;
|
||||
extern glm::mat4 gGLInverseDeltaModelView;
|
||||
|
||||
extern thread_local LLRender gGL;
|
||||
|
||||
|
|
@ -559,19 +554,20 @@ const F32 OGL_TO_CFR_ROTATION[16] = { 0.f, 0.f, -1.f, 0.f, // -Z becomes X
|
|||
0.f, 1.f, 0.f, 0.f, // Y becomes Z
|
||||
0.f, 0.f, 0.f, 1.f };
|
||||
|
||||
glh::matrix4f copy_matrix(F32* src);
|
||||
glh::matrix4f get_current_modelview();
|
||||
glh::matrix4f get_current_projection();
|
||||
glh::matrix4f get_last_modelview();
|
||||
glh::matrix4f get_last_projection();
|
||||
glm::mat4 copy_matrix(F32* src);
|
||||
glm::mat4 get_current_modelview();
|
||||
glm::mat4 get_current_projection();
|
||||
glm::mat4 get_last_modelview();
|
||||
glm::mat4 get_last_projection();
|
||||
|
||||
void copy_matrix(const glh::matrix4f& src, F32* dst);
|
||||
void set_current_modelview(const glh::matrix4f& mat);
|
||||
void set_current_projection(glh::matrix4f& mat);
|
||||
void copy_matrix(const glm::mat4& src, F32* dst);
|
||||
void set_current_modelview(const glm::mat4& mat);
|
||||
void set_current_projection(const glm::mat4& mat);
|
||||
void set_last_modelview(const glm::mat4& mat);
|
||||
void set_last_projection(const glm::mat4& mat);
|
||||
|
||||
glh::matrix4f gl_ortho(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat znear, GLfloat zfar);
|
||||
glh::matrix4f gl_perspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar);
|
||||
glh::matrix4f gl_lookat(LLVector3 eye, LLVector3 center, LLVector3 up);
|
||||
// glh compat
|
||||
glm::vec3 mul_mat4_vec3(const glm::mat4& mat, const glm::vec3& vec);
|
||||
|
||||
#define LL_SHADER_LOADING_WARNS(...) LL_WARNS()
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -34,6 +34,8 @@
|
|||
#include "llerror.h"
|
||||
|
||||
#include "llglheaders.h"
|
||||
#include "llvertexbuffer.h"
|
||||
#include "llglslshader.h"
|
||||
|
||||
LLRenderSphere gSphere;
|
||||
|
||||
|
|
@ -53,12 +55,20 @@ inline LLVector3 polar_to_cart(F32 latitude, F32 longitude)
|
|||
|
||||
void LLRenderSphere::renderGGL()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
S32 const LATITUDE_SLICES = 20;
|
||||
S32 const LONGITUDE_SLICES = 30;
|
||||
|
||||
if (mSpherePoints.empty())
|
||||
if (mVertexBuffer.isNull())
|
||||
{
|
||||
mSpherePoints.resize(LATITUDE_SLICES + 1);
|
||||
mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX);
|
||||
|
||||
mVertexBuffer->allocateBuffer((U32)(LATITUDE_SLICES + 1) * (LONGITUDE_SLICES + 1), LATITUDE_SLICES * LONGITUDE_SLICES * 6);
|
||||
|
||||
LLStrider<LLVector3> v;
|
||||
mVertexBuffer->getVertexStrider(v);
|
||||
|
||||
for (S32 lat_i = 0; lat_i < LATITUDE_SLICES + 1; lat_i++)
|
||||
{
|
||||
mSpherePoints[lat_i].resize(LONGITUDE_SLICES + 1);
|
||||
|
|
@ -68,24 +78,52 @@ void LLRenderSphere::renderGGL()
|
|||
F32 lon = (F32)lon_i / LONGITUDE_SLICES;
|
||||
|
||||
mSpherePoints[lat_i][lon_i] = polar_to_cart(lat, lon);
|
||||
v[lat_i * (LONGITUDE_SLICES + 1) + lon_i] = mSpherePoints[lat_i][lon_i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gGL.begin(LLRender::TRIANGLES);
|
||||
LLStrider<U16> i;
|
||||
mVertexBuffer->getIndexStrider(i);
|
||||
|
||||
for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++)
|
||||
{
|
||||
for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++)
|
||||
for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++)
|
||||
{
|
||||
gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV);
|
||||
gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
|
||||
gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
|
||||
for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++)
|
||||
{
|
||||
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 0] = lat_i * (LONGITUDE_SLICES + 1) + lon_i;
|
||||
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 1] = lat_i * (LONGITUDE_SLICES + 1) + lon_i + 1;
|
||||
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 2] = (lat_i + 1) * (LONGITUDE_SLICES + 1) + lon_i;
|
||||
|
||||
gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i].mV);
|
||||
gGL.vertex3fv(mSpherePoints[lat_i][lon_i+1].mV);
|
||||
gGL.vertex3fv(mSpherePoints[lat_i+1][lon_i+1].mV);
|
||||
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 3] = (lat_i + 1) * (LONGITUDE_SLICES + 1) + lon_i;
|
||||
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 4] = lat_i * (LONGITUDE_SLICES + 1) + lon_i + 1;
|
||||
i[(lat_i * LONGITUDE_SLICES + lon_i) * 6 + 5] = (lat_i + 1) * (LONGITUDE_SLICES + 1) + lon_i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
mVertexBuffer->unmapBuffer();
|
||||
}
|
||||
|
||||
|
||||
if (LLGLSLShader::sCurBoundShaderPtr->mAttributeMask == LLVertexBuffer::MAP_VERTEX)
|
||||
{ // shader expects only vertex positions in vertex buffer, use fast path
|
||||
mVertexBuffer->setBuffer();
|
||||
mVertexBuffer->drawRange(LLRender::TRIANGLES, 0, mVertexBuffer->getNumVerts(), mVertexBuffer->getNumIndices(), 0);
|
||||
}
|
||||
else
|
||||
{ //shader wants colors in the vertex stream, use slow path
|
||||
gGL.begin(LLRender::TRIANGLES);
|
||||
for (S32 lat_i = 0; lat_i < LATITUDE_SLICES; lat_i++)
|
||||
{
|
||||
for (S32 lon_i = 0; lon_i < LONGITUDE_SLICES; lon_i++)
|
||||
{
|
||||
gGL.vertex3fv(mSpherePoints[lat_i][lon_i].mV);
|
||||
gGL.vertex3fv(mSpherePoints[lat_i][lon_i + 1].mV);
|
||||
gGL.vertex3fv(mSpherePoints[lat_i + 1][lon_i].mV);
|
||||
|
||||
gGL.vertex3fv(mSpherePoints[lat_i + 1][lon_i].mV);
|
||||
gGL.vertex3fv(mSpherePoints[lat_i][lon_i + 1].mV);
|
||||
gGL.vertex3fv(mSpherePoints[lat_i + 1][lon_i + 1].mV);
|
||||
}
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
gGL.end();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ public:
|
|||
|
||||
private:
|
||||
std::vector< std::vector<LLVector3> > mSpherePoints;
|
||||
LLPointer<LLVertexBuffer> mVertexBuffer;
|
||||
};
|
||||
|
||||
extern LLRenderSphere gSphere;
|
||||
|
|
|
|||
|
|
@ -475,12 +475,10 @@ void LLRenderTarget::clear(U32 mask_in)
|
|||
|
||||
U32 LLRenderTarget::getTexture(U32 attachment) const
|
||||
{
|
||||
if (attachment > mTex.size()-1)
|
||||
{
|
||||
LL_ERRS() << "Invalid attachment index." << LL_ENDL;
|
||||
}
|
||||
if (mTex.empty())
|
||||
if (attachment >= mTex.size())
|
||||
{
|
||||
LL_WARNS() << "Invalid attachment index " << attachment << " for size " << mTex.size() << LL_ENDL;
|
||||
llassert(false);
|
||||
return 0;
|
||||
}
|
||||
return mTex[attachment];
|
||||
|
|
@ -511,7 +509,6 @@ void LLRenderTarget::bindTexture(U32 index, S32 channel, LLTexUnit::eTextureFilt
|
|||
}
|
||||
|
||||
gGL.getTexUnit(channel)->setTextureFilteringOption(filter_options);
|
||||
gGL.getTexUnit(channel)->setTextureColorSpace(isSRGB ? LLTexUnit::TCS_SRGB : LLTexUnit::TCS_LINEAR);
|
||||
}
|
||||
|
||||
void LLRenderTarget::flush()
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
|||
//////////////////////////////////////
|
||||
|
||||
// NOTE order of shader object attaching is VERY IMPORTANT!!!
|
||||
if (features->calculatesAtmospherics)
|
||||
if (features->calculatesAtmospherics || features->hasGamma || features->isDeferred)
|
||||
{
|
||||
if (!shader->attachVertexObject("windlight/atmosphericsVarsV.glsl"))
|
||||
{
|
||||
|
|
@ -223,6 +223,14 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
|||
}
|
||||
}
|
||||
|
||||
if (features->hasFullGBuffer)
|
||||
{
|
||||
if (!shader->attachFragmentObject("deferred/gbufferUtil.glsl"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (features->hasScreenSpaceReflections || features->hasReflectionProbes)
|
||||
{
|
||||
if (!shader->attachFragmentObject("deferred/screenSpaceReflUtil.glsl"))
|
||||
|
|
@ -565,17 +573,11 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
|
|||
}
|
||||
else if (major_version == 3)
|
||||
{
|
||||
if (minor_version < 10)
|
||||
if (minor_version <= 29)
|
||||
{
|
||||
shader_code_text[shader_code_count++] = strdup("#version 300\n");
|
||||
}
|
||||
else if (minor_version <= 19)
|
||||
{
|
||||
shader_code_text[shader_code_count++] = strdup("#version 310\n");
|
||||
}
|
||||
else if (minor_version <= 29)
|
||||
{
|
||||
shader_code_text[shader_code_count++] = strdup("#version 320\n");
|
||||
// OpenGL 3.2 had GLSL version 1.50. anything after that the version numbers match.
|
||||
// https://www.khronos.org/opengl/wiki/Core_Language_(GLSL)#OpenGL_and_GLSL_versions
|
||||
shader_code_text[shader_code_count++] = strdup("#version 150\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -584,7 +586,8 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
|
|||
}
|
||||
else
|
||||
{
|
||||
if (type == GL_GEOMETRY_SHADER)
|
||||
// OpenGL 3.2 had GLSL version 1.50. anything after that the version numbers match.
|
||||
if (type == GL_GEOMETRY_SHADER || minor_version >= 50)
|
||||
{
|
||||
//set version to 1.50
|
||||
shader_code_text[shader_code_count++] = strdup("#version 150\n");
|
||||
|
|
@ -601,8 +604,15 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
|
|||
extra_code_text[extra_code_count++] = strdup("precision highp float;\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extra_code_text[extra_code_count++] = strdup("#define FXAA_GLSL_130 1\n");
|
||||
if (type == GL_FRAGMENT_SHADER)
|
||||
{
|
||||
extra_code_text[extra_code_count++] = strdup("#define FRAGMENT_SHADER 1\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
extra_code_text[extra_code_count++] = strdup("#define VERTEX_SHADER 1\n");
|
||||
}
|
||||
|
||||
// Use alpha float to store bit flags
|
||||
|
|
@ -611,7 +621,7 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
|
|||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_ATMOS 0.34\n"); // bit 0
|
||||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_PBR 0.67\n"); // bit 1
|
||||
extra_code_text[extra_code_count++] = strdup("#define GBUFFER_FLAG_HAS_HDRI 1.0\n"); // bit 2
|
||||
extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(flag) (abs(norm.w-flag)< 0.1)\n");
|
||||
extra_code_text[extra_code_count++] = strdup("#define GET_GBUFFER_FLAG(data, flag) (abs(data-flag)< 0.1)\n");
|
||||
|
||||
if (defines)
|
||||
{
|
||||
|
|
@ -722,6 +732,9 @@ GLuint LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shader_lev
|
|||
}
|
||||
}
|
||||
|
||||
// Master definition can be found in deferredUtil.glsl
|
||||
extra_code_text[extra_code_count++] = strdup("struct GBufferInfo { vec4 albedo; vec4 specular; vec3 normal; vec4 emissive; float gbufferFlag; float envIntensity; };\n");
|
||||
|
||||
//copy file into memory
|
||||
enum {
|
||||
flag_write_to_out_of_extra_block_area = 0x01
|
||||
|
|
@ -1254,6 +1267,7 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
mReservedUniforms.push_back("sky_hdr_scale");
|
||||
mReservedUniforms.push_back("sky_sunlight_scale");
|
||||
mReservedUniforms.push_back("sky_ambient_scale");
|
||||
mReservedUniforms.push_back("classic_mode");
|
||||
mReservedUniforms.push_back("blue_horizon");
|
||||
mReservedUniforms.push_back("blue_density");
|
||||
mReservedUniforms.push_back("haze_horizon");
|
||||
|
|
@ -1488,6 +1502,11 @@ void LLShaderMgr::initAttribsAndUniforms()
|
|||
|
||||
mReservedUniforms.push_back("debug_normal_draw_length");
|
||||
|
||||
mReservedUniforms.push_back("edgesTex");
|
||||
mReservedUniforms.push_back("areaTex");
|
||||
mReservedUniforms.push_back("searchTex");
|
||||
mReservedUniforms.push_back("blendTex");
|
||||
|
||||
llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
|
||||
|
||||
std::set<std::string> dupe_check;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ public:
|
|||
SKY_HDR_SCALE, // "sky_hdr_scale"
|
||||
SKY_SUNLIGHT_SCALE, // "sky_sunlight_scale"
|
||||
SKY_AMBIENT_SCALE, // "sky_ambient_scale"
|
||||
CLASSIC_MODE, // "classic_mode"
|
||||
BLUE_HORIZON, // "blue_horizon"
|
||||
BLUE_DENSITY, // "blue_density"
|
||||
HAZE_HORIZON, // "haze_horizon"
|
||||
|
|
@ -345,6 +346,11 @@ public:
|
|||
|
||||
DEBUG_NORMAL_DRAW_LENGTH, // "debug_normal_draw_length"
|
||||
|
||||
SMAA_EDGE_TEX, // "edgesTex"
|
||||
SMAA_AREA_TEX, // "areaTex"
|
||||
SMAA_SEARCH_TEX, // "searchTex"
|
||||
SMAA_BLEND_TEX, // "blendTex"
|
||||
|
||||
END_RESERVED_UNIFORMS
|
||||
} eGLSLReservedUniforms;
|
||||
// clang-format on
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "llshadermgr.h"
|
||||
#include "llglslshader.h"
|
||||
#include "llmemory.h"
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
//Next Highest Power Of Two
|
||||
//helper function, returns first number > v that is a power of 2, or v if v is already a power of 2
|
||||
|
|
@ -272,11 +273,13 @@ static GLuint gen_buffer()
|
|||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("gen buffer");
|
||||
sIndex = pool_size;
|
||||
#if !LL_DARWIN
|
||||
if (!gGLManager.mIsAMD)
|
||||
{
|
||||
glGenBuffers(pool_size, sNamePool);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{ // work around for AMD driver bug
|
||||
for (U32 i = 0; i < pool_size; ++i)
|
||||
{
|
||||
|
|
@ -289,22 +292,58 @@ static GLuint gen_buffer()
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void delete_buffers(S32 count, GLuint* buffers)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
|
||||
// wait a few frames before actually deleting the buffers to avoid
|
||||
// synchronization issues with the GPU
|
||||
static std::vector<GLuint> sFreeList[4];
|
||||
|
||||
if (gGLManager.mInited)
|
||||
{
|
||||
U32 idx = LLImageGL::sFrameCount % 4;
|
||||
|
||||
for (S32 i = 0; i < count; ++i)
|
||||
{
|
||||
sFreeList[idx].push_back(buffers[i]);
|
||||
}
|
||||
|
||||
idx = (LLImageGL::sFrameCount + 3) % 4;
|
||||
|
||||
if (!sFreeList[idx].empty())
|
||||
{
|
||||
glDeleteBuffers((GLsizei)sFreeList[idx].size(), sFreeList[idx].data());
|
||||
sFreeList[idx].resize(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define ANALYZE_VBO_POOL 0
|
||||
|
||||
#if LL_DARWIN
|
||||
|
||||
// experimental -- disable VBO pooling on OS X and use glMapBuffer
|
||||
// VBO Pool interface
|
||||
class LLVBOPool
|
||||
{
|
||||
public:
|
||||
virtual ~LLVBOPool() = default;
|
||||
virtual void allocate(GLenum type, U32 size, GLuint& name, U8*& data) = 0;
|
||||
virtual void free(GLenum type, U32 size, GLuint name, U8* data) = 0;
|
||||
virtual U64 getVramBytesUsed() = 0;
|
||||
};
|
||||
|
||||
// VBO Pool for Apple GPUs (as in M1/M2 etc, not Intel macs)
|
||||
// Effectively disables VBO pooling
|
||||
class LLAppleVBOPool final: public LLVBOPool
|
||||
{
|
||||
public:
|
||||
U64 mAllocated = 0;
|
||||
|
||||
U64 getVramBytesUsed()
|
||||
U64 getVramBytesUsed() override
|
||||
{
|
||||
return mAllocated;
|
||||
}
|
||||
|
||||
void allocate(GLenum type, U32 size, GLuint& name, U8*& data)
|
||||
void allocate(GLenum type, U32 size, GLuint& name, U8*& data) override
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
|
||||
STOP_GLERROR;
|
||||
|
|
@ -324,7 +363,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void free(GLenum type, U32 size, GLuint name, U8* data)
|
||||
void free(GLenum type, U32 size, GLuint name, U8* data) override
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
|
||||
llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER);
|
||||
|
|
@ -339,19 +378,17 @@ public:
|
|||
STOP_GLERROR;
|
||||
if (name)
|
||||
{
|
||||
glDeleteBuffers(1, &name);
|
||||
delete_buffers(1, &name);
|
||||
}
|
||||
STOP_GLERROR;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class LLVBOPool
|
||||
// VBO Pool for GPUs that benefit from VBO pooling
|
||||
class LLDefaultVBOPool final : public LLVBOPool
|
||||
{
|
||||
public:
|
||||
typedef std::chrono::steady_clock::time_point Time;
|
||||
|
||||
struct Entry
|
||||
{
|
||||
U8* mData;
|
||||
|
|
@ -359,7 +396,7 @@ public:
|
|||
Time mAge;
|
||||
};
|
||||
|
||||
~LLVBOPool()
|
||||
~LLDefaultVBOPool() override
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
|
@ -377,7 +414,7 @@ public:
|
|||
U32 mMisses = 0;
|
||||
U32 mHits = 0;
|
||||
|
||||
U64 getVramBytesUsed()
|
||||
U64 getVramBytesUsed() override
|
||||
{
|
||||
return mAllocated + mReserved;
|
||||
}
|
||||
|
|
@ -393,7 +430,7 @@ public:
|
|||
size += block_size - (size % block_size);
|
||||
}
|
||||
|
||||
void allocate(GLenum type, U32 size, GLuint& name, U8*& data)
|
||||
void allocate(GLenum type, U32 size, GLuint& name, U8*& data) override
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
|
||||
llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER);
|
||||
|
|
@ -449,7 +486,7 @@ public:
|
|||
clean();
|
||||
}
|
||||
|
||||
void free(GLenum type, U32 size, GLuint name, U8* data)
|
||||
void free(GLenum type, U32 size, GLuint name, U8* data) override
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
|
||||
llassert(type == GL_ARRAY_BUFFER || type == GL_ELEMENT_ARRAY_BUFFER);
|
||||
|
|
@ -512,7 +549,7 @@ public:
|
|||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vbo cache timeout");
|
||||
auto& entry = entries.back();
|
||||
ll_aligned_free_16(entry.mData);
|
||||
glDeleteBuffers(1, &entry.mGLName);
|
||||
delete_buffers(1, &entry.mGLName);
|
||||
llassert(mReserved >= iter->first);
|
||||
mReserved -= iter->first;
|
||||
entries.pop_back();
|
||||
|
|
@ -548,7 +585,7 @@ public:
|
|||
for (auto& entry : entries.second)
|
||||
{
|
||||
ll_aligned_free_16(entry.mData);
|
||||
glDeleteBuffers(1, &entry.mGLName);
|
||||
delete_buffers(1, &entry.mGLName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -557,7 +594,7 @@ public:
|
|||
for (auto& entry : entries.second)
|
||||
{
|
||||
ll_aligned_free_16(entry.mData);
|
||||
glDeleteBuffers(1, &entry.mGLName);
|
||||
delete_buffers(1, &entry.mGLName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -567,10 +604,71 @@ public:
|
|||
mVBOPool.clear();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static LLVBOPool* sVBOPool = nullptr;
|
||||
|
||||
void LLVertexBufferData::drawWithMatrix()
|
||||
{
|
||||
if (!mVB)
|
||||
{
|
||||
llassert(false);
|
||||
// Not supposed to happen, check buffer generation
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTexName)
|
||||
{
|
||||
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTexName);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadMatrix(glm::value_ptr(mModelView));
|
||||
gGL.matrixMode(LLRender::MM_PROJECTION);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadMatrix(glm::value_ptr(mProjection));
|
||||
gGL.matrixMode(LLRender::MM_TEXTURE0);
|
||||
gGL.pushMatrix();
|
||||
gGL.loadMatrix(glm::value_ptr(mTexture0));
|
||||
|
||||
mVB->setBuffer();
|
||||
mVB->drawArrays(mMode, 0, mCount);
|
||||
|
||||
gGL.popMatrix();
|
||||
gGL.matrixMode(LLRender::MM_PROJECTION);
|
||||
gGL.popMatrix();
|
||||
gGL.matrixMode(LLRender::MM_MODELVIEW);
|
||||
gGL.popMatrix();
|
||||
}
|
||||
|
||||
void LLVertexBufferData::draw()
|
||||
{
|
||||
if (!mVB)
|
||||
{
|
||||
llassert(false);
|
||||
// Not supposed to happen, check buffer generation
|
||||
return;
|
||||
}
|
||||
|
||||
if (mTexName)
|
||||
{
|
||||
gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, mTexName);
|
||||
}
|
||||
else
|
||||
{
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
}
|
||||
|
||||
mVB->setBuffer();
|
||||
mVB->drawArrays(mMode, 0, mCount);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
//static
|
||||
U64 LLVertexBuffer::getBytesAllocated()
|
||||
{
|
||||
|
|
@ -633,7 +731,6 @@ const U32 LLVertexBuffer::sGLMode[LLRender::NUM_MODES] =
|
|||
GL_POINTS,
|
||||
GL_LINES,
|
||||
GL_LINE_STRIP,
|
||||
//GL_QUADS, // <FS:Ansariel> Remove QUADS rendering mode
|
||||
GL_LINE_LOOP,
|
||||
};
|
||||
|
||||
|
|
@ -864,7 +961,17 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
|
|||
void LLVertexBuffer::initClass(LLWindow* window)
|
||||
{
|
||||
llassert(sVBOPool == nullptr);
|
||||
sVBOPool = new LLVBOPool();
|
||||
|
||||
if (gGLManager.mIsApple)
|
||||
{
|
||||
LL_INFOS() << "VBO Pooling Disabled" << LL_ENDL;
|
||||
sVBOPool = new LLAppleVBOPool();
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "VBO Pooling Enabled" << LL_ENDL;
|
||||
sVBOPool = new LLDefaultVBOPool();
|
||||
}
|
||||
|
||||
#if ENABLE_GL_WORK_QUEUE
|
||||
sQueue = new GLWorkQueue();
|
||||
|
|
@ -923,6 +1030,24 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask)
|
|||
}
|
||||
}
|
||||
|
||||
// list of mapped buffers
|
||||
// NOTE: must not be LLPointer<LLVertexBuffer> to avoid breaking non-ref-counted LLVertexBuffer instances
|
||||
static std::vector<LLVertexBuffer*> sMappedBuffers;
|
||||
|
||||
//static
|
||||
void LLVertexBuffer::flushBuffers()
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
|
||||
// must only be called from main thread
|
||||
for (auto& buffer : sMappedBuffers)
|
||||
{
|
||||
buffer->_unmapBuffer();
|
||||
buffer->mMapped = false;
|
||||
}
|
||||
|
||||
sMappedBuffers.resize(0);
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLVertexBuffer::calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices)
|
||||
{
|
||||
|
|
@ -966,6 +1091,12 @@ U32 LLVertexBuffer::calcVertexSize(const U32& typemask)
|
|||
//virtual
|
||||
LLVertexBuffer::~LLVertexBuffer()
|
||||
{
|
||||
if (mMapped)
|
||||
{ // is on the mapped buffer list but doesn't need to be flushed
|
||||
mMapped = false;
|
||||
unmapBuffer();
|
||||
}
|
||||
|
||||
destroyGLBuffer();
|
||||
destroyGLIndices();
|
||||
|
||||
|
|
@ -1167,34 +1298,36 @@ bool expand_region(LLVertexBuffer::MappedRegion& region, U32 start, U32 end)
|
|||
U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 index, S32 count)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
|
||||
_mapBuffer();
|
||||
|
||||
if (count == -1)
|
||||
{
|
||||
count = mNumVerts - index;
|
||||
}
|
||||
|
||||
#if !LL_DARWIN
|
||||
U32 start = mOffsets[type] + sTypeSize[type] * index;
|
||||
U32 end = start + sTypeSize[type] * count-1;
|
||||
|
||||
bool flagged = false;
|
||||
// flag region as mapped
|
||||
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
|
||||
if (!gGLManager.mIsApple)
|
||||
{
|
||||
MappedRegion& region = mMappedVertexRegions[i];
|
||||
if (expand_region(region, start, end))
|
||||
U32 start = mOffsets[type] + sTypeSize[type] * index;
|
||||
U32 end = start + sTypeSize[type] * count-1;
|
||||
|
||||
bool flagged = false;
|
||||
// flag region as mapped
|
||||
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
|
||||
{
|
||||
flagged = true;
|
||||
break;
|
||||
MappedRegion& region = mMappedVertexRegions[i];
|
||||
if (expand_region(region, start, end))
|
||||
{
|
||||
flagged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flagged)
|
||||
{
|
||||
//didn't expand an existing region, make a new one
|
||||
mMappedVertexRegions.push_back({ start, end });
|
||||
}
|
||||
}
|
||||
|
||||
if (!flagged)
|
||||
{
|
||||
//didn't expand an existing region, make a new one
|
||||
mMappedVertexRegions.push_back({ start, end });
|
||||
}
|
||||
#endif
|
||||
return mMappedData+mOffsets[type]+sTypeSize[type]*index;
|
||||
}
|
||||
|
||||
|
|
@ -1202,35 +1335,37 @@ U8* LLVertexBuffer::mapVertexBuffer(LLVertexBuffer::AttributeType type, U32 inde
|
|||
U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED_CATEGORY_VERTEX;
|
||||
_mapBuffer();
|
||||
|
||||
if (count == -1)
|
||||
{
|
||||
count = mNumIndices-index;
|
||||
}
|
||||
|
||||
#if !LL_DARWIN
|
||||
U32 start = sizeof(U16) * index;
|
||||
U32 end = start + sizeof(U16) * count-1;
|
||||
|
||||
bool flagged = false;
|
||||
// flag region as mapped
|
||||
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
|
||||
if (!gGLManager.mIsApple)
|
||||
{
|
||||
MappedRegion& region = mMappedIndexRegions[i];
|
||||
if (expand_region(region, start, end))
|
||||
U32 start = sizeof(U16) * index;
|
||||
U32 end = start + sizeof(U16) * count-1;
|
||||
|
||||
bool flagged = false;
|
||||
// flag region as mapped
|
||||
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
|
||||
{
|
||||
flagged = true;
|
||||
break;
|
||||
MappedRegion& region = mMappedIndexRegions[i];
|
||||
if (expand_region(region, start, end))
|
||||
{
|
||||
flagged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flagged)
|
||||
{
|
||||
//didn't expand an existing region, make a new one
|
||||
mMappedIndexRegions.push_back({ start, end });
|
||||
}
|
||||
}
|
||||
|
||||
if (!flagged)
|
||||
{
|
||||
//didn't expand an existing region, make a new one
|
||||
mMappedIndexRegions.push_back({ start, end });
|
||||
}
|
||||
#endif
|
||||
|
||||
return mMappedIndexData + sizeof(U16)*index;
|
||||
}
|
||||
|
||||
|
|
@ -1242,39 +1377,64 @@ U8* LLVertexBuffer::mapIndexBuffer(U32 index, S32 count)
|
|||
// dst -- mMappedData or mMappedIndexData
|
||||
void LLVertexBuffer::flush_vbo(GLenum target, U32 start, U32 end, void* data, U8* dst)
|
||||
{
|
||||
#if LL_DARWIN
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy");
|
||||
STOP_GLERROR;
|
||||
// copy into mapped buffer
|
||||
memcpy(dst+start, data, end-start+1);
|
||||
#else
|
||||
llassert(target == GL_ARRAY_BUFFER ? sGLRenderBuffer == mGLBuffer : sGLRenderIndices == mGLIndices);
|
||||
|
||||
// skip mapped data and stream to GPU via glBufferSubData
|
||||
if (end != 0)
|
||||
if (gGLManager.mIsApple)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData");
|
||||
LL_PROFILE_ZONE_NUM(start);
|
||||
LL_PROFILE_ZONE_NUM(end);
|
||||
LL_PROFILE_ZONE_NUM(end-start);
|
||||
// on OS X, flush_vbo doesn't actually write to the GL buffer, so be sure to call
|
||||
// _mapBuffer to tag the buffer for flushing to GL
|
||||
_mapBuffer();
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("vb memcpy");
|
||||
STOP_GLERROR;
|
||||
// copy into mapped buffer
|
||||
memcpy(dst+start, data, end-start+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(target == GL_ARRAY_BUFFER ? sGLRenderBuffer == mGLBuffer : sGLRenderIndices == mGLIndices);
|
||||
|
||||
constexpr U32 block_size = 8192;
|
||||
|
||||
for (U32 i = start; i <= end; i += block_size)
|
||||
// skip mapped data and stream to GPU via glBufferSubData
|
||||
if (end != 0)
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block");
|
||||
//LL_PROFILE_GPU_ZONE("glBufferSubData");
|
||||
U32 tend = llmin(i + block_size, end);
|
||||
U32 size = tend - i + 1;
|
||||
glBufferSubData(target, i, size, (U8*) data + (i-start));
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData");
|
||||
LL_PROFILE_ZONE_NUM(start);
|
||||
LL_PROFILE_ZONE_NUM(end);
|
||||
LL_PROFILE_ZONE_NUM(end-start);
|
||||
|
||||
constexpr U32 block_size = 65536;
|
||||
|
||||
for (U32 i = start; i <= end; i += block_size)
|
||||
{
|
||||
//LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("glBufferSubData block");
|
||||
//LL_PROFILE_GPU_ZONE("glBufferSubData");
|
||||
U32 tend = llmin(i + block_size, end);
|
||||
U32 size = tend - i + 1;
|
||||
glBufferSubData(target, i, size, (U8*) data + (i-start));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LLVertexBuffer::unmapBuffer()
|
||||
{
|
||||
flushBuffers();
|
||||
}
|
||||
|
||||
void LLVertexBuffer::_mapBuffer()
|
||||
{
|
||||
if (!mMapped)
|
||||
{
|
||||
mMapped = true;
|
||||
sMappedBuffers.push_back(this);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVertexBuffer::_unmapBuffer()
|
||||
{
|
||||
STOP_GLERROR;
|
||||
if (!mMapped)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct SortMappedRegion
|
||||
{
|
||||
bool operator()(const MappedRegion& lhs, const MappedRegion& rhs)
|
||||
|
|
@ -1283,114 +1443,116 @@ void LLVertexBuffer::unmapBuffer()
|
|||
}
|
||||
};
|
||||
|
||||
#if LL_DARWIN
|
||||
STOP_GLERROR;
|
||||
if (mMappedData)
|
||||
if (gGLManager.mIsApple)
|
||||
{
|
||||
if (mGLBuffer)
|
||||
STOP_GLERROR;
|
||||
if (mMappedData)
|
||||
{
|
||||
glDeleteBuffers(1, &mGLBuffer);
|
||||
if (mGLBuffer)
|
||||
{
|
||||
delete_buffers(1, &mGLBuffer);
|
||||
}
|
||||
mGLBuffer = gen_buffer();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
|
||||
sGLRenderBuffer = mGLBuffer;
|
||||
glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW);
|
||||
}
|
||||
mGLBuffer = gen_buffer();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
|
||||
sGLRenderBuffer = mGLBuffer;
|
||||
glBufferData(GL_ARRAY_BUFFER, mSize, mMappedData, GL_STATIC_DRAW);
|
||||
}
|
||||
else if (mGLBuffer != sGLRenderBuffer)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
|
||||
sGLRenderBuffer = mGLBuffer;
|
||||
}
|
||||
STOP_GLERROR;
|
||||
|
||||
if (mMappedIndexData)
|
||||
{
|
||||
if (mGLIndices)
|
||||
{
|
||||
glDeleteBuffers(1, &mGLIndices);
|
||||
}
|
||||
|
||||
mGLIndices = gen_buffer();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
|
||||
sGLRenderIndices = mGLIndices;
|
||||
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STATIC_DRAW);
|
||||
}
|
||||
else if (mGLIndices != sGLRenderIndices)
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
|
||||
sGLRenderIndices = mGLIndices;
|
||||
}
|
||||
STOP_GLERROR;
|
||||
#else
|
||||
|
||||
if (!mMappedVertexRegions.empty())
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - vertex");
|
||||
|
||||
if (sGLRenderBuffer != mGLBuffer)
|
||||
else if (mGLBuffer != sGLRenderBuffer)
|
||||
{
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
|
||||
sGLRenderBuffer = mGLBuffer;
|
||||
}
|
||||
STOP_GLERROR;
|
||||
|
||||
U32 start = 0;
|
||||
U32 end = 0;
|
||||
|
||||
std::sort(mMappedVertexRegions.begin(), mMappedVertexRegions.end(), SortMappedRegion());
|
||||
|
||||
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
|
||||
if (mMappedIndexData)
|
||||
{
|
||||
const MappedRegion& region = mMappedVertexRegions[i];
|
||||
if (region.mStart == end + 1)
|
||||
if (mGLIndices)
|
||||
{
|
||||
end = region.mEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData);
|
||||
start = region.mStart;
|
||||
end = region.mEnd;
|
||||
delete_buffers(1, &mGLIndices);
|
||||
}
|
||||
|
||||
mGLIndices = gen_buffer();
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
|
||||
sGLRenderIndices = mGLIndices;
|
||||
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mIndicesSize, mMappedIndexData, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData);
|
||||
mMappedVertexRegions.clear();
|
||||
}
|
||||
|
||||
if (!mMappedIndexRegions.empty())
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - index");
|
||||
|
||||
if (mGLIndices != sGLRenderIndices)
|
||||
else if (mGLIndices != sGLRenderIndices)
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
|
||||
sGLRenderIndices = mGLIndices;
|
||||
}
|
||||
U32 start = 0;
|
||||
U32 end = 0;
|
||||
|
||||
std::sort(mMappedIndexRegions.begin(), mMappedIndexRegions.end(), SortMappedRegion());
|
||||
|
||||
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
|
||||
STOP_GLERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!mMappedVertexRegions.empty())
|
||||
{
|
||||
const MappedRegion& region = mMappedIndexRegions[i];
|
||||
if (region.mStart == end + 1)
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - vertex");
|
||||
|
||||
if (sGLRenderBuffer != mGLBuffer)
|
||||
{
|
||||
end = region.mEnd;
|
||||
glBindBuffer(GL_ARRAY_BUFFER, mGLBuffer);
|
||||
sGLRenderBuffer = mGLBuffer;
|
||||
}
|
||||
else
|
||||
|
||||
U32 start = 0;
|
||||
U32 end = 0;
|
||||
|
||||
std::sort(mMappedVertexRegions.begin(), mMappedVertexRegions.end(), SortMappedRegion());
|
||||
|
||||
for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)
|
||||
{
|
||||
flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData);
|
||||
start = region.mStart;
|
||||
end = region.mEnd;
|
||||
const MappedRegion& region = mMappedVertexRegions[i];
|
||||
if (region.mStart == end + 1)
|
||||
{
|
||||
end = region.mEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData);
|
||||
start = region.mStart;
|
||||
end = region.mEnd;
|
||||
}
|
||||
}
|
||||
|
||||
flush_vbo(GL_ARRAY_BUFFER, start, end, (U8*)mMappedData + start, mMappedData);
|
||||
mMappedVertexRegions.clear();
|
||||
}
|
||||
|
||||
flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData);
|
||||
mMappedIndexRegions.clear();
|
||||
if (!mMappedIndexRegions.empty())
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_VERTEX("unmapBuffer - index");
|
||||
|
||||
if (mGLIndices != sGLRenderIndices)
|
||||
{
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mGLIndices);
|
||||
sGLRenderIndices = mGLIndices;
|
||||
}
|
||||
U32 start = 0;
|
||||
U32 end = 0;
|
||||
|
||||
std::sort(mMappedIndexRegions.begin(), mMappedIndexRegions.end(), SortMappedRegion());
|
||||
|
||||
for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)
|
||||
{
|
||||
const MappedRegion& region = mMappedIndexRegions[i];
|
||||
if (region.mStart == end + 1)
|
||||
{
|
||||
end = region.mEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData);
|
||||
start = region.mStart;
|
||||
end = region.mEnd;
|
||||
}
|
||||
}
|
||||
|
||||
flush_vbo(GL_ELEMENT_ARRAY_BUFFER, start, end, (U8*)mMappedIndexData + start, mMappedIndexData);
|
||||
mMappedIndexRegions.clear();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
@ -1523,12 +1685,13 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider<LLVector4a>& strider, U32 i
|
|||
void LLVertexBuffer::setBuffer()
|
||||
{
|
||||
STOP_GLERROR;
|
||||
#if LL_DARWIN
|
||||
if (!mGLBuffer)
|
||||
{ // OS X doesn't allocate a buffer until we call unmapBuffer
|
||||
return;
|
||||
|
||||
if (mMapped)
|
||||
{
|
||||
LL_WARNS_ONCE() << "Missing call to unmapBuffer or flushBuffers" << LL_ENDL;
|
||||
_unmapBuffer();
|
||||
}
|
||||
#endif
|
||||
|
||||
// no data may be pending
|
||||
llassert(mMappedVertexRegions.empty());
|
||||
llassert(mMappedIndexRegions.empty());
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <set>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#define LL_MAX_VERTEX_ATTRIB_LOCATION 64
|
||||
|
||||
|
|
@ -53,6 +54,41 @@
|
|||
//============================================================================
|
||||
// base class
|
||||
class LLPrivateMemoryPool;
|
||||
class LLVertexBuffer;
|
||||
|
||||
class LLVertexBufferData
|
||||
{
|
||||
public:
|
||||
LLVertexBufferData()
|
||||
: mVB(nullptr)
|
||||
, mMode(0)
|
||||
, mCount(0)
|
||||
, mTexName(0)
|
||||
, mProjection(glm::identity<glm::mat4>())
|
||||
, mModelView(glm::identity<glm::mat4>())
|
||||
, mTexture0(glm::identity<glm::mat4>())
|
||||
{}
|
||||
LLVertexBufferData(LLVertexBuffer* buffer, U8 mode, U32 count, U32 tex_name, const glm::mat4& model_view, const glm::mat4& projection, const glm::mat4& texture0)
|
||||
: mVB(buffer)
|
||||
, mMode(mode)
|
||||
, mCount(count)
|
||||
, mTexName(tex_name)
|
||||
, mProjection(model_view)
|
||||
, mModelView(projection)
|
||||
, mTexture0(texture0)
|
||||
{}
|
||||
void drawWithMatrix();
|
||||
void draw();
|
||||
LLPointer<LLVertexBuffer> mVB;
|
||||
U8 mMode;
|
||||
U32 mCount;
|
||||
U32 mTexName;
|
||||
glm::mat4 mProjection;
|
||||
glm::mat4 mModelView;
|
||||
glm::mat4 mTexture0;
|
||||
};
|
||||
typedef std::list<LLVertexBufferData> buffer_data_list_t;
|
||||
|
||||
class LLVertexBuffer final : public LLRefCount
|
||||
{
|
||||
public:
|
||||
|
|
@ -89,6 +125,9 @@ public:
|
|||
// indexed by the following enum
|
||||
static U32 calcOffsets(const U32& typemask, U32* offsets, U32 num_vertices);
|
||||
|
||||
// flush any pending mapped buffers
|
||||
static void flushBuffers();
|
||||
|
||||
//WARNING -- when updating these enums you MUST
|
||||
// 1 - update LLVertexBuffer::sTypeSize
|
||||
// 2 - update LLVertexBuffer::vb_type_name
|
||||
|
|
@ -159,6 +198,8 @@ public:
|
|||
// map for data access (see also getFooStrider below)
|
||||
U8* mapVertexBuffer(AttributeType type, U32 index, S32 count = -1);
|
||||
U8* mapIndexBuffer(U32 index, S32 count = -1);
|
||||
|
||||
// synonym for flushBuffers
|
||||
void unmapBuffer();
|
||||
|
||||
// set for rendering
|
||||
|
|
@ -285,6 +326,13 @@ private:
|
|||
|
||||
bool allocateBuffer(S32 nverts, S32 nindices, bool create) { return allocateBuffer(nverts, nindices); }
|
||||
|
||||
// actually unmap buffer
|
||||
void _unmapBuffer();
|
||||
|
||||
// add to set of mapped buffers
|
||||
void _mapBuffer();
|
||||
bool mMapped = false;
|
||||
|
||||
public:
|
||||
|
||||
static U64 getBytesAllocated();
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#define LLBADGE_CPP
|
||||
#include "llbadge.h"
|
||||
|
||||
#include "llfontgl.h"
|
||||
#include "llfontvertexbuffer.h"
|
||||
#include "llscrollcontainer.h"
|
||||
#include "lluictrlfactory.h"
|
||||
|
||||
|
|
@ -202,29 +204,17 @@ void renderBadgeBackground(F32 centerX, F32 centerY, F32 width, F32 height, cons
|
|||
(F32)ll_round(x) + width,
|
||||
(F32)ll_round(y) + height);
|
||||
|
||||
LLVector3 vertices[4];
|
||||
// <FS:Ansariel> Remove QUADS rendering mode
|
||||
//vertices[0] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f);
|
||||
//vertices[1] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f);
|
||||
//vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f);
|
||||
//vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f);
|
||||
//
|
||||
//gGL.begin(LLRender::QUADS);
|
||||
//{
|
||||
// gGL.vertexBatchPreTransformed(vertices, 4);
|
||||
//}
|
||||
//gGL.end();
|
||||
vertices[0] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 1.0f);
|
||||
vertices[1] = LLVector3(screen_rect.mRight, screen_rect.mTop, 1.0f);
|
||||
vertices[2] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 1.0f);
|
||||
vertices[3] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 1.0f);
|
||||
LLVector4a vertices[4];
|
||||
vertices[0].set(screen_rect.mLeft, screen_rect.mTop, 1.0f);
|
||||
vertices[1].set(screen_rect.mRight, screen_rect.mTop, 1.0f);
|
||||
vertices[2].set(screen_rect.mLeft, screen_rect.mBottom, 1.0f);
|
||||
vertices[3].set(screen_rect.mRight, screen_rect.mBottom, 1.0f);
|
||||
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
{
|
||||
gGL.vertexBatchPreTransformed(vertices, 4);
|
||||
}
|
||||
gGL.end();
|
||||
// </FS:Ansariel>
|
||||
|
||||
gGL.popUIMatrix();
|
||||
}
|
||||
|
|
@ -363,17 +353,17 @@ void LLBadge::draw()
|
|||
//
|
||||
// Draw the label
|
||||
//
|
||||
|
||||
mGLFont->render(mLabel.getWString(),
|
||||
badge_label_begin_offset,
|
||||
badge_center_x + mLabelOffsetHoriz,
|
||||
badge_center_y + mLabelOffsetVert,
|
||||
mLabelColor % alpha,
|
||||
LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position
|
||||
LLFontGL::NORMAL, // normal text (not bold, italics, etc.)
|
||||
LLFontGL::DROP_SHADOW_SOFT,
|
||||
badge_char_length, badge_pixel_length,
|
||||
right_position_out, do_not_use_ellipses);
|
||||
mFontBuffer.render(mGLFont,
|
||||
mLabel.getWString(),
|
||||
badge_label_begin_offset,
|
||||
badge_center_x + mLabelOffsetHoriz,
|
||||
badge_center_y + mLabelOffsetVert,
|
||||
mLabelColor % alpha,
|
||||
LLFontGL::HCENTER, LLFontGL::VCENTER, // centered around the position
|
||||
LLFontGL::NORMAL, // normal text (not bold, italics, etc.)
|
||||
LLFontGL::DROP_SHADOW_SOFT,
|
||||
badge_char_length, badge_pixel_length,
|
||||
right_position_out, do_not_use_ellipses);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,12 +34,14 @@
|
|||
#include "llstring.h"
|
||||
#include "lluiimage.h"
|
||||
#include "llview.h"
|
||||
#include "llfontvertexbuffer.h"
|
||||
|
||||
//
|
||||
// Declarations
|
||||
//
|
||||
|
||||
class LLFontGL;
|
||||
class LLFontVertexBuffer;
|
||||
class LLScrollContainer;
|
||||
class LLUICtrlFactory;
|
||||
|
||||
|
|
@ -144,6 +146,7 @@ private:
|
|||
LLUIColor mBorderColor;
|
||||
|
||||
const LLFontGL* mGLFont;
|
||||
LLFontVertexBuffer mFontBuffer;
|
||||
|
||||
LLPointer< LLUIImage > mImage;
|
||||
LLUIColor mImageColor;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@
|
|||
#include "llfloater.h"
|
||||
#include "llfloaterreg.h"
|
||||
#include "llfocusmgr.h"
|
||||
#include "llfontgl.h"
|
||||
#include "llfontvertexbuffer.h"
|
||||
#include "llwindow.h"
|
||||
#include "llnotificationsutil.h"
|
||||
#include "llrender.h"
|
||||
|
|
@ -127,11 +129,10 @@ LLButton::Params::Params()
|
|||
|
||||
|
||||
LLButton::LLButton(const LLButton::Params& p)
|
||||
: LLUICtrl(p),
|
||||
: LLUICtrl(p),
|
||||
LLBadgeOwner(getHandle()),
|
||||
mMouseDownFrame(0),
|
||||
mMouseHeldDownCount(0),
|
||||
mBorderEnabled( false ),
|
||||
mFlashing( false ),
|
||||
mCurGlowStrength(0.f),
|
||||
mNeedsHighlight(false),
|
||||
|
|
@ -349,6 +350,30 @@ void LLButton::onCommit()
|
|||
LLUICtrl::onCommit();
|
||||
}
|
||||
|
||||
void LLButton::setUnselectedLabelColor(const LLUIColor& c)
|
||||
{
|
||||
mUnselectedLabelColor = c;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setSelectedLabelColor(const LLUIColor& c)
|
||||
{
|
||||
mSelectedLabelColor = c;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setUseEllipses(bool use_ellipses)
|
||||
{
|
||||
mUseEllipses = use_ellipses;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setUseFontColor(bool use_font_color)
|
||||
{
|
||||
mUseFontColor = use_font_color;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
boost::signals2::connection LLButton::setClickedCallback(const CommitCallbackParam& cb)
|
||||
{
|
||||
return setClickedCallback(initCommitCallback(cb));
|
||||
|
|
@ -453,6 +478,18 @@ bool LLButton::postBuild()
|
|||
return LLUICtrl::postBuild();
|
||||
}
|
||||
|
||||
void LLButton::onVisibilityChange(bool new_visibility)
|
||||
{
|
||||
mFontBuffer.reset();
|
||||
return LLUICtrl::onVisibilityChange(new_visibility);
|
||||
}
|
||||
|
||||
void LLButton::dirtyRect()
|
||||
{
|
||||
LLUICtrl::dirtyRect();
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
bool LLButton::handleUnicodeCharHere(llwchar uni_char)
|
||||
{
|
||||
bool handled = false;
|
||||
|
|
@ -639,19 +676,25 @@ void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)
|
|||
{
|
||||
LLUICtrl::onMouseLeave(x, y, mask);
|
||||
|
||||
mNeedsHighlight = false;
|
||||
setHighlight(false);
|
||||
}
|
||||
|
||||
void LLButton::setHighlight(bool b)
|
||||
{
|
||||
mNeedsHighlight = b;
|
||||
if (mNeedsHighlight != b)
|
||||
{
|
||||
mNeedsHighlight = b;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool LLButton::handleHover(S32 x, S32 y, MASK mask)
|
||||
{
|
||||
if (isInEnabledChain()
|
||||
&& (!gFocusMgr.getMouseCapture() || gFocusMgr.getMouseCapture() == this))
|
||||
mNeedsHighlight = true;
|
||||
{
|
||||
setHighlight(true);
|
||||
}
|
||||
|
||||
if (!childrenHandleHover(x, y, mask))
|
||||
{
|
||||
|
|
@ -1020,7 +1063,7 @@ void LLButton::draw()
|
|||
// LLFontGL::render expects S32 max_chars variable but process in a separate way -1 value.
|
||||
// Due to U32_MAX is equal to S32 -1 value I have rest this value for non-ellipses mode.
|
||||
// Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars.
|
||||
mLastDrawCharsCount = mGLFont->render(label, 0,
|
||||
mLastDrawCharsCount = mFontBuffer.render(mGLFont, label, 0,
|
||||
(F32)x,
|
||||
(F32)(getRect().getHeight() / 2 + mBottomVPad),
|
||||
label_color % alpha,
|
||||
|
|
@ -1071,6 +1114,7 @@ void LLButton::setToggleState(bool b)
|
|||
setFlashing(false); // stop flash state whenever the selected/unselected state if reset
|
||||
// Unselected label assignments
|
||||
autoResize();
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1100,11 +1144,13 @@ bool LLButton::toggleState()
|
|||
void LLButton::setLabel( const std::string& label )
|
||||
{
|
||||
mUnselectedLabel = mSelectedLabel = label;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setLabel( const LLUIString& label )
|
||||
{
|
||||
mUnselectedLabel = mSelectedLabel = label;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setLabel( const LLStringExplicit& label )
|
||||
|
|
@ -1118,17 +1164,32 @@ bool LLButton::setLabelArg( const std::string& key, const LLStringExplicit& text
|
|||
{
|
||||
mUnselectedLabel.setArg(key, text);
|
||||
mSelectedLabel.setArg(key, text);
|
||||
mFontBuffer.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLButton::setLabelUnselected( const LLStringExplicit& label )
|
||||
{
|
||||
mUnselectedLabel = label;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setLabelSelected( const LLStringExplicit& label )
|
||||
{
|
||||
mSelectedLabel = label;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setDisabledLabelColor(const LLUIColor& c)
|
||||
{
|
||||
mDisabledLabelColor = c;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setFont(const LLFontGL* font)
|
||||
{
|
||||
mGLFont = (font ? font : LLFontGL::getFontSansSerif());
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
bool LLButton::labelIsTruncated() const
|
||||
|
|
@ -1141,6 +1202,12 @@ const LLUIString& LLButton::getCurrentLabel() const
|
|||
return getToggleState() ? mSelectedLabel : mUnselectedLabel;
|
||||
}
|
||||
|
||||
void LLButton::setDropShadowedText(bool b)
|
||||
{
|
||||
mDropShadowedText = b;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setImageUnselected(LLPointer<LLUIImage> image)
|
||||
{
|
||||
mImageUnselected = image;
|
||||
|
|
@ -1224,6 +1291,7 @@ void LLButton::setImageDisabledSelected(LLPointer<LLUIImage> image)
|
|||
mImageDisabledSelected = image;
|
||||
mDisabledImageColor = mImageColor;
|
||||
mFadeWhenDisabled = true;
|
||||
mFontBuffer.reset();
|
||||
}
|
||||
|
||||
void LLButton::setImagePressed(LLPointer<LLUIImage> image)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue