mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-11 17:54:20 +02:00
Compare commits
296 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 42ce97aca5 | |||
| a4df5c300e | |||
| 4bf51e735a | |||
| d7e7c8164c | |||
| eb5e3fcd13 | |||
| 8f8968cbb1 | |||
| ac83e93426 | |||
| 78d0cf4a4f | |||
| 2444c6090b | |||
| 7e49bc5a50 | |||
| 457719d0cc | |||
| c3e63d5a0e | |||
| 8c1b3f8ce3 | |||
| 55b37b794c | |||
| 1aca396e34 | |||
| cb000a5101 | |||
| 1ae2a96747 | |||
| 6834086c37 | |||
| b33b493c6e | |||
| 437fe1e442 | |||
| 2a348dcff9 | |||
| 2821986fb2 | |||
| 1a13f9707b | |||
| ff1b47942c | |||
| 13e4973b48 | |||
| fd46054fb7 | |||
| f618f39bee | |||
| 603486ad2f | |||
| a4b11651a4 | |||
| b6e9a04433 | |||
| 05a2bbbf35 | |||
| 16b6572826 | |||
| 806f06fba6 | |||
| 7a90caedec | |||
| 017b4d07da | |||
| 05015bc476 | |||
| 1f0f3b92b3 | |||
| fe3ce7f578 | |||
| 51c995168a | |||
| f83e4ff4bf | |||
| b67e793283 | |||
| d87ec54a5f | |||
| a6b1040caf | |||
| 9650c4b79a | |||
| 3f8eb5adf0 | |||
| 99a78f9a55 | |||
| c3ace64205 | |||
| 3b2c1ec6e3 | |||
| dba432639e | |||
| 166c4491c2 | |||
| d1cd5a62ed | |||
| b11a406519 | |||
| c7042e1877 | |||
| 896e0b82c2 | |||
| 7856757087 | |||
| b0ce5d7582 | |||
| e23416aa92 | |||
| 9a9cfca706 | |||
| 59feb88ef7 | |||
| 247cda0e26 | |||
| 9f3233224e | |||
| ef14238b4e | |||
| 13b7345189 | |||
| 48ca476a2f | |||
| 57ef8e7c25 | |||
| d09ce46700 | |||
| 3afc1c2663 | |||
| 5821762870 | |||
| 86b7a19f19 | |||
| cc85cef17c | |||
| 5f08f523c2 | |||
| b612959682 | |||
| aea83d5ece | |||
| 07aa5786e5 | |||
| 5bd70aff90 | |||
| 22b8d52311 | |||
| ee6c7e6286 | |||
| 66ea4c4967 | |||
| a6769818fd | |||
| 95535215aa | |||
| eadb46c5ac | |||
| b2b7943dbe | |||
| a0a261db50 | |||
| 8e73dea7e2 | |||
| e2a3670d65 | |||
| 342db51523 | |||
| 414f1660ed | |||
| cd9530eec3 | |||
| 53675cf5ce | |||
| e0566546c6 | |||
| 6c4a8efe25 | |||
| a8db6587cb | |||
| 1d8fb3d407 | |||
| 2d09d53805 | |||
| f5310f0ca4 | |||
| 972fcfa0f0 | |||
| b0582f6ea3 | |||
| 8b6c28b374 | |||
| 0a3c27765d | |||
| 040a8b8fc6 | |||
| 9f67f72d3c | |||
| 04438ace57 | |||
| e16236e450 | |||
| 3807517e02 | |||
| ab8bd8e754 | |||
| 65d63085f8 | |||
| 2c8ecc3ea7 | |||
| 5fbc79c466 | |||
| 8fe4183856 | |||
| 0d52608f1d | |||
| 5df3c54b84 | |||
| b2db2e71b6 | |||
| 7978370b39 | |||
| d187c61599 | |||
| fa745a58b2 | |||
| 16592f3a6e | |||
| 2b5d3510c3 | |||
| 76f690d96e | |||
| d5f75c9e42 | |||
| 13d3491571 | |||
| 8a6d6818fb | |||
| d7c1cbbc4e | |||
| 5644ca09c4 | |||
| 863307d871 | |||
| 904a0942f0 | |||
| 7f20ff60ea | |||
| 1ce246e05d | |||
| f79461b407 | |||
| bbfe32e963 | |||
| 06c67b0319 | |||
| c68753d776 | |||
| 15172303e4 | |||
| 9017ad626d | |||
| ef18567d9f | |||
| d0c2097cd4 | |||
| b5ed65ddd6 | |||
| 673917ae66 | |||
| e31f57a02f | |||
| ee57382d6e | |||
| 6683f84da0 | |||
| d2cb0aaf63 | |||
| 51a5e10b4e | |||
| c2dfc10c18 | |||
| 6628de5262 | |||
| 37f2837a55 | |||
| 4b76157b9e | |||
| 3b2962fe1c | |||
| 20721b05fb | |||
| 75187d69c6 | |||
| 3df128d9f9 | |||
| 426d77a932 | |||
| b3b1ff0f50 | |||
| 88029a1411 | |||
| 57e46f07fe | |||
| 254d955f89 | |||
| e490685b42 | |||
| 7b0c39a20d | |||
| 059d631a6d | |||
| 7c255bd58d | |||
| bbcd5ec25e | |||
| 5369d6b38e | |||
| b3834427bc | |||
| d7002433a2 | |||
| e1291d5b7c | |||
| e1fd632ba3 | |||
| fbaba52bc2 | |||
| 224e82f33e | |||
| 8df49d7676 | |||
| 88d8c561db | |||
| 78697466e0 | |||
| 5e150cd3eb | |||
| 23dd23b468 | |||
| 7d47dab728 | |||
| 74f2f73ce6 | |||
| 1e2f60a9b8 | |||
| bf892e9ece | |||
| a44fe80caa | |||
| 093287f6bf | |||
| e0365c1d10 | |||
| 6cb2086dfc | |||
| 3f4b424200 | |||
| 051fdd55b0 | |||
| 29f4318ef8 | |||
| 30d7fed0e5 | |||
| f0177a879c | |||
| 88af1e54a4 | |||
| d3ba0542f2 | |||
| 4d25bdcabb | |||
| 02c5f8f648 | |||
| fc23783224 | |||
| 7ade24fc77 | |||
| db16fa4403 | |||
| 1bc08722fd | |||
| 3a0a9f6705 | |||
| ae0b5834a0 | |||
| 55eddba08f | |||
| 0783ec1b9c | |||
| fc77fa1389 | |||
| 0f9b8afe04 | |||
| d39457951a | |||
| 9fcb526aca | |||
| 9cd0ec1634 | |||
| 0e178aecb8 | |||
| 66f764cf02 | |||
| 63f2d8d880 | |||
| b123f016ab | |||
| f08f679ba7 | |||
| 054e0509c4 | |||
| f86cd4c3d2 | |||
| a19b3747ea | |||
| 30440099c2 | |||
| 30dd35a743 | |||
| 4f1dab7b5f | |||
| baad1891eb | |||
| 6ea9e4a5b0 | |||
| 534330aa99 | |||
| 58a0ced8be | |||
| e18d5b7183 | |||
| b006366ea3 | |||
| 1db914f964 | |||
| 6b34999a51 | |||
| 85ea218b5d | |||
| 137f4f2666 | |||
| 4cc2a81f00 | |||
| da340c9e92 | |||
| a7356d3765 | |||
| 3aa0685786 | |||
| 2f8c98dccf | |||
| 59e422c538 | |||
| 5ef5e41e69 | |||
| 58facc8ab1 | |||
| 3341514bb4 | |||
| 0434aba3a8 | |||
| c1cb214a03 | |||
| 3233a3cf8f | |||
| 469a3d60b2 | |||
| bb35bed104 | |||
| 624acf5533 | |||
| f71f0b9cb0 | |||
| 07279568a6 | |||
| 4ef84fa51c | |||
| 38ee1e1e22 | |||
| 2b02a5dc78 | |||
| dead00eb62 | |||
| 4fa2b8e45d | |||
| fc90973509 | |||
| ff9176f83e | |||
| 63d3dd9978 | |||
| b704c6caaa | |||
| a64465681c | |||
| 539357436c | |||
| 22cb6b0c9c | |||
| 81df4e5def | |||
| a3f3e8733d | |||
| 6fc84f76bb | |||
| 0949f193b8 | |||
| 5f3dc1a76e | |||
| 9afea55bb6 | |||
| 433614ae85 | |||
| 00c85c4a8f | |||
| f9885315bd | |||
| 26563dbae2 | |||
| 53e3838c1d | |||
| 4509d11daf | |||
| 37d5bf33e8 | |||
| 76842401ee | |||
| bf9d38e86a | |||
| 7de2aad05a | |||
| 7d11e1f963 | |||
| 452e239eb4 | |||
| 8b82fbb449 | |||
| de84c41757 | |||
| 3000e113e2 | |||
| c5d6b28be4 | |||
| c0dfb8cfa0 | |||
| f9feca4f4d | |||
| 4fa9c4e382 | |||
| 93f1fcbe88 | |||
| 3d71e310c0 | |||
| 02d0f613ba | |||
| 3091407e9e | |||
| 70f6169eff | |||
| a1a3cd9d1b | |||
| 86c5d2ae2a | |||
| d759055231 | |||
| c6474852d5 | |||
| a2ac576711 | |||
| 1b6924a033 | |||
| 8e5e053b81 | |||
| 6891511a1d | |||
| c186f8d366 | |||
| eed53d19a0 | |||
| abb218c5cf | |||
| 249ac51827 | |||
| 3da22f126e | |||
| a509350646 |
@@ -8,4 +8,4 @@
|
||||
<!-- If applicable, including examples you've already tested with / recommendations for how to test further is very helpful! -->
|
||||
|
||||
### Did you use AI to help find, test, or implement this issue or feature?
|
||||
<!-- Answer yes or no. If you answer yes, please provide a brief explanation how. -->
|
||||
<!-- Answer yes or no. If you answer yes, please provide a brief explanation as to how you used it. Please see the Large Language Model (LLM) Usage Policy for more information: https://pcsx2.net/docs/contributing/#large-language-model-llm-usage-policy -->
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
name: "Update Base Translation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Update Base Translation
|
||||
run: ./.github/workflows/scripts/common/update_base_translation.sh
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Get Latest DB and Prepare DB File
|
||||
run: |
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
set-safe-directory: ${{ env.GITHUB_WORKSPACE }}
|
||||
# 10 here, since the odds of having 10 untagged commits in a row should be slim to none
|
||||
@@ -157,4 +157,21 @@ jobs:
|
||||
with:
|
||||
name: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
path: ci-artifacts
|
||||
report-error:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build_linux
|
||||
if: always() && needs.build_linux.result == 'failure' && inputs.publish == true
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Push Discord Webhook
|
||||
env:
|
||||
OWNER: PCSX2
|
||||
REPO: pcsx2
|
||||
DISCORD_BUILD_WEBHOOK: ${{ secrets.DISCORD_BUILD_WEBHOOK }}
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/announce-release
|
||||
npm ci
|
||||
FLATHUB_FAILURE=1 node index.js
|
||||
|
||||
@@ -20,6 +20,18 @@ jobs:
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
secrets: inherit
|
||||
build_linux_debug:
|
||||
name: "Debug"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "Debug Build"
|
||||
artifactPrefixName: "PCSX2-linux-Qt-x64-debug"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
cmakeBuildType: Debug
|
||||
secrets: inherit
|
||||
build_linux_flatpak:
|
||||
name: "Flatpak"
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
|
||||
@@ -39,6 +39,10 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
cmakeBuildType:
|
||||
required: false
|
||||
type: string
|
||||
default: Release
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -55,7 +59,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -129,7 +133,7 @@ jobs:
|
||||
ADDITIONAL_CMAKE_ARGS: ${{ inputs.cmakeflags }}
|
||||
run: |
|
||||
cmake -B build -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_BUILD_TYPE="${{ inputs.cmakeBuildType }}" \
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
||||
-DCMAKE_PREFIX_PATH="$HOME/deps" \
|
||||
-DCMAKE_C_COMPILER=clang-17 \
|
||||
|
||||
@@ -52,7 +52,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
outputs:
|
||||
new_tag: ${{ steps.tag_version.outputs.new_tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
# Docs - https://github.com/mathieudutour/github-tag-action
|
||||
- name: Bump Version and Push Tag
|
||||
@@ -176,7 +176,7 @@ jobs:
|
||||
name: "Upload Artifacts"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
@@ -209,6 +209,7 @@ jobs:
|
||||
gh release upload "${TAG_VAL}" ${{ github.WORKSPACE }}/ci-artifacts/out/* --repo PCSX2/pcsx2 --clobber
|
||||
|
||||
- name: Publish Release
|
||||
if: github.event_name != 'workflow_dispatch' || inputs.is_prerelease == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
|
||||
@@ -18,28 +18,28 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
QT=6.11.0
|
||||
QT=6.11.1
|
||||
QTAPNG=1.3.0
|
||||
|
||||
FFMPEG=8.1
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.4.1
|
||||
LIBPNG=1.6.56
|
||||
LIBJPEGTURBO=3.2.0
|
||||
LIBPNG=1.6.58
|
||||
LIBWEBP=1.6.0
|
||||
NVENC=13.0.19.0
|
||||
SDL=SDL3-3.4.4
|
||||
SDL=SDL3-3.4.12
|
||||
LZ4=1.10.0
|
||||
VULKAN=1.4.328.1
|
||||
ZSTD=1.5.7
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.2
|
||||
PLUTOSVG=0.0.7
|
||||
RAPIDYAML=0.11.1
|
||||
RAPIDYAML=0.12.1
|
||||
|
||||
SHADERC=2026.1
|
||||
SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
SHADERC=2026.2
|
||||
SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c
|
||||
SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375
|
||||
SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
@@ -47,21 +47,21 @@ cd deps-build
|
||||
export PKG_CONFIG_PATH="$INSTALLDIR/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||
|
||||
grep . > SHASUMS <<EOF
|
||||
231ad85979864d914dc9568a1b71c91d6cf20d7b2021d059103bf0eb51cb755e qtbase-everywhere-src-$QT.tar.xz
|
||||
d3adb02ac5e2fe24068dbdaee0d7cc68cc3fa8553291c1bfce77c9fe8e940cc8 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
dfa8d653be07087d9407ed4a4ebae847f8953e0b7abd829f089803ab652a30e6 qtsvg-everywhere-src-$QT.tar.xz
|
||||
cfb1993d7a10848965b01b9cf33a54b8a4ba4e5e3a6d28d59483e73f10d9fc76 qttools-everywhere-src-$QT.tar.xz
|
||||
54f48b2fe4316892ff930195f170a5385644acc7393505f3155c066b8e1ffe56 qttranslations-everywhere-src-$QT.tar.xz
|
||||
e710e6e760f92922b86e4dd68f6bbe94ef6510919519d1b0068e874b5ad84d37 qtwayland-everywhere-src-$QT.tar.xz
|
||||
d9594a31228aa23ad6b531719a29b45f0f3989fe6c136d45767ea179f233c1ac qtbase-everywhere-src-$QT.tar.xz
|
||||
b2bf6c6845ac175ed7f819145483ba4676f617aaa6a5012c8efee63c8bbac413 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
7f3cf02f4824bf03c2c5859ea6db173bf1482a1daf24e6cdf7bc78cfa26a8a94 qtsvg-everywhere-src-$QT.tar.xz
|
||||
8e61835a679c93fa9c6065b142353c2071ba68e297898937c32a03777fcaf50d qttools-everywhere-src-$QT.tar.xz
|
||||
37c02c81206594c7bb4edca85ac93e8e55a9836b70c960fde6cb0f8623ec5677 qttranslations-everywhere-src-$QT.tar.xz
|
||||
95788aa502f75441d4edf65932b235f76523084e13dbbb7b9ee2d207b32bd9b3 qtwayland-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
|
||||
b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz
|
||||
96e5c2d7f2c482a60d5804da48a2eb9a0db0719b2c65dcc169fbfdcf37f3a45d libbacktrace-$LIBBACKTRACE.tar.gz
|
||||
ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 libpng-$LIBPNG.tar.xz
|
||||
6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
ee712dbe6a89bb140bbfc2ce72358fb5ee5cc2240abeabd54855012db30b3864 $SDL.tar.gz
|
||||
9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 libpng-$LIBPNG-apng.patch.gz
|
||||
f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7 $SDL.tar.gz
|
||||
eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
13da39edb3a40ed9713ae390ca89faa2f1202c9dda869ef306a8d4383e242bee nv-codec-headers-$NVENC.tar.gz
|
||||
c465aa56757e7746ac707f582b6e2d51546569a4a2488c1172fb543aa5fdfc2c vulkan-sdk-$VULKAN.tar.gz
|
||||
@@ -69,12 +69,12 @@ eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
9d9938269adc25e9a9b84650338b87d130cf469d82685fffc028c325279619c1 rapidyaml-$RAPIDYAML-src.tgz
|
||||
e9efcdd17f86287748793cf21d106e461fcad8d103a3e5a23632afe93828660d rapidyaml-$RAPIDYAML-src.tgz
|
||||
|
||||
245002feccbe7f8361b223545a5654cea69780745886872d7efff50a38d96c66 shaderc-$SHADERC.tar.gz
|
||||
bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
f924178e75e3293082481b25ed64d5e48a795b479dac3bd3c83d23070855df42 shaderc-$SHADERC.tar.gz
|
||||
971848a1cc639ce8dc244e778b17efe0f690e32ac398a75e31d1c67ad06d3e0a shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
a6cb1b300bb8171795e116457e858e555334749f9cacaed8068ae0ef8681110c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
e156be0bd81c8812f1bff8e520422bfa9df61b3045587b9eb483185f1074a7b2 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
EOF
|
||||
|
||||
if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then
|
||||
|
||||
@@ -24,7 +24,7 @@ LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
PLUTOVG=1.3.2
|
||||
PLUTOSVG=0.0.7
|
||||
RAPIDYAML=0.11.1
|
||||
RAPIDYAML=0.12.1
|
||||
|
||||
SHADERC=2025.4
|
||||
SHADERC_GLSLANG=7a47e2531cb334982b2a2dd8513dca0a3de4373d
|
||||
@@ -50,7 +50,7 @@ c693867f10a7760ef1bcf85419d51783586768cc2c601d03841bc6a8b2554b9c shaderc-spirv-
|
||||
06b0a042f2e121e954badb4fd78c9e2d4bc7ed6087eceb26ab559c23cf94334f shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
9d9938269adc25e9a9b84650338b87d130cf469d82685fffc028c325279619c1 rapidyaml-$RAPIDYAML-src.tgz
|
||||
e9efcdd17f86287748793cf21d106e461fcad8d103a3e5a23632afe93828660d rapidyaml-$RAPIDYAML-src.tgz
|
||||
EOF
|
||||
|
||||
if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL3-3.4.4.tar.gz",
|
||||
"sha256": "ee712dbe6a89bb140bbfc2ce72358fb5ee5cc2240abeabd54855012db30b3864"
|
||||
"url": "https://libsdl.org/release/SDL3-3.4.12.tar.gz",
|
||||
"sha256": "f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -15,24 +15,24 @@
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/google/shaderc.git",
|
||||
"commit": "301b4ede53d59b68bf55f95bb26412d9233c8187"
|
||||
"commit": "d5f08ae5c5a9a45165578445cbd0f9adf0223448"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/KhronosGroup/glslang/archive/f0bd0257c308b9a26562c1a30c4748a0219cc951.tar.gz",
|
||||
"sha256": "bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647",
|
||||
"url": "https://github.com/KhronosGroup/glslang/archive/275822a6261ee689aadb1da5f09a0ec2f058685c.tar.gz",
|
||||
"sha256": "971848a1cc639ce8dc244e778b17efe0f690e32ac398a75e31d1c67ad06d3e0a",
|
||||
"dest": "third_party/glslang"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Headers/archive/04f10f650d514df88b76d25e83db360142c7b174.tar.gz",
|
||||
"sha256": "1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Headers/archive/58006c901d1d5c37dece6b6610e9af87fa951375.tar.gz",
|
||||
"sha256": "a6cb1b300bb8171795e116457e858e555334749f9cacaed8068ae0ef8681110c",
|
||||
"dest": "third_party/spirv-headers"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Tools/archive/fbe4f3ad913c44fe8700545f8ffe35d1382b7093.tar.gz",
|
||||
"sha256": "cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Tools/archive/6337eb62cadd7d124ac6789bf39c0f71148f0a73.tar.gz",
|
||||
"sha256": "e156be0bd81c8812f1bff8e520422bfa9df61b3045587b9eb483185f1074a7b2",
|
||||
"dest": "third_party/spirv-tools"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -14,21 +14,21 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.56/libpng-1.6.56.tar.xz",
|
||||
"sha256": "f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18"
|
||||
"url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.58/libpng-1.6.58.tar.xz",
|
||||
"sha256": "28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.56-apng.patch.gz",
|
||||
"dest-filename": "libpng-1.6.56-apng.patch.gz",
|
||||
"sha256": "9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8"
|
||||
"url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.58-apng.patch.gz",
|
||||
"dest-filename": "libpng-1.6.58-apng.patch.gz",
|
||||
"sha256": "eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"commands":
|
||||
[
|
||||
"gunzip -f libpng-1.6.56-apng.patch.gz",
|
||||
"patch -p1 < \"libpng-1.6.56-apng.patch\""
|
||||
"gunzip -f libpng-1.6.58-apng.patch.gz",
|
||||
"patch -p1 < \"libpng-1.6.58-apng.patch\""
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/biojppm/rapidyaml.git",
|
||||
"tag": "v0.11.1",
|
||||
"commit": "119b6042064d3828819e428e32e5a0f3035d5643"
|
||||
"tag": "v0.12.1",
|
||||
"commit": "b56567b0bd24e9ce7beb08d6950a5732f62f6e74"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -3,7 +3,7 @@ Version=1.0
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Name=PCSX2
|
||||
StartupWMClass=PCSX2
|
||||
StartupWMClass=pcsx2-qt
|
||||
GenericName=PlayStation 2 Emulator
|
||||
Comment=Sony PlayStation 2 emulator
|
||||
Exec=pcsx2-qt
|
||||
|
||||
@@ -43,28 +43,28 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
QT=6.11.0
|
||||
QT=6.11.1
|
||||
QTAPNG=1.3.0
|
||||
|
||||
FREETYPE=2.14.3
|
||||
SDL=SDL3-3.4.4
|
||||
HARFBUZZ=14.0.0
|
||||
SDL=SDL3-3.4.12
|
||||
HARFBUZZ=14.2.0
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.56
|
||||
LIBJPEGTURBO=3.1.4.1
|
||||
LIBPNG=1.6.58
|
||||
LIBJPEGTURBO=3.2.0
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.1
|
||||
MOLTENVK=1.4.1
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.2
|
||||
PLUTOSVG=0.0.7
|
||||
RAPIDYAML=0.11.1
|
||||
RAPIDYAML=0.12.1
|
||||
|
||||
SHADERC=2026.1
|
||||
SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
SHADERC=2026.2
|
||||
SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c
|
||||
SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375
|
||||
SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
@@ -85,33 +85,33 @@ CMAKE_ARCH_ARM64=-DCMAKE_OSX_ARCHITECTURES="arm64"
|
||||
CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
|
||||
grep . > SHASUMS <<EOF
|
||||
231ad85979864d914dc9568a1b71c91d6cf20d7b2021d059103bf0eb51cb755e qtbase-everywhere-src-$QT.tar.xz
|
||||
d3adb02ac5e2fe24068dbdaee0d7cc68cc3fa8553291c1bfce77c9fe8e940cc8 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
dfa8d653be07087d9407ed4a4ebae847f8953e0b7abd829f089803ab652a30e6 qtsvg-everywhere-src-$QT.tar.xz
|
||||
cfb1993d7a10848965b01b9cf33a54b8a4ba4e5e3a6d28d59483e73f10d9fc76 qttools-everywhere-src-$QT.tar.xz
|
||||
54f48b2fe4316892ff930195f170a5385644acc7393505f3155c066b8e1ffe56 qttranslations-everywhere-src-$QT.tar.xz
|
||||
d9594a31228aa23ad6b531719a29b45f0f3989fe6c136d45767ea179f233c1ac qtbase-everywhere-src-$QT.tar.xz
|
||||
b2bf6c6845ac175ed7f819145483ba4676f617aaa6a5012c8efee63c8bbac413 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
7f3cf02f4824bf03c2c5859ea6db173bf1482a1daf24e6cdf7bc78cfa26a8a94 qtsvg-everywhere-src-$QT.tar.xz
|
||||
8e61835a679c93fa9c6065b142353c2071ba68e297898937c32a03777fcaf50d qttools-everywhere-src-$QT.tar.xz
|
||||
37c02c81206594c7bb4edca85ac93e8e55a9836b70c960fde6cb0f8623ec5677 qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
|
||||
36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz
|
||||
ee712dbe6a89bb140bbfc2ce72358fb5ee5cc2240abeabd54855012db30b3864 $SDL.tar.gz
|
||||
f29db9470e0ca5cef484e04e27baeec233aa428e8fdabe9e51b0f706c0809d24 harfbuzz-$HARFBUZZ.tar.gz
|
||||
f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7 $SDL.tar.gz
|
||||
c652d5d94971031654ab3989891a490a895d3e3f2b71171c62692b28e94b1b93 harfbuzz-$HARFBUZZ.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 libpng-$LIBPNG.tar.xz
|
||||
28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 libpng-$LIBPNG-apng.patch.gz
|
||||
ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz
|
||||
6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz
|
||||
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c MoltenVK-$MOLTENVK.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
9d9938269adc25e9a9b84650338b87d130cf469d82685fffc028c325279619c1 rapidyaml-$RAPIDYAML-src.tgz
|
||||
e9efcdd17f86287748793cf21d106e461fcad8d103a3e5a23632afe93828660d rapidyaml-$RAPIDYAML-src.tgz
|
||||
|
||||
245002feccbe7f8361b223545a5654cea69780745886872d7efff50a38d96c66 shaderc-$SHADERC.tar.gz
|
||||
bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
f924178e75e3293082481b25ed64d5e48a795b479dac3bd3c83d23070855df42 shaderc-$SHADERC.tar.gz
|
||||
971848a1cc639ce8dc244e778b17efe0f690e32ac398a75e31d1c67ad06d3e0a shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
a6cb1b300bb8171795e116457e858e555334749f9cacaed8068ae0ef8681110c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
e156be0bd81c8812f1bff8e520422bfa9df61b3045587b9eb483185f1074a7b2 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
EOF
|
||||
|
||||
if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then
|
||||
|
||||
@@ -20,28 +20,28 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
QT=6.11.0
|
||||
QT=6.11.1
|
||||
QTAPNG=1.3.0
|
||||
|
||||
FREETYPE=2.14.3
|
||||
SDL=SDL3-3.4.4
|
||||
HARFBUZZ=14.0.0
|
||||
SDL=SDL3-3.4.12
|
||||
HARFBUZZ=14.2.0
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.56
|
||||
LIBJPEGTURBO=3.1.4.1
|
||||
LIBPNG=1.6.58
|
||||
LIBJPEGTURBO=3.2.0
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.1
|
||||
MOLTENVK=1.4.1
|
||||
KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.2
|
||||
PLUTOSVG=0.0.7
|
||||
RAPIDYAML=0.11.1
|
||||
RAPIDYAML=0.12.1
|
||||
|
||||
SHADERC=2026.1
|
||||
SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
SHADERC=2026.2
|
||||
SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c
|
||||
SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375
|
||||
SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
@@ -61,33 +61,33 @@ CMAKE_COMMON=(
|
||||
)
|
||||
|
||||
grep . > SHASUMS <<EOF
|
||||
231ad85979864d914dc9568a1b71c91d6cf20d7b2021d059103bf0eb51cb755e qtbase-everywhere-src-$QT.tar.xz
|
||||
d3adb02ac5e2fe24068dbdaee0d7cc68cc3fa8553291c1bfce77c9fe8e940cc8 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
dfa8d653be07087d9407ed4a4ebae847f8953e0b7abd829f089803ab652a30e6 qtsvg-everywhere-src-$QT.tar.xz
|
||||
cfb1993d7a10848965b01b9cf33a54b8a4ba4e5e3a6d28d59483e73f10d9fc76 qttools-everywhere-src-$QT.tar.xz
|
||||
54f48b2fe4316892ff930195f170a5385644acc7393505f3155c066b8e1ffe56 qttranslations-everywhere-src-$QT.tar.xz
|
||||
d9594a31228aa23ad6b531719a29b45f0f3989fe6c136d45767ea179f233c1ac qtbase-everywhere-src-$QT.tar.xz
|
||||
b2bf6c6845ac175ed7f819145483ba4676f617aaa6a5012c8efee63c8bbac413 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
7f3cf02f4824bf03c2c5859ea6db173bf1482a1daf24e6cdf7bc78cfa26a8a94 qtsvg-everywhere-src-$QT.tar.xz
|
||||
8e61835a679c93fa9c6065b142353c2071ba68e297898937c32a03777fcaf50d qttools-everywhere-src-$QT.tar.xz
|
||||
37c02c81206594c7bb4edca85ac93e8e55a9836b70c960fde6cb0f8623ec5677 qttranslations-everywhere-src-$QT.tar.xz
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
|
||||
36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz
|
||||
ee712dbe6a89bb140bbfc2ce72358fb5ee5cc2240abeabd54855012db30b3864 $SDL.tar.gz
|
||||
f29db9470e0ca5cef484e04e27baeec233aa428e8fdabe9e51b0f706c0809d24 harfbuzz-$HARFBUZZ.tar.gz
|
||||
f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7 $SDL.tar.gz
|
||||
c652d5d94971031654ab3989891a490a895d3e3f2b71171c62692b28e94b1b93 harfbuzz-$HARFBUZZ.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
f7d8bf1601b7804f583a254ab343a6549ca6cf27d255c302c47af2d9d36a6f18 libpng-$LIBPNG.tar.xz
|
||||
28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 libpng-$LIBPNG-apng.patch.gz
|
||||
ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz
|
||||
6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a ffmpeg-$FFMPEG.tar.xz
|
||||
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
9d9938269adc25e9a9b84650338b87d130cf469d82685fffc028c325279619c1 rapidyaml-$RAPIDYAML-src.tgz
|
||||
e9efcdd17f86287748793cf21d106e461fcad8d103a3e5a23632afe93828660d rapidyaml-$RAPIDYAML-src.tgz
|
||||
|
||||
245002feccbe7f8361b223545a5654cea69780745886872d7efff50a38d96c66 shaderc-$SHADERC.tar.gz
|
||||
bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
f924178e75e3293082481b25ed64d5e48a795b479dac3bd3c83d23070855df42 shaderc-$SHADERC.tar.gz
|
||||
971848a1cc639ce8dc244e778b17efe0f690e32ac398a75e31d1c67ad06d3e0a shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
a6cb1b300bb8171795e116457e858e555334749f9cacaed8068ae0ef8681110c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
e156be0bd81c8812f1bff8e520422bfa9df61b3045587b9eb483185f1074a7b2 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
EOF
|
||||
|
||||
if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then
|
||||
|
||||
@@ -38,39 +38,54 @@ const octokit = new Octokit({
|
||||
}
|
||||
});
|
||||
|
||||
if (process.env.TAG_VAL === undefined || process.env.TAG_VAL === "") {
|
||||
console.log(`Not announcing - TAG_VAL not defined`);
|
||||
process.exit(1);
|
||||
let embed;
|
||||
|
||||
if (process.env.FLATHUB_FAILURE === undefined)
|
||||
{
|
||||
if (process.env.TAG_VAL === undefined || process.env.TAG_VAL === "") {
|
||||
console.log(`Not announcing - TAG_VAL not defined`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { data: releaseInfo } = await octokit.rest.repos.getReleaseByTag({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
tag: process.env.TAG_VAL,
|
||||
});
|
||||
|
||||
if (releaseInfo === undefined) {
|
||||
console.log(`Not announcing - could not locate release with tag ${process.env.TAG_VAL}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (!releaseInfo.prerelease) {
|
||||
console.log("Not announcing - release was not a pre-release (aka a Nightly)");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Publish Webhook
|
||||
embed = new MessageEmbed()
|
||||
.setColor('#FF8000')
|
||||
.setTitle('New PCSX2 Nightly Build Available!')
|
||||
.setDescription("To download the latest or previous builds, [visit the official downloads page](https://pcsx2.net/downloads/).")
|
||||
.addFields(
|
||||
{ name: 'Version', value: releaseInfo.tag_name, inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://pcsx2.net/docs/category/setup)', inline: true },
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
console.log(embed);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Flathub upload failure
|
||||
|
||||
const { data: releaseInfo } = await octokit.rest.repos.getReleaseByTag({
|
||||
owner: owner,
|
||||
repo: repo,
|
||||
tag: process.env.TAG_VAL,
|
||||
});
|
||||
|
||||
if (releaseInfo === undefined) {
|
||||
console.log(`Not announcing - could not locate release with tag ${process.env.TAG_VAL}`);
|
||||
process.exit(1);
|
||||
embed = new MessageEmbed()
|
||||
.setColor('#FF0000')
|
||||
.setTitle('PCSX2 Failed to Build/Upload to FlatHub')
|
||||
.setDescription("Please check the latest Flathub build job to determine the root cause.")
|
||||
console.log(embed);
|
||||
}
|
||||
|
||||
if (!releaseInfo.prerelease) {
|
||||
console.log("Not announcing - release was not a pre-release (aka a Nightly)");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Publish Webhook
|
||||
const embed = new MessageEmbed()
|
||||
.setColor('#FF8000')
|
||||
.setTitle('New PCSX2 Nightly Build Available!')
|
||||
.setDescription("To download the latest or previous builds, [visit the official downloads page](https://pcsx2.net/downloads/).")
|
||||
.addFields(
|
||||
{ name: 'Version', value: releaseInfo.tag_name, inline: true },
|
||||
{ name: 'Installation Steps', value: '[See Here](https://pcsx2.net/docs/category/setup)', inline: true },
|
||||
{ name: 'Included Changes', value: releaseInfo.body, inline: false }
|
||||
);
|
||||
console.log(embed);
|
||||
|
||||
// Get all webhooks, simple comma-sep string
|
||||
const webhookUrls = process.env.DISCORD_BUILD_WEBHOOK.split(",");
|
||||
|
||||
|
||||
Regular → Executable
+28
-28
@@ -54,16 +54,16 @@ echo INSTALLDIR=%INSTALLDIR%
|
||||
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set QT=6.11.0
|
||||
set QT=6.11.1
|
||||
set QTMINOR=6.11
|
||||
set QTAPNG=1.3.0
|
||||
|
||||
set FREETYPE=2.14.3
|
||||
set HARFBUZZ=14.0.0
|
||||
set SDL=SDL3-3.4.4
|
||||
set LIBJPEGTURBO=3.1.4.1
|
||||
set LIBPNG=1656
|
||||
set LIBPNGLONG=1.6.56
|
||||
set HARFBUZZ=14.2.0
|
||||
set SDL=SDL3-3.4.12
|
||||
set LIBJPEGTURBO=3.2.0
|
||||
set LIBPNG=1658
|
||||
set LIBPNGLONG=1.6.58
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.2
|
||||
@@ -72,42 +72,42 @@ set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.4.0
|
||||
set PLUTOVG=1.3.2
|
||||
set PLUTOSVG=0.0.7
|
||||
set RAPIDYAML=0.11.1
|
||||
set RAPIDYAML=0.12.1
|
||||
|
||||
set SHADERC=2026.1
|
||||
set SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
set SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
set SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
set SHADERC=2026.2
|
||||
set SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c
|
||||
set SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375
|
||||
set SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73
|
||||
|
||||
set AGILITYSDK=1.619.1
|
||||
set AGILITYSDK=1.619.2
|
||||
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 590d5ae246c85fa14d6458a36ff75a11236acfe8987c2475090aab1770acbdf8 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 5dfb3c0cb84d2c935c1716b3b86358ca496fb9216676e7e28fee1357fb4a050e || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" c92e1b46170b8671bbd46c783939f0c2dba4986882c5ebd37aaa9eba5b224fbe || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" ded4420823cb7b1bc49f38c5c56dd43ec27b6577ccbc7f620790abfabcc33b62 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" f9c4fd4fd73dff51e9043d2825b04361b678f63798ed798021ef47f1ff0bfccf || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 3529cc37297a5a7aae4486843b9fd41c30df1d79a770f85e240b537dcc327ca5 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 37fba768f2780580dfae535ad6654cb9dc0bf2272e71b9b9781988de9ed0dac0 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 767730188d4610a89bf8da502f87acf1c8881a3ac54f1e0eb167ab1e08b03a75 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 2d6ed2a98f458152e3cb17bf0be0494250194933a2d937b5a434e5b2006efca9 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" eef43700ffd079f5893e435aca1330c8bdbf2a94ae45013e3fc63870df53d3b0 || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip f4b86f4d107bc4f0b005c97d6cde43e548a125ee2810fa00d41844b46b6fe16a || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1656.zip 1ccf023c5f4ee1a7b75c5624f53acede5066f79b2fb14ddffaa28369adf9baac || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip bb2f83255706b1c92d731541c7cefaf98bb5b93e8f76d16f6deda05225ff20ee || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1658.zip b32f170855dbbe3e6d9e645af40b538137041773672c3ba3e02db5816c82d376 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 6bd4fbb665f77899a488b381c5b6e9681fc57c60b669738f985fea714f3456c5 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 3d4de8967a49c0451e775a0c1e9022092c19fdef41ba38a83fcf031c5a6496e2 || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 4fe4e48f28aa80171b2166d45c0976ab0f21eecedb52cd4c3ef73b5afb48fac9 || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" 9073a264301e93183844026239c9081717d52d13fb71aae68a0555c576b8de44 || goto error
|
||||
call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 30054b74abdf0ba35bf2cb435b6e49fcb6d62a8e78a240a018c36aa60dba765f || goto error
|
||||
call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" eb92d90bb23b2ec23410c41d791e41dbdbec942ab946924d1fdcb31eac6f0735 || goto error
|
||||
call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 96276f55b9fa7837ac8f3f72fd52965879cbb5d5d2e6af548c69a177fb078304 || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 3ac59c8216d367ab7858684d39c8faf872a64150aeb139335f4e083c5f79dde0 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 42a30acca4a35955370ed8ff6e54b823b4d4a5a86571baec1203d3fce87da447 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 00ecd73dcaaa956cf2221ce899ce096e9535ba20695483c5277adede462d1bde || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 65b23ace0ff0c64daf51f7741ebb6448899fa4aceefc72403e56f5b95607ca8e || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" f9401cc5cb36c276cd1e072b6595dbd728148e8dba389e50f7339e2d388dbc08 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 2b63189efad0348d88d410a5e12ec550a612e0b6ceef64624b8f45491269fb9c || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" d2f071e94c081f5a4606559770ebf1f7d1eac92a1def0c3e10609844aa8b69b2 || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 4011be89aa73e3461c9deef73936a62c79a3097590c5135d058041cc9fb99c6f || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
echo Building debug and release libraries...
|
||||
|
||||
Regular → Executable
+40
-28
@@ -61,7 +61,7 @@ set "PATH=%PATH%;%INSTALLDIR%\bin"
|
||||
|
||||
cd "%BUILDDIR%"
|
||||
|
||||
set QT=6.11.0
|
||||
set QT=6.11.1
|
||||
set QTMINOR=6.11
|
||||
set QTAPNG=1.3.0
|
||||
|
||||
@@ -76,11 +76,11 @@ set LIBSVTAV1=4.0.1
|
||||
set LIBX264=b35605ace3ddf7c1a5d67a2eb553f034aef41d55
|
||||
|
||||
set FREETYPE=2.14.3
|
||||
set HARFBUZZ=14.0.0
|
||||
set SDL=SDL3-3.4.4
|
||||
set LIBJPEGTURBO=3.1.4.1
|
||||
set LIBPNG=1656
|
||||
set LIBPNGLONG=1.6.56
|
||||
set HARFBUZZ=14.2.0
|
||||
set SDL=SDL3-3.4.12
|
||||
set LIBJPEGTURBO=3.2.0
|
||||
set LIBPNG=1658
|
||||
set LIBPNGLONG=1.6.58
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.2
|
||||
@@ -89,20 +89,21 @@ set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.4.0
|
||||
set PLUTOVG=1.3.2
|
||||
set PLUTOSVG=0.0.7
|
||||
set RAPIDYAML=0.11.1
|
||||
set RAPIDYAML=0.12.1
|
||||
|
||||
set SHADERC=2026.1
|
||||
set SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
set SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
set SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
set SHADERC=2026.2
|
||||
set SHADERC_GLSLANG=275822a6261ee689aadb1da5f09a0ec2f058685c
|
||||
set SHADERC_SPIRVHEADERS=58006c901d1d5c37dece6b6610e9af87fa951375
|
||||
set SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73
|
||||
|
||||
set AGILITYSDK=1.619.1
|
||||
set AGILITYSDK=1.619.2
|
||||
set DXHEADERS=1.619.1
|
||||
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 590d5ae246c85fa14d6458a36ff75a11236acfe8987c2475090aab1770acbdf8 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 5dfb3c0cb84d2c935c1716b3b86358ca496fb9216676e7e28fee1357fb4a050e || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" c92e1b46170b8671bbd46c783939f0c2dba4986882c5ebd37aaa9eba5b224fbe || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" ded4420823cb7b1bc49f38c5c56dd43ec27b6577ccbc7f620790abfabcc33b62 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" f9c4fd4fd73dff51e9043d2825b04361b678f63798ed798021ef47f1ff0bfccf || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 3529cc37297a5a7aae4486843b9fd41c30df1d79a770f85e240b537dcc327ca5 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 37fba768f2780580dfae535ad6654cb9dc0bf2272e71b9b9781988de9ed0dac0 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 767730188d4610a89bf8da502f87acf1c8881a3ac54f1e0eb167ab1e08b03a75 || goto error
|
||||
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 2d6ed2a98f458152e3cb17bf0be0494250194933a2d937b5a434e5b2006efca9 || goto error
|
||||
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" eef43700ffd079f5893e435aca1330c8bdbf2a94ae45013e3fc63870df53d3b0 || goto error
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
|
||||
call :downloadfile "ffmpeg-%FFMPEG%.tar.xz" "https://ffmpeg.org/releases/ffmpeg-%FFMPEG%.tar.xz" b072aed6871998cce9b36e7774033105ca29e33632be5b6347f3206898e0756a || goto error
|
||||
@@ -116,25 +117,26 @@ call :downloadfile "SVT-AV1-v%LIBSVTAV1%.zip" "https://gitlab.com/AOMediaCodec/S
|
||||
call :downloadfile "x264-%LIBX264%.zip" "https://code.videolan.org/videolan/x264/-/archive/%LIBX264%.zip" d95d059eff81cc565165cd058b66e208f0cc9874106a8fe94a811a66cf8a85a2 || goto error
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip f4b86f4d107bc4f0b005c97d6cde43e548a125ee2810fa00d41844b46b6fe16a || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1656.zip 1ccf023c5f4ee1a7b75c5624f53acede5066f79b2fb14ddffaa28369adf9baac || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 9ce32d4a2763a2ac5f258726ba2f49e9011327c1ee8c30862a32d0f30889fbe8 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" ecae8008e2cc9ade2f2c1bb9d5e6d4fb73e7c433866a056bd82980741571a022 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip bb2f83255706b1c92d731541c7cefaf98bb5b93e8f76d16f6deda05225ff20ee || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1658.zip b32f170855dbbe3e6d9e645af40b538137041773672c3ba3e02db5816c82d376 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 6bd4fbb665f77899a488b381c5b6e9681fc57c60b669738f985fea714f3456c5 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 3d4de8967a49c0451e775a0c1e9022092c19fdef41ba38a83fcf031c5a6496e2 || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 4fe4e48f28aa80171b2166d45c0976ab0f21eecedb52cd4c3ef73b5afb48fac9 || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" 9073a264301e93183844026239c9081717d52d13fb71aae68a0555c576b8de44 || goto error
|
||||
call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 30054b74abdf0ba35bf2cb435b6e49fcb6d62a8e78a240a018c36aa60dba765f || goto error
|
||||
call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" eb92d90bb23b2ec23410c41d791e41dbdbec942ab946924d1fdcb31eac6f0735 || goto error
|
||||
call :downloadfile "DirectX-Headers-%DXHEADERS%.zip" "https://github.com/microsoft/DirectX-Headers/archive/v%DXHEADERS%.zip" 9eb8b102a90a42e4ea72a825f7d249d55ec90d164f030966c9b7784b93374927 || goto error
|
||||
call :downloadfile "rapidyaml-%RAPIDYAML%-src.zip" "https://github.com/biojppm/rapidyaml/releases/download/v%RAPIDYAML%/rapidyaml-%RAPIDYAML%-src.zip" 96276f55b9fa7837ac8f3f72fd52965879cbb5d5d2e6af548c69a177fb078304 || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 3ac59c8216d367ab7858684d39c8faf872a64150aeb139335f4e083c5f79dde0 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 42a30acca4a35955370ed8ff6e54b823b4d4a5a86571baec1203d3fce87da447 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 00ecd73dcaaa956cf2221ce899ce096e9535ba20695483c5277adede462d1bde || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 65b23ace0ff0c64daf51f7741ebb6448899fa4aceefc72403e56f5b95607ca8e || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" f9401cc5cb36c276cd1e072b6595dbd728148e8dba389e50f7339e2d388dbc08 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 2b63189efad0348d88d410a5e12ec550a612e0b6ceef64624b8f45491269fb9c || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" d2f071e94c081f5a4606559770ebf1f7d1eac92a1def0c3e10609844aa8b69b2 || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 4011be89aa73e3461c9deef73936a62c79a3097590c5135d058041cc9fb99c6f || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
echo Building debug and release libraries...
|
||||
@@ -506,6 +508,16 @@ if %DEBUG%==1 (
|
||||
)
|
||||
cd .. || goto error
|
||||
|
||||
rem DirectX Headers include a CMakeList file, which is absent in the Nuget package
|
||||
echo Unpacking DirectX Headers
|
||||
rmdir /S /Q "DirectX-Headers-%DXHEADERS%"
|
||||
%SEVENZIP% x "DirectX-Headers-%DXHEADERS%.zip" || goto error
|
||||
cd "DirectX-Headers-%DXHEADERS%" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DDXHEADERS_BUILD_TEST=OFF -DDXHEADERS_BUILD_GOOGLE_TEST=OFF -B build -G Ninja || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
echo Building shaderc...
|
||||
rmdir /S /Q "shaderc-%SHADERC%"
|
||||
%SEVENZIP% x "shaderc-%SHADERC%.zip" || goto error
|
||||
|
||||
@@ -13,10 +13,10 @@ jobs:
|
||||
lint_vs_proj_files:
|
||||
name: Lint VS Project Files
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
runs-on: windows-2025
|
||||
runs-on: windows-2025-vs2026
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
- name: Verify VS Project Files
|
||||
run: .github\workflows\scripts\windows\validate-vs-filters.ps1
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ on:
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: windows-2025
|
||||
default: windows-2025-vs2026
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v6
|
||||
uses: actions/checkout@v7
|
||||
|
||||
- name: Configure MSBuild Clang Version
|
||||
if: inputs.configuration != 'CMake'
|
||||
|
||||
@@ -11,6 +11,10 @@ obj/
|
||||
*.pyc
|
||||
*.pyo
|
||||
|
||||
# Bazel-related files
|
||||
bazel-*
|
||||
MODULE.bazel.lock
|
||||
|
||||
# System files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
|
||||
Vendored
+1
-1
@@ -42,7 +42,7 @@ ENDMACRO()
|
||||
|
||||
MACRO(CPUINFO_TARGET_ENABLE_CXX11 target)
|
||||
SET_TARGET_PROPERTIES(${target} PROPERTIES
|
||||
CXX_STANDARD 14
|
||||
CXX_STANDARD 17
|
||||
CXX_EXTENSIONS NO)
|
||||
ENDMACRO()
|
||||
|
||||
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.18 FATAL_ERROR)
|
||||
|
||||
PROJECT(googletest-download NONE)
|
||||
|
||||
INCLUDE(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
URL https://github.com/google/googletest/archive/release-1.8.0.zip
|
||||
URL_HASH SHA256=f3ed3b58511efd272eb074a3a6d6fb79d7c2e6a0e374323d1e6bcbcc1ef141bf
|
||||
URL https://github.com/google/googletest/archive/refs/tags/v1.17.0.zip
|
||||
URL_HASH SHA256=40d4ec942217dcc84a9ebe2a68584ada7d4a33a8ee958755763278ea1c5e18ff
|
||||
SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/googletest"
|
||||
BINARY_DIR "${CONFU_DEPENDENCIES_BINARY_DIR}/googletest"
|
||||
CONFIGURE_COMMAND ""
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.1 FATAL_ERROR)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.10 FATAL_ERROR)
|
||||
|
||||
INCLUDE(GNUInstallDirs)
|
||||
|
||||
|
||||
Vendored
+32
@@ -355,6 +355,14 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_sunny_cove = 0x0010020C,
|
||||
/** Intel Willow Cove microarchitecture (10 nm, Tiger Lake). */
|
||||
cpuinfo_uarch_willow_cove = 0x0010020D,
|
||||
/** Intel Golden Cove microarchitecture (Sapphire Rapids). */
|
||||
cpuinfo_uarch_golden_cove = 0x0010020E,
|
||||
/** Intel Raptor Cove microarchitecture (Emerald Rapids). */
|
||||
cpuinfo_uarch_raptor_cove = 0x0010020F,
|
||||
/** Intel Redwood Cove microarchitecture (Granite Rapids). */
|
||||
cpuinfo_uarch_redwood_cove = 0x00100210,
|
||||
/** Intel Coyote Cove microarchitecture. */
|
||||
cpuinfo_uarch_coyote_cove = 0x00100211,
|
||||
|
||||
/** Pentium 4 with Willamette, Northwood, or Foster cores. */
|
||||
cpuinfo_uarch_willamette = 0x00100300,
|
||||
@@ -519,6 +527,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_cortex_a510 = 0x00300551,
|
||||
/** ARM Cortex-A520. */
|
||||
cpuinfo_uarch_cortex_a520 = 0x00300552,
|
||||
/** ARM Cortex-A320. */
|
||||
cpuinfo_uarch_cortex_a320 = 0x00300553,
|
||||
/** ARM Cortex-A710. */
|
||||
cpuinfo_uarch_cortex_a710 = 0x00300571,
|
||||
/** ARM Cortex-A715. */
|
||||
@@ -2226,6 +2236,12 @@ struct cpuinfo_riscv_isa {
|
||||
bool c;
|
||||
/* Vector Extension. */
|
||||
bool v;
|
||||
|
||||
/* ISA Extensions */
|
||||
/* Half-Precision Floating-Point Extension. */
|
||||
bool zfh;
|
||||
/* Half-Precision Floating-Point Vector Extension. */
|
||||
bool zvfh;
|
||||
};
|
||||
|
||||
extern struct cpuinfo_riscv_isa cpuinfo_isa;
|
||||
@@ -2301,6 +2317,22 @@ static inline bool cpuinfo_has_riscv_v(void) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_riscv_zfh(void) {
|
||||
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
|
||||
return cpuinfo_isa.zfh;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline bool cpuinfo_has_riscv_zvfh(void) {
|
||||
#if CPUINFO_ARCH_RISCV32 || CPUINFO_ARCH_RISCV64
|
||||
return cpuinfo_isa.zvfh;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
const struct cpuinfo_processor* CPUINFO_ABI cpuinfo_get_processors(void);
|
||||
const struct cpuinfo_core* CPUINFO_ABI cpuinfo_get_cores(void);
|
||||
const struct cpuinfo_cluster* CPUINFO_ABI cpuinfo_get_clusters(void);
|
||||
|
||||
Vendored
+3
@@ -1,3 +1,6 @@
|
||||
/* for syscall() */
|
||||
#define _DEFAULT_SOURCE
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
|
||||
+1
@@ -13,6 +13,7 @@ enum cpuinfo_android_chipset_property {
|
||||
cpuinfo_android_chipset_property_ro_arch,
|
||||
cpuinfo_android_chipset_property_ro_chipname,
|
||||
cpuinfo_android_chipset_property_ro_hardware_chipname,
|
||||
cpuinfo_android_chipset_property_ro_soc_model,
|
||||
cpuinfo_android_chipset_property_max,
|
||||
};
|
||||
|
||||
|
||||
@@ -63,4 +63,7 @@ void cpuinfo_arm_android_parse_properties(struct cpuinfo_android_properties prop
|
||||
cpuinfo_android_property_get("ro.hardware.chipname", properties->ro_hardware_chipname);
|
||||
cpuinfo_log_debug(
|
||||
"read ro.hardware.chipname = \"%.*s\"", ro_hardware_chipname_length, properties->ro_hardware_chipname);
|
||||
|
||||
const int ro_soc_model_length = cpuinfo_android_property_get("ro.soc.model", properties->ro_soc_model);
|
||||
cpuinfo_log_debug("read ro.soc.model = \"%.*s\"", ro_soc_model_length, properties->ro_soc_model);
|
||||
}
|
||||
|
||||
Vendored
+3
@@ -36,6 +36,7 @@ enum cpuinfo_arm_chipset_vendor {
|
||||
cpuinfo_arm_chipset_vendor_texas_instruments,
|
||||
cpuinfo_arm_chipset_vendor_unisoc,
|
||||
cpuinfo_arm_chipset_vendor_wondermedia,
|
||||
cpuinfo_arm_chipset_vendor_google,
|
||||
cpuinfo_arm_chipset_vendor_max,
|
||||
};
|
||||
|
||||
@@ -45,6 +46,7 @@ enum cpuinfo_arm_chipset_series {
|
||||
cpuinfo_arm_chipset_series_qualcomm_msm,
|
||||
cpuinfo_arm_chipset_series_qualcomm_apq,
|
||||
cpuinfo_arm_chipset_series_qualcomm_snapdragon,
|
||||
cpuinfo_arm_chipset_series_qualcomm_sm,
|
||||
cpuinfo_arm_chipset_series_mediatek_mt,
|
||||
cpuinfo_arm_chipset_series_samsung_exynos,
|
||||
cpuinfo_arm_chipset_series_hisilicon_k3v,
|
||||
@@ -72,6 +74,7 @@ enum cpuinfo_arm_chipset_series {
|
||||
cpuinfo_arm_chipset_series_unisoc_t,
|
||||
cpuinfo_arm_chipset_series_unisoc_ums,
|
||||
cpuinfo_arm_chipset_series_wondermedia_wm,
|
||||
cpuinfo_arm_chipset_series_google_tensor,
|
||||
cpuinfo_arm_chipset_series_max,
|
||||
};
|
||||
|
||||
|
||||
Vendored
+3
@@ -29,6 +29,7 @@ struct cpuinfo_android_properties {
|
||||
char ro_arch[CPUINFO_BUILD_PROP_VALUE_MAX];
|
||||
char ro_chipname[CPUINFO_BUILD_PROP_VALUE_MAX];
|
||||
char ro_hardware_chipname[CPUINFO_BUILD_PROP_VALUE_MAX];
|
||||
char ro_soc_model[CPUINFO_BUILD_PROP_VALUE_MAX];
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -364,6 +365,8 @@ CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_f
|
||||
const char ro_chipname[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
|
||||
CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_hardware_chipname(
|
||||
const char ro_hardware_chipname[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
|
||||
CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_soc_model(
|
||||
const char soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
|
||||
#else
|
||||
CPUINFO_INTERNAL struct cpuinfo_arm_chipset cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_revision(
|
||||
const char proc_cpuinfo_revision[restrict static CPUINFO_REVISION_VALUE_MAX]);
|
||||
|
||||
+90
-6
@@ -264,7 +264,7 @@ static bool match_sm(const char* start, const char* end, struct cpuinfo_arm_chip
|
||||
/* Return parsed chipset. */
|
||||
*chipset = (struct cpuinfo_arm_chipset){
|
||||
.vendor = cpuinfo_arm_chipset_vendor_qualcomm,
|
||||
.series = cpuinfo_arm_chipset_series_qualcomm_snapdragon,
|
||||
.series = cpuinfo_arm_chipset_series_qualcomm_sm,
|
||||
.model = model,
|
||||
};
|
||||
return true;
|
||||
@@ -3491,6 +3491,65 @@ struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_chipname(
|
||||
.series = cpuinfo_arm_chipset_series_unknown,
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Decodes chipset name from ro.soc.model Android system property.
|
||||
*
|
||||
* @param[in] soc_model - ro.soc.model value.
|
||||
*
|
||||
* @returns Decoded chipset name. If chipset could not be decoded, the resulting
|
||||
* structure would use `unknown` vendor and series identifiers.
|
||||
*/
|
||||
struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_soc_model(
|
||||
const char soc_model[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]) {
|
||||
struct cpuinfo_arm_chipset chipset = {
|
||||
.vendor = cpuinfo_arm_chipset_vendor_unknown,
|
||||
.series = cpuinfo_arm_chipset_series_unknown,
|
||||
};
|
||||
const size_t soc_model_length = strnlen(soc_model, CPUINFO_BUILD_PROP_VALUE_MAX);
|
||||
const char* soc_model_end = soc_model + soc_model_length;
|
||||
|
||||
/* Check Qualcomm SMxxxx signature */
|
||||
if (match_sm(soc_model, soc_model_end, &chipset)) {
|
||||
cpuinfo_log_debug(
|
||||
"matched Qualcomm SM signature in ro.soc.model string \"%.*s\"",
|
||||
(int)soc_model_length,
|
||||
soc_model);
|
||||
return chipset;
|
||||
}
|
||||
|
||||
/* Check Qualcomm MSM/APQ signatures */
|
||||
if (match_msm_apq(soc_model, soc_model_end, &chipset)) {
|
||||
cpuinfo_log_debug(
|
||||
"matched Qualcomm MSM/APQ signature in ro.soc.model string \"%.*s\"",
|
||||
(int)soc_model_length,
|
||||
soc_model);
|
||||
return chipset;
|
||||
}
|
||||
|
||||
if (soc_model[0] != '\0') {
|
||||
if (strncmp(soc_model, "Tensor", 6) == 0) {
|
||||
chipset.vendor = cpuinfo_arm_chipset_vendor_google;
|
||||
chipset.series = cpuinfo_arm_chipset_series_google_tensor;
|
||||
const char* suffix_start = soc_model + 6;
|
||||
while (*suffix_start == ' ') {
|
||||
suffix_start++;
|
||||
}
|
||||
const size_t suffix_length = strnlen(suffix_start, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
|
||||
if (suffix_length > 0) {
|
||||
strncpy(chipset.suffix, suffix_start, suffix_length);
|
||||
}
|
||||
return chipset;
|
||||
} else if (strncmp(soc_model, "GS201", 5) == 0) {
|
||||
chipset.vendor = cpuinfo_arm_chipset_vendor_google;
|
||||
chipset.series = cpuinfo_arm_chipset_series_google_tensor;
|
||||
strncpy(chipset.suffix, "G2", 2);
|
||||
return chipset;
|
||||
}
|
||||
}
|
||||
|
||||
return chipset;
|
||||
}
|
||||
#endif /* __ANDROID__ */
|
||||
|
||||
/*
|
||||
@@ -3828,6 +3887,7 @@ static const char* chipset_vendor_string[cpuinfo_arm_chipset_vendor_max] = {
|
||||
[cpuinfo_arm_chipset_vendor_texas_instruments] = "Texas Instruments",
|
||||
[cpuinfo_arm_chipset_vendor_unisoc] = "Unisoc",
|
||||
[cpuinfo_arm_chipset_vendor_wondermedia] = "WonderMedia",
|
||||
[cpuinfo_arm_chipset_vendor_google] = "Google",
|
||||
};
|
||||
|
||||
/* Map from ARM chipset series ID to its string representation */
|
||||
@@ -3837,6 +3897,7 @@ static const char* chipset_series_string[cpuinfo_arm_chipset_series_max] = {
|
||||
[cpuinfo_arm_chipset_series_qualcomm_msm] = "MSM",
|
||||
[cpuinfo_arm_chipset_series_qualcomm_apq] = "APQ",
|
||||
[cpuinfo_arm_chipset_series_qualcomm_snapdragon] = "Snapdragon ",
|
||||
[cpuinfo_arm_chipset_series_qualcomm_sm] = "SM",
|
||||
[cpuinfo_arm_chipset_series_mediatek_mt] = "MT",
|
||||
[cpuinfo_arm_chipset_series_samsung_exynos] = "Exynos ",
|
||||
[cpuinfo_arm_chipset_series_hisilicon_k3v] = "K3V",
|
||||
@@ -3864,6 +3925,7 @@ static const char* chipset_series_string[cpuinfo_arm_chipset_series_max] = {
|
||||
[cpuinfo_arm_chipset_series_unisoc_t] = "T",
|
||||
[cpuinfo_arm_chipset_series_unisoc_ums] = "UMS",
|
||||
[cpuinfo_arm_chipset_series_wondermedia_wm] = "WM",
|
||||
[cpuinfo_arm_chipset_series_google_tensor] = "Tensor",
|
||||
};
|
||||
|
||||
/* Convert chipset name represented by cpuinfo_arm_chipset structure to a string
|
||||
@@ -3882,14 +3944,35 @@ void cpuinfo_arm_chipset_to_string(
|
||||
const char* vendor_string = chipset_vendor_string[vendor];
|
||||
const char* series_string = chipset_series_string[series];
|
||||
const uint32_t model = chipset->model;
|
||||
const size_t suffix_length = strnlen(chipset->suffix, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
|
||||
if (model == 0) {
|
||||
if (series == cpuinfo_arm_chipset_series_unknown) {
|
||||
strncpy(name, vendor_string, CPUINFO_ARM_CHIPSET_NAME_MAX);
|
||||
if (suffix_length > 0) {
|
||||
if (series == cpuinfo_arm_chipset_series_unknown) {
|
||||
snprintf(
|
||||
name,
|
||||
CPUINFO_ARM_CHIPSET_NAME_MAX,
|
||||
"%s %.*s",
|
||||
vendor_string,
|
||||
(int)suffix_length,
|
||||
chipset->suffix);
|
||||
} else {
|
||||
snprintf(
|
||||
name,
|
||||
CPUINFO_ARM_CHIPSET_NAME_MAX,
|
||||
"%s %s %.*s",
|
||||
vendor_string,
|
||||
series_string,
|
||||
(int)suffix_length,
|
||||
chipset->suffix);
|
||||
}
|
||||
} else {
|
||||
snprintf(name, CPUINFO_ARM_CHIPSET_NAME_MAX, "%s %s", vendor_string, series_string);
|
||||
if (series == cpuinfo_arm_chipset_series_unknown) {
|
||||
strncpy(name, vendor_string, CPUINFO_ARM_CHIPSET_NAME_MAX);
|
||||
} else {
|
||||
snprintf(name, CPUINFO_ARM_CHIPSET_NAME_MAX, "%s %s", vendor_string, series_string);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const size_t suffix_length = strnlen(chipset->suffix, CPUINFO_ARM_CHIPSET_SUFFIX_MAX);
|
||||
snprintf(
|
||||
name,
|
||||
CPUINFO_ARM_CHIPSET_NAME_MAX,
|
||||
@@ -4020,7 +4103,6 @@ static enum cpuinfo_arm_chipset_vendor disambiguate_chipset_vendor(
|
||||
(vendor_a == cpuinfo_arm_chipset_vendor_spreadtrum && vendor_b == cpuinfo_arm_chipset_vendor_unisoc)) {
|
||||
return cpuinfo_arm_chipset_vendor_unisoc;
|
||||
}
|
||||
|
||||
return cpuinfo_arm_chipset_vendor_unknown;
|
||||
}
|
||||
|
||||
@@ -4074,6 +4156,8 @@ struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset(
|
||||
cpuinfo_arm_android_decode_chipset_from_ro_chipname(properties->ro_chipname),
|
||||
[cpuinfo_android_chipset_property_ro_hardware_chipname] =
|
||||
cpuinfo_arm_android_decode_chipset_from_ro_chipname(properties->ro_hardware_chipname),
|
||||
[cpuinfo_android_chipset_property_ro_soc_model] =
|
||||
cpuinfo_arm_android_decode_chipset_from_ro_soc_model(properties->ro_soc_model),
|
||||
};
|
||||
enum cpuinfo_arm_chipset_vendor vendor = cpuinfo_arm_chipset_vendor_unknown;
|
||||
for (size_t i = 0; i < cpuinfo_android_chipset_property_max; i++) {
|
||||
|
||||
+124
-9
@@ -1,5 +1,7 @@
|
||||
#include <ctype.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -14,6 +16,92 @@
|
||||
#include <cpuinfo/log.h>
|
||||
#include <linux/api.h>
|
||||
|
||||
/* Parse a uint32 from sysfs file content */
|
||||
static bool uint32_parser(const char* filename, const char* text_start, const char* text_end, void* context) {
|
||||
uint32_t* value_ptr = (uint32_t*)context;
|
||||
if (text_start == text_end) {
|
||||
return false;
|
||||
}
|
||||
uint32_t value = 0;
|
||||
for (const char* p = text_start; p < text_end && *p >= '0' && *p <= '9'; p++) {
|
||||
value = value * 10 + (*p - '0');
|
||||
}
|
||||
*value_ptr = value;
|
||||
return value > 0;
|
||||
}
|
||||
|
||||
/* Parse cache size with K/M suffix from /sys/devices/system/cpu/cpuN/cache/indexN/size (e.g. "2048K", "1M") */
|
||||
static bool cache_size_parser(const char* filename, const char* text_start, const char* text_end, void* context) {
|
||||
uint32_t* size_ptr = (uint32_t*)context;
|
||||
if (text_start == text_end) {
|
||||
return false;
|
||||
}
|
||||
uint32_t value = 0;
|
||||
const char* p = text_start;
|
||||
while (p < text_end && *p >= '0' && *p <= '9') {
|
||||
value = value * 10 + (*p - '0');
|
||||
p++;
|
||||
}
|
||||
if (p == text_start || value == 0) {
|
||||
return false;
|
||||
}
|
||||
uint32_t multiplier = 1024;
|
||||
if (p < text_end && toupper(*p) == 'M') {
|
||||
multiplier = 1024 * 1024;
|
||||
}
|
||||
*size_ptr = value * multiplier;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Check if /sys/devices/system/cpu/cpuN/cache/index2/shared_cpu_list indicates a single CPU (per-core cache) */
|
||||
static bool shared_cpu_list_parser(const char* filename, const char* text_start, const char* text_end, void* context) {
|
||||
bool* is_per_core = (bool*)context;
|
||||
for (const char* p = text_start; p < text_end; p++) {
|
||||
if (*p == ',' || *p == '-') {
|
||||
*is_per_core = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*is_per_core = (text_start != text_end);
|
||||
return *is_per_core;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read cache size from sysfs.
|
||||
*
|
||||
* ARM CPUs lack a CPUID-equivalent instruction to query cache properties,
|
||||
* so the library relies on hardcoded values that are often incorrect.
|
||||
* Linux exposes cache topology via sysfs (existed before 2008, documented 2014):
|
||||
* https://raw.githubusercontent.com/torvalds/linux/master/Documentation/ABI/testing/sysfs-devices-system-cpu
|
||||
*
|
||||
*/
|
||||
static uint32_t cpuinfo_linux_read_sysfs_cache_size(uint32_t cpu_id, uint32_t cache_level) {
|
||||
char path[256];
|
||||
|
||||
/* Verify the index corresponds to the requested cache level */
|
||||
snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%u/cache/index%u/level", cpu_id, cache_level);
|
||||
uint32_t actual_level = 0;
|
||||
if (!cpuinfo_linux_parse_small_file(path, 16, uint32_parser, &actual_level) || actual_level != cache_level) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%u/cache/index%u/size", cpu_id, cache_level);
|
||||
uint32_t size = 0;
|
||||
if (!cpuinfo_linux_parse_small_file(path, 32, cache_size_parser, &size)) {
|
||||
return 0;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Check if L2 cache is per-core by reading sysfs shared_cpu_list */
|
||||
static bool cpuinfo_linux_is_l2_per_core(uint32_t cpu_id) {
|
||||
char path[256];
|
||||
snprintf(path, sizeof(path), "/sys/devices/system/cpu/cpu%u/cache/index2/shared_cpu_list", cpu_id);
|
||||
bool is_per_core = false;
|
||||
cpuinfo_linux_parse_small_file(path, 128, shared_cpu_list_parser, &is_per_core);
|
||||
return is_per_core;
|
||||
}
|
||||
|
||||
struct cpuinfo_arm_isa cpuinfo_isa = {0};
|
||||
|
||||
static struct cpuinfo_package package = {{0}};
|
||||
@@ -168,12 +256,12 @@ void cpuinfo_arm_linux_init(void) {
|
||||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
struct cpuinfo_android_properties android_properties;
|
||||
struct cpuinfo_android_properties android_properties = {0};
|
||||
cpuinfo_arm_android_parse_properties(&android_properties);
|
||||
#else
|
||||
char proc_cpuinfo_hardware[CPUINFO_HARDWARE_VALUE_MAX];
|
||||
char proc_cpuinfo_hardware[CPUINFO_HARDWARE_VALUE_MAX] = {0};
|
||||
#endif
|
||||
char proc_cpuinfo_revision[CPUINFO_REVISION_VALUE_MAX];
|
||||
char proc_cpuinfo_revision[CPUINFO_REVISION_VALUE_MAX] = {0};
|
||||
|
||||
if (!cpuinfo_arm_linux_parse_proc_cpuinfo(
|
||||
#if defined(__ANDROID__)
|
||||
@@ -719,11 +807,21 @@ void cpuinfo_arm_linux_init(void) {
|
||||
*/
|
||||
shared_l3 = false;
|
||||
if (temp_l2.size != 0) {
|
||||
/* Assume L2 is shared by cores in the same
|
||||
* cluster */
|
||||
if (arm_linux_processors[i].package_leader_id ==
|
||||
arm_linux_processors[i].system_processor_id) {
|
||||
/* Check if L2 is per-core using sysfs */
|
||||
uint32_t sysfs_l2_size = cpuinfo_linux_read_sysfs_cache_size(
|
||||
arm_linux_processors[i].system_processor_id, 2);
|
||||
bool l2_is_per_core = (sysfs_l2_size > 0) &&
|
||||
cpuinfo_linux_is_l2_per_core(arm_linux_processors[i].system_processor_id);
|
||||
|
||||
if (l2_is_per_core) {
|
||||
/* L2 is private to each core */
|
||||
l2_count += 1;
|
||||
} else {
|
||||
/* Assume L2 is shared by cores in the same cluster */
|
||||
if (arm_linux_processors[i].package_leader_id ==
|
||||
arm_linux_processors[i].system_processor_id) {
|
||||
l2_count += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -771,10 +869,27 @@ void cpuinfo_arm_linux_init(void) {
|
||||
&temp_l2,
|
||||
&temp_l3);
|
||||
|
||||
if (temp_l3.size != 0) {
|
||||
/* Try to read L2 cache size from sysfs (more accurate) */
|
||||
uint32_t sysfs_l2_size =
|
||||
cpuinfo_linux_read_sysfs_cache_size(arm_linux_processors[i].system_processor_id, 2);
|
||||
if (sysfs_l2_size > 0) {
|
||||
temp_l2.size = sysfs_l2_size;
|
||||
/* Recalculate sets to maintain consistency: size = associativity * sets * partitions *
|
||||
* line_size */
|
||||
if (temp_l2.associativity > 0 && temp_l2.line_size > 0 && temp_l2.partitions > 0) {
|
||||
temp_l2.sets = sysfs_l2_size /
|
||||
(temp_l2.associativity * temp_l2.partitions * temp_l2.line_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if L2 is per-core by reading sysfs */
|
||||
bool l2_is_per_core = (sysfs_l2_size > 0) &&
|
||||
cpuinfo_linux_is_l2_per_core(arm_linux_processors[i].system_processor_id);
|
||||
|
||||
if (temp_l3.size != 0 || l2_is_per_core) {
|
||||
/*
|
||||
* Assumptions:
|
||||
* - L2 is private to each core
|
||||
* - L2 is private to each core (either has L3, or sysfs confirms per-core L2)
|
||||
* - L3 is shared by cores in the same cluster
|
||||
* - If cores in different clusters report the same L3,
|
||||
* it is shared between all cores.
|
||||
|
||||
Vendored
+59
-7
@@ -11,6 +11,11 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
#endif /* CPUINFO_ARCH_ARM */
|
||||
enum cpuinfo_vendor vendor[RESTRICT_STATIC 1],
|
||||
enum cpuinfo_uarch uarch[RESTRICT_STATIC 1]) {
|
||||
/* Ensure the out-parameters are always initialized, including for
|
||||
* implementers that are not handled in the switch below. */
|
||||
*vendor = cpuinfo_vendor_unknown;
|
||||
*uarch = cpuinfo_uarch_unknown;
|
||||
|
||||
switch (midr_get_implementer(midr)) {
|
||||
case 'A':
|
||||
*vendor = cpuinfo_vendor_arm;
|
||||
@@ -141,17 +146,20 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
case 0xD87: /* Cortex-A725 */
|
||||
*uarch = cpuinfo_uarch_cortex_a725;
|
||||
break;
|
||||
case 0xD8C:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_ultra;
|
||||
break;
|
||||
case 0xD90:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_premium;
|
||||
case 0xD8A:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_nano;
|
||||
break;
|
||||
case 0xD8B:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_pro;
|
||||
break;
|
||||
case 0xD8A:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_nano;
|
||||
case 0xD8C:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_ultra;
|
||||
break;
|
||||
case 0xD8F: /* Cortex-A320 */
|
||||
*uarch = cpuinfo_uarch_cortex_a320;
|
||||
break;
|
||||
case 0xD90:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_premium;
|
||||
break;
|
||||
default:
|
||||
switch (midr_get_part(midr) >> 8) {
|
||||
@@ -435,6 +443,50 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
midr_get_part(midr));
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
*vendor = cpuinfo_vendor_apple;
|
||||
switch (midr_get_part(midr)) {
|
||||
case 0x022:
|
||||
case 0x024:
|
||||
case 0x028:
|
||||
*uarch = cpuinfo_uarch_icestorm;
|
||||
break;
|
||||
case 0x023:
|
||||
case 0x025:
|
||||
case 0x029:
|
||||
*uarch = cpuinfo_uarch_firestorm;
|
||||
break;
|
||||
case 0x032:
|
||||
case 0x034:
|
||||
case 0x038:
|
||||
*uarch = cpuinfo_uarch_blizzard;
|
||||
break;
|
||||
case 0x033:
|
||||
case 0x035:
|
||||
case 0x039:
|
||||
*uarch = cpuinfo_uarch_avalanche;
|
||||
break;
|
||||
case 0x042:
|
||||
case 0x044:
|
||||
case 0x048:
|
||||
*uarch = cpuinfo_uarch_coll_sawtooth;
|
||||
break;
|
||||
case 0x043:
|
||||
case 0x045:
|
||||
case 0x049:
|
||||
*uarch = cpuinfo_uarch_coll_everest;
|
||||
break;
|
||||
case 0x052:
|
||||
*uarch = cpuinfo_uarch_donan_sawtooth;
|
||||
break;
|
||||
case 0x053:
|
||||
*uarch = cpuinfo_uarch_donan_everest;
|
||||
break;
|
||||
default:
|
||||
cpuinfo_log_warning(
|
||||
"unknown Apple CPU part 0x%03" PRIx32 " ignored", midr_get_part(midr));
|
||||
}
|
||||
break;
|
||||
#if CPUINFO_ARCH_ARM
|
||||
case 'V':
|
||||
*vendor = cpuinfo_vendor_marvell;
|
||||
|
||||
+3
-1
@@ -61,11 +61,13 @@ CPUINFO_INTERNAL void cpuinfo_riscv_linux_decode_isa_from_hwcap(struct cpuinfo_r
|
||||
* @param[processor] - The Linux ID of the target processor.
|
||||
* @param[vendor] - Reference to the cpuinfo_vendor to populate.
|
||||
* @param[uarch] - Reference to the cpuinfo_uarch to populate.
|
||||
* @param[isa] - Reference to the cpuinfo_riscv_isa to populate isa extensions.
|
||||
*/
|
||||
CPUINFO_INTERNAL void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
|
||||
uint32_t processor,
|
||||
enum cpuinfo_vendor vendor[restrict static 1],
|
||||
enum cpuinfo_uarch uarch[restrict static 1]);
|
||||
enum cpuinfo_uarch uarch[restrict static 1],
|
||||
struct cpuinfo_riscv_isa isa[restrict static 1]);
|
||||
|
||||
/* Used to determine which uarch is associated with the current thread. */
|
||||
extern CPUINFO_INTERNAL const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map;
|
||||
|
||||
+3
-2
@@ -6,7 +6,7 @@
|
||||
#include <riscv/linux/api.h>
|
||||
|
||||
/* ISA structure to hold supported extensions. */
|
||||
struct cpuinfo_riscv_isa cpuinfo_isa;
|
||||
struct cpuinfo_riscv_isa cpuinfo_isa = {0};
|
||||
|
||||
/* Helper function to bitmask flags and ensure operator precedence. */
|
||||
static inline bool bitmask_all(uint32_t flags, uint32_t mask) {
|
||||
@@ -320,7 +320,8 @@ void cpuinfo_riscv_linux_init(void) {
|
||||
cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
|
||||
processor,
|
||||
&riscv_linux_processors[processor].core.vendor,
|
||||
&riscv_linux_processors[processor].core.uarch);
|
||||
&riscv_linux_processors[processor].core.uarch,
|
||||
&cpuinfo_isa);
|
||||
|
||||
/* Populate frequency information of this core. */
|
||||
uint32_t frequency = cpuinfo_linux_get_processor_cur_frequency(processor);
|
||||
|
||||
+43
-1
@@ -53,6 +53,30 @@ struct riscv_hwprobe {
|
||||
#define RISCV_HWPROBE_EXT_ZBB (1 << 4)
|
||||
#define RISCV_HWPROBE_EXT_ZBS (1 << 5)
|
||||
#define RISCV_HWPROBE_EXT_ZICBOZ (1 << 6)
|
||||
#define RISCV_HWPROBE_EXT_ZBC (1 << 7)
|
||||
#define RISCV_HWPROBE_EXT_ZBKB (1 << 8)
|
||||
#define RISCV_HWPROBE_EXT_ZBKC (1 << 9)
|
||||
#define RISCV_HWPROBE_EXT_ZBKX (1 << 10)
|
||||
#define RISCV_HWPROBE_EXT_ZKND (1 << 11)
|
||||
#define RISCV_HWPROBE_EXT_ZKNE (1 << 12)
|
||||
#define RISCV_HWPROBE_EXT_ZKNH (1 << 13)
|
||||
#define RISCV_HWPROBE_EXT_ZKSED (1 << 14)
|
||||
#define RISCV_HWPROBE_EXT_ZKSH (1 << 15)
|
||||
#define RISCV_HWPROBE_EXT_ZKT (1 << 16)
|
||||
#define RISCV_HWPROBE_EXT_ZVBB (1 << 17)
|
||||
#define RISCV_HWPROBE_EXT_ZVBC (1 << 18)
|
||||
#define RISCV_HWPROBE_EXT_ZVKB (1 << 19)
|
||||
#define RISCV_HWPROBE_EXT_ZVKG (1 << 20)
|
||||
#define RISCV_HWPROBE_EXT_ZVKNED (1 << 21)
|
||||
#define RISCV_HWPROBE_EXT_ZVKNHA (1 << 22)
|
||||
#define RISCV_HWPROBE_EXT_ZVKNHB (1 << 23)
|
||||
#define RISCV_HWPROBE_EXT_ZVKSED (1 << 24)
|
||||
#define RISCV_HWPROBE_EXT_ZVKSH (1 << 25)
|
||||
#define RISCV_HWPROBE_EXT_ZVKT (1 << 26)
|
||||
#define RISCV_HWPROBE_EXT_ZFH (1 << 27)
|
||||
#define RISCV_HWPROBE_EXT_ZFHMIN (1 << 28)
|
||||
#define RISCV_HWPROBE_EXT_ZIHINTNTL (1 << 29)
|
||||
#define RISCV_HWPROBE_EXT_ZVFH (1 << 30)
|
||||
#define RISCV_HWPROBE_KEY_CPUPERF_0 5
|
||||
#define RISCV_HWPROBE_MISALIGNED_UNKNOWN (0 << 0)
|
||||
#define RISCV_HWPROBE_MISALIGNED_EMULATED (1 << 0)
|
||||
@@ -72,7 +96,8 @@ struct riscv_hwprobe {
|
||||
void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
|
||||
uint32_t processor,
|
||||
enum cpuinfo_vendor vendor[restrict static 1],
|
||||
enum cpuinfo_uarch uarch[restrict static 1]) {
|
||||
enum cpuinfo_uarch uarch[restrict static 1],
|
||||
struct cpuinfo_riscv_isa isa[restrict static 1]) {
|
||||
struct riscv_hwprobe pairs[] = {
|
||||
{
|
||||
.key = RISCV_HWPROBE_KEY_MVENDORID,
|
||||
@@ -83,6 +108,9 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
|
||||
{
|
||||
.key = RISCV_HWPROBE_KEY_MIMPID,
|
||||
},
|
||||
{
|
||||
.key = RISCV_HWPROBE_KEY_IMA_EXT_0,
|
||||
},
|
||||
};
|
||||
const size_t pairs_count = sizeof(pairs) / sizeof(struct riscv_hwprobe);
|
||||
|
||||
@@ -128,6 +156,7 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
|
||||
uint32_t vendor_id = 0;
|
||||
uint32_t arch_id = 0;
|
||||
uint32_t imp_id = 0;
|
||||
uint64_t ima_ext_0 = 0;
|
||||
for (size_t pair = 0; pair < pairs_count; pair++) {
|
||||
switch (pairs[pair].key) {
|
||||
case RISCV_HWPROBE_KEY_MVENDORID:
|
||||
@@ -139,6 +168,9 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
|
||||
case RISCV_HWPROBE_KEY_MIMPID:
|
||||
imp_id = pairs[pair].value;
|
||||
break;
|
||||
case RISCV_HWPROBE_KEY_IMA_EXT_0:
|
||||
ima_ext_0 = pairs[pair].value;
|
||||
break;
|
||||
default:
|
||||
/* The key value may be -1 if unsupported. */
|
||||
break;
|
||||
@@ -146,6 +178,16 @@ void cpuinfo_riscv_linux_decode_vendor_uarch_from_hwprobe(
|
||||
}
|
||||
cpuinfo_riscv_decode_vendor_uarch(vendor_id, arch_id, imp_id, vendor, uarch);
|
||||
|
||||
/* Parse ISA extensions retrieved. */
|
||||
if (ima_ext_0 != 0) {
|
||||
if (ima_ext_0 & RISCV_HWPROBE_EXT_ZFH) {
|
||||
isa->zfh = true;
|
||||
}
|
||||
if (ima_ext_0 & RISCV_HWPROBE_EXT_ZVFH) {
|
||||
isa->zvfh = true;
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
CPU_FREE(cpu_set);
|
||||
}
|
||||
|
||||
Vendored
+9
@@ -307,6 +307,15 @@ static bool transform_token(char* token_start, char* token_end, struct parser_st
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
/*
|
||||
* Erase everything starting with "with" on AMD
|
||||
* processors, e.g. "AMD Ryzen 5 PRO 6650U with Radeon
|
||||
* Graphics"
|
||||
*/
|
||||
if (erase_matching(token_start, token_length, "with")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Remember to erase "Dual Core" in "AMD Athlon(tm) 64
|
||||
* X2 Dual Core Processor 3800+" */
|
||||
if (memcmp(token_start, "Dual", token_length) == 0) {
|
||||
|
||||
Vendored
+13
@@ -171,6 +171,12 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
case 0x8C: // Tiger U
|
||||
case 0x8D: // Tiger H
|
||||
return cpuinfo_uarch_willow_cove;
|
||||
case 0x8F: // Sapphire Rapids
|
||||
return cpuinfo_uarch_golden_cove;
|
||||
case 0xCF: // Emerald Rapids
|
||||
return cpuinfo_uarch_raptor_cove;
|
||||
case 0xAD: // Granite Rapids
|
||||
return cpuinfo_uarch_redwood_cove;
|
||||
/* Low-power cores */
|
||||
case 0x1C: // Diamondville,
|
||||
// Silverthorne,
|
||||
@@ -264,8 +270,15 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
return cpuinfo_uarch_prescott;
|
||||
}
|
||||
break;
|
||||
case 0x12:
|
||||
switch (model_info->model) {
|
||||
case 0x01: // Nova Lake P-core (Coyote Cove)
|
||||
return cpuinfo_uarch_coyote_cove;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case cpuinfo_vendor_amd:
|
||||
switch (model_info->family) {
|
||||
#if CPUINFO_ARCH_X86
|
||||
|
||||
-2
@@ -265,8 +265,6 @@ BOOL CALLBACK cpuinfo_x86_windows_init(PINIT_ONCE init_once, PVOID parameter, PV
|
||||
* APIC order */
|
||||
const uint32_t core_id = cores_count++;
|
||||
uint32_t smt_id = 0;
|
||||
/* Reconstruct core part of APIC ID */
|
||||
const uint32_t core_apic_id = (core_id & core_bits_mask) << x86_processor.topology.core_bits_offset;
|
||||
/* Iterate processor groups and set the core & SMT parts of APIC
|
||||
* ID */
|
||||
for (uint32_t i = 0; i < core_info->Processor.GroupCount; i++) {
|
||||
|
||||
Vendored
+3
-2
@@ -585,8 +585,9 @@ cubeb_destroy(cubeb * context);
|
||||
NULL if this stream is input only. When input
|
||||
and output stream parameters are supplied, their
|
||||
rate has to be the same.
|
||||
@param latency_frames Stream latency in frames. Valid range
|
||||
is [1, 96000].
|
||||
@param latency_frames Requested stream latency in frames. Valid range is
|
||||
[1, 96000]. The actual latency may differ depending
|
||||
on the backend, platform, and hardware.
|
||||
@param data_callback Will be called to preroll data before playback is
|
||||
started by cubeb_stream_start.
|
||||
@param state_callback A pointer to a state callback.
|
||||
|
||||
Vendored
+3
@@ -294,6 +294,9 @@ set_timeout(struct timeval * timeout, unsigned int ms)
|
||||
static void
|
||||
stream_buffer_decrement(cubeb_stream * stm, long count)
|
||||
{
|
||||
if (count < 0 || (snd_pcm_uframes_t)count > stm->bufframes) {
|
||||
count = stm->bufframes;
|
||||
}
|
||||
char * bufremains =
|
||||
stm->buffer + WRAP(snd_pcm_frames_to_bytes)(stm->pcm, count);
|
||||
memmove(stm->buffer, bufremains,
|
||||
|
||||
Vendored
+13
-2
@@ -405,12 +405,15 @@ cbjack_process(jack_nframes_t nframes, void * arg)
|
||||
|
||||
for (int j = 0; j < MAX_STREAMS; j++) {
|
||||
cubeb_stream * stm = &ctx->streams[j];
|
||||
float * bufs_out[stm->out_params.channels];
|
||||
float * bufs_in[stm->in_params.channels];
|
||||
|
||||
if (!stm->in_use)
|
||||
continue;
|
||||
|
||||
float * bufs_out[MAX_CHANNELS] = {};
|
||||
float * bufs_in[MAX_CHANNELS] = {};
|
||||
XASSERT(stm->out_params.channels <= MAX_CHANNELS);
|
||||
XASSERT(stm->in_params.channels <= MAX_CHANNELS);
|
||||
|
||||
// handle xruns by skipping audio that should have been played
|
||||
stm->position += t_jack_xruns * ctx->fragment_size * stm->ratio;
|
||||
|
||||
@@ -851,6 +854,14 @@ cbjack_stream_init(cubeb * context, cubeb_stream ** stream,
|
||||
return CUBEB_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
if ((output_stream_params &&
|
||||
(output_stream_params->channels < 1 ||
|
||||
output_stream_params->channels > MAX_CHANNELS)) ||
|
||||
(input_stream_params && (input_stream_params->channels < 1 ||
|
||||
input_stream_params->channels > MAX_CHANNELS))) {
|
||||
return CUBEB_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
|
||||
if ((input_device && input_device != JACK_DEFAULT_IN) ||
|
||||
(output_device && output_device != JACK_DEFAULT_OUT)) {
|
||||
return CUBEB_ERROR_NOT_SUPPORTED;
|
||||
|
||||
Vendored
+173
-24
@@ -14,6 +14,7 @@
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <audioclient.h>
|
||||
#include <audiopolicy.h>
|
||||
#include <avrt.h>
|
||||
#include <cmath>
|
||||
#include <devicetopology.h>
|
||||
@@ -317,6 +318,7 @@ struct cubeb {
|
||||
};
|
||||
|
||||
class wasapi_endpoint_notification_client;
|
||||
class wasapi_session_notification_client;
|
||||
|
||||
/* We have three possible callbacks we can use with a stream:
|
||||
* - input only
|
||||
@@ -415,6 +417,10 @@ struct cubeb_stream {
|
||||
audio device changes and route the audio to the new default audio output
|
||||
device */
|
||||
com_ptr<wasapi_endpoint_notification_client> notification_client;
|
||||
/* Session notification client, to be notified when the audio session is
|
||||
disconnected (e.g. when an audio device is removed from the system). */
|
||||
com_ptr<IAudioSessionControl> session_control;
|
||||
com_ptr<wasapi_session_notification_client> session_notification_client;
|
||||
/* Main andle to the WASAPI capture stream. */
|
||||
com_ptr<IAudioClient> input_client;
|
||||
/* Interface to use the event driven capture interface */
|
||||
@@ -431,6 +437,10 @@ struct cubeb_stream {
|
||||
* practice, we read from the input stream in the output callback, so
|
||||
* this is not used, but it is necessary to start getting input data. */
|
||||
HANDLE input_available_event = 0;
|
||||
/* Signaled by stream_start/stream_stop when the active state changes,
|
||||
so the render thread can promote/demote its MMCSS task accordingly
|
||||
instead of remaining promoted while idle. */
|
||||
HANDLE mmcss_event = 0;
|
||||
/* Each cubeb_stream has its own thread. */
|
||||
HANDLE thread = 0;
|
||||
/* The lock protects all members that are touched by the render thread or
|
||||
@@ -834,6 +844,89 @@ private:
|
||||
DWORD last_device_change;
|
||||
};
|
||||
|
||||
class wasapi_session_notification_client : public IAudioSessionEvents {
|
||||
public:
|
||||
ULONG STDMETHODCALLTYPE AddRef() { return InterlockedIncrement(&ref_count); }
|
||||
|
||||
ULONG STDMETHODCALLTYPE Release()
|
||||
{
|
||||
ULONG ulRef = InterlockedDecrement(&ref_count);
|
||||
if (0 == ulRef) {
|
||||
delete this;
|
||||
}
|
||||
return ulRef;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, VOID ** ppvInterface)
|
||||
{
|
||||
if (__uuidof(IUnknown) == riid) {
|
||||
AddRef();
|
||||
*ppvInterface = (IUnknown *)this;
|
||||
} else if (__uuidof(IAudioSessionEvents) == riid) {
|
||||
AddRef();
|
||||
*ppvInterface = (IAudioSessionEvents *)this;
|
||||
} else {
|
||||
*ppvInterface = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
wasapi_session_notification_client(HANDLE event)
|
||||
: ref_count(1), reconfigure_event(event)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~wasapi_session_notification_client() {}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE
|
||||
OnSessionDisconnected(AudioSessionDisconnectReason reason)
|
||||
{
|
||||
LOG("session: Audio session disconnected, reason: %d", reason);
|
||||
BOOL ok = SetEvent(reconfigure_event);
|
||||
if (!ok) {
|
||||
LOG("session: SetEvent on reconfigure_event failed: %lx", GetLastError());
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE OnDisplayNameChanged(LPCWSTR value,
|
||||
LPCGUID event_context)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE OnIconPathChanged(LPCWSTR value,
|
||||
LPCGUID event_context)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE OnSimpleVolumeChanged(float volume, BOOL mute,
|
||||
LPCGUID event_context)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE OnChannelVolumeChanged(DWORD channel_count,
|
||||
float volumes[],
|
||||
DWORD changed_channel,
|
||||
LPCGUID event_context)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE OnGroupingParamChanged(LPCGUID grouping_param,
|
||||
LPCGUID event_context)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
HRESULT STDMETHODCALLTYPE OnStateChanged(AudioSessionState state)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
LONG ref_count;
|
||||
HANDLE reconfigure_event;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
long
|
||||
@@ -1414,8 +1507,9 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
} com;
|
||||
|
||||
bool is_playing = true;
|
||||
HANDLE wait_array[4] = {stm->shutdown_event, stm->reconfigure_event,
|
||||
stm->refill_event, stm->input_available_event};
|
||||
HANDLE wait_array[5] = {stm->shutdown_event, stm->mmcss_event,
|
||||
stm->reconfigure_event, stm->refill_event,
|
||||
stm->input_available_event};
|
||||
HANDLE mmcss_handle = NULL;
|
||||
HRESULT hr = 0;
|
||||
DWORD mmcss_task_index = 0;
|
||||
@@ -1428,15 +1522,6 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We could consider using "Pro Audio" here for WebAudio and
|
||||
maybe WebRTC. */
|
||||
mmcss_handle = AvSetMmThreadCharacteristicsA("Audio", &mmcss_task_index);
|
||||
if (!mmcss_handle) {
|
||||
/* This is not fatal, but we might glitch under heavy load. */
|
||||
LOG("Unable to use mmcss to bump the render thread priority: %lx",
|
||||
GetLastError());
|
||||
}
|
||||
|
||||
while (is_playing) {
|
||||
DWORD waitResult = WaitForMultipleObjects(ARRAY_LENGTH(wait_array),
|
||||
wait_array, FALSE, INFINITE);
|
||||
@@ -1450,7 +1535,30 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case WAIT_OBJECT_0 + 1: { /* reconfigure */
|
||||
case WAIT_OBJECT_0 + 1: { /* mmcss: active state changed */
|
||||
/* stm->active was set by wasapi_stream_start/_stop before signaling,
|
||||
and SetEvent provides the necessary memory barrier. */
|
||||
if (stm->active && !mmcss_handle) {
|
||||
/* We could consider using "Pro Audio" here for WebAudio and
|
||||
maybe WebRTC. */
|
||||
mmcss_handle =
|
||||
AvSetMmThreadCharacteristicsA("Audio", &mmcss_task_index);
|
||||
if (!mmcss_handle) {
|
||||
/* This is not fatal, but we might glitch under heavy load. */
|
||||
LOG("Unable to use mmcss to bump the render thread priority: %lx",
|
||||
GetLastError());
|
||||
} else {
|
||||
LOG("MMCSS render thread promoted (task index %lu)",
|
||||
mmcss_task_index);
|
||||
}
|
||||
} else if (!stm->active && mmcss_handle) {
|
||||
AvRevertMmThreadCharacteristics(mmcss_handle);
|
||||
mmcss_handle = NULL;
|
||||
LOG("MMCSS render thread demoted");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
case WAIT_OBJECT_0 + 2: { /* reconfigure */
|
||||
auto_lock lock(stm->stream_reset_lock);
|
||||
if (!stm->active) {
|
||||
/* Avoid reconfiguring, stream start will handle it. */
|
||||
@@ -1460,13 +1568,12 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
XASSERT(stm->output_client || stm->input_client);
|
||||
LOG("Reconfiguring the stream");
|
||||
/* Close the stream */
|
||||
bool was_running = false;
|
||||
if (stm->output_client) {
|
||||
was_running = stm->output_client->Stop() == S_OK;
|
||||
stm->output_client->Stop();
|
||||
LOG("Output stopped.");
|
||||
}
|
||||
if (stm->input_client) {
|
||||
was_running = stm->input_client->Stop() == S_OK;
|
||||
stm->input_client->Stop();
|
||||
LOG("Input stopped.");
|
||||
}
|
||||
close_wasapi_stream(stm);
|
||||
@@ -1484,7 +1591,7 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
}
|
||||
LOG("Stream setup successfuly.");
|
||||
XASSERT(stm->output_client || stm->input_client);
|
||||
if (was_running && stm->output_client) {
|
||||
if (stm->output_client) {
|
||||
hr = stm->output_client->Start();
|
||||
if (FAILED(hr)) {
|
||||
LOG("Error starting output after reconfigure, error: %lx", hr);
|
||||
@@ -1493,7 +1600,7 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
}
|
||||
LOG("Output started after reconfigure.");
|
||||
}
|
||||
if (was_running && stm->input_client) {
|
||||
if (stm->input_client) {
|
||||
hr = stm->input_client->Start();
|
||||
if (FAILED(hr)) {
|
||||
LOG("Error starting input after reconfiguring, error: %lx", hr);
|
||||
@@ -1504,12 +1611,12 @@ static unsigned int __stdcall wasapi_stream_render_loop(LPVOID stream)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WAIT_OBJECT_0 + 2: /* refill */
|
||||
case WAIT_OBJECT_0 + 3: /* refill */
|
||||
XASSERT((has_input(stm) && has_output(stm)) ||
|
||||
(!has_input(stm) && has_output(stm)));
|
||||
is_playing = stm->refill_callback(stm);
|
||||
break;
|
||||
case WAIT_OBJECT_0 + 3: { /* input available */
|
||||
case WAIT_OBJECT_0 + 4: { /* input available */
|
||||
bool rv = get_input_buffer(stm);
|
||||
if (!rv) {
|
||||
is_playing = false;
|
||||
@@ -2643,6 +2750,22 @@ setup_wasapi_stream(cubeb_stream * stm)
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
hr = stm->output_client->GetService(__uuidof(IAudioSessionControl),
|
||||
stm->session_control.receive_vpp());
|
||||
if (SUCCEEDED(hr)) {
|
||||
stm->session_notification_client.reset(
|
||||
new wasapi_session_notification_client(stm->reconfigure_event));
|
||||
hr = stm->session_control->RegisterAudioSessionNotification(
|
||||
stm->session_notification_client.get());
|
||||
if (FAILED(hr)) {
|
||||
LOG("Could not register session notification client: %lx", hr);
|
||||
stm->session_notification_client = nullptr;
|
||||
stm->session_control = nullptr;
|
||||
}
|
||||
} else {
|
||||
LOG("Could not get the IAudioSessionControl: %lx", hr);
|
||||
}
|
||||
|
||||
#ifdef CUBEB_WASAPI_USE_IAUDIOSTREAMVOLUME
|
||||
/* Restore the stream volume over a device change. */
|
||||
if (stream_set_volume(stm, stm->volume) != CUBEB_OK) {
|
||||
@@ -2842,6 +2965,12 @@ wasapi_stream_init(cubeb * context, cubeb_stream ** stream,
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
stm->mmcss_event = CreateEvent(NULL, 0, 0, NULL);
|
||||
if (!stm->mmcss_event) {
|
||||
LOG("Can't create the mmcss event, error: %lx", GetLastError());
|
||||
return CUBEB_ERROR;
|
||||
}
|
||||
|
||||
stm->thread_ready_event = CreateEvent(NULL, 0, 0, NULL);
|
||||
if (!stm->thread_ready_event) {
|
||||
LOG("Can't create the thread ready event, error: %lx", GetLastError());
|
||||
@@ -2906,6 +3035,13 @@ close_wasapi_stream(cubeb_stream * stm)
|
||||
|
||||
stm->stream_reset_lock.assert_current_thread_owns();
|
||||
|
||||
if (stm->session_control && stm->session_notification_client) {
|
||||
stm->session_control->UnregisterAudioSessionNotification(
|
||||
stm->session_notification_client.get());
|
||||
stm->session_notification_client = nullptr;
|
||||
stm->session_control = nullptr;
|
||||
}
|
||||
|
||||
#ifdef CUBEB_WASAPI_USE_IAUDIOSTREAMVOLUME
|
||||
stm->audio_stream_volume = nullptr;
|
||||
#endif
|
||||
@@ -2960,6 +3096,7 @@ wasapi_stream_release(cubeb_stream * stm)
|
||||
CloseHandle(stm->reconfigure_event);
|
||||
CloseHandle(stm->refill_event);
|
||||
CloseHandle(stm->input_available_event);
|
||||
CloseHandle(stm->mmcss_event);
|
||||
|
||||
CloseHandle(stm->thread);
|
||||
|
||||
@@ -3056,6 +3193,11 @@ wasapi_stream_start(cubeb_stream * stm)
|
||||
|
||||
stm->active = true;
|
||||
|
||||
if (!SetEvent(stm->mmcss_event)) {
|
||||
LOG("wasapi_stream_start: SetEvent(mmcss_event) failed: %lx",
|
||||
GetLastError());
|
||||
}
|
||||
|
||||
stm->state_callback(stm, stm->user_ptr, CUBEB_STATE_STARTED);
|
||||
|
||||
return CUBEB_OK;
|
||||
@@ -3088,6 +3230,11 @@ wasapi_stream_stop(cubeb_stream * stm)
|
||||
|
||||
stm->active = false;
|
||||
|
||||
if (!SetEvent(stm->mmcss_event)) {
|
||||
LOG("wasapi_stream_stop: SetEvent(mmcss_event) failed: %lx",
|
||||
GetLastError());
|
||||
}
|
||||
|
||||
wasapi_state_callback(stm, stm->user_ptr, CUBEB_STATE_STOPPED);
|
||||
}
|
||||
|
||||
@@ -3563,11 +3710,13 @@ wasapi_register_device_collection_changed(
|
||||
}
|
||||
|
||||
if (collection_changed_callback) {
|
||||
// Make sure it has been unregistered first.
|
||||
XASSERT(((devtype & CUBEB_DEVICE_TYPE_INPUT) &&
|
||||
!context->input_collection_changed_callback) ||
|
||||
((devtype & CUBEB_DEVICE_TYPE_OUTPUT) &&
|
||||
!context->output_collection_changed_callback));
|
||||
if (((devtype & CUBEB_DEVICE_TYPE_INPUT) &&
|
||||
context->input_collection_changed_callback) ||
|
||||
((devtype & CUBEB_DEVICE_TYPE_OUTPUT) &&
|
||||
context->output_collection_changed_callback)) {
|
||||
LOG("register_device_collection_changed: callback already registered");
|
||||
return CUBEB_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
// Stop the notification client. Notifications arrive on
|
||||
// a separate thread. We stop them here to avoid
|
||||
|
||||
+2
@@ -3,5 +3,7 @@ add_library(D3D12MemAlloc
|
||||
src/D3D12MemAlloc.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(D3D12MemAlloc PRIVATE Microsoft::DirectX-Headers)
|
||||
|
||||
target_include_directories(D3D12MemAlloc PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
disable_compiler_warnings_for_target(D3D12MemAlloc)
|
||||
|
||||
+3
-2
@@ -20,6 +20,7 @@
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="..\DefaultProjectRootDir.props" />
|
||||
<Import Project="..\3rdparty.props" />
|
||||
<Import Project="..\..\common\vsprops\DepsDir.props" />
|
||||
<Import Condition="$(Configuration.Contains(Debug))" Project="..\..\common\vsprops\CodeGen_Debug.props" />
|
||||
<Import Condition="$(Configuration.Contains(Devel))" Project="..\..\common\vsprops\CodeGen_Devel.props" />
|
||||
<Import Condition="$(Configuration.Contains(Release))" Project="..\..\common\vsprops\CodeGen_Release.props" />
|
||||
@@ -37,9 +38,9 @@
|
||||
</ItemGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>D3D12MA_USING_DIRECTX_HEADERS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>TurnOffAllWarnings</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)include;$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(DepsIncludeDir);$(ProjectDir)include;$(ProjectDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
+12
-3
@@ -24,7 +24,7 @@
|
||||
|
||||
/** \mainpage D3D12 Memory Allocator
|
||||
|
||||
<b>Version 3.1.0</b> (2026-02-23)
|
||||
<b>Version 3.2.0</b> (2026-06-05)
|
||||
|
||||
Copyright (c) 2019-2026 Advanced Micro Devices, Inc. All rights reserved. \n
|
||||
License: MIT
|
||||
@@ -889,10 +889,17 @@ enum POOL_FLAGS
|
||||
*/
|
||||
POOL_FLAG_MSAA_TEXTURES_ALWAYS_COMMITTED = 0x2,
|
||||
/** Every allocation made in this pool will be created as a committed resource - will have its own memory block.
|
||||
|
||||
|
||||
There is also an equivalent flag for the entire allocator: D3D12MA::ALLOCATOR_FLAG_ALWAYS_COMMITTED.
|
||||
*/
|
||||
POOL_FLAG_ALWAYS_COMMITTED = 0x4,
|
||||
/** Disables tight resource alignment for all resources created from this pool.
|
||||
|
||||
When tight alignment is supported and enabled for the allocator, resources created from custom pools
|
||||
normally use it automatically. Specify this flag to restore pre-tight-alignment behavior for this pool:
|
||||
tight alignment won't be requested and small buffers may again be preferred as committed resources.
|
||||
*/
|
||||
POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT = 0x8,
|
||||
|
||||
// Bit mask to extract only `ALGORITHM` bits from entire set of flags.
|
||||
POOL_FLAG_ALGORITHM_MASK = POOL_FLAG_ALGORITHM_LINEAR
|
||||
@@ -1114,7 +1121,8 @@ enum ALLOCATOR_FLAGS
|
||||
It can also be disabled for a single allocation by using #ALLOCATION_FLAG_STRATEGY_MIN_TIME.
|
||||
|
||||
If the tight resource alignment feature is used by the library (which happens automatically whenever supported,
|
||||
unless you use flag #ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT), then small buffers are not preferred as committed.
|
||||
unless you use flag #ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT or
|
||||
#POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT on a custom pool), then small buffers are not preferred as committed.
|
||||
Long story short, you don't need to specify any of these flags.
|
||||
The library chooses the most optimal method automatically.
|
||||
*/
|
||||
@@ -2892,6 +2900,7 @@ as it is no longer needed.
|
||||
|
||||
You can check if the tight alignment it is available in the current system by calling D3D12MA::Allocator::IsTightAlignmentSupported().
|
||||
You can tell the library to not use it by specifying D3D12MA::ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT.
|
||||
Custom pools can opt out independently by specifying D3D12MA::POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT.
|
||||
Typically, you don't need to do any of those.
|
||||
|
||||
The library automatically aligns all buffers to at least 256 B, even when the system supports smaller alignment.
|
||||
|
||||
+249
-57
@@ -163,6 +163,14 @@ especially to test compatibility with D3D12_RESOURCE_HEAP_TIER_1 on modern GPUs.
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef D3D12MA_OPTIONS4_SUPPORTED
|
||||
#ifdef __ID3D12Device5_INTERFACE_DEFINED__
|
||||
#define D3D12MA_OPTIONS4_SUPPORTED 1
|
||||
#else
|
||||
#define D3D12MA_OPTIONS4_SUPPORTED 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef D3D12MA_DEBUG_LOG
|
||||
#define D3D12MA_DEBUG_LOG(format, ...)
|
||||
/*
|
||||
@@ -703,6 +711,13 @@ static UINT GetBitsPerPixel(DXGI_FORMAT format)
|
||||
case DXGI_FORMAT_R24_UNORM_X8_TYPELESS:
|
||||
case DXGI_FORMAT_X24_TYPELESS_G8_UINT:
|
||||
return 32;
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8A8_TYPELESS:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
|
||||
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
|
||||
return 32;
|
||||
case DXGI_FORMAT_R8G8_TYPELESS:
|
||||
case DXGI_FORMAT_R8G8_UNORM:
|
||||
case DXGI_FORMAT_R8G8_UINT:
|
||||
@@ -717,6 +732,9 @@ static UINT GetBitsPerPixel(DXGI_FORMAT format)
|
||||
case DXGI_FORMAT_R16_SNORM:
|
||||
case DXGI_FORMAT_R16_SINT:
|
||||
return 16;
|
||||
case DXGI_FORMAT_B5G6R5_UNORM:
|
||||
case DXGI_FORMAT_B5G5R5A1_UNORM:
|
||||
return 16;
|
||||
case DXGI_FORMAT_R8_TYPELESS:
|
||||
case DXGI_FORMAT_R8_UNORM:
|
||||
case DXGI_FORMAT_R8_UINT:
|
||||
@@ -767,46 +785,175 @@ static ResourceClass ResourceDescToResourceClass(const D3D12_RESOURCE_DESC_T& re
|
||||
(resDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0;
|
||||
return isRenderTargetOrDepthStencil ? ResourceClass::RT_DS_Texture : ResourceClass::Non_RT_DS_Texture;
|
||||
}
|
||||
|
||||
static bool ResourceDimensionIsTexture(D3D12_RESOURCE_DIMENSION dimension)
|
||||
{
|
||||
return dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D ||
|
||||
dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D ||
|
||||
dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D;
|
||||
}
|
||||
|
||||
static bool ResourceFlagsContainRenderTargetOrDepthStencil(D3D12_RESOURCE_FLAGS flags)
|
||||
{
|
||||
return (flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0;
|
||||
}
|
||||
|
||||
// This algorithm is overly conservative.
|
||||
struct SmallAlignmentTileShape
|
||||
{
|
||||
UINT Width;
|
||||
UINT Height;
|
||||
UINT Depth;
|
||||
};
|
||||
|
||||
static bool GetSmallAlignmentTileShape(
|
||||
D3D12_RESOURCE_DIMENSION dimension,
|
||||
bool isMsaa,
|
||||
UINT bitsPerUnit,
|
||||
SmallAlignmentTileShape& outTileShape)
|
||||
{
|
||||
if (isMsaa)
|
||||
{
|
||||
if (dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D)
|
||||
return false;
|
||||
|
||||
switch (bitsPerUnit)
|
||||
{
|
||||
case 8: outTileShape = { 256, 256, 1 }; return true;
|
||||
case 16: outTileShape = { 256, 128, 1 }; return true;
|
||||
case 32: outTileShape = { 128, 128, 1 }; return true;
|
||||
case 64: outTileShape = { 128, 64, 1 }; return true;
|
||||
case 128: outTileShape = { 64, 64, 1 }; return true;
|
||||
case 256: outTileShape = { 64, 32, 1 }; return true;
|
||||
case 512: outTileShape = { 32, 32, 1 }; return true;
|
||||
case 1024: outTileShape = { 32, 16, 1 }; return true;
|
||||
case 2048: outTileShape = { 16, 16, 1 }; return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (dimension)
|
||||
{
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
switch (bitsPerUnit)
|
||||
{
|
||||
case 8: outTileShape = { 4096, 1, 1 }; return true;
|
||||
case 16: outTileShape = { 2048, 1, 1 }; return true;
|
||||
case 32: outTileShape = { 1024, 1, 1 }; return true;
|
||||
case 64: outTileShape = { 512, 1, 1 }; return true;
|
||||
case 128: outTileShape = { 256, 1, 1 }; return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
switch (bitsPerUnit)
|
||||
{
|
||||
case 8: outTileShape = { 64, 64, 1 }; return true;
|
||||
case 16: outTileShape = { 64, 32, 1 }; return true;
|
||||
case 32: outTileShape = { 32, 32, 1 }; return true;
|
||||
case 64: outTileShape = { 32, 16, 1 }; return true;
|
||||
case 128: outTileShape = { 16, 16, 1 }; return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
||||
// 4 KB counterparts of the documented 64 KB volume-tile shapes.
|
||||
switch (bitsPerUnit)
|
||||
{
|
||||
case 8: outTileShape = { 16, 16, 16 }; return true;
|
||||
case 16: outTileShape = { 16, 16, 8 }; return true;
|
||||
case 32: outTileShape = { 16, 8, 8 }; return true;
|
||||
case 64: outTileShape = { 8, 8, 8 }; return true;
|
||||
case 128: outTileShape = { 8, 8, 4 }; return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This algorithm is overly conservative and applies only to the legacy small-alignment heuristic path.
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
static bool CanUseSmallAlignment(const D3D12_RESOURCE_DESC_T& resourceDesc)
|
||||
{
|
||||
if (resourceDesc.Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE2D)
|
||||
if (resourceDesc.SampleDesc.Count == 0 ||
|
||||
resourceDesc.Layout != D3D12_TEXTURE_LAYOUT_UNKNOWN ||
|
||||
resourceDesc.Width > UINT_MAX)
|
||||
{
|
||||
return false;
|
||||
if ((resourceDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) != 0)
|
||||
}
|
||||
|
||||
const bool isMsaa = resourceDesc.SampleDesc.Count > 1;
|
||||
const bool isRtDs = ResourceFlagsContainRenderTargetOrDepthStencil(resourceDesc.Flags);
|
||||
if (isMsaa && !isRtDs)
|
||||
{
|
||||
return false;
|
||||
if (resourceDesc.SampleDesc.Count > 1)
|
||||
return false;
|
||||
if (resourceDesc.DepthOrArraySize != 1)
|
||||
}
|
||||
if (!isMsaa &&
|
||||
isRtDs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT sizeX = (UINT)resourceDesc.Width;
|
||||
UINT sizeY = resourceDesc.Height;
|
||||
UINT bitsPerPixel = GetBitsPerPixel(resourceDesc.Format);
|
||||
if (bitsPerPixel == 0)
|
||||
UINT sizeY = 1;
|
||||
UINT sizeZ = 1;
|
||||
UINT bitsPerUnit = GetBitsPerPixel(resourceDesc.Format);
|
||||
if (bitsPerUnit == 0)
|
||||
return false;
|
||||
|
||||
if (IsFormatCompressed(resourceDesc.Format))
|
||||
switch (resourceDesc.Dimension)
|
||||
{
|
||||
sizeX = DivideRoundingUp(sizeX, 4u);
|
||||
sizeY = DivideRoundingUp(sizeY, 4u);
|
||||
bitsPerPixel *= 16;
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE1D:
|
||||
if (isMsaa)
|
||||
return false;
|
||||
// For 1D arrays, small-alignment eligibility depends on the mip0 slice size, not array size.
|
||||
if (IsFormatCompressed(resourceDesc.Format))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE2D:
|
||||
// For 2D arrays, small-alignment eligibility depends on mip0 width/height, not array size.
|
||||
sizeY = resourceDesc.Height;
|
||||
if (isMsaa && IsFormatCompressed(resourceDesc.Format))
|
||||
return false;
|
||||
if (IsFormatCompressed(resourceDesc.Format))
|
||||
{
|
||||
sizeX = DivideRoundingUp(sizeX, 4u);
|
||||
sizeY = DivideRoundingUp(sizeY, 4u);
|
||||
bitsPerUnit *= 16;
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D12_RESOURCE_DIMENSION_TEXTURE3D:
|
||||
if (isMsaa)
|
||||
return false;
|
||||
sizeY = resourceDesc.Height;
|
||||
sizeZ = resourceDesc.DepthOrArraySize;
|
||||
if (IsFormatCompressed(resourceDesc.Format))
|
||||
{
|
||||
sizeX = DivideRoundingUp(sizeX, 4u);
|
||||
sizeY = DivideRoundingUp(sizeY, 4u);
|
||||
bitsPerUnit *= 16;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
UINT tileSizeX = 0, tileSizeY = 0;
|
||||
switch (bitsPerPixel)
|
||||
{
|
||||
case 8: tileSizeX = 64; tileSizeY = 64; break;
|
||||
case 16: tileSizeX = 64; tileSizeY = 32; break;
|
||||
case 32: tileSizeX = 32; tileSizeY = 32; break;
|
||||
case 64: tileSizeX = 32; tileSizeY = 16; break;
|
||||
case 128: tileSizeX = 16; tileSizeY = 16; break;
|
||||
default: return false;
|
||||
}
|
||||
bitsPerUnit *= resourceDesc.SampleDesc.Count;
|
||||
|
||||
const UINT tileCount = DivideRoundingUp(sizeX, tileSizeX) * DivideRoundingUp(sizeY, tileSizeY);
|
||||
return tileCount <= 16;
|
||||
SmallAlignmentTileShape tileShape = {};
|
||||
if (!GetSmallAlignmentTileShape(resourceDesc.Dimension, isMsaa, bitsPerUnit, tileShape))
|
||||
return false;
|
||||
|
||||
const UINT64 tileCount =
|
||||
UINT64(DivideRoundingUp(sizeX, tileShape.Width)) *
|
||||
UINT64(DivideRoundingUp(sizeY, tileShape.Height)) *
|
||||
UINT64(DivideRoundingUp(sizeZ, tileShape.Depth));
|
||||
// Non-MSAA compares 64 KB against 4 KB tiles => 16 pages. MSAA compares 4 MB against 64 KB tiles => 64 pages.
|
||||
return tileCount <= (isMsaa ? 64 : 16);
|
||||
}
|
||||
|
||||
static bool ValidateAllocateMemoryParameters(
|
||||
@@ -5988,6 +6135,7 @@ public:
|
||||
BOOL IsCacheCoherentUMA() const { return m_D3D12Architecture.CacheCoherentUMA; }
|
||||
bool SupportsResourceHeapTier2() const { return m_D3D12Options.ResourceHeapTier >= D3D12_RESOURCE_HEAP_TIER_2; }
|
||||
bool IsGPUUploadHeapSupported() const { return m_GPUUploadHeapSupported != FALSE; }
|
||||
bool IsMsaa64KBAlignedTextureSupported() const { return m_MSAA64KBAlignedTextureSupported != FALSE; }
|
||||
bool IsTightAlignmentSupported() const { return m_TightAlignmentSupported != FALSE; }
|
||||
bool IsTightAlignmentEnabled() const { return IsTightAlignmentSupported() && m_UseTightAlignment; }
|
||||
bool UseMutex() const { return m_UseMutex; }
|
||||
@@ -6076,7 +6224,7 @@ private:
|
||||
const bool m_UseMutex;
|
||||
const bool m_AlwaysCommitted;
|
||||
const bool m_MsaaAlwaysCommitted;
|
||||
bool m_PreferSmallBuffersCommitted;
|
||||
const bool m_PreferSmallBuffersCommitted;
|
||||
const bool m_UseTightAlignment;
|
||||
bool m_DefaultPoolsNotZeroed = false;
|
||||
ID3D12Device* m_Device; // AddRef
|
||||
@@ -6105,6 +6253,7 @@ private:
|
||||
DXGI_ADAPTER_DESC m_AdapterDesc;
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS m_D3D12Options;
|
||||
BOOL m_GPUUploadHeapSupported = FALSE;
|
||||
BOOL m_MSAA64KBAlignedTextureSupported = FALSE;
|
||||
BOOL m_TightAlignmentSupported = FALSE;
|
||||
D3D12_FEATURE_DATA_ARCHITECTURE m_D3D12Architecture;
|
||||
AllocationObjectAllocator m_AllocationObjectAllocator;
|
||||
@@ -6121,7 +6270,7 @@ private:
|
||||
*/
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
bool PrefersCommittedAllocation(const D3D12_RESOURCE_DESC_T& resourceDesc,
|
||||
ALLOCATION_FLAGS strategy);
|
||||
ALLOCATION_FLAGS strategy, bool useTightAlignment) const;
|
||||
|
||||
// Allocates and registers new committed resource with implicit heap, as dedicated allocation.
|
||||
// Creates and returns Allocation object and optionally D3D12 resource.
|
||||
@@ -6141,6 +6290,7 @@ private:
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
HRESULT CalcAllocationParams(const ALLOCATION_DESC& allocDesc, UINT64 allocSize,
|
||||
const D3D12_RESOURCE_DESC_T* resDesc, // Optional
|
||||
bool useTightAlignment,
|
||||
BlockVector*& outBlockVector, CommittedAllocationParameters& outCommittedAllocationParams, bool& outPreferCommitted);
|
||||
|
||||
// Returns UINT32_MAX if index cannot be calculcated.
|
||||
@@ -6174,7 +6324,10 @@ private:
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
HRESULT GetResourceAllocationInfo(D3D12_RESOURCE_DESC_T& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const;
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo,
|
||||
bool useTightAlignment) const;
|
||||
|
||||
bool IsTightAlignmentEnabled(const ALLOCATION_DESC& allocDesc) const;
|
||||
|
||||
bool NewAllocationWithinBudget(D3D12_HEAP_TYPE heapType, UINT64 size);
|
||||
|
||||
@@ -6277,6 +6430,17 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc)
|
||||
}
|
||||
#endif // #if D3D12MA_OPTIONS16_SUPPORTED
|
||||
|
||||
#if D3D12MA_OPTIONS4_SUPPORTED
|
||||
{
|
||||
D3D12_FEATURE_DATA_D3D12_OPTIONS4 options4 = {};
|
||||
hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS4, &options4, sizeof(options4));
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
m_MSAA64KBAlignedTextureSupported = options4.MSAA64KBAlignedTextureSupported;
|
||||
}
|
||||
}
|
||||
#endif // #if D3D12MA_OPTIONS4_SUPPORTED
|
||||
|
||||
#if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED
|
||||
{
|
||||
D3D12_FEATURE_DATA_TIGHT_ALIGNMENT tightAlignment = {};
|
||||
@@ -6285,13 +6449,6 @@ HRESULT AllocatorPimpl::Init(const ALLOCATOR_DESC& desc)
|
||||
{
|
||||
m_TightAlignmentSupported = tightAlignment.SupportTier >= D3D12_TIGHT_ALIGNMENT_TIER_1;
|
||||
|
||||
// If tight alignment is supported (checked by the code above) and wasn't disabled by the developer
|
||||
// (with ALLOCATOR_FLAG_DONT_USE_TIGHT_ALIGNMENT), disable the preference for creating small buffers as committed,
|
||||
// as if ALLOCATOR_FLAG_DONT_PREFER_SMALL_BUFFERS_COMMITTED was specified.
|
||||
if (IsTightAlignmentEnabled())
|
||||
{
|
||||
m_PreferSmallBuffersCommitted = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // #if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED
|
||||
@@ -6490,6 +6647,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
}
|
||||
|
||||
HRESULT hr = E_NOINTERFACE;
|
||||
const bool useTightAlignment = IsTightAlignmentEnabled(*pAllocDesc);
|
||||
CREATE_RESOURCE_PARAMS finalCreateParams = createParams;
|
||||
D3D12_RESOURCE_DESC finalResourceDesc;
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
@@ -6500,7 +6658,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
{
|
||||
finalResourceDesc = *createParams.GetResourceDesc();
|
||||
finalCreateParams.AccessResourceDesc() = &finalResourceDesc;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo, useTightAlignment);
|
||||
}
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
@@ -6509,7 +6667,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
{
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo, useTightAlignment);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6521,7 +6679,7 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1,
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo);
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo, useTightAlignment);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6547,14 +6705,14 @@ HRESULT AllocatorPimpl::CreateResource(
|
||||
if (createParams.Variant >= CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
{
|
||||
hr = CalcAllocationParams<D3D12_RESOURCE_DESC1>(*pAllocDesc, resAllocInfo.SizeInBytes,
|
||||
createParams.GetResourceDesc1(),
|
||||
createParams.GetResourceDesc1(), useTightAlignment,
|
||||
blockVector, committedAllocationParams, preferCommitted);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
hr = CalcAllocationParams<D3D12_RESOURCE_DESC>(*pAllocDesc, resAllocInfo.SizeInBytes,
|
||||
createParams.GetResourceDesc(),
|
||||
createParams.GetResourceDesc(), useTightAlignment,
|
||||
blockVector, committedAllocationParams, preferCommitted);
|
||||
}
|
||||
if (FAILED(hr))
|
||||
@@ -6601,6 +6759,7 @@ HRESULT AllocatorPimpl::AllocateMemory(
|
||||
bool preferCommitted = false;
|
||||
HRESULT hr = CalcAllocationParams<D3D12_RESOURCE_DESC>(*pAllocDesc, pAllocInfo->SizeInBytes,
|
||||
NULL, // pResDesc
|
||||
false, // useTightAlignment - irrelevant for AllocateMemory
|
||||
blockVector, committedAllocationParams, preferCommitted);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
@@ -6649,7 +6808,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource(
|
||||
{
|
||||
finalResourceDesc = *createParams.GetResourceDesc();
|
||||
finalCreateParams.AccessResourceDesc() = &finalResourceDesc;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc, 0, NULL, resAllocInfo, IsTightAlignmentEnabled());
|
||||
}
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
else if (createParams.Variant == CREATE_RESOURCE_PARAMS::VARIANT_WITH_STATE_AND_DESC1)
|
||||
@@ -6658,7 +6817,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource(
|
||||
{
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo);
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1, 0, NULL, resAllocInfo, IsTightAlignmentEnabled());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6670,7 +6829,7 @@ HRESULT AllocatorPimpl::CreateAliasingResource(
|
||||
finalResourceDesc1 = *createParams.GetResourceDesc1();
|
||||
finalCreateParams.AccessResourceDesc1() = &finalResourceDesc1;
|
||||
hr = GetResourceAllocationInfo(finalResourceDesc1,
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo);
|
||||
createParams.GetNumCastableFormats(), createParams.GetCastableFormats(), resAllocInfo, IsTightAlignmentEnabled());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -7305,13 +7464,14 @@ void AllocatorPimpl::FreeStatsString(WCHAR* pStatsString)
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
bool AllocatorPimpl::PrefersCommittedAllocation(const D3D12_RESOURCE_DESC_T& resourceDesc,
|
||||
ALLOCATION_FLAGS strategy)
|
||||
ALLOCATION_FLAGS strategy, bool useTightAlignment) const
|
||||
{
|
||||
// Prefer creating small buffers <= 32 KB as committed, because drivers pack them better,
|
||||
// while placed buffers require 64 KB alignment.
|
||||
if(resourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
|
||||
resourceDesc.Width <= D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT / 2 &&
|
||||
strategy != ALLOCATION_FLAG_STRATEGY_MIN_TIME && // Creating as committed would be slower.
|
||||
!useTightAlignment &&
|
||||
m_PreferSmallBuffersCommitted)
|
||||
{
|
||||
return true;
|
||||
@@ -7526,7 +7686,7 @@ HRESULT AllocatorPimpl::AllocateHeap(
|
||||
|
||||
template<typename D3D12_RESOURCE_DESC_T>
|
||||
HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, UINT64 allocSize,
|
||||
const D3D12_RESOURCE_DESC_T* resDesc,
|
||||
const D3D12_RESOURCE_DESC_T* resDesc, bool useTightAlignment,
|
||||
BlockVector*& outBlockVector, CommittedAllocationParameters& outCommittedAllocationParams, bool& outPreferCommitted)
|
||||
{
|
||||
outBlockVector = NULL;
|
||||
@@ -7599,7 +7759,7 @@ HRESULT AllocatorPimpl::CalcAllocationParams(const ALLOCATION_DESC& allocDesc, U
|
||||
{
|
||||
if (resDesc->SampleDesc.Count > 1 && msaaAlwaysCommitted)
|
||||
outBlockVector = NULL;
|
||||
if (!outPreferCommitted && PrefersCommittedAllocation(*resDesc, allocDesc.Flags & ALLOCATION_FLAG_STRATEGY_MASK))
|
||||
if (!outPreferCommitted && PrefersCommittedAllocation(*resDesc, allocDesc.Flags & ALLOCATION_FLAG_STRATEGY_MASK, useTightAlignment))
|
||||
outPreferCommitted = true;
|
||||
}
|
||||
|
||||
@@ -7810,12 +7970,13 @@ template<typename D3D12_RESOURCE_DESC_T>
|
||||
HRESULT AllocatorPimpl::GetResourceAllocationInfo(
|
||||
D3D12_RESOURCE_DESC_T& inOutResourceDesc,
|
||||
UINT32 NumCastableFormats, const DXGI_FORMAT* pCastableFormats,
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo) const
|
||||
D3D12_RESOURCE_ALLOCATION_INFO& outAllocInfo,
|
||||
bool useTightAlignment) const
|
||||
{
|
||||
#ifdef __ID3D12Device1_INTERFACE_DEFINED__
|
||||
|
||||
#if D3D12MA_TIGHT_ALIGNMENT_SUPPORTED
|
||||
if (IsTightAlignmentEnabled())
|
||||
if (useTightAlignment)
|
||||
{
|
||||
// Don't allow USE_TIGHT_ALIGNMENT together with ALLOW_CROSS_ADAPTER as there is a D3D Debug Layer error:
|
||||
// D3D12 ERROR: ID3D12Device::GetResourceAllocationInfo: D3D12_RESOURCE_DESC::Flag D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT will be ignored since D3D12_RESOURCE_FLAG_ALLOW_CROSS_ADAPTER is set. [ STATE_CREATION ERROR #599: CREATERESOURCE_INVALIDMISCFLAGS]
|
||||
@@ -7839,7 +8000,7 @@ HRESULT AllocatorPimpl::GetResourceAllocationInfo(
|
||||
*/
|
||||
if (inOutResourceDesc.Alignment == 0 &&
|
||||
inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
|
||||
!IsTightAlignmentEnabled())
|
||||
!useTightAlignment)
|
||||
{
|
||||
outAllocInfo = {
|
||||
AlignUp<UINT64>(inOutResourceDesc.Width, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT), // SizeInBytes
|
||||
@@ -7852,16 +8013,33 @@ HRESULT AllocatorPimpl::GetResourceAllocationInfo(
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
#if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT
|
||||
if (inOutResourceDesc.Alignment == 0 &&
|
||||
(inOutResourceDesc.Flags & D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY) == 0 &&
|
||||
(inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE1D ||
|
||||
inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D ||
|
||||
inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D) &&
|
||||
(inOutResourceDesc.Flags & (D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL)) == 0
|
||||
bool trySmallAlignment = false;
|
||||
|
||||
if (inOutResourceDesc.Alignment == 0
|
||||
&& (inOutResourceDesc.Flags & D3D12_RESOURCE_FLAG_USE_TIGHT_ALIGNMENT_COPY) == 0
|
||||
&& inOutResourceDesc.Layout == D3D12_TEXTURE_LAYOUT_UNKNOWN
|
||||
&& ResourceDimensionIsTexture(inOutResourceDesc.Dimension))
|
||||
{
|
||||
// MSAA texture.
|
||||
if(inOutResourceDesc.SampleDesc.Count > 1)
|
||||
{
|
||||
trySmallAlignment = IsMsaa64KBAlignedTextureSupported()
|
||||
&& ResourceFlagsContainRenderTargetOrDepthStencil(inOutResourceDesc.Flags)
|
||||
&& inOutResourceDesc.Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE2D;
|
||||
}
|
||||
// Non-MSAA texture.
|
||||
else
|
||||
{
|
||||
trySmallAlignment = !ResourceFlagsContainRenderTargetOrDepthStencil(inOutResourceDesc.Flags);
|
||||
}
|
||||
}
|
||||
|
||||
#if D3D12MA_USE_SMALL_RESOURCE_PLACEMENT_ALIGNMENT == 1
|
||||
&& CanUseSmallAlignment(inOutResourceDesc)
|
||||
if(trySmallAlignment)
|
||||
trySmallAlignment = CanUseSmallAlignment(inOutResourceDesc);
|
||||
#endif
|
||||
)
|
||||
|
||||
if (trySmallAlignment)
|
||||
{
|
||||
/*
|
||||
The algorithm here is based on Microsoft sample: "Small Resources Sample"
|
||||
@@ -7886,6 +8064,20 @@ HRESULT AllocatorPimpl::GetResourceAllocationInfo(
|
||||
inOutResourceDesc, NumCastableFormats, pCastableFormats, outAllocInfo);
|
||||
}
|
||||
|
||||
bool AllocatorPimpl::IsTightAlignmentEnabled(const ALLOCATION_DESC& allocDesc) const
|
||||
{
|
||||
if (!IsTightAlignmentEnabled())
|
||||
return false;
|
||||
|
||||
if (allocDesc.CustomPool != NULL &&
|
||||
(allocDesc.CustomPool->m_Pimpl->GetDesc().Flags & POOL_FLAG_DONT_USE_TIGHT_ALIGNMENT) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AllocatorPimpl::NewAllocationWithinBudget(D3D12_HEAP_TYPE heapType, UINT64 size)
|
||||
{
|
||||
Budget budget = {};
|
||||
|
||||
Vendored
+40
-10
@@ -3,6 +3,9 @@
|
||||
|
||||
[](https://github.com/fastfloat/fast_float/actions/workflows/ubuntu22.yml)
|
||||
|
||||
*Note: This library is for C++ users. C programmers should consider [ffc.h](https://github.com/kolemannix/ffc.h). It is a high-performance port of fast_float to C.*
|
||||
|
||||
|
||||
The fast_float library provides fast header-only implementations for the C++
|
||||
from_chars functions for `float` and `double` types as well as integer types.
|
||||
These functions convert ASCII strings representing decimal values (e.g.,
|
||||
@@ -10,6 +13,7 @@ These functions convert ASCII strings representing decimal values (e.g.,
|
||||
even). In our experience, these `fast_float` functions many times faster than
|
||||
comparable number-parsing functions from existing C++ standard libraries.
|
||||
|
||||
|
||||
Specifically, `fast_float` provides the following two functions to parse
|
||||
floating-point numbers with a C++17-like syntax (the library itself only
|
||||
requires C++11):
|
||||
@@ -18,9 +22,9 @@ requires C++11):
|
||||
from_chars_result from_chars(char const *first, char const *last, float &value, ...);
|
||||
from_chars_result from_chars(char const *first, char const *last, double &value, ...);
|
||||
```
|
||||
If they are available on your system, we also support fixed-width floating-point types such as `std::float64_t`, `std::float32_t`, `std::float16_t`, and `std::bfloat16_t`.
|
||||
|
||||
You can also parse integer types:
|
||||
|
||||
You can also parse integer types such as `char`, `short`, `long`, `long long`, `unsigned char`, `unsigned short`, `unsigned long`, `unsigned long long`, `bool` (0/1), `int8_t`, `int16_t`, `int32_t`, `int64_t`, `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t`.
|
||||
```C++
|
||||
from_chars_result from_chars(char const *first, char const *last, int &value, ...);
|
||||
from_chars_result from_chars(char const *first, char const *last, unsigned &value, ...);
|
||||
@@ -69,7 +73,7 @@ int main() {
|
||||
}
|
||||
```
|
||||
|
||||
Though the C++17 standard has you do a comparison with `std::errc()` to check whether the conversion worked, you can avoid it by casting the result to a `bool` like so:
|
||||
Prior to C++26, checking for a successful `std::from_chars` conversion requires comparing the `from_chars_result::ec` member to `std::errc()`. As an extension `fast_float::from_chars` supports the improved C++26 API that allows checking the result by converting it to `bool`, like so:
|
||||
|
||||
```cpp
|
||||
#include "fast_float/fast_float.h"
|
||||
@@ -83,7 +87,7 @@ int main() {
|
||||
std::cout << "parsed the number " << result << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
std::cerr << "failed to parse " << result << std::endl;
|
||||
std::cerr << "failed to parse " << input << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
```
|
||||
@@ -141,9 +145,12 @@ Furthermore, we have the following restrictions:
|
||||
fixed-width floating-point types such as `std::float64_t`, `std::float32_t`,
|
||||
`std::float16_t`, and `std::bfloat16_t`.
|
||||
* We only support the decimal format: we do not support hexadecimal strings.
|
||||
* For values that are either very large or very small (e.g., `1e9999`), we
|
||||
represent it using the infinity or negative infinity value and the returned
|
||||
* For values that are very large positives or negatives (e.g., `1e9999`), we
|
||||
represent them using a positive or negative infinity and the returned
|
||||
`ec` is set to `std::errc::result_out_of_range`.
|
||||
* For values that are very close to zero (e.g., `1e-9999`), we represent them
|
||||
using a positive or negative zero and the returned `ec` is set to
|
||||
`std::errc::result_out_of_range`.
|
||||
|
||||
We support Visual Studio, macOS, Linux, freeBSD. We support big and little
|
||||
endian. We support 32-bit and 64-bit systems.
|
||||
@@ -401,6 +408,23 @@ except `fast_float::integer_times_pow10()` does not report out-of-range errors,
|
||||
underflows to zero or overflows to infinity when the resulting value is
|
||||
out of range.
|
||||
|
||||
You can use template overloads to get the result converted to different
|
||||
supported floating-point types: `float`, `double`, etc.
|
||||
For example, to get result as `float` use
|
||||
`fast_float::integer_times_pow10<float>()` specialization:
|
||||
```C++
|
||||
const uint64_t W = 12345678;
|
||||
const int Q = 23;
|
||||
const float result = fast_float::integer_times_pow10<float>(W, Q);
|
||||
std::cout.precision(9);
|
||||
std::cout << "float: " << W << " * 10^" << Q << " = " << result << " ("
|
||||
<< (result == 12345678e23f ? "==" : "!=") << "expected)\n";
|
||||
```
|
||||
outputs
|
||||
```
|
||||
float: 12345678 * 10^23 = 1.23456782e+30 (==expected)
|
||||
```
|
||||
|
||||
Overloads of `fast_float::integer_times_pow10()` are provided for
|
||||
signed and unsigned integer types: `int64_t`, `uint64_t`, etc.
|
||||
|
||||
@@ -443,7 +467,7 @@ framework](https://github.com/microsoft/LightGBM).
|
||||
Packages
|
||||
------
|
||||
|
||||
[](https://repology.org/project/fastfloat/versions)
|
||||
[](https://repology.org/project/fast-float/versions)
|
||||
|
||||
|
||||
## References
|
||||
@@ -468,6 +492,7 @@ Packages
|
||||
[Jackson](https://github.com/FasterXML/jackson-core).
|
||||
* [There is a C# port of the fast_float
|
||||
library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`.
|
||||
* [There is a plain C port of the fast_float library](https://github.com/kolemannix/ffc.h) called ffc.h
|
||||
|
||||
## How fast is it?
|
||||
|
||||
@@ -516,7 +541,7 @@ sufficiently recent version of CMake (3.11 or better at least):
|
||||
FetchContent_Declare(
|
||||
fast_float
|
||||
GIT_REPOSITORY https://github.com/fastfloat/fast_float.git
|
||||
GIT_TAG tags/v8.1.0
|
||||
GIT_TAG tags/v8.2.5
|
||||
GIT_SHALLOW TRUE)
|
||||
|
||||
FetchContent_MakeAvailable(fast_float)
|
||||
@@ -532,7 +557,7 @@ You may also use [CPM](https://github.com/cpm-cmake/CPM.cmake), like so:
|
||||
CPMAddPackage(
|
||||
NAME fast_float
|
||||
GITHUB_REPOSITORY "fastfloat/fast_float"
|
||||
GIT_TAG v8.1.0)
|
||||
GIT_TAG v8.2.5)
|
||||
```
|
||||
|
||||
## Using as single header
|
||||
@@ -544,7 +569,7 @@ if desired as described in the command line help.
|
||||
|
||||
You may directly download automatically generated single-header files:
|
||||
|
||||
<https://github.com/fastfloat/fast_float/releases/download/v8.1.0/fast_float.h>
|
||||
<https://github.com/fastfloat/fast_float/releases/download/v8.2.5/fast_float.h>
|
||||
|
||||
## Benchmarking
|
||||
|
||||
@@ -598,6 +623,11 @@ long digits.
|
||||
The library includes code adapted from Google Wuffs (written by Nigel Tao) which
|
||||
was originally published under the Apache 2.0 license.
|
||||
|
||||
## Stars
|
||||
|
||||
|
||||
[](https://www.star-history.com/#fastfloat/fast_float&Date)
|
||||
|
||||
## License
|
||||
|
||||
<sup>
|
||||
|
||||
+179
-1
@@ -32,7 +32,7 @@ template <typename UC> fastfloat_really_inline constexpr bool has_simd_opt() {
|
||||
// able to optimize it well.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline constexpr bool is_integer(UC c) noexcept {
|
||||
return !(c > UC('9') || c < UC('0'));
|
||||
return (unsigned)(c - UC('0')) <= 9u;
|
||||
}
|
||||
|
||||
fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
|
||||
@@ -42,6 +42,11 @@ fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
|
||||
(val & 0x000000000000FF00) << 40 | (val & 0x00000000000000FF) << 56;
|
||||
}
|
||||
|
||||
fastfloat_really_inline constexpr uint32_t byteswap_32(uint32_t val) {
|
||||
return (val >> 24) | ((val >> 8) & 0x0000FF00u) | ((val << 8) & 0x00FF0000u) |
|
||||
(val << 24);
|
||||
}
|
||||
|
||||
// Read 8 UC into a u64. Truncates UC if not char.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
|
||||
@@ -63,6 +68,25 @@ read8_to_u64(UC const *chars) {
|
||||
return val;
|
||||
}
|
||||
|
||||
// Read 4 UC into a u32. Truncates UC if not char.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint32_t
|
||||
read4_to_u32(UC const *chars) {
|
||||
if (cpp20_and_in_constexpr() || !std::is_same<UC, char>::value) {
|
||||
uint32_t val = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
val |= uint32_t(uint8_t(*chars)) << (i * 8);
|
||||
++chars;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
uint32_t val;
|
||||
::memcpy(&val, chars, sizeof(uint32_t));
|
||||
#if FASTFLOAT_IS_BIG_ENDIAN == 1
|
||||
val = byteswap_32(val);
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
#ifdef FASTFLOAT_SSE2
|
||||
|
||||
fastfloat_really_inline uint64_t simd_read8_to_u64(__m128i const data) {
|
||||
@@ -144,6 +168,18 @@ is_made_of_eight_digits_fast(uint64_t val) noexcept {
|
||||
0x8080808080808080));
|
||||
}
|
||||
|
||||
fastfloat_really_inline constexpr bool
|
||||
is_made_of_four_digits_fast(uint32_t val) noexcept {
|
||||
return !((((val + 0x46464646) | (val - 0x30303030)) & 0x80808080));
|
||||
}
|
||||
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t
|
||||
parse_four_digits_unrolled(uint32_t val) noexcept {
|
||||
val -= 0x30303030;
|
||||
val = (val * 10) + (val >> 8);
|
||||
return (((val & 0x00FF00FF) * 0x00640001) >> 16) & 0xFFFF;
|
||||
}
|
||||
|
||||
#ifdef FASTFLOAT_HAS_SIMD
|
||||
|
||||
// Call this if chars might not be 8 digits.
|
||||
@@ -509,6 +545,148 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
||||
|
||||
UC const *const start_digits = p;
|
||||
|
||||
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value)) {
|
||||
if (base == 10) {
|
||||
const size_t len = (size_t)(pend - p);
|
||||
if (len == 0) {
|
||||
if (has_leading_zeros) {
|
||||
value = 0;
|
||||
answer.ec = std::errc();
|
||||
answer.ptr = p;
|
||||
} else {
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
uint32_t digits;
|
||||
|
||||
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST
|
||||
if (std::is_constant_evaluated()) {
|
||||
uint8_t str[4]{};
|
||||
for (size_t j = 0; j < 4 && j < len; ++j) {
|
||||
str[j] = static_cast<uint8_t>(p[j]);
|
||||
}
|
||||
digits = std::bit_cast<uint32_t>(str);
|
||||
#if FASTFLOAT_IS_BIG_ENDIAN
|
||||
digits = byteswap_32(digits);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
if (false) {
|
||||
}
|
||||
#endif
|
||||
else if (len >= 4) {
|
||||
::memcpy(&digits, p, 4);
|
||||
#if FASTFLOAT_IS_BIG_ENDIAN
|
||||
digits = byteswap_32(digits);
|
||||
#endif
|
||||
} else {
|
||||
uint32_t b0 = static_cast<uint8_t>(p[0]);
|
||||
uint32_t b1 = (len > 1) ? static_cast<uint8_t>(p[1]) : 0xFFu;
|
||||
uint32_t b2 = (len > 2) ? static_cast<uint8_t>(p[2]) : 0xFFu;
|
||||
uint32_t b3 = 0xFFu;
|
||||
digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
|
||||
}
|
||||
|
||||
uint32_t magic =
|
||||
((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u;
|
||||
uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32
|
||||
uint32_t nd = (tz == 32) ? 4 : (tz >> 3);
|
||||
nd = (uint32_t)(nd < len ? nd : len);
|
||||
if (nd == 0) {
|
||||
if (has_leading_zeros) {
|
||||
value = 0;
|
||||
answer.ec = std::errc();
|
||||
answer.ptr = p;
|
||||
return answer;
|
||||
}
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
return answer;
|
||||
}
|
||||
if (nd > 3) {
|
||||
const UC *q = p + nd;
|
||||
size_t rem = len - nd;
|
||||
while (rem) {
|
||||
if (*q < UC('0') || *q > UC('9'))
|
||||
break;
|
||||
++q;
|
||||
--rem;
|
||||
}
|
||||
answer.ec = std::errc::result_out_of_range;
|
||||
answer.ptr = q;
|
||||
return answer;
|
||||
}
|
||||
|
||||
digits ^= 0x30303030u;
|
||||
digits <<= ((4 - nd) * 8);
|
||||
|
||||
uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) |
|
||||
((digits << 8) & 0xff0000);
|
||||
if (check > 0x00020505) {
|
||||
answer.ec = std::errc::result_out_of_range;
|
||||
answer.ptr = p + nd;
|
||||
return answer;
|
||||
}
|
||||
value = (uint8_t)((0x640a01 * digits) >> 24);
|
||||
answer.ec = std::errc();
|
||||
answer.ptr = p + nd;
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
|
||||
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint16_t>::value)) {
|
||||
if (base == 10) {
|
||||
const size_t len = size_t(pend - p);
|
||||
if (len == 0) {
|
||||
if (has_leading_zeros) {
|
||||
value = 0;
|
||||
answer.ec = std::errc();
|
||||
answer.ptr = p;
|
||||
} else {
|
||||
answer.ec = std::errc::invalid_argument;
|
||||
answer.ptr = first;
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
if (len >= 4) {
|
||||
uint32_t digits = read4_to_u32(p);
|
||||
if (is_made_of_four_digits_fast(digits)) {
|
||||
uint32_t v = parse_four_digits_unrolled(digits);
|
||||
if (len >= 5 && is_integer(p[4])) {
|
||||
v = v * 10 + uint32_t(p[4] - '0');
|
||||
if (len >= 6 && is_integer(p[5])) {
|
||||
answer.ec = std::errc::result_out_of_range;
|
||||
const UC *q = p + 5;
|
||||
while (q != pend && is_integer(*q)) {
|
||||
q++;
|
||||
}
|
||||
answer.ptr = q;
|
||||
return answer;
|
||||
}
|
||||
if (v > 65535) {
|
||||
answer.ec = std::errc::result_out_of_range;
|
||||
answer.ptr = p + 5;
|
||||
return answer;
|
||||
}
|
||||
value = uint16_t(v);
|
||||
answer.ec = std::errc();
|
||||
answer.ptr = p + 5;
|
||||
return answer;
|
||||
}
|
||||
// 4 digits
|
||||
value = uint16_t(v);
|
||||
answer.ec = std::errc();
|
||||
answer.ptr = p + 4;
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t i = 0;
|
||||
if (base == 10) {
|
||||
loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef FASTFLOAT_DIGIT_COMPARISON_H
|
||||
#define FASTFLOAT_DIGIT_COMPARISON_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
@@ -38,11 +37,8 @@ constexpr static uint64_t powers_of_ten_uint64[] = {1UL,
|
||||
// this algorithm is not even close to optimized, but it has no practical
|
||||
// effect on performance: in order to have a faster algorithm, we'd need
|
||||
// to slow down performance for faster algorithms, and this is still fast.
|
||||
template <typename UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t
|
||||
scientific_exponent(parsed_number_string_t<UC> &num) noexcept {
|
||||
uint64_t mantissa = num.mantissa;
|
||||
int32_t exponent = int32_t(num.exponent);
|
||||
scientific_exponent(uint64_t mantissa, int32_t exponent) noexcept {
|
||||
while (mantissa >= 10000) {
|
||||
mantissa /= 10000;
|
||||
exponent += 4;
|
||||
@@ -112,7 +108,7 @@ fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void round(adjusted_mantissa &am,
|
||||
if (-am.power2 >= mantissa_shift) {
|
||||
// have a denormal float
|
||||
int32_t shift = -am.power2 + 1;
|
||||
cb(am, std::min<int32_t>(shift, 64));
|
||||
cb(am, (shift < 64 ? shift : 64));
|
||||
// check for round-up: if rounding-nearest carried us to the hidden bit.
|
||||
am.power2 = (am.mantissa <
|
||||
(uint64_t(1) << binary_format<T>::mantissa_explicit_bits()))
|
||||
@@ -398,7 +394,7 @@ inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp(
|
||||
FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp)));
|
||||
}
|
||||
|
||||
// compare digits, and use it to director rounding
|
||||
// compare digits, and use it to direct rounding
|
||||
int ord = real_digits.compare(theor_digits);
|
||||
adjusted_mantissa answer = am;
|
||||
round<T>(answer, [ord](adjusted_mantissa &a, int32_t shift) {
|
||||
@@ -419,7 +415,7 @@ inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp(
|
||||
return answer;
|
||||
}
|
||||
|
||||
// parse the significant digits as a big integer to unambiguously round the
|
||||
// parse the significant digits as a big integer to unambiguously round
|
||||
// the significant digits. here, we are trying to determine how to round
|
||||
// an extended float representation close to `b+h`, halfway between `b`
|
||||
// (the float rounded-down) and `b+u`, the next positive float. this
|
||||
@@ -438,7 +434,8 @@ digit_comp(parsed_number_string_t<UC> &num, adjusted_mantissa am) noexcept {
|
||||
// remove the invalid exponent bias
|
||||
am.power2 -= invalid_am_bias;
|
||||
|
||||
int32_t sci_exp = scientific_exponent(num);
|
||||
int32_t sci_exp =
|
||||
scientific_exponent(num.mantissa, static_cast<int32_t>(num.exponent));
|
||||
size_t max_digits = binary_format<T>::max_digits();
|
||||
size_t digits = 0;
|
||||
bigint bigmant;
|
||||
|
||||
@@ -63,6 +63,20 @@ integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept;
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
|
||||
|
||||
/**
|
||||
* This function is a template overload of `integer_times_pow10()`
|
||||
* that returns a floating-point value of type `T` that is one of
|
||||
* supported floating-point types (e.g. `double`, `float`).
|
||||
*/
|
||||
template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept;
|
||||
template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept;
|
||||
|
||||
/**
|
||||
* from_chars for integer types.
|
||||
*/
|
||||
|
||||
+192
-11
@@ -2,6 +2,7 @@
|
||||
#define FASTFLOAT_FLOAT_COMMON_H
|
||||
|
||||
#include <cfloat>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
@@ -16,8 +17,8 @@
|
||||
#include "constexpr_feature_detect.h"
|
||||
|
||||
#define FASTFLOAT_VERSION_MAJOR 8
|
||||
#define FASTFLOAT_VERSION_MINOR 1
|
||||
#define FASTFLOAT_VERSION_PATCH 0
|
||||
#define FASTFLOAT_VERSION_MINOR 2
|
||||
#define FASTFLOAT_VERSION_PATCH 5
|
||||
|
||||
#define FASTFLOAT_STRINGIZE_IMPL(x) #x
|
||||
#define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x)
|
||||
@@ -267,18 +268,147 @@ struct is_supported_char_type
|
||||
> {
|
||||
};
|
||||
|
||||
template <typename UC>
|
||||
inline FASTFLOAT_CONSTEXPR14 bool
|
||||
fastfloat_strncasecmp3(UC const *actual_mixedcase,
|
||||
UC const *expected_lowercase) {
|
||||
uint64_t mask{0};
|
||||
FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { mask = 0x2020202020202020; }
|
||||
else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) {
|
||||
mask = 0x0020002000200020;
|
||||
}
|
||||
else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) {
|
||||
mask = 0x0000002000000020;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint64_t val1{0}, val2{0};
|
||||
if (cpp20_and_in_constexpr()) {
|
||||
for (size_t i = 0; i < 3; i++) {
|
||||
if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1 || sizeof(UC) == 2) {
|
||||
::memcpy(&val1, actual_mixedcase, 3 * sizeof(UC));
|
||||
::memcpy(&val2, expected_lowercase, 3 * sizeof(UC));
|
||||
val1 |= mask;
|
||||
val2 |= mask;
|
||||
return val1 == val2;
|
||||
}
|
||||
else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) {
|
||||
::memcpy(&val1, actual_mixedcase, 2 * sizeof(UC));
|
||||
::memcpy(&val2, expected_lowercase, 2 * sizeof(UC));
|
||||
val1 |= mask;
|
||||
if (val1 != val2) {
|
||||
return false;
|
||||
}
|
||||
return (actual_mixedcase[2] | 32) == (expected_lowercase[2]);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename UC>
|
||||
inline FASTFLOAT_CONSTEXPR14 bool
|
||||
fastfloat_strncasecmp5(UC const *actual_mixedcase,
|
||||
UC const *expected_lowercase) {
|
||||
uint64_t mask{0};
|
||||
uint64_t val1{0}, val2{0};
|
||||
if (cpp20_and_in_constexpr()) {
|
||||
for (size_t i = 0; i < 5; i++) {
|
||||
if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) {
|
||||
mask = 0x2020202020202020;
|
||||
::memcpy(&val1, actual_mixedcase, 5 * sizeof(UC));
|
||||
::memcpy(&val2, expected_lowercase, 5 * sizeof(UC));
|
||||
val1 |= mask;
|
||||
val2 |= mask;
|
||||
return val1 == val2;
|
||||
}
|
||||
else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) {
|
||||
mask = 0x0020002000200020;
|
||||
::memcpy(&val1, actual_mixedcase, 4 * sizeof(UC));
|
||||
::memcpy(&val2, expected_lowercase, 4 * sizeof(UC));
|
||||
val1 |= mask;
|
||||
if (val1 != val2) {
|
||||
return false;
|
||||
}
|
||||
return (actual_mixedcase[4] | 32) == (expected_lowercase[4]);
|
||||
}
|
||||
else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) {
|
||||
mask = 0x0000002000000020;
|
||||
::memcpy(&val1, actual_mixedcase, 2 * sizeof(UC));
|
||||
::memcpy(&val2, expected_lowercase, 2 * sizeof(UC));
|
||||
val1 |= mask;
|
||||
if (val1 != val2) {
|
||||
return false;
|
||||
}
|
||||
::memcpy(&val1, actual_mixedcase + 2, 2 * sizeof(UC));
|
||||
::memcpy(&val2, expected_lowercase + 2, 2 * sizeof(UC));
|
||||
val1 |= mask;
|
||||
if (val1 != val2) {
|
||||
return false;
|
||||
}
|
||||
return (actual_mixedcase[4] | 32) == (expected_lowercase[4]);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compares two ASCII strings in a case insensitive manner.
|
||||
template <typename UC>
|
||||
inline FASTFLOAT_CONSTEXPR14 bool
|
||||
fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase,
|
||||
size_t length) {
|
||||
for (size_t i = 0; i < length; ++i) {
|
||||
UC const actual = actual_mixedcase[i];
|
||||
if ((actual < 256 ? actual | 32 : actual) != expected_lowercase[i]) {
|
||||
return false;
|
||||
}
|
||||
uint64_t mask{0};
|
||||
FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 1) { mask = 0x2020202020202020; }
|
||||
else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 2) {
|
||||
mask = 0x0020002000200020;
|
||||
}
|
||||
else FASTFLOAT_IF_CONSTEXPR17(sizeof(UC) == 4) {
|
||||
mask = 0x0000002000000020;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cpp20_and_in_constexpr()) {
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
if ((actual_mixedcase[i] | 32) != expected_lowercase[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
uint64_t val1{0}, val2{0};
|
||||
size_t sz{8 / (sizeof(UC))};
|
||||
for (size_t i = 0; i < length; i += sz) {
|
||||
val1 = val2 = 0;
|
||||
sz = sz < (length - i) ? sz : length - i;
|
||||
::memcpy(&val1, actual_mixedcase + i, sz * sizeof(UC));
|
||||
::memcpy(&val2, expected_lowercase + i, sz * sizeof(UC));
|
||||
val1 |= mask;
|
||||
val2 |= mask;
|
||||
if (val1 != val2) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef FLT_EVAL_METHOD
|
||||
@@ -362,6 +492,52 @@ leading_zeroes(uint64_t input_num) {
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Helper C++14 constexpr generic implementation of countr_zero for 32-bit */
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int
|
||||
countr_zero_generic_32(uint32_t input_num) {
|
||||
if (input_num == 0) {
|
||||
return 32;
|
||||
}
|
||||
int last_bit = 0;
|
||||
if (!(input_num & 0x0000FFFF)) {
|
||||
input_num >>= 16;
|
||||
last_bit |= 16;
|
||||
}
|
||||
if (!(input_num & 0x00FF)) {
|
||||
input_num >>= 8;
|
||||
last_bit |= 8;
|
||||
}
|
||||
if (!(input_num & 0x0F)) {
|
||||
input_num >>= 4;
|
||||
last_bit |= 4;
|
||||
}
|
||||
if (!(input_num & 0x3)) {
|
||||
input_num >>= 2;
|
||||
last_bit |= 2;
|
||||
}
|
||||
if (!(input_num & 0x1)) {
|
||||
last_bit |= 1;
|
||||
}
|
||||
return last_bit;
|
||||
}
|
||||
|
||||
/* count trailing zeroes for 32-bit integers */
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 int
|
||||
countr_zero_32(uint32_t input_num) {
|
||||
if (cpp20_and_in_constexpr()) {
|
||||
return countr_zero_generic_32(input_num);
|
||||
}
|
||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||
unsigned long trailing_zero = 0;
|
||||
if (_BitScanForward(&trailing_zero, input_num)) {
|
||||
return (int)trailing_zero;
|
||||
}
|
||||
return 32;
|
||||
#else
|
||||
return input_num == 0 ? 32 : __builtin_ctz(input_num);
|
||||
#endif
|
||||
}
|
||||
|
||||
// slow emulation routine for 32-bit
|
||||
fastfloat_really_inline constexpr uint64_t emulu(uint32_t x, uint32_t y) {
|
||||
return x * (uint64_t)y;
|
||||
@@ -406,8 +582,8 @@ full_multiplication(uint64_t a, uint64_t b) {
|
||||
// But MinGW on ARM64 doesn't have native support for 64-bit multiplications
|
||||
answer.high = __umulh(a, b);
|
||||
answer.low = a * b;
|
||||
#elif defined(FASTFLOAT_32BIT) || \
|
||||
(defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64))
|
||||
#elif defined(FASTFLOAT_32BIT) || (defined(_WIN64) && !defined(__clang__) && \
|
||||
!defined(_M_ARM64) && !defined(__GNUC__))
|
||||
answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64
|
||||
#elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__)
|
||||
__uint128_t r = ((__uint128_t)a) * b;
|
||||
@@ -1166,6 +1342,9 @@ static_assert(std::is_same<equiv_uint_t<std::float64_t>, uint64_t>::value,
|
||||
static_assert(
|
||||
std::numeric_limits<std::float64_t>::is_iec559,
|
||||
"std::float64_t must fulfill the requirements of IEC 559 (IEEE 754)");
|
||||
|
||||
template <>
|
||||
struct binary_format<std::float64_t> : public binary_format<double> {};
|
||||
#endif // __STDCPP_FLOAT64_T__
|
||||
|
||||
#ifdef __STDCPP_FLOAT32_T__
|
||||
@@ -1174,6 +1353,9 @@ static_assert(std::is_same<equiv_uint_t<std::float32_t>, uint32_t>::value,
|
||||
static_assert(
|
||||
std::numeric_limits<std::float32_t>::is_iec559,
|
||||
"std::float32_t must fulfill the requirements of IEC 559 (IEEE 754)");
|
||||
|
||||
template <>
|
||||
struct binary_format<std::float32_t> : public binary_format<float> {};
|
||||
#endif // __STDCPP_FLOAT32_T__
|
||||
|
||||
#ifdef __STDCPP_FLOAT16_T__
|
||||
@@ -1245,7 +1427,6 @@ constexpr chars_format adjust_for_feature_macros(chars_format fmt) {
|
||||
;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
} // namespace fast_float
|
||||
|
||||
#endif
|
||||
|
||||
+56
-21
@@ -35,7 +35,7 @@ from_chars_result_t<UC>
|
||||
++first;
|
||||
}
|
||||
if (last - first >= 3) {
|
||||
if (fastfloat_strncasecmp(first, str_const_nan<UC>(), 3)) {
|
||||
if (fastfloat_strncasecmp3(first, str_const_nan<UC>())) {
|
||||
answer.ptr = (first += 3);
|
||||
value = minusSign ? -std::numeric_limits<T>::quiet_NaN()
|
||||
: std::numeric_limits<T>::quiet_NaN();
|
||||
@@ -54,9 +54,9 @@ from_chars_result_t<UC>
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
if (fastfloat_strncasecmp(first, str_const_inf<UC>(), 3)) {
|
||||
if (fastfloat_strncasecmp3(first, str_const_inf<UC>())) {
|
||||
if ((last - first >= 8) &&
|
||||
fastfloat_strncasecmp(first + 3, str_const_inf<UC>() + 3, 5)) {
|
||||
fastfloat_strncasecmp5(first + 3, str_const_inf<UC>() + 3)) {
|
||||
answer.ptr = first + 8;
|
||||
} else {
|
||||
answer.ptr = first + 3;
|
||||
@@ -155,7 +155,7 @@ template <> struct from_chars_caller<std::float32_t> {
|
||||
// if std::float32_t is defined, and we are in C++23 mode; macro set for
|
||||
// float32; set value to float due to equivalence between float and
|
||||
// float32_t
|
||||
float val;
|
||||
float val = 0.0f;
|
||||
auto ret = from_chars_advanced(first, last, val, options);
|
||||
value = val;
|
||||
return ret;
|
||||
@@ -172,7 +172,7 @@ template <> struct from_chars_caller<std::float64_t> {
|
||||
// if std::float64_t is defined, and we are in C++23 mode; macro set for
|
||||
// float64; set value as double due to equivalence between double and
|
||||
// float64_t
|
||||
double val;
|
||||
double val = 0.0;
|
||||
auto ret = from_chars_advanced(first, last, val, options);
|
||||
value = val;
|
||||
return ret;
|
||||
@@ -251,7 +251,7 @@ clinger_fast_path_impl(uint64_t mantissa, int64_t exponent, bool is_negative,
|
||||
* parsing options or other parsing custom function implemented by user.
|
||||
*/
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept {
|
||||
static_assert(is_supported_float_type<T>::value,
|
||||
"only some floating-point types are supported");
|
||||
@@ -290,7 +290,7 @@ from_chars_advanced(parsed_number_string_t<UC> &pns, T &value) noexcept {
|
||||
}
|
||||
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_float_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
|
||||
@@ -344,44 +344,79 @@ from_chars(UC const *first, UC const *last, T &value, int base) noexcept {
|
||||
return from_chars_advanced(first, last, value, options);
|
||||
}
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
|
||||
double value;
|
||||
template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
|
||||
T value;
|
||||
if (clinger_fast_path_impl(mantissa, decimal_exponent, false, value))
|
||||
return value;
|
||||
|
||||
adjusted_mantissa am =
|
||||
compute_float<binary_format<double>>(decimal_exponent, mantissa);
|
||||
compute_float<binary_format<T>>(decimal_exponent, mantissa);
|
||||
to_float(false, am, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
|
||||
template <typename T>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value, T>::type
|
||||
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
|
||||
const bool is_negative = mantissa < 0;
|
||||
const uint64_t m = static_cast<uint64_t>(is_negative ? -mantissa : mantissa);
|
||||
|
||||
double value;
|
||||
T value;
|
||||
if (clinger_fast_path_impl(m, decimal_exponent, is_negative, value))
|
||||
return value;
|
||||
|
||||
adjusted_mantissa am =
|
||||
compute_float<binary_format<double>>(decimal_exponent, m);
|
||||
adjusted_mantissa am = compute_float<binary_format<T>>(decimal_exponent, m);
|
||||
to_float(is_negative, am, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(uint64_t mantissa, int decimal_exponent) noexcept {
|
||||
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
||||
}
|
||||
|
||||
FASTFLOAT_CONSTEXPR20 inline double
|
||||
integer_times_pow10(int64_t mantissa, int decimal_exponent) noexcept {
|
||||
return integer_times_pow10<double>(mantissa, decimal_exponent);
|
||||
}
|
||||
|
||||
// the following overloads are here to avoid surprising ambiguity for int,
|
||||
// unsigned, etc.
|
||||
template <typename T, typename Int>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value &&
|
||||
std::is_integral<Int>::value &&
|
||||
!std::is_signed<Int>::value,
|
||||
T>::type
|
||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||
return integer_times_pow10<T>(static_cast<uint64_t>(mantissa),
|
||||
decimal_exponent);
|
||||
}
|
||||
|
||||
template <typename T, typename Int>
|
||||
FASTFLOAT_CONSTEXPR20
|
||||
typename std::enable_if<is_supported_float_type<T>::value &&
|
||||
std::is_integral<Int>::value &&
|
||||
std::is_signed<Int>::value,
|
||||
T>::type
|
||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||
return integer_times_pow10<T>(static_cast<int64_t>(mantissa),
|
||||
decimal_exponent);
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
|
||||
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
||||
std::is_integral<Int>::value && !std::is_signed<Int>::value, double>::type
|
||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||
return integer_times_pow10(static_cast<uint64_t>(mantissa), decimal_exponent);
|
||||
}
|
||||
|
||||
template <typename Int>
|
||||
FASTFLOAT_CONSTEXPR20 inline typename std::enable_if<
|
||||
FASTFLOAT_CONSTEXPR20 typename std::enable_if<
|
||||
std::is_integral<Int>::value && std::is_signed<Int>::value, double>::type
|
||||
integer_times_pow10(Int mantissa, int decimal_exponent) noexcept {
|
||||
return integer_times_pow10(static_cast<int64_t>(mantissa), decimal_exponent);
|
||||
@@ -421,7 +456,7 @@ template <size_t TypeIx> struct from_chars_advanced_caller {
|
||||
|
||||
template <> struct from_chars_advanced_caller<1> {
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
call(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_float_advanced(first, last, value, options);
|
||||
@@ -430,7 +465,7 @@ template <> struct from_chars_advanced_caller<1> {
|
||||
|
||||
template <> struct from_chars_advanced_caller<2> {
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 static from_chars_result_t<UC>
|
||||
call(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_int_advanced(first, last, value, options);
|
||||
@@ -438,7 +473,7 @@ template <> struct from_chars_advanced_caller<2> {
|
||||
};
|
||||
|
||||
template <typename T, typename UC>
|
||||
FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t<UC>
|
||||
from_chars_advanced(UC const *first, UC const *last, T &value,
|
||||
parse_options_t<UC> options) noexcept {
|
||||
return from_chars_advanced_caller<
|
||||
|
||||
Vendored
+191
@@ -39,6 +39,197 @@ HOW TO UPDATE?
|
||||
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
|
||||
- Please report any issue!
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.8 (Released 2026-05-12)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.8
|
||||
|
||||
Breaking Changes:
|
||||
|
||||
- DrawList: swapped the last two arguments of `AddRect()`, `AddPolyline()`, `PathStroke()`.
|
||||
- Before: `void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f);`
|
||||
- After: `void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0);`
|
||||
- Before: `void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);`
|
||||
- After: `void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);`
|
||||
- Before: `void ImDrawList::PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f);`
|
||||
- After: `void ImDrawList::PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);`
|
||||
Added inline redirection functions when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is off.
|
||||
Marked the old functions are =delete when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is on, to allow for better type-checking.
|
||||
Effectively the typical call site is changing from:
|
||||
- Before: `window->DrawList->AddRect(p_min, p_max, color, rounding, ImDrawFlags_None, border_size);`
|
||||
- After: `window->DrawList->AddRect(p_min, p_max, color, rounding, border_size);`
|
||||
Notes:
|
||||
- Users of C++ and other languages with type-checking will be notified at compile-time of any mistakes.
|
||||
- Users of high-level bindings or languages with no type-checking will be notified at runtime via an assert for invalid flags value.
|
||||
If you are a binding maintainer consider doing something to facilitate transition or error detection.
|
||||
- This is perhaps the worst breaking change in our history :( but it makes ImDrawList function signatures consistent.
|
||||
As we are aiming to add flags and features to variety of ImDrawList functions, that consistency becomes more important.
|
||||
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
|
||||
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
|
||||
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
|
||||
- DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
|
||||
which is part of our new standard draw callbacks. (#9378)
|
||||
Redirecting the earlier value into the later one when set, so both old and new code should work.
|
||||
- Backends:
|
||||
- Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (#914)
|
||||
This change allows us to facilitate changing samplers, in line with other backends. [@yaz0r, @ocornut]
|
||||
- When creating your own descriptor pool (instead of letting backend creates its own):
|
||||
- Before: need at least `IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER`.
|
||||
- After: need at least `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`.
|
||||
+ `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLER`.
|
||||
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
|
||||
- Before: `ImGui_ImplVulkan_AddTexture(VkSampler, VkImageView, VkImageLayout)`
|
||||
- After: `ImGui_ImplVulkan_AddTexture(VkImageView, VkImageLayout)`
|
||||
- Kept inline redirection function that ignores the sampler (will obsolete).
|
||||
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from `ImGui_ImplXXXX_RenderState`.
|
||||
Prefer to use backend-agnostic DrawCallback_SetSamplerLinear which works everywhere! (#9378)
|
||||
If there is a legit need/request for them or any render state we can always add them back.
|
||||
|
||||
Other Changes:
|
||||
|
||||
- DrawList:
|
||||
- Added room in `ImGuiPlatformIO` for standard backend-agnostic draw callbacks. Those callbacks
|
||||
are setup/provided by the backend and available in most of our standard backends.
|
||||
They allow backend-agnostic code from e.g. switching to a Nearest/Point sampler without
|
||||
messing with custom Renderer-specific callbacks.
|
||||
platform_io.DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
|
||||
platform_io.DrawCallback_SetSamplerLinear; // Request to set current texture sampling to Linear
|
||||
platform_io.DrawCallback_SetSamplerNearest; // Request to set current texture sampling to Nearest/Point
|
||||
Note that some backends might not support all callbacks.
|
||||
(#9378, #9371, #3590, #8926, #2973, #7485, #7468, #6969, #5118, #7616, #9173, #8322, #7230,
|
||||
#5999, #6452, #5156, #7342, #7592, #7511)
|
||||
- Made `AddCallback()` user data default to Null for convenience.
|
||||
- Added `AddLineH()`, `AddLineV()` helpers to draw horizontal and vertical lines. [@memononen]
|
||||
- InputText:
|
||||
- InputTextMultiline: fixed an issue processing deactivation logic when an active
|
||||
multi-line edit is clipped due to being out of view.
|
||||
- Fixed a crash when toggling ReadOnly while active. (#9354)
|
||||
- `CharFilter` callback event sets CursorPos/SelectionStart/SelectionEnd. (#816)
|
||||
- Tables:
|
||||
- Fixed issues reporting ideal size to parent window/container: (#9352, #7651)
|
||||
- When both scrollbars are visible but only one of ScrollX/ScrollY was explicitly requested.
|
||||
- When vertical scrollbar was not at the top, the computation was often incorrect.
|
||||
- Windows:
|
||||
- Fixed a single-axis auto-resizing feedback loop issue with nested containers
|
||||
and varying scrollbar visibility. (#9352)
|
||||
- Detect and report error when calling End() instead of EndPopup() on a popup. (#9351)
|
||||
- Child windows with only `ImGuiChildFlags_AutoResizeY` flag keep using the proportional
|
||||
default `ItemWidth`. (#9355)
|
||||
- Using mouse wheel to scroll takes and keeps ownership of the corresponding keys
|
||||
(e.g. `ImGuiKey_MouseWheelY`) while a wheeling window is locked. (#2604, #3795)
|
||||
- InputInt, InputFloat, InputScalar:
|
||||
- Reinstated `ImGuiInputTextFlags_EnterReturnsTrue` support which was removed in 1.91.4.
|
||||
(#8665, #9299, #8065, #3946, #6284, #9117)
|
||||
- Fixed the fact that it didn't return true when validating same value.
|
||||
- Fixed losing value when tabbing out or losing focus.
|
||||
- Made it that pressing +/- step buttons also return true, which is in line
|
||||
with 1.91.4 behavior.
|
||||
- In a majority of cases you should use `IsItemDeactivatedAfterEdit()` instead,
|
||||
but it still has a few edge cases flaws (to be addressed soon).
|
||||
- Allow passing a format string that does not display the scalar value.
|
||||
Parsing input with default format for the type. (#9385) [@FireFox2000000]
|
||||
- Multi-Select:
|
||||
- Fixed an issue using Multi-Select within a Table causing column width measurement to
|
||||
be invalid when trailing column contents is not submitted in the last row. (#9341, #8250)
|
||||
- Fixed an issue using Multi-Select within a Table with the right-most column visible,
|
||||
which could lead to an extra vertical offset in the Header row. (#8250)
|
||||
- Multi-Select + Box-Select:
|
||||
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect1d` mode while scrolling.
|
||||
Notably, using mouse wheel while holding a box-selection could lead items close to windows
|
||||
edges from not being correctly unselected. (#7994, #8250, #7821, #7850, #7970)
|
||||
- Improved dirty/unclip rectangle logic for `ImGuiMultiSelectFlags_BoxSelect2d`.
|
||||
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect2d` mode, where
|
||||
items out of view wouldn't be properly selected while scrolling while mouse cursor
|
||||
is hovering outside of selection scope. (#7994, #1861, #6518)
|
||||
- Fixed an issue where items out of horizontal view would sometimes lead
|
||||
to incorrect merging of sequential selection requests while also scrolling fast
|
||||
enough to overlap multiple rows during a frame. (#7994, #1861, #6518)
|
||||
- Fixed an issue using `ImGuiMultiSelectFlags_BoxSelect2d` mode in a Table
|
||||
while relying on the `TableNextColumn()` return value to perform coarse clipping. (#7994)
|
||||
- Disabled merging consecutive selection requests as we have no reliable
|
||||
way of detecting if user has submitted all consecutive items without clipping gaps,
|
||||
and `ImGuiSelectionUserData` is technically opaque storage. (#7994, #1861)
|
||||
(we will probably bring this back as a minor optimization if we have a way to for
|
||||
user to tell us `ImGuiSelectionUserData` are indices)
|
||||
- Fixes for using across nested child windows. (#8364)
|
||||
- Box-Select + Clipper: fixed an issue selecting items while scrolling while a clipper
|
||||
active. (#7994, #8250, #7821, #7850, #7970)
|
||||
- Box-Select + Tables: fixed an issue using box-selection in a tables with
|
||||
items straying out of columns boundaries. (#7994, #2221)
|
||||
- Box-Select + Tables: fixed an issue when calling `BeginMultiSelect()` in a table
|
||||
before layout has been locked (first row or headers row submitted). (#8250)
|
||||
- Menus:
|
||||
- BeginMenu()/MenuItem(): fixed accidental triggering of child menu items when
|
||||
opening a menu inside a small host window forcing the child menu window to be
|
||||
repositioned under the mouse cursor. (#8233, #9394)
|
||||
Done by reworking `BeginMenu()`/`MenuItem()`: they previously avoiding taking
|
||||
ActiveID + key/click ownership (in order to allow releasing button on another item).
|
||||
Now they take them and release them once the mouse is moved outside item boundaries.
|
||||
- Inputs:
|
||||
- SetItemKeyOwner(): return true if ownership has been requested, which typically
|
||||
needs to to checked for gating further tests. This is important as the function
|
||||
may fail. (#456, #2637, #2620, #2891, #3370, #3724, #4828, #5108, #5242, #5641)
|
||||
- SetItemKeyOwner(): does not set ownership is key is already taken. Effectively
|
||||
this makes using `SetItemKeyOwner(ImGuiKey_MouseWheelY)` over an item work as
|
||||
expected while not having item react if a scroll wheel is actively in progress.
|
||||
May be subject to further redesign, e.g. conditional flags. Feedback welcome!
|
||||
- Style:
|
||||
- Checkbox: added `ImGuiCol_CheckboxSelectedBg` to change or accentuate the
|
||||
background color of checked/mixed checkboxes. (#9392)
|
||||
- Added `ImGuiStyleVar_DragDropTargetRounding`. (#9056)
|
||||
- Fixed vertical scrollbar top coordinates when using thick borders on windows
|
||||
with no title bar and no menu bar. (#9366)
|
||||
- Fonts:
|
||||
- imgui_freetype: add FreeType headers & compiled version in 'About Dear ImGui' details.
|
||||
- Assert when using MergeMode with an explicit size over a target font with an implicit
|
||||
size, as scale factor are likely erroneous. (#9361)
|
||||
- Clipper:
|
||||
- Improved error reporting when misusing the clipper inside a table (prioritize
|
||||
reporting the common clipper error over a table sanity check assert). (#9350)
|
||||
- Tweaked assert triggering when first item height measurement fails, and made it
|
||||
a better recoverable error. (#9350)
|
||||
- Misc:
|
||||
- Minor optimization: reduce redundant label scanning in common widgets.
|
||||
- Added missing Test Engine hooks for `PlotLines()`, `PlotHistogram()`, `VSliderXXX()`
|
||||
and `TableHeader()` functions.
|
||||
- Demo:
|
||||
- Added simple demo for a scrollable/zoomable image viewer with a grid.
|
||||
Available in `Examples->Image Viewer` and `Widgets->Images`.
|
||||
- Backends:
|
||||
- Added support for new standardized draw callbacks in most backends: (#9378)
|
||||
- Allegro5: Reset n/a n/a
|
||||
- DX9: Reset SetSamplerLinear SetSamplerNearest
|
||||
- DX10: Reset SetSamplerLinear SetSamplerNearest
|
||||
- DX11: Reset SetSamplerLinear SetSamplerNearest
|
||||
- DX12: Reset SetSamplerLinear SetSamplerNearest
|
||||
- Metal: Reset SetSamplerLinear SetSamplerNearest
|
||||
- OpenGL2: Reset SetSamplerLinear SetSamplerNearest
|
||||
- OpenGL3+: Reset SetSamplerLinear SetSamplerNearest
|
||||
- SDLGPU3: Reset SetSamplerLinear SetSamplerNearest
|
||||
- SDLRenderer2: Reset n/a n/a
|
||||
- SDLRenderer3: Reset SetSamplerLinear SetSamplerNearest
|
||||
- Vulkan: Reset SetSamplerLinear SetSamplerNearest
|
||||
- WebGPU: Reset SetSamplerLinear SetSamplerNearest
|
||||
(Vulkan backend by @yaz0r, Metal by @ssh4net, others by @ocornut)
|
||||
- GLFW: added a Win32-specific implementation of `ImGui_ImplGlfw_GetContentScaleXXXX`
|
||||
functions for legacy GLFW 3.2. (#9003)
|
||||
- Metal: avoid redundant vertex buffer bind in `SetupRenderState()`, which leads
|
||||
to validation issue. (#9343) [@Hunam6]
|
||||
- Metal: use a dedicated `bufferCacheLock` to avoid crashing when `bufferCache` is
|
||||
replaced by a new object while being used for `@synchronize()`. (#9367) [@andygrundman]
|
||||
- SDL2: made `ImGui_ImplSDL2_GetContentScaleForWindow()`/`ImGui_ImplSDL2_GetContentScaleForDisplay()`
|
||||
helpers return a minimum of 1.0f, as some Linux setup seems to report <1.0f value
|
||||
and this breaks scaling border size. (#9369)
|
||||
- WebGPU: rework choice/detection of using WGSL/SPIR-V shader on WGVK. (#9316, #9246, #9257, #9387)
|
||||
- Examples:
|
||||
- Update VS toolset in all .vcxproj from VS2015 (v140) to VS2017 (v141). The later is the
|
||||
first that supports vcpkg. Onward we will likely stop testing building the library with VS2015.
|
||||
- GLFW+Vulkan, SDL2+Vulkan, SDL3+Vulkan, Win32+Vulkan: reworked to create a descriptor pool with:
|
||||
- `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE`.
|
||||
- `IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE` descriptors of type `VK_DESCRIPTOR_TYPE_SAMPLER`.
|
||||
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
VERSION 1.92.7 (Released 2026-04-02)
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
Vendored
+47
-30
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (headers)
|
||||
|
||||
// Help:
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
// Library Version
|
||||
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
|
||||
#define IMGUI_VERSION "1.92.7"
|
||||
#define IMGUI_VERSION_NUM 19270
|
||||
#define IMGUI_VERSION "1.92.8"
|
||||
#define IMGUI_VERSION_NUM 19280
|
||||
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
|
||||
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
|
||||
|
||||
@@ -1092,10 +1092,11 @@ namespace ImGui
|
||||
// Inputs Utilities: Key/Input Ownership [BETA]
|
||||
// - One common use case would be to allow your items to disable standard inputs behaviors such
|
||||
// as Tab or Alt key handling, Mouse Wheel scrolling, etc.
|
||||
// e.g. Button(...); SetItemKeyOwner(ImGuiKey_MouseWheelY); to make hovering/activating a button disable wheel for scrolling.
|
||||
// e.g. `Button(...); if (SetItemKeyOwner(ImGuiKey_MouseWheelY)) { ... }` to make hovering/activating a button disable wheel for scrolling.
|
||||
// - Reminder ImGuiKey enum include access to mouse buttons and gamepad, so key ownership can apply to them.
|
||||
// - The return value of SetItemKeyOwner() says if ownership has been requested for the item, which is a shortcut to calling yet non-public TestKeyOwner() function.
|
||||
// - Many related features are still in imgui_internal.h. For instance, most IsKeyXXX()/IsMouseXXX() functions have an owner-id-aware version.
|
||||
IMGUI_API void SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
|
||||
IMGUI_API bool SetItemKeyOwner(ImGuiKey key); // Set key owner to last item ID if it is hovered or active. Return true when ownership has been set. Roughly equivalent to 'if (TestKeyOwner(key, GetItemID()) && (IsItemHovered() || IsItemActive())) { SetKeyOwner(key, GetItemID());'.
|
||||
|
||||
// Inputs Utilities: Mouse
|
||||
// - To refer to a mouse button, you may use named enums in your code e.g. ImGuiMouseButton_Left, ImGuiMouseButton_Right.
|
||||
@@ -1401,7 +1402,7 @@ enum ImGuiTabBarFlags_
|
||||
ImGuiTabBarFlags_DrawSelectedOverline = 1 << 6, // Draw selected overline markers over selected tab
|
||||
|
||||
// Fitting/Resize policy
|
||||
ImGuiTabBarFlags_FittingPolicyMixed = 1 << 7, // Shrink down tabs when they don't fit, until width is style.TabMinWidthShrink, then enable scrolling buttons.
|
||||
ImGuiTabBarFlags_FittingPolicyMixed = 1 << 7, // Shrink down tabs when they don't fit, until width is style.TabMinWidthShrink, then enable scrolling. Setting TabMinWidthShrink to FLT_MAX makes this behave like ImGuiTabBarFlags_FittingPolicyScroll.
|
||||
ImGuiTabBarFlags_FittingPolicyShrink = 1 << 8, // Shrink down tabs when they don't fit
|
||||
ImGuiTabBarFlags_FittingPolicyScroll = 1 << 9, // Enable scrolling buttons when tabs don't fit
|
||||
ImGuiTabBarFlags_FittingPolicyMask_ = ImGuiTabBarFlags_FittingPolicyMixed | ImGuiTabBarFlags_FittingPolicyShrink | ImGuiTabBarFlags_FittingPolicyScroll,
|
||||
@@ -1755,6 +1756,7 @@ enum ImGuiCol_
|
||||
ImGuiCol_ScrollbarGrabHovered,
|
||||
ImGuiCol_ScrollbarGrabActive,
|
||||
ImGuiCol_CheckMark, // Checkbox tick and RadioButton circle
|
||||
ImGuiCol_CheckboxSelectedBg, // Checkbox background when Selected, otherwise use FrameBg
|
||||
ImGuiCol_SliderGrab,
|
||||
ImGuiCol_SliderGrabActive,
|
||||
ImGuiCol_Button,
|
||||
@@ -1852,6 +1854,7 @@ enum ImGuiStyleVar_
|
||||
ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign
|
||||
ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize
|
||||
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
|
||||
ImGuiStyleVar_DragDropTargetRounding, // float DragDropTargetRounding
|
||||
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
|
||||
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
|
||||
ImGuiStyleVar_SeparatorSize, // float SeparatorSize
|
||||
@@ -2319,7 +2322,7 @@ struct ImGuiStyle
|
||||
float TabBorderSize; // Thickness of border around tabs.
|
||||
float TabMinWidthBase; // Minimum tab width, to make tabs larger than their contents. TabBar buttons are not affected.
|
||||
float TabMinWidthShrink; // Minimum tab width after shrinking, when using ImGuiTabBarFlags_FittingPolicyMixed policy.
|
||||
float TabCloseButtonMinWidthSelected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width.
|
||||
float TabCloseButtonMinWidthSelected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never shrink, will behave like ImGuiTabBarFlags_FittingPolicyScroll.
|
||||
float TabCloseButtonMinWidthUnselected; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never show close button when unselected.
|
||||
float TabBarBorderSize; // Thickness of tab-bar separator, which takes on the tab active color to denote focus.
|
||||
float TabBarOverlineSize; // Thickness of tab-bar overline, which highlights the selected tab-bar.
|
||||
@@ -2328,14 +2331,14 @@ struct ImGuiStyle
|
||||
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
|
||||
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
|
||||
float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line.
|
||||
float DragDropTargetRounding; // Radius of the drag and drop target frame.
|
||||
float DragDropTargetRounding; // Radius of the drag and drop target frame. When <0.0f: use FrameRounding.
|
||||
float DragDropTargetBorderSize; // Thickness of the drag and drop target border.
|
||||
float DragDropTargetPadding; // Size to expand the drag and drop target from actual target item size.
|
||||
float ColorMarkerSize; // Size of R/G/B/A color markers for ColorEdit4() and for Drags/Sliders when using ImGuiSliderFlags_ColorMarkers.
|
||||
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
|
||||
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
|
||||
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
|
||||
float SeparatorSize; // Thickness of border in Separator()
|
||||
float SeparatorSize; // Thickness of border in Separator(). Must be >= 1.0f.
|
||||
float SeparatorTextBorderSize; // Thickness of border in SeparatorText()
|
||||
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
|
||||
ImVec2 SeparatorTextPadding; // Horizontal offset of text from each edge of the separator + spacing on other axis. Generally small values. .y is recommended to be == FramePadding.y.
|
||||
@@ -2365,7 +2368,7 @@ struct ImGuiStyle
|
||||
|
||||
// Functions
|
||||
IMGUI_API ImGuiStyle();
|
||||
IMGUI_API void ScaleAllSizes(float scale_factor); // Scale all spacing/padding/thickness values. Do not scale fonts.
|
||||
IMGUI_API void ScaleAllSizes(float scale_factor); // Scale all spacing/padding/thickness values. Do not scale fonts. See comments in definition. Consider not calling this if your initial scale factor if <1.0.
|
||||
|
||||
// Obsolete names
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
@@ -2642,7 +2645,7 @@ struct ImGuiInputTextCallbackData
|
||||
ImGuiInputTextFlags EventFlag; // One ImGuiInputTextFlags_Callback* // Read-only
|
||||
ImGuiInputTextFlags Flags; // What user passed to InputText() // Read-only
|
||||
void* UserData; // What user passed to InputText() // Read-only
|
||||
ImGuiID ID; // Widget ID // Read-only
|
||||
ImGuiID ID; // Widget ID // Read-only
|
||||
|
||||
// Arguments for the different callback events
|
||||
// - During Resize callback, Buf will be same as your input buffer.
|
||||
@@ -2656,9 +2659,9 @@ struct ImGuiInputTextCallbackData
|
||||
char* Buf; // Text buffer // Read-write // [Resize] Can replace pointer / [Completion,History,Always] Only write to pointed data, don't replace the actual pointer!
|
||||
int BufTextLen; // Text length (in bytes) // Read-write // [Resize,Completion,History,Always] Exclude zero-terminator storage. In C land: == strlen(some_text), in C++ land: string.length()
|
||||
int BufSize; // Buffer size (in bytes) = capacity+1 // Read-only // [Resize,Completion,History,Always] Include zero-terminator storage. In C land: == ARRAYSIZE(my_char_array), in C++ land: string.capacity()+1
|
||||
int CursorPos; // // Read-write // [Completion,History,Always]
|
||||
int SelectionStart; // // Read-write // [Completion,History,Always] == to SelectionEnd when no selection
|
||||
int SelectionEnd; // // Read-write // [Completion,History,Always]
|
||||
int CursorPos; // // Read-write // [Completion,History,Always,CharFilter]
|
||||
int SelectionStart; // // Read-write // [Completion,History,Always,CharFilter] == to SelectionEnd when no selection
|
||||
int SelectionEnd; // // Read-write // [Completion,History,Always,CharFilter]
|
||||
|
||||
// Helper functions for text manipulation.
|
||||
// Use those function to benefit from the CallbackResize behaviors. Calling those function reset the selection.
|
||||
@@ -3166,12 +3169,6 @@ typedef unsigned short ImDrawIdx; // Default: 16-bit (for maximum compatibilit
|
||||
typedef void (*ImDrawCallback)(const ImDrawList* parent_list, const ImDrawCmd* cmd);
|
||||
#endif
|
||||
|
||||
// Special Draw callback value to request renderer backend to reset the graphics/render state.
|
||||
// The renderer backend needs to handle this special value, otherwise it will crash trying to call a function at this address.
|
||||
// This is useful, for example, if you submitted callbacks which you know have altered the render state and you want it to be restored.
|
||||
// Render state is not reset by default because they are many perfectly useful way of altering render state (e.g. changing shader/blending settings before an Image call).
|
||||
#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-8)
|
||||
|
||||
// Typically, 1 command = 1 GPU draw call (unless command is a callback)
|
||||
// - VtxOffset: When 'io.BackendFlags & ImGuiBackendFlags_RendererHasVtxOffset' is enabled,
|
||||
// this fields allow us to render meshes larger than 64K vertices while keeping 16-bit indices.
|
||||
@@ -3245,16 +3242,15 @@ struct ImDrawListSplitter
|
||||
};
|
||||
|
||||
// Flags for ImDrawList functions
|
||||
// (Legacy: bit 0 must always correspond to ImDrawFlags_Closed to be backward compatible with old API using a bool. Bits 1..3 must be unused)
|
||||
enum ImDrawFlags_
|
||||
{
|
||||
ImDrawFlags_None = 0,
|
||||
ImDrawFlags_Closed = 1 << 0, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
|
||||
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01.
|
||||
ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02.
|
||||
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04.
|
||||
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08.
|
||||
ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag!
|
||||
ImDrawFlags_Closed = 1 << 9, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
|
||||
ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
|
||||
ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
|
||||
ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
|
||||
@@ -3262,6 +3258,7 @@ enum ImDrawFlags_
|
||||
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
|
||||
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified.
|
||||
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone,
|
||||
ImDrawFlags_InvalidMask_ = (ImDrawFlags)0x8000000F,
|
||||
};
|
||||
|
||||
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
|
||||
@@ -3327,7 +3324,9 @@ struct ImDrawList
|
||||
// In future versions we will use textures to provide cheaper and higher-quality circles.
|
||||
// Use AddNgon() and AddNgonFilled() functions if you need to guarantee a specific number of sides.
|
||||
IMGUI_API void AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float thickness = 1.0f);
|
||||
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f); // a: upper-left, b: lower-right (== upper-left + size)
|
||||
IMGUI_API void AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness = 1.0f);
|
||||
IMGUI_API void AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness = 1.0f);
|
||||
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
|
||||
IMGUI_API void AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0); // a: upper-left, b: lower-right (== upper-left + size)
|
||||
IMGUI_API void AddRectFilledMultiColor(const ImVec2& p_min, const ImVec2& p_max, ImU32 col_upr_left, ImU32 col_upr_right, ImU32 col_bot_right, ImU32 col_bot_left);
|
||||
IMGUI_API void AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col, float thickness = 1.0f);
|
||||
@@ -3348,7 +3347,7 @@ struct ImDrawList
|
||||
// General polygon
|
||||
// - Only simple polygons are supported by filling functions (no self-intersections, no holes).
|
||||
// - Concave polygon fill is more expensive than convex one: it has O(N^2) complexity. Provided as a convenience for the user but not used by the main library.
|
||||
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
|
||||
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);
|
||||
IMGUI_API void AddConvexPolyFilled(const ImVec2* points, int num_points, ImU32 col);
|
||||
IMGUI_API void AddConcavePolyFilled(const ImVec2* points, int num_points, ImU32 col);
|
||||
|
||||
@@ -3368,7 +3367,7 @@ struct ImDrawList
|
||||
inline void PathLineToMergeDuplicate(const ImVec2& pos) { if (_Path.Size == 0 || memcmp(&_Path.Data[_Path.Size - 1], &pos, 8) != 0) _Path.push_back(pos); }
|
||||
inline void PathFillConvex(ImU32 col) { AddConvexPolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
|
||||
inline void PathFillConcave(ImU32 col) { AddConcavePolyFilled(_Path.Data, _Path.Size, col); _Path.Size = 0; }
|
||||
inline void PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f) { AddPolyline(_Path.Data, _Path.Size, col, flags, thickness); _Path.Size = 0; }
|
||||
inline void PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0) { AddPolyline(_Path.Data, _Path.Size, col, thickness, flags); _Path.Size = 0; }
|
||||
IMGUI_API void PathArcTo(const ImVec2& center, float radius, float a_min, float a_max, int num_segments = 0);
|
||||
IMGUI_API void PathArcToFast(const ImVec2& center, float radius, int a_min_of_12, int a_max_of_12); // Use precomputed angles for a 12 steps circle
|
||||
IMGUI_API void PathEllipticalArcTo(const ImVec2& center, const ImVec2& radius, float rot, float a_min, float a_max, int num_segments = 0); // Ellipse
|
||||
@@ -3378,14 +3377,15 @@ struct ImDrawList
|
||||
|
||||
// Advanced: Draw Callbacks
|
||||
// - May be used to alter render state (change sampler, blending, current shader). May be used to emit custom rendering commands (difficult to do correctly, but possible).
|
||||
// - Use special ImDrawCallback_ResetRenderState callback to instruct backend to reset its render state to the default.
|
||||
// - Use special GetPlatformIO().DrawCallback_ResetRenderState callback to instruct backend to reset its render state to the default.
|
||||
// - See other standard callbacks in GetPlatformIO(), which may or not be supported by your backend.
|
||||
// - Your rendering loop must check for 'UserCallback' in ImDrawCmd and call the function instead of rendering triangles. All standard backends are honoring this.
|
||||
// - For some backends, the callback may access selected render-states exposed by the backend in a ImGui_ImplXXXX_RenderState structure pointed to by platform_io.Renderer_RenderState.
|
||||
// - IMPORTANT: please be mindful of the different level of indirection between using size==0 (copying argument) and using size>0 (copying pointed data into a buffer).
|
||||
// - If userdata_size == 0: we copy/store the 'userdata' argument as-is. It will be available unmodified in ImDrawCmd::UserCallbackData during render.
|
||||
// - If userdata_size > 0, we copy/store 'userdata_size' bytes pointed to by 'userdata'. We store them in a buffer stored inside the drawlist. ImDrawCmd::UserCallbackData will point inside that buffer so you have to retrieve data from there. Your callback may need to use ImDrawCmd::UserCallbackDataSize if you expect dynamically-sized data.
|
||||
// - Support for userdata_size > 0 was added in v1.91.4, October 2024. So earlier code always only allowed to copy/store a simple void*.
|
||||
IMGUI_API void AddCallback(ImDrawCallback callback, void* userdata, size_t userdata_size = 0);
|
||||
IMGUI_API void AddCallback(ImDrawCallback callback, void* userdata = NULL, size_t userdata_size = 0);
|
||||
|
||||
// Advanced: Miscellaneous
|
||||
IMGUI_API void AddDrawCmd(); // This is useful if you need to forcefully create a new draw call (to allow for dependent rendering / blending). Otherwise primitives are merged into the same draw-call as much as possible
|
||||
@@ -3415,8 +3415,15 @@ struct ImDrawList
|
||||
|
||||
// Obsolete names
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
inline void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness) { AddRect(p_min, p_max, col, rounding, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
|
||||
inline void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) { AddPolyline(points, num_points, col, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
|
||||
inline void PathStroke(ImU32 col, ImDrawFlags flags, float thickness) { PathStroke(col, thickness, flags); } // OBSOLETED in 1.92.8: NEW FUNCTION SIGNATURE HAS 'thickness' AND 'flags' SWAPPED.
|
||||
inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0
|
||||
inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0
|
||||
#else
|
||||
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
|
||||
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete;
|
||||
inline void PathStroke(ImU32 col, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
|
||||
#endif
|
||||
//inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024)
|
||||
//inline void AddEllipseFilled(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0) { AddEllipseFilled(center, ImVec2(radius_x, radius_y), col, rot, num_segments); } // OBSOLETED in 1.90.5 (Mar 2024)
|
||||
@@ -3528,6 +3535,7 @@ struct ImTextureData
|
||||
bool WantDestroyNextFrame; // rw - // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
|
||||
|
||||
// Functions
|
||||
// - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear() instead of ClearFonts()?
|
||||
ImTextureData() { memset((void*)this, 0, sizeof(*this)); Status = ImTextureStatus_Destroyed; TexID = ImTextureID_Invalid; }
|
||||
~ImTextureData() { DestroyPixels(); }
|
||||
IMGUI_API void Create(ImTextureFormat format, int w, int h);
|
||||
@@ -3684,13 +3692,13 @@ struct ImFontAtlas
|
||||
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
|
||||
IMGUI_API void RemoveFont(ImFont* font);
|
||||
|
||||
IMGUI_API void Clear(); // Clear everything (input fonts, output glyphs/textures).
|
||||
IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame!
|
||||
IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. You can call this mid-frame if you load new fonts afterwards!
|
||||
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
|
||||
IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime.
|
||||
|
||||
// As we are transitioning toward a new font system, we expect to obsolete those soon:
|
||||
IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
|
||||
IMGUI_API void ClearFonts(); // [OBSOLETE] Clear input+output font data (same as ClearInputData() + glyphs storage, UV coordinates).
|
||||
IMGUI_API void ClearTexData(); // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory.
|
||||
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
@@ -3862,6 +3870,7 @@ enum ImFontFlags_
|
||||
ImFontFlags_NoLoadError = 1 << 1, // Disable throwing an error/assert when calling AddFontXXX() with missing file/data. Calling code is expected to check AddFontXXX() return value.
|
||||
ImFontFlags_NoLoadGlyphs = 1 << 2, // [Internal] Disable loading new glyphs.
|
||||
ImFontFlags_LockBakedSizes = 1 << 3, // [Internal] Disable loading new baked sizes, disable garbage collecting current ones. e.g. if you want to lock a font to a single size. Important: if you use this to preload given sizes, consider the possibility of multiple font density used on Retina display.
|
||||
ImFontFlags_ImplicitRefSize = 1 << 4, // [Internal] Reference size was not set explicitly.
|
||||
};
|
||||
|
||||
// Font runtime data and rendering
|
||||
@@ -3876,7 +3885,7 @@ struct ImFont
|
||||
ImFontAtlas* OwnerAtlas; // 4-8 // What we have been loaded into.
|
||||
ImFontFlags Flags; // 4 // Font flags.
|
||||
float CurrentRasterizerDensity; // Current rasterizer density. This is a varying state of the font.
|
||||
float LineHeight; // 4 // Line Height
|
||||
float LineHeight; // 4 // Line Height
|
||||
|
||||
// [Internal] Members: Cold ~24-52 bytes
|
||||
// Conceptually Sources[] is the list of font sources merged to create this font.
|
||||
@@ -4023,6 +4032,12 @@ struct ImGuiPlatformIO
|
||||
// Written by some backends during ImGui_ImplXXXX_RenderDrawData() call to point backend_specific ImGui_ImplXXXX_RenderState* structure.
|
||||
void* Renderer_RenderState;
|
||||
|
||||
// Standard draw callbacks provided by renderer backend.
|
||||
ImDrawCallback DrawCallback_ResetRenderState; // Request to reset the graphics/render state.
|
||||
ImDrawCallback DrawCallback_SetSamplerLinear; // Request backend to set texture sampling to Linear.
|
||||
ImDrawCallback DrawCallback_SetSamplerNearest; // Request backend to set texture sampling to Nearest/Point.
|
||||
//ImDrawCallback DrawCallback_SetSamplerCustom; // Request backend to set texture sampling using Backend Specific data.
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Output
|
||||
//------------------------------------------------------------------
|
||||
@@ -4151,6 +4166,8 @@ namespace ImGui
|
||||
//static inline void SetScrollPosHere() { SetScrollHere(); } // OBSOLETED in 1.42
|
||||
}
|
||||
|
||||
#define ImDrawCallback_ResetRenderState (ImDrawCallback)(-8) // OBSOLETED in 1.92.8: Use ImGui::GetPlatformIO().DrawCallback_ResetRenderState
|
||||
|
||||
//-- OBSOLETED in 1.92.0: ImFontAtlasCustomRect becomes ImTextureRect
|
||||
// - ImFontAtlasCustomRect::X,Y --> ImTextureRect::x,y
|
||||
// - ImFontAtlasCustomRect::Width,Height --> ImTextureRect::w,h
|
||||
|
||||
+22
-6
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (internal structures/api)
|
||||
|
||||
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
|
||||
@@ -252,6 +252,9 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
|
||||
#define IMGUI_DEBUG_LOG_FONT(...) do { ImGuiContext* g2 = GImGui; if (g2 && g2->DebugLogFlags & ImGuiDebugLogFlags_EventFont) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Called from ImFontAtlas function which may operate without a context.
|
||||
#define IMGUI_DEBUG_LOG_INPUTROUTING(...) do{if (g.DebugLogFlags & ImGuiDebugLogFlags_EventInputRouting)IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
|
||||
|
||||
// Debug options (also see ones on top of imgui.cpp)
|
||||
//#define IMGUI_DEBUG_BOXSELECT
|
||||
|
||||
// Static Asserts
|
||||
#define IM_STATIC_ASSERT(_COND) static_assert(_COND, "")
|
||||
|
||||
@@ -506,7 +509,8 @@ inline double ImRsqrt(double x) { return 1.0 / sqrt(x); }
|
||||
template<typename T> T ImMin(T lhs, T rhs) { return lhs < rhs ? lhs : rhs; }
|
||||
template<typename T> T ImMax(T lhs, T rhs) { return lhs >= rhs ? lhs : rhs; }
|
||||
template<typename T> T ImClamp(T v, T mn, T mx) { return (v < mn) ? mn : (v > mx) ? mx : v; }
|
||||
template<typename T> T ImLerp(T a, T b, float t) { return (T)(a + (b - a) * t); }
|
||||
template<typename T> T ImLerp(double a, double b, float t) { return (T)(a + (b - a) * (double)t); }
|
||||
template<typename T> T ImLerp(T a, T b, float t) { return (T)((float)a + (float)(b - a) * t); }
|
||||
template<typename T> void ImSwap(T& a, T& b) { T tmp = a; a = b; b = tmp; }
|
||||
template<typename T> T ImAddClampOverflow(T a, T b, T mn, T mx) { if (b < 0 && (a < mn - b)) return mn; if (b > 0 && (a > mx - b)) return mx; return a + b; }
|
||||
template<typename T> T ImSubClampOverflow(T a, T b, T mn, T mx) { if (b > 0 && (a < mn + b)) return mn; if (b < 0 && (a > mx + b)) return mx; return a - b; }
|
||||
@@ -603,6 +607,8 @@ struct IMGUI_API ImRect
|
||||
bool Overlaps(const ImRect& r) const { return r.Min.y < Max.y && r.Max.y > Min.y && r.Min.x < Max.x && r.Max.x > Min.x; }
|
||||
void Add(const ImVec2& p) { if (Min.x > p.x) Min.x = p.x; if (Min.y > p.y) Min.y = p.y; if (Max.x < p.x) Max.x = p.x; if (Max.y < p.y) Max.y = p.y; }
|
||||
void Add(const ImRect& r) { if (Min.x > r.Min.x) Min.x = r.Min.x; if (Min.y > r.Min.y) Min.y = r.Min.y; if (Max.x < r.Max.x) Max.x = r.Max.x; if (Max.y < r.Max.y) Max.y = r.Max.y; }
|
||||
void AddX(float x) { if (Min.x > x) Min.x = x; if (Max.x < x) Max.x = x; }
|
||||
void AddY(float y) { if (Min.y > y) Min.y = y; if (Max.y < y) Max.y = y; }
|
||||
void Expand(const float amount) { Min.x -= amount; Min.y -= amount; Max.x += amount; Max.y += amount; }
|
||||
void Expand(const ImVec2& amount) { Min.x -= amount.x; Min.y -= amount.y; Max.x += amount.x; Max.y += amount.y; }
|
||||
void Translate(const ImVec2& d) { Min.x += d.x; Min.y += d.y; Max.x += d.x; Max.y += d.y; }
|
||||
@@ -999,6 +1005,7 @@ enum ImGuiItemStatusFlags_
|
||||
ImGuiItemStatusFlags_HasClipRect = 1 << 9, // g.LastItemData.ClipRect is valid.
|
||||
ImGuiItemStatusFlags_HasShortcut = 1 << 10, // g.LastItemData.Shortcut valid. Set by SetNextItemShortcut() -> ItemAdd().
|
||||
//ImGuiItemStatusFlags_FocusedByTabbing = 1 << 8, // Removed IN 1.90.1 (Dec 2023). The trigger is part of g.NavActivateId. See commit 54c1bdeceb.
|
||||
ImGuiItemStatusFlags_EditedInternal = 1 << 11, // Similar to ImGuiItemStatusFlags_Edited but bypassing ImGuiItemFlags_NoMarkEdited.
|
||||
|
||||
// Additional status + semantic for ImGuiTestEngine
|
||||
#ifdef IMGUI_ENABLE_TEST_ENGINE
|
||||
@@ -1204,6 +1211,7 @@ struct IMGUI_API ImGuiMenuColumns
|
||||
};
|
||||
|
||||
// Internal temporary state for deactivating InputText() instances.
|
||||
// Store as part of ImGuiDeactivatedItemData?
|
||||
struct IMGUI_API ImGuiInputTextDeactivatedState
|
||||
{
|
||||
ImGuiID ID; // widget id owning the text state (which just got deactivated)
|
||||
@@ -1449,6 +1457,7 @@ struct ImGuiPtrOrIndex
|
||||
};
|
||||
|
||||
// Data used by IsItemDeactivated()/IsItemDeactivatedAfterEdit() functions
|
||||
// Also see ImGuiInputTextDeactivatedState which is an extension for this for InputText()
|
||||
struct ImGuiDeactivatedItemData
|
||||
{
|
||||
ImGuiID ID;
|
||||
@@ -1890,6 +1899,7 @@ struct ImGuiBoxSelectState
|
||||
// Temporary/Transient data
|
||||
bool UnclipMode; // (Temp/Transient, here in hot area). Set/cleared by the BeginMultiSelect()/EndMultiSelect() owning active box-select.
|
||||
ImRect UnclipRect; // Rectangle where ItemAdd() clipping may be temporarily disabled. Need support by multi-select supporting widgets.
|
||||
ImRect UnclipRects[2]; // Per-axis versions.
|
||||
ImRect BoxSelectRectPrev; // Selection rectangle in absolute coordinates (derived every frame from BoxSelectStartPosRel and MousePos)
|
||||
ImRect BoxSelectRectCurr;
|
||||
|
||||
@@ -1912,7 +1922,8 @@ struct IMGUI_API ImGuiMultiSelectTempData
|
||||
ImGuiMultiSelectFlags Flags;
|
||||
ImVec2 ScopeRectMin;
|
||||
ImVec2 BackupCursorMaxPos;
|
||||
ImGuiSelectionUserData LastSubmittedItem; // Copy of last submitted item data, used to merge output ranges.
|
||||
//ImGuiSelectionUserData CurrSubmittedItem; // Copy of last submitted item data, used to merge output ranges.
|
||||
//ImGuiSelectionUserData PrevSubmittedItem; // Copy of previous submitted item data, used to merge output ranges.
|
||||
ImGuiID BoxSelectId;
|
||||
ImGuiKeyChord KeyMods;
|
||||
ImS8 LoopRequestSetAll; // -1: no operation, 0: clear all, 1: select all.
|
||||
@@ -2213,6 +2224,7 @@ struct ImGuiContext
|
||||
float CurrentDpiScale; // Current window/viewport DpiScale == CurrentViewport->DpiScale
|
||||
ImDrawListSharedData DrawListSharedData;
|
||||
ImGuiID WithinEndChildID; // Set within EndChild()
|
||||
ImGuiID WithinEndPopupID; // Set within EndPopup()
|
||||
void* TestEngine; // Test engine user data
|
||||
|
||||
// Inputs
|
||||
@@ -3205,7 +3217,7 @@ namespace ImGui
|
||||
IMGUI_API void SetNextWindowRefreshPolicy(ImGuiWindowRefreshFlags flags);
|
||||
|
||||
// Fonts, drawing
|
||||
IMGUI_API void RegisterUserTexture(ImTextureData* tex); // Register external texture. EXPERIMENTAL: DO NOT USE YET.
|
||||
IMGUI_API void RegisterUserTexture(ImTextureData* tex); // Register external texture. EXPERIMENTAL.
|
||||
IMGUI_API void UnregisterUserTexture(ImTextureData* tex);
|
||||
IMGUI_API void RegisterFontAtlas(ImFontAtlas* atlas);
|
||||
IMGUI_API void UnregisterFontAtlas(ImFontAtlas* atlas);
|
||||
@@ -3320,6 +3332,7 @@ namespace ImGui
|
||||
|
||||
// Childs
|
||||
IMGUI_API bool BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags);
|
||||
IMGUI_API ImGuiWindow* FindFrontMostVisibleChildWindow(ImGuiWindow* window);
|
||||
|
||||
// Popups, Modals
|
||||
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags);
|
||||
@@ -3425,7 +3438,7 @@ namespace ImGui
|
||||
IMGUI_API ImGuiID GetKeyOwner(ImGuiKey key);
|
||||
IMGUI_API void SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
|
||||
IMGUI_API void SetKeyOwnersForKeyChord(ImGuiKeyChord key, ImGuiID owner_id, ImGuiInputFlags flags = 0);
|
||||
IMGUI_API void SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags); // Set key owner to last item if it is hovered or active. Equivalent to 'if (IsItemHovered() || IsItemActive()) { SetKeyOwner(key, GetItemID());'.
|
||||
IMGUI_API bool SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags);
|
||||
IMGUI_API bool TestKeyOwner(ImGuiKey key, ImGuiID owner_id); // Test that key is either not owned, either owned by 'owner_id'
|
||||
inline ImGuiKeyOwnerData* GetKeyOwnerData(ImGuiContext* ctx, ImGuiKey key) { if (key & ImGuiMod_Mask_) key = ConvertSingleModFlagToKey(key); IM_ASSERT(IsNamedKey(key)); return &ctx->KeysOwnerData[key - ImGuiKey_NamedKey_BEGIN]; }
|
||||
|
||||
@@ -3473,6 +3486,7 @@ namespace ImGui
|
||||
// We don't use the ID Stack for this as it is common to want them separate.
|
||||
IMGUI_API void PushFocusScope(ImGuiID id);
|
||||
IMGUI_API void PopFocusScope();
|
||||
IMGUI_API bool IsInNavFocusRoute(ImGuiID focus_scope_id);
|
||||
inline ImGuiID GetCurrentFocusScope() { ImGuiContext& g = *GImGui; return g.CurrentFocusScopeId; } // Focus scope we are outputting into, set by PushFocusScope()
|
||||
|
||||
// Drag and Drop
|
||||
@@ -3482,7 +3496,7 @@ namespace ImGui
|
||||
IMGUI_API void ClearDragDrop();
|
||||
IMGUI_API bool IsDragDropPayloadBeingAccepted();
|
||||
IMGUI_API void RenderDragDropTargetRectForItem(const ImRect& bb);
|
||||
IMGUI_API void RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb);
|
||||
IMGUI_API void RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding);
|
||||
|
||||
// Typing-Select API
|
||||
// (provide Windows Explorer style "select items by typing partial name" + "cycle through items by typing same letter" feature)
|
||||
@@ -3539,6 +3553,7 @@ namespace ImGui
|
||||
IMGUI_API void TableUpdateLayout(ImGuiTable* table);
|
||||
IMGUI_API void TableUpdateBorders(ImGuiTable* table);
|
||||
IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table);
|
||||
IMGUI_API void TableApplyExternalUnclipRect(ImGuiTable* table, ImRect& rect);
|
||||
IMGUI_API void TableDrawBorders(ImGuiTable* table);
|
||||
IMGUI_API void TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags_for_section_to_display);
|
||||
IMGUI_API bool TableBeginContextMenuPopup(ImGuiTable* table);
|
||||
@@ -3964,6 +3979,7 @@ IMGUI_API void ImFontAtlasTextureBlockFill(ImTextureData* dst_tex,
|
||||
IMGUI_API void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h);
|
||||
IMGUI_API void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h);
|
||||
|
||||
IMGUI_API void ImTextureDataQueueUpload(ImTextureData* tex, int x, int y, int w, int h);
|
||||
IMGUI_API int ImTextureDataGetFormatBytesPerPixel(ImTextureFormat format);
|
||||
IMGUI_API const char* ImTextureDataGetStatusName(ImTextureStatus status);
|
||||
IMGUI_API const char* ImTextureDataGetFormatName(ImTextureFormat format);
|
||||
|
||||
Vendored
+171
-80
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (main code and documentation)
|
||||
|
||||
// Help:
|
||||
@@ -395,6 +395,31 @@ IMPLEMENTING SUPPORT for ImGuiBackendFlags_RendererHasTextures:
|
||||
When you are not sure about an old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all imgui files.
|
||||
You can read releases logs https://github.com/ocornut/imgui/releases for more details.
|
||||
|
||||
- 2026/05/07 (1.92.8) - DrawList: swapped the last two arguments of AddRect(), AddPolyline(), PathStroke().
|
||||
- Before: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, ImDrawFlags flags = 0, float thickness = 1.0f);
|
||||
- After: void ImDrawList::AddRect(ImVec2 p_min, ImVec2 p_max, ImU32 col, float rounding = 0.0f, float thickness = 1.0f, ImDrawFlags flags = 0);
|
||||
- Before: void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness);
|
||||
- After: void ImDrawList::AddPolyline(const ImVec2* points, int num_points, ImU32 col, float thickness, ImDrawFlags flags = 0);
|
||||
- Before: void ImDrawList::PathStroke(ImU32 col, ImDrawFlags flags = 0, float thickness = 1.0f);
|
||||
- After: void ImDrawList::PathStroke(ImU32 col, float thickness = 1.0f, ImDrawFlags flags = 0);
|
||||
Added inline redirection functions when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is off.
|
||||
Marked the old functions are =delete when IMGUI_DISABLE_OBSOLETE_FUNCTIONS is on, to allow for better type-checking.
|
||||
Effectively the typical call site is changing from:
|
||||
- Before: window->DrawList->AddRect(p_min, p_max, color, rounding, ImDrawFlags_None, border_size);
|
||||
- After: window->DrawList->AddRect(p_min, p_max, color, rounding, border_size);
|
||||
Notes:
|
||||
- Users of C++ and other languages with type-checking will be notified at compile-time of any mistakes.
|
||||
- Users of high-level bindings or languages with no type-checking will be notified at runtime via an assert for invalid flags value.
|
||||
If you are a binding maintainer consider doing something to facilitate transition or error detection.
|
||||
- This is perhaps the worst breaking change in our history :( but it makes ImDrawList function signatures consistent.
|
||||
As we are aiming to add flags and features to variety of ImDrawList functions, that consistency becomes more important.
|
||||
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
|
||||
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
|
||||
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
|
||||
- 2026/04/23 (1.92.8) - DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`, which is part of our new standard draw callbacks. (#9378)
|
||||
- 2026/04/22 (1.92.8) - Backends: Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler.
|
||||
- When registering custom textures: changed ImGui_ImplVulkan_AddTexture() signature to remove Sampler.
|
||||
- When creating your own descriptor pool (instead of letting backend creates its own): need at least IMGUI_IMPL_VULKAN_MINIMUM_SAMPLED_IMAGE_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + IMGUI_IMPL_VULKAN_MINIMUM_SAMPLER_POOL_SIZE descriptors of type VK_DESCRIPTOR_TYPE_SAMPLER.
|
||||
- 2026/03/19 (1.92.7) - MultiSelect: renamed ImGuiMultiSelectFlags_SelectOnClick to ImGuiMultiSelectFlags_SelectOnAuto.
|
||||
- 2026/02/26 (1.92.7) - Separator: fixed a legacy quirk where Separator() was submitting a zero-height item for layout purpose, even though it draws a 1-pixel separator.
|
||||
The fix could affect code e.g. computing height from multiple widgets in order to allocate vertical space for a footer or multi-line status bar. (#2657, #9263)
|
||||
@@ -1495,7 +1520,7 @@ ImGuiStyle::ImGuiStyle()
|
||||
TabRounding = 5.0f; // Radius of upper corners of a tab. Set to 0.0f to have rectangular tabs.
|
||||
TabBorderSize = 0.0f; // Thickness of border around tabs.
|
||||
TabMinWidthBase = 1.0f; // Minimum tab width, to make tabs larger than their contents. TabBar buttons are not affected.
|
||||
TabMinWidthShrink = 80.0f; // Minimum tab width after shrinking, when using ImGuiTabBarFlags_FittingPolicyMixed policy.
|
||||
TabMinWidthShrink = 80.0f; // Minimum tab width after shrinking, when using ImGuiTabBarFlags_FittingPolicyMixed policy. FLT_MAX: never shrink, will behave like ImGuiTabBarFlags_FittingPolicyScroll.
|
||||
TabCloseButtonMinWidthSelected = -1.0f; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width.
|
||||
TabCloseButtonMinWidthUnselected = 0.0f; // -1: always visible. 0.0f: visible when hovered. >0.0f: visible when hovered if minimum width. FLT_MAX: never show close button when unselected.
|
||||
TabBarBorderSize = 1.0f; // Thickness of tab-bar separator, which takes on the tab active color to denote focus.
|
||||
@@ -1542,6 +1567,7 @@ ImGuiStyle::ImGuiStyle()
|
||||
|
||||
|
||||
// Scale all spacing/padding/thickness values. Do not scale fonts.
|
||||
// Consider not calling this if your initial scale factor if <1.0.
|
||||
// Important: This operation is lossy because we round all sizes to integer. If you need to change your scale multiples, call this over a freshly initialized ImGuiStyle structure rather than scaling multiple times.
|
||||
void ImGuiStyle::ScaleAllSizes(float scale_factor)
|
||||
{
|
||||
@@ -3387,9 +3413,6 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
||||
if (clipper->ItemsHeight <= 0.0f)
|
||||
{
|
||||
IM_ASSERT(data->StepNo == 1);
|
||||
if (table)
|
||||
IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
|
||||
|
||||
bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision((float)clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y);
|
||||
if (affected_by_floating_point_precision)
|
||||
{
|
||||
@@ -3403,7 +3426,14 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
||||
}
|
||||
if (clipper->ItemsHeight == 0.0f && clipper->ItemsCount == INT_MAX) // Accept that no item have been submitted if in indeterminate mode.
|
||||
return false;
|
||||
IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!");
|
||||
if (clipper->ItemsHeight <= 0.0f)
|
||||
{
|
||||
IM_ASSERT_USER_ERROR(clipper->ItemsHeight > 0.0f, "ImGuiListClipper: Failed to calculate item height! First item hasn't been submitted by user code, or has not moved the cursor vertically!");
|
||||
return false;
|
||||
}
|
||||
if (table)
|
||||
IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y);
|
||||
|
||||
calc_clipping = true; // If item height had to be calculated, calculate clipping afterwards.
|
||||
}
|
||||
|
||||
@@ -3449,12 +3479,14 @@ static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper)
|
||||
// FIXME: Selectable() use of half-ItemSpacing isn't consistent in matter of layout, as ItemAdd(bb) stray above ItemSize()'s CursorPos.
|
||||
// RangeSelect's BoxSelect relies on comparing overlap of previous and current rectangle and is sensitive to that.
|
||||
// As a workaround we currently half ItemSpacing worth on each side.
|
||||
min_y -= g.Style.ItemSpacing.y;
|
||||
max_y += g.Style.ItemSpacing.y;
|
||||
float pad_y = g.Style.ItemSpacing.y;
|
||||
min_y -= pad_y;
|
||||
max_y += pad_y;
|
||||
|
||||
// Box-select on 2D area requires different clipping.
|
||||
// (best adding pad_y here than in BeginBoxSelect() as we are closer to current state)
|
||||
if (bs->UnclipMode)
|
||||
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y, bs->UnclipRect.Max.y, 0, 0));
|
||||
data->Ranges.push_back(ImGuiListClipperRange::FromPositions(bs->UnclipRect.Min.y - pad_y, bs->UnclipRect.Max.y + pad_y, 0, 0));
|
||||
}
|
||||
|
||||
// Add main visible range
|
||||
@@ -3648,6 +3680,7 @@ static const ImGuiStyleVarInfo GStyleVarsInfo[] =
|
||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TableAngledHeadersTextAlign)},// ImGuiStyleVar_TableAngledHeadersTextAlign
|
||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesSize)}, // ImGuiStyleVar_TreeLinesSize
|
||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, TreeLinesRounding)}, // ImGuiStyleVar_TreeLinesRounding
|
||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, DragDropTargetRounding)}, // ImGuiStyleVar_DragDropTargetRounding
|
||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, ButtonTextAlign) }, // ImGuiStyleVar_ButtonTextAlign
|
||||
{ 2, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SelectableTextAlign) }, // ImGuiStyleVar_SelectableTextAlign
|
||||
{ 1, ImGuiDataType_Float, (ImU32)offsetof(ImGuiStyle, SeparatorSize)}, // ImGuiStyleVar_SeparatorSize
|
||||
@@ -3748,6 +3781,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
|
||||
case ImGuiCol_ScrollbarGrabHovered: return "ScrollbarGrabHovered";
|
||||
case ImGuiCol_ScrollbarGrabActive: return "ScrollbarGrabActive";
|
||||
case ImGuiCol_CheckMark: return "CheckMark";
|
||||
case ImGuiCol_CheckboxSelectedBg: return "CheckboxSelectedBg";
|
||||
case ImGuiCol_SliderGrab: return "SliderGrab";
|
||||
case ImGuiCol_SliderGrabActive: return "SliderGrabActive";
|
||||
case ImGuiCol_Button: return "Button";
|
||||
@@ -3828,7 +3862,7 @@ void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool
|
||||
else
|
||||
{
|
||||
if (!text_end)
|
||||
text_end = text + ImStrlen(text); // FIXME-OPT
|
||||
text_end = text + ImStrlen(text); // FIXME-OPT (not reached by our internal calls)
|
||||
text_display_end = text_end;
|
||||
}
|
||||
|
||||
@@ -3846,7 +3880,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
if (!text_end)
|
||||
text_end = text + ImStrlen(text); // FIXME-OPT
|
||||
text_end = text + ImStrlen(text); // FIXME-OPT (not reached by our internal calls)
|
||||
|
||||
if (text != text_end)
|
||||
{
|
||||
@@ -3915,8 +3949,8 @@ void ImGui::RenderTextEllipsis(ImDrawList* draw_list, const ImVec2& pos_min, con
|
||||
text_end_full = FindRenderedTextEnd(text);
|
||||
const ImVec2 text_size = text_size_if_known ? *text_size_if_known : CalcTextSize(text, text_end_full, false, 0.0f);
|
||||
|
||||
//draw_list->AddLine(ImVec2(pos_max.x, pos_min.y - 4), ImVec2(pos_max.x, pos_max.y + 6), IM_COL32(0, 0, 255, 255));
|
||||
//draw_list->AddLine(ImVec2(ellipsis_max_x, pos_min.y - 2), ImVec2(ellipsis_max_x, pos_max.y + 3), IM_COL32(0, 255, 0, 255));
|
||||
//draw_list->AddLineV(pos_max.x, pos_min.y - 4, pos_max.y + 6, IM_COL32(0, 0, 255, 255));
|
||||
//draw_list->AddLineV(ellipsis_max_x, pos_min.y - 2, pos_max.y + 3, IM_COL32(0, 255, 0, 255));
|
||||
|
||||
// FIXME: We could technically remove (last_glyph->AdvanceX - last_glyph->X1) from text_size.x here and save a few pixels.
|
||||
if (text_size.x > pos_max.x - pos_min.x)
|
||||
@@ -3961,8 +3995,8 @@ void ImGui::RenderFrame(ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, bool borders
|
||||
const float border_size = g.Style.FrameBorderSize;
|
||||
if (borders && border_size > 0.0f)
|
||||
{
|
||||
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
|
||||
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
|
||||
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, border_size);
|
||||
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, border_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3973,8 +4007,8 @@ void ImGui::RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding)
|
||||
const float border_size = g.Style.FrameBorderSize;
|
||||
if (border_size > 0.0f)
|
||||
{
|
||||
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, 0, border_size);
|
||||
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, 0, border_size);
|
||||
window->DrawList->AddRect(p_min + ImVec2(1, 1), p_max + ImVec2(1, 1), GetColorU32(ImGuiCol_BorderShadow), rounding, border_size);
|
||||
window->DrawList->AddRect(p_min, p_max, GetColorU32(ImGuiCol_Border), rounding, border_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4009,7 +4043,7 @@ void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFl
|
||||
const float thickness = 2.0f;
|
||||
if (flags & ImGuiNavRenderCursorFlags_Compact)
|
||||
{
|
||||
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
|
||||
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, thickness);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4018,7 +4052,7 @@ void ImGui::RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFl
|
||||
bool fully_visible = window->ClipRect.Contains(display_rect);
|
||||
if (!fully_visible)
|
||||
window->DrawList->PushClipRect(display_rect.Min, display_rect.Max);
|
||||
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, 0, thickness);
|
||||
window->DrawList->AddRect(display_rect.Min, display_rect.Max, GetColorU32(ImGuiCol_NavCursor), rounding, thickness);
|
||||
if (!fully_visible)
|
||||
window->DrawList->PopClipRect();
|
||||
}
|
||||
@@ -4052,7 +4086,7 @@ void ImGui::RenderMouseCursor(ImVec2 base_pos, float base_scale, ImGuiMouseCurso
|
||||
float a_min = ImFmod((float)g.Time * 5.0f, 2.0f * IM_PI);
|
||||
float a_max = a_min + IM_PI * 1.65f;
|
||||
draw_list->PathArcTo(pos + ImVec2(14, -1) * scale, 6.0f * scale, a_min, a_max);
|
||||
draw_list->PathStroke(col_fill, ImDrawFlags_None, 3.0f * scale);
|
||||
draw_list->PathStroke(col_fill, 3.0f * scale);
|
||||
}
|
||||
draw_list->PopTexture();
|
||||
}
|
||||
@@ -4150,7 +4184,7 @@ ImGuiContext::ImGuiContext(ImFontAtlas* shared_font_atlas)
|
||||
IO.Fonts = shared_font_atlas ? shared_font_atlas : IM_NEW(ImFontAtlas)();
|
||||
if (shared_font_atlas == NULL)
|
||||
IO.Fonts->OwnerContext = this;
|
||||
WithinEndChildID = 0;
|
||||
WithinEndChildID = WithinEndPopupID = 0;
|
||||
TestEngine = NULL;
|
||||
|
||||
InputEventsNextMouseSource = ImGuiMouseSource_Mouse;
|
||||
@@ -4686,7 +4720,8 @@ void ImGui::SetActiveID(ImGuiID id, ImGuiWindow* window)
|
||||
g.ActiveIdIsJustActivated = (g.ActiveId != id);
|
||||
if (g.ActiveIdIsJustActivated)
|
||||
{
|
||||
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() old:0x%08X (window \"%s\") -> new:0x%08X (window \"%s\")\n", g.ActiveId, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "", id, window ? window->Name : "");
|
||||
IMGUI_DEBUG_LOG_ACTIVEID("SetActiveID() 0x%08X in \"%s\"%*s(previously 0x%08X in \"%s\")\n", id, window ? window->Name : "",
|
||||
ImMax(0, 20 - (int)(window ? strlen(window->Name) : 0)), "", g.ActiveId, g.ActiveIdWindow ? g.ActiveIdWindow->Name : "");
|
||||
g.ActiveIdTimer = 0.0f;
|
||||
g.ActiveIdHasBeenPressedBefore = false;
|
||||
g.ActiveIdHasBeenEditedBefore = false;
|
||||
@@ -4742,8 +4777,12 @@ void ImGui::MarkItemEdited(ImGuiID id)
|
||||
// This marking is to be able to provide info for IsItemDeactivatedAfterEdit().
|
||||
// ActiveId might have been released by the time we call this (as in the typical press/release button behavior) but still need to fill the data.
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_EditedInternal;
|
||||
if (g.LastItemData.ItemFlags & ImGuiItemFlags_NoMarkEdited)
|
||||
return;
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
||||
|
||||
if (g.ActiveId == id || g.ActiveId == 0)
|
||||
{
|
||||
// FIXME: Can't we fully rely on LastItemData yet?
|
||||
@@ -4757,9 +4796,6 @@ void ImGui::MarkItemEdited(ImGuiID id)
|
||||
// We accept 'ActiveIdPreviousFrame == id' for InputText() returning an edit after it has been taken ActiveId away (#4714)
|
||||
// FIXME: This assert is getting a bit meaningless over time. It helped detect some unusual use cases but eventually it is becoming an unnecessary restriction.
|
||||
IM_ASSERT(g.DragDropActive || g.ActiveId == id || g.ActiveId == 0 || g.ActiveIdPreviousFrame == id || g.NavJustMovedToId || (g.CurrentMultiSelect != NULL && g.BoxSelectState.IsActive));
|
||||
|
||||
//IM_ASSERT(g.CurrentWindow->DC.LastItemId == id);
|
||||
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_Edited;
|
||||
}
|
||||
|
||||
bool ImGui::IsWindowContentHoverable(ImGuiWindow* window, ImGuiHoveredFlags flags)
|
||||
@@ -4924,7 +4960,7 @@ bool ImGui::ItemHoverable(const ImRect& bb, ImGuiID id, ImGuiItemFlags item_flag
|
||||
{
|
||||
g.HoveredIdPreviousFrameItemCount++;
|
||||
if (g.DebugDrawIdConflictsId == id)
|
||||
window->DrawList->AddRect(bb.Min - ImVec2(1,1), bb.Max + ImVec2(1,1), IM_COL32(255, 0, 0, 255), 0.0f, ImDrawFlags_None, 2.0f);
|
||||
window->DrawList->AddRect(bb.Min - ImVec2(1,1), bb.Max + ImVec2(1,1), IM_COL32(255, 0, 0, 255), 0.0f, 2.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -5721,7 +5757,7 @@ void ImGui::NewFrame()
|
||||
g.CurrentWindowStack.resize(0);
|
||||
g.BeginPopupStack.resize(0);
|
||||
g.ItemFlagsStack.resize(0);
|
||||
g.ItemFlagsStack.push_back(ImGuiItemFlags_AutoClosePopups); // Default flags
|
||||
g.ItemFlagsStack.push_back(ImGuiItemFlags_Default_); // Default flags
|
||||
g.CurrentItemFlags = g.ItemFlagsStack.back();
|
||||
g.GroupStack.resize(0);
|
||||
|
||||
@@ -5956,7 +5992,7 @@ static void ImGui::RenderDimmedBackgrounds()
|
||||
if (window->DrawList->CmdBuffer.Size == 0)
|
||||
window->DrawList->AddDrawCmd();
|
||||
window->DrawList->PushClipRect(viewport->Pos, viewport->Pos + viewport->Size);
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 0, 3.0f); // FIXME-DPI
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_NavWindowingHighlight, g.NavWindowingHighlightAlpha), window->WindowRounding, 3.0f); // FIXME-DPI
|
||||
window->DrawList->PopClipRect();
|
||||
}
|
||||
}
|
||||
@@ -6432,7 +6468,7 @@ bool ImGui::BeginChildEx(const char* name, ImGuiID id, const ImVec2& size_arg, I
|
||||
window_flags |= ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_NoTitleBar;
|
||||
window_flags |= (parent_window->Flags & ImGuiWindowFlags_NoMove); // Inherit the NoMove flag
|
||||
if (child_flags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AutoResizeY | ImGuiChildFlags_AlwaysAutoResize))
|
||||
window_flags |= ImGuiWindowFlags_AlwaysAutoResize;
|
||||
window_flags |= ImGuiWindowFlags_AlwaysAutoResize; // FIXME: Would be sane to not make single-axis flag set this. (#9355)
|
||||
if ((child_flags & (ImGuiChildFlags_ResizeX | ImGuiChildFlags_ResizeY)) == 0)
|
||||
window_flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings;
|
||||
|
||||
@@ -6581,6 +6617,14 @@ void ImGui::EndChild()
|
||||
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
|
||||
}
|
||||
|
||||
ImGuiWindow* ImGui::FindFrontMostVisibleChildWindow(ImGuiWindow* window)
|
||||
{
|
||||
for (int n = window->DC.ChildWindows.Size - 1; n >= 0; n--)
|
||||
if (IsWindowActiveAndVisible(window->DC.ChildWindows[n]))
|
||||
return FindFrontMostVisibleChildWindow(window->DC.ChildWindows[n]);
|
||||
return window;
|
||||
}
|
||||
|
||||
static void SetWindowConditionAllowFlags(ImGuiWindow* window, ImGuiCond flags, bool enabled)
|
||||
{
|
||||
window->SetWindowPosAllowFlags = enabled ? (window->SetWindowPosAllowFlags | flags) : (window->SetWindowPosAllowFlags & ~flags);
|
||||
@@ -6744,8 +6788,8 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont
|
||||
const float decoration_h_without_scrollbars = window->DecoOuterSizeY1 + window->DecoOuterSizeY2 - window->ScrollbarSizes.y;
|
||||
ImVec2 size_pad = window->WindowPadding * 2.0f;
|
||||
ImVec2 size_desired;
|
||||
size_desired[ImGuiAxis_X] = (axis_mask & 1) ? size_contents.x + size_pad.x + decoration_w_without_scrollbars : window->Size.x;
|
||||
size_desired[ImGuiAxis_Y] = (axis_mask & 2) ? size_contents.y + size_pad.y + decoration_h_without_scrollbars : window->Size.y;
|
||||
size_desired.x = (axis_mask & 1) ? size_contents.x + size_pad.x + decoration_w_without_scrollbars : window->Size.x;
|
||||
size_desired.y = (axis_mask & 2) ? size_contents.y + size_pad.y + decoration_h_without_scrollbars : window->Size.y;
|
||||
|
||||
// Determine maximum window size
|
||||
// Child windows are laid within their parent (unless they are also popups/menus) and thus have no restriction
|
||||
@@ -6764,8 +6808,10 @@ static ImVec2 CalcWindowAutoFitSize(ImGuiWindow* window, const ImVec2& size_cont
|
||||
// When the window cannot fit all contents (either because of constraints, either because screen is too small),
|
||||
// we are growing the size on the other axis to compensate for expected scrollbar. FIXME: Might turn bigger than ViewportSize-WindowPadding.
|
||||
ImVec2 size_auto_fit_after_constraint = CalcWindowSizeAfterConstraint(window, size_auto_fit);
|
||||
bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x - size_pad.x - decoration_w_without_scrollbars < size_contents.x && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||
bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y - size_pad.y - decoration_h_without_scrollbars < size_contents.y && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
float size_contents_for_scrollbar_x = (axis_mask & 1) ? size_contents.x : window->ContentSize.x; // See #9352. In theory this should use same logic as `window->ScrollbarY = ...` codepath in Begin(). Needs some plumbling.
|
||||
float size_contents_for_scrollbar_y = (axis_mask & 2) ? size_contents.y : window->ContentSize.y;
|
||||
bool will_have_scrollbar_x = (size_auto_fit_after_constraint.x < size_contents_for_scrollbar_x + size_pad.x + decoration_w_without_scrollbars && !(window->Flags & ImGuiWindowFlags_NoScrollbar) && (window->Flags & ImGuiWindowFlags_HorizontalScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar);
|
||||
bool will_have_scrollbar_y = (size_auto_fit_after_constraint.y < size_contents_for_scrollbar_y + size_pad.y + decoration_h_without_scrollbars && !(window->Flags & ImGuiWindowFlags_NoScrollbar)) || (window->Flags & ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
||||
if (will_have_scrollbar_x)
|
||||
size_auto_fit.y += style.ScrollbarSize;
|
||||
if (will_have_scrollbar_y)
|
||||
@@ -7106,7 +7152,7 @@ static void RenderWindowOuterSingleBorder(ImGuiWindow* window, int border_n, ImU
|
||||
const ImRect border_r = GetResizeBorderRect(window, border_n, rounding, 0.0f);
|
||||
window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN1) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle - IM_PI * 0.25f, def.OuterAngle);
|
||||
window->DrawList->PathArcTo(ImLerp(border_r.Min, border_r.Max, def.SegmentN2) + ImVec2(0.5f, 0.5f) + def.InnerDir * rounding, rounding, def.OuterAngle, def.OuterAngle + IM_PI * 0.25f);
|
||||
window->DrawList->PathStroke(border_col, ImDrawFlags_None, border_size);
|
||||
window->DrawList->PathStroke(border_col, border_size);
|
||||
}
|
||||
|
||||
static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
|
||||
@@ -7115,7 +7161,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
|
||||
const float border_size = window->WindowBorderSize;
|
||||
const ImU32 border_col = GetColorU32(ImGuiCol_Border);
|
||||
if (border_size > 0.0f && (window->Flags & ImGuiWindowFlags_NoBackground) == 0)
|
||||
window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, 0, window->WindowBorderSize);
|
||||
window->DrawList->AddRect(window->Pos, window->Pos + window->Size, border_col, window->WindowRounding, window->WindowBorderSize);
|
||||
else if (border_size > 0.0f)
|
||||
{
|
||||
if (window->ChildFlags & ImGuiChildFlags_ResizeX) // Similar code as 'resize_border_mask' computation in UpdateWindowManualResize() but we specifically only always draw explicit child resize border.
|
||||
@@ -7132,7 +7178,7 @@ static void ImGui::RenderWindowOuterBorders(ImGuiWindow* window)
|
||||
if (g.Style.FrameBorderSize > 0 && !(window->Flags & ImGuiWindowFlags_NoTitleBar))
|
||||
{
|
||||
float y = window->Pos.y + window->TitleBarHeight - 1;
|
||||
window->DrawList->AddLine(ImVec2(window->Pos.x + border_size * 0.5f, y), ImVec2(window->Pos.x + window->Size.x - border_size * 0.5f, y), border_col, g.Style.FrameBorderSize);
|
||||
window->DrawList->AddLineH(window->Pos.x + border_size * 0.5f, window->Pos.x + window->Size.x - border_size * 0.5f, y, border_col, g.Style.FrameBorderSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7180,7 +7226,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
||||
if (bg_col & IM_COL32_A_MASK)
|
||||
{
|
||||
ImRect bg_rect(window->Pos + ImVec2(0, window->TitleBarHeight), window->Pos + window->Size);
|
||||
ImDrawFlags bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? 0 : ImDrawFlags_RoundCornersBottom;
|
||||
ImDrawFlags bg_rounding_flags = (flags & ImGuiWindowFlags_NoTitleBar) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersBottom;
|
||||
ImDrawList* bg_draw_list = window->DrawList;
|
||||
bg_draw_list->AddRectFilled(bg_rect.Min, bg_rect.Max, bg_col, window_rounding, bg_rounding_flags);
|
||||
}
|
||||
@@ -7200,7 +7246,7 @@ void ImGui::RenderWindowDecorations(ImGuiWindow* window, const ImRect& title_bar
|
||||
menu_bar_rect.ClipWith(window->Rect()); // Soft clipping, in particular child window don't have minimum size covering the menu bar so this is useful for them.
|
||||
window->DrawList->AddRectFilled(menu_bar_rect.Min, menu_bar_rect.Max, GetColorU32(ImGuiCol_MenuBarBg), (flags & ImGuiWindowFlags_NoTitleBar) ? window_rounding : 0.0f, ImDrawFlags_RoundCornersTop);
|
||||
if (style.FrameBorderSize > 0.0f && menu_bar_rect.Max.y < window->Pos.y + window->Size.y)
|
||||
window->DrawList->AddLine(menu_bar_rect.GetBL() + ImVec2(window_border_size * 0.5f, 0.0f), menu_bar_rect.GetBR() - ImVec2(window_border_size * 0.5f, 0.0f), GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
|
||||
window->DrawList->AddLineH(menu_bar_rect.Min.x + window_border_size * 0.5f, menu_bar_rect.Max.x - window_border_size * 0.5f, menu_bar_rect.Max.y, GetColorU32(ImGuiCol_Border), style.FrameBorderSize);
|
||||
}
|
||||
|
||||
// Scrollbars
|
||||
@@ -7844,12 +7890,12 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
ImVec2 avail_size_from_current_frame = ImVec2(window->SizeFull.x, window->SizeFull.y - (window->DecoOuterSizeY1 + window->DecoOuterSizeY2));
|
||||
ImVec2 avail_size_from_last_frame = window->InnerRect.GetSize() + scrollbar_sizes_from_last_frame;
|
||||
ImVec2 needed_size_from_last_frame = window_just_created ? ImVec2(0, 0) : window->ContentSize + window->WindowPadding * 2.0f;
|
||||
float size_x_for_scrollbars = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
|
||||
float size_y_for_scrollbars = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
|
||||
float size_for_scrollbars_x = use_current_size_for_scrollbar_x ? avail_size_from_current_frame.x : avail_size_from_last_frame.x;
|
||||
float size_for_scrollbars_y = use_current_size_for_scrollbar_y ? avail_size_from_current_frame.y : avail_size_from_last_frame.y;
|
||||
bool scrollbar_x_prev = window->ScrollbarX;
|
||||
//bool scrollbar_y_from_last_frame = window->ScrollbarY; // FIXME: May want to use that in the ScrollbarX expression? How many pros vs cons?
|
||||
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_y_for_scrollbars) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
||||
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_x_for_scrollbars - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
||||
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((needed_size_from_last_frame.y > size_for_scrollbars_y) && !(flags & ImGuiWindowFlags_NoScrollbar));
|
||||
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((needed_size_from_last_frame.x > size_for_scrollbars_x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f)) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
|
||||
|
||||
// Track when ScrollbarX visibility keeps toggling, which is a sign of a feedback loop, and stabilize by enforcing visibility (#3285, #8488)
|
||||
// (Feedback loops of this sort can manifest in various situations, but combining horizontal + vertical scrollbar + using a clipper with varying width items is one frequent cause.
|
||||
@@ -7864,7 +7910,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
window->ScrollbarXStabilizeEnabled = scrollbar_x_stabilize;
|
||||
|
||||
if (window->ScrollbarX && !window->ScrollbarY)
|
||||
window->ScrollbarY = (needed_size_from_last_frame.y > size_y_for_scrollbars - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
||||
window->ScrollbarY = (needed_size_from_last_frame.y > size_for_scrollbars_y - style.ScrollbarSize) && !(flags & ImGuiWindowFlags_NoScrollbar);
|
||||
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
|
||||
|
||||
// Amend the partially filled window->DecorationXXX values.
|
||||
@@ -8029,9 +8075,14 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
|
||||
window->DC.LayoutType = ImGuiLayoutType_Vertical;
|
||||
window->DC.ParentLayoutType = parent_window ? parent_window->DC.LayoutType : ImGuiLayoutType_Vertical;
|
||||
|
||||
// Default item width. Make it proportional to window size if window manually resizes
|
||||
const bool is_resizable_window = (window->Size.x > 0.0f && !(flags & ImGuiWindowFlags_Tooltip) && !(flags & ImGuiWindowFlags_AlwaysAutoResize));
|
||||
if (is_resizable_window)
|
||||
// Default item width. Make it proportional to window size if window can be manually resized.
|
||||
// (we cannot use AutoFitFramesX/AutoFitFramesY which is a temporary state)
|
||||
bool is_resizable_width;
|
||||
if (flags & ImGuiWindowFlags_ChildWindow)
|
||||
is_resizable_width = (window->Size.x > 0.0f) && !(window->ChildFlags & (ImGuiChildFlags_AutoResizeX | ImGuiChildFlags_AlwaysAutoResize));
|
||||
else
|
||||
is_resizable_width = (window->Size.x > 0.0f) && !(flags & ImGuiWindowFlags_AlwaysAutoResize);
|
||||
if (is_resizable_width)
|
||||
window->DC.ItemWidthDefault = ImTrunc(window->Size.x * 0.65f);
|
||||
else
|
||||
window->DC.ItemWidthDefault = ImTrunc(g.FontSize * 16.0f);
|
||||
@@ -8201,6 +8252,8 @@ void ImGui::End()
|
||||
ImGuiWindowStackData& window_stack_data = g.CurrentWindowStack.back();
|
||||
|
||||
// Error checking: verify that user doesn't directly call End() on a child window.
|
||||
if (window->Flags & ImGuiWindowFlags_Popup)
|
||||
IM_ASSERT_USER_ERROR(g.WithinEndPopupID == window->ID, "Must call EndPopup() and not End()!");
|
||||
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||
IM_ASSERT_USER_ERROR(g.WithinEndChildID == window->ID, "Must call EndChild() and not End()!");
|
||||
|
||||
@@ -8738,6 +8791,17 @@ void ImGui::PopFocusScope()
|
||||
g.CurrentFocusScopeId = g.FocusScopeStack.Size ? g.FocusScopeStack.back().ID : 0;
|
||||
}
|
||||
|
||||
bool ImGui::IsInNavFocusRoute(ImGuiID focus_scope_id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.NavFocusScopeId == focus_scope_id)
|
||||
return true;
|
||||
for (const ImGuiFocusScopeData& focus_scope : g.NavFocusRoute)
|
||||
if (focus_scope.ID == focus_scope_id)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImGui::SetNavFocusScope(ImGuiID focus_scope_id)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -8972,7 +9036,7 @@ ImFont* ImGui::GetDefaultFont()
|
||||
return g.IO.FontDefault ? g.IO.FontDefault : atlas->Fonts[0];
|
||||
}
|
||||
|
||||
// EXPERIMENTAL: DO NOT USE YET.
|
||||
// EXPERIMENTAL. Use ImTextureDataQueueUpload() to queue updates.
|
||||
void ImGui::RegisterUserTexture(ImTextureData* tex)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -9094,7 +9158,7 @@ void ImGui::UpdateCurrentFontSize(float restore_font_size_after_scaling)
|
||||
}
|
||||
|
||||
g.FontBaked = (g.Font != NULL && window != NULL) ? g.Font->GetFontBaked(final_size) : NULL;
|
||||
g.FontBakedScale = (g.Font != NULL && window != NULL) ? (g.FontSize / g.FontBaked->Size) : 0.0f;
|
||||
g.FontBakedScale = (g.FontBaked != NULL) ? (g.FontSize / g.FontBaked->Size) : 0.0f;
|
||||
g.DrawListSharedData.FontScale = g.FontBakedScale;
|
||||
}
|
||||
|
||||
@@ -10302,15 +10366,21 @@ void ImGui::UpdateMouseWheel()
|
||||
LockWheelingWindow(NULL, 0.0f);
|
||||
}
|
||||
|
||||
ImVec2 wheel;
|
||||
wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, ImGuiKeyOwner_NoOwner) ? g.IO.MouseWheelH : 0.0f;
|
||||
wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, ImGuiKeyOwner_NoOwner) ? g.IO.MouseWheel : 0.0f;
|
||||
|
||||
//IMGUI_DEBUG_LOG("MouseWheel X:%.3f Y:%.3f\n", wheel_x, wheel_y);
|
||||
ImGuiWindow* mouse_window = g.WheelingWindow ? g.WheelingWindow : g.HoveredWindow;
|
||||
if (!mouse_window || mouse_window->Collapsed)
|
||||
return;
|
||||
|
||||
ImGuiID owner_id = mouse_window->ID;
|
||||
ImVec2 wheel;
|
||||
wheel.x = TestKeyOwner(ImGuiKey_MouseWheelX, owner_id) ? g.IO.MouseWheelH : 0.0f;
|
||||
wheel.y = TestKeyOwner(ImGuiKey_MouseWheelY, owner_id) ? g.IO.MouseWheel : 0.0f;
|
||||
//IMGUI_DEBUG_LOG("MouseWheel X:%.3f Y:%.3f\n", wheel_x, wheel_y);
|
||||
if (g.WheelingWindow != NULL)
|
||||
{
|
||||
SetKeyOwner(ImGuiKey_MouseWheelX, owner_id);
|
||||
SetKeyOwner(ImGuiKey_MouseWheelY, owner_id);
|
||||
}
|
||||
|
||||
// Zoom / Scale window
|
||||
// FIXME-OBSOLETE: This is an old feature, it still works but pretty much nobody is using it and may be best redesigned.
|
||||
if (wheel.y != 0.0f && g.IO.KeyCtrl && g.IO.FontAllowUserScaling)
|
||||
@@ -10614,6 +10684,7 @@ bool ImGui::TestKeyOwner(ImGuiKey key, ImGuiID owner_id)
|
||||
// - SetKeyOwner(..., None) : clears owner
|
||||
// - SetKeyOwner(..., Any, !Lock) : illegal (assert)
|
||||
// - SetKeyOwner(..., Any or None, Lock) : set lock
|
||||
// Ownership is automatically released on the frame after a release, see code in UpdateKeyboardInputs().
|
||||
void ImGui::SetKeyOwner(ImGuiKey key, ImGuiID owner_id, ImGuiInputFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@@ -10640,30 +10711,34 @@ void ImGui::SetKeyOwnersForKeyChord(ImGuiKeyChord key_chord, ImGuiID owner_id, I
|
||||
if (key_chord & ~ImGuiMod_Mask_) { SetKeyOwner((ImGuiKey)(key_chord & ~ImGuiMod_Mask_), owner_id, flags); }
|
||||
}
|
||||
|
||||
// This is more or less equivalent to:
|
||||
// This is more or less equivalent to a fancier version of:
|
||||
// if (IsItemHovered() || IsItemActive())
|
||||
// SetKeyOwner(key, GetItemID());
|
||||
// Extensive uses of that (e.g. many calls for a single item) may want to manually perform the tests once and then call SetKeyOwner() multiple times.
|
||||
// More advanced usage scenarios may want to call SetKeyOwner() manually based on different condition.
|
||||
// Worth noting is that only one item can be hovered and only one item can be active, therefore this usage pattern doesn't need to bother with routing and priority.
|
||||
void ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
|
||||
bool ImGui::SetItemKeyOwner(ImGuiKey key, ImGuiInputFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiID id = g.LastItemData.ID;
|
||||
if (id == 0 || (g.HoveredId != id && g.ActiveId != id))
|
||||
return;
|
||||
return false;
|
||||
if ((flags & ImGuiInputFlags_CondMask_) == 0)
|
||||
flags |= ImGuiInputFlags_CondDefault_;
|
||||
if ((g.HoveredId == id && (flags & ImGuiInputFlags_CondHovered)) || (g.ActiveId == id && (flags & ImGuiInputFlags_CondActive)))
|
||||
{
|
||||
IM_ASSERT((flags & ~ImGuiInputFlags_SupportedBySetItemKeyOwner) == 0); // Passing flags not supported by this function!
|
||||
if (!TestKeyOwner(key, id))
|
||||
return false;
|
||||
SetKeyOwner(key, id, flags & ~ImGuiInputFlags_CondMask_);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImGui::SetItemKeyOwner(ImGuiKey key)
|
||||
bool ImGui::SetItemKeyOwner(ImGuiKey key)
|
||||
{
|
||||
SetItemKeyOwner(key, ImGuiInputFlags_None);
|
||||
return SetItemKeyOwner(key, ImGuiInputFlags_None);
|
||||
}
|
||||
|
||||
// This is the only public API until we expose owner_id versions of the API as replacements.
|
||||
@@ -10804,7 +10879,8 @@ bool ImGui::DebugCheckVersionAndDataLayout(const char* version, size_t sz_io, si
|
||||
// to extend contents size of our parent container (e.g. window contents size, which is used for auto-resizing
|
||||
// windows, table column contents size used for auto-resizing columns, group size).
|
||||
// This was causing issues and ambiguities and we needed to retire that.
|
||||
// From 1.89, extending contents size boundaries REQUIRES AN ITEM TO BE SUBMITTED.
|
||||
// 2022/08/05 (1.89): extending contents size boundaries REQUIRES AN ITEM TO BE SUBMITTED. However we gated the new logic behind a '#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS' block.
|
||||
// 2025/06/25 (1.92): removed the legacy path and turned into an assert. It was a mistake that there was a #ifndef before: our obsolescence schedule gets pushed back a bit more :(
|
||||
//
|
||||
// Previously this would make the window content size ~200x200:
|
||||
// Begin(...) + SetCursorScreenPos(GetCursorScreenPos() + ImVec2(200,200)) + End(); // NOT OK ANYMORE
|
||||
@@ -12413,6 +12489,17 @@ bool ImGui::BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags ext
|
||||
return false;
|
||||
}
|
||||
|
||||
// As we bypass BeginChild(), set ImGuiChildFlags_AlwaysAutoResize as it is checked independently from ImGuiWindowFlags_AlwaysAutoResize for now (see #9355)
|
||||
// Ideally we should remove setting ImGuiWindowFlags_AlwaysAutoResize in BeginChild().
|
||||
if ((extra_window_flags & ImGuiWindowFlags_ChildWindow) && (extra_window_flags & ImGuiWindowFlags_AlwaysAutoResize))
|
||||
{
|
||||
if (g.NextWindowData.HasFlags & ImGuiNextWindowDataFlags_HasChildFlags)
|
||||
g.NextWindowData.ChildFlags |= ImGuiChildFlags_AlwaysAutoResize;
|
||||
else
|
||||
g.NextWindowData.ChildFlags = ImGuiChildFlags_AlwaysAutoResize;
|
||||
g.NextWindowData.HasFlags |= ImGuiNextWindowDataFlags_HasChildFlags;
|
||||
}
|
||||
|
||||
char name[128];
|
||||
IM_ASSERT(extra_window_flags & ImGuiWindowFlags_ChildMenu);
|
||||
ImFormatString(name, IM_COUNTOF(name), "%s###Menu_%02d", label, g.BeginMenuDepth); // Recycle windows based on depth
|
||||
@@ -12485,10 +12572,13 @@ void ImGui::EndPopup()
|
||||
NavMoveRequestTryWrapping(window, ImGuiNavMoveFlags_LoopY);
|
||||
|
||||
// Child-popups don't need to be laid out
|
||||
const ImGuiID backup_within_end_popup_id = g.WithinEndPopupID;
|
||||
const ImGuiID backup_within_end_child_id = g.WithinEndChildID;
|
||||
g.WithinEndPopupID = window->ID;
|
||||
if (window->Flags & ImGuiWindowFlags_ChildWindow)
|
||||
g.WithinEndChildID = window->ID;
|
||||
End();
|
||||
g.WithinEndPopupID = backup_within_end_popup_id;
|
||||
g.WithinEndChildID = backup_within_end_child_id;
|
||||
}
|
||||
|
||||
@@ -13310,7 +13400,7 @@ static void ImGui::NavProcessItem()
|
||||
const ImGuiID id = g.LastItemData.ID;
|
||||
const ImGuiItemFlags item_flags = g.LastItemData.ItemFlags;
|
||||
|
||||
// When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221, #8816)
|
||||
// When inside a container that isn't scrollable with Left<>Right, clip NavRect accordingly (#2221, #8816, #7994)
|
||||
ImRect nav_bb = g.LastItemData.NavRect;
|
||||
if (window->DC.NavIsScrollPushableX == false)
|
||||
{
|
||||
@@ -15074,7 +15164,7 @@ const ImGuiPayload* ImGui::AcceptDragDropPayload(const char* type, ImGuiDragDrop
|
||||
{
|
||||
ImRect bb = g.DragDropTargetRect;
|
||||
bb.Expand(-3.5f);
|
||||
RenderDragDropTargetRectEx(GetForegroundDrawList(), bb);
|
||||
RenderDragDropTargetRectEx(GetForegroundDrawList(), bb, g.Style.DragDropTargetRounding);
|
||||
}
|
||||
else if (draw_target_rect)
|
||||
{
|
||||
@@ -15105,16 +15195,16 @@ void ImGui::RenderDragDropTargetRectForItem(const ImRect& bb)
|
||||
bool push_clip_rect = !window->ClipRect.Contains(bb_display);
|
||||
if (push_clip_rect)
|
||||
window->DrawList->PushClipRectFullScreen();
|
||||
RenderDragDropTargetRectEx(window->DrawList, bb_display);
|
||||
RenderDragDropTargetRectEx(window->DrawList, bb_display, g.Style.DragDropTargetRounding);
|
||||
if (push_clip_rect)
|
||||
window->DrawList->PopClipRect();
|
||||
}
|
||||
|
||||
void ImGui::RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb)
|
||||
void ImGui::RenderDragDropTargetRectEx(ImDrawList* draw_list, const ImRect& bb, float rounding)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
draw_list->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTargetBg), g.Style.DragDropTargetRounding, 0);
|
||||
draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTarget), g.Style.DragDropTargetRounding, 0, g.Style.DragDropTargetBorderSize);
|
||||
draw_list->AddRectFilled(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTargetBg), rounding, 0);
|
||||
draw_list->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_DragDropTarget), rounding, g.Style.DragDropTargetBorderSize);
|
||||
}
|
||||
|
||||
const ImGuiPayload* ImGui::GetDragDropPayload()
|
||||
@@ -15774,6 +15864,7 @@ void ImGuiPlatformIO::ClearRendererHandlers()
|
||||
{
|
||||
Renderer_TextureMaxWidth = Renderer_TextureMaxHeight = 0;
|
||||
Renderer_RenderState = NULL;
|
||||
DrawCallback_ResetRenderState = DrawCallback_SetSamplerLinear = DrawCallback_SetSamplerNearest = NULL;
|
||||
}
|
||||
|
||||
ImGuiViewport* ImGui::GetMainViewport()
|
||||
@@ -16215,7 +16306,7 @@ void ImGui::DebugRenderKeyboardPreview(ImDrawList* draw_list)
|
||||
draw_list->AddRect(key_min, key_max, IM_COL32(24, 24, 24, 255), key_rounding);
|
||||
ImVec2 face_min = ImVec2(key_min.x + key_face_pos.x, key_min.y + key_face_pos.y);
|
||||
ImVec2 face_max = ImVec2(face_min.x + key_face_size.x, face_min.y + key_face_size.y);
|
||||
draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, ImDrawFlags_None, 2.0f);
|
||||
draw_list->AddRect(face_min, face_max, IM_COL32(193, 193, 193, 255), key_face_rounding, 2.0f);
|
||||
draw_list->AddRectFilled(face_min, face_max, IM_COL32(252, 252, 252, 255), key_face_rounding);
|
||||
ImVec2 label_min = ImVec2(key_min.x + key_label_pos.x, key_min.y + key_label_pos.y);
|
||||
draw_list->AddText(label_min, IM_COL32(64, 64, 64, 255), key_data->Label);
|
||||
@@ -16638,7 +16729,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
|
||||
BulletText("Table 0x%08X (%d columns, in '%s')", table->ID, table->ColumnsCount, table->OuterWindow->Name);
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(table->OuterRect.Min - ImVec2(1, 1), table->OuterRect.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 2.0f);
|
||||
Indent();
|
||||
char buf[128];
|
||||
for (int rect_n = 0; rect_n < TRT_Count; rect_n++)
|
||||
@@ -16653,7 +16744,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImFormatString(buf, IM_COUNTOF(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) Col %d %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), column_n, trt_rects_names[rect_n]);
|
||||
Selectable(buf);
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 2.0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -16662,7 +16753,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImFormatString(buf, IM_COUNTOF(buf), "(%6.1f,%6.1f) (%6.1f,%6.1f) Size (%6.1f,%6.1f) %s", r.Min.x, r.Min.y, r.Max.x, r.Max.y, r.GetWidth(), r.GetHeight(), trt_rects_names[rect_n]);
|
||||
Selectable(buf);
|
||||
if (IsItemHovered())
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 0, 2.0f);
|
||||
GetForegroundDrawList(table->OuterWindow)->AddRect(r.Min - ImVec2(1, 1), r.Max + ImVec2(1, 1), IM_COL32(255, 255, 0, 255), 0.0f, 2.0f);
|
||||
}
|
||||
}
|
||||
Unindent();
|
||||
@@ -17070,7 +17161,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImRect r = Funcs::GetTableRect(table, cfg->ShowTablesRectsType, column_n);
|
||||
ImU32 col = (table->HoveredColumnBody == column_n) ? IM_COL32(255, 255, 128, 255) : IM_COL32(255, 0, 128, 255);
|
||||
float thickness = (table->HoveredColumnBody == column_n) ? 3.0f : 1.0f;
|
||||
draw_list->AddRect(r.Min, r.Max, col, 0.0f, 0, thickness);
|
||||
draw_list->AddRect(r.Min, r.Max, col, 0.0f, thickness);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -17247,7 +17338,7 @@ void ImGui::DebugNodeDrawList(ImGuiWindow* window, ImGuiViewportP* viewport, con
|
||||
{
|
||||
ImDrawListFlags backup_flags = fg_draw_list->Flags;
|
||||
fg_draw_list->Flags &= ~ImDrawListFlags_AntiAliasedLines; // Disable AA on triangle outlines is more readable for very large and thin triangles.
|
||||
fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f);
|
||||
fg_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0f, ImDrawFlags_Closed);
|
||||
fg_draw_list->Flags = backup_flags;
|
||||
}
|
||||
}
|
||||
@@ -17275,7 +17366,7 @@ void ImGui::DebugNodeDrawCmdShowMeshAndBoundingBox(ImDrawList* out_draw_list, co
|
||||
for (int n = 0; n < 3; n++, idx_n++)
|
||||
vtxs_rect.Add((triangle[n] = vtx_buffer[idx_buffer ? idx_buffer[idx_n] : idx_n].pos));
|
||||
if (show_mesh)
|
||||
out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), ImDrawFlags_Closed, 1.0f); // In yellow: mesh triangles
|
||||
out_draw_list->AddPolyline(triangle, 3, IM_COL32(255, 255, 0, 255), 1.0f, ImDrawFlags_Closed); // In yellow: mesh triangles
|
||||
}
|
||||
// Draw bounding boxes
|
||||
if (show_aabb)
|
||||
@@ -17556,8 +17647,8 @@ void ImGui::DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label)
|
||||
{
|
||||
ImDrawList* draw_list = GetForegroundDrawList(tab_bar->Window);
|
||||
draw_list->AddRect(tab_bar->BarRect.Min, tab_bar->BarRect.Max, IM_COL32(255, 255, 0, 255));
|
||||
draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
|
||||
draw_list->AddLine(ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y), ImVec2(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Max.y), IM_COL32(0, 255, 0, 255));
|
||||
draw_list->AddLineV(tab_bar->ScrollingRectMinX, tab_bar->BarRect.Min.y, tab_bar->BarRect.Max.y, IM_COL32(0, 255, 0, 255));
|
||||
draw_list->AddLineV(tab_bar->ScrollingRectMaxX, tab_bar->BarRect.Min.y, tab_bar->BarRect.Max.y, IM_COL32(0, 255, 0, 255));
|
||||
}
|
||||
if (open)
|
||||
{
|
||||
@@ -17886,8 +17977,8 @@ void ImGui::DebugDrawCursorPos(ImU32 col)
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
window->DrawList->AddLine(ImVec2(pos.x, pos.y - 3.0f), ImVec2(pos.x, pos.y + 4.0f), col, 1.0f);
|
||||
window->DrawList->AddLine(ImVec2(pos.x - 3.0f, pos.y), ImVec2(pos.x + 4.0f, pos.y), col, 1.0f);
|
||||
window->DrawList->AddLineV(pos.x, pos.y - 3.0f, pos.y + 4.0f, col, 1.0f);
|
||||
window->DrawList->AddLineH(pos.x - 3.0f, pos.x + 4.0f, pos.y, col, 1.0f);
|
||||
}
|
||||
|
||||
// Draw a 10px wide rectangle around CurposPos.x using Line Y1/Y2 in current window's DrawList
|
||||
@@ -17898,9 +17989,9 @@ void ImGui::DebugDrawLineExtents(ImU32 col)
|
||||
float curr_x = window->DC.CursorPos.x;
|
||||
float line_y1 = (window->DC.IsSameLine ? window->DC.CursorPosPrevLine.y : window->DC.CursorPos.y);
|
||||
float line_y2 = line_y1 + (window->DC.IsSameLine ? window->DC.PrevLineSize.y : window->DC.CurrLineSize.y);
|
||||
window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y1), ImVec2(curr_x + 5.0f, line_y1), col, 1.0f);
|
||||
window->DrawList->AddLine(ImVec2(curr_x - 0.5f, line_y1), ImVec2(curr_x - 0.5f, line_y2), col, 1.0f);
|
||||
window->DrawList->AddLine(ImVec2(curr_x - 5.0f, line_y2), ImVec2(curr_x + 5.0f, line_y2), col, 1.0f);
|
||||
window->DrawList->AddLineH(curr_x - 5.0f, curr_x + 5.0f, line_y1, col, 1.0f);
|
||||
window->DrawList->AddLineV(curr_x - 0.5f, line_y1, line_y2, col, 1.0f);
|
||||
window->DrawList->AddLineH(curr_x - 5.0f, curr_x + 5.0f, line_y2, col, 1.0f);
|
||||
}
|
||||
|
||||
// Draw last item rect in ForegroundDrawList (so it is always visible)
|
||||
@@ -18270,7 +18361,7 @@ void ImGui::ShowFontSelector(const char* label)
|
||||
"- Load additional fonts with io.Fonts->AddFontXXX() functions.\n"
|
||||
"- The font atlas is built when calling io.Fonts->GetTexDataAsXXXX() or io.Fonts->Build().\n"
|
||||
"- Read FAQ and docs/FONTS.md for more details.\n"
|
||||
"- If you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
|
||||
"- Legacy backend: if you need to add/remove fonts at runtime (e.g. for DPI change), do it before calling NewFrame().");
|
||||
}
|
||||
#endif // #if !defined(IMGUI_DISABLE_DEMO_WINDOWS) || !defined(IMGUI_DISABLE_DEBUG_TOOLS)
|
||||
|
||||
|
||||
Vendored
+154
-46
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (demo code)
|
||||
|
||||
// Help:
|
||||
@@ -73,6 +73,7 @@ Index of this file:
|
||||
// [SECTION] Demo Window / ShowDemoWindow()
|
||||
// [SECTION] DemoWindowMenuBar()
|
||||
// [SECTION] Helpers: ExampleTreeNode, ExampleMemberInfo (for use by Property Editor & Multi-Select demos)
|
||||
// [SECTION] Helpers: ExampleImageViewer
|
||||
// [SECTION] DemoWindowWidgetsBasic()
|
||||
// [SECTION] DemoWindowWidgetsBullets()
|
||||
// [SECTION] DemoWindowWidgetsCollapsingHeaders()
|
||||
@@ -108,6 +109,7 @@ Index of this file:
|
||||
// [SECTION] User Guide / ShowUserGuide()
|
||||
// [SECTION] Example App: Main Menu Bar / ShowExampleAppMainMenuBar()
|
||||
// [SECTION] Example App: Debug Console / ShowExampleAppConsole()
|
||||
// [SECTION] Example App: Image Viewer / ShowExampleAppImageViewer()
|
||||
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
|
||||
// [SECTION] Example App: Simple Layout / ShowExampleAppLayout()
|
||||
// [SECTION] Example App: Property Editor / ShowExampleAppPropertyEditor()
|
||||
@@ -238,6 +240,7 @@ static void ShowExampleAppAssetsBrowser(bool* p_open);
|
||||
static void ShowExampleAppConsole(bool* p_open);
|
||||
static void ShowExampleAppCustomRendering(bool* p_open);
|
||||
static void ShowExampleAppDocuments(bool* p_open);
|
||||
static void ShowExampleAppImageViewer(bool* p_open);
|
||||
static void ShowExampleAppLog(bool* p_open);
|
||||
static void ShowExampleAppLayout(bool* p_open);
|
||||
static void ShowExampleAppPropertyEditor(bool* p_open, ImGuiDemoWindowData* demo_data);
|
||||
@@ -308,6 +311,7 @@ struct ImGuiDemoWindowData
|
||||
bool ShowAppConsole = false;
|
||||
bool ShowAppCustomRendering = false;
|
||||
bool ShowAppDocuments = false;
|
||||
bool ShowAppImageViewer = false;
|
||||
bool ShowAppLog = false;
|
||||
bool ShowAppLayout = false;
|
||||
bool ShowAppPropertyEditor = false;
|
||||
@@ -353,6 +357,7 @@ void ImGui::ShowDemoWindow(bool* p_open)
|
||||
if (demo_data.ShowAppAssetsBrowser) { ShowExampleAppAssetsBrowser(&demo_data.ShowAppAssetsBrowser); }
|
||||
if (demo_data.ShowAppConsole) { ShowExampleAppConsole(&demo_data.ShowAppConsole); }
|
||||
if (demo_data.ShowAppCustomRendering) { ShowExampleAppCustomRendering(&demo_data.ShowAppCustomRendering); }
|
||||
if (demo_data.ShowAppImageViewer) { ShowExampleAppImageViewer(&demo_data.ShowAppImageViewer); }
|
||||
if (demo_data.ShowAppLog) { ShowExampleAppLog(&demo_data.ShowAppLog); }
|
||||
if (demo_data.ShowAppLayout) { ShowExampleAppLayout(&demo_data.ShowAppLayout); }
|
||||
if (demo_data.ShowAppPropertyEditor) { ShowExampleAppPropertyEditor(&demo_data.ShowAppPropertyEditor, &demo_data); }
|
||||
@@ -677,6 +682,7 @@ static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
|
||||
ImGui::MenuItem("Console", NULL, &demo_data->ShowAppConsole);
|
||||
ImGui::MenuItem("Custom rendering", NULL, &demo_data->ShowAppCustomRendering);
|
||||
ImGui::MenuItem("Documents", NULL, &demo_data->ShowAppDocuments);
|
||||
ImGui::MenuItem("Image Viewer", NULL, &demo_data->ShowAppImageViewer);
|
||||
ImGui::MenuItem("Log", NULL, &demo_data->ShowAppLog);
|
||||
ImGui::MenuItem("Property editor", NULL, &demo_data->ShowAppPropertyEditor);
|
||||
ImGui::MenuItem("Simple layout", NULL, &demo_data->ShowAppLayout);
|
||||
@@ -708,7 +714,7 @@ static void DemoWindowMenuBar(ImGuiDemoWindowData* demo_data)
|
||||
ImGui::Checkbox("Highlight ID Conflicts", &io.ConfigDebugHighlightIdConflicts);
|
||||
ImGui::EndDisabled();
|
||||
ImGui::Checkbox("Assert on error recovery", &io.ConfigErrorRecoveryEnableAssert);
|
||||
ImGui::TextDisabled("(see Demo->Configuration for details & more)");
|
||||
ImGui::TextDisabled("(see Demo->Configuration for more)");
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::MenuItem("Debug Log", NULL, &demo_data->ShowDebugLog, has_debug_tools);
|
||||
@@ -825,6 +831,87 @@ static ExampleTreeNode* ExampleTree_CreateDemoTree()
|
||||
return node_L0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Helpers: ExampleImageViewer
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct ExampleImageViewerData
|
||||
{
|
||||
ImU32 ImageBgColor = IM_COL32(100, 100, 100, 255);
|
||||
ImU32 GridColor = IM_COL32(255, 255, 255, 100);
|
||||
bool GridEnabled = true;
|
||||
bool ViewReset = true;
|
||||
ImVec2 ViewOffset; // in image space
|
||||
float Zoom = 10.0f;
|
||||
float ZoomMin = 1.0f;
|
||||
float ZoomMax = 10000.0f;
|
||||
};
|
||||
|
||||
static void ExampleImageViewer_DrawOptions(ExampleImageViewerData* data)
|
||||
{
|
||||
ImGui::SetNextItemShortcut(ImGuiKey_G, ImGuiInputFlags_Tooltip); // | ImGuiInputFlags_RouteGlobal
|
||||
ImGui::Checkbox("Grid", &data->GridEnabled);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetFontSize() * 10.0f);
|
||||
float zoom_100 = data->Zoom * 100.0f;
|
||||
if (ImGui::DragFloat("##Zoom", &zoom_100, 5.0f, data->ZoomMin * 100.0f, data->ZoomMax * 100.0f, "%.0f%%", ImGuiSliderFlags_AlwaysClamp))
|
||||
data->Zoom = zoom_100 / 100.0f;
|
||||
}
|
||||
|
||||
static void ExampleImageViewer_DrawCanvas(ExampleImageViewerData* data, ImVec2 canvas_size, ImTextureRef image_tex_ref, int image_w, int image_h)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
IM_ASSERT(canvas_size.x >= 0.0f && canvas_size.y >= 0.0f);
|
||||
|
||||
// Layout canvas
|
||||
ImGui::InvisibleButton("##Canvas", canvas_size);
|
||||
ImVec2 canvas_min = ImGui::GetItemRectMin();
|
||||
ImVec2 canvas_max = ImGui::GetItemRectMax();
|
||||
|
||||
if (data->ViewReset)
|
||||
data->ViewOffset = ImVec2((canvas_size.x * 0.5f / data->Zoom) - 0.5f, (canvas_size.y * 0.5f / data->Zoom) - 0.5f); // Add half a pixel padding
|
||||
data->ViewReset = false;
|
||||
|
||||
// Handle inputs
|
||||
if (ImGui::SetItemKeyOwner(ImGuiKey_MouseWheelY))
|
||||
if (io.MouseWheel != 0.0f)
|
||||
data->Zoom = IM_CLAMP(data->Zoom * (1.0f + io.MouseWheel * 0.10f), data->ZoomMin, data->ZoomMax);
|
||||
float zoom = data->Zoom; // (float)(int)ViewZoom;
|
||||
if (ImGui::IsItemActive() && ImGui::IsMouseDragging(0))
|
||||
{
|
||||
data->ViewOffset.x -= io.MouseDelta.x / zoom;
|
||||
data->ViewOffset.y -= io.MouseDelta.y / zoom;
|
||||
}
|
||||
|
||||
// Display image
|
||||
ImVec2 image_min, image_max;
|
||||
image_min.x = (float)(int)((canvas_min.x - (data->ViewOffset.x * zoom)) + (canvas_size.x * 0.5f));
|
||||
image_min.y = (float)(int)((canvas_min.y - (data->ViewOffset.y * zoom)) + (canvas_size.y * 0.5f));
|
||||
image_max.x = (float)(int)(image_min.x + image_w * zoom);
|
||||
image_max.y = (float)(int)(image_min.y + image_h * zoom);
|
||||
draw_list->AddRect(ImVec2(canvas_min.x - 1.0f, canvas_min.y - 1.0f), ImVec2(canvas_max.x + 1.0f, canvas_max.y + 1.0f), IM_COL32(255, 255, 255, 255));
|
||||
draw_list->PushClipRect(canvas_min, canvas_max, true);
|
||||
draw_list->AddRectFilled(image_min, image_max, data->ImageBgColor);
|
||||
if (platform_io.DrawCallback_SetSamplerNearest != NULL)
|
||||
draw_list->AddCallback(platform_io.DrawCallback_SetSamplerNearest);
|
||||
draw_list->AddImage(image_tex_ref, image_min, image_max);
|
||||
if (platform_io.DrawCallback_SetSamplerLinear != NULL)
|
||||
draw_list->AddCallback(ImGui::GetPlatformIO().DrawCallback_SetSamplerLinear);
|
||||
|
||||
// Display grid lines for visible pixels
|
||||
if (data->GridEnabled && zoom > 6.0f)
|
||||
{
|
||||
const float step = (float)zoom;
|
||||
for (int px = (int)((canvas_min.x - image_min.x) / step); px <= (int)((canvas_max.x - image_min.x) / step); px++)
|
||||
draw_list->AddLineV(image_min.x + px * step, canvas_min.y, canvas_max.y, data->GridColor, 1.0f);
|
||||
for (int py = (int)((canvas_min.y - image_min.y) / step); py <= (int)((canvas_max.y - image_min.y) / step); py++)
|
||||
draw_list->AddLineH(canvas_min.x, canvas_max.x, image_min.y + py * step, data->GridColor, 1.0f);
|
||||
}
|
||||
draw_list->PopClipRect();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] DemoWindowWidgetsBasic()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1802,40 +1889,29 @@ static void DemoWindowWidgetsImages()
|
||||
// - Read https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
|
||||
|
||||
// Grab the current texture identifier used by the font atlas.
|
||||
ImTextureRef my_tex_id = io.Fonts->TexRef;
|
||||
ImFontAtlas* atlas = io.Fonts;
|
||||
ImTextureRef my_tex_id = atlas->TexRef;
|
||||
float my_tex_w = (float)atlas->TexData->Width; // Regular user code should never have to care about TexData-> fields, but since we want to display the entire texture here, we pull Width/Height from it.
|
||||
float my_tex_h = (float)atlas->TexData->Height;
|
||||
ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
|
||||
|
||||
// Regular user code should never have to care about TexData-> fields, but since we want to display the entire texture here, we pull Width/Height from it.
|
||||
float my_tex_w = (float)io.Fonts->TexData->Width;
|
||||
float my_tex_h = (float)io.Fonts->TexData->Height;
|
||||
// Basic drawing
|
||||
ImGui::SeparatorText("Image()/ImageWithBg() function");
|
||||
ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
|
||||
ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, IM_MAX(1.0f, ImGui::GetStyle().ImageBorderSize));
|
||||
ImGui::ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
{
|
||||
ImGui::Text("%.0fx%.0f", my_tex_w, my_tex_h);
|
||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
ImVec2 uv_min = ImVec2(0.0f, 0.0f); // Top-left
|
||||
ImVec2 uv_max = ImVec2(1.0f, 1.0f); // Lower-right
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ImageBorderSize, IM_MAX(1.0f, ImGui::GetStyle().ImageBorderSize));
|
||||
ImGui::ImageWithBg(my_tex_id, ImVec2(my_tex_w, my_tex_h), uv_min, uv_max, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
if (ImGui::BeginItemTooltip())
|
||||
{
|
||||
float region_sz = 32.0f;
|
||||
float region_x = io.MousePos.x - pos.x - region_sz * 0.5f;
|
||||
float region_y = io.MousePos.y - pos.y - region_sz * 0.5f;
|
||||
float zoom = 4.0f;
|
||||
if (region_x < 0.0f) { region_x = 0.0f; }
|
||||
else if (region_x > my_tex_w - region_sz) { region_x = my_tex_w - region_sz; }
|
||||
if (region_y < 0.0f) { region_y = 0.0f; }
|
||||
else if (region_y > my_tex_h - region_sz) { region_y = my_tex_h - region_sz; }
|
||||
ImGui::Text("Min: (%.2f, %.2f)", region_x, region_y);
|
||||
ImGui::Text("Max: (%.2f, %.2f)", region_x + region_sz, region_y + region_sz);
|
||||
ImVec2 uv0 = ImVec2((region_x) / my_tex_w, (region_y) / my_tex_h);
|
||||
ImVec2 uv1 = ImVec2((region_x + region_sz) / my_tex_w, (region_y + region_sz) / my_tex_h);
|
||||
ImGui::ImageWithBg(my_tex_id, ImVec2(region_sz * zoom, region_sz * zoom), uv0, uv1, ImVec4(0.0f, 0.0f, 0.0f, 1.0f));
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
}
|
||||
// Fancy widget
|
||||
ImGui::SeparatorText("Interactive Image Viewer");
|
||||
static ExampleImageViewerData image_viewer;
|
||||
ImVec2 canvas_size(ImGui::GetContentRegionAvail().x, my_tex_h * 2.0f);
|
||||
ExampleImageViewer_DrawOptions(&image_viewer);
|
||||
ExampleImageViewer_DrawCanvas(&image_viewer, canvas_size, my_tex_id, (int)my_tex_w, (int)my_tex_h);
|
||||
|
||||
IMGUI_DEMO_MARKER("Widgets/Images/Textured buttons");
|
||||
ImGui::SeparatorText("Textured Buttons");
|
||||
ImGui::TextWrapped("And now some textured buttons..");
|
||||
static int pressed_count = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
@@ -8827,7 +8903,7 @@ static void ShowExampleMenuFile()
|
||||
IMGUI_DEMO_MARKER("Examples/Menu/Options");
|
||||
static bool enabled = true;
|
||||
ImGui::MenuItem("Enabled", "", &enabled);
|
||||
ImGui::BeginChild("child", ImVec2(0, 60), ImGuiChildFlags_Borders);
|
||||
ImGui::BeginChild("child", ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 5.0f), ImGuiChildFlags_Borders);
|
||||
for (int i = 0; i < 10; i++)
|
||||
ImGui::Text("Scrolling Text %d", i);
|
||||
ImGui::EndChild();
|
||||
@@ -9239,6 +9315,28 @@ static void ShowExampleAppConsole(bool* p_open)
|
||||
console.Draw("Example: Console", p_open);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Example App: Image Viewer / ShowExampleAppImageViewer()
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void ShowExampleAppImageViewer(bool* p_open)
|
||||
{
|
||||
ImFontAtlas* atlas = ImGui::GetIO().Fonts;
|
||||
ImTextureRef tex_ref = atlas->TexRef; // We don't have access to other textures in this demo!
|
||||
int tex_w = atlas->TexData->Width;
|
||||
int tex_h = atlas->TexData->Height;
|
||||
if (ImGui::Begin("Example: Image Viewer", p_open))
|
||||
{
|
||||
static ExampleImageViewerData image_viewer;
|
||||
ExampleImageViewer_DrawOptions(&image_viewer);
|
||||
ImVec2 canvas_size = ImGui::GetContentRegionAvail();
|
||||
ImVec2 canvas_min_size = ImGui::IsWindowAppearing() ? ImVec2(3.0f * tex_w, 4.0f * tex_h) : ImVec2(1.0f, 1.0f);
|
||||
canvas_size = ImVec2(IM_MAX(canvas_size.x, canvas_min_size.x), IM_MAX(canvas_size.y, canvas_min_size.y));
|
||||
ExampleImageViewer_DrawCanvas(&image_viewer, canvas_size, tex_ref, tex_w, tex_h);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Example App: Debug Log / ShowExampleAppLog()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -10131,20 +10229,20 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
||||
draw_list->AddNgon(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, ngon_sides, th); x += sz + spacing; // N-gon
|
||||
draw_list->AddCircle(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, col, circle_segments, th); x += sz + spacing; // Circle
|
||||
draw_list->AddEllipse(ImVec2(x + sz*0.5f, y + sz*0.5f), ImVec2(sz*0.5f, sz*0.3f), col, -0.3f, circle_segments, th); x += sz + spacing; // Ellipse
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, ImDrawFlags_None, th); x += sz + spacing; // Square
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, ImDrawFlags_None, th); x += sz + spacing; // Square with all rounded corners
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, corners_tl_br, th); x += sz + spacing; // Square with two rounded corners
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, 0.0f, th); x += sz + spacing; // Square
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, th); x += sz + spacing; // Square with all rounded corners
|
||||
draw_list->AddRect(ImVec2(x, y), ImVec2(x + sz, y + sz), col, rounding, th, corners_tl_br); x += sz + spacing; // Square with two rounded corners
|
||||
draw_list->AddTriangle(ImVec2(x+sz*0.5f,y), ImVec2(x+sz, y+sz-0.5f), ImVec2(x, y+sz-0.5f), col, th);x += sz + spacing; // Triangle
|
||||
//draw_list->AddTriangle(ImVec2(x+sz*0.2f,y), ImVec2(x, y+sz-0.5f), ImVec2(x+sz*0.4f, y+sz-0.5f), col, th);x+= sz*0.4f + spacing; // Thin triangle
|
||||
PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, ImDrawFlags_Closed, th); x += sz + spacing; // Concave Shape
|
||||
PathConcaveShape(draw_list, x, y, sz); draw_list->PathStroke(col, th, ImDrawFlags_Closed); x += sz + spacing; // Concave Shape
|
||||
//draw_list->AddPolyline(concave_shape, IM_COUNTOF(concave_shape), col, ImDrawFlags_Closed, th);
|
||||
draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y), col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
|
||||
draw_list->AddLine(ImVec2(x, y), ImVec2(x, y + sz), col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
|
||||
draw_list->AddLineH(x, x + sz, y, col, th); x += sz + spacing; // Horizontal line (note: drawing a filled rectangle will be faster!)
|
||||
draw_list->AddLineV(x, y, y + sz, col, th); x += spacing; // Vertical line (note: drawing a filled rectangle will be faster!)
|
||||
draw_list->AddLine(ImVec2(x, y), ImVec2(x + sz, y + sz), col, th); x += sz + spacing; // Diagonal line
|
||||
|
||||
// Path
|
||||
draw_list->PathArcTo(ImVec2(x + sz*0.5f, y + sz*0.5f), sz*0.5f, 3.141592f, 3.141592f * -0.5f);
|
||||
draw_list->PathStroke(col, ImDrawFlags_None, th);
|
||||
draw_list->PathStroke(col, th);
|
||||
x += sz + spacing;
|
||||
|
||||
// Quadratic Bezier Curve (3 control points)
|
||||
@@ -10278,9 +10376,9 @@ static void ShowExampleAppCustomRendering(bool* p_open)
|
||||
{
|
||||
const float GRID_STEP = 64.0f;
|
||||
for (float x = fmodf(scrolling.x, GRID_STEP); x < canvas_sz.x; x += GRID_STEP)
|
||||
draw_list->AddLine(ImVec2(canvas_p0.x + x, canvas_p0.y), ImVec2(canvas_p0.x + x, canvas_p1.y), IM_COL32(200, 200, 200, 40));
|
||||
draw_list->AddLineV(canvas_p0.x + x, canvas_p0.y, canvas_p1.y, IM_COL32(200, 200, 200, 40));
|
||||
for (float y = fmodf(scrolling.y, GRID_STEP); y < canvas_sz.y; y += GRID_STEP)
|
||||
draw_list->AddLine(ImVec2(canvas_p0.x, canvas_p0.y + y), ImVec2(canvas_p1.x, canvas_p0.y + y), IM_COL32(200, 200, 200, 40));
|
||||
draw_list->AddLineH(canvas_p0.x, canvas_p1.x, canvas_p0.y + y, IM_COL32(200, 200, 200, 40));
|
||||
}
|
||||
for (int n = 0; n < points.Size; n += 2)
|
||||
draw_list->AddLine(ImVec2(origin.x + points[n].x, origin.y + points[n].y), ImVec2(origin.x + points[n + 1].x, origin.y + points[n + 1].y), IM_COL32(255, 255, 0, 255), 2.0f);
|
||||
@@ -10724,10 +10822,11 @@ struct ExampleAssetsBrowser
|
||||
bool AllowBoxSelect = true; // Will set ImGuiMultiSelectFlags_BoxSelect2d
|
||||
bool AllowBoxSelectInsideSelection = false; // Will set ImGuiMultiSelectFlags_SelectOnClickAlways
|
||||
bool AllowDragUnselected = false; // Will set ImGuiMultiSelectFlags_SelectOnClickRelease
|
||||
float IconSize = 32.0f;
|
||||
float IconSize = 0;
|
||||
int IconSpacing = 10;
|
||||
int IconHitSpacing = 4; // Increase hit-spacing if you want to make it possible to clear or box-select from gaps. Some spacing is required to able to amend with Shift+box-select. Value is small in Explorer.
|
||||
int IconHitSpacing = 4; // Increase hit-spacing if you want to make it possible to clear or box-select from gaps. Some spacing is required to able to amend with Shift+box-select. Value is small in Explorer.
|
||||
bool StretchSpacing = true;
|
||||
bool UseScrollX = false; // Debug: submit twice the number of items per line (overflow horizontally to exercise ScrollX + box-select)
|
||||
|
||||
// State
|
||||
ImVector<ExampleAsset> Items; // Our items
|
||||
@@ -10778,12 +10877,15 @@ struct ExampleAssetsBrowser
|
||||
// Layout: calculate number of icon per line and number of lines
|
||||
LayoutItemSize = ImVec2(floorf(IconSize), floorf(IconSize));
|
||||
LayoutColumnCount = IM_MAX((int)(avail_width / (LayoutItemSize.x + LayoutItemSpacing)), 1);
|
||||
LayoutLineCount = (Items.Size + LayoutColumnCount - 1) / LayoutColumnCount;
|
||||
|
||||
// Layout: when stretching: allocate remaining space to more spacing. Round before division, so item_spacing may be non-integer.
|
||||
if (StretchSpacing && LayoutColumnCount > 1)
|
||||
LayoutItemSpacing = floorf(avail_width - LayoutItemSize.x * LayoutColumnCount) / LayoutColumnCount;
|
||||
|
||||
if (UseScrollX)
|
||||
LayoutColumnCount *= 2;
|
||||
LayoutLineCount = (Items.Size + LayoutColumnCount - 1) / LayoutColumnCount;
|
||||
|
||||
LayoutItemStep = ImVec2(LayoutItemSize.x + LayoutItemSpacing, LayoutItemSize.y + LayoutItemSpacing);
|
||||
LayoutSelectableSpacing = IM_MAX(floorf(LayoutItemSpacing) - IconHitSpacing, 0.0f);
|
||||
LayoutOuterPadding = floorf(LayoutItemSpacing * 0.5f);
|
||||
@@ -10791,6 +10893,9 @@ struct ExampleAssetsBrowser
|
||||
|
||||
void Draw(const char* title, bool* p_open)
|
||||
{
|
||||
if (IconSize <= 0.0f)
|
||||
IconSize = ImGui::CalcTextSize("99999").x;
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(IconSize * 25, IconSize * 15), ImGuiCond_FirstUseEver);
|
||||
if (!ImGui::Begin(title, p_open, ImGuiWindowFlags_MenuBar))
|
||||
{
|
||||
@@ -10840,6 +10945,7 @@ struct ExampleAssetsBrowser
|
||||
ImGui::SliderInt("Icon Spacing", &IconSpacing, 0, 32);
|
||||
ImGui::SliderInt("Icon Hit Spacing", &IconHitSpacing, 0, 32);
|
||||
ImGui::Checkbox("Stretch Spacing", &StretchSpacing);
|
||||
ImGui::Checkbox("Use ScrollX", &UseScrollX);
|
||||
ImGui::PopItemWidth();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
@@ -10869,7 +10975,7 @@ struct ExampleAssetsBrowser
|
||||
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui::SetNextWindowContentSize(ImVec2(0.0f, LayoutOuterPadding + LayoutLineCount * (LayoutItemSize.y + LayoutItemSpacing)));
|
||||
if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove))
|
||||
if (ImGui::BeginChild("Assets", ImVec2(0.0f, -ImGui::GetTextLineHeightWithSpacing()), ImGuiChildFlags_Borders, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_HorizontalScrollbar))
|
||||
{
|
||||
ImDrawList* draw_list = ImGui::GetWindowDrawList();
|
||||
|
||||
@@ -11013,6 +11119,8 @@ struct ExampleAssetsBrowser
|
||||
}
|
||||
}
|
||||
clipper.End();
|
||||
if (Items.Size == 0)
|
||||
ImGui::Dummy(ImVec2(0, 0));
|
||||
ImGui::PopStyleVar(); // ImGuiStyleVar_ItemSpacing
|
||||
|
||||
// Context menu
|
||||
|
||||
Vendored
+106
-71
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (drawing and font code)
|
||||
|
||||
/*
|
||||
@@ -208,6 +208,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.41f, 0.41f, 0.41f, 1.00f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.51f, 0.51f, 0.51f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_CheckboxSelectedBg] = ImLerp(colors[ImGuiCol_FrameBg], colors[ImGuiCol_FrameBgHovered], 0.65f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.24f, 0.52f, 0.88f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
|
||||
@@ -275,6 +276,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.40f, 0.40f, 0.80f, 0.40f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.90f, 0.90f, 0.90f, 0.50f);
|
||||
colors[ImGuiCol_CheckboxSelectedBg] = ImLerp(colors[ImGuiCol_FrameBg], colors[ImGuiCol_FrameBgActive], 0.65f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.41f, 0.39f, 0.80f, 0.60f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.35f, 0.40f, 0.61f, 0.62f);
|
||||
@@ -343,6 +345,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
|
||||
colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.49f, 0.49f, 0.49f, 0.80f);
|
||||
colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.49f, 0.49f, 0.49f, 1.00f);
|
||||
colors[ImGuiCol_CheckMark] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
|
||||
colors[ImGuiCol_CheckboxSelectedBg] = ImVec4(0.95f, 0.97f, 1.00f, 1.00f);
|
||||
colors[ImGuiCol_SliderGrab] = ImVec4(0.26f, 0.59f, 0.98f, 0.78f);
|
||||
colors[ImGuiCol_SliderGrabActive] = ImVec4(0.46f, 0.54f, 0.80f, 0.60f);
|
||||
colors[ImGuiCol_Button] = ImVec4(0.26f, 0.59f, 0.98f, 0.40f);
|
||||
@@ -528,9 +531,14 @@ void ImDrawList::_PopUnusedDrawCmd()
|
||||
|
||||
void ImDrawList::AddCallback(ImDrawCallback callback, void* userdata, size_t userdata_size)
|
||||
{
|
||||
IM_ASSERT(callback != NULL);
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
if (callback == ImDrawCallback_ResetRenderState && _Data->Context != NULL && _Data->Context->PlatformIO.DrawCallback_ResetRenderState != NULL)
|
||||
callback = _Data->Context->PlatformIO.DrawCallback_ResetRenderState; // == ImGui::GetPlatformIO().DrawCallback_ResetRenderState
|
||||
#endif
|
||||
|
||||
IM_ASSERT_PARANOID(CmdBuffer.Size > 0);
|
||||
ImDrawCmd* curr_cmd = &CmdBuffer.Data[CmdBuffer.Size - 1];
|
||||
IM_ASSERT(callback != NULL);
|
||||
IM_ASSERT(curr_cmd->UserCallback == NULL);
|
||||
if (curr_cmd->ElemCount != 0)
|
||||
{
|
||||
@@ -662,7 +670,7 @@ void ImDrawList::PushClipRect(const ImVec2& cr_min, const ImVec2& cr_max, bool i
|
||||
if (intersect_with_current_clip_rect)
|
||||
{
|
||||
ImVec4 current = _CmdHeader.ClipRect;
|
||||
if (cr.x < current.x) cr.x = current.x;
|
||||
if (cr.x < current.x) cr.x = current.x; // = ClipWith(). Note that passing inverted range wouldn't be fixed here.
|
||||
if (cr.y < current.y) cr.y = current.y;
|
||||
if (cr.z > current.z) cr.z = current.z;
|
||||
if (cr.w > current.w) cr.w = current.w;
|
||||
@@ -806,7 +814,7 @@ void ImDrawList::PrimQuadUV(const ImVec2& a, const ImVec2& b, const ImVec2& c, c
|
||||
|
||||
// TODO: Thickness anti-aliased lines cap are missing their AA fringe.
|
||||
// We avoid using the ImVec2 math operators here to reduce cost to a minimum for debug/non-inlined builds.
|
||||
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, ImDrawFlags flags, float thickness)
|
||||
void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32 col, float thickness, ImDrawFlags flags)
|
||||
{
|
||||
if (points_count < 2 || (col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
@@ -815,6 +823,7 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
|
||||
const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
|
||||
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
|
||||
const bool thick_line = (thickness > _FringeScale);
|
||||
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?");
|
||||
|
||||
if (Flags & ImDrawListFlags_AntiAliasedLines)
|
||||
{
|
||||
@@ -1432,35 +1441,13 @@ void ImDrawList::PathBezierQuadraticCurveTo(const ImVec2& p2, const ImVec2& p3,
|
||||
}
|
||||
}
|
||||
|
||||
static inline ImDrawFlags FixRectCornerFlags(ImDrawFlags flags)
|
||||
{
|
||||
/*
|
||||
IM_STATIC_ASSERT(ImDrawFlags_RoundCornersTopLeft == (1 << 4));
|
||||
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
|
||||
// Obsoleted in 1.82 (from February 2021). This code was stripped/simplified and mostly commented in 1.90 (from September 2023)
|
||||
// - Legacy Support for hard coded ~0 (used to be a suggested equivalent to ImDrawCornerFlags_All)
|
||||
if (flags == ~0) { return ImDrawFlags_RoundCornersAll; }
|
||||
// - Legacy Support for hard coded 0x01 to 0x0F (matching 15 out of 16 old flags combinations). Read details in older version of this code.
|
||||
if (flags >= 0x01 && flags <= 0x0F) { return (flags << 4); }
|
||||
// We cannot support hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'
|
||||
#endif
|
||||
*/
|
||||
// If this assert triggers, please update your code replacing hardcoded values with new ImDrawFlags_RoundCorners* values.
|
||||
// Note that ImDrawFlags_Closed (== 0x01) is an invalid flag for AddRect(), AddRectFilled(), PathRect() etc. anyway.
|
||||
// See details in 1.82 Changelog as well as 2021/03/12 and 2023/09/08 entries in "API BREAKING CHANGES" section.
|
||||
IM_ASSERT((flags & 0x0F) == 0 && "Misuse of legacy hardcoded ImDrawCornerFlags values!");
|
||||
|
||||
if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
|
||||
flags |= ImDrawFlags_RoundCornersAll;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void ImDrawList::PathRect(const ImVec2& a, const ImVec2& b, float rounding, ImDrawFlags flags)
|
||||
{
|
||||
if (rounding >= 0.5f)
|
||||
{
|
||||
flags = FixRectCornerFlags(flags);
|
||||
if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
|
||||
flags |= ImDrawFlags_RoundCornersAll;
|
||||
|
||||
rounding = ImMin(rounding, ImFabs(b.x - a.x) * (((flags & ImDrawFlags_RoundCornersTop) == ImDrawFlags_RoundCornersTop) || ((flags & ImDrawFlags_RoundCornersBottom) == ImDrawFlags_RoundCornersBottom) ? 0.5f : 1.0f) - 1.0f);
|
||||
rounding = ImMin(rounding, ImFabs(b.y - a.y) * (((flags & ImDrawFlags_RoundCornersLeft) == ImDrawFlags_RoundCornersLeft) || ((flags & ImDrawFlags_RoundCornersRight) == ImDrawFlags_RoundCornersRight) ? 0.5f : 1.0f) - 1.0f);
|
||||
}
|
||||
@@ -1490,20 +1477,48 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th
|
||||
return;
|
||||
PathLineTo(p1 + ImVec2(0.5f, 0.5f));
|
||||
PathLineTo(p2 + ImVec2(0.5f, 0.5f));
|
||||
PathStroke(col, 0, thickness);
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
PathLineTo(ImVec2(min_x + 0.5f, y + 0.5f)); // Same as AddLine() above.
|
||||
PathLineTo(ImVec2(max_x + 0.5f, y + 0.5f));
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness)
|
||||
{
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
PathLineTo(ImVec2(x + 0.5f, min_y + 0.5f)); // Same as AddLine() above.
|
||||
PathLineTo(ImVec2(x + 0.5f, max_y + 0.5f));
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
// p_min = upper-left, p_max = lower-right
|
||||
// Note we don't render 1 pixels sized rectangles properly.
|
||||
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags, float thickness)
|
||||
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, float thickness, ImDrawFlags flags)
|
||||
{
|
||||
// If this assert triggers on legacy code:
|
||||
// - 1.92.8 (2025/04): swapped two last parameters order: flags, thickness --> thickness, flags. This should normally be caught by compile-time type-checking.
|
||||
// - 1.82.0 (2021/03): changed ImDrawCornerFlags to ImDrawFlags_RoundCornersXXX values.
|
||||
// If you used hard-coded 1 to 15 or ~0 in flags to configure corner rounding use the new flags!
|
||||
// - Hard coded support for ~0 == ImDrawFlags_RoundCornersAll.
|
||||
// - Hard coded support for values 0x01 to 0x0F (matching 15 out of 16 old flags combinations) --> see FixRectCornerFlags() in <1.90 code.
|
||||
// - Hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'.
|
||||
// See "API BREAKING CHANGES" section for 1.82 and 1.90.
|
||||
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?"); // Or misuse of legacy hard-coded ImDrawCornerFlags values
|
||||
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
if (Flags & ImDrawListFlags_AntiAliasedLines)
|
||||
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.50f, 0.50f), rounding, flags);
|
||||
else
|
||||
PathRect(p_min + ImVec2(0.50f, 0.50f), p_max - ImVec2(0.49f, 0.49f), rounding, flags); // Better looking lower-right corner and rounded non-AA shapes.
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddRectFilled(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, ImDrawFlags flags)
|
||||
@@ -1547,7 +1562,7 @@ void ImDrawList::AddQuad(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, c
|
||||
PathLineTo(p2);
|
||||
PathLineTo(p3);
|
||||
PathLineTo(p4);
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddQuadFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const ImVec2& p4, ImU32 col)
|
||||
@@ -1570,7 +1585,7 @@ void ImDrawList::AddTriangle(const ImVec2& p1, const ImVec2& p2, const ImVec2& p
|
||||
PathLineTo(p1);
|
||||
PathLineTo(p2);
|
||||
PathLineTo(p3);
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddTriangleFilled(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, ImU32 col)
|
||||
@@ -1605,7 +1620,7 @@ void ImDrawList::AddCircle(const ImVec2& center, float radius, ImU32 col, int nu
|
||||
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
|
||||
}
|
||||
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddCircleFilled(const ImVec2& center, float radius, ImU32 col, int num_segments)
|
||||
@@ -1641,7 +1656,7 @@ void ImDrawList::AddNgon(const ImVec2& center, float radius, ImU32 col, int num_
|
||||
// Because we are filling a closed shape we remove 1 from the count of segments/points
|
||||
const float a_max = (IM_PI * 2.0f) * ((float)num_segments - 1.0f) / (float)num_segments;
|
||||
PathArcTo(center, radius - 0.5f, 0.0f, a_max, num_segments - 1);
|
||||
PathStroke(col, ImDrawFlags_Closed, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
// Guaranteed to honor 'num_segments'
|
||||
@@ -1668,7 +1683,7 @@ void ImDrawList::AddEllipse(const ImVec2& center, const ImVec2& radius, ImU32 co
|
||||
// Because we are filling a closed shape we remove 1 from the count of segments/points
|
||||
const float a_max = IM_PI * 2.0f * ((float)num_segments - 1.0f) / (float)num_segments;
|
||||
PathEllipticalArcTo(center, radius, rot, 0.0f, a_max, num_segments - 1);
|
||||
PathStroke(col, true, thickness);
|
||||
PathStroke(col, thickness, ImDrawFlags_Closed);
|
||||
}
|
||||
|
||||
void ImDrawList::AddEllipseFilled(const ImVec2& center, const ImVec2& radius, ImU32 col, float rot, int num_segments)
|
||||
@@ -1693,7 +1708,7 @@ void ImDrawList::AddBezierCubic(const ImVec2& p1, const ImVec2& p2, const ImVec2
|
||||
|
||||
PathLineTo(p1);
|
||||
PathBezierCubicCurveTo(p2, p3, p4, num_segments);
|
||||
PathStroke(col, 0, thickness);
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
// Quadratic Bezier takes 3 controls points
|
||||
@@ -1704,7 +1719,7 @@ void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const Im
|
||||
|
||||
PathLineTo(p1);
|
||||
PathBezierQuadraticCurveTo(p2, p3, num_segments);
|
||||
PathStroke(col, 0, thickness);
|
||||
PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect)
|
||||
@@ -1776,7 +1791,10 @@ void ImDrawList::AddImageRounded(ImTextureRef tex_ref, const ImVec2& p_min, cons
|
||||
if ((col & IM_COL32_A_MASK) == 0)
|
||||
return;
|
||||
|
||||
flags = FixRectCornerFlags(flags);
|
||||
IM_ASSERT((flags & 0x0F) == 0 && "Misuse of legacy hardcoded ImDrawCornerFlags values!"); // If this assert triggers on legacy code: see comments in ImDrawList::PathRect().
|
||||
if ((flags & ImDrawFlags_RoundCornersMask_) == 0)
|
||||
flags |= ImDrawFlags_RoundCornersAll;
|
||||
|
||||
if (rounding < 0.5f || (flags & ImDrawFlags_RoundCornersMask_) == ImDrawFlags_RoundCornersNone)
|
||||
{
|
||||
AddImage(tex_ref, p_min, p_max, uv_min, uv_max, col);
|
||||
@@ -2502,10 +2520,11 @@ void ImTextureData::DestroyPixels()
|
||||
// - Default texture data encoded in ASCII
|
||||
// - ImFontAtlas()
|
||||
// - ImFontAtlas::Clear()
|
||||
// - ImFontAtlas::CompactCache()
|
||||
// - ImFontAtlas::ClearFonts()
|
||||
// - ImFontAtlas::ClearInputData()
|
||||
// - ImFontAtlas::ClearTexData()
|
||||
// - ImFontAtlas::ClearFonts()
|
||||
// - ImFontAtlas::CompactCache()
|
||||
// - ImFontAtlas::SetFontLoader()
|
||||
//-----------------------------------------------------------------------------
|
||||
// - ImFontAtlasUpdateNewFrame()
|
||||
// - ImFontAtlasTextureBlockConvert()
|
||||
@@ -2666,7 +2685,9 @@ ImFontAtlas::~ImFontAtlas()
|
||||
TexData = NULL;
|
||||
}
|
||||
|
||||
// If you call this mid-frame, you would need to add new font and bind them!
|
||||
// You probably should not call this directly. It is not well specified.
|
||||
// If you want to replace all your fonts mid-frame, most likely you should instead call ClearFonts() then load the new fonts.
|
||||
// Calling this mid-frame will discard the CPU-side copy of the texture data which is generally unreliable as you may have textures queued for creation or updates.
|
||||
void ImFontAtlas::Clear()
|
||||
{
|
||||
bool backup_renderer_has_textures = RendererHasTextures;
|
||||
@@ -2676,20 +2697,27 @@ void ImFontAtlas::Clear()
|
||||
RendererHasTextures = backup_renderer_has_textures;
|
||||
}
|
||||
|
||||
void ImFontAtlas::CompactCache()
|
||||
void ImFontAtlas::ClearFonts()
|
||||
{
|
||||
ImFontAtlasTextureCompact(this);
|
||||
}
|
||||
|
||||
void ImFontAtlas::SetFontLoader(const ImFontLoader* font_loader)
|
||||
{
|
||||
ImFontAtlasBuildSetupFontLoader(this, font_loader);
|
||||
// FIXME-NEWATLAS: Illegal to remove currently bound font.
|
||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
||||
for (ImFont* font : Fonts)
|
||||
ImFontAtlasBuildNotifySetFont(this, font, NULL);
|
||||
ImFontAtlasBuildDestroy(this);
|
||||
ClearInputData();
|
||||
Fonts.clear_delete();
|
||||
TexIsBuilt = false;
|
||||
for (ImDrawListSharedData* shared_data : DrawListSharedDatas)
|
||||
if (shared_data->FontAtlas == this)
|
||||
{
|
||||
shared_data->Font = NULL;
|
||||
shared_data->FontScale = shared_data->FontSize = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void ImFontAtlas::ClearInputData()
|
||||
{
|
||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
||||
|
||||
for (ImFont* font : Fonts)
|
||||
ImFontAtlasFontDestroyOutput(this, font);
|
||||
for (ImFontConfig& font_cfg : Sources)
|
||||
@@ -2713,22 +2741,14 @@ void ImFontAtlas::ClearTexData()
|
||||
//Locked = true; // Hoped to be able to lock this down but some reload patterns may not be happy with it.
|
||||
}
|
||||
|
||||
void ImFontAtlas::ClearFonts()
|
||||
void ImFontAtlas::CompactCache()
|
||||
{
|
||||
// FIXME-NEWATLAS: Illegal to remove currently bound font.
|
||||
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
|
||||
for (ImFont* font : Fonts)
|
||||
ImFontAtlasBuildNotifySetFont(this, font, NULL);
|
||||
ImFontAtlasBuildDestroy(this);
|
||||
ClearInputData();
|
||||
Fonts.clear_delete();
|
||||
TexIsBuilt = false;
|
||||
for (ImDrawListSharedData* shared_data : DrawListSharedDatas)
|
||||
if (shared_data->FontAtlas == this)
|
||||
{
|
||||
shared_data->Font = NULL;
|
||||
shared_data->FontScale = shared_data->FontSize = 0.0f;
|
||||
}
|
||||
ImFontAtlasTextureCompact(this);
|
||||
}
|
||||
|
||||
void ImFontAtlas::SetFontLoader(const ImFontLoader* font_loader)
|
||||
{
|
||||
ImFontAtlasBuildSetupFontLoader(this, font_loader);
|
||||
}
|
||||
|
||||
static void ImFontAtlasBuildUpdateRendererHasTexturesFromContext(ImFontAtlas* atlas)
|
||||
@@ -2962,12 +2982,17 @@ void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, I
|
||||
memcpy(dst_tex->GetPixelsAt(dst_x, dst_y + y), src_tex->GetPixelsAt(src_x, src_y + y), w * dst_tex->BytesPerPixel);
|
||||
}
|
||||
|
||||
// Queue texture block update for renderer backend
|
||||
void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h)
|
||||
{
|
||||
ImTextureDataQueueUpload(tex, x, y, w, h);
|
||||
atlas->TexIsBuilt = false;
|
||||
}
|
||||
|
||||
// Queue texture block update for renderer backend
|
||||
void ImTextureDataQueueUpload(ImTextureData* tex, int x, int y, int w, int h)
|
||||
{
|
||||
IM_ASSERT(tex->Status != ImTextureStatus_WantDestroy && tex->Status != ImTextureStatus_Destroyed);
|
||||
IM_ASSERT(x >= 0 && x <= 0xFFFF && y >= 0 && y <= 0xFFFF && w >= 0 && x + w <= 0x10000 && h >= 0 && y + h <= 0x10000);
|
||||
IM_UNUSED(atlas);
|
||||
|
||||
ImTextureRect req = { (unsigned short)x, (unsigned short)y, (unsigned short)w, (unsigned short)h };
|
||||
int new_x1 = ImMax(tex->UpdateRect.w == 0 ? 0 : tex->UpdateRect.x + tex->UpdateRect.w, req.x + req.w);
|
||||
@@ -2980,7 +3005,6 @@ void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex,
|
||||
tex->UsedRect.y = ImMin(tex->UsedRect.y, req.y);
|
||||
tex->UsedRect.w = (unsigned short)(ImMax(tex->UsedRect.x + tex->UsedRect.w, req.x + req.w) - tex->UsedRect.x);
|
||||
tex->UsedRect.h = (unsigned short)(ImMax(tex->UsedRect.y + tex->UsedRect.h, req.y + req.h) - tex->UsedRect.y);
|
||||
atlas->TexIsBuilt = false;
|
||||
|
||||
// No need to queue if status is == ImTextureStatus_WantCreate
|
||||
if (tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantUpdates)
|
||||
@@ -3052,7 +3076,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in)
|
||||
}
|
||||
else
|
||||
{
|
||||
IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font"); // When using MergeMode make sure that a font has already been added before.
|
||||
IM_ASSERT(Fonts.Size > 0 && "Cannot use MergeMode for the first font!"); // When using MergeMode make sure that a font has already been added before.
|
||||
font = font_cfg_in->DstFont ? font_cfg_in->DstFont : Fonts.back();
|
||||
ImFontAtlasFontDiscardBakes(this, font, 0); // Need to discard bakes if the font was already used, because baked->FontLoaderDatas[] will change size. (#9162)
|
||||
}
|
||||
@@ -3080,6 +3104,11 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in)
|
||||
IM_ASSERT(font_cfg->FontLoader->FontBakedLoadGlyph != NULL);
|
||||
IM_ASSERT(font_cfg->FontLoader->LoaderInit == NULL && font_cfg->FontLoader->LoaderShutdown == NULL); // FIXME-NEWATLAS: Unsupported yet.
|
||||
}
|
||||
// | Target w/ Implicit RefSize | Target w/ Explicit RefSize |
|
||||
// Adding w/ Implicit RefSize: | OK (same scale) | OK (same scale) |
|
||||
// Adding w/ Explicit RefSize: | KO | OK (custom scale) |
|
||||
if (font_cfg_in->MergeMode && font_cfg_in->SizePixels > 0)
|
||||
IM_ASSERT((font->Flags & ImFontFlags_ImplicitRefSize) == 0 && "Cannot use MergeMode with an explicit reference size when the destination font used an implicit reference size!");
|
||||
IM_ASSERT(font_cfg->FontLoaderData == NULL);
|
||||
|
||||
if (!ImFontAtlasFontSourceInit(this, font_cfg))
|
||||
@@ -3147,7 +3176,10 @@ ImFont* ImFontAtlas::AddFontDefaultBitmap(const ImFontConfig* font_cfg_template)
|
||||
if (!font_cfg_template)
|
||||
font_cfg.PixelSnapH = true; // Prevents sub-integer scaling factors at lower-level layers.
|
||||
if (font_cfg.SizePixels <= 0.0f)
|
||||
{
|
||||
font_cfg.SizePixels = 13.0f; // This only serves (1) as a reference for GlyphOffset.y setting and (2) as a default for pre-1.92 backend.
|
||||
font_cfg.Flags |= ImFontFlags_ImplicitRefSize;
|
||||
}
|
||||
if (font_cfg.Name[0] == '\0')
|
||||
ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "ProggyClean.ttf");
|
||||
font_cfg.EllipsisChar = (ImWchar)0x0085;
|
||||
@@ -3172,7 +3204,10 @@ ImFont* ImFontAtlas::AddFontDefaultVector(const ImFontConfig* font_cfg_template)
|
||||
if (!font_cfg_template)
|
||||
font_cfg.PixelSnapH = true; // Precisely match ProggyClean, but prevents sub-integer scaling factors at lower-level layers.
|
||||
if (font_cfg.SizePixels <= 0.0f)
|
||||
{
|
||||
font_cfg.SizePixels = 13.0f;
|
||||
font_cfg.Flags |= ImFontFlags_ImplicitRefSize;
|
||||
}
|
||||
if (font_cfg.Name[0] == '\0')
|
||||
ImFormatString(font_cfg.Name, IM_COUNTOF(font_cfg.Name), "ProggyForever.ttf");
|
||||
font_cfg.ExtraSizeScale *= 1.015f; // Match ProggyClean
|
||||
@@ -6016,7 +6051,7 @@ void ImGui::RenderCheckMark(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float
|
||||
draw_list->PathLineTo(ImVec2(bx - third, by - third));
|
||||
draw_list->PathLineTo(ImVec2(bx, by));
|
||||
draw_list->PathLineTo(ImVec2(bx + third * 2.0f, by - third * 2.0f));
|
||||
draw_list->PathStroke(col, 0, thickness);
|
||||
draw_list->PathStroke(col, thickness);
|
||||
}
|
||||
|
||||
// Render an arrow. 'pos' is position of the arrow tip. half_sz.x is length from base to tip. half_sz.y is length on each side.
|
||||
|
||||
+24
-13
@@ -95,6 +95,10 @@ static void* (*GImGuiFreeTypeAllocFunc)(size_t size, void* user_data) = ImGuiFre
|
||||
static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc;
|
||||
static void* GImGuiFreeTypeAllocatorUserData = nullptr;
|
||||
|
||||
// Load struct
|
||||
static ImFontLoader GImGuiFreeTypeLoader;
|
||||
static char GImGuiFreeTypeLoaderName[48] = "FreeType";
|
||||
|
||||
// Lunasvg support
|
||||
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
static FT_Error ImGuiLunasvgPortInit(FT_Pointer* state);
|
||||
@@ -146,6 +150,7 @@ struct ImGui_ImplFreeType_Data
|
||||
{
|
||||
FT_Library Library;
|
||||
FT_MemoryRec_ MemoryManager;
|
||||
char BackendName[48];
|
||||
ImGui_ImplFreeType_Data() { memset((void*)this, 0, sizeof(*this)); }
|
||||
};
|
||||
|
||||
@@ -359,6 +364,11 @@ static bool ImGui_ImplFreeType_LoaderInit(ImFontAtlas* atlas)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update ImFontLoader::Name field with linked version
|
||||
FT_Int ver_linked_major, ver_linked_minor, ver_linked_patch;
|
||||
FT_Library_Version(bd->Library, &ver_linked_major, &ver_linked_minor, &ver_linked_patch);
|
||||
snprintf(GImGuiFreeTypeLoaderName, sizeof(GImGuiFreeTypeLoaderName), "FreeType (%d.%d.%d; %d.%d.%d)", FREETYPE_MAJOR, FREETYPE_MINOR, FREETYPE_PATCH, ver_linked_major, ver_linked_minor, ver_linked_patch);
|
||||
|
||||
// If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator.
|
||||
FT_Add_Default_Modules(bd->Library);
|
||||
|
||||
@@ -418,8 +428,9 @@ static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* s
|
||||
{
|
||||
IM_UNUSED(atlas);
|
||||
float size = baked->Size;
|
||||
const float ref_size = baked->OwnerFont->Sources[0]->SizePixels;
|
||||
if (src->MergeMode && src->SizePixels != 0.0f)
|
||||
size *= (src->SizePixels / baked->OwnerFont->Sources[0]->SizePixels);
|
||||
size *= (src->SizePixels / ref_size);
|
||||
size *= src->ExtraSizeScale;
|
||||
|
||||
ImGui_ImplFreeType_FontSrcData* bd_font_data = (ImGui_ImplFreeType_FontSrcData*)src->FontLoaderData;
|
||||
@@ -569,18 +580,18 @@ static bool ImGui_ImplFreetype_FontSrcContainsGlyph(ImFontAtlas* atlas, ImFontCo
|
||||
|
||||
const ImFontLoader* ImGuiFreeType::GetFontLoader()
|
||||
{
|
||||
static ImFontLoader loader;
|
||||
loader.Name = "FreeType";
|
||||
loader.LoaderInit = ImGui_ImplFreeType_LoaderInit;
|
||||
loader.LoaderShutdown = ImGui_ImplFreeType_LoaderShutdown;
|
||||
loader.FontSrcInit = ImGui_ImplFreeType_FontSrcInit;
|
||||
loader.FontSrcDestroy = ImGui_ImplFreeType_FontSrcDestroy;
|
||||
loader.FontSrcContainsGlyph = ImGui_ImplFreetype_FontSrcContainsGlyph;
|
||||
loader.FontBakedInit = ImGui_ImplFreeType_FontBakedInit;
|
||||
loader.FontBakedDestroy = ImGui_ImplFreeType_FontBakedDestroy;
|
||||
loader.FontBakedLoadGlyph = ImGui_ImplFreeType_FontBakedLoadGlyph;
|
||||
loader.FontBakedSrcLoaderDataSize = sizeof(ImGui_ImplFreeType_FontSrcBakedData);
|
||||
return &loader;
|
||||
ImFontLoader* loader = &GImGuiFreeTypeLoader;
|
||||
loader->Name = GImGuiFreeTypeLoaderName; // Initially "FreeType" then updated during the call to ImGui_ImplFreeType_LoaderInit()
|
||||
loader->LoaderInit = ImGui_ImplFreeType_LoaderInit;
|
||||
loader->LoaderShutdown = ImGui_ImplFreeType_LoaderShutdown;
|
||||
loader->FontSrcInit = ImGui_ImplFreeType_FontSrcInit;
|
||||
loader->FontSrcDestroy = ImGui_ImplFreeType_FontSrcDestroy;
|
||||
loader->FontSrcContainsGlyph = ImGui_ImplFreetype_FontSrcContainsGlyph;
|
||||
loader->FontBakedInit = ImGui_ImplFreeType_FontBakedInit;
|
||||
loader->FontBakedDestroy = ImGui_ImplFreeType_FontBakedDestroy;
|
||||
loader->FontBakedLoadGlyph = ImGui_ImplFreeType_FontBakedLoadGlyph;
|
||||
loader->FontBakedSrcLoaderDataSize = sizeof(ImGui_ImplFreeType_FontSrcBakedData);
|
||||
return loader;
|
||||
}
|
||||
|
||||
void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data)
|
||||
|
||||
Vendored
+50
-27
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (tables and columns code)
|
||||
|
||||
/*
|
||||
@@ -240,6 +240,7 @@ Index of this file:
|
||||
#pragma GCC diagnostic ignored "-Wformat" // warning: format '%p' expects argument of type 'int'/'void*', but argument X has type 'unsigned int'/'ImGuiWindow*'
|
||||
#pragma GCC diagnostic ignored "-Wstrict-overflow"
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
|
||||
#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may change value
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion" // warning: conversion to 'xxxx' from 'xxxx' may change the sign of the result
|
||||
#endif
|
||||
|
||||
@@ -1315,14 +1316,32 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
|
||||
table->InnerWindow->DecoInnerSizeY1 = table_instance->LastFrozenHeight;
|
||||
table_instance->LastFrozenHeight = 0.0f;
|
||||
|
||||
// Initial state
|
||||
ImGuiWindow* inner_window = table->InnerWindow;
|
||||
ImGuiBoxSelectState* bs = &g.BoxSelectState;
|
||||
if (bs->Window == inner_window && bs->UnclipMode)
|
||||
TableApplyExternalUnclipRect(table, bs->UnclipRect);
|
||||
|
||||
// Initial state
|
||||
if (table->Flags & ImGuiTableFlags_NoClip)
|
||||
table->DrawSplitter->SetCurrentChannel(inner_window->DrawList, TABLE_DRAW_CHANNEL_NOCLIP);
|
||||
else
|
||||
inner_window->DrawList->PushClipRect(inner_window->InnerClipRect.Min, inner_window->InnerClipRect.Max, false); // FIXME: use table->InnerClipRect?
|
||||
}
|
||||
|
||||
// When starting a BeginMultiSelect() after table has been layout we update IsRequestOutput fields.
|
||||
void ImGui::TableApplyExternalUnclipRect(ImGuiTable* table, ImRect& rect)
|
||||
{
|
||||
if (rect.IsInverted())
|
||||
return;
|
||||
for (int column_n = 0; column_n < table->ColumnsCount; column_n++)
|
||||
{
|
||||
ImGuiTableColumn* column = &table->Columns[column_n];
|
||||
if (!column->IsRequestOutput)
|
||||
if (rect.Overlaps(ImRect(column->MinX, table->WorkRect.Min.y, column->MaxX, FLT_MAX)))
|
||||
column->IsRequestOutput = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process hit-testing on resizing borders. Actual size change will be applied in EndTable()
|
||||
// - Set table->HoveredColumnBorder with a short delay/timer to reduce visual feedback noise.
|
||||
void ImGui::TableUpdateBorders(ImGuiTable* table)
|
||||
@@ -1436,12 +1455,12 @@ void ImGui::EndTable()
|
||||
if (table->Flags & ImGuiTableFlags_ScrollX)
|
||||
{
|
||||
const float outer_padding_for_border = (table->Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f;
|
||||
float max_pos_x = table->InnerWindow->DC.CursorMaxPos.x;
|
||||
float max_pos_x = inner_window->DC.CursorMaxPos.x;
|
||||
if (table->RightMostEnabledColumn != -1)
|
||||
max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border);
|
||||
if (table->ResizedColumn != -1)
|
||||
max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2);
|
||||
table->InnerWindow->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledHeadersExtraWidth;
|
||||
inner_window->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledHeadersExtraWidth;
|
||||
}
|
||||
|
||||
// Pop clipping rect
|
||||
@@ -1550,7 +1569,7 @@ void ImGui::EndTable()
|
||||
}
|
||||
else
|
||||
{
|
||||
table->InnerWindow->DC.TreeDepth--;
|
||||
inner_window->DC.TreeDepth--;
|
||||
ItemSize(table->OuterRect.GetSize());
|
||||
ItemAdd(table->OuterRect, 0);
|
||||
}
|
||||
@@ -1565,13 +1584,12 @@ void ImGui::EndTable()
|
||||
}
|
||||
else if (temp_data->UserOuterSize.x <= 0.0f)
|
||||
{
|
||||
// Some references for this: #7651 + tests "table_reported_size", "table_reported_size_outer" equivalent Y block
|
||||
// - Checking for ImGuiTableFlags_ScrollX/ScrollY flag makes us a frame ahead when disabling those flags.
|
||||
// - FIXME-TABLE: Would make sense to pre-compute expected scrollbar visibility/sizes to generally save a frame of feedback.
|
||||
const float inner_content_max_x = table->OuterRect.Min.x + table->ColumnsAutoFitWidth; // Slightly misleading name but used for code symmetry with inner_content_max_y
|
||||
const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((table->Flags & ImGuiTableFlags_ScrollY) ? inner_window->ScrollbarSizes.x : 0.0f);
|
||||
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, inner_content_max_x + decoration_size - temp_data->UserOuterSize.x);
|
||||
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, inner_content_max_x + decoration_size));
|
||||
// Some references for this: #7651 + tests "table_reported_size", "table_reported_size_outer" equivalent Y block, #9352
|
||||
// - FIXME-TABLE: Would make sense to pre-compute expected scrollbar visibility/sizes to generally save a frame of feedback? See broken test in 'table_reported_size_outer'
|
||||
const float outer_content_max_x = table->OuterRect.Min.x + table->ColumnsAutoFitWidth;
|
||||
const float decoration_size = table->TempData->AngledHeadersExtraWidth + ((inner_window != outer_window) ? inner_window->ScrollbarSizes.x : 0.0f);
|
||||
outer_window->DC.IdealMaxPos.x = ImMax(outer_window->DC.IdealMaxPos.x, outer_content_max_x + decoration_size - temp_data->UserOuterSize.x);
|
||||
outer_window->DC.CursorMaxPos.x = ImMax(backup_outer_max_pos.x, ImMin(table->OuterRect.Max.x, outer_content_max_x + decoration_size));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1579,9 +1597,12 @@ void ImGui::EndTable()
|
||||
}
|
||||
if (temp_data->UserOuterSize.y <= 0.0f)
|
||||
{
|
||||
const float decoration_size = (table->Flags & ImGuiTableFlags_ScrollX) ? inner_window->ScrollbarSizes.y : 0.0f;
|
||||
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, inner_content_max_y + decoration_size - temp_data->UserOuterSize.y);
|
||||
outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, inner_content_max_y + decoration_size));
|
||||
// (same comment as above)
|
||||
const float outer_content_size_y = (inner_window == outer_window) ? (inner_content_max_y - table->InnerRect.Min.y) : (inner_content_max_y - inner_window->DC.CursorStartPos.y);
|
||||
const float outer_content_max_y = table->OuterRect.Min.y + outer_content_size_y;
|
||||
const float decoration_size = (inner_window != outer_window ? inner_window->ScrollbarSizes.y : 0.0f);
|
||||
outer_window->DC.IdealMaxPos.y = ImMax(outer_window->DC.IdealMaxPos.y, outer_content_max_y + decoration_size - temp_data->UserOuterSize.y);
|
||||
outer_window->DC.CursorMaxPos.y = ImMax(backup_outer_max_pos.y, ImMin(table->OuterRect.Max.y, outer_content_max_y + decoration_size));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1641,7 +1662,7 @@ void ImGui::TableSetupColumn(const char* label, ImGuiTableColumnFlags flags, flo
|
||||
ImGuiTable* table = g.CurrentTable;
|
||||
IM_ASSERT_USER_ERROR_RET(table != NULL, "Call should only be done while in BeginTable() scope!");
|
||||
IM_ASSERT_USER_ERROR_RET(table->DeclColumnsCount < table->ColumnsCount, "TableSetupColumn(): called too many times!");
|
||||
IM_ASSERT_USER_ERROR_RET(table->IsLayoutLocked == false, "TableSetupColumn(): need to call before first row!");
|
||||
IM_ASSERT_USER_ERROR_RET(table->IsLayoutLocked == false, "TableSetupColumn(): need to call before first row!"); // Table layout is locked when submitting a row or when calling BeginMultiSelect() with box-select.
|
||||
IM_ASSERT((flags & ImGuiTableColumnFlags_StatusMask_) == 0 && "Illegal to pass StatusMask values to TableSetupColumn()");
|
||||
|
||||
ImGuiTableColumn* column = &table->Columns[table->DeclColumnsCount];
|
||||
@@ -2053,11 +2074,11 @@ void ImGui::TableEndRow(ImGuiTable* table)
|
||||
|
||||
// Draw top border
|
||||
if (top_border_col && bg_y1 >= table->BgClipRect.Min.y && bg_y1 < table->BgClipRect.Max.y)
|
||||
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y1), ImVec2(table->BorderX2, bg_y1), top_border_col, border_size);
|
||||
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y1, top_border_col, border_size);
|
||||
|
||||
// Draw bottom border at the row unfreezing mark (always strong)
|
||||
if (draw_strong_bottom_border && bg_y2 >= table->BgClipRect.Min.y && bg_y2 < table->BgClipRect.Max.y)
|
||||
window->DrawList->AddLine(ImVec2(table->BorderX1, bg_y2), ImVec2(table->BorderX2, bg_y2), table->BorderColorStrong, border_size);
|
||||
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y2, table->BorderColorStrong, border_size);
|
||||
}
|
||||
|
||||
// End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle)
|
||||
@@ -2834,7 +2855,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
else if ((table->Flags & (ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_NoBordersInBody)) == 0)
|
||||
draw_y2 = draw_y2_body;
|
||||
if (draw_y2 > draw_y1)
|
||||
inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), TableGetColumnBorderCol(table, order_n, column_n), border_size);
|
||||
inner_drawlist->AddLineV(column->MaxX, draw_y1, draw_y2, TableGetColumnBorderCol(table, order_n, column_n), border_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2851,17 +2872,17 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
const ImU32 outer_col = table->BorderColorStrong;
|
||||
if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
|
||||
{
|
||||
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, 0, border_size);
|
||||
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, border_size);
|
||||
}
|
||||
else if (table->Flags & ImGuiTableFlags_BordersOuterV)
|
||||
{
|
||||
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Min.x, outer_border.Max.y), outer_col, border_size);
|
||||
inner_drawlist->AddLine(ImVec2(outer_border.Max.x, outer_border.Min.y), outer_border.Max, outer_col, border_size);
|
||||
inner_drawlist->AddLineV(outer_border.Min.x, outer_border.Min.y, outer_border.Max.y, outer_col, border_size);
|
||||
inner_drawlist->AddLineV(outer_border.Max.x, outer_border.Min.y, outer_border.Max.y, outer_col, border_size);
|
||||
}
|
||||
else if (table->Flags & ImGuiTableFlags_BordersOuterH)
|
||||
{
|
||||
inner_drawlist->AddLine(outer_border.Min, ImVec2(outer_border.Max.x, outer_border.Min.y), outer_col, border_size);
|
||||
inner_drawlist->AddLine(ImVec2(outer_border.Min.x, outer_border.Max.y), outer_border.Max, outer_col, border_size);
|
||||
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Min.y, outer_col, border_size);
|
||||
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Max.y, outer_col, border_size);
|
||||
}
|
||||
}
|
||||
if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y)
|
||||
@@ -2869,7 +2890,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
|
||||
// Draw bottom-most row border between it is above outer border.
|
||||
const float border_y = table->RowPosY2;
|
||||
if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
|
||||
inner_drawlist->AddLine(ImVec2(table->BorderX1, border_y), ImVec2(table->BorderX2, border_y), table->BorderColorLight, border_size);
|
||||
inner_drawlist->AddLineH(table->BorderX1, table->BorderX2, border_y, table->BorderColorLight, border_size);
|
||||
}
|
||||
|
||||
inner_drawlist->PopClipRect();
|
||||
@@ -3174,7 +3195,7 @@ void ImGui::TableHeader(const char* label)
|
||||
if (label == NULL)
|
||||
label = "";
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, true);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
ImVec2 label_pos = window->DC.CursorPos;
|
||||
|
||||
// If we already got a row height, there's use that.
|
||||
@@ -3293,6 +3314,8 @@ void ImGui::TableHeader(const char* label)
|
||||
// We don't use BeginPopupContextItem() because we want the popup to stay up even after the column is hidden
|
||||
if (IsPopupOpenRequestForItem(ImGuiPopupFlags_None, id))
|
||||
TableOpenContextMenu(column_n);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
}
|
||||
|
||||
// Unlike TableHeadersRow() it is not expected that you can reimplement or customize this with custom widgets.
|
||||
@@ -4595,7 +4618,7 @@ void ImGui::EndColumns()
|
||||
// Draw column
|
||||
const ImU32 col = GetColorU32(held ? ImGuiCol_SeparatorActive : hovered ? ImGuiCol_SeparatorHovered : ImGuiCol_Separator);
|
||||
const float xi = IM_TRUNC(x);
|
||||
window->DrawList->AddLine(ImVec2(xi, y1 + 1.0f), ImVec2(xi, y2), col);
|
||||
window->DrawList->AddLineV(xi, y1 + 1.0f, y2, col);
|
||||
}
|
||||
|
||||
// Apply dragging after drawing the column lines, so our rendered lines are in sync with how items were displayed during the frame.
|
||||
|
||||
Vendored
+256
-104
@@ -1,4 +1,4 @@
|
||||
// dear imgui, v1.92.7
|
||||
// dear imgui, v1.92.8
|
||||
// (widgets code)
|
||||
|
||||
/*
|
||||
@@ -92,6 +92,7 @@ Index of this file:
|
||||
#pragma GCC diagnostic ignored "-Wstrict-overflow" // warning: assuming signed overflow does not occur when simplifying division / ..when changing X +- C1 cmp C2 to X cmp C2 -+ C1
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess" // [__GNUC__ >= 8] warning: 'memset/memcpy' clearing/writing an object of type 'xxxx' with no trivial copy-assignment; use assignment or value-initialization instead
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual" // warning: cast from type 'const xxxx *' to type 'xxxx *' casts away qualifiers
|
||||
#pragma GCC diagnostic ignored "-Wconversion" // warning: conversion to 'xxxx' from 'xxxx' may change value
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion" // warning: conversion to 'xxxx' from 'xxxx' may change the sign of the result
|
||||
#endif
|
||||
|
||||
@@ -401,7 +402,8 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
|
||||
const char* value_text_begin, *value_text_end;
|
||||
ImFormatStringToTempBufferV(&value_text_begin, &value_text_end, fmt, args);
|
||||
const ImVec2 value_size = CalcTextSize(value_text_begin, value_text_end, false);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
const ImRect value_bb(pos, pos + ImVec2(w, value_size.y + style.FramePadding.y * 2));
|
||||
@@ -413,7 +415,7 @@ void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
|
||||
// Render
|
||||
RenderTextClipped(value_bb.Min + style.FramePadding, value_bb.Max, value_text_begin, value_text_end, &value_size, ImVec2(0.0f, 0.0f));
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
}
|
||||
|
||||
void ImGui::BulletText(const char* fmt, ...)
|
||||
@@ -788,7 +790,8 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
if ((flags & ImGuiButtonFlags_AlignTextBaseLine) && style.FramePadding.y < window->DC.CurrLineTextBaseOffset) // Try to vertically align buttons that are smaller/have no padding so that text baseline matches (bit hacky, since it shouldn't be a flag)
|
||||
@@ -810,7 +813,7 @@ bool ImGui::ButtonEx(const char* label, const ImVec2& size_arg, ImGuiButtonFlags
|
||||
|
||||
if (g.LogEnabled)
|
||||
LogSetNextTextDecoration("[", "]");
|
||||
RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, NULL, &label_size, style.ButtonTextAlign, &bb);
|
||||
RenderTextClipped(bb.Min + style.FramePadding, bb.Max - style.FramePadding, label, label_end, &label_size, style.ButtonTextAlign, &bb);
|
||||
|
||||
// Automatically close popups
|
||||
//if (pressed && !(flags & ImGuiButtonFlags_DontClosePopups) && (window->Flags & ImGuiWindowFlags_Popup))
|
||||
@@ -975,7 +978,7 @@ ImRect ImGui::GetWindowScrollbarRect(ImGuiWindow* window, ImGuiAxis axis)
|
||||
const float scrollbar_size = window->ScrollbarSizes[axis ^ 1]; // (ScrollbarSizes.x = width of Y scrollbar; ScrollbarSizes.y = height of X scrollbar)
|
||||
IM_ASSERT(scrollbar_size >= 0.0f);
|
||||
const float border_size = IM_ROUND(window->WindowBorderSize * 0.5f);
|
||||
const float border_top = (window->Flags & ImGuiWindowFlags_MenuBar) ? IM_ROUND(g.Style.FrameBorderSize * 0.5f) : 0.0f;
|
||||
const float border_top = (window->Flags & ImGuiWindowFlags_MenuBar) ? IM_ROUND(g.Style.FrameBorderSize * 0.5f) : (window->Flags & ImGuiWindowFlags_NoTitleBar) ? border_size : 0;
|
||||
if (axis == ImGuiAxis_X)
|
||||
return ImRect(inner_rect.Min.x + border_size, ImMax(outer_rect.Min.y + border_size, outer_rect.Max.y - border_size - scrollbar_size), inner_rect.Max.x - border_size, outer_rect.Max.y - border_size);
|
||||
else
|
||||
@@ -1148,7 +1151,7 @@ void ImGui::ImageWithBg(ImTextureRef tex_ref, const ImVec2& image_size, const Im
|
||||
else
|
||||
window->DrawList->AddImage(tex_ref, bb.Min + padding, bb.Max - padding, uv0, uv1, GetColorU32(tint_col));
|
||||
if (g.Style.ImageBorderSize > 0.0f)
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), rounding, ImDrawFlags_None, g.Style.ImageBorderSize);
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_Border), rounding, g.Style.ImageBorderSize);
|
||||
}
|
||||
|
||||
void ImGui::Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0, const ImVec2& uv1)
|
||||
@@ -1243,7 +1246,8 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
const float square_sz = GetFrameHeight();
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
@@ -1284,8 +1288,9 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
if (is_visible)
|
||||
{
|
||||
RenderNavCursor(total_bb, id);
|
||||
RenderFrame(check_bb.Min, check_bb.Max, GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg), true, style.FrameRounding);
|
||||
ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_FrameBgActive : hovered ? ImGuiCol_FrameBgHovered : (mixed_value || checked) ? ImGuiCol_CheckboxSelectedBg : ImGuiCol_FrameBg);
|
||||
ImU32 check_col = GetColorU32(ImGuiCol_CheckMark);
|
||||
RenderFrame(check_bb.Min, check_bb.Max, bg_col, true, style.FrameRounding);
|
||||
if (mixed_value)
|
||||
{
|
||||
// Undocumented tristate/mixed/indeterminate checkbox (#2644)
|
||||
@@ -1303,7 +1308,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
|
||||
if (g.LogEnabled)
|
||||
LogRenderedText(&label_pos, mixed_value ? "[~]" : *v ? "[x]" : "[ ]");
|
||||
if (is_visible && label_size.x > 0.0f)
|
||||
RenderText(label_pos, label);
|
||||
RenderText(label_pos, label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (*v ? ImGuiItemStatusFlags_Checked : 0));
|
||||
return pressed;
|
||||
@@ -1365,7 +1370,8 @@ bool ImGui::RadioButton(const char* label, bool active)
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
const float square_sz = GetFrameHeight();
|
||||
const ImVec2 pos = window->DC.CursorPos;
|
||||
@@ -1404,7 +1410,7 @@ bool ImGui::RadioButton(const char* label, bool active)
|
||||
if (g.LogEnabled)
|
||||
LogRenderedText(&label_pos, active ? "(x)" : "( )");
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(label_pos, label);
|
||||
RenderText(label_pos, label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
return pressed;
|
||||
@@ -1520,7 +1526,7 @@ bool ImGui::TextLink(const char* label)
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
|
||||
ImVec2 pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset);
|
||||
ImVec2 size = CalcTextSize(label, label_end, true);
|
||||
ImVec2 size = CalcTextSize(label, label_end, false);
|
||||
ImRect bb(pos, pos + size);
|
||||
ItemSize(size, 0.0f);
|
||||
if (!ItemAdd(bb, id))
|
||||
@@ -1551,10 +1557,10 @@ bool ImGui::TextLink(const char* label)
|
||||
}
|
||||
|
||||
float line_y = bb.Max.y + ImFloor(g.FontBaked->Descent * g.FontBakedScale * 0.20f);
|
||||
window->DrawList->AddLine(ImVec2(bb.Min.x, line_y), ImVec2(bb.Max.x, line_y), GetColorU32(line_colf), 1.0f * (float)(int)g.Style._MainScale); // FIXME-TEXT: Underline mode // FIXME-DPI
|
||||
window->DrawList->AddLineH(bb.Min.x, bb.Max.x, line_y, GetColorU32(line_colf), 1.0f * (float)(int)g.Style._MainScale); // FIXME-TEXT: Underline mode // FIXME-DPI
|
||||
|
||||
PushStyleColor(ImGuiCol_Text, GetColorU32(text_colf));
|
||||
RenderText(bb.Min, label, label_end);
|
||||
RenderText(bb.Min, label, label_end, false);
|
||||
PopStyleColor();
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
@@ -1724,7 +1730,7 @@ void ImGui::Separator()
|
||||
if (window->DC.CurrentColumns)
|
||||
flags |= ImGuiSeparatorFlags_SpanAllColumns;
|
||||
|
||||
SeparatorEx(flags, g.Style.SeparatorSize);
|
||||
SeparatorEx(flags, ImMax(g.Style.SeparatorSize, 1.0f));
|
||||
}
|
||||
|
||||
void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end, float extra_w)
|
||||
@@ -1761,9 +1767,9 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
|
||||
const float sep1_x2 = label_pos.x - style.ItemSpacing.x;
|
||||
const float sep2_x1 = label_pos.x + label_size.x + extra_w + style.ItemSpacing.x;
|
||||
if (sep1_x2 > sep1_x1 && separator_thickness > 0.0f)
|
||||
window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep1_x2, seps_y), separator_col, separator_thickness);
|
||||
window->DrawList->AddLineH(sep1_x1, sep1_x2, seps_y, separator_col, separator_thickness);
|
||||
if (sep2_x2 > sep2_x1 && separator_thickness > 0.0f)
|
||||
window->DrawList->AddLine(ImVec2(sep2_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
|
||||
window->DrawList->AddLineH(sep2_x1, sep2_x2, seps_y, separator_col, separator_thickness);
|
||||
if (g.LogEnabled)
|
||||
LogSetNextTextDecoration("---", NULL);
|
||||
RenderTextEllipsis(window->DrawList, label_pos, ImVec2(bb.Max.x, bb.Max.y + style.ItemSpacing.y), bb.Max.x, label, label_end, &label_size);
|
||||
@@ -1773,7 +1779,7 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
|
||||
if (g.LogEnabled)
|
||||
LogText("---");
|
||||
if (separator_thickness > 0.0f)
|
||||
window->DrawList->AddLine(ImVec2(sep1_x1, seps_y), ImVec2(sep2_x2, seps_y), separator_col, separator_thickness);
|
||||
window->DrawList->AddLineH(sep1_x1, sep2_x2, seps_y, separator_col, separator_thickness);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1944,8 +1950,9 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | (ImGuiComboFlags)ImGuiComboFlags_CustomPreview)) == 0);
|
||||
|
||||
const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, true).x : 0.0f;
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, false).x : 0.0f;
|
||||
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : ((flags & ImGuiComboFlags_WidthFitPreview) ? (arrow_size + preview_width + style.FramePadding.x * 2.0f) : CalcItemWidth());
|
||||
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
|
||||
const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
@@ -1996,7 +2003,7 @@ bool ImGui::BeginCombo(const char* label, const char* preview_value, ImGuiComboF
|
||||
RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL);
|
||||
}
|
||||
if (label_size.x > 0)
|
||||
RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
if (!popup_open)
|
||||
return false;
|
||||
@@ -2369,12 +2376,17 @@ bool ImGui::DataTypeApplyFromText(const char* buf, ImGuiDataType data_type, void
|
||||
|
||||
// Sanitize format
|
||||
// - For float/double we have to ignore format with precision (e.g. "%.2f") because sscanf doesn't take them in, so force them into %f and %lf
|
||||
// - In theory could treat empty format as using default, but this would only cover rare/bizarre case of using InputScalar() + integer + format string without %.
|
||||
char format_sanitized[32];
|
||||
if (data_type == ImGuiDataType_Float || data_type == ImGuiDataType_Double)
|
||||
{
|
||||
format = type_info->ScanFmt;
|
||||
}
|
||||
else
|
||||
{
|
||||
format = ImParseFormatSanitizeForScanning(format, format_sanitized, IM_COUNTOF(format_sanitized));
|
||||
if (format[0] == '\0')
|
||||
format = type_info->ScanFmt; // Format doesn't want us to show the number currently, but we still need to parse the resulting input
|
||||
}
|
||||
|
||||
// Small types need a 32-bit buffer to receive the result from scanf()
|
||||
int v32 = 0;
|
||||
@@ -2709,7 +2721,8 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
const float w = CalcItemWidth();
|
||||
const ImU32 color_marker = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasColorMarker) ? g.NextItemData.ColorMarker : 0;
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
|
||||
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
|
||||
@@ -2785,7 +2798,7 @@ bool ImGui::DragScalar(const char* label, ImGuiDataType data_type, void* p_data,
|
||||
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
|
||||
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0));
|
||||
return value_changed;
|
||||
@@ -3310,7 +3323,8 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
const float w = CalcItemWidth();
|
||||
const ImU32 color_marker = (g.NextItemData.HasFlags & ImGuiNextItemDataFlags_HasColorMarker) ? g.NextItemData.ColorMarker : 0;
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
|
||||
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
|
||||
@@ -3382,7 +3396,7 @@ bool ImGui::SliderScalar(const char* label, ImGuiDataType data_type, void* p_dat
|
||||
RenderTextClipped(frame_bb.Min, frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.5f));
|
||||
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | (temp_input_allowed ? ImGuiItemStatusFlags_Inputable : 0));
|
||||
return value_changed;
|
||||
@@ -3487,7 +3501,8 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + size);
|
||||
const ImRect bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
|
||||
|
||||
@@ -3532,8 +3547,9 @@ bool ImGui::VSliderScalar(const char* label, const ImVec2& size, ImGuiDataType d
|
||||
const char* value_buf_end = value_buf + DataTypeFormatString(value_buf, IM_COUNTOF(value_buf), data_type, p_data, format);
|
||||
RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, value_buf, value_buf_end, NULL, ImVec2(0.5f, 0.0f));
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@@ -3556,7 +3572,8 @@ bool ImGui::VSliderInt(const char* label, const ImVec2& size, int* v, int v_min,
|
||||
// - ImParseFormatSanitizeForPrinting() [Internal]
|
||||
// - ImParseFormatSanitizeForScanning() [Internal]
|
||||
// - ImParseFormatPrecision() [Internal]
|
||||
// - TempInputTextScalar() [Internal]
|
||||
// - TempInputText() [Internal]
|
||||
// - TempInputScalar() [Internal]
|
||||
// - InputScalar()
|
||||
// - InputScalarN()
|
||||
// - InputFloat()
|
||||
@@ -3785,7 +3802,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiStyle& style = g.Style;
|
||||
IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()!
|
||||
//IM_ASSERT((flags & ImGuiInputTextFlags_EnterReturnsTrue) == 0); // Not supported by InputScalar(). Please open an issue if you this would be useful to you. Otherwise use IsItemDeactivatedAfterEdit()!
|
||||
|
||||
if (format == NULL)
|
||||
format = DataTypeGetInfo(data_type)->PrintFmt;
|
||||
@@ -3822,7 +3839,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
}
|
||||
|
||||
// Apply
|
||||
bool value_changed = ret ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
|
||||
bool input_edited = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_EditedInternal) != 0; // We would be using 'ret' if ImGuiInputTextFlags_EnterReturnsTrue was not involved.
|
||||
bool value_changed = input_edited ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
|
||||
|
||||
// Step buttons
|
||||
if (has_step_buttons)
|
||||
@@ -3836,13 +3854,13 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
if (ButtonEx("-", ImVec2(button_size, button_size)))
|
||||
{
|
||||
DataTypeApplyOp(data_type, '-', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
|
||||
value_changed = true;
|
||||
value_changed = ret = true;
|
||||
}
|
||||
SameLine(0, style.ItemInnerSpacing.x);
|
||||
if (ButtonEx("+", ImVec2(button_size, button_size)))
|
||||
{
|
||||
DataTypeApplyOp(data_type, '+', p_data, p_data, g.IO.KeyCtrl && p_step_fast ? p_step_fast : p_step);
|
||||
value_changed = true;
|
||||
value_changed = ret = true;
|
||||
}
|
||||
PopItemFlag();
|
||||
if (flags & ImGuiInputTextFlags_ReadOnly)
|
||||
@@ -3864,6 +3882,8 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
|
||||
if (value_changed)
|
||||
MarkItemEdited(g.LastItemData.ID);
|
||||
|
||||
if (flags & ImGuiInputTextFlags_EnterReturnsTrue)
|
||||
return ret;
|
||||
return value_changed;
|
||||
}
|
||||
|
||||
@@ -4513,6 +4533,9 @@ static bool InputTextFilterCharacter(ImGuiContext* ctx, ImGuiInputTextState* sta
|
||||
callback_data.EventFlag = ImGuiInputTextFlags_CallbackCharFilter;
|
||||
callback_data.EventChar = (ImWchar)c;
|
||||
callback_data.EventActivated = (g.ActiveId == state->ID && g.ActiveIdIsJustActivated);
|
||||
callback_data.CursorPos = state->Stb->cursor;
|
||||
callback_data.SelectionStart = state->Stb->select_start;
|
||||
callback_data.SelectionEnd = state->Stb->select_end;
|
||||
callback_data.UserData = user_data;
|
||||
if (callback(&callback_data) != 0)
|
||||
return false;
|
||||
@@ -4561,6 +4584,7 @@ void ImGui::InputTextDeactivateHook(ImGuiID id)
|
||||
ImGuiInputTextState* state = &g.InputTextState;
|
||||
if (id == 0 || state->ID != id)
|
||||
return;
|
||||
//IMGUI_DEBUG_LOG_ACTIVEID("InputTextDeactivateHook() id = 0x%08X\n", id);
|
||||
g.InputTextDeactivatedState.ID = state->ID;
|
||||
if (state->Flags & ImGuiInputTextFlags_ReadOnly)
|
||||
{
|
||||
@@ -4695,7 +4719,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (is_multiline) // Open group before calling GetID() because groups tracks id created within their scope (including the scrollbar)
|
||||
BeginGroup();
|
||||
const ImGuiID id = window->GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), (is_multiline ? g.FontSize * 8.0f : label_size.y) + style.FramePadding.y * 2.0f); // Arbitrary default of 8 lines high for multi-line
|
||||
const ImVec2 total_size = ImVec2(frame_size.x + (label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f), frame_size.y);
|
||||
|
||||
@@ -4709,7 +4734,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
{
|
||||
ImVec2 backup_pos = window->DC.CursorPos;
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable))
|
||||
bool no_clip = (g.InputTextDeactivatedState.ID == id) || (g.ActiveId == id) || (id == g.NavActivateId); // Mimic some of ItemAdd() logic + add InputTextDeactivatedState.ID check.
|
||||
if (!ItemAdd(total_bb, id, &frame_bb, ImGuiItemFlags_Inputable) && !no_clip)
|
||||
{
|
||||
EndGroup();
|
||||
return false;
|
||||
@@ -4735,7 +4761,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
g.NavActivateId = backup_activate_id;
|
||||
PopStyleVar(3);
|
||||
PopStyleColor();
|
||||
if (!child_visible)
|
||||
if (!child_visible && !no_clip)
|
||||
{
|
||||
EndChild();
|
||||
EndGroup();
|
||||
@@ -4799,7 +4825,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
float scroll_y = is_multiline ? draw_window->Scroll.y : FLT_MAX;
|
||||
|
||||
const bool init_reload_from_user_buf = (state != NULL && state->WantReloadUserBuf);
|
||||
const bool init_changed_specs = (state != NULL && state->Stb->single_line != !is_multiline); // state != NULL means its our state.
|
||||
const bool init_changed_specs_multiline = (state != NULL && (state->Stb->single_line != !is_multiline)); // state != NULL means its our state.
|
||||
const bool init_changed_specs_readonly = (state != NULL && ((state->Flags ^ flags) & ImGuiInputTextFlags_ReadOnly)); // state != NULL means its our state.
|
||||
const bool init_make_active = (input_requested_by_user || input_requested_by_nav || input_requested_by_reactivate || user_scroll_finish);
|
||||
if (init_reload_from_user_buf)
|
||||
{
|
||||
@@ -4813,7 +4840,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
state->Stb->select_start = state->ReloadSelectionStart;
|
||||
state->Stb->cursor = state->Stb->select_end = state->ReloadSelectionEnd; // will be clamped to bounds below
|
||||
}
|
||||
else if ((init_make_active && g.ActiveId != id) || init_changed_specs)
|
||||
else if ((init_make_active && g.ActiveId != id) || init_changed_specs_multiline || init_changed_specs_readonly)
|
||||
{
|
||||
// Access state even if we don't own it yet.
|
||||
state = &g.InputTextState;
|
||||
@@ -4834,8 +4861,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
|
||||
// Preserve cursor position and undo/redo stack if we come back to same widget
|
||||
// FIXME: Since we reworked this on 2022/06, may want to differentiate recycle_cursor vs recycle_undostate?
|
||||
bool recycle_state = (state->ID == id && !init_changed_specs);
|
||||
if (recycle_state && (state->TextLen != buf_len || (state->TextA.Data == NULL || strncmp(state->TextA.Data, buf, buf_len) != 0)))
|
||||
bool recycle_state = (state->ID == id && !init_changed_specs_multiline);
|
||||
if (recycle_state && !init_changed_specs_readonly && (state->TextLen != buf_len || (state->TextA.Data == NULL || strncmp(state->TextA.Data, buf, buf_len) != 0)))
|
||||
recycle_state = false;
|
||||
|
||||
// Start edition
|
||||
@@ -4873,7 +4900,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
|
||||
const bool is_osx = io.ConfigMacOSXBehaviors;
|
||||
if (g.ActiveId != id && init_make_active)
|
||||
if (init_make_active && g.ActiveId != id)
|
||||
{
|
||||
IM_ASSERT(state && state->ID == id);
|
||||
SetActiveID(id, window);
|
||||
@@ -4944,13 +4971,17 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
if (is_password && !is_displaying_hint)
|
||||
PushPasswordFont();
|
||||
|
||||
// Word-wrapping: attempt to keep cursor in view while resizing frame/parent
|
||||
// FIXME-WORDWRAP: It would be better to preserve same relative offset.
|
||||
if (is_wordwrap && state != NULL && state->ID == id && state->WrapWidth != wrap_width)
|
||||
if (state != NULL && state->ID == id)
|
||||
{
|
||||
state->CursorCenterY = true;
|
||||
state->WrapWidth = wrap_width;
|
||||
render_cursor = true;
|
||||
state->Flags = flags;
|
||||
|
||||
// Word-wrapping: attempt to keep cursor in view while resizing frame/parent (FIXME-WORDWRAP: would be better to preserve same relative offset)
|
||||
if (is_wordwrap && state->WrapWidth != wrap_width)
|
||||
{
|
||||
state->CursorCenterY = true;
|
||||
state->WrapWidth = wrap_width;
|
||||
render_cursor = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Process mouse inputs and character inputs
|
||||
@@ -4959,7 +4990,6 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
IM_ASSERT(state != NULL);
|
||||
state->EditedThisFrame = false;
|
||||
state->BufCapacity = buf_size;
|
||||
state->Flags = flags;
|
||||
state->WrapWidth = wrap_width;
|
||||
|
||||
// Although we are active we don't prevent mouse from hovering other elements unless we are interacting right now with the widget.
|
||||
@@ -5611,7 +5641,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
|
||||
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
|
||||
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
|
||||
draw_window->DrawList->AddLine(cursor_screen_rect.Min, cursor_screen_rect.GetBL(), GetColorU32(ImGuiCol_InputTextCursor), 1.0f * (float)(int)style._MainScale); // FIXME-DPI: Cursor thickness (#7031)
|
||||
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), 1.0f * (float)(int)style._MainScale); // FIXME-DPI: Cursor thickness (#7031)
|
||||
|
||||
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
|
||||
// This is required for some backends (SDL3) to start emitting character/text inputs.
|
||||
@@ -5659,7 +5689,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
|
||||
}
|
||||
|
||||
if (label_size.x > 0)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label, label_end, false);
|
||||
|
||||
if (value_changed)
|
||||
MarkItemEdited(id);
|
||||
@@ -6325,7 +6355,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
|
||||
const float a1 = (n+1.0f)/6.0f * 2.0f * IM_PI + aeps;
|
||||
const int vert_start_idx = draw_list->VtxBuffer.Size;
|
||||
draw_list->PathArcTo(wheel_center, (wheel_r_inner + wheel_r_outer)*0.5f, a0, a1, segment_per_arc);
|
||||
draw_list->PathStroke(col_white, 0, wheel_thickness);
|
||||
draw_list->PathStroke(col_white, wheel_thickness);
|
||||
const int vert_end_idx = draw_list->VtxBuffer.Size;
|
||||
|
||||
// Paint colors over existing vertices
|
||||
@@ -6469,7 +6499,7 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
|
||||
if (g.Style.FrameBorderSize > 0.0f)
|
||||
RenderFrameBorder(bb.Min, bb.Max, rounding);
|
||||
else
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding, 0, 1.0f * (float)(int)g.Style._MainScale); // Color buttons are often in need of some sort of border // FIXME-DPI
|
||||
window->DrawList->AddRect(bb.Min, bb.Max, GetColorU32(ImGuiCol_FrameBg), rounding, 1.0f * (float)(int)g.Style._MainScale); // Color buttons are often in need of some sort of border // FIXME-DPI
|
||||
}
|
||||
|
||||
// Drag and Drop Source
|
||||
@@ -7142,11 +7172,11 @@ void ImGui::TreeNodeDrawLineToChildNode(const ImVec2& target_pos)
|
||||
window->DrawList->PathArcToFast(ImVec2(x1, y - rounding), rounding, 6, 3);
|
||||
if (x1 < x2)
|
||||
window->DrawList->PathLineTo(ImVec2(x2, y));
|
||||
window->DrawList->PathStroke(GetColorU32(ImGuiCol_TreeLines), ImDrawFlags_None, g.Style.TreeLinesSize);
|
||||
window->DrawList->PathStroke(GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
window->DrawList->AddLine(ImVec2(x1, y), ImVec2(x2, y), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
window->DrawList->AddLineH(x1, x2, y, GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7172,7 +7202,7 @@ void ImGui::TreeNodeDrawLineToTreePop(const ImGuiTreeNodeStackData* data)
|
||||
float x = ImTrunc(data->DrawLinesX1);
|
||||
if (data->DrawLinesTableColumn != -1)
|
||||
TablePushColumnChannel(data->DrawLinesTableColumn);
|
||||
window->DrawList->AddLine(ImVec2(x, y1), ImVec2(x, y2), GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
window->DrawList->AddLineV(x, y1, y2, GetColorU32(ImGuiCol_TreeLines), g.Style.TreeLinesSize);
|
||||
if (data->DrawLinesTableColumn != -1)
|
||||
TablePopColumnChannel();
|
||||
}
|
||||
@@ -7331,7 +7361,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
|
||||
// Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle.
|
||||
ImGuiID id = window->GetID(label);
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
pos.y += window->DC.CurrLineTextBaseOffset;
|
||||
@@ -7486,7 +7517,11 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
|
||||
|
||||
// Text stays at the submission position. Alignment/clipping extents ignore SpanAllColumns.
|
||||
if (is_visible)
|
||||
RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, NULL, &label_size, style.SelectableTextAlign, &bb);
|
||||
RenderTextClipped(pos, ImVec2(ImMin(pos.x + size.x, window->WorkRect.Max.x), pos.y + size.y), label, label_end, &label_size, style.SelectableTextAlign, &bb);
|
||||
|
||||
#ifdef IMGUI_DEBUG_BOXSELECT
|
||||
if (g.BoxSelectState.UnclipMode) { GetForegroundDrawList()->AddText(pos, IM_COL32(255,255,0,200), label, label_end); }
|
||||
#endif
|
||||
|
||||
// Automatically close popups
|
||||
if (pressed && !auto_selected && (window->Flags & ImGuiWindowFlags_Popup) && !(flags & ImGuiSelectableFlags_NoAutoClosePopups) && (g.LastItemData.ItemFlags & ImGuiItemFlags_AutoClosePopups))
|
||||
@@ -7803,7 +7838,7 @@ bool ImGui::BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiI
|
||||
return false;
|
||||
|
||||
// Current frame absolute prev/current rectangles are used to toggle selection.
|
||||
// They are derived from positions relative to scrolling space.
|
||||
// They are derived from positions relative to scrolling space, so "previous" rectangle is reprojected for current frame coordinates.
|
||||
ImVec2 start_pos_abs = WindowPosRelToAbs(window, bs->StartPosRel);
|
||||
ImVec2 prev_end_pos_abs = WindowPosRelToAbs(window, bs->EndPosRel); // Clamped already
|
||||
ImVec2 curr_end_pos_abs = g.IO.MousePos;
|
||||
@@ -7813,20 +7848,69 @@ bool ImGui::BeginBoxSelect(const ImRect& scope_rect, ImGuiWindow* window, ImGuiI
|
||||
bs->BoxSelectRectPrev.Max = ImMax(start_pos_abs, prev_end_pos_abs);
|
||||
bs->BoxSelectRectCurr.Min = ImMin(start_pos_abs, curr_end_pos_abs);
|
||||
bs->BoxSelectRectCurr.Max = ImMax(start_pos_abs, curr_end_pos_abs);
|
||||
//IMGUI_DEBUG_LOG("StartPosRel (%.2f,%.2f) EndPosRel (%.2f,%.2f) -> (%.2f,%.2f)\n", bs->StartPosRel.x, bs->StartPosRel.y, bs->EndPosRel.x, bs->EndPosRel.y, WindowPosAbsToRel(window, g.IO.MousePos).x, WindowPosAbsToRel(window, g.IO.MousePos).y);
|
||||
|
||||
// Box-select 2D mode detects horizontal changes (vertical ones are already picked by Clipper)
|
||||
// Storing an extra rect used by widgets supporting box-select.
|
||||
if (ms_flags & ImGuiMultiSelectFlags_BoxSelect2d)
|
||||
if (bs->BoxSelectRectPrev.Min.x != bs->BoxSelectRectCurr.Min.x || bs->BoxSelectRectPrev.Max.x != bs->BoxSelectRectCurr.Max.x)
|
||||
// Box-select 2D mode detects change of the rectangle.
|
||||
// Storing unclip rects which will be tested by widgets supporting box-select. Always update rectangles when active (even if we don't use them).
|
||||
// To facilitate understanding this: enable IMGUI_DEBUG_BOXSELECT and visualize all geometry.
|
||||
if (ms_flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||
{
|
||||
// For both sides, compute the area differing between Prev and Curr rectangles.
|
||||
bs->UnclipRects[0] = bs->UnclipRects[1] = ImRect(+FLT_MAX, +FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
for (int side = 0; side < 2; side++)
|
||||
{
|
||||
bs->UnclipMode = true;
|
||||
bs->UnclipRect = bs->BoxSelectRectPrev; // FIXME-OPT: UnclipRect x coordinates could be intersection of Prev and Curr rect on X axis.
|
||||
bs->UnclipRect.Add(bs->BoxSelectRectCurr);
|
||||
ImVec2 d_min = (side == 0) ? ImMin(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectPrev.Min) : ImMin(bs->BoxSelectRectCurr.Max, bs->BoxSelectRectPrev.Max);
|
||||
ImVec2 d_max = (side == 0) ? ImMax(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectPrev.Min) : ImMax(bs->BoxSelectRectCurr.Max, bs->BoxSelectRectPrev.Max);
|
||||
if (d_min.x != d_max.x)
|
||||
{
|
||||
bs->UnclipRects[0].AddX(d_min.x);
|
||||
bs->UnclipRects[0].AddX(d_max.x);
|
||||
}
|
||||
if (d_min.y != d_max.y)
|
||||
{
|
||||
bs->UnclipRects[1].AddY(d_min.y);
|
||||
bs->UnclipRects[1].AddY(d_max.y);
|
||||
}
|
||||
}
|
||||
|
||||
//GetForegroundDrawList()->AddRect(bs->UnclipRect.Min, bs->UnclipRect.Max, IM_COL32(255,0,0,200), 0.0f, 0, 3.0f);
|
||||
ImRect box_select_intersection = bs->BoxSelectRectPrev;
|
||||
box_select_intersection.Add(bs->BoxSelectRectCurr);
|
||||
if (ms_flags & ImGuiMultiSelectFlags_BoxSelect2d)
|
||||
if (bs->BoxSelectRectPrev.Min.x != bs->BoxSelectRectCurr.Min.x || bs->BoxSelectRectPrev.Max.x != bs->BoxSelectRectCurr.Max.x)
|
||||
{
|
||||
bs->UnclipRects[0].AddY(box_select_intersection.Min.y);
|
||||
bs->UnclipRects[0].AddY(box_select_intersection.Max.y);
|
||||
}
|
||||
if (ms_flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||
if (bs->BoxSelectRectPrev.Min.y != bs->BoxSelectRectCurr.Min.y || bs->BoxSelectRectPrev.Max.y != bs->BoxSelectRectCurr.Max.y)
|
||||
{
|
||||
bs->UnclipRects[1].AddX(box_select_intersection.Min.x);
|
||||
bs->UnclipRects[1].AddX(box_select_intersection.Max.x);
|
||||
}
|
||||
|
||||
// Merge both rectangles into one.
|
||||
// FIXME-OPT: When UnclipRect.Area() is much larger than the sum of UnclipRects[0]/[1] Areas, widgets should
|
||||
// ideally first use UnclipRect as a first coarse cull layer + the individual ones as a second validation.
|
||||
bs->UnclipRect = bs->UnclipRects[0];
|
||||
bs->UnclipRect.Add(bs->UnclipRects[1]);
|
||||
if (!bs->UnclipRect.IsInverted() && (!window->ClipRect.Contains(bs->UnclipRect.Min) || !window->ClipRect.Contains(bs->UnclipRect.Max))) // !! Don't use Contains(ImRect)
|
||||
bs->UnclipMode = true;
|
||||
if (bs->UnclipMode && g.CurrentTable != NULL)
|
||||
TableApplyExternalUnclipRect(g.CurrentTable, bs->UnclipRect); // No need submitting both
|
||||
}
|
||||
|
||||
#ifdef IMGUI_DEBUG_BOXSELECT
|
||||
//GetForegroundDrawList()->AddRect(scope_rect.Min, scope_rect.Max, IM_COL32(0, 255, 0, 200), 0.0f, 0, 4.0f);
|
||||
//GetForegroundDrawList()->AddRect(bs->BoxSelectRectPrev.Min, bs->BoxSelectRectPrev.Max, IM_COL32(255,0,0,200), 0.0f, 0, 3.0f);
|
||||
//GetForegroundDrawList()->AddRect(bs->BoxSelectRectCurr.Min, bs->BoxSelectRectCurr.Max, IM_COL32(0,255,0,200), 0.0f, 0, 1.0f);
|
||||
if (ms_flags & (ImGuiMultiSelectFlags_BoxSelect1d | ImGuiMultiSelectFlags_BoxSelect2d))
|
||||
{
|
||||
for (ImRect& unclip_r : bs->UnclipRects)
|
||||
if (!unclip_r.IsInverted())
|
||||
GetForegroundDrawList()->AddRect(unclip_r.Min, unclip_r.Max, bs->UnclipMode ? IM_COL32(255, 255, 0, 200) : IM_COL32(255, 0, 0, 200), 0.0f, 0, 4.0f);
|
||||
GetForegroundDrawList()->AddRect(bs->UnclipRect.Min, bs->UnclipRect.Max, bs->UnclipMode ? IM_COL32(255, 255, 0, 200) : IM_COL32(255, 0, 0, 200), 0.0f, 0, 2.0f);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7842,8 +7926,9 @@ void ImGui::EndBoxSelect(const ImRect& scope_rect, ImGuiMultiSelectFlags ms_flag
|
||||
bs->EndPosRel = WindowPosAbsToRel(window, ImClamp(g.IO.MousePos, scope_rect.Min, scope_rect.Max)); // Clamp stored position according to current scrolling view
|
||||
ImRect box_select_r = bs->BoxSelectRectCurr;
|
||||
box_select_r.ClipWith(scope_rect);
|
||||
window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
|
||||
window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT FIXME-DPI: Styling
|
||||
ImGuiWindow* draw_window = FindFrontMostVisibleChildWindow(window);
|
||||
draw_window->DrawList->AddRectFilled(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_SeparatorHovered, 0.30f)); // FIXME-MULTISELECT: Styling
|
||||
draw_window->DrawList->AddRect(box_select_r.Min, box_select_r.Max, GetColorU32(ImGuiCol_NavCursor)); // FIXME-MULTISELECT FIXME-DPI: Styling
|
||||
|
||||
// Scroll
|
||||
const bool enable_scroll = (ms_flags & ImGuiMultiSelectFlags_ScopeWindow) && (ms_flags & ImGuiMultiSelectFlags_BoxSelectNoScroll) == 0;
|
||||
@@ -7883,18 +7968,18 @@ static void DebugLogMultiSelectRequests(const char* function, const ImGuiMultiSe
|
||||
|
||||
static ImRect CalcScopeRect(ImGuiMultiSelectTempData* ms, ImGuiWindow* window)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (ms->Flags & ImGuiMultiSelectFlags_ScopeRect)
|
||||
{
|
||||
// Warning: this depends on CursorMaxPos so it means to be called by EndMultiSelect() only
|
||||
// This probably doesn't work inside a table as there are ample ambiguities related to exact time of calling BeginMultiSelect()/EndMultiSelect().
|
||||
return ImRect(ms->ScopeRectMin, ImMax(window->DC.CursorMaxPos, ms->ScopeRectMin));
|
||||
}
|
||||
else
|
||||
{
|
||||
// When a table, pull HostClipRect, which allows us to predict ClipRect before first row/layout is performed. (#7970)
|
||||
//// When a table, pull HostClipRect, which allows us to predict ClipRect before first row/layout is performed. (#7970)
|
||||
ImRect scope_rect = window->InnerClipRect;
|
||||
if (g.CurrentTable != NULL)
|
||||
scope_rect = g.CurrentTable->HostClipRect;
|
||||
//if (g.CurrentTable != NULL)
|
||||
// scope_rect = g.CurrentTable->HostClipRect;
|
||||
|
||||
// Add inner table decoration (#7821) // FIXME: Why not baking in InnerClipRect?
|
||||
scope_rect.Min = ImMin(scope_rect.Min + ImVec2(window->DecoInnerSizeX1, window->DecoInnerSizeY1), scope_rect.Max);
|
||||
@@ -7930,18 +8015,24 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
|
||||
// FIXME: Workaround to the fact we override CursorMaxPos, meaning size measurement are lost. (#8250)
|
||||
// They should perhaps be stacked properly?
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
if (table->CurrentColumn != -1)
|
||||
{
|
||||
if (!table->IsLayoutLocked)
|
||||
TableUpdateLayout(table);
|
||||
else if (table->CurrentColumn != -1)
|
||||
TableEndCell(table); // This is currently safe to call multiple time. If that properly is lost we can extract the "save measurement" part of it.
|
||||
}
|
||||
|
||||
// FIXME: BeginFocusScope()
|
||||
const ImGuiID id = window->IDStack.back();
|
||||
ms->Clear();
|
||||
ms->FocusScopeId = id;
|
||||
ms->Flags = flags;
|
||||
ms->IsFocused = (ms->FocusScopeId == g.NavFocusScopeId);
|
||||
ms->BackupCursorMaxPos = window->DC.CursorMaxPos;
|
||||
ms->ScopeRectMin = window->DC.CursorMaxPos = window->DC.CursorPos;
|
||||
ms->ScopeRectMin = window->DC.CursorPos;
|
||||
if (flags & ImGuiMultiSelectFlags_ScopeRect)
|
||||
window->DC.CursorMaxPos = ms->ScopeRectMin; // CalcScopeRect() for ImGuiMultiSelectFlags_ScopeRect will measure in EndMultiSelect().
|
||||
PushFocusScope(ms->FocusScopeId);
|
||||
ms->IsFocused = IsInNavFocusRoute(g.CurrentFocusScopeId);
|
||||
if (flags & ImGuiMultiSelectFlags_ScopeWindow) // Mark parent child window as navigable into, with highlight. Assume user will always submit interactive items.
|
||||
window->DC.NavLayersActiveMask |= 1 << ImGuiNavLayer_Main;
|
||||
|
||||
@@ -8023,7 +8114,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
|
||||
storage->LastSelectionSize = 0;
|
||||
}
|
||||
ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1;
|
||||
ms->LastSubmittedItem = ImGuiSelectionUserData_Invalid;
|
||||
//ms->PrevSubmittedItem = ImGuiSelectionUserData_Invalid;
|
||||
|
||||
if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)
|
||||
DebugLogMultiSelectRequests("BeginMultiSelect", &ms->IO);
|
||||
@@ -8069,7 +8160,7 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
|
||||
// Clear selection when clicking void?
|
||||
// We specifically test for IsMouseDragPastThreshold(0) == false to allow box-selection!
|
||||
// The InnerRect test is necessary for non-child/decorated windows.
|
||||
bool scope_hovered = IsWindowHovered() && window->InnerRect.Contains(g.IO.MousePos);
|
||||
bool scope_hovered = window->InnerRect.Contains(g.IO.MousePos) && IsWindowHovered(ImGuiHoveredFlags_ChildWindows);
|
||||
if (scope_hovered && (ms->Flags & ImGuiMultiSelectFlags_ScopeRect))
|
||||
scope_hovered &= scope_rect.Contains(g.IO.MousePos);
|
||||
if (scope_hovered && g.HoveredId == 0 && g.ActiveId == 0)
|
||||
@@ -8095,10 +8186,13 @@ ImGuiMultiSelectIO* ImGui::EndMultiSelect()
|
||||
if (ms->Flags & ImGuiMultiSelectFlags_NavWrapX)
|
||||
{
|
||||
IM_ASSERT(ms->Flags & ImGuiMultiSelectFlags_ScopeWindow); // Only supported at window scope
|
||||
ImGui::NavMoveRequestTryWrapping(ImGui::GetCurrentWindow(), ImGuiNavMoveFlags_WrapX);
|
||||
NavMoveRequestTryWrapping(GetCurrentWindow(), ImGuiNavMoveFlags_WrapX);
|
||||
}
|
||||
|
||||
// Unwind
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
if (table->IsInsideRow)
|
||||
TableEndRow(table);
|
||||
window->DC.CursorMaxPos = ImMax(ms->BackupCursorMaxPos, window->DC.CursorMaxPos);
|
||||
PopFocusScope();
|
||||
|
||||
@@ -8126,6 +8220,8 @@ void ImGui::SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_d
|
||||
g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData | ImGuiItemFlags_IsMultiSelect;
|
||||
if (ms->IO.RangeSrcItem == selection_user_data)
|
||||
ms->RangeSrcPassedBy = true;
|
||||
//ms->PrevSubmittedItem = ms->CurrSubmittedItem; // Can't rely on previous g.NextItemData.SelectionUserData because NextItemData is not restored on nested multi-select.
|
||||
//ms->CurrSubmittedItem = selection_user_data;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -8274,8 +8370,31 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
if (ms->BoxSelectId != 0)
|
||||
if (ImGuiBoxSelectState* bs = GetBoxSelectState(ms->BoxSelectId))
|
||||
{
|
||||
const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(g.LastItemData.Rect);
|
||||
const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(g.LastItemData.Rect);
|
||||
ImRect item_rect = g.LastItemData.Rect;
|
||||
if (!window->DC.NavIsScrollPushableX) // FIXME: Rename to be more generic.
|
||||
if (ImGuiTable* table = g.CurrentTable)
|
||||
if (table->CurrentColumn != -1)
|
||||
{
|
||||
// FIXME: We cannot solely use current ClipRect as it includes HostClipRect.
|
||||
// However we account for ClipRect being larger than current column (e.g. when using SpanAllColumns)
|
||||
// A more generic version would be nice, but window->WorkRect.Min/Max exclude CellPadding. (#7994, #9383)
|
||||
ImGuiTableColumn* column = &table->Columns[table->CurrentColumn];
|
||||
float clip_min_x = (g.LastItemData.ItemFlags & ImGuiItemStatusFlags_HasClipRect) ? g.LastItemData.ClipRect.Min.x : window->ClipRect.Min.x;
|
||||
float clip_max_x = (g.LastItemData.ItemFlags & ImGuiItemStatusFlags_HasClipRect) ? g.LastItemData.ClipRect.Max.x : window->ClipRect.Max.x;
|
||||
if (clip_min_x != clip_max_x) // When zero sized we expect that bounds have been clamped and thus are unreliable
|
||||
{
|
||||
item_rect.Min.x = ImMax(item_rect.Min.x, ImMin(column->MinX, clip_min_x));
|
||||
item_rect.Max.x = ImMin(item_rect.Max.x, ImMax(column->MaxX, clip_max_x));
|
||||
}
|
||||
else
|
||||
{
|
||||
item_rect.Min.x = ImMax(item_rect.Min.x, column->MinX);
|
||||
item_rect.Max.x = ImMin(item_rect.Max.x, column->MaxX);
|
||||
}
|
||||
//GetForegroundDrawList()->AddRect(item_rect.Min, item_rect.Max, IM_COL32(255, 0, 255, 255));
|
||||
}
|
||||
const bool rect_overlap_curr = bs->BoxSelectRectCurr.Overlaps(item_rect);
|
||||
const bool rect_overlap_prev = bs->BoxSelectRectPrev.Overlaps(item_rect);
|
||||
if ((rect_overlap_curr && !rect_overlap_prev && !selected) || (rect_overlap_prev && !rect_overlap_curr))
|
||||
{
|
||||
if (storage->LastSelectionSize <= 0 && bs->IsStartedSetNavIdOnce)
|
||||
@@ -8287,6 +8406,9 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
{
|
||||
selected = !selected;
|
||||
MultiSelectAddSetRange(ms, selected, +1, item_data, item_data);
|
||||
#ifdef IMGUI_DEBUG_BOXSELECT
|
||||
GetForegroundDrawList()->AddRectFilled(g.LastItemData.Rect.Min, g.LastItemData.Rect.Max, selected ? IM_COL32(0, 255, 0, 200) : IM_COL32(255, 0, 0, 200));
|
||||
#endif
|
||||
}
|
||||
storage->LastSelectionSize = ImMax(storage->LastSelectionSize + 1, 1);
|
||||
}
|
||||
@@ -8400,7 +8522,6 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
|
||||
}
|
||||
if (storage->NavIdItem == item_data)
|
||||
ms->NavIdPassedBy = true;
|
||||
ms->LastSubmittedItem = item_data;
|
||||
|
||||
*p_selected = selected;
|
||||
*p_pressed = pressed;
|
||||
@@ -8416,15 +8537,20 @@ void ImGui::MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected)
|
||||
void ImGui::MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item)
|
||||
{
|
||||
// Merge contiguous spans into same request (unless NoRangeSelect is set which guarantees single-item ranges)
|
||||
// FIXME-OPT: Disabled on 2026/04/09 as this would break with any form of coarse clipping that we don't know about (e.g. TableNextColumn() return value).
|
||||
// The low-hanging fruit would be to know that ImGuiSelectionUserData are sequential indices, in which case we can trivially compare PrevSubmittedItem + RangeDir == FirstItem.
|
||||
// User can always perform this merge if required.
|
||||
#if 0
|
||||
if (ms->IO.Requests.Size > 0 && first_item == last_item && (ms->Flags & ImGuiMultiSelectFlags_NoRangeSelect) == 0)
|
||||
{
|
||||
ImGuiSelectionRequest* prev = &ms->IO.Requests.Data[ms->IO.Requests.Size - 1];
|
||||
if (prev->Type == ImGuiSelectionRequestType_SetRange && prev->RangeLastItem == ms->LastSubmittedItem && prev->Selected == selected)
|
||||
if (prev->Type == ImGuiSelectionRequestType_SetRange && prev->RangeLastItem == ms->PrevSubmittedItem && prev->Selected == selected)
|
||||
{
|
||||
prev->RangeLastItem = last_item;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ImGuiSelectionRequest req = { ImGuiSelectionRequestType_SetRange, selected, (ImS8)range_dir, (range_dir > 0) ? first_item : last_item, (range_dir > 0) ? last_item : first_item };
|
||||
ms->IO.Requests.push_back(req); // Add new request
|
||||
@@ -8662,7 +8788,8 @@ bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
|
||||
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = GetID(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
// Size default to hold ~7.25 items.
|
||||
// Fractional number of items helps seeing that we can scroll down/up without looking at scrollbar.
|
||||
@@ -8685,7 +8812,7 @@ bool ImGui::BeginListBox(const char* label, const ImVec2& size_arg)
|
||||
if (label_size.x > 0.0f)
|
||||
{
|
||||
ImVec2 label_pos = ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y);
|
||||
RenderText(label_pos, label);
|
||||
RenderText(label_pos, label, label_end, false);
|
||||
window->DC.CursorMaxPos = ImMax(window->DC.CursorMaxPos, label_pos + label_size);
|
||||
AlignTextToFramePadding();
|
||||
}
|
||||
@@ -8766,9 +8893,7 @@ bool ImGui::ListBox(const char* label, int* current_item, const char* (*getter)(
|
||||
// - PlotHistogram()
|
||||
//-------------------------------------------------------------------------
|
||||
// Plot/Graph widgets are not very good.
|
||||
// Consider writing your own, or using a third-party one, see:
|
||||
// - ImPlot https://github.com/epezent/implot
|
||||
// - others https://github.com/ocornut/imgui/wiki/Useful-Extensions
|
||||
// Consider using ImPlot (https://github.com/epezent/implot) which is much better!
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_getter)(void* data, int idx), void* data, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, const ImVec2& size_arg)
|
||||
@@ -8781,7 +8906,8 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = window->GetID(label);
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
const ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
const ImVec2 frame_size = CalcItemSize(size_arg, CalcItemWidth(), label_size.y + style.FramePadding.y * 2.0f);
|
||||
|
||||
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + frame_size);
|
||||
@@ -8880,10 +9006,11 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
|
||||
RenderTextClipped(ImVec2(frame_bb.Min.x, frame_bb.Min.y + style.FramePadding.y), frame_bb.Max, overlay_text, NULL, NULL, ImVec2(0.5f, 0.0f));
|
||||
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label);
|
||||
RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, inner_bb.Min.y), label, label_end, false);
|
||||
|
||||
// Return hovered index or -1 if none are hovered.
|
||||
// This is currently not exposed in the public API because we need a larger redesign of the whole thing, but in the short-term we are making it available in PlotEx().
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags);
|
||||
return idx_hovered;
|
||||
}
|
||||
|
||||
@@ -8913,6 +9040,7 @@ void ImGui::PlotLines(const char* label, float (*values_getter)(void* data, int
|
||||
PlotEx(ImGuiPlotType_Lines, label, values_getter, data, values_count, values_offset, overlay_text, scale_min, scale_max, graph_size);
|
||||
}
|
||||
|
||||
// Plot Histogram (the data provided _is_ histogram data. it doesn't compute the histogram of your data)
|
||||
void ImGui::PlotHistogram(const char* label, const float* values, int values_count, int values_offset, const char* overlay_text, float scale_min, float scale_max, ImVec2 graph_size, int stride)
|
||||
{
|
||||
ImGuiPlotArrayGetterData data(values, stride);
|
||||
@@ -9245,7 +9373,8 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
// Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu
|
||||
g.MenusIdSubmittedThisFrame.push_back(id);
|
||||
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
// Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent without always being a Child window)
|
||||
// This is only done for items for the menu set and not the full parent window.
|
||||
@@ -9264,8 +9393,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
|
||||
bool pressed;
|
||||
|
||||
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_NoAutoClosePopups;
|
||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoAutoClosePopups | (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnClick;
|
||||
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||
{
|
||||
@@ -9277,7 +9405,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, pos.y + window->DC.CurrLineTextBaseOffset);
|
||||
pressed = Selectable("", menu_is_open, selectable_flags, label_size);
|
||||
LogSetNextTextDecoration("[", "]");
|
||||
RenderText(text_pos, label);
|
||||
RenderText(text_pos, label, label_end, false);
|
||||
PopStyleVar();
|
||||
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
|
||||
popup_pos = ImVec2(pos.x - 1.0f - IM_TRUNC(style.ItemSpacing.x * 0.5f), text_pos.y - style.FramePadding.y + window->MenuBarHeight);
|
||||
@@ -9294,7 +9422,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
ImVec2 text_pos(window->DC.CursorPos.x, pos.y + window->DC.CurrLineTextBaseOffset);
|
||||
pressed = Selectable("", menu_is_open, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
||||
LogSetNextTextDecoration("", ">");
|
||||
RenderText(ImVec2(text_pos.x + offsets->OffsetLabel, text_pos.y), label);
|
||||
RenderText(ImVec2(text_pos.x + offsets->OffsetLabel, text_pos.y), label, label_end, false);
|
||||
if (icon_w > 0.0f)
|
||||
RenderText(ImVec2(text_pos.x + offsets->OffsetIcon, text_pos.y), icon);
|
||||
RenderArrow(window->DrawList, ImVec2(text_pos.x + offsets->OffsetMark + extra_w + g.FontSize * 0.30f, text_pos.y), GetColorU32(ImGuiCol_Text), ImGuiDir_Right);
|
||||
@@ -9303,6 +9431,14 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
if (!enabled)
|
||||
EndDisabled();
|
||||
|
||||
// Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394)
|
||||
// Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.
|
||||
if (g.ActiveId == id && g.HoveredId != id && g.ActiveIdSource == ImGuiInputSource_Mouse && IsMouseDragging(0))
|
||||
{
|
||||
ClearActiveID();
|
||||
SetKeyOwner(ImGuiKey_MouseLeft, ImGuiKeyOwner_NoOwner);
|
||||
}
|
||||
|
||||
const bool hovered = (g.HoveredId == id) && enabled && !g.NavHighlightItemUnderNav;
|
||||
if (menuset_is_open)
|
||||
PopItemFlag();
|
||||
@@ -9383,6 +9519,9 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Openable | (menu_is_open ? ImGuiItemStatusFlags_Opened : 0));
|
||||
PopID();
|
||||
|
||||
if (g.ActiveId == id && want_open)
|
||||
g.ActiveIdNoClearOnFocusLoss = true;
|
||||
|
||||
if (want_open && !menu_is_open && g.OpenPopupStack.Size > g.BeginPopupStack.Size)
|
||||
{
|
||||
// Don't reopen/recycle same menu level in the same frame if it is a different menu ID, first close the other menu and yield for a frame.
|
||||
@@ -9459,7 +9598,8 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiStyle& style = g.Style;
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
// See BeginMenuEx() for comments about this.
|
||||
const bool menuset_is_open = IsRootOfOpenMenuSet();
|
||||
@@ -9474,7 +9614,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
BeginDisabled();
|
||||
|
||||
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
|
||||
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SetNavIdOnHover;
|
||||
const ImGuiSelectableFlags selectable_flags = (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnRelease | (ImGuiSelectableFlags)ImGuiSelectableFlags_SetNavIdOnHover;
|
||||
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
|
||||
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
|
||||
{
|
||||
@@ -9486,7 +9626,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
pressed = Selectable("", selected, selectable_flags, ImVec2(label_size.x, 0.0f));
|
||||
PopStyleVar();
|
||||
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
|
||||
RenderText(text_pos, label);
|
||||
RenderText(text_pos, label, label_end, false);
|
||||
window->DC.CursorPos.x += IM_TRUNC(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar().
|
||||
}
|
||||
else
|
||||
@@ -9503,7 +9643,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, label_size.y));
|
||||
if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible)
|
||||
{
|
||||
RenderText(text_pos + ImVec2(offsets->OffsetLabel, 0.0f), label);
|
||||
RenderText(text_pos + ImVec2(offsets->OffsetLabel, 0.0f), label, label_end, false);
|
||||
if (icon_w > 0.0f)
|
||||
RenderText(text_pos + ImVec2(offsets->OffsetIcon, 0.0f), icon);
|
||||
if (shortcut_w > 0.0f)
|
||||
@@ -9517,6 +9657,17 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
|
||||
RenderCheckMark(window->DrawList, text_pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
|
||||
}
|
||||
}
|
||||
|
||||
// Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394)
|
||||
// Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.
|
||||
const ImGuiID id = g.LastItemData.ID;
|
||||
if (g.ActiveId == id && g.HoveredId != id && g.ActiveIdSource == ImGuiInputSource_Mouse && IsMouseDragging(0))
|
||||
{
|
||||
ClearActiveID();
|
||||
SetKeyOwner(ImGuiKey_MouseLeft, ImGuiKeyOwner_NoOwner);
|
||||
}
|
||||
|
||||
|
||||
IMGUI_TEST_ENGINE_ITEM_INFO(g.LastItemData.ID, label, g.LastItemData.StatusFlags | ImGuiItemStatusFlags_Checkable | (selected ? ImGuiItemStatusFlags_Checked : 0));
|
||||
if (!enabled)
|
||||
EndDisabled();
|
||||
@@ -10557,7 +10708,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
// We don't have CPU clipping primitives to clip the CloseButton (until it becomes a texture), so need to add an extra draw call (temporary in the case of vertical animation)
|
||||
const bool want_clip_rect = is_central_section && (bb.Min.x < tab_bar->ScrollingRectMinX || bb.Max.x > tab_bar->ScrollingRectMaxX);
|
||||
if (want_clip_rect)
|
||||
PushClipRect(ImVec2(ImMax(bb.Min.x, tab_bar->ScrollingRectMinX), bb.Min.y - 1), ImVec2(tab_bar->ScrollingRectMaxX, bb.Max.y), true);
|
||||
PushClipRect(ImVec2(ImClamp(bb.Min.x, tab_bar->ScrollingRectMinX, tab_bar->ScrollingRectMaxX), bb.Min.y - 1), ImVec2(tab_bar->ScrollingRectMaxX, bb.Max.y), true);
|
||||
|
||||
ImVec2 backup_cursor_max_pos = window->DC.CursorMaxPos;
|
||||
ItemSize(bb.GetSize(), style.FramePadding.y);
|
||||
@@ -10629,7 +10780,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
float rounding = style.TabRounding;
|
||||
display_draw_list->PathArcToFast(tl + ImVec2(+rounding, +rounding), rounding, 7, 9);
|
||||
display_draw_list->PathArcToFast(tr + ImVec2(-rounding, +rounding), rounding, 9, 11);
|
||||
display_draw_list->PathStroke(overline_col, 0, style.TabBarOverlineSize);
|
||||
display_draw_list->PathStroke(overline_col, style.TabBarOverlineSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -10733,7 +10884,7 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
|
||||
draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding + 0.5f, y1 + rounding + 0.5f), rounding, 6, 9);
|
||||
draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding - 0.5f, y1 + rounding + 0.5f), rounding, 9, 12);
|
||||
draw_list->PathLineTo(ImVec2(bb.Max.x - 0.5f, y2));
|
||||
draw_list->PathStroke(GetColorU32(ImGuiCol_Border), 0, g.Style.TabBorderSize);
|
||||
draw_list->PathStroke(GetColorU32(ImGuiCol_Border), g.Style.TabBorderSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10742,7 +10893,8 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
|
||||
void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImVec2 frame_padding, const char* label, ImGuiID tab_id, ImGuiID close_button_id, bool is_contents_visible, bool* out_just_closed, bool* out_text_clipped)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const char* label_end = FindRenderedTextEnd(label);
|
||||
ImVec2 label_size = CalcTextSize(label, label_end, false);
|
||||
|
||||
if (out_just_closed)
|
||||
*out_just_closed = false;
|
||||
@@ -10827,7 +10979,7 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
|
||||
}
|
||||
}
|
||||
LogSetNextTextDecoration("/", "\\");
|
||||
RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, ellipsis_max_x, label, NULL, &label_size);
|
||||
RenderTextEllipsis(draw_list, text_ellipsis_clip_bb.Min, text_ellipsis_clip_bb.Max, ellipsis_max_x, label, label_end, &label_size);
|
||||
|
||||
#if 0
|
||||
if (!is_contents_visible)
|
||||
|
||||
Vendored
+1
-2
@@ -1,12 +1,11 @@
|
||||
/* 7zFile.h -- File IO
|
||||
2023-03-05 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_FILE_H
|
||||
#define ZIP7_INC_FILE_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#define USE_WINDOWS_FILE
|
||||
// #include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_WINDOWS_FILE
|
||||
|
||||
Vendored
+4
-2
@@ -1,5 +1,5 @@
|
||||
/* 7zTypes.h -- Basic types
|
||||
2024-01-24 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_7Z_TYPES_H
|
||||
#define ZIP7_7Z_TYPES_H
|
||||
@@ -46,8 +46,9 @@ typedef int SRes;
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define MY_ALIGN_IN_STRUCT(n) __declspec(align(n))
|
||||
#if _MSC_VER > 1200
|
||||
#define MY_ALIGN(n) __declspec(align(n))
|
||||
#define MY_ALIGN(n) MY_ALIGN_IN_STRUCT(n)
|
||||
#else
|
||||
#define MY_ALIGN(n)
|
||||
#endif
|
||||
@@ -58,6 +59,7 @@ typedef int SRes;
|
||||
#define MY_ALIGN(n) alignas(n)
|
||||
*/
|
||||
#define MY_ALIGN(n) __attribute__ ((aligned(n)))
|
||||
#define MY_ALIGN_IN_STRUCT(n) MY_ALIGN(n)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
Vendored
+5
-5
@@ -1,7 +1,7 @@
|
||||
#define MY_VER_MAJOR 25
|
||||
#define MY_VER_MINOR 0
|
||||
#define MY_VER_MAJOR 26
|
||||
#define MY_VER_MINOR 1
|
||||
#define MY_VER_BUILD 0
|
||||
#define MY_VERSION_NUMBERS "25.00"
|
||||
#define MY_VERSION_NUMBERS "26.01"
|
||||
#define MY_VERSION MY_VERSION_NUMBERS
|
||||
|
||||
#ifdef MY_CPU_NAME
|
||||
@@ -10,12 +10,12 @@
|
||||
#define MY_VERSION_CPU MY_VERSION
|
||||
#endif
|
||||
|
||||
#define MY_DATE "2025-07-05"
|
||||
#define MY_DATE "2026-04-27"
|
||||
#undef MY_COPYRIGHT
|
||||
#undef MY_VERSION_COPYRIGHT_DATE
|
||||
#define MY_AUTHOR_NAME "Igor Pavlov"
|
||||
#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2025 Igor Pavlov"
|
||||
#define MY_COPYRIGHT_CR "Copyright (c) 1999-2026 Igor Pavlov"
|
||||
|
||||
#ifdef USE_COPYRIGHT_CR
|
||||
#define MY_COPYRIGHT MY_COPYRIGHT_CR
|
||||
|
||||
Vendored
+8
-2
@@ -1,11 +1,17 @@
|
||||
/* 7zWindows.h -- StdAfx
|
||||
2023-04-02 : Igor Pavlov : Public domain */
|
||||
/* 7zWindows.h -- Windows.h and related code
|
||||
Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_7Z_WINDOWS_H
|
||||
#define ZIP7_INC_7Z_WINDOWS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1950 && !defined(__clang__) // VS2026
|
||||
// <Windows.h> and some another windows files need that option
|
||||
// VS2026: wtypesbase.h: warning C4865: 'tagCLSCTX': the underlying type will change from 'int' to 'unsigned int' when '/Zc:enumTypes' is specified on the command line
|
||||
#pragma warning(disable : 4865)
|
||||
#endif
|
||||
|
||||
#if defined(__clang__)
|
||||
# pragma clang diagnostic push
|
||||
#endif
|
||||
|
||||
Vendored
+27
-27
@@ -1,5 +1,5 @@
|
||||
/* Alloc.h -- Memory allocation functions
|
||||
2024-01-22 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_ALLOC_H
|
||||
#define ZIP7_INC_ALLOC_H
|
||||
@@ -25,40 +25,40 @@ void *MyRealloc(void *address, size_t size);
|
||||
void *z7_AlignedAlloc(size_t size);
|
||||
void z7_AlignedFree(void *p);
|
||||
|
||||
extern const ISzAlloc g_Alloc;
|
||||
extern const ISzAlloc g_AlignedAlloc;
|
||||
|
||||
#ifdef _WIN32
|
||||
void *MidAlloc(size_t size);
|
||||
void MidFree(void *address);
|
||||
extern const ISzAlloc g_MidAlloc;
|
||||
#else
|
||||
#define MidAlloc(size) z7_AlignedAlloc(size)
|
||||
#define MidFree(address) z7_AlignedFree(address)
|
||||
#define g_MidAlloc g_AlignedAlloc
|
||||
#endif
|
||||
|
||||
#ifdef Z7_LARGE_PAGES
|
||||
void SetLargePageSize(void);
|
||||
#endif
|
||||
|
||||
void *MidAlloc(size_t size);
|
||||
void MidFree(void *address);
|
||||
void *BigAlloc(size_t size);
|
||||
void BigFree(void *address);
|
||||
|
||||
/* #define Z7_BIG_ALLOC_IS_ZERO_FILLED */
|
||||
#define Z7_LARGE_PAGES_FLAG_USE_HUGEPAGE (1 << 0) // PAGE_ALIGNED / MADV_HUGEPAGE
|
||||
#define Z7_LARGE_PAGES_FLAG_NO_PAGECODE (1 << 1) // no PAGE_ALIGNED / no madvise
|
||||
#define Z7_LARGE_PAGES_FLAG_NO_MADVISE (1 << 2) // PAGE_ALIGNED / no madvise : for THP=always
|
||||
#define Z7_LARGE_PAGES_FLAG_NO_HUGEPAGE (1 << 3) // PAGE_ALIGNED / MADV_NOHUGEPAGE
|
||||
#define Z7_LARGE_PAGES_FLAG_FAIL_STOP (1 << 15) // for benchmarks
|
||||
#define Z7_LARGE_PAGES_FLAG_DIRECT_PAGE_SIZE (1 << 16)
|
||||
#define Z7_LARGE_PAGES_FLAG_DIRECT_THRESHOLD (1 << 17)
|
||||
|
||||
void z7_LargePage_Set(UInt32 flags, size_t pageSize, size_t threshold);
|
||||
|
||||
void *BigAlloc(size_t size);
|
||||
void BigFree(void *address);
|
||||
extern const ISzAlloc g_BigAlloc;
|
||||
#else
|
||||
|
||||
#define MidAlloc(size) z7_AlignedAlloc(size)
|
||||
#define MidFree(address) z7_AlignedFree(address)
|
||||
#define BigAlloc(size) z7_AlignedAlloc(size)
|
||||
#define BigFree(address) z7_AlignedFree(address)
|
||||
|
||||
#define BigAlloc(size) MidAlloc(size)
|
||||
#define BigFree(address) MidFree(address)
|
||||
#define g_BigAlloc g_MidAlloc
|
||||
#endif
|
||||
|
||||
extern const ISzAlloc g_Alloc;
|
||||
|
||||
#ifdef _WIN32
|
||||
extern const ISzAlloc g_BigAlloc;
|
||||
extern const ISzAlloc g_MidAlloc;
|
||||
#else
|
||||
#define g_BigAlloc g_AlignedAlloc
|
||||
#define g_MidAlloc g_AlignedAlloc
|
||||
#endif
|
||||
|
||||
extern const ISzAlloc g_AlignedAlloc;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
Vendored
+7
-1
@@ -54,6 +54,12 @@
|
||||
#pragma GCC diagnostic ignored "-Wexcess-padding"
|
||||
#endif
|
||||
|
||||
#if defined(Z7_APPLE_CLANG_VERSION) && __clang_major__ >= 21
|
||||
// warning: function MyAlloc might be an allocator wrapper
|
||||
// clang in xcode: clang 21.0.0
|
||||
#pragma GCC diagnostic ignored "-Wallocator-wrappers"
|
||||
#endif
|
||||
|
||||
#if __clang_major__ >= 16
|
||||
#pragma GCC diagnostic ignored "-Wunsafe-buffer-usage"
|
||||
#endif
|
||||
@@ -72,7 +78,7 @@
|
||||
|
||||
#endif // __clang__
|
||||
|
||||
#if defined(_WIN32) && defined(__clang__) && __clang_major__ >= 16
|
||||
#if defined(__clang__) && __clang_major__ >= 16
|
||||
// #pragma GCC diagnostic ignored "-Wcast-function-type-strict"
|
||||
#define Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION \
|
||||
_Pragma("GCC diagnostic ignored \"-Wcast-function-type-strict\"")
|
||||
|
||||
Vendored
+20
-2
@@ -31,7 +31,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
|
||||
#define MY_CPU_NAME "x32"
|
||||
#define MY_CPU_SIZEOF_POINTER 4
|
||||
#else
|
||||
#define MY_CPU_NAME "x64"
|
||||
#if defined(__APX_EGPR__) || defined(__EGPR__)
|
||||
#define MY_CPU_NAME "x64-apx"
|
||||
#define MY_CPU_AMD64_APX
|
||||
#else
|
||||
#define MY_CPU_NAME "x64"
|
||||
#endif
|
||||
#define MY_CPU_SIZEOF_POINTER 8
|
||||
#endif
|
||||
#define MY_CPU_64BIT
|
||||
@@ -249,11 +254,12 @@ MY_CPU_64BIT means that processor can work with 64-bit registers.
|
||||
#endif
|
||||
|
||||
|
||||
// _LITTLE_ENDIAN macro can be defined for big-endian platform with some compilers
|
||||
|
||||
#if defined(MY_CPU_X86_OR_AMD64) \
|
||||
|| defined(MY_CPU_ARM_LE) \
|
||||
|| defined(MY_CPU_ARM64_LE) \
|
||||
|| defined(MY_CPU_IA64_LE) \
|
||||
|| defined(_LITTLE_ENDIAN) \
|
||||
|| defined(__LITTLE_ENDIAN__) \
|
||||
|| defined(__ARMEL__) \
|
||||
|| defined(__THUMBEL__) \
|
||||
@@ -596,8 +602,20 @@ problem-4 : performace:
|
||||
#define SetBe32a(p, v) { *(UInt32 *)(void *)(p) = (v); }
|
||||
#define SetBe16a(p, v) { *(UInt16 *)(void *)(p) = (v); }
|
||||
|
||||
// gcc and clang for powerpc can transform load byte access to load reverse word access.
|
||||
// sp we can use byte access instead of word access. Z7_BSWAP64 cab be slow
|
||||
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED) && defined(MY_CPU_64BIT)
|
||||
#define GetUi64a(p) Z7_BSWAP64 (*(const UInt64 *)(const void *)(p))
|
||||
#else
|
||||
#define GetUi64a(p) GetUi64(p)
|
||||
#endif
|
||||
|
||||
#if 1 && defined(Z7_CPU_FAST_BSWAP_SUPPORTED)
|
||||
#define GetUi32a(p) Z7_BSWAP32 (*(const UInt32 *)(const void *)(p))
|
||||
#else
|
||||
#define GetUi32a(p) GetUi32(p)
|
||||
#endif
|
||||
|
||||
#define GetUi16a(p) GetUi16(p)
|
||||
#define SetUi32a(p, v) SetUi32(p, v)
|
||||
#define SetUi16a(p, v) SetUi16(p, v)
|
||||
|
||||
Vendored
+7
-7
@@ -1,5 +1,5 @@
|
||||
/* Precomp.h -- precompilation file
|
||||
2024-01-25 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef ZIP7_INC_PRECOMP_H
|
||||
#define ZIP7_INC_PRECOMP_H
|
||||
@@ -40,18 +40,18 @@
|
||||
#endif
|
||||
*/
|
||||
|
||||
#ifndef Z7_LARGE_PAGES
|
||||
#if !defined(Z7_NO_LARGE_PAGES) && !defined(UNDER_CE)
|
||||
#define Z7_LARGE_PAGES 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
this "Precomp.h" file must be included before <windows.h>,
|
||||
if we want to define _WIN32_WINNT before <windows.h>.
|
||||
*/
|
||||
|
||||
#ifndef Z7_LARGE_PAGES
|
||||
#ifndef Z7_NO_LARGE_PAGES
|
||||
#define Z7_LARGE_PAGES 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef Z7_LONG_PATH
|
||||
#ifndef Z7_NO_LONG_PATH
|
||||
#define Z7_LONG_PATH 1
|
||||
|
||||
Vendored
+23
-29
@@ -1,5 +1,5 @@
|
||||
/* 7zArcIn.c -- 7z Input functions
|
||||
2023-09-07 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -289,9 +289,9 @@ static SRes WaitId(CSzData *sd, UInt32 id)
|
||||
}
|
||||
}
|
||||
|
||||
static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)
|
||||
static SRes RememberBitVector(CSzData *sd, size_t numItems, const Byte **v)
|
||||
{
|
||||
const UInt32 numBytes = (numItems + 7) >> 3;
|
||||
const size_t numBytes = (numItems + 7) >> 3;
|
||||
if (numBytes > sd->Size)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
*v = sd->Data;
|
||||
@@ -317,11 +317,11 @@ static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
|
||||
return sum;
|
||||
}
|
||||
|
||||
static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAllocPtr alloc)
|
||||
static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, size_t numItems, Byte **v, ISzAllocPtr alloc)
|
||||
{
|
||||
Byte allAreDefined;
|
||||
Byte *v2;
|
||||
const UInt32 numBytes = (numItems + 7) >> 3;
|
||||
const size_t numBytes = (numItems + 7) >> 3;
|
||||
*v = NULL;
|
||||
SZ_READ_BYTE(allAreDefined)
|
||||
if (numBytes == 0)
|
||||
@@ -345,9 +345,9 @@ static Z7_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, I
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
|
||||
static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, size_t numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
|
||||
{
|
||||
UInt32 i;
|
||||
size_t i;
|
||||
CSzData sd;
|
||||
UInt32 *vals;
|
||||
const Byte *defs;
|
||||
@@ -366,7 +366,7 @@ static Z7_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *c
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
|
||||
static SRes ReadBitUi32s(CSzData *sd, size_t numItems, CSzBitUi32s *crcs, ISzAllocPtr alloc)
|
||||
{
|
||||
SzBitUi32s_Free(crcs, alloc);
|
||||
RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc))
|
||||
@@ -1027,42 +1027,39 @@ static SRes SzReadAndDecodePackedStreams(
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
// (size & 1) == 0
|
||||
// (data) is aligned for 2-bytes
|
||||
static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets)
|
||||
{
|
||||
size_t pos = 0;
|
||||
const Byte *p, *lim;
|
||||
*offsets++ = 0;
|
||||
if (numFiles == 0)
|
||||
return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE;
|
||||
if (size < 2)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
if (data[size - 2] != 0 || data[size - 1] != 0)
|
||||
lim = data + size;
|
||||
if (*(const UInt16 *)(const void *)(lim - 2))
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
p = data;
|
||||
do
|
||||
{
|
||||
const Byte *p;
|
||||
if (pos == size)
|
||||
if (p >= lim)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
for (p = data + pos;
|
||||
#ifdef _WIN32
|
||||
*(const UInt16 *)(const void *)p != 0
|
||||
#else
|
||||
p[0] != 0 || p[1] != 0
|
||||
#endif
|
||||
; p += 2);
|
||||
pos = (size_t)(p - data) + 2;
|
||||
*offsets++ = (pos >> 1);
|
||||
for (; *(const UInt16 *)(const void *)p; p += 2);
|
||||
p += 2;
|
||||
*offsets++ = (size_t)(p - data) >> 1;
|
||||
}
|
||||
while (--numFiles);
|
||||
return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
|
||||
return (p == lim) ? SZ_OK : SZ_ERROR_ARCHIVE;
|
||||
}
|
||||
|
||||
static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
|
||||
static Z7_NO_INLINE SRes ReadTime(CSzBitUi64s *p, size_t num,
|
||||
CSzData *sd2,
|
||||
const CBuf *tempBufs, UInt32 numTempBufs,
|
||||
ISzAllocPtr alloc)
|
||||
{
|
||||
CSzData sd;
|
||||
UInt32 i;
|
||||
size_t i;
|
||||
CNtfsFileTime *vals;
|
||||
Byte *defs;
|
||||
Byte external;
|
||||
@@ -1215,6 +1212,7 @@ static SRes SzReadHeader2(
|
||||
{
|
||||
namesSize = (size_t)size - 1;
|
||||
namesData = sd->Data;
|
||||
SKIP_DATA(sd, namesSize)
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1226,15 +1224,11 @@ static SRes SzReadHeader2(
|
||||
namesSize = (tempBufs)[index].size;
|
||||
}
|
||||
|
||||
if ((namesSize & 1) != 0)
|
||||
if (namesSize & 1)
|
||||
return SZ_ERROR_ARCHIVE;
|
||||
MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain)
|
||||
MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain)
|
||||
RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))
|
||||
if (external == 0)
|
||||
{
|
||||
SKIP_DATA(sd, namesSize)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case k7zIdEmptyStream:
|
||||
|
||||
Vendored
+208
-39
@@ -1,5 +1,5 @@
|
||||
/* Alloc.c -- Memory allocation functions
|
||||
2024-02-18 : Igor Pavlov : Public domain */
|
||||
: Igor Pavlov : Public domain */
|
||||
|
||||
#include "Precomp.h"
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
#endif
|
||||
|
||||
// #define SZ_ALLOC_DEBUG
|
||||
/* #define SZ_ALLOC_DEBUG */
|
||||
|
||||
/* use SZ_ALLOC_DEBUG to debug alloc/free operations */
|
||||
#ifdef SZ_ALLOC_DEBUG
|
||||
|
||||
@@ -34,9 +32,10 @@
|
||||
static int g_allocCount = 0;
|
||||
#ifdef _WIN32
|
||||
static int g_allocCountMid = 0;
|
||||
#ifdef Z7_LARGE_PAGES
|
||||
static int g_allocCountBig = 0;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define CONVERT_INT_TO_STR(charType, tempSize) \
|
||||
char temp[tempSize]; unsigned i = 0; \
|
||||
@@ -140,8 +139,10 @@ static void PrintAddr(void *p)
|
||||
#else
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef Z7_LARGE_PAGES
|
||||
#define PRINT_ALLOC(name, cnt, size, ptr)
|
||||
#endif
|
||||
#endif
|
||||
#define PRINT_FREE(name, cnt, ptr)
|
||||
#define Print(s)
|
||||
#define PrintLn()
|
||||
@@ -245,6 +246,7 @@ void MidFree(void *address)
|
||||
}
|
||||
|
||||
#ifdef Z7_LARGE_PAGES
|
||||
// #pragma message("Z7_LARGE_PAGES")
|
||||
|
||||
#ifdef MEM_LARGE_PAGES
|
||||
#define MY_MEM_LARGE_PAGES MEM_LARGE_PAGES
|
||||
@@ -253,32 +255,14 @@ void MidFree(void *address)
|
||||
#endif
|
||||
|
||||
extern
|
||||
SIZE_T g_LargePageSize;
|
||||
SIZE_T g_LargePageSize = 0;
|
||||
typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID);
|
||||
|
||||
void SetLargePageSize(void)
|
||||
{
|
||||
SIZE_T size;
|
||||
#ifdef Z7_USE_DYN_GetLargePageMinimum
|
||||
Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
|
||||
|
||||
const
|
||||
Func_GetLargePageMinimum fn =
|
||||
(Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"GetLargePageMinimum");
|
||||
if (!fn)
|
||||
return;
|
||||
size = fn();
|
||||
#else
|
||||
size = GetLargePageMinimum();
|
||||
#endif
|
||||
if (size == 0 || (size & (size - 1)) != 0)
|
||||
return;
|
||||
g_LargePageSize = size;
|
||||
}
|
||||
|
||||
#endif // Z7_LARGE_PAGES
|
||||
size_t g_LargePageSize;
|
||||
size_t g_LargePageSize = 0;
|
||||
extern
|
||||
size_t g_LargePageThresholdMin;
|
||||
size_t g_LargePageThresholdMin = 0;
|
||||
extern
|
||||
UInt32 g_LargePageFlags;
|
||||
UInt32 g_LargePageFlags = 0;
|
||||
|
||||
void *BigAlloc(size_t size)
|
||||
{
|
||||
@@ -289,12 +273,10 @@ void *BigAlloc(size_t size)
|
||||
|
||||
#ifdef Z7_LARGE_PAGES
|
||||
{
|
||||
SIZE_T ps = g_LargePageSize;
|
||||
if (ps != 0 && ps <= (1 << 30) && size > (ps / 2))
|
||||
const size_t ps = g_LargePageSize - 1;
|
||||
if (ps < (1u << 30) && size > g_LargePageThresholdMin)
|
||||
{
|
||||
size_t size2;
|
||||
ps--;
|
||||
size2 = (size + ps) & ~ps;
|
||||
const size_t size2 = (size + ps) & ~ps;
|
||||
if (size2 >= size)
|
||||
{
|
||||
void *p = VirtualAlloc(NULL, size2, MEM_COMMIT | MY_MEM_LARGE_PAGES, PAGE_READWRITE);
|
||||
@@ -303,6 +285,8 @@ void *BigAlloc(size_t size)
|
||||
PRINT_ALLOC("Alloc-BM ", g_allocCountMid, size2, p)
|
||||
return p;
|
||||
}
|
||||
if (g_LargePageFlags & Z7_LARGE_PAGES_FLAG_FAIL_STOP)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -317,6 +301,7 @@ void BigFree(void *address)
|
||||
MidFree(address);
|
||||
}
|
||||
|
||||
#endif // Z7_LARGE_PAGES
|
||||
#endif // _WIN32
|
||||
|
||||
|
||||
@@ -327,9 +312,12 @@ const ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
#ifdef _WIN32
|
||||
static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return MidAlloc(size); }
|
||||
static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) MidFree(address); }
|
||||
const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
|
||||
#endif
|
||||
|
||||
#if defined(Z7_LARGE_PAGES)
|
||||
static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p) return BigAlloc(size); }
|
||||
static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p) BigFree(address); }
|
||||
const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree };
|
||||
const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree };
|
||||
#endif
|
||||
|
||||
@@ -371,10 +359,16 @@ typedef
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) \
|
||||
&& (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \
|
||||
|| defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L))
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h> // for _POSIX_ADVISORY_INFO : for some linux
|
||||
#if (defined(Z7_ALLOC_NO_OFFSET_ALLOCATOR) \
|
||||
|| defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) \
|
||||
|| defined(_POSIX_ADVISORY_INFO) && (_POSIX_ADVISORY_INFO >= 200112L) \
|
||||
|| defined(__APPLE__) \
|
||||
/* || defined(__linux__) */)
|
||||
#define USE_posix_memalign
|
||||
// #pragma message("USE_posix_memalign")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef USE_posix_memalign
|
||||
@@ -488,6 +482,181 @@ static void SzAlignedFree(ISzAllocPtr pp, void *address)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifdef Z7_LARGE_PAGES
|
||||
|
||||
#if 0 // 1 for debug
|
||||
#include <stdio.h>
|
||||
#include <string.h> // for strerror()
|
||||
#define PRF(x) x
|
||||
#else
|
||||
#define PRF(x)
|
||||
#endif
|
||||
|
||||
#ifdef USE_posix_memalign
|
||||
/* madvise():
|
||||
glibc <= 2.19 : _BSD_SOURCE
|
||||
glibc > 2.19 : _DEFAULT_SOURCE
|
||||
*/
|
||||
/* && (defined(_DEFAULT_SOURCE) || defined(_BSD_SOURCE)) */
|
||||
#if 1 && !defined(Z7_NO_MADVISE) && \
|
||||
(defined(__linux__) || defined(__unix__) || defined(__APPLE__))
|
||||
#include <sys/mman.h> // for madvise
|
||||
// #pragma message("sys/mman.h")
|
||||
#if (defined(MADV_HUGEPAGE) && defined(MADV_NOHUGEPAGE))
|
||||
#define Z7_USE_BIG_ALLOC_MADVISE
|
||||
// #pragma message("Z7_USE_BIG_ALLOC_MADVISE")
|
||||
#endif
|
||||
#endif
|
||||
#endif // USE_posix_memalign
|
||||
|
||||
#ifdef Z7_USE_BIG_ALLOC_MADVISE
|
||||
#define LARGE_PAGE_SIZE_DEFAULT (1 << 21)
|
||||
#else
|
||||
#define LARGE_PAGE_SIZE_DEFAULT 0
|
||||
#endif
|
||||
|
||||
extern
|
||||
size_t g_LargePageSize;
|
||||
size_t g_LargePageSize = LARGE_PAGE_SIZE_DEFAULT;
|
||||
extern
|
||||
size_t g_LargePageThresholdMin;
|
||||
size_t g_LargePageThresholdMin = LARGE_PAGE_SIZE_DEFAULT / 2;
|
||||
extern
|
||||
UInt32 g_LargePageFlags;
|
||||
UInt32 g_LargePageFlags = 0;
|
||||
|
||||
void *BigAlloc(size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
#ifdef USE_posix_memalign
|
||||
{
|
||||
const size_t pageSize = g_LargePageSize;
|
||||
void *buf = NULL; // on Linux (and other systems), posix_memalign() does not modify memptr on failure (POSIX.1-2008 TC2).
|
||||
PRF(printf("\nBigAlloc 0x%08x=%5uMB", (unsigned)(size), (unsigned)(size >> 20));)
|
||||
if (pageSize && size > g_LargePageThresholdMin)
|
||||
{
|
||||
int res;
|
||||
const size_t mask = pageSize - 1;
|
||||
/* we can allocate aligned size, so data at the end of buffer also will use huge page
|
||||
if (size2 for madvise() is not aligned for huge page size)
|
||||
{ Last data block will use small pages. It reduces memory allocation,
|
||||
but last data block with small pages can work slower.
|
||||
It's useful, if we have very large HUGE_PAGE: 32MB or 512MB. }
|
||||
*/
|
||||
size_t size2 = (size + mask) & ~mask;
|
||||
if (size2 < size || (size & mask) <= g_LargePageThresholdMin)
|
||||
size2 = size;
|
||||
res = posix_memalign(&buf, pageSize, size2);
|
||||
PRF(printf(" posix_memalign size=0x%08x=%5uMB align=%u",
|
||||
(unsigned)(size2), (unsigned)(size2 >> 20), (unsigned)pageSize);)
|
||||
PRF(printf(" buf=%p", (void *)buf);)
|
||||
if (res == 0)
|
||||
{
|
||||
#ifdef Z7_USE_BIG_ALLOC_MADVISE
|
||||
if ((g_LargePageFlags & Z7_LARGE_PAGES_FLAG_NO_MADVISE) == 0)
|
||||
{
|
||||
// Advise the kernel to use huge pages for this memory range
|
||||
// MADV_HUGEPAGE / MADV_NOHUGEPAGE : since Linux 2.6.38
|
||||
// madvise() only operates on whole pages, therefore addr must be page-aligned (4KB/8KB/16KB/64KB).
|
||||
// The value of size is rounded up to a multiple of page size.
|
||||
PRF(printf(" madvise g_LargePageFlags=%x", (unsigned)g_LargePageFlags);)
|
||||
res = madvise(buf, size2, (g_LargePageFlags & Z7_LARGE_PAGES_FLAG_NO_HUGEPAGE) ? MADV_NOHUGEPAGE : MADV_HUGEPAGE);
|
||||
if (res)
|
||||
{
|
||||
PRF(printf("\nERROR res=%d, errno=%d=%s\n", res, (int)errno, strerror(errno));)
|
||||
if (g_LargePageFlags & Z7_LARGE_PAGES_FLAG_FAIL_STOP)
|
||||
{
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // Z7_USE_BIG_ALLOC_MADVISE
|
||||
PRF(printf("\n");)
|
||||
return buf;
|
||||
}
|
||||
PRF(printf("\nERROR res=%d=%s\n", res, strerror(res));)
|
||||
if (g_LargePageFlags & Z7_LARGE_PAGES_FLAG_FAIL_STOP)
|
||||
return NULL;
|
||||
// (res == ENOMEM) "Out of memory" is possible, if pageSize is too big.
|
||||
// so we do second attempt with smaller alignment
|
||||
}
|
||||
}
|
||||
#endif // !USE_posix_memalign
|
||||
PRF(printf(" z7_AlignedAlloc size=0x%08x=%5uMB\n", (unsigned)(size), (unsigned)(size >> 20));)
|
||||
return z7_AlignedAlloc(size);
|
||||
}
|
||||
|
||||
|
||||
void BigFree(void *address)
|
||||
{
|
||||
z7_AlignedFree(address);
|
||||
}
|
||||
#endif // Z7_LARGE_PAGES
|
||||
#endif // !_WIN32
|
||||
|
||||
|
||||
#ifdef Z7_LARGE_PAGES
|
||||
void z7_LargePage_Set(UInt32 flags, size_t pageSize, size_t threshold)
|
||||
{
|
||||
g_LargePageFlags = flags;
|
||||
|
||||
#ifdef _WIN32
|
||||
if ((flags & Z7_LARGE_PAGES_FLAG_USE_HUGEPAGE) == 0)
|
||||
{
|
||||
g_LargePageSize = 0;
|
||||
g_LargePageThresholdMin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((flags & Z7_LARGE_PAGES_FLAG_DIRECT_PAGE_SIZE) == 0)
|
||||
{
|
||||
#ifdef Z7_USE_DYN_GetLargePageMinimum
|
||||
Z7_DIAGNOSTIC_IGNORE_CAST_FUNCTION
|
||||
typedef SIZE_T (WINAPI *Func_GetLargePageMinimum)(VOID);
|
||||
const
|
||||
Func_GetLargePageMinimum fn =
|
||||
(Func_GetLargePageMinimum) Z7_CAST_FUNC_C GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"GetLargePageMinimum");
|
||||
if (fn)
|
||||
pageSize = fn();
|
||||
else
|
||||
pageSize = 0;
|
||||
#else
|
||||
pageSize = GetLargePageMinimum();
|
||||
#endif
|
||||
if (pageSize & (pageSize - 1))
|
||||
pageSize = 0;
|
||||
}
|
||||
g_LargePageSize = pageSize;
|
||||
if ((flags & Z7_LARGE_PAGES_FLAG_DIRECT_THRESHOLD) == 0)
|
||||
threshold = pageSize / 2;
|
||||
g_LargePageThresholdMin = threshold;
|
||||
}
|
||||
|
||||
#else // !_WIN32
|
||||
|
||||
if (flags & Z7_LARGE_PAGES_FLAG_NO_PAGECODE)
|
||||
{
|
||||
g_LargePageSize = 0;
|
||||
g_LargePageThresholdMin = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((flags & Z7_LARGE_PAGES_FLAG_DIRECT_PAGE_SIZE) == 0)
|
||||
pageSize = LARGE_PAGE_SIZE_DEFAULT;
|
||||
g_LargePageSize = pageSize;
|
||||
if ((flags & Z7_LARGE_PAGES_FLAG_DIRECT_THRESHOLD) == 0)
|
||||
threshold = pageSize / 2;
|
||||
g_LargePageThresholdMin = threshold;
|
||||
}
|
||||
// PRF(printf("\ng_LargePageSize=%x g_LargePageThresholdMin = %x g_LargePageFlags = %x", (unsigned)g_LargePageSize, (unsigned)g_LargePageThresholdMin, (unsigned)g_LargePageFlags);)
|
||||
#endif // !_WIN32
|
||||
}
|
||||
#endif // Z7_LARGE_PAGES
|
||||
|
||||
const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree };
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -859,7 +859,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
|
||||
|
||||
#if defined(__GLIBC__) && (__GLIBC__ * 100 + __GLIBC_MINOR__ >= 216)
|
||||
#define Z7_GETAUXV_AVAILABLE
|
||||
#else
|
||||
#elif !defined(__QNXNTO__)
|
||||
// #pragma message("=== is not NEW GLIBC === ")
|
||||
#if defined __has_include
|
||||
#if __has_include (<sys/auxv.h>)
|
||||
@@ -877,7 +877,7 @@ BoolInt CPU_IsSupported_AES (void) { return APPLE_CRYPTO_SUPPORT_VAL; }
|
||||
|
||||
#ifdef USE_HWCAP
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||
static unsigned long MY_getauxval(int aux)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
Vendored
+1
-1
@@ -598,7 +598,7 @@ void MatchFinder_Init(void *_p)
|
||||
|
||||
#ifdef MY_CPU_X86_OR_AMD64
|
||||
#if defined(__clang__) && (__clang_major__ >= 4) \
|
||||
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40701)
|
||||
|| defined(Z7_GCC_VERSION) && (Z7_GCC_VERSION >= 40900)
|
||||
// || defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1900)
|
||||
|
||||
#define USE_LZFIND_SATUR_SUB_128
|
||||
|
||||
Vendored
+2
-3
@@ -2351,10 +2351,9 @@ static void LzmaEnc_Construct(CLzmaEnc *p)
|
||||
|
||||
CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc)
|
||||
{
|
||||
void *p;
|
||||
p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));
|
||||
CLzmaEncHandle p = (CLzmaEncHandle)ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc));
|
||||
if (p)
|
||||
LzmaEnc_Construct((CLzmaEnc *)p);
|
||||
LzmaEnc_Construct(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+18
-4
@@ -153,6 +153,17 @@ static void PrintProcess_Info()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* if we send (stackSize=0) to CreateThread(), it will
|
||||
use default value PE::SizeOfStackReserve from exe file.
|
||||
PE::SizeOfStackReserve == 1 MiB in exe file with default linker options.
|
||||
Windows aligns specified value to the next 64 KB range. */
|
||||
static const unsigned k_StackSize_ReserveSize =
|
||||
#ifdef UNDER_CE
|
||||
1 << 17;
|
||||
#else
|
||||
1 << 20;
|
||||
#endif
|
||||
|
||||
WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||
{
|
||||
/* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */
|
||||
@@ -160,12 +171,15 @@ WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param)
|
||||
#ifdef USE_THREADS_CreateThread
|
||||
|
||||
DWORD threadId;
|
||||
*p = CreateThread(NULL, 0, func, param, 0, &threadId);
|
||||
*p = CreateThread(NULL, k_StackSize_ReserveSize, func, param, STACK_SIZE_PARAM_IS_A_RESERVATION, &threadId);
|
||||
|
||||
#else
|
||||
|
||||
#define CALL_beginthreadex(func2, param2, flags, threadIdPtr) \
|
||||
((HANDLE)(_beginthreadex(NULL, k_StackSize_ReserveSize, func2, param2, (flags) | STACK_SIZE_PARAM_IS_A_RESERVATION, threadIdPtr)))
|
||||
|
||||
unsigned threadId;
|
||||
*p = (HANDLE)(_beginthreadex(NULL, 0, func, param, 0, &threadId));
|
||||
*p = CALL_beginthreadex(func, param, 0, &threadId);
|
||||
|
||||
#if 0 // 1 : for debug
|
||||
{
|
||||
@@ -223,7 +237,7 @@ WRes Thread_Create_With_Affinity(CThread *p, THREAD_FUNC_TYPE func, LPVOID param
|
||||
HANDLE h;
|
||||
WRes wres;
|
||||
unsigned threadId;
|
||||
h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId));
|
||||
h = CALL_beginthreadex(func, param, CREATE_SUSPENDED, &threadId);
|
||||
*p = h;
|
||||
wres = HandleToWRes(h);
|
||||
if (h)
|
||||
@@ -272,7 +286,7 @@ WRes Thread_Create_With_Group(CThread *p, THREAD_FUNC_TYPE func, LPVOID param, u
|
||||
HANDLE h;
|
||||
WRes wres;
|
||||
unsigned threadId;
|
||||
h = (HANDLE)(_beginthreadex(NULL, 0, func, param, CREATE_SUSPENDED, &threadId));
|
||||
h = CALL_beginthreadex(func, param, CREATE_SUSPENDED, &threadId);
|
||||
*p = h;
|
||||
wres = HandleToWRes(h);
|
||||
if (h)
|
||||
|
||||
Vendored
+3
-3
@@ -279,7 +279,7 @@ SRes Xz_StateCoder_Bc_SetFromMethod_Func(IStateCoder *p, UInt64 id,
|
||||
decoder = (CXzBcFilterState *)ISzAlloc_Alloc(alloc, sizeof(CXzBcFilterState));
|
||||
if (!decoder)
|
||||
return SZ_ERROR_MEM;
|
||||
decoder->buf = ISzAlloc_Alloc(alloc, BRA_BUF_SIZE);
|
||||
decoder->buf = (Byte *)ISzAlloc_Alloc(alloc, BRA_BUF_SIZE);
|
||||
if (!decoder->buf)
|
||||
{
|
||||
ISzAlloc_Free(alloc, decoder);
|
||||
@@ -1243,7 +1243,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||
UInt32 digest32[XZ_CHECK_SIZE_MAX / 4];
|
||||
p->state = XZ_STATE_BLOCK_HEADER;
|
||||
p->pos = 0;
|
||||
if (XzCheck_Final(&p->check, (void *)digest32) && memcmp(digest32, p->buf, checkSize) != 0)
|
||||
if (XzCheck_Final(&p->check, (Byte *)(void *)digest32) && memcmp(digest32, p->buf, checkSize) != 0)
|
||||
return SZ_ERROR_CRC;
|
||||
if (p->decodeOnlyOneBlock)
|
||||
{
|
||||
@@ -1292,7 +1292,7 @@ SRes XzUnpacker_Code(CXzUnpacker *p, Byte *dest, SizeT *destLen,
|
||||
p->state = XZ_STATE_STREAM_INDEX_CRC;
|
||||
p->indexSize += 4;
|
||||
p->pos = 0;
|
||||
Sha256_Final(&p->sha, (void *)digest32);
|
||||
Sha256_Final(&p->sha, (Byte *)(void *)digest32);
|
||||
if (memcmp(digest32, p->shaDigest32, SHA256_DIGEST_SIZE) != 0)
|
||||
return SZ_ERROR_CRC;
|
||||
}
|
||||
|
||||
Vendored
+3
@@ -7,6 +7,7 @@ add_library(vixl
|
||||
include/vixl/aarch64/decoder-aarch64.h
|
||||
include/vixl/aarch64/decoder-constants-aarch64.h
|
||||
include/vixl/aarch64/decoder-visitor-map-aarch64.h
|
||||
include/vixl/aarch64/debugger-aarch64.h
|
||||
include/vixl/aarch64/disasm-aarch64.h
|
||||
include/vixl/aarch64/instructions-aarch64.h
|
||||
include/vixl/aarch64/macro-assembler-aarch64.h
|
||||
@@ -31,6 +32,7 @@ add_library(vixl
|
||||
src/aarch64/cpu-aarch64.cc
|
||||
src/aarch64/cpu-features-auditor-aarch64.cc
|
||||
src/aarch64/decoder-aarch64.cc
|
||||
src/aarch64/debugger-aarch64.cc
|
||||
src/aarch64/disasm-aarch64.cc
|
||||
src/aarch64/instructions-aarch64.cc
|
||||
src/aarch64/logic-aarch64.cc
|
||||
@@ -39,6 +41,7 @@ add_library(vixl
|
||||
src/aarch64/operands-aarch64.cc
|
||||
src/aarch64/pointer-auth-aarch64.cc
|
||||
src/aarch64/registers-aarch64.cc
|
||||
src/aarch64/simulator-aarch64.cc
|
||||
src/code-buffer-vixl.cc
|
||||
src/compiler-intrinsics-vixl.cc
|
||||
src/cpu-features.cc
|
||||
|
||||
Vendored
+116
-48
@@ -1,14 +1,16 @@
|
||||
VIXL: Armv8 Runtime Code Generation Library, 3.0.0
|
||||
==================================================
|
||||
VIXL: Arm Runtime Code Generation Library
|
||||
=========================================
|
||||
|
||||
Contents:
|
||||
|
||||
* Overview
|
||||
* Licence
|
||||
* Requirements
|
||||
* Known limitations
|
||||
* Usage
|
||||
|
||||
* [Overview](#overview)
|
||||
* [Licence](#licence)
|
||||
* [Requirements](#requirements)
|
||||
* [Versioning](#versioning)
|
||||
* [Supported Arm Architecture Features](#supported-arm-architecture-features)
|
||||
* [Known limitations](#known-limitations)
|
||||
* [Bug reports](#bug-reports)
|
||||
* [Usage](#usage)
|
||||
|
||||
Overview
|
||||
========
|
||||
@@ -16,17 +18,16 @@ Overview
|
||||
VIXL contains three components.
|
||||
|
||||
1. Programmatic **assemblers** to generate A64, A32 or T32 code at runtime. The
|
||||
assemblers abstract some of the constraints of each ISA; for example, most
|
||||
assemblers abstract some of the constraints of each ISA; for example, some
|
||||
instructions support any immediate.
|
||||
2. **Disassemblers** that can print any instruction emitted by the assemblers.
|
||||
3. A **simulator** that can simulate any instruction emitted by the A64
|
||||
3. An **A64 simulator** that can simulate any instruction emitted by the A64
|
||||
assembler. The simulator allows generated code to be run on another
|
||||
architecture without the need for a full ISA model.
|
||||
|
||||
The VIXL git repository can be found [on 'https://git.linaro.org'][vixl].
|
||||
The VIXL git repository can be found [on GitLab][vixl].
|
||||
|
||||
Changes from previous versions of VIXL can be found in the
|
||||
[Changelog](doc/changelog.md).
|
||||
Build status: [](https://gitlab.arm.com/runtimes/vixl/-/pipelines)
|
||||
|
||||
|
||||
Licence
|
||||
@@ -35,32 +36,78 @@ Licence
|
||||
This software is covered by the licence described in the [LICENCE](LICENCE)
|
||||
file.
|
||||
|
||||
Contributions, as pull requests or via other means, are accepted under the terms
|
||||
of the same [LICENCE](LICENCE).
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
To build VIXL the following software is required:
|
||||
|
||||
1. Python 2.7
|
||||
1. Python 3.5+
|
||||
2. SCons 2.0
|
||||
3. GCC 4.8+ or Clang 3.4+
|
||||
3. GCC 4.8+ or Clang 4.0+
|
||||
|
||||
A 64-bit host machine is required, implementing an LP64 data model. VIXL has
|
||||
been tested using GCC on AArch64 Debian, GCC and Clang on amd64 Ubuntu
|
||||
systems.
|
||||
|
||||
To run the linter and code formatting stages of the tests, the following
|
||||
software is also required:
|
||||
To run the code formatting stages of the tests, the following software is also required:
|
||||
|
||||
1. Git
|
||||
2. [Google's `cpplint.py`][cpplint]
|
||||
3. clang-format-3.8
|
||||
1. clang-format 11+
|
||||
2. clang-tidy 11+
|
||||
|
||||
Refer to the 'Usage' section for details.
|
||||
|
||||
Note that in Ubuntu 18.04, clang-tidy-4.0 will only work if the clang-4.0
|
||||
package is also installed.
|
||||
|
||||
Known Limitations for AArch64 code generation
|
||||
=============================================
|
||||
Versioning
|
||||
==========
|
||||
|
||||
VIXL uses [Semantic Versioning 2.0.0][semver] - see [VERSIONS](VERSIONS.md) for details.
|
||||
|
||||
Supported Arm Architecture Features
|
||||
===================================
|
||||
|
||||
| Feature | VIXL CPUFeatures Flag | Notes |
|
||||
|------------|-------------------------------|---------------------------------|
|
||||
| BTI | kBTI | Per-page enabling not supported |
|
||||
| CSSC | kCSSC | |
|
||||
| DotProd | kDotProduct | |
|
||||
| FCMA | kFcma | |
|
||||
| FHM | kFHM | |
|
||||
| FP16 | kFPHalf, kNEONHalf | |
|
||||
| FRINTTS | kFrintToFixedSizedInt | |
|
||||
| FlagM | kFlagM | |
|
||||
| FlagM2 | kAXFlag | |
|
||||
| I8MM | kI8MM | |
|
||||
| JSCVT | kJSCVT | |
|
||||
| LOR | kLORegions | |
|
||||
| LRCPC | kRCpc | |
|
||||
| LRCPC2 | kRCpcImm | |
|
||||
| LSE | kAtomics | |
|
||||
| MOPS | kMOPS | |
|
||||
| MTE | kMTEInstructions, kMTE, kMTE3 | |
|
||||
| PAuth | kPAuth, kPAuthGeneric | Not ERETAA, ERETAB |
|
||||
| RAS | kRAS | |
|
||||
| RDM | kRDM | |
|
||||
| SVE | kSVE | |
|
||||
| SVE2 | kSVE2 | |
|
||||
| SVEBitPerm | kSVEBitPerm | |
|
||||
| SVEF32MM | kSVEF32MM | |
|
||||
| SVEF64MM | kSVEF64MM | |
|
||||
| SVEI8MM | kSVEI8MM | |
|
||||
|
||||
Enable generating code for an architecture feature by combining a flag with
|
||||
the MacroAssembler's defaults. For example, to generate code for SVE, use
|
||||
`masm.GetCPUFeatures()->Combine(CPUFeatures::kSVE);`.
|
||||
|
||||
See [the cpu features header file](src/cpu-features.h) for more information.
|
||||
|
||||
|
||||
Known Limitations
|
||||
=================
|
||||
|
||||
VIXL was developed for JavaScript engines so a number of features from A64 were
|
||||
deemed unnecessary:
|
||||
@@ -79,11 +126,6 @@ builds and mostly works for 32-bit x86 platforms, there are a number of
|
||||
floating-point operations which do not work correctly, and a number of tests
|
||||
fail as a result.
|
||||
|
||||
VIXL may not build using Clang 3.7, due to a compiler warning. A workaround is
|
||||
to disable conversion of warnings to errors, or to delete the offending
|
||||
`return` statement reported and rebuild. This problem will be fixed in the next
|
||||
release.
|
||||
|
||||
Debug Builds
|
||||
------------
|
||||
|
||||
@@ -125,6 +167,45 @@ Instructions affected by these limitations:
|
||||
`stlxrh`, `stlxr`, `ldaxrb`, `ldaxrh`, `ldaxr`, `stlxp`, `ldaxp`, `stlrb`,
|
||||
`stlrh`, `stlr`, `ldarb`, `ldarh`, `ldar`, `clrex`.
|
||||
|
||||
Security Considerations
|
||||
-----------------------
|
||||
|
||||
VIXL allows callers to generate any code they want. The generated code is
|
||||
arbitrary, and can therefore call back into any other component in the process.
|
||||
As with any self-modifying code, vulnerabilities in the client or in VIXL itself
|
||||
could lead to arbitrary code generation.
|
||||
|
||||
For performance reasons, VIXL's Assembler only performs debug-mode checking of
|
||||
instruction operands (such as immediate field encodability). This can minimise
|
||||
code-generation overheads for advanced compilers that already model instructions
|
||||
accurately, and might consider the Assembler's checks to be redundant. The
|
||||
Assembler should only be used directly where encodability is independently
|
||||
checked, and where fine control over all generated code is required.
|
||||
|
||||
The MacroAssembler synthesises multiple-instruction sequences to support _some_
|
||||
unencodable operand combinations. The MacroAssembler can provide a useful safety
|
||||
check in cases where the Assembler's precision is not required; an unexpected
|
||||
unencodable operand should result in a macro with the correct behaviour, rather
|
||||
than an invalid instruction.
|
||||
|
||||
In general, the MacroAssembler handles operands which are likely to vary with
|
||||
user-supplied data, but does not usually handle inputs which are likely to be
|
||||
easily covered by tests. For example, move-immediate arguments are likely to be
|
||||
data-dependent, but register types (e.g. `x` vs `w`) are not.
|
||||
|
||||
We recommend that _all_ users use the MacroAssembler, using `ExactAssemblyScope`
|
||||
to invoke the Assembler when specific instruction sequences are required. This
|
||||
approach is recommended even in cases where a compiler can model the
|
||||
instructions precisely, because, subject to the limitations described above, it
|
||||
offers an additional layer of protection against logic bugs in instruction
|
||||
selection.
|
||||
|
||||
Bug reports
|
||||
===========
|
||||
|
||||
Bug reports may be made in the Issues section of GitLab, or sent to
|
||||
vixl@arm.com. Please provide any steps required to recreate a bug, along with
|
||||
build environment and host system information.
|
||||
|
||||
Usage
|
||||
=====
|
||||
@@ -137,23 +218,10 @@ with VIXL, in both release and debug mode. It is a useful script for verifying
|
||||
that all of VIXL's dependencies are in place and that VIXL is working as it
|
||||
should.
|
||||
|
||||
By default, the `tools/test.py` script runs a linter to check that the source
|
||||
code conforms with the code style guide, and to detect several common errors
|
||||
that the compiler may not warn about. This is most useful for VIXL developers.
|
||||
The linter has the following dependencies:
|
||||
|
||||
1. Git must be installed, and the VIXL project must be in a valid Git
|
||||
repository, such as one produced using `git clone`.
|
||||
2. `cpplint.py`, [as provided by Google][cpplint], must be available (and
|
||||
executable) on the `PATH`.
|
||||
|
||||
It is possible to tell `tools/test.py` to skip the linter stage by passing
|
||||
`--nolint`. This removes the dependency on `cpplint.py` and Git. The `--nolint`
|
||||
option is implied if the VIXL project is a snapshot (with no `.git` directory).
|
||||
|
||||
Additionally, `tools/test.py` tests code formatting using `clang-format-3.8`.
|
||||
If you don't have `clang-format-3.8`, disable the test using the
|
||||
`--noclang-format` option.
|
||||
By default, `tools/test.py` tests code formatting using `clang-format-4.0`,
|
||||
and performs static analysis using `clang-tidy-4.0`. If you don't have these
|
||||
tools, disable the test using `--noclang-format` or `--noclang-tidy`,
|
||||
respectively.
|
||||
|
||||
Also note that the tests for the tracing features depend upon external `diff`
|
||||
and `sed` tools. If these tools are not available in `PATH`, these tests will
|
||||
@@ -173,11 +241,11 @@ aarch32_examples` or `scons aarch64_examples` from the root directory, or use
|
||||
|
||||
|
||||
|
||||
[cpplint]: http://google-styleguide.googlecode.com/svn/trunk/cpplint/cpplint.py
|
||||
"Google's cpplint.py script."
|
||||
[vixl]: https://gitlab.arm.com/runtimes/vixl
|
||||
"The VIXL repository on GitLab."
|
||||
|
||||
[vixl]: https://git.linaro.org/arm/vixl.git
|
||||
"The VIXL repository at 'https://git.linaro.org'."
|
||||
[semver]: https://semver.org/spec/v2.0.0.html
|
||||
"Semantic Versioning 2.0.0 Specification"
|
||||
|
||||
[getting-started-aarch32]: doc/aarch32/getting-started-aarch32.md
|
||||
"Introduction to VIXL for AArch32."
|
||||
|
||||
@@ -538,12 +538,18 @@ class Assembler : public vixl::internal::AssemblerBase {
|
||||
// Conditional branch to label.
|
||||
void b(Label* label, Condition cond);
|
||||
|
||||
// Conditional branch consistent to label.
|
||||
void bc(Label* label, Condition cond);
|
||||
|
||||
// Unconditional branch to PC offset.
|
||||
void b(int64_t imm26);
|
||||
|
||||
// Conditional branch to PC offset.
|
||||
void b(int64_t imm19, Condition cond);
|
||||
|
||||
// Conditional branch consistent to PC offset.
|
||||
void bc(int64_t imm19, Condition cond);
|
||||
|
||||
// Branch with link to label.
|
||||
void bl(Label* label);
|
||||
|
||||
@@ -2081,6 +2087,9 @@ class Assembler : public vixl::internal::AssemblerBase {
|
||||
// Prefetch from pc + imm19 << 2 (allowing unallocated hints).
|
||||
void prfm(int op, int64_t imm19);
|
||||
|
||||
// Yield.
|
||||
void yield();
|
||||
|
||||
// Move instructions. The default shift of -1 indicates that the move
|
||||
// instruction will calculate an appropriate 16-bit immediate and left shift
|
||||
// that is equal to the 64-bit immediate argument. If an explicit left shift
|
||||
@@ -2450,6 +2459,16 @@ class Assembler : public vixl::internal::AssemblerBase {
|
||||
// FP convert to unsigned integer, round towards +infinity.
|
||||
void fcvtpu(const VRegister& vd, const VRegister& vn);
|
||||
|
||||
// Floating-point convert from single-precision to BFloat16 format (scalar).
|
||||
void bfcvt(const VRegister& vd, const VRegister& vn);
|
||||
|
||||
// Floating-point convert from single-precision to BFloat16 format (vector).
|
||||
void bfcvtn(const VRegister& vd, const VRegister& vn);
|
||||
|
||||
// Floating-point convert from single-precision to BFloat16 format (second
|
||||
// part).
|
||||
void bfcvtn2(const VRegister& vd, const VRegister& vn);
|
||||
|
||||
// Convert signed integer or fixed point to FP.
|
||||
void scvtf(const VRegister& fd, const Register& rn, int fbits = 0);
|
||||
|
||||
@@ -3732,6 +3751,12 @@ class Assembler : public vixl::internal::AssemblerBase {
|
||||
const VRegister& vm,
|
||||
int index);
|
||||
|
||||
// SM4 Encode.
|
||||
void sm4e(const VRegister& vd, const VRegister& vn);
|
||||
|
||||
// SM4 Key.
|
||||
void sm4ekey(const VRegister& vd, const VRegister& vn, const VRegister& vm);
|
||||
|
||||
// Scalable Vector Extensions.
|
||||
|
||||
// Absolute value (predicated).
|
||||
@@ -3839,6 +3864,12 @@ class Assembler : public vixl::internal::AssemblerBase {
|
||||
const PRegisterWithLaneSize& pn,
|
||||
const PRegisterWithLaneSize& pm);
|
||||
|
||||
// Floating-point down convert to BFloat16 format (predicated).
|
||||
void bfcvt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn);
|
||||
|
||||
// Floating-point down convert and narrow to BFloat16 (top, predicated).
|
||||
void bfcvtnt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn);
|
||||
|
||||
// Break after first true condition.
|
||||
void brka(const PRegisterWithLaneSize& pd,
|
||||
const PRegister& pg,
|
||||
|
||||
+257
-261
File diff suppressed because it is too large
Load Diff
@@ -173,6 +173,7 @@ class AA64ISAR2 : public IDRegister {
|
||||
static const Field kRPRES;
|
||||
static const Field kMOPS;
|
||||
static const Field kCSSC;
|
||||
static const Field kHBC;
|
||||
};
|
||||
|
||||
class AA64MMFR0 : public IDRegister {
|
||||
|
||||
@@ -111,9 +111,10 @@ class CPUFeaturesAuditor : public DecoderVisitor {
|
||||
class RecordInstructionFeaturesScope;
|
||||
|
||||
#define DECLARE(A) virtual void Visit##A(const Instruction* instr);
|
||||
VISITOR_LIST(DECLARE)
|
||||
SIM_AUD_VISITOR_LIST(DECLARE)
|
||||
#undef DECLARE
|
||||
void VisitCryptoSM3(const Instruction* instr);
|
||||
void VisitCryptoSM4(const Instruction* instr);
|
||||
|
||||
void LoadStoreHelper(const Instruction* instr);
|
||||
void LoadStorePairHelper(const Instruction* instr);
|
||||
|
||||
+210
-192
@@ -30,240 +30,244 @@
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "../globals-vixl.h"
|
||||
|
||||
#include "instructions-aarch64.h"
|
||||
|
||||
// List macro containing all visitors needed by the decoder class.
|
||||
#define VISITOR_LIST_THAT_RETURN(V) \
|
||||
V(AddSubExtended) \
|
||||
V(AddSubImmediate) \
|
||||
V(AddSubShifted) \
|
||||
V(AddSubWithCarry) \
|
||||
V(AtomicMemory) \
|
||||
V(Bitfield) \
|
||||
V(CompareBranch) \
|
||||
V(ConditionalBranch) \
|
||||
V(ConditionalCompareImmediate) \
|
||||
V(ConditionalCompareRegister) \
|
||||
V(ConditionalSelect) \
|
||||
V(Crypto2RegSHA) \
|
||||
V(Crypto3RegSHA) \
|
||||
V(CryptoAES) \
|
||||
V(DataProcessing1Source) \
|
||||
V(DataProcessing2Source) \
|
||||
V(DataProcessing3Source) \
|
||||
V(EvaluateIntoFlags) \
|
||||
V(Exception) \
|
||||
V(Extract) \
|
||||
V(FPCompare) \
|
||||
V(FPConditionalCompare) \
|
||||
V(FPConditionalSelect) \
|
||||
V(FPDataProcessing1Source) \
|
||||
V(FPDataProcessing2Source) \
|
||||
V(FPDataProcessing3Source) \
|
||||
V(FPFixedPointConvert) \
|
||||
V(FPImmediate) \
|
||||
V(FPIntegerConvert) \
|
||||
V(LoadLiteral) \
|
||||
V(LoadStoreExclusive) \
|
||||
V(LoadStorePAC) \
|
||||
V(LoadStorePairNonTemporal) \
|
||||
V(LoadStorePairOffset) \
|
||||
V(LoadStorePairPostIndex) \
|
||||
V(LoadStorePairPreIndex) \
|
||||
V(LoadStorePostIndex) \
|
||||
V(LoadStorePreIndex) \
|
||||
V(LoadStoreRCpcUnscaledOffset) \
|
||||
V(LoadStoreRegisterOffset) \
|
||||
V(LoadStoreUnscaledOffset) \
|
||||
V(LoadStoreUnsignedOffset) \
|
||||
V(LogicalImmediate) \
|
||||
V(LogicalShifted) \
|
||||
V(MoveWideImmediate) \
|
||||
V(NEON2RegMisc) \
|
||||
V(NEON2RegMiscFP16) \
|
||||
V(NEON3Different) \
|
||||
V(NEON3Same) \
|
||||
V(NEON3SameExtra) \
|
||||
V(NEON3SameFP16) \
|
||||
V(NEONAcrossLanes) \
|
||||
V(NEONByIndexedElement) \
|
||||
V(NEONCopy) \
|
||||
V(NEONExtract) \
|
||||
V(NEONLoadStoreMultiStruct) \
|
||||
V(NEONLoadStoreMultiStructPostIndex) \
|
||||
V(NEONLoadStoreSingleStruct) \
|
||||
V(NEONLoadStoreSingleStructPostIndex) \
|
||||
V(NEONModifiedImmediate) \
|
||||
V(NEONPerm) \
|
||||
V(NEONScalar2RegMisc) \
|
||||
#define VISITOR_LIST_THAT_RETURN(V) \
|
||||
V(SVEBroadcastBitmaskImm) \
|
||||
V(Unallocated) \
|
||||
V(Unimplemented)
|
||||
|
||||
#define SIM_AUD_VISITOR_LIST_THAT_RETURN(V) \
|
||||
V(NEONScalar2RegMiscFP16) \
|
||||
V(NEONScalar3Diff) \
|
||||
V(NEONScalar3Same) \
|
||||
V(NEONScalar3SameExtra) \
|
||||
V(NEONScalar3SameFP16) \
|
||||
V(NEONScalarByIndexedElement) \
|
||||
V(NEONScalarCopy) \
|
||||
V(NEONScalarPairwise) \
|
||||
V(NEONScalarShiftImmediate) \
|
||||
V(NEONShiftImmediate) \
|
||||
V(NEONTable) \
|
||||
V(PCRelAddressing) \
|
||||
V(RotateRightIntoFlags) \
|
||||
V(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets) \
|
||||
V(SVE32BitGatherLoad_VectorPlusImm) \
|
||||
V(NEONScalar3SameExtra) \
|
||||
V(SVE32BitGatherLoadHalfwords_ScalarPlus32BitScaledOffsets) \
|
||||
V(SVE32BitGatherLoadWords_ScalarPlus32BitScaledOffsets) \
|
||||
V(SVE32BitGatherLoad_ScalarPlus32BitUnscaledOffsets) \
|
||||
V(SVE32BitGatherPrefetch_ScalarPlus32BitScaledOffsets) \
|
||||
V(SVE32BitGatherPrefetch_VectorPlusImm) \
|
||||
V(SVE32BitScatterStore_ScalarPlus32BitScaledOffsets) \
|
||||
V(SVE32BitScatterStore_ScalarPlus32BitUnscaledOffsets) \
|
||||
V(SVE32BitScatterStore_VectorPlusImm) \
|
||||
V(SVE64BitGatherLoad_ScalarPlus32BitUnpackedScaledOffsets) \
|
||||
V(SVE64BitGatherLoad_ScalarPlus64BitScaledOffsets) \
|
||||
V(SVE64BitGatherLoad_ScalarPlus64BitUnscaledOffsets) \
|
||||
V(SVE64BitGatherLoad_ScalarPlusUnpacked32BitUnscaledOffsets) \
|
||||
V(SVE64BitGatherLoad_VectorPlusImm) \
|
||||
V(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets) \
|
||||
V(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets) \
|
||||
V(SVE64BitGatherPrefetch_VectorPlusImm) \
|
||||
V(SVE64BitScatterStore_ScalarPlus64BitScaledOffsets) \
|
||||
V(SVE64BitScatterStore_ScalarPlus64BitUnscaledOffsets) \
|
||||
V(SVE64BitScatterStore_ScalarPlusUnpacked32BitScaledOffsets) \
|
||||
V(SVE64BitScatterStore_ScalarPlusUnpacked32BitUnscaledOffsets) \
|
||||
V(SVE64BitScatterStore_VectorPlusImm) \
|
||||
V(SVEAddressGeneration) \
|
||||
V(SVEBitwiseLogicalUnpredicated) \
|
||||
V(SVEBitwiseShiftUnpredicated) \
|
||||
V(SVEBitwiseLogical_Predicated) \
|
||||
V(SVEBitwiseShiftByVector_Predicated) \
|
||||
V(SVEConditionallyBroadcastElementToVector) \
|
||||
V(SVEConditionallyExtractElementToSIMDFPScalar) \
|
||||
V(SVEConstructivePrefix_Unpredicated) \
|
||||
V(SVEContiguousNonTemporalLoad_ScalarPlusScalar) \
|
||||
V(SVEContiguousNonTemporalStore_ScalarPlusScalar) \
|
||||
V(SVEContiguousStore_ScalarPlusScalar) \
|
||||
V(SVEExtractElementToSIMDFPScalarRegister) \
|
||||
V(SVEFFRInitialise) \
|
||||
V(SVEFFRWriteFromPredicate) \
|
||||
V(SVEFPAccumulatingReduction) \
|
||||
V(SVEFPArithmeticUnpredicated) \
|
||||
V(SVEFPCompareVectors) \
|
||||
V(SVEFPCompareWithZero) \
|
||||
V(SVEFPComplexAddition) \
|
||||
V(SVEFPComplexMulAdd) \
|
||||
V(SVEFPConvertToInt) \
|
||||
V(SVEInsertSIMDFPScalarRegister) \
|
||||
V(SVEIntAddSubtractVectors_Predicated) \
|
||||
V(SVEIntMinMaxDifference_Predicated) \
|
||||
V(SVEIntMinMaxImm_Unpredicated) \
|
||||
V(SVEIntMulImm_Unpredicated) \
|
||||
V(SVEIntMulVectors_Predicated) \
|
||||
V(SVELoadAndBroadcastQOWord_ScalarPlusScalar) \
|
||||
V(SVELoadMultipleStructures_ScalarPlusImm) \
|
||||
V(SVELoadMultipleStructures_ScalarPlusScalar) \
|
||||
V(SVEPartitionBreakCondition) \
|
||||
V(SVEPermutePredicateElements) \
|
||||
V(SVEPredicateFirstActive) \
|
||||
V(SVEPredicateReadFromFFR_Unpredicated) \
|
||||
V(SVEPredicateTest) \
|
||||
V(SVEPredicateZero) \
|
||||
V(SVEPropagateBreakToNextPartition) \
|
||||
V(SVEStoreMultipleStructures_ScalarPlusImm) \
|
||||
V(SVEStoreMultipleStructures_ScalarPlusScalar) \
|
||||
V(SVETableLookup) \
|
||||
V(SVEUnpackPredicateElements) \
|
||||
V(SVEVectorSplice) \
|
||||
V(SVEFPComplexMulAddIndex) \
|
||||
V(SVEFPFastReduction) \
|
||||
V(SVEFPMulIndex) \
|
||||
V(SVEFPMulAdd) \
|
||||
V(SVEFPMulAddIndex) \
|
||||
V(SVEFPUnaryOpUnpredicated) \
|
||||
V(SVEIncDecByPredicateCount) \
|
||||
V(SVEIndexGeneration) \
|
||||
V(SVEIntArithmeticUnpredicated) \
|
||||
V(SVEIntCompareSignedImm) \
|
||||
V(SVEIntCompareUnsignedImm) \
|
||||
V(SVEIntCompareVectors) \
|
||||
V(SVEIntMulAddPredicated) \
|
||||
V(SVEIntMulAddUnpredicated) \
|
||||
V(SVEIntReduction) \
|
||||
V(SVEIntUnaryArithmeticPredicated) \
|
||||
V(SVEMovprfx) \
|
||||
V(SVEMulIndex) \
|
||||
V(SVEPermuteVectorExtract) \
|
||||
V(SVEPermuteVectorInterleaving) \
|
||||
V(SVEPredicateCount) \
|
||||
V(SVEPredicateLogical) \
|
||||
V(SVEPredicateNextActive) \
|
||||
V(SVEPredicateReadFromFFR_Predicated) \
|
||||
V(SVEPropagateBreak) \
|
||||
V(SVEStackFrameAdjustment) \
|
||||
V(SVEStackFrameSize) \
|
||||
V(SVEVectorSelect) \
|
||||
V(SVEBitwiseLogical_Predicated) \
|
||||
V(SVEBitwiseLogicalWithImm_Unpredicated) \
|
||||
V(SVEBitwiseShiftByImm_Predicated) \
|
||||
V(SVEBitwiseShiftByVector_Predicated) \
|
||||
V(SVEBitwiseShiftByWideElements_Predicated) \
|
||||
V(SVEBroadcastBitmaskImm) \
|
||||
V(SVEBroadcastFPImm_Unpredicated) \
|
||||
V(SVEBroadcastGeneralRegister) \
|
||||
V(SVEBroadcastIndexElement) \
|
||||
V(SVEBroadcastIntImm_Unpredicated) \
|
||||
V(SVECompressActiveElements) \
|
||||
V(SVEConditionallyBroadcastElementToVector) \
|
||||
V(SVEConditionallyExtractElementToSIMDFPScalar) \
|
||||
V(SVEConditionallyExtractElementToGeneralRegister) \
|
||||
V(SVEConditionallyTerminateScalars) \
|
||||
V(SVEConstructivePrefix_Unpredicated) \
|
||||
V(SVEContiguousFirstFaultLoad_ScalarPlusScalar) \
|
||||
V(SVEContiguousLoad_ScalarPlusImm) \
|
||||
V(SVEContiguousLoad_ScalarPlusScalar) \
|
||||
V(SVEContiguousNonFaultLoad_ScalarPlusImm) \
|
||||
V(SVEContiguousNonTemporalLoad_ScalarPlusImm) \
|
||||
V(SVEContiguousNonTemporalLoad_ScalarPlusScalar) \
|
||||
V(SVEContiguousNonTemporalStore_ScalarPlusImm) \
|
||||
V(SVEContiguousNonTemporalStore_ScalarPlusScalar) \
|
||||
V(SVEContiguousPrefetch_ScalarPlusImm) \
|
||||
V(SVEContiguousPrefetch_ScalarPlusScalar) \
|
||||
V(SVEContiguousStore_ScalarPlusImm) \
|
||||
V(SVEContiguousStore_ScalarPlusScalar) \
|
||||
V(SVECopySIMDFPScalarRegisterToVector_Predicated) \
|
||||
V(SVECopyFPImm_Predicated) \
|
||||
V(SVECopyGeneralRegisterToVector_Predicated) \
|
||||
V(SVECopyIntImm_Predicated) \
|
||||
V(SVEElementCount) \
|
||||
V(SVEExtractElementToSIMDFPScalarRegister) \
|
||||
V(SVEExtractElementToGeneralRegister) \
|
||||
V(SVEFPArithmetic_Predicated) \
|
||||
V(SVEFPArithmeticWithImm_Predicated) \
|
||||
V(SVEFPConvertPrecision) \
|
||||
V(SVEFPConvertToInt) \
|
||||
V(SVEFPExponentialAccelerator) \
|
||||
V(SVEFPRoundToIntegralValue) \
|
||||
V(SVEFPTrigMulAddCoefficient) \
|
||||
V(SVEFPTrigSelectCoefficient) \
|
||||
V(SVEFPUnaryOp) \
|
||||
V(SVEIncDecRegisterByElementCount) \
|
||||
V(SVEIncDecVectorByElementCount) \
|
||||
V(SVEInsertSIMDFPScalarRegister) \
|
||||
V(SVEInsertGeneralRegister) \
|
||||
V(SVEIntAddSubtractImm_Unpredicated) \
|
||||
V(SVEIntAddSubtractVectors_Predicated) \
|
||||
V(SVEIntCompareScalarCountAndLimit) \
|
||||
V(SVEIntConvertToFP) \
|
||||
V(SVEIntDivideVectors_Predicated) \
|
||||
V(SVEIntMinMaxImm_Unpredicated) \
|
||||
V(SVEIntMinMaxDifference_Predicated) \
|
||||
V(SVEIntMulImm_Unpredicated) \
|
||||
V(SVEIntMulVectors_Predicated) \
|
||||
V(SVELoadAndBroadcastElement) \
|
||||
V(SVELoadAndBroadcastQOWord_ScalarPlusImm) \
|
||||
V(SVELoadAndBroadcastQOWord_ScalarPlusScalar) \
|
||||
V(SVELoadMultipleStructures_ScalarPlusImm) \
|
||||
V(SVELoadMultipleStructures_ScalarPlusScalar) \
|
||||
V(SVELoadPredicateRegister) \
|
||||
V(SVELoadVectorRegister) \
|
||||
V(SVEPartitionBreakCondition) \
|
||||
V(SVEPermutePredicateElements) \
|
||||
V(SVEPredicateFirstActive) \
|
||||
V(RotateRightIntoFlags) \
|
||||
V(EvaluateIntoFlags) \
|
||||
V(ConditionalCompareRegister) \
|
||||
V(ConditionalCompareImmediate) \
|
||||
V(PCRelAddressing) \
|
||||
V(UnconditionalBranch) \
|
||||
V(DataProcessing1Source) \
|
||||
V(CompareBranch) \
|
||||
V(TestBranch) \
|
||||
V(LoadStoreRCpcUnscaledOffset) \
|
||||
V(LoadStoreUnscaledOffset) \
|
||||
V(LoadLiteral) \
|
||||
V(LoadStorePairNonTemporal) \
|
||||
V(LoadStorePAC) \
|
||||
V(FPCompare) \
|
||||
V(FPConditionalCompare) \
|
||||
V(FPConditionalSelect) \
|
||||
V(FPDataProcessing2Source) \
|
||||
V(FPDataProcessing3Source) \
|
||||
V(FPIntegerConvert) \
|
||||
V(FPFixedPointConvert) \
|
||||
V(Exception) \
|
||||
V(Crypto2RegSHA) \
|
||||
V(Crypto3RegSHA) \
|
||||
V(CryptoAES) \
|
||||
V(NEON2RegMiscFP16) \
|
||||
V(SVEContiguousLoad_ScalarPlusImm) \
|
||||
V(SVEPredicateInitialize) \
|
||||
V(SVEPredicateNextActive) \
|
||||
V(SVEPredicateReadFromFFR_Predicated) \
|
||||
V(SVEPredicateReadFromFFR_Unpredicated) \
|
||||
V(SVEPredicateTest) \
|
||||
V(SVEPredicateZero) \
|
||||
V(SVEPropagateBreakToNextPartition) \
|
||||
V(SVEIndexGeneration) \
|
||||
V(SVEAddressGeneration) \
|
||||
V(SVELoadAndBroadcastQOWord_ScalarPlusImm) \
|
||||
V(SVEIntAddSubtractImm_Unpredicated) \
|
||||
V(SVEIntCompareScalarCountAndLimit) \
|
||||
V(FPImmediate) \
|
||||
V(FPDataProcessing1Source) \
|
||||
V(NEONModifiedImmediate) \
|
||||
V(NEONTable) \
|
||||
V(SVEIntReduction) \
|
||||
V(SVEMulIndex) \
|
||||
V(NEON3SameFP16) \
|
||||
V(NEONLoadStoreSingleStruct) \
|
||||
V(NEONLoadStoreSingleStructPostIndex) \
|
||||
V(NEONLoadStoreMultiStructPostIndex) \
|
||||
V(LoadStorePreIndex) \
|
||||
V(LoadStorePostIndex) \
|
||||
V(LoadStoreUnsignedOffset) \
|
||||
V(LoadStoreRegisterOffset) \
|
||||
V(LoadStorePairPostIndex) \
|
||||
V(LoadStorePairOffset) \
|
||||
V(LoadStorePairPreIndex) \
|
||||
V(SVEBitwiseShiftByWideElements_Predicated) \
|
||||
V(NEONScalarPairwise) \
|
||||
V(SVEFPUnaryOp) \
|
||||
V(SVEFPRoundToIntegralValue) \
|
||||
V(SVEFPUnaryOpUnpredicated) \
|
||||
V(SVEFPMulAdd) \
|
||||
V(SVEFPFastReduction) \
|
||||
V(SVEFPComplexMulAdd) \
|
||||
V(SVEFPComplexAddition) \
|
||||
V(SVEFPCompareWithZero) \
|
||||
V(SVEFPCompareVectors) \
|
||||
V(SVEFPArithmeticUnpredicated) \
|
||||
V(SVEFPAccumulatingReduction) \
|
||||
V(SVEIntUnaryArithmeticPredicated) \
|
||||
V(SVEBitwiseShiftUnpredicated) \
|
||||
V(SVEUnpackVectorElements) \
|
||||
V(SVEIntConvertToFP) \
|
||||
V(SVEReverseWithinElements) \
|
||||
V(SVEReversePredicateElements) \
|
||||
V(SVEReverseVectorElements) \
|
||||
V(SVEReverseWithinElements) \
|
||||
V(SVESaturatingIncDecRegisterByElementCount) \
|
||||
V(SVESaturatingIncDecVectorByElementCount) \
|
||||
V(SVEStoreMultipleStructures_ScalarPlusImm) \
|
||||
V(SVEStoreMultipleStructures_ScalarPlusScalar) \
|
||||
V(SVEStorePredicateRegister) \
|
||||
V(SVEStoreVectorRegister) \
|
||||
V(SVETableLookup) \
|
||||
V(SVEUnpackPredicateElements) \
|
||||
V(SVEUnpackVectorElements) \
|
||||
V(SVEVectorSplice) \
|
||||
V(System) \
|
||||
V(TestBranch) \
|
||||
V(Unallocated) \
|
||||
V(UnconditionalBranch) \
|
||||
V(SVEInsertGeneralRegister) \
|
||||
V(SVEFPTrigSelectCoefficient) \
|
||||
V(SVEFPTrigMulAddCoefficient) \
|
||||
V(SVEFPExponentialAccelerator) \
|
||||
V(SVEFPArithmetic_Predicated) \
|
||||
V(SVEFPArithmeticWithImm_Predicated) \
|
||||
V(SVEBitwiseLogicalWithImm_Unpredicated) \
|
||||
V(UnconditionalBranchToRegister) \
|
||||
V(Unimplemented)
|
||||
V(NEONExtract) \
|
||||
V(ConditionalSelect) \
|
||||
V(LogicalImmediate) \
|
||||
V(AddSubImmediate) \
|
||||
V(AddSubShifted) \
|
||||
V(AddSubExtended) \
|
||||
V(LogicalShifted) \
|
||||
V(Extract) \
|
||||
V(DataProcessing2Source) \
|
||||
V(DataProcessing3Source) \
|
||||
V(ConditionalBranch) \
|
||||
V(Bitfield) \
|
||||
V(AtomicMemory) \
|
||||
V(SVEVectorSelect) \
|
||||
V(SVEPredicateLogical) \
|
||||
V(SVEIntDivideVectors_Predicated) \
|
||||
V(SVEBroadcastIntImm_Unpredicated) \
|
||||
V(SVEBroadcastFPImm_Unpredicated) \
|
||||
V(SVEBroadcastGeneralRegister) \
|
||||
V(SVECompressActiveElements) \
|
||||
V(SVEConditionallyTerminateScalars) \
|
||||
V(SVEConditionallyExtractElementToGeneralRegister) \
|
||||
V(SVEBitwiseShiftByImm_Predicated) \
|
||||
V(SVECopyGeneralRegisterToVector_Predicated) \
|
||||
V(SVECopyIntImm_Predicated) \
|
||||
V(SVECopySIMDFPScalarRegisterToVector_Predicated) \
|
||||
V(SVECopyFPImm_Predicated) \
|
||||
V(SVEExtractElementToGeneralRegister) \
|
||||
V(SVEIntMulAddUnpredicated) \
|
||||
V(SVEContiguousStore_ScalarPlusImm) \
|
||||
V(SVEContiguousPrefetch_ScalarPlusScalar) \
|
||||
V(SVEContiguousPrefetch_ScalarPlusImm) \
|
||||
V(SVEContiguousNonFaultLoad_ScalarPlusImm) \
|
||||
V(SVEBitwiseLogicalUnpredicated) \
|
||||
V(SVE64BitGatherPrefetch_ScalarPlus64BitScaledOffsets) \
|
||||
V(SVE64BitGatherPrefetch_ScalarPlusUnpacked32BitScaledOffsets) \
|
||||
V(SVE64BitGatherPrefetch_VectorPlusImm) \
|
||||
V(SVE32BitGatherPrefetch_VectorPlusImm) \
|
||||
V(SVELoadVectorRegister) \
|
||||
V(SVEStoreVectorRegister) \
|
||||
V(SVELoadPredicateRegister) \
|
||||
V(SVEStorePredicateRegister) \
|
||||
V(SVEFPConvertPrecision) \
|
||||
V(SVE32BitGatherLoad_VectorPlusImm) \
|
||||
V(SVE32BitScatterStore_VectorPlusImm) \
|
||||
V(SVE64BitScatterStore_VectorPlusImm) \
|
||||
V(SVEContiguousFirstFaultLoad_ScalarPlusScalar) \
|
||||
V(SVEContiguousNonTemporalLoad_ScalarPlusImm) \
|
||||
V(SVEContiguousNonTemporalStore_ScalarPlusImm) \
|
||||
V(SVELoadAndBroadcastElement) \
|
||||
V(NEONPerm) \
|
||||
V(NEONLoadStoreMultiStruct) \
|
||||
V(NEON3Same) \
|
||||
V(NEON3SameExtra) \
|
||||
V(NEON2RegMisc) \
|
||||
V(NEONByIndexedElement) \
|
||||
V(SVE64BitGatherLoad_VectorPlusImm) \
|
||||
V(NEONShiftImmediate) \
|
||||
V(NEONCopy) \
|
||||
V(NEONScalar2RegMisc) \
|
||||
V(NEONScalar3Diff) \
|
||||
V(NEONScalar3Same) \
|
||||
V(NEONScalarCopy) \
|
||||
V(NEONScalarByIndexedElement) \
|
||||
V(NEONAcrossLanes) \
|
||||
V(NEONScalarShiftImmediate) \
|
||||
V(NEON3Different) \
|
||||
V(MoveWideImmediate) \
|
||||
V(SVEElementCount) \
|
||||
V(SVEIncDecRegisterByElementCount) \
|
||||
V(SVEIncDecVectorByElementCount) \
|
||||
V(SVESaturatingIncDecVectorByElementCount) \
|
||||
V(SVESaturatingIncDecRegisterByElementCount) \
|
||||
V(LoadStoreExclusive) \
|
||||
V(SVEBroadcastIndexElement) \
|
||||
V(System) \
|
||||
V(AddSubWithCarry)
|
||||
|
||||
#define VISITOR_LIST_THAT_DONT_RETURN(V) V(Reserved)
|
||||
|
||||
@@ -271,6 +275,10 @@
|
||||
VISITOR_LIST_THAT_RETURN(V) \
|
||||
VISITOR_LIST_THAT_DONT_RETURN(V)
|
||||
|
||||
#define SIM_AUD_VISITOR_LIST(V) \
|
||||
VISITOR_LIST(V) \
|
||||
SIM_AUD_VISITOR_LIST_THAT_RETURN(V)
|
||||
|
||||
namespace vixl {
|
||||
namespace aarch64 {
|
||||
|
||||
@@ -311,7 +319,10 @@ class CompiledDecodeNode;
|
||||
// handles the instruction.
|
||||
class Decoder {
|
||||
public:
|
||||
Decoder() { ConstructDecodeGraph(); }
|
||||
Decoder() {
|
||||
ConstructDecodeGraph();
|
||||
PopulatePerInstructionUnallocatedMap(&form_to_unalloc_);
|
||||
}
|
||||
|
||||
// Top-level wrappers around the actual decoding function.
|
||||
void Decode(const Instruction* instr);
|
||||
@@ -392,6 +403,13 @@ class Decoder {
|
||||
|
||||
// Map of node names to DecodeNodes.
|
||||
std::map<std::string, DecodeNode> decode_nodes_;
|
||||
|
||||
// Map from instruction form strings to a mask/value of encodings for that
|
||||
// form.
|
||||
using FormToUnallocMap = std::unordered_multimap<uint32_t, uint64_t>;
|
||||
FormToUnallocMap form_to_unalloc_;
|
||||
|
||||
static void PopulatePerInstructionUnallocatedMap(FormToUnallocMap* ftm);
|
||||
};
|
||||
|
||||
typedef void (Decoder::*DecodeFnPtr)(const Instruction*);
|
||||
@@ -471,7 +489,7 @@ class CompiledDecodeNode {
|
||||
bool IsLeafNode() const {
|
||||
VIXL_ASSERT(((instruction_name_ == "node") && (bit_extract_fn_ != NULL)) ||
|
||||
((instruction_name_ != "node") && (bit_extract_fn_ == NULL)));
|
||||
return instruction_name_ != "node";
|
||||
return bit_extract_fn_ == NULL;
|
||||
}
|
||||
|
||||
// Get a pointer to the next node required in the decode process, based on the
|
||||
|
||||
@@ -1923,8 +1923,24 @@ static const DecodeMapping kDecodeMapping[] = {
|
||||
},
|
||||
|
||||
{ "_kjsrkm",
|
||||
{18, 17, 16, 13, 12, 11, 10, 9, 8, 7, 4, 3, 2, 1, 0},
|
||||
{ {"000000000011111"_b, "_zztypv"},
|
||||
{11, 10, 9, 8},
|
||||
{ {"0000"_b, "_flags"},
|
||||
{"xxx1"_b, "_msrimm"},
|
||||
{"xx1x"_b, "_msrimm"},
|
||||
{"x1xx"_b, "_msrimm"},
|
||||
{"1xxx"_b, "_msrimm"},
|
||||
},
|
||||
},
|
||||
|
||||
{ "_msrimm",
|
||||
{13, 12, 4, 3, 2, 1, 0},
|
||||
{ {"0011111"_b, "msr_si_pstate"},
|
||||
},
|
||||
},
|
||||
|
||||
{ "_flags",
|
||||
{18, 17, 16, 13, 12, 7, 4, 3, 2, 1, 0},
|
||||
{ {"00000011111"_b, "_zztypv"},
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
+2524
-2600
File diff suppressed because it is too large
Load Diff
+18
-127
@@ -117,11 +117,17 @@ class Disassembler : public DecoderVisitor {
|
||||
VISITOR_LIST(DECLARE)
|
||||
#undef DECLARE
|
||||
|
||||
std::string GetMnemonicAlias(const Instruction* instr);
|
||||
|
||||
using FormToVisitorFnMap = std::unordered_map<
|
||||
uint32_t,
|
||||
std::function<void(Disassembler*, const Instruction*)>>;
|
||||
static const FormToVisitorFnMap* GetFormToVisitorFnMap();
|
||||
|
||||
using FormToStringMap = std::unordered_map<uint32_t, const char*>;
|
||||
static void PopulateFormToStringMap(FormToStringMap* fts);
|
||||
|
||||
FormToStringMap form_to_string_;
|
||||
std::string mnemonic_;
|
||||
uint32_t form_hash_;
|
||||
|
||||
@@ -132,119 +138,6 @@ class Disassembler : public DecoderVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
void Disassemble_PdT_PgZ_ZnT_ZmT(const Instruction* instr);
|
||||
void Disassemble_ZdB_Zn1B_Zn2B_imm(const Instruction* instr);
|
||||
void Disassemble_ZdB_ZnB_ZmB(const Instruction* instr);
|
||||
void Disassemble_ZdD_PgM_ZnS(const Instruction* instr);
|
||||
void Disassemble_ZdD_ZnD_ZmD(const Instruction* instr);
|
||||
void Disassemble_ZdD_ZnD_ZmD_imm(const Instruction* instr);
|
||||
void Disassemble_ZdD_ZnS_ZmS_imm(const Instruction* instr);
|
||||
void Disassemble_ZdH_PgM_ZnS(const Instruction* instr);
|
||||
void Disassemble_ZdH_ZnH_ZmH_imm(const Instruction* instr);
|
||||
void Disassemble_ZdS_PgM_ZnD(const Instruction* instr);
|
||||
void Disassemble_ZdS_PgM_ZnH(const Instruction* instr);
|
||||
void Disassemble_ZdS_PgM_ZnS(const Instruction* instr);
|
||||
void Disassemble_ZdS_ZnH_ZmH_imm(const Instruction* instr);
|
||||
void Disassemble_ZdS_ZnS_ZmS(const Instruction* instr);
|
||||
void Disassemble_ZdS_ZnS_ZmS_imm(const Instruction* instr);
|
||||
void Disassemble_ZdT_PgM_ZnT(const Instruction* instr);
|
||||
void Disassemble_ZdT_PgZ_ZnT_ZmT(const Instruction* instr);
|
||||
void Disassemble_ZdT_Pg_Zn1T_Zn2T(const Instruction* instr);
|
||||
void Disassemble_ZdT_Zn1T_Zn2T_ZmT(const Instruction* instr);
|
||||
void Disassemble_ZdT_ZnT_ZmT(const Instruction* instr);
|
||||
void Disassemble_ZdT_ZnT_ZmTb(const Instruction* instr);
|
||||
void Disassemble_ZdT_ZnTb(const Instruction* instr);
|
||||
void Disassemble_ZdT_ZnTb_ZmTb(const Instruction* instr);
|
||||
void Disassemble_ZdaD_ZnD_ZmD_imm(const Instruction* instr);
|
||||
void Disassemble_ZdaD_ZnH_ZmH_imm_const(const Instruction* instr);
|
||||
void Disassemble_ZdaD_ZnS_ZmS_imm(const Instruction* instr);
|
||||
void Disassemble_ZdaH_ZnH_ZmH_imm(const Instruction* instr);
|
||||
void Disassemble_ZdaH_ZnH_ZmH_imm_const(const Instruction* instr);
|
||||
void Disassemble_ZdaS_ZnB_ZmB_imm_const(const Instruction* instr);
|
||||
void Disassemble_ZdaS_ZnH_ZmH(const Instruction* instr);
|
||||
void Disassemble_ZdaS_ZnH_ZmH_imm(const Instruction* instr);
|
||||
void Disassemble_ZdaS_ZnS_ZmS_imm(const Instruction* instr);
|
||||
void Disassemble_ZdaS_ZnS_ZmS_imm_const(const Instruction* instr);
|
||||
void Disassemble_ZdaT_PgM_ZnTb(const Instruction* instr);
|
||||
void Disassemble_ZdaT_ZnT_ZmT(const Instruction* instr);
|
||||
void Disassemble_ZdaT_ZnT_ZmT_const(const Instruction* instr);
|
||||
void Disassemble_ZdaT_ZnT_const(const Instruction* instr);
|
||||
void Disassemble_ZdaT_ZnTb_ZmTb(const Instruction* instr);
|
||||
void Disassemble_ZdaT_ZnTb_ZmTb_const(const Instruction* instr);
|
||||
void Disassemble_ZdnB_ZdnB(const Instruction* instr);
|
||||
void Disassemble_ZdnB_ZdnB_ZmB(const Instruction* instr);
|
||||
void Disassemble_ZdnS_ZdnS_ZmS(const Instruction* instr);
|
||||
void Disassemble_ZdnT_PgM_ZdnT_ZmT(const Instruction* instr);
|
||||
void Disassemble_ZdnT_PgM_ZdnT_const(const Instruction* instr);
|
||||
void Disassemble_ZdnT_ZdnT_ZmT_const(const Instruction* instr);
|
||||
void Disassemble_ZtD_PgZ_ZnD_Xm(const Instruction* instr);
|
||||
void Disassemble_ZtD_Pg_ZnD_Xm(const Instruction* instr);
|
||||
void Disassemble_ZtS_PgZ_ZnS_Xm(const Instruction* instr);
|
||||
void Disassemble_ZtS_Pg_ZnS_Xm(const Instruction* instr);
|
||||
void Disassemble_ZdaS_ZnB_ZmB(const Instruction* instr);
|
||||
void Disassemble_Vd4S_Vn16B_Vm16B(const Instruction* instr);
|
||||
|
||||
void DisassembleCpy(const Instruction* instr);
|
||||
void DisassembleSet(const Instruction* instr);
|
||||
void DisassembleMinMaxImm(const Instruction* instr);
|
||||
|
||||
void DisassembleSVEShiftLeftImm(const Instruction* instr);
|
||||
void DisassembleSVEShiftRightImm(const Instruction* instr);
|
||||
void DisassembleSVEAddSubCarry(const Instruction* instr);
|
||||
void DisassembleSVEAddSubHigh(const Instruction* instr);
|
||||
void DisassembleSVEComplexIntAddition(const Instruction* instr);
|
||||
void DisassembleSVEBitwiseTernary(const Instruction* instr);
|
||||
void DisassembleSVEFlogb(const Instruction* instr);
|
||||
void DisassembleSVEFPPair(const Instruction* instr);
|
||||
|
||||
void DisassembleNoArgs(const Instruction* instr);
|
||||
|
||||
void DisassembleNEONMulByElementLong(const Instruction* instr);
|
||||
void DisassembleNEONDotProdByElement(const Instruction* instr);
|
||||
void DisassembleNEONFPMulByElement(const Instruction* instr);
|
||||
void DisassembleNEONHalfFPMulByElement(const Instruction* instr);
|
||||
void DisassembleNEONFPMulByElementLong(const Instruction* instr);
|
||||
void DisassembleNEONComplexMulByElement(const Instruction* instr);
|
||||
void DisassembleNEON2RegLogical(const Instruction* instr);
|
||||
void DisassembleNEON2RegExtract(const Instruction* instr);
|
||||
void DisassembleNEON2RegAddlp(const Instruction* instr);
|
||||
void DisassembleNEON2RegCompare(const Instruction* instr);
|
||||
void DisassembleNEON2RegFPCompare(const Instruction* instr);
|
||||
void DisassembleNEON2RegFPConvert(const Instruction* instr);
|
||||
void DisassembleNEON2RegFP(const Instruction* instr);
|
||||
void DisassembleNEON3SameLogical(const Instruction* instr);
|
||||
void DisassembleNEON3SameFHM(const Instruction* instr);
|
||||
void DisassembleNEON3SameNoD(const Instruction* instr);
|
||||
void DisassembleNEONShiftLeftLongImm(const Instruction* instr);
|
||||
void DisassembleNEONShiftRightImm(const Instruction* instr);
|
||||
void DisassembleNEONShiftRightNarrowImm(const Instruction* instr);
|
||||
void DisassembleNEONScalarSatMulLongIndex(const Instruction* instr);
|
||||
void DisassembleNEONFPScalarMulIndex(const Instruction* instr);
|
||||
void DisassembleNEONFPScalar3Same(const Instruction* instr);
|
||||
void DisassembleNEONScalar3SameOnlyD(const Instruction* instr);
|
||||
void DisassembleNEONFPAcrossLanes(const Instruction* instr);
|
||||
void DisassembleNEONFP16AcrossLanes(const Instruction* instr);
|
||||
void DisassembleNEONScalarShiftImmOnlyD(const Instruction* instr);
|
||||
void DisassembleNEONScalarShiftRightNarrowImm(const Instruction* instr);
|
||||
void DisassembleNEONScalar2RegMiscOnlyD(const Instruction* instr);
|
||||
void DisassembleNEONFPScalar2RegMisc(const Instruction* instr);
|
||||
void DisassembleNEONPolynomialMul(const Instruction* instr);
|
||||
void DisassembleNEON4Same(const Instruction* instr);
|
||||
void DisassembleNEONXar(const Instruction* instr);
|
||||
void DisassembleNEONRax1(const Instruction* instr);
|
||||
void DisassembleSHA512(const Instruction* instr);
|
||||
|
||||
void DisassembleMTELoadTag(const Instruction* instr);
|
||||
void DisassembleMTEStoreTag(const Instruction* instr);
|
||||
void DisassembleMTEStoreTagPair(const Instruction* instr);
|
||||
|
||||
void Disassemble_XdSP_XnSP_Xm(const Instruction* instr);
|
||||
void Disassemble_XdSP_XnSP_uimm6_uimm4(const Instruction* instr);
|
||||
void Disassemble_Xd_XnSP_Xm(const Instruction* instr);
|
||||
void Disassemble_Xd_XnSP_XmSP(const Instruction* instr);
|
||||
|
||||
void VisitCryptoSM3(const Instruction* instr);
|
||||
|
||||
void Format(const Instruction* instr,
|
||||
const char* mnemonic,
|
||||
const char* format0,
|
||||
@@ -253,42 +146,39 @@ class Disassembler : public DecoderVisitor {
|
||||
const char* format0,
|
||||
const char* format1 = NULL);
|
||||
|
||||
void Substitute(const Instruction* instr, const char* string);
|
||||
int Substitute(const Instruction* instr, const char* string);
|
||||
int SubstituteField(const Instruction* instr, const char* format);
|
||||
int SubstituteRegisterField(const Instruction* instr, const char* format);
|
||||
int SubstitutePredicateRegisterField(const Instruction* instr,
|
||||
const char* format);
|
||||
int SubstituteImmediateField(const Instruction* instr, const char* format);
|
||||
int SubstituteLiteralField(const Instruction* instr, const char* format);
|
||||
int SubstituteBitfieldImmediateField(const Instruction* instr,
|
||||
const char* format);
|
||||
int SubstituteShiftField(const Instruction* instr, const char* format);
|
||||
int SubstituteExtendField(const Instruction* instr, const char* format);
|
||||
int SubstituteConditionField(const Instruction* instr, const char* format);
|
||||
int SubstitutePCRelAddressField(const Instruction* instr, const char* format);
|
||||
int SubstituteBranchTargetField(const Instruction* instr, const char* format);
|
||||
int SubstituteLSRegOffsetField(const Instruction* instr, const char* format);
|
||||
int SubstitutePrefetchField(const Instruction* instr, const char* format);
|
||||
int SubstituteBarrierField(const Instruction* instr, const char* format);
|
||||
int SubstituteSysOpField(const Instruction* instr, const char* format);
|
||||
int SubstituteCrField(const Instruction* instr, const char* format);
|
||||
int SubstituteIntField(const Instruction* instr, const char* format);
|
||||
int SubstituteSVESize(const Instruction* instr, const char* format);
|
||||
int SubstituteFPField(const Instruction* instr, const char* format);
|
||||
int SubstituteTernary(const Instruction* instr, const char* format);
|
||||
int SubstituteConditionalBlock(const Instruction* instr, const char* format);
|
||||
int SubstituteGenericArray(const Instruction* instr, const char* format);
|
||||
int SubstituteGenericHash(const Instruction* instr, const char* format);
|
||||
int SubstituteExpression(const Instruction* instr, const char* format);
|
||||
int SubstituteEnd(const Instruction* instr, const char* format);
|
||||
|
||||
std::pair<unsigned, unsigned> GetRegNumForField(const Instruction* instr,
|
||||
char reg_prefix,
|
||||
const char* field);
|
||||
|
||||
bool RdIsZROrSP(const Instruction* instr) const {
|
||||
public:
|
||||
static bool RdIsZROrSP(const Instruction* instr) {
|
||||
return (instr->GetRd() == kZeroRegCode);
|
||||
}
|
||||
|
||||
bool RnIsZROrSP(const Instruction* instr) const {
|
||||
static bool RnIsZROrSP(const Instruction* instr) {
|
||||
return (instr->GetRn() == kZeroRegCode);
|
||||
}
|
||||
|
||||
bool RmIsZROrSP(const Instruction* instr) const {
|
||||
static bool RmIsZROrSP(const Instruction* instr) {
|
||||
return (instr->GetRm() == kZeroRegCode);
|
||||
}
|
||||
|
||||
@@ -298,6 +188,7 @@ class Disassembler : public DecoderVisitor {
|
||||
|
||||
bool IsMovzMovnImm(unsigned reg_size, uint64_t value);
|
||||
|
||||
private:
|
||||
int64_t code_address_offset() const { return code_address_offset_; }
|
||||
|
||||
protected:
|
||||
|
||||
+12
-5
@@ -373,6 +373,7 @@ class Instruction {
|
||||
|
||||
std::pair<int, int> GetSVEPermuteIndexAndLaneSizeLog2() const;
|
||||
|
||||
std::pair<int, int> GetNEONMulRmAndIndex() const;
|
||||
std::pair<int, int> GetSVEMulZmAndIndex() const;
|
||||
std::pair<int, int> GetSVEMulLongZmAndIndex() const;
|
||||
|
||||
@@ -855,11 +856,13 @@ class NEONFormatDecoder {
|
||||
// Set the format mapping for all or individual substitutions.
|
||||
void SetFormatMaps(const NEONFormatMap* format0,
|
||||
const NEONFormatMap* format1 = NULL,
|
||||
const NEONFormatMap* format2 = NULL) {
|
||||
const NEONFormatMap* format2 = NULL,
|
||||
const NEONFormatMap* format3 = NULL) {
|
||||
VIXL_ASSERT(format0 != NULL);
|
||||
formats_[0] = format0;
|
||||
formats_[1] = (format1 == NULL) ? formats_[0] : format1;
|
||||
formats_[2] = (format2 == NULL) ? formats_[1] : format2;
|
||||
formats_[3] = (format3 == NULL) ? formats_[2] : format3;
|
||||
}
|
||||
void SetFormatMap(unsigned index, const NEONFormatMap* format) {
|
||||
VIXL_ASSERT(index <= ArrayLength(formats_));
|
||||
@@ -878,12 +881,15 @@ class NEONFormatDecoder {
|
||||
const char* Substitute(const char* string,
|
||||
SubstitutionMode mode0 = kFormat,
|
||||
SubstitutionMode mode1 = kFormat,
|
||||
SubstitutionMode mode2 = kFormat) {
|
||||
SubstitutionMode mode2 = kFormat,
|
||||
SubstitutionMode mode3 = kFormat) {
|
||||
const char* subst0 = GetSubstitute(0, mode0);
|
||||
const char* subst1 = GetSubstitute(1, mode1);
|
||||
const char* subst2 = GetSubstitute(2, mode2);
|
||||
const char* subst3 = GetSubstitute(3, mode3);
|
||||
|
||||
if ((subst0 == NULL) || (subst1 == NULL) || (subst2 == NULL)) {
|
||||
if ((subst0 == NULL) || (subst1 == NULL) || (subst2 == NULL) ||
|
||||
(subst3 == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -892,7 +898,8 @@ class NEONFormatDecoder {
|
||||
string,
|
||||
subst0,
|
||||
subst1,
|
||||
subst2);
|
||||
subst2,
|
||||
subst3);
|
||||
return form_buffer_;
|
||||
}
|
||||
|
||||
@@ -1130,7 +1137,7 @@ class NEONFormatDecoder {
|
||||
}
|
||||
|
||||
Instr instrbits_;
|
||||
const NEONFormatMap* formats_[3];
|
||||
const NEONFormatMap* formats_[4];
|
||||
char form_buffer_[64];
|
||||
char mne_buffer_[16];
|
||||
};
|
||||
|
||||
@@ -1099,11 +1099,24 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface {
|
||||
}
|
||||
}
|
||||
|
||||
void B(Label* label);
|
||||
void B(Label* label, BranchType type, Register reg = NoReg, int bit = -1);
|
||||
|
||||
void B(Label* label);
|
||||
void B(Label* label, Condition cond);
|
||||
void B(Label* label, Condition cond) {
|
||||
Bcommon(label, cond, /* use_bc = */ false);
|
||||
}
|
||||
void Bc(Label* label, Condition cond) {
|
||||
Bcommon(label, cond, /* use_bc = */ true);
|
||||
}
|
||||
// Aliases that match the instruction set ordering.
|
||||
void B(Condition cond, Label* label) { B(label, cond); }
|
||||
void Bc(Condition cond, Label* label) { Bc(label, cond); }
|
||||
|
||||
private:
|
||||
// Common method for B and Bc.
|
||||
void Bcommon(Label* label, Condition cond, bool use_bc);
|
||||
|
||||
public:
|
||||
void Bfm(const Register& rd,
|
||||
const Register& rn,
|
||||
unsigned immr,
|
||||
@@ -1190,6 +1203,31 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface {
|
||||
SingleEmissionCheckScope guard(this);
|
||||
retab();
|
||||
}
|
||||
void Bfcvt(const VRegister& vd, const VRegister& vn) {
|
||||
VIXL_ASSERT(allow_macro_instructions_);
|
||||
SingleEmissionCheckScope guard(this);
|
||||
bfcvt(vd, vn);
|
||||
}
|
||||
void Bfcvtn(const VRegister& vd, const VRegister& vn) {
|
||||
VIXL_ASSERT(allow_macro_instructions_);
|
||||
SingleEmissionCheckScope guard(this);
|
||||
bfcvtn(vd, vn);
|
||||
}
|
||||
void Bfcvtn2(const VRegister& vd, const VRegister& vn) {
|
||||
VIXL_ASSERT(allow_macro_instructions_);
|
||||
SingleEmissionCheckScope guard(this);
|
||||
bfcvtn2(vd, vn);
|
||||
}
|
||||
void Bfcvt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
|
||||
VIXL_ASSERT(allow_macro_instructions_);
|
||||
SingleEmissionCheckScope guard(this);
|
||||
bfcvt(zd, pg, zn);
|
||||
}
|
||||
void Bfcvtnt(const ZRegister& zd, const PRegisterM& pg, const ZRegister& zn) {
|
||||
VIXL_ASSERT(allow_macro_instructions_);
|
||||
SingleEmissionCheckScope guard(this);
|
||||
bfcvtnt(zd, pg, zn);
|
||||
}
|
||||
void Braa(const Register& xn, const Register& xm) {
|
||||
VIXL_ASSERT(allow_macro_instructions_);
|
||||
SingleEmissionCheckScope guard(this);
|
||||
@@ -2814,6 +2852,7 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface {
|
||||
V(shsub, Shsub) \
|
||||
V(sm3partw1, Sm3partw1) \
|
||||
V(sm3partw2, Sm3partw2) \
|
||||
V(sm4ekey, Sm4ekey) \
|
||||
V(smax, Smax) \
|
||||
V(smaxp, Smaxp) \
|
||||
V(smin, Smin) \
|
||||
@@ -2964,6 +3003,7 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface {
|
||||
V(sha1su1, Sha1su1) \
|
||||
V(sha256su0, Sha256su0) \
|
||||
V(sha512su0, Sha512su0) \
|
||||
V(sm4e, Sm4e) \
|
||||
V(smaxv, Smaxv) \
|
||||
V(sminv, Sminv) \
|
||||
V(sqabs, Sqabs) \
|
||||
@@ -7878,6 +7918,12 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface {
|
||||
void Umax(const Register& rd, const Register& rn, const Operand& op);
|
||||
void Umin(const Register& rd, const Register& rn, const Operand& op);
|
||||
|
||||
void Yield() {
|
||||
VIXL_ASSERT(allow_macro_instructions_);
|
||||
SingleEmissionCheckScope guard(this);
|
||||
yield();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Literal<T>* CreateLiteralDestroyedWithPool(T value) {
|
||||
return new Literal<T>(value,
|
||||
@@ -8249,9 +8295,10 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface {
|
||||
UseScratchRegisterScope* scratch_scope);
|
||||
|
||||
bool LabelIsOutOfRange(Label* label, ImmBranchType branch_type) {
|
||||
int64_t offset = label->GetLocation() - GetCursorOffset();
|
||||
VIXL_ASSERT(IsMultiple(offset, kInstructionSize));
|
||||
return !Instruction::IsValidImmPCOffset(branch_type,
|
||||
label->GetLocation() -
|
||||
GetCursorOffset());
|
||||
offset / kInstructionSize);
|
||||
}
|
||||
|
||||
void ConfigureSimulatorCPUFeaturesHelper(const CPUFeatures& features,
|
||||
|
||||
+133
-51
@@ -643,7 +643,7 @@ class SimVRegister : public SimRegisterBase<kZRegMaxSize> {
|
||||
class LogicPRegister {
|
||||
public:
|
||||
inline LogicPRegister(
|
||||
SimPRegister& other) // NOLINT(runtime/references)(runtime/explicit)
|
||||
SimPRegister& other) // NOLINT(google-runtime-references)
|
||||
: register_(other) {}
|
||||
|
||||
// Set a conveniently-sized block to 16 bits as the minimum predicate length
|
||||
@@ -744,7 +744,7 @@ using vixl_uint128_t = std::pair<uint64_t, uint64_t>;
|
||||
class LogicVRegister {
|
||||
public:
|
||||
inline LogicVRegister(
|
||||
SimVRegister& other) // NOLINT(runtime/references)(runtime/explicit)
|
||||
SimVRegister& other) // NOLINT(google-runtime-references)
|
||||
: register_(other) {
|
||||
for (size_t i = 0; i < ArrayLength(saturated_); i++) {
|
||||
saturated_[i] = kNotSaturated;
|
||||
@@ -872,10 +872,9 @@ class LogicVRegister {
|
||||
SetUint(vform, index, value.second);
|
||||
return;
|
||||
}
|
||||
// TODO: Extend this to SVE.
|
||||
VIXL_ASSERT((vform == kFormat1Q) && (index == 0));
|
||||
SetUint(kFormat2D, 0, value.second);
|
||||
SetUint(kFormat2D, 1, value.first);
|
||||
VIXL_ASSERT((vform == kFormat1Q) || (vform == kFormatVnQ));
|
||||
SetUint(kFormatVnD, 2 * index, value.second);
|
||||
SetUint(kFormatVnD, 2 * index + 1, value.first);
|
||||
}
|
||||
|
||||
void SetUintArray(VectorFormat vform, const uint64_t* src) const {
|
||||
@@ -1447,6 +1446,7 @@ class Simulator : public DecoderVisitor {
|
||||
|
||||
#define DECLARE(A) virtual void Visit##A(const Instruction* instr);
|
||||
VISITOR_LIST_THAT_RETURN(DECLARE)
|
||||
SIM_AUD_VISITOR_LIST_THAT_RETURN(DECLARE)
|
||||
#undef DECLARE
|
||||
#define DECLARE(A) \
|
||||
VIXL_NO_RETURN virtual void Visit##A(const Instruction* instr);
|
||||
@@ -1504,6 +1504,7 @@ class Simulator : public DecoderVisitor {
|
||||
void SimulateSVESaturatingMulAddHigh(const Instruction* instr);
|
||||
void SimulateSVESaturatingMulHighIndex(const Instruction* instr);
|
||||
void SimulateSVEFPConvertLong(const Instruction* instr);
|
||||
void SimulateSVEPmull128(const Instruction* instr);
|
||||
void SimulateMatrixMul(const Instruction* instr);
|
||||
void SimulateSVEFPMatrixMul(const Instruction* instr);
|
||||
void SimulateNEONMulByElementLong(const Instruction* instr);
|
||||
@@ -1532,8 +1533,16 @@ class Simulator : public DecoderVisitor {
|
||||
void SimulateSignedMinMax(const Instruction* instr);
|
||||
void SimulateUnsignedMinMax(const Instruction* instr);
|
||||
void SimulateSHA512(const Instruction* instr);
|
||||
void SimulateFPConvert(const Instruction* instr);
|
||||
void SimulateFPRoundInt(const Instruction* instr);
|
||||
void SimulateFPRoundIntToSize(const Instruction* instr);
|
||||
void SimulateNEONRoundInt(const Instruction* instr);
|
||||
void SimulateNEONRoundIntToSize(const Instruction* instr);
|
||||
void SimulateNEONFPConvert(const Instruction* instr);
|
||||
void SimulateNEONFP2RegMisc(const Instruction* instr);
|
||||
|
||||
void VisitCryptoSM3(const Instruction* instr);
|
||||
void VisitCryptoSM4(const Instruction* instr);
|
||||
|
||||
// Integer register accessors.
|
||||
|
||||
@@ -2574,6 +2583,14 @@ class Simulator : public DecoderVisitor {
|
||||
void PrintPWrite(int rt_code, uintptr_t address) {
|
||||
PrintPAccess(rt_code, "->", address);
|
||||
}
|
||||
void PrintWriteU64(uint64_t x, uintptr_t address) {
|
||||
fprintf(stream_,
|
||||
"# 0x%016" PRIx64 " -> %s0x%016" PRIxPTR "%s\n",
|
||||
x,
|
||||
clr_memory_address,
|
||||
address,
|
||||
clr_normal);
|
||||
}
|
||||
|
||||
// Like Print* (above), but respect GetTraceParameters().
|
||||
void LogRead(int rt_code, PrintRegisterFormat format, uintptr_t address) {
|
||||
@@ -2608,6 +2625,9 @@ class Simulator : public DecoderVisitor {
|
||||
void LogPWrite(int rt_code, uintptr_t address) {
|
||||
if (ShouldTraceWrites()) PrintPWrite(rt_code, address);
|
||||
}
|
||||
void LogWriteU64(uint64_t x, uintptr_t address) {
|
||||
if (ShouldTraceWrites()) PrintWriteU64(x, address);
|
||||
}
|
||||
void LogMemTransfer(uintptr_t dst, uintptr_t src, uint8_t value) {
|
||||
if (ShouldTraceWrites()) PrintMemTransfer(dst, src, value);
|
||||
}
|
||||
@@ -4587,6 +4607,11 @@ class Simulator : public DecoderVisitor {
|
||||
int index,
|
||||
bool is_a);
|
||||
|
||||
LogicVRegister sm4(LogicVRegister dst,
|
||||
const LogicVRegister& src1,
|
||||
const LogicVRegister& src2,
|
||||
bool is_key);
|
||||
|
||||
#define NEON_3VREG_LOGIC_LIST(V) \
|
||||
V(addhn) \
|
||||
V(addhn2) \
|
||||
@@ -4883,6 +4908,12 @@ class Simulator : public DecoderVisitor {
|
||||
LogicVRegister fcvtxn2(VectorFormat vform,
|
||||
LogicVRegister dst,
|
||||
const LogicVRegister& src);
|
||||
LogicVRegister bfcvtn(VectorFormat vform,
|
||||
LogicVRegister dst,
|
||||
const LogicVRegister& src);
|
||||
LogicVRegister bfcvtn2(VectorFormat vform,
|
||||
LogicVRegister dst,
|
||||
const LogicVRegister& src);
|
||||
LogicVRegister fsqrt(VectorFormat vform,
|
||||
LogicVRegister dst,
|
||||
const LogicVRegister& src);
|
||||
@@ -5000,7 +5031,7 @@ class Simulator : public DecoderVisitor {
|
||||
uint32_t Crc32Checksum(uint32_t acc, T val, uint32_t poly);
|
||||
uint32_t Crc32Checksum(uint32_t acc, uint64_t val, uint32_t poly);
|
||||
|
||||
void SysOp_W(int op, int64_t val);
|
||||
bool SysOp_W(int op, int64_t val);
|
||||
|
||||
template <typename T>
|
||||
T FPRecipSqrtEstimate(T op);
|
||||
@@ -5343,7 +5374,7 @@ class Simulator : public DecoderVisitor {
|
||||
std::function<void(Simulator*, const Instruction*)>>;
|
||||
static const FormToVisitorFnMap* GetFormToVisitorFnMap();
|
||||
|
||||
uint32_t form_hash_;
|
||||
uint32_t form_hash_{};
|
||||
|
||||
static const PACKey kPACKeyIA;
|
||||
static const PACKey kPACKeyIB;
|
||||
@@ -5421,9 +5452,10 @@ class Simulator : public DecoderVisitor {
|
||||
// in vreg is non-zero. Clear the flag, otherwise. This is almost the opposite
|
||||
// operation to ExpandToSimVRegister(), except that any non-zero lane is
|
||||
// interpreted as true.
|
||||
void ExtractFromSimVRegister(VectorFormat vform,
|
||||
SimPRegister& pd, // NOLINT(runtime/references)
|
||||
SimVRegister vreg);
|
||||
void ExtractFromSimVRegister(
|
||||
VectorFormat vform,
|
||||
SimPRegister& pd, // NOLINT(google-runtime-references)
|
||||
SimVRegister vreg);
|
||||
|
||||
bool coloured_trace_;
|
||||
|
||||
@@ -5450,6 +5482,9 @@ class Simulator : public DecoderVisitor {
|
||||
// A configurable size of SVE vector registers.
|
||||
unsigned vector_length_;
|
||||
|
||||
// DC ZVA enable (= 0) status and block size.
|
||||
unsigned dczid_ = (0 << 4) | 4; // 2^4 words => 64-byte block size.
|
||||
|
||||
// Representation of memory attributes such as MTE tagging and BTI page
|
||||
// protection in addition to branch interceptions.
|
||||
MetaDataDepot meta_data_;
|
||||
@@ -5462,19 +5497,54 @@ class Simulator : public DecoderVisitor {
|
||||
|
||||
// The Guarded Control Stack is represented using a vector, where the more
|
||||
// recently stored addresses are at higher-numbered indices.
|
||||
using GuardedControlStack = std::vector<uint64_t>;
|
||||
using GuardedControlStackStorage = std::vector<uint64_t>;
|
||||
|
||||
public:
|
||||
struct GuardedControlStack {
|
||||
GuardedControlStackStorage* ptr;
|
||||
uint64_t token;
|
||||
};
|
||||
|
||||
private:
|
||||
// The GCSManager handles the synchronisation of GCS across multiple
|
||||
// Simulator instances. Each Simulator has its own stack, but all share
|
||||
// a GCSManager instance. This allows exchanging stacks between Simulators
|
||||
// in a threaded application.
|
||||
class GCSManager {
|
||||
public:
|
||||
// Allocate a new Guarded Control Stack and add it to the vector of stacks.
|
||||
// Interface for users outside the Simulator.
|
||||
|
||||
// Allocate a new Guarded Control Stack. This method returns a token, which
|
||||
// uniquely identifies the GCS, and can be passed *once* to the stack
|
||||
// switching instructions (GSSS*), when the stack has not been used yet.
|
||||
// Later arguments to the stack switching instructions must either be
|
||||
// fresh tokens, or return values from the stack switching instructions.
|
||||
uint64_t AllocateStack() {
|
||||
GuardedControlStack gcs = AllocateStackInternal();
|
||||
return gcs.token;
|
||||
}
|
||||
|
||||
// Free a Guarded Control Stack based on its token.
|
||||
void FreeStack(uint64_t token) {
|
||||
const std::lock_guard<std::mutex> lock(stacks_mtx_);
|
||||
uint64_t gcs_index = GetGCSIndexFromToken(token);
|
||||
GuardedControlStackStorage* gcsptr = stacks_[gcs_index];
|
||||
if (gcsptr == nullptr) {
|
||||
VIXL_ABORT_WITH_MSG("Tried to double free GCS ");
|
||||
} else {
|
||||
delete gcsptr;
|
||||
// To ensure other tokens remain valid, we do not remove this element
|
||||
// but set it to nullptr instead.
|
||||
stacks_[gcs_index] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
// Allocate a new Guarded Control Stack and add it to the vector of stacks.
|
||||
GuardedControlStack AllocateStackInternal() {
|
||||
const std::lock_guard<std::mutex> lock(stacks_mtx_);
|
||||
|
||||
GuardedControlStack* new_stack = new GuardedControlStack;
|
||||
GuardedControlStackStorage* new_stack = new GuardedControlStackStorage;
|
||||
uint64_t result;
|
||||
|
||||
// Put the new stack into the first available slot.
|
||||
@@ -5490,42 +5560,46 @@ class Simulator : public DecoderVisitor {
|
||||
stacks_.push_back(new_stack);
|
||||
}
|
||||
|
||||
// Shift the index to look like a stack pointer aligned to a page.
|
||||
result <<= kPageSizeLog2;
|
||||
result = GetGCSTokenFromIndex(result);
|
||||
|
||||
// Push the tagged index onto the new stack as a seal.
|
||||
new_stack->push_back(result + 1);
|
||||
return result;
|
||||
|
||||
return {new_stack, result};
|
||||
}
|
||||
|
||||
// Free a Guarded Control Stack and set the stacks_ slot to null.
|
||||
void FreeStack(uint64_t gcs) {
|
||||
// Get a pointer to the GCS storage using a GCS index.
|
||||
GuardedControlStackStorage* GetGCSPtr(uint64_t gcs_index) {
|
||||
const std::lock_guard<std::mutex> lock(stacks_mtx_);
|
||||
uint64_t gcs_index = GetGCSIndex(gcs);
|
||||
GuardedControlStack* gcsptr = stacks_[gcs_index];
|
||||
if (gcsptr == nullptr) {
|
||||
VIXL_ABORT_WITH_MSG("Tried to free unallocated GCS ");
|
||||
} else {
|
||||
delete gcsptr;
|
||||
stacks_[gcs_index] = nullptr;
|
||||
}
|
||||
return stacks_.at(GetGCSIndexFromToken(gcs_index));
|
||||
}
|
||||
|
||||
// Get a pointer to the GCS vector using a GCS id.
|
||||
GuardedControlStack* GetGCSPtr(uint64_t gcs) const {
|
||||
return stacks_[GetGCSIndex(gcs)];
|
||||
// Get an index into stacks_ given a GCS token.
|
||||
static uint64_t GetGCSIndexFromToken(uint64_t token) {
|
||||
return token >> kPageSizeLog2;
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t GetGCSIndex(uint64_t gcs) const { return gcs >> 12; }
|
||||
// Get a GCS token from an index into stacks_.
|
||||
static uint64_t GetGCSTokenFromIndex(uint64_t index) {
|
||||
// Shift the index to look like a stack pointer aligned to a page.
|
||||
return index << kPageSizeLog2;
|
||||
}
|
||||
|
||||
std::vector<GuardedControlStack*> stacks_;
|
||||
std::vector<GuardedControlStackStorage*> stacks_;
|
||||
std::mutex stacks_mtx_;
|
||||
|
||||
friend class Simulator;
|
||||
};
|
||||
|
||||
GuardedControlStackStorage* GetGCSStorage() { return gcs_.ptr; }
|
||||
uint64_t GetGCSToken() { return gcs_.token; }
|
||||
|
||||
// A GCS id indicating no GCS has been allocated.
|
||||
static const uint64_t kGCSNoStack = kPageSize - 1;
|
||||
uint64_t gcs_;
|
||||
// We cache both the GCS token, and the pointer to the GCS underlying
|
||||
// storage, which allows us to avoid calls into GCSManager that
|
||||
// would require synchronisation.
|
||||
GuardedControlStack gcs_;
|
||||
bool gcs_enabled_;
|
||||
|
||||
public:
|
||||
@@ -5539,37 +5613,45 @@ class Simulator : public DecoderVisitor {
|
||||
bool IsGCSCheckEnabled() const { return gcs_enabled_; }
|
||||
|
||||
private:
|
||||
bool IsAllocatedGCS(uint64_t gcs) const { return gcs != kGCSNoStack; }
|
||||
void ResetGCSState() {
|
||||
GCSManager& m = GetGCSManager();
|
||||
if (IsAllocatedGCS(gcs_)) {
|
||||
m.FreeStack(gcs_);
|
||||
// This method is also called in the constructor, before we have set up the
|
||||
// GCS, so the call to FreeStack must be conditional.
|
||||
if (GetGCSStorage() != nullptr) {
|
||||
m.FreeStack(GetGCSToken());
|
||||
}
|
||||
ActivateGCS(m.AllocateStack());
|
||||
ActivateGCS(m.AllocateStackInternal());
|
||||
GCSPop(); // Remove seal.
|
||||
}
|
||||
|
||||
GuardedControlStack* GetGCSPtr(uint64_t gcs) {
|
||||
GuardedControlStackStorage* GetGCSPtr(uint64_t gcs) {
|
||||
GCSManager& m = GetGCSManager();
|
||||
GuardedControlStack* result = m.GetGCSPtr(gcs);
|
||||
GuardedControlStackStorage* result = m.GetGCSPtr(gcs);
|
||||
return result;
|
||||
}
|
||||
GuardedControlStack* GetActiveGCSPtr() { return GetGCSPtr(gcs_); }
|
||||
|
||||
uint64_t ActivateGCS(uint64_t gcs) {
|
||||
uint64_t outgoing_gcs = gcs_;
|
||||
gcs_ = gcs;
|
||||
return outgoing_gcs;
|
||||
GuardedControlStack ActivateGCS(GuardedControlStack incoming) {
|
||||
GuardedControlStack outgoing = gcs_;
|
||||
gcs_ = incoming;
|
||||
return outgoing;
|
||||
}
|
||||
|
||||
GuardedControlStack ActivateGCS(uint64_t token) {
|
||||
GuardedControlStack incoming = {GetGCSPtr(token), token};
|
||||
GuardedControlStack outgoing = gcs_;
|
||||
gcs_ = incoming;
|
||||
return outgoing;
|
||||
}
|
||||
|
||||
void GCSPush(uint64_t addr) {
|
||||
GetActiveGCSPtr()->push_back(addr);
|
||||
size_t entry = GetActiveGCSPtr()->size() - 1;
|
||||
GuardedControlStackStorage* gcs = GetGCSStorage();
|
||||
gcs->push_back(addr);
|
||||
size_t entry = gcs->size() - 1;
|
||||
LogGCS(/* is_push = */ true, addr, entry);
|
||||
}
|
||||
|
||||
uint64_t GCSPop() {
|
||||
GuardedControlStack* gcs = GetActiveGCSPtr();
|
||||
GuardedControlStackStorage* gcs = GetGCSStorage();
|
||||
if (gcs->empty()) {
|
||||
return 0;
|
||||
}
|
||||
@@ -5581,7 +5663,7 @@ class Simulator : public DecoderVisitor {
|
||||
}
|
||||
|
||||
uint64_t GCSPeek() {
|
||||
GuardedControlStack* gcs = GetActiveGCSPtr();
|
||||
GuardedControlStackStorage* gcs = GetGCSStorage();
|
||||
if (gcs->empty()) {
|
||||
return 0;
|
||||
}
|
||||
@@ -5590,8 +5672,8 @@ class Simulator : public DecoderVisitor {
|
||||
}
|
||||
|
||||
void ReportGCSFailure(const char* msg) {
|
||||
GuardedControlStackStorage* gcs = GetGCSStorage();
|
||||
if (IsGCSCheckEnabled()) {
|
||||
GuardedControlStack* gcs = GetActiveGCSPtr();
|
||||
printf("%s", msg);
|
||||
if (gcs == nullptr) {
|
||||
printf("GCS pointer is null\n");
|
||||
@@ -5604,7 +5686,7 @@ class Simulator : public DecoderVisitor {
|
||||
gcs->pop_back();
|
||||
int index = most_recent_index - i;
|
||||
printf(" gcs%" PRIu64 "[%d]: 0x%016" PRIx64 "\n",
|
||||
gcs_,
|
||||
GCSManager::GetGCSIndexFromToken(GetGCSToken()),
|
||||
index,
|
||||
entry);
|
||||
}
|
||||
|
||||
+2
-1
@@ -202,7 +202,8 @@ namespace vixl {
|
||||
V(kEBF16, "EBF16", "ebf16") \
|
||||
V(kSVE_EBF16, "EBF16 (SVE)", "sveebf16") \
|
||||
V(kCSSC, "CSSC", "cssc") \
|
||||
V(kGCS, "GCS", "gcs")
|
||||
V(kGCS, "GCS", "gcs") \
|
||||
V(kHBC, "HBC", "hbc")
|
||||
// clang-format on
|
||||
|
||||
|
||||
|
||||
+40
-7
@@ -49,7 +49,7 @@ namespace vixl {
|
||||
#ifdef __GNUC__
|
||||
#define VIXL_HAS_DEPRECATED_WITH_MSG
|
||||
#elif defined(__clang__)
|
||||
#if __has_extension(attribute_deprecated_with_message)
|
||||
#ifdef __has_extension(attribute_deprecated_with_message)
|
||||
#define VIXL_HAS_DEPRECATED_WITH_MSG
|
||||
#endif
|
||||
#endif
|
||||
@@ -258,9 +258,22 @@ class Float16 {
|
||||
uint16_t rawbits_;
|
||||
};
|
||||
|
||||
// Floating point representation.
|
||||
uint16_t Float16ToRawbits(Float16 value);
|
||||
Float16 RawbitsToFloat16(uint16_t bits);
|
||||
|
||||
class BFloat16 {
|
||||
public:
|
||||
explicit BFloat16(float value);
|
||||
BFloat16() : rawbits_(0) {}
|
||||
friend uint16_t BFloat16ToRawbits(BFloat16 value);
|
||||
friend BFloat16 RawbitsToBFloat16(uint16_t bits);
|
||||
|
||||
protected:
|
||||
uint16_t rawbits_;
|
||||
};
|
||||
|
||||
uint16_t BFloat16ToRawbits(BFloat16 value);
|
||||
BFloat16 RawbitsToBFloat16(uint16_t bits);
|
||||
|
||||
uint32_t FloatToRawbits(float value);
|
||||
VIXL_DEPRECATED("FloatToRawbits",
|
||||
@@ -274,8 +287,6 @@ VIXL_DEPRECATED("DoubleToRawbits",
|
||||
return DoubleToRawbits(value);
|
||||
}
|
||||
|
||||
Float16 RawbitsToFloat16(uint16_t bits);
|
||||
|
||||
float RawbitsToFloat(uint32_t bits);
|
||||
VIXL_DEPRECATED("RawbitsToFloat",
|
||||
inline float rawbits_to_float(uint32_t bits)) {
|
||||
@@ -629,8 +640,8 @@ bool IsRepeatingPattern(T value) {
|
||||
VIXL_ASSERT(IsMultiple(sizeof(value) * kBitsPerByte, BITS));
|
||||
VIXL_ASSERT(IsMultiple(BITS, 2));
|
||||
VIXL_STATIC_ASSERT(BITS >= 2);
|
||||
#if (defined(__x86_64__) || defined(__i386)) && \
|
||||
__clang_major__ >= 17 && __clang_major__ <= 19
|
||||
#if (defined(__x86_64__) || defined(__i386)) && __clang_major__ >= 17 && \
|
||||
__clang_major__ <= 19
|
||||
// Workaround for https://github.com/llvm/llvm-project/issues/108722
|
||||
unsigned hbits = BITS / 2;
|
||||
T midmask = (~static_cast<T>(0) >> BITS) << hbits;
|
||||
@@ -1132,6 +1143,8 @@ const unsigned kFloatMantissaBits = 23;
|
||||
const unsigned kFloatExponentBits = 8;
|
||||
const unsigned kFloat16MantissaBits = 10;
|
||||
const unsigned kFloat16ExponentBits = 5;
|
||||
const unsigned kBFloat16MantissaBits = 7;
|
||||
const unsigned kBFloat16ExponentBits = kFloatExponentBits;
|
||||
|
||||
enum FPRounding {
|
||||
// The first four values are encodable directly by FPCR<RMode>.
|
||||
@@ -1388,6 +1401,16 @@ static inline float FPRoundToFloat(int64_t sign,
|
||||
return RawbitsToFloat(bits);
|
||||
}
|
||||
|
||||
// See FPRound for a description of this function.
|
||||
static inline BFloat16 FPRoundToBFloat16(int64_t sign,
|
||||
int64_t exponent,
|
||||
uint64_t mantissa,
|
||||
FPRounding round_mode) {
|
||||
return RawbitsToBFloat16(
|
||||
FPRound<uint16_t, kBFloat16ExponentBits, kBFloat16MantissaBits>(
|
||||
sign, exponent, mantissa, round_mode));
|
||||
}
|
||||
|
||||
|
||||
float FPToFloat(Float16 value, UseDefaultNaN DN, bool* exception = NULL);
|
||||
float FPToFloat(double value,
|
||||
@@ -1408,6 +1431,16 @@ Float16 FPToFloat16(double value,
|
||||
UseDefaultNaN DN,
|
||||
bool* exception = NULL);
|
||||
|
||||
BFloat16 FPToBFloat16(float value,
|
||||
FPRounding round_mode,
|
||||
UseDefaultNaN DN,
|
||||
bool* exception = NULL);
|
||||
|
||||
BFloat16 FPToBFloat16(double value,
|
||||
FPRounding round_mode,
|
||||
UseDefaultNaN DN,
|
||||
bool* exception = NULL);
|
||||
|
||||
// Like static_cast<T>(value), but with specialisations for the Float16 type.
|
||||
template <typename T, typename F>
|
||||
T StaticCastFPTo(F value) {
|
||||
@@ -1480,7 +1513,7 @@ constexpr uint32_t Hash(const char* str, uint32_t hash = 0) {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr uint32_t operator"" _h(const char* x, size_t) { return Hash(x); }
|
||||
constexpr uint32_t operator""_h(const char* x, size_t) { return Hash(x); }
|
||||
|
||||
} // namespace vixl
|
||||
|
||||
|
||||
+49
-1
@@ -263,6 +263,10 @@ void Assembler::b(int64_t imm19, Condition cond) {
|
||||
Emit(B_cond | ImmCondBranch(imm19) | cond);
|
||||
}
|
||||
|
||||
void Assembler::bc(int64_t imm19, Condition cond) {
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kHBC));
|
||||
Emit(B_cond | ImmCondBranch(imm19) | (1 << 4) | cond);
|
||||
}
|
||||
|
||||
void Assembler::b(Label* label) {
|
||||
int64_t offset = LinkAndGetInstructionOffsetTo(label);
|
||||
@@ -277,6 +281,11 @@ void Assembler::b(Label* label, Condition cond) {
|
||||
b(static_cast<int>(offset), cond);
|
||||
}
|
||||
|
||||
void Assembler::bc(Label* label, Condition cond) {
|
||||
int64_t offset = LinkAndGetInstructionOffsetTo(label);
|
||||
VIXL_ASSERT(Instruction::IsValidImmPCOffset(CondBranchType, offset));
|
||||
bc(static_cast<int>(offset), cond);
|
||||
}
|
||||
|
||||
void Assembler::bl(int64_t imm26) { Emit(BL | ImmUncondBranch(imm26)); }
|
||||
|
||||
@@ -3689,6 +3698,23 @@ void Assembler::fjcvtzs(const Register& rd, const VRegister& vn) {
|
||||
Emit(FJCVTZS | Rn(vn) | Rd(rd));
|
||||
}
|
||||
|
||||
void Assembler::bfcvt(const VRegister& vd, const VRegister& vn) {
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kFP, CPUFeatures::kBF16));
|
||||
VIXL_ASSERT(vd.Is1H() && vn.Is1S());
|
||||
Emit(0x1e634000 | Rn(vn) | Rd(vd));
|
||||
}
|
||||
|
||||
void Assembler::bfcvtn(const VRegister& vd, const VRegister& vn) {
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kBF16));
|
||||
VIXL_ASSERT(vn.Is4S() && vd.Is4H());
|
||||
Emit(0x0ea16800 | Rn(vn) | Rd(vd));
|
||||
}
|
||||
|
||||
void Assembler::bfcvtn2(const VRegister& vd, const VRegister& vn) {
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kNEON, CPUFeatures::kBF16));
|
||||
VIXL_ASSERT(vn.Is4S() && vd.Is8H());
|
||||
Emit(0x4ea16800 | Rn(vn) | Rd(vd));
|
||||
}
|
||||
|
||||
void Assembler::NEONFPConvertToInt(const Register& rd,
|
||||
const VRegister& vn,
|
||||
@@ -4527,7 +4553,10 @@ void Assembler::fcmla(const VRegister& vd,
|
||||
VIXL_ASSERT(vd.IsVector() && AreSameFormat(vd, vn));
|
||||
VIXL_ASSERT((vm.IsH() && (vd.Is8H() || vd.Is4H())) ||
|
||||
(vm.IsS() && vd.Is4S()));
|
||||
if (vd.IsLaneSizeH()) VIXL_ASSERT(CPUHas(CPUFeatures::kNEONHalf));
|
||||
if (vd.IsLaneSizeH()) {
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kNEONHalf));
|
||||
VIXL_ASSERT(vd.Is8H() || (vm_index <= 1));
|
||||
}
|
||||
int index_num_bits = vd.Is4S() ? 1 : 2;
|
||||
Emit(VFormat(vd) | Rm(vm) | NEON_FCMLA_byelement |
|
||||
ImmNEONHLM(vm_index, index_num_bits) | ImmRotFcmlaSca(rot) | Rn(vn) |
|
||||
@@ -6117,6 +6146,24 @@ void Assembler::sm3tt2b(const VRegister& vd, const VRegister& vn, const VRegiste
|
||||
Emit(0xce408c00 | Rd(vd) | Rn(vn) | Rm(vm) | i);
|
||||
}
|
||||
|
||||
void Assembler::sm4e(const VRegister& vd, const VRegister& vn) {
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kSM4));
|
||||
VIXL_ASSERT(vd.Is4S() && vn.Is4S());
|
||||
|
||||
Emit(0xcec08400 | Rd(vd) | Rn(vn));
|
||||
}
|
||||
|
||||
void Assembler::sm4ekey(const VRegister& vd, const VRegister& vn, const VRegister& vm) {
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kNEON));
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kSM4));
|
||||
VIXL_ASSERT(vd.Is4S() && vn.Is4S() && vm.Is4S());
|
||||
|
||||
Emit(0xce60c800 | Rd(vd) | Rn(vn) | Rm(vm));
|
||||
}
|
||||
|
||||
void Assembler::yield() { hint(YIELD); }
|
||||
|
||||
// Note:
|
||||
// For all ToImm instructions below, a difference in case
|
||||
// for the same letter indicates a negated bit.
|
||||
@@ -7161,6 +7208,7 @@ bool Assembler::CPUHas(SystemRegister sysreg) const {
|
||||
return CPUHas(CPUFeatures::kRNG);
|
||||
case FPCR:
|
||||
case NZCV:
|
||||
case DCZID_EL0:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
||||
+26
-6
@@ -7410,13 +7410,13 @@ void Assembler::pmullb(const ZRegister& zd,
|
||||
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
|
||||
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEPmull128) || !zd.IsLaneSizeQ());
|
||||
VIXL_ASSERT(AreSameLaneSize(zn, zm));
|
||||
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS());
|
||||
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
|
||||
// SVEPmull128 is not supported
|
||||
VIXL_ASSERT(!zd.IsLaneSizeQ());
|
||||
Instr size = zd.IsLaneSizeQ() ? 0 : SVESize(zd);
|
||||
|
||||
Emit(0x45006800 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
|
||||
Emit(0x45006800 | size | Rd(zd) | Rn(zn) | Rm(zm));
|
||||
}
|
||||
|
||||
void Assembler::pmullt(const ZRegister& zd,
|
||||
@@ -7427,13 +7427,13 @@ void Assembler::pmullt(const ZRegister& zd,
|
||||
// size<23:22> | Zm<20:16> | op<12> | U<11> | T<10> | Zn<9:5> | Zd<4:0>
|
||||
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE2));
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kSVEPmull128) || !zd.IsLaneSizeQ());
|
||||
VIXL_ASSERT(AreSameLaneSize(zn, zm));
|
||||
VIXL_ASSERT(!zd.IsLaneSizeB() && !zd.IsLaneSizeS());
|
||||
VIXL_ASSERT(zd.GetLaneSizeInBytes() == zn.GetLaneSizeInBytes() * 2);
|
||||
// SVEPmull128 is not supported
|
||||
VIXL_ASSERT(!zd.IsLaneSizeQ());
|
||||
Instr size = zd.IsLaneSizeQ() ? 0 : SVESize(zd);
|
||||
|
||||
Emit(0x45006c00 | SVESize(zd) | Rd(zd) | Rn(zn) | Rm(zm));
|
||||
Emit(0x45006c00 | size | Rd(zd) | Rn(zn) | Rm(zm));
|
||||
}
|
||||
|
||||
void Assembler::raddhnb(const ZRegister& zd,
|
||||
@@ -9895,5 +9895,25 @@ void Assembler::sudot(const ZRegister& zda,
|
||||
Emit(0x44a01c00 | Rx<18, 16>(zm) | (index << 19) | Rd(zda) | Rn(zn));
|
||||
}
|
||||
|
||||
void Assembler::bfcvt(const ZRegister& zd,
|
||||
const PRegisterM& pg,
|
||||
const ZRegister& zn) {
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kBF16));
|
||||
VIXL_ASSERT(zd.IsLaneSizeH() && zn.IsLaneSizeS());
|
||||
|
||||
Emit(0x658aa000 | Rd(zd) | PgLow8(pg) | Rn(zn));
|
||||
}
|
||||
|
||||
void Assembler::bfcvtnt(const ZRegister& zd,
|
||||
const PRegisterM& pg,
|
||||
const ZRegister& zn) {
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kSVE));
|
||||
VIXL_ASSERT(CPUHas(CPUFeatures::kBF16));
|
||||
VIXL_ASSERT(zd.IsLaneSizeH() && zn.IsLaneSizeS());
|
||||
|
||||
Emit(0x648aa000 | Rd(zd) | PgLow8(pg) | Rn(zn));
|
||||
}
|
||||
|
||||
} // namespace aarch64
|
||||
} // namespace vixl
|
||||
|
||||
+2
@@ -82,6 +82,7 @@ const IDRegister::Field AA64ISAR1::kI8MM(52);
|
||||
const IDRegister::Field AA64ISAR2::kWFXT(0);
|
||||
const IDRegister::Field AA64ISAR2::kRPRES(4);
|
||||
const IDRegister::Field AA64ISAR2::kMOPS(16);
|
||||
const IDRegister::Field AA64ISAR2::kHBC(20);
|
||||
const IDRegister::Field AA64ISAR2::kCSSC(52);
|
||||
|
||||
const IDRegister::Field AA64MMFR0::kECV(60);
|
||||
@@ -198,6 +199,7 @@ CPUFeatures AA64ISAR2::GetCPUFeatures() const {
|
||||
if (Get(kWFXT) >= 2) f.Combine(CPUFeatures::kWFXT);
|
||||
if (Get(kRPRES) >= 1) f.Combine(CPUFeatures::kRPRES);
|
||||
if (Get(kMOPS) >= 1) f.Combine(CPUFeatures::kMOPS);
|
||||
if (Get(kHBC) >= 1) f.Combine(CPUFeatures::kHBC);
|
||||
if (Get(kCSSC) >= 1) f.Combine(CPUFeatures::kCSSC);
|
||||
return f;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,111 @@ CPUFeaturesAuditor::GetFormToVisitorFnMap() {
|
||||
static const FormToVisitorFnMap form_to_visitor = {
|
||||
DEFAULT_FORM_TO_VISITOR_MAP(CPUFeaturesAuditor),
|
||||
SIM_AUD_VISITOR_MAP(CPUFeaturesAuditor),
|
||||
{"fcvt_dh_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"fcvt_ds_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"fcvt_hd_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"fcvt_hs_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"fcvt_sd_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"fcvt_sh_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"fmov_d_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"fmov_h_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"fmov_s_floatdp1"_h, &CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frint32x_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frint32x_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frint32z_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frint32z_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frint64x_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frint64x_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frint64z_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frint64z_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frinta_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frinta_h_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frinta_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frinti_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frinti_h_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frinti_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintm_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintm_h_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintm_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintn_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintn_h_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintn_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintp_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintp_h_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintp_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintx_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintx_h_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintx_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintz_d_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintz_h_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frintz_s_floatdp1"_h,
|
||||
&CPUFeaturesAuditor::VisitFPDataProcessing1Source},
|
||||
{"frint32x_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frint32z_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frint64x_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frint64z_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frinta_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frinti_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frintm_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frintn_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frintp_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frintx_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frintz_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtas_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtau_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtl_asimdmisc_l"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtms_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtmu_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtns_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtnu_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtn_asimdmisc_n"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtps_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtpu_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtxn_asimdmisc_n"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtzs_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcvtzu_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fabs_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcmeq_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcmge_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcmgt_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcmle_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcmlt_asimdmisc_fz"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fneg_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frecpe_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"frsqrte_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fsqrt_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"scvtf_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"ucvtf_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"urecpe_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"ursqrte_asimdmisc_r"_h, &CPUFeaturesAuditor::VisitNEON2RegMisc},
|
||||
{"fcmla_asimdelem_c_h"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
|
||||
{"fcmla_asimdelem_c_s"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
|
||||
{"fmlal2_asimdelem_lh"_h, &CPUFeaturesAuditor::VisitNEONByIndexedElement},
|
||||
@@ -226,6 +331,9 @@ void CPUFeaturesAuditor::VisitCompareBranch(const Instruction* instr) {
|
||||
void CPUFeaturesAuditor::VisitConditionalBranch(const Instruction* instr) {
|
||||
RecordInstructionFeaturesScope scope(this);
|
||||
USE(instr);
|
||||
if (form_hash_ == "bc_only_condbranch"_h) {
|
||||
scope.Record(CPUFeatures::kHBC);
|
||||
}
|
||||
}
|
||||
|
||||
void CPUFeaturesAuditor::VisitConditionalCompareImmediate(
|
||||
@@ -285,6 +393,12 @@ void CPUFeaturesAuditor::VisitCryptoSM3(const Instruction* instr) {
|
||||
USE(instr);
|
||||
}
|
||||
|
||||
void CPUFeaturesAuditor::VisitCryptoSM4(const Instruction* instr) {
|
||||
RecordInstructionFeaturesScope scope(this);
|
||||
scope.Record(CPUFeatures::kNEON, CPUFeatures::kSM4);
|
||||
USE(instr);
|
||||
}
|
||||
|
||||
void CPUFeaturesAuditor::VisitDataProcessing1Source(const Instruction* instr) {
|
||||
RecordInstructionFeaturesScope scope(this);
|
||||
switch (instr->Mask(DataProcessing1SourceMask)) {
|
||||
@@ -1876,6 +1990,18 @@ void CPUFeaturesAuditor::Visit(Metadata* metadata, const Instruction* instr) {
|
||||
CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kSHA512)},
|
||||
{"sha512su1_vvv2_cryptosha512_3"_h,
|
||||
CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kSHA512)},
|
||||
{"pmullb_z_zz_q"_h,
|
||||
CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEPmull128)},
|
||||
{"pmullt_z_zz_q"_h,
|
||||
CPUFeatures(CPUFeatures::kSVE2, CPUFeatures::kSVEPmull128)},
|
||||
{"bfcvt_bs_floatdp1"_h,
|
||||
CPUFeatures(CPUFeatures::kFP, CPUFeatures::kBF16)},
|
||||
{"bfcvtn_asimdmisc_4s"_h,
|
||||
CPUFeatures(CPUFeatures::kNEON, CPUFeatures::kBF16)},
|
||||
{"bfcvt_z_p_z_s2bf"_h,
|
||||
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kBF16)},
|
||||
{"bfcvtnt_z_p_z_s2bf"_h,
|
||||
CPUFeatures(CPUFeatures::kSVE, CPUFeatures::kBF16)},
|
||||
};
|
||||
|
||||
if (features.count(form_hash_) > 0) {
|
||||
|
||||
+498
@@ -0,0 +1,498 @@
|
||||
// Copyright 2023, VIXL authors
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
// * Neither the name of ARM Limited nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
|
||||
|
||||
#include "debugger-aarch64.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <errno.h>
|
||||
#include <limits>
|
||||
|
||||
namespace vixl {
|
||||
namespace aarch64 {
|
||||
|
||||
|
||||
Debugger::Debugger(Simulator* sim)
|
||||
: sim_(sim), input_stream_(&std::cin), ostream_(sim->GetOutputStream()) {
|
||||
// Register all basic debugger commands.
|
||||
RegisterCmd<HelpCmd>();
|
||||
RegisterCmd<BreakCmd>();
|
||||
RegisterCmd<StepCmd>();
|
||||
RegisterCmd<ContinueCmd>();
|
||||
RegisterCmd<PrintCmd>();
|
||||
RegisterCmd<TraceCmd>();
|
||||
RegisterCmd<GdbCmd>();
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
void Debugger::RegisterCmd() {
|
||||
auto new_command = std::make_unique<T>(sim_);
|
||||
|
||||
// Check that the new command word and alias, don't already exist.
|
||||
std::string_view new_cmd_word = new_command->GetCommandWord();
|
||||
std::string_view new_cmd_alias = new_command->GetCommandAlias();
|
||||
for (const auto& cmd : debugger_cmds_) {
|
||||
std::string_view cmd_word = cmd->GetCommandWord();
|
||||
std::string_view cmd_alias = cmd->GetCommandAlias();
|
||||
|
||||
if (new_cmd_word == cmd_word) {
|
||||
VIXL_ABORT_WITH_MSG("Command word matches an existing command word.");
|
||||
} else if (new_cmd_word == cmd_alias) {
|
||||
VIXL_ABORT_WITH_MSG("Command word matches an existing command alias.");
|
||||
}
|
||||
|
||||
if (new_cmd_alias != "") {
|
||||
if (new_cmd_alias == cmd_word) {
|
||||
VIXL_ABORT_WITH_MSG("Command alias matches an existing command word.");
|
||||
} else if (new_cmd_alias == cmd_alias) {
|
||||
VIXL_ABORT_WITH_MSG("Command alias matches an existing command alias.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debugger_cmds_.push_back(std::move(new_command));
|
||||
}
|
||||
|
||||
|
||||
bool Debugger::IsAtBreakpoint() const {
|
||||
return IsBreakpoint(reinterpret_cast<uint64_t>(sim_->ReadPc()));
|
||||
}
|
||||
|
||||
|
||||
void Debugger::Debug() {
|
||||
DebugReturn done = DebugContinue;
|
||||
while (done == DebugContinue) {
|
||||
// Disassemble the next instruction to execute.
|
||||
PrintDisassembler print_disasm = PrintDisassembler(ostream_);
|
||||
print_disasm.Disassemble(sim_->ReadPc());
|
||||
|
||||
// Read the command line.
|
||||
fprintf(ostream_, "sim> ");
|
||||
std::string line;
|
||||
std::getline(*input_stream_, line);
|
||||
|
||||
// Remove all control characters from the command string.
|
||||
line.erase(std::remove_if(line.begin(),
|
||||
line.end(),
|
||||
[](char c) { return std::iscntrl(c); }),
|
||||
line.end());
|
||||
|
||||
// Assume input from std::cin has already been output (e.g: by a terminal)
|
||||
// but input from elsewhere (e.g: from a testing input stream) has not.
|
||||
if (input_stream_ != &std::cin) {
|
||||
fprintf(ostream_, "%s\n", line.c_str());
|
||||
}
|
||||
|
||||
// Parse the command into tokens.
|
||||
std::vector<std::string> tokenized_cmd = Tokenize(line);
|
||||
if (!tokenized_cmd.empty()) {
|
||||
done = ExecDebugCommand(tokenized_cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::optional<uint64_t> Debugger::ParseUint64String(std::string_view uint64_str,
|
||||
int base) {
|
||||
// Clear any previous errors.
|
||||
errno = 0;
|
||||
|
||||
// strtoull uses 0 to indicate that no conversion was possible so first
|
||||
// check that the string isn't zero.
|
||||
if (IsZeroUint64String(uint64_str, base)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Cannot use stoi as it might not be possible to use exceptions.
|
||||
char* end;
|
||||
uint64_t value = std::strtoull(uint64_str.data(), &end, base);
|
||||
if (value == 0 || *end != '\0' || errno == ERANGE) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
std::optional<Debugger::RegisterParsedFormat> Debugger::ParseRegString(
|
||||
std::string_view reg_str) {
|
||||
// A register should only have 2 (e.g: X0) or 3 (e.g: X31) characters.
|
||||
if (reg_str.size() < 2 || reg_str.size() > 3) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// Check for aliases of registers.
|
||||
if (reg_str == "lr") {
|
||||
return {{'X', kLinkRegCode}};
|
||||
} else if (reg_str == "sp") {
|
||||
return {{'X', kSpRegCode}};
|
||||
}
|
||||
|
||||
unsigned max_reg_num;
|
||||
char reg_prefix = std::toupper(reg_str.front());
|
||||
switch (reg_prefix) {
|
||||
case 'W':
|
||||
VIXL_FALLTHROUGH();
|
||||
case 'X':
|
||||
max_reg_num = kNumberOfRegisters - 1;
|
||||
break;
|
||||
case 'V':
|
||||
max_reg_num = kNumberOfVRegisters - 1;
|
||||
break;
|
||||
case 'Z':
|
||||
max_reg_num = kNumberOfZRegisters - 1;
|
||||
break;
|
||||
case 'P':
|
||||
max_reg_num = kNumberOfPRegisters - 1;
|
||||
break;
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string_view str_code = reg_str.substr(1, reg_str.size());
|
||||
auto reg_code = ParseUint64String(str_code, 10);
|
||||
if (!reg_code) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (*reg_code > max_reg_num) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return {{reg_prefix, static_cast<unsigned int>(*reg_code)}};
|
||||
}
|
||||
|
||||
|
||||
void Debugger::PrintUsage() {
|
||||
for (const auto& cmd : debugger_cmds_) {
|
||||
// Print commands in the following format:
|
||||
// foo / f
|
||||
// foo <arg>
|
||||
// A description of the foo command.
|
||||
//
|
||||
|
||||
std::string_view cmd_word = cmd->GetCommandWord();
|
||||
std::string_view cmd_alias = cmd->GetCommandAlias();
|
||||
if (cmd_alias != "") {
|
||||
fprintf(ostream_, "%s / %s\n", cmd_word.data(), cmd_alias.data());
|
||||
} else {
|
||||
fprintf(ostream_, "%s\n", cmd_word.data());
|
||||
}
|
||||
|
||||
std::string_view args_str = cmd->GetArgsString();
|
||||
if (args_str != "") {
|
||||
fprintf(ostream_, "\t%s %s\n", cmd_word.data(), args_str.data());
|
||||
}
|
||||
|
||||
std::string_view description = cmd->GetDescription();
|
||||
if (description != "") {
|
||||
fprintf(ostream_, "\t%s\n", description.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> Debugger::Tokenize(std::string_view input_line,
|
||||
char separator) {
|
||||
std::vector<std::string> words;
|
||||
|
||||
if (input_line.empty()) {
|
||||
return words;
|
||||
}
|
||||
|
||||
for (auto separator_pos = input_line.find(separator);
|
||||
separator_pos != input_line.npos;
|
||||
separator_pos = input_line.find(separator)) {
|
||||
// Skip consecutive, repeated separators.
|
||||
if (separator_pos != 0) {
|
||||
words.push_back(std::string{input_line.substr(0, separator_pos)});
|
||||
}
|
||||
|
||||
// Remove characters up to and including the separator.
|
||||
input_line.remove_prefix(separator_pos + 1);
|
||||
}
|
||||
|
||||
// Add the rest of the string to the vector.
|
||||
words.push_back(std::string{input_line});
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
|
||||
DebugReturn Debugger::ExecDebugCommand(
|
||||
const std::vector<std::string>& tokenized_cmd) {
|
||||
std::string cmd_word = tokenized_cmd.front();
|
||||
for (const auto& cmd : debugger_cmds_) {
|
||||
if (cmd_word == cmd->GetCommandWord() ||
|
||||
cmd_word == cmd->GetCommandAlias()) {
|
||||
const std::vector<std::string> args(tokenized_cmd.begin() + 1,
|
||||
tokenized_cmd.end());
|
||||
|
||||
// Call the handler for the command and pass the arguments.
|
||||
return cmd->Action(args);
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(ostream_, "Error: command '%s' not found\n", cmd_word.c_str());
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
|
||||
bool Debugger::IsZeroUint64String(std::string_view uint64_str, int base) {
|
||||
// Remove any hex prefixes.
|
||||
if (base == 0 || base == 16) {
|
||||
std::string_view prefix = uint64_str.substr(0, 2);
|
||||
if (prefix == "0x" || prefix == "0X") {
|
||||
uint64_str.remove_prefix(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (uint64_str.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check all remaining digits in the string for anything other than zero.
|
||||
for (char c : uint64_str) {
|
||||
if (c != '0') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
DebuggerCmd::DebuggerCmd(Simulator* sim,
|
||||
std::string cmd_word,
|
||||
std::string cmd_alias,
|
||||
std::string args_str,
|
||||
std::string description)
|
||||
: sim_(sim),
|
||||
ostream_(sim->GetOutputStream()),
|
||||
command_word_(cmd_word),
|
||||
command_alias_(cmd_alias),
|
||||
args_str_(args_str),
|
||||
description_(description) {}
|
||||
|
||||
|
||||
DebugReturn HelpCmd::Action(const std::vector<std::string>& args) {
|
||||
USE(args);
|
||||
sim_->GetDebugger()->PrintUsage();
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
|
||||
DebugReturn BreakCmd::Action(const std::vector<std::string>& args) {
|
||||
if (args.size() != 1) {
|
||||
fprintf(ostream_, "Error: Use `break <address>` to set a breakpoint\n");
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
std::string arg = args.front();
|
||||
auto break_addr = Debugger::ParseUint64String(arg);
|
||||
if (!break_addr) {
|
||||
fprintf(ostream_, "Error: Use `break <address>` to set a breakpoint\n");
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
if (sim_->GetDebugger()->IsBreakpoint(*break_addr)) {
|
||||
sim_->GetDebugger()->RemoveBreakpoint(*break_addr);
|
||||
fprintf(ostream_,
|
||||
"Breakpoint successfully removed at: 0x%" PRIx64 "\n",
|
||||
*break_addr);
|
||||
} else {
|
||||
sim_->GetDebugger()->RegisterBreakpoint(*break_addr);
|
||||
fprintf(ostream_,
|
||||
"Breakpoint successfully added at: 0x%" PRIx64 "\n",
|
||||
*break_addr);
|
||||
}
|
||||
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
|
||||
DebugReturn StepCmd::Action(const std::vector<std::string>& args) {
|
||||
if (args.size() > 1) {
|
||||
fprintf(ostream_,
|
||||
"Error: use `step [number]` to step an optional number of"
|
||||
" instructions\n");
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
// Step 1 instruction by default.
|
||||
std::optional<uint64_t> number_of_instructions_to_execute{1};
|
||||
|
||||
if (args.size() == 1) {
|
||||
// Parse the argument to step that number of instructions.
|
||||
std::string arg = args.front();
|
||||
number_of_instructions_to_execute = Debugger::ParseUint64String(arg);
|
||||
if (!number_of_instructions_to_execute) {
|
||||
fprintf(ostream_,
|
||||
"Error: use `step [number]` to step an optional number of"
|
||||
" instructions\n");
|
||||
return DebugContinue;
|
||||
}
|
||||
}
|
||||
|
||||
while (!sim_->IsSimulationFinished() &&
|
||||
*number_of_instructions_to_execute > 0) {
|
||||
sim_->ExecuteInstruction();
|
||||
(*number_of_instructions_to_execute)--;
|
||||
|
||||
// The first instruction has already been printed by Debug() so only
|
||||
// enable instruction tracing after the first instruction has been
|
||||
// executed.
|
||||
sim_->SetTraceParameters(sim_->GetTraceParameters() | LOG_DISASM);
|
||||
}
|
||||
|
||||
// Disable instruction tracing after all instructions have been executed.
|
||||
sim_->SetTraceParameters(sim_->GetTraceParameters() & ~LOG_DISASM);
|
||||
|
||||
if (sim_->IsSimulationFinished()) {
|
||||
fprintf(ostream_,
|
||||
"Debugger at the end of simulation, leaving simulator...\n");
|
||||
return DebugExit;
|
||||
}
|
||||
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
|
||||
DebugReturn ContinueCmd::Action(const std::vector<std::string>& args) {
|
||||
USE(args);
|
||||
|
||||
fprintf(ostream_, "Continuing...\n");
|
||||
|
||||
if (sim_->GetDebugger()->IsAtBreakpoint()) {
|
||||
// This breakpoint has already been hit, so execute it before continuing.
|
||||
sim_->ExecuteInstruction();
|
||||
}
|
||||
|
||||
return DebugExit;
|
||||
}
|
||||
|
||||
|
||||
DebugReturn PrintCmd::Action(const std::vector<std::string>& args) {
|
||||
if (args.size() != 1) {
|
||||
fprintf(ostream_,
|
||||
"Error: use `print <register|all>` to print the contents of a"
|
||||
" specific register or all registers.\n");
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
if (args.front() == "all") {
|
||||
sim_->PrintRegisters();
|
||||
sim_->PrintZRegisters();
|
||||
} else if (args.front() == "system") {
|
||||
sim_->PrintSystemRegisters();
|
||||
} else if (args.front() == "ffr") {
|
||||
sim_->PrintFFR();
|
||||
} else {
|
||||
auto reg = Debugger::ParseRegString(args.front());
|
||||
if (!reg) {
|
||||
fprintf(ostream_,
|
||||
"Error: incorrect register format, use e.g: X0, x0, etc...\n");
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
// Ensure the stack pointer is printed instead of the zero register.
|
||||
if ((*reg).second == kSpRegCode) {
|
||||
(*reg).second = kSPRegInternalCode;
|
||||
}
|
||||
|
||||
// Registers are printed in different ways depending on their type.
|
||||
switch ((*reg).first) {
|
||||
case 'W':
|
||||
sim_->PrintRegister(
|
||||
(*reg).second,
|
||||
static_cast<Simulator::PrintRegisterFormat>(
|
||||
Simulator::PrintRegisterFormat::kPrintWReg |
|
||||
Simulator::PrintRegisterFormat::kPrintRegPartial));
|
||||
break;
|
||||
case 'X':
|
||||
sim_->PrintRegister((*reg).second,
|
||||
Simulator::PrintRegisterFormat::kPrintXReg);
|
||||
break;
|
||||
case 'V':
|
||||
sim_->PrintVRegister((*reg).second);
|
||||
break;
|
||||
case 'Z':
|
||||
sim_->PrintZRegister((*reg).second);
|
||||
break;
|
||||
case 'P':
|
||||
sim_->PrintPRegister((*reg).second);
|
||||
break;
|
||||
default:
|
||||
// ParseRegString should only allow valid register characters.
|
||||
VIXL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
|
||||
DebugReturn TraceCmd::Action(const std::vector<std::string>& args) {
|
||||
if (args.size() != 0) {
|
||||
fprintf(ostream_, "Error: use `trace` to toggle tracing of registers.\n");
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
int trace_params = sim_->GetTraceParameters();
|
||||
if ((trace_params & LOG_ALL) != LOG_ALL) {
|
||||
fprintf(ostream_,
|
||||
"Enabling disassembly, registers and memory write tracing\n");
|
||||
sim_->SetTraceParameters(trace_params | LOG_ALL);
|
||||
} else {
|
||||
fprintf(ostream_,
|
||||
"Disabling disassembly, registers and memory write tracing\n");
|
||||
sim_->SetTraceParameters(trace_params & ~LOG_ALL);
|
||||
}
|
||||
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
|
||||
DebugReturn GdbCmd::Action(const std::vector<std::string>& args) {
|
||||
if (args.size() != 0) {
|
||||
fprintf(ostream_,
|
||||
"Error: use `gdb` to enter GDB from the simulator debugger.\n");
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
HostBreakpoint();
|
||||
return DebugContinue;
|
||||
}
|
||||
|
||||
|
||||
} // namespace aarch64
|
||||
} // namespace vixl
|
||||
|
||||
#endif // VIXL_INCLUDE_SIMULATOR_AARCH64
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user