diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 87a5c69e3b..6585e73db2 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -90,7 +90,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Setup python
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
python-version: "3.11"
- name: Checkout build variables
diff --git a/.github/workflows/build_viewer.yml b/.github/workflows/build_viewer.yml
index f5b0f1f6a8..4d74d5ba3d 100644
--- a/.github/workflows/build_viewer.yml
+++ b/.github/workflows/build_viewer.yml
@@ -73,7 +73,7 @@ jobs:
- name: Set up Python (normal case)
if: matrix.container_image != 'ubuntu:22.04'
id: py311_setup
- uses: actions/setup-python@v5
+ uses: actions/setup-python@v6
with:
python-version: '3.11'
check-latest: true
diff --git a/.github/workflows/check-pr.yaml b/.github/workflows/check-pr.yaml
index a5cee9157c..08e907e83f 100644
--- a/.github/workflows/check-pr.yaml
+++ b/.github/workflows/check-pr.yaml
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check PR description
- uses: actions/github-script@v7
+ uses: actions/github-script@v8
with:
script: |
const description = context.payload.pull_request.body || '';
diff --git a/.github/workflows/label.yaml b/.github/workflows/label.yaml
index a34c575680..218327ef47 100644
--- a/.github/workflows/label.yaml
+++ b/.github/workflows/label.yaml
@@ -9,7 +9,7 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- - uses: actions/labeler@v5
+ - uses: actions/labeler@v6
with:
configuration-path: .github/labeler.yaml
repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml
index 73ec1c32e9..8f942fa11b 100644
--- a/.github/workflows/pre-commit.yaml
+++ b/.github/workflows/pre-commit.yaml
@@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- - uses: actions/setup-python@v5
+ - uses: actions/setup-python@v6
with:
python-version: 3.x
- uses: pre-commit/action@v3.0.1
diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml
index 85138c7bcd..edfe71b693 100644
--- a/.github/workflows/stale.yaml
+++ b/.github/workflows/stale.yaml
@@ -12,7 +12,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v9
+ - uses: actions/stale@v10
id: stale
with:
stale-pr-message: This pull request is stale because it has been open 30 days with no activity. Remove stale label or comment or it will be closed in 7 days
diff --git a/.github/workflows/tag-release.yaml b/.github/workflows/tag-release.yaml
index 24ee2de794..2922065f99 100644
--- a/.github/workflows/tag-release.yaml
+++ b/.github/workflows/tag-release.yaml
@@ -35,7 +35,7 @@ jobs:
echo NIGHTLY_DATE=${NIGHTLY_DATE} >> ${GITHUB_ENV}
echo TAG_ID="$(echo ${{ github.sha }} | cut -c1-8)-${{ inputs.project || '${NIGHTLY_DATE}' }}" >> ${GITHUB_ENV}
- name: Update Tag
- uses: actions/github-script@v7.0.1
+ uses: actions/github-script@v8
with:
# use a real access token instead of GITHUB_TOKEN default.
# required so that the results of this tag creation can trigger the build workflow
diff --git a/autobuild.xml b/autobuild.xml
index fbab2fa858..643588388f 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -1328,9 +1328,9 @@
archive
name
darwin64
@@ -1340,9 +1340,9 @@
archive
name
linux64
@@ -1352,9 +1352,9 @@
archive
name
windows64
diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp
index 7d9a9c1072..fa2214dcdf 100644
--- a/indra/llfilesystem/lldiskcache.cpp
+++ b/indra/llfilesystem/lldiskcache.cpp
@@ -328,7 +328,11 @@ void LLDiskCache::purge()
const std::string LLDiskCache::metaDataToFilepath(const LLUUID& id, LLAssetType::EType at)
{
- return llformat("%s%s%s_%s_0.asset", sCacheDir.c_str(), gDirUtilp->getDirDelimiter().c_str(), CACHE_FILENAME_PREFIX.c_str(), id.asString().c_str());
+ // Store assets in subfolders
+ //return llformat("%s%s%s_%s_0.asset", sCacheDir.c_str(), gDirUtilp->getDirDelimiter().c_str(), CACHE_FILENAME_PREFIX.c_str(), id.asString().c_str());
+ char id_string[36]{};
+ return llformat("%s%s%c%s%s_%s_0.asset", sCacheDir.c_str(), gDirUtilp->getDirDelimiter().c_str(), id.toStringFast(id_string)[0], gDirUtilp->getDirDelimiter().c_str(), CACHE_FILENAME_PREFIX.c_str(), id.asString().c_str());
+ //
}
const std::string LLDiskCache::getCacheInfo()
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 1cb92d5c48..23ef3d74e8 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -276,29 +276,111 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r
// Estimate the number of layers. This is consistent with what's done for j2c encoding in LLImageJ2CKDU::encodeImpl().
constexpr S32 precision = 8; // assumed bitrate per component channel, might change in future for HDR support
constexpr S32 max_components = 4; // assumed the file has four components; three color and alpha
- // Use MAX_IMAGE_SIZE_DEFAULT (currently 2048) if either dimension is unknown (zero)
- S32 width = (w > 0) ? w : 2048;
- S32 height = (h > 0) ? h : 2048;
- S32 max_dimension = llmax(width, height); // Find largest dimension
- S32 block_area = MAX_BLOCK_SIZE * MAX_BLOCK_SIZE; // Calculated initial block area from established max block size (currently 64)
- S32 max_layers = (S32)llmax(llround(log2f((float)max_dimension) - log2f((float)MAX_BLOCK_SIZE)), 4); // Find number of powers of two between extents and block size to a minimum of 4
- block_area *= llmax(max_layers, 1); // Adjust initial block area by max number of layers
- S32 totalbytes = (S32) (MIN_LAYER_SIZE * max_components * precision); // Start estimation with a minimum reasonable size
- S32 block_layers = 0;
- while (block_layers <= max_layers) // Walk the layers
+
+ // [FIRE-35987] slow textures due to overfetch in j2c header size estimation
+ // Preserve recent LL body for reference (see PRs #2406, #2525, #4018, #4020):
+ // // Use MAX_IMAGE_SIZE_DEFAULT (currently 2048) if either dimension is unknown (zero)
+ // S32 width = (w > 0) ? w : 2048;
+ // S32 height = (h > 0) ? h : 2048;
+ // S32 max_dimension = llmax(width, height); // Find largest dimension
+ // S32 block_area = MAX_BLOCK_SIZE * MAX_BLOCK_SIZE; // Calculated initial block area from established max block size (currently 64)
+ // S32 max_layers = (S32)llmax(llround(log2f((float)max_dimension) - log2f((float)MAX_BLOCK_SIZE)), 4); // Find number of powers of two between extents and block size to a minimum of 4
+ // block_area *= llmax(max_layers, 1); // Adjust initial block area by max number of layers
+ // S32 totalbytes = (S32) (MIN_LAYER_SIZE * max_components * precision); // Start estimation with a minimum reasonable size
+ // S32 block_layers = 0;
+ // while (block_layers <= max_layers) // Walk the layers
+ // {
+ // if (block_layers <= (5 - discard_level)) // Walk backwards from discard 5 to required discard layer.
+ // totalbytes += (S32) (block_area * max_components * precision * rate); // Add each block layer reduced by assumed compression rate
+ // block_layers++; // Move to next layer
+ // block_area *= 4; // Increase block area by power of four
+ // }
+ // totalbytes /= 8; // to bytes
+ // totalbytes += calcHeaderSizeJ2C(); // header
+ //
+ // return totalbytes;
+
+ // --- Use 7.1.11 basis with fixes implied by LL PRs ---
+ (void)comp; // retained for parity with the viewer signature
+ const S32 hard_cap = 12; // sanity cap
+ const S64 base_layer_area = static_cast(MAX_BLOCK_SIZE) * static_cast(MAX_BLOCK_SIZE); // 64x64 blocks at discard 5
+ const S32 discard_layers = std::max(5 - discard_level, 0);
+ const double rate64 = static_cast(rate);
+ const S64 header_bytes = static_cast(calcHeaderSizeJ2C());
+ const S64 bits_per_tile = static_cast(max_components) * static_cast(precision);
+
+ // helper lambda: layer area to estimated bit budget
+ auto scaled_bits = [rate64, bits_per_tile](S64 layer_area) -> S64
{
- if (block_layers <= (5 - discard_level)) // Walk backwards from discard 5 to required discard layer.
- totalbytes += (S32) (block_area * max_components * precision * rate); // Add each block layer reduced by assumed compression rate
- block_layers++; // Move to next layer
- block_area *= 4; // Increase block area by power of four
+ const S64 layer_bits = layer_area * bits_per_tile;
+ return static_cast(std::llround(static_cast(layer_bits) * rate64));
+ };
+
+ // If dimensions are unknown, provide a *reliable discard-5 estimate* without assuming a 2k texture.
+ // This lets the fetcher skip a header pass for d5 while avoiding the large overfetch seen previously.
+ S64 total_bits = 0;
+ if (w <= 0 || h <= 0)
+ {
+ total_bits = scaled_bits(base_layer_area);
}
+ else
+ {
+ // Classic surface walk: start at 64x64 and grow by 4x until we cover the surface.
+ const S64 surface = static_cast(w) * static_cast(h);
- totalbytes /= 8; // to bytes
- totalbytes += calcHeaderSizeJ2C(); // header
+ S64 layer_area = base_layer_area;
+ S32 nb_layers = 1;
- return totalbytes;
+ // First layer (7.1.11 did first-term outside loop). Keep it explicit for clarity.
+ total_bits = scaled_bits(layer_area);
+
+ while (surface > layer_area && nb_layers < hard_cap)
+ {
+ if (nb_layers <= discard_layers)
+ {
+ total_bits += scaled_bits(layer_area);
+ }
+ ++nb_layers;
+ layer_area *= 4;
+ }
+
+ // Allow extra layers for large (2k+) assets uploaded with 7–8 layers (from LL change justification)
+ // If the max dimension implies more pyramid steps than the surface loop used, extend the walk up to that.
+ // Note: this mostly affect long thin textures like 2048x256 as best I can tell.
+ {
+ const S32 max_dimension = std::max(w, h);
+ const float ratio = (max_dimension > 0)
+ ? static_cast(max_dimension) / static_cast(MAX_BLOCK_SIZE)
+ : 0.0f;
+ const S32 dimension_layers = (ratio > 0.0f)
+ ? std::max(static_cast(std::floor(std::log2(ratio))) + 1, 1)
+ : 1;
+
+ if (dimension_layers > nb_layers)
+ {
+ S32 extra = std::min(dimension_layers, hard_cap) - nb_layers;
+ while (extra-- > 0)
+ {
+ if (nb_layers <= discard_layers)
+ {
+ total_bits += scaled_bits(layer_area);
+ }
+ ++nb_layers;
+ layer_area *= 4;
+ }
+ }
+ }
+ }
+ // Convert to bytes and add header.
+ S64 est = total_bits / 8;
+ est += header_bytes;
+
+ est = llclamp(est, (S64)0, (S64)std::numeric_limits::max());
+ return static_cast(est);
+ //
}
+
S32 LLImageJ2C::calcHeaderSize()
{
return calcHeaderSizeJ2C();
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index 84fde40a1f..03cd7771d4 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -774,6 +774,7 @@ void LLPermissions::importLLSD(const LLSD& sd_perm)
}
}
+ fixOwnership();
fix();
}
diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index 8ddc8c5e71..5ed1f3b687 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -642,6 +642,11 @@ bool LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_leve
if(discard_level > 0)
{
mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)discard_level);
+ // [FIRE-35361] RenderMaxTextureResolution caps texture resolution lower than intended
+ // 2K textures could set the mMaxDiscardLevel above MAX_DISCARD_LEVEL, which would
+ // cause them to not be down-scaled so they would get stuck at 0 discard all the time.
+ mMaxDiscardLevel = llmin(mMaxDiscardLevel, (S8)MAX_DISCARD_LEVEL);
+ // [FIRE-35361]
}
}
else
@@ -1097,6 +1102,8 @@ void sub_image_lines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 w
// full width texture, do 32 lines at a time
for (U32 y_pos = y_offset; y_pos < y_offset_end; y_pos += batch_size)
{
+ // If this keeps crashing, pass down data_size, looks like it is using
+ // imageraw->getData(); for data, but goes way over allocated size limit
glTexSubImage2D(target, miplevel, x_offset, y_pos, width, batch_size, pixformat, pixtype, src);
src += line_width * batch_size;
}
@@ -1106,6 +1113,8 @@ void sub_image_lines(U32 target, S32 miplevel, S32 x_offset, S32 y_offset, S32 w
// partial width or strange height
for (U32 y_pos = y_offset; y_pos < y_offset_end; y_pos += 1)
{
+ // If this keeps crashing, pass down data_size, looks like it is using
+ // imageraw->getData(); for data, but goes way over allocated size limit
glTexSubImage2D(target, miplevel, x_offset, y_pos, width, 1, pixformat, pixtype, src);
src += line_width;
}
@@ -1546,6 +1555,7 @@ bool LLImageGL::createGLTexture(S32 discard_level, const LLImageRaw* imageraw, S
llassert(mCurrentDiscardLevel >= 0);
discard_level = mCurrentDiscardLevel;
}
+ discard_level = llmin(discard_level, MAX_DISCARD_LEVEL);
// Actual image width/height = raw image width/height * 2^discard_level
S32 raw_w = imageraw->getWidth() ;
@@ -1644,6 +1654,7 @@ bool LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, bool data_
discard_level = mCurrentDiscardLevel;
}
discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
+ discard_level = llmin(discard_level, MAX_DISCARD_LEVEL);
if (main_thread // <--- always force creation of new_texname when not on main thread ...
&& !defer_copy // <--- ... or defer copy is set
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index a43c102ca7..3e2827daa5 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -167,6 +167,7 @@ set(viewer_SOURCE_FILES
fsparticipantlist.cpp
fspose.cpp
fsposeranimator.cpp
+ fsposestate.cpp
fsposingmotion.cpp
fsprimfeedauth.cpp
fsradar.cpp
@@ -1008,6 +1009,7 @@ set(viewer_HEADER_FILES
fsparticipantlist.h
fspose.h
fsposeranimator.h
+ fsposestate.h
fsposingmotion.h
fsprimfeedauth.h
fsradar.h
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index f4b098c2a3..20a9e2760b 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -14022,13 +14022,13 @@ Change of this parameter will affect the layout of buttons in notification toast
SceneLoadRearMaxRadiusFraction
SceneLoadRearPixelThreshold
+ DisableCameraJoystickCenterReset
+
FSNetMapScripted
+ FSSnapshotShowGuides
+
FSSnapshotFrameBorderColor
- if (override_tex_discard_level != 0)
+ if (override_tex_discard_level != 0 && override_tex_discard_level <= MAX_DISCARD_LEVEL)
{
desired_discard = override_tex_discard_level;
}
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index fe8d590810..54f68f3a29 100644
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -515,7 +515,7 @@ void LLVOCacheEntry::updateDebugSettings()
sNearRadius = MIN_RADIUS + ((clamped_min_radius - MIN_RADIUS) * adjust_factor);
// a percentage of draw distance beyond which all objects outside of view frustum will be unloaded, regardless of pixel threshold
- static LLCachedControl rear_max_radius_frac(gSavedSettings,"SceneLoadRearMaxRadiusFraction");
+ static LLCachedControl rear_max_radius_frac(gSavedSettings,"SceneLoadRearMaxRadiusFraction", .75f);
const F32 min_radius_plus_one = sNearRadius + 1.f;
const F32 max_radius = rear_max_radius_frac * draw_radius;
const F32 clamped_max_radius = llclamp(max_radius, min_radius_plus_one, draw_radius); // [sNearRadius, mDrawDistance]
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index bf86e4ddc7..ca76a164b6 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -8603,7 +8603,7 @@ void LLPipeline::renderFinalize()
};
//
// new shader for snapshot frame helper
- if (renderSnapshotFrame(auxTargetBuffer, auxActiveBuffer))
+ if (renderSnapshotFrame(auxActiveBuffer, auxTargetBuffer))
{
std::swap(auxActiveBuffer, auxTargetBuffer);
};
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_UI.xml b/indra/newview/skins/default/xui/de/panel_preferences_UI.xml
index a6332de47d..92e474c815 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_UI.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_UI.xml
@@ -151,6 +151,7 @@
+
Eigene Fenster verwenden für:
diff --git a/indra/newview/skins/default/xui/en/floater_fs_poser.xml b/indra/newview/skins/default/xui/en/floater_fs_poser.xml
index a2d35e8384..f74b357403 100644
--- a/indra/newview/skins/default/xui/en/floater_fs_poser.xml
+++ b/indra/newview/skins/default/xui/en/floater_fs_poser.xml
@@ -1838,6 +1838,15 @@ width="430">
+
name="load_poses_button"
left_pad="1"
top_delta="0"
- width="95"/>
+ width="85"/>