From 09bf5432072257cd881746f14c38cd4771506a73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 2 Oct 2026 17:24:40 +0900 Subject: [PATCH 1/3] feat(dds): support Linux --- .gitmodules | 9 +++++++++ CMakeLists.txt | 20 ++++++++++++++++++-- README.md | 2 +- dependencies/CMakeLists.txt | 9 +++++++-- dependencies/DirectX-Headers | 1 + dependencies/DirectXMath | 1 + dependencies/DirectXTex | 2 +- include/tev/Common.h | 12 ++++++------ src/HelpWindow.cpp | 4 +++- src/ImageViewer.cpp | 2 +- src/imageio/DdsImageLoader.cpp | 6 +++++- src/imageio/ImageLoader.cpp | 14 ++++---------- 12 files changed, 57 insertions(+), 25 deletions(-) create mode 160000 dependencies/DirectX-Headers create mode 160000 dependencies/DirectXMath diff --git a/.gitmodules b/.gitmodules index dd5b972c..061aabc5 100644 --- a/.gitmodules +++ b/.gitmodules @@ -126,3 +126,12 @@ path = dependencies/LibRaw-cmake url = https://github.com/Tom94/LibRaw-cmake shallow = true +[submodule "dependencies/DirectXMath"] + path = dependencies/DirectXMath + url = https://github.com/Tom94/DirectXMath + shallow = true +[submodule "dependencies/DirectX-Headers"] + path = dependencies/DirectX-Headers + url = https://github.com/Tom94/DirectX-Headers + shallow = true + diff --git a/CMakeLists.txt b/CMakeLists.txt index 1c476379..f599cf3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,15 @@ if (TEV_LINUX_REVERSE_DNS_APP_ID) set(TEV_LINUX_APP_ID "io.github.tom94.tev") endif() +# DirectXTex only compiles on Linux and Windows +if (APPLE) + set(TEV_SUPPORT_DDS_DEFAULT OFF) +else() + set(TEV_SUPPORT_DDS_DEFAULT ON) +endif() + option(TEV_SUPPORT_AVIF "Support loading AVIF images" ON) +option(TEV_SUPPORT_DDS "Support loading DDS images" ${TEV_SUPPORT_DDS_DEFAULT}) option(TEV_SUPPORT_HEIC "Support loading HEIC images" OFF) option(TEV_SUPPORT_JXL "Support loading/saving JPEG XL images" ON) @@ -200,10 +208,12 @@ set(TEV_SOURCES if (MSVC) list(APPEND TEV_SOURCES resources/windows/icon.rc) list(APPEND TEV_SOURCES resources/windows/tev.manifest) - list(APPEND TEV_SOURCES include/tev/imageio/DdsImageLoader.h src/imageio/DdsImageLoader.cpp) elseif (APPLE) list(APPEND TEV_SOURCES resources/macos/icon.icns) endif() +if (TEV_SUPPORT_DDS) + list(APPEND TEV_SOURCES include/tev/imageio/DdsImageLoader.h src/imageio/DdsImageLoader.cpp) +endif() if (TEV_USE_LIBHEIF) list(APPEND TEV_SOURCES include/tev/imageio/HeifImageLoader.h src/imageio/HeifImageLoader.cpp) endif() @@ -258,6 +268,9 @@ endif() if (TEV_SUPPORT_AVIF) list(APPEND TEV_DEFINITIONS -DTEV_SUPPORT_AVIF) endif() +if (TEV_SUPPORT_DDS) + list(APPEND TEV_DEFINITIONS -DTEV_SUPPORT_DDS) +endif() if (TEV_SUPPORT_HEIC) list(APPEND TEV_DEFINITIONS -DTEV_SUPPORT_HEIC) endif() @@ -272,11 +285,14 @@ target_compile_definitions(tev PRIVATE ${TEV_DEFINITIONS}) set(TEV_LIBS cfitsio clip exif_static gdcm-tev JPEG::JPEG jxrglue libraw::libraw_r nanogui OpenEXR::OpenEXR openjpeg-tev png_static tiff webpdemux XMPCore xsimd) if (MSVC) - list(APPEND TEV_LIBS DirectXTex wsock32 ws2_32) + list(APPEND TEV_LIBS wsock32 ws2_32) endif() if (TEV_USE_LIBHEIF) list(APPEND TEV_LIBS lcms2-tev heif) endif() +if (TEV_SUPPORT_DDS) + list(APPEND TEV_LIBS DirectXTex) +endif() if (TEV_SUPPORT_JXL) # jxl_dec for decoding, jxl_extras for gain maps, jxl_threads for threading support list(APPEND TEV_LIBS jxl jxl_dec jxl_extras_nocodec-internal jxl_threads) diff --git a/README.md b/README.md index 4437fc91..bd854eb2 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ $ cpack --config build/CPackConfig.cmake - __PNG__, APNG (via [libpng](https://github.com/pnggroup/libpng)) - __PFM__, PAM, PNM, PBM, PGM, PPM (generally: see [NetPBM](https://netpbm.sourceforge.net/) and [PFM](https://www.pauldebevec.com/Research/HDR/PFM/)) - __QOI__ (via [qoi](https://github.com/phoboslab/qoi)) -- __DDS__ (via [DirectXTex](https://github.com/microsoft/DirectXTex); Windows only) +- __DDS__ (via [DirectXTex](https://github.com/microsoft/DirectXTex); Windows and Linux only) - __WEBP__ (via [libwebp](https://chromium.googlesource.com/webm/libwebp)) - __TIFF__, __DNG__ (via [libtiff](https://gitlab.com/libtiff/libtiff)) - __AVIF__ (including gain maps, e.g. HDR pictures from Android; via [dav1d](https://github.com/videolan/dav1d)+[libheif](https://github.com/strukturag/libheif)) diff --git a/dependencies/CMakeLists.txt b/dependencies/CMakeLists.txt index caded40d..b8e5d84c 100644 --- a/dependencies/CMakeLists.txt +++ b/dependencies/CMakeLists.txt @@ -58,13 +58,18 @@ set(NANOGUI_SKIP_METAL_SHADER_PRECOMPILATION ON CACHE BOOL " " FORCE) add_subdirectory(nanogui) # Compile DirectXTex (only on Windows) -if (WIN32) +if (TEV_SUPPORT_DDS) set(BUILD_TOOLS OFF CACHE BOOL " " FORCE) set(BUILD_DX11 OFF CACHE BOOL " " FORCE) set(BUILD_DX12 OFF CACHE BOOL " " FORCE) set(BC_USE_OPENMP OFF CACHE BOOL " " FORCE) - add_subdirectory(DirectXTex) + if (NOT WIN32) + add_subdirectory(DirectXMath EXCLUDE_FROM_ALL) + add_subdirectory(DirectX-Headers EXCLUDE_FROM_ALL) + endif() + + add_subdirectory(DirectXTex EXCLUDE_FROM_ALL) endif() # Compile Little-CMS for ICC color profile handling. The library name is set to lcms2-tev to avoid conflicts with libjxl which also comes diff --git a/dependencies/DirectX-Headers b/dependencies/DirectX-Headers new file mode 160000 index 00000000..adbd6f3b --- /dev/null +++ b/dependencies/DirectX-Headers @@ -0,0 +1 @@ +Subproject commit adbd6f3ba40795c46a8d0f33af00bcb57ff0f0a4 diff --git a/dependencies/DirectXMath b/dependencies/DirectXMath new file mode 160000 index 00000000..519d4738 --- /dev/null +++ b/dependencies/DirectXMath @@ -0,0 +1 @@ +Subproject commit 519d47388a30fa61a75529b022e93790ede6c551 diff --git a/dependencies/DirectXTex b/dependencies/DirectXTex index db7185a1..ba681576 160000 --- a/dependencies/DirectXTex +++ b/dependencies/DirectXTex @@ -1 +1 @@ -Subproject commit db7185a1510a2fc24465a9b6c877a9d2db35787b +Subproject commit ba6815763f4c90dae5f2e9d3cbc9986e0f4c4acf diff --git a/include/tev/Common.h b/include/tev/Common.h index f86799b3..149eec42 100644 --- a/include/tev/Common.h +++ b/include/tev/Common.h @@ -65,12 +65,12 @@ # define SYSTEM_COMMAND_RIGHT GLFW_KEY_RIGHT_CONTROL #endif -#define TEV_ASSERT(cond, description, ...) \ - if (!(cond)) [[unlikely]] { \ - const auto s = std::source_location::current(); \ - throw std::runtime_error{ \ - fmt::format("{}({}:{}) `{}`: " description, s.file_name(), s.line(), s.column(), s.function_name(), ##__VA_ARGS__) \ - }; \ +#define TEV_ASSERT(cond, description, ...) \ + if (!(cond)) [[unlikely]] { \ + const auto s_ = std::source_location::current(); \ + throw std::runtime_error{ \ + fmt::format("{}({}:{}) `{}`: " description, s_.file_name(), s_.line(), s_.column(), s_.function_name(), ##__VA_ARGS__) \ + }; \ } #ifndef TEV_VERSION diff --git a/src/HelpWindow.cpp b/src/HelpWindow.cpp index 26242fc0..3650b18f 100644 --- a/src/HelpWindow.cpp +++ b/src/HelpWindow.cpp @@ -237,8 +237,10 @@ HelpWindow::HelpWindow(Widget* parent, weak_ptr weakIpc, function c #ifdef TEV_SUPPORT_AVIF addLibrary(about, "dav1d", "Fast AV1 decoder library"); #endif -#ifdef _WIN32 +#ifdef TEV_SUPPORT_DDS addLibrary(about, "DirectXTex", "DirectX texture processing library"); + addLibrary(about, "DirectXMath", "DirectX math library"); + addLibrary(about, "DirectX-Headers", "DirectX headers"); #endif addLibrary(about, "GDCM", "Grassroots library for DICOM medical files"); addLibrary(about, "Glad", "Multi-language GL loader-generator"); diff --git a/src/ImageViewer.cpp b/src/ImageViewer.cpp index ea9aa02a..fef83cdb 100644 --- a/src/ImageViewer.cpp +++ b/src/ImageViewer.cpp @@ -2418,7 +2418,7 @@ void ImageViewer::openImageDialog() { #endif {"bmp", "Bitmap image" }, {"cur", "Microsoft cursor image" }, -#ifdef _WIN32 +#ifdef TEV_SUPPORT_DDS {"dds", "DirectDraw Surface image" }, #endif {"dng", "Digital Negative image" }, diff --git a/src/imageio/DdsImageLoader.cpp b/src/imageio/DdsImageLoader.cpp index 99b890d3..119b08e3 100644 --- a/src/imageio/DdsImageLoader.cpp +++ b/src/imageio/DdsImageLoader.cpp @@ -159,6 +159,7 @@ Task> throw FormatNotSupported{"File is not a DDS file."}; } +#ifdef _WIN32 // COM must be initialized on the thread executing the following DirectX calls. Thus: when editing this file *make sure* that no // co_await calls are made before the last DirectX call! Note that it is not a problem that CoInitializeEx will potentially get called // multiple times across different threads, or even multiple times by the same thread pool thread. Both situations are explicitly @@ -167,6 +168,7 @@ Task> if (const auto res = CoInitializeEx(nullptr, COINIT_MULTITHREADED); res != S_OK && res != S_FALSE) { throw ImageLoadError{"Failed to initialize COM."}; } +#endif // The correct way to clean up would be to call CoUninitialize() on every task pool thread on shutdown. Using a scope guard here // wouldn't work for multiple reasons: (i) the coroutine might have been scheduled to another thread once the scope ends, and (ii) it @@ -177,7 +179,9 @@ Task> DirectX::ScratchImage scratchImage; DirectX::TexMetadata metadata; - if (DirectX::LoadFromDDSMemory(data.data(), data.size(), DirectX::DDS_FLAGS_NONE, &metadata, scratchImage) != S_OK) { + if (DirectX::LoadFromDDSMemory( + reinterpret_cast(data.data()), data.size(), DirectX::DDS_FLAGS_NONE, &metadata, scratchImage + ) != S_OK) { throw ImageLoadError{"Failed to read DDS file."}; } diff --git a/src/imageio/ImageLoader.cpp b/src/imageio/ImageLoader.cpp index 0e914519..cf7044df 100644 --- a/src/imageio/ImageLoader.cpp +++ b/src/imageio/ImageLoader.cpp @@ -35,7 +35,7 @@ #include #include -#ifdef _WIN32 +#ifdef TEV_SUPPORT_DDS # include #endif #ifdef TEV_USE_LIBHEIF @@ -59,7 +59,7 @@ const vector>& ImageLoader::getLoaders() { imageLoaders.emplace_back(new PfmImageLoader()); imageLoaders.emplace_back(new ClipboardImageLoader()); imageLoaders.emplace_back(new EmptyImageLoader()); -#ifdef _WIN32 +#ifdef TEV_SUPPORT_DDS imageLoaders.emplace_back(new DdsImageLoader()); #endif #ifdef TEV_USE_LIBHEIF @@ -118,7 +118,7 @@ const vector& ImageLoader::supportedMimeTypes() { "image/vnd.radiance", "image/webp", "image/x-adobe-dng", -#ifdef _WIN32 +#ifdef TEV_SUPPORT_DDS "image/x-dds", "image/x-direct-draw-surface", #endif @@ -141,13 +141,7 @@ const vector& ImageLoader::supportedMimeTypes() { } Task> ImageLoader::makeInterleavedChannels( - size_t numChannels, - bool hasAlpha, - Vector2i size, - EPixelFormat pixelFormat, - EPixelFormat desiredFormat, - string_view layer, - int priority + size_t numChannels, bool hasAlpha, Vector2i size, EPixelFormat pixelFormat, EPixelFormat desiredFormat, string_view layer, int priority ) { if (numChannels == 0) { throw ImageLoadError{"Invalid number of rgba channels."}; From 86217c4021605a514f62323ca8eb2de0bbf904f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 2 Oct 2026 20:13:20 +0900 Subject: [PATCH 2/3] fix(dds): warnings about macro redefinition --- src/imageio/DdsImageLoader.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/imageio/DdsImageLoader.cpp b/src/imageio/DdsImageLoader.cpp index 119b08e3..1efbf489 100644 --- a/src/imageio/DdsImageLoader.cpp +++ b/src/imageio/DdsImageLoader.cpp @@ -20,6 +20,7 @@ #include #include +#include #include using namespace nanogui; From 9e2c0a1eff3e271ff866d36f5ec8a7ff46bc0749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Fri, 2 Oct 2026 20:13:47 +0900 Subject: [PATCH 3/3] feat(dds): enable on macOS as well --- CMakeLists.txt | 9 +-------- README.md | 2 +- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f599cf3e..d9d582fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,15 +43,8 @@ if (TEV_LINUX_REVERSE_DNS_APP_ID) set(TEV_LINUX_APP_ID "io.github.tom94.tev") endif() -# DirectXTex only compiles on Linux and Windows -if (APPLE) - set(TEV_SUPPORT_DDS_DEFAULT OFF) -else() - set(TEV_SUPPORT_DDS_DEFAULT ON) -endif() - option(TEV_SUPPORT_AVIF "Support loading AVIF images" ON) -option(TEV_SUPPORT_DDS "Support loading DDS images" ${TEV_SUPPORT_DDS_DEFAULT}) +option(TEV_SUPPORT_DDS "Support loading DDS images" ON) option(TEV_SUPPORT_HEIC "Support loading HEIC images" OFF) option(TEV_SUPPORT_JXL "Support loading/saving JPEG XL images" ON) diff --git a/README.md b/README.md index bd854eb2..506602f2 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ $ cpack --config build/CPackConfig.cmake - __PNG__, APNG (via [libpng](https://github.com/pnggroup/libpng)) - __PFM__, PAM, PNM, PBM, PGM, PPM (generally: see [NetPBM](https://netpbm.sourceforge.net/) and [PFM](https://www.pauldebevec.com/Research/HDR/PFM/)) - __QOI__ (via [qoi](https://github.com/phoboslab/qoi)) -- __DDS__ (via [DirectXTex](https://github.com/microsoft/DirectXTex); Windows and Linux only) +- __DDS__ (via [DirectXTex](https://github.com/microsoft/DirectXTex)) - __WEBP__ (via [libwebp](https://chromium.googlesource.com/webm/libwebp)) - __TIFF__, __DNG__ (via [libtiff](https://gitlab.com/libtiff/libtiff)) - __AVIF__ (including gain maps, e.g. HDR pictures from Android; via [dav1d](https://github.com/videolan/dav1d)+[libheif](https://github.com/strukturag/libheif))