diff --git a/CLAUDE.md b/CLAUDE.md
index 65fad33b11..d0320559cc 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Project Overview
-Alchemy Viewer is a third-party client for Second Life, forked from the official Linden Lab viewer. It is a large C++ desktop application (~750 source files in the main viewer module alone) using OpenGL for rendering, with builds targeting Windows, macOS, and Linux.
+Vayu Viewer is a third-party client for Second Life, forked from Alchemy Viewer, which is itself forked from the official Linden Lab viewer. It is a large C++ desktop application (~750 source files in the main viewer module alone) using OpenGL for rendering, with builds targeting Windows, macOS, and Linux.
## Build System
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 80a9ea89c0..a8033eacd6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,6 +1,6 @@
# Contributor guidelines
-Thanks for your interest in contributing to Alchemy Viewer! This document
+Thanks for your interest in contributing to Vayu Viewer! This document
summarizes some of the most important points for people looking to contribute
to the project especially those looking to provide bug reports and code
changes.
@@ -14,64 +14,57 @@ changes.
- [Importance of Your Feedback](#importance-of-your-feedback)
- [Our Relationship with Linden Lab and Code Inheritance](#our-relationship-with-linden-lab-and-code-inheritance)
- [Reporting Bugs to Linden Lab](#reporting-bugs-to-linden-lab)
- - [Submitting Feedback to Alchemy Viewer](#submitting-feedback-to-alchemy-viewer)
+ - [Submitting Feedback to Vayu Viewer](#submitting-feedback-to-vayu-viewer)
- [Contributing pull requests](#contributing-pull-requests)
## Communication
-Alchemy Viewer has multiple channels for communication. Some of these channels are
-more end-user focused while others are more tailored for developer-to-developer or support.
+Vayu Viewer is a young fork and does not yet have its own community chat.
-- [Our Discord][discord] is the primary community engagement platform for the project.
- This is where we announce our releases, answer questions from the community,
- and provide support to users. This is also a great place for developers to interact
- with the Alchemy users to determine if their feature is interesting to them.
- [Github issues][] provide a means for developers and contributors to organize
- their work and collaborate with other developers. By default most user-facing
- discussions should happen on [the Discord][discord] so that they are
- visible to more people, and can build consensus.
+ their work and collaborate with other developers.
## Reporting Bugs and Requesting Features
### Importance of Your Feedback
-We value your feedback and invite you to help us identify bugs and suggest new features for Alchemy Viewer.
+We value your feedback and invite you to help us identify bugs and suggest new features for Vayu Viewer.
Your input is crucial in shaping the future of our project.
-Your cooperation with these guidelines will help us improve Alchemy Viewer,
-and ensures that Linden Lab can address broader issues within their codebase.
+Your cooperation with these guidelines will help us improve Vayu Viewer,
+and ensures that Linden Lab and the Alchemy Viewer project can address broader issues within their codebases.
### Our Relationship with Linden Lab and Code Inheritance
It's important to note that while we are not affiliated with or endorsed by Linden Lab,
-the creators of Second Life, our viewer incorporates a significant amount of code from them.
+the creators of Second Life, or by the Alchemy Viewer project from which we are forked,
+our viewer incorporates a significant amount of code from both of them.
-This shared codebase means some issues may originate from the Linden Lab viewer,
-and addressing these effectively benefits both viewers.
+This shared codebase means some issues may originate upstream, in either the Linden Lab
+viewer or Alchemy Viewer, and addressing these effectively benefits all three viewers.
### Reporting Bugs to Linden Lab
If you encounter defects or unwanted behavior that are inherited from the official Second Life viewer,
please report these issues directly to Linden Lab.
-Before submitting a bug report to Alchemy Viewer, kindly check the [official Second Life viewer][lindenviewer]
+Before submitting a bug report to Vayu Viewer, kindly check the [official Second Life viewer][lindenviewer]
to determine if the defect exists there as well.
Reporting it to Linden Lab, if it hasn't already been reported, will ensure they are aware of the issue.
-If you are unsure, you are encouraged to share your findings with an Alchemy team member to receive guidance.
Linden Lab's page for submitting bug reports can be found on [feedback.secondlife.com/bug-reports][lindenbugs].
-### Submitting Feedback to Alchemy Viewer
+### Submitting Feedback to Vayu Viewer
-If the defect is unique to Alchemy Viewer or pertains to features exclusive to our viewer, please proceed to submit your bug report to us on Github. Provide as much detail as possible, including steps to reproduce the issue, logs, and screenshots if available. This information will help us diagnose and address the problem more efficiently.
+If the defect is unique to Vayu Viewer or pertains to features exclusive to our viewer, please proceed to submit your bug report to us on Github. Provide as much detail as possible, including steps to reproduce the issue, logs, and screenshots if available. This information will help us diagnose and address the problem more efficiently.
## Contributing pull requests
If you wish to contribute a new pull request, please ensure that:
- You talk to other developers about how best to implement the work.
-- The functionality is desired. Be sure to talk to users and members of the Alchemy
- team to ensure the work is a good idea and will be accepted.
+- The functionality is desired. Be sure to talk to users and maintainers of Vayu
+ Viewer to ensure the work is a good idea and will be accepted.
- The work is high quality and the PR follows [PR etiquette][]
- You have tested the work locally
@@ -79,7 +72,6 @@ The [Git Style Guide](https://github.com/agis/git-style-guide) is also a good
reference for best git practices.
[PR etiquette]: https://gist.github.com/mikepea/863f63d6e37281e329f8
-[Github issues]: https://github.com/AlchemyViewer/Alchemy/issues
-[discord]: https://discordapp.com/invite/KugCgs6
+[Github issues]: https://github.com/Shadowolf7/Vayu-Viewer/issues
[lindenviewer]: https://releasenotes.secondlife.com/viewer.html
[lindenbugs]: https://feedback.secondlife.com/bug-reports
diff --git a/README.md b/README.md
index 6905874f03..6df6974f3f 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,26 @@
-
-
+
+
-# Alchemy Viewer
+# Vayu Viewer
[](LICENSE)
-[](https://github.com/AlchemyViewer/Alchemy/releases)
-[][discord]
+[](https://github.com/Shadowolf7/Vayu-Viewer/releases)
-[Alchemy Viewer](https://www.alchemyviewer.org) is a third-party client for [Second Life](https://secondlife.com), forked from the official [Linden Lab viewer](https://github.com/secondlife/viewer). We focus on a cohesive, modern experience built on thoughtful defaults — while staying on the bleeding edge of new platform features.
+Vayu Viewer is a third-party client for [Second Life](https://secondlife.com), forked from [Alchemy Viewer](https://www.alchemyviewer.org), which is itself forked from the official [Linden Lab viewer](https://github.com/secondlife/viewer).
## 📥 Download
-Most users install a [pre-built release][releasesgh] for Windows, macOS, or Linux. Release candidates and project viewers are announced on our [Discord server][discord].
+Pre-built releases for Windows, macOS, or Linux are published on the [releases page][releasesgh] once available.
## 🔨 Building from source
-Alchemy uses CMake with vcpkg for dependency management. Platform setup, presets, build options, tests, packaging, and troubleshooting all live in [**doc/BUILD.md**](doc/BUILD.md).
+Vayu Viewer uses CMake with vcpkg for dependency management. Platform setup, presets, build options, tests, packaging, and troubleshooting all live in [**doc/BUILD.md**](doc/BUILD.md).
```
-git clone --recurse-submodules https://github.com/AlchemyViewer/Alchemy.git alchemy
-cd alchemy
+git clone --recurse-submodules https://github.com/Shadowolf7/Vayu-Viewer.git vayu-viewer
+cd vayu-viewer
python3 -m venv .venv && source .venv/bin/activate # Windows: .\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
dotnet tool restore # packaging only
@@ -35,21 +34,19 @@ File bug reports, suggest enhancements, or open a pull request — see [CONTRIBU
## 🙏 Acknowledgements
-Alchemy stands on the work of:
+Vayu Viewer stands on the work of:
+- [Alchemy Viewer](https://www.alchemyviewer.org), the project this is forked from
- [Linden Lab](https://www.lindenlab.com/) and the [Second Life Viewer](https://github.com/secondlife/viewer) contributors
- The many open-source libraries that power the viewer (see [`indra/vcpkg.json`](indra/vcpkg.json))
## 🔗 Resources
-- [Website](https://www.alchemyviewer.org)
- [Downloads][releasesgh]
-- [Issue tracker](https://github.com/AlchemyViewer/Alchemy/issues)
-- [Discord][discord]
+- [Issue tracker](https://github.com/Shadowolf7/Vayu-Viewer/issues)
## 📜 License
-Alchemy is licensed under the [GNU Lesser General Public License v2.1](LICENSE), inherited from the upstream Linden Lab viewer.
+Vayu Viewer is licensed under the [GNU Lesser General Public License v2.1](LICENSE), inherited from the upstream Alchemy Viewer and Linden Lab viewer.
-[releasesgh]: https://github.com/AlchemyViewer/Alchemy/releases
-[discord]: https://discordapp.com/invite/KugCgs6
+[releasesgh]: https://github.com/Shadowolf7/Vayu-Viewer/releases
diff --git a/doc/BUILD.md b/doc/BUILD.md
index 02630c4328..ea6110f4c3 100644
--- a/doc/BUILD.md
+++ b/doc/BUILD.md
@@ -1,6 +1,6 @@
-# Building Alchemy Viewer
+# Building Vayu Viewer
-Everything you need to build Alchemy from source: platform setup, presets, options, tests, packaging, and troubleshooting.
+Everything you need to build Vayu Viewer from source: platform setup, presets, options, tests, packaging, and troubleshooting.
- [Prerequisites](#prerequisites)
- [Platform setup](#platform-setup) — Windows, macOS, Linux
@@ -164,11 +164,11 @@ rustup default stable
## Clone and bootstrap
-Alchemy vendors the [Dullahan](https://github.com/AlchemyViewer/dullahan) CEF wrapper — used by the in-world web media plugin — as a git submodule under `indra/dullahan`. It builds from source as part of the tree, so the submodule must be present before you configure. Clone with `--recurse-submodules`, then set up the Python venv and .NET tools:
+Vayu Viewer vendors the [Dullahan](https://github.com/AlchemyViewer/dullahan) CEF wrapper — used by the in-world web media plugin — as a git submodule under `indra/dullahan`. It builds from source as part of the tree, so the submodule must be present before you configure. Clone with `--recurse-submodules`, then set up the Python venv and .NET tools:
```
-git clone --recurse-submodules https://github.com/AlchemyViewer/Alchemy.git alchemy
-cd alchemy
+git clone --recurse-submodules https://github.com/Shadowolf7/Vayu-Viewer.git vayu-viewer
+cd vayu-viewer
python3 -m venv .venv
# Windows: .\.venv\Scripts\Activate.ps1
# Unix: source .venv/bin/activate
@@ -257,10 +257,10 @@ cmake --build --preset ninja-os-release
```
# Visual Studio
-start .\build-Windows-vs2026-os\Alchemy.slnx
+start .\build-Windows-vs2026-os\Vayu.slnx
# Xcode
-open ./build-Darwin-xcode-os-arm64/Alchemy.xcodeproj
+open ./build-Darwin-xcode-os-arm64/Vayu.xcodeproj
```
> `.slnx` is the newer Visual Studio solution format. Requires VS 2022 17.10+ or VS 2026.
@@ -275,7 +275,7 @@ The viewer executable lands under `build--/newview//`:
| macOS | `build-Darwin-/newview//.app` |
| Linux | `build-Linux-/newview//` |
-`` follows `VIEWER_CHANNEL` (default `Alchemy Test` → `AlchemyTest.exe` / `AlchemyTest.app`).
+`` follows `VIEWER_CHANNEL` (default `Vayu Test` → `VayuTest.exe` / `VayuTest.app`).
## Configuration types
@@ -413,7 +413,7 @@ If the run produces no output for a very long time it usually isn't hung — che
### CMake is too old
-Alchemy requires CMake 3.27+. If your distro ships something older, install a newer version via pip inside your venv:
+Vayu Viewer requires CMake 3.27+. If your distro ships something older, install a newer version via pip inside your venv:
```
pip install --upgrade cmake ninja
@@ -454,7 +454,7 @@ cmake -S indra --preset ninja-os -DGCC_DISABLE_FATAL_WARNINGS=TRUE
cmake -S indra --preset ninja-os -DCLANG_DISABLE_FATAL_WARNINGS=TRUE
```
-### Visual Studio doesn't recognize `Alchemy.slnx`
+### Visual Studio doesn't recognize `Vayu.slnx`
`.slnx` is the newer Visual Studio solution format. Use Visual Studio 2022 17.10+ or Visual Studio 2026, or configure with the `vs2022-os` preset on an older compatible edition.
@@ -472,8 +472,7 @@ Double-check the package list for your distro under [Platform setup → Linux](#
### Still stuck?
-- Ask on the [Discord](https://discordapp.com/invite/KugCgs6).
-- File a build bug at .
+- File a build bug at .
## See also
diff --git a/doc/vayu_logo.png b/doc/vayu_logo.png
new file mode 100644
index 0000000000..fe88e541d5
Binary files /dev/null and b/doc/vayu_logo.png differ
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 08f28b1131..fbcc5fd2a9 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -8,11 +8,11 @@ cmake_minimum_required(VERSION 3.27...4.2 FATAL_ERROR)
include(CMakeDependentOption)
-set(ROOT_PROJECT_NAME "Alchemy" CACHE STRING
- "The root project/makefile/solution name. Defaults to Alchemy.")
+set(ROOT_PROJECT_NAME "Vayu" CACHE STRING
+ "The root project/makefile/solution name. Defaults to Vayu.")
# Set our base channel
-set(VIEWER_CHANNEL "Alchemy Test" CACHE STRING "Viewer Channel Name")
+set(VIEWER_CHANNEL "Vayu Test" CACHE STRING "Viewer Channel Name")
# Default deploy grid
set(GRID agni CACHE STRING "Target Grid")
@@ -42,6 +42,7 @@ option(USE_LTO "Enable Link Time Optimization" OFF)
option(USE_NVAPI "Use NVidia NVAPI library for gpu profile support (Windows Only)" ON)
option(USE_OPENXR "Enable building with OpenXR support (Experimental)" OFF)
option(USE_PRECOMPILED_HEADERS "Enable use of precompiled header directives where supported." ON)
+option(USE_CCACHE "Use ccache to speed up recompilation if it is available" ON)
# Audio Engines
option(USE_FMODSTUDIO "Enable support for the FMOD Studio audio engine" OFF)
@@ -104,7 +105,7 @@ option(USE_SENTRY "Use the Sentry crash reporting system" OFF)
# Default Tracy profiling on for test builds, but off for all others
set(BUILDING_TEST_CHANNEL OFF)
string(TOLOWER "${VIEWER_CHANNEL}" channel_lower)
-if(channel_lower MATCHES "^alchemy test")
+if(channel_lower MATCHES "^vayu test")
set(BUILDING_TEST_CHANNEL ON)
endif()
cmake_dependent_option(USE_TRACY "Enable support for Tracy profiler" ON "BUILDING_TEST_CHANNEL" OFF)
@@ -207,6 +208,23 @@ set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" "${CMAKE_CURRENT_BINAR
# Setup VCPKG toolchains and targets
include(BootstrapVcpkg)
+# Wire up ccache (if present) before project()/enable_language(), since that's
+# when CMake does compiler detection and starts honoring
+# CMAKE__COMPILER_LAUNCHER. Silently a no-op if ccache isn't installed,
+# so this is safe to leave on by default for everyone.
+if(USE_CCACHE)
+ find_program(CCACHE_PROGRAM ccache)
+ if(CCACHE_PROGRAM)
+ message(STATUS "Using ccache: ${CCACHE_PROGRAM}")
+ set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
+ set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
+ if(DARWIN)
+ set(CMAKE_OBJC_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
+ set(CMAKE_OBJCXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
+ endif()
+ endif()
+endif()
+
# Generate base project after setting pre-generation variables
project(${ROOT_PROJECT_NAME})
diff --git a/indra/cmake/FMODSTUDIO.cmake b/indra/cmake/FMODSTUDIO.cmake
index fae726c2f9..5bd8f78248 100644
--- a/indra/cmake/FMODSTUDIO.cmake
+++ b/indra/cmake/FMODSTUDIO.cmake
@@ -25,7 +25,9 @@ if (USE_FMODSTUDIO)
if(WINDOWS)
set(fmod_lib_paths "${FMODSTUDIO_SDK_DIR}/api/core/lib/x64")
elseif(LINUX)
- set(fmod_lib_paths "${FMODSTUDIO_SDK_DIR}/api/core/lib/x64")
+ set(fmod_lib_paths
+ "${FMODSTUDIO_SDK_DIR}/api/core/lib/x86_64"
+ "${FMODSTUDIO_SDK_DIR}/api/core/lib/x64")
endif()
set(fmod_inc_paths "${FMODSTUDIO_SDK_DIR}/api/core/inc")
diff --git a/indra/lib/python/indra/util/llmanifest.py b/indra/lib/python/indra/util/llmanifest.py
index b651fd2f2a..5c83922261 100644
--- a/indra/lib/python/indra/util/llmanifest.py
+++ b/indra/lib/python/indra/util/llmanifest.py
@@ -91,7 +91,7 @@ def get_default_platform(dummy):
}[sys.platform]
DEFAULT_SRCTREE = os.path.dirname(sys.argv[0])
-CHANNEL_VENDOR_BASE = 'Alchemy'
+CHANNEL_VENDOR_BASE = 'Vayu'
RELEASE_CHANNEL = CHANNEL_VENDOR_BASE + ' Release'
BASE_ARGUMENTS=[
@@ -117,7 +117,7 @@ def get_default_platform(dummy):
dict(name='buildtype', description='Build type (i.e. Debug, Release, RelWithDebInfo).', default=None),
dict(name='bundleid',
description="""The macOS Bundle identifier.""",
- default="org.alchemyviewer.viewer"),
+ default="org.vayuviewer.viewer"),
dict(name='channel',
description="""The channel to use for updates, packaging, settings name, etc.""",
default='CHANNEL UNSET'),
diff --git a/indra/llaudio/llaudioengine_fmodstudio.cpp b/indra/llaudio/llaudioengine_fmodstudio.cpp
index bc9109c97b..98bbd5bcf1 100644
--- a/indra/llaudio/llaudioengine_fmodstudio.cpp
+++ b/indra/llaudio/llaudioengine_fmodstudio.cpp
@@ -53,6 +53,17 @@ float LLAudioEngine_FMODSTUDIO::sReverbSendScale = 0.0f;
namespace
{
+ // Reinterpret-casting an LLVector3's float array to FMOD_VECTOR* (as
+ // this file used to do at its set3DAttributes call site) is
+ // type-punning that violates strict aliasing -- GCC flags it as an
+ // error under -Werror=strict-aliasing. FMOD_VECTOR is layout-compatible
+ // (three floats), so building one by value sidesteps the violation.
+ // Mirrors lllistener_fmodstudio.cpp's identical helper.
+ FMOD_VECTOR to_fmod_vector(const LLVector3& v)
+ {
+ return FMOD_VECTOR{ v.mV[0], v.mV[1], v.mV[2] };
+ }
+
// Serialise an FMOD_GUID into the canonical Windows-style
// "{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" form. Used as the stable
// device id in the picker UI / settings; round-trips via simple
@@ -802,7 +813,9 @@ void LLAudioChannelFMODSTUDIO::update3DPosition()
LLVector3 float_pos;
float_pos.setVec(mCurrentSourcep->getPositionGlobal());
- FMOD_RESULT result = mChannelp->set3DAttributes((FMOD_VECTOR*)float_pos.mV, (FMOD_VECTOR*)mCurrentSourcep->getVelocity().mV);
+ FMOD_VECTOR pos = to_fmod_vector(float_pos);
+ FMOD_VECTOR vel = to_fmod_vector(mCurrentSourcep->getVelocity());
+ FMOD_RESULT result = mChannelp->set3DAttributes(&pos, &vel);
Check_FMOD_Error(result, "FMOD::Channel::set3DAttributes");
}
}
@@ -1026,10 +1039,16 @@ FMOD_RESULT F_CALL windCallback(FMOD_DSP_STATE *dsp_state, float *inbuffer, floa
// outbuffer = the buffer passed from the previous DSP unit.
// length = length in samples at this mix time.
- LLWindGen *windgen = nullptr;
FMOD::DSP *thisdsp = (FMOD::DSP *)dsp_state->instance;
- thisdsp->getUserData((void **)&windgen);
+ // Receive as void* and convert the pointer *value* afterward, rather
+ // than handing FMOD a (void**) alias of an LLWindGen<...>* lvalue --
+ // the latter is type-punning that GCC flags under
+ // -Werror=strict-aliasing.
+ void *userdata = nullptr;
+ thisdsp->getUserData(&userdata);
+ LLWindGen *windgen =
+ static_cast*>(userdata);
if (windgen)
{
diff --git a/indra/llaudio/lllistener_fmodstudio.cpp b/indra/llaudio/lllistener_fmodstudio.cpp
index 9f77a3e42e..00a13af90b 100644
--- a/indra/llaudio/lllistener_fmodstudio.cpp
+++ b/indra/llaudio/lllistener_fmodstudio.cpp
@@ -30,6 +30,21 @@
#include "lllistener_fmodstudio.h"
#include
+namespace
+{
+ // Reinterpret-casting an LLVector3's float array to FMOD_VECTOR* and
+ // dereferencing it (as this file used to do at every call site below)
+ // is type-punning that violates strict aliasing -- GCC flags it as an
+ // error under -Werror=strict-aliasing. FMOD_VECTOR is layout-compatible
+ // (three floats), so building one by value sidesteps the aliasing
+ // violation entirely instead of relying on the cast being "safe enough
+ // in practice".
+ FMOD_VECTOR to_fmod_vector(const LLVector3& v)
+ {
+ return FMOD_VECTOR{ v.mV[0], v.mV[1], v.mV[2] };
+ }
+}
+
//-----------------------------------------------------------------------
// constructor
//-----------------------------------------------------------------------
@@ -58,7 +73,10 @@ void LLListener_FMODSTUDIO::translate(LLVector3 offset)
{
LLListener::translate(offset);
- mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, nullptr, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
+ FMOD_VECTOR pos = to_fmod_vector(mPosition);
+ FMOD_VECTOR at = to_fmod_vector(mListenAt);
+ FMOD_VECTOR up = to_fmod_vector(mListenUp);
+ mSystem->set3DListenerAttributes(0, &pos, nullptr, &at, &up);
}
//-----------------------------------------------------------------------
@@ -66,7 +84,10 @@ void LLListener_FMODSTUDIO::setPosition(LLVector3 pos)
{
LLListener::setPosition(pos);
- mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, nullptr, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
+ FMOD_VECTOR fmod_pos = to_fmod_vector(mPosition);
+ FMOD_VECTOR at = to_fmod_vector(mListenAt);
+ FMOD_VECTOR up = to_fmod_vector(mListenUp);
+ mSystem->set3DListenerAttributes(0, &fmod_pos, nullptr, &at, &up);
}
//-----------------------------------------------------------------------
@@ -74,7 +95,10 @@ void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel)
{
LLListener::setVelocity(vel);
- mSystem->set3DListenerAttributes(0, nullptr, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
+ FMOD_VECTOR fmod_vel = to_fmod_vector(mVelocity);
+ FMOD_VECTOR at = to_fmod_vector(mListenAt);
+ FMOD_VECTOR up = to_fmod_vector(mListenUp);
+ mSystem->set3DListenerAttributes(0, nullptr, &fmod_vel, &at, &up);
}
//-----------------------------------------------------------------------
@@ -85,7 +109,9 @@ void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at)
// at = -at; by default Fmod studio is 'left-handed' but we are providing
// flag FMOD_INIT_3D_RIGHTHANDED so no correction are needed
- mSystem->set3DListenerAttributes(0, nullptr, nullptr, (FMOD_VECTOR*)at.mV, (FMOD_VECTOR*)up.mV);
+ FMOD_VECTOR fmod_at = to_fmod_vector(at);
+ FMOD_VECTOR fmod_up = to_fmod_vector(up);
+ mSystem->set3DListenerAttributes(0, nullptr, nullptr, &fmod_at, &fmod_up);
}
//-----------------------------------------------------------------------
@@ -109,8 +135,10 @@ void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor)
if (mRolloffFactor != factor)
{
LLVector3 pos = mPosition - LLVector3(0.f, 0.f, .1f);
- mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, nullptr, nullptr, nullptr);
- mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, nullptr, nullptr, nullptr);
+ FMOD_VECTOR fmod_pos = to_fmod_vector(pos);
+ FMOD_VECTOR fmod_mPosition = to_fmod_vector(mPosition);
+ mSystem->set3DListenerAttributes(0, &fmod_pos, nullptr, nullptr, nullptr);
+ mSystem->set3DListenerAttributes(0, &fmod_mPosition, nullptr, nullptr, nullptr);
}
mRolloffFactor = factor;
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
diff --git a/indra/llcorehttp/_httpinternal.h b/indra/llcorehttp/_httpinternal.h
index 2a191fa550..3761457f8b 100644
--- a/indra/llcorehttp/_httpinternal.h
+++ b/indra/llcorehttp/_httpinternal.h
@@ -157,6 +157,9 @@ constexpr long HTTP_PIPELINING_MAX = 20L;
constexpr bool HTTP_USE_RETRY_AFTER_DEFAULT = true;
constexpr long HTTP_THROTTLE_RATE_DEFAULT = 0L;
+// Content-Encoding auto-decode: on by default, matching historical behavior
+constexpr long HTTP_CONTENT_DECODING_DEFAULT = 1L;
+
// Tuning parameters
// Time worker thread sleeps after a pass through the
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index b3f6cd27be..52d445c87f 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -278,9 +278,12 @@ void HttpOpRequest::visitNotifier(HttpRequest * request)
HttpResponse::TransferStats::ptr_t stats = std::make_shared();
- curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_DOWNLOAD, &stats->mSizeDownload);
+ curl_off_t size_download = 0, speed_download = 0;
+ curl_easy_getinfo(mCurlHandle, CURLINFO_SIZE_DOWNLOAD_T, &size_download);
curl_easy_getinfo(mCurlHandle, CURLINFO_TOTAL_TIME, &stats->mTotalTime);
- curl_easy_getinfo(mCurlHandle, CURLINFO_SPEED_DOWNLOAD, &stats->mSpeedDownload);
+ curl_easy_getinfo(mCurlHandle, CURLINFO_SPEED_DOWNLOAD_T, &speed_download);
+ stats->mSizeDownload = static_cast(size_download);
+ stats->mSpeedDownload = static_cast(speed_download);
response->setTransferStats(stats);
@@ -519,7 +522,24 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
check_curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1);
check_curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str());
check_curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, getHandle());
- check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
+ // Auto-negotiate and auto-decode Content-Encoding, unless this class
+ // disables it (PO_CONTENT_DECODING=0): some asset servers send a
+ // non-encoding value here (e.g. a MIME type where a transfer coding
+ // was meant), which libcurl treats as a hard failure
+ // (CURLE_BAD_CONTENT_ENCODING) once content decoding is enabled.
+ // CURLOPT_HTTP_CONTENT_DECODING is the actual gate on whether libcurl
+ // inspects/validates the response's Content-Encoding at all -- it
+ // defaults to enabled independently of CURLOPT_ENCODING, so clearing
+ // just CURLOPT_ENCODING (as a prior version of this fix did) left
+ // libcurl still validating the header and still failing. Both are
+ // set explicitly (not just left unset) on every request, not only
+ // when disabling: easy handles are recycled from a pool
+ // (HandleCache::getHandle()) with no reset, so a handle last used by
+ // a decoding-enabled class would otherwise carry that setting forward.
+ check_curl_easy_setopt(mCurlHandle, CURLOPT_HTTP_CONTENT_DECODING,
+ cpolicy.mContentDecoding ? 1L : 0L);
+ check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING,
+ cpolicy.mContentDecoding ? "" : static_cast(NULL));
check_curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
check_curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);
@@ -622,7 +642,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
case HOR_POST:
{
check_curl_easy_setopt(mCurlHandle, CURLOPT_POST, 1);
- check_curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
+ // CURLOPT_ENCODING already set above for all methods.
long data_size(0);
if (mReqBody)
{
diff --git a/indra/llcorehttp/_httppolicyclass.cpp b/indra/llcorehttp/_httppolicyclass.cpp
index 811b004032..6ad255d27a 100644
--- a/indra/llcorehttp/_httppolicyclass.cpp
+++ b/indra/llcorehttp/_httppolicyclass.cpp
@@ -37,7 +37,8 @@ HttpPolicyClass::HttpPolicyClass()
: mConnectionLimit(HTTP_CONNECTION_LIMIT_DEFAULT),
mPerHostConnectionLimit(HTTP_CONNECTION_LIMIT_DEFAULT),
mPipelining(HTTP_PIPELINING_DEFAULT),
- mThrottleRate(HTTP_THROTTLE_RATE_DEFAULT)
+ mThrottleRate(HTTP_THROTTLE_RATE_DEFAULT),
+ mContentDecoding(HTTP_CONTENT_DECODING_DEFAULT)
{}
@@ -53,6 +54,7 @@ HttpPolicyClass & HttpPolicyClass::operator=(const HttpPolicyClass & other)
mPerHostConnectionLimit = other.mPerHostConnectionLimit;
mPipelining = other.mPipelining;
mThrottleRate = other.mThrottleRate;
+ mContentDecoding = other.mContentDecoding;
}
return *this;
}
@@ -62,7 +64,8 @@ HttpPolicyClass::HttpPolicyClass(const HttpPolicyClass & other)
: mConnectionLimit(other.mConnectionLimit),
mPerHostConnectionLimit(other.mPerHostConnectionLimit),
mPipelining(other.mPipelining),
- mThrottleRate(other.mThrottleRate)
+ mThrottleRate(other.mThrottleRate),
+ mContentDecoding(other.mContentDecoding)
{}
@@ -86,6 +89,10 @@ HttpStatus HttpPolicyClass::set(HttpRequest::EPolicyOption opt, long value)
mThrottleRate = llclamp(value, 0L, 1000000L);
break;
+ case HttpRequest::PO_CONTENT_DECODING:
+ mContentDecoding = value;
+ break;
+
default:
return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);
}
@@ -114,6 +121,10 @@ HttpStatus HttpPolicyClass::get(HttpRequest::EPolicyOption opt, long * value) co
*value = mThrottleRate;
break;
+ case HttpRequest::PO_CONTENT_DECODING:
+ *value = mContentDecoding;
+ break;
+
default:
return HttpStatus(HttpStatus::LLCORE, HE_INVALID_ARG);
}
diff --git a/indra/llcorehttp/_httppolicyclass.h b/indra/llcorehttp/_httppolicyclass.h
index 5bf0fa1fa7..ce281835db 100644
--- a/indra/llcorehttp/_httppolicyclass.h
+++ b/indra/llcorehttp/_httppolicyclass.h
@@ -64,6 +64,7 @@ class HttpPolicyClass
long mPerHostConnectionLimit;
long mPipelining;
long mThrottleRate;
+ long mContentDecoding;
}; // end class HttpPolicyClass
} // end namespace LLCore
diff --git a/indra/llcorehttp/_httpservice.cpp b/indra/llcorehttp/_httpservice.cpp
index e14a533479..6ed96c41de 100644
--- a/indra/llcorehttp/_httpservice.cpp
+++ b/indra/llcorehttp/_httpservice.cpp
@@ -62,7 +62,8 @@ const HttpService::OptionDescriptor HttpService::sOptionDesc[] =
{ true, true, true, false, false }, // PO_TRACE
{ true, true, false, true, false }, // PO_ENABLE_PIPELINING
{ true, true, false, true, false }, // PO_THROTTLE_RATE
- { false, false, true, false, true } // PO_SSL_VERIFY_CALLBACK
+ { false, false, true, false, true }, // PO_SSL_VERIFY_CALLBACK
+ { true, true, false, true, false } // PO_CONTENT_DECODING
};
HttpService * HttpService::sInstance(NULL);
volatile HttpService::EState HttpService::sState(NOT_INITIALIZED);
diff --git a/indra/llcorehttp/httprequest.h b/indra/llcorehttp/httprequest.h
index f7516f127a..431f95f902 100644
--- a/indra/llcorehttp/httprequest.h
+++ b/indra/llcorehttp/httprequest.h
@@ -232,6 +232,22 @@ class HttpRequest
/// Global only
PO_SSL_VERIFY_CALLBACK,
+ /// Long value controlling whether libcurl is asked to
+ /// negotiate and auto-decode HTTP Content-Encoding for this
+ /// class (non-zero, the default) or left entirely alone
+ /// (zero). When left alone, libcurl neither advertises
+ /// Accept-Encoding nor inspects/validates any Content-Encoding
+ /// the server sends back -- the payload is delivered as-is.
+ ///
+ /// Use zero for classes whose servers are known to send a
+ /// non-encoding value in Content-Encoding (e.g. a MIME type
+ /// where a transfer coding was meant): libcurl treats an
+ /// unrecognized value as a hard transfer failure
+ /// (CURLE_BAD_CONTENT_ENCODING) when decoding is requested.
+ ///
+ /// Per-class only
+ PO_CONTENT_DECODING,
+
PO_LAST // Always at end
};
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 9b883322ba..4b9896d40f 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -1647,6 +1647,12 @@ void LLGLManager::initExtensions()
mHasAnisotropic = mGLExtensions.contains("GL_EXT_texture_filter_anisotropic");
}
+ mHasBPTCTextureCompression = mGLVersion >= 4.19f;
+ if (!mHasBPTCTextureCompression)
+ {
+ mHasBPTCTextureCompression = mGLExtensions.contains("GL_ARB_texture_compression_bptc");
+ }
+
mHasNVXGpuMemoryInfo = mGLExtensions.contains("GL_NVX_gpu_memory_info");
mHasATIMemInfo = mGLExtensions.contains("GL_ATI_meminfo"); //Basic AMD method, also see mHasAMDAssociations
mHasEXTMemoryObject = mGLExtensions.contains("GL_EXT_memory_object");
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index cbf440ebe4..8635c011d6 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -100,6 +100,7 @@ class LLGLManager
bool mHasDebugOutput = false;
bool mHasTransformFeedback = false;
bool mHasAnisotropic = false;
+ bool mHasBPTCTextureCompression = false;
// Vendor-specific extensions
bool mHasAMDAssociations = false;
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 0ea1bd1c8a..61d71ebcbb 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -356,6 +356,9 @@ S32 LLImageGL::dataFormatBits(S32 dataformat)
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 8;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 8;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 8;
+ // BC7/BPTC: fixed 16 bytes per 4x4 block, same 8 bits/pixel rate as DXT3/DXT5
+ case GL_COMPRESSED_RGBA_BPTC_UNORM: return 8;
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: return 8;
case GL_LUMINANCE: return 8;
case GL_LUMINANCE8: return 8;
case GL_ALPHA: return 8;
@@ -408,6 +411,10 @@ S64 LLImageGL::dataFormatBytes(S32 dataformat, S32 width, S32 height)
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+ // All 4x4-block formats: a texture smaller than one block still
+ // consumes a full block's worth of storage.
if (width < 4) width = 4;
if (height < 4) height = 4;
break;
@@ -447,6 +454,10 @@ S64 LLImageGL::dataFormatVRAMBytes(S32 dataformat, S32 width, S32 height)
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+ case GL_COMPRESSED_RGBA_BPTC_UNORM:
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
+ // All 4x4-block formats: a texture smaller than one block still
+ // consumes a full block's worth of storage.
if (width < 4) width = 4;
if (height < 4) height = 4;
break;
@@ -469,6 +480,8 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat)
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: return 4;
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return 4;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: return 4;
+ case GL_COMPRESSED_RGBA_BPTC_UNORM: return 4;
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: return 4;
case GL_LUMINANCE: return 1;
case GL_ALPHA: return 1;
case GL_RED: return 1;
@@ -1246,6 +1259,20 @@ bool LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
dump();
LL_ERRS() << "setSubImage called with mipmapped image (not supported)" << LL_ENDL;
}
+ if (isCompressed() || willCompressOnUpload())
+ {
+ // glTexSubImage2D is illegal on a compressed internal format --
+ // GL requires glCompressedTexSubImage2D instead, and for the
+ // generic driver-chosen compression path (willCompressOnUpload)
+ // there isn't even a way to implement that: the driver encodes
+ // the whole image opaquely on upload, and there's no API to ask
+ // it to compress just this sub-rectangle and splice it in. A
+ // real fix only exists for source data compressed via a format
+ // we control the encoder for. Until then, refuse rather than
+ // issue a GL call that silently corrupts or no-ops the update.
+ dump();
+ LL_ERRS() << "setSubImage called with a compressed (or to-be-compressed) image (not supported)" << LL_ENDL;
+ }
llassert_always(mCurrentDiscardLevel == 0);
llassert_always(x_pos >= 0 && y_pos >= 0);
@@ -1293,7 +1320,7 @@ bool LLImageGL::setSubImage(const U8* datap, S32 data_width, S32 data_height, S3
if (!res) LL_ERRS() << "LLImageGL::setSubImage(): bindTexture failed" << LL_ENDL;
stop_glerror();
- const bool use_sub_image = should_stagger_image_set(isCompressed());
+ const bool use_sub_image = should_stagger_image_set(isCompressed() || willCompressOnUpload());
if (!use_sub_image)
{
// *TODO: Why does this work here, in setSubImage, but not in
@@ -1334,6 +1361,14 @@ bool LLImageGL::setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S3
// Copy sub image from frame buffer
bool LLImageGL::setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height)
{
+ if (isCompressed() || willCompressOnUpload())
+ {
+ // Same issue as the setSubImage() guard above: glCopyTexSubImage2D
+ // is illegal on a compressed internal format, for the same reasons.
+ dump();
+ LL_ERRS() << "setSubImageFromFrameBuffer called on a compressed (or to-be-compressed) image (not supported)" << LL_ENDL;
+ }
+
if (gGL.getTexUnit(0)->bind(this, false, true))
{
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, x_pos, y_pos, fb_x, fb_y, width, height);
@@ -1407,6 +1442,69 @@ void LLImageGL::deleteTextures(S32 numTextures, const U32 *textures)
}
}
+// Generic (driver-chosen) GPU compression only applies to a fixed set of
+// uncompressed internal formats -- this is the single source of truth for
+// that set, shared between the swap performed in setManualImage and
+// LLImageGL::willCompressOnUpload()'s prediction of it. Keeping one table
+// here avoids the two silently drifting apart, which is how
+// willCompressOnUpload() (folded into isCompressed() in an earlier version
+// of this fix) missed this compression path entirely: setManualImage's swap
+// is local to that call and never written back to mFormatInternal, so
+// nothing could observe it without duplicating this logic.
+static bool compressed_internal_format(S32 intformat, S32& out_compressed)
+{
+ switch (intformat)
+ {
+ case GL_RED:
+ case GL_R8:
+ out_compressed = GL_COMPRESSED_RED;
+ return true;
+ case GL_RG:
+ case GL_RG8:
+ out_compressed = GL_COMPRESSED_RG;
+ return true;
+ case GL_RGB:
+ case GL_RGB8:
+ // BC7/BPTC has no RGB-only (alpha-less) variant -- only the RGBA
+ // form exists. Promoting an alpha-less source to it is harmless
+ // (same as the pre-existing GL_COMPRESSED_RGB generic case, which
+ // is also driver-chosen and may itself pad an implicit alpha), and
+ // BC7's fixed 16 bytes/4x4 block cost doesn't change either way.
+ out_compressed = gGLManager.mHasBPTCTextureCompression ?
+ GL_COMPRESSED_RGBA_BPTC_UNORM : GL_COMPRESSED_RGB;
+ return true;
+ case GL_SRGB:
+ case GL_SRGB8:
+ out_compressed = gGLManager.mHasBPTCTextureCompression ?
+ GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM : GL_COMPRESSED_SRGB;
+ return true;
+ case GL_RGBA:
+ case GL_RGBA8:
+ out_compressed = gGLManager.mHasBPTCTextureCompression ?
+ GL_COMPRESSED_RGBA_BPTC_UNORM : GL_COMPRESSED_RGBA;
+ return true;
+ case GL_SRGB_ALPHA:
+ case GL_SRGB8_ALPHA8:
+ out_compressed = gGLManager.mHasBPTCTextureCompression ?
+ GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM : GL_COMPRESSED_SRGB_ALPHA;
+ return true;
+ case GL_LUMINANCE:
+ case GL_LUMINANCE8:
+ out_compressed = GL_COMPRESSED_LUMINANCE;
+ return true;
+ case GL_LUMINANCE_ALPHA:
+ case GL_LUMINANCE8_ALPHA8:
+ out_compressed = GL_COMPRESSED_LUMINANCE_ALPHA;
+ return true;
+ case GL_ALPHA:
+ case GL_ALPHA8:
+ out_compressed = GL_COMPRESSED_ALPHA;
+ return true;
+ default:
+ return false;
+ }
+}
+
// static
void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 width, S32 height, U32 pixformat, U32 pixtype, const void* pixels, bool allow_compression, bool has_mips)
{
@@ -1540,47 +1638,21 @@ void LLImageGL::setManualImage(U32 target, S32 miplevel, S32 intformat, S32 widt
const bool compress = LLImageGL::sCompressTextures && allow_compression;
if (compress)
{
- switch (intformat)
+ S32 compressed_format;
+ if (compressed_internal_format(intformat, compressed_format))
+ {
+ // Logged once so RenderCompressTextures can be verified from a
+ // log file instead of guessed at -- which format actually gets
+ // used matters here: BC7 and driver-generic compression are
+ // very different encode-cost profiles on the upload hot path.
+ LL_INFOS_ONCE("Texture") << "Texture compression active, using "
+ << (gGLManager.mHasBPTCTextureCompression ? "BC7/BPTC" : "generic driver-chosen")
+ << " compressed formats" << LL_ENDL;
+ intformat = compressed_format;
+ }
+ else
{
- 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;
- break;
- case GL_SRGB:
- case GL_SRGB8:
- intformat = GL_COMPRESSED_SRGB;
- break;
- case GL_RGBA:
- case GL_RGBA8:
- intformat = GL_COMPRESSED_RGBA;
- break;
- case GL_SRGB_ALPHA:
- case GL_SRGB8_ALPHA8:
- intformat = GL_COMPRESSED_SRGB_ALPHA;
- break;
- case GL_LUMINANCE:
- case GL_LUMINANCE8:
- intformat = GL_COMPRESSED_LUMINANCE;
- break;
- case GL_LUMINANCE_ALPHA:
- case GL_LUMINANCE8_ALPHA8:
- intformat = GL_COMPRESSED_LUMINANCE_ALPHA;
- break;
- case GL_ALPHA:
- case GL_ALPHA8:
- intformat = GL_COMPRESSED_ALPHA;
- break;
- default:
LL_WARNS() << "Could not compress format: " << std::hex << intformat << std::dec << LL_ENDL;
- break;
}
}
@@ -2612,6 +2684,23 @@ bool LLImageGL::isCompressed()
return is_compressed;
}
+bool LLImageGL::willCompressOnUpload()
+{
+ // setManualImage swaps mFormatInternal to a compressed GL_COMPRESSED_*
+ // internal format at upload time when RenderCompressTextures is enabled
+ // -- BC7/BPTC where the driver supports it, generic driver-chosen
+ // compression otherwise -- but that swap is local to the call and never
+ // written back to mFormatInternal here. Predict it via the same table
+ // setManualImage uses. Distinct from isCompressed(), which
+ // answers "is my source data already GPU-compressed blocks" (the S3TC/
+ // DXT-container case) -- conflating the two broke setImage()'s
+ // data_hasmips branch, which uses isCompressed() to decide whether the
+ // incoming bytes are raw pixels or pre-compressed blocks.
+ S32 compressed_format;
+ return LLImageGL::sCompressTextures && mAllowCompression &&
+ compressed_internal_format(mFormatInternal, compressed_format);
+}
+
//----------------------------------------------------------------------------
void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in)
{
diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h
index b819462484..0f8320480e 100644
--- a/indra/llrender/llimagegl.h
+++ b/indra/llrender/llimagegl.h
@@ -190,9 +190,12 @@ class LLImageGL : public LLRefCount
bool createGLTexture(S32 discard_level, const U8* data, bool data_hasmips = false, S32 usename = 0, bool defer_copy = false, LLGLuint* tex_name = nullptr);
void setImage(const LLImageRaw* imageraw);
bool setImage(const U8* data_in, bool data_hasmips = false, S32 usename = 0);
- // *TODO: This function may not work if the textures is compressed (i.e.
- // RenderCompressTextures is 0). Partial image updates do not work on
- // compressed textures.
+ // Partial (non-whole-image) sub-region updates do not work on
+ // compressed textures -- glTexSubImage2D is illegal on a compressed
+ // internal format, and there is no way to implement the generic
+ // driver-compression case at all (see the LL_ERRS in the .cpp).
+ // A whole-image call (x=0, y=0, width/height == getWidth()/getHeight())
+ // redirects to setImage() instead, which does handle compression.
bool setSubImage(const LLImageRaw* imageraw, S32 x_pos, S32 y_pos, S32 width, S32 height, bool force_fast_update = false, LLGLuint use_name = 0, bool skip_unbind = false);
bool setSubImage(const U8* datap, S32 data_width, S32 data_height, S32 x_pos, S32 y_pos, S32 width, S32 height, bool force_fast_update = false, LLGLuint use_name = 0, bool skip_unbind = false);
bool setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height);
@@ -294,6 +297,7 @@ class LLImageGL : public LLRefCount
U32 createPickMask(S32 pWidth, S32 pHeight);
void freePickMask();
bool isCompressed();
+ bool willCompressOnUpload();
LLPointer mSaveData; // used for destroyGL/restoreGL
LL::WorkQueue::weak_t mMainQueue;
diff --git a/indra/media_plugins/cef/CMakeLists.txt b/indra/media_plugins/cef/CMakeLists.txt
index 8864795625..9a9aca3bd2 100644
--- a/indra/media_plugins/cef/CMakeLists.txt
+++ b/indra/media_plugins/cef/CMakeLists.txt
@@ -91,8 +91,8 @@ else ()
set_target_properties(media_plugin_cef PROPERTIES
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/SLPluginCEF-Info.plist.in
- MACOSX_BUNDLE_GUI_IDENTIFIER "org.alchemyviewer.viewer.mediaplugincef"
- XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.alchemyviewer.viewer.mediaplugincef"
+ MACOSX_BUNDLE_GUI_IDENTIFIER "org.vayuviewer.viewer.mediaplugincef"
+ XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "org.vayuviewer.viewer.mediaplugincef"
)
endif ()
endif ()
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 42c23a6fc6..9b6f897660 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -6,7 +6,7 @@ include(CMakeCopyIfDifferent)
include(Velopack)
include(TemplateCheck)
-set(VIEWER_BINARY_NAME "alchemy-bin" CACHE STRING
+set(VIEWER_BINARY_NAME "vayu-bin" CACHE STRING
"The name of the viewer executable to create.")
# Generate version vars header
@@ -56,33 +56,33 @@ endforeach()
set(ICON_PATH "test")
set(VIEWER_MACOSX_PHASE "d")
string(TOLOWER ${VIEWER_CHANNEL} channel_lower)
-if(channel_lower MATCHES "^alchemy release")
+if(channel_lower MATCHES "^vayu release")
set(ICON_PATH "release")
set(VIEWER_MACOSX_PHASE "f")
-elseif(channel_lower MATCHES "^alchemy beta")
+elseif(channel_lower MATCHES "^vayu beta")
set(ICON_PATH "beta")
set(VIEWER_MACOSX_PHASE "b")
-elseif(channel_lower MATCHES "^alchemy project")
+elseif(channel_lower MATCHES "^vayu project")
set(ICON_PATH "project")
set(VIEWER_MACOSX_PHASE "a")
endif()
message(STATUS "Copying icons for ${ICON_PATH}")
-set(BRANDING_SOURCE_DIR "${_VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/share/alchemy-branding")
+set(BRANDING_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/branding")
if (WINDOWS)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
- "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy.ico"
+ "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/vayu.ico"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ll_icon.ico"
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
- "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy_256.BMP"
+ "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/vayu_256.BMP"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ll_icon.BMP"
)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
- "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy_256.BMP"
+ "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/vayu_256.BMP"
"${CMAKE_CURRENT_SOURCE_DIR}/res-sdl/ll_icon.BMP"
)
execute_process(
@@ -98,13 +98,13 @@ if (WINDOWS)
elseif(DARWIN)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
- "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy.icns"
- "${CMAKE_CURRENT_SOURCE_DIR}/alchemy.icns"
+ "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/vayu.icns"
+ "${CMAKE_CURRENT_SOURCE_DIR}/vayu.icns"
)
elseif(LINUX)
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
- "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy_256.BMP"
+ "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/vayu_256.BMP"
"${CMAKE_CURRENT_SOURCE_DIR}/res-sdl/ll_icon.BMP"
)
endif ()
@@ -114,8 +114,8 @@ endif ()
# finds it regardless of which backend the package ends up using.
execute_process(
COMMAND ${CMAKE_COMMAND} -E copy_if_different
- "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/alchemy_256.png"
- "${CMAKE_CURRENT_SOURCE_DIR}/app_settings/alchemy_logo.png"
+ "${BRANDING_SOURCE_DIR}/viewer/icons/${ICON_PATH}/vayu_256.png"
+ "${CMAKE_CURRENT_SOURCE_DIR}/app_settings/vayu_logo.png"
)
if (HAVOK)
@@ -1698,7 +1698,7 @@ if (DARWIN)
# Add resource files to the project.
set(viewer_RESOURCE_FILES
- alchemy.icns
+ vayu.icns
# CMake doesn't seem to support Xcode language variants well just yet
English.lproj/InfoPlist.strings
English.lproj/language.txt
@@ -1710,7 +1710,7 @@ if (DARWIN)
LIST(APPEND viewer_SOURCE_FILES llappviewersdl.cpp)
LIST(APPEND viewer_HEADER_FILES llappviewersdl.h)
LIST(APPEND viewer_RESOURCE_FILES
- Info-AlchemySDL.plist
+ Info-VayuSDL.plist
)
set_source_files_properties(llappviewersdl.cpp PROPERTIES LANGUAGE OBJCXX)
@@ -2049,8 +2049,8 @@ set(VIEWER_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}$
- COMMENT "Generating Alchemy.dSYM")
+ COMMENT "Generating Vayu Viewer.dSYM")
endif()
endif()
@@ -2170,8 +2170,8 @@ elseif(LINUX)
endif()
string(TOLOWER ${VIEWER_CHANNEL} channel_lower)
- if(channel_lower MATCHES "^alchemy release")
- set(OUTPUT_PRODUCT_NAME "AlchemyViewer")
+ if(channel_lower MATCHES "^vayu release")
+ set(OUTPUT_PRODUCT_NAME "VayuViewer")
else()
set(OUTPUT_PRODUCT_NAME "${VIEWER_CHANNEL_ONEWORD}")
endif()
@@ -2181,18 +2181,38 @@ elseif(LINUX)
set(MANIFEST_PACKAGE_OUT_FILE ${product}.tar.xz)
endif()
+# FMOD Studio isn't a vcpkg package (see FMODSTUDIO.cmake) so viewer_manifest.py
+# needs to be told directly where to find its shared libraries to bundle them
+# on Linux. Empty when FMOD Studio isn't in use.
+set(FMOD_MANIFEST_LIB_DIR "")
+if(LINUX AND USE_FMODSTUDIO)
+ set(FMOD_MANIFEST_LIB_DIR "${FMODSTUDIO_SDK_DIR}/api/core/lib/x86_64")
+endif()
+
# Viewer Manifest Copy
+#
+# --actions must include both "copy" and "package": is_packaging_viewer()
+# (which gates whether shaders/fonts/skins/app_settings XML etc. are even
+# considered in construct()) checks for "package" in the actions list, but
+# the actual file-write only happens via copy_action() -- package_action()
+# on its own is a no-op. Passing "copy" alone (as this used to) silently
+# produced a package missing everything gated by is_packaging_viewer(),
+# which doesn't fail the build -- it just makes the result fail to launch.
+# strip_binaries() (invoked by package_finish()) is a no-op for anything
+# other than a Release buildtype, so this doesn't strip debug info from
+# the more common Debug/RelWithDebInfo/OptDebug dev builds.
add_custom_command(
TARGET ${VIEWER_BINARY_NAME} POST_BUILD
COMMAND ${Python3_EXECUTABLE}
ARGS
${CMAKE_CURRENT_SOURCE_DIR}/viewer_manifest.py
- --actions=copy
+ "--actions=\"copy package\""
--arch=${ARCH}
--artwork=${ARTWORK_DIR}
"--bugsplat=${BUGSPLAT_DB}"
"--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
+ "--fmod=${FMOD_MANIFEST_LIB_DIR}"
"--tracy=${USE_TRACY}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=$
@@ -2226,6 +2246,7 @@ if(IS_DIRECTORY ${LOCAL_DIST_DIR})
"--bugsplat=${BUGSPLAT_DB}"
"--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
+ "--fmod=${FMOD_MANIFEST_LIB_DIR}"
"--tracy=${USE_TRACY}"
--build=${CMAKE_CURRENT_BINARY_DIR}
--buildtype=$
@@ -2265,6 +2286,7 @@ if (PACKAGE)
--bundleid=${MACOSX_BUNDLE_GUI_IDENTIFIER}
"--discord=${USE_DISCORD}"
"--openal=${USE_OPENAL}"
+ "--fmod=${FMOD_MANIFEST_LIB_DIR}"
"--tracy=${USE_TRACY}"
"--velopack=${USE_VELOPACK}"
--build=${CMAKE_CURRENT_BINARY_DIR}
diff --git a/indra/newview/Info-AlchemySDL.plist b/indra/newview/Info-VayuSDL.plist
similarity index 94%
rename from indra/newview/Info-AlchemySDL.plist
rename to indra/newview/Info-VayuSDL.plist
index d63ee1ac08..22dc4080c9 100644
--- a/indra/newview/Info-AlchemySDL.plist
+++ b/indra/newview/Info-VayuSDL.plist
@@ -27,7 +27,7 @@
NSHumanReadableCopyright${MACOSX_BUNDLE_COPYRIGHT}NSMicrophoneUsageDescription
- For voice chat, you must grant permission for Alchemy to use the microphone.
+ For voice chat, you must grant permission for Vayu Viewer to use the microphone.CFBundleDocumentTypes
@@ -36,7 +36,7 @@
slurlCFBundleTypeIconFile
- alchemy.icns
+ vayu.icnsCFBundleTypeMIMETypesapplication/x-grid-location-info
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 364e55d56d..484fee3414 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7403,6 +7403,17 @@
Value-1
+ QAModeHttpTrace
+
QAModeTermCode