Merge branch develop into project/fonts-update

# Conflicts:
#	indra/llrender/llfontfreetype.cpp
This commit is contained in:
Andrey Kleshchev
2025-11-25 22:34:59 +02:00
1155 changed files with 76436 additions and 34560 deletions
+1
View File
@@ -1,6 +1,7 @@
# Replace tabs with spaces
1b68f71348ecf3983b76b40d7940da8377f049b7
33418a77b716e122da9778869cdbabe97c83ff37
6b974724826a038b0db794460b322eb4921da735
# Trim trailing whitespace
a0b3021bdcf76859054fda8e30abb3ed47749e83
8444cd9562a6a7b755fcb075864e205122354192
-3
View File
@@ -1,8 +1,5 @@
* text eol=lf
# VSTool (normalization disabled)
indra/tools/vstool/* -text
# Images
*.bmp binary
*.BMP binary
+7
View File
@@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: monthly
+63 -35
View File
@@ -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'
+37
View File
@@ -0,0 +1,37 @@
## Description
<!--
Describe what this PR changes or adds. Include any relevant context or motivation.
-->
## 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: <!-- e.g., closes #123 or relates to #456 -->
---
## 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
<!--
Add any other information, screenshots, or suggestions for reviewers here.
-->
+1
View File
@@ -0,0 +1 @@
qatest.yaml -text eol=crlf
+36 -29
View File
@@ -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: |
+21
View File
@@ -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.");
}
+1 -1
View File
@@ -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*
+1 -1
View File
@@ -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 }}"
+3 -3
View File
@@ -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
+610
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
-1
View File
@@ -26,7 +26,6 @@ debian/files
debian/secondlife-appearance-utility*
debian/secondlife-viewer*
indra/.distcc
indra/cmake/*
indra/out/*
indra/packages/*
+4 -4
View File
@@ -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)$
+13 -1
View File
@@ -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 youve 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
+416 -394
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -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"
@@ -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.
+16 -1
View File
@@ -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)
+34 -30
View File
@@ -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)
+21 -31
View File
@@ -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)
+25 -19
View File
@@ -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} )
+110 -32
View File
@@ -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)
-1
View File
@@ -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)
+4
View File
@@ -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
+9 -15
View File
@@ -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)
+10 -20
View File
@@ -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)
+11
View File
@@ -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)
+13 -10
View File
@@ -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)
+6 -5
View File
@@ -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})
+10 -10
View File
@@ -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)
+10 -10
View File
@@ -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)
+11 -1
View File
@@ -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
+14 -2
View File
@@ -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)
+20 -9
View File
@@ -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 ()
+24 -15
View File
@@ -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)
+13 -17
View File
@@ -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})
+8 -6
View File
@@ -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/$<LOWER_CASE:$<CONFIG>>)
link_directories(${AUTOBUILD_INSTALL_DIR}/lib/release)
if(NOT DARWIN)
link_directories(${AUTOBUILD_INSTALL_DIR}/lib/$<LOWER_CASE:$<CONFIG>>)
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()
+8 -8
View File
@@ -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)
+9 -6
View File
@@ -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)
+8 -5
View File
@@ -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)
+18 -17
View File
@@ -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 ()
+15 -4
View File
@@ -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)
+18 -6
View File
@@ -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)
+9 -6
View File
@@ -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)
+4
View File
@@ -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)
+1 -1
View File
@@ -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()
+12
View File
@@ -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()
+3 -3
View File
@@ -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
+9
View File
@@ -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/)
+5 -40
View File
@@ -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
+12 -20
View File
@@ -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 ()
+8 -5
View File
@@ -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)
+6
View File
@@ -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")
+1 -4
View File
@@ -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)
-14
View File
@@ -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)
-1
View File
@@ -1 +0,0 @@
+1 -6
View File
@@ -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)
@@ -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}/$<IF:$<BOOL:${LL_GENERATOR_IS_MULTI_CONFIG}>,$<CONFIG>,>/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)
@@ -43,6 +43,8 @@
#include "v4coloru.h"
#include "llsdserialize.h"
#include "llcleanup.h"
#include "lltrace.h"
#include "llfasttimer.h"
// system libraries
#include <iostream>
@@ -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;
}
+1
View File
@@ -14,6 +14,7 @@ set(llappearance_SOURCE_FILES
llavatarjoint.cpp
llavatarjointmesh.cpp
lldriverparam.cpp
lljointdata.h
lllocaltextureobject.cpp
llpolyskeletaldistortion.cpp
llpolymesh.cpp
+64 -3
View File
@@ -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<LLAvatarBoneInfo*> 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<LLAvatarBoneInfo*> 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<LLJointData> &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 <skeleton> nodes from XML tree
+7 -3
View File
@@ -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<std::string, LLJoint*> joint_map_t;
typedef std::map<std::string, LLJoint*, std::less<>> joint_map_t;
joint_map_t mJointMap;
typedef std::map<std::string, LLVector3> joint_state_map_t;
@@ -151,9 +153,11 @@ public:
public:
typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;
const avatar_joint_list_t& getSkeleton() { return mSkeleton; }
typedef std::map<std::string, std::string> joint_alias_map_t;
typedef std::map<std::string, std::string, std::less<>> joint_alias_map_t;
const joint_alias_map_t& getJointAliases();
typedef std::map<std::string, std::string> joint_parent_map_t; // matrix plus parent
typedef std::map<std::string, glm::mat4> joint_rest_map_t;
void getJointMatricesAndHierarhy(std::vector<LLJointData> &data) const;
protected:
static bool parseSkeletonFile(const std::string& filename, LLXmlTree& skeleton_xml_tree);
+66
View File
@@ -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<LLJointData> 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
+2 -1
View File
@@ -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)
{
+4 -4
View File
@@ -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;
}
+18 -11
View File
@@ -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();
+7 -6
View File
@@ -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.
+3 -1
View File
@@ -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;
}
-32
View File
@@ -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;
+3 -3
View File
@@ -131,7 +131,7 @@ LLQuaternion::Order bvhStringToOrder( char *str )
// LLBVHLoader()
//-----------------------------------------------------------------------------
LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string>& joint_alias_map )
LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string, std::less<>>& 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<std::string, std::string>::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 */
+1 -1
View File
@@ -227,7 +227,7 @@ class LLBVHLoader
friend class LLKeyframeMotion;
public:
// Constructor
LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string>& joint_alias_map );
LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine, std::map<std::string, std::string, std::less<>>& joint_alias_map );
~LLBVHLoader();
/*
+3 -4
View File
@@ -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);
}
+3 -1
View File
@@ -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
+3 -4
View File
@@ -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;
}
+1 -1
View File
@@ -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 );
+2 -1
View File
@@ -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})
+28 -19
View File
@@ -12,7 +12,10 @@
#if ! defined(LL_FSYSPATH_H)
#define LL_FSYSPATH_H
#include <boost/iterator/transform_iterator.hpp>
#include <filesystem>
#include <string>
#include <string_view>
// 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<char8_t> to engage std::filesystem::path's own UTF-8 conversion. But
// sigh, as of 2024-04-03 we're not yet there.
//
// Anyway, encapsulating the important UTF-8 conversions in our own subclass
// allows us to migrate forward to C++20 conventions without changing
// referencing code.
// 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<u8ify, std::string_view::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;
}
+194 -192
View File
@@ -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
-6
View File
@@ -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!
//
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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:
+17
View File
@@ -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;
}
+2
View File
@@ -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:
+37 -39
View File
@@ -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;
+41 -16
View File
@@ -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
+9
View File
@@ -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;
+1
View File
@@ -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);
/**
+7 -7
View File
@@ -171,13 +171,13 @@ constexpr U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 +
// recursion tail
template <typename T>
inline auto llmax(T data)
constexpr auto llmax(T data)
{
return data;
}
template <typename T0, typename T1, typename... Ts>
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 <typename T>
inline auto llmin(T data)
constexpr auto llmin(T data)
{
return data;
}
template <typename T0, typename T1, typename... Ts>
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 <typename A, typename MIN, typename MAX>
inline A llclamp(A a, MIN minval, MAX maxval)
constexpr A llclamp(A a, MIN minval, MAX maxval)
{
A aminval{ static_cast<A>(minval) }, amaxval{ static_cast<A>(maxval) };
if ( a < aminval )
@@ -213,13 +213,13 @@ inline A llclamp(A a, MIN minval, MAX maxval)
}
template <class LLDATATYPE>
inline LLDATATYPE llclampf(LLDATATYPE a)
constexpr LLDATATYPE llclampf(LLDATATYPE a)
{
return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(1));
}
template <class LLDATATYPE>
inline LLDATATYPE llclampb(LLDATATYPE a)
constexpr LLDATATYPE llclampb(LLDATATYPE a)
{
return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(255));
}
+1 -1
View File
@@ -79,7 +79,7 @@ namespace {
//
if (s.size())
{
OutputDebugString(utf8str_to_utf16str(s).c_str());
OutputDebugString(ll_convert<std::wstring>(s).c_str());
OutputDebugString(TEXT("\n"));
}
}
+1 -1
View File
@@ -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
+29 -35
View File
@@ -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 <intrin.h>
#else
#include <x86intrin.h>
#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 <intrin.h>
//#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<U32>(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<U64>(__rdtsc());
}
#endif
#endif
static BlockTimerStatHandle& getRootTimeBlock();
+268 -146
View File
@@ -35,7 +35,6 @@
#if LL_WINDOWS
#include "llwin32headers.h"
#include <stdlib.h> // Windows errno
#include <vector>
#else
#include <errno.h>
@@ -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<char,std::char_traits < char > > _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<std::wstring>(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<std::wstring>(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::wstring>(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<std::wstring>( _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<std::wstring>(_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<std::wstring>( _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<std::wstring>( _Filename ).c_str(),
_Mode | ios_base::out);
}
+92 -16
View File
@@ -41,8 +41,9 @@ typedef FILE LLFILE;
#include <sys/stat.h>
#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 <sys/types.h>
@@ -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();
};
+11
View File
@@ -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;
+9
View File
@@ -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 */
+47 -10
View File
@@ -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 <xmmintrin.h>
#endif
template <typename T> 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<size_t ALIGNMENT>
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__
+31 -5
View File
@@ -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

Some files were not shown because too many files have changed in this diff Show More