Merge branch 'release/2024.12-ForeverFPS' of https://github.com/secondlife/viewer
# Conflicts: # indra/llcommon/llqueuedthread.cppmaster
commit
5bf1f485f3
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
needs: setup
|
||||
strategy:
|
||||
matrix:
|
||||
runner: [windows-large, macos-12-large]
|
||||
runner: [windows-large, macos-15-xlarge]
|
||||
configuration: ${{ fromJSON(needs.setup.outputs.configurations) }}
|
||||
runs-on: ${{ matrix.runner }}
|
||||
outputs:
|
||||
|
|
@ -64,7 +64,7 @@ jobs:
|
|||
# autobuild-package.xml.
|
||||
AUTOBUILD_VCS_INFO: "true"
|
||||
AUTOBUILD_VSVER: "170"
|
||||
DEVELOPER_DIR: "/Applications/Xcode_14.0.1.app/Contents/Developer"
|
||||
DEVELOPER_DIR: "/Applications/Xcode_16.1.app/Contents/Developer"
|
||||
# Ensure that Linden viewer builds engage Bugsplat.
|
||||
BUGSPLAT_DB: ${{ needs.setup.outputs.bugsplat_db }}
|
||||
build_coverity: false
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@ else()
|
|||
set( USE_AUTOBUILD_3P ON )
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
endif()
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
include(Variables)
|
||||
include(BuildVersion)
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,11 @@ public:
|
|||
}
|
||||
|
||||
// shadow base-class string() method with UTF-8 aware method
|
||||
std::string string() const { return super::u8string(); }
|
||||
std::string string() const
|
||||
{
|
||||
auto u8 = super::u8string();
|
||||
return std::string(u8.begin(), u8.end());
|
||||
}
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -146,7 +146,7 @@ size_t LLQueuedThread::updateQueue(F32 max_time_ms)
|
|||
// schedule a call to threadedUpdate for every call to updateQueue
|
||||
if (!isQuitting())
|
||||
{
|
||||
mRequestQueue.post([=]()
|
||||
mRequestQueue.post([=, this]()
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_THREAD("qt - update");
|
||||
mIdleThread = false;
|
||||
|
|
@ -497,7 +497,7 @@ void LLQueuedThread::processRequest(LLQueuedThread::QueuedRequest* req)
|
|||
#else
|
||||
using namespace std::chrono_literals;
|
||||
// <FS:Beq> improve retry behaviour
|
||||
// mRequestQueue.post([=]
|
||||
// mRequestQueue.post([=, this]
|
||||
// {
|
||||
// LL_PROFILE_ZONE_NAMED("processRequest - retry");
|
||||
// if (LL::WorkQueue::TimePoint::clock::now() < retry_time)
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ bool LLFontBitmapCache::nextOpenPos(S32 width, S32& pos_x, S32& pos_y, EFontGlyp
|
|||
mBitmapHeight = image_height;
|
||||
|
||||
S32 num_components = getNumComponents(bitmap_type);
|
||||
mImageRawVec[bitmap_idx].push_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components));
|
||||
mImageRawVec[bitmap_idx].emplace_back(new LLImageRaw(mBitmapWidth, mBitmapHeight, num_components));
|
||||
bitmap_num = static_cast<U32>(mImageRawVec[bitmap_idx].size()) - 1;
|
||||
|
||||
LLImageRaw* image_raw = getImageRaw(bitmap_type, bitmap_num);
|
||||
|
|
@ -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, false));
|
||||
mImageGLVec[bitmap_idx].emplace_back(new LLImageGL(image_raw, false, false));
|
||||
LLImageGL* image_gl = getImageGL(bitmap_type, bitmap_num);
|
||||
|
||||
// Start at beginning of the new image.
|
||||
|
|
|
|||
|
|
@ -812,7 +812,7 @@ void LLFontFreetype::renderGlyph(EFontGlyphType bitmap_type, U32 glyph_index, ll
|
|||
if (error == FT_Err_Out_Of_Memory)
|
||||
{
|
||||
LLError::LLUserWarningMsg::showOutOfMemory();
|
||||
LL_ERRS() << "Out of memory loading glyph for character " << wch << LL_ENDL;
|
||||
LL_ERRS() << "Out of memory loading glyph for character " << llformat("U+%xu", U32(wch)) << LL_ENDL;
|
||||
}
|
||||
|
||||
std::string message = llformat(
|
||||
|
|
|
|||
|
|
@ -166,6 +166,7 @@ public:
|
|||
|
||||
void setStyle(U8 style);
|
||||
U8 getStyle() const;
|
||||
S32 getAddedGlyphs() const { return mAddGlyphCount; }
|
||||
|
||||
private:
|
||||
void resetBitmapCache();
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ F32 LLFontGL::sVertDPI = 96.f;
|
|||
F32 LLFontGL::sHorizDPI = 96.f;
|
||||
F32 LLFontGL::sScaleX = 1.f;
|
||||
F32 LLFontGL::sScaleY = 1.f;
|
||||
S32 LLFontGL::sResolutionGeneration = 0;
|
||||
bool LLFontGL::sDisplayFont = true ;
|
||||
std::string LLFontGL::sAppDir;
|
||||
|
||||
|
|
@ -109,6 +110,11 @@ S32 LLFontGL::getNumFaces(const std::string& filename)
|
|||
return mFontFreetype->getNumFaces(filename);
|
||||
}
|
||||
|
||||
S32 LLFontGL::getKnownGlyphCount() const
|
||||
{
|
||||
return mFontFreetype ? mFontFreetype->getAddedGlyphs() : 0;
|
||||
}
|
||||
|
||||
S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,
|
||||
ShadowType shadow, S32 max_chars, F32* right_x, bool use_ellipses, bool use_color) const
|
||||
{
|
||||
|
|
@ -249,6 +255,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
|
||||
const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
|
||||
|
||||
// This looks wrong, value is dynamic.
|
||||
// LLFontBitmapCache::nextOpenPos can alter these values when
|
||||
// new characters get added to cache, which affects whole string.
|
||||
// Todo: Perhaps value should update after symbols were added?
|
||||
F32 inv_width = 1.f / font_bitmap_cache->getBitmapWidth();
|
||||
F32 inv_height = 1.f / font_bitmap_cache->getBitmapHeight();
|
||||
|
||||
|
|
@ -270,6 +280,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
|
||||
const LLFontGlyphInfo* next_glyph = NULL;
|
||||
|
||||
// string can have more than one glyph per char (ex: bold or shadow),
|
||||
// make sure that GLYPH_BATCH_SIZE won't end up with half a symbol.
|
||||
// See drawGlyph.
|
||||
// Ex: with shadows it's 6 glyps per char. 30 fits exactly 5 chars.
|
||||
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];
|
||||
|
|
@ -282,6 +296,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
|
||||
std::pair<EFontGlyphType, S32> bitmap_entry = std::make_pair(EFontGlyphType::Grayscale, -1);
|
||||
S32 glyph_count = 0;
|
||||
llwchar last_char = wstr[begin_offset];
|
||||
for (i = begin_offset; i < begin_offset + length; i++)
|
||||
{
|
||||
llwchar wch = wstr[i];
|
||||
|
|
@ -299,7 +314,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
}
|
||||
// Per-glyph bitmap texture.
|
||||
std::pair<EFontGlyphType, S32> next_bitmap_entry = fgi->mBitmapEntry;
|
||||
if (next_bitmap_entry != bitmap_entry)
|
||||
if (next_bitmap_entry != bitmap_entry || last_char != wch)
|
||||
{
|
||||
// Actually draw the queued glyphs before switching their texture;
|
||||
// otherwise the queued glyphs will be taken from wrong textures.
|
||||
|
|
@ -317,6 +332,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
|
|||
bitmap_entry = next_bitmap_entry;
|
||||
LLImageGL* font_image = font_bitmap_cache->getImageGL(bitmap_entry.first, bitmap_entry.second);
|
||||
gGL.getTexUnit(0)->bind(font_image);
|
||||
|
||||
// For some reason it's not enough to compare by bitmap_entry.
|
||||
// Issue hits emojis, japenese and chinese glyphs, only on first run.
|
||||
// Todo: figure it out, there might be a bug with raw image data.
|
||||
last_char = wch;
|
||||
}
|
||||
|
||||
if ((start_x + scaled_max_pixels) < (cur_x + fgi->mXBearing + fgi->mWidth))
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ public:
|
|||
bool loadFace(const std::string& filename, F32 point_size, const F32 vert_dpi, const F32 horz_dpi, bool is_fallback, S32 face_n);
|
||||
|
||||
S32 getNumFaces(const std::string& filename);
|
||||
S32 getKnownGlyphCount() const;
|
||||
|
||||
S32 render(const LLWString &text, S32 begin_offset,
|
||||
const LLRect& rect,
|
||||
|
|
@ -235,6 +236,7 @@ public:
|
|||
static F32 sHorizDPI;
|
||||
static F32 sScaleX;
|
||||
static F32 sScaleY;
|
||||
static S32 sResolutionGeneration;
|
||||
static bool sDisplayFont ;
|
||||
static std::string sAppDir; // For loading fonts
|
||||
|
||||
|
|
|
|||
|
|
@ -146,7 +146,9 @@ S32 LLFontVertexBuffer::render(
|
|||
|| mLastScaleY != LLFontGL::sScaleY
|
||||
|| mLastVertDPI != LLFontGL::sVertDPI
|
||||
|| mLastHorizDPI != LLFontGL::sHorizDPI
|
||||
|| mLastOrigin != LLFontGL::sCurOrigin)
|
||||
|| mLastOrigin != LLFontGL::sCurOrigin
|
||||
|| mLastResGeneration != LLFontGL::sResolutionGeneration
|
||||
|| mLastFontGlyphCount != fontp->getKnownGlyphCount())
|
||||
{
|
||||
genBuffers(fontp, text, begin_offset, x, y, color, halign, valign,
|
||||
style, shadow, max_chars, max_pixels, right_x, use_ellipses, use_color);
|
||||
|
|
@ -201,6 +203,8 @@ void LLFontVertexBuffer::genBuffers(
|
|||
mLastVertDPI = LLFontGL::sVertDPI;
|
||||
mLastHorizDPI = LLFontGL::sHorizDPI;
|
||||
mLastOrigin = LLFontGL::sCurOrigin;
|
||||
mLastResGeneration = LLFontGL::sResolutionGeneration;
|
||||
mLastFontGlyphCount = fontp->getKnownGlyphCount();
|
||||
|
||||
if (right_x)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -117,8 +117,13 @@ private:
|
|||
F32 mLastScaleY = 1.f;
|
||||
F32 mLastVertDPI = 0.f;
|
||||
F32 mLastHorizDPI = 0.f;
|
||||
S32 mLastResGeneration = 0;
|
||||
LLCoordGL mLastOrigin;
|
||||
|
||||
// Adding new characters to bitmap cache can alter value from getBitmapWidth();
|
||||
// which alters whole string. So rerender when new characters were added to cache.
|
||||
S32 mLastFontGlyphCount = 0;
|
||||
|
||||
static bool sEnableBufferCollection;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ public:
|
|||
bool attachNothing = false;
|
||||
bool hasHeroProbes = false;
|
||||
bool isPBRTerrain = false;
|
||||
bool hasTonemap = false;
|
||||
};
|
||||
|
||||
// ============= Structure for caching shader uniforms ===============
|
||||
|
|
|
|||
|
|
@ -1773,7 +1773,7 @@ void LLImageGL::syncToMainThread(LLGLuint new_tex_name)
|
|||
ref();
|
||||
LL::WorkQueue::postMaybe(
|
||||
mMainQueue,
|
||||
[=]()
|
||||
[=, this]()
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_TEXTURE("cglt - delete callback");
|
||||
syncTexName(new_tex_name);
|
||||
|
|
|
|||
|
|
@ -291,6 +291,14 @@ bool LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)
|
|||
}
|
||||
}
|
||||
|
||||
if (features->hasTonemap)
|
||||
{
|
||||
if (!shader->attachFragmentObject("deferred/tonemapUtilF.glsl"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE order of shader object attaching is VERY IMPORTANT!!!
|
||||
if (features->hasAtmospherics)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -194,6 +194,11 @@ bool LLWindowCallbacks::handleDPIChanged(LLWindow *window, F32 ui_scale_factor,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LLWindowCallbacks::handleDisplayChanged()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLWindowCallbacks::handleWindowDidChangeScreen(LLWindow *window)
|
||||
{
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ public:
|
|||
virtual bool handleTimerEvent(LLWindow *window);
|
||||
virtual bool handleDeviceChange(LLWindow *window);
|
||||
virtual bool handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
|
||||
virtual bool handleDisplayChanged();
|
||||
virtual bool handleWindowDidChangeScreen(LLWindow *window);
|
||||
|
||||
enum DragNDropAction {
|
||||
|
|
|
|||
|
|
@ -1069,7 +1069,7 @@ F32 LLWindowMacOSX::getGamma()
|
|||
&greenGamma,
|
||||
&blueMin,
|
||||
&blueMax,
|
||||
&blueGamma) == noErr)
|
||||
&blueGamma) == kCGErrorSuccess)
|
||||
{
|
||||
// So many choices...
|
||||
// Let's just return the green channel gamma for now.
|
||||
|
|
@ -1120,7 +1120,7 @@ bool LLWindowMacOSX::setGamma(const F32 gamma)
|
|||
&greenGamma,
|
||||
&blueMin,
|
||||
&blueMax,
|
||||
&blueGamma) != noErr)
|
||||
&blueGamma) != kCGErrorSuccess)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1135,7 +1135,7 @@ bool LLWindowMacOSX::setGamma(const F32 gamma)
|
|||
gamma,
|
||||
blueMin,
|
||||
blueMax,
|
||||
gamma) != noErr)
|
||||
gamma) != kCGErrorSuccess)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1187,7 +1187,7 @@ bool LLWindowMacOSX::setCursorPosition(const LLCoordWindow position)
|
|||
newPosition.y = screen_pos.mY;
|
||||
|
||||
CGSetLocalEventsSuppressionInterval(0.0);
|
||||
if(CGWarpMouseCursorPosition(newPosition) == noErr)
|
||||
if(CGWarpMouseCursorPosition(newPosition) == kCGErrorSuccess)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,10 +81,6 @@ const S32 BITS_PER_PIXEL = 32;
|
|||
const S32 MAX_NUM_RESOLUTIONS = 32;
|
||||
const F32 ICON_FLASH_TIME = 0.5f;
|
||||
|
||||
#ifndef WM_DPICHANGED
|
||||
#define WM_DPICHANGED 0x02E0
|
||||
#endif
|
||||
|
||||
#ifndef USER_DEFAULT_SCREEN_DPI
|
||||
#define USER_DEFAULT_SCREEN_DPI 96 // Win7
|
||||
#endif
|
||||
|
|
@ -3005,6 +3001,11 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_
|
|||
return 0;
|
||||
}
|
||||
|
||||
case WM_DISPLAYCHANGE:
|
||||
{
|
||||
WINDOW_IMP_POST(window_imp->mCallbacks->handleDisplayChanged());
|
||||
}
|
||||
|
||||
case WM_SETFOCUS:
|
||||
{
|
||||
LL_PROFILE_ZONE_NAMED_CATEGORY_WIN32("mwp - WM_SETFOCUS");
|
||||
|
|
|
|||
|
|
@ -28,138 +28,11 @@
|
|||
out vec4 frag_color;
|
||||
|
||||
uniform sampler2D diffuseRect;
|
||||
uniform sampler2D exposureMap;
|
||||
|
||||
uniform vec2 screen_res;
|
||||
in vec2 vary_fragcoord;
|
||||
|
||||
vec3 linear_to_srgb(vec3 cl);
|
||||
|
||||
//===============================================================
|
||||
// tone mapping taken from Khronos sample implementation
|
||||
//===============================================================
|
||||
|
||||
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
|
||||
const mat3 ACESInputMat = mat3
|
||||
(
|
||||
0.59719, 0.07600, 0.02840,
|
||||
0.35458, 0.90834, 0.13383,
|
||||
0.04823, 0.01566, 0.83777
|
||||
);
|
||||
|
||||
|
||||
// ODT_SAT => XYZ => D60_2_D65 => sRGB
|
||||
const mat3 ACESOutputMat = mat3
|
||||
(
|
||||
1.60475, -0.10208, -0.00327,
|
||||
-0.53108, 1.10813, -0.07276,
|
||||
-0.07367, -0.00605, 1.07602
|
||||
);
|
||||
|
||||
// ACES tone map (faster approximation)
|
||||
// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
||||
vec3 toneMapACES_Narkowicz(vec3 color)
|
||||
{
|
||||
const float A = 2.51;
|
||||
const float B = 0.03;
|
||||
const float C = 2.43;
|
||||
const float D = 0.59;
|
||||
const float E = 0.14;
|
||||
return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
// ACES filmic tone map approximation
|
||||
// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
|
||||
vec3 RRTAndODTFit(vec3 color)
|
||||
{
|
||||
vec3 a = color * (color + 0.0245786) - 0.000090537;
|
||||
vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081;
|
||||
return a / b;
|
||||
}
|
||||
|
||||
|
||||
// tone mapping
|
||||
vec3 toneMapACES_Hill(vec3 color)
|
||||
{
|
||||
color = ACESInputMat * color;
|
||||
|
||||
// Apply RRT and ODT
|
||||
color = RRTAndODTFit(color);
|
||||
|
||||
color = ACESOutputMat * color;
|
||||
|
||||
// Clamp to [0, 1]
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Khronos Neutral tonemapping
|
||||
// https://github.com/KhronosGroup/ToneMapping/tree/main
|
||||
// Input color is non-negative and resides in the Linear Rec. 709 color space.
|
||||
// Output color is also Linear Rec. 709, but in the [0, 1] range.
|
||||
vec3 PBRNeutralToneMapping( vec3 color )
|
||||
{
|
||||
const float startCompression = 0.8 - 0.04;
|
||||
const float desaturation = 0.15;
|
||||
|
||||
float x = min(color.r, min(color.g, color.b));
|
||||
float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;
|
||||
color -= offset;
|
||||
|
||||
float peak = max(color.r, max(color.g, color.b));
|
||||
if (peak < startCompression) return color;
|
||||
|
||||
const float d = 1. - startCompression;
|
||||
float newPeak = 1. - d * d / (peak + d - startCompression);
|
||||
color *= newPeak / peak;
|
||||
|
||||
float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);
|
||||
return mix(color, newPeak * vec3(1, 1, 1), g);
|
||||
}
|
||||
|
||||
uniform float exposure;
|
||||
uniform float tonemap_mix;
|
||||
uniform int tonemap_type;
|
||||
|
||||
vec3 toneMap(vec3 color)
|
||||
{
|
||||
#ifndef NO_POST
|
||||
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
|
||||
|
||||
color *= exposure * exp_scale;
|
||||
|
||||
vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0));
|
||||
|
||||
switch(tonemap_type)
|
||||
{
|
||||
case 0:
|
||||
color = PBRNeutralToneMapping(color);
|
||||
break;
|
||||
case 1:
|
||||
color = toneMapACES_Hill(color);
|
||||
break;
|
||||
}
|
||||
|
||||
// mix tonemapped and linear here to provide adjustment
|
||||
color = mix(clamped_color, color, tonemap_mix);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
//===============================================================
|
||||
|
||||
void debugExposure(inout vec3 color)
|
||||
{
|
||||
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
|
||||
exp_scale *= 0.5;
|
||||
if (abs(vary_fragcoord.y-exp_scale) < 0.01 && vary_fragcoord.x < 0.1)
|
||||
{
|
||||
color = vec3(1,0,0);
|
||||
}
|
||||
}
|
||||
vec3 toneMap(vec3 color);
|
||||
|
||||
void main()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
/**
|
||||
* @file postDeferredTonemap.glsl
|
||||
*
|
||||
* $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$
|
||||
*/
|
||||
|
||||
/*[EXTRA_CODE_HERE]*/
|
||||
|
||||
uniform sampler2D exposureMap;
|
||||
uniform vec2 screen_res;
|
||||
in vec2 vary_fragcoord;
|
||||
|
||||
//===============================================================
|
||||
// tone mapping taken from Khronos sample implementation
|
||||
//===============================================================
|
||||
|
||||
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
|
||||
const mat3 ACESInputMat = mat3
|
||||
(
|
||||
0.59719, 0.07600, 0.02840,
|
||||
0.35458, 0.90834, 0.13383,
|
||||
0.04823, 0.01566, 0.83777
|
||||
);
|
||||
|
||||
|
||||
// ODT_SAT => XYZ => D60_2_D65 => sRGB
|
||||
const mat3 ACESOutputMat = mat3
|
||||
(
|
||||
1.60475, -0.10208, -0.00327,
|
||||
-0.53108, 1.10813, -0.07276,
|
||||
-0.07367, -0.00605, 1.07602
|
||||
);
|
||||
|
||||
// ACES tone map (faster approximation)
|
||||
// see: https://knarkowicz.wordpress.com/2016/01/06/aces-filmic-tone-mapping-curve/
|
||||
vec3 toneMapACES_Narkowicz(vec3 color)
|
||||
{
|
||||
const float A = 2.51;
|
||||
const float B = 0.03;
|
||||
const float C = 2.43;
|
||||
const float D = 0.59;
|
||||
const float E = 0.14;
|
||||
return clamp((color * (A * color + B)) / (color * (C * color + D) + E), 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
||||
// ACES filmic tone map approximation
|
||||
// see https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl
|
||||
vec3 RRTAndODTFit(vec3 color)
|
||||
{
|
||||
vec3 a = color * (color + 0.0245786) - 0.000090537;
|
||||
vec3 b = color * (0.983729 * color + 0.4329510) + 0.238081;
|
||||
return a / b;
|
||||
}
|
||||
|
||||
|
||||
// tone mapping
|
||||
vec3 toneMapACES_Hill(vec3 color)
|
||||
{
|
||||
color = ACESInputMat * color;
|
||||
|
||||
// Apply RRT and ODT
|
||||
color = RRTAndODTFit(color);
|
||||
|
||||
color = ACESOutputMat * color;
|
||||
|
||||
// Clamp to [0, 1]
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
// Khronos Neutral tonemapping
|
||||
// https://github.com/KhronosGroup/ToneMapping/tree/main
|
||||
// Input color is non-negative and resides in the Linear Rec. 709 color space.
|
||||
// Output color is also Linear Rec. 709, but in the [0, 1] range.
|
||||
vec3 PBRNeutralToneMapping( vec3 color )
|
||||
{
|
||||
const float startCompression = 0.8 - 0.04;
|
||||
const float desaturation = 0.15;
|
||||
|
||||
float x = min(color.r, min(color.g, color.b));
|
||||
float offset = x < 0.08 ? x - 6.25 * x * x : 0.04;
|
||||
color -= offset;
|
||||
|
||||
float peak = max(color.r, max(color.g, color.b));
|
||||
if (peak < startCompression) return color;
|
||||
|
||||
const float d = 1. - startCompression;
|
||||
float newPeak = 1. - d * d / (peak + d - startCompression);
|
||||
color *= newPeak / peak;
|
||||
|
||||
float g = 1. - 1. / (desaturation * (peak - newPeak) + 1.);
|
||||
return mix(color, newPeak * vec3(1, 1, 1), g);
|
||||
}
|
||||
|
||||
uniform float exposure;
|
||||
uniform float tonemap_mix;
|
||||
uniform int tonemap_type;
|
||||
|
||||
vec3 toneMap(vec3 color)
|
||||
{
|
||||
#ifndef NO_POST
|
||||
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
|
||||
|
||||
color *= exposure * exp_scale;
|
||||
|
||||
vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0));
|
||||
|
||||
switch(tonemap_type)
|
||||
{
|
||||
case 0:
|
||||
color = PBRNeutralToneMapping(color);
|
||||
break;
|
||||
case 1:
|
||||
color = toneMapACES_Hill(color);
|
||||
break;
|
||||
}
|
||||
|
||||
// mix tonemapped and linear here to provide adjustment
|
||||
color = mix(clamped_color, color, tonemap_mix);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
vec3 toneMapNoExposure(vec3 color)
|
||||
{
|
||||
#ifndef NO_POST
|
||||
vec3 clamped_color = clamp(color.rgb, vec3(0.0), vec3(1.0));
|
||||
|
||||
switch(tonemap_type)
|
||||
{
|
||||
case 0:
|
||||
color = PBRNeutralToneMapping(color);
|
||||
break;
|
||||
case 1:
|
||||
color = toneMapACES_Hill(color);
|
||||
break;
|
||||
}
|
||||
|
||||
// mix tonemapped and linear here to provide adjustment
|
||||
color = mix(clamped_color, color, tonemap_mix);
|
||||
#endif
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
//===============================================================
|
||||
|
||||
void debugExposure(inout vec3 color)
|
||||
{
|
||||
float exp_scale = texture(exposureMap, vec2(0.5,0.5)).r;
|
||||
exp_scale *= 0.5;
|
||||
if (abs(vary_fragcoord.y-exp_scale) < 0.01 && vary_fragcoord.x < 0.1)
|
||||
{
|
||||
color = vec3(1,0,0);
|
||||
}
|
||||
}
|
||||
|
|
@ -90,21 +90,15 @@ uniform sampler2D depthMap;
|
|||
|
||||
uniform sampler2D exclusionTex;
|
||||
|
||||
uniform float sunAngle;
|
||||
uniform float sunAngle2;
|
||||
uniform int classic_mode;
|
||||
uniform vec3 lightDir;
|
||||
uniform vec3 specular;
|
||||
uniform float lightExp;
|
||||
uniform float blurMultiplier;
|
||||
uniform float refScale;
|
||||
uniform float kd;
|
||||
uniform vec2 screenRes;
|
||||
uniform vec3 normScale;
|
||||
uniform float fresnelScale;
|
||||
uniform float fresnelOffset;
|
||||
uniform float blurMultiplier;
|
||||
uniform vec4 waterFogColor;
|
||||
uniform vec3 waterFogColorLinear;
|
||||
|
||||
|
||||
//bigWave is (refCoord.w, view.w);
|
||||
in vec4 refCoord;
|
||||
|
|
@ -126,6 +120,7 @@ vec3 linear_to_srgb(vec3 col);
|
|||
|
||||
vec3 atmosLighting(vec3 light);
|
||||
vec3 scaleSoftClip(vec3 light);
|
||||
vec3 toneMapNoExposure(vec3 color);
|
||||
|
||||
vec3 vN, vT, vB;
|
||||
|
||||
|
|
@ -171,18 +166,18 @@ void calculateFresnelFactors(out vec3 df3, out vec2 df2, vec3 viewVec, vec3 wave
|
|||
// We calculate the fresnel here.
|
||||
// We do this by getting the dot product for each sets of waves, and applying scale and offset.
|
||||
|
||||
df3 = vec3(
|
||||
df3 = max(vec3(0), vec3(
|
||||
dot(viewVec, wave1),
|
||||
dot(viewVec, (wave2 + wave3) * 0.5),
|
||||
dot(viewVec, wave3)
|
||||
) * fresnelScale + fresnelOffset;
|
||||
) * fresnelScale + fresnelOffset);
|
||||
|
||||
df3 *= df3;
|
||||
|
||||
df2 = vec2(
|
||||
df2 = max(vec2(0), vec2(
|
||||
df3.x + df3.y + df3.z,
|
||||
dot(viewVec, wavef) * fresnelScale + fresnelOffset
|
||||
);
|
||||
));
|
||||
}
|
||||
|
||||
void main()
|
||||
|
|
@ -194,6 +189,7 @@ void main()
|
|||
vB = cross(vN, vT);
|
||||
|
||||
vec3 pos = vary_position.xyz;
|
||||
float linear_depth = 1 / -pos.z;
|
||||
|
||||
float dist = length(pos.xyz);
|
||||
|
||||
|
|
@ -216,6 +212,12 @@ void main()
|
|||
vec3 df3 = vec3(0);
|
||||
vec2 df2 = vec2(0);
|
||||
|
||||
vec3 sunlit;
|
||||
vec3 amblit;
|
||||
vec3 additive;
|
||||
vec3 atten;
|
||||
calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
|
||||
|
||||
calculateFresnelFactors(df3, df2, normalize(view.xyz), wave1, wave2, wave3, wavef);
|
||||
|
||||
vec3 waver = wavef*3;
|
||||
|
|
@ -230,7 +232,7 @@ void main()
|
|||
vec3 norm = transform_normal(normalize(wavef));
|
||||
|
||||
vdu = clamp(vdu, 0, 1);
|
||||
wavef.z *= max(vdu*vdu*vdu, 0.1);
|
||||
//wavef.z *= max(vdu*vdu*vdu, 0.1);
|
||||
|
||||
wavef = normalize(wavef);
|
||||
|
||||
|
|
@ -245,11 +247,6 @@ void main()
|
|||
|
||||
distort2 = clamp(distort2, vec2(0), vec2(0.999));
|
||||
|
||||
vec3 sunlit;
|
||||
vec3 amblit;
|
||||
vec3 additive;
|
||||
vec3 atten;
|
||||
|
||||
float shadow = 1.0f;
|
||||
|
||||
float water_mask = texture(exclusionTex, distort).r;
|
||||
|
|
@ -258,8 +255,6 @@ void main()
|
|||
shadow = sampleDirectionalShadow(pos.xyz, norm.xyz, distort);
|
||||
#endif
|
||||
|
||||
calcAtmosphericVarsLinear(pos.xyz, wavef, vary_light_dir, sunlit, amblit, additive, atten);
|
||||
|
||||
vec3 sunlit_linear = srgb_to_linear(sunlit);
|
||||
float fade = 0;
|
||||
#ifdef TRANSPARENT_WATER
|
||||
|
|
@ -289,8 +284,8 @@ void main()
|
|||
#endif
|
||||
|
||||
float metallic = 1.0;
|
||||
float perceptualRoughness = 0.1;
|
||||
float gloss = 0.95;
|
||||
float perceptualRoughness = blurMultiplier;
|
||||
float gloss = 1 - perceptualRoughness;
|
||||
|
||||
vec3 irradiance = vec3(0);
|
||||
vec3 radiance = vec3(0);
|
||||
|
|
@ -300,7 +295,7 @@ void main()
|
|||
#ifdef WATER_MINIMAL
|
||||
sampleReflectionProbesWater(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, amblit);
|
||||
#elif WATER_MINIMAL_PLUS
|
||||
sampleReflectionProbes(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, 1, false, amblit);
|
||||
sampleReflectionProbes(irradiance, radiance, distort2, pos.xyz, wave_ibl.xyz, gloss, false, amblit);
|
||||
#endif
|
||||
|
||||
vec3 diffuseColor = vec3(0);
|
||||
|
|
@ -323,20 +318,26 @@ void main()
|
|||
pbrPunctual(diffuseColor, specularColor, perceptualRoughness, metallic, normalize(wavef+up*max(dist, 32.0)/32.0*(1.0-vdu)), v, normalize(light_dir), nl, diffPunc, specPunc);
|
||||
|
||||
vec3 punctual = clamp(nl * (diffPunc + specPunc), vec3(0), vec3(10)) * sunlit_linear * shadow;
|
||||
|
||||
radiance *= df2.y;
|
||||
//radiance = toneMapNoExposure(radiance);
|
||||
vec3 color = vec3(0);
|
||||
color = mix(fb.rgb, radiance * df2.y, df2.x * 0.99999) + punctual.rgb;
|
||||
color = mix(fb.rgb, radiance, min(1, df2.x)) + punctual.rgb;
|
||||
|
||||
float water_haze_scale = 4;
|
||||
|
||||
if (classic_mode > 0)
|
||||
water_haze_scale = 1;
|
||||
|
||||
// This looks super janky, but we do this to restore water haze in the distance.
|
||||
// These values were finagled in to try and bring back some of the distant brightening on legacy water. Also works reasonably well on PBR skies such as PBR midday.
|
||||
color += color * min(vec3(4),pow(1 - atten, vec3(1.35)) * 16 * fade);
|
||||
// color = mix(color, additive * water_haze_scale, (1 - atten));
|
||||
|
||||
// We shorten the fade here at the shoreline so it doesn't appear too soft from a distance.
|
||||
fade *= 60;
|
||||
fade = min(1, fade);
|
||||
color = mix(fb.rgb, color, fade);
|
||||
|
||||
float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0.05);
|
||||
float spec = min(max(max(punctual.r, punctual.g), punctual.b), 0);
|
||||
|
||||
frag_color = min(vec4(1),max(vec4(color.rgb, spec * water_mask), vec4(0)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -500,7 +500,7 @@ void GLTFSceneManager::update()
|
|||
LLNewBufferedResourceUploadInfo::uploadFinish_f finish = [this, buffer](LLUUID assetId, LLSD response)
|
||||
{
|
||||
LLAppViewer::instance()->postToMainCoro(
|
||||
[=]()
|
||||
[=, this]()
|
||||
{
|
||||
if (mUploadingAsset)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -107,10 +107,9 @@ private:
|
|||
|
||||
LLAgentPicksInfo::LLAgentPicksInfo()
|
||||
: mAgentPicksObserver(NULL)
|
||||
, mMaxNumberOfPicks(MAX_AVATAR_PICKS)
|
||||
// Disable Pick creation until we get number of Picks from server - in case
|
||||
// avatar has maximum number of Picks.
|
||||
, mNumberOfPicks(mMaxNumberOfPicks)
|
||||
, mNumberOfPicks(S32_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +131,13 @@ void LLAgentPicksInfo::requestNumberOfPicks()
|
|||
mAgentPicksObserver->sendAgentPicksRequest();
|
||||
}
|
||||
|
||||
bool LLAgentPicksInfo::isPickLimitReached()
|
||||
// static
|
||||
S32 LLAgentPicksInfo::getMaxNumberOfPicks()
|
||||
{
|
||||
return LLAgentBenefitsMgr::current().getPicksLimit();
|
||||
}
|
||||
|
||||
bool LLAgentPicksInfo::isPickLimitReached() const
|
||||
{
|
||||
// <FS:Ansariel> Picks premium perks integration
|
||||
//return getNumberOfPicks() >= getMaxNumberOfPicks();
|
||||
|
|
|
|||
|
|
@ -52,17 +52,17 @@ public:
|
|||
/**
|
||||
* Returns number of Picks.
|
||||
*/
|
||||
S32 getNumberOfPicks() { return mNumberOfPicks; }
|
||||
S32 getNumberOfPicks() const { return mNumberOfPicks; }
|
||||
|
||||
/**
|
||||
* Returns maximum number of Picks.
|
||||
*/
|
||||
S32 getMaxNumberOfPicks() { return mMaxNumberOfPicks; }
|
||||
static S32 getMaxNumberOfPicks();
|
||||
|
||||
/**
|
||||
* Returns true if Agent has maximum allowed number of Picks.
|
||||
*/
|
||||
bool isPickLimitReached();
|
||||
bool isPickLimitReached() const;
|
||||
|
||||
/**
|
||||
* After creating or deleting a Pick we can assume operation on server will be
|
||||
|
|
@ -83,15 +83,9 @@ private:
|
|||
*/
|
||||
void setNumberOfPicks(S32 number) { mNumberOfPicks = number; }
|
||||
|
||||
/**
|
||||
* Sets maximum number of Picks.
|
||||
*/
|
||||
void setMaxNumberOfPicks(S32 max_picks) { mMaxNumberOfPicks = max_picks; }
|
||||
|
||||
private:
|
||||
|
||||
LLAgentPicksObserver* mAgentPicksObserver;
|
||||
S32 mMaxNumberOfPicks;
|
||||
S32 mNumberOfPicks;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -189,154 +189,133 @@ void LLDrawPoolWater::renderPostDeferred(S32 pass)
|
|||
light_diffuse *= (1.5f + (6.f * ground_proj_sq));
|
||||
}
|
||||
|
||||
// set up normal maps filtering
|
||||
for (auto norm_map : mWaterNormp)
|
||||
{
|
||||
if (norm_map) norm_map->setFilteringOption(has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT);
|
||||
}
|
||||
LLTexUnit::eTextureFilterOptions filter_mode = has_normal_mips ? LLTexUnit::TFO_ANISOTROPIC : LLTexUnit::TFO_POINT;
|
||||
|
||||
LLColor4 specular(sun_up ? psky->getSunlightColor() : psky->getMoonlightColor());
|
||||
F32 phase_time = (F32) LLFrameTimer::getElapsedSeconds() * 0.5f;
|
||||
LLGLSLShader *shader = nullptr;
|
||||
|
||||
// two passes, first with standard water shader bound, second with edge water shader bound
|
||||
for (int edge = 0; edge < 2; edge++)
|
||||
// One pass, one of two shaders. Void water and region water share state.
|
||||
// There isn't a good reason anymore to really have void water run in a separate pass.
|
||||
// It also just introduced a bunch of weird state consistency stuff that we really don't need.
|
||||
// Not to mention, re-binding the the same shader and state for that shader is kind of wasteful.
|
||||
// - Geenz 2025-02-11
|
||||
// select shader
|
||||
if (underwater)
|
||||
{
|
||||
// select shader
|
||||
if (underwater)
|
||||
{
|
||||
shader = &gUnderWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (edge)
|
||||
{
|
||||
shader = &gWaterEdgeProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = &gWaterProgram;
|
||||
}
|
||||
}
|
||||
|
||||
gPipeline.bindDeferredShader(*shader, nullptr, &gPipeline.mWaterDis);
|
||||
|
||||
//bind normal map
|
||||
S32 bumpTex = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP);
|
||||
S32 bumpTex2 = shader->enableTexture(LLViewerShaderMgr::BUMP_MAP2);
|
||||
|
||||
LLViewerTexture* tex_a = mWaterNormp[0];
|
||||
LLViewerTexture* tex_b = mWaterNormp[1];
|
||||
|
||||
F32 blend_factor = (F32)pwater->getBlendFactor();
|
||||
|
||||
gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
if (tex_a && (!tex_b || (tex_a == tex_b)))
|
||||
{
|
||||
gGL.getTexUnit(bumpTex)->bind(tex_a);
|
||||
blend_factor = 0; // only one tex provided, no blending
|
||||
}
|
||||
else if (tex_b && !tex_a)
|
||||
{
|
||||
gGL.getTexUnit(bumpTex)->bind(tex_b);
|
||||
blend_factor = 0; // only one tex provided, no blending
|
||||
}
|
||||
else if (tex_b != tex_a)
|
||||
{
|
||||
gGL.getTexUnit(bumpTex)->bind(tex_a);
|
||||
gGL.getTexUnit(bumpTex2)->bind(tex_b);
|
||||
}
|
||||
|
||||
shader->bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &gPipeline.mWaterExclusionMask);
|
||||
|
||||
// bind reflection texture from RenderTarget
|
||||
S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);
|
||||
|
||||
F32 screenRes[] = { 1.f / gGLViewport[2], 1.f / gGLViewport[3] };
|
||||
|
||||
shader->uniform2fv(LLShaderMgr::DEFERRED_SCREEN_RES, 1, screenRes);
|
||||
shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
|
||||
|
||||
F32 fog_density = pwater->getModifiedWaterFogDensity(underwater);
|
||||
|
||||
if (screentex > -1)
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, fog_density);
|
||||
gGL.getTexUnit(screentex)->bind(&gPipeline.mWaterDis);
|
||||
}
|
||||
|
||||
if (mShaderLevel == 1)
|
||||
{
|
||||
fog_color.mV[VALPHA] = (F32)(log(fog_density) / log(2));
|
||||
}
|
||||
|
||||
F32 water_height = environment.getWaterHeight();
|
||||
F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2];
|
||||
shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height);
|
||||
shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time);
|
||||
shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
|
||||
|
||||
shader->uniform4fv(LLShaderMgr::SPECULAR_COLOR, 1, specular.mV);
|
||||
shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, fog_color.mV);
|
||||
shader->uniform3fv(LLShaderMgr::WATER_FOGCOLOR_LINEAR, 1, fog_color_linear.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
|
||||
shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp);
|
||||
|
||||
shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
|
||||
shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV);
|
||||
shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale());
|
||||
shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset());
|
||||
shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, pwater->getBlurMultiplier());
|
||||
|
||||
F32 sunAngle = llmax(0.f, light_dir.mV[1]);
|
||||
F32 scaledAngle = 1.f - sunAngle;
|
||||
|
||||
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0);
|
||||
shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle);
|
||||
shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle);
|
||||
shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f * sunAngle);
|
||||
shader->uniform1i(LLShaderMgr::WATER_EDGE_FACTOR, edge ? 1 : 0);
|
||||
|
||||
// SL-15861 This was changed from getRotatedLightNorm() as it was causing
|
||||
// lightnorm in shaders\class1\windlight\atmosphericsFuncs.glsl in have inconsistent additive lighting for 180 degrees of the FOV.
|
||||
LLVector4 rotated_light_direction = LLEnvironment::instance().getClampedLightNorm();
|
||||
shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
|
||||
|
||||
if (LLViewerCamera::getInstance()->cameraUnderWater())
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow());
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove());
|
||||
}
|
||||
|
||||
LLGLDisable cullface(GL_CULL_FACE);
|
||||
|
||||
pushWaterPlanes(edge);
|
||||
|
||||
shader->disableTexture(LLShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP);
|
||||
shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);
|
||||
shader->disableTexture(LLShaderMgr::BUMP_MAP);
|
||||
|
||||
// clean up
|
||||
gPipeline.unbindDeferredShader(*shader);
|
||||
|
||||
gGL.getTexUnit(bumpTex)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
gGL.getTexUnit(bumpTex2)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
shader = &gUnderWaterProgram;
|
||||
}
|
||||
else
|
||||
{
|
||||
shader = &gWaterProgram;
|
||||
}
|
||||
|
||||
gGL.getTexUnit(0)->activate();
|
||||
gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE);
|
||||
gPipeline.bindDeferredShader(*shader, nullptr, &gPipeline.mWaterDis);
|
||||
|
||||
LLViewerTexture* tex_a = mWaterNormp[0];
|
||||
LLViewerTexture* tex_b = mWaterNormp[1];
|
||||
|
||||
F32 blend_factor = (F32)pwater->getBlendFactor();
|
||||
|
||||
if (tex_a && (!tex_b || (tex_a == tex_b)))
|
||||
{
|
||||
shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a);
|
||||
tex_a->setFilteringOption(filter_mode);
|
||||
blend_factor = 0; // only one tex provided, no blending
|
||||
}
|
||||
else if (tex_b && !tex_a)
|
||||
{
|
||||
shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_b);
|
||||
tex_a->setFilteringOption(filter_mode);
|
||||
blend_factor = 0; // only one tex provided, no blending
|
||||
}
|
||||
else if (tex_b != tex_a)
|
||||
{
|
||||
shader->bindTexture(LLViewerShaderMgr::BUMP_MAP, tex_a);
|
||||
tex_a->setFilteringOption(filter_mode);
|
||||
shader->bindTexture(LLViewerShaderMgr::BUMP_MAP2, tex_b);
|
||||
tex_b->setFilteringOption(filter_mode);
|
||||
}
|
||||
|
||||
shader->bindTexture(LLShaderMgr::WATER_EXCLUSIONTEX, &gPipeline.mWaterExclusionMask);
|
||||
|
||||
shader->uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
|
||||
|
||||
F32 fog_density = pwater->getModifiedWaterFogDensity(underwater);
|
||||
|
||||
shader->bindTexture(LLShaderMgr::WATER_SCREENTEX, &gPipeline.mWaterDis);
|
||||
|
||||
if (mShaderLevel == 1)
|
||||
{
|
||||
fog_color.mV[VALPHA] = (F32)(log(fog_density) / log(2));
|
||||
}
|
||||
|
||||
F32 water_height = environment.getWaterHeight();
|
||||
F32 camera_height = LLViewerCamera::getInstance()->getOrigin().mV[2];
|
||||
shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, camera_height - water_height);
|
||||
shader->uniform1f(LLShaderMgr::WATER_TIME, phase_time);
|
||||
shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV);
|
||||
|
||||
shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, pwater->getWave1Dir().mV);
|
||||
shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, pwater->getWave2Dir().mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, pwater->getNormalScale().mV);
|
||||
shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, pwater->getFresnelScale());
|
||||
shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, pwater->getFresnelOffset());
|
||||
shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, fmaxf(0, pwater->getBlurMultiplier()) * 2);
|
||||
|
||||
static LLStaticHashedString s_exposure("exposure");
|
||||
static LLStaticHashedString tonemap_mix("tonemap_mix");
|
||||
static LLStaticHashedString tonemap_type("tonemap_type");
|
||||
|
||||
static LLCachedControl<F32> exposure(gSavedSettings, "RenderExposure", 1.f);
|
||||
|
||||
F32 e = llclamp(exposure(), 0.5f, 4.f);
|
||||
|
||||
static LLCachedControl<bool> should_auto_adjust(gSavedSettings, "RenderSkyAutoAdjustLegacy", false);
|
||||
|
||||
shader->uniform1f(s_exposure, e);
|
||||
static LLCachedControl<U32> tonemap_type_setting(gSavedSettings, "RenderTonemapType", 0U);
|
||||
shader->uniform1i(tonemap_type, tonemap_type_setting);
|
||||
shader->uniform1f(tonemap_mix, psky->getTonemapMix(should_auto_adjust()));
|
||||
|
||||
F32 sunAngle = llmax(0.f, light_dir.mV[1]);
|
||||
F32 scaledAngle = 1.f - sunAngle;
|
||||
|
||||
shader->uniform1i(LLShaderMgr::SUN_UP_FACTOR, sun_up ? 1 : 0);
|
||||
|
||||
// SL-15861 This was changed from getRotatedLightNorm() as it was causing
|
||||
// lightnorm in shaders\class1\windlight\atmosphericsFuncs.glsl in have inconsistent additive lighting for 180 degrees of the FOV.
|
||||
LLVector4 rotated_light_direction = LLEnvironment::instance().getClampedLightNorm();
|
||||
shader->uniform3fv(LLViewerShaderMgr::LIGHTNORM, 1, rotated_light_direction.mV);
|
||||
|
||||
shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);
|
||||
|
||||
if (LLViewerCamera::getInstance()->cameraUnderWater())
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleBelow());
|
||||
}
|
||||
else
|
||||
{
|
||||
shader->uniform1f(LLShaderMgr::WATER_REFSCALE, pwater->getScaleAbove());
|
||||
}
|
||||
|
||||
LLGLDisable cullface(GL_CULL_FACE);
|
||||
|
||||
// Only push the water planes once.
|
||||
// Previously we did this twice: once for void water and one for region water.
|
||||
// However, the void water and region water shaders are the same exact shader.
|
||||
// They also had the same exact state with the sole exception setting an edge water flag.
|
||||
// That flag was not actually used anywhere in the shaders.
|
||||
// - Geenz 2025-02-11
|
||||
pushWaterPlanes(0);
|
||||
|
||||
// clean up
|
||||
gPipeline.unbindDeferredShader(*shader);
|
||||
|
||||
gGL.setColorMask(true, false);
|
||||
}
|
||||
|
|
@ -346,22 +325,18 @@ void LLDrawPoolWater::pushWaterPlanes(int pass)
|
|||
LLVOWater* water = nullptr;
|
||||
for (LLFace* const& face : mDrawFace)
|
||||
{
|
||||
if (!face)
|
||||
continue;
|
||||
water = static_cast<LLVOWater*>(face->getViewerObject());
|
||||
if (!water)
|
||||
continue;
|
||||
|
||||
if ((bool)pass == (bool)water->getIsEdgePatch())
|
||||
face->renderIndexed();
|
||||
|
||||
// Note non-void water being drawn, updates required
|
||||
// Previously we had some logic to determine if this pass was also our water edge pass.
|
||||
// Now we only have one pass. Check if we're doing a region water plane or void water plane.
|
||||
// - Geenz 2025-02-11
|
||||
if (!water->getIsEdgePatch())
|
||||
{
|
||||
face->renderIndexed();
|
||||
|
||||
// Note non-void water being drawn, updates required
|
||||
if (!pass) // SL-16461 remove !LLPipeline::sUseOcclusion check
|
||||
{
|
||||
sNeedsReflectionUpdate = true;
|
||||
sNeedsDistortionUpdate = true;
|
||||
}
|
||||
sNeedsReflectionUpdate = true;
|
||||
sNeedsDistortionUpdate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -647,7 +647,7 @@ void LLInventoryPanel::itemChanged(const LLUUID& item_id, U32 mask, const LLInve
|
|||
{
|
||||
if (model_item && view_item && viewmodel_item)
|
||||
{
|
||||
const LLUUID& idp = viewmodel_item->getUUID();
|
||||
const LLUUID idp = viewmodel_item->getUUID();
|
||||
view_item->destroyView();
|
||||
removeItemID(idp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -564,8 +564,8 @@ LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMate
|
|||
return ppTex ? (*ppTex).get() : NULL;
|
||||
}
|
||||
|
||||
volatile S32 LLMeshRepoThread::sActiveHeaderRequests = 0;
|
||||
volatile S32 LLMeshRepoThread::sActiveLODRequests = 0;
|
||||
std::atomic<S32> LLMeshRepoThread::sActiveHeaderRequests = 0;
|
||||
std::atomic<S32> LLMeshRepoThread::sActiveLODRequests = 0;
|
||||
U32 LLMeshRepoThread::sMaxConcurrentRequests = 1;
|
||||
S32 LLMeshRepoThread::sRequestLowWater = REQUEST2_LOW_WATER_MIN;
|
||||
S32 LLMeshRepoThread::sRequestHighWater = REQUEST2_HIGH_WATER_MIN;
|
||||
|
|
@ -4080,7 +4080,7 @@ void LLMeshRepository::notifyLoadedMeshes()
|
|||
}
|
||||
|
||||
// erase from background thread
|
||||
mThread->mWorkQueue.post([=]()
|
||||
mThread->mWorkQueue.post([=, this]()
|
||||
{
|
||||
mThread->mSkinMap.erase(id);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -266,8 +266,8 @@ class LLMeshRepoThread : public LLThread
|
|||
{
|
||||
public:
|
||||
|
||||
volatile static S32 sActiveHeaderRequests;
|
||||
volatile static S32 sActiveLODRequests;
|
||||
static std::atomic<S32> sActiveHeaderRequests;
|
||||
static std::atomic<S32> sActiveLODRequests;
|
||||
static U32 sMaxConcurrentRequests;
|
||||
static S32 sRequestLowWater;
|
||||
static S32 sRequestHighWater;
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ void LLPanelEmojiComplete::updateConstraints()
|
|||
{
|
||||
mRenderRect = getLocalRect();
|
||||
|
||||
mEmojiWidth = (U16)(mIconFont->getWidthF32(u8"\U0001F431") + mPadding * 2);
|
||||
mEmojiWidth = (U16)(mIconFont->getWidthF32(LLWString(1, 0x1F431).c_str()) + mPadding * 2);
|
||||
if (mVertical)
|
||||
{
|
||||
mEmojiHeight = mIconFont->getLineHeight() + mPadding * 2;
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include <iostream>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
|
||||
#include "lltexturefetch.h"
|
||||
|
||||
|
|
@ -3156,7 +3157,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, S3
|
|||
bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
|
||||
{
|
||||
LL_PROFILE_ZONE_SCOPED;
|
||||
mRequestQueue.tryPost([=]()
|
||||
mRequestQueue.tryPost([=, this]()
|
||||
{
|
||||
LLTextureFetchWorker* worker = getWorker(id);
|
||||
if (worker)
|
||||
|
|
@ -4274,29 +4275,30 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher)
|
|||
//if (! gViewerAssetStatsThread1)
|
||||
// return true;
|
||||
|
||||
static volatile bool reporting_started(false);
|
||||
static volatile S32 report_sequence(0);
|
||||
static std::atomic<bool> reporting_started(false);
|
||||
static std::atomic<S32> report_sequence(0);
|
||||
|
||||
// In mStatsSD, we have a copy we own of the LLSD representation
|
||||
// of the asset stats. Add some additional fields and ship it off.
|
||||
|
||||
static const S32 metrics_data_version = 2;
|
||||
|
||||
bool initial_report = !reporting_started;
|
||||
bool initial_report = !reporting_started.load();
|
||||
mStatsSD["session_id"] = mSessionID;
|
||||
mStatsSD["agent_id"] = mAgentID;
|
||||
mStatsSD["message"] = "ViewerAssetMetrics";
|
||||
mStatsSD["sequence"] = report_sequence;
|
||||
mStatsSD["sequence"] = report_sequence.load();
|
||||
mStatsSD["initial"] = initial_report;
|
||||
mStatsSD["version"] = metrics_data_version;
|
||||
mStatsSD["break"] = static_cast<bool>(LLTextureFetch::svMetricsDataBreak);
|
||||
|
||||
// Update sequence number
|
||||
if (S32_MAX == ++report_sequence)
|
||||
if (S32_MAX == report_sequence.fetch_add(1))
|
||||
{
|
||||
report_sequence = 0;
|
||||
report_sequence.store(0);
|
||||
}
|
||||
reporting_started = true;
|
||||
|
||||
reporting_started.store(true);
|
||||
|
||||
// Limit the size of the stats report if necessary.
|
||||
|
||||
|
|
|
|||
|
|
@ -2947,14 +2947,14 @@ void LLViewerMediaImpl::update()
|
|||
media_tex->ref();
|
||||
main_queue->postTo(
|
||||
mTexUpdateQueue, // Worker thread queue
|
||||
[=]() // work done on update worker thread
|
||||
[=, this]() // work done on update worker thread
|
||||
{
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
media_tex->getGLTexture()->mActiveThread = LLThread::currentID();
|
||||
#endif
|
||||
doMediaTexUpdate(media_tex, data, data_width, data_height, x_pos, y_pos, width, height, true);
|
||||
},
|
||||
[=]() // callback to main thread
|
||||
[=, this]() // callback to main thread
|
||||
{
|
||||
#if LL_IMAGEGL_THREAD_CHECK
|
||||
media_tex->getGLTexture()->mActiveThread = LLThread::currentID();
|
||||
|
|
|
|||
|
|
@ -114,7 +114,6 @@ LLGLSLShader gObjectAlphaMaskNoColorProgram;
|
|||
|
||||
//environment shaders
|
||||
LLGLSLShader gWaterProgram;
|
||||
LLGLSLShader gWaterEdgeProgram;
|
||||
LLGLSLShader gUnderWaterProgram;
|
||||
|
||||
//interface shaders
|
||||
|
|
@ -415,7 +414,6 @@ void LLViewerShaderMgr::finalizeShaderList()
|
|||
//ONLY shaders that need WL Param management should be added here
|
||||
mShaderList.push_back(&gAvatarProgram);
|
||||
mShaderList.push_back(&gWaterProgram);
|
||||
mShaderList.push_back(&gWaterEdgeProgram);
|
||||
mShaderList.push_back(&gAvatarEyeballProgram);
|
||||
mShaderList.push_back(&gImpostorProgram);
|
||||
mShaderList.push_back(&gObjectBumpProgram);
|
||||
|
|
@ -882,6 +880,7 @@ std::string LLViewerShaderMgr::loadBasicShaders()
|
|||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/shadowUtil.glsl", 1) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/aoUtil.glsl", 1) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/pbrterrainUtilF.glsl", 1) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/tonemapUtilF.glsl", 1) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/reflectionProbeF.glsl", has_reflection_probes ? 3 : 2) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "deferred/screenSpaceReflUtil.glsl", ssr ? 3 : 1) );
|
||||
index_channels.push_back(-1); shaders.push_back( make_pair( "lighting/lightNonIndexedF.glsl", mShaderLevel[SHADER_LIGHTING] ) );
|
||||
|
|
@ -914,7 +913,6 @@ bool LLViewerShaderMgr::loadShadersWater()
|
|||
if (mShaderLevel[SHADER_WATER] == 0)
|
||||
{
|
||||
gWaterProgram.unload();
|
||||
gWaterEdgeProgram.unload();
|
||||
gUnderWaterProgram.unload();
|
||||
return true;
|
||||
}
|
||||
|
|
@ -928,6 +926,7 @@ bool LLViewerShaderMgr::loadShadersWater()
|
|||
gWaterProgram.mFeatures.hasGamma = true;
|
||||
gWaterProgram.mFeatures.hasSrgb = true;
|
||||
gWaterProgram.mFeatures.hasReflectionProbes = true;
|
||||
gWaterProgram.mFeatures.hasTonemap = true;
|
||||
gWaterProgram.mFeatures.hasShadows = use_sun_shadow;
|
||||
gWaterProgram.mShaderFiles.clear();
|
||||
gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER));
|
||||
|
|
@ -949,36 +948,6 @@ bool LLViewerShaderMgr::loadShadersWater()
|
|||
llassert(success);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
// load water shader
|
||||
gWaterEdgeProgram.mName = "Water Edge Shader";
|
||||
gWaterEdgeProgram.mFeatures.calculatesAtmospherics = true;
|
||||
gWaterEdgeProgram.mFeatures.hasAtmospherics = true;
|
||||
gWaterEdgeProgram.mFeatures.hasGamma = true;
|
||||
gWaterEdgeProgram.mFeatures.hasSrgb = true;
|
||||
gWaterEdgeProgram.mFeatures.hasReflectionProbes = true;
|
||||
gWaterEdgeProgram.mFeatures.hasShadows = use_sun_shadow;
|
||||
gWaterEdgeProgram.mShaderFiles.clear();
|
||||
gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER));
|
||||
gWaterEdgeProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER));
|
||||
gWaterEdgeProgram.clearPermutations();
|
||||
gWaterEdgeProgram.addPermutation("WATER_EDGE", "1");
|
||||
if (LLPipeline::sRenderTransparentWater)
|
||||
{
|
||||
gWaterEdgeProgram.addPermutation("TRANSPARENT_WATER", "1");
|
||||
}
|
||||
|
||||
if (use_sun_shadow)
|
||||
{
|
||||
gWaterEdgeProgram.addPermutation("HAS_SUN_SHADOW", "1");
|
||||
}
|
||||
gWaterEdgeProgram.mShaderGroup = LLGLSLShader::SG_WATER;
|
||||
gWaterEdgeProgram.mShaderLevel = mShaderLevel[SHADER_WATER];
|
||||
success = gWaterEdgeProgram.createShader();
|
||||
llassert(success);
|
||||
}
|
||||
|
||||
if (success)
|
||||
{
|
||||
//load under water vertex shader
|
||||
|
|
@ -2517,6 +2486,7 @@ bool LLViewerShaderMgr::loadShadersDeferred()
|
|||
gDeferredPostTonemapProgram.mName = "Deferred Tonemap Post Process";
|
||||
gDeferredPostTonemapProgram.mFeatures.hasSrgb = true;
|
||||
gDeferredPostTonemapProgram.mFeatures.isDeferred = true;
|
||||
gDeferredPostTonemapProgram.mFeatures.hasTonemap = true;
|
||||
gDeferredPostTonemapProgram.mShaderFiles.clear();
|
||||
gDeferredPostTonemapProgram.clearPermutations();
|
||||
gDeferredPostTonemapProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoTCV.glsl", GL_VERTEX_SHADER));
|
||||
|
|
@ -2531,6 +2501,7 @@ bool LLViewerShaderMgr::loadShadersDeferred()
|
|||
gNoPostTonemapProgram.mName = "No Post Tonemap Post Process";
|
||||
gNoPostTonemapProgram.mFeatures.hasSrgb = true;
|
||||
gNoPostTonemapProgram.mFeatures.isDeferred = true;
|
||||
gNoPostTonemapProgram.mFeatures.hasTonemap = true;
|
||||
gNoPostTonemapProgram.mShaderFiles.clear();
|
||||
gNoPostTonemapProgram.clearPermutations();
|
||||
gNoPostTonemapProgram.addPermutation("NO_POST", "1");
|
||||
|
|
|
|||
|
|
@ -192,7 +192,6 @@ extern LLGLSLShader gObjectAlphaMaskNoColorProgram;
|
|||
|
||||
//environment shaders
|
||||
extern LLGLSLShader gWaterProgram;
|
||||
extern LLGLSLShader gWaterEdgeProgram;
|
||||
extern LLGLSLShader gUnderWaterProgram;
|
||||
extern LLGLSLShader gGlowProgram;
|
||||
extern LLGLSLShader gGlowExtractProgram;
|
||||
|
|
|
|||
|
|
@ -1094,7 +1094,8 @@ F32 LLViewerTextureList::updateImagesCreateTextures(F32 max_time)
|
|||
imagep->mCreatePending = false;
|
||||
mCreateTextureList.pop();
|
||||
|
||||
if (imagep->hasGLTexture() && imagep->getDiscardLevel() < imagep->getDesiredDiscardLevel())
|
||||
if (imagep->hasGLTexture() && imagep->getDiscardLevel() < imagep->getDesiredDiscardLevel() &&
|
||||
(imagep->getDesiredDiscardLevel() <= MAX_DISCARD_LEVEL))
|
||||
{
|
||||
// NOTE: this may happen if the desired discard reduces while a decode is in progress and does not
|
||||
// necessarily indicate a problem, but if log occurrences excede that of dsiplay_stats: FPS,
|
||||
|
|
|
|||
|
|
@ -778,7 +778,7 @@ public:
|
|||
ypos += y_inc;
|
||||
|
||||
// <FS:Ansariel> Mesh debugging
|
||||
addText(xpos, ypos, llformat("%d Mesh Active LOD Requests", LLMeshRepoThread::sActiveLODRequests));
|
||||
addText(xpos, ypos, llformat("%d Mesh Active LOD Requests", LLMeshRepoThread::sActiveLODRequests.load()));
|
||||
ypos += y_inc;
|
||||
// </FS:Ansariel>
|
||||
|
||||
|
|
@ -1437,7 +1437,7 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
|
|||
// Check the whitelist, if there's media (otherwise just show it)
|
||||
if (te->getMediaData() == NULL || te->getMediaData()->checkCandidateUrl(url))
|
||||
{
|
||||
if ( obj != mDragHoveredObject)
|
||||
if ( obj != mDragHoveredObject.get())
|
||||
{
|
||||
// Highlight the dragged object
|
||||
LLSelectMgr::getInstance()->unhighlightObjectOnly(mDragHoveredObject);
|
||||
|
|
@ -1852,6 +1852,7 @@ bool LLViewerWindow::handleDeviceChange(LLWindow *window)
|
|||
|
||||
bool LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height)
|
||||
{
|
||||
LLFontGL::sResolutionGeneration++;
|
||||
if (ui_scale_factor >= MIN_UI_SCALE && ui_scale_factor <= MAX_UI_SCALE)
|
||||
{
|
||||
LLViewerWindow::reshape(window_width, window_height);
|
||||
|
|
@ -1865,6 +1866,12 @@ bool LLViewerWindow::handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32
|
|||
}
|
||||
}
|
||||
|
||||
bool LLViewerWindow::handleDisplayChanged()
|
||||
{
|
||||
LLFontGL::sResolutionGeneration++;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLViewerWindow::handleWindowDidChangeScreen(LLWindow *window)
|
||||
{
|
||||
LLCoordScreen window_rect;
|
||||
|
|
@ -2037,6 +2044,7 @@ LLViewerWindow::LLViewerWindow(const Params& p)
|
|||
mDisplayScale.setVec(llmax(1.f / mWindow->getPixelAspectRatio(), 1.f), llmax(mWindow->getPixelAspectRatio(), 1.f));
|
||||
mDisplayScale *= ui_scale_factor;
|
||||
LLUI::setScaleFactor(mDisplayScale);
|
||||
LLFontGL::sResolutionGeneration++;
|
||||
|
||||
{
|
||||
LLCoordWindow size;
|
||||
|
|
@ -2758,6 +2766,7 @@ void LLViewerWindow::reshape(S32 width, S32 height)
|
|||
|
||||
bool display_scale_changed = mDisplayScale != LLUI::getScaleFactor();
|
||||
LLUI::setScaleFactor(mDisplayScale);
|
||||
LLFontGL::sResolutionGeneration++;
|
||||
|
||||
// update our window rectangle
|
||||
mWindowRectScaled.mRight = mWindowRectScaled.mLeft + ll_round((F32)width / mDisplayScale.mV[VX]);
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ public:
|
|||
/*virtual*/ bool handleTimerEvent(LLWindow *window);
|
||||
/*virtual*/ bool handleDeviceChange(LLWindow *window);
|
||||
/*virtual*/ bool handleDPIChanged(LLWindow *window, F32 ui_scale_factor, S32 window_width, S32 window_height);
|
||||
/*virtual*/ bool handleDisplayChanged();
|
||||
/*virtual*/ bool handleWindowDidChangeScreen(LLWindow *window);
|
||||
|
||||
/*virtual*/ void handlePingWatchdog(LLWindow *window, const char * msg);
|
||||
|
|
|
|||
|
|
@ -2105,7 +2105,7 @@ bool LLVivoxVoiceClient::waitForChannel()
|
|||
{
|
||||
recordingAndPlaybackMode();
|
||||
}
|
||||
else if (mProcessChannels && (mNextAudioSession == NULL) && checkParcelChanged())
|
||||
else if (mProcessChannels && ((mNextAudioSession == NULL) || checkParcelChanged()))
|
||||
{
|
||||
// the parcel is changed, or we have no pending audio sessions,
|
||||
// so try to request the parcel voice info
|
||||
|
|
|
|||
|
|
@ -556,7 +556,7 @@ void LLWebRTCVoiceClient::voiceConnectionCoro()
|
|||
}
|
||||
}
|
||||
LL::WorkQueue::postMaybe(mMainQueue,
|
||||
[=] {
|
||||
[=, this] {
|
||||
if (sShuttingDown)
|
||||
{
|
||||
return;
|
||||
|
|
@ -674,7 +674,7 @@ void LLWebRTCVoiceClient::OnDevicesChanged(const llwebrtc::LLWebRTCVoiceDeviceLi
|
|||
{
|
||||
|
||||
LL::WorkQueue::postMaybe(mMainQueue,
|
||||
[=]
|
||||
[=, this]
|
||||
{
|
||||
OnDevicesChangedImpl(render_devices, capture_devices);
|
||||
});
|
||||
|
|
@ -2211,7 +2211,7 @@ LLVoiceWebRTCConnection::~LLVoiceWebRTCConnection()
|
|||
void LLVoiceWebRTCConnection::OnIceGatheringState(llwebrtc::LLWebRTCSignalingObserver::EIceGatheringState state)
|
||||
{
|
||||
LL::WorkQueue::postMaybe(mMainQueue,
|
||||
[=] {
|
||||
[=, this] {
|
||||
LL_DEBUGS("Voice") << "Ice Gathering voice account. " << state << LL_ENDL;
|
||||
|
||||
switch (state)
|
||||
|
|
@ -2234,7 +2234,7 @@ void LLVoiceWebRTCConnection::OnIceGatheringState(llwebrtc::LLWebRTCSignalingObs
|
|||
// callback from llwebrtc
|
||||
void LLVoiceWebRTCConnection::OnIceCandidate(const llwebrtc::LLWebRTCIceCandidate& candidate)
|
||||
{
|
||||
LL::WorkQueue::postMaybe(mMainQueue, [=] { mIceCandidates.push_back(candidate); });
|
||||
LL::WorkQueue::postMaybe(mMainQueue, [=, this] { mIceCandidates.push_back(candidate); });
|
||||
}
|
||||
|
||||
void LLVoiceWebRTCConnection::processIceUpdates()
|
||||
|
|
@ -2352,7 +2352,7 @@ void LLVoiceWebRTCConnection::processIceUpdatesCoro(connectionPtr_t connection)
|
|||
void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp)
|
||||
{
|
||||
LL::WorkQueue::postMaybe(mMainQueue,
|
||||
[=] {
|
||||
[=, this] {
|
||||
if (mShutDown)
|
||||
{
|
||||
return;
|
||||
|
|
@ -2379,7 +2379,7 @@ void LLVoiceWebRTCConnection::OnOfferAvailable(const std::string &sdp)
|
|||
void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterface* audio_interface)
|
||||
{
|
||||
LL::WorkQueue::postMaybe(mMainQueue,
|
||||
[=] {
|
||||
[=, this] {
|
||||
if (mShutDown)
|
||||
{
|
||||
return;
|
||||
|
|
@ -2401,7 +2401,7 @@ void LLVoiceWebRTCConnection::OnAudioEstablished(llwebrtc::LLWebRTCAudioInterfac
|
|||
void LLVoiceWebRTCConnection::OnRenegotiationNeeded()
|
||||
{
|
||||
LL::WorkQueue::postMaybe(mMainQueue,
|
||||
[=] {
|
||||
[=, this] {
|
||||
LL_DEBUGS("Voice") << "Voice channel requires renegotiation." << LL_ENDL;
|
||||
if (!mShutDown)
|
||||
{
|
||||
|
|
@ -2415,7 +2415,7 @@ void LLVoiceWebRTCConnection::OnRenegotiationNeeded()
|
|||
void LLVoiceWebRTCConnection::OnPeerConnectionClosed()
|
||||
{
|
||||
LL::WorkQueue::postMaybe(mMainQueue,
|
||||
[=] {
|
||||
[=, this] {
|
||||
LL_DEBUGS("Voice") << "Peer connection has closed." << LL_ENDL;
|
||||
if (mVoiceConnectionState == VOICE_STATE_WAIT_FOR_CLOSE)
|
||||
{
|
||||
|
|
@ -2890,7 +2890,7 @@ bool LLVoiceWebRTCConnection::connectionStateMachine()
|
|||
// llwebrtc callback
|
||||
void LLVoiceWebRTCConnection::OnDataReceived(const std::string& data, bool binary)
|
||||
{
|
||||
LL::WorkQueue::postMaybe(mMainQueue, [=] { LLVoiceWebRTCConnection::OnDataReceivedImpl(data, binary); });
|
||||
LL::WorkQueue::postMaybe(mMainQueue, [=, this] { LLVoiceWebRTCConnection::OnDataReceivedImpl(data, binary); });
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -3046,7 +3046,7 @@ void LLVoiceWebRTCConnection::OnDataReceivedImpl(const std::string &data, bool b
|
|||
void LLVoiceWebRTCConnection::OnDataChannelReady(llwebrtc::LLWebRTCDataInterface *data_interface)
|
||||
{
|
||||
LL::WorkQueue::postMaybe(mMainQueue,
|
||||
[=] {
|
||||
[=, this] {
|
||||
if (mShutDown)
|
||||
{
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ void LLLogin::Impl::connect(const std::string& uri, const LLSD& login_params)
|
|||
// Launch a coroutine with our login_() method. Run the coroutine until
|
||||
// its first wait; at that point, return here.
|
||||
std::string coroname =
|
||||
LLCoros::instance().launch("LLLogin::Impl::login_", [=]() { loginCoro(uri, login_params); });
|
||||
LLCoros::instance().launch("LLLogin::Impl::login_", [=, this]() { loginCoro(uri, login_params); });
|
||||
|
||||
LL_DEBUGS("LLLogin") << " connected with uri '" << uri << "', login_params " << login_params << LL_ENDL;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue