diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index c68131402b..ce934f1a21 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -1,6 +1,7 @@
# Replace tabs with spaces
1b68f71348ecf3983b76b40d7940da8377f049b7
33418a77b716e122da9778869cdbabe97c83ff37
+6b974724826a038b0db794460b322eb4921da735
# Trim trailing whitespace
a0b3021bdcf76859054fda8e30abb3ed47749e83
8444cd9562a6a7b755fcb075864e205122354192
diff --git a/.gitattributes b/.gitattributes
index 30cc9de8f1..5c7f5b73b0 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,8 +1,5 @@
* text eol=lf
-# VSTool (normalization disabled)
-indra/tools/vstool/* -text
-
# Images
*.bmp binary
*.BMP binary
diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml
new file mode 100644
index 0000000000..3e3e1df3e2
--- /dev/null
+++ b/.github/dependabot.yaml
@@ -0,0 +1,7 @@
+version: 2
+updates:
+
+ - package-ecosystem: github-actions
+ directory: /
+ schedule:
+ interval: monthly
diff --git a/.github/labeler.yaml b/.github/labeler.yaml
index 5a6590d4aa..6359419ba6 100644
--- a/.github/labeler.yaml
+++ b/.github/labeler.yaml
@@ -1,81 +1,109 @@
llappearance:
- - indra/llappearance/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llappearance/**
llaudio:
- - indra/llaudio/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llaudio/**
llcharacter:
- - indra/llcharacter/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llcharacter/**
llcommon:
- - indra/llcommon/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llcommon/**
llcorehttp:
- - indra/llcorehttp/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llcorehttp/**
llcrashlogger:
- - indra/llcrashlogger/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llcrashlogger/**
llfilesystem:
- - indra/llfilesystem/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llfilesystem/**
llimage:
- - indra/llimage/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llimage/**
llimagej2coj:
- - indra/llimagej2coj/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llimagej2coj/**
llinventory:
- - indra/llinventory/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llinventory/**
llkdu:
- - indra/llkdu/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llkdu/**
llmath:
- - indra/llmath/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llmath/**
llmeshoptimizer:
- - indra/llmeshoptimizer/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llmeshoptimizer/**
llmessage:
- - indra/llmessage/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llmessage/**
llplugin:
- - indra/llplugin/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llplugin/**
llprimitive:
- - indra/llprimitive/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llprimitive/**
llrender:
- - indra/llrender/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llrender/**
llui:
- - indra/llui/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llui/**
llwindow:
- - indra/llwindow/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llwindow/**
llxml:
- - indra/llxml/**/*
+- changed-files:
+ - any-glob-to-any-file: indra/llxml/**
cmake:
- - '**/*.cmake'
- - '**/*/cmake/*'
- - '**/CMakeLists.txt'
+- changed-files:
+ - any-glob-to-any-file:
+ - '**/*.cmake'
+ - '**/*/cmake/*'
+ - '**/CMakeLists.txt'
python:
- - '**/*.py'
+- changed-files:
+ - any-glob-to-any-file: '**/*.py'
c/cpp:
- - '**/*.c'
- - '**/*.cpp'
- - '**/*.cxx'
- - '**/*.h'
- - '**/*.hpp'
- - '**/*.hxx'
- - '**/*.i'
- - '**/*.inl'
- - '**/*.y'
+- changed-files:
+ - any-glob-to-any-file:
+ - '**/*.c'
+ - '**/*.cpp'
+ - '**/*.cxx'
+ - '**/*.h'
+ - '**/*.hpp'
+ - '**/*.hxx'
+ - '**/*.i'
+ - '**/*.inl'
+ - '**/*.y'
-'team:viewer':
- - '*'
+objc:
+- changed-files:
+ - any-glob-to-any-file:
+ - '**/*.m'
+ - '**/*.mm'
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
new file mode 100644
index 0000000000..5fe8870337
--- /dev/null
+++ b/.github/pull_request_template.md
@@ -0,0 +1,37 @@
+## Description
+
+
+
+## Related Issues
+
+- [ ] **Please link to a relevant GitHub issue for additional context.**
+ - **Bug Fix:** Link to an issue that includes reproduction steps and testing guidance.
+ - **Feature/Enhancement:** Link to an issue with a write-up, rationale, and requirements.
+
+Issue Link:
+
+---
+
+## Checklist
+
+Please ensure the following before requesting review:
+
+- [ ] I have provided a clear title and detailed description for this pull request.
+- [ ] If useful, I have included media such as screenshots and video to show off my changes.
+- [ ] The PR is linked to a relevant issue with sufficient context.
+- [ ] I have tested the changes locally and verified they work as intended.
+- [ ] All new and existing tests pass.
+- [ ] Code follows the project's style guidelines.
+- [ ] Documentation has been updated if needed.
+- [ ] Any dependent changes have been merged and published in downstream modules
+- [ ] I have reviewed the [contributing guidelines](https://github.com/secondlife/viewer/blob/develop/CONTRIBUTING.md).
+
+---
+
+## Additional Notes
+
+
diff --git a/.github/workflows/.gitattributes b/.github/workflows/.gitattributes
new file mode 100644
index 0000000000..6dc1cca42a
--- /dev/null
+++ b/.github/workflows/.gitattributes
@@ -0,0 +1 @@
+qatest.yaml -text eol=crlf
diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 60ad7e8fe5..4c8d98ce2f 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -1,6 +1,7 @@
name: Build
on:
+ workflow_dispatch:
pull_request:
push:
branches: ["main", "release/*", "project/*"]
@@ -42,8 +43,8 @@ jobs:
needs: setup
strategy:
matrix:
- runner: [windows-large, macos-15-xlarge]
- configuration: ${{ fromJSON(needs.setup.outputs.configurations) }}
+ runner: ${{ fromJson((github.ref_type == 'tag' && startsWith(github.ref, 'refs/tags/Second_Life')) && '["windows-large","macos-15-xlarge"]' || '["windows-2022","macos-15-xlarge"]') }}
+ configuration: ${{ fromJson(needs.setup.outputs.configurations) }}
runs-on: ${{ matrix.runner }}
outputs:
viewer_channel: ${{ steps.build.outputs.viewer_channel }}
@@ -64,7 +65,7 @@ jobs:
# autobuild-package.xml.
AUTOBUILD_VCS_INFO: "true"
AUTOBUILD_VSVER: "170"
- DEVELOPER_DIR: "/Applications/Xcode_16.1.app/Contents/Developer"
+ DEVELOPER_DIR: "/Applications/Xcode_16.4.app/Contents/Developer"
# Ensure that Linden viewer builds engage Bugsplat.
BUGSPLAT_DB: ${{ needs.setup.outputs.bugsplat_db }}
build_coverity: false
@@ -85,24 +86,23 @@ jobs:
variants: ${{ matrix.configuration }}
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
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
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
repository: secondlife/build-variables
ref: master
path: .build-variables
- name: Checkout master-message-template
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
repository: secondlife/master-message-template
path: .master-message-template
@@ -218,8 +218,10 @@ jobs:
prefix=${ba[0]}
if [ "$prefix" == "project" ]; then
IFS='_' read -ra prj <<< "${ba[1]}"
+ prj_str="${prj[*]}"
# uppercase first letter of each word
- export viewer_channel="Second Life Project ${prj[*]^}"
+ capitalized=$(echo "$prj_str" | awk '{for (i=1; i<=NF; i++) $i = toupper(substr($i,1,1)) substr($i,2); print}')
+ export viewer_channel="Second Life Project $capitalized"
elif [[ "$prefix" == "release" || "$prefix" == "main" ]];
then
export viewer_channel="Second Life Release"
@@ -304,11 +306,11 @@ jobs:
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
needs: build
- runs-on: windows-large
+ runs-on: windows-2022
steps:
- name: Sign and package Windows viewer
if: env.AZURE_KEY_VAULT_URI && env.AZURE_CERT_NAME && env.AZURE_CLIENT_ID && env.AZURE_CLIENT_SECRET && env.AZURE_TENANT_ID
- uses: secondlife/viewer-build-util/sign-pkg-windows@v2
+ uses: secondlife/viewer-build-util/sign-pkg-windows@v2.0.4
with:
vault_uri: "${{ env.AZURE_KEY_VAULT_URI }}"
cert_name: "${{ env.AZURE_CERT_NAME }}"
@@ -360,8 +362,9 @@ jobs:
post-windows-symbols:
env:
- BUGSPLAT_USER: ${{ secrets.BUGSPLAT_USER }}
- BUGSPLAT_PASS: ${{ secrets.BUGSPLAT_PASS }}
+ BUGSPLAT_DATABASE: "${{ secrets.BUGSPLAT_DATABASE }}"
+ SYMBOL_UPLOAD_CLIENT_ID: "${{ secrets.BUGSPLAT_SYMBOL_UPLOAD_CLIENT_ID }}"
+ SYMBOL_UPLOAD_CLIENT_SECRET: "${{ secrets.BUGSPLAT_SYMBOL_UPLOAD_CLIENT_SECRET }}"
needs: build
if: needs.build.outputs.configuration == 'Release'
runs-on: ubuntu-latest
@@ -372,51 +375,56 @@ jobs:
name: Windows-app
path: _artifacts
- name: Download Windows Symbols
- if: env.BUGSPLAT_USER && env.BUGSPLAT_PASS
+ if: env.BUGSPLAT_DATABASE && env.SYMBOL_UPLOAD_CLIENT_ID
uses: actions/download-artifact@v4
with:
name: Windows-symbols
- name: Extract viewer pdb
- if: env.BUGSPLAT_USER && env.BUGSPLAT_PASS
+ if: env.BUGSPLAT_DATABASE && env.SYMBOL_UPLOAD_CLIENT_ID
shell: bash
run: |
tar -xJf "${{ needs.build.outputs.viewer_channel }}.sym.tar.xz" -C _artifacts
- name: Post Windows symbols
- if: env.BUGSPLAT_USER && env.BUGSPLAT_PASS
- uses: secondlife-3p/symbol-upload@v10
+ if: env.BUGSPLAT_DATABASE && env.SYMBOL_UPLOAD_CLIENT_ID
+ uses: BugSplat-Git/symbol-upload@095d163ae9ceb006d286a731dcd35cf6a1b458c8
with:
- username: ${{ env.BUGSPLAT_USER }}
- password: ${{ env.BUGSPLAT_PASS }}
- database: "SecondLife_Viewer_2018"
+ clientId: "${{ env.SYMBOL_UPLOAD_CLIENT_ID }}"
+ clientSecret: "${{ env.SYMBOL_UPLOAD_CLIENT_SECRET }}"
+ database: "${{ env.BUGSPLAT_DATABASE }}"
application: ${{ needs.build.outputs.viewer_channel }}
version: ${{ needs.build.outputs.viewer_version }}
directory: _artifacts
files: "**/{SecondLifeViewer.exe,llwebrtc.dll,*.pdb}"
+ node-version: "22"
+ dumpSyms: false
post-mac-symbols:
env:
- BUGSPLAT_USER: ${{ secrets.BUGSPLAT_USER }}
- BUGSPLAT_PASS: ${{ secrets.BUGSPLAT_PASS }}
+ BUGSPLAT_DATABASE: "${{ secrets.BUGSPLAT_DATABASE }}"
+ SYMBOL_UPLOAD_CLIENT_ID: "${{ secrets.BUGSPLAT_SYMBOL_UPLOAD_CLIENT_ID }}"
+ SYMBOL_UPLOAD_CLIENT_SECRET: "${{ secrets.BUGSPLAT_SYMBOL_UPLOAD_CLIENT_SECRET }}"
needs: build
if: needs.build.outputs.configuration == 'Release'
runs-on: ubuntu-latest
steps:
- name: Download Mac Symbols
- if: env.BUGSPLAT_USER && env.BUGSPLAT_PASS
+ if: env.BUGSPLAT_DATABASE && env.SYMBOL_UPLOAD_CLIENT_ID
uses: actions/download-artifact@v4
with:
name: macOS-symbols
- name: Post Mac symbols
- if: env.BUGSPLAT_USER && env.BUGSPLAT_PASS
- uses: secondlife-3p/symbol-upload@v10
+ if: env.BUGSPLAT_DATABASE && env.SYMBOL_UPLOAD_CLIENT_ID
+ uses: BugSplat-Git/symbol-upload@095d163ae9ceb006d286a731dcd35cf6a1b458c8
with:
- username: ${{ env.BUGSPLAT_USER }}
- password: ${{ env.BUGSPLAT_PASS }}
- database: "SecondLife_Viewer_2018"
+ clientId: "${{ env.SYMBOL_UPLOAD_CLIENT_ID }}"
+ clientSecret: "${{ env.SYMBOL_UPLOAD_CLIENT_SECRET }}"
+ database: "${{ env.BUGSPLAT_DATABASE }}"
application: ${{ needs.build.outputs.viewer_channel }}
version: ${{ needs.build.outputs.viewer_version }} (${{ needs.build.outputs.viewer_version }})
directory: .
files: "**/*.xcarchive.zip"
+ node-version: "22"
+ dumpSyms: false
release:
needs: [setup, build, sign-and-package-windows, sign-and-package-mac]
@@ -455,7 +463,6 @@ jobs:
prerelease: true
generate_release_notes: true
target_commitish: ${{ github.sha }}
- previous_tag: release
append_body: true
fail_on_unmatched_files: true
files: |
diff --git a/.github/workflows/check-pr.yaml b/.github/workflows/check-pr.yaml
new file mode 100644
index 0000000000..08e907e83f
--- /dev/null
+++ b/.github/workflows/check-pr.yaml
@@ -0,0 +1,21 @@
+name: Check PR
+
+on:
+ pull_request:
+ types: [opened, edited, reopened, synchronize]
+
+permissions:
+ contents: read
+
+jobs:
+ check-description:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check PR description
+ uses: actions/github-script@v8
+ with:
+ script: |
+ const description = context.payload.pull_request.body || '';
+ if (description.trim().length < 20) {
+ core.setFailed("❌ PR description is too short. Please provide at least 20 characters.");
+ }
diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml
index 7866f943b5..5b31c584d5 100644
--- a/.github/workflows/cla.yaml
+++ b/.github/workflows/cla.yaml
@@ -23,4 +23,4 @@ jobs:
path-to-signatures: signatures.json
remote-organization-name: secondlife
remote-repository-name: cla-signatures
- allowlist: callum@mbp.localdomain,rye@lindenlab.com
+ allowlist: callum@mbp.localdomain,rye@lindenlab.com,rye,bot*
diff --git a/.github/workflows/label.yaml b/.github/workflows/label.yaml
index 6e41d8aa2d..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@v4
+ - 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 d626eef38d..8f942fa11b 100644
--- a/.github/workflows/pre-commit.yaml
+++ b/.github/workflows/pre-commit.yaml
@@ -11,8 +11,8 @@ jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v4
+ - uses: actions/checkout@v5
+ - uses: actions/setup-python@v6
with:
python-version: 3.x
- - uses: pre-commit/action@v3.0.0
+ - uses: pre-commit/action@v3.0.1
diff --git a/.github/workflows/qatest.yaml b/.github/workflows/qatest.yaml
new file mode 100644
index 0000000000..b6883d88d4
--- /dev/null
+++ b/.github/workflows/qatest.yaml
@@ -0,0 +1,610 @@
+name: Run QA Test # Runs automated tests on self-hosted QA machines
+
+permissions:
+ contents: read
+
+on:
+ workflow_run:
+ workflows: ["Build"]
+ types:
+ - completed
+ workflow_dispatch:
+ inputs:
+ build_id:
+ description: 'Build workflow run ID (e.g. For github.com/secondlife/viewer/actions/runs/1234567890 the ID is 1234567890)'
+ required: true
+ default: '14806728332'
+
+jobs:
+ debug-workflow:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Debug Workflow Variables
+ run: |
+ echo "Workflow Conclusion: ${{ github.event.workflow_run.conclusion }}"
+ echo "Workflow Head Branch: ${{ github.event.workflow_run.head_branch }}"
+ echo "Workflow Run ID: ${{ github.event.workflow_run.id }}"
+ echo "Head Commit Message: ${{ github.event.workflow_run.head_commit.message }}"
+ echo "GitHub Ref: ${{ github.ref }}"
+ echo "GitHub Ref Name: ${{ github.ref_name }}"
+ echo "GitHub Event Name: ${{ github.event_name }}"
+ echo "GitHub Workflow Name: ${{ github.workflow }}"
+
+ install-viewer-and-run-tests:
+ concurrency:
+ group: ${{ github.workflow }}-${{ matrix.runner }}
+ cancel-in-progress: false # Prevents cancellation of in-progress jobs
+
+ strategy:
+ matrix:
+ include:
+ - os: windows
+ runner: qa-windows-atlas
+ artifact: Windows-installer
+ install-path: 'C:\viewer-automation-main'
+ - os: windows
+ runner: qa-windows-asus-dan
+ artifact: Windows-installer
+ install-path: 'C:\viewer-automation-main'
+ - os: windows
+ runner: qa-windows-kurt
+ artifact: Windows-installer
+ install-path: 'C:\viewer-automation-main'
+ - os: mac
+ runner: qa-mac-dan
+ artifact: macOS-installer
+ install-path: '$HOME/Documents/viewer-automation'
+ - os: mac
+ runner: qa-mac-atlas
+ artifact: macOS-installer
+ install-path: '$HOME/Documents/viewer-automation'
+ - os: mac
+ runner: qa-mac-caleb
+ artifact: macOS-installer
+ install-path: '$HOME/Documents/viewer-automation'
+ fail-fast: false
+
+ runs-on: [self-hosted, "${{ matrix.runner }}"]
+ # Run test only on successful builds of Second_Life_X branches or on manual dispatch
+ if: >
+ (github.event_name == 'workflow_run' &&
+ github.event.workflow_run.conclusion == 'success' &&
+ startsWith(github.event.workflow_run.head_branch, 'Second_Life')) ||
+ github.event_name == 'workflow_dispatch'
+
+ steps:
+ # Windows-specific steps
+ - name: Set Build ID
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ if ("${{ github.event_name }}" -eq "workflow_dispatch") {
+ echo "BUILD_ID=${{ github.event.inputs.build_id }}" | Out-File -FilePath $env:GITHUB_ENV -Append
+ echo "ARTIFACTS_URL=https://api.github.com/repos/secondlife/viewer/actions/runs/${{ github.event.inputs.build_id }}/artifacts" | Out-File -FilePath $env:GITHUB_ENV -Append
+ } else {
+ echo "BUILD_ID=${{ github.event.workflow_run.id }}" | Out-File -FilePath $env:GITHUB_ENV -Append
+ echo "ARTIFACTS_URL=https://api.github.com/repos/secondlife/viewer/actions/runs/${{ github.event.workflow_run.id }}/artifacts" | Out-File -FilePath $env:GITHUB_ENV -Append
+ }
+
+ - name: Temporarily Allow PowerShell Scripts (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ Set-ExecutionPolicy RemoteSigned -Scope Process -Force
+
+ - name: Verify viewer-automation-main Exists (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ if (-Not (Test-Path -Path '${{ matrix.install-path }}')) {
+ Write-Host '❌ Error: viewer-automation folder not found on runner!'
+ exit 1
+ }
+ Write-Host '✅ viewer-automation folder is provided.'
+
+ - name: Verify viewer-automation-main is Up-To-Date (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ continue-on-error: true
+ run: |
+ cd ${{ matrix.install-path }}
+ Write-Host "Checking for repository updates..."
+
+ # Check if .git directory exists
+ if (Test-Path -Path ".git") {
+ try {
+ # Save local changes instead of discarding them
+ git stash push -m "Automated stash before update $(Get-Date)"
+ Write-Host "Local changes saved (if any)"
+
+ # Update the repository
+ git pull
+ Write-Host "✅ Repository updated successfully"
+
+ # Try to restore local changes if any were stashed
+ $stashList = git stash list
+ if ($stashList -match "Automated stash before update") {
+ try {
+ git stash pop
+ Write-Host "✅ Local changes restored successfully"
+ } catch {
+ Write-Host "⚠️ Conflict when restoring local changes"
+ # Save the conflicted state in a new branch for later review
+ $branchName = "conflict-recovery-$(Get-Date -Format 'yyyyMMdd-HHmmss')"
+ git checkout -b $branchName
+ Write-Host "✅ Created branch '$branchName' with conflicted state"
+
+ # For test execution, revert to a clean state
+ git reset --hard HEAD
+ Write-Host "✅ Reset to clean state for test execution"
+ }
+ }
+ } catch {
+ Write-Host "⚠️ Could not update repository: $_"
+ Write-Host "Continuing with existing files..."
+ }
+ } else {
+ Write-Host "⚠️ Not a Git repository, using existing files"
+ }
+
+ - name: Verify Python Installation (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ try {
+ $pythonVersion = (python --version)
+ Write-Host "✅ Python found: $pythonVersion"
+ } catch {
+ Write-Host "❌ Error: Python not found in PATH. Please install Python on this runner."
+ exit 1
+ }
+
+ - name: Setup Python Virtual Environment (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
+ cd ${{ matrix.install-path }}
+
+ if (-Not (Test-Path -Path ".venv")) {
+ Write-Host "Creating virtual environment..."
+ python -m venv .venv
+ } else {
+ Write-Host "Using existing virtual environment"
+ }
+
+ # Direct environment activation to avoid script execution issues
+ $env:VIRTUAL_ENV = "$PWD\.venv"
+ $env:PATH = "$env:VIRTUAL_ENV\Scripts;$env:PATH"
+
+ # Install dependencies
+ if (Test-Path -Path "requirements.txt") {
+ Write-Host "Installing dependencies from requirements.txt..."
+ pip install -r requirements.txt
+
+ # Install Playwright browsers - add this line
+ Write-Host "Installing Playwright browsers..."
+ python -m playwright install
+ } else {
+ pip install outleap requests behave playwright
+ # Install Playwright browsers - add this line
+ Write-Host "Installing Playwright browsers..."
+ python -m playwright install
+ }
+
+ - name: Fetch & Download Installer Artifact (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ $BUILD_ID = "${{ env.BUILD_ID }}"
+ $ARTIFACTS_URL = "${{ env.ARTIFACTS_URL }}"
+
+ # Fetch the correct artifact URL
+ $response = Invoke-RestMethod -Headers @{Authorization="token ${{ secrets.GITHUB_TOKEN }}" } -Uri $ARTIFACTS_URL
+ $ARTIFACT_NAME = ($response.artifacts | Where-Object { $_.name -eq "${{ matrix.artifact }}" }).archive_download_url
+
+ if (-Not $ARTIFACT_NAME) {
+ Write-Host "❌ Error: ${{ matrix.artifact }} artifact not found!"
+ exit 1
+ }
+
+ Write-Host "✅ Artifact found: $ARTIFACT_NAME"
+
+ # Secure download path
+ $DownloadPath = "$env:TEMP\secondlife-build-$BUILD_ID"
+ New-Item -ItemType Directory -Path $DownloadPath -Force | Out-Null
+ $InstallerPath = "$DownloadPath\installer.zip"
+
+ # Download the ZIP
+ Invoke-WebRequest -Uri $ARTIFACT_NAME -Headers @{Authorization="token ${{ secrets.GITHUB_TOKEN }}"} -OutFile $InstallerPath
+
+ # Ensure download succeeded
+ if (-Not (Test-Path $InstallerPath)) {
+ Write-Host "❌ Error: Failed to download ${{ matrix.artifact }}.zip"
+ exit 1
+ }
+
+ # Set the path for other steps
+ echo "DOWNLOAD_PATH=$DownloadPath" | Out-File -FilePath $env:GITHUB_ENV -Append
+
+ - name: Extract Installer & Locate Executable (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ $BUILD_ID = "${{ env.BUILD_ID }}"
+ $ExtractPath = "${{ env.DOWNLOAD_PATH }}"
+ $InstallerZip = "$ExtractPath\installer.zip"
+
+ # Print paths for debugging
+ Write-Host "Extract Path: $ExtractPath"
+ Write-Host "Installer ZIP Path: $InstallerZip"
+
+ # Verify ZIP exists before extracting
+ if (-Not (Test-Path $InstallerZip)) {
+ Write-Host "❌ Error: ZIP file not found at $InstallerZip!"
+ exit 1
+ }
+
+ Write-Host "✅ ZIP file exists and is valid. Extracting..."
+
+ Expand-Archive -Path $InstallerZip -DestinationPath $ExtractPath -Force
+
+ # Find installer executable
+ $INSTALLER_PATH = (Get-ChildItem -Path $ExtractPath -Filter '*.exe' -Recurse | Select-Object -First 1).FullName
+
+ if (-Not $INSTALLER_PATH -or $INSTALLER_PATH -eq "") {
+ Write-Host "❌ Error: No installer executable found in the extracted files!"
+ Write-Host "📂 Extracted Files:"
+ Get-ChildItem -Path $ExtractPath -Recurse | Format-Table -AutoSize
+ exit 1
+ }
+
+ Write-Host "✅ Installer found: $INSTALLER_PATH"
+ echo "INSTALLER_PATH=$INSTALLER_PATH" | Out-File -FilePath $env:GITHUB_ENV -Append
+
+ - name: Install Second Life (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ # Windows - Use Task Scheduler to bypass UAC
+ $action = New-ScheduledTaskAction -Execute "${{ env.INSTALLER_PATH }}" -Argument "/S"
+ $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
+ $task = New-ScheduledTask -Action $action -Principal $principal
+ Register-ScheduledTask -TaskName "SilentSLInstaller" -InputObject $task -Force
+ Start-ScheduledTask -TaskName "SilentSLInstaller"
+
+ - name: Wait for Installation to Complete (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ Write-Host "Waiting for the Second Life installer to finish..."
+ do {
+ Start-Sleep -Seconds 5
+ $installerProcess = Get-Process | Where-Object { $_.Path -eq "${{ env.INSTALLER_PATH }}" }
+ } while ($installerProcess)
+
+ Write-Host "✅ Installation completed!"
+
+ - name: Cleanup After Installation (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ # Cleanup Task Scheduler Entry
+ Unregister-ScheduledTask -TaskName "SilentSLInstaller" -Confirm:$false
+ Write-Host "✅ Task Scheduler entry removed."
+
+ # Delete Installer ZIP
+ $DeletePath = "${{ env.DOWNLOAD_PATH }}\installer.zip"
+
+ Write-Host "Checking if installer ZIP exists: $DeletePath"
+
+ # Ensure the ZIP file exists before trying to delete it
+ if (Test-Path $DeletePath) {
+ Remove-Item -Path $DeletePath -Force
+ Write-Host "✅ Successfully deleted: $DeletePath"
+ } else {
+ Write-Host "⚠️ Warning: ZIP file does not exist, skipping deletion."
+ }
+
+ - name: Run QA Test Script (Windows)
+ if: matrix.os == 'windows'
+ shell: pwsh
+ run: |
+ Write-Host "Running QA Test script on Windows runner: ${{ matrix.runner }}..."
+ cd ${{ matrix.install-path }}
+
+ # Activate virtual environment
+ Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
+ $env:VIRTUAL_ENV = "$PWD\.venv"
+ $env:PATH = "$env:VIRTUAL_ENV\Scripts;$env:PATH"
+
+ # Set runner name as environment variable
+ $env:RUNNER_NAME = "${{ matrix.runner }}"
+
+ # Run the test script
+ python runTests.py
+
+ # Mac-specific steps
+ - name: Set Build ID (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
+ echo "BUILD_ID=${{ github.event.inputs.build_id }}" >> $GITHUB_ENV
+ echo "ARTIFACTS_URL=https://api.github.com/repos/secondlife/viewer/actions/runs/${{ github.event.inputs.build_id }}/artifacts" >> $GITHUB_ENV
+ else
+ echo "BUILD_ID=${{ github.event.workflow_run.id }}" >> $GITHUB_ENV
+ echo "ARTIFACTS_URL=https://api.github.com/repos/secondlife/viewer/actions/runs/${{ github.event.workflow_run.id }}/artifacts" >> $GITHUB_ENV
+ fi
+
+ - name: Verify viewer-automation-main Exists (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ if [ ! -d "${{ matrix.install-path }}" ]; then
+ echo "❌ Error: viewer-automation folder not found on runner!"
+ exit 1
+ fi
+ echo "✅ viewer-automation is provided."
+
+ - name: Verify viewer-automation-main is Up-To-Date (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ continue-on-error: true
+ run: |
+ cd ${{ matrix.install-path }}
+ echo "Checking for repository updates..."
+
+ # Check if .git directory exists
+ if [ -d ".git" ]; then
+ # Save local changes instead of discarding them
+ git stash push -m "Automated stash before update $(date)"
+ echo "Local changes saved (if any)"
+
+ # Update the repository
+ git pull || echo "⚠️ Could not update repository"
+ echo "✅ Repository updated (or attempted update)"
+
+ # Try to restore local changes if any were stashed
+ if git stash list | grep -q "Automated stash before update"; then
+ # Try to pop the stash, but be prepared for conflicts
+ if ! git stash pop; then
+ echo "⚠️ Conflict when restoring local changes"
+ # Save the conflicted state in a new branch for later review
+ branch_name="conflict-recovery-$(date +%Y%m%d-%H%M%S)"
+ git checkout -b "$branch_name"
+ echo "✅ Created branch '$branch_name' with conflicted state"
+
+ # For test execution, revert to a clean state
+ git reset --hard HEAD
+ echo "✅ Reset to clean state for test execution"
+ else
+ echo "✅ Local changes restored successfully"
+ fi
+ fi
+ else
+ echo "⚠️ Not a Git repository, using existing files"
+ fi
+
+ - name: Verify Python Installation (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ if command -v python3 &> /dev/null; then
+ PYTHON_VERSION=$(python3 --version)
+ echo "✅ Python found: $PYTHON_VERSION"
+ else
+ echo "❌ Error: Python3 not found in PATH. Please install Python on this runner."
+ exit 1
+ fi
+
+ - name: Setup Python Virtual Environment (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ cd ${{ matrix.install-path }}
+
+ # Create virtual environment if it doesn't exist
+ if [ ! -d ".venv" ]; then
+ echo "Creating virtual environment..."
+ python3 -m venv .venv
+ else
+ echo "Using existing virtual environment"
+ fi
+
+ # Activate virtual environment
+ source .venv/bin/activate
+
+ # Install dependencies
+ if [ -f "requirements.txt" ]; then
+ pip install -r requirements.txt
+ echo "✅ Installed dependencies from requirements.txt"
+
+ # Install Playwright browsers - add this line
+ echo "Installing Playwright browsers..."
+ python -m playwright install
+ else
+ pip install outleap requests behave playwright
+ echo "⚠️ requirements.txt not found, installed basic dependencies"
+
+ # Install Playwright browsers - add this line
+ echo "Installing Playwright browsers..."
+ python -m playwright install
+ fi
+
+ - name: Fetch & Download Installer Artifact (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ # Mac-specific Bash commands
+ response=$(curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -s ${{ env.ARTIFACTS_URL }})
+ ARTIFACT_NAME=$(echo $response | jq -r '.artifacts[] | select(.name=="${{ matrix.artifact }}") | .archive_download_url')
+
+ if [ -z "$ARTIFACT_NAME" ]; then
+ echo "❌ Error: ${{ matrix.artifact }} artifact not found!"
+ exit 1
+ fi
+
+ echo "✅ Artifact found: $ARTIFACT_NAME"
+
+ # Secure download path
+ DOWNLOAD_PATH="/tmp/secondlife-build-${{ env.BUILD_ID }}"
+ mkdir -p $DOWNLOAD_PATH
+ INSTALLER_PATH="$DOWNLOAD_PATH/installer.zip"
+
+ # Download the ZIP
+ curl -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" -L $ARTIFACT_NAME -o $INSTALLER_PATH
+
+ # Ensure download succeeded
+ if [ ! -f "$INSTALLER_PATH" ]; then
+ echo "❌ Error: Failed to download ${{ matrix.artifact }}.zip"
+ exit 1
+ fi
+
+ # Set the path for other steps
+ echo "DOWNLOAD_PATH=$DOWNLOAD_PATH" >> $GITHUB_ENV
+
+ - name: Extract Installer & Locate Executable (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ EXTRACT_PATH="${{ env.DOWNLOAD_PATH }}"
+ INSTALLER_ZIP="$EXTRACT_PATH/installer.zip"
+
+ # Debug output
+ echo "Extract Path: $EXTRACT_PATH"
+ echo "Installer ZIP Path: $INSTALLER_ZIP"
+
+ # Verify ZIP exists
+ if [ ! -f "$INSTALLER_ZIP" ]; then
+ echo "❌ Error: ZIP file not found at $INSTALLER_ZIP!"
+ exit 1
+ fi
+
+ echo "✅ ZIP file exists and is valid. Extracting..."
+
+ # Extract the ZIP
+ unzip -o "$INSTALLER_ZIP" -d "$EXTRACT_PATH"
+
+ # Find DMG file
+ INSTALLER_PATH=$(find "$EXTRACT_PATH" -name "*.dmg" -type f | head -1)
+
+ if [ -z "$INSTALLER_PATH" ]; then
+ echo "❌ Error: No installer DMG found in the extracted files!"
+ echo "📂 Extracted Files:"
+ ls -la "$EXTRACT_PATH"
+ exit 1
+ fi
+
+ echo "✅ Installer found: $INSTALLER_PATH"
+ echo "INSTALLER_PATH=$INSTALLER_PATH" >> $GITHUB_ENV
+
+ - name: Install Second Life (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ # Mac installation
+ echo "Mounting DMG installer..."
+ MOUNT_POINT="/tmp/secondlife-dmg"
+ mkdir -p "$MOUNT_POINT"
+
+ # Mount the DMG
+ hdiutil attach "$INSTALLER_PATH" -mountpoint "$MOUNT_POINT" -nobrowse
+
+ echo "✅ DMG mounted at $MOUNT_POINT"
+
+ echo "Installing application to default location from DMG..."
+
+ # Find the .app bundle in the DMG
+ APP_PATH=$(find "$MOUNT_POINT" -name "*.app" -type d | head -1)
+
+ if [ -z "$APP_PATH" ]; then
+ echo "❌ Error: No .app bundle found in the mounted DMG!"
+ exit 1
+ fi
+
+ APP_NAME=$(basename "$APP_PATH")
+ DEST_PATH="/Applications/$APP_NAME"
+
+ # Handle existing installation
+ if [ -d "$DEST_PATH" ]; then
+ echo "Found existing installation at: $DEST_PATH"
+ echo "Moving existing installation to trash..."
+
+ # Move to trash instead of force removing
+ TRASH_PATH="$HOME/.Trash/$(date +%Y%m%d_%H%M%S)_$APP_NAME"
+ mv "$DEST_PATH" "$TRASH_PATH" || {
+ echo "⚠️ Could not move to trash, trying direct removal..."
+ rm -rf "$DEST_PATH" || {
+ echo "❌ Could not remove existing installation"
+ echo "Please manually remove: $DEST_PATH"
+ exit 1
+ }
+ }
+
+ echo "✅ Existing installation handled successfully"
+ fi
+
+ # Copy the .app to /Applications
+ echo "Copying app from: $APP_PATH"
+ echo "To destination: /Applications/"
+ cp -R "$APP_PATH" /Applications/
+
+ # Verify the app was copied successfully
+ if [ ! -d "$DEST_PATH" ]; then
+ echo "❌ Error: Failed to install application to /Applications!"
+ exit 1
+ fi
+
+ echo "✅ Application installed successfully to /Applications"
+
+ # Save mount point for cleanup
+ echo "MOUNT_POINT=$MOUNT_POINT" >> $GITHUB_ENV
+
+ - name: Wait for Installation to Complete (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ echo "Waiting for installation to complete..."
+ # Sleep to allow installation to finish (adjust as needed)
+ sleep 30
+ echo "✅ Installation completed"
+
+ - name: Cleanup After Installation (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ # Mac cleanup
+ # Unmount the DMG
+ echo "Unmounting DMG..."
+ hdiutil detach "${{ env.MOUNT_POINT }}" -force
+
+ # Clean up temporary files
+ echo "Cleaning up temporary files..."
+ rm -rf "${{ env.DOWNLOAD_PATH }}"
+ rm -rf "${{ env.MOUNT_POINT }}"
+
+ echo "✅ Cleanup completed"
+
+ - name: Run QA Test Script (Mac)
+ if: matrix.os == 'mac'
+ shell: bash
+ run: |
+ echo "Running QA Test script on Mac runner: ${{ matrix.runner }}..."
+ cd ${{ matrix.install-path }}
+
+ # Activate virtual environment
+ source .venv/bin/activate
+
+ # Set runner name as environment variable
+ export RUNNER_NAME="${{ matrix.runner }}"
+
+ # Run the test script
+ python runTests.py
+
+ # - name: Upload Test Results
+ # if: always()
+ # uses: actions/upload-artifact@v4
+ # with:
+ # name: test-results-${{ matrix.runner }}
+ # path: ${{ matrix.install-path }}/regressionTest/test_results.html
diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml
index f77151a815..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@v6
+ - 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/.gitignore b/.gitignore
index 3b3666af84..c4accf37b5 100755
--- a/.gitignore
+++ b/.gitignore
@@ -26,7 +26,6 @@ debian/files
debian/secondlife-appearance-utility*
debian/secondlife-viewer*
indra/.distcc
-indra/cmake/*
indra/out/*
indra/packages/*
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 1dd7c8c800..d1dcc93976 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -7,14 +7,14 @@ repos:
- id: no-trigraphs
- id: copyright
- id: end-of-file
- files: \.(cpp|c|h|py|glsl|cmake|txt)$
+ files: \.(cpp|c|m|mm|h|py|glsl|cmake|txt)$
exclude: language.txt
- id: indent-with-spaces
- files: \.(cpp|c|h|inl|py|glsl|cmake)$
+ files: \.(cpp|c|m|mm|h|inl|py|glsl|cmake)$
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.4.0
+ rev: v6.0.0
hooks:
- id: check-xml
- id: mixed-line-ending
- id: trailing-whitespace
- files: \.(cpp|c|h|inl|py|glsl|cmake|yaml|sh)$
+ files: \.(cpp|c|m|mm|h|inl|py|glsl|cmake|yaml|sh)$
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6bd8a2b74c..9f38432ff7 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,6 +8,7 @@ changes.
## Table of contents
- [Communication](#communication)
+- [What to work on](#what-to-work-on)
- [Reporting bugs and requesting features](#reporting-bugs-and-requesting-features)
- [Contributing pull requests](#contributing-pull-requests)
@@ -32,8 +33,19 @@ developer-to-developer or support.
- [Official forums][] exist for many topics including content creation,
scripting, social topics and more.
- The [opensource-dev mailing list][] is useful for announcements and
- discussion between viewer maintainers.
+ discussion between viewer maintainers.
+- Our [discord channel](https://discord.com/channels/677442248157167619/1357059883400167585) is available for real-time discussion.
+## What to work on
+
+If you're looking for ways to contribute code, here are some ways to get involved:
+
+- Explore existing issues on the [GitHub issue tracker](https://github.com/secondlife/viewer/issues) to find known problems, bugs, or enhancement discussions.
+- File new issues if you’ve discovered a bug or have a specific idea to propose. If your idea is user-facing, consider submitting it through feedback.secondlife.com so it can reach a broader audience and be prioritized by Linden Lab staff.
+- Look for the [help wanted](https://github.com/secondlife/viewer/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22) label. These are tasks the core maintainers have specifically identified as good candidates for community help.
+- Talk to maintainers before starting significant work. Even if an issue exists, discussing your approach first ensures alignment with ongoing efforts and increases the likelihood your pull request will be accepted.
+
+Collaboration is essential. We encourage contributors to work closely with the Second Life engineering team and other developers to keep work consistent and maintainable.
## Reporting bugs and requesting features
diff --git a/autobuild.xml b/autobuild.xml
index 1fa5182ef5..5a4c04324b 100644
--- a/autobuild.xml
+++ b/autobuild.xml
@@ -46,11 +46,11 @@
archive
name
darwin64
@@ -60,11 +60,11 @@
archive
name
linux64
@@ -74,11 +74,11 @@
archive
name
windows64
@@ -91,7 +91,7 @@
copyright
Copyright © 2012 The Apache Software Foundation, Licensed under the Apache License, Version 2.0.
version
- 1.7.4-10338381102
+ 1.7.5-18696779749
name
apr_suite
description
@@ -99,16 +99,6 @@
boost
+ license
+ boost 1.0
+ license_file
+ LICENSES/boost.txt
+ copyright
+ (see individual source files)
version
1.86
+ name
+ boost
+ description
+ Boost C++ Libraries
bugsplat
@@ -166,11 +166,11 @@
archive
hash
- cd1f1d55a2488657ec2253774b3a414621f81b24
+ 9bcafdd7e1df6b92096fa850627d4f3437630d4a
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-bugsplat/releases/download/v1.1.5-71fc41e/bugsplat-1.1.1-9599607655-darwin64-9599607655.tar.zst
+ https://github.com/secondlife/3p-bugsplat/releases/download/v1.2.6-a475cbb/bugsplat-1.2.6-19430122611-darwin64-19430122611.tar.zst
name
darwin64
@@ -180,11 +180,11 @@
archive
hash
- 9fb0615d17988bd89a2e5ae6d4d19e150afb54a9
+ 4e9f0c1cdbc1cebf6185ecc45228ced7f9af1532
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-bugsplat/releases/download/v1.1.5-71fc41e/bugsplat-5.0.1.0-9599607655-windows64-9599607655.tar.zst
+ https://github.com/secondlife/3p-bugsplat/releases/download/v1.2.6-a475cbb/bugsplat-6.1.1.0-19430122611-windows64-19430122611.tar.zst
name
windows64
@@ -205,14 +205,6 @@
colladadom
- copyright
- Copyright 2006 Sony Computer Entertainment Inc.
- license
- SCEA
- license_file
- LICENSES/collada.txt
- name
- colladadom
platforms
darwin64
@@ -220,11 +212,11 @@
archive
hash
- 18b46ce8ebb5ae6ef6527b4e95408433e29ad3f4
+ bf2fe4e8272e990bc8687b3b37bf4bb2b2ad6eb4
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r8/colladadom-2.3.0-r8-darwin64-10476582237.tar.zst
+ https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r10/colladadom-2.3.0-r10-darwin64-13259816660.tar.zst
name
darwin64
@@ -234,11 +226,11 @@
archive
hash
- c088fe0be9ce7e42983c3c7708abe4ac8bd5a894
+ 118e509ca464182ef4b94ee8c4aa5b14a6c52a94
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r8/colladadom-2.3.0-r8-linux64-10476582237.tar.zst
+ https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r10/colladadom-2.3.0-r10-linux64-13259816660.tar.zst
name
linux64
@@ -248,18 +240,26 @@
archive
hash
- 8bfa9f1a78d077f3bd422f14ae360150b98c82f9
+ d7aee1b2ec17bd88a2c27359281b58a11ec52d48
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r8/colladadom-2.3.0-r8-windows64-10476582237.tar.zst
+ https://github.com/secondlife/3p-colladadom/releases/download/v2.3-r10/colladadom-2.3.0-r10-windows64-13259816660.tar.zst
name
windows64
+ license
+ SCEA
+ license_file
+ LICENSES/collada.txt
+ copyright
+ Copyright 2006 Sony Computer Entertainment Inc.
version
- 2.3.0-r8
+ 2.3.0-r10
+ name
+ colladadom
cubemaptoequirectangular
@@ -290,6 +290,8 @@
url
https://github.com/secondlife/3p-cubemap_to_eqr_js/releases/download/v1.1.0-d7afe27/cubemaptoequirectangular-1.1.0-linux64-d7afe27.tar.zst
+ name
+ linux64
windows64
@@ -326,11 +328,11 @@
archive
hash
- 9c74adfd217fcc04869ef574078bc56a4a1380f3
+ e742b1e2d0a58d607b023bf55411041ac65e8a76
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r1/curl-7.54.1-10342910827-darwin64-10342910827.tar.zst
+ https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r3/curl-7.54.1-13259824618-darwin64-13259824618.tar.zst
name
darwin64
@@ -340,11 +342,11 @@
archive
hash
- 325ad581a1ba99fbc1e74d48481e07546eaf1e0e
+ 49621c70f385d37c95bcb69a9a24d86ac25f4781
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r1/curl-7.54.1-10342910827-linux64-10342910827.tar.zst
+ https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r3/curl-7.54.1-13259824618-linux64-13259824618.tar.zst
name
linux64
@@ -354,11 +356,11 @@
archive
hash
- 794480208e72a928552760cd048438b90aa1c80d
+ 2522201692116cf0adb7203e169be9126885108c
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r1/curl-7.54.1-10342910827-windows64-10342910827.tar.zst
+ https://github.com/secondlife/3p-curl/releases/download/v7.54.1-r3/curl-7.54.1-13259824618-windows64-13259824618.tar.zst
name
windows64
@@ -371,7 +373,7 @@
copyright
Copyright (c) 1996 - 2014, Daniel Stenberg, (daniel@haxx.se).
version
- 7.54.1-10342910827
+ 7.54.1-13259824618
name
curl
description
@@ -441,16 +443,6 @@
dullahan
- copyright
- Copyright (c) 2017, Linden Research, Inc.
- description
- A headless browser SDK that uses the Chromium Embedded Framework (CEF). It is designed to make it easier to write applications that render modern web content directly to a memory buffer, inject synthesized mouse and keyboard events as well as interact with web based features like JavaScript or cookies.
- license
- MPL
- license_file
- LICENSES/LICENSE.txt
- name
- dullahan
platforms
darwin64
@@ -458,11 +450,11 @@
archive
hash
- 7fde76e3f0e62d0e0593b6157f4d740ecef2429d
+ 126e0fa4c16dfd433c9fb7d1d242da98f213d933
hash_algorithm
sha1
url
- https://github.com/secondlife/dullahan/releases/download/v1.14.0-r3/dullahan-1.14.0.202408091638_118.4.1_g3dd6078_chromium-118.0.5993.54-darwin64-10322607516.tar.zst
+ https://github.com/secondlife/dullahan/releases/download/v1.24.0-CEF_139.0.40/dullahan-1.24.0.202510081737_139.0.40_g465474a_chromium-139.0.7258.139-darwin64-18353103947.tar.zst
name
darwin64
@@ -486,18 +478,28 @@
archive
hash
- 4124c79d8b0e319877ffa4c12581d5c1318b4d93
+ 20de62c9e57d9e6539c1e2437ec4b46c3ca237bc
hash_algorithm
sha1
url
- https://github.com/secondlife/dullahan/releases/download/v1.14.0-r3/dullahan-1.14.0.202408091639_118.4.1_g3dd6078_chromium-118.0.5993.54-windows64-10322607516.tar.zst
+ https://github.com/secondlife/dullahan/releases/download/v1.24.0-CEF_139.0.40/dullahan-1.24.0.202510081738_139.0.40_g465474a_chromium-139.0.7258.139-windows64-18353103947.tar.zst
name
windows64
+ license
+ MPL
+ license_file
+ LICENSES/LICENSE.txt
+ copyright
+ Copyright (c) 2017, Linden Research, Inc.
version
- 1.14.0.202408091639_118.4.1_g3dd6078_chromium-118.0.5993.54
+ 1.24.0.202510081737_139.0.40_g465474a_chromium-139.0.7258.139
+ name
+ dullahan
+ description
+ A headless browser SDK that uses the Chromium Embedded Framework (CEF). It is designed to make it easier to write applications that render modern web content directly to a memory buffer, inject synthesized mouse and keyboard events as well as interact with web based features like JavaScript or cookies.
emoji_shortcodes
@@ -542,11 +544,11 @@
archive
hash
- 8cc4f38fd809d9ff5d8ca617d7e068eb236f4162
+ e0ba69946f2203c03faf89c1f6d5bbc48d88d2a9
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-expat/releases/download/v2.6.2-r5/expat-2.6.2-r5-darwin64-10337781902.tar.zst
+ https://github.com/secondlife/3p-expat/releases/download/v2.6.4-r1/expat-2.6.4-r1-darwin64-11943227858.tar.zst
name
darwin64
@@ -556,11 +558,11 @@
archive
hash
- d7f3bbfd65fce365c3cd5be9ab72072580408dec
+ 13483477c1f8b4bad9055fba561c64137453c3da
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-expat/releases/download/v2.6.2-r5/expat-2.6.2-r5-linux64-10337781902.tar.zst
+ https://github.com/secondlife/3p-expat/releases/download/v2.6.4-r1/expat-2.6.4-r1-linux64-11943227858.tar.zst
name
linux64
@@ -570,11 +572,11 @@
archive
hash
- f11d91205bb753d7389a73e629627b200219c62f
+ 542af7d8bb8de3297c80c23a771bbcb513a630b7
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-expat/releases/download/v2.6.2-r5/expat-2.6.2-r5-windows64-10337781902.tar.zst
+ https://github.com/secondlife/3p-expat/releases/download/v2.6.4-r1/expat-2.6.4-r1-windows64-11943227858.tar.zst
name
windows64
@@ -587,7 +589,7 @@
copyright
Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper - Copyright (c) 2001-2022 Expat maintainers.
version
- 2.6.2-r5
+ 2.6.4-r1
name
expat
description
@@ -625,16 +627,6 @@
freetype
- copyright
- Copyright 2006, 2007, 2008, 2009, 2010 by David Turner, Robert Wilhelm, and Werner Lemberg.
- description
- Font rendering library
- license
- FreeType
- license_file
- LICENSES/freetype.txt
- name
- freetype
platforms
darwin64
@@ -642,11 +634,11 @@
archive
hash
- 51ad743c8943602913eedd2b6e2309abf46849d8
+ 5e6c7b9aaf73d90d7feab846a4024193c48eff6c
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-cb2e120/freetype-2.13.3-cb2e120-darwin64-10475886095.tar.zst
+ https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-r3/freetype-2.13.3-r3-darwin64-13259804885.tar.zst
name
darwin64
@@ -656,11 +648,11 @@
archive
hash
- bc27e272e004dc2fc573550e8c1cd8b4ad07f5b2
+ a9a3c371958e64a49b07d7be8f59218dfd6b0352
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-cb2e120/freetype-2.13.3-cb2e120-linux64-10475886095.tar.zst
+ https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-r3/freetype-2.13.3-r3-linux64-13259804885.tar.zst
name
linux64
@@ -670,18 +662,28 @@
archive
hash
- 01971b998122a17c97e3616c428cc77077a0c39a
+ ad7fbc4a01607ec43d86035a49dadd43d6f2a4e5
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-cb2e120/freetype-2.13.3-cb2e120-windows64-10475886095.tar.zst
+ https://github.com/secondlife/3p-freetype/releases/download/v2.13.3-r3/freetype-2.13.3-r3-windows64-13259804885.tar.zst
name
windows64
+ license
+ FreeType
+ license_file
+ LICENSES/freetype.txt
+ copyright
+ Copyright 2006, 2007, 2008, 2009, 2010 by David Turner, Robert Wilhelm, and Werner Lemberg.
version
- 2.13.3-cb2e120
+ 2.13.3-r3
+ name
+ freetype
+ description
+ Font rendering library
glext
@@ -916,11 +918,11 @@
archive
hash
- f271809c0d4244128fb52a71226a4d7674e14e0a
+ b05374300cdd40c381614f2ee4497de340eda991
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-jpeg_encoder_js/releases/download/v1.0-9165e47/jpegencoderbasic-1.0-darwin64-9165e47.tar.zst
+ https://github.com/secondlife/3p-jpeg_encoder_js/releases/download/v1.0-790015a/jpegencoderbasic-1.0-darwin64-790015a.tar.zst
name
darwin64
@@ -930,23 +932,25 @@
archive
hash
- 35d6a617444fde9c8a5e998ef29dc43b95747637
+ 23daab838f4b8f92e5dc1a2f6c568cb7b0cb43b7
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-jpeg_encoder_js/releases/download/v1.0-9165e47/jpegencoderbasic-1.0-linux64-9165e47.tar.zst
+ https://github.com/secondlife/3p-jpeg_encoder_js/releases/download/v1.0-790015a/jpegencoderbasic-1.0-linux64-790015a.tar.zst
+ name
+ linux64
windows64
archive
hash
- 8ec22e9fc8734ba3d1826f4b88171a6017cc8676
+ 23e8ba22aadf88d249a21844bfcdd01138c05937
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-jpeg_encoder_js/releases/download/v1.0-9165e47/jpegencoderbasic-1.0-windows64-9165e47.tar.zst
+ https://github.com/secondlife/3p-jpeg_encoder_js/releases/download/v1.0-790015a/jpegencoderbasic-1.0-windows64-790015a.tar.zst
name
windows64
@@ -972,11 +976,11 @@
archive
hash
- 34cf4fdbbc999e67b0528f7ca3c7f31f35267ecf
+ 10f14875ce5c7f5028217c8b7468733190fd333d
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libjpeg-turbo/releases/download/v3.0.3-r2/libjpeg_turbo-3.0.3-r2-windows64-10341191820.tar.zst
+ https://github.com/secondlife/3p-libjpeg-turbo/releases/download/v3.0.4-r1/libjpeg_turbo-3.0.4-r1-windows64-11968659895.tar.zst
name
windows64
@@ -986,11 +990,11 @@
archive
hash
- 5ff05a0e5ed0aba1514b84d3c2edaf70c18738b5
+ d3b1b0fde28c8cf0c33fed167dba87bba5c6cc64
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libjpeg-turbo/releases/download/v3.0.3-r2/libjpeg_turbo-3.0.3-r2-linux64-10341191820.tar.zst
+ https://github.com/secondlife/3p-libjpeg-turbo/releases/download/v3.0.4-r1/libjpeg_turbo-3.0.4-r1-linux64-11968659895.tar.zst
name
linux64
@@ -1000,11 +1004,11 @@
archive
hash
- 7c38eabc050b4a6bdb183a1d7a38da885341049c
+ 79e78cbaaec9a99c0ae4a5cdd4a98535c8fa3c6d
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libjpeg-turbo/releases/download/v3.0.3-r2/libjpeg_turbo-3.0.3-r2-darwin64-10341191820.tar.zst
+ https://github.com/secondlife/3p-libjpeg-turbo/releases/download/v3.0.4-r1/libjpeg_turbo-3.0.4-r1-darwin64-11968659895.tar.zst
name
darwin64
@@ -1017,7 +1021,7 @@
copyright
Copyright (C)2009-2024 D. R. Commander. All Rights Reserved. Copyright (C)2015 Viktor Szathmáry. All Rights Reserved.
version
- 3.0.3-r2
+ 3.0.4-r1
name
libjpeg-turbo
canonical_repo
@@ -1036,11 +1040,11 @@
creds
github
hash
- ad72fa1d103df777906f0d98f3e882b9916aeada
+ da318f0813e4126d90e35b22a8dce235e908707a
hash_algorithm
sha1
url
- https://api.github.com/repos/secondlife/3p-kdu/releases/assets/136774118
+ https://api.github.com/repos/secondlife/3p-kdu/releases/assets/208381808
name
darwin64
@@ -1052,11 +1056,11 @@
creds
github
hash
- e46e4ac93a237b5c4a14183766f76ba5d58935a2
+ 1ba58cf884726dfdf02a7662d52f1befe3f16d44
hash_algorithm
sha1
url
- https://api.github.com/repos/secondlife/3p-kdu/releases/assets/136774125
+ https://api.github.com/repos/secondlife/3p-kdu/releases/assets/208381812
name
linux64
@@ -1068,11 +1072,11 @@
creds
github
hash
- bb37557f78c72b26580a521f8b8dabfa1b34e6e6
+ e8d693089b9ecd15b6644f13ada7ae7c317944df
hash_algorithm
sha1
url
- https://api.github.com/repos/secondlife/3p-kdu/releases/assets/136774126
+ https://api.github.com/repos/secondlife/3p-kdu/releases/assets/208381814
name
windows64
@@ -1084,11 +1088,11 @@
creds
github
hash
- 711b82f9f588d3a125af7dcd8c81f93d9c343a7d
+ 85e294becce8b2ac5d2e5e052b0e21ff865d1108
hash_algorithm
sha1
url
- https://api.github.com/repos/secondlife/3p-kdu/releases/assets/136774121
+ https://api.github.com/repos/secondlife/3p-kdu/releases/assets/208381806
name
linux
@@ -1101,7 +1105,7 @@
copyright
Kakadu software
version
- 7.10.4.4b9ec5f
+ 8.4.1.11976899217
name
kdu
description
@@ -1116,11 +1120,11 @@
archive
hash
- e71ae7a645603fe967a69aa5beb5b3009185e177
+ 91acd05f450162b07ca2f68094778c483d28128d
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libhunspell/releases/download/v1.7.2-r1/libhunspell-1.7.2.10207243663-darwin64-10207243663.tar.zst
+ https://github.com/secondlife/3p-libhunspell/releases/download/v1.7.2-r2/libhunspell-1.7.2.11968900321-darwin64-11968900321.tar.zst
name
darwin64
@@ -1130,11 +1134,11 @@
archive
hash
- 275ffb7f60064d8008aed8406f80f34229f651fc
+ 10e5b5d793c3c5cb5335dea89734302bda5a9f59
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libhunspell/releases/download/v1.7.2-r1/libhunspell-1.7.2.10207243663-linux64-10207243663.tar.zst
+ https://github.com/secondlife/3p-libhunspell/releases/download/v1.7.2-r2/libhunspell-1.7.2.11968900321-linux64-11968900321.tar.zst
name
linux64
@@ -1144,11 +1148,11 @@
archive
hash
- 89ff24e93eaeca7949ccdb5cc368f938f5b1f307
+ 0f7b9c46dc4e81a6296e4836467f5fe52aa5761d
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libhunspell/releases/download/v1.7.2-r1/libhunspell-1.7.2.10207243663-windows64-10207243663.tar.zst
+ https://github.com/secondlife/3p-libhunspell/releases/download/v1.7.2-r2/libhunspell-1.7.2.11968900321-windows64-11968900321.tar.zst
name
windows64
@@ -1161,7 +1165,7 @@
copyright
LGPL 2.1
version
- 1.7.2.10207243663
+ 1.7.2.11968900321
name
libhunspell
description
@@ -1176,11 +1180,11 @@
archive
hash
- e3dd320c90e67e0c80caf4d4df23257b0196dfb6
+ d1638886671b31935ea7e3c824e015ea1a45b12e
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libndofdev/releases/download/v0.1.8e9edc7/libndofdev-0.1.8e9edc7-darwin64-8e9edc7.tar.zst
+ https://github.com/secondlife/3p-libndofdev/releases/download/v0.1.a0b7d99/libndofdev-0.1.11968678219-darwin64-11968678219.tar.zst
name
darwin64
@@ -1190,11 +1194,11 @@
archive
hash
- ae9d554e8839f42230b8ed6c850445d54654a38f
+ 7b3e504885c4c0cc75db298e682f408c4f2e95f7
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libndofdev/releases/download/v0.1.8e9edc7/libndofdev-0.1.8e9edc7-windows64-8e9edc7.tar.zst
+ https://github.com/secondlife/3p-libndofdev/releases/download/v0.1.a0b7d99/libndofdev-0.1.11968678219-windows64-11968678219.tar.zst
name
windows64
@@ -1207,7 +1211,7 @@
copyright
Copyright (c) 2007, 3Dconnexion, Inc. - All rights reserved.
version
- 0.1.8e9edc7
+ 0.1.11968678219
name
libndofdev
description
@@ -1222,11 +1226,11 @@
archive
hash
- 6fe46ed1e2e40616abdacf7115e510645d5f62e7
+ a453355ee032f79aea4142218a957085a22c7656
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libpng/releases/download/v1.6.43-r2/libpng-1.6.43-r2-darwin64-10329429325.tar.zst
+ https://github.com/secondlife/3p-libpng/releases/download/v1.6.44-r2/libpng-1.6.44-r2-darwin64-13246065198.tar.zst
name
darwin64
@@ -1236,11 +1240,11 @@
archive
hash
- b54a4710d9c3ddfa044e1d29f9c38974e9fc645d
+ 75c7608646c9f5b99b1a9e3946326e2804a304d7
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libpng/releases/download/v1.6.43-r2/libpng-1.6.43-r2-linux64-10329429325.tar.zst
+ https://github.com/secondlife/3p-libpng/releases/download/v1.6.44-r2/libpng-1.6.44-r2-linux64-13246065198.tar.zst
name
linux64
@@ -1250,11 +1254,11 @@
archive
hash
- eddb96c73c8916bf71eaa5d0edb812d20e72c255
+ 09af51774c4ee7c03fe67a87dfc52e846aa625ea
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libpng/releases/download/v1.6.43-r2/libpng-1.6.43-r2-windows64-10329429325.tar.zst
+ https://github.com/secondlife/3p-libpng/releases/download/v1.6.44-r2/libpng-1.6.44-r2-windows64-13246065198.tar.zst
name
windows64
@@ -1267,7 +1271,7 @@
copyright
Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson
version
- 1.6.43-r2
+ 1.6.44-r2
name
libpng
description
@@ -1312,11 +1316,11 @@
archive
hash
- b2bf9adc84841b6fcf48d4c00787b221607cdea3
+ 372c92936d940b1cfb5ba34310691d4bb435c161
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libxml2/releases/download/v2.13.3-r1/libxml2-2.13.3-r1-darwin64-10329675166.tar.zst
+ https://github.com/secondlife/3p-libxml2/releases/download/v2.13.5-r2/libxml2-2.13.5-r2-darwin64-13246071272.tar.zst
name
darwin64
@@ -1326,11 +1330,11 @@
archive
hash
- 6ab8108ea0a42e0bd462568c495e5ce5c4cdc0ff
+ ba6fbc34112b1acab1c8615dcd13de983f3678d3
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libxml2/releases/download/v2.13.3-r1/libxml2-2.13.3-r1-linux64-10329675166.tar.zst
+ https://github.com/secondlife/3p-libxml2/releases/download/v2.13.5-r2/libxml2-2.13.5-r2-linux64-13246071272.tar.zst
name
linux64
@@ -1340,11 +1344,11 @@
archive
hash
- 5181bd267de3ad4466227f91c7e2cbed7e8b85d9
+ 71968c4b621636e8ae0c5680e631f4aa67561944
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-libxml2/releases/download/v2.13.3-r1/libxml2-2.13.3-r1-windows64-10329675166.tar.zst
+ https://github.com/secondlife/3p-libxml2/releases/download/v2.13.5-r2/libxml2-2.13.5-r2-windows64-13246071272.tar.zst
name
windows64
@@ -1357,7 +1361,7 @@
copyright
Copyright (C) 1998-2012 Daniel Veillard. All Rights Reserved.
version
- 2.13.3-r1
+ 2.13.5-r2
name
libxml2
description
@@ -1395,15 +1399,6 @@
llca
- copyright
- Copyright (c) 2016, Linden Research, Inc.; data provided by the Mozilla NSS Project.
-
- license
- mit
- license_file
- LICENSES/ca-license.txt
- name
- llca
platforms
common
@@ -1421,60 +1416,37 @@
common
+ license
+ mit
+ license_file
+ LICENSES/ca-license.txt
+ copyright
+ Copyright (c) 2016, Linden Research, Inc.; data provided by the Mozilla NSS Project.
+
version
202407221423.0
+ name
+ llca
llphysicsextensions_source
platforms
- darwin64
+ common
archive
creds
github
hash
- 9e59c93c7110e87b4ff3db330f11a23c50e5000f
+ fff82c79edb900c547c40dca9a0e3ebac5a8c7da
hash_algorithm
sha1
url
- https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/178910560
+ https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/299858950
name
- darwin64
-
- linux64
-
- archive
-
- creds
- github
- hash
- 7ed994db5bafa9a7ad09a1b53da850a84715c65e
- hash_algorithm
- sha1
- url
- https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/178910561
-
- name
- linux64
-
- windows64
-
- archive
-
- creds
- github
- hash
- 66824c02e0e5eabbfbe37bfb173360195f89697c
- hash_algorithm
- sha1
- url
- https://api.github.com/repos/secondlife/llphysicsextensions_source/releases/assets/178910562
-
- name
- windows64
+ common
license
@@ -1484,62 +1456,10 @@
copyright
Copyright (c) 2010, Linden Research, Inc.
version
- 1.0.66e6919
+ 1.0.11137145495
name
llphysicsextensions_source
- llphysicsextensions_stub
-
- platforms
-
- darwin64
-
- archive
-
- hash
- f290b000b31f9e36f2489946cbc99f5e
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/59995/563653/llphysicsextensions_stub-1.0.542456-darwin64-542456.tar.bz2
-
- name
- darwin64
-
- linux64
-
- archive
-
- hash
- 711f4ec769e4b5f59ba25ee43c11bcbc
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/4724/14846/llphysicsextensions_stub-1.0.504712-linux64-504712.tar.bz2
-
- name
- linux64
-
- windows64
-
- archive
-
- hash
- 2e5f1f7046a49d8b0bc295aa878116bc
- url
- http://automated-builds-secondlife-com.s3.amazonaws.com/ct2/60043/564063/llphysicsextensions_stub-1.0.542456-windows-542456.tar.bz2
-
- name
- windows64
-
-
- license
- internal
- license_file
- LICENSES/llphysicsextensions.txt
- copyright
- Copyright (c) 2010, Linden Research, Inc.
- version
- 1.0.542456
- name
- llphysicsextensions_stub
-
llphysicsextensions_tpv
platforms
@@ -1627,43 +1547,43 @@
archive
hash
- d79631d845e2b5e4a9e6f6b660310795fd49023e
+ 874a7d2bc843554aa4facd03b3a6d681f2b5150c
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-meshoptimizer/releases/download/v210-r2/meshoptimizer-210.0.0-r2-darwin64-10341021290.tar.zst
+ https://github.com/secondlife/3p-meshoptimizer/releases/download/v220-r1/meshoptimizer-220.0.0-r1-darwin64-11968851109.tar.zst
name
darwin64
- windows64
-
- archive
-
- hash
- 024ce689a6f13e66d0c7e431ac34071434e2365a
- hash_algorithm
- sha1
- url
- https://github.com/secondlife/3p-meshoptimizer/releases/download/v210-r2/meshoptimizer-210.0.0-r2-windows64-10341021290.tar.zst
-
- name
- windows64
-
linux64
archive
hash
- c947107c0aca46e94e22f66328a3cbbd01d99b36
+ 31a537f1a3d38ef85443214315111dd56a534d9a
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-meshoptimizer/releases/download/v210-r2/meshoptimizer-210.0.0-r2-linux64-10341021290.tar.zst
+ https://github.com/secondlife/3p-meshoptimizer/releases/download/v220-r1/meshoptimizer-220.0.0-r1-linux64-11968851109.tar.zst
name
linux64
+ windows64
+
+ archive
+
+ hash
+ 6fd727a9ccb3e7a6c6b4ffef8179e266c032eb3e
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-meshoptimizer/releases/download/v220-r1/meshoptimizer-220.0.0-r1-windows64-11968851109.tar.zst
+
+ name
+ windows64
+
license
meshoptimizer
@@ -1672,7 +1592,7 @@
copyright
Copyright (c) 2016-2021 Arseny Kapoulkine
version
- 210.0.0-r2
+ 220.0.0-r1
name
meshoptimizer
canonical_repo
@@ -1751,11 +1671,11 @@
archive
hash
- 6bedaa9d770ef0ae6147f49a26fc3209fde9cb80
+ b628d088e1f368a0cd51a6b66292aaf9a025e2d4
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r1/minizip_ng-4.0.7-r1-darwin64-10324657515.tar.zst
+ https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r3/minizip_ng-4.0.7-r3-darwin64-13246046977.tar.zst
name
darwin64
@@ -1765,11 +1685,11 @@
archive
hash
- ce2c91b8c4f89af252ce1b6a96af6985fe54f509
+ 492ce9175b730d43df63821c4481685e035af623
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r1/minizip_ng-4.0.7-r1-linux64-10324657515.tar.zst
+ https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r3/minizip_ng-4.0.7-r3-linux64-13246046977.tar.zst
name
linux64
@@ -1779,11 +1699,11 @@
archive
hash
- 9cee9d85f9a7c6fb051125775f0122a926da5cc9
+ 58773e707ff3490822b7b8217d7729ade2186632
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r1/minizip_ng-4.0.7-r1-windows64-10324657515.tar.zst
+ https://github.com/secondlife/3p-minizip-ng/releases/download/v4.0.7-r3/minizip_ng-4.0.7-r3-windows64-13246046977.tar.zst
name
windows64
@@ -1796,7 +1716,7 @@
copyright
This project uses the zlib license. Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
version
- 4.0.7-r1
+ 4.0.7-r3
name
minizip-ng
canonical_repo
@@ -1869,11 +1789,11 @@
archive
hash
- 3f3374a5d97803bf78acf20847c2900c7d68ce2b
+ f45ea5a42d6a419f9b605dd3f976fbcb3850d736
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-nghttp2/releases/download/v1.62.1/nghttp2-1.62.1-darwin64-10329456052.tar.zst
+ https://github.com/secondlife/3p-nghttp2/releases/download/v1.64.0-r2/nghttp2-1.64.0-r1-darwin64-13184359419.tar.zst
name
darwin64
@@ -1883,11 +1803,11 @@
archive
hash
- bd9c211f9f53c04821f0ab0e1268a691926331b6
+ c6e450fa41f24f1b4103d2006d706595f2a36c59
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-nghttp2/releases/download/v1.62.1/nghttp2-1.62.1-linux64-10329456052.tar.zst
+ https://github.com/secondlife/3p-nghttp2/releases/download/v1.64.0-r2/nghttp2-1.64.0-r1-linux64-13184359419.tar.zst
name
linux64
@@ -1897,11 +1817,11 @@
archive
hash
- c23e25a7c47f5233f543a90f1a9ccf4da9282379
+ 3bd92f892e155104740570fe244ea4dbb0b57d4b
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-nghttp2/releases/download/v1.62.1/nghttp2-1.62.1-windows64-10329456052.tar.zst
+ https://github.com/secondlife/3p-nghttp2/releases/download/v1.64.0-r2/nghttp2-1.64.0-r1-windows64-13184359419.tar.zst
name
windows64
@@ -1915,7 +1835,7 @@
Copyright (c) 2012, 2014, 2015, 2016 Tatsuhiro Tsujikawa
Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
version
- 1.62.1
+ 1.64.0-r1
name
nghttp2
description
@@ -1964,11 +1884,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 3abb5d21655aeca9d6a4de37704e8475821c28d9
+ 68657c5c161c3fe8ff64eac3787172fcb06da972
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-ogg_vorbis/releases/download/v1.3.5-1.3.7-r1/ogg_vorbis-1.3.5-1.3.7.10341271136-darwin64-10341271136.tar.zst
+ https://github.com/secondlife/3p-ogg_vorbis/releases/download/v1.3.5-1.3.7-r2/ogg_vorbis-1.3.5-1.3.7.11968798109-darwin64-11968798109.tar.zst
name
darwin64
@@ -1978,11 +1898,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- d89dff615c51b46ebdb3d42ac6bd9e0faae5ddf1
+ 9a6ffad7b4186a158c019c5a5a5d7b8badb441da
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-ogg_vorbis/releases/download/v1.3.5-1.3.7-r1/ogg_vorbis-1.3.5-1.3.7.10341271136-linux64-10341271136.tar.zst
+ https://github.com/secondlife/3p-ogg_vorbis/releases/download/v1.3.5-1.3.7-r2/ogg_vorbis-1.3.5-1.3.7.11968798109-linux64-11968798109.tar.zst
name
linux64
@@ -1992,11 +1912,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 0dc0f5334d1c882d5d7bce6d2cfaecf2f7ab1ae6
+ 5f4cbb928ebfe774a9c07d3f2c255fd38bd6b4d6
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-ogg_vorbis/releases/download/v1.3.5-1.3.7-r1/ogg_vorbis-1.3.5-1.3.7.10341271136-windows64-10341271136.tar.zst
+ https://github.com/secondlife/3p-ogg_vorbis/releases/download/v1.3.5-1.3.7-r2/ogg_vorbis-1.3.5-1.3.7.11968798109-windows64-11968798109.tar.zst
name
windows64
@@ -2009,7 +1929,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (c) 2002, Xiph.org Foundation
version
- 1.3.5-1.3.7.10341271136
+ 1.3.5-1.3.7.11968798109
name
ogg_vorbis
description
@@ -2024,7 +1944,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (c) 2008, Jan Ciger (jan.ciger (at) gmail.com)
version
- 0.3
+ 0.14.11968684513
name
open-libndofdev
description
@@ -2039,11 +1959,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 191e4ef07a35f7147708415465191ce7622e3012
+ a3cc405d48a48a474d05b3de3d28da2005d80037
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-openal-soft/releases/download/v1.23.1-8668009/openal-1.23.1-darwin64-8979520327.tar.zst
+ https://github.com/secondlife/3p-openal-soft/releases/download/v1.24.2-r1/openal-1.24.2-r1-darwin64-13245988487.tar.zst
name
darwin64
@@ -2053,11 +1973,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 3bd8c9028ef42bdb43c7422e7d324e213fdb081e
+ a2b63f0f85ca156c59ee1d34ef96c8e50b89153c
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-openal-soft/releases/download/v1.23.1-8668009/openal-1.23.1-linux64-8979520327.tar.zst
+ https://github.com/secondlife/3p-openal-soft/releases/download/v1.24.2-r1/openal-1.24.2-r1-linux64-13245988487.tar.zst
name
linux64
@@ -2067,11 +1987,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 4b849609abec790e89be5fad8ddee3717ee301c4
+ 8ad24fba1191c9cb0d2ab36e64b04b4648a99f43
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-openal-soft/releases/download/v1.23.1-8668009/openal-1.23.1-windows64-8979520327.tar.zst
+ https://github.com/secondlife/3p-openal-soft/releases/download/v1.24.2-r1/openal-1.24.2-r1-windows64-13245988487.tar.zst
name
windows64
@@ -2084,7 +2004,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (C) 1999-2007 by authors.
version
- 1.23.1
+ 1.24.2-r1
name
openal
description
@@ -2099,11 +2019,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 76444e37be0cfccdbb5921370ba150ded2bf3c59
+ 94a72c6ddbfb23796ce913c55bc47c128542a582
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.2-r1/openjpeg-2.5.2.10604495243-darwin64-10604495243.tar.zst
+ https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.3-r1/openjpeg-2.5.3.15590356935-darwin64-15590356935.tar.zst
name
darwin64
@@ -2113,11 +2033,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 6bd289a9c4564b80369ce40ecbb24a213c2732ff
+ 751172af405f4a47a3aebb37729d62229cab6c07
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.2-r1/openjpeg-2.5.2.10604495243-linux64-10604495243.tar.zst
+ https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.3-r1/openjpeg-2.5.3.15590356935-linux64-15590356935.tar.zst
name
linux64
@@ -2127,11 +2047,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 5e6e0180adc01e07438cb98daec96543b5d85019
+ 8aab9cf250dfee252386e1c79b5205e6d3b3e19e
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.2-r1/openjpeg-2.5.2.10604495243-windows64-10604495243.tar.zst
+ https://github.com/secondlife/3p-openjpeg/releases/download/v2.5.3-r1/openjpeg-2.5.3.15590356935-windows64-15590356935.tar.zst
name
windows64
@@ -2144,7 +2064,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (c) 2002-2007, Communications and Remote Sensing Laboratory, Universite catholique de Louvain (UCL), Belgium; Copyright (c) 2002-2007, Professor Benoit Macq; Copyright (c) 2001-2003, David Janssens; Copyright (c) 2002-2003, Yannick Verschueren; Copyright (c) 2003-2007, Francois-Olivier Devaux and Antonin Descampe; Copyright (c) 2005, Herve Drolon, FreeImage Team; Copyright (c) 2006-2007, Parvatha Elangovan; Copyright (c) 2008, Jerome Fimes, Communications & Systemes <jerome.fimes@c-s.fr>; Copyright (c) 2010-2011, Kaori Hagihara; Copyright (c) 2011-2012, Centre National d'Etudes Spatiales (CNES), France; Copyright (c) 2012, CS Systemes d'Information, France;
version
- 2.5.0.ea12248
+ 2.5.3.15590356935
name
openjpeg
description
@@ -2159,11 +2079,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- a20277991043a4a00fb8280a27a41fbd87c4b840
+ 157193699127ac5056c5fc1a410f9c98d39731e2
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r1/openssl-1.1.1w-darwin64-10329796904.tar.zst
+ https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r3/openssl-1.1.1w-r3-darwin64-13246054022.tar.zst
name
darwin64
@@ -2173,11 +2093,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 0f2cd519431b11cacf85971c66c49e5b4d26c56f
+ 2e29c127dbd002d64ae55bc000f8b6ed0249fad7
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r1/openssl-1.1.1w-linux64-10329796904.tar.zst
+ https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r3/openssl-1.1.1w-r3-linux64-13246054022.tar.zst
name
linux64
@@ -2187,11 +2107,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 5e396eedf1492d18126b7281367123c1d64b89aa
+ ae9ced89051e03a99628c99b9ac78530fdea1e5a
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r1/openssl-1.1.1w-windows64-10329796904.tar.zst
+ https://github.com/secondlife/3p-openssl/releases/download/v1.1.1w-r3/openssl-1.1.1w-r3-windows64-13246054022.tar.zst
name
windows64
@@ -2204,7 +2124,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (c) 1998-2011 The OpenSSL Project. All rights reserved; Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
version
- 1.1.1w
+ 1.1.1w-r3
name
openssl
description
@@ -2330,49 +2250,57 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
description
Vivox SDK components
+ sse2neon
+
+ platforms
+
+ common
+
+ archive
+
+ hash
+ e51fb1d24836d897ce90b8a72010635915b959d6
+ hash_algorithm
+ sha1
+ url
+ https://github.com/secondlife/3p-sse2neon/releases/download/v1.8.0/sse2neon-1.8.0-common-17657389472.tar.zst
+
+ name
+ common
+
+
+ license
+ MIT
+ license_file
+ LICENSES/sse2neon.txt
+ copyright
+ Copyright (c) 2015-2024 SSE2NEON Contributors.
+ version
+ 1.8.0
+ name
+ sse2neon
+ canonical_repo
+ https://github.com/secondlife/3p-sse2neon
+ description
+ A translator from Intel SSE intrinsics to Arm/Aarch64 NEON implementation
+
threejs
platforms
- darwin64
+ common
archive
hash
- cfed00d8ea7265c035c2d86a234b28efb0b23756
+ 982c0fa427458082ea9e3cb9603904210732b64e
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-b8f6746/threejs-0.132.2-darwin64-b8f6746.tar.zst
+ https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-5da28d9/threejs-0.132.2-common-8454371083.tar.zst
name
- darwin64
-
- linux64
-
- archive
-
- hash
- 9de1295b157c9913c28be81ff933c73493ecc132
- hash_algorithm
- sha1
- url
- https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-b8f6746/threejs-0.132.2-linux64-b8f6746.tar.zst
-
-
- windows64
-
- archive
-
- hash
- 4141710fccbd1ea2b3b53d00e189bdfa2ee9d441
- hash_algorithm
- sha1
- url
- https://github.com/secondlife/3p-three_js/releases/download/v0.132.2-b8f6746/threejs-0.132.2-windows64-b8f6746.tar.zst
-
- name
- windows64
+ common
license
@@ -2433,11 +2361,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 226225ec049826c35adc5e897e0398ed64d4bedb
+ 0c3d01b7e9e39c23f0f40c56a1a04d1fba08ead0
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-tracy/releases/download/v0.11.0%2Br1/tracy-v0.11.0.10376230034-darwin64-10376230034.tar.zst
+ https://github.com/secondlife/3p-tracy/releases/download/v0.11.1-r1/tracy-v0.11.1.11706699176-darwin64-11706699176.tar.zst
name
darwin64
@@ -2447,11 +2375,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 8c5429d1a1486f40cf7e5e88a232222d1fa4f78e
+ b46cef5646a8d0471ab6256fe5119220fa238772
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-tracy/releases/download/v0.11.0%2Br1/tracy-v0.11.0.10376230034-windows64-10376230034.tar.zst
+ https://github.com/secondlife/3p-tracy/releases/download/v0.11.1-r1/tracy-v0.11.1.11706699176-windows64-11706699176.tar.zst
name
windows64
@@ -2461,11 +2389,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- ed0664a009aba1dcf1246d845839f524e857162e
+ beab04c9ea6036b1851a485b65c66cf6a38f0be4
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-tracy/releases/download/v0.11.0%2Br1/tracy-v0.11.0.10376230034-linux64-10376230034.tar.zst
+ https://github.com/secondlife/3p-tracy/releases/download/v0.11.1-r1/tracy-v0.11.1.11706699176-linux64-11706699176.tar.zst
name
linux64
@@ -2478,7 +2406,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (c) 2017-2024, Bartosz Taudul (wolf@nereid.pl)
version
- v0.11.0.10376230034
+ v0.11.1.11706699176
name
tracy
canonical_repo
@@ -2654,14 +2582,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
vlc-bin
- copyright
- Copyright (C) 1998-2016 VLC authors and VideoLAN
- license
- GPL2
- license_file
- LICENSES/vlc.txt
- name
- vlc-bin
platforms
darwin64
@@ -2669,11 +2589,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- f13c82042ef8311e57dd75a3b2bda02d70f711b5
+ 6d72afd5cc21446c65899615909b1f09f155585d
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-vlc-bin/releases/download/v3.0.21.e60ee26/vlc_bin-3.0.21.10218721728-darwin64-10218721728.tar.zst
+ https://github.com/secondlife/3p-vlc-bin/releases/download/v3.0.21.296d9f4/vlc_bin-3.0.21.11968962952-darwin64-11968962952.tar.zst
name
darwin64
@@ -2683,18 +2603,26 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- bd995441c1a229ed1432ddd837d7d1663b8c5548
+ f986e6e93acf8a32a8be5b638f0bd0e2e07d7507
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-vlc-bin/releases/download/v3.0.21.e60ee26/vlc_bin-3.0.21.10218721728-windows64-10218721728.tar.zst
+ https://github.com/secondlife/3p-vlc-bin/releases/download/v3.0.21.296d9f4/vlc_bin-3.0.21.11968962952-windows64-11968962952.tar.zst
name
windows64
+ license
+ GPL2
+ license_file
+ LICENSES/vlc.txt
+ copyright
+ Copyright (C) 1998-2016 VLC authors and VideoLAN
version
- 3.0.21.10218721728
+ 3.0.21.11968962952
+ name
+ vlc-bin
vulkan_gltf
@@ -2739,11 +2667,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 3570b6442d472cd97bad8622c2ec2571d72218a0
+ 43c5f93517794aeade550e4266b959d1f0cfcb7f
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.72-test/webrtc-m114.5735.08.72-test.10444682919-darwin64-10444682919.tar.zst
+ https://github.com/secondlife/3p-webrtc-build/releases/download/m137.7151.04.20-universal/webrtc-m137.7151.04.20-universal.17630578914-darwin64-17630578914.tar.zst
name
darwin64
@@ -2753,11 +2681,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- eadf6aa99313940ded11801d42c11375669f1628
+ efc5b176d878cfc16b8f82445d82ddb96815b6ab
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.72-test/webrtc-m114.5735.08.72-test.10444682919-linux64-10444682919.tar.zst
+ https://github.com/secondlife/3p-webrtc-build/releases/download/m137.7151.04.20-universal/webrtc-m137.7151.04.20-universal.17630578914-linux64-17630578914.tar.zst
name
linux64
@@ -2767,11 +2695,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 0081fd35290adbc8e66dd366535fb6cd8a966f1e
+ 1e36f100de32c7c71325497a672fb1659b3f206d
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-webrtc-build/releases/download/m114.5735.08.72-test/webrtc-m114.5735.08.72-test.10444682919-windows64-10444682919.tar.zst
+ https://github.com/secondlife/3p-webrtc-build/releases/download/m137.7151.04.20-universal/webrtc-m137.7151.04.20-universal.17630578914-windows64-17630578914.tar.zst
name
windows64
@@ -2784,7 +2712,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (c) 2011, The WebRTC project authors. All rights reserved.
version
- m114.5735.08.72-test.10444682919
+ m137.7151.04.20-universal.17630578914
name
webrtc
vcs_branch
@@ -2837,11 +2765,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 3a6593c71c59ace76d1349483759fcde4b719a76
+ e363e3b889c52fda7601d7aeaa9832307034651e
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.1-r2/zlib_ng-2.2.1-r2-darwin64-10324415171.tar.zst
+ https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.3-r1/zlib_ng-2.2.3-dev0.g8aa13e3.d20250206-darwin64-13183604450.tar.zst
name
darwin64
@@ -2851,11 +2779,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- fbadeb0b8c771cb06c0055c9fab6d40c6764dacd
+ 3cdd52f7fb3691789d50f0b40ed6f5642321ff32
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.1-r2/zlib_ng-2.2.1-r2-linux64-10324415171.tar.zst
+ https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.3-r1/zlib_ng-2.2.3-dev0.g8aa13e3.d20250206-linux64-13183604450.tar.zst
name
linux64
@@ -2865,11 +2793,11 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
archive
hash
- 0094031715662be626f5106ff6c814f4fc3dacfa
+ e802a28139328bb2421ad39e13d996d350d8106d
hash_algorithm
sha1
url
- https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.1-r2/zlib_ng-2.2.1-r2-windows64-10324415171.tar.zst
+ https://github.com/secondlife/3p-zlib-ng/releases/download/v2.2.3-r1/zlib_ng-2.2.3-dev0.g8aa13e3.d20250206-windows64-13183604450.tar.zst
name
windows64
@@ -2882,7 +2810,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
copyright
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
version
- 2.2.1-r2
+ 2.2.3-dev0.g8aa13e3.d20250206
name
zlib-ng
canonical_repo
@@ -2892,16 +2820,6 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
tinyexr
- copyright
- Copyright (c) 2014 - 2021, Syoyo Fujita and many contributors.
- description
- tinyexr import library
- license
- 3-clause BSD
- license_file
- LICENSES/tinyexr_license.txt
- name
- tinyexr
platforms
common
@@ -2919,16 +2837,116 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
common
- source_type
- git
+ license
+ 3-clause BSD
+ license_file
+ LICENSES/tinyexr_license.txt
+ copyright
+ Copyright (c) 2014 - 2021, Syoyo Fujita and many contributors.
+ version
+ 1.0.9-5e8947c
+ name
+ tinyexr
vcs_branch
dependabot/github_actions/secondlife/action-autobuild-4
vcs_revision
4dc4d1d90d82a22843e2adf5130f9ecb5ee5769e
vcs_url
https://github.com/secondlife/3p-tinyexr
+ description
+ tinyexr import library
+ source_type
+ git
+
+ discord_sdk
+
+ platforms
+
+ windows64
+
+ archive
+
+ creds
+ github
+ hash
+ e11571bf76b27d15c244069988ae372eaa5afae9
+ hash_algorithm
+ sha1
+ url
+ https://api.github.com/repos/secondlife/3p-discord-sdk/releases/assets/279333720
+
+ name
+ windows64
+
+ darwin64
+
+ archive
+
+ creds
+ github
+ hash
+ dc21df8b051c425163acf3eff8f06e32f407c9e0
+ hash_algorithm
+ sha1
+ url
+ https://api.github.com/repos/secondlife/3p-discord-sdk/releases/assets/279333706
+
+ name
+ darwin64
+
+
+ license
+ discord_sdk
+ license_file
+ LICENSES/discord_sdk.txt
+ copyright
+ Discord Inc.
version
- 1.0.9-5e8947c
+ 1.4.9649.16733550144
+ name
+ discord_sdk
+ vcs_branch
+ main
+ vcs_revision
+ ef5c7c4a490ceac2df2b2f046788b1daf1bbb392
+ vcs_url
+ https://github.com/secondlife/3p-discord-sdk
+ canonical_repo
+ https://github.com/secondlife/3p-discord-sdk
+ description
+ Discord Social SDK
+
+ vhacd
+
+ platforms
+
+ common
+
+ archive
+
+ hash
+ 140d8fc952a10edb5f2d72ab405336019ef32cadfa64f0cfce76c9de4bc6268cbc87cc8cd89d3417fb78b531d441701afc8d016bafe4bd275df2707f7daf1387
+ hash_algorithm
+ blake2b
+ url
+ https://github.com/AlchemyViewer/3p-vhacd/releases/download/v4.1.0-r2/vhacd-4.1.0-r2-common-18166921729.tar.zst
+
+ name
+ common
+
+
+ license
+ BSD
+ license_file
+ LICENSES/vhacd.txt
+ copyright
+ Copyright (c) 2011, Khaled Mamou
+ version
+ 4.1.0-r2
+ name
+ vhacd
+ description
+ Voxelized Hierarchical Approximate Convex Decomposition
package_description
@@ -3048,14 +3066,15 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
build
command
- xcodebuild
+ cmake
options
- -configuration
+ --build
+ .
+ --config
RelWithDebInfo
- -project
- SecondLife.xcodeproj
- -parallelizeTargets
+ --parallel
+ $AUTOBUILD_CPU_COUNT
default
@@ -3076,14 +3095,15 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
build
command
- xcodebuild
+ cmake
options
- -configuration
+ --build
+ .
+ --config
RelWithDebInfo
- -project
- SecondLife.xcodeproj
- -parallelizeTargets
+ --parallel
+ $AUTOBUILD_CPU_COUNT
name
@@ -3106,14 +3126,15 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
build
command
- xcodebuild
+ cmake
options
- -configuration
+ --build
+ .
+ --config
Release
- -project
- SecondLife.xcodeproj
- -parallelizeTargets
+ --parallel
+ $AUTOBUILD_CPU_COUNT
name
@@ -3132,14 +3153,15 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
build
command
- xcodebuild
+ cmake
options
- -configuration
+ --build
+ .
+ --config
Release
- -project
- SecondLife.xcodeproj
- -parallelizeTargets
+ --parallel
+ $AUTOBUILD_CPU_COUNT
name
@@ -3147,7 +3169,7 @@ Copyright (c) 2012, 2014, 2015, 2016 nghttp2 contributors
build_directory
- build-darwin-x86_64
+ build-darwin-universal
name
darwin64
diff --git a/build.sh b/build.sh
index eb81ff319a..ba90065827 100755
--- a/build.sh
+++ b/build.sh
@@ -40,7 +40,7 @@ retry_cmd()
build_dir_Darwin()
{
- echo build-darwin-x86_64
+ echo build-darwin-universal
}
build_dir_Linux()
@@ -70,7 +70,7 @@ installer_Darwin()
{
local package_name="$1"
local package_dir="$(build_dir_Darwin)/newview/"
- local pattern=".*$(viewer_channel_suffix ${package_name})_[0-9]+_[0-9]+_[0-9]+_[0-9]+_x86_64\\.dmg\$"
+ local pattern=".*$(viewer_channel_suffix ${package_name})_[0-9]+_[0-9]+_[0-9]+_[0-9]+_universal\\.dmg\$"
# since the additional packages are built after the base package,
# sorting oldest first ensures that the unqualified package is returned
# even if someone makes a qualified name that duplicates the last word of the base name
@@ -261,8 +261,8 @@ build()
done
fi
- # *TODO: Make this a build extension.
- package_llphysicsextensions_tpv || fatal "failed building llphysicsextensions packages"
+ # *TODO: Make this a build extension. disabled for now
+ # package_llphysicsextensions_tpv || fatal "failed building llphysicsextensions packages"
end_section "extensions $variant"
else
@@ -387,7 +387,7 @@ do
if `cat "$build_dir/build_ok"`
then
case "$variant" in
- Release)
+ Release*)
if [ -r "$build_dir/autobuild-package.xml" ]
then
begin_section "Autobuild metadata"
diff --git a/doc/testplans/PRIM_MEDIA_FIRST_CLICK_INTERACT.md b/doc/testplans/PRIM_MEDIA_FIRST_CLICK_INTERACT.md
new file mode 100644
index 0000000000..afb3d5b337
--- /dev/null
+++ b/doc/testplans/PRIM_MEDIA_FIRST_CLICK_INTERACT.md
@@ -0,0 +1,158 @@
+# Test plan for PRIM_MEDIA_FIRST_CLICK_INTERACT
+
+## Requirements
+
+- At least two accounts
+- At least one group
+- Land under your control
+
+## Feature Brief
+
+Historically media-on-a-prim (MOAP) in Second Life has been bound to a focus system which blocks mouse click/hover events, this feature creates exceptions to this focus system for a configurable set of objects to meet user preference.
+
+## Testing
+
+The following scripts and test cases cover each individual operational mode of the feature; in practice these modes can be combined by advanced users in any configuration they desire from debug settings. Even though the intended use case combines multiple modes, individual modes can be tested for functionality when tested as described below.
+
+If testing an arbitrary combination of operational modes beyond what the GUI offers is desired, the parameters of the bitfield for calculation are located in lltoolpie.h under the MediaFirstClickTypes enum. As of writing there exists a total of ~127 possible unique/valid combinations, which is why testing each mode individually is considered the most efficient for a full functionality test.
+
+### Scripts
+
+#### Script A
+
+This script creates a media surface that is eligible for media first-click interact. Depending on test conditions, this will exhibit new behavior.
+
+```lsl
+default {
+ state_entry() {
+ llSetLinkMedia( LINK_THIS, 0, [
+ PRIM_MEDIA_CURRENT_URL, "http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/agni/avatars.html",
+ PRIM_MEDIA_HOME_URL, "http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/agni/avatars.html",
+ PRIM_MEDIA_FIRST_CLICK_INTERACT, TRUE,
+ PRIM_MEDIA_AUTO_PLAY, TRUE,
+ PRIM_MEDIA_CONTROLS, PRIM_MEDIA_CONTROLS_MINI
+ ] );
+ }
+}
+
+```
+
+#### Script B
+
+This script creates a media surface that is NOT eligible for media first-click interact. In all but one test case, this will behave the same way.
+
+```lsl
+default {
+ state_entry() {
+ llSetLinkMedia( LINK_THIS, 0, [
+ PRIM_MEDIA_CURRENT_URL, "http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/agni/avatars.html",
+ PRIM_MEDIA_HOME_URL, "http://lecs-viewer-web-components.s3.amazonaws.com/v3.0/agni/avatars.html",
+ PRIM_MEDIA_FIRST_CLICK_INTERACT, FALSE,
+ PRIM_MEDIA_AUTO_PLAY, TRUE,
+ PRIM_MEDIA_CONTROLS, PRIM_MEDIA_CONTROLS_MINI
+ ] );
+ }
+}
+
+```
+
+## Standard testing procedure
+
+You will be asked to enable media faces on multiple cubes, make sure that the webpage loads on each, and interact with them in the following ways.
+
+1. Enable media for the cube, and verify that it displays a webpage.
+2. Click on the terrain to clear any focus.
+3. Hover your mouse over UI elements of the webpage, and **observe** if they highlight/react to the mouse cursor.
+4. If hover events are not registered, clicking on the webpage and then **observe** if they begin reacting to hover events.
+5. Clicking on the terrain to clear any focus once again.
+6. Clicking on a UI element of the webpage and **observe** if it reacts to the first click, or requires a second click. *(Maximum of 2 clicks per attempt)*
+
+These steps will be repeated for one or more pairs of cubes per test case to ensure that media first click interact is functioning within expectations. Unless otherwise mentioned for a specific test case, you simply need only be in the same region as the cubes to test with them.
+
+## Test cases
+
+All test cases begin with at least two cubes rezzed, one containing Script A henceforth referred to as Cube A and one with Script B referred to as Cube B. The steps of some test cases may impact the condition of the cubes, so keeping a spare set rezzed or in inventory to rapidly duplicate should improve efficiency if testing cases in series.
+
+### Case 1 (MEDIA_FIRST_CLICK_NONE)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `0`
+
+Starting with Cube A and Cube B, perform the testing procedure on each.
+
+**Expected observations:** Both webpages do not react to hover events until clicked, both webpages do not react to clicks until clicked once to establish focus
+
+### Case 2 (MEDIA_FIRST_CLICK_HUD)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `1`
+
+Starting with Cube A and Cube B, attach them both to your HUD and perform the testing procedure on each. You may need to rotate or scale the cubes to fit on your screen before beginning testing. You may attach both at the same time, or only one at a time.
+
+**Expected observations:** The webpage on Cube A will react to mouse cursor hover events and clicks without needing a focus click, but the webpage on Cube B will not.
+
+### Case 3 (MEDIA_FIRST_CLICK_OWN)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `2`
+
+This test case requires two pairs of cubes, and the second pair must not be owned by your testing account. What owns them is not important, it can be a group or your second testing account.
+
+Perform the testing procedure on both sets of cubes.
+
+**Expected observations:** The webpage on Cube A will react to mouse cursor hover events and clicks without needing a focus click, but the webpage on Cube B will not. The other pair of cubes will react the same as your Cube B.
+
+### Case 4 (MEDIA_FIRST_CLICK_GROUP)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `4`
+
+This test case requires two cubes, and the second cube must be deeded or set to a group that your testing account is a member of. As long as the second set of cubes is set to a group that your test account is a member of, the avatar that owns them does not matter.
+
+Perform the testing procedure on both sets of cubes.
+
+**Expected observations:** The cube owned by your primary account will not react to mouse cursor hover events and clicks without needing a focus click. The cube set to group will react to mouse cursor hover events and clicks without needing a focus click.
+
+### Case 5 (MEDIA_FIRST_CLICK_FRIEND)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `8`
+
+This test case requires three sets of cubes, one owned by you, one owned by another avatar on your friend list, and a third set owned by an avatar that is not on your friend list, or deeded to group. You can optionally use two sets of cubes, and dissolve friendship with your second account to test non-friend cubes.
+
+Perform the testing procedure on all cubes
+
+**Expected observations:** Cube A owned by a friended avatar will react to mouse cursor hover events and clicks without needing a focus click. All other cubes will not.
+
+### Case 6 (MEDIA_FIRST_CLICK_LAND)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `16`
+
+This is the most tricky test case due to the multiple combinations that this operational mode considers valid. You will need multiple cubes, and can omit Cube B for brevity unless running a full test pass. This is probably most efficiently tested from your second account, using your first account to adjust the test parameters to fit other sub-cases.
+
+Note: This requires the avatar that is performing the tests to physically be in the same parcel as the test cube(s). If you are standing outside of the parcel the media cubes are in, they will never react to mouse cursor hover events and clicks without needing a focus click under this operational mode.
+
+1. Place down a set of cubes owned by the same avatar as the land
+ - The second account should see Cube A react to mouse cursor hover events and clicks without needing a focus click
+ - Cube B if tested, will not react in all further sub-cases and will not be mentioned further.
+
+2. Adjust the conditions of the cubes and parcel such that they are owned by another avatar, but have the same group as the land set
+ - The second account should see Cube A react to mouse cursor hover events and clicks without needing a focus click
+
+3. Adjust the conditions of the cubes and parcel such that they are deeded to the same group that the parcel is deeded to
+ - The second account should see Cube A react to mouse cursor hover events and clicks without needing a focus click
+
+4. Adjust the conditions of the cubes and parcel such that the parcel and cubes do not share an owner, or a group
+ - The second account should see Cube A NOT react to mouse cursor hover events until clicked, and clicks WILL need a focus click before registering.
+
+### Case 7 (MEDIA_FIRST_CLICK_ANY) (optional)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `32767`
+
+Repeat test cases 1-6.
+
+1. Test case 1 should fail
+2. Test cases 2-6 should pass
+
+### Case 8 (MEDIA_FIRST_CLICK_BYPASS_MOAP_FLAG) (optional)
+
+Ensure that debug setting `MediaFirstClickInteract` is set to `65535`
+
+Repeat test cases 1-6, there is no pass/fail for this run.
+
+All cubes including B types should exhibit the same first-click interact behavior.
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 3170dbc180..8fde58fa43 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -10,7 +10,13 @@
## Nicky: Ideally we want at least 3.21 for good preset support
## We're not there yet, but once done, there is a kludge in Linking.cmake
# "if(${CMAKE_VERSION} VERSION_LESS "3.20.0")" that can also be removed
-cmake_minimum_required(VERSION 3.16.0 FATAL_ERROR)
+cmake_minimum_required(VERSION 3.16.0...4.0 FATAL_ERROR)
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.29.0")
+ cmake_policy(SET CMP0156 NEW)
+endif()
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.31.0")
+ cmake_policy(SET CMP0179 NEW)
+endif()
set(ROOT_PROJECT_NAME "SecondLife" CACHE STRING
"The root project/makefile/solution name. Defaults to SecondLife.")
@@ -33,6 +39,14 @@ if (NOT DEFINED CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 20)
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_CXX_SCAN_FOR_MODULES OFF) # This slows down build massively
+
+set(CMAKE_OPTIMIZE_DEPENDENCIES ON)
+
+set(CMAKE_COLOR_DIAGNOSTICS ON)
+
+# Speeds up cmake generation significantly in some cases
+set(CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY ON)
include(Variables)
include(BuildVersion)
@@ -56,6 +70,7 @@ add_subdirectory(${LIBS_OPEN_PREFIX}llinventory)
add_subdirectory(${LIBS_OPEN_PREFIX}llmath)
add_subdirectory(${LIBS_OPEN_PREFIX}llmeshoptimizer)
add_subdirectory(${LIBS_OPEN_PREFIX}llmessage)
+add_subdirectory(${LIBS_OPEN_PREFIX}llphysicsextensionsos)
add_subdirectory(${LIBS_OPEN_PREFIX}llprimitive)
add_subdirectory(${LIBS_OPEN_PREFIX}llrender)
add_subdirectory(${LIBS_OPEN_PREFIX}llfilesystem)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 39f26ced5d..99ea22ab4b 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -34,7 +34,10 @@ add_compile_definitions(BOOST_BIND_GLOBAL_PLACEHOLDERS)
# Force enable SSE2 instructions in GLM per the manual
# https://github.com/g-truc/glm/blob/master/manual.md#section2_10
-add_compile_definitions(GLM_FORCE_DEFAULT_ALIGNED_GENTYPES=1 GLM_FORCE_SSE2=1)
+add_compile_definitions(GLM_FORCE_DEFAULT_ALIGNED_GENTYPES=1 GLM_ENABLE_EXPERIMENTAL=1)
+
+# SSE2NEON throws a pointless warning when compiler optimizations are enabled
+add_compile_definitions(SSE2NEON_SUPPRESS_WARNINGS=1)
# Configure crash reporting
set(RELEASE_CRASH_REPORTING OFF CACHE BOOL "Enable use of crash reporting in release builds")
@@ -48,6 +51,11 @@ if(NON_RELEASE_CRASH_REPORTING)
add_compile_definitions( LL_SEND_CRASH_REPORTS=1)
endif()
+set(USE_LTO OFF CACHE BOOL "Enable Link Time Optimization")
+if(USE_LTO)
+ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON)
+endif()
+
# Don't bother with a MinSizeRel or Debug builds.
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo;Release" CACHE STRING "Supported build types." FORCE)
@@ -73,6 +81,8 @@ if (WINDOWS)
NOMINMAX
# DOM_DYNAMIC # For shared library colladadom
_CRT_SECURE_NO_WARNINGS # Allow use of sprintf etc
+ _CRT_NONSTDC_NO_DEPRECATE # Allow use of sprintf etc
+ _CRT_OBSOLETE_NO_WARNINGS
_WINSOCK_DEPRECATED_NO_WARNINGS # Disable deprecated WinSock API warnings
)
add_compile_options(
@@ -101,7 +111,7 @@ if (WINDOWS)
#ND: When using something like buildcache (https://github.com/mbitsnbites/buildcache)
# to make those wrappers work /Zi must be changed to /Z7, as /Zi due to it's nature is not compatible with caching
- if( ${CMAKE_CXX_COMPILER_LAUNCHER} MATCHES ".*cache.*")
+ if(${CMAKE_CXX_COMPILER_LAUNCHER} MATCHES ".*cache.*")
add_compile_options( /Z7 )
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
@@ -155,46 +165,40 @@ if (LINUX)
set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
endif (LINUX)
-
if (DARWIN)
+ # Use rpath loading on macos
+ set(CMAKE_MACOSX_RPATH TRUE)
+
# Warnings should be fatal -- thanks, Nicky Perian, for spotting reversed default
set(CLANG_DISABLE_FATAL_WARNINGS OFF)
set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}")
- set(DARWIN_extra_cstar_flags "-Wno-unused-local-typedef -Wno-deprecated-declarations")
- # Ensure that CMAKE_CXX_FLAGS has the correct -g debug information format --
- # see Variables.cmake.
- string(REPLACE "-gdwarf-2" "-g${CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT}"
- CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${DARWIN_extra_cstar_flags}")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${DARWIN_extra_cstar_flags}")
- # NOTE: it's critical that the optimization flag is put in front.
- # NOTE: it's critical to have both CXX_FLAGS and C_FLAGS covered.
-## Really?? On developer machines too?
-##set(ENABLE_SIGNING TRUE)
-##set(SIGNING_IDENTITY "Developer ID Application: Linden Research, Inc.")
- # required for clang-15/xcode-15 since our boost package still uses deprecated std::unary_function/binary_function
- # see https://developer.apple.com/documentation/xcode-release-notes/xcode-15-release-notes#C++-Standard-Library
- add_compile_definitions(_LIBCPP_ENABLE_CXX17_REMOVED_UNARY_BINARY_FUNCTION)
-endif (DARWIN)
+ # Ensure debug symbols are always generated
+ add_compile_options(-g --debug) # --debug is a clang synonym for -g that bypasses cmake behaviors
+
+ # Silence GL deprecation warnings
+ add_compile_definitions(GL_SILENCE_DEPRECATION=1)
+endif(DARWIN)
if (LINUX OR DARWIN)
- set(GCC_WARNINGS -Wall -Wno-sign-compare -Wno-trigraphs)
+ add_compile_options(-Wall -Wno-sign-compare -Wno-trigraphs -Wno-reorder -Wno-unused-but-set-variable -Wno-unused-variable)
- if (NOT GCC_DISABLE_FATAL_WARNINGS)
- list(APPEND GCC_WARNINGS -Werror)
- endif (NOT GCC_DISABLE_FATAL_WARNINGS)
-
- list(APPEND GCC_WARNINGS -Wno-reorder -Wno-non-virtual-dtor )
-
- if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 13)
- list(APPEND GCC_WARNINGS -Wno-unused-but-set-variable -Wno-unused-variable )
+ if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
+ # libstdc++ headers contain deprecated declarations that fail on clang
+ # macOS currently has many deprecated calls
+ add_compile_options(-Wno-unused-local-typedef)
endif()
+ if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
+ add_compile_options(-Wno-stringop-truncation -Wno-parentheses -Wno-maybe-uninitialized)
+ endif()
+
+ if (NOT GCC_DISABLE_FATAL_WARNINGS AND NOT CLANG_DISABLE_FATAL_WARNINGS)
+ add_compile_options(-Werror)
+ endif ()
+
add_compile_options(${GCC_WARNINGS})
add_compile_options(-m${ADDRESS_SIZE})
endif (LINUX OR DARWIN)
-
-
diff --git a/indra/cmake/APR.cmake b/indra/cmake/APR.cmake
index 97b316c4c7..e0807a7d19 100644
--- a/indra/cmake/APR.cmake
+++ b/indra/cmake/APR.cmake
@@ -9,35 +9,25 @@ use_system_binary( apr apr-util )
use_prebuilt_binary(apr_suite)
if (WINDOWS)
- if (LLCOMMON_LINK_SHARED)
- set(APR_selector "lib")
- else (LLCOMMON_LINK_SHARED)
- set(APR_selector "")
- endif (LLCOMMON_LINK_SHARED)
- target_link_libraries( ll::apr INTERFACE
- ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}apr-1.lib
- ${ARCH_PREBUILT_DIRS_RELEASE}/${APR_selector}aprutil-1.lib
- )
- target_compile_definitions( ll::apr INTERFACE APR_DECLARE_STATIC=1 APU_DECLARE_STATIC=1 API_DECLARE_STATIC=1)
-elseif (DARWIN)
- if (LLCOMMON_LINK_SHARED)
- set(APR_selector "0.dylib")
- set(APRUTIL_selector "0.dylib")
- else (LLCOMMON_LINK_SHARED)
- set(APR_selector "a")
- set(APRUTIL_selector "a")
- endif (LLCOMMON_LINK_SHARED)
-
- target_link_libraries( ll::apr INTERFACE
- ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.${APR_selector}
- ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.${APR_selector}
- iconv
- )
-else()
- target_link_libraries( ll::apr INTERFACE
- ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.a
- ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.a
- rt
- )
+ target_compile_definitions(ll::apr INTERFACE APR_DECLARE_STATIC=1 APU_DECLARE_STATIC=1 API_DECLARE_STATIC=1)
endif ()
-target_include_directories( ll::apr SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/apr-1 )
+
+find_library(APR_LIBRARY
+ NAMES
+ apr-1.lib
+ libapr-1.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+find_library(APRUTIL_LIBRARY
+ NAMES
+ aprutil-1.lib
+ libaprutil-1.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::apr INTERFACE ${APR_LIBRARY} ${APRUTIL_LIBRARY})
+
+if(DARWIN)
+ target_link_libraries(ll::apr INTERFACE iconv)
+endif()
+
+target_include_directories(ll::apr SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/apr-1)
diff --git a/indra/cmake/Audio.cmake b/indra/cmake/Audio.cmake
index 8c82749cab..5a7a7ab0b5 100644
--- a/indra/cmake/Audio.cmake
+++ b/indra/cmake/Audio.cmake
@@ -9,23 +9,29 @@ use_system_binary(vorbis)
use_prebuilt_binary(ogg_vorbis)
target_include_directories( ll::vorbis SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include )
-if (WINDOWS)
- target_link_libraries(ll::vorbis INTERFACE
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libogg.lib
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libogg.lib
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libvorbisenc.lib
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libvorbisenc.lib
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libvorbisfile.lib
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libvorbisfile.lib
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libvorbis.lib
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libvorbis.lib
- )
-else (WINDOWS)
- target_link_libraries(ll::vorbis INTERFACE
- ${ARCH_PREBUILT_DIRS_RELEASE}/libogg.a
- ${ARCH_PREBUILT_DIRS_RELEASE}/libvorbisenc.a
- ${ARCH_PREBUILT_DIRS_RELEASE}/libvorbisfile.a
- ${ARCH_PREBUILT_DIRS_RELEASE}/libvorbis.a
- )
-endif (WINDOWS)
+find_library(OGG_LIBRARY
+ NAMES
+ libogg.lib
+ libogg.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+find_library(VORBIS_LIBRARY
+ NAMES
+ libvorbis.lib
+ libvorbis.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+find_library(VORBISENC_LIBRARY
+ NAMES
+ libvorbisenc.lib
+ libvorbisenc.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+find_library(VORBISFILE_LIBRARY
+ NAMES
+ libvorbisfile.lib
+ libvorbisfile.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::vorbis INTERFACE ${VORBISENC_LIBRARY} ${VORBISFILE_LIBRARY} ${VORBIS_LIBRARY} ${OGG_LIBRARY} )
diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake
index 8c5b946753..b57c33c3e0 100644
--- a/indra/cmake/Boost.cmake
+++ b/indra/cmake/Boost.cmake
@@ -17,40 +17,118 @@ use_prebuilt_binary(boost)
set(addrsfx "-x${ADDRESS_SIZE}")
if (WINDOWS)
- target_link_libraries( ll::boost INTERFACE
- libboost_context-mt${addrsfx}
- libboost_fiber-mt${addrsfx}
- libboost_filesystem-mt${addrsfx}
- libboost_program_options-mt${addrsfx}
- libboost_regex-mt${addrsfx}
- libboost_system-mt${addrsfx}
- libboost_thread-mt${addrsfx}
- libboost_url-mt${addrsfx})
-elseif (LINUX)
- target_link_libraries( ll::boost INTERFACE
- boost_context-mt${addrsfx}
- boost_fiber-mt${addrsfx}
- boost_filesystem-mt${addrsfx}
- boost_program_options-mt${addrsfx}
- boost_regex-mt${addrsfx}
- boost_signals-mt${addrsfx}
- boost_system-mt${addrsfx}
- boost_thread-mt${addrsfx}
- boost_url-mt${addrsfx})
-elseif (DARWIN)
- target_link_libraries( ll::boost INTERFACE
- boost_context-mt${addrsfx}
- boost_fiber-mt${addrsfx}
- boost_filesystem-mt${addrsfx}
- boost_program_options-mt${addrsfx}
- boost_regex-mt${addrsfx}
- boost_system-mt${addrsfx}
- boost_thread-mt${addrsfx}
- boost_url-mt${addrsfx})
+
+ find_library(BOOST_CONTEXT_LIBRARY
+ NAMES
+ libboost_context-mt
+ libboost_context-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_FIBER_LIBRARY
+ NAMES
+ libboost_fiber-mt
+ libboost_fiber-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_FILESYSTEM_LIBRARY
+ NAMES
+ libboost_filesystem-mt
+ libboost_filesystem-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_PROGRAMOPTIONS_LIBRARY
+ NAMES
+ libboost_program_options-mt
+ libboost_program_options-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_REGEX_LIBRARY
+ NAMES
+ libboost_regex-mt
+ libboost_regex-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_SYSTEM_LIBRARY
+ NAMES
+ libboost_system-mt
+ libboost_system-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_THREAD_LIBRARY
+ NAMES
+ libboost_thread-mt
+ libboost_thread-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_URL_LIBRARY
+ NAMES
+ libboost_url-mt
+ libboost_url-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+else (WINDOWS)
+
+ find_library(BOOST_CONTEXT_LIBRARY
+ NAMES
+ boost_context-mt
+ boost_context-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_FIBER_LIBRARY
+ NAMES
+ boost_fiber-mt
+ boost_fiber-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_FILESYSTEM_LIBRARY
+ NAMES
+ boost_filesystem-mt
+ boost_filesystem-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_PROGRAMOPTIONS_LIBRARY
+ NAMES
+ boost_program_options-mt
+ boost_program_options-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_REGEX_LIBRARY
+ NAMES
+ boost_regex-mt
+ boost_regex-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_SYSTEM_LIBRARY
+ NAMES
+ boost_system-mt
+ boost_system-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_THREAD_LIBRARY
+ NAMES
+ boost_thread-mt
+ boost_thread-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(BOOST_URL_LIBRARY
+ NAMES
+ boost_url-mt
+ boost_url-mt${addrsfx}
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
endif (WINDOWS)
+target_link_libraries(ll::boost INTERFACE
+ ${BOOST_FIBER_LIBRARY}
+ ${BOOST_CONTEXT_LIBRARY}
+ ${BOOST_FILESYSTEM_LIBRARY}
+ ${BOOST_PROGRAMOPTIONS_LIBRARY}
+ ${BOOST_REGEX_LIBRARY}
+ ${BOOST_SYSTEM_LIBRARY}
+ ${BOOST_THREAD_LIBRARY}
+ ${BOOST_URL_LIBRARY})
+
if (LINUX)
- set(BOOST_SYSTEM_LIBRARY ${BOOST_SYSTEM_LIBRARY} rt)
- set(BOOST_THREAD_LIBRARY ${BOOST_THREAD_LIBRARY} rt)
+ target_link_libraries(ll::boost INTERFACE rt)
endif (LINUX)
diff --git a/indra/cmake/CEFPlugin.cmake b/indra/cmake/CEFPlugin.cmake
index 9b77becf29..e27929fa08 100644
--- a/indra/cmake/CEFPlugin.cmake
+++ b/indra/cmake/CEFPlugin.cmake
@@ -29,7 +29,6 @@ elseif (DARWIN)
${ARCH_PREBUILT_DIRS_RELEASE}/libcef_dll_wrapper.a
${ARCH_PREBUILT_DIRS_RELEASE}/libdullahan.a
${APPKIT_LIBRARY}
- "-F ${CEF_LIBRARY}"
)
elseif (LINUX)
diff --git a/indra/cmake/CMakeLists.txt b/indra/cmake/CMakeLists.txt
index cc217b0563..2ba282bdb7 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -20,6 +20,7 @@ set(cmake_SOURCE_FILES
Copy3rdPartyLibs.cmake
DBusGlib.cmake
DeploySharedLibs.cmake
+ Discord.cmake
DragDrop.cmake
EXPAT.cmake
FindAutobuild.cmake
@@ -52,13 +53,16 @@ set(cmake_SOURCE_FILES
Prebuilt.cmake
PulseAudio.cmake
Python.cmake
+ SSE2NEON.cmake
TemplateCheck.cmake
TinyEXR.cmake
TinyGLTF.cmake
+ Tracy.cmake
Tut.cmake
UI.cmake
UnixInstall.cmake
Variables.cmake
+ VHACD.cmake
ViewerMiscLibs.cmake
VisualLeakDetector.cmake
LibVLCPlugin.cmake
diff --git a/indra/cmake/CURL.cmake b/indra/cmake/CURL.cmake
index eea0a2da62..b1595d57a8 100644
--- a/indra/cmake/CURL.cmake
+++ b/indra/cmake/CURL.cmake
@@ -7,19 +7,13 @@ add_library( ll::libcurl INTERFACE IMPORTED )
use_system_binary(libcurl)
use_prebuilt_binary(curl)
-if (WINDOWS)
- target_link_libraries(ll::libcurl INTERFACE
- ${ARCH_PREBUILT_DIRS_RELEASE}/libcurl.lib
- ll::openssl
- ll::nghttp2
- ll::zlib-ng
- )
-else ()
- target_link_libraries(ll::libcurl INTERFACE
- ${ARCH_PREBUILT_DIRS_RELEASE}/libcurl.a
- ll::openssl
- ll::nghttp2
- ll::zlib-ng
- )
-endif ()
+
+find_library(CURL_LIBRARY
+ NAMES
+ libcurl.lib
+ libcurl.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::libcurl INTERFACE ${CURL_LIBRARY} ll::openssl ll::nghttp2 ll::zlib-ng)
+
target_include_directories( ll::libcurl SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake
index 6ac00fd131..680f2f3ac2 100644
--- a/indra/cmake/Copy3rdPartyLibs.cmake
+++ b/indra/cmake/Copy3rdPartyLibs.cmake
@@ -6,6 +6,9 @@
include(CMakeCopyIfDifferent)
include(Linking)
+if (USE_DISCORD)
+ include(Discord)
+endif ()
include(OPENAL)
# When we copy our dependent libraries, we almost always want to copy them to
@@ -56,11 +59,6 @@ if(WINDOWS)
openjp2.dll
)
- if(LLCOMMON_LINK_SHARED)
- set(release_files ${release_files} libapr-1.dll)
- set(release_files ${release_files} libaprutil-1.dll)
- endif()
-
# Filenames are different for 32/64 bit BugSplat file and we don't
# have any control over them so need to branch.
if (USE_BUGSPLAT)
@@ -75,6 +73,10 @@ if(WINDOWS)
endif(ADDRESS_SIZE EQUAL 32)
endif (USE_BUGSPLAT)
+ if (TARGET ll::discord_sdk)
+ list(APPEND release_files discord_partner_sdk.dll)
+ endif ()
+
if (TARGET ll::openal)
list(APPEND release_files openal32.dll alut.dll)
endif ()
@@ -171,14 +173,9 @@ elseif(DARWIN)
libndofdev.dylib
)
- if(LLCOMMON_LINK_SHARED)
- set(release_files ${release_files}
- libapr-1.0.dylib
- libapr-1.dylib
- libaprutil-1.0.dylib
- libaprutil-1.dylib
- )
- endif()
+ if (TARGET ll::discord_sdk)
+ list(APPEND release_files libdiscord_partner_sdk.dylib)
+ endif ()
if (TARGET ll::openal)
list(APPEND release_files libalut.dylib libopenal.dylib)
@@ -225,13 +222,6 @@ elseif(LINUX)
libgmodule-2.0.so
libgobject-2.0.so
)
-
- if(LLCOMMON_LINK_SHARED)
- set(release_files ${release_files}
- libapr-1.so.0
- libaprutil-1.so.0
- )
- endif()
endif()
else(WINDOWS)
diff --git a/indra/cmake/Discord.cmake b/indra/cmake/Discord.cmake
new file mode 100644
index 0000000000..95cfaacf5b
--- /dev/null
+++ b/indra/cmake/Discord.cmake
@@ -0,0 +1,11 @@
+include(Prebuilt)
+
+include_guard()
+
+add_library(ll::discord_sdk INTERFACE IMPORTED)
+target_compile_definitions(ll::discord_sdk INTERFACE LL_DISCORD=1)
+
+use_prebuilt_binary(discord_sdk)
+
+target_include_directories(ll::discord_sdk SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/discord_sdk)
+target_link_libraries(ll::discord_sdk INTERFACE discord_partner_sdk)
diff --git a/indra/cmake/EXPAT.cmake b/indra/cmake/EXPAT.cmake
index 1a0b8789dc..fe6dced795 100644
--- a/indra/cmake/EXPAT.cmake
+++ b/indra/cmake/EXPAT.cmake
@@ -2,18 +2,21 @@
include(Prebuilt)
include_guard()
-add_library( ll::expat INTERFACE IMPORTED )
+add_library(ll::expat INTERFACE IMPORTED)
use_system_binary(expat)
use_prebuilt_binary(expat)
+
if (WINDOWS)
- target_compile_definitions( ll::expat INTERFACE XML_STATIC=1)
- target_link_libraries( ll::expat INTERFACE
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libexpatd.lib
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libexpat.lib)
-else ()
- target_link_libraries( ll::expat INTERFACE
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libexpat.a
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libexpat.a)
+ target_compile_definitions(ll::expat INTERFACE XML_STATIC=1)
endif ()
-target_include_directories( ll::expat SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include )
+
+find_library(EXPAT_LIBRARY
+ NAMES
+ libexpat.lib
+ libexpat.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::expat INTERFACE ${EXPAT_LIBRARY})
+
+target_include_directories(ll::expat SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake
index 563491556d..3c635e851b 100644
--- a/indra/cmake/FreeType.cmake
+++ b/indra/cmake/FreeType.cmake
@@ -9,9 +9,10 @@ use_system_binary(freetype)
use_prebuilt_binary(freetype)
target_include_directories( ll::freetype SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/freetype2/)
-if (WINDOWS)
- target_link_libraries( ll::freetype INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/freetype.lib)
-else()
- target_link_libraries( ll::freetype INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libfreetype.a)
-endif()
+find_library(FREETYPE_LIBRARY
+ NAMES
+ freetype.lib
+ libfreetype.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+target_link_libraries(ll::freetype INTERFACE ${FREETYPE_LIBRARY})
diff --git a/indra/cmake/Hunspell.cmake b/indra/cmake/Hunspell.cmake
index 129679febd..b063363bc0 100644
--- a/indra/cmake/Hunspell.cmake
+++ b/indra/cmake/Hunspell.cmake
@@ -8,17 +8,17 @@ use_prebuilt_binary(dictionaries)
add_library( ll::hunspell INTERFACE IMPORTED )
use_system_binary(hunspell)
use_prebuilt_binary(libhunspell)
+
if (WINDOWS)
target_compile_definitions( ll::hunspell INTERFACE HUNSPELL_STATIC=1)
- target_link_libraries( ll::hunspell INTERFACE
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/libhunspell.lib
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libhunspell.lib
- )
-elseif(DARWIN)
- target_link_libraries( ll::hunspell INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libhunspell-1.7.a
- )
-elseif(LINUX)
- target_link_libraries( ll::hunspell INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libhunspell-1.7.a
- )
endif()
+
+find_library(HUNSPELL_LIBRARY
+ NAMES
+ libhunspell.lib
+ libhunspell-1.7.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::hunspell INTERFACE ${HUNSPELL_LIBRARY})
+
target_include_directories( ll::hunspell SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/hunspell)
diff --git a/indra/cmake/JPEG.cmake b/indra/cmake/JPEG.cmake
index ade5a070cc..f864ca7f8d 100644
--- a/indra/cmake/JPEG.cmake
+++ b/indra/cmake/JPEG.cmake
@@ -8,13 +8,13 @@ add_library( ll::libjpeg INTERFACE IMPORTED )
use_system_binary(libjpeg)
use_prebuilt_binary(libjpeg-turbo)
-if (LINUX)
- target_link_libraries( ll::libjpeg INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libjpeg.a)
-elseif (DARWIN)
- target_link_libraries( ll::libjpeg INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libjpeg.a)
-elseif (WINDOWS)
- target_link_libraries( ll::libjpeg INTERFACE
- debug ${ARCH_PREBUILT_DIRS_DEBUG}/jpeg.lib
- optimized ${ARCH_PREBUILT_DIRS_RELEASE}/jpeg.lib)
-endif (LINUX)
-target_include_directories( ll::libjpeg SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
+
+find_library(JPEG_LIBRARY
+ NAMES
+ jpeg.lib
+ libjpeg.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::libjpeg INTERFACE ${JPEG_LIBRARY})
+
+target_include_directories(ll::libjpeg SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
diff --git a/indra/cmake/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 6408f1200c..83725ffd1b 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -92,6 +92,13 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
target_include_directories (PROJECT_${project}_TEST_${name} PRIVATE ${LIBS_OPEN_DIR}/test )
set_target_properties(PROJECT_${project}_TEST_${name} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${EXE_STAGING_DIR}")
+ if (DARWIN)
+ set_target_properties(PROJECT_${project}_TEST_${name}
+ PROPERTIES
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_RPATH "@executable_path/Resources"
+ )
+ endif(DARWIN)
#
# Per-codefile additional / external project dep and lib dep property extraction
@@ -225,7 +232,10 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
# test binaries always need to be signed for local development
set_target_properties(INTEGRATION_TEST_${testname}
PROPERTIES
- XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-")
+ XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-"
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_RPATH "@executable_path/Resources"
+ )
endif ()
# Add link deps to the executable
diff --git a/indra/cmake/LLKDU.cmake b/indra/cmake/LLKDU.cmake
index 668b07ffab..7680ab7b54 100644
--- a/indra/cmake/LLKDU.cmake
+++ b/indra/cmake/LLKDU.cmake
@@ -13,14 +13,26 @@ add_library( ll::kdu INTERFACE IMPORTED )
if (USE_KDU)
include(Prebuilt)
use_prebuilt_binary(kdu)
+
if (WINDOWS)
- target_link_libraries( ll::kdu INTERFACE kdu.lib)
+ find_library(KDU_LIBRARY
+ NAMES
+ kdu
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
else (WINDOWS)
- target_link_libraries( ll::kdu INTERFACE libkdu.a)
+ find_library(KDU_LIBRARY
+ NAMES
+ libkdu.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
endif (WINDOWS)
+ target_link_libraries(ll::kdu INTERFACE ${KDU_LIBRARY})
+
target_include_directories( ll::kdu SYSTEM INTERFACE
${AUTOBUILD_INSTALL_DIR}/include/kdu
${LIBS_OPEN_DIR}/llkdu
)
+ target_compile_definitions(ll::kdu INTERFACE KDU_NO_THREADS=1)
endif (USE_KDU)
diff --git a/indra/cmake/LLPhysicsExtensions.cmake b/indra/cmake/LLPhysicsExtensions.cmake
index 80d243d9f8..84722b45a7 100644
--- a/indra/cmake/LLPhysicsExtensions.cmake
+++ b/indra/cmake/LLPhysicsExtensions.cmake
@@ -22,14 +22,25 @@ if (HAVOK)
include(Havok)
use_prebuilt_binary(llphysicsextensions_source)
set(LLPHYSICSEXTENSIONS_SRC_DIR ${LIBS_PREBUILT_DIR}/llphysicsextensions/src)
- target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensions)
+ if(DARWIN)
+ set(LLPHYSICSEXTENSIONS_STUB_DIR ${LIBS_PREBUILT_DIR}/llphysicsextensions/stub)
+ # can't set these library dependencies per-arch here, need to do it using XCODE_ATTRIBUTE_OTHER_LDFLAGS[arch=*] in newview/CMakeLists.txt
+ #target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensions)
+ #target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensionsstub)
+ else()
+ target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensions)
+ target_compile_definitions( llphysicsextensions_impl INTERFACE LL_HAVOK=1 )
+ endif()
+ target_include_directories( llphysicsextensions_impl INTERFACE ${LIBS_PREBUILT_DIR}/include/llphysicsextensions)
elseif (HAVOK_TPV)
use_prebuilt_binary(llphysicsextensions_tpv)
- target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensions_tpv)
-else (HAVOK)
- use_prebuilt_binary(llphysicsextensions_stub)
- set(LLPHYSICSEXTENSIONS_SRC_DIR ${LIBS_PREBUILT_DIR}/llphysicsextensions/stub)
- target_link_libraries( llphysicsextensions_impl INTERFACE llphysicsextensionsstub)
-endif (HAVOK)
-
-target_include_directories( llphysicsextensions_impl INTERFACE ${LIBS_PREBUILT_DIR}/include/llphysicsextensions)
+ if (NOT DARWIN)
+ if(WINDOWS)
+ target_link_libraries( llphysicsextensions_impl INTERFACE ${ARCH_PREBUILT_DIRS}/llphysicsextensions_tpv.lib)
+ elseif(LINUX)
+ target_link_libraries( llphysicsextensions_impl INTERFACE ${ARCH_PREBUILT_DIRS}/libllphysicsextensions_tpv.a)
+ endif()
+ target_compile_definitions( llphysicsextensions_impl INTERFACE LL_HAVOK=1 )
+ endif()
+ target_include_directories( llphysicsextensions_impl INTERFACE ${LIBS_PREBUILT_DIR}/include/llphysicsextensions)
+endif ()
diff --git a/indra/cmake/LLPrimitive.cmake b/indra/cmake/LLPrimitive.cmake
index d0a52ffb63..2699f8efee 100644
--- a/indra/cmake/LLPrimitive.cmake
+++ b/indra/cmake/LLPrimitive.cmake
@@ -24,26 +24,35 @@ use_prebuilt_binary(colladadom)
use_prebuilt_binary(minizip-ng) # needed for colladadom
use_prebuilt_binary(libxml2)
-if (WINDOWS)
- target_link_libraries( ll::minizip-ng INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/minizip.lib )
-else()
- target_link_libraries( ll::minizip-ng INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libminizip.a )
-endif()
+find_library(MINIZIPNG_LIBRARY
+ NAMES
+ minizip.lib
+ libminizip.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::minizip-ng INTERFACE ${MINIZIPNG_LIBRARY})
+
+find_library(LIBXML2_LIBRARY
+ NAMES
+ libxml2.lib
+ libxml2.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::libxml INTERFACE ${LIBXML2_LIBRARY})
if (WINDOWS)
- target_link_libraries( ll::libxml INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libxml2.lib Bcrypt.lib)
-else()
- target_link_libraries( ll::libxml INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libxml2.a)
+ target_link_libraries( ll::libxml INTERFACE Bcrypt.lib)
endif()
target_include_directories( ll::colladadom SYSTEM INTERFACE
${LIBS_PREBUILT_DIR}/include/collada
${LIBS_PREBUILT_DIR}/include/collada/1.4
)
-if (WINDOWS)
- target_link_libraries(ll::colladadom INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libcollada14dom23-s.lib ll::libxml ll::minizip-ng )
-elseif (DARWIN)
- target_link_libraries(ll::colladadom INTERFACE collada14dom ll::boost ll::libxml ll::minizip-ng)
-elseif (LINUX)
- target_link_libraries(ll::colladadom INTERFACE collada14dom ll::boost ll::libxml ll::minizip-ng)
-endif()
+
+find_library(COLLADADOM_LIBRARY
+ NAMES
+ libcollada14dom23-s.lib
+ collada14dom
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::colladadom INTERFACE ${COLLADADOM_LIBRARY} ll::boost ll::libxml ll::minizip-ng)
diff --git a/indra/cmake/LibVLCPlugin.cmake b/indra/cmake/LibVLCPlugin.cmake
index 599ce02844..6361028c0c 100644
--- a/indra/cmake/LibVLCPlugin.cmake
+++ b/indra/cmake/LibVLCPlugin.cmake
@@ -9,20 +9,16 @@ use_prebuilt_binary(vlc-bin)
set(LIBVLCPLUGIN ON CACHE BOOL
"LIBVLCPLUGIN support for the llplugin/llmedia test apps.")
-if (WINDOWS)
- target_link_libraries( ll::libvlc INTERFACE
- libvlc.lib
- libvlccore.lib
- )
-elseif (DARWIN)
- target_link_libraries( ll::libvlc INTERFACE
- libvlc.dylib
- libvlccore.dylib
- )
-elseif (LINUX)
- # Specify a full path to make sure we get a static link
- target_link_libraries( ll::libvlc INTERFACE
- ${LIBS_PREBUILT_DIR}/lib/libvlc.a
- ${LIBS_PREBUILT_DIR}/lib/libvlccore.a
- )
-endif (WINDOWS)
+find_library(VLC_LIBRARY
+ NAMES
+ libvlc.lib
+ libvlc.dylib
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+find_library(VLCCORE_LIBRARY
+ NAMES
+ libvlccore.lib
+ libvlccore.dylib
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::libvlc INTERFACE ${VLC_LIBRARY} ${VLCCORE_LIBRARY})
diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake
index 1d757abeff..900a64e2dd 100644
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -38,9 +38,10 @@ endif ()
# windows) and CMAKE_BUILD_TYPE on Makefile based generators (like linux). The reason for this is
# that CMAKE_BUILD_TYPE is essentially meaningless at configuration time for IDE generators and
# CMAKE_CFG_INTDIR is meaningless at build time for Makefile generators
-
-link_directories(${AUTOBUILD_INSTALL_DIR}/lib/$>)
-link_directories(${AUTOBUILD_INSTALL_DIR}/lib/release)
+if(NOT DARWIN)
+ link_directories(${AUTOBUILD_INSTALL_DIR}/lib/$>)
+ link_directories(${AUTOBUILD_INSTALL_DIR}/lib/release)
+endif(NOT DARWIN)
add_library( ll::oslibraries INTERFACE IMPORTED )
@@ -67,24 +68,25 @@ elseif (WINDOWS)
legacy_stdio_definitions
)
else()
- include(CMakeFindFrameworks)
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
find_library(CARBON_LIBRARY Carbon)
find_library(COCOA_LIBRARY Cocoa)
find_library(IOKIT_LIBRARY IOKit)
- find_library(AGL_LIBRARY AGL)
find_library(APPKIT_LIBRARY AppKit)
find_library(COREAUDIO_LIBRARY CoreAudio)
+ find_library(COREGRAPHICS_LIBRARY CoreGraphics)
+ find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox)
target_link_libraries( ll::oslibraries INTERFACE
${COCOA_LIBRARY}
${IOKIT_LIBRARY}
${COREFOUNDATION_LIBRARY}
${CARBON_LIBRARY}
- ${AGL_LIBRARY}
${APPKIT_LIBRARY}
${COREAUDIO_LIBRARY}
+ ${AUDIOTOOLBOX_LIBRARY}
+ ${COREGRAPHICS_LIBRARY}
)
endif()
diff --git a/indra/cmake/Meshoptimizer.cmake b/indra/cmake/Meshoptimizer.cmake
index fd144d2b97..af1c51f032 100644
--- a/indra/cmake/Meshoptimizer.cmake
+++ b/indra/cmake/Meshoptimizer.cmake
@@ -9,12 +9,12 @@ add_library( ll::meshoptimizer INTERFACE IMPORTED )
use_system_binary(meshoptimizer)
use_prebuilt_binary(meshoptimizer)
-if (WINDOWS)
- target_link_libraries( ll::meshoptimizer INTERFACE meshoptimizer.lib)
-elseif (LINUX)
- target_link_libraries( ll::meshoptimizer INTERFACE meshoptimizer.o)
-elseif (DARWIN)
- target_link_libraries( ll::meshoptimizer INTERFACE libmeshoptimizer.a)
-endif (WINDOWS)
+find_library(MESHOPTIMIZER_LIBRARY
+ NAMES
+ meshoptimizer.lib
+ libmeshoptimizer.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
-target_include_directories( ll::meshoptimizer SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/meshoptimizer)
+target_link_libraries(ll::meshoptimizer INTERFACE ${MESHOPTIMIZER_LIBRARY})
+
+target_include_directories(ll::meshoptimizer SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/meshoptimizer)
diff --git a/indra/cmake/NDOF.cmake b/indra/cmake/NDOF.cmake
index b88fbccf2a..a8f63f945b 100644
--- a/indra/cmake/NDOF.cmake
+++ b/indra/cmake/NDOF.cmake
@@ -13,12 +13,15 @@ if (NDOF)
use_prebuilt_binary(open-libndofdev)
endif (WINDOWS OR DARWIN)
- if (WINDOWS)
- target_link_libraries( ll::ndof INTERFACE libndofdev)
- elseif (DARWIN OR LINUX)
- target_link_libraries( ll::ndof INTERFACE ndofdev)
- endif (WINDOWS)
- target_compile_definitions( ll::ndof INTERFACE LIB_NDOF=1)
+ find_library(NDOF_LIBRARY
+ NAMES
+ libndofdev
+ ndofdev
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ target_link_libraries(ll::ndof INTERFACE ${NDOF_LIBRARY})
+
+ target_compile_definitions(ll::ndof INTERFACE LIB_NDOF=1)
endif (NDOF)
diff --git a/indra/cmake/NGHTTP2.cmake b/indra/cmake/NGHTTP2.cmake
index 7b2aa5971f..e81204d716 100644
--- a/indra/cmake/NGHTTP2.cmake
+++ b/indra/cmake/NGHTTP2.cmake
@@ -6,9 +6,12 @@ add_library( ll::nghttp2 INTERFACE IMPORTED )
use_system_binary(nghttp2)
use_prebuilt_binary(nghttp2)
-if (WINDOWS)
- target_link_libraries( ll::nghttp2 INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/nghttp2.lib)
-else ()
- target_link_libraries( ll::nghttp2 INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libnghttp2.a)
-endif ()
+
+find_library(NGHTTP2_LIBRARY
+ NAMES
+ nghttp2.lib
+ libnghttp2.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::nghttp2 INTERFACE ${NGHTTP2_LIBRARY})
target_include_directories( ll::nghttp2 SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/nghttp2)
diff --git a/indra/cmake/OPENAL.cmake b/indra/cmake/OPENAL.cmake
index 347dd02cd7..ab1604aa22 100644
--- a/indra/cmake/OPENAL.cmake
+++ b/indra/cmake/OPENAL.cmake
@@ -8,7 +8,7 @@ include_guard()
# to have memory leaks, has no option to play music streams
# It probably makes sense to to completely remove it
-set(USE_OPENAL OFF CACHE BOOL "Enable OpenAL")
+set(USE_OPENAL ON CACHE BOOL "Enable OpenAL")
# ND: To streamline arguments passed, switch from OPENAL to USE_OPENAL
# To not break all old build scripts convert old arguments but warn about it
if(OPENAL)
@@ -22,20 +22,21 @@ if (USE_OPENAL)
target_compile_definitions( ll::openal INTERFACE LL_OPENAL=1)
use_prebuilt_binary(openal)
- if(WINDOWS)
- target_link_libraries( ll::openal INTERFACE
- OpenAL32
- alut
- )
- elseif(LINUX)
- target_link_libraries( ll::openal INTERFACE
- openal
- alut
- )
- else()
- target_link_libraries( ll::openal INTERFACE
- openal
- alut
- )
- endif()
+ find_library(OPENAL_LIBRARY
+ NAMES
+ OpenAL32
+ openal
+ libopenal.dylib
+ libopenal.so
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ find_library(ALUT_LIBRARY
+ NAMES
+ alut
+ libalut.dylib
+ libalut.so
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+ target_link_libraries(ll::openal INTERFACE ${OPENAL_LIBRARY} ${ALUT_LIBRARY})
+
endif ()
diff --git a/indra/cmake/OpenJPEG.cmake b/indra/cmake/OpenJPEG.cmake
index c4aab2e9e5..95e71fd78e 100644
--- a/indra/cmake/OpenJPEG.cmake
+++ b/indra/cmake/OpenJPEG.cmake
@@ -1,11 +1,22 @@
# -*- cmake -*-
-include(Prebuilt)
-
include_guard()
+
+include(Prebuilt)
+include(Linking)
+
add_library( ll::openjpeg INTERFACE IMPORTED )
use_system_binary(openjpeg)
use_prebuilt_binary(openjpeg)
-target_link_libraries(ll::openjpeg INTERFACE openjp2 )
-target_include_directories( ll::openjpeg SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/openjpeg)
+find_library(OPENJPEG_LIBRARY
+ NAMES
+ openjp2
+ openjp2.lib
+ libopenjp2.a
+ libopenjp2.so
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::openjpeg INTERFACE ${OPENJPEG_LIBRARY})
+
+target_include_directories(ll::openjpeg SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/openjpeg)
diff --git a/indra/cmake/OpenSSL.cmake b/indra/cmake/OpenSSL.cmake
index 67a84e14af..9d33f2e0de 100644
--- a/indra/cmake/OpenSSL.cmake
+++ b/indra/cmake/OpenSSL.cmake
@@ -7,12 +7,24 @@ add_library( ll::openssl INTERFACE IMPORTED )
use_system_binary(openssl)
use_prebuilt_binary(openssl)
+
+find_library(SSL_LIBRARY
+ NAMES
+ libssl.lib
+ libssl.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+find_library(CRYPTO_LIBRARY
+ NAMES
+ libcrypto.lib
+ libcrypto.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::openssl INTERFACE ${SSL_LIBRARY} ${CRYPTO_LIBRARY})
+
if (WINDOWS)
- target_link_libraries(ll::openssl INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libssl.lib ${ARCH_PREBUILT_DIRS_RELEASE}/libcrypto.lib Crypt32.lib)
-elseif (LINUX)
- target_link_libraries(ll::openssl INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libssl.a ${ARCH_PREBUILT_DIRS_RELEASE}/libcrypto.a dl)
-else()
- target_link_libraries(ll::openssl INTERFACE ssl crypto)
+ target_link_libraries(ll::openssl INTERFACE Crypt32.lib)
endif (WINDOWS)
-target_include_directories( ll::openssl SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
+
+target_include_directories(ll::openssl SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include)
diff --git a/indra/cmake/PNG.cmake b/indra/cmake/PNG.cmake
index e5893e9a20..0c01e5ee78 100644
--- a/indra/cmake/PNG.cmake
+++ b/indra/cmake/PNG.cmake
@@ -6,9 +6,12 @@ add_library( ll::libpng INTERFACE IMPORTED )
use_system_binary(libpng)
use_prebuilt_binary(libpng)
-if (WINDOWS)
- target_link_libraries(ll::libpng INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libpng16.lib)
-else()
- target_link_libraries(ll::libpng INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libpng16.a)
-endif()
-target_include_directories( ll::libpng SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/libpng16)
+
+find_library(LIBPNG_LIBRARY
+ NAMES
+ libpng16.lib
+ libpng16.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::libpng INTERFACE ${LIBPNG_LIBRARY})
+target_include_directories(ll::libpng SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/libpng16)
diff --git a/indra/cmake/PluginAPI.cmake b/indra/cmake/PluginAPI.cmake
index 114415e514..a2bf13db2c 100644
--- a/indra/cmake/PluginAPI.cmake
+++ b/indra/cmake/PluginAPI.cmake
@@ -1,5 +1,7 @@
# -*- cmake -*-
+include(OpenGL)
+
add_library( ll::pluginlibraries INTERFACE IMPORTED )
if (WINDOWS)
@@ -13,4 +15,6 @@ if (WINDOWS)
)
endif (WINDOWS)
+target_link_libraries( ll::pluginlibraries INTERFACE OpenGL::GL)
+target_include_directories( ll::pluginlibraries INTERFACE ${CMAKE_SOURCE_DIR}/llimage ${CMAKE_SOURCE_DIR}/llrender)
diff --git a/indra/cmake/Python.cmake b/indra/cmake/Python.cmake
index da5d2ef22c..7cce190f6a 100644
--- a/indra/cmake/Python.cmake
+++ b/indra/cmake/Python.cmake
@@ -13,7 +13,7 @@ elseif (WINDOWS)
foreach(hive HKEY_CURRENT_USER HKEY_LOCAL_MACHINE)
# prefer more recent Python versions to older ones, if multiple versions
# are installed
- foreach(pyver 3.12 3.11 3.10 3.9 3.8 3.7)
+ foreach(pyver 3.13 3.12 3.11 3.10 3.9 3.8 3.7)
list(APPEND regpaths "[${hive}\\SOFTWARE\\Python\\PythonCore\\${pyver}\\InstallPath]")
endforeach()
endforeach()
diff --git a/indra/cmake/SSE2NEON.cmake b/indra/cmake/SSE2NEON.cmake
new file mode 100644
index 0000000000..797f2af80e
--- /dev/null
+++ b/indra/cmake/SSE2NEON.cmake
@@ -0,0 +1,12 @@
+# -*- cmake -*-
+
+include(Prebuilt)
+
+add_library(ll::sse2neon INTERFACE IMPORTED)
+
+if (DARWIN)
+ use_system_binary(sse2neon)
+ use_prebuilt_binary(sse2neon)
+
+ target_include_directories( ll::sse2neon SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/sse2neon)
+endif()
diff --git a/indra/cmake/Tracy.cmake b/indra/cmake/Tracy.cmake
index a7eac2711f..cb09337d15 100644
--- a/indra/cmake/Tracy.cmake
+++ b/indra/cmake/Tracy.cmake
@@ -15,6 +15,7 @@ endif()
if (USE_TRACY)
option(USE_TRACY_ON_DEMAND "Use on-demand Tracy profiling." ON)
option(USE_TRACY_LOCAL_ONLY "Disallow remote Tracy profiling." OFF)
+ option(USE_TRACY_GPU "Use Tracy GPU profiling" OFF)
use_system_binary(tracy)
use_prebuilt_binary(tracy)
@@ -31,9 +32,8 @@ if (USE_TRACY)
target_compile_definitions(ll::tracy INTERFACE -DTRACY_NO_BROADCAST=1 -DTRACY_ONLY_LOCALHOST=1)
endif ()
- # GHA runners don't always provide invariant TSC support, but always build with LL_TESTS enabled
- if (DARWIN AND LL_TESTS)
- target_compile_definitions(ll::tracy INTERFACE -DTRACY_TIMER_FALLBACK=1)
+ if (USE_TRACY_GPU AND NOT DARWIN) # Tracy OpenGL mode is incompatible with macOS/iOS
+ target_compile_definitions(ll::tracy INTERFACE -DLL_PROFILER_ENABLE_TRACY_OPENGL=1)
endif ()
# See: indra/llcommon/llprofiler.h
diff --git a/indra/cmake/VHACD.cmake b/indra/cmake/VHACD.cmake
new file mode 100644
index 0000000000..9f37f32b2d
--- /dev/null
+++ b/indra/cmake/VHACD.cmake
@@ -0,0 +1,9 @@
+# -*- cmake -*-
+include(Prebuilt)
+
+add_library(ll::vhacd INTERFACE IMPORTED)
+
+use_system_binary(vhacd)
+use_prebuilt_binary(vhacd)
+
+target_include_directories(ll::vhacd SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/vhacd/)
diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake
index 5b3aeb8b7f..22c2156bb8 100644
--- a/indra/cmake/Variables.cmake
+++ b/indra/cmake/Variables.cmake
@@ -144,52 +144,19 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(DARWIN 1)
string(REGEX MATCH "-mmacosx-version-min=([^ ]+)" scratch "$ENV{LL_BUILD}")
- set(CMAKE_OSX_DEPLOYMENT_TARGET "${CMAKE_MATCH_1}")
+ set(CMAKE_OSX_DEPLOYMENT_TARGET "${CMAKE_MATCH_1}" CACHE STRING "macOS Deploy Target" FORCE)
message(STATUS "CMAKE_OSX_DEPLOYMENT_TARGET = '${CMAKE_OSX_DEPLOYMENT_TARGET}'")
- string(REGEX MATCH "-stdlib=([^ ]+)" scratch "$ENV{LL_BUILD}")
- set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "${CMAKE_MATCH_1}")
- message(STATUS "CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY = '${CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY}'")
-
- string(REGEX MATCH " -g([^ ]*)" scratch "$ENV{LL_BUILD}")
- set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "${CMAKE_MATCH_1}")
- # -gdwarf-2 is passed in LL_BUILD according to 00-COMPILE-LINK-RUN.txt.
- # However, when CMake 3.9.2 sees -gdwarf-2, it silently deletes the whole -g
- # switch, producing no symbols at all! The same thing happens if we specify
- # plain -g ourselves, i.e. CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT is
- # the empty string. Specifying -gdwarf-with-dsym or just -gdwarf drives a
- # different CMake behavior: it substitutes plain -g. As of 2017-09-19,
- # viewer-build-variables/variables still passes -gdwarf-2, which is the
- # no-symbols case. Set -gdwarf, triggering CMake to substitute plain -g --
- # at least that way we should get symbols, albeit mangled ones. It Would Be
- # Nice if CMake's behavior could be predicted from a consistent mental
- # model, instead of only observed experimentally.
- string(REPLACE "dwarf-2" "dwarf"
- CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT
- "${CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT}")
- message(STATUS "CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT = '${CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT}'")
+ # Use dwarf symbols for most libraries for compilation speed
+ set(CMAKE_XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf")
string(REGEX MATCH "-O([^ ]*)" scratch "$ENV{LL_BUILD}")
set(CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL "${CMAKE_MATCH_1}")
message(STATUS "CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL = '${CMAKE_XCODE_ATTRIBUTE_GCC_OPTIMIZATION_LEVEL}'")
- # allow disabling this check by setting LL_SKIP_REQUIRE_SYSROOT either ON as cmake cache var or non-empty as environment var
- set(LL_SKIP_REQUIRE_SYSROOT OFF CACHE BOOL "Skip requirement to set toolchain sysroot ahead of time. Not skipped by default for consistency, but skipping can be useful for selecting alternative xcode versions side by side")
- if("$ENV{LL_SKIP_REQUIRE_SYSROOT}" STREQUAL "" AND NOT ${LL_SKIP_REQUIRE_SYSROOT})
- string(REGEX MATCHALL "[^ ]+" LL_BUILD_LIST "$ENV{LL_BUILD}")
- list(FIND LL_BUILD_LIST "-iwithsysroot" sysroot_idx)
- if ("${sysroot_idx}" LESS 0)
- message(FATAL_ERROR "Environment variable LL_BUILD must contain '-iwithsysroot'")
- endif ()
- math(EXPR sysroot_idx "${sysroot_idx} + 1")
- list(GET LL_BUILD_LIST "${sysroot_idx}" CMAKE_OSX_SYSROOT)
- endif()
- message(STATUS "CMAKE_OSX_SYSROOT = '${CMAKE_OSX_SYSROOT}'")
-
- set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvm.clang.1_0")
set(CMAKE_XCODE_ATTRIBUTE_GCC_STRICT_ALIASING NO)
set(CMAKE_XCODE_ATTRIBUTE_GCC_FAST_MATH NO)
- set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS ssse3)
+ set(CMAKE_XCODE_ATTRIBUTE_CLANG_X86_VECTOR_INSTRUCTIONS sse4.2)
# we must hard code this to off for now. xcode's built in signing does not
# handle embedded app bundles such as CEF and others. Any signing for local
# development must be done after the build as we do in viewer_manifest.py for
@@ -204,9 +171,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_ENTITLEMENTS "")
set(CMAKE_XCODE_ATTRIBUTE_DISABLE_MANUAL_TARGET_ORDER_BUILD_WARNING YES)
set(CMAKE_XCODE_ATTRIBUTE_GCC_WARN_64_TO_32_BIT_CONVERSION NO)
- set(CMAKE_OSX_ARCHITECTURES "${ARCH}")
- string(REPLACE "i686" "i386" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
- string(REPLACE "AMD64" "x86_64" CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}")
+ set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "macOS Build Arch" FORCE)
endif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# Default deploy grid
diff --git a/indra/cmake/WebRTC.cmake b/indra/cmake/WebRTC.cmake
index 230522a40a..7fefaa4152 100644
--- a/indra/cmake/WebRTC.cmake
+++ b/indra/cmake/WebRTC.cmake
@@ -1,32 +1,24 @@
# -*- cmake -*-
+include_guard()
+
include(Linking)
include(Prebuilt)
-include_guard()
-
add_library( ll::webrtc INTERFACE IMPORTED )
target_include_directories( ll::webrtc SYSTEM INTERFACE "${LIBS_PREBUILT_DIR}/include/webrtc" "${LIBS_PREBUILT_DIR}/include/webrtc/third_party/abseil-cpp")
use_prebuilt_binary(webrtc)
-if (WINDOWS)
- target_link_libraries( ll::webrtc INTERFACE webrtc.lib )
-elseif (DARWIN)
- FIND_LIBRARY(COREAUDIO_LIBRARY CoreAudio)
- FIND_LIBRARY(COREGRAPHICS_LIBRARY CoreGraphics)
- FIND_LIBRARY(AUDIOTOOLBOX_LIBRARY AudioToolbox)
- FIND_LIBRARY(COREFOUNDATION_LIBRARY CoreFoundation)
- FIND_LIBRARY(COCOA_LIBRARY Cocoa)
+find_library(WEBRTC_LIBRARY
+ NAMES
+ webrtc
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
- target_link_libraries( ll::webrtc INTERFACE
- libwebrtc.a
- ${COREAUDIO_LIBRARY}
- ${AUDIOTOOLBOX_LIBRARY}
- ${COREGRAPHICS_LIBRARY}
- ${COREFOUNDATION_LIBRARY}
- ${COCOA_LIBRARY}
- )
+target_link_libraries( ll::webrtc INTERFACE ${WEBRTC_LIBRARY} )
+
+if (DARWIN)
+ target_link_libraries( ll::webrtc INTERFACE ll::oslibraries )
elseif (LINUX)
- target_link_libraries( ll::webrtc INTERFACE libwebrtc.a X11 )
-endif (WINDOWS)
+ target_link_libraries( ll::webrtc INTERFACE X11 )
+endif ()
diff --git a/indra/cmake/ZLIBNG.cmake b/indra/cmake/ZLIBNG.cmake
index d7b920da26..a6d67489e7 100644
--- a/indra/cmake/ZLIBNG.cmake
+++ b/indra/cmake/ZLIBNG.cmake
@@ -11,11 +11,14 @@ if(USE_CONAN )
endif()
use_prebuilt_binary(zlib-ng)
-if (WINDOWS)
- target_link_libraries( ll::zlib-ng INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/zlib.lib )
-else()
- target_link_libraries( ll::zlib-ng INTERFACE ${ARCH_PREBUILT_DIRS_RELEASE}/libz.a )
-endif (WINDOWS)
+
+find_library(ZLIBNG_LIBRARY
+ NAMES
+ zlib.lib
+ libz.a
+ PATHS "${ARCH_PREBUILT_DIRS_RELEASE}" REQUIRED NO_DEFAULT_PATH)
+
+target_link_libraries(ll::zlib-ng INTERFACE ${ZLIBNG_LIBRARY})
if( NOT LINUX )
target_include_directories( ll::zlib-ng SYSTEM INTERFACE ${LIBS_PREBUILT_DIR}/include/zlib-ng)
diff --git a/indra/cmake/bugsplat.cmake b/indra/cmake/bugsplat.cmake
index 509981d72c..d2a8fcca46 100644
--- a/indra/cmake/bugsplat.cmake
+++ b/indra/cmake/bugsplat.cmake
@@ -23,8 +23,14 @@ if (USE_BUGSPLAT)
elseif (DARWIN)
find_library(BUGSPLAT_LIBRARIES BugsplatMac REQUIRED
NO_DEFAULT_PATH PATHS "${ARCH_PREBUILT_DIRS_RELEASE}")
+ find_library(CRASHREPORTED_LIBRARIES CrashReporter REQUIRED
+ NO_DEFAULT_PATH PATHS "${ARCH_PREBUILT_DIRS_RELEASE}")
+ find_library(HOCKEYSDK_LIBRARIES HockeySDK REQUIRED
+ NO_DEFAULT_PATH PATHS "${ARCH_PREBUILT_DIRS_RELEASE}")
target_link_libraries( ll::bugsplat INTERFACE
${BUGSPLAT_LIBRARIES}
+ ${CRASHREPORTED_LIBRARIES}
+ ${HOCKEYSDK_LIBRARIES}
)
else (WINDOWS)
message(FATAL_ERROR "BugSplat is not supported; add -DUSE_BUGSPLAT=OFF")
diff --git a/indra/cmake/xxHash.cmake b/indra/cmake/xxHash.cmake
index a7c1cba62c..e4f8517d9b 100644
--- a/indra/cmake/xxHash.cmake
+++ b/indra/cmake/xxHash.cmake
@@ -1,8 +1,5 @@
# -*- cmake -*-
-if (XXHASH_CMAKE_INCLUDED)
- return()
-endif (XXHASH_CMAKE_INCLUDED)
-set (XXHASH_CMAKE_INCLUDED TRUE)
+include_guard()
include(Prebuilt)
use_prebuilt_binary(xxhash)
diff --git a/indra/doxygen/CMakeLists.txt b/indra/doxygen/CMakeLists.txt
index 616b5cd09c..43ebf4ae26 100644
--- a/indra/doxygen/CMakeLists.txt
+++ b/indra/doxygen/CMakeLists.txt
@@ -1,19 +1,5 @@
# -*- cmake -*-
-# cmake_minimum_required should appear before any
-# other commands to guarantee full compatibility
-# with the version specified
-## prior to 2.8, the add_custom_target commands used in setting the version did not work correctly
-cmake_minimum_required(VERSION 3.8.0 FATAL_ERROR)
-
-set(ROOT_PROJECT_NAME "SecondLife" CACHE STRING
- "The root project/makefile/solution name. Defaults to SecondLife.")
-project(${ROOT_PROJECT_NAME})
-
-set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
-
-include(Variables)
-
# add a target to generate API documentation with Doxygen
find_package(Doxygen)
if(DOXYGEN_FOUND)
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
deleted file mode 100644
index 8b13789179..0000000000
--- a/indra/edit-me-to-trigger-new-build.txt
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/indra/integration_tests/CMakeLists.txt b/indra/integration_tests/CMakeLists.txt
index ced2b3dbcf..1d5f0772b5 100644
--- a/indra/integration_tests/CMakeLists.txt
+++ b/indra/integration_tests/CMakeLists.txt
@@ -1,8 +1,3 @@
# -*- cmake -*-
add_subdirectory(llui_libtest)
-IF (LLIMAGE_LIBTEST)
- MESSAGE(STATUS "Build llimage_libtest")
- add_subdirectory(llimage_libtest)
-ELSE (LLIMAGE_LIBTEST)
- MESSAGE(STATUS "Skip llimage_libtest")
-ENDIF (LLIMAGE_LIBTEST)
+add_subdirectory(llimage_libtest)
diff --git a/indra/integration_tests/llimage_libtest/CMakeLists.txt b/indra/integration_tests/llimage_libtest/CMakeLists.txt
index ee2890778b..e6ff142626 100644
--- a/indra/integration_tests/llimage_libtest/CMakeLists.txt
+++ b/indra/integration_tests/llimage_libtest/CMakeLists.txt
@@ -1,6 +1,7 @@
# -*- cmake -*-
# Integration tests of the llimage library (JPEG2000, PNG, jpeg, etc... images reading and writing)
+if (LL_TESTS)
project (llimage_libtest)
@@ -8,9 +9,7 @@ include(00-Common)
include(LLCommon)
include(LLImage)
include(LLMath)
-include(LLImageJ2COJ)
include(LLKDU)
-include(LLFileSystem)
set(llimage_libtest_SOURCE_FILES
llimage_libtest.cpp
@@ -24,17 +23,9 @@ set(llimage_libtest_HEADER_FILES
list(APPEND llimage_libtest_SOURCE_FILES ${llimage_libtest_HEADER_FILES})
add_executable(llimage_libtest
- WIN32
- MACOSX_BUNDLE
${llimage_libtest_SOURCE_FILES}
)
-set_target_properties(llimage_libtest
- PROPERTIES
- WIN32_EXECUTABLE
- FALSE
-)
-
# Libraries on which this application depends on
# Sort by high-level to low-level
target_link_libraries(llimage_libtest
@@ -42,64 +33,9 @@ target_link_libraries(llimage_libtest
llfilesystem
llmath
llimage
- llkdu
- llimagej2coj
)
-
-if (DARWIN)
- # Path inside the app bundle where we'll need to copy libraries
- set(LLIMAGE_LIBTEST_DESTINATION_DIR
- ${CMAKE_CURRENT_BINARY_DIR}/$,$,>/llimage_libtest.app/Contents/Resources
- )
- # Create the Contents/Resources directory
- add_custom_command(
- TARGET llimage_libtest POST_BUILD
- COMMAND ${CMAKE_COMMAND}
- ARGS
- -E
- make_directory
- ${LLIMAGE_LIBTEST_DESTINATION_DIR}
- COMMENT "Creating Resources directory in app bundle."
- )
-else (DARWIN)
- set(LLIMAGE_LIBTEST_DESTINATION_DIR
- ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
- )
-endif (DARWIN)
-
-get_target_property(BUILT_LLCOMMON llcommon LOCATION)
-add_custom_command(TARGET llimage_libtest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_LLCOMMON} ${LLIMAGE_LIBTEST_DESTINATION_DIR}
- DEPENDS ${BUILT_LLCOMMON}
-)
-
-if (DARWIN)
- # Copy the required libraries to the package app
- add_custom_command(TARGET llimage_libtest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libapr-1.0.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
- DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libapr-1.0.dylib
- )
- add_custom_command(TARGET llimage_libtest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libaprutil-1.0.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
- DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libaprutil-1.0.dylib
- )
- add_custom_command(TARGET llimage_libtest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/libexception_handler.dylib ${LLIMAGE_LIBTEST_DESTINATION_DIR}
- DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/libexception_handler.dylib
- )
- foreach(expat ${EXPAT_COPY})
- add_custom_command(TARGET llimage_libtest POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E copy ${AUTOBUILD_INSTALL_DIR}/lib/release/${expat} ${LLIMAGE_LIBTEST_DESTINATION_DIR}
- DEPENDS ${AUTOBUILD_INSTALL_DIR}/lib/release/${expat}
- )
- endforeach(expat)
-endif (DARWIN)
-
-if (WINDOWS)
- # Check indra/test_apps/llplugintest/CMakeLists.txt for an example of what to copy over for Windows and how
-endif (WINDOWS)
# Ensure people working on the viewer don't break this library
-# *NOTE: This could be removed, or only built by TeamCity, if the build
-# and link times become too long.
add_dependencies(viewer llimage_libtest)
+
+endif(LL_TESTS)
diff --git a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
index 95102094ae..c45bd6fd01 100644
--- a/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
+++ b/indra/integration_tests/llimage_libtest/llimage_libtest.cpp
@@ -43,6 +43,8 @@
#include "v4coloru.h"
#include "llsdserialize.h"
#include "llcleanup.h"
+#include "lltrace.h"
+#include "llfasttimer.h"
// system libraries
#include
@@ -573,10 +575,10 @@ int main(int argc, char** argv)
// Create the logging thread if required
- if (LLFastTimer::sMetricLog)
+ if (LLTrace::BlockTimer::sMetricLog)
{
- LLFastTimer::sLogLock = new LLMutex(NULL);
- fast_timer_log_thread = new LogThread(LLFastTimer::sLogName);
+ LLTrace::BlockTimer::setLogLock(new LLMutex());
+ fast_timer_log_thread = new LogThread(LLTrace::BlockTimer::sLogName);
fast_timer_log_thread->start();
}
@@ -618,9 +620,9 @@ int main(int argc, char** argv)
// Output perf data if requested by user
if (analyze_performance)
{
- std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp";
- std::string current_name = LLFastTimer::sLogName + ".slp";
- std::string report_name = LLFastTimer::sLogName + "_report.csv";
+ std::string baseline_name = LLTrace::BlockTimer::sLogName + "_baseline.slp";
+ std::string current_name = LLTrace::BlockTimer::sLogName + ".slp";
+ std::string report_name = LLTrace::BlockTimer::sLogName + "_report.csv";
std::cout << "Analyzing performance, check report in : " << report_name << std::endl;
@@ -628,9 +630,9 @@ int main(int argc, char** argv)
}
// Stop the perf gathering system if needed
- if (LLFastTimer::sMetricLog)
+ if (LLTrace::BlockTimer::sMetricLog)
{
- LLMetricPerformanceTesterBasic::deleteTester(LLFastTimer::sLogName);
+ LLMetricPerformanceTesterBasic::deleteTester(LLTrace::BlockTimer::sLogName);
sAllDone = true;
}
diff --git a/indra/llappearance/CMakeLists.txt b/indra/llappearance/CMakeLists.txt
index c3be8bc78e..6744c8d8a4 100644
--- a/indra/llappearance/CMakeLists.txt
+++ b/indra/llappearance/CMakeLists.txt
@@ -14,6 +14,7 @@ set(llappearance_SOURCE_FILES
llavatarjoint.cpp
llavatarjointmesh.cpp
lldriverparam.cpp
+ lljointdata.h
lllocaltextureobject.cpp
llpolyskeletaldistortion.cpp
llpolymesh.cpp
diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp
index 95d55c835f..dab18c240d 100644
--- a/indra/llappearance/llavatarappearance.cpp
+++ b/indra/llappearance/llavatarappearance.cpp
@@ -29,16 +29,17 @@
#include "llavatarappearance.h"
#include "llavatarappearancedefines.h"
#include "llavatarjointmesh.h"
+#include "lljointdata.h"
#include "llstl.h"
#include "lldir.h"
#include "llpolymorph.h"
#include "llpolymesh.h"
#include "llpolyskeletaldistortion.h"
-#include "llstl.h"
#include "lltexglobalcolor.h"
#include "llwearabledata.h"
#include "boost/bind.hpp"
#include "boost/tokenizer.hpp"
+#include "v4math.h"
using namespace LLAvatarAppearanceDefines;
@@ -71,11 +72,13 @@ public:
mChildren.clear();
}
bool parseXml(LLXmlTreeNode* node);
+ glm::mat4 getJointMatrix();
private:
std::string mName;
std::string mSupport;
std::string mAliases;
+ std::string mGroup;
bool mIsJoint;
LLVector3 mPos;
LLVector3 mEnd;
@@ -105,11 +108,17 @@ public:
S32 getNumBones() const { return mNumBones; }
S32 getNumCollisionVolumes() const { return mNumCollisionVolumes; }
+private:
+ typedef std::vector bone_info_list_t;
+ static void getJointMatricesAndHierarhy(
+ LLAvatarBoneInfo* bone_info,
+ LLJointData& data,
+ const glm::mat4& parent_mat);
+
private:
S32 mNumBones;
S32 mNumCollisionVolumes;
LLAvatarAppearance::joint_alias_map_t mJointAliasMap;
- typedef std::vector bone_info_list_t;
bone_info_list_t mBoneInfoList;
};
@@ -799,7 +808,6 @@ void LLAvatarAppearance::buildCharacter()
bool status = loadAvatar();
stop_glerror();
-// gPrintMessagesThisFrame = true;
LL_DEBUGS() << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << LL_ENDL;
if (!status)
@@ -1599,6 +1607,15 @@ bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
mSupport = "base";
}
+ // Skeleton has 133 bones, but shader only allows 110 (LL_MAX_JOINTS_PER_MESH_OBJECT)
+ // Groups can be used by importer to cut out unused groups of joints
+ static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group");
+ if (!node->getFastAttributeString(group_string, mGroup))
+ {
+ LL_WARNS() << "Bone without group " << mName << LL_ENDL;
+ mGroup = "global";
+ }
+
if (mIsJoint)
{
static LLStdStringHandle pivot_string = LLXmlTree::addAttributeString("pivot");
@@ -1624,6 +1641,21 @@ bool LLAvatarBoneInfo::parseXml(LLXmlTreeNode* node)
return true;
}
+
+glm::mat4 LLAvatarBoneInfo::getJointMatrix()
+{
+ glm::mat4 mat(1.0f);
+ // 1. Scaling
+ mat = glm::scale(mat, glm::vec3(mScale[0], mScale[1], mScale[2]));
+ // 2. Rotation (Euler angles rad)
+ mat = glm::rotate(mat, mRot[0], glm::vec3(1, 0, 0));
+ mat = glm::rotate(mat, mRot[1], glm::vec3(0, 1, 0));
+ mat = glm::rotate(mat, mRot[2], glm::vec3(0, 0, 1));
+ // 3. Position
+ mat = glm::translate(mat, glm::vec3(mPos[0], mPos[1], mPos[2]));
+ return mat;
+}
+
//-----------------------------------------------------------------------------
// LLAvatarSkeletonInfo::parseXml()
//-----------------------------------------------------------------------------
@@ -1654,6 +1686,25 @@ bool LLAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node)
return true;
}
+void LLAvatarSkeletonInfo::getJointMatricesAndHierarhy(
+ LLAvatarBoneInfo* bone_info,
+ LLJointData& data,
+ const glm::mat4& parent_mat)
+{
+ data.mName = bone_info->mName;
+ data.mJointMatrix = bone_info->getJointMatrix();
+ data.mScale = glm::vec3(bone_info->mScale[0], bone_info->mScale[1], bone_info->mScale[2]);
+ data.mRotation = bone_info->mRot;
+ data.mRestMatrix = parent_mat * data.mJointMatrix;
+ data.mIsJoint = bone_info->mIsJoint;
+ data.mGroup = bone_info->mGroup;
+ for (LLAvatarBoneInfo* child_info : bone_info->mChildren)
+ {
+ LLJointData& child_data = data.mChildren.emplace_back();
+ getJointMatricesAndHierarhy(child_info, child_data, data.mRestMatrix);
+ }
+}
+
//Make aliases for joint and push to map.
void LLAvatarAppearance::makeJointAliases(LLAvatarBoneInfo *bone_info)
{
@@ -1715,6 +1766,16 @@ const LLAvatarAppearance::joint_alias_map_t& LLAvatarAppearance::getJointAliases
return mJointAliasMap;
}
+void LLAvatarAppearance::getJointMatricesAndHierarhy(std::vector &data) const
+{
+ glm::mat4 identity(1.f);
+ for (LLAvatarBoneInfo* bone_info : sAvatarSkeletonInfo->mBoneInfoList)
+ {
+ LLJointData& child_data = data.emplace_back();
+ LLAvatarSkeletonInfo::getJointMatricesAndHierarhy(bone_info, child_data, identity);
+ }
+}
+
//-----------------------------------------------------------------------------
// parseXmlSkeletonNode(): parses nodes from XML tree
diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h
index 13e504e639..84cb42056a 100644
--- a/indra/llappearance/llavatarappearance.h
+++ b/indra/llappearance/llavatarappearance.h
@@ -34,6 +34,7 @@
#include "lltexlayer.h"
#include "llviewervisualparam.h"
#include "llxmltree.h"
+#include "v4math.h"
class LLTexLayerSet;
class LLTexGlobalColor;
@@ -41,6 +42,7 @@ class LLTexGlobalColorInfo;
class LLWearableData;
class LLAvatarBoneInfo;
class LLAvatarSkeletonInfo;
+class LLJointData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// LLAvatarAppearance
@@ -138,7 +140,7 @@ public:
LLVector3 mHeadOffset{}; // current head position
LLAvatarJoint* mRoot{ nullptr };
- typedef std::map joint_map_t;
+ typedef std::map> joint_map_t;
joint_map_t mJointMap;
typedef std::map joint_state_map_t;
@@ -151,9 +153,11 @@ public:
public:
typedef std::vector avatar_joint_list_t;
const avatar_joint_list_t& getSkeleton() { return mSkeleton; }
- typedef std::map joint_alias_map_t;
+ typedef std::map> joint_alias_map_t;
const joint_alias_map_t& getJointAliases();
-
+ typedef std::map joint_parent_map_t; // matrix plus parent
+ typedef std::map joint_rest_map_t;
+ void getJointMatricesAndHierarhy(std::vector &data) const;
protected:
static bool parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree);
diff --git a/indra/llappearance/lljointdata.h b/indra/llappearance/lljointdata.h
new file mode 100644
index 0000000000..2fc26198ee
--- /dev/null
+++ b/indra/llappearance/lljointdata.h
@@ -0,0 +1,66 @@
+/**
+ * @file lljointdata.h
+ * @brief LLJointData class for holding individual joint data and skeleton
+ *
+ * $LicenseInfo:firstyear=2025&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2025, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLJOINTDATA_H
+#define LL_LLJOINTDATA_H
+
+#include "v4math.h"
+
+// may be just move LLAvatarBoneInfo
+class LLJointData
+{
+public:
+ std::string mName;
+ std::string mGroup;
+ glm::mat4 mJointMatrix;
+ glm::mat4 mRestMatrix;
+ glm::vec3 mScale;
+ LLVector3 mRotation;
+
+ typedef std::vector bones_t;
+ bones_t mChildren;
+
+ bool mIsJoint; // if not, collision_volume
+ enum SupportCategory
+ {
+ SUPPORT_BASE,
+ SUPPORT_EXTENDED
+ };
+ SupportCategory mSupport;
+ void setSupport(const std::string& support)
+ {
+ if (support == "extended")
+ {
+ mSupport = SUPPORT_EXTENDED;
+ }
+ else
+ {
+ mSupport = SUPPORT_BASE;
+ }
+ }
+};
+
+#endif //LL_LLJOINTDATA_H
diff --git a/indra/llappearance/llpolymesh.cpp b/indra/llappearance/llpolymesh.cpp
index 97f9ca68b6..d5323e0b84 100644
--- a/indra/llappearance/llpolymesh.cpp
+++ b/indra/llappearance/llpolymesh.cpp
@@ -283,6 +283,7 @@ bool LLPolyMeshSharedData::loadMesh( const std::string& fileName )
LLFILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/
if (!fp)
{
+ LLError::LLUserWarningMsg::showMissingFiles();
LL_ERRS() << "can't open: " << fileName << LL_ENDL;
return false;
}
@@ -981,7 +982,7 @@ void LLPolyMesh::initializeForMorph()
LLVector4a::memcpyNonAliased16((F32*) mScaledNormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
LLVector4a::memcpyNonAliased16((F32*) mBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
LLVector4a::memcpyNonAliased16((F32*) mScaledBinormals, (F32*) mSharedData->mBaseNormals, sizeof(LLVector4a) * mSharedData->mNumVertices);
- LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices + mSharedData->mNumVertices%2));
+ memcpy((F32*) mTexCoords, (F32*) mSharedData->mTexCoords, sizeof(LLVector2) * (mSharedData->mNumVertices)); // allocated in LLPolyMeshSharedData::allocateVertexData
for (S32 i = 0; i < mSharedData->mNumVertices; ++i)
{
diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp
index 8df8a9726f..5ee6649164 100644
--- a/indra/llappearance/llpolymorph.cpp
+++ b/indra/llappearance/llpolymorph.cpp
@@ -550,12 +550,12 @@ void LLPolyMorphTarget::apply( ESex avatar_sex )
mLastSex = avatar_sex;
- // Check for NaN condition (NaN is detected if a variable doesn't equal itself.
- if (mCurWeight != mCurWeight)
+ // Check for NaN condition
+ if (llisnan(mCurWeight))
{
- mCurWeight = 0.0;
+ mCurWeight = 0.f;
}
- if (mLastWeight != mLastWeight)
+ if (llisnan(mLastWeight))
{
mLastWeight = mCurWeight+.001f;
}
diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp
index aa48a2d621..b3800e6981 100644
--- a/indra/llappearance/lltexlayer.cpp
+++ b/indra/llappearance/lltexlayer.cpp
@@ -1293,7 +1293,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
{
if (!force_render && !hasMorph())
{
- LL_DEBUGS() << "skipping renderMorphMasks for " << getUUID() << LL_ENDL;
+ LL_DEBUGS("Morph") << "skipping renderMorphMasks for " << getUUID() << LL_ENDL;
return;
}
LL_PROFILE_ZONE_SCOPED;
@@ -1325,7 +1325,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
success &= param->render( x, y, width, height );
if (!success && !force_render)
{
- LL_DEBUGS() << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL;
+ LL_DEBUGS("Morph") << "Failed to render param " << param->getID() << " ; skipping morph mask." << LL_ENDL;
return;
}
}
@@ -1365,7 +1365,7 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
else
{
- LL_WARNS() << "Skipping rendering of " << getInfo()->mStaticImageFileName
+ LL_WARNS("Morph") << "Skipping rendering of " << getInfo()->mStaticImageFileName
<< "; expected 1 or 4 components." << LL_ENDL;
}
}
@@ -1404,8 +1404,8 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
// We can get bad morph masks during login, on minimize, and occasional gl errors.
// We should only be doing this when we believe something has changed with respect to the user's appearance.
{
- LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL;
- // clear out a slot if we have filled our cache
+ LL_DEBUGS("Morph") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL;
+ // clear out a slot if we have filled our cache
S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1;
while ((S32)mAlphaCache.size() >= max_cache_entries)
{
@@ -1444,13 +1444,20 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
}
glGetTexImage(LLTexUnit::getInternalType(LLTexUnit::TT_TEXTURE), 0, GL_RGBA, GL_UNSIGNED_BYTE, temp);
-
- U8* alpha_cursor = alpha_data;
- U8* pixel = temp;
- for (int i = 0; i < pixels; i++)
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR)
{
- *alpha_cursor++ = pixel[3];
- pixel += 4;
+ LL_INFOS("Morph") << "GL Error while reading back morph texture. Error code: " << error << LL_ENDL;
+ }
+ else
+ {
+ U8* alpha_cursor = alpha_data;
+ U8* pixel = temp;
+ for (int i = 0; i < pixels; i++)
+ {
+ *alpha_cursor++ = pixel[3];
+ pixel += 4;
+ }
}
gGL.getTexUnit(0)->disable();
diff --git a/indra/llappearance/llwearable.cpp b/indra/llappearance/llwearable.cpp
index f30c147b91..4acb0ef3d4 100644
--- a/indra/llappearance/llwearable.cpp
+++ b/indra/llappearance/llwearable.cpp
@@ -645,9 +645,10 @@ void LLWearable::addVisualParam(LLVisualParam *param)
void LLWearable::setVisualParamWeight(S32 param_index, F32 value)
{
- if( is_in_map(mVisualParamIndexMap, param_index ) )
+ visual_param_index_map_t::iterator found = mVisualParamIndexMap.find(param_index);
+ if(found != mVisualParamIndexMap.end())
{
- LLVisualParam *wearable_param = mVisualParamIndexMap[param_index];
+ LLVisualParam *wearable_param = found->second;
wearable_param->setWeight(value);
}
else
@@ -658,10 +659,10 @@ void LLWearable::setVisualParamWeight(S32 param_index, F32 value)
F32 LLWearable::getVisualParamWeight(S32 param_index) const
{
- if( is_in_map(mVisualParamIndexMap, param_index ) )
+ visual_param_index_map_t::const_iterator found = mVisualParamIndexMap.find(param_index);
+ if(found != mVisualParamIndexMap.end())
{
- const LLVisualParam *wearable_param = mVisualParamIndexMap.find(param_index)->second;
- return wearable_param->getWeight();
+ return found->second->getWeight();
}
else
{
@@ -726,7 +727,7 @@ void LLWearable::writeToAvatar(LLAvatarAppearance* avatarp)
if (!avatarp) return;
// Pull params
- for( LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() )
+ for( const LLVisualParam* param = avatarp->getFirstVisualParam(); param; param = avatarp->getNextVisualParam() )
{
// cross-wearable parameters are not authoritative, as they are driven by a different wearable. So don't copy the values to the
// avatar object if cross wearable. Cross wearable params get their values from the avatar, they shouldn't write the other way.
diff --git a/indra/llaudio/llaudioengine_openal.cpp b/indra/llaudio/llaudioengine_openal.cpp
index 18d682b554..755547bfaa 100644
--- a/indra/llaudio/llaudioengine_openal.cpp
+++ b/indra/llaudio/llaudioengine_openal.cpp
@@ -79,7 +79,7 @@ bool LLAudioEngine_OpenAL::init(void* userdata, const std::string &app_title)
ALCdevice *device = alcGetContextsDevice(alcGetCurrentContext());
alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major);
- alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &minor);
+ alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor);
LL_INFOS() << "ALC version: " << major << "." << minor << LL_ENDL;
LL_INFOS() << "ALC default device: "
@@ -190,6 +190,8 @@ LLAudioChannelOpenAL::~LLAudioChannelOpenAL()
void LLAudioChannelOpenAL::cleanup()
{
alSourceStop(mALSource);
+ alSourcei(mALSource, AL_BUFFER, AL_NONE);
+
mCurrentBufferp = NULL;
}
diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp
index 83e7fad92f..d115dc309d 100644
--- a/indra/llaudio/llvorbisencode.cpp
+++ b/indra/llaudio/llvorbisencode.cpp
@@ -34,38 +34,6 @@
#include "llmath.h"
#include "llapr.h"
-//#if LL_DARWIN
-// MBW -- XXX -- Getting rid of SecondLifeVorbis for now
-#if 0
-#include "VorbisFramework.h"
-
-#define vorbis_analysis mac_vorbis_analysis
-#define vorbis_analysis_headerout mac_vorbis_analysis_headerout
-#define vorbis_analysis_init mac_vorbis_analysis_init
-#define vorbis_encode_ctl mac_vorbis_encode_ctl
-#define vorbis_encode_setup_init mac_vorbis_encode_setup_init
-#define vorbis_encode_setup_managed mac_vorbis_encode_setup_managed
-
-#define vorbis_info_init mac_vorbis_info_init
-#define vorbis_info_clear mac_vorbis_info_clear
-#define vorbis_comment_init mac_vorbis_comment_init
-#define vorbis_comment_clear mac_vorbis_comment_clear
-#define vorbis_block_init mac_vorbis_block_init
-#define vorbis_block_clear mac_vorbis_block_clear
-#define vorbis_dsp_clear mac_vorbis_dsp_clear
-#define vorbis_analysis_buffer mac_vorbis_analysis_buffer
-#define vorbis_analysis_wrote mac_vorbis_analysis_wrote
-#define vorbis_analysis_blockout mac_vorbis_analysis_blockout
-
-#define ogg_stream_packetin mac_ogg_stream_packetin
-#define ogg_stream_init mac_ogg_stream_init
-#define ogg_stream_flush mac_ogg_stream_flush
-#define ogg_stream_pageout mac_ogg_stream_pageout
-#define ogg_page_eos mac_ogg_page_eos
-#define ogg_stream_clear mac_ogg_stream_clear
-
-#endif
-
S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& error_msg)
{
U16 num_channels = 0;
diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp
index 9dace08e6f..581e9f62d5 100644
--- a/indra/llcharacter/llbvhloader.cpp
+++ b/indra/llcharacter/llbvhloader.cpp
@@ -131,7 +131,7 @@ LLQuaternion::Order bvhStringToOrder( char *str )
// LLBVHLoader()
//-----------------------------------------------------------------------------
-LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map& joint_alias_map )
+LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map>& joint_alias_map )
{
reset();
errorLine = 0;
@@ -156,9 +156,9 @@ LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &error
}
// Recognize all names we've been told are legal.
- for (std::map::value_type& alias_pair : joint_alias_map)
+ for (const auto& [alias, joint] : joint_alias_map)
{
- makeTranslation( alias_pair.first , alias_pair.second );
+ makeTranslation(alias, joint);
}
char error_text[128]; /* Flawfinder: ignore */
diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h
index de31f76dd3..ae2e347ba1 100644
--- a/indra/llcharacter/llbvhloader.h
+++ b/indra/llcharacter/llbvhloader.h
@@ -227,7 +227,7 @@ class LLBVHLoader
friend class LLKeyframeMotion;
public:
// Constructor
- LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map& joint_alias_map );
+ LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map>& joint_alias_map );
~LLBVHLoader();
/*
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index ecbcdb3bf5..8efcd9dd29 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -77,12 +77,11 @@ LLCharacter::~LLCharacter()
//-----------------------------------------------------------------------------
// getJoint()
//-----------------------------------------------------------------------------
-LLJoint *LLCharacter::getJoint( const std::string &name )
+LLJoint* LLCharacter::getJoint(std::string_view name)
{
- LLJoint* joint = NULL;
+ LLJoint* joint = nullptr;
- LLJoint *root = getRootJoint();
- if (root)
+ if (LLJoint* root = getRootJoint())
{
joint = root->findJoint(name);
}
diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h
index 6143ec8cd1..079bcd132a 100644
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -76,7 +76,7 @@ public:
// get the specified joint
// default implementation does recursive search,
// subclasses may optimize/cache results.
- virtual LLJoint *getJoint( const std::string &name );
+ virtual LLJoint* getJoint(std::string_view name);
// get the position of the character
virtual LLVector3 getCharacterPosition() = 0;
@@ -119,6 +119,8 @@ public:
virtual void addDebugText( const std::string& text ) = 0;
+ virtual std::string getDebugName() const { return getID().asString(); }
+
virtual const LLUUID& getID() const = 0;
//-------------------------------------------------------------------------
// End Interface
diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp
index f31aa5d4c9..405e62a38b 100644
--- a/indra/llcharacter/lljoint.cpp
+++ b/indra/llcharacter/lljoint.cpp
@@ -242,21 +242,20 @@ LLJoint *LLJoint::getRoot()
//-----------------------------------------------------------------------------
// findJoint()
//-----------------------------------------------------------------------------
-LLJoint *LLJoint::findJoint( const std::string &name )
+LLJoint* LLJoint::findJoint(std::string_view name)
{
if (name == getName())
return this;
for (LLJoint* joint : mChildren)
{
- LLJoint *found = joint->findJoint(name);
- if (found)
+ if (LLJoint* found = joint->findJoint(name))
{
return found;
}
}
- return NULL;
+ return nullptr;
}
diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h
index 763c1e3865..b58dc797f8 100644
--- a/indra/llcharacter/lljoint.h
+++ b/indra/llcharacter/lljoint.h
@@ -222,7 +222,7 @@ public:
LLJoint *getRoot();
// search for child joints by name
- LLJoint *findJoint( const std::string &name );
+ LLJoint* findJoint(std::string_view name);
// add/remove children
void addChild( LLJoint *joint );
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index a504e71340..2de9deea70 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -11,7 +11,7 @@ include(LLSharedLibs)
include(Copy3rdPartyLibs)
include(ZLIBNG)
include(Tracy)
-
+include(SSE2NEON)
set(llcommon_SOURCE_FILES
apply.cpp
@@ -277,6 +277,7 @@ target_link_libraries(
ll::boost
ll::oslibraries
ll::tracy
+ ll::sse2neon
)
target_include_directories(llcommon INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
diff --git a/indra/llcommon/fsyspath.h b/indra/llcommon/fsyspath.h
index e9c96edce3..2c900c02a7 100644
--- a/indra/llcommon/fsyspath.h
+++ b/indra/llcommon/fsyspath.h
@@ -12,7 +12,10 @@
#if ! defined(LL_FSYSPATH_H)
#define LL_FSYSPATH_H
+#include
#include
+#include
+#include
// While std::filesystem::path can be directly constructed from std::string on
// both Posix and Windows, that's not what we want on Windows. Per
@@ -33,37 +36,43 @@
// char"), the "native narrow encoding" isn't UTF-8, so file paths containing
// non-ASCII characters get mangled.
//
-// Once we're building with C++20, we could pass a UTF-8 std::string through a
-// vector to engage std::filesystem::path's own UTF-8 conversion. But
-// sigh, as of 2024-04-03 we're not yet there.
-//
-// Anyway, encapsulating the important UTF-8 conversions in our own subclass
-// allows us to migrate forward to C++20 conventions without changing
-// referencing code.
+// Encapsulating the important UTF-8 conversions in our own subclass allows us
+// to migrate forward to C++20 conventions without changing referencing code.
class fsyspath: public std::filesystem::path
{
using super = std::filesystem::path;
+ // In C++20 (__cpp_lib_char8_t), std::filesystem::u8path() is deprecated.
+ // std::filesystem::path(iter, iter) performs UTF-8 conversions when the
+ // value_type of the iterators is char8_t. While we could copy into a
+ // temporary std::u8string and from there into std::filesystem::path, to
+ // minimize string copying we'll define a transform_iterator that accepts
+ // a std::string_view::iterator and dereferences to char8_t.
+ struct u8ify
+ {
+ char8_t operator()(char c) const { return char8_t(c); }
+ };
+ using u8iter = boost::transform_iterator;
+
public:
// default
fsyspath() {}
- // construct from UTF-8 encoded std::string
- fsyspath(const std::string& path): super(std::filesystem::u8path(path)) {}
- // construct from UTF-8 encoded const char*
- fsyspath(const char* path): super(std::filesystem::u8path(path)) {}
+ // construct from UTF-8 encoded string
+ fsyspath(const std::string& path): fsyspath(std::string_view(path)) {}
+ fsyspath(const char* path): fsyspath(std::string_view(path)) {}
+ fsyspath(std::string_view path):
+ super(u8iter(path.begin(), u8ify()), u8iter(path.end(), u8ify()))
+ {}
// construct from existing path
fsyspath(const super& path): super(path) {}
- fsyspath& operator=(const super& p) { super::operator=(p); return *this; }
- fsyspath& operator=(const std::string& p)
+ fsyspath& operator=(const super& p) { super::operator=(p); return *this; }
+ fsyspath& operator=(const std::string& p) { return (*this) = std::string_view(p); }
+ fsyspath& operator=(const char* p) { return (*this) = std::string_view(p); }
+ fsyspath& operator=(std::string_view p)
{
- super::operator=(std::filesystem::u8path(p));
- return *this;
- }
- fsyspath& operator=(const char* p)
- {
- super::operator=(std::filesystem::u8path(p));
+ assign(u8iter(p.begin(), u8ify()), u8iter(p.end(), u8ify()));
return *this;
}
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index d2de88ff0a..a0394da281 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -31,15 +31,15 @@
class LLUUID;
-static const F32 REGION_WIDTH_METERS = 256.f;
-static const S32 REGION_WIDTH_UNITS = 256;
-static const U32 REGION_WIDTH_U32 = 256;
+static constexpr F32 REGION_WIDTH_METERS = 256.f;
+static constexpr S32 REGION_WIDTH_UNITS = 256;
+static constexpr U32 REGION_WIDTH_U32 = 256;
-const F32 REGION_HEIGHT_METERS = 4096.f;
+constexpr F32 REGION_HEIGHT_METERS = 4096.f;
-const F32 DEFAULT_AGENT_DEPTH = 0.45f;
-const F32 DEFAULT_AGENT_WIDTH = 0.60f;
-const F32 DEFAULT_AGENT_HEIGHT = 1.9f;
+constexpr F32 DEFAULT_AGENT_DEPTH = 0.45f;
+constexpr F32 DEFAULT_AGENT_WIDTH = 0.60f;
+constexpr F32 DEFAULT_AGENT_HEIGHT = 1.9f;
enum ETerrainBrushType
{
@@ -67,112 +67,112 @@ enum EMouseClickType{
// keys
// Bit masks for various keyboard modifier keys.
-const MASK MASK_NONE = 0x0000;
-const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs
-const MASK MASK_ALT = 0x0002;
-const MASK MASK_SHIFT = 0x0004;
-const MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys
-const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows
-const MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL;
+constexpr MASK MASK_NONE = 0x0000;
+constexpr MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs
+constexpr MASK MASK_ALT = 0x0002;
+constexpr MASK MASK_SHIFT = 0x0004;
+constexpr MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys
+constexpr MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows
+constexpr MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL;
// Special keys go into >128
-const KEY KEY_SPECIAL = 0x80; // special keys start here
-const KEY KEY_RETURN = 0x81;
-const KEY KEY_LEFT = 0x82;
-const KEY KEY_RIGHT = 0x83;
-const KEY KEY_UP = 0x84;
-const KEY KEY_DOWN = 0x85;
-const KEY KEY_ESCAPE = 0x86;
-const KEY KEY_BACKSPACE =0x87;
-const KEY KEY_DELETE = 0x88;
-const KEY KEY_SHIFT = 0x89;
-const KEY KEY_CONTROL = 0x8A;
-const KEY KEY_ALT = 0x8B;
-const KEY KEY_HOME = 0x8C;
-const KEY KEY_END = 0x8D;
-const KEY KEY_PAGE_UP = 0x8E;
-const KEY KEY_PAGE_DOWN = 0x8F;
-const KEY KEY_HYPHEN = 0x90;
-const KEY KEY_EQUALS = 0x91;
-const KEY KEY_INSERT = 0x92;
-const KEY KEY_CAPSLOCK = 0x93;
-const KEY KEY_TAB = 0x94;
-const KEY KEY_ADD = 0x95;
-const KEY KEY_SUBTRACT =0x96;
-const KEY KEY_MULTIPLY =0x97;
-const KEY KEY_DIVIDE = 0x98;
-const KEY KEY_F1 = 0xA1;
-const KEY KEY_F2 = 0xA2;
-const KEY KEY_F3 = 0xA3;
-const KEY KEY_F4 = 0xA4;
-const KEY KEY_F5 = 0xA5;
-const KEY KEY_F6 = 0xA6;
-const KEY KEY_F7 = 0xA7;
-const KEY KEY_F8 = 0xA8;
-const KEY KEY_F9 = 0xA9;
-const KEY KEY_F10 = 0xAA;
-const KEY KEY_F11 = 0xAB;
-const KEY KEY_F12 = 0xAC;
+constexpr KEY KEY_SPECIAL = 0x80; // special keys start here
+constexpr KEY KEY_RETURN = 0x81;
+constexpr KEY KEY_LEFT = 0x82;
+constexpr KEY KEY_RIGHT = 0x83;
+constexpr KEY KEY_UP = 0x84;
+constexpr KEY KEY_DOWN = 0x85;
+constexpr KEY KEY_ESCAPE = 0x86;
+constexpr KEY KEY_BACKSPACE =0x87;
+constexpr KEY KEY_DELETE = 0x88;
+constexpr KEY KEY_SHIFT = 0x89;
+constexpr KEY KEY_CONTROL = 0x8A;
+constexpr KEY KEY_ALT = 0x8B;
+constexpr KEY KEY_HOME = 0x8C;
+constexpr KEY KEY_END = 0x8D;
+constexpr KEY KEY_PAGE_UP = 0x8E;
+constexpr KEY KEY_PAGE_DOWN = 0x8F;
+constexpr KEY KEY_HYPHEN = 0x90;
+constexpr KEY KEY_EQUALS = 0x91;
+constexpr KEY KEY_INSERT = 0x92;
+constexpr KEY KEY_CAPSLOCK = 0x93;
+constexpr KEY KEY_TAB = 0x94;
+constexpr KEY KEY_ADD = 0x95;
+constexpr KEY KEY_SUBTRACT =0x96;
+constexpr KEY KEY_MULTIPLY =0x97;
+constexpr KEY KEY_DIVIDE = 0x98;
+constexpr KEY KEY_F1 = 0xA1;
+constexpr KEY KEY_F2 = 0xA2;
+constexpr KEY KEY_F3 = 0xA3;
+constexpr KEY KEY_F4 = 0xA4;
+constexpr KEY KEY_F5 = 0xA5;
+constexpr KEY KEY_F6 = 0xA6;
+constexpr KEY KEY_F7 = 0xA7;
+constexpr KEY KEY_F8 = 0xA8;
+constexpr KEY KEY_F9 = 0xA9;
+constexpr KEY KEY_F10 = 0xAA;
+constexpr KEY KEY_F11 = 0xAB;
+constexpr KEY KEY_F12 = 0xAC;
-const KEY KEY_PAD_UP = 0xC0;
-const KEY KEY_PAD_DOWN = 0xC1;
-const KEY KEY_PAD_LEFT = 0xC2;
-const KEY KEY_PAD_RIGHT = 0xC3;
-const KEY KEY_PAD_HOME = 0xC4;
-const KEY KEY_PAD_END = 0xC5;
-const KEY KEY_PAD_PGUP = 0xC6;
-const KEY KEY_PAD_PGDN = 0xC7;
-const KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle
-const KEY KEY_PAD_INS = 0xC9;
-const KEY KEY_PAD_DEL = 0xCA;
-const KEY KEY_PAD_RETURN = 0xCB;
-const KEY KEY_PAD_ADD = 0xCC; // not used
-const KEY KEY_PAD_SUBTRACT = 0xCD; // not used
-const KEY KEY_PAD_MULTIPLY = 0xCE; // not used
-const KEY KEY_PAD_DIVIDE = 0xCF; // not used
+constexpr KEY KEY_PAD_UP = 0xC0;
+constexpr KEY KEY_PAD_DOWN = 0xC1;
+constexpr KEY KEY_PAD_LEFT = 0xC2;
+constexpr KEY KEY_PAD_RIGHT = 0xC3;
+constexpr KEY KEY_PAD_HOME = 0xC4;
+constexpr KEY KEY_PAD_END = 0xC5;
+constexpr KEY KEY_PAD_PGUP = 0xC6;
+constexpr KEY KEY_PAD_PGDN = 0xC7;
+constexpr KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle
+constexpr KEY KEY_PAD_INS = 0xC9;
+constexpr KEY KEY_PAD_DEL = 0xCA;
+constexpr KEY KEY_PAD_RETURN = 0xCB;
+constexpr KEY KEY_PAD_ADD = 0xCC; // not used
+constexpr KEY KEY_PAD_SUBTRACT = 0xCD; // not used
+constexpr KEY KEY_PAD_MULTIPLY = 0xCE; // not used
+constexpr KEY KEY_PAD_DIVIDE = 0xCF; // not used
-const KEY KEY_BUTTON0 = 0xD0;
-const KEY KEY_BUTTON1 = 0xD1;
-const KEY KEY_BUTTON2 = 0xD2;
-const KEY KEY_BUTTON3 = 0xD3;
-const KEY KEY_BUTTON4 = 0xD4;
-const KEY KEY_BUTTON5 = 0xD5;
-const KEY KEY_BUTTON6 = 0xD6;
-const KEY KEY_BUTTON7 = 0xD7;
-const KEY KEY_BUTTON8 = 0xD8;
-const KEY KEY_BUTTON9 = 0xD9;
-const KEY KEY_BUTTON10 = 0xDA;
-const KEY KEY_BUTTON11 = 0xDB;
-const KEY KEY_BUTTON12 = 0xDC;
-const KEY KEY_BUTTON13 = 0xDD;
-const KEY KEY_BUTTON14 = 0xDE;
-const KEY KEY_BUTTON15 = 0xDF;
+constexpr KEY KEY_BUTTON0 = 0xD0;
+constexpr KEY KEY_BUTTON1 = 0xD1;
+constexpr KEY KEY_BUTTON2 = 0xD2;
+constexpr KEY KEY_BUTTON3 = 0xD3;
+constexpr KEY KEY_BUTTON4 = 0xD4;
+constexpr KEY KEY_BUTTON5 = 0xD5;
+constexpr KEY KEY_BUTTON6 = 0xD6;
+constexpr KEY KEY_BUTTON7 = 0xD7;
+constexpr KEY KEY_BUTTON8 = 0xD8;
+constexpr KEY KEY_BUTTON9 = 0xD9;
+constexpr KEY KEY_BUTTON10 = 0xDA;
+constexpr KEY KEY_BUTTON11 = 0xDB;
+constexpr KEY KEY_BUTTON12 = 0xDC;
+constexpr KEY KEY_BUTTON13 = 0xDD;
+constexpr KEY KEY_BUTTON14 = 0xDE;
+constexpr KEY KEY_BUTTON15 = 0xDF;
-const KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only.
+constexpr KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only.
-const S32 KEY_COUNT = 256;
+constexpr S32 KEY_COUNT = 256;
-const F32 DEFAULT_WATER_HEIGHT = 20.0f;
+constexpr F32 DEFAULT_WATER_HEIGHT = 20.0f;
// Maturity ratings for simulators
-const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG
-const U8 SIM_ACCESS_PG = 13;
-const U8 SIM_ACCESS_MATURE = 21;
-const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
-const U8 SIM_ACCESS_DOWN = 254;
-const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
+constexpr U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG
+constexpr U8 SIM_ACCESS_PG = 13;
+constexpr U8 SIM_ACCESS_MATURE = 21;
+constexpr U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
+constexpr U8 SIM_ACCESS_DOWN = 254;
+constexpr U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
// attachment constants
-const U8 ATTACHMENT_ADD = 0x80;
+constexpr U8 ATTACHMENT_ADD = 0x80;
// god levels
-const U8 GOD_MAINTENANCE = 250;
-const U8 GOD_FULL = 200;
-const U8 GOD_LIAISON = 150;
-const U8 GOD_CUSTOMER_SERVICE = 100;
-const U8 GOD_LIKE = 1;
-const U8 GOD_NOT = 0;
+constexpr U8 GOD_MAINTENANCE = 250;
+constexpr U8 GOD_FULL = 200;
+constexpr U8 GOD_LIAISON = 150;
+constexpr U8 GOD_CUSTOMER_SERVICE = 100;
+constexpr U8 GOD_LIKE = 1;
+constexpr U8 GOD_NOT = 0;
// "agent id" for things that should be done to ALL agents
LL_COMMON_API extern const LLUUID LL_UUID_ALL_AGENTS;
@@ -239,121 +239,123 @@ LL_COMMON_API extern const LLUUID BLANK_OBJECT_NORMAL;
LL_COMMON_API extern const LLUUID BLANK_MATERIAL_ASSET_ID;
// radius within which a chat message is fully audible
-const F32 CHAT_NORMAL_RADIUS = 20.f;
+constexpr F32 CHAT_NORMAL_RADIUS = 20.f;
// media commands
-const U32 PARCEL_MEDIA_COMMAND_STOP = 0;
-const U32 PARCEL_MEDIA_COMMAND_PAUSE = 1;
-const U32 PARCEL_MEDIA_COMMAND_PLAY = 2;
-const U32 PARCEL_MEDIA_COMMAND_LOOP = 3;
-const U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4;
-const U32 PARCEL_MEDIA_COMMAND_URL = 5;
-const U32 PARCEL_MEDIA_COMMAND_TIME = 6;
-const U32 PARCEL_MEDIA_COMMAND_AGENT = 7;
-const U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8;
-const U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9;
-const U32 PARCEL_MEDIA_COMMAND_TYPE = 10;
-const U32 PARCEL_MEDIA_COMMAND_SIZE = 11;
-const U32 PARCEL_MEDIA_COMMAND_DESC = 12;
-const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
+constexpr U32 PARCEL_MEDIA_COMMAND_STOP = 0;
+constexpr U32 PARCEL_MEDIA_COMMAND_PAUSE = 1;
+constexpr U32 PARCEL_MEDIA_COMMAND_PLAY = 2;
+constexpr U32 PARCEL_MEDIA_COMMAND_LOOP = 3;
+constexpr U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4;
+constexpr U32 PARCEL_MEDIA_COMMAND_URL = 5;
+constexpr U32 PARCEL_MEDIA_COMMAND_TIME = 6;
+constexpr U32 PARCEL_MEDIA_COMMAND_AGENT = 7;
+constexpr U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8;
+constexpr U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9;
+constexpr U32 PARCEL_MEDIA_COMMAND_TYPE = 10;
+constexpr U32 PARCEL_MEDIA_COMMAND_SIZE = 11;
+constexpr U32 PARCEL_MEDIA_COMMAND_DESC = 12;
+constexpr U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
const S32 CHAT_CHANNEL_DEBUG = S32_MAX;
// agent constants
-const U32 CONTROL_AT_POS_INDEX = 0;
-const U32 CONTROL_AT_NEG_INDEX = 1;
-const U32 CONTROL_LEFT_POS_INDEX = 2;
-const U32 CONTROL_LEFT_NEG_INDEX = 3;
-const U32 CONTROL_UP_POS_INDEX = 4;
-const U32 CONTROL_UP_NEG_INDEX = 5;
-const U32 CONTROL_PITCH_POS_INDEX = 6;
-const U32 CONTROL_PITCH_NEG_INDEX = 7;
-const U32 CONTROL_YAW_POS_INDEX = 8;
-const U32 CONTROL_YAW_NEG_INDEX = 9;
-const U32 CONTROL_FAST_AT_INDEX = 10;
-const U32 CONTROL_FAST_LEFT_INDEX = 11;
-const U32 CONTROL_FAST_UP_INDEX = 12;
-const U32 CONTROL_FLY_INDEX = 13;
-const U32 CONTROL_STOP_INDEX = 14;
-const U32 CONTROL_FINISH_ANIM_INDEX = 15;
-const U32 CONTROL_STAND_UP_INDEX = 16;
-const U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
-const U32 CONTROL_MOUSELOOK_INDEX = 18;
-const U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
-const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
-const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
-const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
-const U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
-const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
-const U32 CONTROL_TURN_LEFT_INDEX = 25;
-const U32 CONTROL_TURN_RIGHT_INDEX = 26;
-const U32 CONTROL_AWAY_INDEX = 27;
-const U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
-const U32 CONTROL_LBUTTON_UP_INDEX = 29;
-const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
-const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
-const U32 TOTAL_CONTROLS = 32;
+constexpr U32 CONTROL_AT_POS_INDEX = 0;
+constexpr U32 CONTROL_AT_NEG_INDEX = 1;
+constexpr U32 CONTROL_LEFT_POS_INDEX = 2;
+constexpr U32 CONTROL_LEFT_NEG_INDEX = 3;
+constexpr U32 CONTROL_UP_POS_INDEX = 4;
+constexpr U32 CONTROL_UP_NEG_INDEX = 5;
+constexpr U32 CONTROL_PITCH_POS_INDEX = 6;
+constexpr U32 CONTROL_PITCH_NEG_INDEX = 7;
+constexpr U32 CONTROL_YAW_POS_INDEX = 8;
+constexpr U32 CONTROL_YAW_NEG_INDEX = 9;
+constexpr U32 CONTROL_FAST_AT_INDEX = 10;
+constexpr U32 CONTROL_FAST_LEFT_INDEX = 11;
+constexpr U32 CONTROL_FAST_UP_INDEX = 12;
+constexpr U32 CONTROL_FLY_INDEX = 13;
+constexpr U32 CONTROL_STOP_INDEX = 14;
+constexpr U32 CONTROL_FINISH_ANIM_INDEX = 15;
+constexpr U32 CONTROL_STAND_UP_INDEX = 16;
+constexpr U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
+constexpr U32 CONTROL_MOUSELOOK_INDEX = 18;
+constexpr U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
+constexpr U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
+constexpr U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
+constexpr U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
+constexpr U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
+constexpr U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
+constexpr U32 CONTROL_TURN_LEFT_INDEX = 25;
+constexpr U32 CONTROL_TURN_RIGHT_INDEX = 26;
+constexpr U32 CONTROL_AWAY_INDEX = 27;
+constexpr U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
+constexpr U32 CONTROL_LBUTTON_UP_INDEX = 29;
+constexpr U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
+constexpr U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
+constexpr U32 TOTAL_CONTROLS = 32;
-const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
-const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
-const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
-const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
-const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
-const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
-const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
-const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
-const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
-const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
+constexpr U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
+constexpr U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
+constexpr U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
+constexpr U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
+constexpr U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
+constexpr U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
+constexpr U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
+constexpr U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
+constexpr U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
+constexpr U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
-const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
-const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
-const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
+constexpr U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
+constexpr U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
+constexpr U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
-const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
-const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
-const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
-const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
-const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
-const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
+constexpr U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
+constexpr U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
+constexpr U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
+constexpr U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
+constexpr U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
+constexpr U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
-const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
-const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
-const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
-const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
-const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
-const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
-const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
-const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
+constexpr U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
+constexpr U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
+constexpr U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
+constexpr U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
+constexpr U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
+constexpr U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
+constexpr U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
+constexpr U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
-const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
+constexpr U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
-const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
-const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
-const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
-const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
+constexpr U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
+constexpr U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
+constexpr U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
+constexpr U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
// move these up so that we can hide them in "State" for object updates
// (for now)
-const U32 AGENT_ATTACH_OFFSET = 4;
-const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
+constexpr U32 AGENT_ATTACH_OFFSET = 4;
+constexpr U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
// RN: this method swaps the upper and lower nibbles to maintain backward
// compatibility with old objects that only used the upper nibble
#define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4)))
// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
-const U8 CLICK_ACTION_NONE = 0;
-const U8 CLICK_ACTION_TOUCH = 0;
-const U8 CLICK_ACTION_SIT = 1;
-const U8 CLICK_ACTION_BUY = 2;
-const U8 CLICK_ACTION_PAY = 3;
-const U8 CLICK_ACTION_OPEN = 4;
-const U8 CLICK_ACTION_PLAY = 5;
-const U8 CLICK_ACTION_OPEN_MEDIA = 6;
-const U8 CLICK_ACTION_ZOOM = 7;
-const U8 CLICK_ACTION_DISABLED = 8;
-const U8 CLICK_ACTION_IGNORE = 9;
+constexpr U8 CLICK_ACTION_NONE = 0;
+constexpr U8 CLICK_ACTION_TOUCH = 0;
+constexpr U8 CLICK_ACTION_SIT = 1;
+constexpr U8 CLICK_ACTION_BUY = 2;
+constexpr U8 CLICK_ACTION_PAY = 3;
+constexpr U8 CLICK_ACTION_OPEN = 4;
+constexpr U8 CLICK_ACTION_PLAY = 5;
+constexpr U8 CLICK_ACTION_OPEN_MEDIA = 6;
+constexpr U8 CLICK_ACTION_ZOOM = 7;
+constexpr U8 CLICK_ACTION_DISABLED = 8;
+constexpr U8 CLICK_ACTION_IGNORE = 9;
// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
+constexpr U32 BEACON_SHOW_MAP = 0x0001;
+constexpr U32 BEACON_FOCUS_MAP = 0x0002;
#endif
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h
index a918caa2e8..a41af153fe 100644
--- a/indra/llcommon/linden_common.h
+++ b/indra/llcommon/linden_common.h
@@ -28,12 +28,6 @@
#define LL_LINDEN_COMMON_H
#include "llprofiler.h"
-#if TRACY_ENABLE && !defined(LL_PROFILER_ENABLE_TRACY_OPENGL) // hooks for memory profiling
-void *tracy_aligned_malloc(size_t size, size_t alignment);
-void tracy_aligned_free(void *memblock);
-#define _aligned_malloc(X, Y) tracy_aligned_malloc((X), (Y))
-#define _aligned_free(X) tracy_aligned_free((X))
-#endif
// *NOTE: Please keep includes here to a minimum!
//
diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp
index 08a43983d3..c532620daa 100644
--- a/indra/llcommon/llapp.cpp
+++ b/indra/llcommon/llapp.cpp
@@ -229,7 +229,7 @@ bool LLApp::parseCommandOptions(int argc, wchar_t** wargv)
if(wargv[ii][1] == '-') ++offset;
#if LL_WINDOWS
- name.assign(utf16str_to_utf8str(&wargv[ii][offset]));
+ name.assign(ll_convert_wide_to_string(&wargv[ii][offset]));
#else
name.assign(wstring_to_utf8str(&wargv[ii][offset]));
#endif
@@ -253,7 +253,7 @@ bool LLApp::parseCommandOptions(int argc, wchar_t** wargv)
++ii;
#if LL_WINDOWS
- value.assign(utf16str_to_utf8str((wargv[ii])));
+ value.assign(ll_convert_wide_to_string((wargv[ii])));
#else
value.assign(wstring_to_utf8str((wargv[ii])));
#endif
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index 3d18864b80..57f5a112d9 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -282,7 +282,7 @@ public:
LLRunner& getRunner() { return mRunner; }
#ifdef LL_WINDOWS
- virtual void reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { }
+ virtual bool reportCrashToBugsplat(void* pExcepInfo /*EXCEPTION_POINTERS*/) { return false; }
#endif
public:
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index c09cf7abd2..9672a3262b 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -29,6 +29,7 @@
#include "llassettype.h"
#include "lldictionary.h"
#include "llmemory.h"
+#include "llsd.h"
#include "llsingleton.h"
///----------------------------------------------------------------------------
@@ -246,3 +247,19 @@ bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type)
}
return false;
}
+
+LLSD LLAssetType::getTypeNames()
+{
+ LLSD type_names;
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ for (S32 type = AT_TEXTURE; type < AT_COUNT; ++type)
+ {
+ const AssetEntry *entry = dict->lookup((LLAssetType::EType) type);
+ // skip llassettype_bad_lookup
+ if (entry)
+ {
+ type_names.append(entry->mTypeName);
+ }
+ }
+ return type_names;
+}
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 547c3f4329..17177d81c3 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -165,6 +165,8 @@ public:
static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
+ static LLSD getTypeNames();
+
static const std::string BADLOOKUP;
protected:
diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp
index 84b35749cc..7a22eaf203 100644
--- a/indra/llcommon/llcommon.cpp
+++ b/indra/llcommon/llcommon.cpp
@@ -33,23 +33,12 @@
#include "lltracethreadrecorder.h"
#include "llcleanup.h"
-thread_local bool gProfilerEnabled = false;
-
-#if (TRACY_ENABLE)
+#if LL_PROFILER_CONFIGURATION >= LL_PROFILER_CONFIG_TRACY && TRACY_ENABLE
// Override new/delete for tracy memory profiling
void* ll_tracy_new(size_t size)
{
- void* ptr;
- if (gProfilerEnabled)
- {
- //LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
- ptr = (malloc)(size);
- }
- else
- {
- ptr = (malloc)(size);
- }
+ void* ptr = (malloc)(size);
if (!ptr)
{
throw std::bad_alloc();
@@ -58,6 +47,29 @@ void* ll_tracy_new(size_t size)
return ptr;
}
+void* ll_tracy_aligned_new(size_t size, size_t alignment)
+{
+ void* ptr = ll_aligned_malloc_fallback(size, alignment);
+ if (!ptr)
+ {
+ throw std::bad_alloc();
+ }
+ LL_PROFILE_ALLOC(ptr, size);
+ return ptr;
+}
+
+void ll_tracy_delete(void* ptr)
+{
+ LL_PROFILE_FREE(ptr);
+ (free)(ptr);
+}
+
+void ll_tracy_aligned_delete(void* ptr)
+{
+ LL_PROFILE_FREE(ptr);
+ ll_aligned_free_fallback(ptr);
+}
+
void* operator new(size_t size)
{
return ll_tracy_new(size);
@@ -68,18 +80,14 @@ void* operator new[](std::size_t count)
return ll_tracy_new(count);
}
-void ll_tracy_delete(void* ptr)
+void* operator new(size_t size, std::align_val_t align)
{
- LL_PROFILE_FREE(ptr);
- if (gProfilerEnabled)
- {
- //LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
- (free)(ptr);
- }
- else
- {
- (free)(ptr);
- }
+ return ll_tracy_aligned_new(size, (size_t)align);
+}
+
+void* operator new[](std::size_t count, std::align_val_t align)
+{
+ return ll_tracy_aligned_new(count, (size_t)align);
}
void operator delete(void *ptr) noexcept
@@ -92,27 +100,17 @@ void operator delete[](void* ptr) noexcept
ll_tracy_delete(ptr);
}
-// C-style malloc/free can't be so easily overridden, so we define tracy versions and use
-// a pre-processor #define in linden_common.h to redirect to them. The parens around the native
-// functions below prevents recursive substitution by the preprocessor.
-//
-// Unaligned mallocs are rare in LL code but hooking them causes problems in 3p lib code (looking at
-// you, Havok), so we'll only capture the aligned version.
-
-void *tracy_aligned_malloc(size_t size, size_t alignment)
+void operator delete(void *ptr, std::align_val_t align) noexcept
{
- auto ptr = ll_aligned_malloc_fallback(size, alignment);
- if (ptr) LL_PROFILE_ALLOC(ptr, size);
- return ptr;
+ ll_tracy_aligned_delete(ptr);
}
-void tracy_aligned_free(void *memblock)
+void operator delete[](void* ptr, std::align_val_t align) noexcept
{
- LL_PROFILE_FREE(memblock);
- ll_aligned_free_fallback(memblock);
+ ll_tracy_aligned_delete(ptr);
}
-#endif
+#endif // TRACY_ENABLE && !LL_PROFILER_ENABLE_TRACY_OPENGL
//static
bool LLCommon::sAprInitialized = false;
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 1539b48bd3..9e95d9c85f 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -310,25 +310,54 @@ namespace
static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
-U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS *exception_infop)
+U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop)
{
- if (code == STATUS_MSC_EXCEPTION)
+ if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop))
+ {
+ // Handled
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else if (code == STATUS_MSC_EXCEPTION)
{
// C++ exception, go on
return EXCEPTION_CONTINUE_SEARCH;
}
else
{
- // handle it
+ // handle it, convert to std::exception
return EXCEPTION_EXECUTE_HANDLER;
}
+
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+void cpphandle(const LLCoros::callable_t& callable, const std::string& name)
+{
+ // SE and C++ can not coexists, thus two handlers
+ try
+ {
+ callable();
+ }
+ catch (const LLCoros::Stop& exc)
+ {
+ LL_INFOS("LLCoros") << "coroutine " << name << " terminating because "
+ << exc.what() << LL_ENDL;
+ }
+ catch (const LLContinueError&)
+ {
+ // Any uncaught exception derived from LLContinueError will be caught
+ // here and logged. This coroutine will terminate but the rest of the
+ // viewer will carry on.
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("coroutine " << name));
+ }
}
-void sehandle(const LLCoros::callable_t& callable)
+void sehandle(const LLCoros::callable_t& callable, const std::string& name)
{
__try
{
- callable();
+ // handle stop and continue exceptions first
+ cpphandle(callable, name);
}
__except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
{
@@ -340,16 +369,7 @@ void sehandle(const LLCoros::callable_t& callable)
throw std::exception(integer_string);
}
}
-
-#else // ! LL_WINDOWS
-
-inline void sehandle(const LLCoros::callable_t& callable)
-{
- callable();
-}
-
-#endif // ! LL_WINDOWS
-
+#endif // LL_WINDOWS
} // anonymous namespace
// Top-level wrapper around caller's coroutine callable.
@@ -362,10 +382,14 @@ void LLCoros::toplevel(std::string name, callable_t callable)
// set it as current
mCurrent.reset(&corodata);
+#ifdef LL_WINDOWS
+ // can not use __try directly, toplevel requires unwinding, thus use of a wrapper
+ sehandle(callable, name);
+#else // LL_WINDOWS
// run the code the caller actually wants in the coroutine
try
{
- sehandle(callable);
+ callable();
}
catch (const Stop& exc)
{
@@ -387,6 +411,7 @@ void LLCoros::toplevel(std::string name, callable_t callable)
<< name << LL_ENDL;
LLCoros::instance().saveException(name, std::current_exception());
}
+#endif // else LL_WINDOWS
}
//static
diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp
index b38864688d..5205699b92 100644
--- a/indra/llcommon/lldate.cpp
+++ b/indra/llcommon/lldate.cpp
@@ -77,6 +77,15 @@ std::string LLDate::asRFC1123() const
return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
}
+std::string LLDate::toLocalDateString (std::string fmt) const
+{
+ LL_PROFILE_ZONE_SCOPED;
+
+ time_t locSeconds = (time_t) mSecondsSinceEpoch;
+ struct tm * lt = localtime (&locSeconds);
+ return toHTTPDateString(lt, fmt);
+}
+
std::string LLDate::toHTTPDateString (std::string fmt) const
{
LL_PROFILE_ZONE_SCOPED;
diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h
index 1a69a04232..34c8692f20 100644
--- a/indra/llcommon/lldate.h
+++ b/indra/llcommon/lldate.h
@@ -77,6 +77,7 @@ public:
std::string asRFC1123() const;
void toStream(std::ostream&) const;
bool split(S32 *year, S32 *month = NULL, S32 *day = NULL, S32 *hour = NULL, S32 *min = NULL, S32 *sec = NULL) const;
+ std::string toLocalDateString(std::string fmt) const;
std::string toHTTPDateString (std::string fmt) const;
static std::string toHTTPDateString (tm * gmt, std::string fmt);
/**
diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h
index 2fbb26dc1a..232987da14 100644
--- a/indra/llcommon/lldefs.h
+++ b/indra/llcommon/lldefs.h
@@ -171,13 +171,13 @@ constexpr U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 +
// recursion tail
template
-inline auto llmax(T data)
+constexpr auto llmax(T data)
{
return data;
}
template
-inline auto llmax(T0 d0, T1 d1, Ts... rest)
+constexpr auto llmax(T0 d0, T1 d1, Ts... rest)
{
auto maxrest = llmax(d1, rest...);
return (d0 > maxrest)? d0 : maxrest;
@@ -185,20 +185,20 @@ inline auto llmax(T0 d0, T1 d1, Ts... rest)
// recursion tail
template
-inline auto llmin(T data)
+constexpr auto llmin(T data)
{
return data;
}
template
-inline auto llmin(T0 d0, T1 d1, Ts... rest)
+constexpr auto llmin(T0 d0, T1 d1, Ts... rest)
{
auto minrest = llmin(d1, rest...);
return (d0 < minrest) ? d0 : minrest;
}
template
-inline A llclamp(A a, MIN minval, MAX maxval)
+constexpr A llclamp(A a, MIN minval, MAX maxval)
{
A aminval{ static_cast(minval) }, amaxval{ static_cast(maxval) };
if ( a < aminval )
@@ -213,13 +213,13 @@ inline A llclamp(A a, MIN minval, MAX maxval)
}
template
-inline LLDATATYPE llclampf(LLDATATYPE a)
+constexpr LLDATATYPE llclampf(LLDATATYPE a)
{
return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(1));
}
template
-inline LLDATATYPE llclampb(LLDATATYPE a)
+constexpr LLDATATYPE llclampb(LLDATATYPE a)
{
return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(255));
}
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index d834098994..3411e9c6bb 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -79,7 +79,7 @@ namespace {
//
if (s.size())
{
- OutputDebugString(utf8str_to_utf16str(s).c_str());
+ OutputDebugString(ll_convert(s).c_str());
OutputDebugString(TEXT("\n"));
}
}
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 722743f453..1c5fe9d2f5 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -64,7 +64,7 @@ bool BlockTimer::sLog = false;
std::string BlockTimer::sLogName = "";
bool BlockTimer::sMetricLog = false;
-#if LL_LINUX
+#if LL_LINUX || (LL_DARWIN && LL_ARM64)
U64 BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
#else
U64 BlockTimer::sClockResolution = 1000000; // Microsecond resolution
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 09fcf8a1af..271dade097 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -30,9 +30,14 @@
#include "llinstancetracker.h"
#include "lltrace.h"
#include "lltreeiterators.h"
+#include "llprocessor.h"
+#if LL_X86 || LL_X86_64
#if LL_WINDOWS
#include
+#else
+#include
+#endif
#endif
#define LL_FAST_TIMER_ON 1
@@ -68,35 +73,10 @@ public:
//
// Windows implementation of CPU clock
//
-
- //
- // NOTE: put back in when we aren't using platform sdk anymore
- //
- // because MS has different signatures for these functions in winnt.h
- // need to rename them to avoid conflicts
- //#define _interlockedbittestandset _renamed_interlockedbittestandset
- //#define _interlockedbittestandreset _renamed_interlockedbittestandreset
- //#include
- //#undef _interlockedbittestandset
- //#undef _interlockedbittestandreset
-
- //inline U32 getCPUClockCount32()
- //{
- // U64 time_stamp = __rdtsc();
- // return (U32)(time_stamp >> 8);
- //}
- //
- //// return full timer value, *not* shifted by 8 bits
- //inline U64 getCPUClockCount64()
- //{
- // return __rdtsc();
- //}
-
-
+#if LL_FASTTIMER_USE_RDTSC
// shift off lower 8 bits for lower resolution but longer term timing
// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
-#if LL_FASTTIMER_USE_RDTSC
static U32 getCPUClockCount32()
{
unsigned __int64 val = __rdtsc();
@@ -159,23 +139,37 @@ public:
#endif // (LL_LINUX) && !(defined(__i386__) || defined(__amd64__))
-#if (LL_LINUX || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
+#if LL_DARWIN && LL_ARM64
//
- // Mac+Linux FAST x86 implementation of CPU clock
+ // Mac implementation of CPU clock - non-x86.
+ //
+ static U64 getCPUClockCount64()
+ {
+ return clock_gettime_nsec_np(CLOCK_UPTIME_RAW);
+ }
+
static U32 getCPUClockCount32()
{
- U32 low(0),high(0);
- __asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
- return (low>>8) | (high<<24);
+ return (U32)(getCPUClockCount64() >> 8);
+ }
+#endif // LL_DARWIN && LL_ARM64
+
+#if (LL_LINUX || LL_DARWIN) && (LL_X86 || LL_X86_64)
+ //
+ // Mac+Linux FAST x86 implementation of CPU clock
+ //
+#if LL_FASTTIMER_USE_RDTSC
+ static U32 getCPUClockCount32()
+ {
+ U64 time_stamp = __rdtsc() >> 8U;
+ return static_cast(time_stamp);
}
static U64 getCPUClockCount64()
{
- U32 low(0),high(0);
- __asm__ volatile (".byte 0x0f, 0x31": "=a"(low), "=d"(high) );
- return (U64)low | ( ((U64)high) << 32);
+ return static_cast(__rdtsc());
}
-
+#endif
#endif
static BlockTimerStatHandle& getRootTimeBlock();
diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp
index d0bc8f7652..a539e4fe28 100644
--- a/indra/llcommon/llfile.cpp
+++ b/indra/llcommon/llfile.cpp
@@ -35,7 +35,6 @@
#if LL_WINDOWS
#include "llwin32headers.h"
-#include // Windows errno
#include
#else
#include
@@ -49,6 +48,86 @@ static std::string empty;
// variants of strerror() to report errors.
#if LL_WINDOWS
+// For the situations where we directly call into Windows API functions we need to translate
+// the Windows error codes into errno values
+namespace
+{
+ struct errentry
+ {
+ unsigned long oserr; // Windows OS error value
+ int errcode; // System V error code
+ };
+}
+
+// translation table between Windows OS error value and System V errno code
+static errentry const errtable[]
+{
+ { ERROR_INVALID_FUNCTION, EINVAL }, // 1
+ { ERROR_FILE_NOT_FOUND, ENOENT }, // 2
+ { ERROR_PATH_NOT_FOUND, ENOENT }, // 3
+ { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, // 4
+ { ERROR_ACCESS_DENIED, EACCES }, // 5
+ { ERROR_INVALID_HANDLE, EBADF }, // 6
+ { ERROR_ARENA_TRASHED, ENOMEM }, // 7
+ { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, // 8
+ { ERROR_INVALID_BLOCK, ENOMEM }, // 9
+ { ERROR_BAD_ENVIRONMENT, E2BIG }, // 10
+ { ERROR_BAD_FORMAT, ENOEXEC }, // 11
+ { ERROR_INVALID_ACCESS, EINVAL }, // 12
+ { ERROR_INVALID_DATA, EINVAL }, // 13
+ { ERROR_INVALID_DRIVE, ENOENT }, // 15
+ { ERROR_CURRENT_DIRECTORY, EACCES }, // 16
+ { ERROR_NOT_SAME_DEVICE, EXDEV }, // 17
+ { ERROR_NO_MORE_FILES, ENOENT }, // 18
+ { ERROR_LOCK_VIOLATION, EACCES }, // 33
+ { ERROR_BAD_NETPATH, ENOENT }, // 53
+ { ERROR_NETWORK_ACCESS_DENIED, EACCES }, // 65
+ { ERROR_BAD_NET_NAME, ENOENT }, // 67
+ { ERROR_FILE_EXISTS, EEXIST }, // 80
+ { ERROR_CANNOT_MAKE, EACCES }, // 82
+ { ERROR_FAIL_I24, EACCES }, // 83
+ { ERROR_INVALID_PARAMETER, EINVAL }, // 87
+ { ERROR_NO_PROC_SLOTS, EAGAIN }, // 89
+ { ERROR_DRIVE_LOCKED, EACCES }, // 108
+ { ERROR_BROKEN_PIPE, EPIPE }, // 109
+ { ERROR_DISK_FULL, ENOSPC }, // 112
+ { ERROR_INVALID_TARGET_HANDLE, EBADF }, // 114
+ { ERROR_WAIT_NO_CHILDREN, ECHILD }, // 128
+ { ERROR_CHILD_NOT_COMPLETE, ECHILD }, // 129
+ { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, // 130
+ { ERROR_NEGATIVE_SEEK, EINVAL }, // 131
+ { ERROR_SEEK_ON_DEVICE, EACCES }, // 132
+ { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, // 145
+ { ERROR_NOT_LOCKED, EACCES }, // 158
+ { ERROR_BAD_PATHNAME, ENOENT }, // 161
+ { ERROR_MAX_THRDS_REACHED, EAGAIN }, // 164
+ { ERROR_LOCK_FAILED, EACCES }, // 167
+ { ERROR_ALREADY_EXISTS, EEXIST }, // 183
+ { ERROR_FILENAME_EXCED_RANGE, ENOENT }, // 206
+ { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, // 215
+ { ERROR_NO_UNICODE_TRANSLATION, EILSEQ }, // 1113
+ { ERROR_NOT_ENOUGH_QUOTA, ENOMEM } // 1816
+};
+
+static int set_errno_from_oserror(unsigned long oserr)
+{
+ if (!oserr)
+ return 0;
+
+ // Check the table for the Windows OS error code
+ for (const struct errentry &entry : errtable)
+ {
+ if (oserr == entry.oserr)
+ {
+ _set_errno(entry.errcode);
+ return -1;
+ }
+ }
+
+ _set_errno(EINVAL);
+ return -1;
+}
+
// On Windows, use strerror_s().
std::string strerr(int errn)
{
@@ -57,7 +136,67 @@ std::string strerr(int errn)
return buffer;
}
-typedef std::basic_ios > _Myios;
+inline bool is_slash(wchar_t const c)
+{
+ return c == L'\\' || c == L'/';
+}
+
+static std::wstring utf8path_to_wstring(const std::string& utf8path)
+{
+ if (utf8path.size() >= MAX_PATH)
+ {
+ // By prepending "\\?\" to a path, Windows widechar file APIs will not fail on long path names
+ std::wstring utf16path = L"\\\\?\\" + ll_convert(utf8path);
+ // We need to make sure that the path does not contain forward slashes as above
+ // prefix does bypass the path normalization that replaces slashes with backslashes
+ // before passing the path to kernel mode APIs
+ std::replace(utf16path.begin(), utf16path.end(), L'/', L'\\');
+ return utf16path;
+ }
+ return ll_convert(utf8path);
+}
+
+static unsigned short get_fileattr(const std::wstring& utf16path, bool dontFollowSymLink = false)
+{
+ unsigned long flags = FILE_FLAG_BACKUP_SEMANTICS;
+ if (dontFollowSymLink)
+ {
+ flags |= FILE_FLAG_OPEN_REPARSE_POINT;
+ }
+ HANDLE file_handle = CreateFileW(utf16path.c_str(), FILE_READ_ATTRIBUTES,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ nullptr, OPEN_EXISTING, flags, nullptr);
+ if (file_handle != INVALID_HANDLE_VALUE)
+ {
+ FILE_ATTRIBUTE_TAG_INFO attribute_info;
+ if (GetFileInformationByHandleEx(file_handle, FileAttributeTagInfo, &attribute_info, sizeof(attribute_info)))
+ {
+ // A volume path alone (only drive letter) is not recognized as directory while it technically is
+ bool is_directory = (attribute_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
+ (iswalpha(utf16path[0]) && utf16path[1] == ':' &&
+ (!utf16path[2] || (is_slash(utf16path[2]) && !utf16path[3])));
+ unsigned short st_mode = is_directory ? S_IFDIR :
+ (attribute_info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT ? S_IFLNK : S_IFREG);
+ st_mode |= (attribute_info.FileAttributes & FILE_ATTRIBUTE_READONLY) ? S_IREAD : S_IREAD | S_IWRITE;
+ // we do not try to guess executable flag
+
+ // propagate user bits to group/other fields:
+ st_mode |= (st_mode & 0700) >> 3;
+ st_mode |= (st_mode & 0700) >> 6;
+
+ CloseHandle(file_handle);
+ return st_mode;
+ }
+ }
+ // Retrieve last error and set errno before calling CloseHandle()
+ set_errno_from_oserror(GetLastError());
+
+ if (file_handle != INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(file_handle);
+ }
+ return 0;
+}
#else
// On Posix we want to call strerror_r(), but alarmingly, there are two
@@ -108,18 +247,13 @@ std::string strerr(int errn)
}
#endif // ! LL_WINDOWS
-// On either system, shorthand call just infers global 'errno'.
-std::string strerr()
-{
- return strerr(errno);
-}
-
-int warnif(const std::string& desc, const std::string& filename, int rc, int accept=0)
+static int warnif(const std::string& desc, const std::string& filename, int rc, int accept = 0)
{
if (rc < 0)
{
// Capture errno before we start emitting output
int errn = errno;
+
// For certain operations, a particular errno value might be
// acceptable -- e.g. stat() could permit ENOENT, mkdir() could permit
// EEXIST. Don't warn if caller explicitly says this errno is okay.
@@ -176,68 +310,59 @@ int warnif(const std::string& desc, const std::string& filename, int rc, int acc
// static
int LLFile::mkdir(const std::string& dirname, int perms)
{
-#if LL_WINDOWS
- // permissions are ignored on Windows
- std::string utf8dirname = dirname;
- llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
- int rc = _wmkdir(utf16dirname.c_str());
-#else
- int rc = ::mkdir(dirname.c_str(), (mode_t)perms);
-#endif
// We often use mkdir() to ensure the existence of a directory that might
// already exist. There is no known case in which we want to call out as
// an error the requested directory already existing.
+#if LL_WINDOWS
+ // permissions are ignored on Windows
+ int rc = 0;
+ std::wstring utf16dirname = utf8path_to_wstring(dirname);
+ if (!CreateDirectoryW(utf16dirname.c_str(), nullptr))
+ {
+ // Only treat other errors than an already existing file as a real error
+ unsigned long oserr = GetLastError();
+ if (oserr != ERROR_ALREADY_EXISTS)
+ {
+ rc = set_errno_from_oserror(oserr);
+ }
+ }
+#else
+ int rc = ::mkdir(dirname.c_str(), (mode_t)perms);
if (rc < 0 && errno == EEXIST)
{
// this is not the error you want, move along
return 0;
}
+#endif
// anything else might be a problem
- return warnif("mkdir", dirname, rc, EEXIST);
+ return warnif("mkdir", dirname, rc);
}
// static
-int LLFile::rmdir(const std::string& dirname)
+int LLFile::rmdir(const std::string& dirname, int suppress_error)
{
#if LL_WINDOWS
- // permissions are ignored on Windows
- std::string utf8dirname = dirname;
- llutf16string utf16dirname = utf8str_to_utf16str(utf8dirname);
+ std::wstring utf16dirname = utf8path_to_wstring(dirname);
int rc = _wrmdir(utf16dirname.c_str());
#else
int rc = ::rmdir(dirname.c_str());
#endif
- return warnif("rmdir", dirname, rc);
+ return warnif("rmdir", dirname, rc, suppress_error);
}
// static
-LLFILE* LLFile::fopen(const std::string& filename, const char* mode) /* Flawfinder: ignore */
+LLFILE* LLFile::fopen(const std::string& filename, const char* mode)
{
#if LL_WINDOWS
- std::string utf8filename = filename;
- std::string utf8mode = std::string(mode);
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
- return _wfopen(utf16filename.c_str(),utf16mode.c_str());
+ std::wstring utf16filename = utf8path_to_wstring(filename);
+ std::wstring utf16mode = ll_convert(std::string(mode));
+ return _wfopen(utf16filename.c_str(), utf16mode.c_str());
#else
- return ::fopen(filename.c_str(),mode); /* Flawfinder: ignore */
-#endif
-}
-
-LLFILE* LLFile::_fsopen(const std::string& filename, const char* mode, int sharingFlag)
-{
-#if LL_WINDOWS
- std::string utf8filename = filename;
- std::string utf8mode = std::string(mode);
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- llutf16string utf16mode = utf8str_to_utf16str(utf8mode);
- return _wfsopen(utf16filename.c_str(),utf16mode.c_str(),sharingFlag);
-#else
- llassert(0);//No corresponding function on non-windows
- return NULL;
+ return ::fopen(filename.c_str(),mode);
#endif
}
+// static
int LLFile::close(LLFILE * file)
{
int ret_value = 0;
@@ -248,9 +373,10 @@ int LLFile::close(LLFILE * file)
return ret_value;
}
+// static
std::string LLFile::getContents(const std::string& filename)
{
- LLFILE* fp = fopen(filename, "rb"); /* Flawfinder: ignore */
+ LLFILE* fp = LLFile::fopen(filename, "rb");
if (fp)
{
fseek(fp, 0, SEEK_END);
@@ -267,45 +393,80 @@ std::string LLFile::getContents(const std::string& filename)
return LLStringUtil::null;
}
-int LLFile::remove(const std::string& filename, int supress_error)
+// static
+int LLFile::remove(const std::string& filename, int suppress_error)
{
#if LL_WINDOWS
- std::string utf8filename = filename;
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- int rc = _wremove(utf16filename.c_str());
+ // Posix remove() works on both files and directories although on Windows
+ // remove() and its wide char variant _wremove() only removes files just
+ // as its siblings unlink() and _wunlink().
+ // If we really only want to support files we should instead use
+ // unlink() in the non-Windows part below too
+ int rc = -1;
+ std::wstring utf16filename = utf8path_to_wstring(filename);
+ unsigned short st_mode = get_fileattr(utf16filename);
+ if (S_ISDIR(st_mode))
+ {
+ rc = _wrmdir(utf16filename.c_str());
+ }
+ else if (S_ISREG(st_mode))
+ {
+ rc = _wunlink(utf16filename.c_str());
+ }
+ else if (st_mode)
+ {
+ // it is something else than a file or directory
+ // this should not really happen as long as we do not allow for symlink
+ // detection in the optional parameter to get_fileattr()
+ rc = set_errno_from_oserror(ERROR_INVALID_PARAMETER);
+ }
+ else
+ {
+ // get_fileattr() failed and already set errno, preserve it for correct error reporting
+ }
#else
int rc = ::remove(filename.c_str());
#endif
- return warnif("remove", filename, rc, supress_error);
+ return warnif("remove", filename, rc, suppress_error);
}
-int LLFile::rename(const std::string& filename, const std::string& newname, int supress_error)
+// static
+int LLFile::rename(const std::string& filename, const std::string& newname, int suppress_error)
{
#if LL_WINDOWS
- std::string utf8filename = filename;
- std::string utf8newname = newname;
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- llutf16string utf16newname = utf8str_to_utf16str(utf8newname);
- int rc = _wrename(utf16filename.c_str(),utf16newname.c_str());
+ // Posix rename() will gladly overwrite a file at newname if it exists, the Windows
+ // rename(), respectively _wrename(), will bark on that. Instead call directly the Windows
+ // API MoveFileEx() and use its flags to specify that overwrite is allowed.
+ std::wstring utf16filename = utf8path_to_wstring(filename);
+ std::wstring utf16newname = utf8path_to_wstring(newname);
+ int rc = 0;
+ if (!MoveFileExW(utf16filename.c_str(), utf16newname.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED))
+ {
+ rc = set_errno_from_oserror(GetLastError());
+ }
#else
int rc = ::rename(filename.c_str(),newname.c_str());
#endif
- return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, supress_error);
+ return warnif(STRINGIZE("rename to '" << newname << "' from"), filename, rc, suppress_error);
}
+// Make this a define rather than using magic numbers multiple times in the code
+#define LLFILE_COPY_BUFFER_SIZE 16384
+
+// static
bool LLFile::copy(const std::string& from, const std::string& to)
{
bool copied = false;
- LLFILE* in = LLFile::fopen(from, "rb"); /* Flawfinder: ignore */
+ LLFILE* in = LLFile::fopen(from, "rb");
if (in)
{
- LLFILE* out = LLFile::fopen(to, "wb"); /* Flawfinder: ignore */
+ LLFILE* out = LLFile::fopen(to, "wb");
if (out)
{
- char buf[16384]; /* Flawfinder: ignore */
+ char buf[LLFILE_COPY_BUFFER_SIZE];
size_t readbytes;
bool write_ok = true;
- while(write_ok && (readbytes = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */
+ while (write_ok && (readbytes = fread(buf, 1, LLFILE_COPY_BUFFER_SIZE, in)))
{
if (fwrite(buf, 1, readbytes, out) != readbytes)
{
@@ -324,34 +485,62 @@ bool LLFile::copy(const std::string& from, const std::string& to)
return copied;
}
-int LLFile::stat(const std::string& filename, llstat* filestatus)
+// static
+int LLFile::stat(const std::string& filename, llstat* filestatus, int suppress_error)
{
#if LL_WINDOWS
- std::string utf8filename = filename;
- llutf16string utf16filename = utf8str_to_utf16str(utf8filename);
- int rc = _wstat(utf16filename.c_str(),filestatus);
+ std::wstring utf16filename = utf8path_to_wstring(filename);
+ int rc = _wstat64(utf16filename.c_str(), filestatus);
#else
- int rc = ::stat(filename.c_str(),filestatus);
+ int rc = ::stat(filename.c_str(), filestatus);
#endif
- // We use stat() to determine existence (see isfile(), isdir()).
- // Don't spam the log if the subject pathname doesn't exist.
- return warnif("stat", filename, rc, ENOENT);
+ return warnif("stat", filename, rc, suppress_error);
}
+// static
+unsigned short LLFile::getattr(const std::string& filename, bool dontFollowSymLink, int suppress_error)
+{
+#if LL_WINDOWS
+ // _wstat64() is a bit heavyweight on Windows, use a more lightweight API
+ // to just get the attributes
+ int rc = -1;
+ std::wstring utf16filename = utf8path_to_wstring(filename);
+ unsigned short st_mode = get_fileattr(utf16filename, dontFollowSymLink);
+ if (st_mode)
+ {
+ return st_mode;
+ }
+#else
+ llstat filestatus;
+ int rc = dontFollowSymLink ? ::lstat(filename.c_str(), &filestatus) : ::stat(filename.c_str(), &filestatus);
+ if (rc == 0)
+ {
+ return filestatus.st_mode;
+ }
+#endif
+ warnif("getattr", filename, rc, suppress_error);
+ return 0;
+}
+
+// static
bool LLFile::isdir(const std::string& filename)
{
- llstat st;
-
- return stat(filename, &st) == 0 && S_ISDIR(st.st_mode);
+ return S_ISDIR(getattr(filename));
}
+// static
bool LLFile::isfile(const std::string& filename)
{
- llstat st;
-
- return stat(filename, &st) == 0 && S_ISREG(st.st_mode);
+ return S_ISREG(getattr(filename));
}
+// static
+bool LLFile::islink(const std::string& filename)
+{
+ return S_ISLNK(getattr(filename, true));
+}
+
+// static
const char *LLFile::tmpdir()
{
static std::string utf8path;
@@ -378,89 +567,22 @@ const char *LLFile::tmpdir()
return utf8path.c_str();
}
-
-/***************** Modified file stream created to overcome the incorrect behaviour of posix fopen in windows *******************/
-
#if LL_WINDOWS
-LLFILE * LLFile::_Fiopen(const std::string& filename,
- std::ios::openmode mode)
-{ // open a file
- static const char *mods[] =
- { // fopen mode strings corresponding to valid[i]
- "r", "w", "w", "a", "rb", "wb", "wb", "ab",
- "r+", "w+", "a+", "r+b", "w+b", "a+b",
- 0};
- static const int valid[] =
- { // valid combinations of open flags
- ios_base::in,
- ios_base::out,
- ios_base::out | ios_base::trunc,
- ios_base::out | ios_base::app,
- ios_base::in | ios_base::binary,
- ios_base::out | ios_base::binary,
- ios_base::out | ios_base::trunc | ios_base::binary,
- ios_base::out | ios_base::app | ios_base::binary,
- ios_base::in | ios_base::out,
- ios_base::in | ios_base::out | ios_base::trunc,
- ios_base::in | ios_base::out | ios_base::app,
- ios_base::in | ios_base::out | ios_base::binary,
- ios_base::in | ios_base::out | ios_base::trunc
- | ios_base::binary,
- ios_base::in | ios_base::out | ios_base::app
- | ios_base::binary,
- 0};
-
- LLFILE *fp = 0;
- int n;
- ios_base::openmode atendflag = mode & ios_base::ate;
- ios_base::openmode norepflag = mode & ios_base::_Noreplace;
-
- if (mode & ios_base::_Nocreate)
- mode |= ios_base::in; // file must exist
- mode &= ~(ios_base::ate | ios_base::_Nocreate | ios_base::_Noreplace);
- for (n = 0; valid[n] != 0 && valid[n] != mode; ++n)
- ; // look for a valid mode
-
- if (valid[n] == 0)
- return (0); // no valid mode
- else if (norepflag && mode & (ios_base::out | ios_base::app)
- && (fp = LLFile::fopen(filename, "r")) != 0) /* Flawfinder: ignore */
- { // file must not exist, close and fail
- fclose(fp);
- return (0);
- }
- else if (fp != 0 && fclose(fp) != 0)
- return (0); // can't close after test open
-// should open with protection here, if other than default
- else if ((fp = LLFile::fopen(filename, mods[n])) == 0) /* Flawfinder: ignore */
- return (0); // open failed
-
- if (!atendflag || fseek(fp, 0, SEEK_END) == 0)
- return (fp); // no need to seek to end, or seek succeeded
-
- fclose(fp); // can't position at end
- return (0);
-}
-
-#endif /* LL_WINDOWS */
-
-
-#if LL_WINDOWS
/************** input file stream ********************************/
llifstream::llifstream() {}
// explicit
llifstream::llifstream(const std::string& _Filename, ios_base::openmode _Mode):
- std::ifstream(utf8str_to_utf16str( _Filename ).c_str(),
+ std::ifstream(ll_convert( _Filename ).c_str(),
_Mode | ios_base::in)
{
}
void llifstream::open(const std::string& _Filename, ios_base::openmode _Mode)
{
- std::ifstream::open(utf8str_to_utf16str(_Filename).c_str(),
+ std::ifstream::open(ll_convert(_Filename).c_str(),
_Mode | ios_base::in);
}
@@ -472,14 +594,14 @@ llofstream::llofstream() {}
// explicit
llofstream::llofstream(const std::string& _Filename, ios_base::openmode _Mode):
- std::ofstream(utf8str_to_utf16str( _Filename ).c_str(),
+ std::ofstream(ll_convert( _Filename ).c_str(),
_Mode | ios_base::out)
{
}
void llofstream::open(const std::string& _Filename, ios_base::openmode _Mode)
{
- std::ofstream::open(utf8str_to_utf16str( _Filename ).c_str(),
+ std::ofstream::open(ll_convert( _Filename ).c_str(),
_Mode | ios_base::out);
}
diff --git a/indra/llcommon/llfile.h b/indra/llcommon/llfile.h
index 1661cbeb55..04a2946ac4 100644
--- a/indra/llcommon/llfile.h
+++ b/indra/llcommon/llfile.h
@@ -41,8 +41,9 @@ typedef FILE LLFILE;
#include
#if LL_WINDOWS
-// windows version of stat function and stat data structure are called _stat
-typedef struct _stat llstat;
+// The Windows version of stat function and stat data structure are called _stat64
+// We use _stat64 here to support 64-bit st_size and time_t values
+typedef struct _stat64 llstat;
#else
typedef struct stat llstat;
#include
@@ -56,35 +57,110 @@ typedef struct stat llstat;
# define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
#endif
+// Windows C runtime library does not define this and does not support symlink detection in the
+// stat functions but we do in our getattr() function
+#ifndef S_IFLNK
+#define S_IFLNK 0xA000 /* symlink */
+#endif
+
+#ifndef S_ISLNK
+#define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK)
+#endif
+
#include "llstring.h" // safe char* -> std::string conversion
+/// LLFile is a class of static functions operating on paths
+/// All the functions with a path string input take UTF8 path/filenames
class LL_COMMON_API LLFile
{
public:
- // All these functions take UTF8 path/filenames.
- static LLFILE* fopen(const std::string& filename,const char* accessmode); /* Flawfinder: ignore */
- static LLFILE* _fsopen(const std::string& filename,const char* accessmode,int sharingFlag);
+ /// open a file with the specified access mode
+ static LLFILE* fopen(const std::string& filename, const char* accessmode); /* Flawfinder: ignore */
+ ///< 'accessmode' follows the rules of the Posix fopen() mode parameter
+ /// "r" open the file for reading only and positions the stream at the beginning
+ /// "r+" open the file for reading and writing and positions the stream at the beginning
+ /// "w" open the file for reading and writing and truncate it to zero length
+ /// "w+" open or create the file for reading and writing and truncate to zero length if it existed
+ /// "a" open the file for reading and writing and position the stream at the end of the file
+ /// "a+" open or create the file for reading and writing and position the stream at the end of the file
+ ///
+ /// in addition to these values, "b" can be appended to indicate binary stream access, but on Linux and Mac
+ /// this is strictly for compatibility and has no effect. On Windows this makes the file functions not
+ /// try to translate line endings. Windows also allows to append "t" to indicate text mode. If neither
+ /// "b" or "t" is defined, Windows uses the value set by _fmode which by default is _O_TEXT.
+ /// This means that it is always a good idea to append "b" specifically for binary file access to
+ /// avoid corruption of the binary consistency of the data stream when reading or writing
+ /// Other characters in 'accessmode' will usually cause an error as fopen will verify this parameter
+ /// @returns a valid LLFILE* pointer on success or NULL on failure
static int close(LLFILE * file);
+ /// retrieve the content of a file into a string
static std::string getContents(const std::string& filename);
+ ///< @returns the content of the file or an empty string on failure
- // perms is a permissions mask like 0777 or 0700. In most cases it will
- // be overridden by the user's umask. It is ignored on Windows.
- // mkdir() considers "directory already exists" to be SUCCESS.
+ /// create a directory
static int mkdir(const std::string& filename, int perms = 0700);
+ ///< perms is a permissions mask like 0777 or 0700. In most cases it will be
+ /// overridden by the user's umask. It is ignored on Windows.
+ /// mkdir() considers "directory already exists" to be not an error.
+ /// @returns 0 on success and -1 on failure.
- static int rmdir(const std::string& filename);
- static int remove(const std::string& filename, int supress_error = 0);
- static int rename(const std::string& filename,const std::string& newname, int supress_error = 0);
+ //// remove a directory
+ static int rmdir(const std::string& filename, int suppress_error = 0);
+ ///< pass ENOENT in the optional 'suppress_error' parameter
+ /// if you don't want a warning in the log when the directory does not exist
+ /// @returns 0 on success and -1 on failure.
+
+ /// remove a file or directory
+ static int remove(const std::string& filename, int suppress_error = 0);
+ ///< pass ENOENT in the optional 'suppress_error' parameter
+ /// if you don't want a warning in the log when the directory does not exist
+ /// @returns 0 on success and -1 on failure.
+
+ /// rename a file
+ static int rename(const std::string& filename, const std::string& newname, int suppress_error = 0);
+ ///< it will silently overwrite newname if it exists without returning an error
+ /// Posix guarantees that if newname already exists, then there will be no moment
+ /// in which for other processes newname does not exist. There is no such guarantee
+ /// under Windows at this time. It may do it in the same way but the used Windows API
+ /// does not make such guarantees.
+ /// @returns 0 on success and -1 on failure.
+
+
+ /// copy the contents of file from 'from' to 'to' filename
static bool copy(const std::string& from, const std::string& to);
+ ///< @returns true on success and false on failure.
- static int stat(const std::string& filename,llstat* file_status);
- static bool isdir(const std::string& filename);
- static bool isfile(const std::string& filename);
- static LLFILE * _Fiopen(const std::string& filename,
- std::ios::openmode mode);
+ /// return the file stat structure for filename
+ static int stat(const std::string& filename, llstat* file_status, int suppress_error = ENOENT);
+ ///< for compatibility with existing uses of LL_File::stat() we use ENOENT as default in the
+ /// optional 'suppress_error' parameter to avoid spamming the log with warnings when the API
+ /// is used to detect if a file exists
+ /// @returns 0 on success and -1 on failure.
+ /// get the file or directory attributes for filename
+ static unsigned short getattr(const std::string& filename, bool dontFollowSymLink = false, int suppress_error = ENOENT);
+ ///< a more lightweight function on Windows to stat, that just returns the file attribute flags
+ /// dontFollowSymLinks set to true returns the attributes of the symlink if it is one, rather than resolving it
+ /// we pass by default ENOENT in the optional 'suppress_error' parameter to not spam the log with
+ /// warnings when the file or directory does not exist
+ /// @returns 0 on failure and a st_mode value with either S_IFDIR or S_IFREG set otherwise
+ /// together with the three access bits which under Windows only the write bit is relevant.
+
+ /// check if filename is an existing directory
+ static bool isdir(const std::string& filename);
+ ///< @returns true if the path is for an existing directory
+
+ /// check if filename is an existing file
+ static bool isfile(const std::string& filename);
+ ///< @returns true if the path is for an existing file
+
+ /// check if filename is a symlink
+ static bool islink(const std::string& filename);
+ ///< @returns true if the path is pointing at a symlink
+
+ /// return a path to the temporary directory on the system
static const char * tmpdir();
};
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index 662a2511cd..ada6b9519e 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -188,6 +188,17 @@ public:
<< childout.peek(0, peeklen) << "..." << LL_ENDL;
}
+ // Handle any remaining stderr data (partial lines) the same way as we do
+ // for stdout: log it.
+ LLProcess::ReadPipe& childerr(mChild->getReadPipe(LLProcess::STDERR));
+ if (childerr.size())
+ {
+ LLProcess::ReadPipe::size_type
+ peeklen((std::min)(LLProcess::ReadPipe::size_type(50), childerr.size()));
+ LL_WARNS("LLLeap") << "Final stderr " << childerr.size() << " bytes: "
+ << childerr.peek(0, peeklen) << "..." << LL_ENDL;
+ }
+
// Kill this instance. MUST BE LAST before return!
delete this;
return false;
diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp
index e999b8f597..c8ca586e7f 100644
--- a/indra/llcommon/llmd5.cpp
+++ b/indra/llcommon/llmd5.cpp
@@ -255,6 +255,11 @@ void LLMD5::raw_digest(unsigned char* s) const
memcpy(s, digest, 16); /* Flawfinder: ignore */
}
+#if LL_DARWIN
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+#endif
+
void LLMD5::hex_digest(char* s) const
{
if (!finalized)
@@ -273,6 +278,10 @@ void LLMD5::hex_digest(char* s) const
s[32] = '\0';
}
+#if LL_DARWIN
+#pragma clang diagnostic pop
+#endif
+
std::ostream& operator<<(std::ostream& stream, const LLMD5& context)
{
char s[33]; /* Flawfinder: ignore */
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index b616edfde7..adc556d180 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -71,7 +71,11 @@ LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
#define ll_assert_aligned(ptr,alignment)
#endif
+#if LL_ARM64
+#include "sse2neon.h"
+#else
#include
+#endif
template T* LL_NEXT_ALIGNED_ADDRESS(T* address)
{
@@ -231,8 +235,6 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
#if defined(LL_WINDOWS)
void* ret = _aligned_malloc(size, 32);
-#elif defined(LL_DARWIN)
- void* ret = ll_aligned_malloc_fallback( size, 32 );
#else
void *ret;
if (0 != posix_memalign(&ret, 32, size))
@@ -248,8 +250,31 @@ inline void ll_aligned_free_32(void *p)
LL_PROFILE_FREE(p);
#if defined(LL_WINDOWS)
_aligned_free(p);
-#elif defined(LL_DARWIN)
- ll_aligned_free_fallback( p );
+#else
+ free(p); // posix_memalign() is compatible with heap deallocator
+#endif
+}
+
+inline void* ll_aligned_malloc_64(size_t size) // returned hunk MUST be freed with ll_aligned_free_32().
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
+#if defined(LL_WINDOWS)
+ void* ret = _aligned_malloc(size, 64);
+#else
+ void *ret;
+ if (0 != posix_memalign(&ret, 64, size))
+ return nullptr;
+#endif
+ LL_PROFILE_ALLOC(ret, size);
+ return ret;
+}
+
+inline void ll_aligned_free_64(void *p)
+{
+ LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
+ LL_PROFILE_FREE(p);
+#if defined(LL_WINDOWS)
+ _aligned_free(p);
#else
free(p); // posix_memalign() is compatible with heap deallocator
#endif
@@ -261,19 +286,23 @@ LL_FORCE_INLINE void* ll_aligned_malloc(size_t size)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
void* ret;
- if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0)
+ if constexpr (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0)
{
ret = malloc(size);
LL_PROFILE_ALLOC(ret, size);
}
- else if (ALIGNMENT == 16)
+ else if constexpr (ALIGNMENT == 16)
{
ret = ll_aligned_malloc_16(size);
}
- else if (ALIGNMENT == 32)
+ else if constexpr (ALIGNMENT == 32)
{
ret = ll_aligned_malloc_32(size);
}
+ else if constexpr (ALIGNMENT == 64)
+ {
+ ret = ll_aligned_malloc_64(size);
+ }
else
{
ret = ll_aligned_malloc_fallback(size, ALIGNMENT);
@@ -285,16 +314,20 @@ template
LL_FORCE_INLINE void ll_aligned_free(void* ptr)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
- if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
+ if constexpr (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
{
LL_PROFILE_FREE(ptr);
free(ptr);
}
- else if (ALIGNMENT == 16)
+ else if constexpr (ALIGNMENT == 16)
{
ll_aligned_free_16(ptr);
}
- else if (ALIGNMENT == 32)
+ else if constexpr (ALIGNMENT == 32)
+ {
+ return ll_aligned_free_32(ptr);
+ }
+ else if constexpr (ALIGNMENT == 64)
{
return ll_aligned_free_32(ptr);
}
@@ -310,6 +343,9 @@ LL_FORCE_INLINE void ll_aligned_free(void* ptr)
inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __restrict src, size_t bytes)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_MEMORY;
+#if defined(LL_ARM64)
+ memcpy(dst, src, bytes);
+#else
assert(src != NULL);
assert(dst != NULL);
assert(bytes > 0);
@@ -375,6 +411,7 @@ inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __
dst += 16;
src += 16;
}
+#endif
}
#ifndef __DEBUG_PRIVATE_MEM__
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index b499a9ce10..b2a9734548 100644
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -76,6 +76,23 @@
#endif
#endif
+// Set up CPU architecture defines
+#if LL_MSVC && defined(_M_ARM64)
+# define LL_ARM64 1
+#elif LL_GNUC && (defined(__arm64__) || defined(__aarch64__))
+# define LL_ARM64 1
+#elif LL_MSVC && _M_X64
+# define LL_X86_64 1
+# define LL_X86 1
+#elif LL_MSVC && _M_IX86
+# define LL_X86 1
+#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) )
+# define LL_X86_64 1
+# define LL_X86 1
+#elif LL_GNUC && ( defined(__i386__) )
+# define LL_X86 1
+#endif
+
// Deal with minor differences on Unixy OSes.
#if LL_DARWIN || LL_LINUX
// Different name, same functionality.
@@ -118,11 +135,8 @@
#if LL_WINDOWS
#define LL_DLLEXPORT __declspec(dllexport)
#define LL_DLLIMPORT __declspec(dllimport)
-#elif LL_LINUX
-#define LL_DLLEXPORT __attribute__ ((visibility("default")))
-#define LL_DLLIMPORT
#else
-#define LL_DLLEXPORT
+#define LL_DLLEXPORT __attribute__ ((visibility("default")))
#define LL_DLLIMPORT
#endif // LL_WINDOWS
@@ -167,7 +181,7 @@
#define LL_TO_STRING_HELPER(x) #x
#define LL_TO_STRING(x) LL_TO_STRING_HELPER(x)
-#define LL_TO_WSTRING_HELPER(x) L#x
+#define LL_TO_WSTRING_HELPER(x) L## #x
#define LL_TO_WSTRING(x) LL_TO_WSTRING_HELPER(x)
#define LL_FILE_LINENO_MSG(msg) __FILE__ "(" LL_TO_STRING(__LINE__) ") : " msg
#define LL_GLUE_IMPL(x, y) x##y
@@ -187,4 +201,16 @@
#define LL_PRETTY_FUNCTION __PRETTY_FUNCTION__
#endif
+#if LL_ARM64
+#define GLM_FORCE_NEON 1
+#else
+#define GLM_FORCE_SSE2 1
+#endif
+
+#if LL_ARM64
+#define KDU_NEON_INTRINSICS 1
+#else
+#define KDU_X86_INTRINSICS 1
+#endif
+
#endif // not LL_LINDEN_PREPROCESSOR_H
diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 912e596c3f..33a9180cc6 100644
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -457,7 +457,8 @@ public:
("slot", LLSD::Integer(mIndex))
("name", whichfile(mIndex))
("desc", mDesc)
- ("eof", state == CLOSED));
+ ("eof", state == CLOSED)
+ ("exhst", state == EXHAUSTED));
}
return false;
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index a783e18e49..0778b123ea 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -628,6 +628,8 @@ private:
#elif LL_DARWIN
+#include
+#include
#include
#include
@@ -638,17 +640,21 @@ public:
{
getCPUIDInfo();
uint64_t frequency = getSysctlInt64("hw.cpufrequency");
+ if (frequency == 0) // fallback to clockrate and tbfrequency
+ {
+ frequency = getSysctlClockrate() * getSysctlInt64("hw.tbfrequency");
+ }
setInfo(eFrequency, (F64)frequency / (F64)1000000);
}
- virtual ~LLProcessorInfoDarwinImpl() {}
+ virtual ~LLProcessorInfoDarwinImpl() = default;
private:
int getSysctlInt(const char* name)
{
int result = 0;
size_t len = sizeof(int);
- int error = sysctlbyname(name, (void*)&result, &len, NULL, 0);
+ int error = sysctlbyname(name, (void*)&result, &len, nullptr, 0);
return error == -1 ? 0 : result;
}
@@ -656,7 +662,7 @@ private:
{
uint64_t value = 0;
size_t size = sizeof(value);
- int result = sysctlbyname(name, (void*)&value, &size, NULL, 0);
+ int result = sysctlbyname(name, (void*)&value, &size, nullptr, 0);
if ( result == 0 )
{
if ( size == sizeof( uint64_t ) )
@@ -676,6 +682,14 @@ private:
return result == -1 ? 0 : value;
}
+ uint64_t getSysctlClockrate()
+ {
+ struct clockinfo clockrate{};
+ size_t size = sizeof(clockrate);
+ int error = sysctlbyname("kern.clockrate", &clockrate, &size, nullptr, 0);
+ return error == -1 ? 0 : clockrate.hz;
+ }
+
void getCPUIDInfo()
{
size_t len = 0;
@@ -725,32 +739,7 @@ private:
}
}
- // *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be
- // The feature bits I think it is. Here's a test:
-#ifndef LL_RELEASE_FOR_DOWNLOAD
- #if defined(__i386__) && defined(__PIC__)
- /* %ebx may be the PIC register. */
- #define __cpuid(level, a, b, c, d) \
- __asm__ ("xchgl\t%%ebx, %1\n\t" \
- "cpuid\n\t" \
- "xchgl\t%%ebx, %1\n\t" \
- : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
- : "0" (level))
- #else
- #define __cpuid(level, a, b, c, d) \
- __asm__ ("cpuid\n\t" \
- : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
- : "0" (level))
- #endif
-
- unsigned int eax, ebx, ecx, edx;
- __cpuid(0x1, eax, ebx, ecx, edx);
- if(feature_infos[0] != (S32)edx)
- {
- LL_WARNS() << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << LL_ENDL;
- }
-#endif // LL_RELEASE_FOR_DOWNLOAD
-
+ // @TODO: Audit our usage of machdep.cpu.feature_bits.
uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits");
S32 *ext_feature_infos = (S32*)(&ext_feature_info);
diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h
index f8ccf686c8..b955f7f55c 100644
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -28,20 +28,7 @@
#ifndef LLPROCESSOR_H
#define LLPROCESSOR_H
#include "llunits.h"
-
-#if LL_MSVC && _M_X64
-# define LL_X86_64 1
-# define LL_X86 1
-#elif LL_MSVC && _M_IX86
-# define LL_X86 1
-#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) )
-# define LL_X86_64 1
-# define LL_X86 1
-#elif LL_GNUC && ( defined(__i386__) )
-# define LL_X86 1
-#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) )
-# define LL_PPC 1
-#endif
+#include "llpreprocessor.h"
class LLProcessorInfoImpl;
diff --git a/indra/llcommon/llprofiler.h b/indra/llcommon/llprofiler.h
index f6a4d24747..5fb32d6280 100644
--- a/indra/llcommon/llprofiler.h
+++ b/indra/llcommon/llprofiler.h
@@ -74,23 +74,18 @@
#define LL_PROFILER_CONFIGURATION LL_PROFILER_CONFIG_FAST_TIMER
#endif
-extern thread_local bool gProfilerEnabled;
-
#if defined(LL_PROFILER_CONFIGURATION) && (LL_PROFILER_CONFIGURATION > LL_PROFILER_CONFIG_NONE)
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY || LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
#include "tracy/Tracy.hpp"
- // Enable OpenGL profiling
- #define LL_PROFILER_ENABLE_TRACY_OPENGL 0
-
// Enable RenderDoc labeling
- #define LL_PROFILER_ENABLE_RENDER_DOC 0
+ //#define LL_PROFILER_ENABLE_RENDER_DOC 0
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY
#define LL_PROFILER_FRAME_END FrameMark
- #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); gProfilerEnabled = true;
+ #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name );
#define LL_RECORD_BLOCK_TIME(name) ZoneScoped // Want descriptive names; was: ZoneNamedN( ___tracy_scoped_zone, #name, true );
#define LL_PROFILE_ZONE_NAMED(name) ZoneNamedN( ___tracy_scoped_zone, name, true );
#define LL_PROFILE_ZONE_NAMED_COLOR(name,color) ZoneNamedNC( ___tracy_scopped_zone, name, color, true ) // RGB
@@ -133,7 +128,7 @@ extern thread_local bool gProfilerEnabled;
#endif
#if LL_PROFILER_CONFIGURATION == LL_PROFILER_CONFIG_TRACY_FAST_TIMER
#define LL_PROFILER_FRAME_END FrameMark
- #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name ); gProfilerEnabled = true;
+ #define LL_PROFILER_SET_THREAD_NAME( name ) tracy::SetThreadName( name );
#define LL_RECORD_BLOCK_TIME(name) ZoneNamedN(___tracy_scoped_zone, #name, true); const LLTrace::BlockTimer& LL_GLUE_TOKENS(block_time_recorder, __LINE__)(LLTrace::timeThisBlock(name)); (void)LL_GLUE_TOKENS(block_time_recorder, __LINE__);
#define LL_PROFILE_ZONE_NAMED(name) ZoneNamedN( ___tracy_scoped_zone, #name, true );
#define LL_PROFILE_ZONE_NAMED_COLOR(name,color) ZoneNamedNC( ___tracy_scopped_zone, name, color, true ) // RGB
@@ -158,23 +153,20 @@ extern thread_local bool gProfilerEnabled;
#endif // LL_PROFILER
#if LL_PROFILER_ENABLE_TRACY_OPENGL
-#define LL_PROFILE_GPU_ZONE(name) TracyGpuZone(name)
-#define LL_PROFILE_GPU_ZONEC(name,color) TracyGpuZoneC(name,color)
+#define LL_PROFILE_GPU_ZONE(name) TracyGpuZone(name)
+#define LL_PROFILE_GPU_ZONEC(name,color) TracyGpuZoneC(name,color)
#define LL_PROFILER_GPU_COLLECT TracyGpuCollect
#define LL_PROFILER_GPU_CONTEXT TracyGpuContext
-
-// disable memory tracking (incompatible with GPU tracing
-#define LL_PROFILE_ALLOC(ptr, size) (void)(ptr); (void)(size);
-#define LL_PROFILE_FREE(ptr) (void)(ptr);
+#define LL_PROFILER_GPU_CONTEXT_NAMED TracyGpuContextName
#else
-#define LL_PROFILE_GPU_ZONE(name) (void)name;
-#define LL_PROFILE_GPU_ZONEC(name,color) (void)name;(void)color;
+#define LL_PROFILE_GPU_ZONE(name) (void)name;
+#define LL_PROFILE_GPU_ZONEC(name,color) (void)name;(void)color;
#define LL_PROFILER_GPU_COLLECT
#define LL_PROFILER_GPU_CONTEXT
+#define LL_PROFILER_GPU_CONTEXT_NAMED(name) (void)name;
+#endif // LL_PROFILER_ENABLE_TRACY_OPENGL
-#define LL_LABEL_OBJECT_GL(type, name, length, label)
-
-#if !LL_DARWIN && LL_PROFILER_CONFIGURATION > 1
+#if LL_PROFILER_CONFIGURATION >= LL_PROFILER_CONFIG_TRACY
#define LL_PROFILE_ALLOC(ptr, size) TracyAlloc(ptr, size)
#define LL_PROFILE_FREE(ptr) TracyFree(ptr)
#else
@@ -182,8 +174,6 @@ extern thread_local bool gProfilerEnabled;
#define LL_PROFILE_FREE(ptr) (void)(ptr);
#endif
-#endif
-
#if LL_PROFILER_ENABLE_RENDER_DOC
#define LL_LABEL_OBJECT_GL(type, name, length, label) glObjectLabel(type, name, length, label)
#else
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 38bbe19ddd..497c0ad3eb 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -553,6 +553,100 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter
} // namespace llsd
+/*****************************************************************************
+* LLSDParam>
+*****************************************************************************/
+// Given an LLSD array, return a const std::vector&, where T is a type
+// supported by LLSDParam. Bonus: if the LLSD value is actually a scalar,
+// return a single-element vector containing the converted value.
+template
+class LLSDParam>: public LLSDParamBase
+{
+public:
+ LLSDParam(const LLSD& array)
+ {
+ // treat undefined "array" as empty vector
+ if (array.isDefined())
+ {
+ // what if it's a scalar?
+ if (! array.isArray())
+ {
+ v.push_back(LLSDParam(array));
+ }
+ else // really is an array
+ {
+ // reserve space for the array entries
+ v.reserve(array.size());
+ for (const auto& item : llsd::inArray(array))
+ {
+ v.push_back(LLSDParam(item));
+ }
+ }
+ }
+ }
+
+ operator const std::vector&() const { return v; }
+
+private:
+ std::vector v;
+};
+
+
+/*****************************************************************************
+ * toArray(), toMap()
+ *****************************************************************************/
+namespace llsd
+{
+
+// For some T convertible to LLSD, given std::vector myVec,
+// toArray(myVec) returns an LLSD array whose entries correspond to the
+// items in myVec.
+// For some U convertible to LLSD, given function U xform(const T&),
+// toArray(myVec, xform) returns an LLSD array whose every entry is
+// xform(item) of the corresponding item in myVec.
+// toArray() actually works with any container usable with range
+// 'for', not just std::vector.
+// (Once we get C++20 we can use std::identity instead of this default lambda.)
+template
+LLSD toArray(const C& container, FUNC&& func = [](const auto& arg) { return arg; })
+{
+ LLSD array;
+ for (const auto& item : container)
+ {
+ array.append(std::forward(func)(item));
+ }
+ return array;
+}
+
+// For some T convertible to LLSD, given std::map myMap,
+// toMap(myMap) returns an LLSD map whose entries correspond to the
+// (key, value) pairs in myMap.
+// For some U convertible to LLSD, given function
+// std::pair xform(const std::pair&),
+// toMap(myMap, xform) returns an LLSD map whose every entry is
+// xform(pair) of the corresponding (key, value) pair in myMap.
+// toMap() actually works with any container usable with range 'for', not
+// just std::map. It need not even be an associative container, as long as
+// you pass an xform function that returns std::pair.
+// (Once we get C++20 we can use std::identity instead of this default lambda.)
+template
+LLSD toMap(const C& container, FUNC&& func = [](const auto& arg) { return arg; })
+{
+ LLSD map;
+ for (const auto& pair : container)
+ {
+ const auto& [key, value] = std::forward(func)(pair);
+ map[key] = value;
+ }
+ return map;
+}
+
+} // namespace llsd
+
+/*****************************************************************************
+ * boost::hash
+ *****************************************************************************/
+
// Specialization for generating a hash value from an LLSD block.
namespace boost
{
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 3f33ad61c5..270ca40086 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -192,6 +192,9 @@ LLOSInfo::LLOSInfo() :
GetSystemInfo(&si); //if it fails get regular system info
//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
+#pragma warning(push)
+#pragma warning(disable : 4996) // ignore 'deprecated.' GetVersionEx is deprecated
+
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
@@ -210,6 +213,8 @@ LLOSInfo::LLOSInfo() :
}
}
+#pragma warning(pop)
+
S32 ubr = 0; // Windows 10 Update Build Revision, can be retrieved from a registry
if (mMajorVer == 10)
{
@@ -1323,7 +1328,7 @@ bool gunzip_file(const std::string& srcfile, const std::string& dstfile)
S32 bytes = 0;
tmpfile = dstfile + ".t";
#ifdef LL_WINDOWS
- llutf16string utf16filename = utf8str_to_utf16str(srcfile);
+ std::wstring utf16filename = ll_convert(srcfile);
src = gzopen_w(utf16filename.c_str(), "rb");
#else
src = gzopen(srcfile.c_str(), "rb");
@@ -1343,10 +1348,6 @@ bool gunzip_file(const std::string& srcfile, const std::string& dstfile)
} while(gzeof(src) == 0);
fclose(dst);
dst = NULL;
-#if LL_WINDOWS
- // Rename in windows needs the dstfile to not exist.
- LLFile::remove(dstfile, ENOENT);
-#endif
if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
retval = true;
err:
@@ -1367,7 +1368,7 @@ bool gzip_file(const std::string& srcfile, const std::string& dstfile)
tmpfile = dstfile + ".t";
#ifdef LL_WINDOWS
- llutf16string utf16filename = utf8str_to_utf16str(tmpfile);
+ std::wstring utf16filename = ll_convert(tmpfile);
dst = gzopen_w(utf16filename.c_str(), "wb");
#else
dst = gzopen(tmpfile.c_str(), "wb");
@@ -1394,10 +1395,6 @@ bool gzip_file(const std::string& srcfile, const std::string& dstfile)
gzclose(dst);
dst = NULL;
-#if LL_WINDOWS
- // Rename in windows needs the dstfile to not exist.
- LLFile::remove(dstfile);
-#endif
if (LLFile::rename(tmpfile, dstfile) == -1) goto err; /* Flawfinder: ignore */
retval = true;
err:
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index e5d25b52f0..692941a892 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -28,6 +28,7 @@
#include "apr_portable.h"
+#include "llapp.h"
#include "llthread.h"
#include "llmutex.h"
@@ -35,6 +36,7 @@
#include "lltrace.h"
#include "lltracethreadrecorder.h"
#include "llexception.h"
+#include "workqueue.h"
#if LL_LINUX
#include
@@ -106,6 +108,27 @@ namespace
return s_thread_id;
}
+#if LL_WINDOWS
+
+ static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
+
+ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop)
+ {
+ if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop))
+ {
+ // Handled
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else if (code == STATUS_MSC_EXCEPTION)
+ {
+ // C++ exception, go on
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // handle it, convert to std::exception
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+#endif // LL_WINDOWS
} // anonymous namespace
LL_COMMON_API bool on_main_thread()
@@ -157,20 +180,11 @@ void LLThread::threadRun()
// Run the user supplied function
do
{
- try
- {
- run();
- }
- catch (const LLContinueError &e)
- {
- LL_WARNS("THREAD") << "ContinueException on thread '" << mName <<
- "' reentering run(). Error what is: '" << e.what() << "'" << LL_ENDL;
- //output possible call stacks to log file.
- LLError::LLCallStacks::print();
-
- LOG_UNHANDLED_EXCEPTION("LLThread");
- continue;
- }
+#ifdef LL_WINDOWS
+ sehHandle(); // Structured Exception Handling
+#else
+ tryRun();
+#endif
break;
} while (true);
@@ -188,6 +202,69 @@ void LLThread::threadRun()
mStatus = STOPPED;
}
+void LLThread::tryRun()
+{
+ try
+ {
+ run();
+ }
+ catch (const LLContinueError& e)
+ {
+ LL_WARNS("THREAD") << "ContinueException on thread '" << mName <<
+ "'. Error what is: '" << e.what() << "'" << LL_ENDL;
+ LLError::LLCallStacks::print();
+
+ LOG_UNHANDLED_EXCEPTION("LLThread");
+ }
+ catch (std::bad_alloc&)
+ {
+ // Todo: improve this, this is going to have a different callstack
+ // instead of showing where it crashed
+ LL_WARNS("THREAD") << "Out of memory in a thread: " << mName << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ []() {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("THREAD") << "Out of memory in a thread" << LL_ENDL;
+ });
+ }
+#ifndef LL_WINDOWS
+ catch (...)
+ {
+ // Stash any other kind of uncaught exception to be rethrown by main thread.
+ LL_WARNS("THREAD") << "Capturing and rethrowing uncaught exception in LLThread "
+ << mName << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ }
+#endif // else LL_WINDOWS
+}
+
+#ifdef LL_WINDOWS
+void LLThread::sehHandle()
+{
+ __try
+ {
+ // handle stop and continue exceptions first
+ tryRun();
+ }
+ __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
+ {
+ // convert to C++ styled exception
+ // Note: it might be better to use _se_set_translator
+ // if you want exception to inherit full callstack
+ char integer_string[512];
+ sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
+ throw std::exception(integer_string);
+ }
+}
+#endif
+
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
mPaused(false),
mName(name),
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 4194e0014d..8794ac93aa 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -68,7 +68,7 @@ public:
// Called from MAIN THREAD.
void pause();
void unpause();
- bool isPaused() { return isStopped() || mPaused; }
+ bool isPaused() const { return isStopped() || mPaused; }
// Cause the thread to wake up and check its condition
void wake();
@@ -97,6 +97,11 @@ private:
// static function passed to APR thread creation routine
void threadRun();
+ void tryRun();
+
+#ifdef LL_WINDOWS
+ void sehHandle();
+#endif
protected:
std::string mName;
diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h
index 034e3f7897..1a1d06a6fd 100644
--- a/indra/llcommon/llthreadsafequeue.h
+++ b/indra/llcommon/llthreadsafequeue.h
@@ -452,7 +452,9 @@ ElementT LLThreadSafeQueue::pop(void)
// so we can finish draining the queue.
pop_result popped = pop_(lock1, value);
if (popped == POPPED)
- return std::move(value);
+ // don't use std::move when returning local value because
+ // it prevents the compiler from optimizing with copy elision
+ return value;
// Once the queue is DONE, there will never be any more coming.
if (popped == DONE)
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index b9bd27aa17..4aae90626e 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -174,14 +174,6 @@ void LLUUID::toString(std::string& out) const
(U8)(mData[15]));
}
-// *TODO: deprecate
-void LLUUID::toString(char* out) const
-{
- std::string buffer;
- toString(buffer);
- strcpy(out, buffer.c_str()); /* Flawfinder: ignore */
-}
-
void LLUUID::toCompressedString(std::string& out) const
{
char bytes[UUID_BYTES + 1];
@@ -190,13 +182,6 @@ void LLUUID::toCompressedString(std::string& out) const
out.assign(bytes, UUID_BYTES);
}
-// *TODO: deprecate
-void LLUUID::toCompressedString(char* out) const
-{
- memcpy(out, mData, UUID_BYTES); /* Flawfinder: ignore */
- out[UUID_BYTES] = '\0';
-}
-
std::string LLUUID::getString() const
{
return asString();
diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h
index bd4edc7993..ca1cf03c4d 100644
--- a/indra/llcommon/lluuid.h
+++ b/indra/llcommon/lluuid.h
@@ -103,9 +103,7 @@ public:
friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid);
friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid);
- void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0)
void toString(std::string& out) const;
- void toCompressedString(char *out) const; // Does not allocate memory, needs 17 characters (including \0)
void toCompressedString(std::string& out) const;
std::string asString() const;
diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h
index 28e50b3d21..f1e4c2bc78 100644
--- a/indra/llcommon/stdtypes.h
+++ b/indra/llcommon/stdtypes.h
@@ -164,14 +164,14 @@ private:
FROM mValue;
public:
- narrow(FROM value): mValue(value) {}
+ constexpr narrow(FROM value): mValue(value) {}
/*---------------------- Narrowing unsigned to signed ----------------------*/
template ::value &&
std::is_signed::value,
bool>::type = true>
- inline
+ constexpr
operator TO() const
{
// The reason we skip the
@@ -189,7 +189,7 @@ public:
typename std::enable_if::value &&
std::is_signed::value),
bool>::type = true>
- inline
+ constexpr
operator TO() const
{
// two different assert()s so we can tell which condition failed
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index b63cc52bec..4adfaf54f3 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -54,14 +54,29 @@ std::string apr_strerror_helper(apr_status_t rv)
*****************************************************************************/
#define ensure_equals_(left, right) \
- ensure_equals(STRINGIZE(#left << " != " << #right), (left), (right))
+do { \
+ auto _left_val = (left); \
+ auto _right_val = (right); \
+ if (_left_val != _right_val) { \
+ std::string _msg = std::string(#left) + " != " + std::string(#right); \
+ tut::ensure_equals(_msg, _left_val, _right_val); \
+ } else { \
+ tut::ensure_equals("", _left_val, _right_val); \
+ } \
+} while(0)
#define aprchk(expr) aprchk_(#expr, (expr))
static void aprchk_(const char* call, apr_status_t rv, apr_status_t expected=APR_SUCCESS)
{
- tut::ensure_equals(STRINGIZE(call << " => " << rv << ": " << apr_strerror_helper
- (rv)),
- rv, expected);
+ if (rv != expected)
+ {
+ std::string msg = std::string(call) + " => " + std::to_string(rv) + ": " + apr_strerror_helper(rv);
+ tut::ensure_equals(msg, rv, expected);
+ }
+ else
+ {
+ tut::ensure_equals("", rv, expected);
+ }
}
/**
@@ -78,11 +93,14 @@ static std::string readfile(const std::string& pathname, const std::string& desc
std::string use_desc(desc);
if (use_desc.empty())
{
- use_desc = STRINGIZE("in " << pathname);
+ use_desc = "in " + pathname;
}
std::ifstream inf(pathname.c_str());
std::string output;
- tut::ensure(STRINGIZE("No output " << use_desc), bool(std::getline(inf, output)));
+ if (!std::getline(inf, output))
+ {
+ tut::ensure("No output " + use_desc, false);
+ }
std::string more;
while (std::getline(inf, more))
{
@@ -108,8 +126,10 @@ void waitfor(LLProcess& proc, int timeout=60)
{
yield();
}
- tut::ensure(STRINGIZE("process took longer than " << timeout << " seconds to terminate"),
- i < timeout);
+ // Pump once more after the process exits to flush any final events such as EOF.
+ yield(0);
+ std::string msg = "process took longer than " + std::to_string(timeout) + " seconds to terminate";
+ tut::ensure(msg, i < timeout);
}
void waitfor(LLProcess::handle h, const std::string& desc, int timeout=60)
@@ -119,8 +139,10 @@ void waitfor(LLProcess::handle h, const std::string& desc, int timeout=60)
{
yield();
}
- tut::ensure(STRINGIZE("process took longer than " << timeout << " seconds to terminate"),
- i < timeout);
+ // Pump once more after the process exits to flush any final events such as EOF.
+ yield(0);
+ std::string msg = "process took longer than " + std::to_string(timeout) + " seconds to terminate";
+ tut::ensure(msg, i < timeout);
}
/**
@@ -153,7 +175,8 @@ struct PythonProcessLauncher
try
{
mPy = LLProcess::create(mParams);
- tut::ensure(STRINGIZE("Couldn't launch " << mDesc << " script"), bool(mPy));
+ std::string msg = "Couldn't launch " + mDesc + " script";
+ tut::ensure(msg, bool(mPy));
}
catch (const tut::failure&)
{
@@ -214,7 +237,8 @@ struct PythonProcessLauncher
mParams.args.add(out.getName());
run();
// assuming the script wrote to that file, read it
- return readfile(out.getName(), STRINGIZE("from " << mDesc << " script"));
+ std::string desc = "from " + mDesc + " script";
+ return readfile(out.getName(), desc);
}
LLProcess::Params mParams;
@@ -1183,8 +1207,8 @@ namespace tut
{
set_test_name("ReadPipe \"eof\" event");
PythonProcessLauncher py(get_test_name(),
- "from __future__ import print_function\n"
- "print('Hello from Python!')\n");
+ "import time\n"
+ "time.sleep(1.5)\n");
py.mParams.files.add(LLProcess::FileParam()); // stdin
py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
py.launch();
diff --git a/indra/llcommon/tests/stringize_test.cpp b/indra/llcommon/tests/stringize_test.cpp
index a3ce7f8e3d..3f99041592 100644
--- a/indra/llcommon/tests/stringize_test.cpp
+++ b/indra/llcommon/tests/stringize_test.cpp
@@ -110,6 +110,17 @@ namespace tut
void stringize_object::test<3>()
{
//Tests rely on validity of wstring_to_utf8str()
+#if LL_WINDOWS // Windows wstring is a 2byte UTF16 type
+ ensure_equals(ll_convert(wstringize(c)), ll_convert(std::wstring(L"c")));
+ ensure_equals(ll_convert(wstringize(s)), ll_convert(std::wstring(L"17")));
+ ensure_equals(ll_convert(wstringize(i)), ll_convert(std::wstring(L"34")));
+ ensure_equals(ll_convert(wstringize(l)), ll_convert(std::wstring(L"68")));
+ ensure_equals(ll_convert(wstringize(f)), ll_convert(std::wstring(L"3.14159")));
+ ensure_equals(ll_convert(wstringize(d)), ll_convert(std::wstring(L"3.14159")));
+ ensure_equals(ll_convert(wstringize(abc)), ll_convert(std::wstring(L"abc def")));
+ ensure_equals(ll_convert(wstringize(abc)), ll_convert(wstringize(abc.c_str())));
+ ensure_equals(ll_convert(wstringize(def)), ll_convert(std::wstring(L"def ghi")));
+#else
ensure_equals(wstring_to_utf8str(wstringize(c)), wstring_to_utf8str(L"c"));
ensure_equals(wstring_to_utf8str(wstringize(s)), wstring_to_utf8str(L"17"));
ensure_equals(wstring_to_utf8str(wstringize(i)), wstring_to_utf8str(L"34"));
@@ -119,6 +130,7 @@ namespace tut
ensure_equals(wstring_to_utf8str(wstringize(abc)), wstring_to_utf8str(L"abc def"));
ensure_equals(wstring_to_utf8str(wstringize(abc)), wstring_to_utf8str(wstringize(abc.c_str())));
ensure_equals(wstring_to_utf8str(wstringize(def)), wstring_to_utf8str(L"def ghi"));
+#endif
// ensure_equals(wstring_to_utf8str(wstringize(llsd)), wstring_to_utf8str(L"{'abc':'abc def','d':r3.14159,'i':i34}"));
}
} // namespace tut
diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h
index 0eb1891754..ac4f415f3e 100644
--- a/indra/llcommon/threadpool.h
+++ b/indra/llcommon/threadpool.h
@@ -55,7 +55,7 @@ namespace LL
* ThreadPool listens for application shutdown messages on the "LLApp"
* LLEventPump. Call close() to shut down this ThreadPool early.
*/
- virtual void close();
+ void close();
std::string getName() const { return mName; }
size_t getWidth() const { return mThreads.size(); }
@@ -122,7 +122,7 @@ namespace LL
size_t threads=1,
size_t capacity=1024*1024,
bool auto_shutdown = true):
- ThreadPoolBase(name, threads, new queue_t(name, capacity), auto_shutdown)
+ ThreadPoolBase(name, threads, new queue_t(name, capacity, false), auto_shutdown)
{}
~ThreadPoolUsing() override {}
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index 6066e74fb5..7efaebd569 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -17,9 +17,11 @@
// std headers
// external library headers
// other Linden headers
+#include "llapp.h"
#include "llcoros.h"
#include LLCOROS_MUTEX_HEADER
#include "llerror.h"
+#include "llevents.h"
#include "llexception.h"
#include "stringize.h"
@@ -29,11 +31,38 @@ using Lock = LLCoros::LockType;
/*****************************************************************************
* WorkQueueBase
*****************************************************************************/
-LL::WorkQueueBase::WorkQueueBase(const std::string& name):
- super(makeName(name))
+LL::WorkQueueBase::WorkQueueBase(const std::string& name, bool auto_shutdown)
+ : super(makeName(name))
{
- // TODO: register for "LLApp" events so we can implicitly close() on
- // viewer shutdown.
+ if (auto_shutdown)
+ {
+ // Register for "LLApp" events so we can implicitly close() on viewer shutdown
+ std::string listener_name = "WorkQueue:" + getKey();
+ LLEventPumps::instance().obtain("LLApp").listen(
+ listener_name,
+ [this](const LLSD& stat)
+ {
+ std::string status(stat["status"]);
+ if (status != "running")
+ {
+ // Viewer is shutting down, close this queue
+ LL_DEBUGS("WorkQueue") << getKey() << " closing on app shutdown" << LL_ENDL;
+ close();
+ }
+ return false;
+ });
+
+ // Store the listener name so we can unregister in the destructor
+ mListenerName = listener_name;
+ }
+}
+
+LL::WorkQueueBase::~WorkQueueBase()
+{
+ if (!mListenerName.empty() && !LLEventPumps::wasDeleted())
+ {
+ LLEventPumps::instance().obtain("LLApp").stopListening(mListenerName);
+ }
}
void LL::WorkQueueBase::runUntilClose()
@@ -102,19 +131,103 @@ std::string LL::WorkQueueBase::makeName(const std::string& name)
return STRINGIZE("WorkQueue" << num);
}
+namespace
+{
+#if LL_WINDOWS
+
+ static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
+
+ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop)
+ {
+ if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop))
+ {
+ // Handled
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else if (code == STATUS_MSC_EXCEPTION)
+ {
+ // C++ exception, go on
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else
+ {
+ // handle it, convert to std::exception
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ void cpphandle(const LL::WorkQueueBase::Work& work)
+ {
+ // SE and C++ can not coexists, thus two handlers
+ try
+ {
+ work();
+ }
+ catch (const LLContinueError&)
+ {
+ // Any uncaught exception derived from LLContinueError will be caught
+ // here and logged. This coroutine will terminate but the rest of the
+ // viewer will carry on.
+ LOG_UNHANDLED_EXCEPTION(STRINGIZE("LLContinue in work queue"));
+ }
+ }
+
+ void sehandle(const LL::WorkQueueBase::Work& work)
+ {
+ __try
+ {
+ // handle stop and continue exceptions first
+ cpphandle(work);
+ }
+ __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
+ {
+ // convert to C++ styled exception
+ char integer_string[512];
+ sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
+ throw std::exception(integer_string);
+ }
+ }
+#endif // LL_WINDOWS
+} // anonymous namespace
+
void LL::WorkQueueBase::callWork(const Work& work)
{
LL_PROFILE_ZONE_SCOPED_CATEGORY_THREAD;
+
+#ifdef LL_WINDOWS
+ // can not use __try directly, toplevel requires unwinding, thus use of a wrapper
+ sehandle(work);
+#else // LL_WINDOWS
try
{
work();
}
- catch (...)
+ catch (LLContinueError&)
{
- // No matter what goes wrong with any individual work item, the worker
- // thread must go on! Log our own instance name with the exception.
LOG_UNHANDLED_EXCEPTION(getKey());
}
+ catch (...)
+ {
+ if (getKey() != "mainloop")
+ {
+ // Stash any other kind of uncaught exception to be rethrown by main thread.
+ LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
+ << getKey() << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ }
+ else
+ {
+ // let main loop crash
+ throw;
+ }
+ }
+#endif // else LL_WINDOWS
}
void LL::WorkQueueBase::error(const std::string& msg)
@@ -135,8 +248,8 @@ void LL::WorkQueueBase::checkCoroutine(const std::string& method)
/*****************************************************************************
* WorkQueue
*****************************************************************************/
-LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity):
- super(name),
+LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity, bool auto_shutdown):
+ super(name, auto_shutdown),
mQueue(capacity)
{
}
@@ -184,8 +297,8 @@ bool LL::WorkQueue::tryPop_(Work& work)
/*****************************************************************************
* WorkSchedule
*****************************************************************************/
-LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity):
- super(name),
+LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity, bool auto_shutdown):
+ super(name, auto_shutdown),
mQueue(capacity)
{
}
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index 9d7bbfbf7a..735ad38a26 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -51,7 +51,9 @@ namespace LL
* You may omit the WorkQueueBase name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkQueueBase(const std::string& name);
+ WorkQueueBase(const std::string& name, bool auto_shutdown);
+
+ virtual ~WorkQueueBase();
/**
* Since the point of WorkQueue is to pass work to some other worker
@@ -197,6 +199,9 @@ namespace LL
private:
virtual Work pop_() = 0;
virtual bool tryPop_(Work&) = 0;
+
+ // Name used for the LLApp event listener (empty if not registered)
+ std::string mListenerName;
};
/*****************************************************************************
@@ -212,7 +217,7 @@ namespace LL
* You may omit the WorkQueue name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkQueue(const std::string& name = std::string(), size_t capacity=1024);
+ WorkQueue(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
/**
* Since the point of WorkQueue is to pass work to some other worker
@@ -282,7 +287,7 @@ namespace LL
* You may omit the WorkSchedule name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkSchedule(const std::string& name = std::string(), size_t capacity=1024);
+ WorkSchedule(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
/**
* Since the point of WorkSchedule is to pass work to some other worker
diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp
index 6186e7a308..081a4d9bac 100644
--- a/indra/llcorehttp/_httpoprequest.cpp
+++ b/indra/llcorehttp/_httpoprequest.cpp
@@ -538,6 +538,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
long sslHostV(0L);
long dnsCacheTimeout(-1L);
long nobody(0L);
+ curl_off_t lastModified(0L);
if (mReqOptions)
{
@@ -546,6 +547,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
sslHostV = mReqOptions->getSSLVerifyHost() ? 2L : 0L;
dnsCacheTimeout = mReqOptions->getDNSCacheTimeout();
nobody = mReqOptions->getHeadersOnly() ? 1L : 0L;
+ lastModified = (curl_off_t)mReqOptions->getLastModified();
}
check_curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, follow_redirect);
@@ -554,6 +556,17 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)
check_curl_easy_setopt(mCurlHandle, CURLOPT_NOBODY, nobody);
+ if (lastModified)
+ {
+ check_curl_easy_setopt(mCurlHandle, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
+#if (LIBCURL_VERSION_NUM >= 0x073B00)
+ // requires curl 7.59.0
+ check_curl_easy_setopt(mCurlHandle, CURLOPT_TIMEVALUE_LARGE, lastModified);
+#else
+ check_curl_easy_setopt(mCurlHandle, CURLOPT_TIMEVALUE, (long)lastModified);
+#endif
+ }
+
// The Linksys WRT54G V5 router has an issue with frequent
// DNS lookups from LAN machines. If they happen too often,
// like for every HTTP request, the router gets annoyed after
diff --git a/indra/llcorehttp/examples/http_texture_load.cpp b/indra/llcorehttp/examples/http_texture_load.cpp
index 72e0c29a24..986e675d00 100644
--- a/indra/llcorehttp/examples/http_texture_load.cpp
+++ b/indra/llcorehttp/examples/http_texture_load.cpp
@@ -52,8 +52,6 @@
void init_curl();
void term_curl();
-void ssl_thread_id_callback(CRYPTO_THREADID*);
-void ssl_locking_callback(int mode, int type, const char * file, int line);
void usage(std::ostream & out);
// Default command line settings
@@ -606,63 +604,15 @@ void WorkingSet::loadAssetUuids(FILE * in)
}
-int ssl_mutex_count(0);
-LLCoreInt::HttpMutex ** ssl_mutex_list = NULL;
-
void init_curl()
{
curl_global_init(CURL_GLOBAL_ALL);
-
- ssl_mutex_count = CRYPTO_num_locks();
- if (ssl_mutex_count > 0)
- {
- ssl_mutex_list = new LLCoreInt::HttpMutex * [ssl_mutex_count];
-
- for (int i(0); i < ssl_mutex_count; ++i)
- {
- ssl_mutex_list[i] = new LLCoreInt::HttpMutex;
- }
-
- CRYPTO_set_locking_callback(ssl_locking_callback);
- CRYPTO_THREADID_set_callback(ssl_thread_id_callback);
- }
}
void term_curl()
{
- CRYPTO_set_locking_callback(NULL);
- for (int i(0); i < ssl_mutex_count; ++i)
- {
- delete ssl_mutex_list[i];
- }
- delete [] ssl_mutex_list;
-}
-
-
-void ssl_thread_id_callback(CRYPTO_THREADID* pthreadid)
-{
-#if defined(WIN32)
- CRYPTO_THREADID_set_pointer(pthreadid, GetCurrentThread());
-#else
- CRYPTO_THREADID_set_pointer(pthreadid, pthread_self());
-#endif
-}
-
-
-void ssl_locking_callback(int mode, int type, const char * /* file */, int /* line */)
-{
- if (type >= 0 && type < ssl_mutex_count)
- {
- if (mode & CRYPTO_LOCK)
- {
- ssl_mutex_list[type]->lock();
- }
- else
- {
- ssl_mutex_list[type]->unlock();
- }
- }
+ curl_global_cleanup();
}
diff --git a/indra/llcorehttp/httpoptions.cpp b/indra/llcorehttp/httpoptions.cpp
index d85f6039b1..5abd28e211 100644
--- a/indra/llcorehttp/httpoptions.cpp
+++ b/indra/llcorehttp/httpoptions.cpp
@@ -47,6 +47,7 @@ HttpOptions::HttpOptions() :
mVerifyPeer(sDefaultVerifyPeer),
mVerifyHost(false),
mDNSCacheTimeout(-1L),
+ mLastModified(0),
mNoBody(false)
{}
@@ -129,6 +130,11 @@ void HttpOptions::setHeadersOnly(bool nobody)
}
}
+void HttpOptions::setLastModified(time_t lastModified)
+{
+ mLastModified = lastModified;
+}
+
void HttpOptions::setDefaultSSLVerifyPeer(bool verify)
{
sDefaultVerifyPeer = verify;
diff --git a/indra/llcorehttp/httpoptions.h b/indra/llcorehttp/httpoptions.h
index 56a28013cb..fdb277c66e 100644
--- a/indra/llcorehttp/httpoptions.h
+++ b/indra/llcorehttp/httpoptions.h
@@ -178,6 +178,13 @@ public:
return mNoBody;
}
+ // Default: 0
+ void setLastModified(time_t lastModified);
+ time_t getLastModified() const
+ {
+ return mLastModified;
+ }
+
/// Sets default behavior for verifying that the name in the
/// security certificate matches the name of the host contacted.
/// Defaults false if not set, but should be set according to
@@ -199,6 +206,7 @@ protected:
bool mVerifyHost;
int mDNSCacheTimeout;
bool mNoBody;
+ time_t mLastModified;
static bool sDefaultVerifyPeer;
}; // end class HttpOptions
diff --git a/indra/llcorehttp/llhttpconstants.cpp b/indra/llcorehttp/llhttpconstants.cpp
index 40d6c7506c..7a671543d9 100755
--- a/indra/llcorehttp/llhttpconstants.cpp
+++ b/indra/llcorehttp/llhttpconstants.cpp
@@ -100,6 +100,7 @@ const std::string HTTP_IN_HEADER_LOCATION("location");
const std::string HTTP_IN_HEADER_RETRY_AFTER("retry-after");
const std::string HTTP_IN_HEADER_SET_COOKIE("set-cookie");
const std::string HTTP_IN_HEADER_USER_AGENT("user-agent");
+const std::string HTTP_IN_HEADER_X_CONTENT_TYPE_OPTIONS("x-content-type-options");
const std::string HTTP_IN_HEADER_X_FORWARDED_FOR("x-forwarded-for");
const std::string HTTP_CONTENT_LLSD_XML("application/llsd+xml");
@@ -122,6 +123,7 @@ const std::string HTTP_CONTENT_IMAGE_BMP("image/bmp");
const std::string HTTP_NO_CACHE("no-cache");
const std::string HTTP_NO_CACHE_CONTROL("no-cache, max-age=0");
+const std::string HTTP_NOSNIFF("nosniff");
const std::string HTTP_VERB_INVALID("(invalid)");
const std::string HTTP_VERB_HEAD("HEAD");
diff --git a/indra/llcorehttp/llhttpconstants.h b/indra/llcorehttp/llhttpconstants.h
index 583f9fbcb7..71c1dfa173 100755
--- a/indra/llcorehttp/llhttpconstants.h
+++ b/indra/llcorehttp/llhttpconstants.h
@@ -190,6 +190,7 @@ extern const std::string HTTP_IN_HEADER_LOCATION;
extern const std::string HTTP_IN_HEADER_RETRY_AFTER;
extern const std::string HTTP_IN_HEADER_SET_COOKIE;
extern const std::string HTTP_IN_HEADER_USER_AGENT;
+extern const std::string HTTP_IN_HEADER_X_CONTENT_TYPE_OPTIONS;
extern const std::string HTTP_IN_HEADER_X_FORWARDED_FOR;
//// HTTP Content Types ////
@@ -215,5 +216,6 @@ extern const std::string HTTP_CONTENT_IMAGE_BMP;
//// HTTP Cache Settings ////
extern const std::string HTTP_NO_CACHE;
extern const std::string HTTP_NO_CACHE_CONTROL;
+extern const std::string HTTP_NOSNIFF;
#endif
diff --git a/indra/llcorehttp/tests/llcorehttp_test.cpp b/indra/llcorehttp/tests/llcorehttp_test.cpp
index c0cc2c8030..c7c50e6166 100755
--- a/indra/llcorehttp/tests/llcorehttp_test.cpp
+++ b/indra/llcorehttp/tests/llcorehttp_test.cpp
@@ -41,11 +41,7 @@
#include "test_httpstatus.hpp"
#include "test_refcounted.hpp"
#include "test_httpoperation.hpp"
-// As of 2019-06-28, test_httprequest.hpp consistently crashes on Mac Release
-// builds for reasons not yet diagnosed.
-#if ! (LL_DARWIN && LL_RELEASE)
#include "test_httprequest.hpp"
-#endif
#include "test_httpheaders.hpp"
#include "test_httprequestqueue.hpp"
#include "_httpservice.h"
@@ -53,9 +49,6 @@
#include "llproxy.h"
#include "llcleanup.h"
-void ssl_thread_id_callback(CRYPTO_THREADID*);
-void ssl_locking_callback(int mode, int type, const char * file, int line);
-
#if 0 // lltut provides main and runner
namespace tut
@@ -80,27 +73,10 @@ int main()
#endif // 0
-int ssl_mutex_count(0);
-LLCoreInt::HttpMutex ** ssl_mutex_list = NULL;
-
void init_curl()
{
curl_global_init(CURL_GLOBAL_ALL);
- ssl_mutex_count = CRYPTO_num_locks();
- if (ssl_mutex_count > 0)
- {
- ssl_mutex_list = new LLCoreInt::HttpMutex * [ssl_mutex_count];
-
- for (int i(0); i < ssl_mutex_count; ++i)
- {
- ssl_mutex_list[i] = new LLCoreInt::HttpMutex;
- }
-
- CRYPTO_set_locking_callback(ssl_locking_callback);
- CRYPTO_THREADID_set_callback(ssl_thread_id_callback);
- }
-
LLProxy::getInstance();
}
@@ -108,39 +84,6 @@ void init_curl()
void term_curl()
{
SUBSYSTEM_CLEANUP(LLProxy);
-
- CRYPTO_set_locking_callback(NULL);
- for (int i(0); i < ssl_mutex_count; ++i)
- {
- delete ssl_mutex_list[i];
- }
- delete [] ssl_mutex_list;
-}
-
-
-void ssl_thread_id_callback(CRYPTO_THREADID* pthreadid)
-{
-#if defined(WIN32)
- CRYPTO_THREADID_set_pointer(pthreadid, GetCurrentThread());
-#else
- CRYPTO_THREADID_set_pointer(pthreadid, pthread_self());
-#endif
-}
-
-
-void ssl_locking_callback(int mode, int type, const char * /* file */, int /* line */)
-{
- if (type >= 0 && type < ssl_mutex_count)
- {
- if (mode & CRYPTO_LOCK)
- {
- ssl_mutex_list[type]->lock();
- }
- else
- {
- ssl_mutex_list[type]->unlock();
- }
- }
}
diff --git a/indra/llcorehttp/tests/test_httprequest.hpp b/indra/llcorehttp/tests/test_httprequest.hpp
index aed906bb8f..77ed8df066 100644
--- a/indra/llcorehttp/tests/test_httprequest.hpp
+++ b/indra/llcorehttp/tests/test_httprequest.hpp
@@ -454,6 +454,10 @@ void HttpRequestTestObjectType::test<4>()
template <> template <>
void HttpRequestTestObjectType::test<5>()
{
+#ifndef LL_WINDOWS
+ skip("Skip due to issues with testing pthread cancellation");
+#endif
+
ScopedCurlInit ready;
set_test_name("HttpRequest Spin (soft) + NoOp + hard termination");
@@ -517,6 +521,9 @@ void HttpRequestTestObjectType::test<5>()
template <> template <>
void HttpRequestTestObjectType::test<6>()
{
+#ifndef LL_WINDOWS
+ skip("Skip due to issues with testing pthread cancellation");
+#endif
ScopedCurlInit ready;
set_test_name("HttpRequest Spin + NoOp + hard termination");
@@ -2779,7 +2786,7 @@ void HttpRequestTestObjectType::test<22>()
for (int i(0); i < test_count; ++i)
{
char buffer[128];
- sprintf(buffer, "/bug2295/%d/", i);
+ snprintf(buffer, sizeof(buffer), "/bug2295/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
url_base + buffer,
0,
@@ -2810,7 +2817,7 @@ void HttpRequestTestObjectType::test<22>()
for (int i(0); i < test2_count; ++i)
{
char buffer[128];
- sprintf(buffer, "/bug2295/00000012/%d/", i);
+ snprintf(buffer, sizeof(buffer), "/bug2295/00000012/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
url_base + buffer,
0,
@@ -2841,7 +2848,7 @@ void HttpRequestTestObjectType::test<22>()
for (int i(0); i < test3_count; ++i)
{
char buffer[128];
- sprintf(buffer, "/bug2295/inv_cont_range/%d/", i);
+ snprintf(buffer, sizeof(buffer), "/bug2295/inv_cont_range/%d/", i);
HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
url_base + buffer,
0,
diff --git a/indra/llcorehttp/tests/test_refcounted.hpp b/indra/llcorehttp/tests/test_refcounted.hpp
index c0c8e78413..eb23a25545 100644
--- a/indra/llcorehttp/tests/test_refcounted.hpp
+++ b/indra/llcorehttp/tests/test_refcounted.hpp
@@ -28,8 +28,6 @@
#include "_refcounted.h"
-// disable all of this because it's hanging win64 builds?
-#if ! (LL_WINDOWS && ADDRESS_SIZE == 64)
using namespace LLCoreInt;
namespace tut
@@ -122,5 +120,4 @@ namespace tut
ensure(rc->getRefCount() == RefCounted::NOT_REF_COUNTED);
}
}
-#endif // disabling on Win64
#endif // TEST_LLCOREINT_REF_COUNTED_H_
diff --git a/indra/llcrashlogger/llcrashlock.cpp b/indra/llcrashlogger/llcrashlock.cpp
index ecd197b2c1..bc34f6798f 100644
--- a/indra/llcrashlogger/llcrashlock.cpp
+++ b/indra/llcrashlogger/llcrashlock.cpp
@@ -189,7 +189,7 @@ LLSD LLCrashLock::getProcessList()
bool LLCrashLock::fileExists(std::string filename)
{
#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- boost::filesystem::path file_path(utf8str_to_utf16str(filename));
+ boost::filesystem::path file_path(ll_convert(filename));
#else
boost::filesystem::path file_path(filename);
#endif
@@ -199,7 +199,7 @@ bool LLCrashLock::fileExists(std::string filename)
void LLCrashLock::cleanupProcess(std::string proc_dir)
{
#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- boost::filesystem::path dir_path(utf8str_to_utf16str(proc_dir));
+ boost::filesystem::path dir_path(ll_convert(proc_dir));
#else
boost::filesystem::path dir_path(proc_dir);
#endif
diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp
index b1b698375a..d5c585b45e 100644
--- a/indra/llcrashlogger/llcrashlogger.cpp
+++ b/indra/llcrashlogger/llcrashlogger.cpp
@@ -576,10 +576,6 @@ bool LLCrashLogger::init()
std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log.old");
std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "crashreport.log");
-#if LL_WINDOWS
- LLAPRFile::remove(old_log_file);
-#endif
-
LLFile::rename(log_file.c_str(), old_log_file.c_str());
// Set the log file to crashreport.log
diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp
index 99d4850610..ea33a3bb90 100644
--- a/indra/llfilesystem/lldir.cpp
+++ b/indra/llfilesystem/lldir.cpp
@@ -103,16 +103,17 @@ std::vector LLDir::getFilesInDir(const std::string &dirname)
//Returns a vector of fullpath filenames.
#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- boost::filesystem::path p(utf8str_to_utf16str(dirname));
+ boost::filesystem::path p(ll_convert(dirname));
#else
boost::filesystem::path p(dirname);
#endif
std::vector v;
- if (exists(p))
+ boost::system::error_code ec;
+ if (exists(p, ec) && !ec.failed())
{
- if (is_directory(p))
+ if (is_directory(p, ec) && !ec.failed())
{
boost::filesystem::directory_iterator end_iter;
for (boost::filesystem::directory_iterator dir_itr(p);
@@ -196,7 +197,7 @@ U32 LLDir::deleteDirAndContents(const std::string& dir_name)
try
{
#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name));
+ boost::filesystem::path dir_path(ll_convert(dir_name));
#else
boost::filesystem::path dir_path(dir_name);
#endif
diff --git a/indra/llfilesystem/lldir_mac.cpp b/indra/llfilesystem/lldir_mac.cpp
index b9be75c528..2db1b6ec5d 100644
--- a/indra/llfilesystem/lldir_mac.cpp
+++ b/indra/llfilesystem/lldir_mac.cpp
@@ -149,7 +149,7 @@ LLDir_Mac::LLDir_Mac()
mWorkingDir = getCurPath();
- mLLPluginDir = mAppRODataDir + mDirDelimiter + "llplugin";
+ mLLPluginDir = mAppRODataDir + mDirDelimiter + "SLPlugin.app" + mDirDelimiter + "Contents" + mDirDelimiter + "Frameworks";
}
}
diff --git a/indra/llfilesystem/lldir_utils_objc.mm b/indra/llfilesystem/lldir_utils_objc.mm
index 01fe9e1f2c..35513d5647 100644
--- a/indra/llfilesystem/lldir_utils_objc.mm
+++ b/indra/llfilesystem/lldir_utils_objc.mm
@@ -1,28 +1,28 @@
-/**
+/**
* @file lldir_utils_objc.mm
* @brief Cocoa implementation of directory utilities for macOS
*
* $LicenseInfo:firstyear=2020&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2020, 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$
- */
+ */
#if LL_DARWIN
//WARNING: This file CANNOT use standard linden includes due to conflicts between definitions of BOOL
@@ -39,18 +39,18 @@ std::string getSystemTempFolder()
tempDir = @"/tmp";
result = std::string([tempDir UTF8String]);
}
-
+
return result;
}
-//findSystemDirectory scoped exclusively to this file.
+//findSystemDirectory scoped exclusively to this file.
std::string findSystemDirectory(NSSearchPathDirectory searchPathDirectory,
NSSearchPathDomainMask domainMask)
{
std::string result;
@autoreleasepool {
NSString *path = nil;
-
+
// Search for the path
NSArray* paths = NSSearchPathForDirectoriesInDomains(searchPathDirectory,
domainMask,
@@ -60,10 +60,10 @@ std::string findSystemDirectory(NSSearchPathDirectory searchPathDirectory,
path = [paths objectAtIndex:0];
//HACK: Always attempt to create directory, ignore errors.
NSError *error = nil;
-
+
[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:&error];
-
-
+
+
result = std::string([path UTF8String]);
}
}
@@ -88,7 +88,7 @@ std::string getSystemResourceFolder()
NSString *bundlePath = [[NSBundle mainBundle] resourcePath];
result = std::string([bundlePath UTF8String]);
}
-
+
return result;
}
@@ -102,7 +102,7 @@ std::string getSystemApplicationSupportFolder()
{
return findSystemDirectory (NSApplicationSupportDirectory,
NSUserDomainMask);
-
+
}
#endif // LL_DARWIN
diff --git a/indra/llfilesystem/lldir_win32.cpp b/indra/llfilesystem/lldir_win32.cpp
index a607c70b44..58c080c982 100644
--- a/indra/llfilesystem/lldir_win32.cpp
+++ b/indra/llfilesystem/lldir_win32.cpp
@@ -172,7 +172,7 @@ LLDir_Win32::LLDir_Win32()
{
w_str[wcslen(w_str)-1] = '\0'; /* Flawfinder: ignore */ // remove trailing slash
}
- mTempDir = utf16str_to_utf8str(llutf16string(w_str));
+ mTempDir = ll_convert(std::wstring(w_str));
if (mOSUserDir.empty())
{
@@ -225,14 +225,14 @@ LLDir_Win32::LLDir_Win32()
// Set working directory, for LLDir::getWorkingDir()
GetCurrentDirectory(MAX_PATH, w_str);
- mWorkingDir = utf16str_to_utf8str(llutf16string(w_str));
+ mWorkingDir = ll_convert(std::wstring(w_str));
// Set the executable directory
S32 size = GetModuleFileName(NULL, w_str, MAX_PATH);
if (size)
{
w_str[size] = '\0';
- mExecutablePathAndName = utf16str_to_utf8str(llutf16string(w_str));
+ mExecutablePathAndName = ll_convert(std::wstring(w_str));
auto path_end = mExecutablePathAndName.find_last_of('\\');
if (path_end != std::string::npos)
{
@@ -347,8 +347,8 @@ U32 LLDir_Win32::countFilesInDir(const std::string &dirname, const std::string &
WIN32_FIND_DATA FileData;
- llutf16string pathname = utf8str_to_utf16str(dirname);
- pathname += utf8str_to_utf16str(mask);
+ std::wstring pathname = ll_convert(dirname);
+ pathname += ll_convert(mask);
if ((count_search_h = FindFirstFile(pathname.c_str(), &FileData)) != INVALID_HANDLE_VALUE)
{
@@ -370,7 +370,7 @@ std::string LLDir_Win32::getCurPath()
WCHAR w_str[MAX_PATH];
GetCurrentDirectory(MAX_PATH, w_str);
- return utf16str_to_utf8str(llutf16string(w_str));
+ return ll_convert(std::wstring(w_str));
}
diff --git a/indra/llfilesystem/lldir_win32.h b/indra/llfilesystem/lldir_win32.h
index ab2726f1a0..21a3f1213b 100644
--- a/indra/llfilesystem/lldir_win32.h
+++ b/indra/llfilesystem/lldir_win32.h
@@ -51,7 +51,7 @@ public:
private:
void* mDirSearch_h{ nullptr };
- llutf16string mCurrentDir;
+ std::wstring mCurrentDir;
};
#endif // LL_LLDIR_WIN32_H
diff --git a/indra/llfilesystem/lldirguard.h b/indra/llfilesystem/lldirguard.h
index fcb179bbc8..c6ce13efb4 100644
--- a/indra/llfilesystem/lldirguard.h
+++ b/indra/llfilesystem/lldirguard.h
@@ -31,6 +31,9 @@
#include "llerror.h"
#if LL_WINDOWS
+
+#include "llwin32headers.h"
+
class LLDirectoryGuard
{
public:
@@ -46,8 +49,8 @@ public:
(wcsncmp(mOrigDir,mFinalDir,mOrigDirLen)!=0))
{
// Dir has changed
- std::string mOrigDirUtf8 = utf16str_to_utf8str(llutf16string(mOrigDir));
- std::string mFinalDirUtf8 = utf16str_to_utf8str(llutf16string(mFinalDir));
+ std::string mOrigDirUtf8 = ll_convert(std::wstring(mOrigDir));
+ std::string mFinalDirUtf8 = ll_convert(std::wstring(mFinalDir));
LL_INFOS() << "Resetting working dir from " << mFinalDirUtf8 << " to " << mOrigDirUtf8 << LL_ENDL;
SetCurrentDirectory(mOrigDir);
}
diff --git a/indra/llfilesystem/lldiriterator.cpp b/indra/llfilesystem/lldiriterator.cpp
index 61f768c512..e8c37389d2 100644
--- a/indra/llfilesystem/lldiriterator.cpp
+++ b/indra/llfilesystem/lldiriterator.cpp
@@ -52,7 +52,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask)
: mIsValid(false)
{
#ifdef LL_WINDOWS // or BOOST_WINDOWS_API
- fs::path dir_path(utf8str_to_utf16str(dirname));
+ fs::path dir_path(ll_convert(dirname));
#else
fs::path dir_path(dirname);
#endif
diff --git a/indra/llfilesystem/lldiskcache.cpp b/indra/llfilesystem/lldiskcache.cpp
index 49904911a9..e971e1885a 100644
--- a/indra/llfilesystem/lldiskcache.cpp
+++ b/indra/llfilesystem/lldiskcache.cpp
@@ -103,7 +103,7 @@ void LLDiskCache::purge()
std::vector file_info;
#if LL_WINDOWS
- std::wstring cache_path(utf8str_to_utf16str(sCacheDir));
+ std::wstring cache_path(ll_convert(sCacheDir));
#else
std::string cache_path(sCacheDir);
#endif
@@ -226,7 +226,7 @@ void LLDiskCache::clearCache()
*/
boost::system::error_code ec;
#if LL_WINDOWS
- std::wstring cache_path(utf8str_to_utf16str(sCacheDir));
+ std::wstring cache_path(ll_convert(sCacheDir));
#else
std::string cache_path(sCacheDir);
#endif
@@ -259,7 +259,7 @@ void LLDiskCache::removeOldVFSFiles()
boost::system::error_code ec;
#if LL_WINDOWS
- std::wstring cache_path(utf8str_to_utf16str(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "")));
+ std::wstring cache_path(ll_convert(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "")));
#else
std::string cache_path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""));
#endif
@@ -300,7 +300,7 @@ uintmax_t LLDiskCache::dirFileSize(const std::string& dir)
*/
boost::system::error_code ec;
#if LL_WINDOWS
- std::wstring dir_path(utf8str_to_utf16str(dir));
+ std::wstring dir_path(ll_convert(dir));
#else
std::string dir_path(dir);
#endif
diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp
index c8ce9531c2..541266af4f 100644
--- a/indra/llfilesystem/llfilesystem.cpp
+++ b/indra/llfilesystem/llfilesystem.cpp
@@ -103,9 +103,6 @@ bool LLFileSystem::renameFile(const LLUUID& old_file_id, const LLAssetType::ETyp
const std::string old_filename = LLDiskCache::metaDataToFilepath(old_file_id, old_file_type);
const std::string new_filename = LLDiskCache::metaDataToFilepath(new_file_id, new_file_type);
- // Rename needs the new file to not exist.
- LLFileSystem::removeFile(new_file_id, new_file_type, ENOENT);
-
if (LLFile::rename(old_filename, new_filename) != 0)
{
// We would like to return false here indicating the operation
@@ -316,7 +313,7 @@ void LLFileSystem::updateFileAccessTime(const std::string& file_path)
boost::system::error_code ec;
#if LL_WINDOWS
// file last write time
- const std::time_t last_write_time = boost::filesystem::last_write_time(utf8str_to_utf16str(file_path), ec);
+ const std::time_t last_write_time = boost::filesystem::last_write_time(ll_convert(file_path), ec);
if (ec.failed())
{
LL_WARNS() << "Failed to read last write time for cache file " << file_path << ": " << ec.message() << LL_ENDL;
@@ -330,7 +327,7 @@ void LLFileSystem::updateFileAccessTime(const std::string& file_path)
// before the last one
if (delta_time > time_threshold)
{
- boost::filesystem::last_write_time(utf8str_to_utf16str(file_path), cur_time, ec);
+ boost::filesystem::last_write_time(ll_convert(file_path), cur_time, ec);
}
#else
// file last write time
diff --git a/indra/llfilesystem/tests/lldir_test.cpp b/indra/llfilesystem/tests/lldir_test.cpp
index 6e191ad096..d7d57fa86f 100644
--- a/indra/llfilesystem/tests/lldir_test.cpp
+++ b/indra/llfilesystem/tests/lldir_test.cpp
@@ -435,7 +435,7 @@ namespace tut
for (counter=0, foundUnused=false; !foundUnused; counter++ )
{
char counterStr[3];
- sprintf(counterStr, "%02d", counter);
+ snprintf(counterStr, sizeof(counterStr), "%02d", counter);
uniqueDir = dirbase + counterStr;
foundUnused = ! ( LLFile::isdir(uniqueDir) || LLFile::isfile(uniqueDir) );
}
diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp
index 2a328675c2..c8f99380ea 100644
--- a/indra/llimage/llimagebmp.cpp
+++ b/indra/llimage/llimagebmp.cpp
@@ -558,6 +558,12 @@ bool LLImageBMP::encode(const LLImageRaw* raw_image, F32 encode_time)
LL_INFOS() << "Dropping alpha information during BMP encoding" << LL_ENDL;
}
+ if (raw_image->isBufferInvalid())
+ {
+ setLastError("Invalid input, no buffer");
+ return false;
+ }
+
setSize(raw_image->getWidth(), raw_image->getHeight(), dst_components);
U8 magic[14];
diff --git a/indra/llimage/llimagedimensionsinfo.cpp b/indra/llimage/llimagedimensionsinfo.cpp
index d4efbcfad2..c896d60c85 100644
--- a/indra/llimage/llimagedimensionsinfo.cpp
+++ b/indra/llimage/llimagedimensionsinfo.cpp
@@ -75,7 +75,7 @@ bool LLImageDimensionsInfo::load(const std::string& src_filename,U32 codec)
bool LLImageDimensionsInfo::getImageDimensionsBmp()
{
// Make sure the file is long enough.
- const S32 DATA_LEN = 26; // BMP header (14) + DIB header size (4) + width (4) + height (4)
+ constexpr S32 DATA_LEN = 26; // BMP header (14) + DIB header size (4) + width (4) + height (4)
if (!checkFileLength(DATA_LEN))
{
LL_WARNS() << "Premature end of file" << LL_ENDL;
@@ -105,7 +105,7 @@ bool LLImageDimensionsInfo::getImageDimensionsBmp()
bool LLImageDimensionsInfo::getImageDimensionsTga()
{
- const S32 TGA_FILE_HEADER_SIZE = 12;
+ constexpr S32 TGA_FILE_HEADER_SIZE = 12;
// Make sure the file is long enough.
if (!checkFileLength(TGA_FILE_HEADER_SIZE + 1 /* width */ + 1 /* height */))
@@ -124,7 +124,7 @@ bool LLImageDimensionsInfo::getImageDimensionsTga()
bool LLImageDimensionsInfo::getImageDimensionsPng()
{
- const S32 PNG_MAGIC_SIZE = 8;
+ constexpr S32 PNG_MAGIC_SIZE = 8;
// Make sure the file is long enough.
if (!checkFileLength(PNG_MAGIC_SIZE + 8 + sizeof(S32) * 2 /* width, height */))
@@ -134,7 +134,7 @@ bool LLImageDimensionsInfo::getImageDimensionsPng()
}
// Read PNG signature.
- const U8 png_magic[PNG_MAGIC_SIZE] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
+ constexpr U8 png_magic[PNG_MAGIC_SIZE] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
U8 signature[PNG_MAGIC_SIZE];
mInfile.read((void*)signature, PNG_MAGIC_SIZE);
@@ -166,34 +166,36 @@ bool LLImageDimensionsInfo::getImageDimensionsJpeg()
{
sJpegErrorEncountered = false;
clean();
- FILE *fp = LLFile::fopen(mSrcFilename, "rb");
- if (fp == NULL)
+ FILE* fp = LLFile::fopen(mSrcFilename, "rb");
+ if (!fp)
{
setLastError("Unable to open file for reading", mSrcFilename);
return false;
}
/* Make sure this is a JPEG file. */
- const size_t JPEG_MAGIC_SIZE = 2;
- const U8 jpeg_magic[JPEG_MAGIC_SIZE] = {0xFF, 0xD8};
+ constexpr size_t JPEG_MAGIC_SIZE = 2;
+ constexpr U8 jpeg_magic[JPEG_MAGIC_SIZE] = {0xFF, 0xD8};
U8 signature[JPEG_MAGIC_SIZE];
if (fread(signature, sizeof(signature), 1, fp) != 1)
{
LL_WARNS() << "Premature end of file" << LL_ENDL;
+ fclose(fp);
return false;
}
if (memcmp(signature, jpeg_magic, JPEG_MAGIC_SIZE) != 0)
{
LL_WARNS() << "Not a JPEG" << LL_ENDL;
mWarning = "texture_load_format_error";
+ fclose(fp);
return false;
}
fseek(fp, 0, SEEK_SET); // go back to start of the file
/* Init jpeg */
jpeg_error_mgr jerr;
- jpeg_decompress_struct cinfo;
+ jpeg_decompress_struct cinfo{};
cinfo.err = jpeg_std_error(&jerr);
// Call our function instead of exit() if Libjpeg encounters an error.
// This is done to avoid crash in this case (STORM-472).
diff --git a/indra/llimage/llimagedimensionsinfo.h b/indra/llimage/llimagedimensionsinfo.h
index 681d66ae4e..4870f2e815 100644
--- a/indra/llimage/llimagedimensionsinfo.h
+++ b/indra/llimage/llimagedimensionsinfo.h
@@ -38,7 +38,7 @@ class LLImageDimensionsInfo
{
public:
LLImageDimensionsInfo():
- mData(NULL)
+ mData(nullptr)
,mHeight(0)
,mWidth(0)
{}
@@ -67,7 +67,7 @@ protected:
{
mInfile.close();
delete[] mData;
- mData = NULL;
+ mData = nullptr;
mWidth = 0;
mHeight = 0;
}
diff --git a/indra/llimage/llimagedxt.cpp b/indra/llimage/llimagedxt.cpp
index 6b960f9077..c3fd0c5aa8 100644
--- a/indra/llimage/llimagedxt.cpp
+++ b/indra/llimage/llimagedxt.cpp
@@ -329,6 +329,12 @@ bool LLImageDXT::encodeDXT(const LLImageRaw* raw_image, F32 time, bool explicit_
{
llassert_always(raw_image);
+ if (raw_image->isBufferInvalid())
+ {
+ setLastError("Invalid input, no buffer");
+ return false;
+ }
+
S32 ncomponents = raw_image->getComponents();
EFileFormat format;
switch (ncomponents)
diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index aa161709a1..5a941dc958 100644
--- a/indra/llimage/llimagej2c.cpp
+++ b/indra/llimage/llimagej2c.cpp
@@ -281,10 +281,11 @@ S32 LLImageJ2C::calcDataSizeJ2C(S32 w, S32 h, S32 comp, S32 discard_level, F32 r
S32 height = (h > 0) ? h : 2048;
S32 max_dimension = llmax(width, height); // Find largest dimension
S32 block_area = MAX_BLOCK_SIZE * MAX_BLOCK_SIZE; // Calculated initial block area from established max block size (currently 64)
- block_area *= llmax((max_dimension / MAX_BLOCK_SIZE / max_components), 1); // Adjust initial block area by ratio of largest dimension to block size per component
- S32 totalbytes = (S32) (block_area * max_components * precision); // First block layer computed before loop without compression rate
- S32 block_layers = 1; // Start at layer 1 since first block layer is computed outside loop
- while (block_layers < 6) // Walk five layers for the five discards in JPEG2000
+ 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
diff --git a/indra/llimage/llimagejpeg.cpp b/indra/llimage/llimagejpeg.cpp
index 0e7ec365d4..ab6c593fc2 100644
--- a/indra/llimage/llimagejpeg.cpp
+++ b/indra/llimage/llimagejpeg.cpp
@@ -31,7 +31,9 @@
#include "llerror.h"
#include "llexception.h"
+#if !LL_ARM64
jmp_buf LLImageJPEG::sSetjmpBuffer ;
+#endif
LLImageJPEG::LLImageJPEG(S32 quality)
: LLImageFormatted(IMG_CODEC_JPEG),
mOutputBuffer( NULL ),
@@ -78,12 +80,15 @@ bool LLImageJPEG::updateData()
//
//try/catch will crash on Mac and Linux if LLImageJPEG::errorExit throws an error
//so as instead, we use setjmp/longjmp to avoid this crash, which is the best we can get. --bao
+ //except in the case of AARCH64/ARM64 where setjmp will crash
//
+#if !LL_ARM64
if(setjmp(sSetjmpBuffer))
{
jpeg_destroy_decompress(&cinfo);
return false;
}
+#endif
try
{
// Now we can initialize the JPEG decompression object.
@@ -223,11 +228,13 @@ bool LLImageJPEG::decode(LLImageRaw* raw_image, F32 decode_time)
//try/catch will crash on Mac and Linux if LLImageJPEG::errorExit throws an error
//so as instead, we use setjmp/longjmp to avoid this crash, which is the best we can get. --bao
//
+#if !LL_ARM64
if(setjmp(sSetjmpBuffer))
{
jpeg_destroy_decompress(&cinfo);
return true; // done
}
+#endif
try
{
// Now we can initialize the JPEG decompression object.
@@ -431,9 +438,10 @@ void LLImageJPEG::errorExit( j_common_ptr cinfo )
// Let the memory manager delete any temp files
jpeg_destroy(cinfo);
-
+#if !LL_ARM64
// Return control to the setjmp point
longjmp(sSetjmpBuffer, 1) ;
+#endif
}
// Decide whether to emit a trace or warning message.
@@ -491,6 +499,12 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
resetLastError();
+ if (raw_image->isBufferInvalid())
+ {
+ setLastError("Invalid input, no buffer");
+ return false;
+ }
+
LLImageDataSharedLock lockIn(raw_image);
LLImageDataLock lockOut(this);
@@ -545,6 +559,7 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
//try/catch will crash on Mac and Linux if LLImageJPEG::errorExit throws an error
//so as instead, we use setjmp/longjmp to avoid this crash, which is the best we can get. --bao
//
+#if !LL_ARM64
if( setjmp(sSetjmpBuffer) )
{
// If we get here, the JPEG code has signaled an error.
@@ -555,7 +570,7 @@ bool LLImageJPEG::encode( const LLImageRaw* raw_image, F32 encode_time )
mOutputBufferSize = 0;
return false;
}
-
+#endif
try
{
diff --git a/indra/llimage/llimagejpeg.h b/indra/llimage/llimagejpeg.h
index 012b87a42d..ee0a8815e8 100644
--- a/indra/llimage/llimagejpeg.h
+++ b/indra/llimage/llimagejpeg.h
@@ -78,7 +78,9 @@ protected:
S32 mEncodeQuality; // on a scale from 1 to 100
private:
+#if !LL_ARM64
static jmp_buf sSetjmpBuffer; // To allow the library to abort.
+#endif
};
#endif // LL_LLIMAGEJPEG_H
diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp
index f4bcb97a5d..7cfadb889d 100644
--- a/indra/llimagej2coj/llimagej2coj.cpp
+++ b/indra/llimagej2coj/llimagej2coj.cpp
@@ -29,10 +29,6 @@
// this is defined so that we get static linking.
#include "openjpeg.h"
-#include "event.h"
-#include "cio.h"
-
-#define MAX_ENCODED_DISCARD_LEVELS 5
// Factory function: see declaration in llimagej2c.cpp
LLImageJ2CImpl* fallbackCreateLLImageJ2CImpl()
@@ -50,6 +46,7 @@ std::string LLImageJ2COJ::getEngineInfo() const
#endif
}
+#if WANT_VERBOSE_OPJ_SPAM
// Return string from message, eliminating final \n if present
static std::string chomp(const char* msg)
{
@@ -65,27 +62,34 @@ static std::string chomp(const char* msg)
}
return message;
}
+#endif
/**
sample error callback expecting a LLFILE* client object
*/
void error_callback(const char* msg, void*)
{
- LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+#if WANT_VERBOSE_OPJ_SPAM
+ LL_WARNS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+#endif
}
/**
sample warning callback expecting a LLFILE* client object
*/
void warning_callback(const char* msg, void*)
{
- LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+#if WANT_VERBOSE_OPJ_SPAM
+ LL_WARNS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+#endif
}
/**
sample debug callback expecting no client object
*/
void info_callback(const char* msg, void*)
{
- LL_DEBUGS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+#if WANT_VERBOSE_OPJ_SPAM
+ LL_INFOS() << "LLImageJ2COJ: " << chomp(msg) << LL_ENDL;
+#endif
}
// Divide a by 2 to the power of b and round upwards
@@ -97,108 +101,105 @@ int ceildivpow2(int a, int b)
class JPEG2KBase
{
public:
- JPEG2KBase() {}
+ JPEG2KBase() = default;
U8* buffer = nullptr;
OPJ_SIZE_T size = 0;
OPJ_OFF_T offset = 0;
};
-#define WANT_VERBOSE_OPJ_SPAM LL_DEBUG
-
-static void opj_info(const char* msg, void* user_data)
-{
- llassert(user_data);
-#if WANT_VERBOSE_OPJ_SPAM
- LL_INFOS("OpenJPEG") << msg << LL_ENDL;
-#endif
-}
-
-static void opj_warn(const char* msg, void* user_data)
-{
- llassert(user_data);
-#if WANT_VERBOSE_OPJ_SPAM
- LL_WARNS("OpenJPEG") << msg << LL_ENDL;
-#endif
-}
-
-static void opj_error(const char* msg, void* user_data)
-{
- llassert(user_data);
-#if WANT_VERBOSE_OPJ_SPAM
- LL_WARNS("OpenJPEG") << msg << LL_ENDL;
-#endif
-}
-
static OPJ_SIZE_T opj_read(void * buffer, OPJ_SIZE_T bytes, void* user_data)
{
- llassert(user_data);
+ llassert(user_data && buffer);
+
JPEG2KBase* jpeg_codec = static_cast(user_data);
- OPJ_SIZE_T remainder = (jpeg_codec->size - jpeg_codec->offset);
- if (remainder <= 0)
+
+ if (jpeg_codec->offset < 0 || static_cast(jpeg_codec->offset) >= jpeg_codec->size)
{
jpeg_codec->offset = jpeg_codec->size;
- // Indicate end of stream (hacky?)
- return (OPJ_OFF_T)-1;
+ return static_cast(-1); // Indicate EOF
}
- OPJ_SIZE_T to_read = llclamp(U32(bytes), U32(0), U32(remainder));
+
+ OPJ_SIZE_T remainder = jpeg_codec->size - static_cast(jpeg_codec->offset);
+ OPJ_SIZE_T to_read = (bytes < remainder) ? bytes : remainder;
+
memcpy(buffer, jpeg_codec->buffer + jpeg_codec->offset, to_read);
jpeg_codec->offset += to_read;
+
return to_read;
}
static OPJ_SIZE_T opj_write(void * buffer, OPJ_SIZE_T bytes, void* user_data)
{
- llassert(user_data);
+ llassert(user_data && buffer);
+
JPEG2KBase* jpeg_codec = static_cast(user_data);
- OPJ_SIZE_T remainder = jpeg_codec->size - jpeg_codec->offset;
- if (remainder < bytes)
+ OPJ_OFF_T required_offset = jpeg_codec->offset + static_cast(bytes);
+
+ // Overflow check
+ if (required_offset < jpeg_codec->offset)
+ return 0; // Overflow detected
+
+ // Resize if needed (exponential growth)
+ if (required_offset > static_cast(jpeg_codec->size))
{
- OPJ_SIZE_T new_size = jpeg_codec->size + (bytes - remainder);
+ OPJ_SIZE_T new_size = jpeg_codec->size ? jpeg_codec->size : 1024;
+ while (required_offset > static_cast(new_size))
+ new_size *= 2;
+
+ const OPJ_SIZE_T MAX_BUFFER_SIZE = 512 * 1024 * 1024; // 512 MB, increase if needed
+ if (new_size > MAX_BUFFER_SIZE) return 0;
+
U8* new_buffer = (U8*)ll_aligned_malloc_16(new_size);
- memcpy(new_buffer, jpeg_codec->buffer, jpeg_codec->offset);
- U8* old_buffer = jpeg_codec->buffer;
+ if (!new_buffer) return 0; // Allocation failed
+
+ if (jpeg_codec->offset > 0)
+ memcpy(new_buffer, jpeg_codec->buffer, static_cast(jpeg_codec->offset));
+
+ ll_aligned_free_16(jpeg_codec->buffer);
jpeg_codec->buffer = new_buffer;
- ll_aligned_free_16(old_buffer);
jpeg_codec->size = new_size;
}
- memcpy(jpeg_codec->buffer + jpeg_codec->offset, buffer, bytes);
- jpeg_codec->offset += bytes;
+
+ memcpy(jpeg_codec->buffer + jpeg_codec->offset, buffer, static_cast(bytes));
+ jpeg_codec->offset = required_offset;
return bytes;
}
static OPJ_OFF_T opj_skip(OPJ_OFF_T bytes, void* user_data)
{
+ llassert(user_data);
JPEG2KBase* jpeg_codec = static_cast(user_data);
- jpeg_codec->offset += bytes;
- if (jpeg_codec->offset > (OPJ_OFF_T)jpeg_codec->size)
+ OPJ_OFF_T new_offset = jpeg_codec->offset + bytes;
+
+ if (new_offset < 0 || new_offset > static_cast(jpeg_codec->size))
{
- jpeg_codec->offset = jpeg_codec->size;
- // Indicate end of stream
- return (OPJ_OFF_T)-1;
- }
-
- if (jpeg_codec->offset < 0)
- {
- // Shouldn't be possible?
- jpeg_codec->offset = 0;
+ // Clamp and indicate EOF or error
+ jpeg_codec->offset = llclamp(new_offset, 0, static_cast(jpeg_codec->size));
return (OPJ_OFF_T)-1;
}
+ jpeg_codec->offset = new_offset;
return bytes;
}
-static OPJ_BOOL opj_seek(OPJ_OFF_T bytes, void * user_data)
+static OPJ_BOOL opj_seek(OPJ_OFF_T offset, void * user_data)
{
+ llassert(user_data);
JPEG2KBase* jpeg_codec = static_cast(user_data);
- jpeg_codec->offset = bytes;
- jpeg_codec->offset = llclamp(U32(jpeg_codec->offset), U32(0), U32(jpeg_codec->size));
+
+ if (offset < 0 || offset > static_cast(jpeg_codec->size))
+ return OPJ_FALSE;
+
+ jpeg_codec->offset = offset;
return OPJ_TRUE;
}
static void opj_free_user_data(void * user_data)
{
+ llassert(user_data);
+
JPEG2KBase* jpeg_codec = static_cast(user_data);
// Don't free, data is managed externally
jpeg_codec->buffer = nullptr;
@@ -208,25 +209,61 @@ static void opj_free_user_data(void * user_data)
static void opj_free_user_data_write(void * user_data)
{
+ llassert(user_data);
+
JPEG2KBase* jpeg_codec = static_cast(user_data);
// Free, data was allocated here
- ll_aligned_free_16(jpeg_codec->buffer);
- jpeg_codec->buffer = nullptr;
+ if (jpeg_codec->buffer)
+ {
+ ll_aligned_free_16(jpeg_codec->buffer);
+ jpeg_codec->buffer = nullptr;
+ }
jpeg_codec->size = 0;
jpeg_codec->offset = 0;
}
+/**
+ * Estimates the number of layers necessary depending on the image surface (w x h)
+ */
+static U32 estimate_num_layers(U32 surface)
+{
+ if (surface <= 1024) return 2; // Tiny (≤32×32)
+ else if (surface <= 16384) return 3; // Small (≤128×128)
+ else if (surface <= 262144) return 4; // Medium (≤512×512)
+ else if (surface <= 1048576) return 5; // Up to ~1MP
+ else return 6; // Up to ~1.5–2MP
+}
+
+/**
+ * Sets the parameters.tcp_rates according to the number of layers and a last tcp_rate value (which equals to the final compression ratio).
+ *
+ * Example for 6 layers:
+ *
+ * i = 5, parameters.tcp_rates[6 - 1 - 5] = 8.0f * (1 << (5 << 1)) = 8192 // Layer 5 (lowest quality)
+ * i = 4, parameters.tcp_rates[6 - 1 - 4] = 8.0f * (1 << (4 << 1)) = 2048 // Layer 4
+ * i = 3, parameters.tcp_rates[6 - 1 - 3] = 8.0f * (1 << (3 << 1)) = 512 // Layer 3
+ * i = 2, parameters.tcp_rates[6 - 1 - 2] = 8.0f * (1 << (2 << 1)) = 128 // Layer 2
+ * i = 1, parameters.tcp_rates[6 - 1 - 1] = 8.0f * (1 << (1 << 1)) = 32 // Layer 1
+ * i = 0, parameters.tcp_rates[6 - 1 - 0] = 8.0f * (1 << (0 << 1)) = 8 // Layer 0 (highest quality)
+ *
+ */
+static void set_tcp_rates(opj_cparameters_t* parameters, U32 num_layers = 1, F32 last_tcp_rate = LAST_TCP_RATE)
+{
+ parameters->tcp_numlayers = num_layers;
+
+ for (int i = num_layers - 1; i >= 0; i--)
+ {
+ parameters->tcp_rates[num_layers - 1 - i] = last_tcp_rate * static_cast(1 << (i << 1));
+ }
+}
+
class JPEG2KDecode : public JPEG2KBase
{
public:
JPEG2KDecode(S8 discardLevel)
{
- memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
memset(¶meters, 0, sizeof(opj_dparameters_t));
- event_mgr.error_handler = error_callback;
- event_mgr.warning_handler = warning_callback;
- event_mgr.info_handler = info_callback;
opj_set_default_decoder_parameters(¶meters);
parameters.cp_reduce = discardLevel;
}
@@ -270,6 +307,11 @@ public:
decoder = opj_create_decompress(OPJ_CODEC_J2K);
+ /* catch events using our callbacks and give a local context */
+ opj_set_error_handler(decoder, error_callback, nullptr);
+ opj_set_warning_handler(decoder, warning_callback, nullptr);
+ opj_set_info_handler(decoder, info_callback, nullptr);
+
if (!opj_setup_decoder(decoder, ¶meters))
{
return false;
@@ -340,9 +382,9 @@ public:
decoder = opj_create_decompress(OPJ_CODEC_J2K);
opj_setup_decoder(decoder, ¶meters);
- opj_set_info_handler(decoder, opj_info, this);
- opj_set_warning_handler(decoder, opj_warn, this);
- opj_set_error_handler(decoder, opj_error, this);
+ opj_set_info_handler(decoder, info_callback, this);
+ opj_set_warning_handler(decoder, warning_callback, this);
+ opj_set_error_handler(decoder, error_callback, this);
if (stream)
{
@@ -408,7 +450,6 @@ public:
private:
opj_dparameters_t parameters;
- opj_event_mgr_t event_mgr;
opj_image_t* image = nullptr;
opj_codec_t* decoder = nullptr;
opj_stream_t* stream = nullptr;
@@ -423,22 +464,19 @@ public:
JPEG2KEncode(const char* comment_text_in, bool reversible)
{
memset(¶meters, 0, sizeof(opj_cparameters_t));
- memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
- event_mgr.error_handler = error_callback;
- event_mgr.warning_handler = warning_callback;
- event_mgr.info_handler = info_callback;
opj_set_default_encoder_parameters(¶meters);
parameters.cod_format = OPJ_CODEC_J2K;
- parameters.cp_disto_alloc = 1;
+ parameters.prog_order = OPJ_RLCP; // should be the default, but, just in case
+ parameters.cp_disto_alloc = 1; // enable rate allocation by distortion
+ parameters.max_cs_size = 0; // do not cap max size because we're using tcp_rates and also irrelevant with lossless.
if (reversible)
{
- parameters.max_cs_size = 0; // do not limit size for reversible compression
parameters.irreversible = 0; // should be the default, but, just in case
parameters.tcp_numlayers = 1;
/* documentation seems to be wrong, should be 0.0f for lossless, not 1.0f
- see https://github.com/uclouvain/openjpeg/blob/39e8c50a2f9bdcf36810ee3d41bcbf1cc78968ae/src/lib/openjp2/j2k.c#L7755
+ see https://github.com/uclouvain/openjpeg/blob/e7453e398b110891778d8da19209792c69ca7169/src/lib/openjp2/j2k.c#L7817
*/
parameters.tcp_rates[0] = 0.0f;
}
@@ -493,53 +531,48 @@ public:
encoder = opj_create_compress(OPJ_CODEC_J2K);
- parameters.tcp_mct = (image->numcomps >= 3) ? 1 : 0;
- parameters.cod_format = OPJ_CODEC_J2K;
- parameters.prog_order = OPJ_RLCP;
- parameters.cp_disto_alloc = 1;
+ /* catch events using our callbacks and give a local context */
+ opj_set_error_handler(encoder, error_callback, nullptr);
+ opj_set_warning_handler(encoder, warning_callback, nullptr);
+ opj_set_info_handler(encoder, info_callback, nullptr);
+
+ parameters.tcp_mct = (image->numcomps >= 3) ? 1 : 0; // no color transform for RGBA images
+
// if not lossless compression, computes tcp_numlayers and max_cs_size depending on the image dimensions
- if( parameters.irreversible ) {
+ if( parameters.irreversible )
+ {
// computes a number of layers
U32 surface = rawImageIn.getWidth() * rawImageIn.getHeight();
- U32 nb_layers = 1;
- U32 s = 64*64;
- while (surface > s)
- {
- nb_layers++;
- s *= 4;
- }
- nb_layers = llclamp(nb_layers, 1, 6);
- parameters.tcp_numlayers = nb_layers;
- parameters.tcp_rates[nb_layers - 1] = (U32)(1.f / DEFAULT_COMPRESSION_RATE); // 1:8 by default
+ // gets the necessary number of layers
+ U32 nb_layers = estimate_num_layers(surface);
- // for each subsequent layer, computes its rate and adds surface * numcomps * 1/rate to the max_cs_size
- U32 max_cs_size = (U32)(surface * image->numcomps * DEFAULT_COMPRESSION_RATE);
- U32 multiplier;
- for (int i = nb_layers - 2; i >= 0; i--)
- {
- if( i == nb_layers - 2 )
- {
- multiplier = 15;
- }
- else if( i == nb_layers - 3 )
- {
- multiplier = 4;
- }
- else
- {
- multiplier = 2;
- }
- parameters.tcp_rates[i] = parameters.tcp_rates[i + 1] * multiplier;
- max_cs_size += (U32)(surface * image->numcomps * (1 / parameters.tcp_rates[i]));
- }
+ // fills parameters.tcp_rates and updates parameters.tcp_numlayers
+ set_tcp_rates(¶meters, nb_layers, LAST_TCP_RATE);
- //ensure that we have at least a minimal size
- max_cs_size = llmax(max_cs_size, (U32)FIRST_PACKET_SIZE);
+ }
- parameters.max_cs_size = max_cs_size;
+ U32 width_tiles = (rawImageIn.getWidth() >> 6);
+ U32 height_tiles = (rawImageIn.getHeight() >> 6);
+
+ // Allow images with a width or height that are MIN_IMAGE_SIZE <= x < 64
+ if (width_tiles == 0 && (rawImageIn.getWidth() >= MIN_IMAGE_SIZE))
+ {
+ width_tiles = 1;
+ }
+ if (height_tiles == 0 && (rawImageIn.getHeight() >= MIN_IMAGE_SIZE))
+ {
+ height_tiles = 1;
+ }
+
+ if (width_tiles == 1 || height_tiles == 1)
+ {
+ // Images with either dimension less than 32 need less number of resolutions otherwise they error
+ int min_dim = rawImageIn.getWidth() < rawImageIn.getHeight() ? rawImageIn.getWidth() : rawImageIn.getHeight();
+ int max_res = 1 + (int)floor(log2(min_dim));
+ parameters.numresolution = max_res;
}
if (!opj_setup_encoder(encoder, ¶meters, image))
@@ -547,11 +580,7 @@ public:
return false;
}
- opj_set_info_handler(encoder, opj_info, this);
- opj_set_warning_handler(encoder, opj_warn, this);
- opj_set_error_handler(encoder, opj_error, this);
-
- U32 tile_count = (rawImageIn.getWidth() >> 6) * (rawImageIn.getHeight() >> 6);
+ U32 tile_count = width_tiles * height_tiles;
U32 data_size_guess = tile_count * TILE_SIZE;
// will be freed in opj_free_user_data_write
@@ -566,7 +595,7 @@ public:
opj_stream_destroy(stream);
}
- stream = opj_stream_create(data_size_guess, false);
+ stream = opj_stream_create(data_size_guess, OPJ_FALSE);
if (!stream)
{
return false;
@@ -607,17 +636,15 @@ public:
void setImage(const LLImageRaw& raw)
{
- opj_image_cmptparm_t cmptparm[MAX_ENCODED_DISCARD_LEVELS];
- memset(&cmptparm[0], 0, MAX_ENCODED_DISCARD_LEVELS * sizeof(opj_image_cmptparm_t));
-
S32 numcomps = raw.getComponents();
- S32 width = raw.getWidth();
- S32 height = raw.getHeight();
+ S32 width = raw.getWidth();
+ S32 height = raw.getHeight();
+
+ std::vector cmptparm(numcomps);
for (S32 c = 0; c < numcomps; c++)
{
- cmptparm[c].prec = 8;
- cmptparm[c].bpp = 8;
+ cmptparm[c].prec = 8; // replaces .bpp
cmptparm[c].sgnd = 0;
cmptparm[c].dx = parameters.subsampling_dx;
cmptparm[c].dy = parameters.subsampling_dy;
@@ -625,7 +652,7 @@ public:
cmptparm[c].h = height;
}
- image = opj_image_create(numcomps, &cmptparm[0], OPJ_CLRSPC_SRGB);
+ image = opj_image_create(numcomps, cmptparm.data(), OPJ_CLRSPC_SRGB);
image->x1 = width;
image->y1 = height;
@@ -637,7 +664,7 @@ public:
{
for (S32 x = 0; x < width; x++)
{
- const U8 *pixel = src_datap + (y*width + x) * numcomps;
+ const U8 *pixel = src_datap + (y * width + x) * numcomps;
for (S32 c = 0; c < numcomps; c++)
{
image->comps[c].data[i] = *pixel;
@@ -744,7 +771,6 @@ public:
private:
opj_cparameters_t parameters;
- opj_event_mgr_t event_mgr;
opj_image_t* image = nullptr;
opj_codec_t* encoder = nullptr;
opj_stream_t* stream = nullptr;
@@ -855,14 +881,19 @@ bool LLImageJ2COJ::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 decod
bool LLImageJ2COJ::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, const char* comment_text, F32 encode_time, bool reversible)
{
+ if (raw_image.isBufferInvalid())
+ {
+ base.setLastError("Invalid input, no buffer");
+ return false;
+ }
+
JPEG2KEncode encode(comment_text, reversible);
bool encoded = encode.encode(raw_image, base);
- if (encoded)
+ if (!encoded)
{
- LL_WARNS() << "Openjpeg encoding implementation isn't complete, returning false" << LL_ENDL;
+ LL_WARNS() << "Openjpeg encoding was unsuccessful, returning false" << LL_ENDL;
}
return encoded;
- //return false;
}
bool LLImageJ2COJ::getMetadata(LLImageJ2C &base)
diff --git a/indra/llimagej2coj/llimagej2coj.h b/indra/llimagej2coj/llimagej2coj.h
index 498502451a..da49597302 100644
--- a/indra/llimagej2coj/llimagej2coj.h
+++ b/indra/llimagej2coj/llimagej2coj.h
@@ -29,6 +29,8 @@
#include "llimagej2c.h"
+const F32 LAST_TCP_RATE = 1.f/DEFAULT_COMPRESSION_RATE; // should be 8, giving a 1:8 ratio
+
class LLImageJ2COJ : public LLImageJ2CImpl
{
public:
diff --git a/indra/llinventory/llfoldertype.cpp b/indra/llinventory/llfoldertype.cpp
index 7e1be17ecc..670405e9b5 100644
--- a/indra/llinventory/llfoldertype.cpp
+++ b/indra/llinventory/llfoldertype.cpp
@@ -29,6 +29,7 @@
#include "llfoldertype.h"
#include "lldictionary.h"
#include "llmemory.h"
+#include "llsd.h"
#include "llsingleton.h"
///----------------------------------------------------------------------------
@@ -220,3 +221,21 @@ const std::string &LLFolderType::badLookup()
static const std::string sBadLookup = "llfoldertype_bad_lookup";
return sBadLookup;
}
+
+LLSD LLFolderType::getTypeNames()
+{
+ LLSD type_names;
+ for (S32 type = FT_TEXTURE; type < FT_COUNT; ++type)
+ {
+ if (lookupIsEnsembleType((LLFolderType::EType)type))
+ continue;
+
+ const FolderEntry* entry = LLFolderDictionary::getInstance()->lookup((LLFolderType::EType)type);
+ // skip llfoldertype_bad_lookup
+ if (entry)
+ {
+ type_names.append(entry->mName);
+ }
+ }
+ return type_names;
+}
diff --git a/indra/llinventory/llfoldertype.h b/indra/llinventory/llfoldertype.h
index 46a1b92a96..dd12693f66 100644
--- a/indra/llinventory/llfoldertype.h
+++ b/indra/llinventory/llfoldertype.h
@@ -115,6 +115,8 @@ public:
static const std::string& badLookup(); // error string when a lookup fails
+ static LLSD getTypeNames();
+
protected:
LLFolderType() {}
~LLFolderType() {}
diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp
index 075abf9536..3defad8f3b 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -46,6 +46,7 @@ static const std::string INV_ITEM_ID_LABEL("item_id");
static const std::string INV_FOLDER_ID_LABEL("cat_id");
static const std::string INV_PARENT_ID_LABEL("parent_id");
static const std::string INV_THUMBNAIL_LABEL("thumbnail");
+static const std::string INV_FAVORITE_LABEL("favorite");
static const std::string INV_THUMBNAIL_ID_LABEL("thumbnail_id");
static const std::string INV_ASSET_TYPE_LABEL("type");
static const std::string INV_PREFERRED_TYPE_LABEL("preferred_type");
@@ -59,6 +60,7 @@ static const std::string INV_LINKED_ID_LABEL("linked_id");
static const std::string INV_SALE_INFO_LABEL("sale_info");
static const std::string INV_FLAGS_LABEL("flags");
static const std::string INV_CREATION_DATE_LABEL("created_at");
+static const std::string INV_TOGGLED_LABEL("toggled");
// key used by agent-inventory-service
static const std::string INV_ASSET_TYPE_LABEL_WS("type_default");
@@ -82,14 +84,16 @@ LLInventoryObject::LLInventoryObject(const LLUUID& uuid,
mParentUUID(parent_uuid),
mType(type),
mName(name),
- mCreationDate(0)
+ mCreationDate(0),
+ mFavorite(false)
{
correctInventoryName(mName);
}
LLInventoryObject::LLInventoryObject()
: mType(LLAssetType::AT_NONE),
- mCreationDate(0)
+ mCreationDate(0),
+ mFavorite(false)
{
}
@@ -104,6 +108,7 @@ void LLInventoryObject::copyObject(const LLInventoryObject* other)
mType = other->mType;
mName = other->mName;
mThumbnailUUID = other->mThumbnailUUID;
+ mFavorite = other->mFavorite;
}
const LLUUID& LLInventoryObject::getUUID() const
@@ -121,6 +126,11 @@ const LLUUID& LLInventoryObject::getThumbnailUUID() const
return mThumbnailUUID;
}
+bool LLInventoryObject::getIsFavorite() const
+{
+ return mFavorite;
+}
+
const std::string& LLInventoryObject::getName() const
{
return mName;
@@ -175,6 +185,11 @@ void LLInventoryObject::setThumbnailUUID(const LLUUID& thumbnail_uuid)
mThumbnailUUID = thumbnail_uuid;
}
+void LLInventoryObject::setFavorite(bool favorite)
+{
+ mFavorite = favorite;
+}
+
void LLInventoryObject::setType(LLAssetType::EType type)
{
mType = type;
@@ -247,6 +262,23 @@ bool LLInventoryObject::importLegacyStream(std::istream& input_stream)
{
setThumbnailUUID(LLUUID::null);
}
+
+ if (metadata.has("favorite"))
+ {
+ const LLSD& favorite = metadata["favorite"];
+ if (favorite.has("toggled"))
+ {
+ setFavorite(favorite["toggled"].asBoolean());
+ }
+ else
+ {
+ setFavorite(false);
+ }
+ }
+ else
+ {
+ setFavorite(false);
+ }
}
else if(0 == strcmp("name", keyword))
{
@@ -735,6 +767,23 @@ bool LLInventoryItem::importLegacyStream(std::istream& input_stream)
{
setThumbnailUUID(LLUUID::null);
}
+
+ if (metadata.has("favorite"))
+ {
+ const LLSD& favorite = metadata["favorite"];
+ if (favorite.has("toggled"))
+ {
+ setFavorite(favorite["toggled"].asBoolean());
+ }
+ else
+ {
+ setFavorite(false);
+ }
+ }
+ else
+ {
+ setFavorite(false);
+ }
}
else if(0 == strcmp("inv_type", keyword))
{
@@ -879,7 +928,7 @@ bool LLInventoryItem::exportLegacyStream(std::ostream& output_stream, bool inclu
LLSD LLInventoryItem::asLLSD() const
{
- LLSD sd = LLSD();
+ LLSD sd;
asLLSD(sd);
return sd;
}
@@ -888,13 +937,18 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
{
sd[INV_ITEM_ID_LABEL] = mUUID;
sd[INV_PARENT_ID_LABEL] = mParentUUID;
- sd[INV_PERMISSIONS_LABEL] = ll_create_sd_from_permissions(mPermissions);
+ ll_fill_sd_from_permissions(sd[INV_PERMISSIONS_LABEL], mPermissions);
if (mThumbnailUUID.notNull())
{
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
+ if (mFavorite)
+ {
+ sd[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
+ }
+
U32 mask = mPermissions.getMaskBase();
if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
|| (mAssetUUID.isNull()))
@@ -909,19 +963,22 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const
cipher.encrypt(shadow_id.mData, UUID_BYTES);
sd[INV_SHADOW_ID_LABEL] = shadow_id;
}
- sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
- sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType;
+ sd[INV_ASSET_TYPE_LABEL] = std::string(LLAssetType::lookup(mType));
const std::string inv_type_str = LLInventoryType::lookup(mInventoryType);
if(!inv_type_str.empty())
{
sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str;
}
+ else
+ {
+ sd[INV_INVENTORY_TYPE_LABEL] = (LLSD::Integer)mInventoryType;
+ }
//sd[INV_FLAGS_LABEL] = (S32)mFlags;
sd[INV_FLAGS_LABEL] = ll_sd_from_U32(mFlags);
- sd[INV_SALE_INFO_LABEL] = mSaleInfo.asLLSD();
+ mSaleInfo.asLLSD(sd[INV_SALE_INFO_LABEL]);
sd[INV_NAME_LABEL] = mName;
sd[INV_DESC_LABEL] = mDescription;
- sd[INV_CREATION_DATE_LABEL] = (S32) mCreationDate;
+ sd[INV_CREATION_DATE_LABEL] = (LLSD::Integer)mCreationDate;
}
bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
@@ -937,6 +994,8 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
// TODO - figure out if this should be moved into the noclobber fields above
mThumbnailUUID.setNull();
+ mFavorite = false;
+ mPermissions.init(LLUUID::null, LLUUID::null, LLUUID::null, LLUUID::null);
// iterate as map to avoid making unnecessary temp copies of everything
LLSD::map_const_iterator i, end;
@@ -982,9 +1041,20 @@ bool LLInventoryItem::fromLLSD(const LLSD& sd, bool is_new)
continue;
}
+ if (i->first == INV_FAVORITE_LABEL)
+ {
+ const LLSD& favorite_map = i->second;
+ const std::string w = INV_TOGGLED_LABEL;
+ if (favorite_map.has(w))
+ {
+ mFavorite = favorite_map[w].asBoolean();
+ }
+ continue;
+ }
+
if (i->first == INV_PERMISSIONS_LABEL)
{
- mPermissions = ll_permissions_from_sd(i->second);
+ mPermissions.importLLSD(i->second);
continue;
}
@@ -1177,6 +1247,11 @@ LLSD LLInventoryCategory::asLLSD() const
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
+ if (mFavorite)
+ {
+ sd[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
+ }
+
return sd;
}
@@ -1188,11 +1263,17 @@ LLSD LLInventoryCategory::asAISCreateCatLLSD() const
S8 type = static_cast(mPreferredType);
sd[INV_ASSET_TYPE_LABEL_WS] = type;
sd[INV_NAME_LABEL] = mName;
+
if (mThumbnailUUID.notNull())
{
sd[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
+ if (mFavorite)
+ {
+ sd[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
+ }
+
return sd;
}
@@ -1240,6 +1321,17 @@ bool LLInventoryCategory::fromLLSD(const LLSD& sd)
mThumbnailUUID = sd[w];
}
}
+ mFavorite = false;
+ w = INV_FAVORITE_LABEL;
+ if (sd.has(w))
+ {
+ const LLSD& favorite_map = sd[w];
+ w = INV_TOGGLED_LABEL;
+ if (favorite_map.has(w))
+ {
+ mFavorite = favorite_map[w].asBoolean();
+ }
+ }
w = INV_ASSET_TYPE_LABEL;
if (sd.has(w))
{
@@ -1362,6 +1454,23 @@ bool LLInventoryCategory::importLegacyStream(std::istream& input_stream)
{
setThumbnailUUID(LLUUID::null);
}
+
+ if (metadata.has("favorite"))
+ {
+ const LLSD& favorite = metadata["favorite"];
+ if (favorite.has("toggled"))
+ {
+ setFavorite(favorite["toggled"].asBoolean());
+ }
+ else
+ {
+ setFavorite(false);
+ }
+ }
+ else
+ {
+ setFavorite(false);
+ }
}
else
{
@@ -1396,12 +1505,11 @@ bool LLInventoryCategory::exportLegacyStream(std::ostream& output_stream, bool)
return true;
}
-LLSD LLInventoryCategory::exportLLSD() const
+void LLInventoryCategory::exportLLSD(LLSD& cat_data) const
{
- LLSD cat_data;
cat_data[INV_FOLDER_ID_LABEL] = mUUID;
cat_data[INV_PARENT_ID_LABEL] = mParentUUID;
- cat_data[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType);
+ cat_data[INV_ASSET_TYPE_LABEL] = std::string(LLAssetType::lookup(mType));
cat_data[INV_PREFERRED_TYPE_LABEL] = LLFolderType::lookup(mPreferredType);
cat_data[INV_NAME_LABEL] = mName;
@@ -1409,49 +1517,76 @@ LLSD LLInventoryCategory::exportLLSD() const
{
cat_data[INV_THUMBNAIL_LABEL] = LLSD().with(INV_ASSET_ID_LABEL, mThumbnailUUID);
}
-
- return cat_data;
+ if (mFavorite)
+ {
+ cat_data[INV_FAVORITE_LABEL] = LLSD().with(INV_TOGGLED_LABEL, mFavorite);
+ }
}
-bool LLInventoryCategory::importLLSD(const LLSD& cat_data)
+bool LLInventoryCategory::importLLSDMap(const LLSD& cat_data)
{
- if (cat_data.has(INV_FOLDER_ID_LABEL))
+ LLSD::map_const_iterator i, end;
+ end = cat_data.endMap();
+ for ( i = cat_data.beginMap(); i != end; ++i)
{
- setUUID(cat_data[INV_FOLDER_ID_LABEL].asUUID());
+ importLLSD(i->first, i->second);
}
- if (cat_data.has(INV_PARENT_ID_LABEL))
- {
- setParent(cat_data[INV_PARENT_ID_LABEL].asUUID());
- }
- if (cat_data.has(INV_ASSET_TYPE_LABEL))
- {
- setType(LLAssetType::lookup(cat_data[INV_ASSET_TYPE_LABEL].asString()));
- }
- if (cat_data.has(INV_PREFERRED_TYPE_LABEL))
- {
- setPreferredType(LLFolderType::lookup(cat_data[INV_PREFERRED_TYPE_LABEL].asString()));
- }
- if (cat_data.has(INV_THUMBNAIL_LABEL))
- {
- LLUUID thumbnail_uuid;
- const LLSD &thumbnail_data = cat_data[INV_THUMBNAIL_LABEL];
- if (thumbnail_data.has(INV_ASSET_ID_LABEL))
- {
- thumbnail_uuid = thumbnail_data[INV_ASSET_ID_LABEL].asUUID();
- }
- setThumbnailUUID(thumbnail_uuid);
- }
- if (cat_data.has(INV_NAME_LABEL))
- {
- mName = cat_data[INV_NAME_LABEL].asString();
- LLStringUtil::replaceNonstandardASCII(mName, ' ');
- LLStringUtil::replaceChar(mName, '|', ' ');
- }
-
return true;
}
+
+bool LLInventoryCategory::importLLSD(const std::string& label, const LLSD& value)
+{
+ if (label == INV_FOLDER_ID_LABEL)
+ {
+ setUUID(value.asUUID());
+ return true;
+ }
+ else if (label == INV_PARENT_ID_LABEL)
+ {
+ setParent(value.asUUID());
+ return true;
+ }
+ else if (label == INV_ASSET_TYPE_LABEL)
+ {
+ setType(LLAssetType::lookup(value.asString()));
+ return true;
+ }
+ else if (label == INV_PREFERRED_TYPE_LABEL)
+ {
+ setPreferredType(LLFolderType::lookup(value.asString()));
+ return true;
+ }
+ else if (label == INV_THUMBNAIL_LABEL)
+ {
+ LLUUID thumbnail_uuid;
+ if (value.has(INV_ASSET_ID_LABEL))
+ {
+ thumbnail_uuid = value[INV_ASSET_ID_LABEL].asUUID();
+ }
+ setThumbnailUUID(thumbnail_uuid);
+ return true;
+ }
+ if (label == INV_FAVORITE_LABEL)
+ {
+ bool favorite = false;
+ if (value.has(INV_TOGGLED_LABEL))
+ {
+ favorite = value[INV_TOGGLED_LABEL].asBoolean();
+ }
+ setFavorite(favorite);
+ }
+ else if (label == INV_NAME_LABEL)
+ {
+ mName = value.asString();
+ LLStringUtil::replaceNonstandardASCII(mName, ' ');
+ LLStringUtil::replaceChar(mName, '|', ' ');
+ return true;
+ }
+ return false;
+}
+
///----------------------------------------------------------------------------
-/// Local function definitions
+/// Local function definitions for testing purposes
///----------------------------------------------------------------------------
LLSD ll_create_sd_from_inventory_item(LLPointer item)
diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h
index e63f2deba7..181c46226c 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -71,6 +71,7 @@ public:
virtual const LLUUID& getLinkedUUID() const; // inventoryID that this item points to, else this item's inventoryID
const LLUUID& getParentUUID() const;
virtual const LLUUID& getThumbnailUUID() const;
+ virtual bool getIsFavorite() const;
virtual const std::string& getName() const;
virtual LLAssetType::EType getType() const;
LLAssetType::EType getActualType() const; // bypasses indirection for linked items
@@ -86,6 +87,7 @@ public:
virtual void rename(const std::string& new_name);
void setParent(const LLUUID& new_parent);
virtual void setThumbnailUUID(const LLUUID& thumbnail_uuid);
+ virtual void setFavorite(bool favorite);
void setType(LLAssetType::EType type);
virtual void setCreationDate(time_t creation_date_utc); // only stored for items
@@ -111,6 +113,7 @@ protected:
LLUUID mUUID;
LLUUID mParentUUID; // Parent category. Root categories have LLUUID::NULL.
LLUUID mThumbnailUUID;
+ bool mFavorite;
LLAssetType::EType mType;
std::string mName;
time_t mCreationDate; // seconds from 1/1/1970, UTC
@@ -270,8 +273,9 @@ public:
virtual bool importLegacyStream(std::istream& input_stream);
virtual bool exportLegacyStream(std::ostream& output_stream, bool include_asset_key = true) const;
- LLSD exportLLSD() const;
- bool importLLSD(const LLSD& cat_data);
+ virtual void exportLLSD(LLSD& sd) const;
+ bool importLLSDMap(const LLSD& cat_data);
+ virtual bool importLLSD(const std::string& label, const LLSD& value);
//--------------------------------------------------------------------
// Member Variables
//--------------------------------------------------------------------
@@ -285,6 +289,7 @@ protected:
//
// These functions convert between structured data and an inventory
// item, appropriate for serialization.
+// Not up to date (no favorites, nor thumbnails), for testing purposes
//-----------------------------------------------------------------------------
LLSD ll_create_sd_from_inventory_item(LLPointer item);
LLSD ll_create_sd_from_inventory_category(LLPointer cat);
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index 67d713db1f..ac50b428bf 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -37,98 +37,98 @@
#include "llsettingsdaycycle.h"
// Grid out of which parcels taken is stepped every 4 meters.
-const F32 PARCEL_GRID_STEP_METERS = 4.f;
+constexpr F32 PARCEL_GRID_STEP_METERS = 4.f;
// Area of one "square" of parcel
-const S32 PARCEL_UNIT_AREA = 16;
+constexpr S32 PARCEL_UNIT_AREA = 16;
// Height _above_ground_ that parcel boundary ends
-const F32 PARCEL_HEIGHT = 50.f;
+constexpr F32 PARCEL_HEIGHT = 50.f;
//Height above ground which parcel boundries exist for explicitly banned avatars
-const F32 BAN_HEIGHT = 5000.f;
+constexpr F32 BAN_HEIGHT = 5000.f;
// Maximum number of entries in an access list
-const S32 PARCEL_MAX_ACCESS_LIST = 300;
+constexpr S32 PARCEL_MAX_ACCESS_LIST = 300;
//Maximum number of entires in an update packet
//for access/ban lists.
-const F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;
+constexpr F32 PARCEL_MAX_ENTRIES_PER_PACKET = 48.f;
// Maximum number of experiences
-const S32 PARCEL_MAX_EXPERIENCE_LIST = 24;
+constexpr S32 PARCEL_MAX_EXPERIENCE_LIST = 24;
// Weekly charge for listing a parcel in the directory
-const S32 PARCEL_DIRECTORY_FEE = 30;
+constexpr S32 PARCEL_DIRECTORY_FEE = 30;
-const S32 PARCEL_PASS_PRICE_DEFAULT = 10;
-const F32 PARCEL_PASS_HOURS_DEFAULT = 1.f;
+constexpr S32 PARCEL_PASS_PRICE_DEFAULT = 10;
+constexpr F32 PARCEL_PASS_HOURS_DEFAULT = 1.f;
// Number of "chunks" in which parcel overlay data is sent
// Chunk 0 = southern rows, entire width
-const S32 PARCEL_OVERLAY_CHUNKS = 4;
+constexpr S32 PARCEL_OVERLAY_CHUNKS = 4;
// Bottom three bits are a color index for the land overlay
-const U8 PARCEL_COLOR_MASK = 0x07;
-const U8 PARCEL_PUBLIC = 0x00;
-const U8 PARCEL_OWNED = 0x01;
-const U8 PARCEL_GROUP = 0x02;
-const U8 PARCEL_SELF = 0x03;
-const U8 PARCEL_FOR_SALE = 0x04;
-const U8 PARCEL_AUCTION = 0x05;
+constexpr U8 PARCEL_COLOR_MASK = 0x07;
+constexpr U8 PARCEL_PUBLIC = 0x00;
+constexpr U8 PARCEL_OWNED = 0x01;
+constexpr U8 PARCEL_GROUP = 0x02;
+constexpr U8 PARCEL_SELF = 0x03;
+constexpr U8 PARCEL_FOR_SALE = 0x04;
+constexpr U8 PARCEL_AUCTION = 0x05;
// unused 0x06
// unused 0x07
// flag, unused 0x08
-const U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility
-const U8 PARCEL_SOUND_LOCAL = 0x20;
-const U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge
-const U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge
+constexpr U8 PARCEL_HIDDENAVS = 0x10; // avatars not visible outside of parcel. Used for 'see avs' feature, but must be off for compatibility
+constexpr U8 PARCEL_SOUND_LOCAL = 0x20;
+constexpr U8 PARCEL_WEST_LINE = 0x40; // flag, property line on west edge
+constexpr U8 PARCEL_SOUTH_LINE = 0x80; // flag, property line on south edge
// Transmission results for parcel properties
-const S32 PARCEL_RESULT_NO_DATA = -1;
-const S32 PARCEL_RESULT_SUCCESS = 0; // got exactly one parcel
-const S32 PARCEL_RESULT_MULTIPLE = 1; // got multiple parcels
+constexpr S32 PARCEL_RESULT_NO_DATA = -1;
+constexpr S32 PARCEL_RESULT_SUCCESS = 0; // got exactly one parcel
+constexpr S32 PARCEL_RESULT_MULTIPLE = 1; // got multiple parcels
-const S32 SELECTED_PARCEL_SEQ_ID = -10000;
-const S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID = -20000;
-const S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000;
-const S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID = -40000;
-const S32 HOVERED_PARCEL_SEQ_ID = -50000;
+constexpr S32 SELECTED_PARCEL_SEQ_ID = -10000;
+constexpr S32 COLLISION_NOT_IN_GROUP_PARCEL_SEQ_ID = -20000;
+constexpr S32 COLLISION_BANNED_PARCEL_SEQ_ID = -30000;
+constexpr S32 COLLISION_NOT_ON_LIST_PARCEL_SEQ_ID = -40000;
+constexpr S32 HOVERED_PARCEL_SEQ_ID = -50000;
-const U32 RT_NONE = 0x1 << 0;
-const U32 RT_OWNER = 0x1 << 1;
-const U32 RT_GROUP = 0x1 << 2;
-const U32 RT_OTHER = 0x1 << 3;
-const U32 RT_LIST = 0x1 << 4;
-const U32 RT_SELL = 0x1 << 5;
+constexpr U32 RT_NONE = 0x1 << 0;
+constexpr U32 RT_OWNER = 0x1 << 1;
+constexpr U32 RT_GROUP = 0x1 << 2;
+constexpr U32 RT_OTHER = 0x1 << 3;
+constexpr U32 RT_LIST = 0x1 << 4;
+constexpr U32 RT_SELL = 0x1 << 5;
-const S32 INVALID_PARCEL_ID = -1;
+constexpr S32 INVALID_PARCEL_ID = -1;
-const S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
+constexpr S32 INVALID_PARCEL_ENVIRONMENT_VERSION = -2;
// if Region settings are used, parcel env. version is -1
-const S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;
+constexpr S32 UNSET_PARCEL_ENVIRONMENT_VERSION = -1;
// Timeouts for parcels
// default is 21 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 1814400000000
-const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
+constexpr U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(1814400000000);
// ***** TESTING is 10 minutes
//const U64 DEFAULT_USEC_CONVERSION_TIMEOUT = U64L(600000000);
// group is 60 days * 24h/d * 60m/h * 60s/m *1000000 usec/s = 5184000000000
-const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
+constexpr U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(5184000000000);
// ***** TESTING is 10 minutes
//const U64 GROUP_USEC_CONVERSION_TIMEOUT = U64L(600000000);
// default sale timeout is 2 days -> 172800000000
-const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
+constexpr U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(172800000000);
// ***** TESTING is 10 minutes
//const U64 DEFAULT_USEC_SALE_TIMEOUT = U64L(600000000);
// more grace period extensions.
-const U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
+constexpr U64 SEVEN_DAYS_IN_USEC = U64L(604800000000);
// if more than 100,000s before sale revert, and no extra extension
// has been given, go ahead and extend it more. That's about 1.2 days.
-const S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
+constexpr S32 EXTEND_GRACE_IF_MORE_THAN_SEC = 100000;
@@ -250,9 +250,9 @@ public:
void setMediaURL(const std::string& url);
void setMediaType(const std::string& type);
void setMediaDesc(const std::string& desc);
- void setMediaID(const LLUUID& id) { mMediaID = id; }
- void setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; }
- void setMediaLoop (U8 loop) { mMediaLoop = loop; }
+ void setMediaID(const LLUUID& id) { mMediaID = id; }
+ void setMediaAutoScale ( U8 flagIn ) { mMediaAutoScale = flagIn; }
+ void setMediaLoop(U8 loop) { mMediaLoop = loop; }
void setMediaWidth(S32 width);
void setMediaHeight(S32 height);
void setMediaCurrentURL(const std::string& url);
@@ -262,6 +262,8 @@ public:
void setMediaURLResetTimer(F32 time);
virtual void setLocalID(S32 local_id);
+ void setRegionID(const LLUUID& id) { mRegionID = id; }
+ const LLUUID& getRegionID() const { return mRegionID; }
// blow away all the extra stuff lurking in parcels, including urls, access lists, etc
void clearParcel();
@@ -651,6 +653,7 @@ public:
S32 mLocalID;
LLUUID mBanListTransactionID;
LLUUID mAccessListTransactionID;
+ LLUUID mRegionID;
std::map mAccessList;
std::map mBanList;
std::map mTempBanList;
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index c8963881df..b17e22e465 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -704,6 +704,80 @@ bool LLPermissions::exportLegacyStream(std::ostream& output_stream) const
return true;
}
+static const std::string PERM_CREATOR_ID_LABEL("creator_id");
+static const std::string PERM_OWNER_ID_LABEL("owner_id");
+static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id");
+static const std::string PERM_GROUP_ID_LABEL("group_id");
+static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group");
+static const std::string PERM_BASE_MASK_LABEL("base_mask");
+static const std::string PERM_OWNER_MASK_LABEL("owner_mask");
+static const std::string PERM_GROUP_MASK_LABEL("group_mask");
+static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask");
+static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask");
+
+void LLPermissions::importLLSD(const LLSD& sd_perm)
+{
+ LLSD::map_const_iterator i, end;
+ end = sd_perm.endMap();
+ for (i = sd_perm.beginMap(); i != end; ++i)
+ {
+ const std::string& label = i->first;
+ if (label == PERM_CREATOR_ID_LABEL)
+ {
+ mCreator = i->second.asUUID();
+ continue;
+ }
+ if (label == PERM_OWNER_ID_LABEL)
+ {
+ mOwner = i->second.asUUID();
+ continue;
+ }
+ if (label == PERM_LAST_OWNER_ID_LABEL)
+ {
+ mLastOwner = i->second.asUUID();
+ continue;
+ }
+ if (label == PERM_GROUP_ID_LABEL)
+ {
+ mGroup = i->second.asUUID();
+ continue;
+ }
+ if (label == PERM_BASE_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskBase = mask;
+ continue;
+ }
+ if (label == PERM_OWNER_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskOwner = mask;
+ continue;
+ }
+ if (label == PERM_EVERYONE_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskEveryone = mask;
+ continue;
+ }
+ if (label == PERM_GROUP_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskGroup = mask;
+ continue;
+ }
+ if (label == PERM_NEXT_OWNER_MASK_LABEL)
+ {
+ PermissionMask mask = i->second.asInteger();
+ mMaskNextOwner = mask;
+ continue;
+ }
+ }
+
+ fixOwnership();
+ fix();
+}
+
bool LLPermissions::operator==(const LLPermissions &rhs) const
{
return
@@ -998,55 +1072,30 @@ std::string mask_to_string(U32 mask)
///----------------------------------------------------------------------------
/// exported functions
///----------------------------------------------------------------------------
-static const std::string PERM_CREATOR_ID_LABEL("creator_id");
-static const std::string PERM_OWNER_ID_LABEL("owner_id");
-static const std::string PERM_LAST_OWNER_ID_LABEL("last_owner_id");
-static const std::string PERM_GROUP_ID_LABEL("group_id");
-static const std::string PERM_IS_OWNER_GROUP_LABEL("is_owner_group");
-static const std::string PERM_BASE_MASK_LABEL("base_mask");
-static const std::string PERM_OWNER_MASK_LABEL("owner_mask");
-static const std::string PERM_GROUP_MASK_LABEL("group_mask");
-static const std::string PERM_EVERYONE_MASK_LABEL("everyone_mask");
-static const std::string PERM_NEXT_OWNER_MASK_LABEL("next_owner_mask");
LLSD ll_create_sd_from_permissions(const LLPermissions& perm)
{
LLSD rv;
+ ll_fill_sd_from_permissions(rv, perm);
+ return rv;
+}
+void ll_fill_sd_from_permissions(LLSD& rv, const LLPermissions& perm)
+{
rv[PERM_CREATOR_ID_LABEL] = perm.getCreator();
rv[PERM_OWNER_ID_LABEL] = perm.getOwner();
rv[PERM_LAST_OWNER_ID_LABEL] = perm.getLastOwner();
rv[PERM_GROUP_ID_LABEL] = perm.getGroup();
rv[PERM_IS_OWNER_GROUP_LABEL] = perm.isGroupOwned();
- rv[PERM_BASE_MASK_LABEL] = (S32)perm.getMaskBase();
- rv[PERM_OWNER_MASK_LABEL] = (S32)perm.getMaskOwner();
- rv[PERM_GROUP_MASK_LABEL] = (S32)perm.getMaskGroup();
- rv[PERM_EVERYONE_MASK_LABEL] = (S32)perm.getMaskEveryone();
- rv[PERM_NEXT_OWNER_MASK_LABEL] = (S32)perm.getMaskNextOwner();
- return rv;
+ rv[PERM_BASE_MASK_LABEL] = (LLSD::Integer)perm.getMaskBase();
+ rv[PERM_OWNER_MASK_LABEL] = (LLSD::Integer)perm.getMaskOwner();
+ rv[PERM_GROUP_MASK_LABEL] = (LLSD::Integer)perm.getMaskGroup();
+ rv[PERM_EVERYONE_MASK_LABEL] = (LLSD::Integer)perm.getMaskEveryone();
+ rv[PERM_NEXT_OWNER_MASK_LABEL] = (LLSD::Integer)perm.getMaskNextOwner();
}
LLPermissions ll_permissions_from_sd(const LLSD& sd_perm)
{
LLPermissions rv;
- rv.init(
- sd_perm[PERM_CREATOR_ID_LABEL].asUUID(),
- sd_perm[PERM_OWNER_ID_LABEL].asUUID(),
- sd_perm[PERM_LAST_OWNER_ID_LABEL].asUUID(),
- sd_perm[PERM_GROUP_ID_LABEL].asUUID());
-
- // We do a cast to U32 here since LLSD does not attempt to
- // represent unsigned ints.
- PermissionMask mask;
- mask = (U32)(sd_perm[PERM_BASE_MASK_LABEL].asInteger());
- rv.setMaskBase(mask);
- mask = (U32)(sd_perm[PERM_OWNER_MASK_LABEL].asInteger());
- rv.setMaskOwner(mask);
- mask = (U32)(sd_perm[PERM_EVERYONE_MASK_LABEL].asInteger());
- rv.setMaskEveryone(mask);
- mask = (U32)(sd_perm[PERM_GROUP_MASK_LABEL].asInteger());
- rv.setMaskGroup(mask);
- mask = (U32)(sd_perm[PERM_NEXT_OWNER_MASK_LABEL].asInteger());
- rv.setMaskNext(mask);
- rv.fix();
+ rv.importLLSD(sd_perm);
return rv;
}
diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h
index a68abcfa34..82cdc03727 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -299,6 +299,8 @@ public:
bool importLegacyStream(std::istream& input_stream);
bool exportLegacyStream(std::ostream& output_stream) const;
+ void importLLSD(const LLSD& sd_perm);
+
bool operator==(const LLPermissions &rhs) const;
bool operator!=(const LLPermissions &rhs) const;
@@ -435,6 +437,7 @@ protected:
// like 'creator_id', 'owner_id', etc, with the value copied from the
// permission object.
LLSD ll_create_sd_from_permissions(const LLPermissions& perm);
+void ll_fill_sd_from_permissions(LLSD& rv, const LLPermissions& perm);
LLPermissions ll_permissions_from_sd(const LLSD& sd_perm);
#endif
diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp
index 35bbc1dbb1..b4d64bb4fb 100644
--- a/indra/llinventory/llsaleinfo.cpp
+++ b/indra/llinventory/llsaleinfo.cpp
@@ -90,15 +90,20 @@ bool LLSaleInfo::exportLegacyStream(std::ostream& output_stream) const
LLSD LLSaleInfo::asLLSD() const
{
LLSD sd;
+ asLLSD(sd);
+ return sd;
+}
+
+void LLSaleInfo::asLLSD(LLSD& sd) const
+{
const char* type = lookup(mSaleType);
if (!type)
{
LL_WARNS_ONCE() << "Unknown sale type: " << mSaleType << LL_ENDL;
type = lookup(LLSaleInfo::FS_NOT);
}
- sd["sale_type"] = type;
+ sd["sale_type"] = std::string(type);
sd["sale_price"] = mSalePrice;
- return sd;
}
bool LLSaleInfo::fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask)
diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h
index 44eb841641..7186e8ab49 100644
--- a/indra/llinventory/llsaleinfo.h
+++ b/indra/llinventory/llsaleinfo.h
@@ -86,6 +86,7 @@ public:
bool exportLegacyStream(std::ostream& output_stream) const;
LLSD asLLSD() const;
+ void asLLSD(LLSD &sd) const;
operator LLSD() const { return asLLSD(); }
bool fromLLSD(const LLSD& sd, bool& has_perm_mask, U32& perm_mask);
bool importLegacyStream(std::istream& input_stream, bool& has_perm_mask, U32& perm_mask);
diff --git a/indra/llinventory/llsettingsbase.cpp b/indra/llinventory/llsettingsbase.cpp
index 0ee71de3a1..d7a94d61a5 100644
--- a/indra/llinventory/llsettingsbase.cpp
+++ b/indra/llinventory/llsettingsbase.cpp
@@ -130,17 +130,6 @@ void LLSettingsBase::saveValuesIfNeeded()
}
//=========================================================================
-void LLSettingsBase::lerpSettings(LLSettingsBase &other, F64 mix)
-{
- LL_PROFILE_ZONE_SCOPED_CATEGORY_ENVIRONMENT;
- saveValuesIfNeeded();
- stringset_t skip = getSkipInterpolateKeys();
- stringset_t slerps = getSlerpKeys();
- mSettings = interpolateSDMap(mSettings, other.getSettings(), other.getParameterMap(), mix, skip, slerps);
- setDirtyFlag(true);
- loadValuesFromLLSD();
-}
-
void LLSettingsBase::lerpVector2(LLVector2& a, const LLVector2& b, F32 mix)
{
a.mV[0] = lerp(a.mV[0], b.mV[0], mix);
@@ -372,14 +361,12 @@ LLSD LLSettingsBase::interpolateSDValue(const std::string& key_name, const LLSD
new_array = q.getValue();
}
else
- { // TODO: We could expand this to inspect the type and do a deep lerp based on type.
- // for now assume a heterogeneous array of reals.
+ {
size_t len = std::max(value.size(), other_value.size());
for (size_t i = 0; i < len; ++i)
{
-
- new_array[i] = lerp((F32)value[i].asReal(), (F32)other_value[i].asReal(), (F32)mix);
+ new_array[i] = interpolateSDValue(key_name, value[i], other_value[i], defaults, mix, skip, slerps);
}
}
diff --git a/indra/llinventory/llsettingsbase.h b/indra/llinventory/llsettingsbase.h
index 816ff3e111..bea6fdec97 100644
--- a/indra/llinventory/llsettingsbase.h
+++ b/indra/llinventory/llsettingsbase.h
@@ -348,13 +348,8 @@ protected:
LLSettingsBase();
LLSettingsBase(const LLSD setting);
- static LLSD settingValidation(LLSD settings);
-
typedef std::set stringset_t;
- // combining settings objects. Customize for specific setting types
- virtual void lerpSettings(LLSettingsBase &other, BlendFactor mix);
-
// combining settings maps where it can based on mix rate
// @settings initial value (mix==0)
// @other target value (mix==1)
@@ -403,7 +398,7 @@ protected:
private:
bool mLLSDDirty;
- bool mDirty;
+ bool mDirty; // gates updateSettings
bool mReplaced; // super dirty!
static LLSD combineSDMaps(const LLSD &first, const LLSD &other);
diff --git a/indra/llinventory/llsettingssky.cpp b/indra/llinventory/llsettingssky.cpp
index ff28c30563..4957cf3c02 100644
--- a/indra/llinventory/llsettingssky.cpp
+++ b/indra/llinventory/llsettingssky.cpp
@@ -657,15 +657,16 @@ void LLSettingsSky::blend(LLSettingsBase::ptr_t &end, F64 blendf)
mHasLegacyHaze |= lerp_legacy_float(mHazeDensity, mLegacyHazeDensity, other->mHazeDensity, other->mLegacyHazeDensity, 0.7f, (F32)blendf);
mHasLegacyHaze |= lerp_legacy_float(mDistanceMultiplier, mLegacyDistanceMultiplier, other->mDistanceMultiplier, other->mLegacyDistanceMultiplier, 0.8f, (F32)blendf);
mHasLegacyHaze |= lerp_legacy_float(mDensityMultiplier, mLegacyDensityMultiplier, other->mDensityMultiplier, other->mLegacyDensityMultiplier, 0.0001f, (F32)blendf);
+ mHasLegacyHaze |= lerp_legacy_color(mAmbientColor, mLegacyAmbientColor, other->mAmbientColor, other->mLegacyAmbientColor, LLColor3(0.25f, 0.25f, 0.25f), (F32)blendf);
mHasLegacyHaze |= lerp_legacy_color(mBlueHorizon, mLegacyBlueHorizon, other->mBlueHorizon, other->mLegacyBlueHorizon, LLColor3(0.4954f, 0.4954f, 0.6399f), (F32)blendf);
mHasLegacyHaze |= lerp_legacy_color(mBlueDensity, mLegacyBlueDensity, other->mBlueDensity, other->mLegacyBlueDensity, LLColor3(0.2447f, 0.4487f, 0.7599f), (F32)blendf);
parammapping_t defaults = other->getParameterMap();
stringset_t skip = getSkipInterpolateKeys();
stringset_t slerps = getSlerpKeys();
- mAbsorptionConfigs = interpolateSDMap(mAbsorptionConfigs, other->mAbsorptionConfigs, defaults, blendf, skip, slerps);
- mMieConfigs = interpolateSDMap(mMieConfigs, other->mMieConfigs, defaults, blendf, skip, slerps);
- mRayleighConfigs = interpolateSDMap(mRayleighConfigs, other->mRayleighConfigs, defaults, blendf, skip, slerps);
+ mAbsorptionConfigs = interpolateSDValue("absorption_config", mAbsorptionConfigs, other->mAbsorptionConfigs, defaults, blendf, skip, slerps);
+ mMieConfigs = interpolateSDValue("mie_config", mMieConfigs, other->mMieConfigs, defaults, blendf, skip, slerps);
+ mRayleighConfigs = interpolateSDValue("rayleigh_config", mRayleighConfigs, other->mRayleighConfigs, defaults, blendf, skip, slerps);
setDirtyFlag(true);
setReplaced();
@@ -1932,6 +1933,7 @@ LLUUID LLSettingsSky::getCloudNoiseTextureId() const
void LLSettingsSky::setCloudNoiseTextureId(const LLUUID &id)
{
mCloudTextureId = id;
+ setDirtyFlag(true);
setLLSDDirty();
}
@@ -1976,6 +1978,7 @@ LLVector2 LLSettingsSky::getCloudScrollRate() const
void LLSettingsSky::setCloudScrollRate(const LLVector2 &val)
{
mScrollRate = val;
+ setDirtyFlag(true);
setLLSDDirty();
}
@@ -2134,6 +2137,7 @@ LLUUID LLSettingsSky::getMoonTextureId() const
void LLSettingsSky::setMoonTextureId(LLUUID id)
{
mMoonTextureId = id;
+ setDirtyFlag(true);
setLLSDDirty();
}
@@ -2218,6 +2222,7 @@ LLUUID LLSettingsSky::getSunTextureId() const
void LLSettingsSky::setSunTextureId(LLUUID id)
{
mSunTextureId = id;
+ setDirtyFlag(true);
setLLSDDirty();
}
diff --git a/indra/llinventory/tests/inventorymisc_test.cpp b/indra/llinventory/tests/inventorymisc_test.cpp
index 9779cb8fbc..f11a4c3bf7 100644
--- a/indra/llinventory/tests/inventorymisc_test.cpp
+++ b/indra/llinventory/tests/inventorymisc_test.cpp
@@ -39,6 +39,34 @@
#pragma warning(disable: 4702)
#endif
+void set_random_inventory_metadata(LLInventoryObject* obj)
+{
+ S32 extra = rand() % 4;
+ switch (extra)
+ {
+ case 0:
+ {
+ LLUUID thumbnail_id;
+ thumbnail_id.generate();
+ obj->setThumbnailUUID(thumbnail_id);
+ break;
+ }
+ case 1:
+ obj->setFavorite(true);
+ break;
+ case 2:
+ {
+ LLUUID thumbnail_id;
+ thumbnail_id.generate();
+ obj->setThumbnailUUID(thumbnail_id);
+ obj->setFavorite(true);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
LLPointer create_random_inventory_item()
{
LLUUID item_id;
@@ -75,6 +103,7 @@ LLPointer create_random_inventory_item()
sale_info,
flags,
creation);
+ set_random_inventory_metadata(item);
return item;
}
@@ -90,6 +119,7 @@ LLPointer create_random_inventory_cat()
parent_id,
LLFolderType::FT_NONE,
std::string("Sample category"));
+ set_random_inventory_metadata(cat);
return cat;
}
@@ -290,6 +320,7 @@ namespace tut
src->setCreationDate(new_creation);
// test a save/load cycle to LLSD and back again
+ // Note: ll_create_sd_from_inventory_item does not support metadata
LLSD sd = ll_create_sd_from_inventory_item(src);
LLPointer dst = new LLInventoryItem;
bool successful_parse = dst->fromLLSD(sd);
@@ -329,7 +360,9 @@ namespace tut
}
LLPointer src1 = create_random_inventory_item();
- fileXML << LLSDOStreamer(src1->asLLSD()) << std::endl;
+ LLSD sd;
+ src1->asLLSD(sd);
+ fileXML << LLSDOStreamer(sd) << std::endl;
fileXML.close();
@@ -364,13 +397,13 @@ namespace tut
ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
-
+ ensure_equals("13.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("14.favorites::getIsFavorite() failed", src1->getIsFavorite(), src2->getIsFavorite());
}
template<> template<>
void inventory_object::test<8>()
{
-
LLPointer src1 = create_random_inventory_item();
std::ostringstream ostream;
@@ -390,8 +423,8 @@ namespace tut
ensure_equals("8.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("9.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("10.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
-
-
+ ensure_equals("11.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("12.favorites::getIsFavorite() failed", false, src2->getIsFavorite()); // not supposed to carry over
}
template<> template<>
@@ -421,6 +454,8 @@ namespace tut
ensure_equals("10.name::getName() failed", src1->getName(), src2->getName());
ensure_equals("11.description::getDescription() failed", src1->getDescription(), src2->getDescription());
ensure_equals("12.creation::getCreationDate() failed", src1->getCreationDate(), src2->getCreationDate());
+ ensure_equals("13.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("14.favorites::getIsFavorite() failed", src1->getIsFavorite(), src2->getIsFavorite());
}
//******class LLInventoryCategory*******//
@@ -458,7 +493,9 @@ namespace tut
}
LLPointer src1 = create_random_inventory_cat();
- fileXML << LLSDOStreamer(src1->exportLLSD()) << std::endl;
+ LLSD sd;
+ src1->exportLLSD(sd);
+ fileXML << LLSDOStreamer(sd) << std::endl;
fileXML.close();
llifstream file(filename.c_str());
@@ -481,13 +518,15 @@ namespace tut
file.close();
LLPointer src2 = new LLInventoryCategory();
- src2->importLLSD(s_item);
+ src2->importLLSDMap(s_item);
ensure_equals("1.item id::getUUID() failed", src1->getUUID(), src2->getUUID());
ensure_equals("2.parent::getParentUUID() failed", src1->getParentUUID(), src2->getParentUUID());
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
+ ensure_equals("6.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("7.favorites::getIsFavorite() failed", src1->getIsFavorite(), src2->getIsFavorite());
}
template<> template<>
@@ -507,6 +546,7 @@ namespace tut
ensure_equals("3.type::getType() failed", src1->getType(), src2->getType());
ensure_equals("4.preferred type::getPreferredType() failed", src1->getPreferredType(), src2->getPreferredType());
ensure_equals("5.name::getName() failed", src1->getName(), src2->getName());
-
+ ensure_equals("13.thumbnails::getThumbnailUUID() failed", src1->getThumbnailUUID(), src2->getThumbnailUUID());
+ ensure_equals("14.favorites::getIsFavorite() failed", false, src2->getIsFavorite()); // currently not supposed to carry over
}
}
diff --git a/indra/llkdu/CMakeLists.txt b/indra/llkdu/CMakeLists.txt
index 7cd9f5eb24..411fff34ae 100644
--- a/indra/llkdu/CMakeLists.txt
+++ b/indra/llkdu/CMakeLists.txt
@@ -27,14 +27,6 @@ set(llkdu_HEADER_FILES
list(APPEND llkdu_SOURCE_FILES ${llkdu_HEADER_FILES})
-# Our KDU package is built with KDU_X86_INTRINSICS in its .vcxproj file.
-# Unless that macro is also set for every consumer build, KDU freaks out,
-# spamming the viewer log with alignment FUD.
-set_source_files_properties(${llkdu_SOURCE_FILES}
- PROPERTIES
- COMPILE_DEFINITIONS
- "KDU_X86_INTRINSICS")
-
if (USE_KDU)
add_library (llkdu ${llkdu_SOURCE_FILES})
@@ -42,10 +34,7 @@ if (USE_KDU)
target_include_directories( llkdu INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
# Add tests
- # ND: llkdu tests are very strange as they include stubs for KDU classes/methods
- # if not having access to the right KDU version this test will fail to compile, incidentally I do not
- # have access to a matching version of KDU and thus cannot get this tests to compile
- if (LL_TESTS_KDU)
+ if (LL_TESTS)
include(LLAddBuildTest)
include(Tut)
SET(llkdu_TEST_SOURCE_FILES
@@ -62,6 +51,6 @@ if (USE_KDU)
set_property( SOURCE ${llkdu_TEST_SOURCE_FILES} PROPERTY LL_TEST_ADDITIONAL_INCLUDE_DIRS ${llimage_include_dir})
LL_ADD_PROJECT_UNIT_TESTS(llkdu "${llkdu_TEST_SOURCE_FILES}")
- endif (LL_TESTS_KDU)
+ endif (LL_TESTS)
endif (USE_KDU)
diff --git a/indra/llkdu/llimagej2ckdu.cpp b/indra/llkdu/llimagej2ckdu.cpp
index bf7cfbe071..7eba9494a6 100644
--- a/indra/llkdu/llimagej2ckdu.cpp
+++ b/indra/llkdu/llimagej2ckdu.cpp
@@ -163,6 +163,7 @@ private:
S32 mNumComponents;
bool mUseYCC;
kdu_dims mDims;
+ kdu_push_pull_params mParams;
kdu_sample_allocator mAllocator;
kdu_tile_comp mComps[4];
kdu_line_buf mLines[4];
@@ -255,7 +256,7 @@ LLImageJ2CKDU::LLImageJ2CKDU() : LLImageJ2CImpl(),
mCodeStreamp(),
mTPosp(),
mTileIndicesp(),
- mRawImagep(NULL),
+ mRawImagep(nullptr),
mDecodeState(),
mBlocksSize(-1),
mPrecinctsSize(-1),
@@ -279,103 +280,118 @@ void LLImageJ2CKDU::setupCodeStream(LLImageJ2C &base, bool keep_codestream, ECod
{
LLImageDataLock lock(&base);
- S32 data_size = base.getDataSize();
- S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
-
- //
- // Initialization
- //
- mCodeStreamp.reset();
-
- // It's not clear to nat under what circumstances we would reuse a
- // pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
- // two U32s and a pointer, so it's not as if it would be a huge overhead
- // to allocate a new one every time.
- // Also -- why is base.getData() tested specifically here? If that returns
- // NULL, shouldn't we bail out of the whole method?
- if (!mInputp && base.getData())
+ try
{
- // The compressed data has been loaded
- // Setup the source for the codestream
- mInputp.reset(new LLKDUMemSource(base.getData(), data_size));
- }
- if (mInputp)
- {
- // This is LLKDUMemSource::reset(), not boost::scoped_ptr::reset().
- mInputp->reset();
- }
+ S32 data_size = base.getDataSize();
+ S32 max_bytes = (base.getMaxBytes() ? base.getMaxBytes() : data_size);
- mCodeStreamp->create(mInputp.get());
+ //
+ // Initialization
+ //
+ mCodeStreamp.reset();
- // Set the maximum number of bytes to use from the codestream
- // *TODO: This seems to be wrong. The base class should have no idea of
- // how j2c compression works so no good way of computing what's the byte
- // range to be used.
- mCodeStreamp->set_max_bytes(max_bytes,true);
-
- // If you want to flip or rotate the image for some reason, change
- // the resolution, or identify a restricted region of interest, this is
- // the place to do it. You may use "kdu_codestream::change_appearance"
- // and "kdu_codestream::apply_input_restrictions" for this purpose.
- // If you wish to truncate the code-stream prior to decompression, you
- // may use "kdu_codestream::set_max_bytes".
- // If you wish to retain all compressed data so that the material
- // can be decompressed multiple times, possibly with different appearance
- // parameters, you should call "kdu_codestream::set_persistent" here.
- // There are a variety of other features which must be enabled at
- // this point if you want to take advantage of them. See the
- // descriptions appearing with the "kdu_codestream" interface functions
- // in "kdu_compressed.h" for an itemized account of these capabilities.
-
- switch (mode)
- {
- case MODE_FAST:
- mCodeStreamp->set_fast();
- break;
- case MODE_RESILIENT:
- mCodeStreamp->set_resilient();
- break;
- case MODE_FUSSY:
- mCodeStreamp->set_fussy();
- break;
- default:
- llassert(0);
- mCodeStreamp->set_fast();
- }
-
- kdu_dims dims;
- mCodeStreamp->get_dims(0,dims);
-
- S32 components = mCodeStreamp->get_num_components();
-
- // Check that components have consistent dimensions (for PPM file)
- for (int idx = 1; idx < components; ++idx)
- {
- kdu_dims other_dims;
- mCodeStreamp->get_dims(idx, other_dims);
- if (other_dims != dims)
+ // It's not clear to nat under what circumstances we would reuse a
+ // pre-existing LLKDUMemSource instance. As of 2016-08-05, it consists of
+ // two U32s and a pointer, so it's not as if it would be a huge overhead
+ // to allocate a new one every time.
+ // Also -- why is base.getData() tested specifically here? If that returns
+ // nullptr, shouldn't we bail out of the whole method?
+ if (!mInputp && base.getData())
{
- // This method is only called from methods that catch KDUError.
- // We want to fail the image load, not crash the viewer.
- LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
- << stringize(other_dims)
- << " do not match component 0 dimensions "
- << stringize(dims) << "!")));
+ // The compressed data has been loaded
+ // Setup the source for the codestream
+ mInputp = std::make_unique(base.getData(), data_size);
+ }
+
+ if (mInputp)
+ {
+ // This is LLKDUMemSource::reset(), not std::unique_ptr::reset().
+ mInputp->reset();
+ }
+
+ mCodeStreamp->create(mInputp.get());
+
+ // Set the maximum number of bytes to use from the codestream
+ // *TODO: This seems to be wrong. The base class should have no idea of
+ // how j2c compression works so no good way of computing what's the byte
+ // range to be used.
+ mCodeStreamp->set_max_bytes(max_bytes);
+
+ // If you want to flip or rotate the image for some reason, change
+ // the resolution, or identify a restricted region of interest, this is
+ // the place to do it. You may use "kdu_codestream::change_appearance"
+ // and "kdu_codestream::apply_input_restrictions" for this purpose.
+ // If you wish to truncate the code-stream prior to decompression, you
+ // may use "kdu_codestream::set_max_bytes".
+ // If you wish to retain all compressed data so that the material
+ // can be decompressed multiple times, possibly with different appearance
+ // parameters, you should call "kdu_codestream::set_persistent" here.
+ // There are a variety of other features which must be enabled at
+ // this point if you want to take advantage of them. See the
+ // descriptions appearing with the "kdu_codestream" interface functions
+ // in "kdu_compressed.h" for an itemized account of these capabilities.
+
+ switch (mode)
+ {
+ case MODE_FAST:
+ mCodeStreamp->set_fast();
+ break;
+ case MODE_RESILIENT:
+ mCodeStreamp->set_resilient();
+ break;
+ case MODE_FUSSY:
+ mCodeStreamp->set_fussy();
+ break;
+ default:
+ llassert(0);
+ mCodeStreamp->set_fast();
+ }
+
+ kdu_dims dims;
+ mCodeStreamp->get_dims(0, dims);
+
+ S32 components = mCodeStreamp->get_num_components();
+
+ // Check that components have consistent dimensions (for PPM file)
+ for (int idx = 1; idx < components; ++idx)
+ {
+ kdu_dims other_dims;
+ mCodeStreamp->get_dims(idx, other_dims);
+ if (other_dims != dims)
+ {
+ // This method is only called from methods that catch KDUError.
+ // We want to fail the image load, not crash the viewer.
+ LLTHROW(KDUError(STRINGIZE("Component " << idx << " dimensions "
+ << stringize(other_dims)
+ << " do not match component 0 dimensions "
+ << stringize(dims) << "!")));
+ }
+ }
+
+ // Get the number of resolution levels in that image
+ mLevels = mCodeStreamp->get_min_dwt_levels();
+
+ // Set the base dimensions
+ base.setSize(dims.size.x, dims.size.y, components);
+ base.setLevels(mLevels);
+
+ if (!keep_codestream)
+ {
+ mCodeStreamp.reset();
+ mInputp.reset();
}
}
-
- // Get the number of resolution levels in that image
- mLevels = mCodeStreamp->get_min_dwt_levels();
-
- // Set the base dimensions
- base.setSize(dims.size.x, dims.size.y, components);
- base.setLevels(mLevels);
-
- if (!keep_codestream)
+ catch (std::bad_alloc&)
{
- mCodeStreamp.reset();
- mInputp.reset();
+ // we are in a thread, can't show an 'out of memory' here,
+ // main thread will keep going
+ throw;
+ }
+ catch (...)
+ {
+ LLTHROW(KDUError(STRINGIZE("Unknown J2C error : " +
+ boost::current_exception_diagnostic_information() << "!")));
}
}
@@ -446,8 +462,8 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
mCodeStreamp->change_appearance(false, true, false);
// Apply loading discard level and cropping if required
- kdu_dims* region_kdu = NULL;
- if (region != NULL)
+ kdu_dims* region_kdu = nullptr;
+ if (region != nullptr)
{
region_kdu = new kdu_dims;
region_kdu->pos.x = region[0];
@@ -464,7 +480,7 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
if (region_kdu)
{
delete region_kdu;
- region_kdu = NULL;
+ region_kdu = nullptr;
}
// Resize raw_image according to the image to be decoded
@@ -475,12 +491,12 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
if (!mTileIndicesp)
{
- mTileIndicesp.reset(new kdu_dims);
+ mTileIndicesp = std::make_unique();
}
mCodeStreamp->get_valid_tiles(*mTileIndicesp);
if (!mTPosp)
{
- mTPosp.reset(new kdu_coords);
+ mTPosp = std::make_unique();
mTPosp->y = 0;
mTPosp->x = 0;
}
@@ -490,7 +506,7 @@ bool LLImageJ2CKDU::initDecode(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
base.setLastError(msg.what());
return false;
}
- catch (kdu_exception kdu_value)
+ catch (const kdu_exception& kdu_value)
{
// KDU internally throws kdu_exception. It's possible that such an
// exception might leak out into our code. Catch kdu_exception
@@ -581,8 +597,7 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
kdu_coords offset = tile_dims.pos - dims.pos;
int row_gap = channels*dims.size.x; // inter-row separation
kdu_byte *buf = buffer + offset.y*row_gap + offset.x*channels;
- mDecodeState.reset(new LLKDUDecodeState(tile, buf, row_gap,
- mCodeStreamp.get()));
+ mDecodeState = std::make_unique(tile, buf, row_gap, mCodeStreamp.get());
}
// Do the actual processing
F32 remaining_time = limit_time ? decode_time - decode_timer.getElapsedTimeF32().value() : 0.0f;
@@ -607,7 +622,7 @@ bool LLImageJ2CKDU::decodeImpl(LLImageJ2C &base, LLImageRaw &raw_image, F32 deco
cleanupCodeStream();
return true; // done
}
- catch (kdu_exception kdu_value)
+ catch (const kdu_exception& kdu_value)
{
// KDU internally throws kdu_exception. It's possible that such an
// exception might leak out into our code. Catch kdu_exception
@@ -647,6 +662,12 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
bool vflip = true;
bool hflip = false;
+ if (raw_image.isBufferInvalid())
+ {
+ base.setLastError("Invalid input, no buffer");
+ return false;
+ }
+
try
{
// Set up input image files
@@ -810,7 +831,7 @@ bool LLImageJ2CKDU::encodeImpl(LLImageJ2C &base, const LLImageRaw &raw_image, co
base.setLastError(msg.what());
return false;
}
- catch (kdu_exception kdu_value)
+ catch (const kdu_exception& kdu_value)
{
// KDU internally throws kdu_exception. It's possible that such an
// exception might leak out into our code. Catch kdu_exception
@@ -844,7 +865,7 @@ bool LLImageJ2CKDU::getMetadata(LLImageJ2C &base)
base.setLastError(msg.what());
return false;
}
- catch (kdu_exception kdu_value)
+ catch (const kdu_exception& kdu_value)
{
// KDU internally throws kdu_exception. It's possible that such an
// exception might leak out into our code. Catch kdu_exception
@@ -976,8 +997,8 @@ void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
//std::cout << "Parsing discard level = " << discard_level << std::endl;
// Create the input codestream object.
setupCodeStream(base, true, MODE_FAST);
- mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, NULL);
- mCodeStreamp->set_max_bytes(KDU_LONG_MAX,true);
+ mCodeStreamp->apply_input_restrictions(0, 4, discard_level, 0, nullptr);
+ mCodeStreamp->set_max_bytes(KDU_LONG_MAX,false);
siz_params *siz_in = mCodeStreamp->access_siz();
// Create the output codestream object.
@@ -1073,8 +1094,10 @@ void LLImageJ2CKDU::findDiscardLevelsBoundaries(LLImageJ2C &base)
void set_default_colour_weights(kdu_params *siz)
{
+ kdu_params *enc = siz->access_cluster(ENC_params);
+ assert(enc != nullptr);
kdu_params *cod = siz->access_cluster(COD_params);
- assert(cod != NULL);
+ assert(cod != nullptr);
bool can_use_ycc = true;
bool rev0 = false;
@@ -1111,7 +1134,7 @@ void set_default_colour_weights(kdu_params *siz)
return;
}
float weight;
- if (cod->get(Clev_weights,0,0,weight) || cod->get(Cband_weights,0,0,weight))
+ if (enc->get(Clev_weights,0,0,weight) || enc->get(Cband_weights,0,0,weight))
{
// Weights already specified explicitly -> nothing to do
return;
@@ -1120,17 +1143,16 @@ void set_default_colour_weights(kdu_params *siz)
// These example weights are adapted from numbers generated by Marcus Nadenau
// at EPFL, for a viewing distance of 15 cm and a display resolution of
// 300 DPI.
-
- cod->parse_string("Cband_weights:C0="
+ enc->parse_string("Cband_weights:C0="
"{0.0901},{0.2758},{0.2758},"
"{0.7018},{0.8378},{0.8378},{1}");
- cod->parse_string("Cband_weights:C1="
+ enc->parse_string("Cband_weights:C1="
"{0.0263},{0.0863},{0.0863},"
"{0.1362},{0.2564},{0.2564},"
"{0.3346},{0.4691},{0.4691},"
"{0.5444},{0.6523},{0.6523},"
"{0.7078},{0.7797},{0.7797},{1}");
- cod->parse_string("Cband_weights:C2="
+ enc->parse_string("Cband_weights:C2="
"{0.0773},{0.1835},{0.1835},"
"{0.2598},{0.4130},{0.4130},"
"{0.5040},{0.6464},{0.6464},"
@@ -1149,7 +1171,7 @@ byte buffer, spacing successive output samples apart by `gap' bytes
all necessary level shifting, type conversion, rounding and truncation. */
{
int width = src.get_width();
- if (src.get_buf32() != NULL)
+ if (src.get_buf32() != nullptr)
{ // Decompressed samples have a 32-bit representation (integer or float)
assert(precision >= 8); // Else would have used 16 bit representation
kdu_sample32 *sp = src.get_buf32();
@@ -1312,11 +1334,11 @@ LLKDUDecodeState::LLKDUDecodeState(kdu_tile tile, kdu_byte *buf, S32 row_gap,
mLines[c].pre_create(&mAllocator,mDims.size.x,mReversible[c],use_shorts,0,0);
if (res.which() == 0) // No DWT levels used
{
- mEngines[c] = kdu_decoder(res.access_subband(LL_BAND),&mAllocator,use_shorts);
+ mEngines[c] = kdu_decoder(res.access_subband(LL_BAND), &mAllocator, mParams, use_shorts);
}
else
{
- mEngines[c] = kdu_synthesis(res,&mAllocator,use_shorts);
+ mEngines[c] = kdu_synthesis(res, &mAllocator, mParams, use_shorts);
}
}
mAllocator.finalize(*codestreamp); // Actually creates buffering resources
@@ -1394,7 +1416,7 @@ kdc_flow_control::kdc_flow_control (kdu_supp::kdu_image_in_base *img_in, kdu_cod
this->codestream = codestream;
codestream.get_valid_tiles(valid_tile_indices);
tile_idx = valid_tile_indices.pos;
- tile = codestream.open_tile(tile_idx,NULL);
+ tile = codestream.open_tile(tile_idx, nullptr);
// Set up the individual components
num_components = codestream.get_num_components(true);
@@ -1403,7 +1425,7 @@ kdc_flow_control::kdc_flow_control (kdu_supp::kdu_image_in_base *img_in, kdu_cod
kdc_component_flow_control *comp = components;
for (n = 0; n < num_components; n++, comp++)
{
- comp->line = NULL;
+ comp->line = nullptr;
comp->reader = img_in;
kdu_coords subsampling;
codestream.get_subsampling(n,subsampling,true);
@@ -1420,12 +1442,12 @@ kdc_flow_control::kdc_flow_control (kdu_supp::kdu_image_in_base *img_in, kdu_cod
assert(num_components >= 0);
tile.set_components_of_interest(num_components);
- max_buffer_memory = engine.create(codestream,tile,false,NULL,false,1,NULL,NULL,false);
+ max_buffer_memory = engine.create(codestream, tile, false, nullptr, false, 1, nullptr, nullptr,false);
}
kdc_flow_control::~kdc_flow_control()
{
- if (components != NULL)
+ if (components != nullptr)
{
delete[] components;
}
@@ -1452,8 +1474,8 @@ bool kdc_flow_control::advance_components()
if (comp->ratio_counter < 0)
{
found_line = true;
- comp->line = engine.exchange_line(n,NULL,NULL);
- assert(comp->line != NULL);
+ comp->line = engine.exchange_line(n,nullptr,nullptr);
+ assert(comp->line != nullptr);
if (comp->line->get_width())
{
comp->reader->get(n,*(comp->line),0);
@@ -1480,9 +1502,9 @@ void kdc_flow_control::process_components()
assert(comp->ratio_counter >= 0);
assert(comp->remaining_lines > 0);
comp->remaining_lines--;
- assert(comp->line != NULL);
- engine.exchange_line(n,comp->line,NULL);
- comp->line = NULL;
+ assert(comp->line != nullptr);
+ engine.exchange_line(n,comp->line,nullptr);
+ comp->line = nullptr;
}
}
}
diff --git a/indra/llkdu/llimagej2ckdu.h b/indra/llkdu/llimagej2ckdu.h
index 8037c81868..c9aa0c5250 100644
--- a/indra/llkdu/llimagej2ckdu.h
+++ b/indra/llkdu/llimagej2ckdu.h
@@ -27,12 +27,13 @@
#ifndef LL_LLIMAGEJ2CKDU_H
#define LL_LLIMAGEJ2CKDU_H
+#include "llpreprocessor.h"
+
#include "llimagej2c.h"
//
// KDU core header files
//
-#define KDU_NO_THREADS
#include "kdu_elementary.h"
#include "kdu_messaging.h"
#include "kdu_params.h"
@@ -41,7 +42,6 @@
#include "include_kdu_xxxx.h"
#include "kdu_sample_processing.h"
-#include
#include
class LLKDUDecodeState;
diff --git a/indra/llkdu/llkdumem.h b/indra/llkdu/llkdumem.h
index 177a8ea976..56aff13c76 100644
--- a/indra/llkdu/llkdumem.h
+++ b/indra/llkdu/llkdumem.h
@@ -27,9 +27,9 @@
#ifndef LL_LLKDUMEM_H
#define LL_LLKDUMEM_H
-// Support classes for reading and writing from memory buffers in KDU
-#define KDU_NO_THREADS
+#include "llpreprocessor.h"
+// Support classes for reading and writing from memory buffers in KDU
#define kdu_xxxx "kdu_image.h"
#include "include_kdu_xxxx.h"
@@ -54,9 +54,7 @@ public:
mCurPos = 0;
}
- ~LLKDUMemSource()
- {
- }
+ ~LLKDUMemSource() = default;
int read(kdu_core::kdu_byte *buf, int num_bytes)
{
@@ -94,9 +92,7 @@ public:
mOutputSize = &output_size;
}
- ~LLKDUMemTarget()
- {
- }
+ ~LLKDUMemTarget() = default;
bool write(const kdu_core::kdu_byte *buf, int num_bytes)
{
diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp
index db81d60d9e..bc52a15c4a 100644
--- a/indra/llkdu/tests/llimagej2ckdu_test.cpp
+++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp
@@ -80,6 +80,7 @@ U8* LLImageBase::getData() { return NULL; }
U8* LLImageBase::reallocateData(S32 ) { return NULL; }
void LLImageBase::sanityCheck() { }
void LLImageBase::setSize(S32 , S32 , S32 ) { }
+bool LLImageBase::isBufferInvalid() const { return false; }
LLImageJ2CImpl::~LLImageJ2CImpl() { }
@@ -139,18 +140,19 @@ int kdu_tile_comp::get_bit_depth(bool ) { return 8; }
bool kdu_tile_comp::get_reversible() { return false; }
int kdu_tile_comp::get_num_resolutions() { return 1; }
kdu_subband kdu_resolution::access_subband(int ) { kdu_subband a; return a; }
-void kdu_resolution::get_dims(kdu_dims& ) { }
-int kdu_resolution::which() { return 0; }
-int kdu_resolution::get_valid_band_indices(int &) { return 1; }
-kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { }
+void kdu_resolution::get_dims(kdu_dims& ) const { }
+int kdu_resolution::which() const { return 0; }
+int kdu_resolution::get_valid_band_indices(int &) const { return 1; }
+kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, kdu_push_pull_params&, bool, float, kdu_thread_env*, kdu_thread_queue*) { }
//kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { }
-kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool, kd_core_local::kd_coremem*) {}
+kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) {}
kdu_params::~kdu_params() { }
+void kdu_params::destroy() { }
void kdu_params::set(const char* , int , int , bool ) { }
void kdu_params::set(const char* , int , int , int ) { }
void kdu_params::finalize_all(bool ) { }
void kdu_params::finalize_all(int, bool ) { }
-void kdu_params::copy_from(kdu_params*, int, int, int, int, int, bool, bool, bool) { }
+void kdu_params::copy_from(kdu_params*, int, int, int, int, int, bool, bool, bool, bool) { }
bool kdu_params::parse_string(const char*) { return false; }
bool kdu_params::get(const char*, int, int, bool&, bool, bool, bool) { return false; }
bool kdu_params::get(const char*, int, int, float&, bool, bool, bool) { return false; }
@@ -159,13 +161,13 @@ kdu_params* kdu_params::access_relation(int, int, int, bool) { return NULL; }
kdu_params* kdu_params::access_cluster(const char*) { return NULL; }
void kdu_codestream::set_fast() { }
void kdu_codestream::set_fussy() { }
-void kdu_codestream::get_dims(int, kdu_dims&, bool ) { }
+void kdu_codestream::get_dims(int, kdu_dims&, bool ) const { }
int kdu_codestream::get_min_dwt_levels() { return 5; }
int kdu_codestream::get_max_tile_layers() { return 1; }
void kdu_codestream::change_appearance(bool, bool, bool, kdu_thread_env *) {}
void kdu_codestream::get_tile_dims(kdu_coords, int, kdu_dims&, bool ) { }
void kdu_codestream::destroy() { }
-void kdu_codestream::collect_timing_stats(int ) { }
+void kdu_codestream::collect_timing_stats(int ) const { }
void kdu_codestream::set_max_bytes(kdu_long, bool, bool ) { }
void kdu_codestream::get_valid_tiles(kdu_dims& ) { }
void kdu_codestream::create(
@@ -182,19 +184,21 @@ void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { }
void kdu_codestream::flush(kdu_long *, int, kdu_uint16 *, bool, bool, double, kdu_thread_env*, int) { }
void kdu_codestream::set_resilient(bool ) { }
int kdu_codestream::get_num_components(bool ) { return 0; }
-kdu_long kdu_codestream::get_total_bytes(bool ) { return 0; }
+kdu_long kdu_codestream::get_total_bytes(bool ) const { return 0; }
kdu_long kdu_codestream::get_compressed_data_memory(bool ) const {return 0; }
void kdu_codestream::share_buffering(kdu_codestream ) { }
-int kdu_codestream::get_num_tparts() { return 0; }
+int kdu_codestream::get_num_tparts() const { return 0; }
int kdu_codestream::trans_out(kdu_long, kdu_long*, int, bool, kdu_thread_env* ) { return 0; }
bool kdu_codestream::ready_for_flush(kdu_thread_env*) { return false; }
siz_params* kdu_codestream::access_siz() { return NULL; }
kdu_tile kdu_codestream::open_tile(kdu_coords , kdu_thread_env* ) { kdu_tile a; return a; }
kdu_codestream_comment kdu_codestream::add_comment(kdu_thread_env*) { kdu_codestream_comment a; return a; }
+kdu_codestream_comment kdu_codestream::get_comment(kdu_codestream_comment) { kdu_codestream_comment a; return a; };
void kdu_subband::close_block(kdu_block*, kdu_thread_env*) { }
void kdu_subband::get_valid_blocks(kdu_dims &indices) const { }
kdu_block * kdu_subband::open_block(kdu_coords, int *, kdu_thread_env *, int, bool) { return NULL; }
bool kdu_codestream_comment::put_text(const char*) { return false; }
+const char *kdu_codestream_comment::get_text() { return nullptr; };
void kdu_customize_warnings(kdu_message*) { }
void kdu_customize_errors(kdu_message*) { }
kdu_long kdu_multi_analysis::create(
@@ -209,16 +213,18 @@ kdu_long kdu_multi_analysis::create(
const kdu_push_pull_params*,
kdu_membroker*) { return kdu_long(0); }
void kdu_multi_analysis::destroy(kdu_thread_env *) {}
+siz_params::siz_params() : kdu_params(NULL, false, false, false, false, false) { }
siz_params::siz_params(kd_core_local::kd_coremem*) : kdu_params(NULL, false, false, false, false, false) { }
siz_params::~siz_params() {}
void siz_params::finalize(bool ) { }
void siz_params::copy_with_xforms(kdu_params*, int, int, bool, bool, bool) { }
-int siz_params::write_marker_segment(kdu_output*, kdu_params*, int) { return 0; }
+int siz_params::write_marker_segment(kdu_output*, kdu_params*, int, int&) { return 0; }
bool siz_params::check_marker_segment(kdu_uint16, int, kdu_byte a[], int&) { return false; }
-bool siz_params::read_marker_segment(kdu_uint16, int, kdu_byte a[], int) { return false; }
+int siz_params::read_marker_segment(kdu_uint16 code, int num_bytes, kdu_byte bytes[], int tpart_idx) { return false; }
kdu_decoder::kdu_decoder(
kdu_subband subband,
kdu_sample_allocator*,
+ kdu_push_pull_params&,
bool, float, int,
kdu_thread_env*,
kdu_thread_queue*,
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index eb29df245a..bd860adc31 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -6,6 +6,7 @@ include(00-Common)
include(LLCommon)
include(bugsplat)
include(Boost)
+include(SSE2NEON)
set(llmath_SOURCE_FILES
llbbox.cpp
@@ -59,6 +60,7 @@ set(llmath_HEADER_FILES
llmath.h
llmatrix3a.h
llmatrix3a.inl
+ llmatrix4a.h
llmodularmath.h
lloctree.h
llperlin.h
@@ -99,7 +101,7 @@ list(APPEND llmath_SOURCE_FILES ${llmath_HEADER_FILES})
add_library (llmath ${llmath_SOURCE_FILES})
-target_link_libraries(llmath llcommon llmeshoptimizer)
+target_link_libraries(llmath llcommon llmeshoptimizer ll::sse2neon)
target_include_directories( llmath INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
# Add tests
diff --git a/indra/llmath/llbbox.h b/indra/llmath/llbbox.h
index 5617eaebde..3a4e09a598 100644
--- a/indra/llmath/llbbox.h
+++ b/indra/llmath/llbbox.h
@@ -95,6 +95,10 @@ private:
bool mEmpty; // Nothing has been added to this bbox yet
};
+static_assert(std::is_trivially_copyable::value, "LLBBox must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLBBox must be trivial move");
+static_assert(std::is_standard_layout::value, "LLBBox must be a standard layout type");
+
//LLBBox operator*(const LLBBox &a, const LLMatrix4 &b);
diff --git a/indra/llmath/llbboxlocal.h b/indra/llmath/llbboxlocal.h
index e215e55460..f743bc0ee4 100644
--- a/indra/llmath/llbboxlocal.h
+++ b/indra/llmath/llbboxlocal.h
@@ -61,5 +61,8 @@ private:
LLBBoxLocal operator*(const LLBBoxLocal &a, const LLMatrix4 &b);
+static_assert(std::is_trivially_copyable::value, "LLBBoxLocal must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLBBoxLocal must be trivial move");
+static_assert(std::is_standard_layout::value, "LLBBoxLocal must be a standard layout type");
#endif // LL_BBOXLOCAL_H
diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h
index b6e0e4a2be..6201761c46 100644
--- a/indra/llmath/llcamera.h
+++ b/indra/llmath/llcamera.h
@@ -33,23 +33,23 @@
#include "llplane.h"
#include "llvector4a.h"
-const F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD;
-const F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f;
-const F32 DEFAULT_NEAR_PLANE = 0.25f;
-const F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions
+constexpr F32 DEFAULT_FIELD_OF_VIEW = 60.f * DEG_TO_RAD;
+constexpr F32 DEFAULT_ASPECT_RATIO = 640.f / 480.f;
+constexpr F32 DEFAULT_NEAR_PLANE = 0.25f;
+constexpr F32 DEFAULT_FAR_PLANE = 64.f; // far reaches across two horizontal, not diagonal, regions
-const F32 MAX_ASPECT_RATIO = 50.0f;
-const F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends
-const F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though.
-const F32 MAX_FAR_CLIP = 512.0f;
+constexpr F32 MAX_ASPECT_RATIO = 50.0f;
+constexpr F32 MAX_NEAR_PLANE = 1023.9f; // Clamp the near plane just before the skybox ends
+constexpr F32 MAX_FAR_PLANE = 100000.0f; //1000000.0f; // Max allowed. Not good Z precision though.
+constexpr F32 MAX_FAR_CLIP = 512.0f;
-const F32 MIN_ASPECT_RATIO = 0.02f;
-const F32 MIN_NEAR_PLANE = 0.1f;
-const F32 MIN_FAR_PLANE = 0.2f;
+constexpr F32 MIN_ASPECT_RATIO = 0.02f;
+constexpr F32 MIN_NEAR_PLANE = 0.1f;
+constexpr F32 MIN_FAR_PLANE = 0.2f;
// Min/Max FOV values for square views. Call getMin/MaxView to get extremes based on current aspect ratio.
-static const F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD;
-static const F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
+constexpr F32 MIN_FIELD_OF_VIEW = 5.0f * DEG_TO_RAD;
+constexpr F32 MAX_FIELD_OF_VIEW = 175.f * DEG_TO_RAD;
// An LLCamera is an LLCoorFrame with a view frustum.
// This means that it has several methods for moving it around
diff --git a/indra/llmath/llcoordframe.cpp b/indra/llmath/llcoordframe.cpp
index 4d6276b2cd..b42541c7c0 100644
--- a/indra/llmath/llcoordframe.cpp
+++ b/indra/llmath/llcoordframe.cpp
@@ -26,7 +26,6 @@
#include "linden_common.h"
-//#include "vmath.h"
#include "v3math.h"
#include "m3math.h"
#include "v4math.h"
@@ -329,28 +328,30 @@ void LLCoordFrame::rotate(const LLMatrix3 &rotation_matrix)
}
+// Rotate 2 normalized orthogonal vectors in direction from `source` to `target`
+static void rotate2(LLVector3& source, LLVector3& target, F32 angle)
+{
+ F32 sx = source[VX], sy = source[VY], sz = source[VZ];
+ F32 tx = target[VX], ty = target[VY], tz = target[VZ];
+ F32 c = cosf(angle), s = sinf(angle);
+
+ source.set(sx * c + tx * s, sy * c + ty * s, sz * c + tz * s);
+ target.set(tx * c - sx * s, ty * c - sy * s, tz * c - sz * s);
+}
+
void LLCoordFrame::roll(F32 angle)
{
- LLQuaternion q(angle, mXAxis);
- LLMatrix3 rotation_matrix(q);
- rotate(rotation_matrix);
- CHECK_FINITE_OBJ();
+ rotate2(mYAxis, mZAxis, angle);
}
void LLCoordFrame::pitch(F32 angle)
{
- LLQuaternion q(angle, mYAxis);
- LLMatrix3 rotation_matrix(q);
- rotate(rotation_matrix);
- CHECK_FINITE_OBJ();
+ rotate2(mZAxis, mXAxis, angle);
}
void LLCoordFrame::yaw(F32 angle)
{
- LLQuaternion q(angle, mZAxis);
- LLMatrix3 rotation_matrix(q);
- rotate(rotation_matrix);
- CHECK_FINITE_OBJ();
+ rotate2(mXAxis, mYAxis, angle);
}
// get*() routines
diff --git a/indra/llmath/llcoordframe.h b/indra/llmath/llcoordframe.h
index aaa701f792..458f6132c9 100644
--- a/indra/llmath/llcoordframe.h
+++ b/indra/llmath/llcoordframe.h
@@ -61,7 +61,7 @@ public:
//LLCoordFrame(const F32 *origin, const F32 *rotation); // Assumes "origin" is 1x3 and "rotation" is 1x9 array
//LLCoordFrame(const F32 *origin_and_rotation); // Assumes "origin_and_rotation" is 1x12 array
- bool isFinite() { return mOrigin.isFinite() && mXAxis.isFinite() && mYAxis.isFinite() && mZAxis.isFinite(); }
+ bool isFinite() const { return mOrigin.isFinite() && mXAxis.isFinite() && mYAxis.isFinite() && mZAxis.isFinite(); }
void reset();
void resetAxes();
diff --git a/indra/llmath/llline.h b/indra/llmath/llline.h
index 33c1eb61a4..fa151f8b20 100644
--- a/indra/llmath/llline.h
+++ b/indra/llmath/llline.h
@@ -33,14 +33,14 @@
#include "stdtypes.h"
#include "v3math.h"
-const F32 DEFAULT_INTERSECTION_ERROR = 0.000001f;
+constexpr F32 DEFAULT_INTERSECTION_ERROR = 0.000001f;
class LLLine
{
public:
LLLine();
LLLine( const LLVector3& first_point, const LLVector3& second_point );
- virtual ~LLLine() {};
+ ~LLLine() = default;
void setPointDirection( const LLVector3& first_point, const LLVector3& second_point );
void setPoints( const LLVector3& first_point, const LLVector3& second_point );
@@ -76,5 +76,8 @@ protected:
LLVector3 mDirection;
};
+static_assert(std::is_trivially_copyable::value, "LLLine must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLLine must be trivial move");
+static_assert(std::is_standard_layout::value, "LLLine must be a standard layout type");
#endif
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index fa315291a3..891f0ffc4c 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -39,18 +39,8 @@
// llcommon depend on llmath.
#include "is_approx_equal_fraction.h"
-// work around for Windows & older gcc non-standard function names.
-#if LL_WINDOWS
-#include
-#define llisnan(val) _isnan(val)
-#define llfinite(val) _finite(val)
-#elif (LL_LINUX && __GNUC__ <= 2)
-#define llisnan(val) isnan(val)
-#define llfinite(val) isfinite(val)
-#else
-#define llisnan(val) std::isnan(val)
-#define llfinite(val) std::isfinite(val)
-#endif
+#define llisnan(val) std::isnan(val)
+#define llfinite(val) std::isfinite(val)
// Single Precision Floating Point Routines
// (There used to be more defined here, but they appeared to be redundant and
@@ -75,7 +65,7 @@ constexpr F32 DEG_TO_RAD = 0.017453292519943295769236907684886f;
constexpr F32 RAD_TO_DEG = 57.295779513082320876798154814105f;
constexpr F32 F_APPROXIMATELY_ZERO = 0.00001f;
constexpr F32 F_LN10 = 2.3025850929940456840179914546844f;
-constexpr F32 OO_LN10 = 0.43429448190325182765112891891661;
+constexpr F32 OO_LN10 = 0.43429448190325182765112891891661f;
constexpr F32 F_LN2 = 0.69314718056f;
constexpr F32 OO_LN2 = 1.4426950408889634073599246810019f;
@@ -89,7 +79,7 @@ constexpr F32 GIMBAL_THRESHOLD = 0.000436f; // sets the gimballock threshold 0
constexpr F32 FP_MAG_THRESHOLD = 0.0000001f;
// TODO: Replace with logic like is_approx_equal
-inline bool is_approx_zero( F32 f ) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); }
+constexpr bool is_approx_zero(F32 f) { return (-F_APPROXIMATELY_ZERO < f) && (f < F_APPROXIMATELY_ZERO); }
// These functions work by interpreting sign+exp+mantissa as an unsigned
// integer.
@@ -148,33 +138,17 @@ inline F64 llabs(const F64 a)
return F64(std::fabs(a));
}
-inline S32 lltrunc( F32 f )
+constexpr S32 lltrunc(F32 f)
{
-#if LL_WINDOWS && !defined( __INTEL_COMPILER ) && (ADDRESS_SIZE == 32)
- // Avoids changing the floating point control word.
- // Add or subtract 0.5 - epsilon and then round
- const static U32 zpfp[] = { 0xBEFFFFFF, 0x3EFFFFFF };
- S32 result;
- __asm {
- fld f
- mov eax, f
- shr eax, 29
- and eax, 4
- fadd dword ptr [zpfp + eax]
- fistp result
- }
- return result;
-#else
- return (S32)f;
-#endif
+ return narrow(f);
}
-inline S32 lltrunc( F64 f )
+constexpr S32 lltrunc(F64 f)
{
- return (S32)f;
+ return narrow(f);
}
-inline S32 llfloor( F32 f )
+inline S32 llfloor(F32 f)
{
#if LL_WINDOWS && !defined( __INTEL_COMPILER ) && (ADDRESS_SIZE == 32)
// Avoids changing the floating point control word.
@@ -284,7 +258,7 @@ constexpr F32 FAST_MAG_BETA = 0.397824734759f;
//constexpr F32 FAST_MAG_ALPHA = 0.948059448969f;
//constexpr F32 FAST_MAG_BETA = 0.392699081699f;
-inline F32 fastMagnitude(F32 a, F32 b)
+constexpr F32 fastMagnitude(F32 a, F32 b)
{
a = (a > 0) ? a : -a;
b = (b > 0) ? b : -b;
@@ -342,7 +316,7 @@ inline F32 llfastpow(const F32 x, const F32 y)
}
-inline F32 snap_to_sig_figs(F32 foo, S32 sig_figs)
+constexpr F32 snap_to_sig_figs(F32 foo, S32 sig_figs)
{
// compute the power of ten
F32 bar = 1.f;
@@ -358,12 +332,9 @@ inline F32 snap_to_sig_figs(F32 foo, S32 sig_figs)
return new_foo;
}
-inline F32 lerp(F32 a, F32 b, F32 u)
-{
- return a + ((b - a) * u);
-}
+using std::lerp;
-inline F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v)
+constexpr F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v)
{
F32 a = x00 + (x01-x00)*u;
F32 b = x10 + (x11-x10)*u;
@@ -371,17 +342,17 @@ inline F32 lerp2d(F32 x00, F32 x01, F32 x10, F32 x11, F32 u, F32 v)
return r;
}
-inline F32 ramp(F32 x, F32 a, F32 b)
+constexpr F32 ramp(F32 x, F32 a, F32 b)
{
return (a == b) ? 0.0f : ((a - x) / (a - b));
}
-inline F32 rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
+constexpr F32 rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
{
return lerp(y1, y2, ramp(x, x1, x2));
}
-inline F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
+constexpr F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
{
if (y1 < y2)
{
@@ -394,7 +365,7 @@ inline F32 clamp_rescale(F32 x, F32 x1, F32 x2, F32 y1, F32 y2)
}
-inline F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
+constexpr F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
{
if (x <= x0)
return s0;
@@ -407,14 +378,14 @@ inline F32 cubic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
return s0 + (s1 - s0) * (f * f) * (3.0f - 2.0f * f);
}
-inline F32 cubic_step( F32 x )
+constexpr F32 cubic_step( F32 x )
{
x = llclampf(x);
return (x * x) * (3.0f - 2.0f * x);
}
-inline F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
+constexpr F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
{
if (x <= x0)
return s0;
@@ -428,7 +399,7 @@ inline F32 quadratic_step( F32 x, F32 x0, F32 x1, F32 s0, F32 s1 )
return (s0 * (1.f - f_squared)) + ((s1 - s0) * f_squared);
}
-inline F32 llsimple_angle(F32 angle)
+constexpr F32 llsimple_angle(F32 angle)
{
while(angle <= -F_PI)
angle += F_TWO_PI;
@@ -438,7 +409,7 @@ inline F32 llsimple_angle(F32 angle)
}
//SDK - Renamed this to get_lower_power_two, since this is what this actually does.
-inline U32 get_lower_power_two(U32 val, U32 max_power_two)
+constexpr U32 get_lower_power_two(U32 val, U32 max_power_two)
{
if(!max_power_two)
{
@@ -460,7 +431,7 @@ inline U32 get_lower_power_two(U32 val, U32 max_power_two)
// number of digits, then add one. We subtract 1 initially to handle
// the case where the number passed in is actually a power of two.
// WARNING: this only works with 32 bit ints.
-inline U32 get_next_power_two(U32 val, U32 max_power_two)
+constexpr U32 get_next_power_two(U32 val, U32 max_power_two)
{
if(!max_power_two)
{
@@ -486,7 +457,7 @@ inline U32 get_next_power_two(U32 val, U32 max_power_two)
//get the gaussian value given the linear distance from axis x and guassian value o
inline F32 llgaussian(F32 x, F32 o)
{
- return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2*o*o));
+ return 1.f/(F_SQRT_TWO_PI*o)*powf(F_E, -(x*x)/(2.f*o*o));
}
//helper function for removing outliers
@@ -539,7 +510,8 @@ inline void ll_remove_outliers(std::vector& data, F32 k)
// Note: in our code, values labeled as sRGB are ALWAYS gamma corrected linear values, NOT linear values with monitor gamma applied
// Note: stored color values should always be gamma corrected linear (i.e. the values returned from an on-screen color swatch)
// Note: DO NOT cache the conversion. This leads to error prone synchronization and is actually slower in the typical case due to cache misses
-inline float linearTosRGB(const float val) {
+inline float linearTosRGB(const float val)
+{
if (val < 0.0031308f) {
return val * 12.92f;
}
@@ -554,7 +526,8 @@ inline float linearTosRGB(const float val) {
// Note: Stored color values should generally be gamma corrected sRGB.
// If you're serializing the return value of this function, you're probably doing it wrong.
// Note: DO NOT cache the conversion. This leads to error prone synchronization and is actually slower in the typical case due to cache misses.
-inline float sRGBtoLinear(const float val) {
+inline float sRGBtoLinear(const float val)
+{
if (val < 0.04045f) {
return val / 12.92f;
}
diff --git a/indra/llmath/llmatrix3a.cpp b/indra/llmath/llmatrix3a.cpp
index 48a72e71e1..c0b00201cf 100644
--- a/indra/llmath/llmatrix3a.cpp
+++ b/indra/llmath/llmatrix3a.cpp
@@ -24,6 +24,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llmath.h"
static LL_ALIGN_16(const F32 M_IDENT_3A[12]) =
diff --git a/indra/llmath/llmatrix3a.h b/indra/llmath/llmatrix3a.h
index dff6604ae5..9b173c22ed 100644
--- a/indra/llmath/llmatrix3a.h
+++ b/indra/llmath/llmatrix3a.h
@@ -56,7 +56,7 @@ public:
//////////////////////////
// Ctor
- LLMatrix3a() {}
+ LLMatrix3a() = default;
// Ctor for setting by columns
inline LLMatrix3a( const LLVector4a& c0, const LLVector4a& c1, const LLVector4a& c2 );
@@ -115,14 +115,18 @@ protected:
};
+static_assert(std::is_trivial::value, "LLMatrix3a must be a trivial type");
+
class LLRotation : public LLMatrix3a
{
public:
- LLRotation() {}
+ LLRotation() = default;
// Returns true if this rotation is orthonormal with det ~= 1
inline bool isOkRotation() const;
};
+static_assert(std::is_trivial::value, "LLRotation must be a trivial type");
+
#endif
diff --git a/indra/llmath/llmatrix4a.cpp b/indra/llmath/llmatrix4a.cpp
index 00e30a248b..bfb4c2b07a 100644
--- a/indra/llmath/llmatrix4a.cpp
+++ b/indra/llmath/llmatrix4a.cpp
@@ -24,6 +24,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llmath.h"
#include "llmatrix4a.h"
diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h
index 3b423f783a..377203098e 100644
--- a/indra/llmath/llmatrix4a.h
+++ b/indra/llmath/llmatrix4a.h
@@ -36,10 +36,7 @@ class LLMatrix4a
public:
LL_ALIGN_16(LLVector4a mMatrix[4]);
- LLMatrix4a()
- {
-
- }
+ LLMatrix4a() = default;
explicit LLMatrix4a(const LLMatrix4& val)
{
@@ -228,6 +225,8 @@ public:
const LLVector4a& getTranslation() const { return mMatrix[3]; }
};
+static_assert(std::is_trivial::value, "LLMatrix4a must be a trivial type");
+
inline LLVector4a rowMul(const LLVector4a &row, const LLMatrix4a &mat)
{
LLVector4a result;
diff --git a/indra/llmath/llplane.h b/indra/llmath/llplane.h
index 4e8546e32b..832004bb64 100644
--- a/indra/llmath/llplane.h
+++ b/indra/llmath/llplane.h
@@ -43,7 +43,7 @@ class LLPlane
public:
// Constructors
- LLPlane() {}; // no default constructor
+ LLPlane() = default;
LLPlane(const LLVector3 &p0, F32 d) { setVec(p0, d); }
LLPlane(const LLVector3 &p0, const LLVector3 &n) { setVec(p0, n); }
inline void setVec(const LLVector3 &p0, F32 d) { mV.set(p0[0], p0[1], p0[2], d); }
@@ -104,6 +104,7 @@ private:
LLVector4a mV;
} LL_ALIGN_POSTFIX(16);
+static_assert(std::is_trivial::value, "LLPlane must be a trivial type");
#endif // LL_LLPLANE_H
diff --git a/indra/llmath/llquaternion.cpp b/indra/llmath/llquaternion.cpp
index aefb82b2f0..3a6748bdb3 100644
--- a/indra/llmath/llquaternion.cpp
+++ b/indra/llmath/llquaternion.cpp
@@ -30,7 +30,6 @@
#include "llquaternion.h"
-//#include "vmath.h"
#include "v3math.h"
#include "v3dmath.h"
#include "v4math.h"
@@ -58,7 +57,7 @@ LLQuaternion::LLQuaternion(const LLMatrix3 &mat)
LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
{
- F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ F32 mag = vec.length();
if (mag > FP_MAG_THRESHOLD)
{
angle *= 0.5;
@@ -77,7 +76,7 @@ LLQuaternion::LLQuaternion(F32 angle, const LLVector4 &vec)
LLQuaternion::LLQuaternion(F32 angle, const LLVector3 &vec)
{
- F32 mag = sqrtf(vec.mV[VX] * vec.mV[VX] + vec.mV[VY] * vec.mV[VY] + vec.mV[VZ] * vec.mV[VZ]);
+ F32 mag = vec.length();
if (mag > FP_MAG_THRESHOLD)
{
angle *= 0.5;
diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h
index 762d13eded..472d7ca62d 100644
--- a/indra/llmath/llquaternion.h
+++ b/indra/llmath/llquaternion.h
@@ -174,6 +174,10 @@ public:
//static U32 mMultCount;
};
+static_assert(std::is_trivially_copyable::value, "LLQuaternion must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLQuaternion must be trivial move");
+static_assert(std::is_standard_layout::value, "LLQuaternion must be a standard layout type");
+
inline LLSD LLQuaternion::getValue() const
{
LLSD ret;
diff --git a/indra/llmath/llquaternion2.h b/indra/llmath/llquaternion2.h
index 902bfb7134..c9dcc4573f 100644
--- a/indra/llmath/llquaternion2.h
+++ b/indra/llmath/llquaternion2.h
@@ -49,7 +49,7 @@ public:
//////////////////////////
// Ctor
- LLQuaternion2() {}
+ LLQuaternion2() = default;
// Ctor from LLQuaternion
explicit LLQuaternion2( const class LLQuaternion& quat );
@@ -102,4 +102,6 @@ protected:
};
+static_assert(std::is_trivial::value, "LLQuaternion2 must be a trivial type");
+
#endif
diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h
index 317578da06..0a3da2fee0 100644
--- a/indra/llmath/llrect.h
+++ b/indra/llmath/llrect.h
@@ -51,10 +51,6 @@ public:
LLRectBase(): mLeft(0), mTop(0), mRight(0), mBottom(0)
{}
- LLRectBase(const LLRectBase &r):
- mLeft(r.mLeft), mTop(r.mTop), mRight(r.mRight), mBottom(r.mBottom)
- {}
-
LLRectBase(Type left, Type top, Type right, Type bottom):
mLeft(left), mTop(top), mRight(right), mBottom(bottom)
{}
@@ -295,4 +291,8 @@ template LLRectBase LLRectBase::null(0,0,0,0);
typedef LLRectBase LLRect;
typedef LLRectBase LLRectf;
+static_assert(std::is_trivially_copyable::value, "LLRect must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLRect must be trivial move");
+static_assert(std::is_standard_layout::value, "LLRect must be a standard layout type");
+
#endif
diff --git a/indra/llmath/llrigginginfo.cpp b/indra/llmath/llrigginginfo.cpp
index 23dbddd78e..2f59f685d5 100644
--- a/indra/llmath/llrigginginfo.cpp
+++ b/indra/llmath/llrigginginfo.cpp
@@ -24,6 +24,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llmath.h"
#include "llrigginginfo.h"
diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h
index 40953dc2e8..b27b034cf3 100644
--- a/indra/llmath/llsimdmath.h
+++ b/indra/llmath/llsimdmath.h
@@ -31,16 +31,26 @@
#error "Please include llmath.h before this file."
#endif
-#if ( ( LL_DARWIN || LL_LINUX ) && !(__SSE2__) ) || ( LL_WINDOWS && ( _M_IX86_FP < 2 && ADDRESS_SIZE == 32 ) )
-#error SSE2 not enabled. LLVector4a and related class will not compile.
+// the check for this error case must be split into multiple parts
+// because some versions of VS complain about '__SSE2__'
+#if ( ( LL_DARWIN || LL_LINUX ) )
+ #if !(__SSE2__) && !(__arm64__) && !(__aarch64__)
+ #error SSE2 not enabled. LLVector4a and related class will not compile.
+ #endif
+#elif ( LL_WINDOWS && ( _M_IX86_FP < 2 && ADDRESS_SIZE == 32 ) )
+ #error SSE2 not enabled. LLVector4a and related class will not compile.
#endif
#if !LL_WINDOWS
#include
#endif
+#if defined(__arm64__) || defined(__aarch64__)
+#include "sse2neon.h"
+#else
#include
#include
+#endif
#include "llmemory.h"
#include "llsimdtypes.h"
diff --git a/indra/llmath/llsimdtypes.h b/indra/llmath/llsimdtypes.h
index a407f51029..6c4f55b0c0 100644
--- a/indra/llmath/llsimdtypes.h
+++ b/indra/llmath/llsimdtypes.h
@@ -36,7 +36,7 @@ typedef __m128 LLQuad;
class LLBool32
{
public:
- inline LLBool32() {}
+ inline LLBool32() = default;
inline LLBool32(int rhs) : m_bool(rhs) {}
inline LLBool32(unsigned int rhs) : m_bool(rhs) {}
inline LLBool32(bool rhs) { m_bool = static_cast(rhs); }
@@ -46,13 +46,15 @@ public:
inline operator bool() const { return static_cast(m_bool); }
private:
- int m_bool{ 0 };
+ int m_bool;
};
+static_assert(std::is_trivial::value, "LLBool32 must be a standard layout type");
+
class LLSimdScalar
{
public:
- inline LLSimdScalar() {}
+ inline LLSimdScalar() = default;
inline LLSimdScalar(LLQuad q)
{
mQ = q;
@@ -100,7 +102,9 @@ public:
}
private:
- LLQuad mQ{};
+ LLQuad mQ;
};
+static_assert(std::is_trivial::value, "LLSimdScalar must be a standard layout type");
+
#endif //LL_SIMD_TYPES_H
diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp
index 0ac91366b6..b81d50f0f9 100644
--- a/indra/llmath/llvector4a.cpp
+++ b/indra/llmath/llvector4a.cpp
@@ -24,6 +24,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llmemory.h"
#include "llmath.h"
#include "llquantize.h"
diff --git a/indra/llmath/llvector4a.h b/indra/llmath/llvector4a.h
index 4004852e06..764a3b94e6 100644
--- a/indra/llmath/llvector4a.h
+++ b/indra/llmath/llvector4a.h
@@ -95,10 +95,7 @@ public:
////////////////////////////////////
//LLVector4a is plain data which should never have a default constructor or destructor(malloc&free won't trigger it)
- LLVector4a()
- { //DO NOT INITIALIZE -- The overhead is completely unnecessary
- ll_assert_aligned(this,16);
- }
+ LLVector4a() = default;
LLVector4a(F32 x, F32 y, F32 z, F32 w = 0.f)
{
@@ -361,8 +358,6 @@ public:
////////////////////////////////////
// Do NOT add aditional operators without consulting someone with SSE experience
- inline const LLVector4a& operator= ( const LLVector4a& rhs );
-
inline const LLVector4a& operator= ( const LLQuad& rhs );
inline operator LLQuad() const;
@@ -378,9 +373,11 @@ public:
};
private:
- LLQuad mQ{};
+ LLQuad mQ;
};
+static_assert(std::is_trivial::value, "LLVector4a must be a trivial type");
+
inline void update_min_max(LLVector4a& min, LLVector4a& max, const LLVector4a& p)
{
min.setMin(min, p);
diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl
index 36dbec078c..443a46c317 100644
--- a/indra/llmath/llvector4a.inl
+++ b/indra/llmath/llvector4a.inl
@@ -115,7 +115,7 @@ inline void LLVector4a::set(F32 x, F32 y, F32 z, F32 w)
// Set to all zeros
inline void LLVector4a::clear()
{
- mQ = LLVector4a::getZero().mQ;
+ mQ = _mm_setzero_ps();
}
inline void LLVector4a::splat(const F32 x)
@@ -272,6 +272,9 @@ inline void LLVector4a::setCross3(const LLVector4a& a, const LLVector4a& b)
// Set all elements to the dot product of the x, y, and z elements in a and b
inline void LLVector4a::setAllDot3(const LLVector4a& a, const LLVector4a& b)
{
+#if (defined(__arm64__) || defined(__aarch64__))
+ mQ = _mm_dp_ps(a.mQ, b.mQ, 0x7f);
+#else
// ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] }
const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ );
// yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] }
@@ -284,11 +287,15 @@ inline void LLVector4a::setAllDot3(const LLVector4a& a, const LLVector4a& b)
const __m128i zSplat = _mm_shuffle_epi32(_mm_castps_si128(ab), _MM_SHUFFLE( 2, 2, 2, 2 ));
// mQ = { a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same }
mQ = _mm_add_ps(_mm_castsi128_ps(zSplat), xPlusYSplat);
+#endif
}
// Set all elements to the dot product of the x, y, z, and w elements in a and b
inline void LLVector4a::setAllDot4(const LLVector4a& a, const LLVector4a& b)
{
+#if (defined(__arm64__) || defined(__aarch64__))
+ mQ = _mm_dp_ps(a.mQ, b.mQ, 0xff);
+#else
// ab = { a[W]*b[W], a[Z]*b[Z], a[Y]*b[Y], a[X]*b[X] }
const LLQuad ab = _mm_mul_ps( a.mQ, b.mQ );
// yzxw = { a[W]*b[W], a[Z]*b[Z], a[X]*b[X], a[Y]*b[Y] }
@@ -301,21 +308,29 @@ inline void LLVector4a::setAllDot4(const LLVector4a& a, const LLVector4a& b)
// mQ = { a[W]*b[W] + a[Z] * b[Z] + a[Y] * b[Y] + a[X] * b[X], same, same, same }
mQ = _mm_add_ps(xPlusYSplat, zPlusWSplat);
+#endif
}
// Return the 3D dot product of this vector and b
inline LLSimdScalar LLVector4a::dot3(const LLVector4a& b) const
{
+#if (defined(__arm64__) || defined(__aarch64__))
+ return _mm_dp_ps(mQ, b.mQ, 0x7f);
+#else
const LLQuad ab = _mm_mul_ps( mQ, b.mQ );
const LLQuad splatY = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(1, 1, 1, 1) ) );
const LLQuad splatZ = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128(ab), _MM_SHUFFLE(2, 2, 2, 2) ) );
const LLQuad xPlusY = _mm_add_ps( ab, splatY );
return _mm_add_ps( xPlusY, splatZ );
+#endif
}
// Return the 4D dot product of this vector and b
inline LLSimdScalar LLVector4a::dot4(const LLVector4a& b) const
{
+#if (defined(__arm64__) || defined(__aarch64__))
+ return _mm_dp_ps(mQ, b.mQ, 0xff);
+#else
// ab = { w, z, y, x }
const LLQuad ab = _mm_mul_ps( mQ, b.mQ );
// upperProdsInLowerElems = { y, x, y, x }
@@ -325,6 +340,7 @@ inline LLSimdScalar LLVector4a::dot4(const LLVector4a& b) const
// shuffled = { z+x, z+x, z+x, z+x }
const LLQuad shuffled = _mm_castsi128_ps( _mm_shuffle_epi32( _mm_castps_si128( sumOfPairs ), _MM_SHUFFLE(1, 1, 1, 1) ) );
return _mm_add_ss( sumOfPairs, shuffled );
+#endif
}
// Normalize this vector with respect to the x, y, and z components only. Accurate to 22 bites of precision. W component is destroyed
@@ -593,12 +609,6 @@ inline bool LLVector4a::equals3(const LLVector4a& rhs, F32 tolerance ) const
////////////////////////////////////
// Do NOT add aditional operators without consulting someone with SSE experience
-inline const LLVector4a& LLVector4a::operator= ( const LLVector4a& rhs )
-{
- mQ = rhs.mQ;
- return *this;
-}
-
inline const LLVector4a& LLVector4a::operator= ( const LLQuad& rhs )
{
mQ = rhs;
diff --git a/indra/llmath/llvector4logical.h b/indra/llmath/llvector4logical.h
index 70759eef5c..77cb5862e5 100644
--- a/indra/llmath/llvector4logical.h
+++ b/indra/llmath/llvector4logical.h
@@ -61,7 +61,7 @@ public:
};
// Empty default ctor
- LLVector4Logical() {}
+ LLVector4Logical() = default;
LLVector4Logical( const LLQuad& quad )
{
@@ -120,7 +120,9 @@ public:
private:
- LLQuad mQ{};
+ LLQuad mQ;
};
+static_assert(std::is_trivial::value, "LLVector4Logical must be a standard layout type");
+
#endif //LL_VECTOR4ALOGICAL_H
diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp
index 44b6e7923b..b3cb278d59 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -1294,10 +1294,11 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en
c = cos(ang)*lerp(radius_start, radius_end, t);
- pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)
+ pt->mPos.set(0 + lerp(0.f, params.getShear().mV[VX], s)
+ lerp(-skew ,skew, t) * 0.5f,
- c + lerp(0,params.getShear().mV[1],s),
+ c + lerp(0.f, params.getShear().mV[VY], s),
s);
+
pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t),
hole_y * lerp(taper_y_begin, taper_y_end, t),
0,1);
@@ -1327,9 +1328,9 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en
c = cos(ang)*lerp(radius_start, radius_end, t);
s = sin(ang)*lerp(radius_start, radius_end, t);
- pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)
+ pt->mPos.set(0 + lerp(0.f, params.getShear().mV[VX], s)
+ lerp(-skew ,skew, t) * 0.5f,
- c + lerp(0,params.getShear().mV[1],s),
+ c + lerp(0.f, params.getShear().mV[VY], s),
s);
pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t),
@@ -1354,9 +1355,9 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en
c = cos(ang)*lerp(radius_start, radius_end, t);
s = sin(ang)*lerp(radius_start, radius_end, t);
- pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)
+ pt->mPos.set(0 + lerp(0.f, params.getShear().mV[VX], s)
+ lerp(-skew ,skew, t) * 0.5f,
- c + lerp(0,params.getShear().mV[1],s),
+ c + lerp(0.f, params.getShear().mV[VY], s),
s);
pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t),
hole_y * lerp(taper_y_begin, taper_y_end, t),
@@ -1494,8 +1495,8 @@ bool LLPath::generate(const LLPathParams& params, F32 detail, S32 split,
for (S32 i=0;imNumIndices;
- p.resize(count);
- n.resize(count);
- tc.resize(count);
- t.resize(count);
-
- if (face->mWeights)
+ try
{
- w.resize(count);
+ p.resize(count);
+ n.resize(count);
+ tc.resize(count);
+ t.resize(count);
+
+ if (face->mWeights)
+ {
+ w.resize(count);
+ }
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("LLCoros") << "Bad memory allocation in MikktData, elements count: " << count << LL_ENDL;
}
@@ -5665,7 +5674,16 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
// and is executed on a background thread
MikktData data(this);
mikk::Mikktspace ctx(data);
- ctx.genTangSpace();
+ try
+ {
+ ctx.genTangSpace();
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("LLCoros") << "Bad memory allocation in MikktData::genTangSpace" << LL_ENDL;
+ }
+
//re-weld
meshopt_Stream mos[] =
@@ -5678,20 +5696,44 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
};
std::vector remap;
- remap.resize(data.p.size());
+ try
+ {
+ remap.resize(data.p.size());
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("LLCoros") << "Failed to allocate memory for remap: " << (S32)data.p.size() << LL_ENDL;
+ }
U32 stream_count = data.w.empty() ? 4 : 5;
S32 vert_count = 0;
if (!data.p.empty())
{
- vert_count = static_cast(meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count));
+ try
+ {
+ // providing mIndices should help avoid unused vertices
+ // but those should have been filtered out on upload
+ vert_count = static_cast(meshopt_generateVertexRemapMulti(&remap[0], nullptr, data.p.size(), data.p.size(), mos, stream_count));
+ }
+ catch (std::bad_alloc&)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("LLCoros") << "Failed to allocate memory for VertexRemap: " << (S32)data.p.size() << LL_ENDL;
+ }
}
- if (vert_count < 65535 && vert_count != 0)
+ // Probably should be using meshopt_remapVertexBuffer instead of remaping manually
+ if (vert_count < 65535 && vert_count > 0)
{
//copy results back into volume
resizeVertices(vert_count);
+ if (mNumVertices == 0)
+ {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("LLCoros") << "Failed to allocate memory for resizeVertices(" << vert_count << ")" << LL_ENDL;
+ }
if (!data.w.empty())
{
@@ -5704,13 +5746,27 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
{
U32 src_idx = i;
U32 dst_idx = remap[i];
- if (dst_idx >= (U32)mNumVertices)
+ if (dst_idx == U32_MAX)
+ {
+ // Unused indices? Probably need to resize mIndices
+ dst_idx = mNumVertices - 1;
+ llassert(false);
+ LL_DEBUGS_ONCE("LLVOLUME") << "U32_MAX destination index, substituting" << LL_ENDL;
+ }
+ else if (dst_idx >= (U32)mNumVertices)
{
dst_idx = mNumVertices - 1;
// Shouldn't happen, figure out what gets returned in remap and why.
llassert(false);
LL_DEBUGS_ONCE("LLVOLUME") << "Invalid destination index, substituting" << LL_ENDL;
}
+ if (src_idx >= (U32)data.p.size())
+ {
+ // data.p.size() is supposed to be equal to mNumIndices
+ src_idx = (U32)(data.p.size() - 1);
+ llassert(false);
+ LL_DEBUGS_ONCE("LLVOLUME") << "Invalid source index, substituting" << LL_ENDL;
+ }
mIndices[i] = dst_idx;
mPositions[dst_idx].load3(data.p[src_idx].mV);
@@ -5744,7 +5800,7 @@ bool LLVolumeFace::cacheOptimize(bool gen_tangents)
}
else
{
- if (vert_count == 0)
+ if (vert_count <= 0)
{
LL_WARNS_ONCE("LLVOLUME") << "meshopt_generateVertexRemapMulti failed to process a model or model was invalid" << LL_ENDL;
}
diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h
index 27c5fc5a49..3496928f7b 100644
--- a/indra/llmath/llvolume.h
+++ b/indra/llmath/llvolume.h
@@ -45,7 +45,6 @@ class LLVolumeOctree;
#include "lluuid.h"
#include "v4color.h"
-//#include "vmath.h"
#include "v2math.h"
#include "v3math.h"
#include "v3dmath.h"
diff --git a/indra/llmath/llvolumeoctree.cpp b/indra/llmath/llvolumeoctree.cpp
index 71288daa89..141317ee8d 100644
--- a/indra/llmath/llvolumeoctree.cpp
+++ b/indra/llmath/llvolumeoctree.cpp
@@ -24,6 +24,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "llvolumeoctree.h"
#include "llvector4a.h"
diff --git a/indra/llmath/m3math.cpp b/indra/llmath/m3math.cpp
index 472d340af5..3c2097f947 100644
--- a/indra/llmath/m3math.cpp
+++ b/indra/llmath/m3math.cpp
@@ -26,7 +26,6 @@
#include "linden_common.h"
-//#include "vmath.h"
#include "v3math.h"
#include "v3dmath.h"
#include "v4math.h"
diff --git a/indra/llmath/m3math.h b/indra/llmath/m3math.h
index cd14290246..36661d2cb0 100644
--- a/indra/llmath/m3math.h
+++ b/indra/llmath/m3math.h
@@ -142,6 +142,10 @@ class LLMatrix3
friend std::ostream& operator<<(std::ostream& s, const LLMatrix3 &a); // Stream a
};
+static_assert(std::is_trivially_copyable::value, "LLMatrix3 must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLMatrix3 must be trivial move");
+static_assert(std::is_standard_layout::value, "LLMatrix3 must be a standard layout type");
+
inline LLMatrix3::LLMatrix3(void)
{
mMatrix[0][0] = 1.f;
diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp
index c46ee587cb..1724a50601 100644
--- a/indra/llmath/m4math.cpp
+++ b/indra/llmath/m4math.cpp
@@ -26,7 +26,6 @@
#include "linden_common.h"
-//#include "vmath.h"
#include "v3math.h"
#include "v4math.h"
#include "m4math.h"
@@ -157,10 +156,6 @@ LLMatrix4::LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw)
mMatrix[3][3] = 1.f;
}
-LLMatrix4::~LLMatrix4(void)
-{
-}
-
// Clear and Assignment Functions
const LLMatrix4& LLMatrix4::setZero()
diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h
index b0f8c90cdf..f164779283 100644
--- a/indra/llmath/m4math.h
+++ b/indra/llmath/m4math.h
@@ -119,8 +119,6 @@ public:
const LLVector4 &pos); // Initializes Matrix with Euler angles
LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw); // Initializes Matrix with Euler angles
- ~LLMatrix4(void); // Destructor
-
LLSD getValue() const;
void setValue(const LLSD&);
@@ -242,6 +240,10 @@ public:
friend std::ostream& operator<<(std::ostream& s, const LLMatrix4 &a); // Stream a
};
+static_assert(std::is_trivially_copyable::value, "LLMatrix4 must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLMatrix4 must be trivial move");
+static_assert(std::is_standard_layout::value, "LLMatrix4 must be a standard layout type");
+
inline const LLMatrix4& LLMatrix4::setIdentity()
{
mMatrix[0][0] = 1.f;
diff --git a/indra/llmath/raytrace.cpp b/indra/llmath/raytrace.cpp
index 893bf1fc70..c0b5f48f2d 100644
--- a/indra/llmath/raytrace.cpp
+++ b/indra/llmath/raytrace.cpp
@@ -27,7 +27,6 @@
#include "linden_common.h"
#include "math.h"
-//#include "vmath.h"
#include "v3math.h"
#include "llquaternion.h"
#include "m3math.h"
diff --git a/indra/llmath/tests/llquaternion_test.cpp b/indra/llmath/tests/llquaternion_test.cpp
index aa3c0ad843..ba18d54d55 100644
--- a/indra/llmath/tests/llquaternion_test.cpp
+++ b/indra/llmath/tests/llquaternion_test.cpp
@@ -349,9 +349,9 @@ namespace tut
ensure(
"2. LLVector4 operator*(const LLVector4 &a, const LLQuaternion &rot) failed",
is_approx_equal(-58153.5390f, result.mV[0]) &&
- (183787.8125f == result.mV[1]) &&
- (116864.164063f == result.mV[2]) &&
- (78.099998f == result.mV[3]));
+ is_approx_equal(183787.8125f, result.mV[1]) &&
+ is_approx_equal(116864.164063f, result.mV[2]) &&
+ is_approx_equal(78.099998f, result.mV[3]));
}
//test case for LLVector3 operator*(const LLVector3 &a, const LLQuaternion &rot) fn.
diff --git a/indra/llmath/v2math.cpp b/indra/llmath/v2math.cpp
index 4649e13376..175f08df88 100644
--- a/indra/llmath/v2math.cpp
+++ b/indra/llmath/v2math.cpp
@@ -26,7 +26,6 @@
#include "linden_common.h"
-//#include "vmath.h"
#include "v2math.h"
#include "v3math.h"
#include "v4math.h"
@@ -47,8 +46,8 @@ bool LLVector2::abs()
{
bool ret{ false };
- if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; }
- if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; }
+ if (mV[VX] < 0.f) { mV[VX] = -mV[VX]; ret = true; }
+ if (mV[VY] < 0.f) { mV[VY] = -mV[VY]; ret = true; }
return ret;
}
@@ -67,14 +66,21 @@ F32 angle_between(const LLVector2& a, const LLVector2& b)
return angle;
}
-bool are_parallel(const LLVector2 &a, const LLVector2 &b, float epsilon)
+F32 signed_angle_between(const LLVector2& a, const LLVector2& b)
+{
+ F32 angle = angle_between(a, b);
+ F32 rhombus_square = a[VX] * b[VY] - b[VX] * a[VY];
+ return rhombus_square < 0 ? -angle : angle;
+}
+
+bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon)
{
LLVector2 an = a;
LLVector2 bn = b;
an.normVec();
bn.normVec();
F32 dot = an * bn;
- if ( (1.0f - fabs(dot)) < epsilon)
+ if ((1.0f - fabs(dot)) < epsilon)
{
return true;
}
@@ -82,28 +88,28 @@ bool are_parallel(const LLVector2 &a, const LLVector2 &b, float epsilon)
}
-F32 dist_vec(const LLVector2 &a, const LLVector2 &b)
+F32 dist_vec(const LLVector2& a, const LLVector2& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
return (F32) sqrt( x*x + y*y );
}
-F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b)
+F32 dist_vec_squared(const LLVector2& a, const LLVector2& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
return x*x + y*y;
}
-F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b)
+F32 dist_vec_squared2D(const LLVector2& a, const LLVector2& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
return x*x + y*y;
}
-LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u)
+LLVector2 lerp(const LLVector2& a, const LLVector2& b, F32 u)
{
return LLVector2(
a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u,
@@ -113,14 +119,14 @@ LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u)
LLSD LLVector2::getValue() const
{
LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
+ ret[VX] = mV[VX];
+ ret[VY] = mV[VY];
return ret;
}
void LLVector2::setValue(const LLSD& sd)
{
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
+ mV[VX] = (F32) sd[0].asReal();
+ mV[VY] = (F32) sd[1].asReal();
}
diff --git a/indra/llmath/v2math.h b/indra/llmath/v2math.h
index a61c946304..b31e4056a3 100644
--- a/indra/llmath/v2math.h
+++ b/indra/llmath/v2math.h
@@ -36,7 +36,7 @@ class LLQuaternion;
// Llvector2 = |x y z w|
-static const U32 LENGTHOFVECTOR2 = 2;
+static constexpr U32 LENGTHOFVECTOR2 = 2;
class LLVector2
{
@@ -82,7 +82,7 @@ class LLVector2
const LLVector2& scaleVec(const LLVector2& vec); // scales per component by vec
- bool isNull(); // Returns true if vector has a _very_small_ length
+ bool isNull() const; // Returns true if vector has a _very_small_ length
bool isExactlyZero() const { return !mV[VX] && !mV[VY]; }
F32 operator[](int idx) const { return mV[idx]; }
@@ -107,43 +107,43 @@ class LLVector2
friend LLVector2 operator-(const LLVector2 &a); // Return vector -a
- friend std::ostream& operator<<(std::ostream& s, const LLVector2 &a); // Stream a
+ friend std::ostream& operator<<(std::ostream& s, const LLVector2 &a); // Stream a
};
+static_assert(std::is_trivially_copyable::value, "LLVector2 must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLVector2 must be trivial move");
+static_assert(std::is_standard_layout::value, "LLVector2 must be a standard layout type");
// Non-member functions
-F32 angle_between(const LLVector2 &a, const LLVector2 &b); // Returns angle (radians) between a and b
-bool are_parallel(const LLVector2 &a, const LLVector2 &b, F32 epsilon=F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel
-F32 dist_vec(const LLVector2 &a, const LLVector2 &b); // Returns distance between a and b
-F32 dist_vec_squared(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b
-F32 dist_vec_squared2D(const LLVector2 &a, const LLVector2 &b);// Returns distance squared between a and b ignoring Z component
-LLVector2 lerp(const LLVector2 &a, const LLVector2 &b, F32 u); // Returns a vector that is a linear interpolation between a and b
+F32 angle_between(const LLVector2& a, const LLVector2& b); // Returns angle (radians) between a and b
+F32 signed_angle_between(const LLVector2& a, const LLVector2& b); // Returns signed angle (radians) between a and b
+bool are_parallel(const LLVector2& a, const LLVector2& b, F32 epsilon = F_APPROXIMATELY_ZERO); // Returns true if a and b are very close to parallel
+F32 dist_vec(const LLVector2& a, const LLVector2& b); // Returns distance between a and b
+F32 dist_vec_squared(const LLVector2& a, const LLVector2& b);// Returns distance squared between a and b
+F32 dist_vec_squared2D(const LLVector2& a, const LLVector2& b);// Returns distance squared between a and b ignoring Z component
+LLVector2 lerp(const LLVector2& a, const LLVector2& b, F32 u); // Returns a vector that is a linear interpolation between a and b
// Constructors
-inline LLVector2::LLVector2(void)
+inline LLVector2::LLVector2()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ clear();
}
inline LLVector2::LLVector2(F32 x, F32 y)
{
- mV[VX] = x;
- mV[VY] = y;
+ set(x, y);
}
inline LLVector2::LLVector2(const F32 *vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
+ set(vec);
}
inline LLVector2::LLVector2(const LLVector3 &vec)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
+ set(vec.mV);
}
inline LLVector2::LLVector2(const LLSD &sd)
@@ -153,30 +153,26 @@ inline LLVector2::LLVector2(const LLSD &sd)
// Clear and Assignment Functions
-inline void LLVector2::clear(void)
+inline void LLVector2::clear()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ mV[VX] = mV[VY] = 0.f;
}
-inline void LLVector2::setZero(void)
+inline void LLVector2::setZero()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ clear();
}
// deprecated
-inline void LLVector2::clearVec(void)
+inline void LLVector2::clearVec()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ clear();
}
// deprecated
-inline void LLVector2::zeroVec(void)
+inline void LLVector2::zeroVec()
{
- mV[VX] = 0.f;
- mV[VY] = 0.f;
+ clear();
}
inline void LLVector2::set(F32 x, F32 y)
@@ -187,108 +183,84 @@ inline void LLVector2::set(F32 x, F32 y)
inline void LLVector2::set(const LLVector2 &vec)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
+ set(vec.mV);
}
inline void LLVector2::set(const F32 *vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
+ set(vec[VX], vec[VY]);
}
// deprecated
inline void LLVector2::setVec(F32 x, F32 y)
{
- mV[VX] = x;
- mV[VY] = y;
+ set(x, y);
}
// deprecated
inline void LLVector2::setVec(const LLVector2 &vec)
{
- mV[VX] = vec.mV[VX];
- mV[VY] = vec.mV[VY];
+ set(vec);
}
// deprecated
inline void LLVector2::setVec(const F32 *vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
+ set(vec);
}
// LLVector2 Magnitude and Normalization Functions
-inline F32 LLVector2::length(void) const
+inline F32 LLVector2::length() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
+ return sqrt(lengthSquared());
}
-inline F32 LLVector2::lengthSquared(void) const
+inline F32 LLVector2::lengthSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1];
+ return mV[VX]*mV[VX] + mV[VY]*mV[VY];
}
-inline F32 LLVector2::normalize(void)
+inline F32 LLVector2::normalize()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
- F32 oomag;
+ F32 mag = length();
if (mag > FP_MAG_THRESHOLD)
{
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
+ *this /= mag;
}
else
{
- mV[0] = 0.f;
- mV[1] = 0.f;
+ clear();
mag = 0;
}
- return (mag);
+ return mag;
}
// checker
inline bool LLVector2::isFinite() const
{
- return (llfinite(mV[VX]) && llfinite(mV[VY]));
+ return llfinite(mV[VX]) && llfinite(mV[VY]);
}
// deprecated
-inline F32 LLVector2::magVec(void) const
+inline F32 LLVector2::magVec() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
+ return length();
}
// deprecated
-inline F32 LLVector2::magVecSquared(void) const
+inline F32 LLVector2::magVecSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1];
+ return lengthSquared();
}
// deprecated
-inline F32 LLVector2::normVec(void)
+inline F32 LLVector2::normVec()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1]);
- F32 oomag;
-
- if (mag > FP_MAG_THRESHOLD)
- {
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- }
- else
- {
- mV[0] = 0.f;
- mV[1] = 0.f;
- mag = 0;
- }
- return (mag);
+ return normalize();
}
inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec)
@@ -299,22 +271,18 @@ inline const LLVector2& LLVector2::scaleVec(const LLVector2& vec)
return *this;
}
-inline bool LLVector2::isNull()
+inline bool LLVector2::isNull() const
{
- if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] )
- {
- return true;
- }
- return false;
+ return F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY];
}
// LLVector2 Operators
// For sorting. By convention, x is "more significant" than y.
-inline bool operator<(const LLVector2 &a, const LLVector2 &b)
+inline bool operator<(const LLVector2& a, const LLVector2& b)
{
- if( a.mV[VX] == b.mV[VX] )
+ if (a.mV[VX] == b.mV[VX])
{
return a.mV[VY] < b.mV[VY];
}
@@ -325,95 +293,92 @@ inline bool operator<(const LLVector2 &a, const LLVector2 &b)
}
-inline LLVector2 operator+(const LLVector2 &a, const LLVector2 &b)
+inline LLVector2 operator+(const LLVector2& a, const LLVector2& b)
{
LLVector2 c(a);
return c += b;
}
-inline LLVector2 operator-(const LLVector2 &a, const LLVector2 &b)
+inline LLVector2 operator-(const LLVector2& a, const LLVector2& b)
{
LLVector2 c(a);
return c -= b;
}
-inline F32 operator*(const LLVector2 &a, const LLVector2 &b)
+inline F32 operator*(const LLVector2& a, const LLVector2& b)
{
- return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1]);
+ return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY]);
}
-inline LLVector2 operator%(const LLVector2 &a, const LLVector2 &b)
+inline LLVector2 operator%(const LLVector2& a, const LLVector2& b)
{
- return LLVector2(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]);
+ return LLVector2(a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY], a.mV[VY]*b.mV[VX] - b.mV[VY]*a.mV[VX]);
}
-inline LLVector2 operator/(const LLVector2 &a, F32 k)
+inline LLVector2 operator/(const LLVector2& a, F32 k)
{
F32 t = 1.f / k;
- return LLVector2( a.mV[0] * t, a.mV[1] * t );
+ return LLVector2( a.mV[VX] * t, a.mV[VY] * t );
}
-inline LLVector2 operator*(const LLVector2 &a, F32 k)
+inline LLVector2 operator*(const LLVector2& a, F32 k)
{
- return LLVector2( a.mV[0] * k, a.mV[1] * k );
+ return LLVector2( a.mV[VX] * k, a.mV[VY] * k );
}
-inline LLVector2 operator*(F32 k, const LLVector2 &a)
+inline LLVector2 operator*(F32 k, const LLVector2& a)
{
- return LLVector2( a.mV[0] * k, a.mV[1] * k );
+ return LLVector2( a.mV[VX] * k, a.mV[VY] * k );
}
-inline bool operator==(const LLVector2 &a, const LLVector2 &b)
+inline bool operator==(const LLVector2& a, const LLVector2& b)
{
- return ( (a.mV[0] == b.mV[0])
- &&(a.mV[1] == b.mV[1]));
+ return ( (a.mV[VX] == b.mV[VX])
+ &&(a.mV[VY] == b.mV[VY]));
}
-inline bool operator!=(const LLVector2 &a, const LLVector2 &b)
+inline bool operator!=(const LLVector2& a, const LLVector2& b)
{
- return ( (a.mV[0] != b.mV[0])
- ||(a.mV[1] != b.mV[1]));
+ return ( (a.mV[VX] != b.mV[VX])
+ ||(a.mV[VY] != b.mV[VY]));
}
-inline const LLVector2& operator+=(LLVector2 &a, const LLVector2 &b)
+inline const LLVector2& operator+=(LLVector2& a, const LLVector2& b)
{
- a.mV[0] += b.mV[0];
- a.mV[1] += b.mV[1];
+ a.mV[VX] += b.mV[VX];
+ a.mV[VY] += b.mV[VY];
return a;
}
-inline const LLVector2& operator-=(LLVector2 &a, const LLVector2 &b)
+inline const LLVector2& operator-=(LLVector2& a, const LLVector2& b)
{
- a.mV[0] -= b.mV[0];
- a.mV[1] -= b.mV[1];
+ a.mV[VX] -= b.mV[VX];
+ a.mV[VY] -= b.mV[VY];
return a;
}
-inline const LLVector2& operator%=(LLVector2 &a, const LLVector2 &b)
+inline const LLVector2& operator%=(LLVector2& a, const LLVector2& b)
{
- LLVector2 ret(a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1], a.mV[1]*b.mV[0] - b.mV[1]*a.mV[0]);
+ LLVector2 ret(a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY], a.mV[VY]*b.mV[VX] - b.mV[VY]*a.mV[VX]);
a = ret;
return a;
}
-inline const LLVector2& operator*=(LLVector2 &a, F32 k)
+inline const LLVector2& operator*=(LLVector2& a, F32 k)
{
- a.mV[0] *= k;
- a.mV[1] *= k;
+ a.mV[VX] *= k;
+ a.mV[VY] *= k;
return a;
}
-inline const LLVector2& operator/=(LLVector2 &a, F32 k)
+inline const LLVector2& operator/=(LLVector2& a, F32 k)
{
- F32 t = 1.f / k;
- a.mV[0] *= t;
- a.mV[1] *= t;
- return a;
+ return a *= 1.f / k;
}
-inline LLVector2 operator-(const LLVector2 &a)
+inline LLVector2 operator-(const LLVector2& a)
{
- return LLVector2( -a.mV[0], -a.mV[1] );
+ return LLVector2( -a.mV[VX], -a.mV[VY] );
}
inline void update_min_max(LLVector2& min, LLVector2& max, const LLVector2& pos)
@@ -431,7 +396,7 @@ inline void update_min_max(LLVector2& min, LLVector2& max, const LLVector2& pos)
}
}
-inline std::ostream& operator<<(std::ostream& s, const LLVector2 &a)
+inline std::ostream& operator<<(std::ostream& s, const LLVector2& a)
{
s << "{ " << a.mV[VX] << ", " << a.mV[VY] << " }";
return s;
diff --git a/indra/llmath/v3color.cpp b/indra/llmath/v3color.cpp
index 4367b993f8..08b3795020 100644
--- a/indra/llmath/v3color.cpp
+++ b/indra/llmath/v3color.cpp
@@ -32,74 +32,79 @@
LLColor3 LLColor3::white(1.0f, 1.0f, 1.0f);
LLColor3 LLColor3::black(0.0f, 0.0f, 0.0f);
-LLColor3 LLColor3::grey (0.5f, 0.5f, 0.5f);
+LLColor3 LLColor3::grey(0.5f, 0.5f, 0.5f);
-LLColor3::LLColor3(const LLColor4 &a)
+LLColor3::LLColor3(const LLColor4& a)
{
- mV[0] = a.mV[0];
- mV[1] = a.mV[1];
- mV[2] = a.mV[2];
+ mV[VRED] = a.mV[VRED];
+ mV[VGREEN] = a.mV[VGREEN];
+ mV[VBLUE] = a.mV[VBLUE];
}
-LLColor3::LLColor3(const LLVector4 &a)
+LLColor3::LLColor3(const LLVector4& a)
{
- mV[0] = a.mV[0];
- mV[1] = a.mV[1];
- mV[2] = a.mV[2];
+ mV[VRED] = a.mV[VRED];
+ mV[VGREEN] = a.mV[VGREEN];
+ mV[VBLUE] = a.mV[VBLUE];
}
-LLColor3::LLColor3(const LLSD &sd)
+LLColor3::LLColor3(const LLSD& sd)
{
setValue(sd);
}
-const LLColor3& LLColor3::operator=(const LLColor4 &a)
+const LLColor3& LLColor3::operator=(const LLColor4& a)
{
- mV[0] = a.mV[0];
- mV[1] = a.mV[1];
- mV[2] = a.mV[2];
+ mV[VRED] = a.mV[VRED];
+ mV[VGREEN] = a.mV[VGREEN];
+ mV[VBLUE] = a.mV[VBLUE];
return (*this);
}
-std::ostream& operator<<(std::ostream& s, const LLColor3 &a)
+std::ostream& operator<<(std::ostream& s, const LLColor3& a)
{
s << "{ " << a.mV[VRED] << ", " << a.mV[VGREEN] << ", " << a.mV[VBLUE] << " }";
return s;
}
-static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+static F32 hueToRgb(F32 val1In, F32 val2In, F32 valHUeIn)
{
- if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
- if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
- if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
- if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
- if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
- return ( val1In );
+ if (valHUeIn < 0.0f)
+ valHUeIn += 1.0f;
+ if (valHUeIn > 1.0f)
+ valHUeIn -= 1.0f;
+ if ((6.0f * valHUeIn) < 1.0f)
+ return (val1In + (val2In - val1In) * 6.0f * valHUeIn);
+ if ((2.0f * valHUeIn) < 1.0f)
+ return (val2In);
+ if ((3.0f * valHUeIn) < 2.0f)
+ return (val1In + (val2In - val1In) * ((2.0f / 3.0f) - valHUeIn) * 6.0f);
+ return (val1In);
}
-void LLColor3::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
+void LLColor3::setHSL(F32 hValIn, F32 sValIn, F32 lValIn)
{
- if ( sValIn < 0.00001f )
+ if (sValIn < 0.00001f)
{
- mV[VRED] = lValIn;
+ mV[VRED] = lValIn;
mV[VGREEN] = lValIn;
- mV[VBLUE] = lValIn;
+ mV[VBLUE] = lValIn;
}
else
{
F32 interVal1;
F32 interVal2;
- if ( lValIn < 0.5f )
- interVal2 = lValIn * ( 1.0f + sValIn );
+ if (lValIn < 0.5f)
+ interVal2 = lValIn * (1.0f + sValIn);
else
- interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
+ interVal2 = (lValIn + sValIn) - (sValIn * lValIn);
interVal1 = 2.0f * lValIn - interVal2;
- mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
- mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
- mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
+ mV[VRED] = hueToRgb(interVal1, interVal2, hValIn + (1.f / 3.f));
+ mV[VGREEN] = hueToRgb(interVal1, interVal2, hValIn);
+ mV[VBLUE] = hueToRgb(interVal1, interVal2, hValIn - (1.f / 3.f));
}
}
@@ -109,45 +114,48 @@ void LLColor3::calcHSL(F32* hue, F32* saturation, F32* luminance) const
F32 var_G = mV[VGREEN];
F32 var_B = mV[VBLUE];
- F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
- F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
+ F32 var_Min = (var_R < (var_G < var_B ? var_G : var_B) ? var_R : (var_G < var_B ? var_G : var_B));
+ F32 var_Max = (var_R > (var_G > var_B ? var_G : var_B) ? var_R : (var_G > var_B ? var_G : var_B));
F32 del_Max = var_Max - var_Min;
- F32 L = ( var_Max + var_Min ) / 2.0f;
+ F32 L = (var_Max + var_Min) / 2.0f;
F32 H = 0.0f;
F32 S = 0.0f;
- if ( del_Max == 0.0f )
+ if (del_Max == 0.0f)
{
- H = 0.0f;
- S = 0.0f;
+ H = 0.0f;
+ S = 0.0f;
}
else
{
- if ( L < 0.5 )
- S = del_Max / ( var_Max + var_Min );
+ if (L < 0.5)
+ S = del_Max / (var_Max + var_Min);
else
- S = del_Max / ( 2.0f - var_Max - var_Min );
+ S = del_Max / (2.0f - var_Max - var_Min);
- F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
- F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
- F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+ F32 del_R = (((var_Max - var_R) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ F32 del_G = (((var_Max - var_G) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ F32 del_B = (((var_Max - var_B) / 6.0f) + (del_Max / 2.0f)) / del_Max;
- if ( var_R >= var_Max )
+ if (var_R >= var_Max)
H = del_B - del_G;
- else
- if ( var_G >= var_Max )
- H = ( 1.0f / 3.0f ) + del_R - del_B;
- else
- if ( var_B >= var_Max )
- H = ( 2.0f / 3.0f ) + del_G - del_R;
+ else if (var_G >= var_Max)
+ H = (1.0f / 3.0f) + del_R - del_B;
+ else if (var_B >= var_Max)
+ H = (2.0f / 3.0f) + del_G - del_R;
- if ( H < 0.0f ) H += 1.0f;
- if ( H > 1.0f ) H -= 1.0f;
+ if (H < 0.0f)
+ H += 1.0f;
+ if (H > 1.0f)
+ H -= 1.0f;
}
- if (hue) *hue = H;
- if (saturation) *saturation = S;
- if (luminance) *luminance = L;
+ if (hue)
+ *hue = H;
+ if (saturation)
+ *saturation = S;
+ if (luminance)
+ *luminance = L;
}
diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h
index f7af469e66..7357d93599 100644
--- a/indra/llmath/v3color.h
+++ b/indra/llmath/v3color.h
@@ -33,12 +33,12 @@ class LLVector4;
#include "llerror.h"
#include "llmath.h"
#include "llsd.h"
-#include "v3math.h" // needed for linearColor3v implemtation below
+#include "v3math.h" // needed for linearColor3v implemtation below
#include
// LLColor3 = |r g b|
-static const U32 LENGTHOFCOLOR3 = 3;
+static constexpr U32 LENGTHOFCOLOR3 = 3;
class LLColor3
{
@@ -50,44 +50,43 @@ public:
static LLColor3 grey;
public:
- LLColor3(); // Initializes LLColor3 to (0, 0, 0)
- LLColor3(F32 r, F32 g, F32 b); // Initializes LLColor3 to (r, g, b)
- LLColor3(const F32 *vec); // Initializes LLColor3 to (vec[0]. vec[1], vec[2])
- LLColor3(const char *color_string); // html format color ie "#FFDDEE"
- explicit LLColor3(const LLColor4& color4); // "explicit" to avoid automatic conversion
- explicit LLColor3(const LLVector4& vector4); // "explicit" to avoid automatic conversion
+ LLColor3(); // Initializes LLColor3 to (0, 0, 0)
+ LLColor3(F32 r, F32 g, F32 b); // Initializes LLColor3 to (r, g, b)
+ LLColor3(const F32* vec); // Initializes LLColor3 to (vec[0]. vec[1], vec[2])
+ LLColor3(const char* color_string); // html format color ie "#FFDDEE"
+ explicit LLColor3(const LLColor4& color4); // "explicit" to avoid automatic conversion
+ explicit LLColor3(const LLVector4& vector4); // "explicit" to avoid automatic conversion
LLColor3(const LLSD& sd);
-
LLSD getValue() const
{
LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
- ret[2] = mV[2];
+ ret[VRED] = mV[VRED];
+ ret[VGREEN] = mV[VGREEN];
+ ret[VBLUE] = mV[VBLUE];
return ret;
}
void setValue(const LLSD& sd)
{
- mV[0] = (F32) sd[0].asReal();;
- mV[1] = (F32) sd[1].asReal();;
- mV[2] = (F32) sd[2].asReal();;
+ mV[VRED] = (F32)sd[VRED].asReal();
+ mV[VGREEN] = (F32)sd[VGREEN].asReal();
+ mV[VBLUE] = (F32)sd[VBLUE].asReal();
}
void setHSL(F32 hue, F32 saturation, F32 luminance);
void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
- const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0)
- const LLColor3& setToWhite(); // Zero LLColor3 to (0, 0, 0)
+ const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0)
+ const LLColor3& setToWhite(); // Zero LLColor3 to (0, 0, 0)
- const LLColor3& setVec(F32 x, F32 y, F32 z); // deprecated
- const LLColor3& setVec(const LLColor3 &vec); // deprecated
- const LLColor3& setVec(const F32 *vec); // deprecated
+ const LLColor3& setVec(F32 x, F32 y, F32 z); // deprecated
+ const LLColor3& setVec(const LLColor3& vec); // deprecated
+ const LLColor3& setVec(const F32* vec); // deprecated
- const LLColor3& set(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z)
- const LLColor3& set(const LLColor3 &vec); // Sets LLColor3 to vec
- const LLColor3& set(const F32 *vec); // Sets LLColor3 to vec
+ const LLColor3& set(F32 x, F32 y, F32 z); // Sets LLColor3 to (x, y, z)
+ const LLColor3& set(const LLColor3& vec); // Sets LLColor3 to vec
+ const LLColor3& set(const F32* vec); // Sets LLColor3 to vec
// set from a vector of unknown type and size
// may leave some data unmodified
@@ -99,414 +98,393 @@ public:
template
void write(std::vector& v) const;
- F32 magVec() const; // deprecated
- F32 magVecSquared() const; // deprecated
- F32 normVec(); // deprecated
+ F32 magVec() const; // deprecated
+ F32 magVecSquared() const; // deprecated
+ F32 normVec(); // deprecated
- F32 length() const; // Returns magnitude of LLColor3
- F32 lengthSquared() const; // Returns magnitude squared of LLColor3
- F32 normalize(); // Normalizes and returns the magnitude of LLColor3
+ F32 length() const; // Returns magnitude of LLColor3
+ F32 lengthSquared() const; // Returns magnitude squared of LLColor3
+ F32 normalize(); // Normalizes and returns the magnitude of LLColor3
- F32 brightness() const; // Returns brightness of LLColor3
+ F32 brightness() const; // Returns brightness of LLColor3
- const LLColor3& operator=(const LLColor4 &a);
+ const LLColor3& operator=(const LLColor4& a);
- LL_FORCE_INLINE LLColor3 divide(const LLColor3 &col2)
+ LL_FORCE_INLINE LLColor3 divide(const LLColor3& col2) const
{
- return LLColor3(
- mV[0] / col2.mV[0],
- mV[1] / col2.mV[1],
- mV[2] / col2.mV[2] );
+ return LLColor3(mV[VRED] / col2.mV[VRED], mV[VGREEN] / col2.mV[VGREEN], mV[VBLUE] / col2.mV[VBLUE]);
}
- LL_FORCE_INLINE LLColor3 color_norm()
+ LL_FORCE_INLINE LLColor3 color_norm() const
{
F32 l = length();
- return LLColor3(
- mV[0] / l,
- mV[1] / l,
- mV[2] / l );
+ return LLColor3(mV[VRED] / l, mV[VGREEN] / l, mV[VBLUE] / l);
}
- friend std::ostream& operator<<(std::ostream& s, const LLColor3 &a); // Print a
- friend LLColor3 operator+(const LLColor3 &a, const LLColor3 &b); // Return vector a + b
- friend LLColor3 operator-(const LLColor3 &a, const LLColor3 &b); // Return vector a minus b
+ friend std::ostream& operator<<(std::ostream& s, const LLColor3& a); // Print a
+ friend LLColor3 operator+(const LLColor3& a, const LLColor3& b); // Return vector a + b
+ friend LLColor3 operator-(const LLColor3& a, const LLColor3& b); // Return vector a minus b
- friend const LLColor3& operator+=(LLColor3 &a, const LLColor3 &b); // Return vector a + b
- friend const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b); // Return vector a minus b
- friend const LLColor3& operator*=(LLColor3 &a, const LLColor3 &b);
+ friend const LLColor3& operator+=(LLColor3& a, const LLColor3& b); // Return vector a + b
+ friend const LLColor3& operator-=(LLColor3& a, const LLColor3& b); // Return vector a minus b
+ friend const LLColor3& operator*=(LLColor3& a, const LLColor3& b);
- friend LLColor3 operator*(const LLColor3 &a, const LLColor3 &b); // Return component wise a * b
- friend LLColor3 operator*(const LLColor3 &a, F32 k); // Return a times scaler k
- friend LLColor3 operator*(F32 k, const LLColor3 &a); // Return a times scaler k
+ friend LLColor3 operator*(const LLColor3& a, const LLColor3& b); // Return component wise a * b
+ friend LLColor3 operator*(const LLColor3& a, F32 k); // Return a times scaler k
+ friend LLColor3 operator*(F32 k, const LLColor3& a); // Return a times scaler k
- friend bool operator==(const LLColor3 &a, const LLColor3 &b); // Return a == b
- friend bool operator!=(const LLColor3 &a, const LLColor3 &b); // Return a != b
+ friend bool operator==(const LLColor3& a, const LLColor3& b); // Return a == b
+ friend bool operator!=(const LLColor3& a, const LLColor3& b); // Return a != b
- friend const LLColor3& operator*=(LLColor3 &a, F32 k); // Return a times scaler k
+ friend const LLColor3& operator*=(LLColor3& a, F32 k); // Return a times scaler k
- friend LLColor3 operator-(const LLColor3 &a); // Return vector 1-rgb (inverse)
+ friend LLColor3 operator-(const LLColor3& a); // Return vector 1-rgb (inverse)
inline void clamp();
- inline void exp(); // Do an exponential on the color
+ inline void exp(); // Do an exponential on the color
};
-LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u);
-
+static_assert(std::is_trivially_copyable::value, "LLColor3 must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLColor3 must be trivial move");
+static_assert(std::is_standard_layout::value, "LLColor3 must be a standard layout type");
+LLColor3 lerp(const LLColor3& a, const LLColor3& b, F32 u);
void LLColor3::clamp()
{
// Clamp the color...
- if (mV[0] < 0.f)
+ if (mV[VRED] < 0.f)
{
- mV[0] = 0.f;
+ mV[VRED] = 0.f;
}
- else if (mV[0] > 1.f)
+ else if (mV[VRED] > 1.f)
{
- mV[0] = 1.f;
+ mV[VRED] = 1.f;
}
- if (mV[1] < 0.f)
+ if (mV[VGREEN] < 0.f)
{
- mV[1] = 0.f;
+ mV[VGREEN] = 0.f;
}
- else if (mV[1] > 1.f)
+ else if (mV[VGREEN] > 1.f)
{
- mV[1] = 1.f;
+ mV[VGREEN] = 1.f;
}
- if (mV[2] < 0.f)
+ if (mV[VBLUE] < 0.f)
{
- mV[2] = 0.f;
+ mV[VBLUE] = 0.f;
}
- else if (mV[2] > 1.f)
+ else if (mV[VBLUE] > 1.f)
{
- mV[2] = 1.f;
+ mV[VBLUE] = 1.f;
}
}
// Non-member functions
-F32 distVec(const LLColor3 &a, const LLColor3 &b); // Returns distance between a and b
-F32 distVec_squared(const LLColor3 &a, const LLColor3 &b);// Returns distance squared between a and b
+F32 distVec(const LLColor3& a, const LLColor3& b); // Returns distance between a and b
+F32 distVec_squared(const LLColor3& a, const LLColor3& b); // Returns distance squared between a and b
-inline LLColor3::LLColor3(void)
+inline LLColor3::LLColor3()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ mV[VRED] = 0.f;
+ mV[VGREEN] = 0.f;
+ mV[VBLUE] = 0.f;
}
inline LLColor3::LLColor3(F32 r, F32 g, F32 b)
{
- mV[VRED] = r;
+ mV[VRED] = r;
mV[VGREEN] = g;
- mV[VBLUE] = b;
+ mV[VBLUE] = b;
}
-
-inline LLColor3::LLColor3(const F32 *vec)
+inline LLColor3::LLColor3(const F32* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
}
inline LLColor3::LLColor3(const char* color_string) // takes a string of format "RRGGBB" where RR is hex 00..FF
{
- if (strlen(color_string) < 6) /* Flawfinder: ignore */
+ if (strlen(color_string) < 6) /* Flawfinder: ignore */
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ mV[VRED] = 0.f;
+ mV[VGREEN] = 0.f;
+ mV[VBLUE] = 0.f;
return;
}
char tempstr[7];
- strncpy(tempstr,color_string,6); /* Flawfinder: ignore */
+ strncpy(tempstr, color_string, 6); /* Flawfinder: ignore */
tempstr[6] = '\0';
- mV[VBLUE] = (F32)strtol(&tempstr[4],NULL,16)/255.f;
+ mV[VBLUE] = (F32)strtol(&tempstr[4], nullptr, 16) / 255.f;
tempstr[4] = '\0';
- mV[VGREEN] = (F32)strtol(&tempstr[2],NULL,16)/255.f;
+ mV[VGREEN] = (F32)strtol(&tempstr[2], nullptr, 16) / 255.f;
tempstr[2] = '\0';
- mV[VRED] = (F32)strtol(&tempstr[0],NULL,16)/255.f;
+ mV[VRED] = (F32)strtol(&tempstr[0], nullptr, 16) / 255.f;
}
-inline const LLColor3& LLColor3::setToBlack(void)
+inline const LLColor3& LLColor3::setToBlack()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ mV[VRED] = 0.f;
+ mV[VGREEN] = 0.f;
+ mV[VBLUE] = 0.f;
return (*this);
}
-inline const LLColor3& LLColor3::setToWhite(void)
+inline const LLColor3& LLColor3::setToWhite()
{
- mV[0] = 1.f;
- mV[1] = 1.f;
- mV[2] = 1.f;
+ mV[VRED] = 1.f;
+ mV[VGREEN] = 1.f;
+ mV[VBLUE] = 1.f;
return (*this);
}
-inline const LLColor3& LLColor3::set(F32 r, F32 g, F32 b)
+inline const LLColor3& LLColor3::set(F32 r, F32 g, F32 b)
{
- mV[0] = r;
- mV[1] = g;
- mV[2] = b;
+ mV[VRED] = r;
+ mV[VGREEN] = g;
+ mV[VBLUE] = b;
return (*this);
}
-inline const LLColor3& LLColor3::set(const LLColor3 &vec)
+inline const LLColor3& LLColor3::set(const LLColor3& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ mV[VRED] = vec.mV[VRED];
+ mV[VGREEN] = vec.mV[VGREEN];
+ mV[VBLUE] = vec.mV[VBLUE];
return (*this);
}
-inline const LLColor3& LLColor3::set(const F32 *vec)
+inline const LLColor3& LLColor3::set(const F32* vec)
{
- mV[0] = vec[0];
- mV[1] = vec[1];
- mV[2] = vec[2];
+ mV[VRED] = vec[VRED];
+ mV[VGREEN] = vec[VGREEN];
+ mV[VBLUE] = vec[VBLUE];
return (*this);
}
// deprecated
-inline const LLColor3& LLColor3::setVec(F32 r, F32 g, F32 b)
+inline const LLColor3& LLColor3::setVec(F32 r, F32 g, F32 b)
{
- mV[0] = r;
- mV[1] = g;
- mV[2] = b;
+ mV[VRED] = r;
+ mV[VGREEN] = g;
+ mV[VBLUE] = b;
return (*this);
}
// deprecated
-inline const LLColor3& LLColor3::setVec(const LLColor3 &vec)
+inline const LLColor3& LLColor3::setVec(const LLColor3& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ mV[VRED] = vec.mV[VRED];
+ mV[VGREEN] = vec.mV[VGREEN];
+ mV[VBLUE] = vec.mV[VBLUE];
return (*this);
}
// deprecated
-inline const LLColor3& LLColor3::setVec(const F32 *vec)
+inline const LLColor3& LLColor3::setVec(const F32* vec)
{
- mV[0] = vec[0];
- mV[1] = vec[1];
- mV[2] = vec[2];
+ mV[VRED] = vec[VRED];
+ mV[VGREEN] = vec[VGREEN];
+ mV[VBLUE] = vec[VBLUE];
return (*this);
}
-inline F32 LLColor3::brightness(void) const
+inline F32 LLColor3::brightness() const
{
- return (mV[0] + mV[1] + mV[2]) / 3.0f;
+ return (mV[VRED] + mV[VGREEN] + mV[VBLUE]) / 3.0f;
}
-inline F32 LLColor3::length(void) const
+inline F32 LLColor3::length() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ return sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
}
-inline F32 LLColor3::lengthSquared(void) const
+inline F32 LLColor3::lengthSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
+ return mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE];
}
-inline F32 LLColor3::normalize(void)
+inline F32 LLColor3::normalize()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ F32 mag = sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
F32 oomag;
if (mag)
{
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- mV[2] *= oomag;
+ oomag = 1.f / mag;
+ mV[VRED] *= oomag;
+ mV[VGREEN] *= oomag;
+ mV[VBLUE] *= oomag;
}
- return (mag);
+ return mag;
}
// deprecated
-inline F32 LLColor3::magVec(void) const
+inline F32 LLColor3::magVec() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ return sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
}
// deprecated
-inline F32 LLColor3::magVecSquared(void) const
+inline F32 LLColor3::magVecSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
+ return mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE];
}
// deprecated
-inline F32 LLColor3::normVec(void)
+inline F32 LLColor3::normVec()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ F32 mag = sqrt(mV[VRED] * mV[VRED] + mV[VGREEN] * mV[VGREEN] + mV[VBLUE] * mV[VBLUE]);
F32 oomag;
if (mag)
{
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- mV[2] *= oomag;
+ oomag = 1.f / mag;
+ mV[VRED] *= oomag;
+ mV[VGREEN] *= oomag;
+ mV[VBLUE] *= oomag;
}
- return (mag);
+ return mag;
}
inline void LLColor3::exp()
{
#if 0
- mV[0] = ::exp(mV[0]);
- mV[1] = ::exp(mV[1]);
- mV[2] = ::exp(mV[2]);
+ mV[VRED] = ::exp(mV[VRED]);
+ mV[VGREEN] = ::exp(mV[VGREEN]);
+ mV[VBLUE] = ::exp(mV[VBLUE]);
#else
- mV[0] = (F32)LL_FAST_EXP(mV[0]);
- mV[1] = (F32)LL_FAST_EXP(mV[1]);
- mV[2] = (F32)LL_FAST_EXP(mV[2]);
+ mV[VRED] = (F32)LL_FAST_EXP(mV[VRED]);
+ mV[VGREEN] = (F32)LL_FAST_EXP(mV[VGREEN]);
+ mV[VBLUE] = (F32)LL_FAST_EXP(mV[VBLUE]);
#endif
}
-
-inline LLColor3 operator+(const LLColor3 &a, const LLColor3 &b)
+inline LLColor3 operator+(const LLColor3& a, const LLColor3& b)
{
- return LLColor3(
- a.mV[0] + b.mV[0],
- a.mV[1] + b.mV[1],
- a.mV[2] + b.mV[2]);
+ return LLColor3(a.mV[VRED] + b.mV[VRED], a.mV[VGREEN] + b.mV[VGREEN], a.mV[VBLUE] + b.mV[VBLUE]);
}
-inline LLColor3 operator-(const LLColor3 &a, const LLColor3 &b)
+inline LLColor3 operator-(const LLColor3& a, const LLColor3& b)
{
- return LLColor3(
- a.mV[0] - b.mV[0],
- a.mV[1] - b.mV[1],
- a.mV[2] - b.mV[2]);
+ return LLColor3(a.mV[VRED] - b.mV[VRED], a.mV[VGREEN] - b.mV[VGREEN], a.mV[VBLUE] - b.mV[VBLUE]);
}
-inline LLColor3 operator*(const LLColor3 &a, const LLColor3 &b)
+inline LLColor3 operator*(const LLColor3& a, const LLColor3& b)
{
- return LLColor3(
- a.mV[0] * b.mV[0],
- a.mV[1] * b.mV[1],
- a.mV[2] * b.mV[2]);
+ return LLColor3(a.mV[VRED] * b.mV[VRED], a.mV[VGREEN] * b.mV[VGREEN], a.mV[VBLUE] * b.mV[VBLUE]);
}
-inline LLColor3 operator*(const LLColor3 &a, F32 k)
+inline LLColor3 operator*(const LLColor3& a, F32 k)
{
- return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k );
+ return LLColor3(a.mV[VRED] * k, a.mV[VGREEN] * k, a.mV[VBLUE] * k);
}
-inline LLColor3 operator*(F32 k, const LLColor3 &a)
+inline LLColor3 operator*(F32 k, const LLColor3& a)
{
- return LLColor3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k );
+ return LLColor3(a.mV[VRED] * k, a.mV[VGREEN] * k, a.mV[VBLUE] * k);
}
-inline bool operator==(const LLColor3 &a, const LLColor3 &b)
+inline bool operator==(const LLColor3& a, const LLColor3& b)
{
- return ( (a.mV[0] == b.mV[0])
- &&(a.mV[1] == b.mV[1])
- &&(a.mV[2] == b.mV[2]));
+ return ((a.mV[VRED] == b.mV[VRED]) && (a.mV[VGREEN] == b.mV[VGREEN]) && (a.mV[VBLUE] == b.mV[VBLUE]));
}
-inline bool operator!=(const LLColor3 &a, const LLColor3 &b)
+inline bool operator!=(const LLColor3& a, const LLColor3& b)
{
- return ( (a.mV[0] != b.mV[0])
- ||(a.mV[1] != b.mV[1])
- ||(a.mV[2] != b.mV[2]));
+ return ((a.mV[VRED] != b.mV[VRED]) || (a.mV[VGREEN] != b.mV[VGREEN]) || (a.mV[VBLUE] != b.mV[VBLUE]));
}
-inline const LLColor3 &operator*=(LLColor3 &a, const LLColor3 &b)
+inline const LLColor3& operator*=(LLColor3& a, const LLColor3& b)
{
- a.mV[0] *= b.mV[0];
- a.mV[1] *= b.mV[1];
- a.mV[2] *= b.mV[2];
+ a.mV[VRED] *= b.mV[VRED];
+ a.mV[VGREEN] *= b.mV[VGREEN];
+ a.mV[VBLUE] *= b.mV[VBLUE];
return a;
}
-inline const LLColor3& operator+=(LLColor3 &a, const LLColor3 &b)
+inline const LLColor3& operator+=(LLColor3& a, const LLColor3& b)
{
- a.mV[0] += b.mV[0];
- a.mV[1] += b.mV[1];
- a.mV[2] += b.mV[2];
+ a.mV[VRED] += b.mV[VRED];
+ a.mV[VGREEN] += b.mV[VGREEN];
+ a.mV[VBLUE] += b.mV[VBLUE];
return a;
}
-inline const LLColor3& operator-=(LLColor3 &a, const LLColor3 &b)
+inline const LLColor3& operator-=(LLColor3& a, const LLColor3& b)
{
- a.mV[0] -= b.mV[0];
- a.mV[1] -= b.mV[1];
- a.mV[2] -= b.mV[2];
+ a.mV[VRED] -= b.mV[VRED];
+ a.mV[VGREEN] -= b.mV[VGREEN];
+ a.mV[VBLUE] -= b.mV[VBLUE];
return a;
}
-inline const LLColor3& operator*=(LLColor3 &a, F32 k)
+inline const LLColor3& operator*=(LLColor3& a, F32 k)
{
- a.mV[0] *= k;
- a.mV[1] *= k;
- a.mV[2] *= k;
+ a.mV[VRED] *= k;
+ a.mV[VGREEN] *= k;
+ a.mV[VBLUE] *= k;
return a;
}
-inline LLColor3 operator-(const LLColor3 &a)
+inline LLColor3 operator-(const LLColor3& a)
{
- return LLColor3(
- 1.f - a.mV[0],
- 1.f - a.mV[1],
- 1.f - a.mV[2] );
+ return LLColor3(1.f - a.mV[VRED], 1.f - a.mV[VGREEN], 1.f - a.mV[VBLUE]);
}
// Non-member functions
-inline F32 distVec(const LLColor3 &a, const LLColor3 &b)
+inline F32 distVec(const LLColor3& a, const LLColor3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
- F32 z = a.mV[2] - b.mV[2];
- return (F32) sqrt( x*x + y*y + z*z );
+ F32 x = a.mV[VRED] - b.mV[VRED];
+ F32 y = a.mV[VGREEN] - b.mV[VGREEN];
+ F32 z = a.mV[VBLUE] - b.mV[VBLUE];
+ return sqrt(x * x + y * y + z * z);
}
-inline F32 distVec_squared(const LLColor3 &a, const LLColor3 &b)
+inline F32 distVec_squared(const LLColor3& a, const LLColor3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
- F32 z = a.mV[2] - b.mV[2];
- return x*x + y*y + z*z;
+ F32 x = a.mV[VRED] - b.mV[VRED];
+ F32 y = a.mV[VGREEN] - b.mV[VGREEN];
+ F32 z = a.mV[VBLUE] - b.mV[VBLUE];
+ return x * x + y * y + z * z;
}
-inline LLColor3 lerp(const LLColor3 &a, const LLColor3 &b, F32 u)
+inline LLColor3 lerp(const LLColor3& a, const LLColor3& b, F32 u)
{
- return LLColor3(
- a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u,
- a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u,
- a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u);
+ return LLColor3(a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u, a.mV[VY] + (b.mV[VY] - a.mV[VY]) * u, a.mV[VZ] + (b.mV[VZ] - a.mV[VZ]) * u);
}
-inline const LLColor3 srgbColor3(const LLColor3 &a) {
+inline const LLColor3 srgbColor3(const LLColor3& a)
+{
LLColor3 srgbColor;
- srgbColor.mV[0] = linearTosRGB(a.mV[0]);
- srgbColor.mV[1] = linearTosRGB(a.mV[1]);
- srgbColor.mV[2] = linearTosRGB(a.mV[2]);
+ srgbColor.mV[VRED] = linearTosRGB(a.mV[VRED]);
+ srgbColor.mV[VGREEN] = linearTosRGB(a.mV[VGREEN]);
+ srgbColor.mV[VBLUE] = linearTosRGB(a.mV[VBLUE]);
return srgbColor;
}
-inline const LLColor3 linearColor3p(const F32* v) {
+inline const LLColor3 linearColor3p(const F32* v)
+{
LLColor3 linearColor;
- linearColor.mV[0] = sRGBtoLinear(v[0]);
- linearColor.mV[1] = sRGBtoLinear(v[1]);
- linearColor.mV[2] = sRGBtoLinear(v[2]);
+ linearColor.mV[VRED] = sRGBtoLinear(v[VRED]);
+ linearColor.mV[VGREEN] = sRGBtoLinear(v[VGREEN]);
+ linearColor.mV[VBLUE] = sRGBtoLinear(v[VBLUE]);
return linearColor;
}
template
-inline const LLColor3 linearColor3(const T& a) {
+inline const LLColor3 linearColor3(const T& a)
+{
return linearColor3p(a.mV);
}
template
-inline const LLVector3 linearColor3v(const T& a) {
+inline const LLVector3 linearColor3v(const T& a)
+{
return LLVector3(linearColor3p(a.mV).mV);
}
diff --git a/indra/llmath/v3colorutil.h b/indra/llmath/v3colorutil.h
index 62005f76a0..4dc3100443 100644
--- a/indra/llmath/v3colorutil.h
+++ b/indra/llmath/v3colorutil.h
@@ -28,60 +28,48 @@
#define LL_V3COLORUTIL_H
#include "v3color.h"
+#include "v4color.h"
-inline LLColor3 componentDiv(LLColor3 const &left, LLColor3 const & right)
+inline LLColor3 componentDiv(const LLColor3& left, const LLColor3& right)
{
- return LLColor3(left.mV[0] / right.mV[0],
- left.mV[1] / right.mV[1],
- left.mV[2] / right.mV[2]);
+ return LLColor3(left.mV[VRED] / right.mV[VRED], left.mV[VGREEN] / right.mV[VGREEN], left.mV[VBLUE] / right.mV[VBLUE]);
}
-
-inline LLColor3 componentMult(LLColor3 const &left, LLColor3 const & right)
+inline LLColor3 componentMult(const LLColor3& left, const LLColor3& right)
{
- return LLColor3(left.mV[0] * right.mV[0],
- left.mV[1] * right.mV[1],
- left.mV[2] * right.mV[2]);
+ return LLColor3(left.mV[VRED] * right.mV[VRED], left.mV[VGREEN] * right.mV[VGREEN], left.mV[VBLUE] * right.mV[VBLUE]);
}
-
-inline LLColor3 componentExp(LLColor3 const &v)
+inline LLColor3 componentExp(const LLColor3& v)
{
- return LLColor3(exp(v.mV[0]),
- exp(v.mV[1]),
- exp(v.mV[2]));
+ return LLColor3(exp(v.mV[VRED]), exp(v.mV[VGREEN]), exp(v.mV[VBLUE]));
}
-inline LLColor3 componentPow(LLColor3 const &v, F32 exponent)
+inline LLColor3 componentPow(const LLColor3& v, F32 exponent)
{
- return LLColor3(pow(v.mV[0], exponent),
- pow(v.mV[1], exponent),
- pow(v.mV[2], exponent));
+ return LLColor3(pow(v.mV[VRED], exponent), pow(v.mV[VGREEN], exponent), pow(v.mV[VBLUE], exponent));
}
-inline LLColor3 componentSaturate(LLColor3 const &v)
+inline LLColor3 componentSaturate(const LLColor3& v)
{
- return LLColor3(std::max(std::min(v.mV[0], 1.f), 0.f),
- std::max(std::min(v.mV[1], 1.f), 0.f),
- std::max(std::min(v.mV[2], 1.f), 0.f));
+ return LLColor3(std::max(std::min(v.mV[VRED], 1.f), 0.f),
+ std::max(std::min(v.mV[VGREEN], 1.f), 0.f),
+ std::max(std::min(v.mV[VBLUE], 1.f), 0.f));
}
-
-inline LLColor3 componentSqrt(LLColor3 const &v)
+inline LLColor3 componentSqrt(const LLColor3& v)
{
- return LLColor3(sqrt(v.mV[0]),
- sqrt(v.mV[1]),
- sqrt(v.mV[2]));
+ return LLColor3(sqrt(v.mV[VRED]), sqrt(v.mV[VGREEN]), sqrt(v.mV[VBLUE]));
}
-inline void componentMultBy(LLColor3 & left, LLColor3 const & right)
+inline void componentMultBy(LLColor3& left, const LLColor3& right)
{
- left.mV[0] *= right.mV[0];
- left.mV[1] *= right.mV[1];
- left.mV[2] *= right.mV[2];
+ left.mV[VRED] *= right.mV[VRED];
+ left.mV[VGREEN] *= right.mV[VGREEN];
+ left.mV[VBLUE] *= right.mV[VBLUE];
}
-inline LLColor3 colorMix(LLColor3 const & left, LLColor3 const & right, F32 amount)
+inline LLColor3 colorMix(const LLColor3& left, const LLColor3& right, F32 amount)
{
return (left + ((right - left) * amount));
}
@@ -91,25 +79,24 @@ inline LLColor3 smear(F32 val)
return LLColor3(val, val, val);
}
-inline F32 color_intens(const LLColor3 &col)
+inline F32 color_intens(const LLColor3& col)
{
- return col.mV[0] + col.mV[1] + col.mV[2];
+ return col.mV[VRED] + col.mV[VGREEN] + col.mV[VBLUE];
}
-inline F32 color_max(const LLColor3 &col)
+inline F32 color_max(const LLColor3& col)
{
- return llmax(col.mV[0], col.mV[1], col.mV[2]);
+ return llmax(col.mV[VRED], col.mV[VGREEN], col.mV[VBLUE]);
}
-inline F32 color_max(const LLColor4 &col)
+inline F32 color_max(const LLColor4& col)
{
- return llmax(col.mV[0], col.mV[1], col.mV[2]);
+ return llmax(col.mV[VRED], col.mV[VGREEN], col.mV[VBLUE]);
}
-
-inline F32 color_min(const LLColor3 &col)
+inline F32 color_min(const LLColor3& col)
{
- return llmin(col.mV[0], col.mV[1], col.mV[2]);
+ return llmin(col.mV[VRED], col.mV[VGREEN], col.mV[VBLUE]);
}
#endif
diff --git a/indra/llmath/v3dmath.cpp b/indra/llmath/v3dmath.cpp
index bb55c812b5..b051303686 100644
--- a/indra/llmath/v3dmath.cpp
+++ b/indra/llmath/v3dmath.cpp
@@ -30,7 +30,6 @@
#include "v3dmath.h"
-//#include "vmath.h"
#include "v4math.h"
#include "m4math.h"
#include "m3math.h"
@@ -57,13 +56,13 @@ bool LLVector3d::clamp(F64 min, F64 max)
{
bool ret{ false };
- if (mdV[0] < min) { mdV[0] = min; ret = true; }
- if (mdV[1] < min) { mdV[1] = min; ret = true; }
- if (mdV[2] < min) { mdV[2] = min; ret = true; }
+ if (mdV[VX] < min) { mdV[VX] = min; ret = true; }
+ if (mdV[VY] < min) { mdV[VY] = min; ret = true; }
+ if (mdV[VZ] < min) { mdV[VZ] = min; ret = true; }
- if (mdV[0] > max) { mdV[0] = max; ret = true; }
- if (mdV[1] > max) { mdV[1] = max; ret = true; }
- if (mdV[2] > max) { mdV[2] = max; ret = true; }
+ if (mdV[VX] > max) { mdV[VX] = max; ret = true; }
+ if (mdV[VY] > max) { mdV[VY] = max; ret = true; }
+ if (mdV[VZ] > max) { mdV[VZ] = max; ret = true; }
return ret;
}
@@ -74,9 +73,9 @@ bool LLVector3d::abs()
{
bool ret{ false };
- if (mdV[0] < 0.0) { mdV[0] = -mdV[0]; ret = true; }
- if (mdV[1] < 0.0) { mdV[1] = -mdV[1]; ret = true; }
- if (mdV[2] < 0.0) { mdV[2] = -mdV[2]; ret = true; }
+ if (mdV[VX] < 0.0) { mdV[VX] = -mdV[VX]; ret = true; }
+ if (mdV[VY] < 0.0) { mdV[VY] = -mdV[VY]; ret = true; }
+ if (mdV[VZ] < 0.0) { mdV[VZ] = -mdV[VZ]; ret = true; }
return ret;
}
@@ -89,37 +88,37 @@ std::ostream& operator<<(std::ostream& s, const LLVector3d &a)
const LLVector3d& LLVector3d::operator=(const LLVector4 &a)
{
- mdV[0] = a.mV[0];
- mdV[1] = a.mV[1];
- mdV[2] = a.mV[2];
+ mdV[VX] = a.mV[VX];
+ mdV[VY] = a.mV[VY];
+ mdV[VZ] = a.mV[VZ];
return *this;
}
-const LLVector3d& LLVector3d::rotVec(const LLMatrix3 &mat)
+const LLVector3d& LLVector3d::rotVec(const LLMatrix3& mat)
{
*this = *this * mat;
return *this;
}
-const LLVector3d& LLVector3d::rotVec(const LLQuaternion &q)
+const LLVector3d& LLVector3d::rotVec(const LLQuaternion& q)
{
*this = *this * q;
return *this;
}
-const LLVector3d& LLVector3d::rotVec(F64 angle, const LLVector3d &vec)
+const LLVector3d& LLVector3d::rotVec(F64 angle, const LLVector3d& vec)
{
- if ( !vec.isExactlyZero() && angle )
+ if (!vec.isExactlyZero() && angle)
{
*this = *this * LLMatrix3((F32)angle, vec);
}
return *this;
}
-const LLVector3d& LLVector3d::rotVec(F64 angle, F64 x, F64 y, F64 z)
+const LLVector3d& LLVector3d::rotVec(F64 angle, F64 x, F64 y, F64 z)
{
LLVector3d vec(x, y, z);
- if ( !vec.isExactlyZero() && angle )
+ if (!vec.isExactlyZero() && angle)
{
*this = *this * LLMatrix3((F32)angle, vec);
}
@@ -129,16 +128,16 @@ const LLVector3d& LLVector3d::rotVec(F64 angle, F64 x, F64 y, F64 z)
bool LLVector3d::parseVector3d(const std::string& buf, LLVector3d* value)
{
- if( buf.empty() || value == nullptr)
+ if (buf.empty() || value == nullptr)
{
return false;
}
LLVector3d v;
- S32 count = sscanf( buf.c_str(), "%lf %lf %lf", v.mdV + 0, v.mdV + 1, v.mdV + 2 );
- if( 3 == count )
+ S32 count = sscanf(buf.c_str(), "%lf %lf %lf", v.mdV + VX, v.mdV + VY, v.mdV + VZ);
+ if (3 == count)
{
- value->setVec( v );
+ value->setVec(v);
return true;
}
diff --git a/indra/llmath/v3dmath.h b/indra/llmath/v3dmath.h
index ece8c54ea4..7c56cf138d 100644
--- a/indra/llmath/v3dmath.h
+++ b/indra/llmath/v3dmath.h
@@ -32,128 +32,131 @@
class LLVector3d
{
- public:
- F64 mdV[3];
+public:
+ F64 mdV[3];
- const static LLVector3d zero;
- const static LLVector3d x_axis;
- const static LLVector3d y_axis;
- const static LLVector3d z_axis;
- const static LLVector3d x_axis_neg;
- const static LLVector3d y_axis_neg;
- const static LLVector3d z_axis_neg;
+ const static LLVector3d zero;
+ const static LLVector3d x_axis;
+ const static LLVector3d y_axis;
+ const static LLVector3d z_axis;
+ const static LLVector3d x_axis_neg;
+ const static LLVector3d y_axis_neg;
+ const static LLVector3d z_axis_neg;
- inline LLVector3d(); // Initializes LLVector3d to (0, 0, 0)
- inline LLVector3d(const F64 x, const F64 y, const F64 z); // Initializes LLVector3d to (x. y, z)
- inline explicit LLVector3d(const F64 *vec); // Initializes LLVector3d to (vec[0]. vec[1], vec[2])
- inline explicit LLVector3d(const LLVector3 &vec);
- explicit LLVector3d(const LLSD& sd)
- {
- setValue(sd);
- }
+ inline LLVector3d(); // Initializes LLVector3d to (0, 0, 0)
+ inline LLVector3d(const F64 x, const F64 y, const F64 z); // Initializes LLVector3d to (x. y, z)
+ inline explicit LLVector3d(const F64 *vec); // Initializes LLVector3d to (vec[0]. vec[1], vec[2])
+ inline explicit LLVector3d(const LLVector3 &vec);
+ explicit LLVector3d(const LLSD& sd)
+ {
+ setValue(sd);
+ }
- void setValue(const LLSD& sd)
- {
- mdV[0] = sd[0].asReal();
- mdV[1] = sd[1].asReal();
- mdV[2] = sd[2].asReal();
- }
+ void setValue(const LLSD& sd)
+ {
+ mdV[VX] = sd[0].asReal();
+ mdV[VY] = sd[1].asReal();
+ mdV[VZ] = sd[2].asReal();
+ }
- LLSD getValue() const
- {
- LLSD ret;
- ret[0] = mdV[0];
- ret[1] = mdV[1];
- ret[2] = mdV[2];
- return ret;
- }
+ LLSD getValue() const
+ {
+ LLSD ret;
+ ret[0] = mdV[VX];
+ ret[1] = mdV[VY];
+ ret[2] = mdV[VZ];
+ return ret;
+ }
- inline bool isFinite() const; // checks to see if all values of LLVector3d are finite
- bool clamp(const F64 min, const F64 max); // Clamps all values to (min,max), returns true if data changed
- bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed
+ inline bool isFinite() const; // checks to see if all values of LLVector3d are finite
+ bool clamp(const F64 min, const F64 max); // Clamps all values to (min,max), returns true if data changed
+ bool abs(); // sets all values to absolute value of original value (first octant), returns true if changed
- inline const LLVector3d& clear(); // Clears LLVector3d to (0, 0, 0, 1)
- inline const LLVector3d& clearVec(); // deprecated
- inline const LLVector3d& setZero(); // Zero LLVector3d to (0, 0, 0, 0)
- inline const LLVector3d& zeroVec(); // deprecated
- inline const LLVector3d& set(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1)
- inline const LLVector3d& set(const LLVector3d &vec); // Sets LLVector3d to vec
- inline const LLVector3d& set(const F64 *vec); // Sets LLVector3d to vec
- inline const LLVector3d& set(const LLVector3 &vec);
- inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // deprecated
- inline const LLVector3d& setVec(const LLVector3d &vec); // deprecated
- inline const LLVector3d& setVec(const F64 *vec); // deprecated
- inline const LLVector3d& setVec(const LLVector3 &vec); // deprecated
+ inline const LLVector3d& clear(); // Clears LLVector3d to (0, 0, 0, 1)
+ inline const LLVector3d& clearVec(); // deprecated
+ inline const LLVector3d& setZero(); // Zero LLVector3d to (0, 0, 0, 0)
+ inline const LLVector3d& zeroVec(); // deprecated
+ inline const LLVector3d& set(const F64 x, const F64 y, const F64 z); // Sets LLVector3d to (x, y, z, 1)
+ inline const LLVector3d& set(const LLVector3d &vec); // Sets LLVector3d to vec
+ inline const LLVector3d& set(const F64 *vec); // Sets LLVector3d to vec
+ inline const LLVector3d& set(const LLVector3 &vec);
+ inline const LLVector3d& setVec(const F64 x, const F64 y, const F64 z); // deprecated
+ inline const LLVector3d& setVec(const LLVector3d &vec); // deprecated
+ inline const LLVector3d& setVec(const F64 *vec); // deprecated
+ inline const LLVector3d& setVec(const LLVector3 &vec); // deprecated
- F64 magVec() const; // deprecated
- F64 magVecSquared() const; // deprecated
- inline F64 normVec(); // deprecated
+ F64 magVec() const; // deprecated
+ F64 magVecSquared() const; // deprecated
+ inline F64 normVec(); // deprecated
- F64 length() const; // Returns magnitude of LLVector3d
- F64 lengthSquared() const; // Returns magnitude squared of LLVector3d
- inline F64 normalize(); // Normalizes and returns the magnitude of LLVector3d
+ F64 length() const; // Returns magnitude of LLVector3d
+ F64 lengthSquared() const; // Returns magnitude squared of LLVector3d
+ inline F64 normalize(); // Normalizes and returns the magnitude of LLVector3d
- const LLVector3d& rotVec(const F64 angle, const LLVector3d &vec); // Rotates about vec by angle radians
- const LLVector3d& rotVec(const F64 angle, const F64 x, const F64 y, const F64 z); // Rotates about x,y,z by angle radians
- const LLVector3d& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
- const LLVector3d& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
+ const LLVector3d& rotVec(const F64 angle, const LLVector3d &vec); // Rotates about vec by angle radians
+ const LLVector3d& rotVec(const F64 angle, const F64 x, const F64 y, const F64 z); // Rotates about x,y,z by angle radians
+ const LLVector3d& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
+ const LLVector3d& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
- bool isNull() const; // Returns true if vector has a _very_small_ length
- bool isExactlyZero() const { return !mdV[VX] && !mdV[VY] && !mdV[VZ]; }
+ bool isNull() const; // Returns true if vector has a _very_small_ length
+ bool isExactlyZero() const { return !mdV[VX] && !mdV[VY] && !mdV[VZ]; }
- const LLVector3d& operator=(const LLVector4 &a);
+ const LLVector3d& operator=(const LLVector4 &a);
- F64 operator[](int idx) const { return mdV[idx]; }
- F64 &operator[](int idx) { return mdV[idx]; }
+ F64 operator[](int idx) const { return mdV[idx]; }
+ F64 &operator[](int idx) { return mdV[idx]; }
- friend LLVector3d operator+(const LLVector3d& a, const LLVector3d& b); // Return vector a + b
- friend LLVector3d operator-(const LLVector3d& a, const LLVector3d& b); // Return vector a minus b
- friend F64 operator*(const LLVector3d& a, const LLVector3d& b); // Return a dot b
- friend LLVector3d operator%(const LLVector3d& a, const LLVector3d& b); // Return a cross b
- friend LLVector3d operator*(const LLVector3d& a, const F64 k); // Return a times scaler k
- friend LLVector3d operator/(const LLVector3d& a, const F64 k); // Return a divided by scaler k
- friend LLVector3d operator*(const F64 k, const LLVector3d& a); // Return a times scaler k
- friend bool operator==(const LLVector3d& a, const LLVector3d& b); // Return a == b
- friend bool operator!=(const LLVector3d& a, const LLVector3d& b); // Return a != b
+ friend LLVector3d operator+(const LLVector3d& a, const LLVector3d& b); // Return vector a + b
+ friend LLVector3d operator-(const LLVector3d& a, const LLVector3d& b); // Return vector a minus b
+ friend F64 operator*(const LLVector3d& a, const LLVector3d& b); // Return a dot b
+ friend LLVector3d operator%(const LLVector3d& a, const LLVector3d& b); // Return a cross b
+ friend LLVector3d operator*(const LLVector3d& a, const F64 k); // Return a times scaler k
+ friend LLVector3d operator/(const LLVector3d& a, const F64 k); // Return a divided by scaler k
+ friend LLVector3d operator*(const F64 k, const LLVector3d& a); // Return a times scaler k
+ friend bool operator==(const LLVector3d& a, const LLVector3d& b); // Return a == b
+ friend bool operator!=(const LLVector3d& a, const LLVector3d& b); // Return a != b
- friend const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b); // Return vector a + b
- friend const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b); // Return vector a minus b
- friend const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b); // Return a cross b
- friend const LLVector3d& operator*=(LLVector3d& a, const F64 k); // Return a times scaler k
- friend const LLVector3d& operator/=(LLVector3d& a, const F64 k); // Return a divided by scaler k
+ friend const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b); // Return vector a + b
+ friend const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b); // Return vector a minus b
+ friend const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b); // Return a cross b
+ friend const LLVector3d& operator*=(LLVector3d& a, const F64 k); // Return a times scaler k
+ friend const LLVector3d& operator/=(LLVector3d& a, const F64 k); // Return a divided by scaler k
- friend LLVector3d operator-(const LLVector3d& a); // Return vector -a
+ friend LLVector3d operator-(const LLVector3d& a); // Return vector -a
- friend std::ostream& operator<<(std::ostream& s, const LLVector3d& a); // Stream a
-
- static bool parseVector3d(const std::string& buf, LLVector3d* value);
+ friend std::ostream& operator<<(std::ostream& s, const LLVector3d& a); // Stream a
+ static bool parseVector3d(const std::string& buf, LLVector3d* value);
};
+static_assert(std::is_trivially_copyable::value, "LLVector3d must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLVector3d must be trivial move");
+static_assert(std::is_standard_layout::value, "LLVector3d must be a standard layout type");
+
typedef LLVector3d LLGlobalVec;
inline const LLVector3d &LLVector3d::set(const LLVector3 &vec)
{
- mdV[0] = vec.mV[0];
- mdV[1] = vec.mV[1];
- mdV[2] = vec.mV[2];
+ mdV[VX] = vec.mV[VX];
+ mdV[VY] = vec.mV[VY];
+ mdV[VZ] = vec.mV[VZ];
return *this;
}
inline const LLVector3d &LLVector3d::setVec(const LLVector3 &vec)
{
- mdV[0] = vec.mV[0];
- mdV[1] = vec.mV[1];
- mdV[2] = vec.mV[2];
+ mdV[VX] = vec.mV[VX];
+ mdV[VY] = vec.mV[VY];
+ mdV[VZ] = vec.mV[VZ];
return *this;
}
inline LLVector3d::LLVector3d(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
}
inline LLVector3d::LLVector3d(const F64 x, const F64 y, const F64 z)
@@ -199,33 +202,33 @@ inline bool LLVector3d::isFinite() const
inline const LLVector3d& LLVector3d::clear(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2]= 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
return (*this);
}
inline const LLVector3d& LLVector3d::clearVec(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2]= 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
return (*this);
}
inline const LLVector3d& LLVector3d::setZero(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
return (*this);
}
inline const LLVector3d& LLVector3d::zeroVec(void)
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.f;
+ mdV[VY] = 0.f;
+ mdV[VZ] = 0.f;
return (*this);
}
@@ -239,17 +242,17 @@ inline const LLVector3d& LLVector3d::set(const F64 x, const F64 y, const F64
inline const LLVector3d& LLVector3d::set(const LLVector3d &vec)
{
- mdV[0] = vec.mdV[0];
- mdV[1] = vec.mdV[1];
- mdV[2] = vec.mdV[2];
+ mdV[VX] = vec.mdV[VX];
+ mdV[VY] = vec.mdV[VY];
+ mdV[VZ] = vec.mdV[VZ];
return (*this);
}
inline const LLVector3d& LLVector3d::set(const F64 *vec)
{
- mdV[0] = vec[0];
- mdV[1] = vec[1];
- mdV[2] = vec[2];
+ mdV[VX] = vec[0];
+ mdV[VY] = vec[1];
+ mdV[VZ] = vec[2];
return (*this);
}
@@ -261,61 +264,62 @@ inline const LLVector3d& LLVector3d::setVec(const F64 x, const F64 y, const F
return (*this);
}
-inline const LLVector3d& LLVector3d::setVec(const LLVector3d &vec)
+inline const LLVector3d& LLVector3d::setVec(const LLVector3d& vec)
{
- mdV[0] = vec.mdV[0];
- mdV[1] = vec.mdV[1];
- mdV[2] = vec.mdV[2];
+ mdV[VX] = vec.mdV[VX];
+ mdV[VY] = vec.mdV[VY];
+ mdV[VZ] = vec.mdV[VZ];
return (*this);
}
-inline const LLVector3d& LLVector3d::setVec(const F64 *vec)
+inline const LLVector3d& LLVector3d::setVec(const F64* vec)
{
- mdV[0] = vec[0];
- mdV[1] = vec[1];
- mdV[2] = vec[2];
+ mdV[VX] = vec[VX];
+ mdV[VY] = vec[VY];
+ mdV[VZ] = vec[VZ];
return (*this);
}
-inline F64 LLVector3d::normVec(void)
+inline F64 LLVector3d::normVec()
{
- F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+ F64 mag = (F32)sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]); // This explicit cast to F32 limits the precision for numerical stability.
+ // Without it, Unit test "v3dmath_h" fails at "1:angle_between" on macos.
F64 oomag;
if (mag > FP_MAG_THRESHOLD)
{
- oomag = 1.f/mag;
- mdV[0] *= oomag;
- mdV[1] *= oomag;
- mdV[2] *= oomag;
+ oomag = 1.0/mag;
+ mdV[VX] *= oomag;
+ mdV[VY] *= oomag;
+ mdV[VZ] *= oomag;
}
else
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.0;
+ mdV[VY] = 0.0;
+ mdV[VZ] = 0.0;
mag = 0;
}
return (mag);
}
-inline F64 LLVector3d::normalize(void)
+inline F64 LLVector3d::normalize()
{
- F64 mag = (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+ F64 mag = (F32)sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]); // Same as in normVec() above.
F64 oomag;
if (mag > FP_MAG_THRESHOLD)
{
- oomag = 1.f/mag;
- mdV[0] *= oomag;
- mdV[1] *= oomag;
- mdV[2] *= oomag;
+ oomag = 1.0/mag;
+ mdV[VX] *= oomag;
+ mdV[VY] *= oomag;
+ mdV[VZ] *= oomag;
}
else
{
- mdV[0] = 0.f;
- mdV[1] = 0.f;
- mdV[2] = 0.f;
+ mdV[VX] = 0.0;
+ mdV[VY] = 0.0;
+ mdV[VZ] = 0.0;
mag = 0;
}
return (mag);
@@ -323,24 +327,24 @@ inline F64 LLVector3d::normalize(void)
// LLVector3d Magnitude and Normalization Functions
-inline F64 LLVector3d::magVec(void) const
+inline F64 LLVector3d::magVec() const
{
- return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+ return sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]);
}
-inline F64 LLVector3d::magVecSquared(void) const
+inline F64 LLVector3d::magVecSquared() const
{
- return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2];
+ return mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ];
}
-inline F64 LLVector3d::length(void) const
+inline F64 LLVector3d::length() const
{
- return (F32) sqrt(mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2]);
+ return sqrt(mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ]);
}
-inline F64 LLVector3d::lengthSquared(void) const
+inline F64 LLVector3d::lengthSquared() const
{
- return mdV[0]*mdV[0] + mdV[1]*mdV[1] + mdV[2]*mdV[2];
+ return mdV[VX]*mdV[VX] + mdV[VY]*mdV[VY] + mdV[VZ]*mdV[VZ];
}
inline LLVector3d operator+(const LLVector3d& a, const LLVector3d& b)
@@ -357,109 +361,109 @@ inline LLVector3d operator-(const LLVector3d& a, const LLVector3d& b)
inline F64 operator*(const LLVector3d& a, const LLVector3d& b)
{
- return (a.mdV[0]*b.mdV[0] + a.mdV[1]*b.mdV[1] + a.mdV[2]*b.mdV[2]);
+ return (a.mdV[VX]*b.mdV[VX] + a.mdV[VY]*b.mdV[VY] + a.mdV[VZ]*b.mdV[VZ]);
}
inline LLVector3d operator%(const LLVector3d& a, const LLVector3d& b)
{
- return LLVector3d( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1] );
+ return LLVector3d( a.mdV[VY]*b.mdV[VZ] - b.mdV[VY]*a.mdV[VZ], a.mdV[VZ]*b.mdV[VX] - b.mdV[VZ]*a.mdV[VX], a.mdV[VX]*b.mdV[VY] - b.mdV[VX]*a.mdV[VY] );
}
inline LLVector3d operator/(const LLVector3d& a, const F64 k)
{
F64 t = 1.f / k;
- return LLVector3d( a.mdV[0] * t, a.mdV[1] * t, a.mdV[2] * t );
+ return LLVector3d( a.mdV[VX] * t, a.mdV[VY] * t, a.mdV[VZ] * t );
}
inline LLVector3d operator*(const LLVector3d& a, const F64 k)
{
- return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k );
+ return LLVector3d( a.mdV[VX] * k, a.mdV[VY] * k, a.mdV[VZ] * k );
}
inline LLVector3d operator*(F64 k, const LLVector3d& a)
{
- return LLVector3d( a.mdV[0] * k, a.mdV[1] * k, a.mdV[2] * k );
+ return LLVector3d( a.mdV[VX] * k, a.mdV[VY] * k, a.mdV[VZ] * k );
}
inline bool operator==(const LLVector3d& a, const LLVector3d& b)
{
- return ( (a.mdV[0] == b.mdV[0])
- &&(a.mdV[1] == b.mdV[1])
- &&(a.mdV[2] == b.mdV[2]));
+ return ( (a.mdV[VX] == b.mdV[VX])
+ &&(a.mdV[VY] == b.mdV[VY])
+ &&(a.mdV[VZ] == b.mdV[VZ]));
}
inline bool operator!=(const LLVector3d& a, const LLVector3d& b)
{
- return ( (a.mdV[0] != b.mdV[0])
- ||(a.mdV[1] != b.mdV[1])
- ||(a.mdV[2] != b.mdV[2]));
+ return ( (a.mdV[VX] != b.mdV[VX])
+ ||(a.mdV[VY] != b.mdV[VY])
+ ||(a.mdV[VZ] != b.mdV[VZ]));
}
inline const LLVector3d& operator+=(LLVector3d& a, const LLVector3d& b)
{
- a.mdV[0] += b.mdV[0];
- a.mdV[1] += b.mdV[1];
- a.mdV[2] += b.mdV[2];
+ a.mdV[VX] += b.mdV[VX];
+ a.mdV[VY] += b.mdV[VY];
+ a.mdV[VZ] += b.mdV[VZ];
return a;
}
inline const LLVector3d& operator-=(LLVector3d& a, const LLVector3d& b)
{
- a.mdV[0] -= b.mdV[0];
- a.mdV[1] -= b.mdV[1];
- a.mdV[2] -= b.mdV[2];
+ a.mdV[VX] -= b.mdV[VX];
+ a.mdV[VY] -= b.mdV[VY];
+ a.mdV[VZ] -= b.mdV[VZ];
return a;
}
inline const LLVector3d& operator%=(LLVector3d& a, const LLVector3d& b)
{
- LLVector3d ret( a.mdV[1]*b.mdV[2] - b.mdV[1]*a.mdV[2], a.mdV[2]*b.mdV[0] - b.mdV[2]*a.mdV[0], a.mdV[0]*b.mdV[1] - b.mdV[0]*a.mdV[1]);
+ LLVector3d ret( a.mdV[VY]*b.mdV[VZ] - b.mdV[VY]*a.mdV[VZ], a.mdV[VZ]*b.mdV[VX] - b.mdV[VZ]*a.mdV[VX], a.mdV[VX]*b.mdV[VY] - b.mdV[VX]*a.mdV[VY]);
a = ret;
return a;
}
inline const LLVector3d& operator*=(LLVector3d& a, const F64 k)
{
- a.mdV[0] *= k;
- a.mdV[1] *= k;
- a.mdV[2] *= k;
+ a.mdV[VX] *= k;
+ a.mdV[VY] *= k;
+ a.mdV[VZ] *= k;
return a;
}
inline const LLVector3d& operator/=(LLVector3d& a, const F64 k)
{
F64 t = 1.f / k;
- a.mdV[0] *= t;
- a.mdV[1] *= t;
- a.mdV[2] *= t;
+ a.mdV[VX] *= t;
+ a.mdV[VY] *= t;
+ a.mdV[VZ] *= t;
return a;
}
inline LLVector3d operator-(const LLVector3d& a)
{
- return LLVector3d( -a.mdV[0], -a.mdV[1], -a.mdV[2] );
+ return LLVector3d( -a.mdV[VX], -a.mdV[VY], -a.mdV[VZ] );
}
inline F64 dist_vec(const LLVector3d& a, const LLVector3d& b)
{
- F64 x = a.mdV[0] - b.mdV[0];
- F64 y = a.mdV[1] - b.mdV[1];
- F64 z = a.mdV[2] - b.mdV[2];
+ F64 x = a.mdV[VX] - b.mdV[VX];
+ F64 y = a.mdV[VY] - b.mdV[VY];
+ F64 z = a.mdV[VZ] - b.mdV[VZ];
return (F32) sqrt( x*x + y*y + z*z );
}
inline F64 dist_vec_squared(const LLVector3d& a, const LLVector3d& b)
{
- F64 x = a.mdV[0] - b.mdV[0];
- F64 y = a.mdV[1] - b.mdV[1];
- F64 z = a.mdV[2] - b.mdV[2];
+ F64 x = a.mdV[VX] - b.mdV[VX];
+ F64 y = a.mdV[VY] - b.mdV[VY];
+ F64 z = a.mdV[VZ] - b.mdV[VZ];
return x*x + y*y + z*z;
}
inline F64 dist_vec_squared2D(const LLVector3d& a, const LLVector3d& b)
{
- F64 x = a.mdV[0] - b.mdV[0];
- F64 y = a.mdV[1] - b.mdV[1];
+ F64 x = a.mdV[VX] - b.mdV[VX];
+ F64 y = a.mdV[VY] - b.mdV[VY];
return x*x + y*y;
}
diff --git a/indra/llmath/v3math.cpp b/indra/llmath/v3math.cpp
index 73ad2a4ed6..eac95ed023 100644
--- a/indra/llmath/v3math.cpp
+++ b/indra/llmath/v3math.cpp
@@ -28,7 +28,6 @@
#include "v3math.h"
-//#include "vmath.h"
#include "v2math.h"
#include "v4math.h"
#include "m4math.h"
@@ -58,13 +57,13 @@ bool LLVector3::clamp(F32 min, F32 max)
{
bool ret{ false };
- if (mV[0] < min) { mV[0] = min; ret = true; }
- if (mV[1] < min) { mV[1] = min; ret = true; }
- if (mV[2] < min) { mV[2] = min; ret = true; }
+ if (mV[VX] < min) { mV[VX] = min; ret = true; }
+ if (mV[VY] < min) { mV[VY] = min; ret = true; }
+ if (mV[VZ] < min) { mV[VZ] = min; ret = true; }
- if (mV[0] > max) { mV[0] = max; ret = true; }
- if (mV[1] > max) { mV[1] = max; ret = true; }
- if (mV[2] > max) { mV[2] = max; ret = true; }
+ if (mV[VX] > max) { mV[VX] = max; ret = true; }
+ if (mV[VY] > max) { mV[VY] = max; ret = true; }
+ if (mV[VZ] > max) { mV[VZ] = max; ret = true; }
return ret;
}
@@ -85,9 +84,9 @@ bool LLVector3::clampLength( F32 length_limit )
{
length_limit = 0.f;
}
- mV[0] *= length_limit;
- mV[1] *= length_limit;
- mV[2] *= length_limit;
+ mV[VX] *= length_limit;
+ mV[VY] *= length_limit;
+ mV[VZ] *= length_limit;
changed = true;
}
}
@@ -116,35 +115,35 @@ bool LLVector3::clampLength( F32 length_limit )
{
// yes it can be salvaged -->
// bring the components down before we normalize
- mV[0] /= max_abs_component;
- mV[1] /= max_abs_component;
- mV[2] /= max_abs_component;
+ mV[VX] /= max_abs_component;
+ mV[VY] /= max_abs_component;
+ mV[VZ] /= max_abs_component;
normalize();
if (length_limit < 0.f)
{
length_limit = 0.f;
}
- mV[0] *= length_limit;
- mV[1] *= length_limit;
- mV[2] *= length_limit;
+ mV[VX] *= length_limit;
+ mV[VY] *= length_limit;
+ mV[VZ] *= length_limit;
}
}
return changed;
}
-bool LLVector3::clamp(const LLVector3 &min_vec, const LLVector3 &max_vec)
+bool LLVector3::clamp(const LLVector3& min_vec, const LLVector3& max_vec)
{
bool ret{ false };
- if (mV[0] < min_vec[0]) { mV[0] = min_vec[0]; ret = true; }
- if (mV[1] < min_vec[1]) { mV[1] = min_vec[1]; ret = true; }
- if (mV[2] < min_vec[2]) { mV[2] = min_vec[2]; ret = true; }
+ if (mV[VX] < min_vec[0]) { mV[VX] = min_vec[0]; ret = true; }
+ if (mV[VY] < min_vec[1]) { mV[VY] = min_vec[1]; ret = true; }
+ if (mV[VZ] < min_vec[2]) { mV[VZ] = min_vec[2]; ret = true; }
- if (mV[0] > max_vec[0]) { mV[0] = max_vec[0]; ret = true; }
- if (mV[1] > max_vec[1]) { mV[1] = max_vec[1]; ret = true; }
- if (mV[2] > max_vec[2]) { mV[2] = max_vec[2]; ret = true; }
+ if (mV[VX] > max_vec[0]) { mV[VX] = max_vec[0]; ret = true; }
+ if (mV[VY] > max_vec[1]) { mV[VY] = max_vec[1]; ret = true; }
+ if (mV[VZ] > max_vec[2]) { mV[VZ] = max_vec[2]; ret = true; }
return ret;
}
@@ -156,15 +155,15 @@ bool LLVector3::abs()
{
bool ret{ false };
- if (mV[0] < 0.f) { mV[0] = -mV[0]; ret = true; }
- if (mV[1] < 0.f) { mV[1] = -mV[1]; ret = true; }
- if (mV[2] < 0.f) { mV[2] = -mV[2]; ret = true; }
+ if (mV[VX] < 0.f) { mV[VX] = -mV[VX]; ret = true; }
+ if (mV[VY] < 0.f) { mV[VY] = -mV[VY]; ret = true; }
+ if (mV[VZ] < 0.f) { mV[VZ] = -mV[VZ]; ret = true; }
return ret;
}
// Quatizations
-void LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
+void LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
{
F32 x = mV[VX];
F32 y = mV[VY];
@@ -179,7 +178,7 @@ void LLVector3::quantize16(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
mV[VZ] = z;
}
-void LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
+void LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
{
mV[VX] = U8_to_F32(F32_to_U8(mV[VX], lowerxy, upperxy), lowerxy, upperxy);;
mV[VY] = U8_to_F32(F32_to_U8(mV[VY], lowerxy, upperxy), lowerxy, upperxy);
@@ -187,20 +186,20 @@ void LLVector3::quantize8(F32 lowerxy, F32 upperxy, F32 lowerz, F32 upperz)
}
-void LLVector3::snap(S32 sig_digits)
+void LLVector3::snap(S32 sig_digits)
{
mV[VX] = snap_to_sig_figs(mV[VX], sig_digits);
mV[VY] = snap_to_sig_figs(mV[VY], sig_digits);
mV[VZ] = snap_to_sig_figs(mV[VZ], sig_digits);
}
-const LLVector3& LLVector3::rotVec(const LLMatrix3 &mat)
+const LLVector3& LLVector3::rotVec(const LLMatrix3& mat)
{
*this = *this * mat;
return *this;
}
-const LLVector3& LLVector3::rotVec(const LLQuaternion &q)
+const LLVector3& LLVector3::rotVec(const LLQuaternion& q)
{
*this = *this * q;
return *this;
@@ -228,26 +227,26 @@ const LLVector3& LLVector3::transVec(const LLMatrix4& mat)
}
-const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3 &vec)
+const LLVector3& LLVector3::rotVec(F32 angle, const LLVector3& vec)
{
- if ( !vec.isExactlyZero() && angle )
+ if (!vec.isExactlyZero() && angle)
{
*this = *this * LLQuaternion(angle, vec);
}
return *this;
}
-const LLVector3& LLVector3::rotVec(F32 angle, F32 x, F32 y, F32 z)
+const LLVector3& LLVector3::rotVec(F32 angle, F32 x, F32 y, F32 z)
{
LLVector3 vec(x, y, z);
- if ( !vec.isExactlyZero() && angle )
+ if (!vec.isExactlyZero() && angle)
{
*this = *this * LLQuaternion(angle, vec);
}
return *this;
}
-const LLVector3& LLVector3::scaleVec(const LLVector3& vec)
+const LLVector3& LLVector3::scaleVec(const LLVector3& vec)
{
mV[VX] *= vec.mV[VX];
mV[VY] *= vec.mV[VY];
@@ -256,42 +255,42 @@ const LLVector3& LLVector3::scaleVec(const LLVector3& vec)
return *this;
}
-LLVector3 LLVector3::scaledVec(const LLVector3& vec) const
+LLVector3 LLVector3::scaledVec(const LLVector3& vec) const
{
LLVector3 ret = LLVector3(*this);
ret.scaleVec(vec);
return ret;
}
-const LLVector3& LLVector3::set(const LLVector3d &vec)
+const LLVector3& LLVector3::set(const LLVector3d& vec)
{
- mV[0] = (F32)vec.mdV[0];
- mV[1] = (F32)vec.mdV[1];
- mV[2] = (F32)vec.mdV[2];
+ mV[VX] = (F32)vec.mdV[VX];
+ mV[VY] = (F32)vec.mdV[VY];
+ mV[VZ] = (F32)vec.mdV[VZ];
return (*this);
}
-const LLVector3& LLVector3::set(const LLVector4 &vec)
+const LLVector3& LLVector3::set(const LLVector4& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ mV[VX] = vec.mV[VX];
+ mV[VY] = vec.mV[VY];
+ mV[VZ] = vec.mV[VZ];
return (*this);
}
-const LLVector3& LLVector3::setVec(const LLVector3d &vec)
+const LLVector3& LLVector3::setVec(const LLVector3d& vec)
{
- mV[0] = (F32)vec.mdV[0];
- mV[1] = (F32)vec.mdV[1];
- mV[2] = (F32)vec.mdV[2];
+ mV[VX] = (F32)vec.mdV[0];
+ mV[VY] = (F32)vec.mdV[1];
+ mV[VZ] = (F32)vec.mdV[2];
return (*this);
}
-const LLVector3& LLVector3::setVec(const LLVector4 &vec)
+const LLVector3& LLVector3::setVec(const LLVector4& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ mV[VX] = vec.mV[VX];
+ mV[VY] = vec.mV[VY];
+ mV[VZ] = vec.mV[VZ];
return (*this);
}
@@ -299,17 +298,17 @@ LLVector3::LLVector3(const LLVector2 &vec)
{
mV[VX] = (F32)vec.mV[VX];
mV[VY] = (F32)vec.mV[VY];
- mV[VZ] = 0;
+ mV[VZ] = 0.f;
}
-LLVector3::LLVector3(const LLVector3d &vec)
+LLVector3::LLVector3(const LLVector3d& vec)
{
mV[VX] = (F32)vec.mdV[VX];
mV[VY] = (F32)vec.mdV[VY];
mV[VZ] = (F32)vec.mdV[VZ];
}
-LLVector3::LLVector3(const LLVector4 &vec)
+LLVector3::LLVector3(const LLVector4& vec)
{
mV[VX] = (F32)vec.mV[VX];
mV[VY] = (F32)vec.mV[VY];
@@ -319,7 +318,6 @@ LLVector3::LLVector3(const LLVector4 &vec)
LLVector3::LLVector3(const LLVector4a& vec)
: LLVector3(vec.getF32ptr())
{
-
}
LLVector3::LLVector3(const LLSD& sd)
@@ -330,20 +328,20 @@ LLVector3::LLVector3(const LLSD& sd)
LLSD LLVector3::getValue() const
{
LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
- ret[2] = mV[2];
+ ret[VX] = mV[VX];
+ ret[VY] = mV[VY];
+ ret[VZ] = mV[VZ];
return ret;
}
void LLVector3::setValue(const LLSD& sd)
{
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
+ mV[VX] = (F32) sd[VX].asReal();
+ mV[VY] = (F32) sd[VY].asReal();
+ mV[VZ] = (F32) sd[VZ].asReal();
}
-const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot)
+const LLVector3& operator*=(LLVector3& a, const LLQuaternion& rot)
{
const F32 rw = - rot.mQ[VX] * a.mV[VX] - rot.mQ[VY] * a.mV[VY] - rot.mQ[VZ] * a.mV[VZ];
const F32 rx = rot.mQ[VW] * a.mV[VX] + rot.mQ[VY] * a.mV[VZ] - rot.mQ[VZ] * a.mV[VY];
@@ -360,16 +358,16 @@ const LLVector3& operator*=(LLVector3 &a, const LLQuaternion &rot)
// static
bool LLVector3::parseVector3(const std::string& buf, LLVector3* value)
{
- if( buf.empty() || value == nullptr)
+ if (buf.empty() || value == nullptr)
{
return false;
}
LLVector3 v;
- S32 count = sscanf( buf.c_str(), "%f %f %f", v.mV + 0, v.mV + 1, v.mV + 2 );
- if( 3 == count )
+ S32 count = sscanf(buf.c_str(), "%f %f %f", v.mV + VX, v.mV + VY, v.mV + VZ);
+ if (3 == count)
{
- value->setVec( v );
+ value->setVec(v);
return true;
}
@@ -381,7 +379,7 @@ bool LLVector3::parseVector3(const std::string& buf, LLVector3* value)
LLVector3 point_to_box_offset(LLVector3& pos, const LLVector3* box)
{
LLVector3 offset;
- for (S32 k=0; k<3; k++)
+ for (S32 k = 0; k < 3; k++)
{
offset[k] = 0;
if (pos[k] < box[0][k])
@@ -410,4 +408,3 @@ bool box_valid_and_non_zero(const LLVector3* box)
}
return false;
}
-
diff --git a/indra/llmath/v3math.h b/indra/llmath/v3math.h
index a3bfa68060..196ecdcf7d 100644
--- a/indra/llmath/v3math.h
+++ b/indra/llmath/v3math.h
@@ -46,7 +46,7 @@ class LLQuaternion;
// LLvector3 = |x y z w|
-static const U32 LENGTHOFVECTOR3 = 3;
+static constexpr U32 LENGTHOFVECTOR3 = 3;
class LLVector3
{
@@ -112,24 +112,24 @@ class LLVector3
const LLVector3& setVec(const LLVector4 &vec); // deprecated
const LLVector3& setVec(const LLVector3d &vec); // deprecated
- F32 length() const; // Returns magnitude of LLVector3
- F32 lengthSquared() const; // Returns magnitude squared of LLVector3
- F32 magVec() const; // deprecated
- F32 magVecSquared() const; // deprecated
+ F32 length() const; // Returns magnitude of LLVector3
+ F32 lengthSquared() const; // Returns magnitude squared of LLVector3
+ F32 magVec() const; // deprecated
+ F32 magVecSquared() const; // deprecated
- inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3
- inline F32 normVec(); // deprecated
+ inline F32 normalize(); // Normalizes and returns the magnitude of LLVector3
+ inline F32 normVec(); // deprecated
- inline bool inRange( F32 min, F32 max ) const; // Returns true if all values of the vector are between min and max
+ inline bool inRange(F32 min, F32 max) const; // Returns true if all values of the vector are between min and max
- const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians
- const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians
- const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
- const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
- const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v)
+ const LLVector3& rotVec(F32 angle, const LLVector3 &vec); // Rotates about vec by angle radians
+ const LLVector3& rotVec(F32 angle, F32 x, F32 y, F32 z); // Rotates about x,y,z by angle radians
+ const LLVector3& rotVec(const LLMatrix3 &mat); // Rotates by LLMatrix4 mat
+ const LLVector3& rotVec(const LLQuaternion &q); // Rotates by LLQuaternion q
+ const LLVector3& transVec(const LLMatrix4& mat); // Transforms by LLMatrix4 mat (mat * v)
- const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec
- LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec
+ const LLVector3& scaleVec(const LLVector3& vec); // scales per component by vec
+ LLVector3 scaledVec(const LLVector3& vec) const; // get a copy of this vector scaled by vec
bool isNull() const; // Returns true if vector has a _very_small_ length
bool isExactlyZero() const { return !mV[VX] && !mV[VY] && !mV[VZ]; }
@@ -164,6 +164,10 @@ class LLVector3
static bool parseVector3(const std::string& buf, LLVector3* value);
};
+static_assert(std::is_trivially_copyable::value, "LLVector3 must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLVector3 must be trivial move");
+static_assert(std::is_standard_layout::value, "LLVector3 must be a standard layout type");
+
typedef LLVector3 LLSimLocalVec;
// Non-member functions
@@ -181,25 +185,19 @@ LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u); // Returns a vect
LLVector3 point_to_box_offset(LLVector3& pos, const LLVector3* box); // Displacement from query point to nearest point on bounding box.
bool box_valid_and_non_zero(const LLVector3* box);
-inline LLVector3::LLVector3(void)
+inline LLVector3::LLVector3()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
}
inline LLVector3::LLVector3(const F32 x, const F32 y, const F32 z)
{
- mV[VX] = x;
- mV[VY] = y;
- mV[VZ] = z;
+ set(x, y, z);
}
inline LLVector3::LLVector3(const F32 *vec)
{
- mV[VX] = vec[VX];
- mV[VY] = vec[VY];
- mV[VZ] = vec[VZ];
+ set(vec);
}
inline LLVector3::LLVector3(const glm::vec3& vec)
@@ -230,38 +228,30 @@ inline LLVector3::LLVector3(const LLVector3 ©)
// checker
inline bool LLVector3::isFinite() const
{
- return (llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]));
+ return llfinite(mV[VX]) && llfinite(mV[VY]) && llfinite(mV[VZ]);
}
// Clear and Assignment Functions
-inline void LLVector3::clear(void)
+inline void LLVector3::clear()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ set(0.f, 0.f, 0.f);
}
-inline void LLVector3::setZero(void)
+inline void LLVector3::setZero()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
}
-inline void LLVector3::clearVec(void)
+inline void LLVector3::clearVec()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
}
-inline void LLVector3::zeroVec(void)
+inline void LLVector3::zeroVec()
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
}
inline void LLVector3::set(F32 x, F32 y, F32 z)
@@ -271,18 +261,14 @@ inline void LLVector3::set(F32 x, F32 y, F32 z)
mV[VZ] = z;
}
-inline void LLVector3::set(const LLVector3 &vec)
+inline void LLVector3::set(const LLVector3& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ set(vec.mV[VX], vec.mV[VY], vec.mV[VZ]);
}
-inline void LLVector3::set(const F32 *vec)
+inline void LLVector3::set(const F32* vec)
{
- mV[0] = vec[0];
- mV[1] = vec[1];
- mV[2] = vec[2];
+ set(vec[VX], vec[VY], vec[VZ]);
}
inline void LLVector3::set(const glm::vec4& vec)
@@ -302,213 +288,181 @@ inline void LLVector3::set(const glm::vec3& vec)
// deprecated
inline void LLVector3::setVec(F32 x, F32 y, F32 z)
{
- mV[VX] = x;
- mV[VY] = y;
- mV[VZ] = z;
+ set(x, y, z);
}
// deprecated
-inline void LLVector3::setVec(const LLVector3 &vec)
+inline void LLVector3::setVec(const LLVector3& vec)
{
- mV[0] = vec.mV[0];
- mV[1] = vec.mV[1];
- mV[2] = vec.mV[2];
+ set(vec);
}
// deprecated
-inline void LLVector3::setVec(const F32 *vec)
+inline void LLVector3::setVec(const F32* vec)
{
- mV[0] = vec[0];
- mV[1] = vec[1];
- mV[2] = vec[2];
+ set(vec);
}
-inline F32 LLVector3::normalize(void)
+inline F32 LLVector3::normalize()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
- F32 oomag;
+ F32 mag = (F32) sqrt(mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ]);
if (mag > FP_MAG_THRESHOLD)
{
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- mV[2] *= oomag;
+ *this /= mag;
}
else
{
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
+ clear();
mag = 0;
}
- return (mag);
+ return mag;
}
// deprecated
-inline F32 LLVector3::normVec(void)
+inline F32 LLVector3::normVec()
{
- F32 mag = (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
- F32 oomag;
-
- if (mag > FP_MAG_THRESHOLD)
- {
- oomag = 1.f/mag;
- mV[0] *= oomag;
- mV[1] *= oomag;
- mV[2] *= oomag;
- }
- else
- {
- mV[0] = 0.f;
- mV[1] = 0.f;
- mV[2] = 0.f;
- mag = 0;
- }
- return (mag);
+ return normalize();
}
// LLVector3 Magnitude and Normalization Functions
-inline F32 LLVector3::length(void) const
+inline F32 LLVector3::length() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ return sqrt(lengthSquared());
}
-inline F32 LLVector3::lengthSquared(void) const
+inline F32 LLVector3::lengthSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
+ return mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
}
-inline F32 LLVector3::magVec(void) const
+inline F32 LLVector3::magVec() const
{
- return (F32) sqrt(mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2]);
+ return length();
}
-inline F32 LLVector3::magVecSquared(void) const
+inline F32 LLVector3::magVecSquared() const
{
- return mV[0]*mV[0] + mV[1]*mV[1] + mV[2]*mV[2];
+ return lengthSquared();
}
-inline bool LLVector3::inRange( F32 min, F32 max ) const
+inline bool LLVector3::inRange(F32 min, F32 max) const
{
- return mV[0] >= min && mV[0] <= max &&
- mV[1] >= min && mV[1] <= max &&
- mV[2] >= min && mV[2] <= max;
+ return mV[VX] >= min && mV[VX] <= max &&
+ mV[VY] >= min && mV[VY] <= max &&
+ mV[VZ] >= min && mV[VZ] <= max;
}
-inline LLVector3 operator+(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 operator+(const LLVector3& a, const LLVector3& b)
{
LLVector3 c(a);
return c += b;
}
-inline LLVector3 operator-(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 operator-(const LLVector3& a, const LLVector3& b)
{
LLVector3 c(a);
return c -= b;
}
-inline F32 operator*(const LLVector3 &a, const LLVector3 &b)
+inline F32 operator*(const LLVector3& a, const LLVector3& b)
{
- return (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]);
+ return (a.mV[VX]*b.mV[VX] + a.mV[VY]*b.mV[VY] + a.mV[VZ]*b.mV[VZ]);
}
-inline LLVector3 operator%(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 operator%(const LLVector3& a, const LLVector3& b)
{
- return LLVector3( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1] );
+ return LLVector3(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]);
}
-inline LLVector3 operator/(const LLVector3 &a, F32 k)
+inline LLVector3 operator/(const LLVector3& a, F32 k)
{
F32 t = 1.f / k;
- return LLVector3( a.mV[0] * t, a.mV[1] * t, a.mV[2] * t );
+ return LLVector3( a.mV[VX] * t, a.mV[VY] * t, a.mV[VZ] * t );
}
-inline LLVector3 operator*(const LLVector3 &a, F32 k)
+inline LLVector3 operator*(const LLVector3& a, F32 k)
{
- return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k );
+ return LLVector3( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k );
}
-inline LLVector3 operator*(F32 k, const LLVector3 &a)
+inline LLVector3 operator*(F32 k, const LLVector3& a)
{
- return LLVector3( a.mV[0] * k, a.mV[1] * k, a.mV[2] * k );
+ return LLVector3( a.mV[VX] * k, a.mV[VY] * k, a.mV[VZ] * k );
}
-inline bool operator==(const LLVector3 &a, const LLVector3 &b)
+inline bool operator==(const LLVector3& a, const LLVector3& b)
{
- return ( (a.mV[0] == b.mV[0])
- &&(a.mV[1] == b.mV[1])
- &&(a.mV[2] == b.mV[2]));
+ return ( (a.mV[VX] == b.mV[VX])
+ &&(a.mV[VY] == b.mV[VY])
+ &&(a.mV[VZ] == b.mV[VZ]));
}
-inline bool operator!=(const LLVector3 &a, const LLVector3 &b)
+inline bool operator!=(const LLVector3& a, const LLVector3& b)
{
- return ( (a.mV[0] != b.mV[0])
- ||(a.mV[1] != b.mV[1])
- ||(a.mV[2] != b.mV[2]));
+ return ( (a.mV[VX] != b.mV[VX])
+ ||(a.mV[VY] != b.mV[VY])
+ ||(a.mV[VZ] != b.mV[VZ]));
}
-inline bool operator<(const LLVector3 &a, const LLVector3 &b)
+inline bool operator<(const LLVector3& a, const LLVector3& b)
{
- return (a.mV[0] < b.mV[0]
- || (a.mV[0] == b.mV[0]
- && (a.mV[1] < b.mV[1]
- || ((a.mV[1] == b.mV[1])
- && a.mV[2] < b.mV[2]))));
+ return (a.mV[VX] < b.mV[VX]
+ || (a.mV[VX] == b.mV[VX]
+ && (a.mV[VY] < b.mV[VY]
+ || ((a.mV[VY] == b.mV[VY])
+ && a.mV[VZ] < b.mV[VZ]))));
}
-inline const LLVector3& operator+=(LLVector3 &a, const LLVector3 &b)
+inline const LLVector3& operator+=(LLVector3& a, const LLVector3& b)
{
- a.mV[0] += b.mV[0];
- a.mV[1] += b.mV[1];
- a.mV[2] += b.mV[2];
+ a.mV[VX] += b.mV[VX];
+ a.mV[VY] += b.mV[VY];
+ a.mV[VZ] += b.mV[VZ];
return a;
}
-inline const LLVector3& operator-=(LLVector3 &a, const LLVector3 &b)
+inline const LLVector3& operator-=(LLVector3& a, const LLVector3& b)
{
- a.mV[0] -= b.mV[0];
- a.mV[1] -= b.mV[1];
- a.mV[2] -= b.mV[2];
+ a.mV[VX] -= b.mV[VX];
+ a.mV[VY] -= b.mV[VY];
+ a.mV[VZ] -= b.mV[VZ];
return a;
}
-inline const LLVector3& operator%=(LLVector3 &a, const LLVector3 &b)
+inline const LLVector3& operator%=(LLVector3& a, const LLVector3& b)
{
- LLVector3 ret( a.mV[1]*b.mV[2] - b.mV[1]*a.mV[2], a.mV[2]*b.mV[0] - b.mV[2]*a.mV[0], a.mV[0]*b.mV[1] - b.mV[0]*a.mV[1]);
+ LLVector3 ret(a.mV[VY]*b.mV[VZ] - b.mV[VY]*a.mV[VZ], a.mV[VZ]*b.mV[VX] - b.mV[VZ]*a.mV[VX], a.mV[VX]*b.mV[VY] - b.mV[VX]*a.mV[VY]);
a = ret;
return a;
}
-inline const LLVector3& operator*=(LLVector3 &a, F32 k)
+inline const LLVector3& operator*=(LLVector3& a, F32 k)
{
- a.mV[0] *= k;
- a.mV[1] *= k;
- a.mV[2] *= k;
+ a.mV[VX] *= k;
+ a.mV[VY] *= k;
+ a.mV[VZ] *= k;
return a;
}
-inline const LLVector3& operator*=(LLVector3 &a, const LLVector3 &b)
+inline const LLVector3& operator*=(LLVector3& a, const LLVector3& b)
{
- a.mV[0] *= b.mV[0];
- a.mV[1] *= b.mV[1];
- a.mV[2] *= b.mV[2];
+ a.mV[VX] *= b.mV[VX];
+ a.mV[VY] *= b.mV[VY];
+ a.mV[VZ] *= b.mV[VZ];
return a;
}
-inline const LLVector3& operator/=(LLVector3 &a, F32 k)
+inline const LLVector3& operator/=(LLVector3& a, F32 k)
{
- F32 t = 1.f / k;
- a.mV[0] *= t;
- a.mV[1] *= t;
- a.mV[2] *= t;
+ a *= 1.f / k;
return a;
}
-inline LLVector3 operator-(const LLVector3 &a)
+inline LLVector3 operator-(const LLVector3& a)
{
- return LLVector3( -a.mV[0], -a.mV[1], -a.mV[2] );
+ return LLVector3(-a.mV[VX], -a.mV[VY], -a.mV[VZ]);
}
inline LLVector3::operator glm::vec3() const
@@ -522,40 +476,37 @@ inline LLVector3::operator glm::vec4() const
return glm::vec4(mV[VX], mV[VY], mV[VZ], 1.f);
}
-inline F32 dist_vec(const LLVector3 &a, const LLVector3 &b)
+inline F32 dist_vec(const LLVector3& a, const LLVector3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
- F32 z = a.mV[2] - b.mV[2];
- return (F32) sqrt( x*x + y*y + z*z );
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
+ F32 z = a.mV[VZ] - b.mV[VZ];
+ return sqrt(x*x + y*y + z*z);
}
-inline F32 dist_vec_squared(const LLVector3 &a, const LLVector3 &b)
+inline F32 dist_vec_squared(const LLVector3& a, const LLVector3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
- F32 z = a.mV[2] - b.mV[2];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
+ F32 z = a.mV[VZ] - b.mV[VZ];
return x*x + y*y + z*z;
}
-inline F32 dist_vec_squared2D(const LLVector3 &a, const LLVector3 &b)
+inline F32 dist_vec_squared2D(const LLVector3& a, const LLVector3& b)
{
- F32 x = a.mV[0] - b.mV[0];
- F32 y = a.mV[1] - b.mV[1];
+ F32 x = a.mV[VX] - b.mV[VX];
+ F32 y = a.mV[VY] - b.mV[VY];
return x*x + y*y;
}
-inline LLVector3 projected_vec(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 projected_vec(const LLVector3& a, const LLVector3& b)
{
F32 bb = b * b;
if (bb > FP_MAG_THRESHOLD * FP_MAG_THRESHOLD)
{
return ((a * b) / bb) * b;
}
- else
- {
- return b.zero;
- }
+ return b.zero;
}
inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b)
@@ -570,18 +521,18 @@ inline LLVector3 inverse_projected_vec(const LLVector3& a, const LLVector3& b)
return normalized_a * (b_length / dot_product);
}
-inline LLVector3 parallel_component(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 parallel_component(const LLVector3& a, const LLVector3& b)
{
return projected_vec(a, b);
}
-inline LLVector3 orthogonal_component(const LLVector3 &a, const LLVector3 &b)
+inline LLVector3 orthogonal_component(const LLVector3& a, const LLVector3& b)
{
return a - projected_vec(a, b);
}
-inline LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u)
+inline LLVector3 lerp(const LLVector3& a, const LLVector3& b, F32 u)
{
return LLVector3(
a.mV[VX] + (b.mV[VX] - a.mV[VX]) * u,
@@ -592,11 +543,7 @@ inline LLVector3 lerp(const LLVector3 &a, const LLVector3 &b, F32 u)
inline bool LLVector3::isNull() const
{
- if ( F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ] )
- {
- return true;
- }
- return false;
+ return F_APPROXIMATELY_ZERO > mV[VX]*mV[VX] + mV[VY]*mV[VY] + mV[VZ]*mV[VZ];
}
inline void update_min_max(LLVector3& min, LLVector3& max, const LLVector3& pos)
@@ -637,17 +584,17 @@ inline F32 angle_between(const LLVector3& a, const LLVector3& b)
ab = 0.0f; // get rid of negative zero
}
LLVector3 c = a % b; // crossproduct
- return atan2f(sqrtf(c * c), ab); // return the angle
+ return atan2f(c.length(), ab); // return the angle
}
-inline bool are_parallel(const LLVector3 &a, const LLVector3 &b, F32 epsilon)
+inline bool are_parallel(const LLVector3& a, const LLVector3& b, F32 epsilon)
{
LLVector3 an = a;
LLVector3 bn = b;
an.normalize();
bn.normalize();
F32 dot = an * bn;
- if ( (1.0f - fabs(dot)) < epsilon)
+ if (1.0f - fabs(dot) < epsilon)
{
return true;
}
diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp
index ad13656bbd..1b687642ca 100644
--- a/indra/llmath/v4color.cpp
+++ b/indra/llmath/v4color.cpp
@@ -124,65 +124,64 @@ LLColor4 LLColor4::cyan6(0.2f, 0.6f, 0.6f, 1.0f);
// conversion
LLColor4::operator LLColor4U() const
{
- return LLColor4U(
- (U8)llclampb(ll_round(mV[VRED]*255.f)),
- (U8)llclampb(ll_round(mV[VGREEN]*255.f)),
- (U8)llclampb(ll_round(mV[VBLUE]*255.f)),
- (U8)llclampb(ll_round(mV[VALPHA]*255.f)));
+ return LLColor4U((U8)llclampb(ll_round(mV[VRED] * 255.f)),
+ (U8)llclampb(ll_round(mV[VGREEN] * 255.f)),
+ (U8)llclampb(ll_round(mV[VBLUE] * 255.f)),
+ (U8)llclampb(ll_round(mV[VALPHA] * 255.f)));
}
-LLColor4::LLColor4(const LLColor3 &vec, F32 a)
+LLColor4::LLColor4(const LLColor3& vec, F32 a)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = a;
}
LLColor4::LLColor4(const LLColor4U& color4u)
{
- const F32 SCALE = 1.f/255.f;
- mV[VRED] = color4u.mV[VRED] * SCALE;
- mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
- mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
- mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
+ constexpr F32 SCALE = 1.f / 255.f;
+ mV[VRED] = color4u.mV[VRED] * SCALE;
+ mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
+ mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
+ mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
}
LLColor4::LLColor4(const LLVector4& vector4)
{
- mV[VRED] = vector4.mV[VRED];
+ mV[VRED] = vector4.mV[VRED];
mV[VGREEN] = vector4.mV[VGREEN];
- mV[VBLUE] = vector4.mV[VBLUE];
+ mV[VBLUE] = vector4.mV[VBLUE];
mV[VALPHA] = vector4.mV[VALPHA];
}
const LLColor4& LLColor4::set(const LLColor4U& color4u)
{
- const F32 SCALE = 1.f/255.f;
- mV[VRED] = color4u.mV[VRED] * SCALE;
- mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
- mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
- mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
+ constexpr F32 SCALE = 1.f / 255.f;
+ mV[VRED] = color4u.mV[VRED] * SCALE;
+ mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
+ mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
+ mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
return (*this);
}
-const LLColor4& LLColor4::set(const LLColor3 &vec)
+const LLColor4& LLColor4::set(const LLColor3& vec)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
-// no change to alpha!
-// mV[VALPHA] = 1.f;
+ // no change to alpha!
+ // mV[VALPHA] = 1.f;
return (*this);
}
-const LLColor4& LLColor4::set(const LLColor3 &vec, F32 a)
+const LLColor4& LLColor4::set(const LLColor3& vec, F32 a)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = a;
return (*this);
}
@@ -190,33 +189,33 @@ const LLColor4& LLColor4::set(const LLColor3 &vec, F32 a)
// deprecated -- use set()
const LLColor4& LLColor4::setVec(const LLColor4U& color4u)
{
- const F32 SCALE = 1.f/255.f;
- mV[VRED] = color4u.mV[VRED] * SCALE;
- mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
- mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
- mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
+ constexpr F32 SCALE = 1.f / 255.f;
+ mV[VRED] = color4u.mV[VRED] * SCALE;
+ mV[VGREEN] = color4u.mV[VGREEN] * SCALE;
+ mV[VBLUE] = color4u.mV[VBLUE] * SCALE;
+ mV[VALPHA] = color4u.mV[VALPHA] * SCALE;
return (*this);
}
// deprecated -- use set()
-const LLColor4& LLColor4::setVec(const LLColor3 &vec)
+const LLColor4& LLColor4::setVec(const LLColor3& vec)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
-// no change to alpha!
-// mV[VALPHA] = 1.f;
+ // no change to alpha!
+ // mV[VALPHA] = 1.f;
return (*this);
}
// deprecated -- use set()
-const LLColor4& LLColor4::setVec(const LLColor3 &vec, F32 a)
+const LLColor4& LLColor4::setVec(const LLColor3& vec, F32 a)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = a;
return (*this);
}
@@ -228,110 +227,110 @@ void LLColor4::setValue(const LLSD& sd)
F32 val;
bool out_of_range = false;
val = sd[0].asReal();
- mV[0] = llclamp(val, 0.f, 1.f);
- out_of_range = mV[0] != val;
+ mV[VRED] = llclamp(val, 0.f, 1.f);
+ out_of_range = mV[VRED] != val;
val = sd[1].asReal();
- mV[1] = llclamp(val, 0.f, 1.f);
- out_of_range |= mV[1] != val;
+ mV[VGREEN] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[VGREEN] != val;
val = sd[2].asReal();
- mV[2] = llclamp(val, 0.f, 1.f);
- out_of_range |= mV[2] != val;
+ mV[VBLUE] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[VBLUE] != val;
val = sd[3].asReal();
- mV[3] = llclamp(val, 0.f, 1.f);
- out_of_range |= mV[3] != val;
+ mV[VALPHA] = llclamp(val, 0.f, 1.f);
+ out_of_range |= mV[VALPHA] != val;
if (out_of_range)
{
LL_WARNS() << "LLSD color value out of range!" << LL_ENDL;
}
#else
- mV[0] = (F32) sd[0].asReal();
- mV[1] = (F32) sd[1].asReal();
- mV[2] = (F32) sd[2].asReal();
- mV[3] = (F32) sd[3].asReal();
+ mV[VRED] = (F32)sd[VRED].asReal();
+ mV[VGREEN] = (F32)sd[VGREEN].asReal();
+ mV[VBLUE] = (F32)sd[VBLUE].asReal();
+ mV[VALPHA] = (F32)sd[VALPHA].asReal();
#endif
}
-const LLColor4& LLColor4::operator=(const LLColor3 &a)
+const LLColor4& LLColor4::operator=(const LLColor3& a)
{
- mV[VRED] = a.mV[VRED];
+ mV[VRED] = a.mV[VRED];
mV[VGREEN] = a.mV[VGREEN];
- mV[VBLUE] = a.mV[VBLUE];
+ mV[VBLUE] = a.mV[VBLUE];
-// converting from an rgb sets a=1 (opaque)
+ // converting from an rgb sets a=1 (opaque)
mV[VALPHA] = 1.f;
return (*this);
}
-
-std::ostream& operator<<(std::ostream& s, const LLColor4 &a)
+std::ostream& operator<<(std::ostream& s, const LLColor4& a)
{
s << "{ " << a.mV[VRED] << ", " << a.mV[VGREEN] << ", " << a.mV[VBLUE] << ", " << a.mV[VALPHA] << " }";
return s;
}
-bool operator==(const LLColor4 &a, const LLColor3 &b)
+bool operator==(const LLColor4& a, const LLColor3& b)
{
- return ( (a.mV[VRED] == b.mV[VRED])
- &&(a.mV[VGREEN] == b.mV[VGREEN])
- &&(a.mV[VBLUE] == b.mV[VBLUE]));
+ return ((a.mV[VRED] == b.mV[VRED]) && (a.mV[VGREEN] == b.mV[VGREEN]) && (a.mV[VBLUE] == b.mV[VBLUE]));
}
-bool operator!=(const LLColor4 &a, const LLColor3 &b)
+bool operator!=(const LLColor4& a, const LLColor3& b)
{
- return ( (a.mV[VRED] != b.mV[VRED])
- ||(a.mV[VGREEN] != b.mV[VGREEN])
- ||(a.mV[VBLUE] != b.mV[VBLUE]));
+ return ((a.mV[VRED] != b.mV[VRED]) || (a.mV[VGREEN] != b.mV[VGREEN]) || (a.mV[VBLUE] != b.mV[VBLUE]));
}
-LLColor3 vec4to3(const LLColor4 &vec)
+LLColor3 vec4to3(const LLColor4& vec)
{
- LLColor3 temp(vec.mV[VRED], vec.mV[VGREEN], vec.mV[VBLUE]);
+ LLColor3 temp(vec.mV[VRED], vec.mV[VGREEN], vec.mV[VBLUE]);
return temp;
}
-LLColor4 vec3to4(const LLColor3 &vec)
+LLColor4 vec3to4(const LLColor3& vec)
{
- LLColor3 temp(vec.mV[VRED], vec.mV[VGREEN], vec.mV[VBLUE]);
+ LLColor3 temp(vec.mV[VRED], vec.mV[VGREEN], vec.mV[VBLUE]);
return temp;
}
-static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn )
+static F32 hueToRgb(F32 val1In, F32 val2In, F32 valHUeIn)
{
- if ( valHUeIn < 0.0f ) valHUeIn += 1.0f;
- if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f;
- if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn );
- if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In );
- if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f );
- return ( val1In );
+ if (valHUeIn < 0.0f)
+ valHUeIn += 1.0f;
+ if (valHUeIn > 1.0f)
+ valHUeIn -= 1.0f;
+ if ((6.0f * valHUeIn) < 1.0f)
+ return (val1In + (val2In - val1In) * 6.0f * valHUeIn);
+ if ((2.0f * valHUeIn) < 1.0f)
+ return (val2In);
+ if ((3.0f * valHUeIn) < 2.0f)
+ return (val1In + (val2In - val1In) * ((2.0f / 3.0f) - valHUeIn) * 6.0f);
+ return (val1In);
}
-void LLColor4::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn)
+void LLColor4::setHSL(F32 hValIn, F32 sValIn, F32 lValIn)
{
- if ( sValIn < 0.00001f )
+ if (sValIn < 0.00001f)
{
- mV[VRED] = lValIn;
+ mV[VRED] = lValIn;
mV[VGREEN] = lValIn;
- mV[VBLUE] = lValIn;
+ mV[VBLUE] = lValIn;
}
else
{
F32 interVal1;
F32 interVal2;
- if ( lValIn < 0.5f )
- interVal2 = lValIn * ( 1.0f + sValIn );
+ if (lValIn < 0.5f)
+ interVal2 = lValIn * (1.0f + sValIn);
else
- interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn );
+ interVal2 = (lValIn + sValIn) - (sValIn * lValIn);
interVal1 = 2.0f * lValIn - interVal2;
- mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) );
- mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn );
- mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) );
+ mV[VRED] = hueToRgb(interVal1, interVal2, hValIn + (1.f / 3.f));
+ mV[VGREEN] = hueToRgb(interVal1, interVal2, hValIn);
+ mV[VBLUE] = hueToRgb(interVal1, interVal2, hValIn - (1.f / 3.f));
}
}
@@ -341,58 +340,61 @@ void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const
F32 var_G = mV[VGREEN];
F32 var_B = mV[VBLUE];
- F32 var_Min = ( var_R < ( var_G < var_B ? var_G : var_B ) ? var_R : ( var_G < var_B ? var_G : var_B ) );
- F32 var_Max = ( var_R > ( var_G > var_B ? var_G : var_B ) ? var_R : ( var_G > var_B ? var_G : var_B ) );
+ F32 var_Min = (var_R < (var_G < var_B ? var_G : var_B) ? var_R : (var_G < var_B ? var_G : var_B));
+ F32 var_Max = (var_R > (var_G > var_B ? var_G : var_B) ? var_R : (var_G > var_B ? var_G : var_B));
F32 del_Max = var_Max - var_Min;
- F32 L = ( var_Max + var_Min ) / 2.0f;
+ F32 L = (var_Max + var_Min) / 2.0f;
F32 H = 0.0f;
F32 S = 0.0f;
- if ( del_Max == 0.0f )
+ if (del_Max == 0.0f)
{
- H = 0.0f;
- S = 0.0f;
+ H = 0.0f;
+ S = 0.0f;
}
else
{
- if ( L < 0.5 )
- S = del_Max / ( var_Max + var_Min );
+ if (L < 0.5f)
+ S = del_Max / (var_Max + var_Min);
else
- S = del_Max / ( 2.0f - var_Max - var_Min );
+ S = del_Max / (2.0f - var_Max - var_Min);
- F32 del_R = ( ( ( var_Max - var_R ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
- F32 del_G = ( ( ( var_Max - var_G ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
- F32 del_B = ( ( ( var_Max - var_B ) / 6.0f ) + ( del_Max / 2.0f ) ) / del_Max;
+ F32 del_R = (((var_Max - var_R) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ F32 del_G = (((var_Max - var_G) / 6.0f) + (del_Max / 2.0f)) / del_Max;
+ F32 del_B = (((var_Max - var_B) / 6.0f) + (del_Max / 2.0f)) / del_Max;
- if ( var_R >= var_Max )
+ if (var_R >= var_Max)
H = del_B - del_G;
- else
- if ( var_G >= var_Max )
- H = ( 1.0f / 3.0f ) + del_R - del_B;
- else
- if ( var_B >= var_Max )
- H = ( 2.0f / 3.0f ) + del_G - del_R;
+ else if (var_G >= var_Max)
+ H = (1.0f / 3.0f) + del_R - del_B;
+ else if (var_B >= var_Max)
+ H = (2.0f / 3.0f) + del_G - del_R;
- if ( H < 0.0f ) H += 1.0f;
- if ( H > 1.0f ) H -= 1.0f;
+ if (H < 0.0f)
+ H += 1.0f;
+ if (H > 1.0f)
+ H -= 1.0f;
}
- if (hue) *hue = H;
- if (saturation) *saturation = S;
- if (luminance) *luminance = L;
+ if (hue)
+ *hue = H;
+ if (saturation)
+ *saturation = S;
+ if (luminance)
+ *luminance = L;
}
// static
bool LLColor4::parseColor(const std::string& buf, LLColor4* color)
{
- if( buf.empty() || color == nullptr)
+ if (buf.empty() || color == nullptr)
{
return false;
}
- boost_tokenizer tokens(buf, boost::char_separator(", "));
+ boost_tokenizer tokens(buf, boost::char_separator(", "));
boost_tokenizer::iterator token_iter = tokens.begin();
if (token_iter == tokens.end())
{
@@ -401,16 +403,16 @@ bool LLColor4::parseColor(const std::string& buf, LLColor4* color)
// Grab the first token into a string, since we don't know
// if this is a float or a color name.
- std::string color_name( (*token_iter) );
+ std::string color_name((*token_iter));
++token_iter;
if (token_iter != tokens.end())
{
// There are more tokens to read. This must be a vector.
LLColor4 v;
- LLStringUtil::convertToF32( color_name, v.mV[VRED] );
- LLStringUtil::convertToF32( *token_iter, v.mV[VGREEN] );
- v.mV[VBLUE] = 0.0f;
+ LLStringUtil::convertToF32(color_name, v.mV[VRED]);
+ LLStringUtil::convertToF32(*token_iter, v.mV[VGREEN]);
+ v.mV[VBLUE] = 0.0f;
v.mV[VALPHA] = 1.0f;
++token_iter;
@@ -422,283 +424,284 @@ bool LLColor4::parseColor(const std::string& buf, LLColor4* color)
else
{
// There is a z-component.
- LLStringUtil::convertToF32( *token_iter, v.mV[VBLUE] );
+ LLStringUtil::convertToF32(*token_iter, v.mV[VBLUE]);
++token_iter;
if (token_iter != tokens.end())
{
// There is an alpha component.
- LLStringUtil::convertToF32( *token_iter, v.mV[VALPHA] );
+ LLStringUtil::convertToF32(*token_iter, v.mV[VALPHA]);
}
}
// Make sure all values are between 0 and 1.
if (v.mV[VRED] > 1.f || v.mV[VGREEN] > 1.f || v.mV[VBLUE] > 1.f || v.mV[VALPHA] > 1.f)
{
- v = v * (1.f / 255.f);
+ constexpr F32 SCALE{ 1.f / 255.f };
+ v *= SCALE;
}
- color->set( v );
+ color->set(v);
}
else // Single value. Read as a named color.
{
// We have a color name
- if ( "red" == color_name )
+ if ("red" == color_name)
{
color->set(LLColor4::red);
}
- else if ( "red1" == color_name )
+ else if ("red1" == color_name)
{
color->set(LLColor4::red1);
}
- else if ( "red2" == color_name )
+ else if ("red2" == color_name)
{
color->set(LLColor4::red2);
}
- else if ( "red3" == color_name )
+ else if ("red3" == color_name)
{
color->set(LLColor4::red3);
}
- else if ( "red4" == color_name )
+ else if ("red4" == color_name)
{
color->set(LLColor4::red4);
}
- else if ( "red5" == color_name )
+ else if ("red5" == color_name)
{
color->set(LLColor4::red5);
}
- else if( "green" == color_name )
+ else if ("green" == color_name)
{
color->set(LLColor4::green);
}
- else if( "green1" == color_name )
+ else if ("green1" == color_name)
{
color->set(LLColor4::green1);
}
- else if( "green2" == color_name )
+ else if ("green2" == color_name)
{
color->set(LLColor4::green2);
}
- else if( "green3" == color_name )
+ else if ("green3" == color_name)
{
color->set(LLColor4::green3);
}
- else if( "green4" == color_name )
+ else if ("green4" == color_name)
{
color->set(LLColor4::green4);
}
- else if( "green5" == color_name )
+ else if ("green5" == color_name)
{
color->set(LLColor4::green5);
}
- else if( "green6" == color_name )
+ else if ("green6" == color_name)
{
color->set(LLColor4::green6);
}
- else if( "blue" == color_name )
+ else if ("blue" == color_name)
{
color->set(LLColor4::blue);
}
- else if( "blue1" == color_name )
+ else if ("blue1" == color_name)
{
color->set(LLColor4::blue1);
}
- else if( "blue2" == color_name )
+ else if ("blue2" == color_name)
{
color->set(LLColor4::blue2);
}
- else if( "blue3" == color_name )
+ else if ("blue3" == color_name)
{
color->set(LLColor4::blue3);
}
- else if( "blue4" == color_name )
+ else if ("blue4" == color_name)
{
color->set(LLColor4::blue4);
}
- else if( "blue5" == color_name )
+ else if ("blue5" == color_name)
{
color->set(LLColor4::blue5);
}
- else if( "blue6" == color_name )
+ else if ("blue6" == color_name)
{
color->set(LLColor4::blue6);
}
- else if( "black" == color_name )
+ else if ("black" == color_name)
{
color->set(LLColor4::black);
}
- else if( "white" == color_name )
+ else if ("white" == color_name)
{
color->set(LLColor4::white);
}
- else if( "yellow" == color_name )
+ else if ("yellow" == color_name)
{
color->set(LLColor4::yellow);
}
- else if( "yellow1" == color_name )
+ else if ("yellow1" == color_name)
{
color->set(LLColor4::yellow1);
}
- else if( "yellow2" == color_name )
+ else if ("yellow2" == color_name)
{
color->set(LLColor4::yellow2);
}
- else if( "yellow3" == color_name )
+ else if ("yellow3" == color_name)
{
color->set(LLColor4::yellow3);
}
- else if( "yellow4" == color_name )
+ else if ("yellow4" == color_name)
{
color->set(LLColor4::yellow4);
}
- else if( "yellow5" == color_name )
+ else if ("yellow5" == color_name)
{
color->set(LLColor4::yellow5);
}
- else if( "yellow6" == color_name )
+ else if ("yellow6" == color_name)
{
color->set(LLColor4::yellow6);
}
- else if( "magenta" == color_name )
+ else if ("magenta" == color_name)
{
color->set(LLColor4::magenta);
}
- else if( "magenta1" == color_name )
+ else if ("magenta1" == color_name)
{
color->set(LLColor4::magenta1);
}
- else if( "magenta2" == color_name )
+ else if ("magenta2" == color_name)
{
color->set(LLColor4::magenta2);
}
- else if( "magenta3" == color_name )
+ else if ("magenta3" == color_name)
{
color->set(LLColor4::magenta3);
}
- else if( "magenta4" == color_name )
+ else if ("magenta4" == color_name)
{
color->set(LLColor4::magenta4);
}
- else if( "purple" == color_name )
+ else if ("purple" == color_name)
{
color->set(LLColor4::purple);
}
- else if( "purple1" == color_name )
+ else if ("purple1" == color_name)
{
color->set(LLColor4::purple1);
}
- else if( "purple2" == color_name )
+ else if ("purple2" == color_name)
{
color->set(LLColor4::purple2);
}
- else if( "purple3" == color_name )
+ else if ("purple3" == color_name)
{
color->set(LLColor4::purple3);
}
- else if( "purple4" == color_name )
+ else if ("purple4" == color_name)
{
color->set(LLColor4::purple4);
}
- else if( "purple5" == color_name )
+ else if ("purple5" == color_name)
{
color->set(LLColor4::purple5);
}
- else if( "purple6" == color_name )
+ else if ("purple6" == color_name)
{
color->set(LLColor4::purple6);
}
- else if( "pink" == color_name )
+ else if ("pink" == color_name)
{
color->set(LLColor4::pink);
}
- else if( "pink1" == color_name )
+ else if ("pink1" == color_name)
{
color->set(LLColor4::pink1);
}
- else if( "pink2" == color_name )
+ else if ("pink2" == color_name)
{
color->set(LLColor4::pink2);
}
- else if( "cyan" == color_name )
+ else if ("cyan" == color_name)
{
color->set(LLColor4::cyan);
}
- else if( "cyan1" == color_name )
+ else if ("cyan1" == color_name)
{
color->set(LLColor4::cyan1);
}
- else if( "cyan2" == color_name )
+ else if ("cyan2" == color_name)
{
color->set(LLColor4::cyan2);
}
- else if( "cyan3" == color_name )
+ else if ("cyan3" == color_name)
{
color->set(LLColor4::cyan3);
}
- else if( "cyan4" == color_name )
+ else if ("cyan4" == color_name)
{
color->set(LLColor4::cyan4);
}
- else if( "cyan5" == color_name )
+ else if ("cyan5" == color_name)
{
color->set(LLColor4::cyan5);
}
- else if( "cyan6" == color_name )
+ else if ("cyan6" == color_name)
{
color->set(LLColor4::cyan6);
}
- else if( "smoke" == color_name )
+ else if ("smoke" == color_name)
{
color->set(LLColor4::smoke);
}
- else if( "grey" == color_name )
+ else if ("grey" == color_name)
{
color->set(LLColor4::grey);
}
- else if( "grey1" == color_name )
+ else if ("grey1" == color_name)
{
color->set(LLColor4::grey1);
}
- else if( "grey2" == color_name )
+ else if ("grey2" == color_name)
{
color->set(LLColor4::grey2);
}
- else if( "grey3" == color_name )
+ else if ("grey3" == color_name)
{
color->set(LLColor4::grey3);
}
- else if( "grey4" == color_name )
+ else if ("grey4" == color_name)
{
color->set(LLColor4::grey4);
}
- else if( "orange" == color_name )
+ else if ("orange" == color_name)
{
color->set(LLColor4::orange);
}
- else if( "orange1" == color_name )
+ else if ("orange1" == color_name)
{
color->set(LLColor4::orange1);
}
- else if( "orange2" == color_name )
+ else if ("orange2" == color_name)
{
color->set(LLColor4::orange2);
}
- else if( "orange3" == color_name )
+ else if ("orange3" == color_name)
{
color->set(LLColor4::orange3);
}
- else if( "orange4" == color_name )
+ else if ("orange4" == color_name)
{
color->set(LLColor4::orange4);
}
- else if( "orange5" == color_name )
+ else if ("orange5" == color_name)
{
color->set(LLColor4::orange5);
}
- else if( "orange6" == color_name )
+ else if ("orange6" == color_name)
{
color->set(LLColor4::orange6);
}
- else if ( "clear" == color_name )
+ else if ("clear" == color_name)
{
color->set(0.f, 0.f, 0.f, 0.f);
}
@@ -714,21 +717,21 @@ bool LLColor4::parseColor(const std::string& buf, LLColor4* color)
// static
bool LLColor4::parseColor4(const std::string& buf, LLColor4* value)
{
- if( buf.empty() || value == nullptr)
+ if (buf.empty() || value == nullptr)
{
return false;
}
LLColor4 v;
- S32 count = sscanf( buf.c_str(), "%f, %f, %f, %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 );
- if (1 == count )
+ S32 count = sscanf(buf.c_str(), "%f, %f, %f, %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3);
+ if (1 == count)
{
// try this format
- count = sscanf( buf.c_str(), "%f %f %f %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3 );
+ count = sscanf(buf.c_str(), "%f %f %f %f", v.mV + 0, v.mV + 1, v.mV + 2, v.mV + 3);
}
- if( 4 == count )
+ if (4 == count)
{
- value->setVec( v );
+ value->setVec(v);
return true;
}
diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h
index cafdbd9d7c..d48020c223 100644
--- a/indra/llmath/v4color.h
+++ b/indra/llmath/v4color.h
@@ -28,7 +28,6 @@
#define LL_V4COLOR_H
#include "llerror.h"
-//#include "vmath.h"
#include "llmath.h"
#include "llsd.h"
@@ -38,213 +37,216 @@ class LLVector4;
// LLColor4 = |x y z w|
-static const U32 LENGTHOFCOLOR4 = 4;
+static constexpr U32 LENGTHOFCOLOR4 = 4;
-static const U32 MAX_LENGTH_OF_COLOR_NAME = 15; //Give plenty of room for additional colors...
+static constexpr U32 MAX_LENGTH_OF_COLOR_NAME = 15; // Give plenty of room for additional colors...
class LLColor4
{
- public:
- F32 mV[LENGTHOFCOLOR4];
- LLColor4(); // Initializes LLColor4 to (0, 0, 0, 1)
- LLColor4(F32 r, F32 g, F32 b); // Initializes LLColor4 to (r, g, b, 1)
- LLColor4(F32 r, F32 g, F32 b, F32 a); // Initializes LLColor4 to (r. g, b, a)
- LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a)
- explicit LLColor4(const LLSD& sd);
- explicit LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1)
- explicit LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc))
- explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion
- explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion
+public:
+ F32 mV[LENGTHOFCOLOR4];
+ LLColor4(); // Initializes LLColor4 to (0, 0, 0, 1)
+ LLColor4(F32 r, F32 g, F32 b); // Initializes LLColor4 to (r, g, b, 1)
+ LLColor4(F32 r, F32 g, F32 b, F32 a); // Initializes LLColor4 to (r. g, b, a)
+ LLColor4(const LLColor3& vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a)
+ explicit LLColor4(const LLSD& sd);
+ explicit LLColor4(const F32* vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1)
+ explicit LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc))
+ explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion
+ explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion
- LLSD getValue() const
- {
- LLSD ret;
- ret[0] = mV[0];
- ret[1] = mV[1];
- ret[2] = mV[2];
- ret[3] = mV[3];
- return ret;
- }
+ LLSD getValue() const
+ {
+ LLSD ret;
+ ret[VRED] = mV[VRED];
+ ret[VGREEN] = mV[VGREEN];
+ ret[VBLUE] = mV[VBLUE];
+ ret[VALPHA] = mV[VALPHA];
+ return ret;
+ }
- void setValue(const LLSD& sd);
+ void setValue(const LLSD& sd);
- void setHSL(F32 hue, F32 saturation, F32 luminance);
- void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
+ void setHSL(F32 hue, F32 saturation, F32 luminance);
+ void calcHSL(F32* hue, F32* saturation, F32* luminance) const;
- const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1)
- const LLColor4& setToWhite(); // zero LLColor4 to (0, 0, 0, 1)
+ const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1)
+ const LLColor4& setToWhite(); // zero LLColor4 to (0, 0, 0, 1)
- const LLColor4& setVec(F32 r, F32 g, F32 b, F32 a); // deprecated -- use set()
- const LLColor4& setVec(F32 r, F32 g, F32 b); // deprecated -- use set()
- const LLColor4& setVec(const LLColor4 &vec); // deprecated -- use set()
- const LLColor4& setVec(const LLColor3 &vec); // deprecated -- use set()
- const LLColor4& setVec(const LLColor3 &vec, F32 a); // deprecated -- use set()
- const LLColor4& setVec(const F32 *vec); // deprecated -- use set()
- const LLColor4& setVec(const LLColor4U& color4u); // deprecated -- use set()
+ const LLColor4& setVec(F32 r, F32 g, F32 b, F32 a); // deprecated -- use set()
+ const LLColor4& setVec(F32 r, F32 g, F32 b); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor4& vec); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor3& vec); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor3& vec, F32 a); // deprecated -- use set()
+ const LLColor4& setVec(const F32* vec); // deprecated -- use set()
+ const LLColor4& setVec(const LLColor4U& color4u); // deprecated -- use set()
- const LLColor4& set(F32 r, F32 g, F32 b, F32 a); // Sets LLColor4 to (r, g, b, a)
- const LLColor4& set(F32 r, F32 g, F32 b); // Sets LLColor4 to (r, g, b) (no change in a)
- const LLColor4& set(const LLColor4 &vec); // Sets LLColor4 to vec
- const LLColor4& set(const LLColor3 &vec); // Sets LLColor4 to LLColor3 vec (no change in alpha)
- const LLColor4& set(const LLColor3 &vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified
- const LLColor4& set(const F32 *vec); // Sets LLColor4 to vec
- const LLColor4& set(const F64 *vec); // Sets LLColor4 to (double)vec
- const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
+ const LLColor4& set(F32 r, F32 g, F32 b, F32 a); // Sets LLColor4 to (r, g, b, a)
+ const LLColor4& set(F32 r, F32 g, F32 b); // Sets LLColor4 to (r, g, b) (no change in a)
+ const LLColor4& set(const LLColor4& vec); // Sets LLColor4 to vec
+ const LLColor4& set(const LLColor3& vec); // Sets LLColor4 to LLColor3 vec (no change in alpha)
+ const LLColor4& set(const LLColor3& vec, F32 a); // Sets LLColor4 to LLColor3 vec, with alpha specified
+ const LLColor4& set(const F32* vec); // Sets LLColor4 to vec
+ const LLColor4& set(const F64* vec); // Sets LLColor4 to (double)vec
+ const LLColor4& set(const LLColor4U& color4u); // Sets LLColor4 to color4u, rescaled.
- // set from a vector of unknown type and size
- // may leave some data unmodified
- template
- const LLColor4& set(const std::vector& v);
+ // set from a vector of unknown type and size
+ // may leave some data unmodified
+ template
+ const LLColor4& set(const std::vector& v);
- // write to a vector of unknown type and size
- // maye leave some data unmodified
- template
- void write(std::vector& v) const;
+ // write to a vector of unknown type and size
+ // maye leave some data unmodified
+ template
+ void write(std::vector& v) const;
- const LLColor4& setAlpha(F32 a);
+ const LLColor4& setAlpha(F32 a);
- F32 magVec() const; // deprecated -- use length()
- F32 magVecSquared() const; // deprecated -- use lengthSquared()
- F32 normVec(); // deprecated -- use normalize()
+ F32 magVec() const; // deprecated -- use length()
+ F32 magVecSquared() const; // deprecated -- use lengthSquared()
+ F32 normVec(); // deprecated -- use normalize()
- F32 length() const; // Returns magnitude of LLColor4
- F32 lengthSquared() const; // Returns magnitude squared of LLColor4
- F32 normalize(); // deprecated -- use normalize()
+ F32 length() const; // Returns magnitude of LLColor4
+ F32 lengthSquared() const; // Returns magnitude squared of LLColor4
+ F32 normalize(); // deprecated -- use normalize()
- bool isOpaque() { return mV[VALPHA] == 1.f; }
+ bool isOpaque() const { return mV[VALPHA] == 1.f; }
- F32 operator[](int idx) const { return mV[idx]; }
- F32 &operator[](int idx) { return mV[idx]; }
+ F32 operator[](int idx) const { return mV[idx]; }
+ F32& operator[](int idx) { return mV[idx]; }
- const LLColor4& operator=(const LLColor3 &a); // Assigns vec3 to vec4 and returns vec4
+ const LLColor4& operator=(const LLColor3& a); // Assigns vec3 to vec4 and returns vec4
- bool operator<(const LLColor4& rhs) const;
- friend std::ostream& operator<<(std::ostream& s, const LLColor4 &a); // Print a
- friend LLColor4 operator+(const LLColor4 &a, const LLColor4 &b); // Return vector a + b
- friend LLColor4 operator-(const LLColor4 &a, const LLColor4 &b); // Return vector a minus b
- friend LLColor4 operator*(const LLColor4 &a, const LLColor4 &b); // Return component wise a * b
- friend LLColor4 operator*(const LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change)
- friend LLColor4 operator/(const LLColor4 &a, F32 k); // Return rgb divided by scalar k (no alpha change)
- friend LLColor4 operator*(F32 k, const LLColor4 &a); // Return rgb times scaler k (no alpha change)
- friend LLColor4 operator%(const LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change)
- friend LLColor4 operator%(F32 k, const LLColor4 &a); // Return alpha times scaler k (no rgb change)
+ bool operator<(const LLColor4& rhs) const;
+ friend std::ostream& operator<<(std::ostream& s, const LLColor4& a); // Print a
+ friend LLColor4 operator+(const LLColor4& a, const LLColor4& b); // Return vector a + b
+ friend LLColor4 operator-(const LLColor4& a, const LLColor4& b); // Return vector a minus b
+ friend LLColor4 operator*(const LLColor4& a, const LLColor4& b); // Return component wise a * b
+ friend LLColor4 operator*(const LLColor4& a, F32 k); // Return rgb times scaler k (no alpha change)
+ friend LLColor4 operator/(const LLColor4& a, F32 k); // Return rgb divided by scalar k (no alpha change)
+ friend LLColor4 operator*(F32 k, const LLColor4& a); // Return rgb times scaler k (no alpha change)
+ friend LLColor4 operator%(const LLColor4& a, F32 k); // Return alpha times scaler k (no rgb change)
+ friend LLColor4 operator%(F32 k, const LLColor4& a); // Return alpha times scaler k (no rgb change)
- friend bool operator==(const LLColor4 &a, const LLColor4 &b); // Return a == b
- friend bool operator!=(const LLColor4 &a, const LLColor4 &b); // Return a != b
+ friend bool operator==(const LLColor4& a, const LLColor4& b); // Return a == b
+ friend bool operator!=(const LLColor4& a, const LLColor4& b); // Return a != b
- friend bool operator==(const LLColor4 &a, const LLColor3 &b); // Return a == b
- friend bool operator!=(const LLColor4 &a, const LLColor3 &b); // Return a != b
+ friend bool operator==(const LLColor4& a, const LLColor3& b); // Return a == b
+ friend bool operator!=(const LLColor4& a, const LLColor3& b); // Return a != b
- friend const LLColor4& operator+=(LLColor4 &a, const LLColor4 &b); // Return vector a + b
- friend const LLColor4& operator-=(LLColor4 &a, const LLColor4 &b); // Return vector a minus b
- friend const LLColor4& operator*=(LLColor4 &a, F32 k); // Return rgb times scaler k (no alpha change)
- friend const LLColor4& operator%=(LLColor4 &a, F32 k); // Return alpha times scaler k (no rgb change)
+ friend const LLColor4& operator+=(LLColor4& a, const LLColor4& b); // Return vector a + b
+ friend const LLColor4& operator-=(LLColor4& a, const LLColor4& b); // Return vector a minus b
+ friend const LLColor4& operator*=(LLColor4& a, F32 k); // Return rgb times scaler k (no alpha change)
+ friend const LLColor4& operator%=(LLColor4& a, F32 k); // Return alpha times scaler k (no rgb change)
- friend const LLColor4& operator*=(LLColor4 &a, const LLColor4 &b); // Doesn't multiply alpha! (for lighting)
+ friend const LLColor4& operator*=(LLColor4& a, const LLColor4& b); // Doesn't multiply alpha! (for lighting)
- // conversion
- operator LLColor4U() const;
+ // conversion
+ operator LLColor4U() const;
- // Basic color values.
- static LLColor4 red;
- static LLColor4 green;
- static LLColor4 blue;
- static LLColor4 black;
- static LLColor4 white;
- static LLColor4 yellow;
- static LLColor4 magenta;
- static LLColor4 cyan;
- static LLColor4 smoke;
- static LLColor4 grey;
- static LLColor4 orange;
- static LLColor4 purple;
- static LLColor4 pink;
- static LLColor4 transparent;
+ // Basic color values.
+ static LLColor4 red;
+ static LLColor4 green;
+ static LLColor4 blue;
+ static LLColor4 black;
+ static LLColor4 white;
+ static LLColor4 yellow;
+ static LLColor4 magenta;
+ static LLColor4 cyan;
+ static LLColor4 smoke;
+ static LLColor4 grey;
+ static LLColor4 orange;
+ static LLColor4 purple;
+ static LLColor4 pink;
+ static LLColor4 transparent;
- // Extra color values.
- static LLColor4 grey1;
- static LLColor4 grey2;
- static LLColor4 grey3;
- static LLColor4 grey4;
+ // Extra color values.
+ static LLColor4 grey1;
+ static LLColor4 grey2;
+ static LLColor4 grey3;
+ static LLColor4 grey4;
- static LLColor4 red1;
- static LLColor4 red2;
- static LLColor4 red3;
- static LLColor4 red4;
- static LLColor4 red5;
+ static LLColor4 red1;
+ static LLColor4 red2;
+ static LLColor4 red3;
+ static LLColor4 red4;
+ static LLColor4 red5;
- static LLColor4 green1;
- static LLColor4 green2;
- static LLColor4 green3;
- static LLColor4 green4;
- static LLColor4 green5;
- static LLColor4 green6;
+ static LLColor4 green1;
+ static LLColor4 green2;
+ static LLColor4 green3;
+ static LLColor4 green4;
+ static LLColor4 green5;
+ static LLColor4 green6;
- static LLColor4 blue1;
- static LLColor4 blue2;
- static LLColor4 blue3;
- static LLColor4 blue4;
- static LLColor4 blue5;
- static LLColor4 blue6;
+ static LLColor4 blue1;
+ static LLColor4 blue2;
+ static LLColor4 blue3;
+ static LLColor4 blue4;
+ static LLColor4 blue5;
+ static LLColor4 blue6;
- static LLColor4 yellow1;
- static LLColor4 yellow2;
- static LLColor4 yellow3;
- static LLColor4 yellow4;
- static LLColor4 yellow5;
- static LLColor4 yellow6;
- static LLColor4 yellow7;
- static LLColor4 yellow8;
- static LLColor4 yellow9;
+ static LLColor4 yellow1;
+ static LLColor4 yellow2;
+ static LLColor4 yellow3;
+ static LLColor4 yellow4;
+ static LLColor4 yellow5;
+ static LLColor4 yellow6;
+ static LLColor4 yellow7;
+ static LLColor4 yellow8;
+ static LLColor4 yellow9;
- static LLColor4 orange1;
- static LLColor4 orange2;
- static LLColor4 orange3;
- static LLColor4 orange4;
- static LLColor4 orange5;
- static LLColor4 orange6;
+ static LLColor4 orange1;
+ static LLColor4 orange2;
+ static LLColor4 orange3;
+ static LLColor4 orange4;
+ static LLColor4 orange5;
+ static LLColor4 orange6;
- static LLColor4 magenta1;
- static LLColor4 magenta2;
- static LLColor4 magenta3;
- static LLColor4 magenta4;
+ static LLColor4 magenta1;
+ static LLColor4 magenta2;
+ static LLColor4 magenta3;
+ static LLColor4 magenta4;
- static LLColor4 purple1;
- static LLColor4 purple2;
- static LLColor4 purple3;
- static LLColor4 purple4;
- static LLColor4 purple5;
- static LLColor4 purple6;
+ static LLColor4 purple1;
+ static LLColor4 purple2;
+ static LLColor4 purple3;
+ static LLColor4 purple4;
+ static LLColor4 purple5;
+ static LLColor4 purple6;
- static LLColor4 pink1;
- static LLColor4 pink2;
+ static LLColor4 pink1;
+ static LLColor4 pink2;
- static LLColor4 cyan1;
- static LLColor4 cyan2;
- static LLColor4 cyan3;
- static LLColor4 cyan4;
- static LLColor4 cyan5;
- static LLColor4 cyan6;
+ static LLColor4 cyan1;
+ static LLColor4 cyan2;
+ static LLColor4 cyan3;
+ static LLColor4 cyan4;
+ static LLColor4 cyan5;
+ static LLColor4 cyan6;
- static bool parseColor(const std::string& buf, LLColor4* color);
- static bool parseColor4(const std::string& buf, LLColor4* color);
+ static bool parseColor(const std::string& buf, LLColor4* color);
+ static bool parseColor4(const std::string& buf, LLColor4* color);
- inline void clamp();
+ inline void clamp();
};
+static_assert(std::is_trivially_copyable::value, "LLColor4 must be trivial copy");
+static_assert(std::is_trivially_move_assignable::value, "LLColor4 must be trivial move");
+static_assert(std::is_standard_layout::value, "LLColor4 must be a standard layout type");
// Non-member functions
-F32 distVec(const LLColor4 &a, const LLColor4 &b); // Returns distance between a and b
-F32 distVec_squared(const LLColor4 &a, const LLColor4 &b); // Returns distance squared between a and b
-LLColor3 vec4to3(const LLColor4 &vec);
-LLColor4 vec3to4(const LLColor3 &vec);
-LLColor4 lerp(const LLColor4 &a, const LLColor4 &b, F32 u);
+F32 distVec(const LLColor4& a, const LLColor4& b); // Returns distance between a and b
+F32 distVec_squared(const LLColor4& a, const LLColor4& b); // Returns distance squared between a and b
+LLColor3 vec4to3(const LLColor4& vec);
+LLColor4 vec3to4(const LLColor3& vec);
+LLColor4 lerp(const LLColor4& a, const LLColor4& b, F32 u);
-inline LLColor4::LLColor4(void)
+inline LLColor4::LLColor4()
{
- mV[VRED] = 0.f;
+ mV[VRED] = 0.f;
mV[VGREEN] = 0.f;
- mV[VBLUE] = 0.f;
+ mV[VBLUE] = 0.f;
mV[VALPHA] = 1.f;
}
@@ -255,149 +257,146 @@ inline LLColor4::LLColor4(const LLSD& sd)
inline LLColor4::LLColor4(F32 r, F32 g, F32 b)
{
- mV[VRED] = r;
+ mV[VRED] = r;
mV[VGREEN] = g;
- mV[VBLUE] = b;
+ mV[VBLUE] = b;
mV[VALPHA] = 1.f;
}
inline LLColor4::LLColor4(F32 r, F32 g, F32 b, F32 a)
{
- mV[VRED] = r;
+ mV[VRED] = r;
mV[VGREEN] = g;
- mV[VBLUE] = b;
+ mV[VBLUE] = b;
mV[VALPHA] = a;
}
inline LLColor4::LLColor4(U32 clr)
{
- mV[VRED] = (clr&0xff) * (1.0f/255.0f);
- mV[VGREEN] = ((clr>>8)&0xff) * (1.0f/255.0f);
- mV[VBLUE] = ((clr>>16)&0xff) * (1.0f/255.0f);
- mV[VALPHA] = (clr>>24) * (1.0f/255.0f);
+ mV[VRED] = (clr & 0xff) * (1.0f / 255.0f);
+ mV[VGREEN] = ((clr >> 8) & 0xff) * (1.0f / 255.0f);
+ mV[VBLUE] = ((clr >> 16) & 0xff) * (1.0f / 255.0f);
+ mV[VALPHA] = (clr >> 24) * (1.0f / 255.0f);
}
-
-inline LLColor4::LLColor4(const F32 *vec)
+inline LLColor4::LLColor4(const F32* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
mV[VALPHA] = vec[VALPHA];
}
-inline const LLColor4& LLColor4::setToBlack(void)
+inline const LLColor4& LLColor4::setToBlack(void)
{
- mV[VRED] = 0.f;
+ mV[VRED] = 0.f;
mV[VGREEN] = 0.f;
- mV[VBLUE] = 0.f;
+ mV[VBLUE] = 0.f;
mV[VALPHA] = 1.f;
return (*this);
}
-inline const LLColor4& LLColor4::setToWhite(void)
+inline const LLColor4& LLColor4::setToWhite(void)
{
- mV[VRED] = 1.f;
+ mV[VRED] = 1.f;
mV[VGREEN] = 1.f;
- mV[VBLUE] = 1.f;
+ mV[VBLUE] = 1.f;
mV[VALPHA] = 1.f;
return (*this);
}
-inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z)
+inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z)
{
- mV[VRED] = x;
+ mV[VRED] = x;
mV[VGREEN] = y;
- mV[VBLUE] = z;
+ mV[VBLUE] = z;
-// no change to alpha!
-// mV[VALPHA] = 1.f;
+ // no change to alpha!
+ // mV[VALPHA] = 1.f;
return (*this);
}
-inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z, F32 a)
+inline const LLColor4& LLColor4::set(F32 x, F32 y, F32 z, F32 a)
{
- mV[VRED] = x;
+ mV[VRED] = x;
mV[VGREEN] = y;
- mV[VBLUE] = z;
+ mV[VBLUE] = z;
mV[VALPHA] = a;
return (*this);
}
-inline const LLColor4& LLColor4::set(const LLColor4 &vec)
+inline const LLColor4& LLColor4::set(const LLColor4& vec)
{
- mV[VRED] = vec.mV[VRED];
+ mV[VRED] = vec.mV[VRED];
mV[VGREEN] = vec.mV[VGREEN];
- mV[VBLUE] = vec.mV[VBLUE];
+ mV[VBLUE] = vec.mV[VBLUE];
mV[VALPHA] = vec.mV[VALPHA];
return (*this);
}
-
-inline const LLColor4& LLColor4::set(const F32 *vec)
+inline const LLColor4& LLColor4::set(const F32* vec)
{
- mV[VRED] = vec[VRED];
+ mV[VRED] = vec[VRED];
mV[VGREEN] = vec[VGREEN];
- mV[VBLUE] = vec[VBLUE];
+ mV[VBLUE] = vec[VBLUE];
mV[VALPHA] = vec[VALPHA];
return (*this);
}
-inline const LLColor4& LLColor4::set(const F64 *vec)
+inline const LLColor4& LLColor4::set(const F64* vec)
{
- mV[VRED] = static_cast(vec[VRED]);
+ mV[VRED] = static_cast(vec[VRED]);
mV[VGREEN] = static_cast