feat: updated engine version to 4.4-rc1
This commit is contained in:
parent
ee00efde1f
commit
21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions
389
engine/thirdparty/README.md
vendored
389
engine/thirdparty/README.md
vendored
|
|
@ -29,7 +29,10 @@ Files extracted from upstream source:
|
|||
- `shaders` folder from `src/ffx-fsr2-api` with `ffx_*.hlsl` files excluded
|
||||
- `LICENSE.txt`
|
||||
|
||||
Apply `patches` to add the new options required by Godot and general compilation fixes.
|
||||
Patches:
|
||||
|
||||
- `0001-build-fixes.patch` (GH-81197)
|
||||
- `0002-godot-fsr2-options.patch` (GH-81197)
|
||||
|
||||
|
||||
## angle
|
||||
|
|
@ -59,16 +62,21 @@ Files extracted from upstream source:
|
|||
## basis_universal
|
||||
|
||||
- Upstream: https://github.com/BinomialLLC/basis_universal
|
||||
- Version: 1.16.4 (900e40fb5d2502927360fe2f31762bdbb624455f, 2023)
|
||||
- Version: 1.50.0 (051ad6d8a64bb95a79e8601c317055fd1782ad3e, 2024)
|
||||
- License: Apache 2.0
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- `encoder/` and `transcoder/` folders, minus `jpgd.{cpp,h}`
|
||||
- `encoder/` and `transcoder/` folders, with the following files removed from `encoder`:
|
||||
`jpgd.{cpp,h}`, `3rdparty/{qoi.h,tinydds.h,tinyexr.cpp,tinyexr.h}`
|
||||
- `LICENSE`
|
||||
|
||||
Applied upstream PR https://github.com/BinomialLLC/basis_universal/pull/344 to
|
||||
fix build with our own copy of zstd (patch in `patches`).
|
||||
Patches:
|
||||
|
||||
- `0001-external-zstd-pr344.patch` (GH-73441)
|
||||
- `0002-external-jpgd.patch` (GH-88508)
|
||||
- `0003-external-tinyexr.patch` (GH-97582)
|
||||
- `0004-remove-tinydds-qoi.patch` (GH-97582)
|
||||
|
||||
|
||||
## brotli
|
||||
|
|
@ -87,14 +95,19 @@ Files extracted from upstream source:
|
|||
## certs
|
||||
|
||||
- Upstream: Mozilla, via https://github.com/bagder/ca-bundle
|
||||
- Version: git (c5a419971b1bec220368c619aaafd0b818aa119f, 2024)
|
||||
- Version: git (4d3fe6683f651d96be1bbef316b201e9b33b274d, 2024),
|
||||
generated from mozilla-release changeset b8ea2342548b8571e58f9176d9555ccdb5ec199f
|
||||
- License: MPL 2.0
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- `ca-bundle.crt` renamed to `ca-certificates.crt`
|
||||
|
||||
|
||||
## clipper2
|
||||
|
||||
- Upstream: https://github.com/AngusJohnson/Clipper2
|
||||
- Version: 1.3.0 (98db5662e8dd1808a5a7b50c5605a2289bb390e8, 2023)
|
||||
- Version: 1.4.0 (736ddb0b53d97fd5f65dd3d9bbf8a0993eaf387c, 2024)
|
||||
- License: BSL 1.0
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
@ -102,8 +115,10 @@ Files extracted from upstream source:
|
|||
- `CPP/Clipper2Lib/` folder (in root)
|
||||
- `LICENSE`
|
||||
|
||||
Apply the patches in the `patches/` folder when syncing on newer upstream
|
||||
commits.
|
||||
Patches:
|
||||
|
||||
- `0001-disable-exceptions.patch` (GH-80796)
|
||||
- `0002-llvm-disable-int1280-math.patch` (GH-95964)
|
||||
|
||||
|
||||
## cvtt
|
||||
|
|
@ -117,10 +132,9 @@ Files extracted from upstream source:
|
|||
- All `.cpp` and `.h` files except the folders `MakeTables` and `etc2packer`
|
||||
- `LICENSE.txt`
|
||||
|
||||
Changes related to BC6H packing and unpacking made upstream in
|
||||
https://github.com/elasota/cvtt/commit/2e4b6b2747aec11f4cc6dd09ef43fa8ce769f6e2
|
||||
have been removed as they caused massive quality regressions. Apply the patches
|
||||
in the `patches/` folder when syncing on newer upstream commits.
|
||||
Patches:
|
||||
|
||||
- `0001-revert-bc6h-reorg.patch` (GH-73715)
|
||||
|
||||
|
||||
## d3d12ma
|
||||
|
|
@ -135,9 +149,9 @@ Files extracted from upstream source:
|
|||
- `include/D3D12MemAlloc.h`
|
||||
- `LICENSE.txt`, `NOTICES.txt`
|
||||
|
||||
Important: Some files have Godot-made changes for use with MinGW.
|
||||
They are marked with `/* GODOT start */` and `/* GODOT end */`
|
||||
comments.
|
||||
Patches:
|
||||
|
||||
- `0001-mingw-support.patch` (GH-83452)
|
||||
|
||||
|
||||
## directx_headers
|
||||
|
|
@ -152,9 +166,10 @@ Files extracted from upstream source:
|
|||
- `include/dxguids/*.h`
|
||||
- `LICENSE`
|
||||
|
||||
Important: Some files have Godot-made changes for use with MinGW.
|
||||
They are marked with `/* GODOT start */` and `/* GODOT end */`
|
||||
comments.
|
||||
Patches:
|
||||
|
||||
- `0001-mingw-pragma.patch` (GH-83452)
|
||||
- `0002-win7-8-dynamic-load.patch` (GH-88496)
|
||||
|
||||
|
||||
## doctest
|
||||
|
|
@ -182,13 +197,17 @@ Files extracted from upstream:
|
|||
- All config files listed in `modules/raycast/godot_update_embree.py`
|
||||
- `LICENSE.txt`
|
||||
|
||||
The `modules/raycast/godot_update_embree.py` script can be used to pull the
|
||||
relevant files from the latest Embree release and apply some automatic changes.
|
||||
Patches:
|
||||
|
||||
Some changes have been made in order to remove exceptions and fix minor build errors.
|
||||
They are marked with `// -- GODOT start --` and `// -- GODOT end --`
|
||||
comments. Apply the patches in the `patches/` folder when syncing on newer upstream
|
||||
commits.
|
||||
- `0001-disable-exceptions.patch` (GH-48050)
|
||||
- `0002-godot-config.patch` (GH-88783)
|
||||
- `0003-emscripten-nthreads.patch` (GH-69799)
|
||||
- `0004-mingw-no-cpuidex.patch` (GH-92488)
|
||||
- `0005-mingw-llvm-arm64.patch` (GH-93364)
|
||||
- `0006-include-order-dllexport.patch` (GH-94256)
|
||||
|
||||
The `modules/raycast/godot_update_embree.py` script can be used to pull the
|
||||
relevant files from the latest Embree release and apply patches automatically.
|
||||
|
||||
|
||||
## enet
|
||||
|
|
@ -202,23 +221,21 @@ Files extracted from upstream source:
|
|||
- All `.c` files in the main directory (except `unix.c` and `win32.c`)
|
||||
- The `include/enet/` folder as `enet/` (except `unix.h` and `win32.h`)
|
||||
- `LICENSE` file
|
||||
- Added 3 files `enet_godot.cpp`, `enet/enet_godot.h`, and `enet/enet_godot_ext.h`,
|
||||
providing ENet socket implementation using Godot classes, allowing IPv6 and DTLS.
|
||||
|
||||
Important: `enet.h`, `host.c`, `protocol.c` have been slightly modified
|
||||
to be usable by Godot's socket implementation and allow IPv6 and DTLS.
|
||||
Apply the patches in the `patches/` folder when syncing on newer upstream
|
||||
commits.
|
||||
Patches:
|
||||
|
||||
Three files (`godot.cpp`, `enet/godot.h`, `enet/godot_ext.h`) have been added to
|
||||
provide ENet socket implementation using Godot classes.
|
||||
- `0001-godot-socket.patch` (GH-7985)
|
||||
|
||||
It is still possible to build against a system wide ENet but doing so will limit
|
||||
its functionality to IPv4 only.
|
||||
Important: Building against a system wide ENet is possible, but will limit its
|
||||
functionality to IPv4 only and no DTLS. We recommend against it.
|
||||
|
||||
|
||||
## etcpak
|
||||
|
||||
- Upstream: https://github.com/wolfpld/etcpak
|
||||
- Version: git (5380688660a3801aec4b25483366027fe0442d7b, 2024)
|
||||
- Version: 2.0 (a43d6925bee49277945cf3e311e4a022ae0c2073, 2024)
|
||||
- License: BSD-3-Clause
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
@ -228,8 +245,14 @@ Files extracted from upstream source:
|
|||
Dither.{cpp,hpp} ForceInline.hpp Math.hpp ProcessCommon.hpp ProcessRGB.{cpp,hpp}
|
||||
ProcessDxtc.{cpp,hpp} Tables.{cpp,hpp} Vector.hpp
|
||||
```
|
||||
- The files `DecodeRGB.{cpp.hpp}` are based on the code from the original repository.
|
||||
- `AUTHORS.txt` and `LICENSE.txt`
|
||||
|
||||
Patches:
|
||||
|
||||
- `0001-remove-bc7enc.patch` (GH-101362)
|
||||
|
||||
|
||||
## fonts
|
||||
|
||||
- `DroidSans*.woff2`:
|
||||
|
|
@ -240,10 +263,6 @@ Files extracted from upstream source:
|
|||
* Upstream: https://github.com/JetBrains/JetBrainsMono
|
||||
* Version: 2.304 (cd5227bd1f61dff3bbd6c814ceaf7ffd95e947d9, 2023)
|
||||
* License: OFL-1.1
|
||||
- `NotoNaskhArabicUI*.woff2`:
|
||||
* Upstream: https://github.com/notofonts/arabic
|
||||
* Version: 2.014 (133ccaebf922ca080a7eef22998611ac3c242df9, 2022)
|
||||
* License: OFL-1.1
|
||||
- `NotoSans*.woff2`:
|
||||
* Upstream: https://github.com/notofonts/latin-greek-cyrillic
|
||||
* Version: 2.012 (9ea0c8d37bff0c0067b03777f40aa04f2bf78f99, 2023)
|
||||
|
|
@ -292,6 +311,10 @@ Files extracted from upstream source:
|
|||
* Upstream: https://fonts.google.com/specimen/Open+Sans
|
||||
* Version: 1.10 (downloaded from Google Fonts in February 2021)
|
||||
* License: Apache 2.0
|
||||
- `Vazirmatn*.woff2`:
|
||||
* Upstream: https://github.com/rastikerdar/vazirmatn
|
||||
* Version: 33.003 (83629f877e8f084cc07b47030b5d3a0ff06c76ec, 2022)
|
||||
* License: OFL-1.1
|
||||
|
||||
All fonts are converted from the unhinted `.ttf` sources using the
|
||||
`https://github.com/google/woff2` tool.
|
||||
|
|
@ -334,11 +357,12 @@ Files generated from [upstream web instance](https://gen.glad.sh/):
|
|||
- `glx.c`
|
||||
- `glad/glx.h`
|
||||
|
||||
See the permalinks in `glad/gl.h` and `glad/glx.h` to regenrate the files with
|
||||
See the permalinks in `glad/gl.h` and `glad/glx.h` to regenerate the files with
|
||||
a new version of the web instance.
|
||||
|
||||
Some changes have been made in order to allow loading OpenGL and OpenGLES APIs at the same time.
|
||||
See the patches in the `patches` directory.
|
||||
Patches:
|
||||
|
||||
- `0001-enable-both-gl-and-gles.patch` (GH-72831)
|
||||
|
||||
|
||||
## glslang
|
||||
|
|
@ -360,6 +384,11 @@ Files extracted from upstream source:
|
|||
- `LICENSE.txt`
|
||||
- Unnecessary files like `CMakeLists.txt` or `updateGrammar` removed
|
||||
|
||||
Patches:
|
||||
|
||||
- `0001-apple-disable-absolute-paths.patch` (GH-92010)
|
||||
- `0002-gcc15-include-fix.patch` (GH-102022)
|
||||
|
||||
|
||||
## graphite
|
||||
|
||||
|
|
@ -377,7 +406,7 @@ Files extracted from upstream source:
|
|||
## harfbuzz
|
||||
|
||||
- Upstream: https://github.com/harfbuzz/harfbuzz
|
||||
- Version: 8.5.0 (30485ee8c3d43c553afb9d78b9924cb71c8d2f19, 2024)
|
||||
- Version: 10.1.0 (9ef44a2d67ac870c1f7f671f6dc98d08a2579865, 2024)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
@ -385,13 +414,13 @@ Files extracted from upstream source:
|
|||
- `AUTHORS`, `COPYING`, `THANKS`
|
||||
- From the `src` folder, recursively:
|
||||
- All the `.cc`, `.h`, `.hh` files
|
||||
- Except `main.cc`, `harfbuzz*.cc`, `failing-alloc.c`, `test*.cc`, `hb-wasm*.*`
|
||||
- Except `main.cc`, `harfbuzz*.cc`, `failing-alloc.c`, `test*.cc`, `hb-wasm*.*`, `wasm/*`
|
||||
|
||||
|
||||
## icu4c
|
||||
|
||||
- Upstream: https://github.com/unicode-org/icu
|
||||
- Version: 75.1 (7750081bda4b3bc1768ae03849ec70f67ea10625, 2024)
|
||||
- Version: 76.1 (8eca245c7484ac6cc179e3e5f7c1ea7680810f39, 2024)
|
||||
- License: Unicode
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
@ -403,7 +432,7 @@ Files extracted from upstream source:
|
|||
|
||||
Files generated from upstream source:
|
||||
|
||||
- The `icudt75l.dat` built with the provided `godot_data.json` config file (see
|
||||
- The `icudt_godot.dat` built with the provided `godot_data.json` config file (see
|
||||
https://github.com/unicode-org/icu/blob/master/docs/userguide/icu_data/buildtool.md
|
||||
for instructions).
|
||||
|
||||
|
|
@ -413,7 +442,19 @@ Files generated from upstream source:
|
|||
3. Reconfigure ICU with custom data config:
|
||||
`ICU_DATA_FILTER_FILE={GODOT_SOURCE}/thirdparty/icu4c/godot_data.json ./runConfigureICU {PLATFORM} --with-data-packaging=common`
|
||||
4. Delete `data/out` folder and rebuild data: `cd data && rm -rf ./out && make`
|
||||
5. Copy `source/data/out/icudt75l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt75l.dat`
|
||||
5. Copy `source/data/out/icudt{ICU_VERSION}l.dat` to the `{GODOT_SOURCE}/thirdparty/icu4c/icudt_godot.dat`
|
||||
|
||||
|
||||
## jolt_physics
|
||||
|
||||
- Upstream: https://github.com/jrouwe/JoltPhysics
|
||||
- Version: 5.2.1 (f094082aa2bbfcbebc725dbe8b8f65c7d5152886, 2024)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- All files in `Jolt/`, except `Jolt/Jolt.cmake` and any files dependent on `ENABLE_OBJECT_STREAM`, as seen in `Jolt/Jolt.cmake`
|
||||
- `LICENSE`
|
||||
|
||||
|
||||
## jpeg-compressor
|
||||
|
|
@ -427,6 +468,10 @@ Files extracted from upstream source:
|
|||
- `jpgd*.{c,h}`
|
||||
- `jpge*.{c,h}`
|
||||
|
||||
Patches:
|
||||
|
||||
- `0001-clang-fortify-fix.patch` (GH-101927)
|
||||
|
||||
|
||||
## libbacktrace
|
||||
|
||||
|
|
@ -436,9 +481,15 @@ Files extracted from upstream source:
|
|||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- `*.{c,h}` files for Windows platform
|
||||
- `*.{c,h}` files for Windows platform, i.e. remove the following:
|
||||
* `allocfail.c`, `instrumented_alloc.c`, `*test*.{c,h}`
|
||||
* `elf.c`, `macho.c`, `mmap.c`, `mmapio.c`, `nounwind.c`, `unknown.c`, `xcoff.c`
|
||||
- `LICENSE`
|
||||
|
||||
Patches:
|
||||
|
||||
- `0001-big-files-support.patch` (GH-100281)
|
||||
|
||||
|
||||
## libktx
|
||||
|
||||
|
|
@ -457,7 +508,10 @@ Files extracted from upstream source:
|
|||
- `other_include/KHR/`
|
||||
- `utils/unused.h`
|
||||
|
||||
Some Godot-specific changes are applied via patches included in the `patches` folder.
|
||||
Patches:
|
||||
|
||||
- `0001-external-basisu.patch` (GH-76572)
|
||||
- `0002-disable-astc-block-ext.patch` (GH-76572)
|
||||
|
||||
|
||||
## libogg
|
||||
|
|
@ -476,14 +530,14 @@ Files extracted from upstream source:
|
|||
## libpng
|
||||
|
||||
- Upstream: http://libpng.org/pub/png/libpng.html
|
||||
- Version: 1.6.43 (ed217e3e601d8e462f7fd1e04bed43ac42212429, 2024)
|
||||
- Version: 1.6.45 (51f5bd68b9b806d2c92b4318164d28b49357da31, 2024)
|
||||
- License: libpng/zlib
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- All `.c` and `.h` files of the main directory, apart from `example.c` and
|
||||
`pngtest.c`
|
||||
- `arm/`, `intel/` and `powerpc/` folders
|
||||
- `arm/` (minus `filter_neon.S`), `intel/`, `loongarch/`, and `powerpc/` (minus `.editorconfig`) folders
|
||||
- `scripts/pnglibconf.h.prebuilt` as `pnglibconf.h`
|
||||
- `LICENSE`
|
||||
|
||||
|
|
@ -525,37 +579,60 @@ Files extracted from upstream source:
|
|||
- `src/` and `sharpyuv/` except from `.am`, `.rc` and `.in` files
|
||||
- `AUTHORS`, `COPYING`, `PATENTS`
|
||||
|
||||
Patch `godot-node-debug-fix.patch` workarounds shadowing of Godot's Node class
|
||||
in the MSVC debugger.
|
||||
Patches:
|
||||
|
||||
- `0001-msvc-node-debug-rename.patch`
|
||||
- `0002-msvc-arm64-fpstrict.patch`
|
||||
- `0003-clang-cl-sse2-sse41.patch`
|
||||
|
||||
|
||||
## linuxbsd_headers
|
||||
|
||||
See `linuxbsd_headers/README.md`.
|
||||
|
||||
|
||||
## manifold
|
||||
|
||||
- Upstream: https://github.com/elalish/manifold
|
||||
- Version: 3.0.1 (98b8142519d35c13e0e25cfa9fd6e3a271403be6, 2024)
|
||||
- License: Apache 2.0
|
||||
|
||||
File extracted from upstream source:
|
||||
|
||||
- `src/` and `include/`, except from `CMakeLists.txt`, `cross_section.cpp` and `meshIO.{cpp,h}`
|
||||
- `AUTHORS`, `LICENSE`
|
||||
|
||||
|
||||
## mbedtls
|
||||
|
||||
- Upstream: https://github.com/Mbed-TLS/mbedtls
|
||||
- Version: 3.6.0 (2ca6c285a0dd3f33982dd57299012dacab1ff206, 2024)
|
||||
- Version: 3.6.2 (107ea89daaefb9867ea9121002fbbdf926780e98, 2024)
|
||||
- License: Apache 2.0
|
||||
|
||||
File extracted from upstream release tarball:
|
||||
|
||||
- All `.h` from `include/mbedtls/` to `thirdparty/mbedtls/include/mbedtls/`
|
||||
and all `.h` from `include/psa/` to `thirdparty/mbedtls/include/psa/`
|
||||
- All `.c` and `.h` from `library/` to `thirdparty/mbedtls/library/` except
|
||||
for the `psa_*.c` source files
|
||||
- All `.c` and `.h` from `library/` to `thirdparty/mbedtls/library/`
|
||||
- From `library/` to `thirdparty/mbedtls/library/`:
|
||||
- All `.c` and `.h` files
|
||||
- Except `bignum_mod.c`, `block_cipher.c`, `ecp_curves_new.c`, `lmots.c`,
|
||||
`lms.c`
|
||||
- The `LICENSE` file (edited to keep only the Apache 2.0 variant)
|
||||
- Applied the patch `no-flexible-arrays.diff` to fix Windows build (see
|
||||
upstream GH-9020)
|
||||
- Applied the patch `msvc-redeclaration-bug.diff` to fix a compilation error
|
||||
with some MSVC versions
|
||||
- Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h`
|
||||
providing configuration for light bundling with core
|
||||
- Added the file `godot_module_mbedtls_config.h` to customize the build
|
||||
configuration when bundling the full library
|
||||
|
||||
Patches:
|
||||
|
||||
- `0001-msvc-2019-psa-redeclaration.patch` (GH-90535)
|
||||
|
||||
|
||||
## meshoptimizer
|
||||
|
||||
- Upstream: https://github.com/zeux/meshoptimizer
|
||||
- Version: 0.20 (c21d3be6ddf627f8ca852ba4b6db9903b0557858, 2023)
|
||||
- Version: 0.22 (4affad044571506a5724c9a6f15424f43e86f731, 2024)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream repository:
|
||||
|
|
@ -563,8 +640,9 @@ Files extracted from upstream repository:
|
|||
- All files in `src/`
|
||||
- `LICENSE.md`
|
||||
|
||||
A patch is included to modify the simplifier to report only distance error
|
||||
metrics instead of a combination of distance and attribute errors.
|
||||
Patches:
|
||||
|
||||
- `0001-simplifier-distance-only-error.patch` (GH-98529)
|
||||
|
||||
|
||||
## mingw-std-threads
|
||||
|
|
@ -582,8 +660,10 @@ Files extracted from upstream repository:
|
|||
- `mingw.shared_mutex.h`
|
||||
- `mingw.thread.h`
|
||||
|
||||
Once copied, apply `godot.patch` (needed because Godot is built without exceptions
|
||||
and to avoid std:: replacements leak in Clang builds).
|
||||
Patches:
|
||||
|
||||
- `0001-disable-exceptions.patch` (GH-85039)
|
||||
- `0002-clang-std-replacements-leak.patch` (GH-85208)
|
||||
|
||||
|
||||
## minimp3
|
||||
|
|
@ -598,26 +678,27 @@ Files extracted from upstream repository:
|
|||
- `minimp3_ex.h`
|
||||
- `LICENSE`
|
||||
|
||||
Some changes have been made in order to fix Windows on ARM build errors, and
|
||||
to solve some MSVC warnings. See the patches in the `patches` directory.
|
||||
Patches:
|
||||
|
||||
- `0001-msvc-arm.patch` (GH-64921)
|
||||
- `0002-msvc-warnings.patch` (GH-66545)
|
||||
|
||||
|
||||
## miniupnpc
|
||||
|
||||
- Upstream: https://github.com/miniupnp/miniupnp
|
||||
- Version: 2.2.7 (d4d5ec7d48c093b37b2ea5d7171ede21ce9d7ff2, 2024)
|
||||
- Version: 2.2.8 (b55145ec095652289a59c33603f3abafee898273, 2024)
|
||||
- License: BSD-3-Clause
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- Copy `miniupnpc/src` and `miniupnpc/include` to `thirdparty/miniupnpc`
|
||||
- `miniupnpc/src/` as `src/`
|
||||
- `miniupnpc/include/` as `include/miniupnpc/`
|
||||
- Remove the following test or sample files:
|
||||
`listdevices.c,minihttptestserver.c,miniupnpcmodule.c,upnpc.c,upnperrors.*,test*`
|
||||
- `LICENSE`
|
||||
|
||||
The only modified file is `src/miniupnpcstrings.h`, which was created for Godot
|
||||
(it is usually autogenerated by cmake). Bump the version number for miniupnpc in
|
||||
that file when upgrading.
|
||||
- `src/miniupnpcstrings.h` was created manually for Godot (it is usually generated
|
||||
by CMake). Bump the version number for miniupnpc in that file when upgrading.
|
||||
|
||||
|
||||
## minizip
|
||||
|
|
@ -632,19 +713,19 @@ Files extracted from the upstream source:
|
|||
`{crypt.h,ioapi.{c,h},unzip.{c,h},zip.{c,h}}`
|
||||
`MiniZip64_info.txt`
|
||||
|
||||
Important: Some files have Godot-made changes for use in core/io.
|
||||
They are marked with `/* GODOT start */` and `/* GODOT end */`
|
||||
comments and a patch is provided in the `patches` folder.
|
||||
Patches:
|
||||
|
||||
- `0001-godot-seek.patch` (GH-10428)
|
||||
|
||||
|
||||
## misc
|
||||
|
||||
Collection of single-file libraries used in Godot components.
|
||||
|
||||
- `clipper.{cpp,hpp}`
|
||||
* Upstream: https://sourceforge.net/projects/polyclipping
|
||||
* Version: 6.4.2 (2017) + Godot changes (added optional exceptions handling)
|
||||
* License: BSL-1.0
|
||||
- `bcdec.h`
|
||||
* Upstream: https://github.com/iOrange/bcdec
|
||||
* Version: git (3b29f8f44466c7d59852670f82f53905cf627d48, 2024)
|
||||
* License: MIT
|
||||
- `cubemap_coeffs.h`
|
||||
* Upstream: https://research.activision.com/publications/archives/fast-filtering-of-reflection-probes
|
||||
File coeffs_const_8.txt (retrieved April 2020)
|
||||
|
|
@ -653,14 +734,27 @@ Collection of single-file libraries used in Godot components.
|
|||
* Upstream: https://github.com/ariya/FastLZ
|
||||
* Version: 0.5.0 (4f20f54d46f5a6dd4fae4def134933369b7602d2, 2020)
|
||||
* License: MIT
|
||||
- `FastNoiseLite.h`
|
||||
* Upstream: https://github.com/Auburn/FastNoiseLite
|
||||
* Version: 1.1.0 (f7af54b56518aa659e1cf9fb103c0b6e36a833d9, 2023)
|
||||
* License: MIT
|
||||
* Patches:
|
||||
- `FastNoiseLite-0001-namespace-warnings.patch` (GH-88526)
|
||||
- `ifaddrs-android.{cc,h}`
|
||||
* Upstream: https://chromium.googlesource.com/external/webrtc/stable/talk/+/master/base/ifaddrs-android.h
|
||||
* Version: git (5976650443d68ccfadf1dea24999ee459dd2819d, 2013)
|
||||
* License: BSD-3-Clause
|
||||
* Patches:
|
||||
- `ifaddrs-android-0001-complete-struct.patch` (GH-34101)
|
||||
- `mikktspace.{c,h}`
|
||||
* Upstream: https://archive.blender.org/wiki/index.php/Dev:Shading/Tangent_Space_Normal_Maps/
|
||||
* Version: 1.0 (2011)
|
||||
* License: zlib
|
||||
- `nvapi_minimal.h`
|
||||
* Upstream: http://download.nvidia.com/XFree86/nvapi-open-source-sdk
|
||||
* Version: R525
|
||||
* License: MIT
|
||||
* Modifications: Created from upstream `nvapi.h` by removing unnecessary code.
|
||||
- `ok_color.h`
|
||||
* Upstream: https://github.com/bottosson/bottosson.github.io/blob/master/misc/ok_color.h
|
||||
* Version: git (d69831edb90ffdcd08b7e64da3c5405acd48ad2c, 2022)
|
||||
|
|
@ -677,13 +771,15 @@ Collection of single-file libraries used in Godot components.
|
|||
- `polypartition.{cpp,h}`
|
||||
* Upstream: https://github.com/ivanfratric/polypartition (`src/polypartition.{cpp,h}`)
|
||||
* Version: git (7bdffb428b2b19ad1c43aa44c714dcc104177e84, 2021)
|
||||
* Modifications: Change from STL to Godot types (see provided patch).
|
||||
* License: MIT
|
||||
- `qoa.h`
|
||||
* Patches:
|
||||
- `polypartition-0001-godot-types.patch` (2185c018f)
|
||||
- `polypartition-0002-shadow-warning.patch` (GH-66808)
|
||||
- `qoa.{c,h}`
|
||||
* Upstream: https://github.com/phoboslab/qoa
|
||||
* Version: git (5c2a86d615661f34636cf179abf4fa278d3257e0, 2024)
|
||||
* Modifications: Inlined functions, patched uninitialized variables and untyped mallocs.
|
||||
* Version: git (a2d927f8ce78a85e903676a33e0f956e53b89f7d, 2024)
|
||||
* License: MIT
|
||||
* Modifications: Added implementation through `qoa.c`.
|
||||
- `r128.{c,h}`
|
||||
* Upstream: https://github.com/fahickman/r128
|
||||
* Version: git (6fc177671c47640d5bb69af10cf4ee91050015a1, 2023)
|
||||
|
|
@ -692,10 +788,12 @@ Collection of single-file libraries used in Godot components.
|
|||
* Upstream: https://github.com/antirez/smaz
|
||||
* Version: git (2f625846a775501fb69456567409a8b12f10ea25, 2012)
|
||||
* License: BSD-3-Clause
|
||||
* Modifications: use `const char*` instead of `char*` for input string
|
||||
* Modifications: License included in header.
|
||||
* Patches:
|
||||
- `smaz-0001-write-string-warning.patch` (GH-8572)
|
||||
- `smolv.{cpp,h}`
|
||||
* Upstream: https://github.com/aras-p/smol-v
|
||||
* Version: git (4b52c165c13763051a18e80ffbc2ee436314ceb2, 2020)
|
||||
* Version: git (9dd54c379ac29fa148cb1b829bb939ba7381d8f4, 2024)
|
||||
* License: Public Domain or MIT
|
||||
- `stb_rect_pack.h`
|
||||
* Upstream: https://github.com/nothings/stb
|
||||
|
|
@ -710,7 +808,7 @@ Collection of single-file libraries used in Godot components.
|
|||
## msdfgen
|
||||
|
||||
- Upstream: https://github.com/Chlumsky/msdfgen
|
||||
- Version: 1.11 (f12d7ca00091a632a289865b85c3f2e0bfc6542d, 2023)
|
||||
- Version: 1.12 (85e8b3d47b3d1a42e4a5ebda0a24fb1cc2e669e0, 2024)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from the upstream source:
|
||||
|
|
@ -720,35 +818,10 @@ Files extracted from the upstream source:
|
|||
- `LICENSE.txt`
|
||||
|
||||
|
||||
## noise
|
||||
|
||||
- Upstream: https://github.com/Auburn/FastNoiseLite
|
||||
- Version: 1.1.0 (f7af54b56518aa659e1cf9fb103c0b6e36a833d9, 2023)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from the upstream source:
|
||||
|
||||
- `FastNoiseLite.h`
|
||||
- `LICENSE`
|
||||
|
||||
Some custom changes were made to fix compiler warnings, and can be re-applied
|
||||
with the provided patch.
|
||||
|
||||
|
||||
## nvapi
|
||||
|
||||
- Upstream: http://download.nvidia.com/XFree86/nvapi-open-source-sdk
|
||||
- Version: R525
|
||||
- License: MIT
|
||||
|
||||
- `nvapi_minimal.h` was created by using `nvapi.h` from upstream and removing
|
||||
unnecessary code.
|
||||
|
||||
|
||||
## openxr
|
||||
|
||||
- Upstream: https://github.com/KhronosGroup/OpenXR-SDK
|
||||
- Version: 1.0.34 (288d3a7ebc1ad959f62d51da75baa3d27438c499, 2024)
|
||||
- Version: 1.1.41 (7d1c0961351bac61fd7bb72d402649d5ac3f2935, 2024)
|
||||
- License: Apache 2.0
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
@ -772,6 +845,10 @@ Exclude:
|
|||
`*.{def,expsym,in,json,map,pom,rc,txt}`
|
||||
- All dotfiles
|
||||
|
||||
Patches:
|
||||
|
||||
- `0001-glad-egl.patch` (GH-98824)
|
||||
|
||||
|
||||
## pcre2
|
||||
|
||||
|
|
@ -827,6 +904,22 @@ and solve conflicts and also enrich the feature set originally
|
|||
proposed by these libraries and better integrate them with Godot.
|
||||
|
||||
|
||||
## spirv-cross
|
||||
|
||||
- Upstream: https://github.com/KhronosGroup/SPIRV-Cross
|
||||
- Version: git (6173e24b31f09a0c3217103a130e74c4ddec14a6, 2024)
|
||||
- License: Apache 2.0
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- All `.cpp`, `.hpp` and `.h` files, minus `main.cpp`, `spirv_cross_c.*`, `spirv_hlsl.*`, `spirv_cpp.*`
|
||||
- `include/` folder
|
||||
- `LICENSE` and `LICENSES/` folder, minus `CC-BY-4.0.txt`
|
||||
|
||||
Versions of this SDK do not have to match the `vulkan` section, as this SDK is required
|
||||
to generate Metal source from Vulkan SPIR-V.
|
||||
|
||||
|
||||
## spirv-reflect
|
||||
|
||||
- Upstream: https://github.com/KhronosGroup/SPIRV-Reflect
|
||||
|
|
@ -842,59 +935,47 @@ Files extracted from upstream source:
|
|||
- `include/` folder
|
||||
- `LICENSE`
|
||||
|
||||
Some downstream changes have been made and are identified by
|
||||
`// -- GODOT begin --` and `// -- GODOT end --` comments.
|
||||
They can be reapplied using the patches included in the `patches`
|
||||
folder.
|
||||
Patches:
|
||||
|
||||
- `0001-specialization-constants.patch` (GH-50325)
|
||||
- `0002-zero-size-for-sc-sized-arrays.patch` (GH-94985)
|
||||
|
||||
|
||||
## squish
|
||||
## thorvg
|
||||
|
||||
- Upstream: https://sourceforge.net/projects/libsquish
|
||||
- Version: 1.15 (r104, 2017)
|
||||
- Upstream: https://github.com/thorvg/thorvg
|
||||
- Version: 0.15.10 (bca94d244c67f573c6eddc27d783d9a6b1ef2f1b, 2025)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- `LICENSE.txt`
|
||||
- All `.cpp`, `.h` and `.inl` files
|
||||
- See `thorvg/update-thorvg.sh` for extraction instructions.
|
||||
Set the version number and run the script.
|
||||
|
||||
Some downstream changes have been made and are identified by
|
||||
`// -- GODOT begin --` and `// -- GODOT end --` comments.
|
||||
They can be reapplied using the patches included in the `patches`
|
||||
folder.
|
||||
Patches:
|
||||
|
||||
- `0001-revert-tvglines-bezier-precision.patch` (GH-96658)
|
||||
|
||||
|
||||
## tinyexr
|
||||
|
||||
- Upstream: https://github.com/syoyo/tinyexr
|
||||
- Version: 1.0.8 (6c8742cc8145c8f629698cd8248900990946d6b1, 2024)
|
||||
- Version: 1.0.9 (5fcb4dcb6e3abf96214b67e5c54db1ceec6a455c, 2024)
|
||||
- License: BSD-3-Clause
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- `tinyexr.{cc,h}`
|
||||
|
||||
The `tinyexr.cc` file was modified to include `zlib.h` which we provide,
|
||||
instead of `miniz.h` as an external dependency.
|
||||
Patches:
|
||||
|
||||
|
||||
## thorvg
|
||||
|
||||
- Upstream: https://github.com/thorvg/thorvg
|
||||
- Version: 0.14.2 (f6c4d8a94e0b2194fe911d6e19a550683055dd50, 2024)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
||||
See `thorvg/update-thorvg.sh` for extraction instructions. Set the version
|
||||
number and run the script.
|
||||
- `0001-external-zlib.patch` (GH-55115)
|
||||
|
||||
|
||||
## ufbx
|
||||
|
||||
- Upstream: https://github.com/ufbx/ufbx
|
||||
- Version: 0.14.0 (80ff790ab36507b99ec7e4ef55b9cfb076ce821b, 2024)
|
||||
- Version: 0.15.0 (24eea6f40929fe0f679b7950def378edb003afdb, 2024)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
@ -914,10 +995,14 @@ Files extracted from upstream source:
|
|||
- From `src/VHACD_Lib/`: `inc`, `public` and `src`
|
||||
- `LICENSE`
|
||||
|
||||
Some downstream changes have been made and are identified by
|
||||
`// -- GODOT start --` and `// -- GODOT end --` comments.
|
||||
They can be reapplied using the patches included in the `vhacd`
|
||||
folder.
|
||||
Patches:
|
||||
|
||||
- `0001-bullet-namespace.patch` (GH-27929)
|
||||
- `0002-fpermissive-fix.patch` (GH-27929)
|
||||
- `0003-fix-musl-build.patch` (GH-34250)
|
||||
- `0004-fix-msvc-arm-build.patch` (GH-34331)
|
||||
- `0005-fix-scale-calculation.patch` (GH-38506)
|
||||
- `0006-gcc13-include-fix.patch` (GH-77949)
|
||||
|
||||
|
||||
## volk
|
||||
|
|
@ -961,7 +1046,12 @@ SDK release: https://github.com/KhronosGroup/Vulkan-Utility-Libraries/blob/main/
|
|||
Version: 3.1.0 (009ecd192c1289c7529bff248a16cfe896254816, 2024)
|
||||
`vk_mem_alloc.cpp` is a Godot file and should be preserved on updates.
|
||||
|
||||
Patches in the `patches` directory should be re-applied after updates.
|
||||
Patches:
|
||||
|
||||
- `0001-VKEnumStringHelper-godot-vulkan.patch` (GH-97510)
|
||||
- `0002-VMA-godot-vulkan.patch` (GH-97510)
|
||||
- `0003-VMA-add-vmaCalculateLazilyAllocatedBytes.patch` (GH-99257)
|
||||
|
||||
|
||||
|
||||
## wayland
|
||||
|
|
@ -992,6 +1082,7 @@ Files extracted from upstream source:
|
|||
- `staging/fractional-scale/fractional-scale-v1.xml`
|
||||
- `staging/xdg-activation/README`
|
||||
- `staging/xdg-activation/xdg-activation-v1.xml`
|
||||
- `staging/xdg-system-bell/xdg-system-bell-v1.xml`
|
||||
- `unstable/idle-inhibit/README`
|
||||
- `unstable/idle-inhibit/idle-inhibit-unstable-v1.xml`
|
||||
- `unstable/pointer-constraints/README`
|
||||
|
|
@ -1025,10 +1116,12 @@ File extracted from upstream release tarball:
|
|||
Contents might need tweaking for Godot, review diff
|
||||
- All `.c` and `.h` files from `lib/`
|
||||
- All `.h` in `lib/includes/wslay/` as `wslay/`
|
||||
- `wslay/wslay.h` has a small Godot addition to fix MSVC build
|
||||
See `patches/msvcfix.diff`
|
||||
- `COPYING`
|
||||
|
||||
Patches:
|
||||
|
||||
- `0001-msvc-build-fix.patch` (GH-30263)
|
||||
|
||||
|
||||
## xatlas
|
||||
|
||||
|
|
@ -1050,7 +1143,7 @@ Files extracted from upstream source:
|
|||
|
||||
Files extracted from upstream source:
|
||||
|
||||
- All `.c` and `.h` files, minus `infback.c`
|
||||
- All `.c` and `.h` files, except `gz*.c` and `infback.c`
|
||||
- `LICENSE`
|
||||
|
||||
|
||||
|
|
|
|||
4
engine/thirdparty/amd-fsr2/ffx_fsr2.cpp
vendored
4
engine/thirdparty/amd-fsr2/ffx_fsr2.cpp
vendored
|
|
@ -36,7 +36,6 @@
|
|||
#pragma clang diagnostic ignored "-Wunused-variable"
|
||||
#endif
|
||||
|
||||
// -- GODOT start --
|
||||
#ifndef _countof
|
||||
#define _countof(array) (sizeof(array) / sizeof(array[0]))
|
||||
#endif
|
||||
|
|
@ -45,7 +44,6 @@
|
|||
#include <wchar.h>
|
||||
#define wcscpy_s wcscpy
|
||||
#endif
|
||||
// -- GODOT end --
|
||||
|
||||
// max queued frames for descriptor management
|
||||
static const uint32_t FSR2_MAX_QUEUED_FRAMES = 16;
|
||||
|
|
@ -954,9 +952,7 @@ static FfxErrorCode fsr2Dispatch(FfxFsr2Context_Private* context, const FfxFsr2D
|
|||
context->constants.lumaMipDimensions[0] = uint32_t(context->constants.maxRenderSize[0] / mipDiv);
|
||||
context->constants.lumaMipDimensions[1] = uint32_t(context->constants.maxRenderSize[1] / mipDiv);
|
||||
|
||||
// -- GODOT start --
|
||||
memcpy(context->constants.reprojectionMatrix, params->reprojectionMatrix, sizeof(context->constants.reprojectionMatrix));
|
||||
// -- GODOT end --
|
||||
|
||||
// reactive mask bias
|
||||
const int32_t threadGroupWorkRegionDim = 8;
|
||||
|
|
|
|||
3
engine/thirdparty/amd-fsr2/ffx_fsr2.h
vendored
3
engine/thirdparty/amd-fsr2/ffx_fsr2.h
vendored
|
|
@ -146,10 +146,7 @@ typedef struct FfxFsr2DispatchDescription {
|
|||
float autoReactiveScale; ///< A value to scale the reactive mask
|
||||
float autoReactiveMax; ///< A value to clamp the reactive mask
|
||||
|
||||
// -- GODOT start --
|
||||
float reprojectionMatrix[16]; ///< The matrix used for reprojecting pixels with invalid motion vectors by using the depth.
|
||||
// -- GODOT end --
|
||||
|
||||
} FfxFsr2DispatchDescription;
|
||||
|
||||
/// A structure encapsulating the parameters for automatic generation of a reactive mask
|
||||
|
|
|
|||
|
|
@ -45,10 +45,8 @@ typedef struct Fsr2Constants {
|
|||
float dynamicResChangeFactor;
|
||||
float viewSpaceToMetersFactor;
|
||||
|
||||
// -- GODOT start --
|
||||
float pad;
|
||||
float reprojectionMatrix[16];
|
||||
// -- GODOT end --
|
||||
} Fsr2Constants;
|
||||
|
||||
struct FfxFsr2ContextDescription;
|
||||
|
|
|
|||
2
engine/thirdparty/amd-fsr2/ffx_types.h
vendored
2
engine/thirdparty/amd-fsr2/ffx_types.h
vendored
|
|
@ -22,9 +22,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
// -- GODOT start --
|
||||
#include <stdlib.h>
|
||||
// -- GODOT end --
|
||||
|
||||
#if defined (FFX_GCC)
|
||||
/// FidelityFX exported functions
|
||||
|
|
|
|||
136
engine/thirdparty/amd-fsr2/patches/0001-build-fixes.patch
vendored
Normal file
136
engine/thirdparty/amd-fsr2/patches/0001-build-fixes.patch
vendored
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
diff --git a/thirdparty/amd-fsr2/ffx_fsr2.cpp b/thirdparty/amd-fsr2/ffx_fsr2.cpp
|
||||
index 051018e437..3970aa7f5b 100644
|
||||
--- a/thirdparty/amd-fsr2/ffx_fsr2.cpp
|
||||
+++ b/thirdparty/amd-fsr2/ffx_fsr2.cpp
|
||||
@@ -36,6 +36,15 @@
|
||||
#pragma clang diagnostic ignored "-Wunused-variable"
|
||||
#endif
|
||||
|
||||
+#ifndef _countof
|
||||
+#define _countof(array) (sizeof(array) / sizeof(array[0]))
|
||||
+#endif
|
||||
+
|
||||
+#ifndef _MSC_VER
|
||||
+#include <wchar.h>
|
||||
+#define wcscpy_s wcscpy
|
||||
+#endif
|
||||
+
|
||||
// max queued frames for descriptor management
|
||||
static const uint32_t FSR2_MAX_QUEUED_FRAMES = 16;
|
||||
|
||||
diff --git a/thirdparty/amd-fsr2/ffx_types.h b/thirdparty/amd-fsr2/ffx_types.h
|
||||
index 74edd192c4..f71b259cce 100644
|
||||
--- a/thirdparty/amd-fsr2/ffx_types.h
|
||||
+++ b/thirdparty/amd-fsr2/ffx_types.h
|
||||
@@ -22,6 +22,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
+#include <stdlib.h>
|
||||
|
||||
#if defined (FFX_GCC)
|
||||
/// FidelityFX exported functions
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_accumulate_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_accumulate_pass.glsl
|
||||
index ebbe610ffa..31d68292d4 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_accumulate_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_accumulate_pass.glsl
|
||||
@@ -19,7 +19,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
-#version 450
|
||||
+//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_autogen_reactive_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_autogen_reactive_pass.glsl
|
||||
index 7ae41cf0c1..3b86c17d4d 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_autogen_reactive_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_autogen_reactive_pass.glsl
|
||||
@@ -19,7 +19,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
-#version 450
|
||||
+//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_compute_luminance_pyramid_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_compute_luminance_pyramid_pass.glsl
|
||||
index 15186e3bb6..8439c4e9d4 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_compute_luminance_pyramid_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_compute_luminance_pyramid_pass.glsl
|
||||
@@ -19,7 +19,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
-#version 450
|
||||
+//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip_pass.glsl
|
||||
index fcb2b76528..45ec5bdb86 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_depth_clip_pass.glsl
|
||||
@@ -19,7 +19,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
-#version 450
|
||||
+//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_lock_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_lock_pass.glsl
|
||||
index f7cad59c20..7c3a4c2740 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_lock_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_lock_pass.glsl
|
||||
@@ -19,7 +19,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
-#version 450
|
||||
+//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_rcas_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_rcas_pass.glsl
|
||||
index f0823c2bc8..8b4ebc6afc 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_rcas_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_rcas_pass.glsl
|
||||
@@ -19,7 +19,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
-#version 450
|
||||
+//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_reconstruct_previous_depth_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_reconstruct_previous_depth_pass.glsl
|
||||
index 20e17eef8c..be4395aaed 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_reconstruct_previous_depth_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_reconstruct_previous_depth_pass.glsl
|
||||
@@ -19,7 +19,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
-#version 450
|
||||
+//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_tcr_autogen_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_tcr_autogen_pass.glsl
|
||||
index bebca91099..7d6a66b8ac 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_tcr_autogen_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_tcr_autogen_pass.glsl
|
||||
@@ -19,7 +19,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
-#version 450
|
||||
+//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
121
engine/thirdparty/amd-fsr2/patches/0002-godot-fsr2-options.patch
vendored
Normal file
121
engine/thirdparty/amd-fsr2/patches/0002-godot-fsr2-options.patch
vendored
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
diff --git a/thirdparty/amd-fsr2/ffx_fsr2.cpp b/thirdparty/amd-fsr2/ffx_fsr2.cpp
|
||||
index 3970aa7f5b..ec571b9cd2 100644
|
||||
--- a/thirdparty/amd-fsr2/ffx_fsr2.cpp
|
||||
+++ b/thirdparty/amd-fsr2/ffx_fsr2.cpp
|
||||
@@ -952,6 +952,8 @@ static FfxErrorCode fsr2Dispatch(FfxFsr2Context_Private* context, const FfxFsr2D
|
||||
context->constants.lumaMipDimensions[0] = uint32_t(context->constants.maxRenderSize[0] / mipDiv);
|
||||
context->constants.lumaMipDimensions[1] = uint32_t(context->constants.maxRenderSize[1] / mipDiv);
|
||||
|
||||
+ memcpy(context->constants.reprojectionMatrix, params->reprojectionMatrix, sizeof(context->constants.reprojectionMatrix));
|
||||
+
|
||||
// reactive mask bias
|
||||
const int32_t threadGroupWorkRegionDim = 8;
|
||||
const int32_t dispatchSrcX = (context->constants.renderSize[0] + (threadGroupWorkRegionDim - 1)) / threadGroupWorkRegionDim;
|
||||
diff --git a/thirdparty/amd-fsr2/ffx_fsr2.h b/thirdparty/amd-fsr2/ffx_fsr2.h
|
||||
index 2a1c74abb1..dfcd4caf35 100644
|
||||
--- a/thirdparty/amd-fsr2/ffx_fsr2.h
|
||||
+++ b/thirdparty/amd-fsr2/ffx_fsr2.h
|
||||
@@ -146,6 +146,7 @@ typedef struct FfxFsr2DispatchDescription {
|
||||
float autoReactiveScale; ///< A value to scale the reactive mask
|
||||
float autoReactiveMax; ///< A value to clamp the reactive mask
|
||||
|
||||
+ float reprojectionMatrix[16]; ///< The matrix used for reprojecting pixels with invalid motion vectors by using the depth.
|
||||
} FfxFsr2DispatchDescription;
|
||||
|
||||
/// A structure encapsulating the parameters for automatic generation of a reactive mask
|
||||
diff --git a/thirdparty/amd-fsr2/ffx_fsr2_private.h b/thirdparty/amd-fsr2/ffx_fsr2_private.h
|
||||
index 6b5fbc5117..8a9aec5778 100644
|
||||
--- a/thirdparty/amd-fsr2/ffx_fsr2_private.h
|
||||
+++ b/thirdparty/amd-fsr2/ffx_fsr2_private.h
|
||||
@@ -44,6 +44,9 @@ typedef struct Fsr2Constants {
|
||||
float deltaTime;
|
||||
float dynamicResChangeFactor;
|
||||
float viewSpaceToMetersFactor;
|
||||
+
|
||||
+ float pad;
|
||||
+ float reprojectionMatrix[16];
|
||||
} Fsr2Constants;
|
||||
|
||||
struct FfxFsr2ContextDescription;
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_accumulate_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_accumulate_pass.glsl
|
||||
index 31d68292d4..2e98c8a6c5 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_accumulate_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_accumulate_pass.glsl
|
||||
@@ -35,7 +35,7 @@
|
||||
#endif
|
||||
#define FSR2_BIND_SRV_INTERNAL_UPSCALED 3
|
||||
#define FSR2_BIND_SRV_LOCK_STATUS 4
|
||||
-#define FSR2_BIND_SRV_INPUT_DEPTH_CLIP 5
|
||||
+//#define FSR2_BIND_SRV_INPUT_DEPTH_CLIP 5
|
||||
#define FSR2_BIND_SRV_PREPARED_INPUT_COLOR 6
|
||||
#define FSR2_BIND_SRV_LUMA_INSTABILITY 7
|
||||
#define FSR2_BIND_SRV_LANCZOS_LUT 8
|
||||
@@ -52,6 +52,10 @@
|
||||
|
||||
#define FSR2_BIND_CB_FSR2 18
|
||||
|
||||
+#if FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS
|
||||
+#define FSR2_BIND_SRV_INPUT_DEPTH 5
|
||||
+#endif
|
||||
+
|
||||
#include "ffx_fsr2_callbacks_glsl.h"
|
||||
#include "ffx_fsr2_common.h"
|
||||
#include "ffx_fsr2_sample.h"
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_callbacks_glsl.h b/thirdparty/amd-fsr2/shaders/ffx_fsr2_callbacks_glsl.h
|
||||
index 10da13fb81..b610037cc6 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_callbacks_glsl.h
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_callbacks_glsl.h
|
||||
@@ -52,6 +52,9 @@
|
||||
FfxFloat32 fDeltaTime;
|
||||
FfxFloat32 fDynamicResChangeFactor;
|
||||
FfxFloat32 fViewSpaceToMetersFactor;
|
||||
+
|
||||
+ FfxFloat32 fPad;
|
||||
+ mat4 mReprojectionMatrix;
|
||||
} cbFSR2;
|
||||
#endif
|
||||
|
||||
@@ -317,7 +320,11 @@ FfxFloat32 LoadInputDepth(FfxInt32x2 iPxPos)
|
||||
#if defined(FSR2_BIND_SRV_REACTIVE_MASK)
|
||||
FfxFloat32 LoadReactiveMask(FfxInt32x2 iPxPos)
|
||||
{
|
||||
+#if FFX_FSR2_OPTION_GODOT_REACTIVE_MASK_CLAMP
|
||||
+ return min(texelFetch(r_reactive_mask, FfxInt32x2(iPxPos), 0).r, 0.9f);
|
||||
+#else
|
||||
return texelFetch(r_reactive_mask, FfxInt32x2(iPxPos), 0).r;
|
||||
+#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -354,6 +361,16 @@ FfxFloat32x2 LoadInputMotionVector(FfxInt32x2 iPxDilatedMotionVectorPos)
|
||||
{
|
||||
FfxFloat32x2 fSrcMotionVector = texelFetch(r_input_motion_vectors, iPxDilatedMotionVectorPos, 0).xy;
|
||||
|
||||
+#if FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS
|
||||
+ bool bInvalidMotionVector = all(lessThanEqual(fSrcMotionVector, vec2(-1.0f, -1.0f)));
|
||||
+ if (bInvalidMotionVector)
|
||||
+ {
|
||||
+ FfxFloat32 fSrcDepth = LoadInputDepth(iPxDilatedMotionVectorPos);
|
||||
+ FfxFloat32x2 fUv = (iPxDilatedMotionVectorPos + FfxFloat32(0.5)) / RenderSize();
|
||||
+ fSrcMotionVector = FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS_FUNCTION(fUv, fSrcDepth, cbFSR2.mReprojectionMatrix);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
FfxFloat32x2 fUvMotionVector = fSrcMotionVector * MotionVectorScale();
|
||||
|
||||
#if FFX_FSR2_OPTION_JITTERED_MOTION_VECTORS
|
||||
diff --git a/thirdparty/amd-fsr2/shaders/ffx_fsr2_tcr_autogen_pass.glsl b/thirdparty/amd-fsr2/shaders/ffx_fsr2_tcr_autogen_pass.glsl
|
||||
index 7d6a66b8ac..5c042c332a 100644
|
||||
--- a/thirdparty/amd-fsr2/shaders/ffx_fsr2_tcr_autogen_pass.glsl
|
||||
+++ b/thirdparty/amd-fsr2/shaders/ffx_fsr2_tcr_autogen_pass.glsl
|
||||
@@ -40,6 +40,10 @@
|
||||
#define FSR2_BIND_CB_FSR2 11
|
||||
#define FSR2_BIND_CB_REACTIVE 12
|
||||
|
||||
+#if FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS
|
||||
+#define FSR2_BIND_SRV_INPUT_DEPTH 13
|
||||
+#endif
|
||||
+
|
||||
#include "ffx_fsr2_callbacks_glsl.h"
|
||||
#include "ffx_fsr2_common.h"
|
||||
|
||||
Binary file not shown.
|
|
@ -19,7 +19,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
|
@ -35,6 +35,7 @@
|
|||
#endif
|
||||
#define FSR2_BIND_SRV_INTERNAL_UPSCALED 3
|
||||
#define FSR2_BIND_SRV_LOCK_STATUS 4
|
||||
//#define FSR2_BIND_SRV_INPUT_DEPTH_CLIP 5
|
||||
#define FSR2_BIND_SRV_PREPARED_INPUT_COLOR 6
|
||||
#define FSR2_BIND_SRV_LUMA_INSTABILITY 7
|
||||
#define FSR2_BIND_SRV_LANCZOS_LUT 8
|
||||
|
|
@ -51,11 +52,9 @@
|
|||
|
||||
#define FSR2_BIND_CB_FSR2 18
|
||||
|
||||
// -- GODOT start --
|
||||
#if FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS
|
||||
#define FSR2_BIND_SRV_INPUT_DEPTH 5
|
||||
#endif
|
||||
// -- GODOT end --
|
||||
|
||||
#include "ffx_fsr2_callbacks_glsl.h"
|
||||
#include "ffx_fsr2_common.h"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
|
|
|||
|
|
@ -52,11 +52,9 @@
|
|||
FfxFloat32 fDeltaTime;
|
||||
FfxFloat32 fDynamicResChangeFactor;
|
||||
FfxFloat32 fViewSpaceToMetersFactor;
|
||||
|
||||
// -- GODOT start --
|
||||
|
||||
FfxFloat32 fPad;
|
||||
mat4 mReprojectionMatrix;
|
||||
// -- GODOT end --
|
||||
} cbFSR2;
|
||||
#endif
|
||||
|
||||
|
|
@ -322,13 +320,11 @@ FfxFloat32 LoadInputDepth(FfxInt32x2 iPxPos)
|
|||
#if defined(FSR2_BIND_SRV_REACTIVE_MASK)
|
||||
FfxFloat32 LoadReactiveMask(FfxInt32x2 iPxPos)
|
||||
{
|
||||
// -- GODOT start --
|
||||
#if FFX_FSR2_OPTION_GODOT_REACTIVE_MASK_CLAMP
|
||||
return min(texelFetch(r_reactive_mask, FfxInt32x2(iPxPos), 0).r, 0.9f);
|
||||
#else
|
||||
return texelFetch(r_reactive_mask, FfxInt32x2(iPxPos), 0).r;
|
||||
#endif
|
||||
// -- GODOT end --
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -365,7 +361,6 @@ FfxFloat32x2 LoadInputMotionVector(FfxInt32x2 iPxDilatedMotionVectorPos)
|
|||
{
|
||||
FfxFloat32x2 fSrcMotionVector = texelFetch(r_input_motion_vectors, iPxDilatedMotionVectorPos, 0).xy;
|
||||
|
||||
// -- GODOT start --
|
||||
#if FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS
|
||||
bool bInvalidMotionVector = all(lessThanEqual(fSrcMotionVector, vec2(-1.0f, -1.0f)));
|
||||
if (bInvalidMotionVector)
|
||||
|
|
@ -375,7 +370,6 @@ FfxFloat32x2 LoadInputMotionVector(FfxInt32x2 iPxDilatedMotionVectorPos)
|
|||
fSrcMotionVector = FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS_FUNCTION(fUv, fSrcDepth, cbFSR2.mReprojectionMatrix);
|
||||
}
|
||||
#endif
|
||||
// -- GODOT end --
|
||||
|
||||
FfxFloat32x2 fUvMotionVector = fSrcMotionVector * MotionVectorScale();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
//#version 450
|
||||
|
||||
#extension GL_GOOGLE_include_directive : require
|
||||
#extension GL_EXT_samplerless_texture_functions : require
|
||||
|
|
@ -40,11 +40,9 @@
|
|||
#define FSR2_BIND_CB_FSR2 11
|
||||
#define FSR2_BIND_CB_REACTIVE 12
|
||||
|
||||
// -- GODOT start --
|
||||
#if FFX_FSR2_OPTION_GODOT_DERIVE_INVALID_MOTION_VECTORS
|
||||
#define FSR2_BIND_SRV_INPUT_DEPTH 13
|
||||
#endif
|
||||
// -- GODOT end --
|
||||
|
||||
#include "ffx_fsr2_callbacks_glsl.h"
|
||||
#include "ffx_fsr2_common.h"
|
||||
|
|
|
|||
2052
engine/thirdparty/basis_universal/encoder/3rdparty/android_astc_decomp.cpp
vendored
Normal file
2052
engine/thirdparty/basis_universal/encoder/3rdparty/android_astc_decomp.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
45
engine/thirdparty/basis_universal/encoder/3rdparty/android_astc_decomp.h
vendored
Normal file
45
engine/thirdparty/basis_universal/encoder/3rdparty/android_astc_decomp.h
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// File: android_astc_decomp.h
|
||||
#ifndef _TCUASTCUTIL_HPP
|
||||
#define _TCUASTCUTIL_HPP
|
||||
/*-------------------------------------------------------------------------
|
||||
* drawElements Quality Program Tester Core
|
||||
* ----------------------------------------
|
||||
*
|
||||
* Copyright 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*//*!
|
||||
* \file
|
||||
* \brief ASTC Utilities.
|
||||
*//*--------------------------------------------------------------------*/
|
||||
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace basisu_astc
|
||||
{
|
||||
namespace astc
|
||||
{
|
||||
|
||||
// Unpacks a single ASTC block to pDst
|
||||
// If isSRGB is true, the spec requires the decoder to scale the LDR 8-bit endpoints to 16-bit before interpolation slightly differently,
|
||||
// which will lead to different outputs. So be sure to set it correctly (ideally it should match whatever the encoder did).
|
||||
bool decompress_ldr(uint8_t* pDst, const uint8_t* data, bool isSRGB, int blockWidth, int blockHeight);
|
||||
bool decompress_hdr(float* pDstRGBA, const uint8_t* data, int blockWidth, int blockHeight);
|
||||
bool is_hdr(const uint8_t* data, int blockWidth, int blockHeight, bool& is_hdr);
|
||||
|
||||
} // astc
|
||||
} // basisu
|
||||
|
||||
#endif
|
||||
3310
engine/thirdparty/basis_universal/encoder/basisu_astc_hdr_enc.cpp
vendored
Normal file
3310
engine/thirdparty/basis_universal/encoder/basisu_astc_hdr_enc.cpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
224
engine/thirdparty/basis_universal/encoder/basisu_astc_hdr_enc.h
vendored
Normal file
224
engine/thirdparty/basis_universal/encoder/basisu_astc_hdr_enc.h
vendored
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
// basisu_astc_hdr_enc.h
|
||||
#pragma once
|
||||
#include "basisu_enc.h"
|
||||
#include "basisu_gpu_texture.h"
|
||||
#include "../transcoder/basisu_astc_helpers.h"
|
||||
#include "../transcoder/basisu_astc_hdr_core.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
// This MUST be called before encoding any blocks.
|
||||
void astc_hdr_enc_init();
|
||||
|
||||
const uint32_t MODE11_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE11_LAST_ISE_RANGE = astc_helpers::BISE_16_LEVELS;
|
||||
const uint32_t MODE7_PART1_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE7_PART1_LAST_ISE_RANGE = astc_helpers::BISE_16_LEVELS;
|
||||
const uint32_t MODE7_PART2_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE7_PART2_LAST_ISE_RANGE = astc_helpers::BISE_8_LEVELS;
|
||||
const uint32_t MODE11_PART2_FIRST_ISE_RANGE = astc_helpers::BISE_3_LEVELS, MODE11_PART2_LAST_ISE_RANGE = astc_helpers::BISE_4_LEVELS;
|
||||
const uint32_t MODE11_TOTAL_SUBMODES = 8; // plus an extra hidden submode, directly encoded, for direct, so really 9 (see tables 99/100 of the ASTC spec)
|
||||
const uint32_t MODE7_TOTAL_SUBMODES = 6;
|
||||
|
||||
struct astc_hdr_codec_options
|
||||
{
|
||||
float m_bc6h_err_weight;
|
||||
|
||||
bool m_use_solid;
|
||||
|
||||
bool m_use_mode11;
|
||||
bool m_mode11_uber_mode;
|
||||
uint32_t m_first_mode11_weight_ise_range;
|
||||
uint32_t m_last_mode11_weight_ise_range;
|
||||
bool m_mode11_direct_only;
|
||||
int32_t m_first_mode11_submode;
|
||||
int32_t m_last_mode11_submode;
|
||||
|
||||
bool m_use_mode7_part1;
|
||||
uint32_t m_first_mode7_part1_weight_ise_range;
|
||||
uint32_t m_last_mode7_part1_weight_ise_range;
|
||||
|
||||
bool m_use_mode7_part2;
|
||||
uint32_t m_mode7_part2_part_masks;
|
||||
uint32_t m_first_mode7_part2_weight_ise_range;
|
||||
uint32_t m_last_mode7_part2_weight_ise_range;
|
||||
|
||||
bool m_use_mode11_part2;
|
||||
uint32_t m_mode11_part2_part_masks;
|
||||
uint32_t m_first_mode11_part2_weight_ise_range;
|
||||
uint32_t m_last_mode11_part2_weight_ise_range;
|
||||
|
||||
float m_r_err_scale, m_g_err_scale;
|
||||
|
||||
bool m_refine_weights;
|
||||
|
||||
uint32_t m_level;
|
||||
|
||||
bool m_use_estimated_partitions;
|
||||
uint32_t m_max_estimated_partitions;
|
||||
|
||||
// If true, the ASTC HDR compressor is allowed to more aggressively vary weight indices for slightly higher compression in non-fastest mode. This will hurt BC6H quality, however.
|
||||
bool m_allow_uber_mode;
|
||||
|
||||
astc_hdr_codec_options();
|
||||
|
||||
void init();
|
||||
|
||||
// TODO: set_quality_level() is preferred to configure the codec for transcoding purposes.
|
||||
static const int cMinLevel = 0;
|
||||
static const int cMaxLevel = 4;
|
||||
static const int cDefaultLevel = 1;
|
||||
void set_quality_level(int level);
|
||||
|
||||
private:
|
||||
void set_quality_best();
|
||||
void set_quality_normal();
|
||||
void set_quality_fastest();
|
||||
};
|
||||
|
||||
struct astc_hdr_pack_results
|
||||
{
|
||||
double m_best_block_error;
|
||||
double m_bc6h_block_error; // note this is not used/set by the encoder, here for convienance
|
||||
|
||||
// Encoder results (logical ASTC block)
|
||||
astc_helpers::log_astc_block m_best_blk;
|
||||
|
||||
// For statistical use
|
||||
uint32_t m_best_submodes[2];
|
||||
uint32_t m_best_pat_index;
|
||||
bool m_constrained_weights;
|
||||
|
||||
bool m_improved_via_refinement_flag;
|
||||
|
||||
// Only valid if the block is solid
|
||||
basist::astc_blk m_solid_blk;
|
||||
|
||||
// The BC6H transcoded block
|
||||
basist::bc6h_block m_bc6h_block;
|
||||
|
||||
// Solid color/void extent flag
|
||||
bool m_is_solid;
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_best_block_error = 1e+30f;
|
||||
m_bc6h_block_error = 1e+30f;
|
||||
|
||||
m_best_blk.clear();
|
||||
m_best_blk.m_grid_width = 4;
|
||||
m_best_blk.m_grid_height = 4;
|
||||
m_best_blk.m_endpoint_ise_range = 20; // 0-255
|
||||
|
||||
clear_obj(m_best_submodes);
|
||||
|
||||
m_best_pat_index = 0;
|
||||
m_constrained_weights = false;
|
||||
|
||||
clear_obj(m_bc6h_block);
|
||||
|
||||
m_is_solid = false;
|
||||
m_improved_via_refinement_flag = false;
|
||||
}
|
||||
};
|
||||
|
||||
void interpolate_qlog12_colors(
|
||||
const int e[2][3],
|
||||
basist::half_float* pDecoded_half,
|
||||
vec3F* pDecoded_float,
|
||||
uint32_t n, uint32_t ise_weight_range);
|
||||
|
||||
bool get_astc_hdr_mode_11_block_colors(
|
||||
const uint8_t* pEndpoints,
|
||||
basist::half_float* pDecoded_half,
|
||||
vec3F* pDecoded_float,
|
||||
uint32_t n, uint32_t ise_weight_range, uint32_t ise_endpoint_range);
|
||||
|
||||
bool get_astc_hdr_mode_7_block_colors(
|
||||
const uint8_t* pEndpoints,
|
||||
basist::half_float* pDecoded_half,
|
||||
vec3F* pDecoded_float,
|
||||
uint32_t n, uint32_t ise_weight_range, uint32_t ise_endpoint_range);
|
||||
|
||||
double eval_selectors(
|
||||
uint32_t num_pixels,
|
||||
uint8_t* pWeights,
|
||||
const basist::half_float* pBlock_pixels_half,
|
||||
uint32_t num_weight_levels,
|
||||
const basist::half_float* pDecoded_half,
|
||||
const astc_hdr_codec_options& coptions,
|
||||
uint32_t usable_selector_bitmask = UINT32_MAX);
|
||||
|
||||
double compute_block_error(const basist::half_float* pOrig_block, const basist::half_float* pPacked_block, const astc_hdr_codec_options& coptions);
|
||||
|
||||
// Encodes a 4x4 ASTC HDR block given a 4x4 array of source block pixels/texels.
|
||||
// Supports solid color blocks, mode 11 (all submodes), mode 7/1 partition (all submodes),
|
||||
// and mode 7/2 partitions (all submodes) - 30 patterns, only the ones also in common with the BC6H format.
|
||||
// The packed ASTC weight grid dimensions are currently always 4x4 texels, but may be also 3x3 in the future.
|
||||
// This function is thread safe, i.e. it may be called from multiple encoding threads simultanously with different blocks.
|
||||
//
|
||||
// Parameters:
|
||||
// pRGBPixels - An array of 48 (16 RGB) floats: the 4x4 block to pack
|
||||
// pPacked_block - A pointer to the packed ASTC HDR block
|
||||
// coptions - Codec options
|
||||
// pInternal_results - An optional pointer to details about how the block was packed, for statistics/debugging purposes. May be nullptr.
|
||||
//
|
||||
// Requirements:
|
||||
// astc_hdr_enc_init() MUST have been called first to initialized the codec.
|
||||
// Input pixels are checked and cannot be NaN's, Inf's, signed, or too large (greater than MAX_HALF_FLOAT, or 65504).
|
||||
// Normal values and denormals are okay.
|
||||
bool astc_hdr_enc_block(
|
||||
const float* pRGBPixels,
|
||||
const astc_hdr_codec_options& coptions,
|
||||
basisu::vector<astc_hdr_pack_results> &all_results);
|
||||
|
||||
bool astc_hdr_pack_results_to_block(basist::astc_blk& dst_blk, const astc_hdr_pack_results& results);
|
||||
|
||||
bool astc_hdr_refine_weights(const basist::half_float* pSource_block, astc_hdr_pack_results& cur_results, const astc_hdr_codec_options& coptions, float bc6h_weight, bool* pImproved_flag);
|
||||
|
||||
struct astc_hdr_block_stats
|
||||
{
|
||||
std::mutex m_mutex;
|
||||
|
||||
uint32_t m_total_blocks;
|
||||
uint32_t m_total_2part, m_total_solid;
|
||||
uint32_t m_total_mode7_1part, m_total_mode7_2part;
|
||||
uint32_t m_total_mode11_1part, m_total_mode11_2part;
|
||||
uint32_t m_total_mode11_1part_constrained_weights;
|
||||
|
||||
uint32_t m_weight_range_hist_7[11];
|
||||
uint32_t m_weight_range_hist_7_2part[11];
|
||||
uint32_t m_mode7_submode_hist[6];
|
||||
|
||||
uint32_t m_weight_range_hist_11[11];
|
||||
uint32_t m_weight_range_hist_11_2part[11];
|
||||
uint32_t m_mode11_submode_hist[9];
|
||||
|
||||
uint32_t m_part_hist[32];
|
||||
|
||||
uint32_t m_total_refined;
|
||||
|
||||
astc_hdr_block_stats() { clear(); }
|
||||
|
||||
void clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(m_mutex);
|
||||
|
||||
m_total_blocks = 0;
|
||||
m_total_mode7_1part = 0, m_total_mode7_2part = 0, m_total_mode11_1part = 0, m_total_2part = 0, m_total_solid = 0, m_total_mode11_2part = 0;
|
||||
m_total_mode11_1part_constrained_weights = 0;
|
||||
m_total_refined = 0;
|
||||
|
||||
clear_obj(m_weight_range_hist_11);
|
||||
clear_obj(m_weight_range_hist_11_2part);
|
||||
clear_obj(m_weight_range_hist_7);
|
||||
clear_obj(m_weight_range_hist_7_2part);
|
||||
clear_obj(m_mode7_submode_hist);
|
||||
clear_obj(m_mode11_submode_hist);
|
||||
clear_obj(m_part_hist);
|
||||
}
|
||||
|
||||
void update(const astc_hdr_pack_results& log_blk);
|
||||
|
||||
void print();
|
||||
};
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_backend.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_backend.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_basis_file.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_basis_file.h
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// File: basisu_bc7enc.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -394,6 +394,7 @@ void bc7enc_compress_block_init()
|
|||
static void compute_least_squares_endpoints_rgba(uint32_t N, const uint8_t *pSelectors, const bc7enc_vec4F* pSelector_weights, bc7enc_vec4F* pXl, bc7enc_vec4F* pXh, const color_quad_u8 *pColors)
|
||||
{
|
||||
// Least squares using normal equations: http://www.cs.cornell.edu/~bindel/class/cs3220-s12/notes/lec10.pdf
|
||||
// https://web.archive.org/web/20150319232457/http://www.cs.cornell.edu/~bindel/class/cs3220-s12/notes/lec10.pdf
|
||||
// I did this in matrix form first, expanded out all the ops, then optimized it a bit.
|
||||
double z00 = 0.0f, z01 = 0.0f, z10 = 0.0f, z11 = 0.0f;
|
||||
double q00_r = 0.0f, q10_r = 0.0f, t_r = 0.0f;
|
||||
|
|
@ -1301,6 +1302,7 @@ void check_best_overall_error(const color_cell_compressor_params *pParams, color
|
|||
for (uint32_t c = 0; c < 4; c++)
|
||||
colors[i].m_c[c] = (uint8_t)astc_interpolate_linear(colors[0].m_c[c], colors[n - 1].m_c[c], pParams->m_pSelector_weights[i]);
|
||||
|
||||
#ifdef _DEBUG
|
||||
uint64_t total_err = 0;
|
||||
for (uint32_t p = 0; p < pParams->m_num_pixels; p++)
|
||||
{
|
||||
|
|
@ -1313,6 +1315,7 @@ void check_best_overall_error(const color_cell_compressor_params *pParams, color
|
|||
total_err += compute_color_distance_rgb(&orig, &packed, pParams->m_perceptual, pParams->m_weights);
|
||||
}
|
||||
assert(total_err == pResults->m_best_overall_err);
|
||||
#endif
|
||||
|
||||
// HACK HACK
|
||||
//if (total_err != pResults->m_best_overall_err)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// File: basisu_bc7enc.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_comp.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -18,9 +18,10 @@
|
|||
#include "basisu_basis_file.h"
|
||||
#include "../transcoder/basisu_transcoder.h"
|
||||
#include "basisu_uastc_enc.h"
|
||||
#include "basisu_astc_hdr_enc.h"
|
||||
|
||||
#define BASISU_LIB_VERSION 116
|
||||
#define BASISU_LIB_VERSION_STRING "1.16"
|
||||
#define BASISU_LIB_VERSION 150
|
||||
#define BASISU_LIB_VERSION_STRING "1.50"
|
||||
|
||||
#ifndef BASISD_SUPPORT_KTX2
|
||||
#error BASISD_SUPPORT_KTX2 is undefined
|
||||
|
|
@ -81,6 +82,8 @@ namespace basisu
|
|||
m_basis_luma_601_psnr = 0.0f;
|
||||
m_basis_luma_709_ssim = 0.0f;
|
||||
|
||||
m_basis_rgb_avg_bc6h_psnr = 0.0f;
|
||||
|
||||
m_bc7_rgb_avg_psnr = 0.0f;
|
||||
m_bc7_rgba_avg_psnr = 0.0f;
|
||||
m_bc7_a_avg_psnr = 0.0f;
|
||||
|
|
@ -100,7 +103,7 @@ namespace basisu
|
|||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
|
||||
// .basis compressed (ETC1S or UASTC statistics)
|
||||
// .basis/.ktx2 compressed (LDR: ETC1S or UASTC statistics, HDR: transcoded BC6H statistics)
|
||||
float m_basis_rgb_avg_psnr;
|
||||
float m_basis_rgba_avg_psnr;
|
||||
float m_basis_a_avg_psnr;
|
||||
|
|
@ -108,7 +111,10 @@ namespace basisu
|
|||
float m_basis_luma_601_psnr;
|
||||
float m_basis_luma_709_ssim;
|
||||
|
||||
// BC7 statistics
|
||||
// UASTC HDR only.
|
||||
float m_basis_rgb_avg_bc6h_psnr;
|
||||
|
||||
// LDR: BC7 statistics
|
||||
float m_bc7_rgb_avg_psnr;
|
||||
float m_bc7_rgba_avg_psnr;
|
||||
float m_bc7_a_avg_psnr;
|
||||
|
|
@ -116,7 +122,7 @@ namespace basisu
|
|||
float m_bc7_luma_601_psnr;
|
||||
float m_bc7_luma_709_ssim;
|
||||
|
||||
// Highest achievable quality ETC1S statistics
|
||||
// LDR: Highest achievable quality ETC1S statistics
|
||||
float m_best_etc1s_rgb_avg_psnr;
|
||||
float m_best_etc1s_luma_709_psnr;
|
||||
float m_best_etc1s_luma_601_psnr;
|
||||
|
|
@ -256,7 +262,7 @@ namespace basisu
|
|||
m_no_selector_rdo.clear();
|
||||
m_selector_rdo_thresh.clear();
|
||||
m_read_source_images.clear();
|
||||
m_write_output_basis_files.clear();
|
||||
m_write_output_basis_or_ktx2_files.clear();
|
||||
m_compression_level.clear();
|
||||
m_compute_stats.clear();
|
||||
m_print_stats.clear();
|
||||
|
|
@ -317,27 +323,38 @@ namespace basisu
|
|||
|
||||
m_validate_output_data.clear();
|
||||
|
||||
m_hdr_ldr_srgb_to_linear_conversion.clear();
|
||||
|
||||
m_hdr_favor_astc.clear();
|
||||
|
||||
m_pJob_pool = nullptr;
|
||||
}
|
||||
|
||||
// True to generate UASTC .basis file data, otherwise ETC1S.
|
||||
// True to generate UASTC .basis/.KTX2 file data, otherwise ETC1S.
|
||||
bool_param<false> m_uastc;
|
||||
|
||||
// Set m_hdr to true to switch to UASTC HDR mode.
|
||||
bool_param<false> m_hdr;
|
||||
|
||||
bool_param<false> m_use_opencl;
|
||||
|
||||
// If m_read_source_images is true, m_source_filenames (and optionally m_source_alpha_filenames) contains the filenames of PNG images to read.
|
||||
// Otherwise, the compressor processes the images in m_source_images.
|
||||
// If m_read_source_images is true, m_source_filenames (and optionally m_source_alpha_filenames) contains the filenames of PNG etc. images to read.
|
||||
// Otherwise, the compressor processes the images in m_source_images or m_source_images_hdr.
|
||||
basisu::vector<std::string> m_source_filenames;
|
||||
basisu::vector<std::string> m_source_alpha_filenames;
|
||||
|
||||
basisu::vector<image> m_source_images;
|
||||
|
||||
basisu::vector<imagef> m_source_images_hdr;
|
||||
|
||||
// Stores mipmaps starting from level 1. Level 0 is still stored in m_source_images, as usual.
|
||||
// If m_source_mipmaps isn't empty, automatic mipmap generation isn't done. m_source_mipmaps.size() MUST equal m_source_images.size() or the compressor returns an error.
|
||||
// The compressor applies the user-provided swizzling (in m_swizzle) to these images.
|
||||
basisu::vector< basisu::vector<image> > m_source_mipmap_images;
|
||||
|
||||
basisu::vector< basisu::vector<imagef> > m_source_mipmap_images_hdr;
|
||||
|
||||
// Filename of the output basis file
|
||||
// Filename of the output basis/ktx2 file
|
||||
std::string m_out_filename;
|
||||
|
||||
// The params are done this way so we can detect when the user has explictly changed them.
|
||||
|
|
@ -373,8 +390,8 @@ namespace basisu
|
|||
// Read source images from m_source_filenames/m_source_alpha_filenames
|
||||
bool_param<false> m_read_source_images;
|
||||
|
||||
// Write the output basis file to disk using m_out_filename
|
||||
bool_param<false> m_write_output_basis_files;
|
||||
// Write the output basis/ktx2 file to disk using m_out_filename
|
||||
bool_param<false> m_write_output_basis_or_ktx2_files;
|
||||
|
||||
// Compute and display image metrics
|
||||
bool_param<false> m_compute_stats;
|
||||
|
|
@ -382,15 +399,15 @@ namespace basisu
|
|||
// Print stats to stdout, if m_compute_stats is true.
|
||||
bool_param<true> m_print_stats;
|
||||
|
||||
// Check to see if any input image has an alpha channel, if so then the output basis file will have alpha channels
|
||||
// Check to see if any input image has an alpha channel, if so then the output basis/ktx2 file will have alpha channels
|
||||
bool_param<true> m_check_for_alpha;
|
||||
|
||||
// Always put alpha slices in the output basis file, even when the input doesn't have alpha
|
||||
// Always put alpha slices in the output basis/ktx2 file, even when the input doesn't have alpha
|
||||
bool_param<false> m_force_alpha;
|
||||
bool_param<true> m_multithreading;
|
||||
|
||||
// Split the R channel to RGB and the G channel to alpha, then write a basis file with alpha channels
|
||||
char m_swizzle[4];
|
||||
// Split the R channel to RGB and the G channel to alpha, then write a basis/ktx2 file with alpha channels
|
||||
uint8_t m_swizzle[4];
|
||||
|
||||
bool_param<false> m_renormalize;
|
||||
|
||||
|
|
@ -448,8 +465,17 @@ namespace basisu
|
|||
param<int> m_ktx2_zstd_supercompression_level;
|
||||
bool_param<false> m_ktx2_srgb_transfer_func;
|
||||
|
||||
astc_hdr_codec_options m_uastc_hdr_options;
|
||||
|
||||
bool_param<false> m_validate_output_data;
|
||||
|
||||
// If true, LDR images (such as PNG) will be converted to normalized [0,1] linear light (via a sRGB->Linear conversion) and then processed as HDR.
|
||||
// Otherwise, LDR images will be processed as HDR as-is.
|
||||
bool_param<true> m_hdr_ldr_srgb_to_linear_conversion;
|
||||
|
||||
// If true, ASTC HDR quality is favored more than BC6H quality. Otherwise it's a rough balance.
|
||||
bool_param<false> m_hdr_favor_astc;
|
||||
|
||||
job_pool *m_pJob_pool;
|
||||
};
|
||||
|
||||
|
|
@ -504,6 +530,7 @@ namespace basisu
|
|||
opencl_context_ptr m_pOpenCL_context;
|
||||
|
||||
basisu::vector<image> m_slice_images;
|
||||
basisu::vector<imagef> m_slice_images_hdr;
|
||||
|
||||
basisu::vector<image_stats> m_stats;
|
||||
|
||||
|
|
@ -515,7 +542,9 @@ namespace basisu
|
|||
uint32_t m_total_blocks;
|
||||
|
||||
basisu_frontend m_frontend;
|
||||
|
||||
pixel_block_vec m_source_blocks;
|
||||
pixel_block_hdr_vec m_source_blocks_hdr;
|
||||
|
||||
basisu::vector<gpu_image> m_frontend_output_textures;
|
||||
|
||||
|
|
@ -526,11 +555,17 @@ namespace basisu
|
|||
|
||||
basisu_file m_basis_file;
|
||||
|
||||
basisu::vector<gpu_image> m_decoded_output_textures;
|
||||
basisu::vector<gpu_image> m_decoded_output_textures; // BC6H in HDR mode
|
||||
basisu::vector<image> m_decoded_output_textures_unpacked;
|
||||
|
||||
basisu::vector<gpu_image> m_decoded_output_textures_bc7;
|
||||
basisu::vector<image> m_decoded_output_textures_unpacked_bc7;
|
||||
|
||||
basisu::vector<imagef> m_decoded_output_textures_bc6h_hdr_unpacked; // BC6H in HDR mode
|
||||
|
||||
basisu::vector<gpu_image> m_decoded_output_textures_astc_hdr;
|
||||
basisu::vector<imagef> m_decoded_output_textures_astc_hdr_unpacked;
|
||||
|
||||
uint8_vec m_output_basis_file;
|
||||
uint8_vec m_output_ktx2_file;
|
||||
|
||||
|
|
@ -541,14 +576,21 @@ namespace basisu
|
|||
|
||||
bool m_opencl_failed;
|
||||
|
||||
void check_for_hdr_inputs();
|
||||
bool sanity_check_input_params();
|
||||
void clean_hdr_image(imagef& src_img);
|
||||
bool read_dds_source_images();
|
||||
bool read_source_images();
|
||||
bool extract_source_blocks();
|
||||
bool process_frontend();
|
||||
bool extract_frontend_texture_data();
|
||||
bool process_backend();
|
||||
bool create_basis_file_and_transcode();
|
||||
bool write_hdr_debug_images(const char* pBasename, const imagef& img, uint32_t width, uint32_t height);
|
||||
bool write_output_files_and_compute_stats();
|
||||
error_code encode_slices_to_uastc_hdr();
|
||||
error_code encode_slices_to_uastc();
|
||||
bool generate_mipmaps(const imagef& img, basisu::vector<imagef>& mips, bool has_alpha);
|
||||
bool generate_mipmaps(const image &img, basisu::vector<image> &mips, bool has_alpha);
|
||||
bool validate_texture_type_constraints();
|
||||
bool validate_ktx2_constraints();
|
||||
|
|
@ -568,7 +610,8 @@ namespace basisu
|
|||
//
|
||||
// flags_and_quality: Combination of the above flags logically OR'd with the ETC1S or UASTC level, i.e. "cFlagSRGB | cFlagGenMipsClamp | cFlagThreaded | 128" or "cFlagSRGB | cFlagGenMipsClamp | cFlagUASTC | cFlagThreaded | cPackUASTCLevelDefault".
|
||||
// In ETC1S mode, the lower 8-bits are the ETC1S quality level which ranges from [1,255] (higher=better quality/larger files)
|
||||
// In UASTC mode, the lower 8-bits are the UASTC pack level (see cPackUASTCLevelFastest, etc.). Fastest/lowest quality is 0, so be sure to set it correctly.
|
||||
// In UASTC mode, the lower 8-bits are the UASTC LDR/HDR pack level (see cPackUASTCLevelFastest, etc.). Fastest/lowest quality is 0, so be sure to set it correctly. Valid values are [0,4] for both LDR/HDR.
|
||||
// In UASTC mode, be sure to set this, otherwise it defaults to 0 (fastest/lowest quality).
|
||||
//
|
||||
// uastc_rdo_quality: Float UASTC RDO quality level (0=no change, higher values lower quality but increase compressibility, initially try .5-1.5)
|
||||
//
|
||||
|
|
@ -594,20 +637,36 @@ namespace basisu
|
|||
cFlagUASTCRDO = 1 << 18, // use RDO postprocessing when generating UASTC files (must set uastc_rdo_quality to the quality scalar)
|
||||
|
||||
cFlagPrintStats = 1 << 19, // print image stats to stdout
|
||||
cFlagPrintStatus = 1 << 20 // print status to stdout
|
||||
cFlagPrintStatus = 1 << 20, // print status to stdout
|
||||
|
||||
cFlagHDR = 1 << 21, // Force encoder into HDR mode, even if source image is LDR.
|
||||
cFlagHDRLDRImageSRGBToLinearConversion = 1 << 22, // In HDR mode, convert LDR source images to linear before encoding.
|
||||
|
||||
cFlagDebugImages = 1 << 23 // enable status output
|
||||
};
|
||||
|
||||
// This function accepts an array of source images.
|
||||
// If more than one image is provided, it's assumed the images form a mipmap pyramid and automatic mipmap generation is disabled.
|
||||
// Returns a pointer to the compressed .basis or .ktx2 file data. *pSize is the size of the compressed data. The returned block must be freed using basis_free_data().
|
||||
// Returns a pointer to the compressed .basis or .ktx2 file data. *pSize is the size of the compressed data.
|
||||
// Important: The returned block MUST be manually freed using basis_free_data().
|
||||
// basisu_encoder_init() MUST be called first!
|
||||
// LDR version. To compress the LDR source image as HDR: Use the cFlagHDR flag.
|
||||
void* basis_compress(
|
||||
const basisu::vector<image> &source_images,
|
||||
uint32_t flags_and_quality, float uastc_rdo_quality,
|
||||
size_t* pSize,
|
||||
image_stats* pStats = nullptr);
|
||||
|
||||
// This function only accepts a single source image.
|
||||
// HDR-only version.
|
||||
// Important: The returned block MUST be manually freed using basis_free_data().
|
||||
void* basis_compress(
|
||||
const basisu::vector<imagef>& source_images_hdr,
|
||||
uint32_t flags_and_quality,
|
||||
size_t* pSize,
|
||||
image_stats* pStats = nullptr);
|
||||
|
||||
// This function only accepts a single LDR source image. It's just a wrapper for basis_compress() above.
|
||||
// Important: The returned block MUST be manually freed using basis_free_data().
|
||||
void* basis_compress(
|
||||
const uint8_t* pImageRGBA, uint32_t width, uint32_t height, uint32_t pitch_in_pixels,
|
||||
uint32_t flags_and_quality, float uastc_rdo_quality,
|
||||
|
|
@ -615,6 +674,7 @@ namespace basisu
|
|||
image_stats* pStats = nullptr);
|
||||
|
||||
// Frees the dynamically allocated file data returned by basis_compress().
|
||||
// This MUST be called on the pointer returned by basis_compress() when you're done with it.
|
||||
void basis_free_data(void* p);
|
||||
|
||||
// Runs a short benchmark using synthetic image data to time OpenCL encoding vs. CPU encoding, with multithreading enabled.
|
||||
|
|
|
|||
1634
engine/thirdparty/basis_universal/encoder/basisu_enc.cpp
vendored
1634
engine/thirdparty/basis_universal/encoder/basisu_enc.cpp
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_enc.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -48,7 +48,8 @@ namespace basisu
|
|||
|
||||
// Encoder library initialization.
|
||||
// This function MUST be called before encoding anything!
|
||||
void basisu_encoder_init(bool use_opencl = false, bool opencl_force_serialization = false);
|
||||
// Returns false if library initialization fails.
|
||||
bool basisu_encoder_init(bool use_opencl = false, bool opencl_force_serialization = false);
|
||||
void basisu_encoder_deinit();
|
||||
|
||||
// basisu_kernels_sse.cpp - will be a no-op and g_cpu_supports_sse41 will always be false unless compiled with BASISU_SUPPORT_SSE=1
|
||||
|
|
@ -70,6 +71,18 @@ namespace basisu
|
|||
return (uint8_t)((i & 0xFFFFFF00U) ? (~(i >> 31)) : i);
|
||||
}
|
||||
|
||||
inline int left_shift32(int val, int shift)
|
||||
{
|
||||
assert((shift >= 0) && (shift < 32));
|
||||
return static_cast<int>(static_cast<uint32_t>(val) << shift);
|
||||
}
|
||||
|
||||
inline uint32_t left_shift32(uint32_t val, int shift)
|
||||
{
|
||||
assert((shift >= 0) && (shift < 32));
|
||||
return val << shift;
|
||||
}
|
||||
|
||||
inline int32_t clampi(int32_t value, int32_t low, int32_t high)
|
||||
{
|
||||
if (value < low)
|
||||
|
|
@ -130,6 +143,31 @@ namespace basisu
|
|||
|
||||
return bits;
|
||||
}
|
||||
|
||||
// Open interval
|
||||
inline int bounds_check(int v, int l, int h) { (void)v; (void)l; (void)h; assert(v >= l && v < h); return v; }
|
||||
inline uint32_t bounds_check(uint32_t v, uint32_t l, uint32_t h) { (void)v; (void)l; (void)h; assert(v >= l && v < h); return v; }
|
||||
|
||||
// Closed interval
|
||||
inline int bounds_check_incl(int v, int l, int h) { (void)v; (void)l; (void)h; assert(v >= l && v <= h); return v; }
|
||||
inline uint32_t bounds_check_incl(uint32_t v, uint32_t l, uint32_t h) { (void)v; (void)l; (void)h; assert(v >= l && v <= h); return v; }
|
||||
|
||||
inline uint32_t clz(uint32_t x)
|
||||
{
|
||||
if (!x)
|
||||
return 32;
|
||||
|
||||
uint32_t n = 0;
|
||||
while ((x & 0x80000000) == 0)
|
||||
{
|
||||
x <<= 1u;
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
bool string_begins_with(const std::string& str, const char* pPhrase);
|
||||
|
||||
// Hashing
|
||||
|
||||
|
|
@ -268,6 +306,7 @@ namespace basisu
|
|||
|
||||
public:
|
||||
enum { num_elements = N };
|
||||
typedef T scalar_type;
|
||||
|
||||
inline vec() { }
|
||||
inline vec(eZero) { set_zero(); }
|
||||
|
|
@ -291,6 +330,7 @@ namespace basisu
|
|||
inline bool operator<(const vec &rhs) const { for (uint32_t i = 0; i < N; i++) { if (m_v[i] < rhs.m_v[i]) return true; else if (m_v[i] != rhs.m_v[i]) return false; } return false; }
|
||||
|
||||
inline void set_zero() { for (uint32_t i = 0; i < N; i++) m_v[i] = 0; }
|
||||
inline void clear() { set_zero(); }
|
||||
|
||||
template <uint32_t OtherN, typename OtherT>
|
||||
inline vec &set(const vec<OtherN, OtherT> &other)
|
||||
|
|
@ -391,7 +431,7 @@ namespace basisu
|
|||
inline T distance(const vec &other) const { return static_cast<T>(sqrt(squared_distance(other))); }
|
||||
inline double distance_d(const vec& other) const { return sqrt(squared_distance_d(other)); }
|
||||
|
||||
inline vec &normalize_in_place() { T len = length(); if (len != 0.0f) *this *= (1.0f / len); return *this; }
|
||||
inline vec &normalize_in_place() { T len = length(); if (len != 0.0f) *this *= (1.0f / len); return *this; }
|
||||
|
||||
inline vec &clamp(T l, T h)
|
||||
{
|
||||
|
|
@ -722,7 +762,7 @@ namespace basisu
|
|||
void job_thread(uint32_t index);
|
||||
};
|
||||
|
||||
// Simple 32-bit color class
|
||||
// Simple 64-bit color class
|
||||
|
||||
class color_rgba_i16
|
||||
{
|
||||
|
|
@ -1116,7 +1156,9 @@ namespace basisu
|
|||
{
|
||||
std::string result(s);
|
||||
for (size_t i = 0; i < result.size(); i++)
|
||||
result[i] = (char)tolower((int)result[i]);
|
||||
{
|
||||
result[i] = (char)tolower((uint8_t)(result[i]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1408,7 +1450,7 @@ namespace basisu
|
|||
|
||||
size_t get_total_training_vecs() const { return m_training_vecs.size(); }
|
||||
const array_of_weighted_training_vecs &get_training_vecs() const { return m_training_vecs; }
|
||||
array_of_weighted_training_vecs &get_training_vecs() { return m_training_vecs; }
|
||||
array_of_weighted_training_vecs &get_training_vecs() { return m_training_vecs; }
|
||||
|
||||
void retrieve(basisu::vector< basisu::vector<uint32_t> > &codebook) const
|
||||
{
|
||||
|
|
@ -1437,36 +1479,36 @@ namespace basisu
|
|||
}
|
||||
|
||||
void retrieve(uint32_t max_clusters, basisu::vector<uint_vec> &codebook) const
|
||||
{
|
||||
{
|
||||
uint_vec node_stack;
|
||||
node_stack.reserve(512);
|
||||
node_stack.reserve(512);
|
||||
|
||||
codebook.resize(0);
|
||||
codebook.reserve(max_clusters);
|
||||
codebook.resize(0);
|
||||
codebook.reserve(max_clusters);
|
||||
|
||||
uint32_t node_index = 0;
|
||||
uint32_t node_index = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
const tsvq_node& cur = m_nodes[node_index];
|
||||
while (true)
|
||||
{
|
||||
const tsvq_node& cur = m_nodes[node_index];
|
||||
|
||||
if (cur.is_leaf() || ((2 + cur.m_codebook_index) > (int)max_clusters))
|
||||
{
|
||||
codebook.resize(codebook.size() + 1);
|
||||
codebook.back() = cur.m_training_vecs;
|
||||
if (cur.is_leaf() || ((2 + cur.m_codebook_index) > (int)max_clusters))
|
||||
{
|
||||
codebook.resize(codebook.size() + 1);
|
||||
codebook.back() = cur.m_training_vecs;
|
||||
|
||||
if (node_stack.empty())
|
||||
break;
|
||||
if (node_stack.empty())
|
||||
break;
|
||||
|
||||
node_index = node_stack.back();
|
||||
node_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
node_index = node_stack.back();
|
||||
node_stack.pop_back();
|
||||
continue;
|
||||
}
|
||||
|
||||
node_stack.push_back(cur.m_right_index);
|
||||
node_index = cur.m_left_index;
|
||||
}
|
||||
}
|
||||
node_stack.push_back(cur.m_right_index);
|
||||
node_index = cur.m_left_index;
|
||||
}
|
||||
}
|
||||
|
||||
bool generate(uint32_t max_size)
|
||||
{
|
||||
|
|
@ -2319,6 +2361,14 @@ namespace basisu
|
|||
m_total_bits = 0;
|
||||
}
|
||||
|
||||
inline void restart()
|
||||
{
|
||||
m_bytes.resize(0);
|
||||
m_bit_buffer = 0;
|
||||
m_bit_buffer_size = 0;
|
||||
m_total_bits = 0;
|
||||
}
|
||||
|
||||
inline const uint8_vec &get_bytes() const { return m_bytes; }
|
||||
|
||||
inline uint64_t get_total_bits() const { return m_total_bits; }
|
||||
|
|
@ -2920,11 +2970,11 @@ namespace basisu
|
|||
inline const color_rgba *get_ptr() const { return &m_pixels[0]; }
|
||||
inline color_rgba *get_ptr() { return &m_pixels[0]; }
|
||||
|
||||
bool has_alpha() const
|
||||
bool has_alpha(uint32_t channel = 3) const
|
||||
{
|
||||
for (uint32_t y = 0; y < m_height; ++y)
|
||||
for (uint32_t x = 0; x < m_width; ++x)
|
||||
if ((*this)(x, y).a < 255)
|
||||
if ((*this)(x, y)[channel] < 255)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
@ -3130,6 +3180,31 @@ namespace basisu
|
|||
return *this;
|
||||
}
|
||||
|
||||
imagef& crop_dup_borders(uint32_t w, uint32_t h)
|
||||
{
|
||||
const uint32_t orig_w = m_width, orig_h = m_height;
|
||||
|
||||
crop(w, h);
|
||||
|
||||
if (orig_w && orig_h)
|
||||
{
|
||||
if (m_width > orig_w)
|
||||
{
|
||||
for (uint32_t x = orig_w; x < m_width; x++)
|
||||
for (uint32_t y = 0; y < m_height; y++)
|
||||
set_clipped(x, y, get_clamped(minimum(x, orig_w - 1U), minimum(y, orig_h - 1U)));
|
||||
}
|
||||
|
||||
if (m_height > orig_h)
|
||||
{
|
||||
for (uint32_t y = orig_h; y < m_height; y++)
|
||||
for (uint32_t x = 0; x < m_width; x++)
|
||||
set_clipped(x, y, get_clamped(minimum(x, orig_w - 1U), minimum(y, orig_h - 1U)));
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const vec4F &operator() (uint32_t x, uint32_t y) const { assert(x < m_width && y < m_height); return m_pixels[x + y * m_pitch]; }
|
||||
inline vec4F &operator() (uint32_t x, uint32_t y) { assert(x < m_width && y < m_height); return m_pixels[x + y * m_pitch]; }
|
||||
|
||||
|
|
@ -3213,19 +3288,128 @@ namespace basisu
|
|||
|
||||
inline const vec4F *get_ptr() const { return &m_pixels[0]; }
|
||||
inline vec4F *get_ptr() { return &m_pixels[0]; }
|
||||
|
||||
bool clean_astc_hdr_pixels(float highest_mag)
|
||||
{
|
||||
bool status = true;
|
||||
bool nan_msg = false;
|
||||
bool inf_msg = false;
|
||||
bool neg_zero_msg = false;
|
||||
bool neg_msg = false;
|
||||
bool clamp_msg = false;
|
||||
|
||||
for (uint32_t iy = 0; iy < m_height; iy++)
|
||||
{
|
||||
for (uint32_t ix = 0; ix < m_width; ix++)
|
||||
{
|
||||
vec4F& c = (*this)(ix, iy);
|
||||
|
||||
for (uint32_t s = 0; s < 4; s++)
|
||||
{
|
||||
float &p = c[s];
|
||||
union { float f; uint32_t u; } x; x.f = p;
|
||||
|
||||
if ((std::isnan(p)) || (std::isinf(p)) || (x.u == 0x80000000))
|
||||
{
|
||||
if (std::isnan(p))
|
||||
{
|
||||
if (!nan_msg)
|
||||
{
|
||||
fprintf(stderr, "One or more pixels was NaN, setting to 0.\n");
|
||||
nan_msg = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (std::isinf(p))
|
||||
{
|
||||
if (!inf_msg)
|
||||
{
|
||||
fprintf(stderr, "One or more pixels was INF, setting to 0.\n");
|
||||
inf_msg = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (x.u == 0x80000000)
|
||||
{
|
||||
if (!neg_zero_msg)
|
||||
{
|
||||
fprintf(stderr, "One or more pixels was -0, setting them to 0.\n");
|
||||
neg_zero_msg = true;
|
||||
}
|
||||
}
|
||||
|
||||
p = 0.0f;
|
||||
status = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//const float o = p;
|
||||
if (p < 0.0f)
|
||||
{
|
||||
p = 0.0f;
|
||||
|
||||
if (!neg_msg)
|
||||
{
|
||||
fprintf(stderr, "One or more pixels was negative -- setting these pixel components to 0 because ASTC HDR doesn't support signed values.\n");
|
||||
neg_msg = true;
|
||||
}
|
||||
|
||||
status = false;
|
||||
}
|
||||
|
||||
if (p > highest_mag)
|
||||
{
|
||||
p = highest_mag;
|
||||
|
||||
if (!clamp_msg)
|
||||
{
|
||||
fprintf(stderr, "One or more pixels had to be clamped to %f.\n", highest_mag);
|
||||
clamp_msg = true;
|
||||
}
|
||||
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
imagef& flip_y()
|
||||
{
|
||||
for (uint32_t y = 0; y < m_height / 2; ++y)
|
||||
for (uint32_t x = 0; x < m_width; ++x)
|
||||
std::swap((*this)(x, y), (*this)(x, m_height - 1 - y));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t m_width, m_height, m_pitch; // all in pixels
|
||||
vec4F_vec m_pixels;
|
||||
};
|
||||
|
||||
// REC 709 coefficients
|
||||
const float REC_709_R = 0.212656f, REC_709_G = 0.715158f, REC_709_B = 0.072186f;
|
||||
|
||||
inline float get_luminance(const vec4F &c)
|
||||
{
|
||||
return c[0] * REC_709_R + c[1] * REC_709_G + c[2] * REC_709_B;
|
||||
}
|
||||
|
||||
float linear_to_srgb(float l);
|
||||
float srgb_to_linear(float s);
|
||||
|
||||
// Image metrics
|
||||
|
||||
class image_metrics
|
||||
{
|
||||
public:
|
||||
// TODO: Add ssim
|
||||
float m_max, m_mean, m_mean_squared, m_rms, m_psnr, m_ssim;
|
||||
double m_max, m_mean, m_mean_squared, m_rms, m_psnr, m_ssim;
|
||||
bool m_has_neg, m_hf_mag_overflow, m_any_abnormal;
|
||||
|
||||
image_metrics()
|
||||
{
|
||||
|
|
@ -3240,10 +3424,17 @@ namespace basisu
|
|||
m_rms = 0;
|
||||
m_psnr = 0;
|
||||
m_ssim = 0;
|
||||
m_has_neg = false;
|
||||
m_hf_mag_overflow = false;
|
||||
m_any_abnormal = false;
|
||||
}
|
||||
|
||||
void print(const char *pPrefix = nullptr) { printf("%sMax: %3.0f Mean: %3.3f RMS: %3.3f PSNR: %2.3f dB\n", pPrefix ? pPrefix : "", m_max, m_mean, m_rms, m_psnr); }
|
||||
void print(const char *pPrefix = nullptr) { printf("%sMax: %3.3f Mean: %3.3f RMS: %3.3f PSNR: %2.3f dB\n", pPrefix ? pPrefix : "", m_max, m_mean, m_rms, m_psnr); }
|
||||
void print_hp(const char* pPrefix = nullptr) { printf("%sMax: %3.6f Mean: %3.6f RMS: %3.6f PSNR: %2.6f dB, Any Neg: %u, Half float overflow: %u, Any NaN/Inf: %u\n", pPrefix ? pPrefix : "", m_max, m_mean, m_rms, m_psnr, m_has_neg, m_hf_mag_overflow, m_any_abnormal); }
|
||||
|
||||
void calc(const imagef& a, const imagef& b, uint32_t first_chan = 0, uint32_t total_chans = 0, bool avg_comp_error = true, bool log = false);
|
||||
void calc_half(const imagef& a, const imagef& b, uint32_t first_chan, uint32_t total_chans, bool avg_comp_error);
|
||||
void calc_half2(const imagef& a, const imagef& b, uint32_t first_chan, uint32_t total_chans, bool avg_comp_error);
|
||||
void calc(const image &a, const image &b, uint32_t first_chan = 0, uint32_t total_chans = 0, bool avg_comp_error = true, bool use_601_luma = false);
|
||||
};
|
||||
|
||||
|
|
@ -3256,6 +3447,8 @@ namespace basisu
|
|||
bool load_tga(const char* pFilename, image& img);
|
||||
inline bool load_tga(const std::string &filename, image &img) { return load_tga(filename.c_str(), img); }
|
||||
|
||||
bool load_qoi(const char* pFilename, image& img);
|
||||
|
||||
bool load_jpg(const char *pFilename, image& img);
|
||||
inline bool load_jpg(const std::string &filename, image &img) { return load_jpg(filename.c_str(), img); }
|
||||
|
||||
|
|
@ -3263,9 +3456,64 @@ namespace basisu
|
|||
bool load_image(const char* pFilename, image& img);
|
||||
inline bool load_image(const std::string &filename, image &img) { return load_image(filename.c_str(), img); }
|
||||
|
||||
// Supports .HDR and most (but not all) .EXR's (see TinyEXR).
|
||||
bool load_image_hdr(const char* pFilename, imagef& img, bool ldr_srgb_to_linear = true);
|
||||
inline bool load_image_hdr(const std::string& filename, imagef& img, bool ldr_srgb_to_linear = true) { return load_image_hdr(filename.c_str(), img, ldr_srgb_to_linear); }
|
||||
|
||||
enum class hdr_image_type
|
||||
{
|
||||
cHITRGBAHalfFloat = 0,
|
||||
cHITRGBAFloat = 1,
|
||||
cHITPNGImage = 2,
|
||||
cHITEXRImage = 3,
|
||||
cHITHDRImage = 4
|
||||
};
|
||||
|
||||
bool load_image_hdr(const void* pMem, size_t mem_size, imagef& img, uint32_t width, uint32_t height, hdr_image_type img_type, bool ldr_srgb_to_linear);
|
||||
|
||||
uint8_t *read_tga(const uint8_t *pBuf, uint32_t buf_size, int &width, int &height, int &n_chans);
|
||||
uint8_t *read_tga(const char *pFilename, int &width, int &height, int &n_chans);
|
||||
|
||||
struct rgbe_header_info
|
||||
{
|
||||
std::string m_program;
|
||||
|
||||
// Note no validation is done, either gamma or exposure may be 0.
|
||||
double m_gamma;
|
||||
bool m_has_gamma;
|
||||
|
||||
double m_exposure; // watts/steradian/m^2.
|
||||
bool m_has_exposure;
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_program.clear();
|
||||
m_gamma = 1.0f;
|
||||
m_has_gamma = false;
|
||||
m_exposure = 1.0f;
|
||||
m_has_exposure = false;
|
||||
}
|
||||
};
|
||||
|
||||
bool read_rgbe(const uint8_vec& filedata, imagef& img, rgbe_header_info& hdr_info);
|
||||
bool read_rgbe(const char* pFilename, imagef& img, rgbe_header_info &hdr_info);
|
||||
|
||||
bool write_rgbe(uint8_vec& file_data, imagef& img, rgbe_header_info& hdr_info);
|
||||
bool write_rgbe(const char* pFilename, imagef& img, rgbe_header_info& hdr_info);
|
||||
|
||||
bool read_exr(const char* pFilename, imagef& img, int& n_chans);
|
||||
bool read_exr(const void* pMem, size_t mem_size, imagef& img);
|
||||
|
||||
enum
|
||||
{
|
||||
WRITE_EXR_LINEAR_HINT = 1, // hint for lossy comp. methods: exr_perceptual_treatment_t, logarithmic or linear, defaults to logarithmic
|
||||
WRITE_EXR_STORE_FLOATS = 2, // use 32-bit floats, otherwise it uses half floats
|
||||
WRITE_EXR_NO_COMPRESSION = 4 // no compression, otherwise it uses ZIP compression (16 scanlines per block)
|
||||
};
|
||||
|
||||
// Supports 1 (Y), 3 (RGB), or 4 (RGBA) channel images.
|
||||
bool write_exr(const char* pFilename, imagef& img, uint32_t n_chans, uint32_t flags);
|
||||
|
||||
enum
|
||||
{
|
||||
cImageSaveGrayscale = 1,
|
||||
|
|
@ -3276,19 +3524,22 @@ namespace basisu
|
|||
inline bool save_png(const std::string &filename, const image &img, uint32_t image_save_flags = 0, uint32_t grayscale_comp = 0) { return save_png(filename.c_str(), img, image_save_flags, grayscale_comp); }
|
||||
|
||||
bool read_file_to_vec(const char* pFilename, uint8_vec& data);
|
||||
|
||||
bool read_file_to_data(const char* pFilename, void *pData, size_t len);
|
||||
|
||||
bool write_data_to_file(const char* pFilename, const void* pData, size_t len);
|
||||
|
||||
inline bool write_vec_to_file(const char* pFilename, const uint8_vec& v) { return v.size() ? write_data_to_file(pFilename, &v[0], v.size()) : write_data_to_file(pFilename, "", 0); }
|
||||
|
||||
float linear_to_srgb(float l);
|
||||
float srgb_to_linear(float s);
|
||||
|
||||
|
||||
bool image_resample(const image &src, image &dst, bool srgb = false,
|
||||
const char *pFilter = "lanczos4", float filter_scale = 1.0f,
|
||||
bool wrapping = false,
|
||||
uint32_t first_comp = 0, uint32_t num_comps = 4);
|
||||
|
||||
bool image_resample(const imagef& src, imagef& dst,
|
||||
const char* pFilter = "lanczos4", float filter_scale = 1.0f,
|
||||
bool wrapping = false,
|
||||
uint32_t first_comp = 0, uint32_t num_comps = 4);
|
||||
|
||||
// Timing
|
||||
|
||||
typedef uint64_t timer_ticks;
|
||||
|
|
@ -3319,6 +3570,8 @@ namespace basisu
|
|||
bool m_started, m_stopped;
|
||||
};
|
||||
|
||||
inline double get_interval_timer() { return interval_timer::ticks_to_secs(interval_timer::get_ticks()); }
|
||||
|
||||
// 2D array
|
||||
|
||||
template<typename T>
|
||||
|
|
@ -3372,8 +3625,8 @@ namespace basisu
|
|||
inline const T &operator[] (uint32_t i) const { return m_values[i]; }
|
||||
inline T &operator[] (uint32_t i) { return m_values[i]; }
|
||||
|
||||
inline const T &at_clamped(int x, int y) const { return (*this)(clamp<int>(x, 0, m_width), clamp<int>(y, 0, m_height)); }
|
||||
inline T &at_clamped(int x, int y) { return (*this)(clamp<int>(x, 0, m_width), clamp<int>(y, 0, m_height)); }
|
||||
inline const T &at_clamped(int x, int y) const { return (*this)(clamp<int>(x, 0, m_width - 1), clamp<int>(y, 0, m_height - 1)); }
|
||||
inline T &at_clamped(int x, int y) { return (*this)(clamp<int>(x, 0, m_width - 1), clamp<int>(y, 0, m_height - 1)); }
|
||||
|
||||
void clear()
|
||||
{
|
||||
|
|
@ -3450,7 +3703,327 @@ namespace basisu
|
|||
}
|
||||
};
|
||||
typedef basisu::vector<pixel_block> pixel_block_vec;
|
||||
|
||||
|
||||
struct pixel_block_hdr
|
||||
{
|
||||
vec4F m_pixels[cPixelBlockHeight][cPixelBlockWidth]; // [y][x]
|
||||
|
||||
inline const vec4F& operator() (uint32_t x, uint32_t y) const { assert((x < cPixelBlockWidth) && (y < cPixelBlockHeight)); return m_pixels[y][x]; }
|
||||
inline vec4F& operator() (uint32_t x, uint32_t y) { assert((x < cPixelBlockWidth) && (y < cPixelBlockHeight)); return m_pixels[y][x]; }
|
||||
|
||||
inline const vec4F* get_ptr() const { return &m_pixels[0][0]; }
|
||||
inline vec4F* get_ptr() { return &m_pixels[0][0]; }
|
||||
|
||||
inline void clear() { clear_obj(*this); }
|
||||
|
||||
inline bool operator== (const pixel_block& rhs) const
|
||||
{
|
||||
return memcmp(m_pixels, rhs.m_pixels, sizeof(m_pixels)) == 0;
|
||||
}
|
||||
};
|
||||
typedef basisu::vector<pixel_block_hdr> pixel_block_hdr_vec;
|
||||
|
||||
void tonemap_image_reinhard(image& ldr_img, const imagef& hdr_img, float exposure);
|
||||
bool tonemap_image_compressive(image& dst_img, const imagef& hdr_test_img);
|
||||
|
||||
// Intersection
|
||||
enum eClear { cClear = 0 };
|
||||
enum eInitExpand { cInitExpand = 0 };
|
||||
|
||||
template<typename vector_type>
|
||||
class ray
|
||||
{
|
||||
public:
|
||||
typedef vector_type vector_t;
|
||||
typedef typename vector_type::scalar_type scalar_type;
|
||||
|
||||
inline ray() { }
|
||||
inline ray(eClear) { clear(); }
|
||||
inline ray(const vector_type& origin, const vector_type& direction) : m_origin(origin), m_direction(direction) { }
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
m_origin.clear();
|
||||
m_direction.clear();
|
||||
}
|
||||
|
||||
inline const vector_type& get_origin(void) const { return m_origin; }
|
||||
inline void set_origin(const vector_type& origin) { m_origin = origin; }
|
||||
|
||||
inline const vector_type& get_direction(void) const { return m_direction; }
|
||||
inline void set_direction(const vector_type& direction) { m_direction = direction; }
|
||||
|
||||
inline void set_endpoints(const vector_type& start, const vector_type& end)
|
||||
{
|
||||
m_origin = start;
|
||||
|
||||
m_direction = end - start;
|
||||
m_direction.normalize_in_place();
|
||||
}
|
||||
|
||||
inline vector_type eval(scalar_type t) const
|
||||
{
|
||||
return m_origin + m_direction * t;
|
||||
}
|
||||
|
||||
private:
|
||||
vector_type m_origin;
|
||||
vector_type m_direction;
|
||||
};
|
||||
|
||||
typedef ray<vec2F> ray2F;
|
||||
typedef ray<vec3F> ray3F;
|
||||
|
||||
template<typename T>
|
||||
class vec_interval
|
||||
{
|
||||
public:
|
||||
enum { N = T::num_elements };
|
||||
typedef typename T::scalar_type scalar_type;
|
||||
|
||||
inline vec_interval(const T& v) { m_bounds[0] = v; m_bounds[1] = v; }
|
||||
inline vec_interval(const T& low, const T& high) { m_bounds[0] = low; m_bounds[1] = high; }
|
||||
|
||||
inline vec_interval() { }
|
||||
inline vec_interval(eClear) { clear(); }
|
||||
inline vec_interval(eInitExpand) { init_expand(); }
|
||||
|
||||
inline void clear() { m_bounds[0].clear(); m_bounds[1].clear(); }
|
||||
|
||||
inline void init_expand()
|
||||
{
|
||||
m_bounds[0].set(1e+30f, 1e+30f, 1e+30f);
|
||||
m_bounds[1].set(-1e+30f, -1e+30f, -1e+30f);
|
||||
}
|
||||
|
||||
inline vec_interval expand(const T& p)
|
||||
{
|
||||
for (uint32_t c = 0; c < N; c++)
|
||||
{
|
||||
if (p[c] < m_bounds[0][c])
|
||||
m_bounds[0][c] = p[c];
|
||||
|
||||
if (p[c] > m_bounds[1][c])
|
||||
m_bounds[1][c] = p[c];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const T& operator[] (uint32_t i) const { assert(i < 2); return m_bounds[i]; }
|
||||
inline T& operator[] (uint32_t i) { assert(i < 2); return m_bounds[i]; }
|
||||
|
||||
const T& get_low() const { return m_bounds[0]; }
|
||||
T& get_low() { return m_bounds[0]; }
|
||||
|
||||
const T& get_high() const { return m_bounds[1]; }
|
||||
T& get_high() { return m_bounds[1]; }
|
||||
|
||||
scalar_type get_dim(uint32_t axis) const { return m_bounds[1][axis] - m_bounds[0][axis]; }
|
||||
|
||||
bool contains(const T& p) const
|
||||
{
|
||||
const T& low = get_low(), high = get_high();
|
||||
|
||||
for (uint32_t i = 0; i < N; i++)
|
||||
{
|
||||
if (p[i] < low[i])
|
||||
return false;
|
||||
|
||||
if (p[i] > high[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
T m_bounds[2];
|
||||
};
|
||||
|
||||
typedef vec_interval<vec1F> vec_interval1F;
|
||||
typedef vec_interval<vec2F> vec_interval2F;
|
||||
typedef vec_interval<vec3F> vec_interval3F;
|
||||
typedef vec_interval<vec4F> vec_interval4F;
|
||||
|
||||
typedef vec_interval2F aabb2F;
|
||||
typedef vec_interval3F aabb3F;
|
||||
|
||||
namespace intersection
|
||||
{
|
||||
enum result
|
||||
{
|
||||
cBackfacing = -1,
|
||||
cFailure = 0,
|
||||
cSuccess,
|
||||
cParallel,
|
||||
cInside,
|
||||
};
|
||||
|
||||
// Returns cInside, cSuccess, or cFailure.
|
||||
// Algorithm: Graphics Gems 1
|
||||
template<typename vector_type, typename scalar_type, typename ray_type, typename aabb_type>
|
||||
result ray_aabb(vector_type& coord, scalar_type& t, const ray_type& ray, const aabb_type& box)
|
||||
{
|
||||
enum
|
||||
{
|
||||
cNumDim = vector_type::num_elements,
|
||||
cRight = 0,
|
||||
cLeft = 1,
|
||||
cMiddle = 2
|
||||
};
|
||||
|
||||
bool inside = true;
|
||||
int quadrant[cNumDim];
|
||||
scalar_type candidate_plane[cNumDim];
|
||||
|
||||
for (int i = 0; i < cNumDim; i++)
|
||||
{
|
||||
if (ray.get_origin()[i] < box[0][i])
|
||||
{
|
||||
quadrant[i] = cLeft;
|
||||
candidate_plane[i] = box[0][i];
|
||||
inside = false;
|
||||
}
|
||||
else if (ray.get_origin()[i] > box[1][i])
|
||||
{
|
||||
quadrant[i] = cRight;
|
||||
candidate_plane[i] = box[1][i];
|
||||
inside = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
quadrant[i] = cMiddle;
|
||||
}
|
||||
}
|
||||
|
||||
if (inside)
|
||||
{
|
||||
coord = ray.get_origin();
|
||||
t = 0.0f;
|
||||
return cInside;
|
||||
}
|
||||
|
||||
scalar_type max_t[cNumDim];
|
||||
for (int i = 0; i < cNumDim; i++)
|
||||
{
|
||||
if ((quadrant[i] != cMiddle) && (ray.get_direction()[i] != 0.0f))
|
||||
max_t[i] = (candidate_plane[i] - ray.get_origin()[i]) / ray.get_direction()[i];
|
||||
else
|
||||
max_t[i] = -1.0f;
|
||||
}
|
||||
|
||||
int which_plane = 0;
|
||||
for (int i = 1; i < cNumDim; i++)
|
||||
if (max_t[which_plane] < max_t[i])
|
||||
which_plane = i;
|
||||
|
||||
if (max_t[which_plane] < 0.0f)
|
||||
return cFailure;
|
||||
|
||||
for (int i = 0; i < cNumDim; i++)
|
||||
{
|
||||
if (i != which_plane)
|
||||
{
|
||||
coord[i] = ray.get_origin()[i] + max_t[which_plane] * ray.get_direction()[i];
|
||||
|
||||
if ((coord[i] < box[0][i]) || (coord[i] > box[1][i]))
|
||||
return cFailure;
|
||||
}
|
||||
else
|
||||
{
|
||||
coord[i] = candidate_plane[i];
|
||||
}
|
||||
|
||||
assert(coord[i] >= box[0][i] && coord[i] <= box[1][i]);
|
||||
}
|
||||
|
||||
t = max_t[which_plane];
|
||||
return cSuccess;
|
||||
}
|
||||
|
||||
template<typename vector_type, typename scalar_type, typename ray_type, typename aabb_type>
|
||||
result ray_aabb(bool& started_within, vector_type& coord, scalar_type& t, const ray_type& ray, const aabb_type& box)
|
||||
{
|
||||
if (!box.contains(ray.get_origin()))
|
||||
{
|
||||
started_within = false;
|
||||
return ray_aabb(coord, t, ray, box);
|
||||
}
|
||||
|
||||
started_within = true;
|
||||
|
||||
typename vector_type::T diag_dist = box.diagonal_length() * 1.5f;
|
||||
ray_type outside_ray(ray.eval(diag_dist), -ray.get_direction());
|
||||
|
||||
result res(ray_aabb(coord, t, outside_ray, box));
|
||||
if (res != cSuccess)
|
||||
return res;
|
||||
|
||||
t = basisu::maximum(0.0f, diag_dist - t);
|
||||
return cSuccess;
|
||||
}
|
||||
|
||||
} // intersect
|
||||
|
||||
// This float->half conversion matches how "F32TO16" works on Intel GPU's.
|
||||
// Input cannot be negative, Inf or Nan.
|
||||
inline basist::half_float float_to_half_non_neg_no_nan_inf(float val)
|
||||
{
|
||||
union { float f; int32_t i; uint32_t u; } fi = { val };
|
||||
const int flt_m = fi.i & 0x7FFFFF, flt_e = (fi.i >> 23) & 0xFF;
|
||||
int e = 0, m = 0;
|
||||
|
||||
assert(((fi.i >> 31) == 0) && (flt_e != 0xFF));
|
||||
|
||||
// not zero or denormal
|
||||
if (flt_e != 0)
|
||||
{
|
||||
int new_exp = flt_e - 127;
|
||||
if (new_exp > 15)
|
||||
e = 31;
|
||||
else if (new_exp < -14)
|
||||
m = lrintf((1 << 24) * fabsf(fi.f));
|
||||
else
|
||||
{
|
||||
e = new_exp + 15;
|
||||
m = lrintf(flt_m * (1.0f / ((float)(1 << 13))));
|
||||
}
|
||||
}
|
||||
|
||||
assert((0 <= m) && (m <= 1024));
|
||||
if (m == 1024)
|
||||
{
|
||||
e++;
|
||||
m = 0;
|
||||
}
|
||||
|
||||
assert((e >= 0) && (e <= 31));
|
||||
assert((m >= 0) && (m <= 1023));
|
||||
|
||||
basist::half_float result = (basist::half_float)((e << 10) | m);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Supports positive and denormals only. No NaN or Inf.
|
||||
inline float fast_half_to_float_pos_not_inf_or_nan(basist::half_float h)
|
||||
{
|
||||
assert(!basist::half_is_signed(h) && !basist::is_half_inf_or_nan(h));
|
||||
|
||||
union fu32
|
||||
{
|
||||
uint32_t u;
|
||||
float f;
|
||||
};
|
||||
|
||||
static const fu32 K = { 0x77800000 };
|
||||
|
||||
fu32 o;
|
||||
o.u = h << 13;
|
||||
o.f *= K.f;
|
||||
|
||||
return o.f;
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basis_etc.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basis_etc.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_frontend.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -2347,6 +2347,7 @@ namespace basisu
|
|||
continue;
|
||||
|
||||
uint64_t overall_best_err = 0;
|
||||
(void)overall_best_err;
|
||||
|
||||
uint64_t total_err[4][4][4];
|
||||
clear_obj(total_err);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_frontend.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_gpu_texture.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -15,13 +15,15 @@
|
|||
#include "basisu_gpu_texture.h"
|
||||
#include "basisu_enc.h"
|
||||
#include "basisu_pvrtc1_4.h"
|
||||
#if BASISU_USE_ASTC_DECOMPRESS
|
||||
#include "basisu_astc_decomp.h"
|
||||
#endif
|
||||
#include "3rdparty/android_astc_decomp.h"
|
||||
#include "basisu_bc7enc.h"
|
||||
#include "../transcoder/basisu_astc_hdr_core.h"
|
||||
|
||||
namespace basisu
|
||||
{
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// ETC2 EAC
|
||||
|
||||
void unpack_etc2_eac(const void *pBlock_bits, color_rgba *pPixels)
|
||||
{
|
||||
static_assert(sizeof(eac_a8_block) == 8, "sizeof(eac_a8_block) == 8");
|
||||
|
|
@ -56,6 +58,8 @@ namespace basisu
|
|||
pPixels[15].a = clamp255(base + pTable[pBlock->get_selector(3, 3, selector_bits)] * mul);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// BC1
|
||||
struct bc1_block
|
||||
{
|
||||
enum { cTotalEndpointBytes = 2, cTotalSelectorBytes = 4 };
|
||||
|
|
@ -274,6 +278,9 @@ namespace basisu
|
|||
return used_punchthrough;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// BC3-5
|
||||
|
||||
struct bc4_block
|
||||
{
|
||||
enum { cBC4SelectorBits = 3, cTotalSelectorBytes = 6, cMaxSelectorValues = 8 };
|
||||
|
|
@ -372,7 +379,8 @@ namespace basisu
|
|||
unpack_bc4(pBlock_bits, &pPixels[0].r, sizeof(color_rgba));
|
||||
unpack_bc4((const uint8_t *)pBlock_bits + sizeof(bc4_block), &pPixels[0].g, sizeof(color_rgba));
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// ATC isn't officially documented, so I'm assuming these references:
|
||||
// http://www.guildsoftware.com/papers/2012.Converting.DXTC.to.ATC.pdf
|
||||
// https://github.com/Triang3l/S3TConv/blob/master/s3tconv_atitc.c
|
||||
|
|
@ -426,6 +434,7 @@ namespace basisu
|
|||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// BC7 mode 0-7 decompression.
|
||||
// Instead of one monster routine to unpack all the BC7 modes, we're lumping the 3 subset, 2 subset, 1 subset, and dual plane modes together into simple shared routines.
|
||||
|
||||
|
|
@ -742,6 +751,255 @@ namespace basisu
|
|||
return false;
|
||||
}
|
||||
|
||||
static inline int bc6h_sign_extend(int val, int bits)
|
||||
{
|
||||
assert((bits >= 1) && (bits < 32));
|
||||
assert((val >= 0) && (val < (1 << bits)));
|
||||
return (val << (32 - bits)) >> (32 - bits);
|
||||
}
|
||||
|
||||
static inline int bc6h_apply_delta(int base, int delta, int num_bits, int is_signed)
|
||||
{
|
||||
int bitmask = ((1 << num_bits) - 1);
|
||||
int v = (base + delta) & bitmask;
|
||||
return is_signed ? bc6h_sign_extend(v, num_bits) : v;
|
||||
}
|
||||
|
||||
static int bc6h_dequantize(int val, int bits, int is_signed)
|
||||
{
|
||||
int result;
|
||||
if (is_signed)
|
||||
{
|
||||
if (bits >= 16)
|
||||
result = val;
|
||||
else
|
||||
{
|
||||
int s_flag = 0;
|
||||
if (val < 0)
|
||||
{
|
||||
s_flag = 1;
|
||||
val = -val;
|
||||
}
|
||||
|
||||
if (val == 0)
|
||||
result = 0;
|
||||
else if (val >= ((1 << (bits - 1)) - 1))
|
||||
result = 0x7FFF;
|
||||
else
|
||||
result = ((val << 15) + 0x4000) >> (bits - 1);
|
||||
|
||||
if (s_flag)
|
||||
result = -result;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bits >= 15)
|
||||
result = val;
|
||||
else if (!val)
|
||||
result = 0;
|
||||
else if (val == ((1 << bits) - 1))
|
||||
result = 0xFFFF;
|
||||
else
|
||||
result = ((val << 16) + 0x8000) >> bits;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int bc6h_interpolate(int a, int b, const uint8_t* pWeights, int index)
|
||||
{
|
||||
return (a * (64 - (int)pWeights[index]) + b * (int)pWeights[index] + 32) >> 6;
|
||||
}
|
||||
|
||||
static inline basist::half_float bc6h_convert_to_half(int val, int is_signed)
|
||||
{
|
||||
if (!is_signed)
|
||||
{
|
||||
// scale by 31/64
|
||||
return (basist::half_float)((val * 31) >> 6);
|
||||
}
|
||||
|
||||
// scale by 31/32
|
||||
val = (val < 0) ? -(((-val) * 31) >> 5) : (val * 31) >> 5;
|
||||
|
||||
int s = 0;
|
||||
if (val < 0)
|
||||
{
|
||||
s = 0x8000;
|
||||
val = -val;
|
||||
}
|
||||
|
||||
return (basist::half_float)(s | val);
|
||||
}
|
||||
|
||||
static inline uint32_t bc6h_get_bits(uint32_t num_bits, uint64_t& l, uint64_t& h, uint32_t& total_bits)
|
||||
{
|
||||
assert((num_bits) && (num_bits <= 63));
|
||||
|
||||
uint32_t v = (uint32_t)(l & ((1U << num_bits) - 1U));
|
||||
|
||||
l >>= num_bits;
|
||||
l |= (h << (64U - num_bits));
|
||||
h >>= num_bits;
|
||||
|
||||
total_bits += num_bits;
|
||||
assert(total_bits <= 128);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline uint32_t bc6h_reverse_bits(uint32_t v, uint32_t num_bits)
|
||||
{
|
||||
uint32_t res = 0;
|
||||
for (uint32_t i = 0; i < num_bits; i++)
|
||||
{
|
||||
uint32_t bit = (v & (1u << i)) != 0u;
|
||||
res |= (bit << (num_bits - 1u - i));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline uint64_t bc6h_read_le_qword(const void* p)
|
||||
{
|
||||
const uint8_t* pSrc = static_cast<const uint8_t*>(p);
|
||||
return ((uint64_t)read_le_dword(pSrc)) | (((uint64_t)read_le_dword(pSrc + sizeof(uint32_t))) << 32U);
|
||||
}
|
||||
|
||||
bool unpack_bc6h(const void* pSrc_block, void* pDst_block, bool is_signed, uint32_t dest_pitch_in_halfs)
|
||||
{
|
||||
assert(dest_pitch_in_halfs >= 4 * 3);
|
||||
|
||||
const uint32_t MAX_SUBSETS = 2, MAX_COMPS = 3;
|
||||
|
||||
const uint8_t* pSrc = static_cast<const uint8_t*>(pSrc_block);
|
||||
basist::half_float* pDst = static_cast<basist::half_float*>(pDst_block);
|
||||
|
||||
uint64_t blo = bc6h_read_le_qword(pSrc), bhi = bc6h_read_le_qword(pSrc + sizeof(uint64_t));
|
||||
|
||||
// Unpack mode
|
||||
const int mode = basist::g_bc6h_mode_lookup[blo & 31];
|
||||
if (mode < 0)
|
||||
{
|
||||
for (int y = 0; y < 4; y++)
|
||||
{
|
||||
memset(pDst, 0, sizeof(basist::half_float) * 4);
|
||||
pDst += dest_pitch_in_halfs;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip mode bits
|
||||
uint32_t total_bits_read = 0;
|
||||
bc6h_get_bits((mode < 2) ? 2 : 5, blo, bhi, total_bits_read);
|
||||
|
||||
assert(mode < (int)basist::NUM_BC6H_MODES);
|
||||
|
||||
const uint32_t num_subsets = (mode >= 10) ? 1 : 2;
|
||||
const bool is_mode_9_or_10 = (mode == 9) || (mode == 10);
|
||||
|
||||
// Unpack endpoint components
|
||||
int comps[MAX_SUBSETS][MAX_COMPS][2] = { { { 0 } } }; // [subset][comp][l/h]
|
||||
int part_index = 0;
|
||||
|
||||
uint32_t layout_index = 0;
|
||||
while (layout_index < basist::MAX_BC6H_LAYOUT_INDEX)
|
||||
{
|
||||
const basist::bc6h_bit_layout& layout = basist::g_bc6h_bit_layouts[mode][layout_index];
|
||||
|
||||
if (layout.m_comp < 0)
|
||||
break;
|
||||
|
||||
const int subset = layout.m_index >> 1, lh_index = layout.m_index & 1;
|
||||
assert((layout.m_comp == 3) || ((subset >= 0) && (subset < (int)MAX_SUBSETS)));
|
||||
|
||||
const int last_bit = layout.m_last_bit, first_bit = layout.m_first_bit;
|
||||
assert(last_bit >= 0);
|
||||
|
||||
int& res = (layout.m_comp == 3) ? part_index : comps[subset][layout.m_comp][lh_index];
|
||||
|
||||
if (first_bit < 0)
|
||||
{
|
||||
res |= (bc6h_get_bits(1, blo, bhi, total_bits_read) << last_bit);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int total_bits = iabs(last_bit - first_bit) + 1;
|
||||
const int bit_shift = basisu::minimum(first_bit, last_bit);
|
||||
|
||||
int b = bc6h_get_bits(total_bits, blo, bhi, total_bits_read);
|
||||
|
||||
if (last_bit < first_bit)
|
||||
b = bc6h_reverse_bits(b, total_bits);
|
||||
|
||||
res |= (b << bit_shift);
|
||||
}
|
||||
|
||||
layout_index++;
|
||||
}
|
||||
assert(layout_index != basist::MAX_BC6H_LAYOUT_INDEX);
|
||||
|
||||
// Sign extend/dequantize endpoints
|
||||
const int num_sig_bits = basist::g_bc6h_mode_sig_bits[mode][0];
|
||||
if (is_signed)
|
||||
{
|
||||
for (uint32_t comp = 0; comp < 3; comp++)
|
||||
comps[0][comp][0] = bc6h_sign_extend(comps[0][comp][0], num_sig_bits);
|
||||
}
|
||||
|
||||
if (is_signed || !is_mode_9_or_10)
|
||||
{
|
||||
for (uint32_t subset = 0; subset < num_subsets; subset++)
|
||||
for (uint32_t comp = 0; comp < 3; comp++)
|
||||
for (uint32_t lh = (subset ? 0 : 1); lh < 2; lh++)
|
||||
comps[subset][comp][lh] = bc6h_sign_extend(comps[subset][comp][lh], basist::g_bc6h_mode_sig_bits[mode][1 + comp]);
|
||||
}
|
||||
|
||||
if (!is_mode_9_or_10)
|
||||
{
|
||||
for (uint32_t subset = 0; subset < num_subsets; subset++)
|
||||
for (uint32_t comp = 0; comp < 3; comp++)
|
||||
for (uint32_t lh = (subset ? 0 : 1); lh < 2; lh++)
|
||||
comps[subset][comp][lh] = bc6h_apply_delta(comps[0][comp][0], comps[subset][comp][lh], num_sig_bits, is_signed);
|
||||
}
|
||||
|
||||
for (uint32_t subset = 0; subset < num_subsets; subset++)
|
||||
for (uint32_t comp = 0; comp < 3; comp++)
|
||||
for (uint32_t lh = 0; lh < 2; lh++)
|
||||
comps[subset][comp][lh] = bc6h_dequantize(comps[subset][comp][lh], num_sig_bits, is_signed);
|
||||
|
||||
// Now unpack weights and output texels
|
||||
const int weight_bits = (mode >= 10) ? 4 : 3;
|
||||
const uint8_t* pWeights = (mode >= 10) ? basist::g_bc6h_weight4 : basist::g_bc6h_weight3;
|
||||
|
||||
dest_pitch_in_halfs -= 4 * 3;
|
||||
|
||||
for (uint32_t y = 0; y < 4; y++)
|
||||
{
|
||||
for (uint32_t x = 0; x < 4; x++)
|
||||
{
|
||||
int subset = (num_subsets == 1) ? ((x | y) ? 0 : 0x80) : basist::g_bc6h_2subset_patterns[part_index][y][x];
|
||||
const int num_bits = weight_bits + ((subset & 0x80) ? -1 : 0);
|
||||
|
||||
subset &= 1;
|
||||
|
||||
const int weight_index = bc6h_get_bits(num_bits, blo, bhi, total_bits_read);
|
||||
|
||||
pDst[0] = bc6h_convert_to_half(bc6h_interpolate(comps[subset][0][0], comps[subset][0][1], pWeights, weight_index), is_signed);
|
||||
pDst[1] = bc6h_convert_to_half(bc6h_interpolate(comps[subset][1][0], comps[subset][1][1], pWeights, weight_index), is_signed);
|
||||
pDst[2] = bc6h_convert_to_half(bc6h_interpolate(comps[subset][2][0], comps[subset][2][1], pWeights, weight_index), is_signed);
|
||||
|
||||
pDst += 3;
|
||||
}
|
||||
|
||||
pDst += dest_pitch_in_halfs;
|
||||
}
|
||||
|
||||
assert(total_bits_read == 128);
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// FXT1 (for fun, and because some modern Intel parts support it, and because a subset is like BC1)
|
||||
|
||||
struct fxt1_block
|
||||
{
|
||||
union
|
||||
|
|
@ -901,6 +1159,9 @@ namespace basisu
|
|||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// PVRTC2 (non-interpolated, hard_flag=1 modulation=0 subset only!)
|
||||
|
||||
struct pvrtc2_block
|
||||
{
|
||||
uint8_t m_modulation[4];
|
||||
|
|
@ -1015,6 +1276,9 @@ namespace basisu
|
|||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// ETC2 EAC R11 or RG11
|
||||
|
||||
struct etc2_eac_r11
|
||||
{
|
||||
uint64_t m_base : 8;
|
||||
|
|
@ -1085,13 +1349,16 @@ namespace basisu
|
|||
unpack_etc2_eac_r(pBlock, pPixels, c);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// UASTC
|
||||
|
||||
void unpack_uastc(const void* p, color_rgba* pPixels)
|
||||
{
|
||||
basist::unpack_uastc(*static_cast<const basist::uastc_block*>(p), (basist::color32 *)pPixels, false);
|
||||
}
|
||||
|
||||
// Unpacks to RGBA, R, RG, or A
|
||||
|
||||
// Unpacks to RGBA, R, RG, or A. LDR GPU texture formats only.
|
||||
bool unpack_block(texture_format fmt, const void* pBlock, color_rgba* pPixels)
|
||||
{
|
||||
switch (fmt)
|
||||
|
|
@ -1150,14 +1417,24 @@ namespace basisu
|
|||
unpack_etc2_eac(pBlock, pPixels);
|
||||
break;
|
||||
}
|
||||
case texture_format::cASTC4x4:
|
||||
case texture_format::cBC6HSigned:
|
||||
case texture_format::cBC6HUnsigned:
|
||||
case texture_format::cASTC_HDR_4x4:
|
||||
case texture_format::cUASTC_HDR_4x4:
|
||||
{
|
||||
// Can't unpack HDR blocks in unpack_block() because it returns 32bpp pixel data.
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
case texture_format::cASTC_LDR_4x4:
|
||||
{
|
||||
#if BASISU_USE_ASTC_DECOMPRESS
|
||||
const bool astc_srgb = false;
|
||||
basisu_astc::astc::decompress(reinterpret_cast<uint8_t*>(pPixels), static_cast<const uint8_t*>(pBlock), astc_srgb, 4, 4);
|
||||
#else
|
||||
memset(pPixels, 255, 16 * sizeof(color_rgba));
|
||||
#endif
|
||||
bool status = basisu_astc::astc::decompress_ldr(reinterpret_cast<uint8_t*>(pPixels), static_cast<const uint8_t*>(pBlock), astc_srgb, 4, 4);
|
||||
assert(status);
|
||||
|
||||
if (!status)
|
||||
return false;
|
||||
|
||||
break;
|
||||
}
|
||||
case texture_format::cATC_RGB:
|
||||
|
|
@ -1206,6 +1483,66 @@ namespace basisu
|
|||
return true;
|
||||
}
|
||||
|
||||
bool unpack_block_hdr(texture_format fmt, const void* pBlock, vec4F* pPixels)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cASTC_HDR_4x4:
|
||||
case texture_format::cUASTC_HDR_4x4:
|
||||
{
|
||||
#if 1
|
||||
bool status = basisu_astc::astc::decompress_hdr(&pPixels[0][0], (uint8_t*)pBlock, 4, 4);
|
||||
assert(status);
|
||||
if (!status)
|
||||
return false;
|
||||
#else
|
||||
basist::half_float half_block[16][4];
|
||||
|
||||
astc_helpers::log_astc_block log_blk;
|
||||
if (!astc_helpers::unpack_block(pBlock, log_blk, 4, 4))
|
||||
return false;
|
||||
if (!astc_helpers::decode_block(log_blk, half_block, 4, 4, astc_helpers::cDecodeModeHDR16))
|
||||
return false;
|
||||
|
||||
for (uint32_t p = 0; p < 16; p++)
|
||||
{
|
||||
pPixels[p][0] = basist::half_to_float(half_block[p][0]);
|
||||
pPixels[p][1] = basist::half_to_float(half_block[p][1]);
|
||||
pPixels[p][2] = basist::half_to_float(half_block[p][2]);
|
||||
pPixels[p][3] = basist::half_to_float(half_block[p][3]);
|
||||
}
|
||||
|
||||
//memset(pPixels, 0, sizeof(vec4F) * 16);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
case texture_format::cBC6HSigned:
|
||||
case texture_format::cBC6HUnsigned:
|
||||
{
|
||||
basist::half_float half_block[16][3];
|
||||
|
||||
unpack_bc6h(pBlock, half_block, fmt == texture_format::cBC6HSigned);
|
||||
|
||||
for (uint32_t p = 0; p < 16; p++)
|
||||
{
|
||||
pPixels[p][0] = basist::half_to_float(half_block[p][0]);
|
||||
pPixels[p][1] = basist::half_to_float(half_block[p][1]);
|
||||
pPixels[p][2] = basist::half_to_float(half_block[p][2]);
|
||||
pPixels[p][3] = 1.0f;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool gpu_image::unpack(image& img) const
|
||||
{
|
||||
img.resize(get_pixel_width(), get_pixel_height());
|
||||
|
|
@ -1252,7 +1589,48 @@ namespace basisu
|
|||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool gpu_image::unpack_hdr(imagef& img) const
|
||||
{
|
||||
if ((m_fmt != texture_format::cASTC_HDR_4x4) &&
|
||||
(m_fmt != texture_format::cUASTC_HDR_4x4) &&
|
||||
(m_fmt != texture_format::cBC6HUnsigned) &&
|
||||
(m_fmt != texture_format::cBC6HSigned))
|
||||
{
|
||||
// Can't call on LDR images, at least currently. (Could unpack the LDR data and convert to float.)
|
||||
assert(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
img.resize(get_pixel_width(), get_pixel_height());
|
||||
img.set_all(vec4F(0.0f));
|
||||
|
||||
if (!img.get_width() || !img.get_height())
|
||||
return true;
|
||||
|
||||
assert((m_block_width <= cMaxBlockSize) && (m_block_height <= cMaxBlockSize));
|
||||
vec4F pixels[cMaxBlockSize * cMaxBlockSize];
|
||||
clear_obj(pixels);
|
||||
|
||||
bool success = true;
|
||||
|
||||
for (uint32_t by = 0; by < m_blocks_y; by++)
|
||||
{
|
||||
for (uint32_t bx = 0; bx < m_blocks_x; bx++)
|
||||
{
|
||||
const void* pBlock = get_block_ptr(bx, by);
|
||||
|
||||
if (!unpack_block_hdr(m_fmt, pBlock, pixels))
|
||||
success = false;
|
||||
|
||||
img.set_block_clipped(pixels, bx * m_block_width, by * m_block_height, m_block_width, m_block_height);
|
||||
} // bx
|
||||
} // by
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// KTX1 texture file writing
|
||||
static const uint8_t g_ktx_file_id[12] = { 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A };
|
||||
|
||||
// KTX/GL enums
|
||||
|
|
@ -1273,6 +1651,8 @@ namespace basisu
|
|||
KTX_COMPRESSED_RGBA8_ETC2_EAC = 0x9278,
|
||||
KTX_COMPRESSED_RGBA_BPTC_UNORM = 0x8E8C,
|
||||
KTX_COMPRESSED_SRGB_ALPHA_BPTC_UNORM = 0x8E8D,
|
||||
KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT = 0x8E8E,
|
||||
KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT = 0x8E8F,
|
||||
KTX_COMPRESSED_RGB_PVRTC_4BPPV1_IMG = 0x8C00,
|
||||
KTX_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG = 0x8C02,
|
||||
KTX_COMPRESSED_RGBA_ASTC_4x4_KHR = 0x93B0,
|
||||
|
|
@ -1319,6 +1699,7 @@ namespace basisu
|
|||
uint32_t width = 0, height = 0, total_levels = 0;
|
||||
basisu::texture_format fmt = texture_format::cInvalidTextureFormat;
|
||||
|
||||
// Sanity check the input
|
||||
if (cubemap_flag)
|
||||
{
|
||||
if ((gpu_images.size() % 6) != 0)
|
||||
|
|
@ -1327,7 +1708,7 @@ namespace basisu
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (uint32_t array_index = 0; array_index < gpu_images.size(); array_index++)
|
||||
{
|
||||
const gpu_image_vec &levels = gpu_images[array_index];
|
||||
|
|
@ -1426,6 +1807,18 @@ namespace basisu
|
|||
base_internal_fmt = KTX_RGBA;
|
||||
break;
|
||||
}
|
||||
case texture_format::cBC6HSigned:
|
||||
{
|
||||
internal_fmt = KTX_COMPRESSED_RGB_BPTC_SIGNED_FLOAT;
|
||||
base_internal_fmt = KTX_RGBA;
|
||||
break;
|
||||
}
|
||||
case texture_format::cBC6HUnsigned:
|
||||
{
|
||||
internal_fmt = KTX_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT;
|
||||
base_internal_fmt = KTX_RGBA;
|
||||
break;
|
||||
}
|
||||
case texture_format::cBC7:
|
||||
{
|
||||
internal_fmt = KTX_COMPRESSED_RGBA_BPTC_UNORM;
|
||||
|
|
@ -1443,7 +1836,10 @@ namespace basisu
|
|||
base_internal_fmt = KTX_RGBA;
|
||||
break;
|
||||
}
|
||||
case texture_format::cASTC4x4:
|
||||
// We use different enums for HDR vs. LDR ASTC, but internally they are both just ASTC.
|
||||
case texture_format::cASTC_LDR_4x4:
|
||||
case texture_format::cASTC_HDR_4x4:
|
||||
case texture_format::cUASTC_HDR_4x4: // UASTC_HDR is just HDR-only ASTC
|
||||
{
|
||||
internal_fmt = KTX_COMPRESSED_RGBA_ASTC_4x4_KHR;
|
||||
base_internal_fmt = KTX_RGBA;
|
||||
|
|
@ -1496,17 +1892,17 @@ namespace basisu
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ktx_header header;
|
||||
header.clear();
|
||||
memcpy(&header.m_identifier, g_ktx_file_id, sizeof(g_ktx_file_id));
|
||||
header.m_endianness = KTX_ENDIAN;
|
||||
|
||||
|
||||
header.m_pixelWidth = width;
|
||||
header.m_pixelHeight = height;
|
||||
|
||||
|
||||
header.m_glTypeSize = 1;
|
||||
|
||||
|
||||
header.m_glInternalFormat = internal_fmt;
|
||||
header.m_glBaseInternalFormat = base_internal_fmt;
|
||||
|
||||
|
|
@ -1517,12 +1913,12 @@ namespace basisu
|
|||
header.m_numberOfMipmapLevels = total_levels;
|
||||
header.m_numberOfFaces = cubemap_flag ? 6 : 1;
|
||||
|
||||
append_vector(ktx_data, (uint8_t *)&header, sizeof(header));
|
||||
append_vector(ktx_data, (uint8_t*)&header, sizeof(header));
|
||||
|
||||
for (uint32_t level_index = 0; level_index < total_levels; level_index++)
|
||||
{
|
||||
uint32_t img_size = gpu_images[0][level_index].get_size_in_bytes();
|
||||
|
||||
|
||||
if ((header.m_numberOfFaces == 1) || (header.m_numberOfArrayElements > 1))
|
||||
{
|
||||
img_size = img_size * header.m_numberOfFaces * maximum<uint32_t>(1, header.m_numberOfArrayElements);
|
||||
|
|
@ -1531,9 +1927,10 @@ namespace basisu
|
|||
assert(img_size && ((img_size & 3) == 0));
|
||||
|
||||
packed_uint<4> packed_img_size(img_size);
|
||||
append_vector(ktx_data, (uint8_t *)&packed_img_size, sizeof(packed_img_size));
|
||||
append_vector(ktx_data, (uint8_t*)&packed_img_size, sizeof(packed_img_size));
|
||||
|
||||
uint32_t bytes_written = 0;
|
||||
(void)bytes_written;
|
||||
|
||||
for (uint32_t array_index = 0; array_index < maximum<uint32_t>(1, header.m_numberOfArrayElements); array_index++)
|
||||
{
|
||||
|
|
@ -1541,11 +1938,11 @@ namespace basisu
|
|||
{
|
||||
const gpu_image& img = gpu_images[cubemap_flag ? (array_index * 6 + face_index) : array_index][level_index];
|
||||
|
||||
append_vector(ktx_data, (uint8_t *)img.get_ptr(), img.get_size_in_bytes());
|
||||
|
||||
append_vector(ktx_data, (uint8_t*)img.get_ptr(), img.get_size_in_bytes());
|
||||
|
||||
bytes_written += img.get_size_in_bytes();
|
||||
}
|
||||
|
||||
|
||||
} // array_index
|
||||
|
||||
} // level_index
|
||||
|
|
@ -1553,7 +1950,58 @@ namespace basisu
|
|||
return true;
|
||||
}
|
||||
|
||||
bool write_compressed_texture_file(const char* pFilename, const basisu::vector<gpu_image_vec>& g, bool cubemap_flag)
|
||||
bool does_dds_support_format(texture_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cBC1_NV:
|
||||
case texture_format::cBC1_AMD:
|
||||
case texture_format::cBC1:
|
||||
case texture_format::cBC3:
|
||||
case texture_format::cBC4:
|
||||
case texture_format::cBC5:
|
||||
case texture_format::cBC6HSigned:
|
||||
case texture_format::cBC6HUnsigned:
|
||||
case texture_format::cBC7:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only supports the basic DirectX BC texture formats.
|
||||
// gpu_images array is: [face/layer][mipmap level]
|
||||
// For cubemap arrays, # of face/layers must be a multiple of 6.
|
||||
// Accepts 2D, 2D mipmapped, 2D array, 2D array mipmapped
|
||||
// and cubemap, cubemap mipmapped, and cubemap array mipmapped.
|
||||
bool write_dds_file(uint8_vec &dds_data, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag, bool use_srgb_format)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool write_dds_file(const char* pFilename, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag, bool use_srgb_format)
|
||||
{
|
||||
uint8_vec dds_data;
|
||||
|
||||
if (!write_dds_file(dds_data, gpu_images, cubemap_flag, use_srgb_format))
|
||||
return false;
|
||||
|
||||
if (!write_vec_to_file(pFilename, dds_data))
|
||||
{
|
||||
fprintf(stderr, "write_dds_file: Failed writing DDS file data\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool read_uncompressed_dds_file(const char* pFilename, basisu::vector<image> &ldr_mips, basisu::vector<imagef>& hdr_mips)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool write_compressed_texture_file(const char* pFilename, const basisu::vector<gpu_image_vec>& g, bool cubemap_flag, bool use_srgb_format)
|
||||
{
|
||||
std::string extension(string_tolower(string_get_extension(pFilename)));
|
||||
|
||||
|
|
@ -1570,8 +2018,8 @@ namespace basisu
|
|||
}
|
||||
else if (extension == "dds")
|
||||
{
|
||||
// TODO
|
||||
return false;
|
||||
if (!write_dds_file(filedata, g, cubemap_flag, use_srgb_format))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1583,11 +2031,18 @@ namespace basisu
|
|||
return basisu::write_vec_to_file(pFilename, filedata);
|
||||
}
|
||||
|
||||
bool write_compressed_texture_file(const char* pFilename, const gpu_image& g)
|
||||
bool write_compressed_texture_file(const char* pFilename, const gpu_image_vec& g, bool use_srgb_format)
|
||||
{
|
||||
basisu::vector<gpu_image_vec> a;
|
||||
a.push_back(g);
|
||||
return write_compressed_texture_file(pFilename, a, false, use_srgb_format);
|
||||
}
|
||||
|
||||
bool write_compressed_texture_file(const char* pFilename, const gpu_image& g, bool use_srgb_format)
|
||||
{
|
||||
basisu::vector<gpu_image_vec> v;
|
||||
enlarge_vector(v, 1)->push_back(g);
|
||||
return write_compressed_texture_file(pFilename, v, false);
|
||||
return write_compressed_texture_file(pFilename, v, false, use_srgb_format);
|
||||
}
|
||||
|
||||
//const uint32_t OUT_FILE_MAGIC = 'TEXC';
|
||||
|
|
@ -1626,5 +2081,49 @@ namespace basisu
|
|||
|
||||
return fclose(pFile) != EOF;
|
||||
}
|
||||
|
||||
// The .astc texture format is readable using ARM's astcenc, AMD Compressonator, and other engines/tools. It oddly doesn't support mipmaps, limiting
|
||||
// its usefulness/relevance.
|
||||
// https://github.com/ARM-software/astc-encoder/blob/main/Docs/FileFormat.md
|
||||
bool write_astc_file(const char* pFilename, const void* pBlocks, uint32_t block_width, uint32_t block_height, uint32_t dim_x, uint32_t dim_y)
|
||||
{
|
||||
assert(pBlocks && (block_width >= 4) && (block_height >= 4) && (dim_x > 0) && (dim_y > 0));
|
||||
|
||||
uint8_vec file_data;
|
||||
file_data.push_back(0x13);
|
||||
file_data.push_back(0xAB);
|
||||
file_data.push_back(0xA1);
|
||||
file_data.push_back(0x5C);
|
||||
|
||||
file_data.push_back((uint8_t)block_width);
|
||||
file_data.push_back((uint8_t)block_height);
|
||||
file_data.push_back(1);
|
||||
|
||||
file_data.push_back((uint8_t)dim_x);
|
||||
file_data.push_back((uint8_t)(dim_x >> 8));
|
||||
file_data.push_back((uint8_t)(dim_x >> 16));
|
||||
|
||||
file_data.push_back((uint8_t)dim_y);
|
||||
file_data.push_back((uint8_t)(dim_y >> 8));
|
||||
file_data.push_back((uint8_t)(dim_y >> 16));
|
||||
|
||||
file_data.push_back((uint8_t)1);
|
||||
file_data.push_back((uint8_t)0);
|
||||
file_data.push_back((uint8_t)0);
|
||||
|
||||
const uint32_t num_blocks_x = (dim_x + block_width - 1) / block_width;
|
||||
const uint32_t num_blocks_y = (dim_y + block_height - 1) / block_height;
|
||||
|
||||
const uint32_t total_bytes = num_blocks_x * num_blocks_y * 16;
|
||||
|
||||
const size_t cur_size = file_data.size();
|
||||
|
||||
file_data.resize(cur_size + total_bytes);
|
||||
|
||||
memcpy(&file_data[cur_size], pBlocks, total_bytes);
|
||||
|
||||
return write_vec_to_file(pFilename, file_data);
|
||||
}
|
||||
|
||||
} // basisu
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_gpu_texture.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -48,6 +48,7 @@ namespace basisu
|
|||
}
|
||||
|
||||
inline texture_format get_format() const { return m_fmt; }
|
||||
inline bool is_hdr() const { return is_hdr_texture_format(m_fmt); }
|
||||
|
||||
// Width/height in pixels
|
||||
inline uint32_t get_pixel_width() const { return m_width; }
|
||||
|
|
@ -100,9 +101,13 @@ namespace basisu
|
|||
m_blocks.resize(m_blocks_x * m_blocks_y * m_qwords_per_block);
|
||||
}
|
||||
|
||||
// Unpacks LDR textures only.
|
||||
bool unpack(image& img) const;
|
||||
|
||||
// Unpacks HDR textures only.
|
||||
bool unpack_hdr(imagef& img) const;
|
||||
|
||||
void override_dimensions(uint32_t w, uint32_t h)
|
||||
inline void override_dimensions(uint32_t w, uint32_t h)
|
||||
{
|
||||
m_width = w;
|
||||
m_height = h;
|
||||
|
|
@ -116,39 +121,50 @@ namespace basisu
|
|||
|
||||
typedef basisu::vector<gpu_image> gpu_image_vec;
|
||||
|
||||
// KTX file writing
|
||||
|
||||
// KTX1 file writing
|
||||
bool create_ktx_texture_file(uint8_vec &ktx_data, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag);
|
||||
|
||||
bool write_compressed_texture_file(const char *pFilename, const basisu::vector<gpu_image_vec>& g, bool cubemap_flag);
|
||||
|
||||
inline bool write_compressed_texture_file(const char *pFilename, const gpu_image_vec &g)
|
||||
{
|
||||
basisu::vector<gpu_image_vec> a;
|
||||
a.push_back(g);
|
||||
return write_compressed_texture_file(pFilename, a, false);
|
||||
}
|
||||
bool does_dds_support_format(texture_format fmt);
|
||||
bool write_dds_file(uint8_vec& dds_data, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag, bool use_srgb_format);
|
||||
bool write_dds_file(const char* pFilename, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag, bool use_srgb_format);
|
||||
|
||||
bool write_compressed_texture_file(const char *pFilename, const gpu_image &g);
|
||||
// Currently reads 2D 32bpp RGBA, 16-bit HALF RGBA, or 32-bit FLOAT RGBA, with or without mipmaps. No tex arrays or cubemaps, yet.
|
||||
bool read_uncompressed_dds_file(const char* pFilename, basisu::vector<image>& ldr_mips, basisu::vector<imagef>& hdr_mips);
|
||||
|
||||
// Supports DDS and KTX
|
||||
bool write_compressed_texture_file(const char *pFilename, const basisu::vector<gpu_image_vec>& g, bool cubemap_flag, bool use_srgb_format);
|
||||
bool write_compressed_texture_file(const char* pFilename, const gpu_image_vec& g, bool use_srgb_format);
|
||||
bool write_compressed_texture_file(const char *pFilename, const gpu_image &g, bool use_srgb_format);
|
||||
|
||||
bool write_3dfx_out_file(const char* pFilename, const gpu_image& gi);
|
||||
|
||||
// GPU texture block unpacking
|
||||
// For ETC1, use in basisu_etc.h: bool unpack_etc1(const etc_block& block, color_rgba *pDst, bool preserve_alpha)
|
||||
void unpack_etc2_eac(const void *pBlock_bits, color_rgba *pPixels);
|
||||
bool unpack_bc1(const void *pBlock_bits, color_rgba *pPixels, bool set_alpha);
|
||||
void unpack_bc4(const void *pBlock_bits, uint8_t *pPixels, uint32_t stride);
|
||||
bool unpack_bc3(const void *pBlock_bits, color_rgba *pPixels);
|
||||
void unpack_bc5(const void *pBlock_bits, color_rgba *pPixels);
|
||||
bool unpack_bc7_mode6(const void *pBlock_bits, color_rgba *pPixels);
|
||||
bool unpack_bc7(const void* pBlock_bits, color_rgba* pPixels);
|
||||
bool unpack_bc7(const void* pBlock_bits, color_rgba* pPixels); // full format
|
||||
bool unpack_bc6h(const void* pSrc_block, void* pDst_block, bool is_signed, uint32_t dest_pitch_in_halfs = 4 * 3); // full format, outputs HALF values, RGB texels only (not RGBA)
|
||||
void unpack_atc(const void* pBlock_bits, color_rgba* pPixels);
|
||||
// We only support CC_MIXED non-alpha blocks here because that's the only mode the transcoder uses at the moment.
|
||||
bool unpack_fxt1(const void* p, color_rgba* pPixels);
|
||||
// PVRTC2 is currently limited to only what our transcoder outputs (non-interpolated, hard_flag=1 modulation=0). In this mode, PVRTC2 looks much like BC1/ATC.
|
||||
bool unpack_pvrtc2(const void* p, color_rgba* pPixels);
|
||||
void unpack_etc2_eac_r(const void *p, color_rgba* pPixels, uint32_t c);
|
||||
void unpack_etc2_eac_rg(const void* p, color_rgba* pPixels);
|
||||
|
||||
|
||||
// unpack_block() is primarily intended to unpack texture data created by the transcoder.
|
||||
// For some texture formats (like ETC2 RGB, PVRTC2, FXT1) it's not a complete implementation.
|
||||
// For some texture formats (like ETC2 RGB, PVRTC2, FXT1) it's not yet a complete implementation.
|
||||
// Unpacks LDR texture formats only.
|
||||
bool unpack_block(texture_format fmt, const void *pBlock, color_rgba *pPixels);
|
||||
|
||||
|
||||
// Unpacks HDR texture formats only.
|
||||
bool unpack_block_hdr(texture_format fmt, const void* pBlock, vec4F* pPixels);
|
||||
|
||||
bool write_astc_file(const char* pFilename, const void* pBlocks, uint32_t block_width, uint32_t block_height, uint32_t dim_x, uint32_t dim_y);
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_kernels_declares.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_kernels_imp.h - Do not directly include
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_kernels_sse.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -22,22 +22,6 @@
|
|||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
#if __AVX__ || __AVX2__ || __AVX512F__
|
||||
#error Please check your compiler options
|
||||
#endif
|
||||
|
||||
#if CPPSPMD_SSE2
|
||||
#if __SSE4_1__ || __SSE3__ || __SSE4_2__ || __SSSE3__
|
||||
#error SSE4.1/SSE3/SSE4.2/SSSE3 cannot be enabled to use this file
|
||||
#endif
|
||||
#else
|
||||
#if !__SSE4_1__ || !__SSE3__ || !__SSSE3__
|
||||
#error Please check your compiler options
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "cppspmd_sse.h"
|
||||
|
||||
#include "cppspmd_type_aliases.h"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Forked from the public domain/unlicense version at: https://code.google.com/archive/p/miniz/
|
||||
|
||||
Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
|
@ -1973,7 +1973,7 @@ static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahe
|
|||
(TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0) );
|
||||
if (!probe_len)
|
||||
{
|
||||
*pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break;
|
||||
*pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN); break;
|
||||
}
|
||||
else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len)
|
||||
{
|
||||
|
|
@ -2101,7 +2101,7 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d)
|
|||
|
||||
total_lz_bytes += cur_match_len;
|
||||
lookahead_pos += cur_match_len;
|
||||
dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE);
|
||||
dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
|
||||
cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
|
||||
MZ_ASSERT(lookahead_size >= cur_match_len);
|
||||
lookahead_size -= cur_match_len;
|
||||
|
|
@ -2129,7 +2129,7 @@ static mz_bool tdefl_compress_fast(tdefl_compressor *d)
|
|||
d->m_huff_count[0][lit]++;
|
||||
|
||||
lookahead_pos++;
|
||||
dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE);
|
||||
dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
|
||||
cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
|
||||
lookahead_size--;
|
||||
|
||||
|
|
@ -2283,7 +2283,7 @@ static mz_bool tdefl_compress_normal(tdefl_compressor *d)
|
|||
d->m_lookahead_pos += len_to_move;
|
||||
MZ_ASSERT(d->m_lookahead_size >= len_to_move);
|
||||
d->m_lookahead_size -= len_to_move;
|
||||
d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE);
|
||||
d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
|
||||
// Check if it's time to flush the current LZ codes to the internal output buffer.
|
||||
if ( (d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
|
||||
( (d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) )
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_opencl.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_opencl.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Note: Undefine or set BASISU_SUPPORT_OPENCL to 0 to completely OpenCL support.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_pvrtc1_4.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_pvrtc1_4.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -231,7 +231,18 @@ namespace basisu
|
|||
|
||||
inline void set_to_black()
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
#endif
|
||||
memset(m_blocks.get_ptr(), 0, m_blocks.size_in_bytes());
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool get_block_uses_transparent_modulation(uint32_t bx, uint32_t by) const
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_resampler_filters.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_resampler.cpp
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_resampler.h
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_resampler_filters.h
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_ssim.cpp
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_ssim.h
|
||||
// Copyright (C) 2019 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_uastc_enc.cpp
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -13,11 +13,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "basisu_uastc_enc.h"
|
||||
|
||||
#if BASISU_USE_ASTC_DECOMPRESS
|
||||
#include "basisu_astc_decomp.h"
|
||||
#endif
|
||||
|
||||
#include "3rdparty/android_astc_decomp.h"
|
||||
#include "basisu_gpu_texture.h"
|
||||
#include "basisu_bc7enc.h"
|
||||
|
||||
|
|
@ -384,6 +380,7 @@ namespace basisu
|
|||
}
|
||||
|
||||
uint32_t total_endpoint_bits = 0;
|
||||
(void)total_endpoint_bits;
|
||||
|
||||
for (uint32_t i = 0; i < total_tq_values; i++)
|
||||
{
|
||||
|
|
@ -428,6 +425,8 @@ namespace basisu
|
|||
#endif
|
||||
|
||||
uint32_t total_weight_bits = 0;
|
||||
(void)total_weight_bits;
|
||||
|
||||
const uint32_t plane_shift = (total_planes == 2) ? 1 : 0;
|
||||
for (uint32_t i = 0; i < 16 * total_planes; i++)
|
||||
{
|
||||
|
|
@ -3175,6 +3174,7 @@ namespace basisu
|
|||
const bool favor_bc7_error = !favor_uastc_error && ((flags & cPackUASTCFavorBC7Error) != 0);
|
||||
//const bool etc1_perceptual = true;
|
||||
|
||||
// TODO: This uses 64KB of stack space!
|
||||
uastc_encode_results results[MAX_ENCODE_RESULTS];
|
||||
|
||||
level = clampi(level, cPackUASTCLevelFastest, cPackUASTCLevelVerySlow);
|
||||
|
|
@ -3567,7 +3567,6 @@ namespace basisu
|
|||
success = basist::unpack_uastc(temp_block, (basist::color32 *)temp_block_unpacked, false);
|
||||
VALIDATE(success);
|
||||
|
||||
#if BASISU_USE_ASTC_DECOMPRESS
|
||||
// Now round trip to packed ASTC and back, then decode to pixels.
|
||||
uint32_t astc_data[4];
|
||||
|
||||
|
|
@ -3580,7 +3579,7 @@ namespace basisu
|
|||
}
|
||||
|
||||
color_rgba decoded_astc_block[4][4];
|
||||
success = basisu_astc::astc::decompress((uint8_t*)decoded_astc_block, (uint8_t*)&astc_data, false, 4, 4);
|
||||
success = basisu_astc::astc::decompress_ldr((uint8_t*)decoded_astc_block, (uint8_t*)&astc_data, false, 4, 4);
|
||||
VALIDATE(success);
|
||||
|
||||
for (uint32_t y = 0; y < 4; y++)
|
||||
|
|
@ -3595,7 +3594,6 @@ namespace basisu
|
|||
VALIDATE(temp_block_unpacked[y][x].c[3] == decoded_uastc_block[y][x].a);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -3789,8 +3787,9 @@ namespace basisu
|
|||
{
|
||||
uint64_t m_sel;
|
||||
uint32_t m_ofs;
|
||||
uint32_t m_pad; // avoid implicit padding for selector_bitsequence_hash
|
||||
selector_bitsequence() { }
|
||||
selector_bitsequence(uint32_t bit_ofs, uint64_t sel) : m_sel(sel), m_ofs(bit_ofs) { }
|
||||
selector_bitsequence(uint32_t bit_ofs, uint64_t sel) : m_sel(sel), m_ofs(bit_ofs), m_pad(0) { }
|
||||
bool operator== (const selector_bitsequence& other) const
|
||||
{
|
||||
return (m_ofs == other.m_ofs) && (m_sel == other.m_sel);
|
||||
|
|
@ -3811,7 +3810,7 @@ namespace basisu
|
|||
{
|
||||
std::size_t operator()(selector_bitsequence const& s) const noexcept
|
||||
{
|
||||
return static_cast<std::size_t>(hash_hsieh((uint8_t *)&s, sizeof(s)) ^ s.m_sel);
|
||||
return hash_hsieh((const uint8_t*)&s, sizeof(s));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_uastc_enc.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Do not include this header directly.
|
||||
// Control flow functionality in common between all the headers.
|
||||
//
|
||||
// Copyright 2020-2021 Binomial LLC
|
||||
// Copyright 2020-2024 Binomial LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
// Do not include this header directly.
|
||||
//
|
||||
// Copyright 2020-2021 Binomial LLC
|
||||
// Copyright 2020-2024 Binomial LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -646,7 +646,7 @@ CPPSPMD_FORCE_INLINE vint spmd_kernel::count_set_bits(vint x)
|
|||
{
|
||||
vint v = x - (VUINT_SHIFT_RIGHT(x, 1) & 0x55555555);
|
||||
vint v1 = (v & 0x33333333) + (VUINT_SHIFT_RIGHT(v, 2) & 0x33333333);
|
||||
return VUINT_SHIFT_RIGHT(((v1 + VUINT_SHIFT_RIGHT(v1, 4) & 0xF0F0F0F) * 0x1010101), 24);
|
||||
return VUINT_SHIFT_RIGHT(((v1 + (VUINT_SHIFT_RIGHT(v1, 4) & 0xF0F0F0F)) * 0x1010101), 24);
|
||||
}
|
||||
|
||||
CPPSPMD_FORCE_INLINE vint cmple_epu16(const vint &a, const vint &b)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// Do not include this header directly.
|
||||
// This header defines shared struct spmd_kernel helpers.
|
||||
//
|
||||
// Copyright 2020-2021 Binomial LLC
|
||||
// Copyright 2020-2024 Binomial LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -450,7 +450,7 @@ struct spmd_kernel
|
|||
CPPSPMD_FORCE_INLINE explicit operator vint() const;
|
||||
|
||||
private:
|
||||
vbool& operator=(const vbool&);
|
||||
//vbool& operator=(const vbool&);
|
||||
};
|
||||
|
||||
friend vbool operator!(const vbool& v);
|
||||
|
|
@ -481,7 +481,7 @@ struct spmd_kernel
|
|||
CPPSPMD_FORCE_INLINE explicit vfloat(int value) : m_value(_mm_set1_ps((float)value)) { }
|
||||
|
||||
private:
|
||||
vfloat& operator=(const vfloat&);
|
||||
//vfloat& operator=(const vfloat&);
|
||||
};
|
||||
|
||||
CPPSPMD_FORCE_INLINE vfloat& store(vfloat& dst, const vfloat& src)
|
||||
|
|
@ -514,7 +514,7 @@ struct spmd_kernel
|
|||
float* m_pValue;
|
||||
|
||||
private:
|
||||
float_lref& operator=(const float_lref&);
|
||||
//float_lref& operator=(const float_lref&);
|
||||
};
|
||||
|
||||
CPPSPMD_FORCE_INLINE const float_lref& store(const float_lref& dst, const vfloat& src)
|
||||
|
|
@ -561,7 +561,7 @@ struct spmd_kernel
|
|||
float* m_pValue;
|
||||
|
||||
private:
|
||||
float_vref& operator=(const float_vref&);
|
||||
//float_vref& operator=(const float_vref&);
|
||||
};
|
||||
|
||||
// Varying ref to varying float
|
||||
|
|
@ -571,7 +571,7 @@ struct spmd_kernel
|
|||
vfloat* m_pValue;
|
||||
|
||||
private:
|
||||
vfloat_vref& operator=(const vfloat_vref&);
|
||||
//vfloat_vref& operator=(const vfloat_vref&);
|
||||
};
|
||||
|
||||
// Varying ref to varying int
|
||||
|
|
@ -581,7 +581,7 @@ struct spmd_kernel
|
|||
vint* m_pValue;
|
||||
|
||||
private:
|
||||
vint_vref& operator=(const vint_vref&);
|
||||
//vint_vref& operator=(const vint_vref&);
|
||||
};
|
||||
|
||||
CPPSPMD_FORCE_INLINE const float_vref& store(const float_vref& dst, const vfloat& src);
|
||||
|
|
@ -624,7 +624,7 @@ struct spmd_kernel
|
|||
int* m_pValue;
|
||||
|
||||
private:
|
||||
int_lref& operator=(const int_lref&);
|
||||
//int_lref& operator=(const int_lref&);
|
||||
};
|
||||
|
||||
CPPSPMD_FORCE_INLINE const int_lref& store(const int_lref& dst, const vint& src)
|
||||
|
|
@ -663,7 +663,7 @@ struct spmd_kernel
|
|||
int16_t* m_pValue;
|
||||
|
||||
private:
|
||||
int16_lref& operator=(const int16_lref&);
|
||||
//int16_lref& operator=(const int16_lref&);
|
||||
};
|
||||
|
||||
CPPSPMD_FORCE_INLINE const int16_lref& store(const int16_lref& dst, const vint& src)
|
||||
|
|
@ -720,7 +720,7 @@ struct spmd_kernel
|
|||
const int* m_pValue;
|
||||
|
||||
private:
|
||||
cint_lref& operator=(const cint_lref&);
|
||||
//cint_lref& operator=(const cint_lref&);
|
||||
};
|
||||
|
||||
CPPSPMD_FORCE_INLINE vint load(const cint_lref& src)
|
||||
|
|
@ -742,7 +742,7 @@ struct spmd_kernel
|
|||
int* m_pValue;
|
||||
|
||||
private:
|
||||
int_vref& operator=(const int_vref&);
|
||||
//int_vref& operator=(const int_vref&);
|
||||
};
|
||||
|
||||
// Varying ref to constant ints
|
||||
|
|
@ -752,7 +752,7 @@ struct spmd_kernel
|
|||
const int* m_pValue;
|
||||
|
||||
private:
|
||||
cint_vref& operator=(const cint_vref&);
|
||||
//cint_vref& operator=(const cint_vref&);
|
||||
};
|
||||
|
||||
// Varying int
|
||||
|
|
@ -810,7 +810,7 @@ struct spmd_kernel
|
|||
}
|
||||
|
||||
private:
|
||||
vint& operator=(const vint&);
|
||||
//vint& operator=(const vint&);
|
||||
};
|
||||
|
||||
// Load/store linear int
|
||||
|
|
@ -1206,7 +1206,7 @@ struct spmd_kernel
|
|||
CPPSPMD_FORCE_INLINE vint load_all(const vint_vref& src)
|
||||
{
|
||||
// TODO: There's surely a better way
|
||||
__m128i k;
|
||||
__m128i k = _mm_setzero_si128();
|
||||
|
||||
k = insert_x(k, ((int*)(&src.m_pValue[extract_x(src.m_vindex)]))[0]);
|
||||
k = insert_y(k, ((int*)(&src.m_pValue[extract_y(src.m_vindex)]))[1]);
|
||||
|
|
@ -1261,7 +1261,7 @@ struct spmd_kernel
|
|||
}
|
||||
|
||||
private:
|
||||
lint& operator=(const lint&);
|
||||
//lint& operator=(const lint&);
|
||||
};
|
||||
|
||||
CPPSPMD_FORCE_INLINE lint& store_all(lint& dst, const lint& src)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
// cppspmd_type_aliases.h
|
||||
// Do not include this file directly
|
||||
//
|
||||
// Copyright 2020-2021 Binomial LLC
|
||||
// Copyright 2020-2024 Binomial LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ public:
|
|||
{
|
||||
if ((sizeof(size_t) == sizeof(uint32_t)) && (new_size > 0x7FFFFFFFUL))
|
||||
return 0;
|
||||
m_buf.resize(new_size);
|
||||
m_buf.resize((size_t)new_size);
|
||||
}
|
||||
|
||||
memcpy(&m_buf[(size_t)m_ofs], pBuf, len);
|
||||
|
|
@ -178,11 +178,11 @@ public:
|
|||
return 0;
|
||||
|
||||
uint64_t max_bytes = minimum<uint64_t>(len, m_buf.size() - m_ofs);
|
||||
memcpy(pBuf, &m_buf[(size_t)m_ofs], max_bytes);
|
||||
memcpy(pBuf, &m_buf[(size_t)m_ofs], (size_t)max_bytes);
|
||||
|
||||
m_ofs += max_bytes;
|
||||
|
||||
return max_bytes;
|
||||
return (size_t)max_bytes;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -249,11 +249,11 @@ public:
|
|||
return 0;
|
||||
|
||||
uint64_t max_bytes = minimum<uint64_t>(len, m_buf_size - m_ofs);
|
||||
memcpy(pBuf, &m_pBuf[(size_t)m_ofs], max_bytes);
|
||||
memcpy(pBuf, &m_pBuf[(size_t)m_ofs], (size_t)max_bytes);
|
||||
|
||||
m_ofs += max_bytes;
|
||||
|
||||
return max_bytes;
|
||||
return (size_t)max_bytes;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -1626,8 +1626,8 @@ int png_decoder::png_decode_start()
|
|||
|
||||
if (m_ihdr.m_ilace_type == 1)
|
||||
{
|
||||
int i;
|
||||
uint32_t total_lines, lines_processed;
|
||||
//int i;
|
||||
//uint32_t total_lines, lines_processed;
|
||||
|
||||
m_adam7_pass_size_x[0] = adam7_pass_size(m_ihdr.m_width, 0, 8);
|
||||
m_adam7_pass_size_x[1] = adam7_pass_size(m_ihdr.m_width, 4, 8);
|
||||
|
|
@ -1651,10 +1651,12 @@ int png_decoder::png_decode_start()
|
|||
|
||||
m_pass_y_left = 0;
|
||||
|
||||
#if 0
|
||||
total_lines = lines_processed = 0;
|
||||
|
||||
for (i = 0; i < 7; i++)
|
||||
total_lines += m_adam7_pass_size_y[i];
|
||||
#endif
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
|
|
@ -1675,7 +1677,7 @@ int png_decoder::png_decode_start()
|
|||
}
|
||||
}
|
||||
|
||||
lines_processed++;
|
||||
//lines_processed++;
|
||||
}
|
||||
|
||||
m_adam7_decoded_flag = TRUE;
|
||||
|
|
|
|||
26
engine/thirdparty/basis_universal/patches/0001-external-zstd-pr344.patch
vendored
Normal file
26
engine/thirdparty/basis_universal/patches/0001-external-zstd-pr344.patch
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
diff --git a/thirdparty/basis_universal/encoder/basisu_comp.cpp b/thirdparty/basis_universal/encoder/basisu_comp.cpp
|
||||
index f16e75bd46..81813257cd 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_comp.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_comp.cpp
|
||||
@@ -33,7 +33,7 @@
|
||||
#endif
|
||||
|
||||
#if BASISD_SUPPORT_KTX2_ZSTD
|
||||
-#include "../zstd/zstd.h"
|
||||
+#include <zstd.h>
|
||||
#endif
|
||||
|
||||
// Set to 1 to disable the mipPadding alignment workaround (which only seems to be needed when no key-values are written at all)
|
||||
diff --git a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
|
||||
index ea994b0c4f..32018cd282 100644
|
||||
--- a/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
|
||||
+++ b/thirdparty/basis_universal/transcoder/basisu_transcoder.cpp
|
||||
@@ -164,7 +164,7 @@
|
||||
// If BASISD_SUPPORT_KTX2_ZSTD is 0, UASTC files compressed with Zstd cannot be loaded.
|
||||
#if BASISD_SUPPORT_KTX2_ZSTD
|
||||
// We only use two Zstd API's: ZSTD_decompress() and ZSTD_isError()
|
||||
- #include "../zstd/zstd.h"
|
||||
+ #include <zstd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
13
engine/thirdparty/basis_universal/patches/0002-external-jpgd.patch
vendored
Normal file
13
engine/thirdparty/basis_universal/patches/0002-external-jpgd.patch
vendored
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
diff --git a/thirdparty/basis_universal/encoder/basisu_enc.cpp b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
index 47e8981bc3..6c0ac0ad37 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
@@ -458,7 +458,7 @@ namespace basisu
|
||||
bool load_jpg(const char *pFilename, image& img)
|
||||
{
|
||||
int width = 0, height = 0, actual_comps = 0;
|
||||
- uint8_t *pImage_data = jpgd::decompress_jpeg_image_from_file(pFilename, &width, &height, &actual_comps, 4, jpgd::jpeg_decoder::cFlagLinearChromaFiltering);
|
||||
+ uint8_t *pImage_data = jpgd::decompress_jpeg_image_from_file(pFilename, &width, &height, &actual_comps, 4, jpgd::jpeg_decoder::cFlagBoxChromaFiltering);
|
||||
if (!pImage_data)
|
||||
return false;
|
||||
|
||||
23
engine/thirdparty/basis_universal/patches/0003-external-tinyexr.patch
vendored
Normal file
23
engine/thirdparty/basis_universal/patches/0003-external-tinyexr.patch
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
diff --git a/thirdparty/basis_universal/encoder/basisu_enc.cpp b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
index 6c0ac0ad37..2bf486a028 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
@@ -27,7 +27,7 @@
|
||||
#ifndef TINYEXR_USE_ZFP
|
||||
#define TINYEXR_USE_ZFP (1)
|
||||
#endif
|
||||
-#include "3rdparty/tinyexr.h"
|
||||
+#include <tinyexr.h>
|
||||
|
||||
#ifndef MINIZ_HEADER_FILE_ONLY
|
||||
#define MINIZ_HEADER_FILE_ONLY
|
||||
@@ -3257,7 +3257,8 @@ namespace basisu
|
||||
float* out_rgba = nullptr;
|
||||
const char* err = nullptr;
|
||||
|
||||
- int status = LoadEXRWithLayer(&out_rgba, &width, &height, pFilename, nullptr, &err, &n_chans);
|
||||
+ int status = LoadEXRWithLayer(&out_rgba, &width, &height, pFilename, nullptr, &err);
|
||||
+ n_chans = 4;
|
||||
if (status != 0)
|
||||
{
|
||||
error_printf("Failed loading .EXR image \"%s\"! (TinyEXR error: %s)\n", pFilename, err ? err : "?");
|
||||
444
engine/thirdparty/basis_universal/patches/0004-remove-tinydds-qoi.patch
vendored
Normal file
444
engine/thirdparty/basis_universal/patches/0004-remove-tinydds-qoi.patch
vendored
Normal file
|
|
@ -0,0 +1,444 @@
|
|||
diff --git a/thirdparty/basis_universal/encoder/basisu_enc.cpp b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
index 2bf486a028..fff98e8301 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_enc.cpp
|
||||
@@ -37,9 +37,6 @@
|
||||
#endif
|
||||
#include "basisu_miniz.h"
|
||||
|
||||
-#define QOI_IMPLEMENTATION
|
||||
-#include "3rdparty/qoi.h"
|
||||
-
|
||||
#if defined(_WIN32)
|
||||
// For QueryPerformanceCounter/QueryPerformanceFrequency
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
@@ -408,16 +405,7 @@ namespace basisu
|
||||
|
||||
bool load_qoi(const char* pFilename, image& img)
|
||||
{
|
||||
- qoi_desc desc;
|
||||
- clear_obj(desc);
|
||||
-
|
||||
- void* p = qoi_read(pFilename, &desc, 4);
|
||||
- if (!p)
|
||||
- return false;
|
||||
-
|
||||
- img.grant_ownership(static_cast<color_rgba *>(p), desc.width, desc.height);
|
||||
-
|
||||
- return true;
|
||||
+ return false;
|
||||
}
|
||||
|
||||
bool load_png(const uint8_t *pBuf, size_t buf_size, image &img, const char *pFilename)
|
||||
diff --git a/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp b/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp
|
||||
index 000869a533..648cfb47ae 100644
|
||||
--- a/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp
|
||||
+++ b/thirdparty/basis_universal/encoder/basisu_gpu_texture.cpp
|
||||
@@ -19,9 +19,6 @@
|
||||
#include "basisu_bc7enc.h"
|
||||
#include "../transcoder/basisu_astc_hdr_core.h"
|
||||
|
||||
-#define TINYDDS_IMPLEMENTATION
|
||||
-#include "3rdparty/tinydds.h"
|
||||
-
|
||||
namespace basisu
|
||||
{
|
||||
//------------------------------------------------------------------------------------------------
|
||||
@@ -1980,207 +1977,7 @@ namespace basisu
|
||||
// and cubemap, cubemap mipmapped, and cubemap array mipmapped.
|
||||
bool write_dds_file(uint8_vec &dds_data, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag, bool use_srgb_format)
|
||||
{
|
||||
- if (!gpu_images.size())
|
||||
- {
|
||||
- assert(0);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- // Sanity check the input
|
||||
- uint32_t slices = 1;
|
||||
- if (cubemap_flag)
|
||||
- {
|
||||
- if ((gpu_images.size() % 6) != 0)
|
||||
- {
|
||||
- assert(0);
|
||||
- return false;
|
||||
- }
|
||||
- slices = gpu_images.size() / 6;
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- slices = gpu_images.size();
|
||||
- }
|
||||
-
|
||||
- uint32_t width = 0, height = 0, total_levels = 0;
|
||||
- basisu::texture_format fmt = texture_format::cInvalidTextureFormat;
|
||||
-
|
||||
- // Sanity check the input for consistent # of dimensions and mip levels
|
||||
- for (uint32_t array_index = 0; array_index < gpu_images.size(); array_index++)
|
||||
- {
|
||||
- const gpu_image_vec& levels = gpu_images[array_index];
|
||||
-
|
||||
- if (!levels.size())
|
||||
- {
|
||||
- // Empty mip chain
|
||||
- assert(0);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- if (!array_index)
|
||||
- {
|
||||
- width = levels[0].get_pixel_width();
|
||||
- height = levels[0].get_pixel_height();
|
||||
- total_levels = (uint32_t)levels.size();
|
||||
- fmt = levels[0].get_format();
|
||||
- }
|
||||
- else
|
||||
- {
|
||||
- if ((width != levels[0].get_pixel_width()) ||
|
||||
- (height != levels[0].get_pixel_height()) ||
|
||||
- (total_levels != levels.size()))
|
||||
- {
|
||||
- // All cubemap/texture array faces must be the same dimension
|
||||
- assert(0);
|
||||
- return false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- for (uint32_t level_index = 0; level_index < levels.size(); level_index++)
|
||||
- {
|
||||
- if (level_index)
|
||||
- {
|
||||
- if ((levels[level_index].get_pixel_width() != maximum<uint32_t>(1, levels[0].get_pixel_width() >> level_index)) ||
|
||||
- (levels[level_index].get_pixel_height() != maximum<uint32_t>(1, levels[0].get_pixel_height() >> level_index)))
|
||||
- {
|
||||
- // Malformed mipmap chain
|
||||
- assert(0);
|
||||
- return false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (fmt != levels[level_index].get_format())
|
||||
- {
|
||||
- // All input textures must use the same GPU format
|
||||
- assert(0);
|
||||
- return false;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // No mipmap levels
|
||||
- if (!total_levels)
|
||||
- {
|
||||
- assert(0);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- // Create the DDS mipmap level data
|
||||
- uint8_vec mipmaps[32];
|
||||
-
|
||||
- // See https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dds-file-layout-for-cubic-environment-maps
|
||||
- // DDS cubemap organization is cubemap face 0 followed by all mips, then cubemap face 1 followed by all mips, etc.
|
||||
- // Unfortunately tinydds.h's writer doesn't handle this case correctly, so we work around it here.
|
||||
- // This also applies with 2D texture arrays, too. RenderDoc and ddsview (DirectXTex) views each type (cubemap array and 2D texture array) correctly.
|
||||
- // Also see "Using Texture Arrays in Direct3D 10/11":
|
||||
- // https://learn.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide
|
||||
- for (uint32_t array_index = 0; array_index < gpu_images.size(); array_index++)
|
||||
- {
|
||||
- const gpu_image_vec& levels = gpu_images[array_index];
|
||||
-
|
||||
- for (uint32_t level_index = 0; level_index < levels.size(); level_index++)
|
||||
- {
|
||||
- append_vector(mipmaps[0], (uint8_t*)levels[level_index].get_ptr(), levels[level_index].get_size_in_bytes());
|
||||
-
|
||||
- } // level_index
|
||||
- } // array_index
|
||||
-
|
||||
-#if 0
|
||||
- // This organization, required by tinydds.h's API, is wrong.
|
||||
- {
|
||||
- for (uint32_t array_index = 0; array_index < gpu_images.size(); array_index++)
|
||||
- {
|
||||
- const gpu_image_vec& levels = gpu_images[array_index];
|
||||
-
|
||||
- for (uint32_t level_index = 0; level_index < levels.size(); level_index++)
|
||||
- {
|
||||
- append_vector(mipmaps[level_index], (uint8_t*)levels[level_index].get_ptr(), levels[level_index].get_size_in_bytes());
|
||||
-
|
||||
- } // level_index
|
||||
- } // array_index
|
||||
- }
|
||||
-#endif
|
||||
-
|
||||
- // Write DDS file using tinydds
|
||||
- TinyDDS_WriteCallbacks cbs;
|
||||
- cbs.error = [](void* user, char const* msg) { BASISU_NOTE_UNUSED(user); fprintf(stderr, "tinydds: %s\n", msg); };
|
||||
- cbs.alloc = [](void* user, size_t size) -> void* { BASISU_NOTE_UNUSED(user); return malloc(size); };
|
||||
- cbs.free = [](void* user, void* memory) { BASISU_NOTE_UNUSED(user); free(memory); };
|
||||
- cbs.write = [](void* user, void const* buffer, size_t byteCount) { BASISU_NOTE_UNUSED(user); uint8_vec* pVec = (uint8_vec*)user; append_vector(*pVec, (const uint8_t*)buffer, byteCount); };
|
||||
-
|
||||
- uint32_t mipmap_sizes[32];
|
||||
- const void* mipmap_ptrs[32];
|
||||
-
|
||||
- clear_obj(mipmap_sizes);
|
||||
- clear_obj(mipmap_ptrs);
|
||||
-
|
||||
- assert(total_levels < 32);
|
||||
- for (uint32_t i = 0; i < total_levels; i++)
|
||||
- {
|
||||
- mipmap_sizes[i] = mipmaps[i].size_in_bytes();
|
||||
- mipmap_ptrs[i] = mipmaps[i].get_ptr();
|
||||
- }
|
||||
-
|
||||
- // Select tinydds texture format
|
||||
- uint32_t tinydds_fmt = 0;
|
||||
-
|
||||
- switch (fmt)
|
||||
- {
|
||||
- case texture_format::cBC1_NV:
|
||||
- case texture_format::cBC1_AMD:
|
||||
- case texture_format::cBC1:
|
||||
- tinydds_fmt = use_srgb_format ? TDDS_BC1_RGBA_SRGB_BLOCK : TDDS_BC1_RGBA_UNORM_BLOCK;
|
||||
- break;
|
||||
- case texture_format::cBC3:
|
||||
- tinydds_fmt = use_srgb_format ? TDDS_BC3_SRGB_BLOCK : TDDS_BC3_UNORM_BLOCK;
|
||||
- break;
|
||||
- case texture_format::cBC4:
|
||||
- tinydds_fmt = TDDS_BC4_UNORM_BLOCK;
|
||||
- break;
|
||||
- case texture_format::cBC5:
|
||||
- tinydds_fmt = TDDS_BC5_UNORM_BLOCK;
|
||||
- break;
|
||||
- case texture_format::cBC6HSigned:
|
||||
- tinydds_fmt = TDDS_BC6H_SFLOAT_BLOCK;
|
||||
- break;
|
||||
- case texture_format::cBC6HUnsigned:
|
||||
- tinydds_fmt = TDDS_BC6H_UFLOAT_BLOCK;
|
||||
- break;
|
||||
- case texture_format::cBC7:
|
||||
- tinydds_fmt = use_srgb_format ? TDDS_BC7_SRGB_BLOCK : TDDS_BC7_UNORM_BLOCK;
|
||||
- break;
|
||||
- default:
|
||||
- {
|
||||
- fprintf(stderr, "Warning: Unsupported format in write_dds_file().\n");
|
||||
- return false;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // DirectXTex's DDSView doesn't handle odd sizes textures correctly. RenderDoc loads them fine, however.
|
||||
- // Trying to work around this here results in invalid mipmaps.
|
||||
- //width = (width + 3) & ~3;
|
||||
- //height = (height + 3) & ~3;
|
||||
-
|
||||
- bool status = TinyDDS_WriteImage(&cbs,
|
||||
- &dds_data,
|
||||
- width,
|
||||
- height,
|
||||
- 1,
|
||||
- slices,
|
||||
- total_levels,
|
||||
- (TinyDDS_Format)tinydds_fmt,
|
||||
- cubemap_flag,
|
||||
- true,
|
||||
- mipmap_sizes,
|
||||
- mipmap_ptrs);
|
||||
-
|
||||
- if (!status)
|
||||
- {
|
||||
- fprintf(stderr, "write_dds_file: Failed creating DDS file\n");
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- return true;
|
||||
+ return false;
|
||||
}
|
||||
|
||||
bool write_dds_file(const char* pFilename, const basisu::vector<gpu_image_vec>& gpu_images, bool cubemap_flag, bool use_srgb_format)
|
||||
@@ -2201,188 +1998,6 @@ namespace basisu
|
||||
|
||||
bool read_uncompressed_dds_file(const char* pFilename, basisu::vector<image> &ldr_mips, basisu::vector<imagef>& hdr_mips)
|
||||
{
|
||||
- const uint32_t MAX_IMAGE_DIM = 16384;
|
||||
-
|
||||
- TinyDDS_Callbacks cbs;
|
||||
-
|
||||
- cbs.errorFn = [](void* user, char const* msg) { BASISU_NOTE_UNUSED(user); fprintf(stderr, "tinydds: %s\n", msg); };
|
||||
- cbs.allocFn = [](void* user, size_t size) -> void* { BASISU_NOTE_UNUSED(user); return malloc(size); };
|
||||
- cbs.freeFn = [](void* user, void* memory) { BASISU_NOTE_UNUSED(user); free(memory); };
|
||||
- cbs.readFn = [](void* user, void* buffer, size_t byteCount) -> size_t { return (size_t)fread(buffer, 1, byteCount, (FILE*)user); };
|
||||
-
|
||||
-#ifdef _MSC_VER
|
||||
- cbs.seekFn = [](void* user, int64_t ofs) -> bool { return _fseeki64((FILE*)user, ofs, SEEK_SET) == 0; };
|
||||
- cbs.tellFn = [](void* user) -> int64_t { return _ftelli64((FILE*)user); };
|
||||
-#else
|
||||
- cbs.seekFn = [](void* user, int64_t ofs) -> bool { return fseek((FILE*)user, (long)ofs, SEEK_SET) == 0; };
|
||||
- cbs.tellFn = [](void* user) -> int64_t { return (int64_t)ftell((FILE*)user); };
|
||||
-#endif
|
||||
-
|
||||
- FILE* pFile = fopen_safe(pFilename, "rb");
|
||||
- if (!pFile)
|
||||
- {
|
||||
- error_printf("Can't open .DDS file \"%s\"\n", pFilename);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- // These are the formats AMD Compressonator supports in its UI.
|
||||
- enum dds_fmt
|
||||
- {
|
||||
- cRGBA32,
|
||||
- cRGBA_HALF,
|
||||
- cRGBA_FLOAT
|
||||
- };
|
||||
-
|
||||
- bool status = false;
|
||||
- dds_fmt fmt = cRGBA32;
|
||||
- uint32_t width = 0, height = 0;
|
||||
- bool hdr_flag = false;
|
||||
- TinyDDS_Format tfmt = TDDS_UNDEFINED;
|
||||
-
|
||||
- TinyDDS_ContextHandle ctx = TinyDDS_CreateContext(&cbs, pFile);
|
||||
- if (!ctx)
|
||||
- goto failure;
|
||||
-
|
||||
- status = TinyDDS_ReadHeader(ctx);
|
||||
- if (!status)
|
||||
- {
|
||||
- error_printf("Failed parsing DDS header in file \"%s\"\n", pFilename);
|
||||
- goto failure;
|
||||
- }
|
||||
-
|
||||
- if ((!TinyDDS_Is2D(ctx)) || (TinyDDS_ArraySlices(ctx) > 1) || (TinyDDS_IsCubemap(ctx)))
|
||||
- {
|
||||
- error_printf("Unsupported DDS texture type in file \"%s\"\n", pFilename);
|
||||
- goto failure;
|
||||
- }
|
||||
-
|
||||
- width = TinyDDS_Width(ctx);
|
||||
- height = TinyDDS_Height(ctx);
|
||||
-
|
||||
- if (!width || !height)
|
||||
- {
|
||||
- error_printf("DDS texture dimensions invalid in file \"%s\"\n", pFilename);
|
||||
- goto failure;
|
||||
- }
|
||||
-
|
||||
- if ((width > MAX_IMAGE_DIM) || (height > MAX_IMAGE_DIM))
|
||||
- {
|
||||
- error_printf("DDS texture dimensions too large in file \"%s\"\n", pFilename);
|
||||
- goto failure;
|
||||
- }
|
||||
-
|
||||
- tfmt = TinyDDS_GetFormat(ctx);
|
||||
- switch (tfmt)
|
||||
- {
|
||||
- case TDDS_R8G8B8A8_SRGB:
|
||||
- case TDDS_R8G8B8A8_UNORM:
|
||||
- case TDDS_B8G8R8A8_SRGB:
|
||||
- case TDDS_B8G8R8A8_UNORM:
|
||||
- fmt = cRGBA32;
|
||||
- break;
|
||||
- case TDDS_R16G16B16A16_SFLOAT:
|
||||
- fmt = cRGBA_HALF;
|
||||
- hdr_flag = true;
|
||||
- break;
|
||||
- case TDDS_R32G32B32A32_SFLOAT:
|
||||
- fmt = cRGBA_FLOAT;
|
||||
- hdr_flag = true;
|
||||
- break;
|
||||
- default:
|
||||
- error_printf("File \"%s\" has an unsupported DDS texture format (only supports RGBA/BGRA 32bpp, RGBA HALF float, or RGBA FLOAT)\n", pFilename);
|
||||
- goto failure;
|
||||
- }
|
||||
-
|
||||
- if (hdr_flag)
|
||||
- hdr_mips.resize(TinyDDS_NumberOfMipmaps(ctx));
|
||||
- else
|
||||
- ldr_mips.resize(TinyDDS_NumberOfMipmaps(ctx));
|
||||
-
|
||||
- for (uint32_t level = 0; level < TinyDDS_NumberOfMipmaps(ctx); level++)
|
||||
- {
|
||||
- const uint32_t level_width = TinyDDS_MipMapReduce(width, level);
|
||||
- const uint32_t level_height = TinyDDS_MipMapReduce(height, level);
|
||||
- const uint32_t total_level_texels = level_width * level_height;
|
||||
-
|
||||
- const void* pImage = TinyDDS_ImageRawData(ctx, level);
|
||||
- const uint32_t image_size = TinyDDS_ImageSize(ctx, level);
|
||||
-
|
||||
- if (fmt == cRGBA32)
|
||||
- {
|
||||
- ldr_mips[level].resize(level_width, level_height);
|
||||
-
|
||||
- if ((ldr_mips[level].get_total_pixels() * sizeof(uint32_t) != image_size))
|
||||
- {
|
||||
- assert(0);
|
||||
- goto failure;
|
||||
- }
|
||||
-
|
||||
- memcpy(ldr_mips[level].get_ptr(), pImage, image_size);
|
||||
-
|
||||
- if ((tfmt == TDDS_B8G8R8A8_SRGB) || (tfmt == TDDS_B8G8R8A8_UNORM))
|
||||
- {
|
||||
- // Swap R and B components.
|
||||
- uint32_t *pTexels = (uint32_t *)ldr_mips[level].get_ptr();
|
||||
- for (uint32_t i = 0; i < total_level_texels; i++)
|
||||
- {
|
||||
- const uint32_t v = pTexels[i];
|
||||
- const uint32_t r = (v >> 16) & 0xFF;
|
||||
- const uint32_t b = v & 0xFF;
|
||||
- pTexels[i] = r | (b << 16) | (v & 0xFF00FF00);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
- else if (fmt == cRGBA_FLOAT)
|
||||
- {
|
||||
- hdr_mips[level].resize(level_width, level_height);
|
||||
-
|
||||
- if ((hdr_mips[level].get_total_pixels() * sizeof(float) * 4 != image_size))
|
||||
- {
|
||||
- assert(0);
|
||||
- goto failure;
|
||||
- }
|
||||
-
|
||||
- memcpy(hdr_mips[level].get_ptr(), pImage, image_size);
|
||||
- }
|
||||
- else if (fmt == cRGBA_HALF)
|
||||
- {
|
||||
- hdr_mips[level].resize(level_width, level_height);
|
||||
-
|
||||
- if ((hdr_mips[level].get_total_pixels() * sizeof(basist::half_float) * 4 != image_size))
|
||||
- {
|
||||
- assert(0);
|
||||
- goto failure;
|
||||
- }
|
||||
-
|
||||
- // Unpack half to float.
|
||||
- const basist::half_float* pSrc_comps = static_cast<const basist::half_float*>(pImage);
|
||||
- vec4F* pDst_texels = hdr_mips[level].get_ptr();
|
||||
-
|
||||
- for (uint32_t i = 0; i < total_level_texels; i++)
|
||||
- {
|
||||
- (*pDst_texels)[0] = basist::half_to_float(pSrc_comps[0]);
|
||||
- (*pDst_texels)[1] = basist::half_to_float(pSrc_comps[1]);
|
||||
- (*pDst_texels)[2] = basist::half_to_float(pSrc_comps[2]);
|
||||
- (*pDst_texels)[3] = basist::half_to_float(pSrc_comps[3]);
|
||||
-
|
||||
- pSrc_comps += 4;
|
||||
- pDst_texels++;
|
||||
- } // y
|
||||
- }
|
||||
- } // level
|
||||
-
|
||||
- TinyDDS_DestroyContext(ctx);
|
||||
- fclose(pFile);
|
||||
-
|
||||
- return true;
|
||||
-
|
||||
- failure:
|
||||
- if (ctx)
|
||||
- TinyDDS_DestroyContext(ctx);
|
||||
-
|
||||
- if (pFile)
|
||||
- fclose(pFile);
|
||||
-
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
From b4a0fa23c13da413d94b99f307e401c3b83e0108 Mon Sep 17 00:00:00 2001
|
||||
From: Ondrej Stava <ondrej.stava@gmail.com>
|
||||
Date: Fri, 23 Apr 2021 18:59:45 -0700
|
||||
Subject: [PATCH] Made it easier to use the library with external zstdlib
|
||||
implementations (mostly in non CMake builds).
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In our internal repository, we have our own version of zstdlib and introducing extra copy is both undesirable and potentially dangerous (due to ODR violations).
|
||||
|
||||
Co-authored-by: Rémi Verschelde <rverschelde@gmail.com>
|
||||
---
|
||||
encoder/basisu_comp.cpp | 2 +-
|
||||
transcoder/basisu_transcoder.cpp | 2 +-
|
||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/encoder/basisu_comp.cpp b/encoder/basisu_comp.cpp
|
||||
index 41eae2b7..4e69e9e2 100644
|
||||
--- a/encoder/basisu_comp.cpp
|
||||
+++ b/encoder/basisu_comp.cpp
|
||||
@@ -28,7 +28,7 @@
|
||||
#endif
|
||||
|
||||
#if BASISD_SUPPORT_KTX2_ZSTD
|
||||
-#include "../zstd/zstd.h"
|
||||
+#include <zstd.h>
|
||||
#endif
|
||||
|
||||
// Set to 1 to disable the mipPadding alignment workaround (which only seems to be needed when no key-values are written at all)
|
||||
diff --git a/transcoder/basisu_transcoder.cpp b/transcoder/basisu_transcoder.cpp
|
||||
index 3aeba0ee..c698861f 100644
|
||||
--- a/transcoder/basisu_transcoder.cpp
|
||||
+++ b/transcoder/basisu_transcoder.cpp
|
||||
@@ -155,7 +155,7 @@
|
||||
// If BASISD_SUPPORT_KTX2_ZSTD is 0, UASTC files compressed with Zstd cannot be loaded.
|
||||
#if BASISD_SUPPORT_KTX2_ZSTD
|
||||
// We only use two Zstd API's: ZSTD_decompress() and ZSTD_isError()
|
||||
- #include "../zstd/zstd.h"
|
||||
+ #include <zstd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -117,13 +117,26 @@ namespace basisu
|
|||
typedef basisu::vector<uint64_t> uint64_vec;
|
||||
typedef basisu::vector<int> int_vec;
|
||||
typedef basisu::vector<bool> bool_vec;
|
||||
typedef basisu::vector<float> float_vec;
|
||||
|
||||
void enable_debug_printf(bool enabled);
|
||||
void debug_printf(const char *pFmt, ...);
|
||||
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <typename T> inline void clear_obj(T& obj) { memset(&obj, 0, sizeof(obj)); }
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <typename T0, typename T1> inline T0 lerp(T0 a, T0 b, T1 c) { return a + (b - a) * c; }
|
||||
|
||||
template <typename S> inline S maximum(S a, S b) { return (a > b) ? a : b; }
|
||||
|
|
@ -162,10 +175,45 @@ namespace basisu
|
|||
template<typename T> inline T open_range_check(T v, T minv, T maxv) { assert(v >= minv && v < maxv); BASISU_NOTE_UNUSED(minv); BASISU_NOTE_UNUSED(maxv); return v; }
|
||||
template<typename T> inline T open_range_check(T v, T maxv) { assert(v < maxv); BASISU_NOTE_UNUSED(maxv); return v; }
|
||||
|
||||
// Open interval
|
||||
inline bool in_bounds(int v, int l, int h)
|
||||
{
|
||||
return (v >= l) && (v < h);
|
||||
}
|
||||
|
||||
// Closed interval
|
||||
inline bool in_range(int v, int l, int h)
|
||||
{
|
||||
return (v >= l) && (v <= h);
|
||||
}
|
||||
|
||||
inline uint32_t total_bits(uint32_t v) { uint32_t l = 0; for ( ; v > 0U; ++l) v >>= 1; return l; }
|
||||
|
||||
template<typename T> inline T saturate(T val) { return clamp(val, 0.0f, 1.0f); }
|
||||
|
||||
inline uint32_t get_bit(uint32_t src, int ndx)
|
||||
{
|
||||
assert(in_bounds(ndx, 0, 32));
|
||||
return (src >> ndx) & 1;
|
||||
}
|
||||
|
||||
inline bool is_bit_set(uint32_t src, int ndx)
|
||||
{
|
||||
return get_bit(src, ndx) != 0;
|
||||
}
|
||||
|
||||
inline uint32_t get_bits(uint32_t val, int low, int high)
|
||||
{
|
||||
const int num_bits = (high - low) + 1;
|
||||
assert(in_range(num_bits, 1, 32));
|
||||
|
||||
val >>= low;
|
||||
if (num_bits != 32)
|
||||
val &= ((1u << num_bits) - 1);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
template<typename T, typename R> inline void append_vector(T &vec, const R *pObjs, size_t n)
|
||||
{
|
||||
if (n)
|
||||
|
|
@ -267,6 +315,11 @@ namespace basisu
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline uint32_t read_le_word(const uint8_t* pBytes)
|
||||
{
|
||||
return (pBytes[1] << 8U) | (pBytes[0]);
|
||||
}
|
||||
|
||||
static inline uint32_t read_le_dword(const uint8_t *pBytes)
|
||||
{
|
||||
return (pBytes[3] << 24U) | (pBytes[2] << 16U) | (pBytes[1] << 8U) | (pBytes[0]);
|
||||
|
|
@ -303,6 +356,10 @@ namespace basisu
|
|||
return *this;
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Warray-bounds"
|
||||
#endif
|
||||
inline operator uint32_t() const
|
||||
{
|
||||
switch (NumBytes)
|
||||
|
|
@ -354,6 +411,9 @@ namespace basisu
|
|||
}
|
||||
}
|
||||
}
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
};
|
||||
|
||||
enum eZero { cZero };
|
||||
|
|
@ -402,8 +462,11 @@ namespace basisu
|
|||
cBC3, // DXT5 (BC4/DXT5A block followed by a BC1/DXT1 block)
|
||||
cBC4, // DXT5A
|
||||
cBC5, // 3DC/DXN (two BC4/DXT5A blocks)
|
||||
cBC6HSigned, // HDR
|
||||
cBC6HUnsigned, // HDR
|
||||
cBC7,
|
||||
cASTC4x4, // LDR only
|
||||
cASTC_LDR_4x4, // ASTC 4x4 LDR only
|
||||
cASTC_HDR_4x4, // ASTC 4x4 HDR only (but may use LDR ASTC blocks internally)
|
||||
cPVRTC1_4_RGB,
|
||||
cPVRTC1_4_RGBA,
|
||||
cATC_RGB,
|
||||
|
|
@ -413,17 +476,22 @@ namespace basisu
|
|||
cETC2_R11_EAC,
|
||||
cETC2_RG11_EAC,
|
||||
cUASTC4x4,
|
||||
cUASTC_HDR_4x4,
|
||||
cBC1_NV,
|
||||
cBC1_AMD,
|
||||
|
||||
|
||||
// Uncompressed/raw pixels
|
||||
cRGBA32,
|
||||
cRGB565,
|
||||
cBGR565,
|
||||
cRGBA4444,
|
||||
cABGR4444
|
||||
cABGR4444,
|
||||
cRGBA_HALF,
|
||||
cRGB_HALF,
|
||||
cRGB_9E5
|
||||
};
|
||||
|
||||
// This is bytes per block for GPU formats, or bytes per texel for uncompressed formats.
|
||||
inline uint32_t get_bytes_per_block(texture_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
|
|
@ -443,13 +511,27 @@ namespace basisu
|
|||
case texture_format::cETC2_R11_EAC:
|
||||
return 8;
|
||||
case texture_format::cRGBA32:
|
||||
return sizeof(uint32_t) * 16;
|
||||
case texture_format::cRGB_9E5:
|
||||
return sizeof(uint32_t);
|
||||
case texture_format::cRGB_HALF:
|
||||
return sizeof(uint16_t) * 3;
|
||||
case texture_format::cRGBA_HALF:
|
||||
return sizeof(uint16_t) * 4;
|
||||
case texture_format::cRGB565:
|
||||
case texture_format::cBGR565:
|
||||
case texture_format::cRGBA4444:
|
||||
case texture_format::cABGR4444:
|
||||
return sizeof(uint16_t);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Everything else is 16 bytes/block.
|
||||
return 16;
|
||||
}
|
||||
|
||||
// This is qwords per block for GPU formats, or not valid for uncompressed formats.
|
||||
inline uint32_t get_qwords_per_block(texture_format fmt)
|
||||
{
|
||||
return get_bytes_per_block(fmt) >> 3;
|
||||
|
|
@ -473,6 +555,17 @@ namespace basisu
|
|||
BASISU_NOTE_UNUSED(fmt);
|
||||
return 4;
|
||||
}
|
||||
|
||||
inline bool is_hdr_texture_format(texture_format fmt)
|
||||
{
|
||||
if (fmt == texture_format::cASTC_HDR_4x4)
|
||||
return true;
|
||||
if (fmt == texture_format::cUASTC_HDR_4x4)
|
||||
return true;
|
||||
if ((fmt == texture_format::cBC6HSigned) || (fmt == texture_format::cBC6HUnsigned))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
|
|
|
|||
102
engine/thirdparty/basis_universal/transcoder/basisu_astc_hdr_core.h
vendored
Normal file
102
engine/thirdparty/basis_universal/transcoder/basisu_astc_hdr_core.h
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
// File: basisu_astc_hdr_core.h
|
||||
#pragma once
|
||||
#include "basisu_astc_helpers.h"
|
||||
|
||||
namespace basist
|
||||
{
|
||||
struct astc_blk
|
||||
{
|
||||
uint8_t m_vals[16];
|
||||
};
|
||||
|
||||
// ASTC_HDR_MAX_VAL is the maximum color component value that can be encoded.
|
||||
// If the input has values higher than this, they need to be linearly scaled so all values are between [0,ASTC_HDR_MAX_VAL], and the linear scaling inverted in the shader.
|
||||
const float ASTC_HDR_MAX_VAL = 65216.0f; // actually MAX_QLOG12_VAL
|
||||
|
||||
// Maximum usable QLOG encodings, and their floating point equivalent values, that don't result in NaN/Inf's.
|
||||
const uint32_t MAX_QLOG7 = 123;
|
||||
//const float MAX_QLOG7_VAL = 55296.0f;
|
||||
|
||||
const uint32_t MAX_QLOG8 = 247;
|
||||
//const float MAX_QLOG8_VAL = 60416.0f;
|
||||
|
||||
const uint32_t MAX_QLOG9 = 495;
|
||||
//const float MAX_QLOG9_VAL = 62976.0f;
|
||||
|
||||
const uint32_t MAX_QLOG10 = 991;
|
||||
//const float MAX_QLOG10_VAL = 64256.0f;
|
||||
|
||||
const uint32_t MAX_QLOG11 = 1983;
|
||||
//const float MAX_QLOG11_VAL = 64896.0f;
|
||||
|
||||
const uint32_t MAX_QLOG12 = 3967;
|
||||
//const float MAX_QLOG12_VAL = 65216.0f;
|
||||
|
||||
const uint32_t MAX_QLOG16 = 63487;
|
||||
const float MAX_QLOG16_VAL = 65504.0f;
|
||||
|
||||
const uint32_t NUM_MODE11_ENDPOINTS = 6, NUM_MODE7_ENDPOINTS = 4;
|
||||
|
||||
// Notes:
|
||||
// qlog16_to_half(half_to_qlog16(half_val_as_int)) == half_val_as_int (is lossless)
|
||||
// However, this is not lossless in the general sense.
|
||||
inline half_float qlog16_to_half_slow(uint32_t qlog16)
|
||||
{
|
||||
assert(qlog16 <= 0xFFFF);
|
||||
|
||||
int C = qlog16;
|
||||
|
||||
int E = (C & 0xF800) >> 11;
|
||||
int M = C & 0x7FF;
|
||||
|
||||
int Mt;
|
||||
if (M < 512)
|
||||
Mt = 3 * M;
|
||||
else if (M >= 1536)
|
||||
Mt = 5 * M - 2048;
|
||||
else
|
||||
Mt = 4 * M - 512;
|
||||
|
||||
int Cf = (E << 10) + (Mt >> 3);
|
||||
return (half_float)Cf;
|
||||
}
|
||||
|
||||
// This is not lossless
|
||||
inline half_float qlog_to_half_slow(uint32_t qlog, uint32_t bits)
|
||||
{
|
||||
assert((bits >= 7U) && (bits <= 16U));
|
||||
assert(qlog < (1U << bits));
|
||||
|
||||
int C = qlog << (16 - bits);
|
||||
return qlog16_to_half_slow(C);
|
||||
}
|
||||
|
||||
void astc_hdr_core_init();
|
||||
|
||||
void decode_mode7_to_qlog12_ise20(
|
||||
const uint8_t* pEndpoints,
|
||||
int e[2][3],
|
||||
int* pScale);
|
||||
|
||||
bool decode_mode7_to_qlog12(
|
||||
const uint8_t* pEndpoints,
|
||||
int e[2][3],
|
||||
int* pScale,
|
||||
uint32_t ise_endpoint_range);
|
||||
|
||||
void decode_mode11_to_qlog12_ise20(
|
||||
const uint8_t* pEndpoints,
|
||||
int e[2][3]);
|
||||
|
||||
bool decode_mode11_to_qlog12(
|
||||
const uint8_t* pEndpoints,
|
||||
int e[2][3],
|
||||
uint32_t ise_endpoint_range);
|
||||
|
||||
bool transcode_bc6h_1subset(half_float h_e[3][2], const astc_helpers::log_astc_block& best_blk, bc6h_block& transcoded_bc6h_blk);
|
||||
bool transcode_bc6h_2subsets(uint32_t common_part_index, const astc_helpers::log_astc_block& best_blk, bc6h_block& transcoded_bc6h_blk);
|
||||
|
||||
bool astc_hdr_transcode_to_bc6h(const astc_blk& src_blk, bc6h_block& dst_blk);
|
||||
bool astc_hdr_transcode_to_bc6h(const astc_helpers::log_astc_block& log_blk, bc6h_block& dst_blk);
|
||||
|
||||
} // namespace basist
|
||||
3587
engine/thirdparty/basis_universal/transcoder/basisu_astc_helpers.h
vendored
Normal file
3587
engine/thirdparty/basis_universal/transcoder/basisu_astc_helpers.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -188,8 +188,9 @@ namespace basisu
|
|||
|
||||
#define BASISU_IS_SCALAR_TYPE(T) (scalar_type<T>::cFlag)
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__<5
|
||||
#define BASISU_IS_TRIVIALLY_COPYABLE(...) __has_trivial_copy(__VA_ARGS__)
|
||||
#if !defined(BASISU_HAVE_STD_TRIVIALLY_COPYABLE) && defined(__GNUC__) && __GNUC__<5
|
||||
//#define BASISU_IS_TRIVIALLY_COPYABLE(...) __has_trivial_copy(__VA_ARGS__)
|
||||
#define BASISU_IS_TRIVIALLY_COPYABLE(...) __is_trivially_copyable(__VA_ARGS__)
|
||||
#else
|
||||
#define BASISU_IS_TRIVIALLY_COPYABLE(...) std::is_trivially_copyable<__VA_ARGS__>::value
|
||||
#endif
|
||||
|
|
@ -286,8 +287,19 @@ namespace basisu
|
|||
|
||||
if (BASISU_IS_BITWISE_COPYABLE(T))
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
#endif
|
||||
if ((m_p) && (other.m_p))
|
||||
memcpy(m_p, other.m_p, m_size * sizeof(T));
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -330,8 +342,19 @@ namespace basisu
|
|||
|
||||
if (BASISU_IS_BITWISE_COPYABLE(T))
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
#endif
|
||||
if ((m_p) && (other.m_p))
|
||||
memcpy(m_p, other.m_p, other.m_size * sizeof(T));
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -501,7 +524,7 @@ namespace basisu
|
|||
|
||||
if (new_capacity > m_capacity)
|
||||
{
|
||||
if (!increase_capacity(new_capacity, false))
|
||||
if (!increase_capacity(new_capacity, false, true))
|
||||
return false;
|
||||
}
|
||||
else if (new_capacity < m_capacity)
|
||||
|
|
@ -509,7 +532,8 @@ namespace basisu
|
|||
// Must work around the lack of a "decrease_capacity()" method.
|
||||
// This case is rare enough in practice that it's probably not worth implementing an optimized in-place resize.
|
||||
vector tmp;
|
||||
tmp.increase_capacity(helpers::maximum(m_size, new_capacity), false);
|
||||
if (!tmp.increase_capacity(helpers::maximum(m_size, new_capacity), false, true))
|
||||
return false;
|
||||
tmp = *this;
|
||||
swap(tmp);
|
||||
}
|
||||
|
|
@ -750,7 +774,21 @@ namespace basisu
|
|||
}
|
||||
|
||||
// Copy "down" the objects to preserve, filling in the empty slots.
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
memmove(pDst, pSrc, num_to_move * sizeof(T));
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1003,7 +1041,21 @@ namespace basisu
|
|||
inline void set_all(const T& o)
|
||||
{
|
||||
if ((sizeof(T) == 1) && (scalar_type<T>::cFlag))
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
#endif
|
||||
memset(m_p, *reinterpret_cast<const uint8_t*>(&o), m_size);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
T* pDst = m_p;
|
||||
|
|
@ -1029,7 +1081,7 @@ namespace basisu
|
|||
// Important: This method is used in Basis Universal. If you change how this container allocates memory, you'll need to change any users of this method.
|
||||
inline bool grant_ownership(T* p, uint32_t size, uint32_t capacity)
|
||||
{
|
||||
// To to prevent the caller from obviously shooting themselves in the foot.
|
||||
// To prevent the caller from obviously shooting themselves in the foot.
|
||||
if (((p + capacity) > m_p) && (p < (m_p + m_capacity)))
|
||||
{
|
||||
// Can grant ownership of a block inside the container itself!
|
||||
|
|
|
|||
|
|
@ -19,23 +19,30 @@ namespace basisu
|
|||
if (m_capacity >= min_new_capacity)
|
||||
return true;
|
||||
|
||||
size_t new_capacity = min_new_capacity;
|
||||
if ((grow_hint) && (!helpers::is_power_of_2((uint64_t)new_capacity)))
|
||||
uint64_t new_capacity_u64 = min_new_capacity;
|
||||
if ((grow_hint) && (!helpers::is_power_of_2(new_capacity_u64)))
|
||||
new_capacity_u64 = helpers::next_pow2(new_capacity_u64);
|
||||
|
||||
size_t new_capacity = (size_t)new_capacity_u64;
|
||||
if (new_capacity != new_capacity_u64)
|
||||
{
|
||||
new_capacity = (size_t)helpers::next_pow2((uint64_t)new_capacity);
|
||||
|
||||
assert(new_capacity && (new_capacity > m_capacity));
|
||||
|
||||
if (new_capacity < min_new_capacity)
|
||||
{
|
||||
if (nofail)
|
||||
return false;
|
||||
fprintf(stderr, "vector too large\n");
|
||||
abort();
|
||||
}
|
||||
if (nofail)
|
||||
return false;
|
||||
fprintf(stderr, "elemental_vector::increase_capacity: vector too large\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
const size_t desired_size = element_size * new_capacity;
|
||||
const uint64_t desired_size_u64 = (uint64_t)element_size * new_capacity;
|
||||
|
||||
const size_t desired_size = (size_t)desired_size_u64;
|
||||
if (desired_size_u64 != desired_size)
|
||||
{
|
||||
if (nofail)
|
||||
return false;
|
||||
fprintf(stderr, "elemental_vector::increase_capacity: vector too large\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
size_t actual_size = 0;
|
||||
if (!pMover)
|
||||
{
|
||||
|
|
@ -46,11 +53,7 @@ namespace basisu
|
|||
return false;
|
||||
|
||||
char buf[256];
|
||||
#ifdef _MSC_VER
|
||||
sprintf_s(buf, sizeof(buf), "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size);
|
||||
#else
|
||||
sprintf(buf, "vector: realloc() failed allocating %u bytes", (uint32_t)desired_size);
|
||||
#endif
|
||||
snprintf(buf, sizeof(buf), "elemental_vector::increase_capacity: realloc() failed allocating %zu bytes", desired_size);
|
||||
fprintf(stderr, "%s", buf);
|
||||
abort();
|
||||
}
|
||||
|
|
@ -75,11 +78,7 @@ namespace basisu
|
|||
return false;
|
||||
|
||||
char buf[256];
|
||||
#ifdef _MSC_VER
|
||||
sprintf_s(buf, sizeof(buf), "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size);
|
||||
#else
|
||||
sprintf(buf, "vector: malloc() failed allocating %u bytes", (uint32_t)desired_size);
|
||||
#endif
|
||||
snprintf(buf, sizeof(buf), "elemental_vector::increase_capacity: malloc() failed allocating %zu bytes", desired_size);
|
||||
fprintf(stderr, "%s", buf);
|
||||
abort();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basis_file_headers.h
|
||||
// Copyright (C) 2019-2020 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
@ -89,7 +89,8 @@ namespace basist
|
|||
enum class basis_tex_format
|
||||
{
|
||||
cETC1S = 0,
|
||||
cUASTC4x4 = 1
|
||||
cUASTC4x4 = 1,
|
||||
cUASTC_HDR_4x4 = 2
|
||||
};
|
||||
|
||||
struct basis_file_header
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_transcoder.h
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
// Set BASISU_FORCE_DEVEL_MESSAGES to 1 to enable debug printf()'s whenever an error occurs, for easier debugging during development.
|
||||
#ifndef BASISU_FORCE_DEVEL_MESSAGES
|
||||
// TODO - disable before checking in
|
||||
#define BASISU_FORCE_DEVEL_MESSAGES 0
|
||||
#endif
|
||||
|
||||
|
|
@ -55,7 +56,7 @@ namespace basist
|
|||
cTFETC2_RGBA = 1, // Opaque+alpha, ETC2_EAC_A8 block followed by a ETC1 block, alpha channel will be opaque for opaque .basis files
|
||||
|
||||
// BC1-5, BC7 (desktop, some mobile devices)
|
||||
cTFBC1_RGB = 2, // Opaque only, no punchthrough alpha support yet, transcodes alpha slice if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
|
||||
cTFBC1_RGB = 2, // Opaque only, no punchthrough alpha support yet, transcodes alpha slice if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
|
||||
cTFBC3_RGBA = 3, // Opaque+alpha, BC4 followed by a BC1 block, alpha channel will be opaque for opaque .basis files
|
||||
cTFBC4_R = 4, // Red only, alpha slice is transcoded to output if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified
|
||||
cTFBC5_RG = 5, // XY: Two BC4 blocks, X=R and Y=Alpha, .basis file should have alpha data (if not Y will be all 255's)
|
||||
|
|
@ -63,10 +64,11 @@ namespace basist
|
|||
|
||||
// PVRTC1 4bpp (mobile, PowerVR devices)
|
||||
cTFPVRTC1_4_RGB = 8, // Opaque only, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified, nearly lowest quality of any texture format.
|
||||
cTFPVRTC1_4_RGBA = 9, // Opaque+alpha, most useful for simple opacity maps. If .basis file doesn't have alpha cTFPVRTC1_4_RGB will be used instead. Lowest quality of any supported texture format.
|
||||
cTFPVRTC1_4_RGBA = 9, // Opaque+alpha, most useful for simple opacity maps. If .basis file doesn't have alpha cTFPVRTC1_4_RGB will be used instead. Lowest quality of any supported texture format.
|
||||
|
||||
// ASTC (mobile, Intel devices, hopefully all desktop GPU's one day)
|
||||
cTFASTC_4x4_RGBA = 10, // Opaque+alpha, ASTC 4x4, alpha channel will be opaque for opaque .basis files. Transcoder uses RGB/RGBA/L/LA modes, void extent, and up to two ([0,47] and [0,255]) endpoint precisions.
|
||||
cTFASTC_4x4_RGBA = 10, // LDR. Opaque+alpha, ASTC 4x4, alpha channel will be opaque for opaque .basis files.
|
||||
// LDR: Transcoder uses RGB/RGBA/L/LA modes, void extent, and up to two ([0,47] and [0,255]) endpoint precisions.
|
||||
|
||||
// ATC (mobile, Adreno devices, this is a niche format)
|
||||
cTFATC_RGB = 11, // Opaque, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified. ATI ATC (GL_ATC_RGB_AMD)
|
||||
|
|
@ -74,8 +76,8 @@ namespace basist
|
|||
|
||||
// FXT1 (desktop, Intel devices, this is a super obscure format)
|
||||
cTFFXT1_RGB = 17, // Opaque only, uses exclusively CC_MIXED blocks. Notable for having a 8x4 block size. GL_3DFX_texture_compression_FXT1 is supported on Intel integrated GPU's (such as HD 630).
|
||||
// Punch-through alpha is relatively easy to support, but full alpha is harder. This format is only here for completeness so opaque-only is fine for now.
|
||||
// See the BASISU_USE_ORIGINAL_3DFX_FXT1_ENCODING macro in basisu_transcoder_internal.h.
|
||||
// Punch-through alpha is relatively easy to support, but full alpha is harder. This format is only here for completeness so opaque-only is fine for now.
|
||||
// See the BASISU_USE_ORIGINAL_3DFX_FXT1_ENCODING macro in basisu_transcoder_internal.h.
|
||||
|
||||
cTFPVRTC2_4_RGB = 18, // Opaque-only, almost BC1 quality, much faster to transcode and supports arbitrary texture dimensions (unlike PVRTC1 RGB).
|
||||
cTFPVRTC2_4_RGBA = 19, // Opaque+alpha, slower to encode than cTFPVRTC2_4_RGB. Premultiplied alpha is highly recommended, otherwise the color channel can leak into the alpha channel on transparent blocks.
|
||||
|
|
@ -83,13 +85,22 @@ namespace basist
|
|||
cTFETC2_EAC_R11 = 20, // R only (ETC2 EAC R11 unsigned)
|
||||
cTFETC2_EAC_RG11 = 21, // RG only (ETC2 EAC RG11 unsigned), R=opaque.r, G=alpha - for tangent space normal maps
|
||||
|
||||
cTFBC6H = 22, // HDR, RGB only, unsigned
|
||||
cTFASTC_HDR_4x4_RGBA = 23, // HDR, RGBA (currently UASTC HDR is only RGB), unsigned
|
||||
|
||||
// Uncompressed (raw pixel) formats
|
||||
// Note these uncompressed formats (RGBA32, 565, and 4444) can only be transcoded to from LDR input files (ETC1S or UASTC LDR).
|
||||
cTFRGBA32 = 13, // 32bpp RGBA image stored in raster (not block) order in memory, R is first byte, A is last byte.
|
||||
cTFRGB565 = 14, // 16bpp RGB image stored in raster (not block) order in memory, R at bit position 11
|
||||
cTFBGR565 = 15, // 16bpp RGB image stored in raster (not block) order in memory, R at bit position 0
|
||||
cTFRGBA4444 = 16, // 16bpp RGBA image stored in raster (not block) order in memory, R at bit position 12, A at bit position 0
|
||||
cTFRGBA4444 = 16, // 16bpp RGBA image stored in raster (not block) order in memory, R at bit position 12, A at bit position 0
|
||||
|
||||
// Note these uncompressed formats (HALF and 9E5) can only be transcoded to from HDR input files (UASTC HDR).
|
||||
cTFRGB_HALF = 24, // 48bpp RGB half (16-bits/component, 3 components)
|
||||
cTFRGBA_HALF = 25, // 64bpp RGBA half (16-bits/component, 4 components) (A will always currently 1.0, UASTC_HDR doesn't support alpha)
|
||||
cTFRGB_9E5 = 26, // 32bpp RGB 9E5 (shared exponent, positive only, see GL_EXT_texture_shared_exponent)
|
||||
|
||||
cTFTotalTextureFormats = 22,
|
||||
cTFTotalTextureFormats = 27,
|
||||
|
||||
// Old enums for compatibility with code compiled against previous versions
|
||||
cTFETC1 = cTFETC1_RGB,
|
||||
|
|
@ -124,6 +135,9 @@ namespace basist
|
|||
// Returns true if the format supports an alpha channel.
|
||||
bool basis_transcoder_format_has_alpha(transcoder_texture_format fmt);
|
||||
|
||||
// Returns true if the format is HDR.
|
||||
bool basis_transcoder_format_is_hdr(transcoder_texture_format fmt);
|
||||
|
||||
// Returns the basisu::texture_format corresponding to the specified transcoder_texture_format.
|
||||
basisu::texture_format basis_get_basisu_texture_format(transcoder_texture_format fmt);
|
||||
|
||||
|
|
@ -142,7 +156,7 @@ namespace basist
|
|||
// Returns the block height for the specified texture format, which is currently always 4.
|
||||
uint32_t basis_get_block_height(transcoder_texture_format tex_type);
|
||||
|
||||
// Returns true if the specified format was enabled at compile time.
|
||||
// Returns true if the specified format was enabled at compile time, and is supported for the specific basis/ktx2 texture format (ETC1S, UASTC, or UASTC HDR).
|
||||
bool basis_is_format_supported(transcoder_texture_format tex_type, basis_tex_format fmt = basis_tex_format::cETC1S);
|
||||
|
||||
// Validates that the output buffer is large enough to hold the entire transcoded texture.
|
||||
|
|
@ -317,6 +331,42 @@ namespace basist
|
|||
int channel0 = -1, int channel1 = -1);
|
||||
};
|
||||
|
||||
class basisu_lowlevel_uastc_hdr_transcoder
|
||||
{
|
||||
friend class basisu_transcoder;
|
||||
|
||||
public:
|
||||
basisu_lowlevel_uastc_hdr_transcoder();
|
||||
|
||||
bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt,
|
||||
uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, bool has_alpha, const uint32_t orig_width, const uint32_t orig_height, uint32_t output_row_pitch_in_blocks_or_pixels = 0,
|
||||
basisu_transcoder_state* pState = nullptr, uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1, uint32_t decode_flags = 0);
|
||||
|
||||
bool transcode_slice(void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, const uint8_t* pImage_data, uint32_t image_data_size, block_format fmt,
|
||||
uint32_t output_block_or_pixel_stride_in_bytes, bool bc1_allow_threecolor_blocks, const basis_file_header& header, const basis_slice_desc& slice_desc, uint32_t output_row_pitch_in_blocks_or_pixels = 0,
|
||||
basisu_transcoder_state* pState = nullptr, uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1, uint32_t decode_flags = 0)
|
||||
{
|
||||
return transcode_slice(pDst_blocks, num_blocks_x, num_blocks_y, pImage_data, image_data_size, fmt,
|
||||
output_block_or_pixel_stride_in_bytes, bc1_allow_threecolor_blocks, (header.m_flags & cBASISHeaderFlagHasAlphaSlices) != 0, slice_desc.m_orig_width, slice_desc.m_orig_height, output_row_pitch_in_blocks_or_pixels,
|
||||
pState, output_rows_in_pixels, channel0, channel1, decode_flags);
|
||||
}
|
||||
|
||||
// Container independent transcoding
|
||||
bool transcode_image(
|
||||
transcoder_texture_format target_format,
|
||||
void* pOutput_blocks, uint32_t output_blocks_buf_size_in_blocks_or_pixels,
|
||||
const uint8_t* pCompressed_data, uint32_t compressed_data_length,
|
||||
uint32_t num_blocks_x, uint32_t num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
|
||||
uint32_t slice_offset, uint32_t slice_length,
|
||||
uint32_t decode_flags = 0,
|
||||
bool has_alpha = false,
|
||||
bool is_video = false,
|
||||
uint32_t output_row_pitch_in_blocks_or_pixels = 0,
|
||||
basisu_transcoder_state* pState = nullptr,
|
||||
uint32_t output_rows_in_pixels = 0,
|
||||
int channel0 = -1, int channel1 = -1);
|
||||
};
|
||||
|
||||
struct basisu_slice_info
|
||||
{
|
||||
uint32_t m_orig_width;
|
||||
|
|
@ -530,6 +580,7 @@ namespace basist
|
|||
private:
|
||||
mutable basisu_lowlevel_etc1s_transcoder m_lowlevel_etc1s_decoder;
|
||||
mutable basisu_lowlevel_uastc_transcoder m_lowlevel_uastc_decoder;
|
||||
mutable basisu_lowlevel_uastc_hdr_transcoder m_lowlevel_uastc_hdr_decoder;
|
||||
|
||||
bool m_ready_to_transcode;
|
||||
|
||||
|
|
@ -612,10 +663,12 @@ namespace basist
|
|||
#pragma pack(pop)
|
||||
|
||||
const uint32_t KTX2_VK_FORMAT_UNDEFINED = 0;
|
||||
const uint32_t KTX2_FORMAT_UASTC_4x4_SFLOAT_BLOCK = 1000066000; // TODO, is this correct?
|
||||
const uint32_t KTX2_KDF_DF_MODEL_UASTC = 166;
|
||||
const uint32_t KTX2_KDF_DF_MODEL_UASTC_HDR = 167;
|
||||
const uint32_t KTX2_KDF_DF_MODEL_ETC1S = 163;
|
||||
const uint32_t KTX2_IMAGE_IS_P_FRAME = 2;
|
||||
const uint32_t KTX2_UASTC_BLOCK_SIZE = 16;
|
||||
const uint32_t KTX2_UASTC_BLOCK_SIZE = 16; // also the block size for UASTC_HDR
|
||||
const uint32_t KTX2_MAX_SUPPORTED_LEVEL_COUNT = 16; // this is an implementation specific constraint and can be increased
|
||||
|
||||
// The KTX2 transfer functions supported by KTX2
|
||||
|
|
@ -800,13 +853,15 @@ namespace basist
|
|||
// Returns 0 or the number of layers in the texture array or texture video. Valid after init().
|
||||
uint32_t get_layers() const { return m_header.m_layer_count; }
|
||||
|
||||
// Returns cETC1S or cUASTC4x4. Valid after init().
|
||||
// Returns cETC1S, cUASTC4x4, or cUASTC_HDR_4x4. Valid after init().
|
||||
basist::basis_tex_format get_format() const { return m_format; }
|
||||
|
||||
|
||||
bool is_etc1s() const { return get_format() == basist::basis_tex_format::cETC1S; }
|
||||
|
||||
bool is_uastc() const { return get_format() == basist::basis_tex_format::cUASTC4x4; }
|
||||
|
||||
bool is_hdr() const { return get_format() == basist::basis_tex_format::cUASTC_HDR_4x4; }
|
||||
|
||||
// Returns true if the ETC1S file has two planes (typically RGBA, or RRRG), or true if the UASTC file has alpha data. Valid after init().
|
||||
uint32_t get_has_alpha() const { return m_has_alpha; }
|
||||
|
||||
|
|
@ -913,6 +968,7 @@ namespace basist
|
|||
|
||||
basist::basisu_lowlevel_etc1s_transcoder m_etc1s_transcoder;
|
||||
basist::basisu_lowlevel_uastc_transcoder m_uastc_transcoder;
|
||||
basist::basisu_lowlevel_uastc_hdr_transcoder m_uastc_hdr_transcoder;
|
||||
|
||||
ktx2_transcoder_state m_def_transcoder_state;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// basisu_transcoder_internal.h - Universal texture format transcoder library.
|
||||
// Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Important: If compiling with gcc, be sure strict aliasing is disabled: -fno-strict-aliasing
|
||||
//
|
||||
|
|
@ -20,8 +20,9 @@
|
|||
#pragma warning (disable: 4127) // conditional expression is constant
|
||||
#endif
|
||||
|
||||
#define BASISD_LIB_VERSION 116
|
||||
#define BASISD_VERSION_STRING "01.16"
|
||||
// v1.50: Added UASTC HDR support
|
||||
#define BASISD_LIB_VERSION 150
|
||||
#define BASISD_VERSION_STRING "01.50"
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define BASISD_BUILD_DEBUG
|
||||
|
|
@ -82,9 +83,15 @@ namespace basist
|
|||
cRGBA4444_ALPHA,
|
||||
cRGBA4444_COLOR_OPAQUE,
|
||||
cRGBA4444,
|
||||
cRGBA_HALF,
|
||||
cRGB_HALF,
|
||||
cRGB_9E5,
|
||||
|
||||
cUASTC_4x4,
|
||||
|
||||
cUASTC_4x4, // LDR, universal
|
||||
cUASTC_HDR_4x4, // HDR, transcodes only to 4x4 HDR ASTC, BC6H, or uncompressed
|
||||
cBC6H,
|
||||
cASTC_HDR_4x4,
|
||||
|
||||
cTotalBlockFormats
|
||||
};
|
||||
|
||||
|
|
@ -264,8 +271,8 @@ namespace basist
|
|||
}
|
||||
|
||||
const basisu::uint8_vec &get_code_sizes() const { return m_code_sizes; }
|
||||
const basisu::int_vec get_lookup() const { return m_lookup; }
|
||||
const basisu::int16_vec get_tree() const { return m_tree; }
|
||||
const basisu::int_vec &get_lookup() const { return m_lookup; }
|
||||
const basisu::int16_vec &get_tree() const { return m_tree; }
|
||||
|
||||
bool is_valid() const { return m_code_sizes.size() > 0; }
|
||||
|
||||
|
|
@ -789,7 +796,198 @@ namespace basist
|
|||
};
|
||||
|
||||
bool basis_block_format_is_uncompressed(block_format tex_type);
|
||||
|
||||
|
||||
//------------------------------------
|
||||
|
||||
typedef uint16_t half_float;
|
||||
|
||||
const double MIN_DENORM_HALF_FLOAT = 0.000000059604645; // smallest positive subnormal number
|
||||
const double MIN_HALF_FLOAT = 0.00006103515625; // smallest positive normal number
|
||||
const double MAX_HALF_FLOAT = 65504.0; // largest normal number
|
||||
|
||||
inline uint32_t get_bits(uint32_t val, int low, int high)
|
||||
{
|
||||
const int num_bits = (high - low) + 1;
|
||||
assert((num_bits >= 1) && (num_bits <= 32));
|
||||
|
||||
val >>= low;
|
||||
if (num_bits != 32)
|
||||
val &= ((1u << num_bits) - 1);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
inline bool is_half_inf_or_nan(half_float v)
|
||||
{
|
||||
return get_bits(v, 10, 14) == 31;
|
||||
}
|
||||
|
||||
inline bool is_half_denorm(half_float v)
|
||||
{
|
||||
int e = (v >> 10) & 31;
|
||||
return !e;
|
||||
}
|
||||
|
||||
inline int get_half_exp(half_float v)
|
||||
{
|
||||
int e = ((v >> 10) & 31);
|
||||
return e ? (e - 15) : -14;
|
||||
}
|
||||
|
||||
inline int get_half_mantissa(half_float v)
|
||||
{
|
||||
if (is_half_denorm(v))
|
||||
return v & 0x3FF;
|
||||
return (v & 0x3FF) | 0x400;
|
||||
}
|
||||
|
||||
inline float get_half_mantissaf(half_float v)
|
||||
{
|
||||
return ((float)get_half_mantissa(v)) / 1024.0f;
|
||||
}
|
||||
|
||||
inline int get_half_sign(half_float v)
|
||||
{
|
||||
return v ? ((v & 0x8000) ? -1 : 1) : 0;
|
||||
}
|
||||
|
||||
inline bool half_is_signed(half_float v)
|
||||
{
|
||||
return (v & 0x8000) != 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int hexp = get_half_exp(Cf);
|
||||
float hman = get_half_mantissaf(Cf);
|
||||
int hsign = get_half_sign(Cf);
|
||||
float k = powf(2.0f, hexp) * hman * hsign;
|
||||
if (is_half_inf_or_nan(Cf))
|
||||
k = std::numeric_limits<float>::quiet_NaN();
|
||||
#endif
|
||||
|
||||
half_float float_to_half(float val);
|
||||
|
||||
inline float half_to_float(half_float hval)
|
||||
{
|
||||
union { float f; uint32_t u; } x = { 0 };
|
||||
|
||||
uint32_t s = ((uint32_t)hval >> 15) & 1;
|
||||
uint32_t e = ((uint32_t)hval >> 10) & 0x1F;
|
||||
uint32_t m = (uint32_t)hval & 0x3FF;
|
||||
|
||||
if (!e)
|
||||
{
|
||||
if (!m)
|
||||
{
|
||||
// +- 0
|
||||
x.u = s << 31;
|
||||
return x.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// denormalized
|
||||
while (!(m & 0x00000400))
|
||||
{
|
||||
m <<= 1;
|
||||
--e;
|
||||
}
|
||||
|
||||
++e;
|
||||
m &= ~0x00000400;
|
||||
}
|
||||
}
|
||||
else if (e == 31)
|
||||
{
|
||||
if (m == 0)
|
||||
{
|
||||
// +/- INF
|
||||
x.u = (s << 31) | 0x7f800000;
|
||||
return x.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// +/- NaN
|
||||
x.u = (s << 31) | 0x7f800000 | (m << 13);
|
||||
return x.f;
|
||||
}
|
||||
}
|
||||
|
||||
e = e + (127 - 15);
|
||||
m = m << 13;
|
||||
|
||||
assert(s <= 1);
|
||||
assert(m <= 0x7FFFFF);
|
||||
assert(e <= 255);
|
||||
|
||||
x.u = m | (e << 23) | (s << 31);
|
||||
return x.f;
|
||||
}
|
||||
|
||||
// Originally from bc6h_enc.h
|
||||
|
||||
void bc6h_enc_init();
|
||||
|
||||
const uint32_t MAX_BLOG16_VAL = 0xFFFF;
|
||||
|
||||
// BC6H internals
|
||||
const uint32_t NUM_BC6H_MODES = 14;
|
||||
const uint32_t BC6H_LAST_MODE_INDEX = 13;
|
||||
const uint32_t BC6H_FIRST_1SUBSET_MODE_INDEX = 10; // in the MS docs, this is "mode 11" (where the first mode is 1), 60 bits for endpoints (10.10, 10.10, 10.10), 63 bits for weights
|
||||
const uint32_t TOTAL_BC6H_PARTITION_PATTERNS = 32;
|
||||
|
||||
extern const uint8_t g_bc6h_mode_sig_bits[NUM_BC6H_MODES][4]; // base, r, g, b
|
||||
|
||||
struct bc6h_bit_layout
|
||||
{
|
||||
int8_t m_comp; // R=0,G=1,B=2,D=3 (D=partition index)
|
||||
int8_t m_index; // 0-3, 0-1 Low/High subset 1, 2-3 Low/High subset 2, -1=partition index (d)
|
||||
int8_t m_last_bit;
|
||||
int8_t m_first_bit; // may be -1 if a single bit, may be >m_last_bit if reversed
|
||||
};
|
||||
|
||||
const uint32_t MAX_BC6H_LAYOUT_INDEX = 25;
|
||||
extern const bc6h_bit_layout g_bc6h_bit_layouts[NUM_BC6H_MODES][MAX_BC6H_LAYOUT_INDEX];
|
||||
|
||||
extern const uint8_t g_bc6h_2subset_patterns[TOTAL_BC6H_PARTITION_PATTERNS][4][4]; // [y][x]
|
||||
|
||||
extern const uint8_t g_bc6h_weight3[8];
|
||||
extern const uint8_t g_bc6h_weight4[16];
|
||||
|
||||
extern const int8_t g_bc6h_mode_lookup[32];
|
||||
|
||||
// Converts b16 to half float
|
||||
inline half_float bc6h_blog16_to_half(uint32_t comp)
|
||||
{
|
||||
assert(comp <= 0xFFFF);
|
||||
|
||||
// scale the magnitude by 31/64
|
||||
comp = (comp * 31u) >> 6u;
|
||||
return (half_float)comp;
|
||||
}
|
||||
|
||||
const uint32_t MAX_BC6H_HALF_FLOAT_AS_UINT = 0x7BFF;
|
||||
|
||||
// Inverts bc6h_blog16_to_half().
|
||||
// Returns the nearest blog16 given a half value.
|
||||
inline uint32_t bc6h_half_to_blog16(half_float h)
|
||||
{
|
||||
assert(h <= MAX_BC6H_HALF_FLOAT_AS_UINT);
|
||||
return (h * 64 + 30) / 31;
|
||||
}
|
||||
|
||||
struct bc6h_block
|
||||
{
|
||||
uint8_t m_bytes[16];
|
||||
};
|
||||
|
||||
void bc6h_enc_block_mode10(bc6h_block* pPacked_block, const half_float pEndpoints[3][2], const uint8_t* pWeights);
|
||||
void bc6h_enc_block_1subset_4bit_weights(bc6h_block* pPacked_block, const half_float pEndpoints[3][2], const uint8_t* pWeights);
|
||||
void bc6h_enc_block_1subset_mode9_3bit_weights(bc6h_block* pPacked_block, const half_float pEndpoints[3][2], const uint8_t* pWeights);
|
||||
void bc6h_enc_block_1subset_3bit_weights(bc6h_block* pPacked_block, const half_float pEndpoints[3][2], const uint8_t* pWeights);
|
||||
void bc6h_enc_block_2subset_mode9_3bit_weights(bc6h_block* pPacked_block, uint32_t common_part_index, const half_float pEndpoints[2][3][2], const uint8_t* pWeights); // pEndpoints[subset][comp][lh_index]
|
||||
void bc6h_enc_block_2subset_3bit_weights(bc6h_block* pPacked_block, uint32_t common_part_index, const half_float pEndpoints[2][3][2], const uint8_t* pWeights); // pEndpoints[subset][comp][lh_index]
|
||||
bool bc6h_enc_block_solid_color(bc6h_block* pPacked_block, const half_float pColor[3]);
|
||||
|
||||
} // namespace basist
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2017-2019 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2017-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (C) 2017-2019 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2017-2024 Binomial LLC. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ namespace basist
|
|||
const uint32_t UASTC_MODE_INDEX_SOLID_COLOR = 8;
|
||||
|
||||
const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS2 = 30;
|
||||
const uint32_t TOTAL_ASTC_BC6H_COMMON_PARTITIONS2 = 27; // BC6H only supports only 5-bit pattern indices, BC7 supports 4-bit or 6-bit
|
||||
const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS3 = 11;
|
||||
const uint32_t TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS = 19;
|
||||
|
||||
|
|
|
|||
149
engine/thirdparty/certs/ca-certificates.crt
vendored
149
engine/thirdparty/certs/ca-certificates.crt
vendored
|
|
@ -1,7 +1,9 @@
|
|||
##
|
||||
## Bundle of CA Root Certificates
|
||||
##
|
||||
## Certificate data from Mozilla as of: Mon Mar 11 15:15:21 2024 GMT
|
||||
## Certificate data from Mozilla as of: Sat Oct 19 21:26:09 2024 GMT
|
||||
##
|
||||
## Find updated versions here: https://curl.se/docs/caextract.html
|
||||
##
|
||||
## This is a bundle of X.509 certificates of public Certificate Authorities
|
||||
## (CA). These were automatically extracted from Mozilla's root certificates
|
||||
|
|
@ -14,7 +16,7 @@
|
|||
## Just configure this file as the SSLCACertificateFile.
|
||||
##
|
||||
## Conversion done with mk-ca-bundle.pl version 1.29.
|
||||
## SHA256: 4d96bd539f4719e9ace493757afbe4a23ee8579de1c97fbebc50bba3c12e8c1e
|
||||
## SHA256: 36105b01631f9fc03b1eca779b44a30a1a5890b9bf8dc07ccb001a07301e01cf
|
||||
##
|
||||
|
||||
|
||||
|
|
@ -2600,36 +2602,6 @@ vLtoURMMA/cVi4RguYv/Uo7njLwcAjA8+RHUjE7AwWHCFUyqqx0LMV87HOIAl0Qx5v5zli/altP+
|
|||
CAezNIm8BZ/3Hobui3A=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
GLOBALTRUST 2020
|
||||
================
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFgjCCA2qgAwIBAgILWku9WvtPilv6ZeUwDQYJKoZIhvcNAQELBQAwTTELMAkGA1UEBhMCQVQx
|
||||
IzAhBgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVT
|
||||
VCAyMDIwMB4XDTIwMDIxMDAwMDAwMFoXDTQwMDYxMDAwMDAwMFowTTELMAkGA1UEBhMCQVQxIzAh
|
||||
BgNVBAoTGmUtY29tbWVyY2UgbW9uaXRvcmluZyBHbWJIMRkwFwYDVQQDExBHTE9CQUxUUlVTVCAy
|
||||
MDIwMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAri5WrRsc7/aVj6B3GyvTY4+ETUWi
|
||||
D59bRatZe1E0+eyLinjF3WuvvcTfk0Uev5E4C64OFudBc/jbu9G4UeDLgztzOG53ig9ZYybNpyrO
|
||||
VPu44sB8R85gfD+yc/LAGbaKkoc1DZAoouQVBGM+uq/ufF7MpotQsjj3QWPKzv9pj2gOlTblzLmM
|
||||
CcpL3TGQlsjMH/1WljTbjhzqLL6FLmPdqqmV0/0plRPwyJiT2S0WR5ARg6I6IqIoV6Lr/sCMKKCm
|
||||
fecqQjuCgGOlYx8ZzHyyZqjC0203b+J+BlHZRYQfEs4kUmSFC0iAToexIiIwquuuvuAC4EDosEKA
|
||||
A1GqtH6qRNdDYfOiaxaJSaSjpCuKAsR49GiKweR6NrFvG5Ybd0mN1MkGco/PU+PcF4UgStyYJ9OR
|
||||
JitHHmkHr96i5OTUawuzXnzUJIBHKWk7buis/UDr2O1xcSvy6Fgd60GXIsUf1DnQJ4+H4xj04KlG
|
||||
DfV0OoIu0G4skaMxXDtG6nsEEFZegB31pWXogvziB4xiRfUg3kZwhqG8k9MedKZssCz3AwyIDMvU
|
||||
clOGvGBG85hqwvG/Q/lwIHfKN0F5VVJjjVsSn8VoxIidrPIwq7ejMZdnrY8XD2zHc+0klGvIg5rQ
|
||||
mjdJBKuxFshsSUktq6HQjJLyQUp5ISXbY9e2nKd+Qmn7OmMCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
|
||||
AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFNwuH9FhN3nkq9XVsxJxaD1qaJwiMB8GA1Ud
|
||||
IwQYMBaAFNwuH9FhN3nkq9XVsxJxaD1qaJwiMA0GCSqGSIb3DQEBCwUAA4ICAQCR8EICaEDuw2jA
|
||||
VC/f7GLDw56KoDEoqoOOpFaWEhCGVrqXctJUMHytGdUdaG/7FELYjQ7ztdGl4wJCXtzoRlgHNQIw
|
||||
4Lx0SsFDKv/bGtCwr2zD/cuz9X9tAy5ZVp0tLTWMstZDFyySCstd6IwPS3BD0IL/qMy/pJTAvoe9
|
||||
iuOTe8aPmxadJ2W8esVCgmxcB9CpwYhgROmYhRZf+I/KARDOJcP5YBugxZfD0yyIMaK9MOzQ0MAS
|
||||
8cE54+X1+NZK3TTN+2/BT+MAi1bikvcoskJ3ciNnxz8RFbLEAwW+uxF7Cr+obuf/WEPPm2eggAe2
|
||||
HcqtbepBEX4tdJP7wry+UUTF72glJ4DjyKDUEuzZpTcdN3y0kcra1LGWge9oXHYQSa9+pTeAsRxS
|
||||
vTOBTI/53WXZFM2KJVj04sWDpQmQ1GwUY7VA3+vA/MRYfg0UFodUJ25W5HCEuGwyEn6CMUO+1918
|
||||
oa2u1qsgEu8KwxCMSZY13At1XrFP1U80DhEgB3VDRemjEdqso5nCtnkn4rnvyOL2NSl6dPrFf4IF
|
||||
YqYK6miyeUcGbvJXqBUzxvd4Sj1Ce2t+/vdG6tHrju+IaFvowdlxfv1k7/9nR4hYJS8+hge9+6jl
|
||||
gqispdNpQ80xiEmEU5LAsTkbOYMBMMTyqfrQA71yN2BWHzZ8vTmR9W0Nv3vXkg==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
ANF Secure Server Root CA
|
||||
=========================
|
||||
-----BEGIN CERTIFICATE-----
|
||||
|
|
@ -3579,3 +3551,116 @@ wPfc5+pbrrLMtTWGS9DiP7bY+A4A7l3j941Y/8+LN+ljX273CXE2whJdV/LItM3z7gLfEdxquVeE
|
|||
HVlNjM7IDiPCtyaaEBRx/pOyiriA8A4QntOoUAw3gi/q4Iqd4Sw5/7W0cwDk90imc6y/st53BIe0
|
||||
o82bNSQ3+pCTE4FCxpgmdTdmQRCsu/WU48IxK63nI1bMNSWSs1A=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
FIRMAPROFESIONAL CA ROOT-A WEB
|
||||
==============================
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICejCCAgCgAwIBAgIQMZch7a+JQn81QYehZ1ZMbTAKBggqhkjOPQQDAzBuMQswCQYDVQQGEwJF
|
||||
UzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25hbCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4
|
||||
MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFMIENBIFJPT1QtQSBXRUIwHhcNMjIwNDA2MDkwMTM2
|
||||
WhcNNDcwMzMxMDkwMTM2WjBuMQswCQYDVQQGEwJFUzEcMBoGA1UECgwTRmlybWFwcm9mZXNpb25h
|
||||
bCBTQTEYMBYGA1UEYQwPVkFURVMtQTYyNjM0MDY4MScwJQYDVQQDDB5GSVJNQVBST0ZFU0lPTkFM
|
||||
IENBIFJPT1QtQSBXRUIwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARHU+osEaR3xyrq89Zfe9MEkVz6
|
||||
iMYiuYMQYneEMy3pA4jU4DP37XcsSmDq5G+tbbT4TIqk5B/K6k84Si6CcyvHZpsKjECcfIr28jlg
|
||||
st7L7Ljkb+qbXbdTkBgyVcUgt5SjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUk+FD
|
||||
Y1w8ndYn81LsF7Kpryz3dvgwHQYDVR0OBBYEFJPhQ2NcPJ3WJ/NS7Beyqa8s93b4MA4GA1UdDwEB
|
||||
/wQEAwIBBjAKBggqhkjOPQQDAwNoADBlAjAdfKR7w4l1M+E7qUW/Runpod3JIha3RxEL2Jq68cgL
|
||||
cFBTApFwhVmpHqTm6iMxoAACMQD94vizrxa5HnPEluPBMBnYfubDl94cT7iJLzPrSA8Z94dGXSaQ
|
||||
pYXFuXqUPoeovQA=
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
TWCA CYBER Root CA
|
||||
==================
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFjTCCA3WgAwIBAgIQQAE0jMIAAAAAAAAAATzyxjANBgkqhkiG9w0BAQwFADBQMQswCQYDVQQG
|
||||
EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB
|
||||
IENZQkVSIFJvb3QgQ0EwHhcNMjIxMTIyMDY1NDI5WhcNNDcxMTIyMTU1OTU5WjBQMQswCQYDVQQG
|
||||
EwJUVzESMBAGA1UEChMJVEFJV0FOLUNBMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJUV0NB
|
||||
IENZQkVSIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDG+Moe2Qkgfh1s
|
||||
Ts6P40czRJzHyWmqOlt47nDSkvgEs1JSHWdyKKHfi12VCv7qze33Kc7wb3+szT3vsxxFavcokPFh
|
||||
V8UMxKNQXd7UtcsZyoC5dc4pztKFIuwCY8xEMCDa6pFbVuYdHNWdZsc/34bKS1PE2Y2yHer43CdT
|
||||
o0fhYcx9tbD47nORxc5zb87uEB8aBs/pJ2DFTxnk684iJkXXYJndzk834H/nY62wuFm40AZoNWDT
|
||||
Nq5xQwTxaWV4fPMf88oon1oglWa0zbfuj3ikRRjpJi+NmykosaS3Om251Bw4ckVYsV7r8Cibt4LK
|
||||
/c/WMw+f+5eesRycnupfXtuq3VTpMCEobY5583WSjCb+3MX2w7DfRFlDo7YDKPYIMKoNM+HvnKkH
|
||||
IuNZW0CP2oi3aQiotyMuRAlZN1vH4xfyIutuOVLF3lSnmMlLIJXcRolftBL5hSmO68gnFSDAS9TM
|
||||
fAxsNAwmmyYxpjyn9tnQS6Jk/zuZQXLB4HCX8SS7K8R0IrGsayIyJNN4KsDAoS/xUgXJP+92ZuJF
|
||||
2A09rZXIx4kmyA+upwMu+8Ff+iDhcK2wZSA3M2Cw1a/XDBzCkHDXShi8fgGwsOsVHkQGzaRP6AzR
|
||||
wyAQ4VRlnrZR0Bp2a0JaWHY06rc3Ga4udfmW5cFZ95RXKSWNOkyrTZpB0F8mAwIDAQABo2MwYTAO
|
||||
BgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBSdhWEUfMFib5do5E83
|
||||
QOGt4A1WNzAdBgNVHQ4EFgQUnYVhFHzBYm+XaORPN0DhreANVjcwDQYJKoZIhvcNAQEMBQADggIB
|
||||
AGSPesRiDrWIzLjHhg6hShbNcAu3p4ULs3a2D6f/CIsLJc+o1IN1KriWiLb73y0ttGlTITVX1olN
|
||||
c79pj3CjYcya2x6a4CD4bLubIp1dhDGaLIrdaqHXKGnK/nZVekZn68xDiBaiA9a5F/gZbG0jAn/x
|
||||
X9AKKSM70aoK7akXJlQKTcKlTfjF/biBzysseKNnTKkHmvPfXvt89YnNdJdhEGoHK4Fa0o635yDR
|
||||
IG4kqIQnoVesqlVYL9zZyvpoBJ7tRCT5dEA7IzOrg1oYJkK2bVS1FmAwbLGg+LhBoF1JSdJlBTrq
|
||||
/p1hvIbZv97Tujqxf36SNI7JAG7cmL3c7IAFrQI932XtCwP39xaEBDG6k5TY8hL4iuO/Qq+n1M0R
|
||||
FxbIQh0UqEL20kCGoE8jypZFVmAGzbdVAaYBlGX+bgUJurSkquLvWL69J1bY73NxW0Qz8ppy6rBe
|
||||
Pm6pUlvscG21h483XjyMnM7k8M4MZ0HMzvaAq07MTFb1wWFZk7Q+ptq4NxKfKjLji7gh7MMrZQzv
|
||||
It6IKTtM1/r+t+FHvpw+PoP7UV31aPcuIYXcv/Fa4nzXxeSDwWrruoBa3lwtcHb4yOWHh8qgnaHl
|
||||
IhInD0Q9HWzq1MKLL295q39QpsQZp6F6t5b5wR9iWqJDB0BeJsas7a5wFsWqynKKTbDPAYsDP27X
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
SecureSign Root CA12
|
||||
====================
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDcjCCAlqgAwIBAgIUZvnHwa/swlG07VOX5uaCwysckBYwDQYJKoZIhvcNAQELBQAwUTELMAkG
|
||||
A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT
|
||||
ZWN1cmVTaWduIFJvb3QgQ0ExMjAeFw0yMDA0MDgwNTM2NDZaFw00MDA0MDgwNTM2NDZaMFExCzAJ
|
||||
BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU
|
||||
U2VjdXJlU2lnbiBSb290IENBMTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6OcE3
|
||||
emhFKxS06+QT61d1I02PJC0W6K6OyX2kVzsqdiUzg2zqMoqUm048luT9Ub+ZyZN+v/mtp7JIKwcc
|
||||
J/VMvHASd6SFVLX9kHrko+RRWAPNEHl57muTH2SOa2SroxPjcf59q5zdJ1M3s6oYwlkm7Fsf0uZl
|
||||
fO+TvdhYXAvA42VvPMfKWeP+bl+sg779XSVOKik71gurFzJ4pOE+lEa+Ym6b3kaosRbnhW70CEBF
|
||||
EaCeVESE99g2zvVQR9wsMJvuwPWW0v4JhscGWa5Pro4RmHvzC1KqYiaqId+OJTN5lxZJjfU+1Uef
|
||||
NzFJM3IFTQy2VYzxV4+Kh9GtxRESOaCtAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
|
||||
AQH/BAQDAgEGMB0GA1UdDgQWBBRXNPN0zwRL1SXm8UC2LEzZLemgrTANBgkqhkiG9w0BAQsFAAOC
|
||||
AQEAPrvbFxbS8hQBICw4g0utvsqFepq2m2um4fylOqyttCg6r9cBg0krY6LdmmQOmFxv3Y67ilQi
|
||||
LUoT865AQ9tPkbeGGuwAtEGBpE/6aouIs3YIcipJQMPTw4WJmBClnW8Zt7vPemVV2zfrPIpyMpce
|
||||
mik+rY3moxtt9XUa5rBouVui7mlHJzWhhpmA8zNL4WukJsPvdFlseqJkth5Ew1DgDzk9qTPxpfPS
|
||||
vWKErI4cqc1avTc7bgoitPQV55FYxTpE05Uo2cBl6XLK0A+9H7MV2anjpEcJnuDLN/v9vZfVvhga
|
||||
aaI5gdka9at/yOPiZwud9AzqVN/Ssq+xIvEg37xEHA==
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
SecureSign Root CA14
|
||||
====================
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFcjCCA1qgAwIBAgIUZNtaDCBO6Ncpd8hQJ6JaJ90t8sswDQYJKoZIhvcNAQEMBQAwUTELMAkG
|
||||
A1UEBhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRT
|
||||
ZWN1cmVTaWduIFJvb3QgQ0ExNDAeFw0yMDA0MDgwNzA2MTlaFw00NTA0MDgwNzA2MTlaMFExCzAJ
|
||||
BgNVBAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMU
|
||||
U2VjdXJlU2lnbiBSb290IENBMTQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDF0nqh
|
||||
1oq/FjHQmNE6lPxauG4iwWL3pwon71D2LrGeaBLwbCRjOfHw3xDG3rdSINVSW0KZnvOgvlIfX8xn
|
||||
bacuUKLBl422+JX1sLrcneC+y9/3OPJH9aaakpUqYllQC6KxNedlsmGy6pJxaeQp8E+BgQQ8sqVb
|
||||
1MWoWWd7VRxJq3qdwudzTe/NCcLEVxLbAQ4jeQkHO6Lo/IrPj8BGJJw4J+CDnRugv3gVEOuGTgpa
|
||||
/d/aLIJ+7sr2KeH6caH3iGicnPCNvg9JkdjqOvn90Ghx2+m1K06Ckm9mH+Dw3EzsytHqunQG+bOE
|
||||
kJTRX45zGRBdAuVwpcAQ0BB8b8VYSbSwbprafZX1zNoCr7gsfXmPvkPx+SgojQlD+Ajda8iLLCSx
|
||||
jVIHvXiby8posqTdDEx5YMaZ0ZPxMBoH064iwurO8YQJzOAUbn8/ftKChazcqRZOhaBgy/ac18iz
|
||||
ju3Gm5h1DVXoX+WViwKkrkMpKBGk5hIwAUt1ax5mnXkvpXYvHUC0bcl9eQjs0Wq2XSqypWa9a4X0
|
||||
dFbD9ed1Uigspf9mR6XU/v6eVL9lfgHWMI+lNpyiUBzuOIABSMbHdPTGrMNASRZhdCyvjG817XsY
|
||||
AFs2PJxQDcqSMxDxJklt33UkN4Ii1+iW/RVLApY+B3KVfqs9TC7XyvDf4Fg/LS8EmjijAQIDAQAB
|
||||
o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUBpOjCl4oaTeq
|
||||
YR3r6/wtbyPk86AwDQYJKoZIhvcNAQEMBQADggIBAJaAcgkGfpzMkwQWu6A6jZJOtxEaCnFxEM0E
|
||||
rX+lRVAQZk5KQaID2RFPeje5S+LGjzJmdSX7684/AykmjbgWHfYfM25I5uj4V7Ibed87hwriZLoA
|
||||
ymzvftAj63iP/2SbNDefNWWipAA9EiOWWF3KY4fGoweITedpdopTzfFP7ELyk+OZpDc8h7hi2/Ds
|
||||
Hzc/N19DzFGdtfCXwreFamgLRB7lUe6TzktuhsHSDCRZNhqfLJGP4xjblJUK7ZGqDpncllPjYYPG
|
||||
FrojutzdfhrGe0K22VoF3Jpf1d+42kd92jjbrDnVHmtsKheMYc2xbXIBw8MgAGJoFjHVdqqGuw6q
|
||||
nsb58Nn4DSEC5MUoFlkRudlpcyqSeLiSV5sI8jrlL5WwWLdrIBRtFO8KvH7YVdiI2i/6GaX7i+B/
|
||||
OfVyK4XELKzvGUWSTLNhB9xNH27SgRNcmvMSZ4PPmz+Ln52kuaiWA3rF7iDeM9ovnhp6dB7h7sxa
|
||||
OgTdsxoEqBRjrLdHEoOabPXm6RUVkRqEGQ6UROcSjiVbgGcZ3GOTEAtlLor6CZpO2oYofaphNdgO
|
||||
pygau1LgePhsumywbrmHXumZNTfxPWQrqaA0k89jL9WB365jJ6UeTo3cKXhZ+PmhIIynJkBugnLN
|
||||
eLLIjzwec+fBH7/PzqUqm9tEZDKgu39cJRNItX+S
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
SecureSign Root CA15
|
||||
====================
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICIzCCAamgAwIBAgIUFhXHw9hJp75pDIqI7fBw+d23PocwCgYIKoZIzj0EAwMwUTELMAkGA1UE
|
||||
BhMCSlAxIzAhBgNVBAoTGkN5YmVydHJ1c3QgSmFwYW4gQ28uLCBMdGQuMR0wGwYDVQQDExRTZWN1
|
||||
cmVTaWduIFJvb3QgQ0ExNTAeFw0yMDA0MDgwODMyNTZaFw00NTA0MDgwODMyNTZaMFExCzAJBgNV
|
||||
BAYTAkpQMSMwIQYDVQQKExpDeWJlcnRydXN0IEphcGFuIENvLiwgTHRkLjEdMBsGA1UEAxMUU2Vj
|
||||
dXJlU2lnbiBSb290IENBMTUwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQLUHSNZDKZmbPSYAi4Io5G
|
||||
dCx4wCtELW1fHcmuS1Iggz24FG1Th2CeX2yF2wYUleDHKP+dX+Sq8bOLbe1PL0vJSpSRZHX+AezB
|
||||
2Ot6lHhWGENfa4HL9rzatAy2KZMIaY+jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
|
||||
AgEGMB0GA1UdDgQWBBTrQciu/NWeUUj1vYv0hyCTQSvT9DAKBggqhkjOPQQDAwNoADBlAjEA2S6J
|
||||
fl5OpBEHvVnCB96rMjhTKkZEBhd6zlHp4P9mLQlO4E/0BdGF9jVg3PVys0Z9AjBEmEYagoUeYWmJ
|
||||
SwdLZrWeqrqgHkHZAXQ6bkU6iYAZezKYVWOr62Nuk22rGwlgMU4=
|
||||
-----END CERTIFICATE-----
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 24 November 2023 *
|
||||
* Date : 12 May 2024 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2023 *
|
||||
* Copyright : Angus Johnson 2010-2024 *
|
||||
* Purpose : Core Clipper Library structures and functions *
|
||||
* License : http://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
|
|
@ -19,6 +19,7 @@
|
|||
#include <algorithm>
|
||||
#include <climits>
|
||||
#include <numeric>
|
||||
#include <optional>
|
||||
#include "clipper2/clipper.version.h"
|
||||
|
||||
#define CLIPPER2_THROW(exception) std::abort()
|
||||
|
|
@ -51,19 +52,19 @@ namespace Clipper2Lib
|
|||
|
||||
// error codes (2^n)
|
||||
const int precision_error_i = 1; // non-fatal
|
||||
const int scale_error_i = 2; // non-fatal
|
||||
const int non_pair_error_i = 4; // non-fatal
|
||||
const int undefined_error_i = 32; // fatal
|
||||
const int scale_error_i = 2; // non-fatal
|
||||
const int non_pair_error_i = 4; // non-fatal
|
||||
const int undefined_error_i = 32; // fatal
|
||||
const int range_error_i = 64;
|
||||
|
||||
#ifndef PI
|
||||
static const double PI = 3.141592653589793238;
|
||||
#endif
|
||||
|
||||
#ifdef CLIPPER2_MAX_PRECISION
|
||||
const int MAX_DECIMAL_PRECISION = CLIPPER2_MAX_PRECISION;
|
||||
#ifdef CLIPPER2_MAX_DECIMAL_PRECISION
|
||||
const int CLIPPER2_MAX_DEC_PRECISION = CLIPPER2_MAX_DECIMAL_PRECISION;
|
||||
#else
|
||||
const int MAX_DECIMAL_PRECISION = 8; // see Discussions #564
|
||||
const int CLIPPER2_MAX_DEC_PRECISION = 8; // see Discussions #564
|
||||
#endif
|
||||
|
||||
static const int64_t MAX_COORD = INT64_MAX >> 2;
|
||||
|
|
@ -74,7 +75,7 @@ namespace Clipper2Lib
|
|||
|
||||
static const double MAX_DBL = (std::numeric_limits<double>::max)();
|
||||
|
||||
static void DoError(int error_code)
|
||||
static void DoError([[maybe_unused]] int error_code)
|
||||
{
|
||||
#if (defined(__cpp_exceptions) && __cpp_exceptions) || (defined(__EXCEPTIONS) && __EXCEPTIONS)
|
||||
switch (error_code)
|
||||
|
|
@ -95,6 +96,13 @@ namespace Clipper2Lib
|
|||
#endif
|
||||
}
|
||||
|
||||
// can we call std::round on T? (default false) (#824)
|
||||
template <typename T, typename = void>
|
||||
struct is_round_invocable : std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
struct is_round_invocable<T, std::void_t<decltype(std::round(std::declval<T>()))>> : std::true_type {};
|
||||
|
||||
|
||||
//By far the most widely used filling rules for polygons are EvenOdd
|
||||
//and NonZero, sometimes called Alternate and Winding respectively.
|
||||
|
|
@ -113,8 +121,8 @@ namespace Clipper2Lib
|
|||
template <typename T2>
|
||||
inline void Init(const T2 x_ = 0, const T2 y_ = 0, const int64_t z_ = 0)
|
||||
{
|
||||
if constexpr (std::numeric_limits<T>::is_integer &&
|
||||
!std::numeric_limits<T2>::is_integer)
|
||||
if constexpr (std::is_integral_v<T> &&
|
||||
is_round_invocable<T2>::value && !std::is_integral_v<T2>)
|
||||
{
|
||||
x = static_cast<T>(std::round(x_));
|
||||
y = static_cast<T>(std::round(y_));
|
||||
|
|
@ -143,6 +151,12 @@ namespace Clipper2Lib
|
|||
Init(p.x, p.y, p.z);
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
explicit Point(const Point<T2>& p, int64_t z_)
|
||||
{
|
||||
Init(p.x, p.y, z_);
|
||||
}
|
||||
|
||||
Point operator * (const double scale) const
|
||||
{
|
||||
return Point(x * scale, y * scale, z);
|
||||
|
|
@ -161,8 +175,8 @@ namespace Clipper2Lib
|
|||
template <typename T2>
|
||||
inline void Init(const T2 x_ = 0, const T2 y_ = 0)
|
||||
{
|
||||
if constexpr (std::numeric_limits<T>::is_integer &&
|
||||
!std::numeric_limits<T2>::is_integer)
|
||||
if constexpr (std::is_integral_v<T> &&
|
||||
is_round_invocable<T2>::value && !std::is_integral_v<T2>)
|
||||
{
|
||||
x = static_cast<T>(std::round(x_));
|
||||
y = static_cast<T>(std::round(y_));
|
||||
|
|
@ -244,6 +258,14 @@ namespace Clipper2Lib
|
|||
(std::numeric_limits<double>::max)(),
|
||||
(std::numeric_limits<double>::max)());
|
||||
|
||||
template<typename T>
|
||||
static inline Point<T> MidPoint(const Point<T>& p1, const Point<T>& p2)
|
||||
{
|
||||
Point<T> result;
|
||||
result.x = (p1.x + p2.x) / 2;
|
||||
result.y = (p1.y + p2.y) / 2;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Rect ------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -275,10 +297,19 @@ namespace Clipper2Lib
|
|||
else
|
||||
{
|
||||
left = top = (std::numeric_limits<T>::max)();
|
||||
right = bottom = (std::numeric_limits<T>::lowest)();
|
||||
right = bottom = std::numeric_limits<T>::lowest();
|
||||
}
|
||||
}
|
||||
|
||||
static Rect<T> InvalidRect()
|
||||
{
|
||||
return {
|
||||
(std::numeric_limits<T>::max)(),
|
||||
(std::numeric_limits<T>::max)(),
|
||||
std::numeric_limits<T>::lowest(),
|
||||
std::numeric_limits<T>::lowest() };
|
||||
}
|
||||
|
||||
bool IsValid() const { return left != (std::numeric_limits<T>::max)(); }
|
||||
|
||||
T Width() const { return right - left; }
|
||||
|
|
@ -329,7 +360,7 @@ namespace Clipper2Lib
|
|||
};
|
||||
|
||||
bool operator==(const Rect<T>& other) const {
|
||||
return left == other.left && right == other.right &&
|
||||
return left == other.left && right == other.right &&
|
||||
top == other.top && bottom == other.bottom;
|
||||
}
|
||||
|
||||
|
|
@ -344,8 +375,8 @@ namespace Clipper2Lib
|
|||
{
|
||||
Rect<T1> result;
|
||||
|
||||
if constexpr (std::numeric_limits<T1>::is_integer &&
|
||||
!std::numeric_limits<T2>::is_integer)
|
||||
if constexpr (std::is_integral_v<T1> &&
|
||||
is_round_invocable<T2>::value && !std::is_integral_v<T2>)
|
||||
{
|
||||
result.left = static_cast<T1>(std::round(rect.left * scale));
|
||||
result.top = static_cast<T1>(std::round(rect.top * scale));
|
||||
|
|
@ -354,32 +385,24 @@ namespace Clipper2Lib
|
|||
}
|
||||
else
|
||||
{
|
||||
result.left = rect.left * scale;
|
||||
result.top = rect.top * scale;
|
||||
result.right = rect.right * scale;
|
||||
result.bottom = rect.bottom * scale;
|
||||
result.left = static_cast<T1>(rect.left * scale);
|
||||
result.top = static_cast<T1>(rect.top * scale);
|
||||
result.right = static_cast<T1>(rect.right * scale);
|
||||
result.bottom = static_cast<T1>(rect.bottom * scale);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static const Rect64 InvalidRect64 = Rect64(
|
||||
(std::numeric_limits<int64_t>::max)(),
|
||||
(std::numeric_limits<int64_t>::max)(),
|
||||
(std::numeric_limits<int64_t>::lowest)(),
|
||||
(std::numeric_limits<int64_t>::lowest)());
|
||||
static const RectD InvalidRectD = RectD(
|
||||
(std::numeric_limits<double>::max)(),
|
||||
(std::numeric_limits<double>::max)(),
|
||||
(std::numeric_limits<double>::lowest)(),
|
||||
(std::numeric_limits<double>::lowest)());
|
||||
static const Rect64 InvalidRect64 = Rect64::InvalidRect();
|
||||
static const RectD InvalidRectD = RectD::InvalidRect();
|
||||
|
||||
template <typename T>
|
||||
Rect<T> GetBounds(const Path<T>& path)
|
||||
{
|
||||
auto xmin = (std::numeric_limits<T>::max)();
|
||||
auto ymin = (std::numeric_limits<T>::max)();
|
||||
auto xmax = std::numeric_limits<T>::lowest();
|
||||
auto ymax = std::numeric_limits<T>::lowest();
|
||||
T xmin = (std::numeric_limits<T>::max)();
|
||||
T ymin = (std::numeric_limits<T>::max)();
|
||||
T xmax = std::numeric_limits<T>::lowest();
|
||||
T ymax = std::numeric_limits<T>::lowest();
|
||||
for (const auto& p : path)
|
||||
{
|
||||
if (p.x < xmin) xmin = p.x;
|
||||
|
|
@ -393,17 +416,52 @@ namespace Clipper2Lib
|
|||
template <typename T>
|
||||
Rect<T> GetBounds(const Paths<T>& paths)
|
||||
{
|
||||
auto xmin = (std::numeric_limits<T>::max)();
|
||||
auto ymin = (std::numeric_limits<T>::max)();
|
||||
auto xmax = std::numeric_limits<T>::lowest();
|
||||
auto ymax = std::numeric_limits<T>::lowest();
|
||||
T xmin = (std::numeric_limits<T>::max)();
|
||||
T ymin = (std::numeric_limits<T>::max)();
|
||||
T xmax = std::numeric_limits<T>::lowest();
|
||||
T ymax = std::numeric_limits<T>::lowest();
|
||||
for (const Path<T>& path : paths)
|
||||
for (const Point<T>& p : path)
|
||||
{
|
||||
if (p.x < xmin) xmin = p.x;
|
||||
if (p.x > xmax) xmax = p.x;
|
||||
if (p.y < ymin) ymin = p.y;
|
||||
if (p.y > ymax) ymax = p.y;
|
||||
if (p.x < xmin) xmin = p.x;
|
||||
if (p.x > xmax) xmax = p.x;
|
||||
if (p.y < ymin) ymin = p.y;
|
||||
if (p.y > ymax) ymax = p.y;
|
||||
}
|
||||
return Rect<T>(xmin, ymin, xmax, ymax);
|
||||
}
|
||||
|
||||
template <typename T, typename T2>
|
||||
Rect<T> GetBounds(const Path<T2>& path)
|
||||
{
|
||||
T xmin = (std::numeric_limits<T>::max)();
|
||||
T ymin = (std::numeric_limits<T>::max)();
|
||||
T xmax = std::numeric_limits<T>::lowest();
|
||||
T ymax = std::numeric_limits<T>::lowest();
|
||||
for (const auto& p : path)
|
||||
{
|
||||
if (p.x < xmin) xmin = static_cast<T>(p.x);
|
||||
if (p.x > xmax) xmax = static_cast<T>(p.x);
|
||||
if (p.y < ymin) ymin = static_cast<T>(p.y);
|
||||
if (p.y > ymax) ymax = static_cast<T>(p.y);
|
||||
}
|
||||
return Rect<T>(xmin, ymin, xmax, ymax);
|
||||
}
|
||||
|
||||
template <typename T, typename T2>
|
||||
Rect<T> GetBounds(const Paths<T2>& paths)
|
||||
{
|
||||
T xmin = (std::numeric_limits<T>::max)();
|
||||
T ymin = (std::numeric_limits<T>::max)();
|
||||
T xmax = std::numeric_limits<T>::lowest();
|
||||
T ymax = std::numeric_limits<T>::lowest();
|
||||
for (const Path<T2>& path : paths)
|
||||
for (const Point<T2>& p : path)
|
||||
{
|
||||
if (p.x < xmin) xmin = static_cast<T>(p.x);
|
||||
if (p.x > xmax) xmax = static_cast<T>(p.x);
|
||||
if (p.y < ymin) ymin = static_cast<T>(p.y);
|
||||
if (p.y > ymax) ymax = static_cast<T>(p.y);
|
||||
}
|
||||
return Rect<T>(xmin, ymin, xmax, ymax);
|
||||
}
|
||||
|
|
@ -431,7 +489,7 @@ namespace Clipper2Lib
|
|||
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline Path<T1> ScalePath(const Path<T2>& path,
|
||||
inline Path<T1> ScalePath(const Path<T2>& path,
|
||||
double scale_x, double scale_y, int& error_code)
|
||||
{
|
||||
Path<T1> result;
|
||||
|
|
@ -447,11 +505,11 @@ namespace Clipper2Lib
|
|||
result.reserve(path.size());
|
||||
#ifdef USINGZ
|
||||
std::transform(path.begin(), path.end(), back_inserter(result),
|
||||
[scale_x, scale_y](const auto& pt)
|
||||
[scale_x, scale_y](const auto& pt)
|
||||
{ return Point<T1>(pt.x * scale_x, pt.y * scale_y, pt.z); });
|
||||
#else
|
||||
std::transform(path.begin(), path.end(), back_inserter(result),
|
||||
[scale_x, scale_y](const auto& pt)
|
||||
[scale_x, scale_y](const auto& pt)
|
||||
{ return Point<T1>(pt.x * scale_x, pt.y * scale_y); });
|
||||
#endif
|
||||
return result;
|
||||
|
|
@ -465,20 +523,19 @@ namespace Clipper2Lib
|
|||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline Paths<T1> ScalePaths(const Paths<T2>& paths,
|
||||
inline Paths<T1> ScalePaths(const Paths<T2>& paths,
|
||||
double scale_x, double scale_y, int& error_code)
|
||||
{
|
||||
Paths<T1> result;
|
||||
|
||||
if constexpr (std::numeric_limits<T1>::is_integer &&
|
||||
!std::numeric_limits<T2>::is_integer)
|
||||
if constexpr (std::is_integral_v<T1>)
|
||||
{
|
||||
RectD r = GetBounds(paths);
|
||||
RectD r = GetBounds<double, T2>(paths);
|
||||
if ((r.left * scale_x) < min_coord ||
|
||||
(r.right * scale_x) > max_coord ||
|
||||
(r.top * scale_y) < min_coord ||
|
||||
(r.bottom * scale_y) > max_coord)
|
||||
{
|
||||
{
|
||||
error_code |= range_error_i;
|
||||
DoError(range_error_i);
|
||||
return result; // empty path
|
||||
|
|
@ -493,7 +550,7 @@ namespace Clipper2Lib
|
|||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
inline Paths<T1> ScalePaths(const Paths<T2>& paths,
|
||||
inline Paths<T1> ScalePaths(const Paths<T2>& paths,
|
||||
double scale, int& error_code)
|
||||
{
|
||||
return ScalePaths<T1, T2>(paths, scale, scale, error_code);
|
||||
|
|
@ -590,20 +647,92 @@ namespace Clipper2Lib
|
|||
|
||||
// Miscellaneous ------------------------------------------------------------
|
||||
|
||||
inline void CheckPrecision(int& precision, int& error_code)
|
||||
inline void CheckPrecisionRange(int& precision, int& error_code)
|
||||
{
|
||||
if (precision >= -MAX_DECIMAL_PRECISION && precision <= MAX_DECIMAL_PRECISION) return;
|
||||
if (precision >= -CLIPPER2_MAX_DEC_PRECISION &&
|
||||
precision <= CLIPPER2_MAX_DEC_PRECISION) return;
|
||||
error_code |= precision_error_i; // non-fatal error
|
||||
DoError(precision_error_i); // does nothing unless exceptions enabled
|
||||
precision = precision > 0 ? MAX_DECIMAL_PRECISION : -MAX_DECIMAL_PRECISION;
|
||||
DoError(precision_error_i); // does nothing when exceptions are disabled
|
||||
precision = precision > 0 ? CLIPPER2_MAX_DEC_PRECISION : -CLIPPER2_MAX_DEC_PRECISION;
|
||||
}
|
||||
|
||||
inline void CheckPrecision(int& precision)
|
||||
inline void CheckPrecisionRange(int& precision)
|
||||
{
|
||||
int error_code = 0;
|
||||
CheckPrecision(precision, error_code);
|
||||
CheckPrecisionRange(precision, error_code);
|
||||
}
|
||||
|
||||
inline int TriSign(int64_t x) // returns 0, 1 or -1
|
||||
{
|
||||
return (x > 0) - (x < 0);
|
||||
}
|
||||
|
||||
struct MultiplyUInt64Result
|
||||
{
|
||||
const uint64_t result = 0;
|
||||
const uint64_t carry = 0;
|
||||
|
||||
bool operator==(const MultiplyUInt64Result& other) const
|
||||
{
|
||||
return result == other.result && carry == other.carry;
|
||||
};
|
||||
};
|
||||
|
||||
inline MultiplyUInt64Result Multiply(uint64_t a, uint64_t b) // #834, #835
|
||||
{
|
||||
const auto lo = [](uint64_t x) { return x & 0xFFFFFFFF; };
|
||||
const auto hi = [](uint64_t x) { return x >> 32; };
|
||||
|
||||
const uint64_t x1 = lo(a) * lo(b);
|
||||
const uint64_t x2 = hi(a) * lo(b) + hi(x1);
|
||||
const uint64_t x3 = lo(a) * hi(b) + lo(x2);
|
||||
const uint64_t result = lo(x3) << 32 | lo(x1);
|
||||
const uint64_t carry = hi(a) * hi(b) + hi(x2) + hi(x3);
|
||||
|
||||
return { result, carry };
|
||||
}
|
||||
|
||||
// returns true if (and only if) a * b == c * d
|
||||
inline bool ProductsAreEqual(int64_t a, int64_t b, int64_t c, int64_t d)
|
||||
{
|
||||
// Work around LLVM issue: https://github.com/llvm/llvm-project/issues/16778
|
||||
// Details: https://github.com/godotengine/godot/pull/95964#issuecomment-2306581804
|
||||
//#if (defined(__clang__) || defined(__GNUC__)) && UINTPTR_MAX >= UINT64_MAX
|
||||
// const auto ab = static_cast<__int128_t>(a) * static_cast<__int128_t>(b);
|
||||
// const auto cd = static_cast<__int128_t>(c) * static_cast<__int128_t>(d);
|
||||
// return ab == cd;
|
||||
//#else
|
||||
// nb: unsigned values needed for calculating overflow carry
|
||||
const auto abs_a = static_cast<uint64_t>(std::abs(a));
|
||||
const auto abs_b = static_cast<uint64_t>(std::abs(b));
|
||||
const auto abs_c = static_cast<uint64_t>(std::abs(c));
|
||||
const auto abs_d = static_cast<uint64_t>(std::abs(d));
|
||||
|
||||
const auto abs_ab = Multiply(abs_a, abs_b);
|
||||
const auto abs_cd = Multiply(abs_c, abs_d);
|
||||
|
||||
// nb: it's important to differentiate 0 values here from other values
|
||||
const auto sign_ab = TriSign(a) * TriSign(b);
|
||||
const auto sign_cd = TriSign(c) * TriSign(d);
|
||||
|
||||
return abs_ab == abs_cd && sign_ab == sign_cd;
|
||||
// #endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline bool IsCollinear(const Point<T>& pt1,
|
||||
const Point<T>& sharedPt, const Point<T>& pt2) // #777
|
||||
{
|
||||
const auto a = sharedPt.x - pt1.x;
|
||||
const auto b = pt2.y - sharedPt.y;
|
||||
const auto c = sharedPt.y - pt1.y;
|
||||
const auto d = pt2.x - sharedPt.x;
|
||||
// When checking for collinearity with very large coordinate values
|
||||
// then ProductsAreEqual is more accurate than using CrossProduct.
|
||||
return ProductsAreEqual(a, b, c, d);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline double CrossProduct(const Point<T>& pt1, const Point<T>& pt2, const Point<T>& pt3) {
|
||||
return (static_cast<double>(pt2.x - pt1.x) * static_cast<double>(pt3.y -
|
||||
|
|
@ -635,15 +764,17 @@ namespace Clipper2Lib
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
inline double DistanceFromLineSqrd(const Point<T>& pt, const Point<T>& ln1, const Point<T>& ln2)
|
||||
inline double PerpendicDistFromLineSqrd(const Point<T>& pt,
|
||||
const Point<T>& line1, const Point<T>& line2)
|
||||
{
|
||||
//perpendicular distance of point (x³,y³) = (Ax³ + By³ + C)/Sqrt(A² + B²)
|
||||
//see http://en.wikipedia.org/wiki/Perpendicular_distance
|
||||
double A = static_cast<double>(ln1.y - ln2.y);
|
||||
double B = static_cast<double>(ln2.x - ln1.x);
|
||||
double C = A * ln1.x + B * ln1.y;
|
||||
C = A * pt.x + B * pt.y - C;
|
||||
return (C * C) / (A * A + B * B);
|
||||
double a = static_cast<double>(pt.x - line1.x);
|
||||
double b = static_cast<double>(pt.y - line1.y);
|
||||
double c = static_cast<double>(line2.x - line1.x);
|
||||
double d = static_cast<double>(line2.y - line1.y);
|
||||
if (c == 0 && d == 0) return 0;
|
||||
return Sqr(a * d - c * b) / (c * c + d * d);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -663,7 +794,7 @@ namespace Clipper2Lib
|
|||
}
|
||||
if (cnt & 1)
|
||||
a += static_cast<double>(it2->y + it1->y) * (it2->x - it1->x);
|
||||
return a * 0.5;
|
||||
return (a * 0.5);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -681,16 +812,73 @@ namespace Clipper2Lib
|
|||
template <typename T>
|
||||
inline bool IsPositive(const Path<T>& poly)
|
||||
{
|
||||
// A curve has positive orientation [and area] if a region 'R'
|
||||
// A curve has positive orientation [and area] if a region 'R'
|
||||
// is on the left when traveling around the outside of 'R'.
|
||||
//https://mathworld.wolfram.com/CurveOrientation.html
|
||||
//nb: This statement is premised on using Cartesian coordinates
|
||||
return Area<T>(poly) >= 0;
|
||||
}
|
||||
|
||||
inline bool GetIntersectPoint(const Point64& ln1a, const Point64& ln1b,
|
||||
const Point64& ln2a, const Point64& ln2b, Point64& ip)
|
||||
{
|
||||
|
||||
#if CLIPPER2_HI_PRECISION
|
||||
// caution: this will compromise performance
|
||||
// https://github.com/AngusJohnson/Clipper2/issues/317#issuecomment-1314023253
|
||||
// See also CPP/BenchMark/GetIntersectPtBenchmark.cpp
|
||||
#define CC_MIN(x,y) ((x)>(y)?(y):(x))
|
||||
#define CC_MAX(x,y) ((x)<(y)?(y):(x))
|
||||
template<typename T>
|
||||
inline bool GetSegmentIntersectPt(const Point<T>& ln1a, const Point<T>& ln1b,
|
||||
const Point<T>& ln2a, const Point<T>& ln2b, Point<T>& ip)
|
||||
{
|
||||
double ln1dy = static_cast<double>(ln1b.y - ln1a.y);
|
||||
double ln1dx = static_cast<double>(ln1a.x - ln1b.x);
|
||||
double ln2dy = static_cast<double>(ln2b.y - ln2a.y);
|
||||
double ln2dx = static_cast<double>(ln2a.x - ln2b.x);
|
||||
double det = (ln2dy * ln1dx) - (ln1dy * ln2dx);
|
||||
if (det == 0.0) return false;
|
||||
T bb0minx = CC_MIN(ln1a.x, ln1b.x);
|
||||
T bb0miny = CC_MIN(ln1a.y, ln1b.y);
|
||||
T bb0maxx = CC_MAX(ln1a.x, ln1b.x);
|
||||
T bb0maxy = CC_MAX(ln1a.y, ln1b.y);
|
||||
T bb1minx = CC_MIN(ln2a.x, ln2b.x);
|
||||
T bb1miny = CC_MIN(ln2a.y, ln2b.y);
|
||||
T bb1maxx = CC_MAX(ln2a.x, ln2b.x);
|
||||
T bb1maxy = CC_MAX(ln2a.y, ln2b.y);
|
||||
|
||||
if constexpr (std::is_integral_v<T>)
|
||||
{
|
||||
int64_t originx = (CC_MIN(bb0maxx, bb1maxx) + CC_MAX(bb0minx, bb1minx)) >> 1;
|
||||
int64_t originy = (CC_MIN(bb0maxy, bb1maxy) + CC_MAX(bb0miny, bb1miny)) >> 1;
|
||||
double ln0c = (ln1dy * static_cast<double>(ln1a.x - originx)) +
|
||||
(ln1dx * static_cast<double>(ln1a.y - originy));
|
||||
double ln1c = (ln2dy * static_cast<double>(ln2a.x - originx)) +
|
||||
(ln2dx * static_cast<double>(ln2a.y - originy));
|
||||
double hitx = ((ln1dx * ln1c) - (ln2dx * ln0c)) / det;
|
||||
double hity = ((ln2dy * ln0c) - (ln1dy * ln1c)) / det;
|
||||
|
||||
ip.x = originx + (T)nearbyint(hitx);
|
||||
ip.y = originy + (T)nearbyint(hity);
|
||||
}
|
||||
else
|
||||
{
|
||||
double originx = (CC_MIN(bb0maxx, bb1maxx) + CC_MAX(bb0minx, bb1minx)) / 2.0;
|
||||
double originy = (CC_MIN(bb0maxy, bb1maxy) + CC_MAX(bb0miny, bb1miny)) / 2.0;
|
||||
double ln0c = (ln1dy * static_cast<double>(ln1a.x - originx)) +
|
||||
(ln1dx * static_cast<double>(ln1a.y - originy));
|
||||
double ln1c = (ln2dy * static_cast<double>(ln2a.x - originx)) +
|
||||
(ln2dx * static_cast<double>(ln2a.y - originy));
|
||||
double hitx = ((ln1dx * ln1c) - (ln2dx * ln0c)) / det;
|
||||
double hity = ((ln2dy * ln0c) - (ln1dy * ln1c)) / det;
|
||||
|
||||
ip.x = originx + static_cast<T>(hitx);
|
||||
ip.y = originy + static_cast<T>(hity);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
template<typename T>
|
||||
inline bool GetSegmentIntersectPt(const Point<T>& ln1a, const Point<T>& ln1b,
|
||||
const Point<T>& ln2a, const Point<T>& ln2b, Point<T>& ip)
|
||||
{
|
||||
// https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection
|
||||
double dx1 = static_cast<double>(ln1b.x - ln1a.x);
|
||||
double dy1 = static_cast<double>(ln1b.y - ln1a.y);
|
||||
|
|
@ -700,15 +888,44 @@ namespace Clipper2Lib
|
|||
double det = dy1 * dx2 - dy2 * dx1;
|
||||
if (det == 0.0) return false;
|
||||
double t = ((ln1a.x - ln2a.x) * dy2 - (ln1a.y - ln2a.y) * dx2) / det;
|
||||
if (t <= 0.0) ip = ln1a; // ?? check further (see also #568)
|
||||
else if (t >= 1.0) ip = ln1b; // ?? check further
|
||||
if (t <= 0.0) ip = ln1a;
|
||||
else if (t >= 1.0) ip = ln1b;
|
||||
else
|
||||
{
|
||||
ip.x = static_cast<int64_t>(ln1a.x + t * dx1);
|
||||
ip.y = static_cast<int64_t>(ln1a.y + t * dy1);
|
||||
}
|
||||
ip.x = static_cast<T>(ln1a.x + t * dx1);
|
||||
ip.y = static_cast<T>(ln1a.y + t * dy1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
template<typename T>
|
||||
inline Point<T> TranslatePoint(const Point<T>& pt, double dx, double dy)
|
||||
{
|
||||
#ifdef USINGZ
|
||||
return Point<T>(pt.x + dx, pt.y + dy, pt.z);
|
||||
#else
|
||||
return Point<T>(pt.x + dx, pt.y + dy);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline Point<T> ReflectPoint(const Point<T>& pt, const Point<T>& pivot)
|
||||
{
|
||||
#ifdef USINGZ
|
||||
return Point<T>(pivot.x + (pivot.x - pt.x), pivot.y + (pivot.y - pt.y), pt.z);
|
||||
#else
|
||||
return Point<T>(pivot.x + (pivot.x - pt.x), pivot.y + (pivot.y - pt.y));
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline int GetSign(const T& val)
|
||||
{
|
||||
if (!val) return 0;
|
||||
return (val > 0) ? 1 : -1;
|
||||
}
|
||||
|
||||
inline bool SegmentsIntersect(const Point64& seg1a, const Point64& seg1b,
|
||||
const Point64& seg2a, const Point64& seg2b, bool inclusive = false)
|
||||
|
|
@ -724,10 +941,10 @@ namespace Clipper2Lib
|
|||
return (res1 || res2 || res3 || res4); // ensures not collinear
|
||||
}
|
||||
else {
|
||||
return (CrossProduct(seg1a, seg2a, seg2b) *
|
||||
CrossProduct(seg1b, seg2a, seg2b) < 0) &&
|
||||
(CrossProduct(seg2a, seg1a, seg1b) *
|
||||
CrossProduct(seg2b, seg1a, seg1b) < 0);
|
||||
return (GetSign(CrossProduct(seg1a, seg2a, seg2b)) *
|
||||
GetSign(CrossProduct(seg1b, seg2a, seg2b)) < 0) &&
|
||||
(GetSign(CrossProduct(seg2a, seg1a, seg1b)) *
|
||||
GetSign(CrossProduct(seg2b, seg1a, seg1b)) < 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -743,7 +960,7 @@ namespace Clipper2Lib
|
|||
static_cast<double>(offPt.y - seg1.y) * dy) /
|
||||
(Sqr(dx) + Sqr(dy));
|
||||
if (q < 0) q = 0; else if (q > 1) q = 1;
|
||||
if constexpr (std::numeric_limits<T>::is_integer)
|
||||
if constexpr (std::is_integral_v<T>)
|
||||
return Point<T>(
|
||||
seg1.x + static_cast<T>(nearbyint(q * dx)),
|
||||
seg1.y + static_cast<T>(nearbyint(q * dy)));
|
||||
|
|
@ -770,7 +987,7 @@ namespace Clipper2Lib
|
|||
return PointInPolygonResult::IsOutside;
|
||||
|
||||
bool is_above = first->y < pt.y, starting_above = is_above;
|
||||
curr = first +1;
|
||||
curr = first +1;
|
||||
while (true)
|
||||
{
|
||||
if (curr == cend)
|
||||
|
|
@ -779,7 +996,7 @@ namespace Clipper2Lib
|
|||
cend = first;
|
||||
curr = cbegin;
|
||||
}
|
||||
|
||||
|
||||
if (is_above)
|
||||
{
|
||||
while (curr != cend && curr->y < pt.y) ++curr;
|
||||
|
|
@ -791,14 +1008,14 @@ namespace Clipper2Lib
|
|||
if (curr == cend) continue;
|
||||
}
|
||||
|
||||
if (curr == cbegin)
|
||||
if (curr == cbegin)
|
||||
prev = polygon.cend() - 1; //nb: NOT cend (since might equal first)
|
||||
else
|
||||
else
|
||||
prev = curr - 1;
|
||||
|
||||
if (curr->y == pt.y)
|
||||
{
|
||||
if (curr->x == pt.x ||
|
||||
if (curr->x == pt.x ||
|
||||
(curr->y == prev->y &&
|
||||
((pt.x < prev->x) != (pt.x < curr->x))))
|
||||
return PointInPolygonResult::IsOn;
|
||||
|
|
@ -822,7 +1039,7 @@ namespace Clipper2Lib
|
|||
is_above = !is_above;
|
||||
++curr;
|
||||
}
|
||||
|
||||
|
||||
if (is_above != starting_above)
|
||||
{
|
||||
cend = polygon.cend();
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 22 November 2023 *
|
||||
* Date : 5 July 2024 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2023 *
|
||||
* Copyright : Angus Johnson 2010-2024 *
|
||||
* Purpose : This is the main polygon clipping module *
|
||||
* License : http://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
|
|
@ -33,7 +33,7 @@ namespace Clipper2Lib {
|
|||
|
||||
//Note: all clipping operations except for Difference are commutative.
|
||||
enum class ClipType { None, Intersection, Union, Difference, Xor };
|
||||
|
||||
|
||||
enum class PathType { Subject, Clip };
|
||||
enum class JoinWith { None, Left, Right };
|
||||
|
||||
|
|
@ -41,7 +41,7 @@ namespace Clipper2Lib {
|
|||
None = 0, OpenStart = 1, OpenEnd = 2, LocalMax = 4, LocalMin = 8
|
||||
};
|
||||
|
||||
constexpr enum VertexFlags operator &(enum VertexFlags a, enum VertexFlags b)
|
||||
constexpr enum VertexFlags operator &(enum VertexFlags a, enum VertexFlags b)
|
||||
{
|
||||
return (enum VertexFlags)(uint32_t(a) & uint32_t(b));
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ namespace Clipper2Lib {
|
|||
Path64 path;
|
||||
bool is_open = false;
|
||||
|
||||
~OutRec() {
|
||||
~OutRec() {
|
||||
if (splits) delete splits;
|
||||
// nb: don't delete the split pointers
|
||||
// as these are owned by ClipperBase's outrec_list_
|
||||
|
|
@ -106,7 +106,7 @@ namespace Clipper2Lib {
|
|||
//Important: UP and DOWN here are premised on Y-axis positive down
|
||||
//displays, which is the orientation used in Clipper's development.
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
struct Active {
|
||||
Point64 bot;
|
||||
Point64 top;
|
||||
|
|
@ -230,7 +230,7 @@ namespace Clipper2Lib {
|
|||
inline bool PopHorz(Active *&e);
|
||||
inline OutPt* StartOpenPath(Active &e, const Point64& pt);
|
||||
inline void UpdateEdgeIntoAEL(Active *e);
|
||||
OutPt* IntersectEdges(Active &e1, Active &e2, const Point64& pt);
|
||||
void IntersectEdges(Active &e1, Active &e2, const Point64& pt);
|
||||
inline void DeleteFromAEL(Active &e);
|
||||
inline void AdjustCurrXAndCopyToSEL(const int64_t top_y);
|
||||
void DoIntersections(const int64_t top_y);
|
||||
|
|
@ -240,7 +240,7 @@ namespace Clipper2Lib {
|
|||
void SwapPositionsInAEL(Active& edge1, Active& edge2);
|
||||
OutRec* NewOutRec();
|
||||
OutPt* AddOutPt(const Active &e, const Point64& pt);
|
||||
OutPt* AddLocalMinPoly(Active &e1, Active &e2,
|
||||
OutPt* AddLocalMinPoly(Active &e1, Active &e2,
|
||||
const Point64& pt, bool is_new = false);
|
||||
OutPt* AddLocalMaxPoly(Active &e1, Active &e2, const Point64& pt);
|
||||
void DoHorizontal(Active &horz);
|
||||
|
|
@ -251,13 +251,13 @@ namespace Clipper2Lib {
|
|||
void JoinOutrecPaths(Active &e1, Active &e2);
|
||||
void FixSelfIntersects(OutRec* outrec);
|
||||
void DoSplitOp(OutRec* outRec, OutPt* splitOp);
|
||||
|
||||
|
||||
inline void AddTrialHorzJoin(OutPt* op);
|
||||
void ConvertHorzSegsToJoins();
|
||||
void ProcessHorzJoins();
|
||||
|
||||
void Split(Active& e, const Point64& pt);
|
||||
inline void CheckJoinLeft(Active& e,
|
||||
inline void CheckJoinLeft(Active& e,
|
||||
const Point64& pt, bool check_curr_x = false);
|
||||
inline void CheckJoinRight(Active& e,
|
||||
const Point64& pt, bool check_curr_x = false);
|
||||
|
|
@ -326,12 +326,12 @@ namespace Clipper2Lib {
|
|||
|
||||
const PolyPath* Parent() const { return parent_; }
|
||||
|
||||
bool IsHole() const
|
||||
bool IsHole() const
|
||||
{
|
||||
unsigned lvl = Level();
|
||||
//Even levels except level 0
|
||||
return lvl && !(lvl & 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef typename std::vector<std::unique_ptr<PolyPath64>> PolyPath64List;
|
||||
|
|
@ -343,15 +343,16 @@ namespace Clipper2Lib {
|
|||
Path64 polygon_;
|
||||
public:
|
||||
explicit PolyPath64(PolyPath64* parent = nullptr) : PolyPath(parent) {}
|
||||
explicit PolyPath64(PolyPath64* parent, const Path64& path) : PolyPath(parent) { polygon_ = path; }
|
||||
|
||||
~PolyPath64() {
|
||||
childs_.resize(0);
|
||||
}
|
||||
|
||||
PolyPath64* operator [] (size_t index) const
|
||||
{
|
||||
{
|
||||
return childs_[index].get(); //std::unique_ptr
|
||||
}
|
||||
}
|
||||
|
||||
PolyPath64* Child(size_t index) const
|
||||
{
|
||||
|
|
@ -363,10 +364,7 @@ namespace Clipper2Lib {
|
|||
|
||||
PolyPath64* AddChild(const Path64& path) override
|
||||
{
|
||||
auto p = std::make_unique<PolyPath64>(this);
|
||||
auto* result = childs_.emplace_back(std::move(p)).get();
|
||||
result->polygon_ = path;
|
||||
return result;
|
||||
return childs_.emplace_back(std::make_unique<PolyPath64>(this, path)).get();
|
||||
}
|
||||
|
||||
void Clear() override
|
||||
|
|
@ -401,12 +399,25 @@ namespace Clipper2Lib {
|
|||
scale_ = parent ? parent->scale_ : 1.0;
|
||||
}
|
||||
|
||||
explicit PolyPathD(PolyPathD* parent, const Path64& path) : PolyPath(parent)
|
||||
{
|
||||
scale_ = parent ? parent->scale_ : 1.0;
|
||||
int error_code = 0;
|
||||
polygon_ = ScalePath<double, int64_t>(path, scale_, error_code);
|
||||
}
|
||||
|
||||
explicit PolyPathD(PolyPathD* parent, const PathD& path) : PolyPath(parent)
|
||||
{
|
||||
scale_ = parent ? parent->scale_ : 1.0;
|
||||
polygon_ = path;
|
||||
}
|
||||
|
||||
~PolyPathD() {
|
||||
childs_.resize(0);
|
||||
}
|
||||
|
||||
PolyPathD* operator [] (size_t index) const
|
||||
{
|
||||
{
|
||||
return childs_[index].get();
|
||||
}
|
||||
|
||||
|
|
@ -420,22 +431,15 @@ namespace Clipper2Lib {
|
|||
|
||||
void SetScale(double value) { scale_ = value; }
|
||||
double Scale() const { return scale_; }
|
||||
|
||||
|
||||
PolyPathD* AddChild(const Path64& path) override
|
||||
{
|
||||
int error_code = 0;
|
||||
auto p = std::make_unique<PolyPathD>(this);
|
||||
PolyPathD* result = childs_.emplace_back(std::move(p)).get();
|
||||
result->polygon_ = ScalePath<double, int64_t>(path, scale_, error_code);
|
||||
return result;
|
||||
return childs_.emplace_back(std::make_unique<PolyPathD>(this, path)).get();
|
||||
}
|
||||
|
||||
PolyPathD* AddChild(const PathD& path)
|
||||
{
|
||||
auto p = std::make_unique<PolyPathD>(this);
|
||||
PolyPathD* result = childs_.emplace_back(std::move(p)).get();
|
||||
result->polygon_ = path;
|
||||
return result;
|
||||
return childs_.emplace_back(std::make_unique<PolyPathD>(this, path)).get();
|
||||
}
|
||||
|
||||
void Clear() override
|
||||
|
|
@ -488,7 +492,7 @@ namespace Clipper2Lib {
|
|||
return Execute(clip_type, fill_rule, closed_paths, dummy);
|
||||
}
|
||||
|
||||
bool Execute(ClipType clip_type, FillRule fill_rule,
|
||||
bool Execute(ClipType clip_type, FillRule fill_rule,
|
||||
Paths64& closed_paths, Paths64& open_paths)
|
||||
{
|
||||
closed_paths.clear();
|
||||
|
|
@ -530,7 +534,7 @@ namespace Clipper2Lib {
|
|||
public:
|
||||
explicit ClipperD(int precision = 2) : ClipperBase()
|
||||
{
|
||||
CheckPrecision(precision, error_code_);
|
||||
CheckPrecisionRange(precision, error_code_);
|
||||
// to optimize scaling / descaling precision
|
||||
// set the scale to a power of double's radix (2) (#25)
|
||||
scale_ = std::pow(std::numeric_limits<double>::radix,
|
||||
|
|
@ -560,12 +564,12 @@ namespace Clipper2Lib {
|
|||
void CheckCallback()
|
||||
{
|
||||
if(zCallbackD_)
|
||||
// if the user defined float point callback has been assigned
|
||||
// if the user defined float point callback has been assigned
|
||||
// then assign the proxy callback function
|
||||
ClipperBase::zCallback_ =
|
||||
ClipperBase::zCallback_ =
|
||||
std::bind(&ClipperD::ZCB, this, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5);
|
||||
std::placeholders::_4, std::placeholders::_5);
|
||||
else
|
||||
ClipperBase::zCallback_ = nullptr;
|
||||
}
|
||||
|
|
@ -632,6 +636,6 @@ namespace Clipper2Lib {
|
|||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif // CLIPPER_ENGINE_H
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 26 November 2023 *
|
||||
* Date : 14 May 2024 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2023 *
|
||||
* Copyright : Angus Johnson 2010-2024 *
|
||||
* Purpose : This module exports the Clipper2 Library (ie DLL/so) *
|
||||
* License : http://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
Boolean clipping:
|
||||
cliptype: None=0, Intersection=1, Union=2, Difference=3, Xor=4
|
||||
fillrule: EvenOdd=0, NonZero=1, Positive=2, Negative=3
|
||||
|
|
@ -19,12 +19,12 @@
|
|||
|
||||
The path structures used extensively in other parts of this library are all
|
||||
based on std::vector classes. Since C++ classes can't be accessed by other
|
||||
languages, these paths must be converted into simple C data structures that
|
||||
can be understood by just about any programming language. And these C style
|
||||
path structures are simple arrays of int64_t (CPath64) and double (CPathD).
|
||||
languages, these paths are converted into very simple array data structures
|
||||
(of either int64_t for CPath64 or double for CPathD) that can be parsed by
|
||||
just about any programming language.
|
||||
|
||||
CPath64 and CPathD:
|
||||
These are arrays of consecutive x and y path coordinates preceeded by
|
||||
These are arrays of consecutive x and y path coordinates preceeded by
|
||||
a pair of values containing the path's length (N) and a 0 value.
|
||||
__________________________________
|
||||
|counter|coord1|coord2|...|coordN|
|
||||
|
|
@ -34,23 +34,24 @@ __________________________________
|
|||
CPaths64 and CPathsD:
|
||||
These are also arrays containing any number of consecutive CPath64 or
|
||||
CPathD structures. But preceeding these consecutive paths, there is pair of
|
||||
values that contain the total length of the array (A) structure and
|
||||
the number (C) of CPath64 or CPathD it contains.
|
||||
values that contain the total length of the array structure (A) and the
|
||||
number of CPath64 or CPathD it contains (C). The space these structures will
|
||||
occupy in memory = A * sizeof(int64_t) or A * sizeof(double) respectively.
|
||||
_______________________________
|
||||
|counter|path1|path2|...|pathC|
|
||||
|A , C | |
|
||||
_______________________________
|
||||
|
||||
CPolytree64 and CPolytreeD:
|
||||
These are also arrays consisting of CPolyPath structures that represent
|
||||
These are also arrays consisting of CPolyPath structures that represent
|
||||
individual paths in a tree structure. However, the very first (ie top)
|
||||
CPolyPath is just the tree container that won't have a path. And because
|
||||
CPolyPath is just the tree container that doesn't have a path. And because
|
||||
of that, its structure will be very slightly different from the remaining
|
||||
CPolyPath. This difference will be discussed below.
|
||||
|
||||
CPolyPath64 and CPolyPathD:
|
||||
These are simple arrays consisting of a series of path coordinates followed
|
||||
by any number of child (ie nested) CPolyPath. Preceeding these are two values
|
||||
These are simple arrays consisting of a series of path coordinates followed
|
||||
by any number of child (ie nested) CPolyPath. Preceeding these are two values
|
||||
indicating the length of the path (N) and the number of child CPolyPath (C).
|
||||
____________________________________________________________
|
||||
|counter|coord1|coord2|...|coordN| child1|child2|...|childC|
|
||||
|
|
@ -58,19 +59,20 @@ ____________________________________________________________
|
|||
____________________________________________________________
|
||||
|
||||
As mentioned above, the very first CPolyPath structure is just a container
|
||||
that owns (both directly and indirectly) every other CPolyPath in the tree.
|
||||
that owns (both directly and indirectly) every other CPolyPath in the tree.
|
||||
Since this first CPolyPath has no path, instead of a path length, its very
|
||||
first value will contain the total length of the CPolytree array structure.
|
||||
first value will contain the total length of the CPolytree array (not its
|
||||
total bytes length).
|
||||
|
||||
All theses exported structures (CPaths64, CPathsD, CPolyTree64 & CPolyTreeD)
|
||||
are arrays of type int64_t or double. And the first value in these arrays
|
||||
will always contain the length of that array.
|
||||
Again, all theses exported structures (CPaths64, CPathsD, CPolyTree64 &
|
||||
CPolyTreeD) are arrays of either type int64_t or double, and the first
|
||||
value in these arrays will always be the length of that array.
|
||||
|
||||
These array structures are allocated in heap memory which will eventually
|
||||
need to be released. But since applications dynamically linking to these
|
||||
functions may use different memory managers, the only safe way to free up
|
||||
this memory is to use the exported DisposeArray64 and DisposeArrayD
|
||||
functions below.
|
||||
These array structures are allocated in heap memory which will eventually
|
||||
need to be released. However, since applications dynamically linking to
|
||||
these functions may use different memory managers, the only safe way to
|
||||
free up this memory is to use the exported DisposeArray64 and
|
||||
DisposeArrayD functions (see below).
|
||||
*/
|
||||
|
||||
|
||||
|
|
@ -128,7 +130,7 @@ inline Rect<T> CRectToRect(const CRect<T>& rect)
|
|||
#ifdef _WIN32
|
||||
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define EXTERN_DLL_EXPORT extern "C"
|
||||
#define EXTERN_DLL_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -173,8 +175,8 @@ EXTERN_DLL_EXPORT int BooleanOp_PolyTreeD(uint8_t cliptype,
|
|||
bool preserve_collinear = true, bool reverse_solution = false);
|
||||
|
||||
EXTERN_DLL_EXPORT CPaths64 InflatePaths64(const CPaths64 paths,
|
||||
double delta, uint8_t jointype, uint8_t endtype,
|
||||
double miter_limit = 2.0, double arc_tolerance = 0.0,
|
||||
double delta, uint8_t jointype, uint8_t endtype,
|
||||
double miter_limit = 2.0, double arc_tolerance = 0.0,
|
||||
bool reverse_solution = false);
|
||||
EXTERN_DLL_EXPORT CPathsD InflatePathsD(const CPathsD paths,
|
||||
double delta, uint8_t jointype, uint8_t endtype,
|
||||
|
|
@ -219,10 +221,10 @@ static size_t GetPolyPath64ArrayLen(const PolyPath64& pp)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void GetPolytreeCountAndCStorageSize(const PolyTree64& tree,
|
||||
static void GetPolytreeCountAndCStorageSize(const PolyTree64& tree,
|
||||
size_t& cnt, size_t& array_len)
|
||||
{
|
||||
cnt = tree.Count(); // nb: top level count only
|
||||
cnt = tree.Count(); // nb: top level count only
|
||||
array_len = GetPolyPath64ArrayLen(tree);
|
||||
}
|
||||
|
||||
|
|
@ -271,17 +273,34 @@ CPathsD CreateCPathsDFromPaths64(const Paths64& paths, double scale)
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static Path<T> ConvertCPath(T* path)
|
||||
{
|
||||
Path<T> result;
|
||||
if (!path) return result;
|
||||
T* v = path;
|
||||
size_t cnt = static_cast<size_t>(*v);
|
||||
v += 2; // skip 0 value
|
||||
result.reserve(cnt);
|
||||
for (size_t j = 0; j < cnt; ++j)
|
||||
{
|
||||
T x = *v++, y = *v++;
|
||||
result.push_back(Point<T>(x, y));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static Paths<T> ConvertCPaths(T* paths)
|
||||
{
|
||||
Paths<T> result;
|
||||
if (!paths) return result;
|
||||
T* v = paths; ++v;
|
||||
size_t cnt = *v++;
|
||||
size_t cnt = static_cast<size_t>(*v++);
|
||||
result.reserve(cnt);
|
||||
for (size_t i = 0; i < cnt; ++i)
|
||||
{
|
||||
size_t cnt2 = *v;
|
||||
size_t cnt2 = static_cast<size_t>(*v);
|
||||
v += 2;
|
||||
Path<T> path;
|
||||
path.reserve(cnt2);
|
||||
|
|
@ -300,17 +319,17 @@ static Paths64 ConvertCPathsDToPaths64(const CPathsD paths, double scale)
|
|||
{
|
||||
Paths64 result;
|
||||
if (!paths) return result;
|
||||
double* v = paths;
|
||||
double* v = paths;
|
||||
++v; // skip the first value (0)
|
||||
int64_t cnt = (int64_t)*v++;
|
||||
size_t cnt = static_cast<size_t>(*v++);
|
||||
result.reserve(cnt);
|
||||
for (int i = 0; i < cnt; ++i)
|
||||
for (size_t i = 0; i < cnt; ++i)
|
||||
{
|
||||
int64_t cnt2 = (int64_t)*v;
|
||||
size_t cnt2 = static_cast<size_t>(*v);
|
||||
v += 2;
|
||||
Path64 path;
|
||||
path.reserve(cnt2);
|
||||
for (int j = 0; j < cnt2; ++j)
|
||||
for (size_t j = 0; j < cnt2; ++j)
|
||||
{
|
||||
double x = *v++ * scale;
|
||||
double y = *v++ * scale;
|
||||
|
|
@ -362,7 +381,7 @@ EXTERN_DLL_EXPORT const char* Version()
|
|||
return CLIPPER2_VERSION;
|
||||
}
|
||||
|
||||
EXTERN_DLL_EXPORT int BooleanOp64(uint8_t cliptype,
|
||||
EXTERN_DLL_EXPORT int BooleanOp64(uint8_t cliptype,
|
||||
uint8_t fillrule, const CPaths64 subjects,
|
||||
const CPaths64 subjects_open, const CPaths64 clips,
|
||||
CPaths64& solution, CPaths64& solution_open,
|
||||
|
|
@ -370,7 +389,7 @@ EXTERN_DLL_EXPORT int BooleanOp64(uint8_t cliptype,
|
|||
{
|
||||
if (cliptype > static_cast<uint8_t>(ClipType::Xor)) return -4;
|
||||
if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3;
|
||||
|
||||
|
||||
Paths64 sub, sub_open, clp, sol, sol_open;
|
||||
sub = ConvertCPaths(subjects);
|
||||
sub_open = ConvertCPaths(subjects_open);
|
||||
|
|
@ -382,7 +401,7 @@ EXTERN_DLL_EXPORT int BooleanOp64(uint8_t cliptype,
|
|||
if (sub.size() > 0) clipper.AddSubject(sub);
|
||||
if (sub_open.size() > 0) clipper.AddOpenSubject(sub_open);
|
||||
if (clp.size() > 0) clipper.AddClip(clp);
|
||||
if (!clipper.Execute(ClipType(cliptype), FillRule(fillrule), sol, sol_open))
|
||||
if (!clipper.Execute(ClipType(cliptype), FillRule(fillrule), sol, sol_open))
|
||||
return -1; // clipping bug - should never happen :)
|
||||
solution = CreateCPaths(sol);
|
||||
solution_open = CreateCPaths(sol_open);
|
||||
|
|
@ -455,7 +474,7 @@ EXTERN_DLL_EXPORT int BooleanOp_PolyTreeD(uint8_t cliptype,
|
|||
if (precision < -8 || precision > 8) return -5;
|
||||
if (cliptype > static_cast<uint8_t>(ClipType::Xor)) return -4;
|
||||
if (fillrule > static_cast<uint8_t>(FillRule::Negative)) return -3;
|
||||
|
||||
|
||||
double scale = std::pow(10, precision);
|
||||
|
||||
int err = 0;
|
||||
|
|
@ -485,10 +504,10 @@ EXTERN_DLL_EXPORT CPaths64 InflatePaths64(const CPaths64 paths,
|
|||
{
|
||||
Paths64 pp;
|
||||
pp = ConvertCPaths(paths);
|
||||
ClipperOffset clip_offset( miter_limit,
|
||||
ClipperOffset clip_offset( miter_limit,
|
||||
arc_tolerance, reverse_solution);
|
||||
clip_offset.AddPaths(pp, JoinType(jointype), EndType(endtype));
|
||||
Paths64 result;
|
||||
Paths64 result;
|
||||
clip_offset.Execute(delta, result);
|
||||
return CreateCPaths(result);
|
||||
}
|
||||
|
|
@ -560,6 +579,22 @@ EXTERN_DLL_EXPORT CPathsD RectClipLinesD(const CRectD& rect,
|
|||
return CreateCPathsDFromPaths64(result, 1 / scale);
|
||||
}
|
||||
|
||||
EXTERN_DLL_EXPORT CPaths64 MinkowskiSum64(const CPath64& cpattern, const CPath64& cpath, bool is_closed)
|
||||
{
|
||||
Path64 path = ConvertCPath(cpath);
|
||||
Path64 pattern = ConvertCPath(cpattern);
|
||||
Paths64 solution = MinkowskiSum(pattern, path, is_closed);
|
||||
return CreateCPaths(solution);
|
||||
}
|
||||
|
||||
EXTERN_DLL_EXPORT CPaths64 MinkowskiDiff64(const CPath64& cpattern, const CPath64& cpath, bool is_closed)
|
||||
{
|
||||
Path64 path = ConvertCPath(cpath);
|
||||
Path64 pattern = ConvertCPath(cpattern);
|
||||
Paths64 solution = MinkowskiDiff(pattern, path, is_closed);
|
||||
return CreateCPaths(solution);
|
||||
}
|
||||
|
||||
} // end Clipper2Lib namespace
|
||||
|
||||
|
||||
#endif // CLIPPER2_EXPORT_H
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 18 November 2023 *
|
||||
* Date : 27 April 2024 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2023 *
|
||||
* Copyright : Angus Johnson 2010-2024 *
|
||||
* Purpose : This module provides a simple interface to the Clipper Library *
|
||||
* License : http://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
|
|
@ -24,7 +24,7 @@ namespace Clipper2Lib {
|
|||
|
||||
inline Paths64 BooleanOp(ClipType cliptype, FillRule fillrule,
|
||||
const Paths64& subjects, const Paths64& clips)
|
||||
{
|
||||
{
|
||||
Paths64 result;
|
||||
Clipper64 clipper;
|
||||
clipper.AddSubject(subjects);
|
||||
|
|
@ -47,7 +47,7 @@ namespace Clipper2Lib {
|
|||
const PathsD& subjects, const PathsD& clips, int precision = 2)
|
||||
{
|
||||
int error_code = 0;
|
||||
CheckPrecision(precision, error_code);
|
||||
CheckPrecisionRange(precision, error_code);
|
||||
PathsD result;
|
||||
if (error_code) return result;
|
||||
ClipperD clipper(precision);
|
||||
|
|
@ -58,12 +58,12 @@ namespace Clipper2Lib {
|
|||
}
|
||||
|
||||
inline void BooleanOp(ClipType cliptype, FillRule fillrule,
|
||||
const PathsD& subjects, const PathsD& clips,
|
||||
const PathsD& subjects, const PathsD& clips,
|
||||
PolyTreeD& polytree, int precision = 2)
|
||||
{
|
||||
polytree.Clear();
|
||||
int error_code = 0;
|
||||
CheckPrecision(precision, error_code);
|
||||
CheckPrecisionRange(precision, error_code);
|
||||
if (error_code) return;
|
||||
ClipperD clipper(precision);
|
||||
clipper.AddSubject(subjects);
|
||||
|
|
@ -75,7 +75,7 @@ namespace Clipper2Lib {
|
|||
{
|
||||
return BooleanOp(ClipType::Intersection, fillrule, subjects, clips);
|
||||
}
|
||||
|
||||
|
||||
inline PathsD Intersect(const PathsD& subjects, const PathsD& clips, FillRule fillrule, int decimal_prec = 2)
|
||||
{
|
||||
return BooleanOp(ClipType::Intersection, fillrule, subjects, clips, decimal_prec);
|
||||
|
|
@ -104,7 +104,7 @@ namespace Clipper2Lib {
|
|||
{
|
||||
PathsD result;
|
||||
int error_code = 0;
|
||||
CheckPrecision(precision, error_code);
|
||||
CheckPrecisionRange(precision, error_code);
|
||||
if (error_code) return result;
|
||||
ClipperD clipper(precision);
|
||||
clipper.AddSubject(subjects);
|
||||
|
|
@ -145,11 +145,11 @@ namespace Clipper2Lib {
|
|||
}
|
||||
|
||||
inline PathsD InflatePaths(const PathsD& paths, double delta,
|
||||
JoinType jt, EndType et, double miter_limit = 2.0,
|
||||
JoinType jt, EndType et, double miter_limit = 2.0,
|
||||
int precision = 2, double arc_tolerance = 0.0)
|
||||
{
|
||||
int error_code = 0;
|
||||
CheckPrecision(precision, error_code);
|
||||
CheckPrecisionRange(precision, error_code);
|
||||
if (!delta) return paths;
|
||||
if (error_code) return PathsD();
|
||||
const double scale = std::pow(10, precision);
|
||||
|
|
@ -219,13 +219,13 @@ namespace Clipper2Lib {
|
|||
{
|
||||
if (rect.IsEmpty() || paths.empty()) return PathsD();
|
||||
int error_code = 0;
|
||||
CheckPrecision(precision, error_code);
|
||||
CheckPrecisionRange(precision, error_code);
|
||||
if (error_code) return PathsD();
|
||||
const double scale = std::pow(10, precision);
|
||||
Rect64 r = ScaleRect<int64_t, double>(rect, scale);
|
||||
RectClip64 rc(r);
|
||||
Paths64 pp = ScalePaths<int64_t, double>(paths, scale, error_code);
|
||||
if (error_code) return PathsD(); // ie: error_code result is lost
|
||||
if (error_code) return PathsD(); // ie: error_code result is lost
|
||||
return ScalePaths<double, int64_t>(
|
||||
rc.Execute(pp), 1 / scale, error_code);
|
||||
}
|
||||
|
|
@ -251,7 +251,7 @@ namespace Clipper2Lib {
|
|||
{
|
||||
if (rect.IsEmpty() || lines.empty()) return PathsD();
|
||||
int error_code = 0;
|
||||
CheckPrecision(precision, error_code);
|
||||
CheckPrecisionRange(precision, error_code);
|
||||
if (error_code) return PathsD();
|
||||
const double scale = std::pow(10, precision);
|
||||
Rect64 r = ScaleRect<int64_t, double>(rect, scale);
|
||||
|
|
@ -290,8 +290,8 @@ namespace Clipper2Lib {
|
|||
{
|
||||
// return false if this child isn't fully contained by its parent
|
||||
|
||||
// checking for a single vertex outside is a bit too crude since
|
||||
// it doesn't account for rounding errors. It's better to check
|
||||
// checking for a single vertex outside is a bit too crude since
|
||||
// it doesn't account for rounding errors. It's better to check
|
||||
// for consecutive vertices found outside the parent's polygon.
|
||||
|
||||
int outsideCnt = 0;
|
||||
|
|
@ -311,7 +311,7 @@ namespace Clipper2Lib {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void OutlinePolyPath(std::ostream& os,
|
||||
static void OutlinePolyPath(std::ostream& os,
|
||||
size_t idx, bool isHole, size_t count, const std::string& preamble)
|
||||
{
|
||||
std::string plural = (count == 1) ? "." : "s.";
|
||||
|
|
@ -342,19 +342,19 @@ namespace Clipper2Lib {
|
|||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline constexpr void MakePathGeneric(const T an_array,
|
||||
inline constexpr void MakePathGeneric(const T an_array,
|
||||
size_t array_size, std::vector<U>& result)
|
||||
{
|
||||
result.reserve(array_size / 2);
|
||||
for (size_t i = 0; i < array_size; i +=2)
|
||||
#ifdef USINGZ
|
||||
result.push_back( U{ an_array[i], an_array[i +1], 0} );
|
||||
result.push_back( U{ an_array[i], an_array[i + 1], 0} );
|
||||
#else
|
||||
result.push_back( U{ an_array[i], an_array[i + 1]} );
|
||||
#endif
|
||||
}
|
||||
|
||||
} // end details namespace
|
||||
} // end details namespace
|
||||
|
||||
inline std::ostream& operator<< (std::ostream& os, const PolyTree64& pp)
|
||||
{
|
||||
|
|
@ -398,7 +398,7 @@ namespace Clipper2Lib {
|
|||
inline bool CheckPolytreeFullyContainsChildren(const PolyTree64& polytree)
|
||||
{
|
||||
for (const auto& child : polytree)
|
||||
if (child->Count() > 0 &&
|
||||
if (child->Count() > 0 &&
|
||||
!details::PolyPath64ContainsChildren(*child))
|
||||
return false;
|
||||
return true;
|
||||
|
|
@ -471,7 +471,7 @@ namespace Clipper2Lib {
|
|||
std::size_t size = N / 3;
|
||||
Path64 result(size);
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
result[i] = Point64(list[i * 3],
|
||||
result[i] = Point64(list[i * 3],
|
||||
list[i * 3 + 1], list[i * 3 + 2]);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -489,7 +489,7 @@ namespace Clipper2Lib {
|
|||
list[i * 3 + 1], list[i * 3 + 2]);
|
||||
else
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
result[i] = PointD(list[i * 3], list[i * 3 + 1],
|
||||
result[i] = PointD(list[i * 3], list[i * 3 + 1],
|
||||
static_cast<int64_t>(list[i * 3 + 2]));
|
||||
return result;
|
||||
}
|
||||
|
|
@ -510,9 +510,9 @@ namespace Clipper2Lib {
|
|||
|
||||
if (!is_open_path)
|
||||
{
|
||||
while (srcIt != stop && !CrossProduct(*stop, *srcIt, *(srcIt + 1)))
|
||||
while (srcIt != stop && IsCollinear(*stop, *srcIt, *(srcIt + 1)))
|
||||
++srcIt;
|
||||
while (srcIt != stop && !CrossProduct(*(stop - 1), *stop, *srcIt))
|
||||
while (srcIt != stop && IsCollinear(*(stop - 1), *stop, *srcIt))
|
||||
--stop;
|
||||
if (srcIt == stop) return Path64();
|
||||
}
|
||||
|
|
@ -521,7 +521,7 @@ namespace Clipper2Lib {
|
|||
dst.push_back(*prevIt);
|
||||
for (; srcIt != stop; ++srcIt)
|
||||
{
|
||||
if (CrossProduct(*prevIt, *srcIt, *(srcIt + 1)))
|
||||
if (!IsCollinear(*prevIt, *srcIt, *(srcIt + 1)))
|
||||
{
|
||||
prevIt = srcIt;
|
||||
dst.push_back(*prevIt);
|
||||
|
|
@ -530,12 +530,12 @@ namespace Clipper2Lib {
|
|||
|
||||
if (is_open_path)
|
||||
dst.push_back(*srcIt);
|
||||
else if (CrossProduct(*prevIt, *stop, dst[0]))
|
||||
else if (!IsCollinear(*prevIt, *stop, dst[0]))
|
||||
dst.push_back(*stop);
|
||||
else
|
||||
{
|
||||
while (dst.size() > 2 &&
|
||||
!CrossProduct(dst[dst.size() - 1], dst[dst.size() - 2], dst[0]))
|
||||
IsCollinear(dst[dst.size() - 1], dst[dst.size() - 2], dst[0]))
|
||||
dst.pop_back();
|
||||
if (dst.size() < 3) return Path64();
|
||||
}
|
||||
|
|
@ -545,7 +545,7 @@ namespace Clipper2Lib {
|
|||
inline PathD TrimCollinear(const PathD& path, int precision, bool is_open_path = false)
|
||||
{
|
||||
int error_code = 0;
|
||||
CheckPrecision(precision, error_code);
|
||||
CheckPrecisionRange(precision, error_code);
|
||||
if (error_code) return PathD();
|
||||
const double scale = std::pow(10, precision);
|
||||
Path64 p = ScalePath<int64_t, double>(path, scale, error_code);
|
||||
|
|
@ -580,23 +580,23 @@ namespace Clipper2Lib {
|
|||
double cp = std::abs(CrossProduct(pt1, pt2, pt3));
|
||||
return (cp * cp) / (DistanceSqr(pt1, pt2) * DistanceSqr(pt2, pt3)) < sin_sqrd_min_angle_rads;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline Path<T> Ellipse(const Rect<T>& rect, int steps = 0)
|
||||
inline Path<T> Ellipse(const Rect<T>& rect, size_t steps = 0)
|
||||
{
|
||||
return Ellipse(rect.MidPoint(),
|
||||
static_cast<double>(rect.Width()) *0.5,
|
||||
return Ellipse(rect.MidPoint(),
|
||||
static_cast<double>(rect.Width()) *0.5,
|
||||
static_cast<double>(rect.Height()) * 0.5, steps);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Path<T> Ellipse(const Point<T>& center,
|
||||
double radiusX, double radiusY = 0, int steps = 0)
|
||||
double radiusX, double radiusY = 0, size_t steps = 0)
|
||||
{
|
||||
if (radiusX <= 0) return Path<T>();
|
||||
if (radiusY <= 0) radiusY = radiusX;
|
||||
if (steps <= 2)
|
||||
steps = static_cast<int>(PI * sqrt((radiusX + radiusY) / 2));
|
||||
steps = static_cast<size_t>(PI * sqrt((radiusX + radiusY) / 2));
|
||||
|
||||
double si = std::sin(2 * PI / steps);
|
||||
double co = std::cos(2 * PI / steps);
|
||||
|
|
@ -604,7 +604,7 @@ namespace Clipper2Lib {
|
|||
Path<T> result;
|
||||
result.reserve(steps);
|
||||
result.push_back(Point<T>(center.x + radiusX, static_cast<double>(center.y)));
|
||||
for (int i = 1; i < steps; ++i)
|
||||
for (size_t i = 1; i < steps; ++i)
|
||||
{
|
||||
result.push_back(Point<T>(center.x + radiusX * dx, center.y + radiusY * dy));
|
||||
double x = dx * co - dy * si;
|
||||
|
|
@ -614,19 +614,7 @@ namespace Clipper2Lib {
|
|||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline double PerpendicDistFromLineSqrd(const Point<T>& pt,
|
||||
const Point<T>& line1, const Point<T>& line2)
|
||||
{
|
||||
double a = static_cast<double>(pt.x - line1.x);
|
||||
double b = static_cast<double>(pt.y - line1.y);
|
||||
double c = static_cast<double>(line2.x - line1.x);
|
||||
double d = static_cast<double>(line2.y - line1.y);
|
||||
if (c == 0 && d == 0) return 0;
|
||||
return Sqr(a * d - c * b) / (c * c + d * d);
|
||||
}
|
||||
|
||||
inline size_t GetNext(size_t current, size_t high,
|
||||
inline size_t GetNext(size_t current, size_t high,
|
||||
const std::vector<bool>& flags)
|
||||
{
|
||||
++current;
|
||||
|
|
@ -637,7 +625,7 @@ namespace Clipper2Lib {
|
|||
return current;
|
||||
}
|
||||
|
||||
inline size_t GetPrior(size_t current, size_t high,
|
||||
inline size_t GetPrior(size_t current, size_t high,
|
||||
const std::vector<bool>& flags)
|
||||
{
|
||||
if (current == 0) current = high;
|
||||
|
|
@ -650,7 +638,7 @@ namespace Clipper2Lib {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
inline Path<T> SimplifyPath(const Path<T> &path,
|
||||
inline Path<T> SimplifyPath(const Path<T> &path,
|
||||
double epsilon, bool isClosedPath = true)
|
||||
{
|
||||
const size_t len = path.size(), high = len -1;
|
||||
|
|
@ -665,7 +653,7 @@ namespace Clipper2Lib {
|
|||
distSqr[0] = PerpendicDistFromLineSqrd(path[0], path[high], path[1]);
|
||||
distSqr[high] = PerpendicDistFromLineSqrd(path[high], path[0], path[high - 1]);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
distSqr[0] = MAX_DBL;
|
||||
distSqr[high] = MAX_DBL;
|
||||
|
|
@ -684,7 +672,7 @@ namespace Clipper2Lib {
|
|||
} while (curr != start && distSqr[curr] > epsSqr);
|
||||
if (curr == start) break;
|
||||
}
|
||||
|
||||
|
||||
prior = GetPrior(curr, high, flags);
|
||||
next = GetNext(curr, high, flags);
|
||||
if (next == prior) break;
|
||||
|
|
@ -699,7 +687,7 @@ namespace Clipper2Lib {
|
|||
}
|
||||
else
|
||||
prior2 = GetPrior(prior, high, flags);
|
||||
|
||||
|
||||
flags[curr] = true;
|
||||
curr = next;
|
||||
next = GetNext(next, high, flags);
|
||||
|
|
@ -717,7 +705,7 @@ namespace Clipper2Lib {
|
|||
}
|
||||
|
||||
template <typename T>
|
||||
inline Paths<T> SimplifyPaths(const Paths<T> &paths,
|
||||
inline Paths<T> SimplifyPaths(const Paths<T> &paths,
|
||||
double epsilon, bool isClosedPath = true)
|
||||
{
|
||||
Paths<T> result;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include <string>
|
||||
#include "clipper2/clipper.core.h"
|
||||
|
||||
namespace Clipper2Lib
|
||||
namespace Clipper2Lib
|
||||
{
|
||||
|
||||
namespace detail
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 19 November 2023 *
|
||||
* Date : 24 March 2024 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2023 *
|
||||
* Copyright : Angus Johnson 2010-2024 *
|
||||
* Purpose : Path Offset (Inflate/Shrink) *
|
||||
* License : http://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
|
|
@ -34,9 +34,7 @@ private:
|
|||
class Group {
|
||||
public:
|
||||
Paths64 paths_in;
|
||||
std::vector<bool> is_hole_list;
|
||||
std::vector<Rect64> bounds_list;
|
||||
int lowest_path_idx = -1;
|
||||
std::optional<size_t> lowest_path_idx{};
|
||||
bool is_reversed = false;
|
||||
JoinType join_type;
|
||||
EndType end_type;
|
||||
|
|
@ -52,7 +50,8 @@ private:
|
|||
double step_cos_ = 0.0;
|
||||
PathD norms;
|
||||
Path64 path_out;
|
||||
Paths64 solution;
|
||||
Paths64* solution = nullptr;
|
||||
PolyTree64* solution_tree = nullptr;
|
||||
std::vector<Group> groups_;
|
||||
JoinType join_type_ = JoinType::Bevel;
|
||||
EndType end_type_ = EndType::Polygon;
|
||||
|
|
@ -64,9 +63,10 @@ private:
|
|||
|
||||
#ifdef USINGZ
|
||||
ZCallback64 zCallback64_ = nullptr;
|
||||
void ZCB(const Point64& bot1, const Point64& top1,
|
||||
const Point64& bot2, const Point64& top2, Point64& ip);
|
||||
#endif
|
||||
DeltaCallback64 deltaCallback64_ = nullptr;
|
||||
|
||||
size_t CalcSolutionCapacity();
|
||||
bool CheckReverseOrientation();
|
||||
void DoBevel(const Path64& path, size_t j, size_t k);
|
||||
|
|
@ -83,7 +83,7 @@ private:
|
|||
public:
|
||||
explicit ClipperOffset(double miter_limit = 2.0,
|
||||
double arc_tolerance = 0.0,
|
||||
bool preserve_collinear = false,
|
||||
bool preserve_collinear = false,
|
||||
bool reverse_solution = false) :
|
||||
miter_limit_(miter_limit), arc_tolerance_(arc_tolerance),
|
||||
preserve_collinear_(preserve_collinear),
|
||||
|
|
@ -91,7 +91,7 @@ public:
|
|||
|
||||
~ClipperOffset() { Clear(); };
|
||||
|
||||
int ErrorCode() { return error_code_; };
|
||||
int ErrorCode() const { return error_code_; };
|
||||
void AddPath(const Path64& path, JoinType jt_, EndType et_);
|
||||
void AddPaths(const Paths64& paths, JoinType jt_, EndType et_);
|
||||
void Clear() { groups_.clear(); norms.clear(); };
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 1 November 2023 *
|
||||
* Date : 5 July 2024 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2023 *
|
||||
* Copyright : Angus Johnson 2010-2024 *
|
||||
* Purpose : FAST rectangular clipping *
|
||||
* License : http://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
|
|
@ -18,6 +18,7 @@
|
|||
namespace Clipper2Lib
|
||||
{
|
||||
|
||||
// Location: the order is important here, see StartLocsIsClockwise()
|
||||
enum class Location { Left, Top, Right, Bottom, Inside };
|
||||
|
||||
class OutPt2;
|
||||
|
|
@ -26,10 +27,10 @@ namespace Clipper2Lib
|
|||
class OutPt2 {
|
||||
public:
|
||||
Point64 pt;
|
||||
size_t owner_idx;
|
||||
OutPt2List* edge;
|
||||
OutPt2* next;
|
||||
OutPt2* prev;
|
||||
size_t owner_idx = 0;
|
||||
OutPt2List* edge = nullptr;
|
||||
OutPt2* next = nullptr;
|
||||
OutPt2* prev = nullptr;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -50,9 +51,9 @@ namespace Clipper2Lib
|
|||
OutPt2List edges_[8]; // clockwise and counter-clockwise
|
||||
std::vector<Location> start_locs_;
|
||||
void CheckEdges();
|
||||
void TidyEdges(int idx, OutPt2List& cw, OutPt2List& ccw);
|
||||
void TidyEdges(size_t idx, OutPt2List& cw, OutPt2List& ccw);
|
||||
void GetNextLocation(const Path64& path,
|
||||
Location& loc, int& i, int highI);
|
||||
Location& loc, size_t& i, size_t highI);
|
||||
OutPt2* Add(Point64 pt, bool start_new = false);
|
||||
void AddCorner(Location prev, Location curr);
|
||||
void AddCorner(Location& loc, bool isClockwise);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef CLIPPER_VERSION_H
|
||||
#define CLIPPER_VERSION_H
|
||||
|
||||
constexpr auto CLIPPER2_VERSION = "1.3.0";
|
||||
constexpr auto CLIPPER2_VERSION = "1.4.0";
|
||||
|
||||
#endif // CLIPPER_VERSION_H
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
diff --git a/thirdparty/clipper2/include/clipper2/clipper.core.h b/thirdparty/clipper2/include/clipper2/clipper.core.h
|
||||
index b3dddeeaa2..a77cdad5f4 100644
|
||||
index 925c04685e..67dd731af6 100644
|
||||
--- a/thirdparty/clipper2/include/clipper2/clipper.core.h
|
||||
+++ b/thirdparty/clipper2/include/clipper2/clipper.core.h
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <numeric>
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <optional>
|
||||
#include "clipper2/clipper.version.h"
|
||||
|
||||
+#define CLIPPER2_THROW(exception) std::abort()
|
||||
|
|
@ -11,7 +11,7 @@ index b3dddeeaa2..a77cdad5f4 100644
|
|||
namespace Clipper2Lib
|
||||
{
|
||||
|
||||
@@ -78,18 +80,18 @@ namespace Clipper2Lib
|
||||
@@ -79,18 +81,18 @@ namespace Clipper2Lib
|
||||
switch (error_code)
|
||||
{
|
||||
case precision_error_i:
|
||||
32
engine/thirdparty/clipper2/patches/0002-llvm-disable-int1280-math.patch
vendored
Normal file
32
engine/thirdparty/clipper2/patches/0002-llvm-disable-int1280-math.patch
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
diff --git a/thirdparty/clipper2/include/clipper2/clipper.core.h b/thirdparty/clipper2/include/clipper2/clipper.core.h
|
||||
index 67dd731af6..dd1b873d5d 100644
|
||||
--- a/thirdparty/clipper2/include/clipper2/clipper.core.h
|
||||
+++ b/thirdparty/clipper2/include/clipper2/clipper.core.h
|
||||
@@ -695,11 +695,13 @@ namespace Clipper2Lib
|
||||
// returns true if (and only if) a * b == c * d
|
||||
inline bool ProductsAreEqual(int64_t a, int64_t b, int64_t c, int64_t d)
|
||||
{
|
||||
-#if (defined(__clang__) || defined(__GNUC__)) && UINTPTR_MAX >= UINT64_MAX
|
||||
- const auto ab = static_cast<__int128_t>(a) * static_cast<__int128_t>(b);
|
||||
- const auto cd = static_cast<__int128_t>(c) * static_cast<__int128_t>(d);
|
||||
- return ab == cd;
|
||||
-#else
|
||||
+// Work around LLVM issue: https://github.com/llvm/llvm-project/issues/16778
|
||||
+// Details: https://github.com/godotengine/godot/pull/95964#issuecomment-2306581804
|
||||
+//#if (defined(__clang__) || defined(__GNUC__)) && UINTPTR_MAX >= UINT64_MAX
|
||||
+// const auto ab = static_cast<__int128_t>(a) * static_cast<__int128_t>(b);
|
||||
+// const auto cd = static_cast<__int128_t>(c) * static_cast<__int128_t>(d);
|
||||
+// return ab == cd;
|
||||
+//#else
|
||||
// nb: unsigned values needed for calculating overflow carry
|
||||
const auto abs_a = static_cast<uint64_t>(std::abs(a));
|
||||
const auto abs_b = static_cast<uint64_t>(std::abs(b));
|
||||
@@ -714,7 +716,7 @@ namespace Clipper2Lib
|
||||
const auto sign_cd = TriSign(c) * TriSign(d);
|
||||
|
||||
return abs_ab == abs_cd && sign_ab == sign_cd;
|
||||
-#endif
|
||||
+// #endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
diff --git a/thirdparty/clipper2/include/clipper2/clipper.core.h b/thirdparty/clipper2/include/clipper2/clipper.core.h
|
||||
index a77cdad5f4..0de7c3720e 100644
|
||||
--- a/thirdparty/clipper2/include/clipper2/clipper.core.h
|
||||
+++ b/thirdparty/clipper2/include/clipper2/clipper.core.h
|
||||
@@ -138,7 +138,7 @@ namespace Clipper2Lib
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
- explicit Point<T>(const Point<T2>& p)
|
||||
+ explicit Point(const Point<T2>& p)
|
||||
{
|
||||
Init(p.x, p.y, p.z);
|
||||
}
|
||||
@@ -180,7 +180,7 @@ namespace Clipper2Lib
|
||||
Point(const T2 x_, const T2 y_) { Init(x_, y_); }
|
||||
|
||||
template <typename T2>
|
||||
- explicit Point<T>(const Point<T2>& p) { Init(p.x, p.y); }
|
||||
+ explicit Point(const Point<T2>& p) { Init(p.x, p.y); }
|
||||
|
||||
Point operator * (const double scale) const
|
||||
{
|
||||
225
engine/thirdparty/clipper2/src/clipper.engine.cpp
vendored
225
engine/thirdparty/clipper2/src/clipper.engine.cpp
vendored
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 22 November 2023 *
|
||||
* Date : 27 April 2024 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2023 *
|
||||
* Copyright : Angus Johnson 2010-2024 *
|
||||
* Purpose : This is the main polygon clipping module *
|
||||
* License : http://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
|
|
@ -31,11 +31,11 @@ namespace Clipper2Lib {
|
|||
|
||||
static const Rect64 invalid_rect = Rect64(false);
|
||||
|
||||
// Every closed path (or polygon) is made up of a series of vertices forming
|
||||
// edges that alternate between going up (relative to the Y-axis) and going
|
||||
// down. Edges consecutively going up or consecutively going down are called
|
||||
// 'bounds' (ie sides if they're simple polygons). 'Local Minima' refer to
|
||||
// vertices where descending bounds become ascending ones.
|
||||
// Every closed path (ie polygon) is made up of a series of vertices forming edge
|
||||
// 'bounds' that alternate between ascending bounds (containing edges going up
|
||||
// relative to the Y-axis) and descending bounds. 'Local Minima' refers to
|
||||
// vertices where ascending and descending bounds join at the bottom, and
|
||||
// 'Local Maxima' are where ascending and descending bounds join at the top.
|
||||
|
||||
struct Scanline {
|
||||
int64_t y = 0;
|
||||
|
|
@ -63,6 +63,7 @@ namespace Clipper2Lib {
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
inline bool IsOdd(int val)
|
||||
{
|
||||
return (val & 1) ? true : false;
|
||||
|
|
@ -188,7 +189,7 @@ namespace Clipper2Lib {
|
|||
}
|
||||
|
||||
//PrevPrevVertex: useful to get the (inverted Y-axis) top of the
|
||||
//alternate edge (ie left or right bound) during edge insertion.
|
||||
//alternate edge (ie left or right bound) during edge insertion.
|
||||
inline Vertex* PrevPrevVertex(const Active& ae)
|
||||
{
|
||||
if (ae.wind_dx > 0)
|
||||
|
|
@ -233,15 +234,15 @@ namespace Clipper2Lib {
|
|||
Vertex* result = e.vertex_top;
|
||||
if (e.wind_dx > 0)
|
||||
while ((result->next->pt.y == result->pt.y) &&
|
||||
((result->flags & (VertexFlags::OpenEnd |
|
||||
((result->flags & (VertexFlags::OpenEnd |
|
||||
VertexFlags::LocalMax)) == VertexFlags::None))
|
||||
result = result->next;
|
||||
else
|
||||
while (result->prev->pt.y == result->pt.y &&
|
||||
((result->flags & (VertexFlags::OpenEnd |
|
||||
((result->flags & (VertexFlags::OpenEnd |
|
||||
VertexFlags::LocalMax)) == VertexFlags::None))
|
||||
result = result->prev;
|
||||
if (!IsMaxima(*result)) result = nullptr; // not a maxima
|
||||
if (!IsMaxima(*result)) result = nullptr; // not a maxima
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -252,7 +253,7 @@ namespace Clipper2Lib {
|
|||
while (result->next->pt.y == result->pt.y) result = result->next;
|
||||
else
|
||||
while (result->prev->pt.y == result->pt.y) result = result->prev;
|
||||
if (!IsMaxima(*result)) result = nullptr; // not a maxima
|
||||
if (!IsMaxima(*result)) result = nullptr; // not a maxima
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -613,13 +614,13 @@ namespace Clipper2Lib {
|
|||
list.push_back(std::make_unique <LocalMinima>(&vert, polytype, is_open));
|
||||
}
|
||||
|
||||
void AddPaths_(const Paths64& paths, PathType polytype, bool is_open,
|
||||
void AddPaths_(const Paths64& paths, PathType polytype, bool is_open,
|
||||
std::vector<Vertex*>& vertexLists, LocalMinimaList& locMinList)
|
||||
{
|
||||
const auto total_vertex_count =
|
||||
std::accumulate(paths.begin(), paths.end(), 0,
|
||||
std::accumulate(paths.begin(), paths.end(), size_t(0),
|
||||
[](const auto& a, const Path64& path)
|
||||
{return a + static_cast<unsigned>(path.size()); });
|
||||
{return a + path.size(); });
|
||||
if (total_vertex_count == 0) return;
|
||||
|
||||
Vertex* vertices = new Vertex[total_vertex_count], * v = vertices;
|
||||
|
|
@ -810,7 +811,7 @@ namespace Clipper2Lib {
|
|||
void ClipperBase::SetZ(const Active& e1, const Active& e2, Point64& ip)
|
||||
{
|
||||
if (!zCallback_) return;
|
||||
// prioritize subject over clip vertices by passing
|
||||
// prioritize subject over clip vertices by passing
|
||||
// subject vertices before clip vertices in the callback
|
||||
if (GetPolyType(e1) == PathType::Subject)
|
||||
{
|
||||
|
|
@ -845,11 +846,11 @@ namespace Clipper2Lib {
|
|||
if (is_open) has_open_paths_ = true;
|
||||
minima_list_sorted_ = false;
|
||||
AddPaths_(paths, polytype, is_open, vertex_lists_, minima_list_);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipperBase::AddReuseableData(const ReuseableDataContainer64& reuseable_data)
|
||||
void ClipperBase::AddReuseableData(const ReuseableDataContainer64& reuseable_data)
|
||||
{
|
||||
// nb: reuseable_data will continue to own the vertices
|
||||
// nb: reuseable_data will continue to own the vertices
|
||||
// and remains responsible for their clean up.
|
||||
succeeded_ = false;
|
||||
minima_list_sorted_ = false;
|
||||
|
|
@ -1117,7 +1118,6 @@ namespace Clipper2Lib {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
bool IsValidAelOrder(const Active& resident, const Active& newcomer)
|
||||
{
|
||||
if (newcomer.curr_x != resident.curr_x)
|
||||
|
|
@ -1149,8 +1149,8 @@ namespace Clipper2Lib {
|
|||
//resident must also have just been inserted
|
||||
else if (resident.is_left_bound != newcomerIsLeft)
|
||||
return newcomerIsLeft;
|
||||
else if (CrossProduct(PrevPrevVertex(resident)->pt,
|
||||
resident.bot, resident.top) == 0) return true;
|
||||
else if (IsCollinear(PrevPrevVertex(resident)->pt,
|
||||
resident.bot, resident.top)) return true;
|
||||
else
|
||||
//compare turning direction of the alternate bound
|
||||
return (CrossProduct(PrevPrevVertex(resident)->pt,
|
||||
|
|
@ -1385,7 +1385,7 @@ namespace Clipper2Lib {
|
|||
{
|
||||
if (IsJoined(e1)) Split(e1, pt);
|
||||
if (IsJoined(e2)) Split(e2, pt);
|
||||
|
||||
|
||||
if (IsFront(e1) == IsFront(e2))
|
||||
{
|
||||
if (IsOpenEnd(e1))
|
||||
|
|
@ -1409,7 +1409,7 @@ namespace Clipper2Lib {
|
|||
{
|
||||
Active* e = GetPrevHotEdge(e1);
|
||||
if (!e)
|
||||
outrec.owner = nullptr;
|
||||
outrec.owner = nullptr;
|
||||
else
|
||||
SetOwner(&outrec, e->outrec);
|
||||
// nb: outRec.owner here is likely NOT the real
|
||||
|
|
@ -1476,7 +1476,7 @@ namespace Clipper2Lib {
|
|||
e2.outrec->pts = e1.outrec->pts;
|
||||
e1.outrec->pts = nullptr;
|
||||
}
|
||||
else
|
||||
else
|
||||
SetOwner(e2.outrec, e1.outrec);
|
||||
|
||||
//and e1 and e2 are maxima and are about to be dropped from the Actives list.
|
||||
|
|
@ -1526,7 +1526,6 @@ namespace Clipper2Lib {
|
|||
return new_op;
|
||||
}
|
||||
|
||||
|
||||
void ClipperBase::CleanCollinear(OutRec* outrec)
|
||||
{
|
||||
outrec = GetRealOutRec(outrec);
|
||||
|
|
@ -1541,7 +1540,7 @@ namespace Clipper2Lib {
|
|||
for (; ; )
|
||||
{
|
||||
//NB if preserveCollinear == true, then only remove 180 deg. spikes
|
||||
if ((CrossProduct(op2->prev->pt, op2->pt, op2->next->pt) == 0) &&
|
||||
if (IsCollinear(op2->prev->pt, op2->pt, op2->next->pt) &&
|
||||
(op2->pt == op2->prev->pt ||
|
||||
op2->pt == op2->next->pt || !preserve_collinear_ ||
|
||||
DotProduct(op2->prev->pt, op2->pt, op2->next->pt) < 0))
|
||||
|
|
@ -1566,14 +1565,14 @@ namespace Clipper2Lib {
|
|||
|
||||
void ClipperBase::DoSplitOp(OutRec* outrec, OutPt* splitOp)
|
||||
{
|
||||
// splitOp.prev -> splitOp &&
|
||||
// splitOp.prev -> splitOp &&
|
||||
// splitOp.next -> splitOp.next.next are intersecting
|
||||
OutPt* prevOp = splitOp->prev;
|
||||
OutPt* nextNextOp = splitOp->next->next;
|
||||
outrec->pts = prevOp;
|
||||
|
||||
Point64 ip;
|
||||
GetIntersectPoint(prevOp->pt, splitOp->pt,
|
||||
GetSegmentIntersectPt(prevOp->pt, splitOp->pt,
|
||||
splitOp->next->pt, nextNextOp->pt, ip);
|
||||
|
||||
#ifdef USINGZ
|
||||
|
|
@ -1617,7 +1616,7 @@ namespace Clipper2Lib {
|
|||
{
|
||||
OutRec* newOr = NewOutRec();
|
||||
newOr->owner = outrec->owner;
|
||||
|
||||
|
||||
splitOp->outrec = newOr;
|
||||
splitOp->next->outrec = newOr;
|
||||
OutPt* newOp = new OutPt(ip, newOr);
|
||||
|
|
@ -1772,12 +1771,12 @@ namespace Clipper2Lib {
|
|||
}
|
||||
|
||||
|
||||
OutPt* ClipperBase::IntersectEdges(Active& e1, Active& e2, const Point64& pt)
|
||||
void ClipperBase::IntersectEdges(Active& e1, Active& e2, const Point64& pt)
|
||||
{
|
||||
//MANAGE OPEN PATH INTERSECTIONS SEPARATELY ...
|
||||
if (has_open_paths_ && (IsOpen(e1) || IsOpen(e2)))
|
||||
{
|
||||
if (IsOpen(e1) && IsOpen(e2)) return nullptr;
|
||||
if (IsOpen(e1) && IsOpen(e2)) return;
|
||||
Active* edge_o, * edge_c;
|
||||
if (IsOpen(e1))
|
||||
{
|
||||
|
|
@ -1791,29 +1790,40 @@ namespace Clipper2Lib {
|
|||
}
|
||||
if (IsJoined(*edge_c)) Split(*edge_c, pt); // needed for safety
|
||||
|
||||
if (abs(edge_c->wind_cnt) != 1) return nullptr;
|
||||
if (abs(edge_c->wind_cnt) != 1) return;
|
||||
switch (cliptype_)
|
||||
{
|
||||
case ClipType::Union:
|
||||
if (!IsHotEdge(*edge_c)) return nullptr;
|
||||
if (!IsHotEdge(*edge_c)) return;
|
||||
break;
|
||||
default:
|
||||
if (edge_c->local_min->polytype == PathType::Subject)
|
||||
return nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (fillrule_)
|
||||
{
|
||||
case FillRule::Positive: if (edge_c->wind_cnt != 1) return nullptr; break;
|
||||
case FillRule::Negative: if (edge_c->wind_cnt != -1) return nullptr; break;
|
||||
default: if (std::abs(edge_c->wind_cnt) != 1) return nullptr; break;
|
||||
case FillRule::Positive:
|
||||
if (edge_c->wind_cnt != 1) return;
|
||||
break;
|
||||
case FillRule::Negative:
|
||||
if (edge_c->wind_cnt != -1) return;
|
||||
break;
|
||||
default:
|
||||
if (std::abs(edge_c->wind_cnt) != 1) return;
|
||||
}
|
||||
|
||||
#ifdef USINGZ
|
||||
OutPt* resultOp;
|
||||
#endif
|
||||
//toggle contribution ...
|
||||
if (IsHotEdge(*edge_o))
|
||||
{
|
||||
#ifdef USINGZ
|
||||
resultOp = AddOutPt(*edge_o, pt);
|
||||
#else
|
||||
AddOutPt(*edge_o, pt);
|
||||
#endif
|
||||
if (IsFront(*edge_o)) edge_o->outrec->front_edge = nullptr;
|
||||
else edge_o->outrec->back_edge = nullptr;
|
||||
edge_o->outrec = nullptr;
|
||||
|
|
@ -1833,18 +1843,26 @@ namespace Clipper2Lib {
|
|||
SetSides(*e3->outrec, *edge_o, *e3);
|
||||
else
|
||||
SetSides(*e3->outrec, *e3, *edge_o);
|
||||
return e3->outrec->pts;
|
||||
return;
|
||||
}
|
||||
else
|
||||
#ifdef USINGZ
|
||||
resultOp = StartOpenPath(*edge_o, pt);
|
||||
#else
|
||||
StartOpenPath(*edge_o, pt);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
#ifdef USINGZ
|
||||
resultOp = StartOpenPath(*edge_o, pt);
|
||||
#else
|
||||
StartOpenPath(*edge_o, pt);
|
||||
#endif
|
||||
|
||||
#ifdef USINGZ
|
||||
if (zCallback_) SetZ(*edge_o, *edge_c, resultOp->pt);
|
||||
#endif
|
||||
return resultOp;
|
||||
return;
|
||||
} // end of an open path intersection
|
||||
|
||||
//MANAGING CLOSED PATHS FROM HERE ON
|
||||
|
|
@ -1913,22 +1931,25 @@ namespace Clipper2Lib {
|
|||
const bool e1_windcnt_in_01 = old_e1_windcnt == 0 || old_e1_windcnt == 1;
|
||||
const bool e2_windcnt_in_01 = old_e2_windcnt == 0 || old_e2_windcnt == 1;
|
||||
|
||||
if ((!IsHotEdge(e1) && !e1_windcnt_in_01) || (!IsHotEdge(e2) && !e2_windcnt_in_01))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
if ((!IsHotEdge(e1) && !e1_windcnt_in_01) ||
|
||||
(!IsHotEdge(e2) && !e2_windcnt_in_01))
|
||||
return;
|
||||
|
||||
//NOW PROCESS THE INTERSECTION ...
|
||||
#ifdef USINGZ
|
||||
OutPt* resultOp = nullptr;
|
||||
#endif
|
||||
//if both edges are 'hot' ...
|
||||
if (IsHotEdge(e1) && IsHotEdge(e2))
|
||||
{
|
||||
if ((old_e1_windcnt != 0 && old_e1_windcnt != 1) || (old_e2_windcnt != 0 && old_e2_windcnt != 1) ||
|
||||
(e1.local_min->polytype != e2.local_min->polytype && cliptype_ != ClipType::Xor))
|
||||
{
|
||||
resultOp = AddLocalMaxPoly(e1, e2, pt);
|
||||
#ifdef USINGZ
|
||||
resultOp = AddLocalMaxPoly(e1, e2, pt);
|
||||
if (zCallback_ && resultOp) SetZ(e1, e2, resultOp->pt);
|
||||
#else
|
||||
AddLocalMaxPoly(e1, e2, pt);
|
||||
#endif
|
||||
}
|
||||
else if (IsFront(e1) || (e1.outrec == e2.outrec))
|
||||
|
|
@ -1937,19 +1958,20 @@ namespace Clipper2Lib {
|
|||
//it's sensible to split polygons that ony touch at
|
||||
//a common vertex (not at common edges).
|
||||
|
||||
resultOp = AddLocalMaxPoly(e1, e2, pt);
|
||||
#ifdef USINGZ
|
||||
resultOp = AddLocalMaxPoly(e1, e2, pt);
|
||||
OutPt* op2 = AddLocalMinPoly(e1, e2, pt);
|
||||
if (zCallback_ && resultOp) SetZ(e1, e2, resultOp->pt);
|
||||
if (zCallback_) SetZ(e1, e2, op2->pt);
|
||||
#else
|
||||
AddLocalMaxPoly(e1, e2, pt);
|
||||
AddLocalMinPoly(e1, e2, pt);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
resultOp = AddOutPt(e1, pt);
|
||||
#ifdef USINGZ
|
||||
resultOp = AddOutPt(e1, pt);
|
||||
OutPt* op2 = AddOutPt(e2, pt);
|
||||
if (zCallback_)
|
||||
{
|
||||
|
|
@ -1957,6 +1979,7 @@ namespace Clipper2Lib {
|
|||
SetZ(e1, e2, op2->pt);
|
||||
}
|
||||
#else
|
||||
AddOutPt(e1, pt);
|
||||
AddOutPt(e2, pt);
|
||||
#endif
|
||||
SwapOutrecs(e1, e2);
|
||||
|
|
@ -1964,17 +1987,21 @@ namespace Clipper2Lib {
|
|||
}
|
||||
else if (IsHotEdge(e1))
|
||||
{
|
||||
resultOp = AddOutPt(e1, pt);
|
||||
#ifdef USINGZ
|
||||
resultOp = AddOutPt(e1, pt);
|
||||
if (zCallback_) SetZ(e1, e2, resultOp->pt);
|
||||
#else
|
||||
AddOutPt(e1, pt);
|
||||
#endif
|
||||
SwapOutrecs(e1, e2);
|
||||
}
|
||||
else if (IsHotEdge(e2))
|
||||
{
|
||||
resultOp = AddOutPt(e2, pt);
|
||||
#ifdef USINGZ
|
||||
resultOp = AddOutPt(e2, pt);
|
||||
if (zCallback_) SetZ(e1, e2, resultOp->pt);
|
||||
#else
|
||||
AddOutPt(e2, pt);
|
||||
#endif
|
||||
SwapOutrecs(e1, e2);
|
||||
}
|
||||
|
|
@ -2004,33 +2031,53 @@ namespace Clipper2Lib {
|
|||
|
||||
if (!IsSamePolyType(e1, e2))
|
||||
{
|
||||
resultOp = AddLocalMinPoly(e1, e2, pt, false);
|
||||
#ifdef USINGZ
|
||||
resultOp = AddLocalMinPoly(e1, e2, pt, false);
|
||||
if (zCallback_) SetZ(e1, e2, resultOp->pt);
|
||||
#else
|
||||
AddLocalMinPoly(e1, e2, pt, false);
|
||||
#endif
|
||||
}
|
||||
else if (old_e1_windcnt == 1 && old_e2_windcnt == 1)
|
||||
{
|
||||
#ifdef USINGZ
|
||||
resultOp = nullptr;
|
||||
#endif
|
||||
switch (cliptype_)
|
||||
{
|
||||
case ClipType::Union:
|
||||
if (e1Wc2 <= 0 && e2Wc2 <= 0)
|
||||
#ifdef USINGZ
|
||||
resultOp = AddLocalMinPoly(e1, e2, pt, false);
|
||||
#else
|
||||
AddLocalMinPoly(e1, e2, pt, false);
|
||||
#endif
|
||||
break;
|
||||
case ClipType::Difference:
|
||||
if (((GetPolyType(e1) == PathType::Clip) && (e1Wc2 > 0) && (e2Wc2 > 0)) ||
|
||||
((GetPolyType(e1) == PathType::Subject) && (e1Wc2 <= 0) && (e2Wc2 <= 0)))
|
||||
{
|
||||
#ifdef USINGZ
|
||||
resultOp = AddLocalMinPoly(e1, e2, pt, false);
|
||||
#else
|
||||
AddLocalMinPoly(e1, e2, pt, false);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case ClipType::Xor:
|
||||
#ifdef USINGZ
|
||||
resultOp = AddLocalMinPoly(e1, e2, pt, false);
|
||||
#else
|
||||
AddLocalMinPoly(e1, e2, pt, false);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
if (e1Wc2 > 0 && e2Wc2 > 0)
|
||||
#ifdef USINGZ
|
||||
resultOp = AddLocalMinPoly(e1, e2, pt, false);
|
||||
#else
|
||||
AddLocalMinPoly(e1, e2, pt, false);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
#ifdef USINGZ
|
||||
|
|
@ -2038,7 +2085,6 @@ namespace Clipper2Lib {
|
|||
#endif
|
||||
}
|
||||
}
|
||||
return resultOp;
|
||||
}
|
||||
|
||||
inline void ClipperBase::DeleteFromAEL(Active& e)
|
||||
|
|
@ -2065,7 +2111,7 @@ namespace Clipper2Lib {
|
|||
e->next_in_sel = e->next_in_ael;
|
||||
e->jump = e->next_in_sel;
|
||||
if (e->join_with == JoinWith::Left)
|
||||
e->curr_x = e->prev_in_ael->curr_x; // also avoids complications
|
||||
e->curr_x = e->prev_in_ael->curr_x; // also avoids complications
|
||||
else
|
||||
e->curr_x = TopX(*e, top_y);
|
||||
e = e->next_in_ael;
|
||||
|
|
@ -2138,7 +2184,7 @@ namespace Clipper2Lib {
|
|||
if (outrecHasEdges)
|
||||
{
|
||||
OutPt* opA = outrec->pts, * opZ = opA->next;
|
||||
while (opP != opZ && opP->prev->pt.y == curr_y)
|
||||
while (opP != opZ && opP->prev->pt.y == curr_y)
|
||||
opP = opP->prev;
|
||||
while (opN != opA && opN->next->pt.y == curr_y)
|
||||
opN = opN->next;
|
||||
|
|
@ -2150,7 +2196,7 @@ namespace Clipper2Lib {
|
|||
while (opN->next != opP && opN->next->pt.y == curr_y)
|
||||
opN = opN->next;
|
||||
}
|
||||
bool result =
|
||||
bool result =
|
||||
SetHorzSegHeadingForward(hs, opP, opN) &&
|
||||
!hs.left_op->horz;
|
||||
|
||||
|
|
@ -2160,13 +2206,14 @@ namespace Clipper2Lib {
|
|||
hs.right_op = nullptr; // (for sorting)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void ClipperBase::ConvertHorzSegsToJoins()
|
||||
{
|
||||
auto j = std::count_if(horz_seg_list_.begin(),
|
||||
auto j = std::count_if(horz_seg_list_.begin(),
|
||||
horz_seg_list_.end(),
|
||||
[](HorzSegment& hs) { return UpdateHorzSegment(hs); });
|
||||
if (j < 2) return;
|
||||
|
||||
std::stable_sort(horz_seg_list_.begin(), horz_seg_list_.end(), HorzSegSorter());
|
||||
|
||||
HorzSegmentList::iterator hs1 = horz_seg_list_.begin(), hs2;
|
||||
|
|
@ -2207,8 +2254,8 @@ namespace Clipper2Lib {
|
|||
DuplicateOp(hs1->left_op, false));
|
||||
horz_join_list_.push_back(join);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MoveSplits(OutRec* fromOr, OutRec* toOr)
|
||||
|
|
@ -2301,7 +2348,7 @@ namespace Clipper2Lib {
|
|||
void ClipperBase::AddNewIntersectNode(Active& e1, Active& e2, int64_t top_y)
|
||||
{
|
||||
Point64 ip;
|
||||
if (!GetIntersectPoint(e1.bot, e1.top, e2.bot, e2.top, ip))
|
||||
if (!GetSegmentIntersectPt(e1.bot, e1.top, e2.bot, e2.top, ip))
|
||||
ip = Point64(e1.curr_x, top_y); //parallel edges
|
||||
|
||||
//rounding errors can occasionally place the calculated intersection
|
||||
|
|
@ -2321,7 +2368,7 @@ namespace Clipper2Lib {
|
|||
ip = GetClosestPointOnSegment(ip, e1.bot, e1.top);
|
||||
else if (abs_dx2 > 100)
|
||||
ip = GetClosestPointOnSegment(ip, e2.bot, e2.top);
|
||||
else
|
||||
else
|
||||
{
|
||||
if (ip.y < top_y) ip.y = top_y;
|
||||
else ip.y = bot_y_;
|
||||
|
|
@ -2453,7 +2500,7 @@ namespace Clipper2Lib {
|
|||
horz_seg_list_.push_back(HorzSegment(op));
|
||||
}
|
||||
|
||||
bool ClipperBase::ResetHorzDirection(const Active& horz,
|
||||
bool ClipperBase::ResetHorzDirection(const Active& horz,
|
||||
const Vertex* max_vertex, int64_t& horz_left, int64_t& horz_right)
|
||||
{
|
||||
if (horz.bot.x == horz.top.x)
|
||||
|
|
@ -2536,8 +2583,8 @@ namespace Clipper2Lib {
|
|||
if (IsHotEdge(horz) && IsJoined(*e))
|
||||
Split(*e, e->top);
|
||||
|
||||
//if (IsHotEdge(horz) != IsHotEdge(*e))
|
||||
// DoError(undefined_error_i);
|
||||
//if (IsHotEdge(horz) != IsHotEdge(*e))
|
||||
// DoError(undefined_error_i);
|
||||
|
||||
if (IsHotEdge(horz))
|
||||
{
|
||||
|
|
@ -2641,7 +2688,7 @@ namespace Clipper2Lib {
|
|||
ResetHorzDirection(horz, vertex_max, horz_left, horz_right);
|
||||
}
|
||||
|
||||
if (IsHotEdge(horz))
|
||||
if (IsHotEdge(horz))
|
||||
{
|
||||
OutPt* op = AddOutPt(horz, horz.top);
|
||||
AddTrialHorzJoin(op);
|
||||
|
|
@ -2754,21 +2801,23 @@ namespace Clipper2Lib {
|
|||
}
|
||||
}
|
||||
|
||||
void ClipperBase::CheckJoinLeft(Active& e,
|
||||
void ClipperBase::CheckJoinLeft(Active& e,
|
||||
const Point64& pt, bool check_curr_x)
|
||||
{
|
||||
Active* prev = e.prev_in_ael;
|
||||
if (IsOpen(e) || !IsHotEdge(e) || !prev ||
|
||||
IsOpen(*prev) || !IsHotEdge(*prev)) return;
|
||||
if (!prev ||
|
||||
!IsHotEdge(e) || !IsHotEdge(*prev) ||
|
||||
IsHorizontal(e) || IsHorizontal(*prev) ||
|
||||
IsOpen(e) || IsOpen(*prev) ) return;
|
||||
if ((pt.y < e.top.y + 2 || pt.y < prev->top.y + 2) &&
|
||||
((e.bot.y > pt.y) || (prev->bot.y > pt.y))) return; // avoid trivial joins
|
||||
((e.bot.y > pt.y) || (prev->bot.y > pt.y))) return; // avoid trivial joins
|
||||
|
||||
if (check_curr_x)
|
||||
{
|
||||
if (DistanceFromLineSqrd(pt, prev->bot, prev->top) > 0.25) return;
|
||||
if (PerpendicDistFromLineSqrd(pt, prev->bot, prev->top) > 0.25) return;
|
||||
}
|
||||
else if (e.curr_x != prev->curr_x) return;
|
||||
if (CrossProduct(e.top, pt, prev->top)) return;
|
||||
if (!IsCollinear(e.top, pt, prev->top)) return;
|
||||
|
||||
if (e.outrec->idx == prev->outrec->idx)
|
||||
AddLocalMaxPoly(*prev, e, pt);
|
||||
|
|
@ -2780,22 +2829,24 @@ namespace Clipper2Lib {
|
|||
e.join_with = JoinWith::Left;
|
||||
}
|
||||
|
||||
void ClipperBase::CheckJoinRight(Active& e,
|
||||
void ClipperBase::CheckJoinRight(Active& e,
|
||||
const Point64& pt, bool check_curr_x)
|
||||
{
|
||||
Active* next = e.next_in_ael;
|
||||
if (IsOpen(e) || !IsHotEdge(e) ||
|
||||
!next || IsOpen(*next) || !IsHotEdge(*next)) return;
|
||||
if (!next ||
|
||||
!IsHotEdge(e) || !IsHotEdge(*next) ||
|
||||
IsHorizontal(e) || IsHorizontal(*next) ||
|
||||
IsOpen(e) || IsOpen(*next)) return;
|
||||
if ((pt.y < e.top.y +2 || pt.y < next->top.y +2) &&
|
||||
((e.bot.y > pt.y) || (next->bot.y > pt.y))) return; // avoid trivial joins
|
||||
((e.bot.y > pt.y) || (next->bot.y > pt.y))) return; // avoid trivial joins
|
||||
|
||||
if (check_curr_x)
|
||||
{
|
||||
if (DistanceFromLineSqrd(pt, next->bot, next->top) > 0.35) return;
|
||||
if (PerpendicDistFromLineSqrd(pt, next->bot, next->top) > 0.35) return;
|
||||
}
|
||||
else if (e.curr_x != next->curr_x) return;
|
||||
if (CrossProduct(e.top, pt, next->top)) return;
|
||||
|
||||
if (!IsCollinear(e.top, pt, next->top)) return;
|
||||
|
||||
if (e.outrec->idx == next->outrec->idx)
|
||||
AddLocalMaxPoly(e, *next, pt);
|
||||
else if (e.outrec->idx < next->outrec->idx)
|
||||
|
|
@ -2863,7 +2914,7 @@ namespace Clipper2Lib {
|
|||
op2 = op2->next;
|
||||
}
|
||||
|
||||
if (path.size() == 3 && IsVerySmallTriangle(*op2)) return false;
|
||||
if (!isOpen && path.size() == 3 && IsVerySmallTriangle(*op2)) return false;
|
||||
else return true;
|
||||
}
|
||||
|
||||
|
|
@ -2872,8 +2923,8 @@ namespace Clipper2Lib {
|
|||
if (!outrec->pts) return false;
|
||||
if (!outrec->bounds.IsEmpty()) return true;
|
||||
CleanCollinear(outrec);
|
||||
if (!outrec->pts ||
|
||||
!BuildPath64(outrec->pts, reverse_solution_, false, outrec->path)){
|
||||
if (!outrec->pts ||
|
||||
!BuildPath64(outrec->pts, reverse_solution_, false, outrec->path)){
|
||||
return false;}
|
||||
outrec->bounds = GetBounds(outrec->path);
|
||||
return true;
|
||||
|
|
@ -2887,10 +2938,10 @@ namespace Clipper2Lib {
|
|||
if(!split || split == outrec || split->recursive_split == outrec) continue;
|
||||
split->recursive_split = outrec; // prevent infinite loops
|
||||
|
||||
if (split->splits && CheckSplitOwner(outrec, split->splits))
|
||||
if (split->splits && CheckSplitOwner(outrec, split->splits))
|
||||
return true;
|
||||
else if (CheckBounds(split) &&
|
||||
IsValidOwner(outrec, split) &&
|
||||
else if (CheckBounds(split) &&
|
||||
IsValidOwner(outrec, split) &&
|
||||
split->bounds.Contains(outrec->bounds) &&
|
||||
Path1InsidePath2(outrec->pts, split->pts))
|
||||
{
|
||||
|
|
@ -2919,7 +2970,7 @@ namespace Clipper2Lib {
|
|||
|
||||
if (outrec->owner)
|
||||
{
|
||||
if (!outrec->owner->polypath)
|
||||
if (!outrec->owner->polypath)
|
||||
RecursiveCheckOwners(outrec->owner, polypath);
|
||||
outrec->polypath = outrec->owner->polypath->AddChild(outrec->path);
|
||||
}
|
||||
|
|
@ -2968,7 +3019,7 @@ namespace Clipper2Lib {
|
|||
open_paths.resize(0);
|
||||
if (has_open_paths_)
|
||||
open_paths.reserve(outrec_list_.size());
|
||||
|
||||
|
||||
// outrec_list_.size() is not static here because
|
||||
// CheckBounds below can indirectly add additional
|
||||
// OutRec (via FixOutRecPts & CleanCollinear)
|
||||
|
|
@ -2991,7 +3042,7 @@ namespace Clipper2Lib {
|
|||
|
||||
bool BuildPathD(OutPt* op, bool reverse, bool isOpen, PathD& path, double inv_scale)
|
||||
{
|
||||
if (!op || op->next == op || (!isOpen && op->next == op->prev))
|
||||
if (!op || op->next == op || (!isOpen && op->next == op->prev))
|
||||
return false;
|
||||
|
||||
path.resize(0);
|
||||
|
|
@ -3024,7 +3075,7 @@ namespace Clipper2Lib {
|
|||
#else
|
||||
path.push_back(PointD(lastPt.x * inv_scale, lastPt.y * inv_scale));
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
if (reverse)
|
||||
op2 = op2->prev;
|
||||
|
|
|
|||
366
engine/thirdparty/clipper2/src/clipper.offset.cpp
vendored
366
engine/thirdparty/clipper2/src/clipper.offset.cpp
vendored
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 28 November 2023 *
|
||||
* Date : 17 April 2024 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2023 *
|
||||
* Copyright : Angus Johnson 2010-2024 *
|
||||
* Purpose : Path Offset (Inflate/Shrink) *
|
||||
* License : http://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
|
|
@ -20,60 +20,19 @@ const double floating_point_tolerance = 1e-12;
|
|||
// Miscellaneous methods
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline bool ToggleBoolIf(bool val, bool condition)
|
||||
std::optional<size_t> GetLowestClosedPathIdx(const Paths64& paths)
|
||||
{
|
||||
return condition ? !val : val;
|
||||
}
|
||||
|
||||
void GetMultiBounds(const Paths64& paths, std::vector<Rect64>& recList)
|
||||
{
|
||||
recList.reserve(paths.size());
|
||||
for (const Path64& path : paths)
|
||||
{
|
||||
if (path.size() < 1)
|
||||
{
|
||||
recList.push_back(InvalidRect64);
|
||||
continue;
|
||||
}
|
||||
int64_t x = path[0].x, y = path[0].y;
|
||||
Rect64 r = Rect64(x, y, x, y);
|
||||
for (const Point64& pt : path)
|
||||
{
|
||||
if (pt.y > r.bottom) r.bottom = pt.y;
|
||||
else if (pt.y < r.top) r.top = pt.y;
|
||||
if (pt.x > r.right) r.right = pt.x;
|
||||
else if (pt.x < r.left) r.left = pt.x;
|
||||
}
|
||||
recList.push_back(r);
|
||||
}
|
||||
}
|
||||
|
||||
bool ValidateBounds(std::vector<Rect64>& recList, double delta)
|
||||
{
|
||||
int64_t int_delta = static_cast<int64_t>(delta);
|
||||
int64_t big = MAX_COORD - int_delta;
|
||||
int64_t small = MIN_COORD + int_delta;
|
||||
for (const Rect64& r : recList)
|
||||
{
|
||||
if (!r.IsValid()) continue; // ignore invalid paths
|
||||
else if (r.left < small || r.right > big ||
|
||||
r.top < small || r.bottom > big) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int GetLowestClosedPathIdx(std::vector<Rect64>& boundsList)
|
||||
{
|
||||
int i = -1, result = -1;
|
||||
std::optional<size_t> result;
|
||||
Point64 botPt = Point64(INT64_MAX, INT64_MIN);
|
||||
for (const Rect64& r : boundsList)
|
||||
{
|
||||
++i;
|
||||
if (!r.IsValid()) continue; // ignore invalid paths
|
||||
else if (r.bottom > botPt.y || (r.bottom == botPt.y && r.left < botPt.x))
|
||||
for (size_t i = 0; i < paths.size(); ++i)
|
||||
{
|
||||
for (const Point64& pt : paths[i])
|
||||
{
|
||||
botPt = Point64(r.left, r.bottom);
|
||||
result = static_cast<int>(i);
|
||||
if ((pt.y < botPt.y) ||
|
||||
((pt.y == botPt.y) && (pt.x >= botPt.x))) continue;
|
||||
result = i;
|
||||
botPt.x = pt.x;
|
||||
botPt.y = pt.y;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
@ -96,14 +55,14 @@ inline bool AlmostZero(double value, double epsilon = 0.001)
|
|||
return std::fabs(value) < epsilon;
|
||||
}
|
||||
|
||||
inline double Hypot(double x, double y)
|
||||
inline double Hypot(double x, double y)
|
||||
{
|
||||
//see https://stackoverflow.com/a/32436148/359538
|
||||
return std::sqrt(x * x + y * y);
|
||||
}
|
||||
|
||||
inline PointD NormalizeVector(const PointD& vec)
|
||||
{
|
||||
{
|
||||
double h = Hypot(vec.x, vec.y);
|
||||
if (AlmostZero(h)) return PointD(0,0);
|
||||
double inverseHypot = 1 / h;
|
||||
|
|
@ -164,30 +123,21 @@ ClipperOffset::Group::Group(const Paths64& _paths, JoinType _join_type, EndType
|
|||
for (Path64& p: paths_in)
|
||||
StripDuplicates(p, is_joined);
|
||||
|
||||
// get bounds of each path --> bounds_list
|
||||
GetMultiBounds(paths_in, bounds_list);
|
||||
|
||||
if (end_type == EndType::Polygon)
|
||||
{
|
||||
is_hole_list.reserve(paths_in.size());
|
||||
for (const Path64& path : paths_in)
|
||||
is_hole_list.push_back(Area(path) < 0);
|
||||
lowest_path_idx = GetLowestClosedPathIdx(bounds_list);
|
||||
lowest_path_idx = GetLowestClosedPathIdx(paths_in);
|
||||
// the lowermost path must be an outer path, so if its orientation is negative,
|
||||
// then flag the whole group is 'reversed' (will negate delta etc.)
|
||||
// as this is much more efficient than reversing every path.
|
||||
is_reversed = (lowest_path_idx >= 0) && is_hole_list[lowest_path_idx];
|
||||
if (is_reversed) is_hole_list.flip();
|
||||
is_reversed = (lowest_path_idx.has_value()) && Area(paths_in[lowest_path_idx.value()]) < 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
lowest_path_idx = -1;
|
||||
lowest_path_idx = std::nullopt;
|
||||
is_reversed = false;
|
||||
is_hole_list.resize(paths_in.size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// ClipperOffset methods
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
@ -216,66 +166,29 @@ void ClipperOffset::BuildNormals(const Path64& path)
|
|||
norms.push_back(GetUnitNormal(*path_stop_iter, *(path.cbegin())));
|
||||
}
|
||||
|
||||
inline PointD TranslatePoint(const PointD& pt, double dx, double dy)
|
||||
{
|
||||
#ifdef USINGZ
|
||||
return PointD(pt.x + dx, pt.y + dy, pt.z);
|
||||
#else
|
||||
return PointD(pt.x + dx, pt.y + dy);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline PointD ReflectPoint(const PointD& pt, const PointD& pivot)
|
||||
{
|
||||
#ifdef USINGZ
|
||||
return PointD(pivot.x + (pivot.x - pt.x), pivot.y + (pivot.y - pt.y), pt.z);
|
||||
#else
|
||||
return PointD(pivot.x + (pivot.x - pt.x), pivot.y + (pivot.y - pt.y));
|
||||
#endif
|
||||
}
|
||||
|
||||
PointD IntersectPoint(const PointD& pt1a, const PointD& pt1b,
|
||||
const PointD& pt2a, const PointD& pt2b)
|
||||
{
|
||||
if (pt1a.x == pt1b.x) //vertical
|
||||
{
|
||||
if (pt2a.x == pt2b.x) return PointD(0, 0);
|
||||
|
||||
double m2 = (pt2b.y - pt2a.y) / (pt2b.x - pt2a.x);
|
||||
double b2 = pt2a.y - m2 * pt2a.x;
|
||||
return PointD(pt1a.x, m2 * pt1a.x + b2);
|
||||
}
|
||||
else if (pt2a.x == pt2b.x) //vertical
|
||||
{
|
||||
double m1 = (pt1b.y - pt1a.y) / (pt1b.x - pt1a.x);
|
||||
double b1 = pt1a.y - m1 * pt1a.x;
|
||||
return PointD(pt2a.x, m1 * pt2a.x + b1);
|
||||
}
|
||||
else
|
||||
{
|
||||
double m1 = (pt1b.y - pt1a.y) / (pt1b.x - pt1a.x);
|
||||
double b1 = pt1a.y - m1 * pt1a.x;
|
||||
double m2 = (pt2b.y - pt2a.y) / (pt2b.x - pt2a.x);
|
||||
double b2 = pt2a.y - m2 * pt2a.x;
|
||||
if (m1 == m2) return PointD(0, 0);
|
||||
double x = (b2 - b1) / (m1 - m2);
|
||||
return PointD(x, m1 * x + b1);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipperOffset::DoBevel(const Path64& path, size_t j, size_t k)
|
||||
{
|
||||
PointD pt1, pt2;
|
||||
if (j == k)
|
||||
{
|
||||
double abs_delta = std::abs(group_delta_);
|
||||
#ifdef USINGZ
|
||||
pt1 = PointD(path[j].x - abs_delta * norms[j].x, path[j].y - abs_delta * norms[j].y, path[j].z);
|
||||
pt2 = PointD(path[j].x + abs_delta * norms[j].x, path[j].y + abs_delta * norms[j].y, path[j].z);
|
||||
#else
|
||||
pt1 = PointD(path[j].x - abs_delta * norms[j].x, path[j].y - abs_delta * norms[j].y);
|
||||
pt2 = PointD(path[j].x + abs_delta * norms[j].x, path[j].y + abs_delta * norms[j].y);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef USINGZ
|
||||
pt1 = PointD(path[j].x + group_delta_ * norms[k].x, path[j].y + group_delta_ * norms[k].y, path[j].z);
|
||||
pt2 = PointD(path[j].x + group_delta_ * norms[j].x, path[j].y + group_delta_ * norms[j].y, path[j].z);
|
||||
#else
|
||||
pt1 = PointD(path[j].x + group_delta_ * norms[k].x, path[j].y + group_delta_ * norms[k].y);
|
||||
pt2 = PointD(path[j].x + group_delta_ * norms[j].x, path[j].y + group_delta_ * norms[j].y);
|
||||
#endif
|
||||
}
|
||||
path_out.push_back(Point64(pt1));
|
||||
path_out.push_back(Point64(pt2));
|
||||
|
|
@ -284,7 +197,7 @@ void ClipperOffset::DoBevel(const Path64& path, size_t j, size_t k)
|
|||
void ClipperOffset::DoSquare(const Path64& path, size_t j, size_t k)
|
||||
{
|
||||
PointD vec;
|
||||
if (j == k)
|
||||
if (j == k)
|
||||
vec = PointD(norms[j].y, -norms[j].x);
|
||||
else
|
||||
vec = GetAvgUnitVector(
|
||||
|
|
@ -304,10 +217,8 @@ void ClipperOffset::DoSquare(const Path64& path, size_t j, size_t k)
|
|||
if (j == k)
|
||||
{
|
||||
PointD pt4 = PointD(pt3.x + vec.x * group_delta_, pt3.y + vec.y * group_delta_);
|
||||
PointD pt = IntersectPoint(pt1, pt2, pt3, pt4);
|
||||
#ifdef USINGZ
|
||||
pt.z = ptQ.z;
|
||||
#endif
|
||||
PointD pt = ptQ;
|
||||
GetSegmentIntersectPt(pt1, pt2, pt3, pt4, pt);
|
||||
//get the second intersect point through reflecion
|
||||
path_out.push_back(Point64(ReflectPoint(pt, ptQ)));
|
||||
path_out.push_back(Point64(pt));
|
||||
|
|
@ -315,10 +226,8 @@ void ClipperOffset::DoSquare(const Path64& path, size_t j, size_t k)
|
|||
else
|
||||
{
|
||||
PointD pt4 = GetPerpendicD(path[j], norms[k], group_delta_);
|
||||
PointD pt = IntersectPoint(pt1, pt2, pt3, pt4);
|
||||
#ifdef USINGZ
|
||||
pt.z = ptQ.z;
|
||||
#endif
|
||||
PointD pt = ptQ;
|
||||
GetSegmentIntersectPt(pt1, pt2, pt3, pt4, pt);
|
||||
path_out.push_back(Point64(pt));
|
||||
//get the second intersect point through reflecion
|
||||
path_out.push_back(Point64(ReflectPoint(pt, ptQ)));
|
||||
|
|
@ -343,7 +252,7 @@ void ClipperOffset::DoMiter(const Path64& path, size_t j, size_t k, double cos_a
|
|||
void ClipperOffset::DoRound(const Path64& path, size_t j, size_t k, double angle)
|
||||
{
|
||||
if (deltaCallback64_) {
|
||||
// when deltaCallback64_ is assigned, group_delta_ won't be constant,
|
||||
// when deltaCallback64_ is assigned, group_delta_ won't be constant,
|
||||
// so we'll need to do the following calculations for *every* vertex.
|
||||
double abs_delta = std::fabs(group_delta_);
|
||||
double arcTol = (arc_tolerance_ > floating_point_tolerance ?
|
||||
|
|
@ -387,7 +296,7 @@ void ClipperOffset::OffsetPoint(Group& group, const Path64& path, size_t j, size
|
|||
// sin(A) < 0: right turning
|
||||
// cos(A) < 0: change in angle is more than 90 degree
|
||||
|
||||
if (path[j] == path[k]) { k = j; return; }
|
||||
if (path[j] == path[k]) return;
|
||||
|
||||
double sin_a = CrossProduct(norms[j], norms[k]);
|
||||
double cos_a = DotProduct(norms[j], norms[k]);
|
||||
|
|
@ -404,18 +313,29 @@ void ClipperOffset::OffsetPoint(Group& group, const Path64& path, size_t j, size
|
|||
return;
|
||||
}
|
||||
|
||||
if (cos_a > -0.99 && (sin_a * group_delta_ < 0)) // test for concavity first (#593)
|
||||
if (cos_a > -0.999 && (sin_a * group_delta_ < 0)) // test for concavity first (#593)
|
||||
{
|
||||
// is concave
|
||||
// is concave (so insert 3 points that will create a negative region)
|
||||
#ifdef USINGZ
|
||||
path_out.push_back(Point64(GetPerpendic(path[j], norms[k], group_delta_), path[j].z));
|
||||
#else
|
||||
path_out.push_back(GetPerpendic(path[j], norms[k], group_delta_));
|
||||
// this extra point is the only (simple) way to ensure that
|
||||
// path reversals are fully cleaned with the trailing clipper
|
||||
path_out.push_back(path[j]); // (#405)
|
||||
#endif
|
||||
|
||||
// this extra point is the only simple way to ensure that path reversals
|
||||
// (ie over-shrunk paths) are fully cleaned out with the trailing union op.
|
||||
// However it's probably safe to skip this whenever an angle is almost flat.
|
||||
if (cos_a < 0.99) path_out.push_back(path[j]); // (#405)
|
||||
|
||||
#ifdef USINGZ
|
||||
path_out.push_back(Point64(GetPerpendic(path[j], norms[j], group_delta_), path[j].z));
|
||||
#else
|
||||
path_out.push_back(GetPerpendic(path[j], norms[j], group_delta_));
|
||||
#endif
|
||||
}
|
||||
else if (cos_a > 0.999 && join_type_ != JoinType::Round)
|
||||
else if (cos_a > 0.999 && join_type_ != JoinType::Round)
|
||||
{
|
||||
// almost straight - less than 2.5 degree (#424, #482, #526 & #724)
|
||||
// almost straight - less than 2.5 degree (#424, #482, #526 & #724)
|
||||
DoMiter(path, j, k, cos_a);
|
||||
}
|
||||
else if (join_type_ == JoinType::Miter)
|
||||
|
|
@ -435,9 +355,9 @@ void ClipperOffset::OffsetPoint(Group& group, const Path64& path, size_t j, size
|
|||
void ClipperOffset::OffsetPolygon(Group& group, const Path64& path)
|
||||
{
|
||||
path_out.clear();
|
||||
for (Path64::size_type j = 0, k = path.size() -1; j < path.size(); k = j, ++j)
|
||||
OffsetPoint(group, path, j, k);
|
||||
solution.push_back(path_out);
|
||||
for (Path64::size_type j = 0, k = path.size() - 1; j < path.size(); k = j, ++j)
|
||||
OffsetPoint(group, path, j, k);
|
||||
solution->push_back(path_out);
|
||||
}
|
||||
|
||||
void ClipperOffset::OffsetOpenJoined(Group& group, const Path64& path)
|
||||
|
|
@ -445,8 +365,8 @@ void ClipperOffset::OffsetOpenJoined(Group& group, const Path64& path)
|
|||
OffsetPolygon(group, path);
|
||||
Path64 reverse_path(path);
|
||||
std::reverse(reverse_path.begin(), reverse_path.end());
|
||||
|
||||
//rebuild normals // BuildNormals(path);
|
||||
|
||||
//rebuild normals
|
||||
std::reverse(norms.begin(), norms.end());
|
||||
norms.push_back(norms[0]);
|
||||
norms.erase(norms.begin());
|
||||
|
|
@ -459,7 +379,7 @@ void ClipperOffset::OffsetOpenPath(Group& group, const Path64& path)
|
|||
{
|
||||
// do the line start cap
|
||||
if (deltaCallback64_) group_delta_ = deltaCallback64_(path, norms, 0, 0);
|
||||
|
||||
|
||||
if (std::fabs(group_delta_) <= floating_point_tolerance)
|
||||
path_out.push_back(path[0]);
|
||||
else
|
||||
|
|
@ -477,13 +397,13 @@ void ClipperOffset::OffsetOpenPath(Group& group, const Path64& path)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t highI = path.size() - 1;
|
||||
// offset the left side going forward
|
||||
for (Path64::size_type j = 1, k = 0; j < highI; k = j, ++j)
|
||||
OffsetPoint(group, path, j, k);
|
||||
|
||||
// reverse normals
|
||||
// reverse normals
|
||||
for (size_t i = highI; i > 0; --i)
|
||||
norms[i] = PointD(-norms[i - 1].x, -norms[i - 1].y);
|
||||
norms[0] = norms[highI];
|
||||
|
|
@ -510,41 +430,34 @@ void ClipperOffset::OffsetOpenPath(Group& group, const Path64& path)
|
|||
}
|
||||
}
|
||||
|
||||
for (size_t j = highI, k = 0; j > 0; k = j, --j)
|
||||
for (size_t j = highI -1, k = highI; j > 0; k = j, --j)
|
||||
OffsetPoint(group, path, j, k);
|
||||
solution.push_back(path_out);
|
||||
solution->push_back(path_out);
|
||||
}
|
||||
|
||||
void ClipperOffset::DoGroupOffset(Group& group)
|
||||
{
|
||||
if (group.end_type == EndType::Polygon)
|
||||
{
|
||||
// a straight path (2 points) can now also be 'polygon' offset
|
||||
// a straight path (2 points) can now also be 'polygon' offset
|
||||
// where the ends will be treated as (180 deg.) joins
|
||||
if (group.lowest_path_idx < 0) delta_ = std::abs(delta_);
|
||||
if (!group.lowest_path_idx.has_value()) delta_ = std::abs(delta_);
|
||||
group_delta_ = (group.is_reversed) ? -delta_ : delta_;
|
||||
}
|
||||
else
|
||||
group_delta_ = std::abs(delta_);// *0.5;
|
||||
|
||||
double abs_delta = std::fabs(group_delta_);
|
||||
if (!ValidateBounds(group.bounds_list, abs_delta))
|
||||
{
|
||||
DoError(range_error_i);
|
||||
error_code_ |= range_error_i;
|
||||
return;
|
||||
}
|
||||
|
||||
join_type_ = group.join_type;
|
||||
end_type_ = group.end_type;
|
||||
|
||||
if (group.join_type == JoinType::Round || group.end_type == EndType::Round)
|
||||
{
|
||||
// calculate a sensible number of steps (for 360 deg for the given offset)
|
||||
// arcTol - when arc_tolerance_ is undefined (0), the amount of
|
||||
// curve imprecision that's allowed is based on the size of the
|
||||
// offset (delta). Obviously very large offsets will almost always
|
||||
// require much less precision. See also offset_triginometry2.svg
|
||||
// calculate the number of steps required to approximate a circle
|
||||
// (see http://www.angusj.com/clipper2/Docs/Trigonometry.htm)
|
||||
// arcTol - when arc_tolerance_ is undefined (0) then curve imprecision
|
||||
// will be relative to the size of the offset (delta). Obviously very
|
||||
//large offsets will almost always require much less precision.
|
||||
double arcTol = (arc_tolerance_ > floating_point_tolerance ?
|
||||
std::min(abs_delta, arc_tolerance_) :
|
||||
std::log10(2 + abs_delta) * default_arc_tolerance);
|
||||
|
|
@ -556,24 +469,29 @@ void ClipperOffset::DoGroupOffset(Group& group)
|
|||
steps_per_rad_ = steps_per_360 / (2 * PI);
|
||||
}
|
||||
|
||||
std::vector<Rect64>::const_iterator path_rect_it = group.bounds_list.cbegin();
|
||||
std::vector<bool>::const_iterator is_hole_it = group.is_hole_list.cbegin();
|
||||
//double min_area = PI * Sqr(group_delta_);
|
||||
Paths64::const_iterator path_in_it = group.paths_in.cbegin();
|
||||
for ( ; path_in_it != group.paths_in.cend(); ++path_in_it, ++path_rect_it, ++is_hole_it)
|
||||
for ( ; path_in_it != group.paths_in.cend(); ++path_in_it)
|
||||
{
|
||||
if (!path_rect_it->IsValid()) continue;
|
||||
Path64::size_type pathLen = path_in_it->size();
|
||||
path_out.clear();
|
||||
|
||||
if (pathLen == 1) // single point
|
||||
{
|
||||
if (deltaCallback64_)
|
||||
{
|
||||
group_delta_ = deltaCallback64_(*path_in_it, norms, 0, 0);
|
||||
if (group.is_reversed) group_delta_ = -group_delta_;
|
||||
abs_delta = std::fabs(group_delta_);
|
||||
}
|
||||
|
||||
if (group_delta_ < 1) continue;
|
||||
const Point64& pt = (*path_in_it)[0];
|
||||
//single vertex so build a circle or square ...
|
||||
if (group.join_type == JoinType::Round)
|
||||
{
|
||||
double radius = abs_delta;
|
||||
int steps = static_cast<int>(std::ceil(steps_per_rad_ * 2 * PI)); //#617
|
||||
size_t steps = steps_per_rad_ > 0 ? static_cast<size_t>(std::ceil(steps_per_rad_ * 2 * PI)) : 0; //#617
|
||||
path_out = Ellipse(pt, radius, radius, steps);
|
||||
#ifdef USINGZ
|
||||
for (auto& p : path_out) p.z = pt.z;
|
||||
|
|
@ -588,19 +506,14 @@ void ClipperOffset::DoGroupOffset(Group& group)
|
|||
for (auto& p : path_out) p.z = pt.z;
|
||||
#endif
|
||||
}
|
||||
solution.push_back(path_out);
|
||||
continue;
|
||||
} // end of offsetting a single point
|
||||
|
||||
// when shrinking outer paths, make sure they can shrink this far (#593)
|
||||
// also when shrinking holes, make sure they too can shrink this far (#715)
|
||||
if ((group_delta_ > 0) == ToggleBoolIf(*is_hole_it, group.is_reversed) &&
|
||||
(std::min(path_rect_it->Width(), path_rect_it->Height()) <= -group_delta_ * 2) )
|
||||
continue;
|
||||
solution->push_back(path_out);
|
||||
continue;
|
||||
} // end of offsetting a single point
|
||||
|
||||
if ((pathLen == 2) && (group.end_type == EndType::Joined))
|
||||
end_type_ = (group.join_type == JoinType::Round) ?
|
||||
EndType::Round :
|
||||
end_type_ = (group.join_type == JoinType::Round) ?
|
||||
EndType::Round :
|
||||
EndType::Square;
|
||||
|
||||
BuildNormals(*path_in_it);
|
||||
|
|
@ -610,6 +523,16 @@ void ClipperOffset::DoGroupOffset(Group& group)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USINGZ
|
||||
void ClipperOffset::ZCB(const Point64& bot1, const Point64& top1,
|
||||
const Point64& bot2, const Point64& top2, Point64& ip)
|
||||
{
|
||||
if (bot1.z && ((bot1.z == bot2.z) || (bot1.z == top2.z))) ip.z = bot1.z;
|
||||
else if (bot2.z && (bot2.z == top1.z)) ip.z = bot2.z;
|
||||
else if (top1.z && (top1.z == top2.z)) ip.z = top1.z;
|
||||
else if (zCallback64_) zCallback64_(bot1, top1, bot2, top2, ip);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t ClipperOffset::CalcSolutionCapacity()
|
||||
{
|
||||
|
|
@ -635,40 +558,35 @@ bool ClipperOffset::CheckReverseOrientation()
|
|||
void ClipperOffset::ExecuteInternal(double delta)
|
||||
{
|
||||
error_code_ = 0;
|
||||
solution.clear();
|
||||
if (groups_.size() == 0) return;
|
||||
solution.reserve(CalcSolutionCapacity());
|
||||
solution->reserve(CalcSolutionCapacity());
|
||||
|
||||
if (std::abs(delta) < 0.5) // ie: offset is insignificant
|
||||
if (std::abs(delta) < 0.5) // ie: offset is insignificant
|
||||
{
|
||||
Paths64::size_type sol_size = 0;
|
||||
for (const Group& group : groups_) sol_size += group.paths_in.size();
|
||||
solution.reserve(sol_size);
|
||||
solution->reserve(sol_size);
|
||||
for (const Group& group : groups_)
|
||||
copy(group.paths_in.begin(), group.paths_in.end(), back_inserter(solution));
|
||||
return;
|
||||
copy(group.paths_in.begin(), group.paths_in.end(), back_inserter(*solution));
|
||||
}
|
||||
|
||||
temp_lim_ = (miter_limit_ <= 1) ?
|
||||
2.0 :
|
||||
2.0 / (miter_limit_ * miter_limit_);
|
||||
|
||||
delta_ = delta;
|
||||
std::vector<Group>::iterator git;
|
||||
for (git = groups_.begin(); git != groups_.end(); ++git)
|
||||
else
|
||||
{
|
||||
DoGroupOffset(*git);
|
||||
if (!error_code_) continue; // all OK
|
||||
solution.clear();
|
||||
|
||||
temp_lim_ = (miter_limit_ <= 1) ?
|
||||
2.0 :
|
||||
2.0 / (miter_limit_ * miter_limit_);
|
||||
|
||||
delta_ = delta;
|
||||
std::vector<Group>::iterator git;
|
||||
for (git = groups_.begin(); git != groups_.end(); ++git)
|
||||
{
|
||||
DoGroupOffset(*git);
|
||||
if (!error_code_) continue; // all OK
|
||||
solution->clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClipperOffset::Execute(double delta, Paths64& paths)
|
||||
{
|
||||
paths.clear();
|
||||
|
||||
ExecuteInternal(delta);
|
||||
if (!solution.size()) return;
|
||||
if (!solution->size()) return;
|
||||
|
||||
bool paths_reversed = CheckReverseOrientation();
|
||||
//clean up self-intersections ...
|
||||
|
|
@ -677,41 +595,45 @@ void ClipperOffset::Execute(double delta, Paths64& paths)
|
|||
//the solution should retain the orientation of the input
|
||||
c.ReverseSolution(reverse_solution_ != paths_reversed);
|
||||
#ifdef USINGZ
|
||||
if (zCallback64_) { c.SetZCallback(zCallback64_); }
|
||||
auto fp = std::bind(&ClipperOffset::ZCB, this, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5);
|
||||
c.SetZCallback(fp);
|
||||
#endif
|
||||
c.AddSubject(solution);
|
||||
if (paths_reversed)
|
||||
c.Execute(ClipType::Union, FillRule::Negative, paths);
|
||||
c.AddSubject(*solution);
|
||||
if (solution_tree)
|
||||
{
|
||||
if (paths_reversed)
|
||||
c.Execute(ClipType::Union, FillRule::Negative, *solution_tree);
|
||||
else
|
||||
c.Execute(ClipType::Union, FillRule::Positive, *solution_tree);
|
||||
}
|
||||
else
|
||||
c.Execute(ClipType::Union, FillRule::Positive, paths);
|
||||
{
|
||||
if (paths_reversed)
|
||||
c.Execute(ClipType::Union, FillRule::Negative, *solution);
|
||||
else
|
||||
c.Execute(ClipType::Union, FillRule::Positive, *solution);
|
||||
}
|
||||
}
|
||||
|
||||
void ClipperOffset::Execute(double delta, Paths64& paths)
|
||||
{
|
||||
paths.clear();
|
||||
solution = &paths;
|
||||
solution_tree = nullptr;
|
||||
ExecuteInternal(delta);
|
||||
}
|
||||
|
||||
|
||||
void ClipperOffset::Execute(double delta, PolyTree64& polytree)
|
||||
{
|
||||
polytree.Clear();
|
||||
|
||||
solution_tree = &polytree;
|
||||
solution = new Paths64();
|
||||
ExecuteInternal(delta);
|
||||
if (!solution.size()) return;
|
||||
|
||||
bool paths_reversed = CheckReverseOrientation();
|
||||
//clean up self-intersections ...
|
||||
Clipper64 c;
|
||||
c.PreserveCollinear(false);
|
||||
//the solution should retain the orientation of the input
|
||||
c.ReverseSolution (reverse_solution_ != paths_reversed);
|
||||
#ifdef USINGZ
|
||||
if (zCallback64_) {
|
||||
c.SetZCallback(zCallback64_);
|
||||
}
|
||||
#endif
|
||||
c.AddSubject(solution);
|
||||
|
||||
|
||||
if (paths_reversed)
|
||||
c.Execute(ClipType::Union, FillRule::Negative, polytree);
|
||||
else
|
||||
c.Execute(ClipType::Union, FillRule::Positive, polytree);
|
||||
delete solution;
|
||||
solution = nullptr;
|
||||
}
|
||||
|
||||
void ClipperOffset::Execute(DeltaCallback64 delta_cb, Paths64& paths)
|
||||
|
|
|
|||
111
engine/thirdparty/clipper2/src/clipper.rectclip.cpp
vendored
111
engine/thirdparty/clipper2/src/clipper.rectclip.cpp
vendored
|
|
@ -1,8 +1,8 @@
|
|||
/*******************************************************************************
|
||||
* Author : Angus Johnson *
|
||||
* Date : 8 September 2023 *
|
||||
* Date : 5 July 2024 *
|
||||
* Website : http://www.angusj.com *
|
||||
* Copyright : Angus Johnson 2010-2023 *
|
||||
* Copyright : Angus Johnson 2010-2024 *
|
||||
* Purpose : FAST rectangular clipping *
|
||||
* License : http://www.boost.org/LICENSE_1_0.txt *
|
||||
*******************************************************************************/
|
||||
|
|
@ -71,7 +71,7 @@ namespace Clipper2Lib {
|
|||
return pt1.y == pt2.y;
|
||||
}
|
||||
|
||||
inline bool GetSegmentIntersection(const Point64& p1,
|
||||
bool GetSegmentIntersection(const Point64& p1,
|
||||
const Point64& p2, const Point64& p3, const Point64& p4, Point64& ip)
|
||||
{
|
||||
double res1 = CrossProduct(p1, p3, p4);
|
||||
|
|
@ -113,7 +113,7 @@ namespace Clipper2Lib {
|
|||
if ((res3 > 0) == (res4 > 0)) return false;
|
||||
|
||||
// segments must intersect to get here
|
||||
return GetIntersectPoint(p1, p2, p3, p4, ip);
|
||||
return GetSegmentIntersectPt(p1, p2, p3, p4, ip);
|
||||
}
|
||||
|
||||
inline bool GetIntersection(const Path64& rectPath,
|
||||
|
|
@ -125,7 +125,7 @@ namespace Clipper2Lib {
|
|||
{
|
||||
case Location::Left:
|
||||
if (GetSegmentIntersection(p, p2, rectPath[0], rectPath[3], ip)) return true;
|
||||
else if ((p.y < rectPath[0].y) && GetSegmentIntersection(p, p2, rectPath[0], rectPath[1], ip))
|
||||
else if ((p.y < rectPath[0].y) && GetSegmentIntersection(p, p2, rectPath[0], rectPath[1], ip))
|
||||
{
|
||||
loc = Location::Top;
|
||||
return true;
|
||||
|
|
@ -180,7 +180,7 @@ namespace Clipper2Lib {
|
|||
else return false;
|
||||
|
||||
default: // loc == rInside
|
||||
if (GetSegmentIntersection(p, p2, rectPath[0], rectPath[3], ip))
|
||||
if (GetSegmentIntersection(p, p2, rectPath[0], rectPath[3], ip))
|
||||
{
|
||||
loc = Location::Left;
|
||||
return true;
|
||||
|
|
@ -320,9 +320,9 @@ namespace Clipper2Lib {
|
|||
// this method is only called by InternalExecute.
|
||||
// Later splitting & rejoining won't create additional op's,
|
||||
// though they will change the (non-storage) results_ count.
|
||||
int curr_idx = static_cast<int>(results_.size()) - 1;
|
||||
size_t curr_idx = results_.size();
|
||||
OutPt2* result;
|
||||
if (curr_idx < 0 || start_new)
|
||||
if (curr_idx == 0 || start_new)
|
||||
{
|
||||
result = &op_container_.emplace_back(OutPt2());
|
||||
result->pt = pt;
|
||||
|
|
@ -332,6 +332,7 @@ namespace Clipper2Lib {
|
|||
}
|
||||
else
|
||||
{
|
||||
--curr_idx;
|
||||
OutPt2* prevOp = results_[curr_idx];
|
||||
if (prevOp->pt == pt) return prevOp;
|
||||
result = &op_container_.emplace_back(OutPt2());
|
||||
|
|
@ -349,27 +350,27 @@ namespace Clipper2Lib {
|
|||
void RectClip64::AddCorner(Location prev, Location curr)
|
||||
{
|
||||
if (HeadingClockwise(prev, curr))
|
||||
Add(rect_as_path_[static_cast<int>(prev)]);
|
||||
Add(rect_as_path_[static_cast<size_t>(prev)]);
|
||||
else
|
||||
Add(rect_as_path_[static_cast<int>(curr)]);
|
||||
Add(rect_as_path_[static_cast<size_t>(curr)]);
|
||||
}
|
||||
|
||||
void RectClip64::AddCorner(Location& loc, bool isClockwise)
|
||||
{
|
||||
if (isClockwise)
|
||||
{
|
||||
Add(rect_as_path_[static_cast<int>(loc)]);
|
||||
Add(rect_as_path_[static_cast<size_t>(loc)]);
|
||||
loc = GetAdjacentLocation(loc, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
loc = GetAdjacentLocation(loc, false);
|
||||
Add(rect_as_path_[static_cast<int>(loc)]);
|
||||
Add(rect_as_path_[static_cast<size_t>(loc)]);
|
||||
}
|
||||
}
|
||||
|
||||
void RectClip64::GetNextLocation(const Path64& path,
|
||||
Location& loc, int& i, int highI)
|
||||
Location& loc, size_t& i, size_t highI)
|
||||
{
|
||||
switch (loc)
|
||||
{
|
||||
|
|
@ -420,31 +421,52 @@ namespace Clipper2Lib {
|
|||
break; //inner loop
|
||||
}
|
||||
break;
|
||||
} //switch
|
||||
} //switch
|
||||
}
|
||||
|
||||
bool StartLocsAreClockwise(const std::vector<Location>& startlocs)
|
||||
{
|
||||
int result = 0;
|
||||
for (size_t i = 1; i < startlocs.size(); ++i)
|
||||
{
|
||||
int d = static_cast<int>(startlocs[i]) - static_cast<int>(startlocs[i - 1]);
|
||||
switch (d)
|
||||
{
|
||||
case -1: result -= 1; break;
|
||||
case 1: result += 1; break;
|
||||
case -3: result += 1; break;
|
||||
case 3: result -= 1; break;
|
||||
}
|
||||
}
|
||||
return result > 0;
|
||||
}
|
||||
|
||||
void RectClip64::ExecuteInternal(const Path64& path)
|
||||
{
|
||||
int i = 0, highI = static_cast<int>(path.size()) - 1;
|
||||
if (path.size() < 1)
|
||||
return;
|
||||
|
||||
size_t highI = path.size() - 1;
|
||||
Location prev = Location::Inside, loc;
|
||||
Location crossing_loc = Location::Inside;
|
||||
Location first_cross_ = Location::Inside;
|
||||
if (!GetLocation(rect_, path[highI], loc))
|
||||
{
|
||||
i = highI - 1;
|
||||
while (i >= 0 && !GetLocation(rect_, path[i], prev)) --i;
|
||||
if (i < 0)
|
||||
size_t i = highI;
|
||||
while (i > 0 && !GetLocation(rect_, path[i - 1], prev))
|
||||
--i;
|
||||
if (i == 0)
|
||||
{
|
||||
// all of path must be inside fRect
|
||||
for (const auto& pt : path) Add(pt);
|
||||
return;
|
||||
}
|
||||
if (prev == Location::Inside) loc = Location::Inside;
|
||||
i = 0;
|
||||
}
|
||||
Location startingLoc = loc;
|
||||
Location starting_loc = loc;
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
size_t i = 0;
|
||||
while (i <= highI)
|
||||
{
|
||||
prev = loc;
|
||||
|
|
@ -454,12 +476,12 @@ namespace Clipper2Lib {
|
|||
|
||||
if (i > highI) break;
|
||||
Point64 ip, ip2;
|
||||
Point64 prev_pt = (i) ?
|
||||
path[static_cast<size_t>(i - 1)] :
|
||||
Point64 prev_pt = (i) ?
|
||||
path[static_cast<size_t>(i - 1)] :
|
||||
path[highI];
|
||||
|
||||
crossing_loc = loc;
|
||||
if (!GetIntersection(rect_as_path_,
|
||||
if (!GetIntersection(rect_as_path_,
|
||||
path[i], prev_pt, crossing_loc, ip))
|
||||
{
|
||||
// ie remaining outside
|
||||
|
|
@ -470,7 +492,7 @@ namespace Clipper2Lib {
|
|||
start_locs_.push_back(prev);
|
||||
prev = GetAdjacentLocation(prev, isClockw);
|
||||
} while (prev != loc);
|
||||
crossing_loc = crossing_prev; // still not crossed
|
||||
crossing_loc = crossing_prev; // still not crossed
|
||||
}
|
||||
else if (prev != Location::Inside && prev != loc)
|
||||
{
|
||||
|
|
@ -504,7 +526,7 @@ namespace Clipper2Lib {
|
|||
}
|
||||
else if (prev != Location::Inside)
|
||||
{
|
||||
// passing right through rect. 'ip' here will be the second
|
||||
// passing right through rect. 'ip' here will be the second
|
||||
// intersect pt but we'll also need the first intersect pt (ip2)
|
||||
loc = prev;
|
||||
GetIntersection(rect_as_path_, prev_pt, path[i], loc, ip2);
|
||||
|
|
@ -543,7 +565,7 @@ namespace Clipper2Lib {
|
|||
if (first_cross_ == Location::Inside)
|
||||
{
|
||||
// path never intersects
|
||||
if (startingLoc != Location::Inside)
|
||||
if (starting_loc != Location::Inside)
|
||||
{
|
||||
// path is outside rect
|
||||
// but being outside, it still may not contain rect
|
||||
|
|
@ -552,11 +574,13 @@ namespace Clipper2Lib {
|
|||
{
|
||||
// yep, the path does fully contain rect
|
||||
// so add rect to the solution
|
||||
bool is_clockwise_path = StartLocsAreClockwise(start_locs_);
|
||||
for (size_t j = 0; j < 4; ++j)
|
||||
{
|
||||
Add(rect_as_path_[j]);
|
||||
size_t k = is_clockwise_path ? j : 3 - j; // reverses result path
|
||||
Add(rect_as_path_[k]);
|
||||
// we may well need to do some splitting later, so
|
||||
AddToEdge(edges_[j * 2], results_[0]);
|
||||
AddToEdge(edges_[k * 2], results_[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -589,8 +613,7 @@ namespace Clipper2Lib {
|
|||
OutPt2* op2 = op;
|
||||
do
|
||||
{
|
||||
if (!CrossProduct(op2->prev->pt,
|
||||
op2->pt, op2->next->pt))
|
||||
if (IsCollinear(op2->prev->pt, op2->pt, op2->next->pt))
|
||||
{
|
||||
if (op2 == op)
|
||||
{
|
||||
|
|
@ -640,7 +663,7 @@ namespace Clipper2Lib {
|
|||
}
|
||||
}
|
||||
|
||||
void RectClip64::TidyEdges(int idx, OutPt2List& cw, OutPt2List& ccw)
|
||||
void RectClip64::TidyEdges(size_t idx, OutPt2List& cw, OutPt2List& ccw)
|
||||
{
|
||||
if (ccw.empty()) return;
|
||||
bool isHorz = ((idx == 1) || (idx == 3));
|
||||
|
|
@ -648,7 +671,7 @@ namespace Clipper2Lib {
|
|||
size_t i = 0, j = 0;
|
||||
OutPt2* p1, * p2, * p1a, * p2a, * op, * op2;
|
||||
|
||||
while (i < cw.size())
|
||||
while (i < cw.size())
|
||||
{
|
||||
p1 = cw[i];
|
||||
if (!p1 || p1->next == p1->prev)
|
||||
|
|
@ -825,8 +848,8 @@ namespace Clipper2Lib {
|
|||
OutPt2* op2 = op->next;
|
||||
while (op2 && op2 != op)
|
||||
{
|
||||
if (CrossProduct(op2->prev->pt,
|
||||
op2->pt, op2->next->pt) == 0)
|
||||
if (IsCollinear(op2->prev->pt,
|
||||
op2->pt, op2->next->pt))
|
||||
{
|
||||
op = op2->prev;
|
||||
op2 = UnlinkOp(op2);
|
||||
|
|
@ -854,7 +877,7 @@ namespace Clipper2Lib {
|
|||
if (rect_.IsEmpty()) return result;
|
||||
|
||||
for (const Path64& path : paths)
|
||||
{
|
||||
{
|
||||
if (path.size() < 3) continue;
|
||||
path_bounds_ = GetBounds(path);
|
||||
if (!rect_.Intersects(path_bounds_))
|
||||
|
|
@ -868,9 +891,9 @@ namespace Clipper2Lib {
|
|||
|
||||
ExecuteInternal(path);
|
||||
CheckEdges();
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
TidyEdges(i, edges_[i * 2], edges_[i * 2 + 1]);
|
||||
|
||||
|
||||
for (OutPt2*& op : results_)
|
||||
{
|
||||
Path64 tmp = GetPath(op);
|
||||
|
|
@ -925,14 +948,14 @@ namespace Clipper2Lib {
|
|||
op_container_ = std::deque<OutPt2>();
|
||||
start_locs_.clear();
|
||||
|
||||
int i = 1, highI = static_cast<int>(path.size()) - 1;
|
||||
size_t i = 1, highI = path.size() - 1;
|
||||
|
||||
Location prev = Location::Inside, loc;
|
||||
Location crossing_loc;
|
||||
if (!GetLocation(rect_, path[0], loc))
|
||||
{
|
||||
while (i <= highI && !GetLocation(rect_, path[i], prev)) ++i;
|
||||
if (i > highI)
|
||||
if (i > highI)
|
||||
{
|
||||
// all of path must be inside fRect
|
||||
for (const auto& pt : path) Add(pt);
|
||||
|
|
@ -953,7 +976,7 @@ namespace Clipper2Lib {
|
|||
Point64 prev_pt = path[static_cast<size_t>(i - 1)];
|
||||
|
||||
crossing_loc = loc;
|
||||
if (!GetIntersection(rect_as_path_,
|
||||
if (!GetIntersection(rect_as_path_,
|
||||
path[i], prev_pt, crossing_loc, ip))
|
||||
{
|
||||
// ie remaining outside
|
||||
|
|
@ -971,10 +994,10 @@ namespace Clipper2Lib {
|
|||
}
|
||||
else if (prev != Location::Inside)
|
||||
{
|
||||
// passing right through rect. 'ip' here will be the second
|
||||
// passing right through rect. 'ip' here will be the second
|
||||
// intersect pt but we'll also need the first intersect pt (ip2)
|
||||
crossing_loc = prev;
|
||||
GetIntersection(rect_as_path_,
|
||||
GetIntersection(rect_as_path_,
|
||||
prev_pt, path[i], crossing_loc, ip2);
|
||||
Add(ip2, true);
|
||||
Add(ip);
|
||||
|
|
@ -991,14 +1014,14 @@ namespace Clipper2Lib {
|
|||
{
|
||||
Path64 result;
|
||||
if (!op || op == op->next) return result;
|
||||
op = op->next; // starting at path beginning
|
||||
op = op->next; // starting at path beginning
|
||||
result.push_back(op->pt);
|
||||
OutPt2 *op2 = op->next;
|
||||
while (op2 != op)
|
||||
{
|
||||
result.push_back(op2->pt);
|
||||
op2 = op2->next;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
6
engine/thirdparty/d3d12ma/D3D12MemAlloc.cpp
vendored
6
engine/thirdparty/d3d12ma/D3D12MemAlloc.cpp
vendored
|
|
@ -33,13 +33,11 @@
|
|||
#include <shared_mutex>
|
||||
#endif
|
||||
|
||||
/* GODOT start */
|
||||
#if !defined(_MSC_VER)
|
||||
#include <guiddef.h>
|
||||
|
||||
#include <dxguids.h>
|
||||
#endif
|
||||
/* GODOT end */
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -8186,7 +8184,6 @@ HRESULT AllocatorPimpl::UpdateD3D12Budget()
|
|||
|
||||
D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfoNative(const D3D12_RESOURCE_DESC& resourceDesc) const
|
||||
{
|
||||
/* GODOT start */
|
||||
#if defined(_MSC_VER) || !defined(_WIN32)
|
||||
return m_Device->GetResourceAllocationInfo(0, 1, &resourceDesc);
|
||||
#else
|
||||
|
|
@ -8194,7 +8191,6 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfoNative(c
|
|||
m_Device->GetResourceAllocationInfo(&ret, 0, 1, &resourceDesc);
|
||||
return ret;
|
||||
#endif
|
||||
/* GODOT end */
|
||||
}
|
||||
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
|
|
@ -8202,7 +8198,6 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfoNative(c
|
|||
{
|
||||
D3D12MA_ASSERT(m_Device8 != NULL);
|
||||
D3D12_RESOURCE_ALLOCATION_INFO1 info1Unused;
|
||||
/* GODOT start */
|
||||
#if defined(_MSC_VER) || !defined(_WIN32)
|
||||
return m_Device8->GetResourceAllocationInfo2(0, 1, &resourceDesc, &info1Unused);
|
||||
#else
|
||||
|
|
@ -8210,7 +8205,6 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfoNative(c
|
|||
m_Device8->GetResourceAllocationInfo2(&ret, 0, 1, &resourceDesc, &info1Unused);
|
||||
return ret;
|
||||
#endif
|
||||
/* GODOT end */
|
||||
}
|
||||
#endif // #ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
|
||||
|
|
|
|||
45
engine/thirdparty/d3d12ma/patches/0001-mingw-support.patch
vendored
Normal file
45
engine/thirdparty/d3d12ma/patches/0001-mingw-support.patch
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
diff --git a/thirdparty/d3d12ma/D3D12MemAlloc.cpp b/thirdparty/d3d12ma/D3D12MemAlloc.cpp
|
||||
index 8e2488091a..80d910e694 100644
|
||||
--- a/thirdparty/d3d12ma/D3D12MemAlloc.cpp
|
||||
+++ b/thirdparty/d3d12ma/D3D12MemAlloc.cpp
|
||||
@@ -33,6 +33,12 @@
|
||||
#include <shared_mutex>
|
||||
#endif
|
||||
|
||||
+#if !defined(_MSC_VER)
|
||||
+#include <guiddef.h>
|
||||
+
|
||||
+#include <dxguids.h>
|
||||
+#endif
|
||||
+
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
@@ -8178,7 +8184,13 @@ HRESULT AllocatorPimpl::UpdateD3D12Budget()
|
||||
|
||||
D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfoNative(const D3D12_RESOURCE_DESC& resourceDesc) const
|
||||
{
|
||||
+#if defined(_MSC_VER) || !defined(_WIN32)
|
||||
return m_Device->GetResourceAllocationInfo(0, 1, &resourceDesc);
|
||||
+#else
|
||||
+ D3D12_RESOURCE_ALLOCATION_INFO ret;
|
||||
+ m_Device->GetResourceAllocationInfo(&ret, 0, 1, &resourceDesc);
|
||||
+ return ret;
|
||||
+#endif
|
||||
}
|
||||
|
||||
#ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
@@ -8186,7 +8198,13 @@ D3D12_RESOURCE_ALLOCATION_INFO AllocatorPimpl::GetResourceAllocationInfoNative(c
|
||||
{
|
||||
D3D12MA_ASSERT(m_Device8 != NULL);
|
||||
D3D12_RESOURCE_ALLOCATION_INFO1 info1Unused;
|
||||
+#if defined(_MSC_VER) || !defined(_WIN32)
|
||||
return m_Device8->GetResourceAllocationInfo2(0, 1, &resourceDesc, &info1Unused);
|
||||
+#else
|
||||
+ D3D12_RESOURCE_ALLOCATION_INFO ret;
|
||||
+ m_Device8->GetResourceAllocationInfo2(&ret, 0, 1, &resourceDesc, &info1Unused);
|
||||
+ return ret;
|
||||
+#endif
|
||||
}
|
||||
#endif // #ifdef __ID3D12Device8_INTERFACE_DEFINED__
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
//*********************************************************
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License (MIT).
|
||||
|
|
|
|||
|
|
@ -25,12 +25,10 @@
|
|||
struct DefaultSampleMask { operator UINT() noexcept { return UINT_MAX; } };
|
||||
struct DefaultSampleDesc { operator DXGI_SAMPLE_DESC() noexcept { return DXGI_SAMPLE_DESC{1, 0}; } };
|
||||
|
||||
/* GODOT start */
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4324)
|
||||
#endif
|
||||
/* GODOT start */
|
||||
template <typename InnerStructType, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type, typename DefaultArg = InnerStructType>
|
||||
class alignas(void*) CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT
|
||||
{
|
||||
|
|
@ -46,11 +44,9 @@ public:
|
|||
InnerStructType* operator&() noexcept { return &pssInner; }
|
||||
InnerStructType const* operator&() const noexcept { return &pssInner; }
|
||||
};
|
||||
/* GODOT start */
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
/* GODOT end */
|
||||
typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PIPELINE_STATE_FLAGS, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS> CD3DX12_PIPELINE_STATE_STREAM_FLAGS;
|
||||
typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK> CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK;
|
||||
typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< ID3D12RootSignature*, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE;
|
||||
|
|
|
|||
|
|
@ -996,9 +996,7 @@ struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE
|
|||
// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when
|
||||
// 1.1 is not supported.
|
||||
inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
/* GODOT start */
|
||||
_In_ HMODULE pLibD3D12,
|
||||
/* GODOT end */
|
||||
_In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,
|
||||
D3D_ROOT_SIGNATURE_VERSION MaxVersion,
|
||||
_Outptr_ ID3DBlob** ppBlob,
|
||||
|
|
@ -1009,22 +1007,18 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
|||
*ppErrorBlob = nullptr;
|
||||
}
|
||||
|
||||
/* GODOT start */
|
||||
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeRootSignature");
|
||||
PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeRootSignature");
|
||||
if (d3d_D3D12SerializeRootSignature == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE d3d_D3D12SerializeVersionedRootSignature = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeVersionedRootSignature");
|
||||
/* GODOT end */
|
||||
switch (MaxVersion)
|
||||
{
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_0:
|
||||
switch (pRootSignatureDesc->Version)
|
||||
{
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_0:
|
||||
/* GODOT start */
|
||||
return d3d_D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
|
||||
/* GODOT end */
|
||||
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_1:
|
||||
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
|
||||
|
|
@ -1126,9 +1120,7 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
|||
if (SUCCEEDED(hr))
|
||||
{
|
||||
const CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
|
||||
/* GODOT start */
|
||||
hr = d3d_D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
|
||||
/* GODOT end */
|
||||
}
|
||||
|
||||
if (pParameters)
|
||||
|
|
@ -1159,9 +1151,7 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
|||
{
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_0:
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_1:
|
||||
/* GODOT start */
|
||||
return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
|
||||
/* GODOT end */
|
||||
|
||||
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_2:
|
||||
|
|
@ -1197,9 +1187,7 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
|||
if (SUCCEEDED(hr))
|
||||
{
|
||||
const CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC desc(desc_1_1.NumParameters, desc_1_1.pParameters, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
|
||||
/* GODOT start */
|
||||
hr = d3d_D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
|
||||
/* GODOT end */
|
||||
}
|
||||
|
||||
if (pStaticSamplers)
|
||||
|
|
@ -1215,9 +1203,7 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
|||
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_2:
|
||||
#endif
|
||||
/* GODOT start */
|
||||
return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
|
||||
/* GODOT end */
|
||||
}
|
||||
|
||||
return E_INVALIDARG;
|
||||
|
|
|
|||
25
engine/thirdparty/directx_headers/patches/0001-mingw-pragma.patch
vendored
Normal file
25
engine/thirdparty/directx_headers/patches/0001-mingw-pragma.patch
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
diff --git a/thirdparty/directx_headers/include/directx/d3dx12_pipeline_state_stream.h b/thirdparty/directx_headers/include/directx/d3dx12_pipeline_state_stream.h
|
||||
index f061e79596..27c7f20448 100644
|
||||
--- a/thirdparty/directx_headers/include/directx/d3dx12_pipeline_state_stream.h
|
||||
+++ b/thirdparty/directx_headers/include/directx/d3dx12_pipeline_state_stream.h
|
||||
@@ -25,8 +25,10 @@
|
||||
struct DefaultSampleMask { operator UINT() noexcept { return UINT_MAX; } };
|
||||
struct DefaultSampleDesc { operator DXGI_SAMPLE_DESC() noexcept { return DXGI_SAMPLE_DESC{1, 0}; } };
|
||||
|
||||
+#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4324)
|
||||
+#endif
|
||||
template <typename InnerStructType, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE Type, typename DefaultArg = InnerStructType>
|
||||
class alignas(void*) CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT
|
||||
{
|
||||
@@ -42,7 +44,9 @@ public:
|
||||
InnerStructType* operator&() noexcept { return &pssInner; }
|
||||
InnerStructType const* operator&() const noexcept { return &pssInner; }
|
||||
};
|
||||
+#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
+#endif
|
||||
typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_PIPELINE_STATE_FLAGS, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS> CD3DX12_PIPELINE_STATE_STREAM_FLAGS;
|
||||
typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK> CD3DX12_PIPELINE_STATE_STREAM_NODE_MASK;
|
||||
typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< ID3D12RootSignature*, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> CD3DX12_PIPELINE_STATE_STREAM_ROOT_SIGNATURE;
|
||||
|
|
@ -1,28 +1,24 @@
|
|||
diff --git a/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h b/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
|
||||
index 572efed852..18efa7a0cb 100644
|
||||
index 572efed852..2da79d10f1 100644
|
||||
--- a/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
|
||||
+++ b/thirdparty/directx_headers/include/directx/d3dx12_root_signature.h
|
||||
@@ -996,6 +996,9 @@ struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE
|
||||
@@ -996,6 +996,7 @@ struct CD3DX12_GPU_DESCRIPTOR_HANDLE : public D3D12_GPU_DESCRIPTOR_HANDLE
|
||||
// two code paths for building root signatures, this helper method reconstructs a 1.0 signature when
|
||||
// 1.1 is not supported.
|
||||
inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
+/* GODOT start */
|
||||
+ _In_ HMODULE pLibD3D12,
|
||||
+/* GODOT end */
|
||||
_In_ const D3D12_VERSIONED_ROOT_SIGNATURE_DESC* pRootSignatureDesc,
|
||||
D3D_ROOT_SIGNATURE_VERSION MaxVersion,
|
||||
_Outptr_ ID3DBlob** ppBlob,
|
||||
@@ -1006,13 +1009,22 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
@@ -1006,13 +1007,18 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
*ppErrorBlob = nullptr;
|
||||
}
|
||||
|
||||
+ /* GODOT start */
|
||||
+ PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeRootSignature");
|
||||
+ PFN_D3D12_SERIALIZE_ROOT_SIGNATURE d3d_D3D12SerializeRootSignature = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeRootSignature");
|
||||
+ if (d3d_D3D12SerializeRootSignature == nullptr) {
|
||||
+ return E_INVALIDARG;
|
||||
+ }
|
||||
+ PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE d3d_D3D12SerializeVersionedRootSignature = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)(void *)GetProcAddress(pLibD3D12, "D3D12SerializeVersionedRootSignature");
|
||||
+ /* GODOT end */
|
||||
switch (MaxVersion)
|
||||
{
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_0:
|
||||
|
|
@ -30,53 +26,43 @@ index 572efed852..18efa7a0cb 100644
|
|||
{
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_0:
|
||||
- return D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
|
||||
+/* GODOT start */
|
||||
+ return d3d_D3D12SerializeRootSignature(&pRootSignatureDesc->Desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
|
||||
+/* GODOT end */
|
||||
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_1:
|
||||
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
|
||||
@@ -1114,7 +1126,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
@@ -1114,7 +1120,7 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
const CD3DX12_ROOT_SIGNATURE_DESC desc_1_0(desc_1_1.NumParameters, pParameters_1_0, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
|
||||
- hr = D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
|
||||
+/* GODOT start */
|
||||
+ hr = d3d_D3D12SerializeRootSignature(&desc_1_0, D3D_ROOT_SIGNATURE_VERSION_1, ppBlob, ppErrorBlob);
|
||||
+/* GODOT end */
|
||||
}
|
||||
|
||||
if (pParameters)
|
||||
@@ -1145,7 +1159,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
@@ -1145,7 +1151,7 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
{
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_0:
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_1:
|
||||
- return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
|
||||
+/* GODOT start */
|
||||
+ return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
|
||||
+/* GODOT end */
|
||||
|
||||
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_2:
|
||||
@@ -1181,7 +1197,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
@@ -1181,7 +1187,7 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
const CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC desc(desc_1_1.NumParameters, desc_1_1.pParameters, desc_1_1.NumStaticSamplers, pStaticSamplers == nullptr ? desc_1_1.pStaticSamplers : pStaticSamplers, desc_1_1.Flags);
|
||||
- hr = D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
|
||||
+/* GODOT start */
|
||||
+ hr = d3d_D3D12SerializeVersionedRootSignature(&desc, ppBlob, ppErrorBlob);
|
||||
+/* GODOT end */
|
||||
}
|
||||
|
||||
if (pStaticSamplers)
|
||||
@@ -1197,7 +1215,9 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
@@ -1197,7 +1203,7 @@ inline HRESULT D3DX12SerializeVersionedRootSignature(
|
||||
#if defined(D3D12_SDK_VERSION) && (D3D12_SDK_VERSION >= 609)
|
||||
case D3D_ROOT_SIGNATURE_VERSION_1_2:
|
||||
#endif
|
||||
- return D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
|
||||
+/* GODOT start */
|
||||
+ return d3d_D3D12SerializeVersionedRootSignature(pRootSignatureDesc, ppBlob, ppErrorBlob);
|
||||
+/* GODOT end */
|
||||
}
|
||||
|
||||
return E_INVALIDARG;
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue