diff --git a/CMakeLists.txt b/CMakeLists.txt index c3f8e281..f750e8ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,7 +42,7 @@ else() option(BASISU_BUILD_X64 "build 64-bit" TRUE) endif() -option(BASISU_ZSTD "ZSTD support for KTX2 transcoding/encoding" TRUE) +option(BASISU_ZSTD "ZSTD support for KTX2 transcoding/encoding and ASTC LDR encoding" TRUE) option(BASISU_OPENCL "OpenCL support in encoder" FALSE) # Old option to new (BASISU_ prefixed) automatic remapping @@ -290,12 +290,24 @@ set(ENCODER_LIB_SRC_LIST ) if (BASISU_ZSTD) - set(ENCODER_LIB_SRC_LIST ${ENCODER_LIB_SRC_LIST} zstd/zstd.c) + # Full zstd library (encoder + decoder) for the encoder + add_library(basisu_zstd_encoder STATIC zstd/zstd.c) + target_include_directories(basisu_zstd_encoder PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/zstd) + set_property(TARGET basisu_zstd_encoder PROPERTY POSITION_INDEPENDENT_CODE ON) + + # Decoder-only zstd library for transcoder-only targets (smaller footprint) + add_library(basisu_zstd_decoder STATIC zstd/zstddeclib.c) + target_include_directories(basisu_zstd_decoder PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/zstd) + set_property(TARGET basisu_zstd_decoder PROPERTY POSITION_INDEPENDENT_CODE ON) endif() # Create the static library add_library(basisu_encoder STATIC ${ENCODER_LIB_SRC_LIST}) +if (BASISU_ZSTD) + target_link_libraries(basisu_encoder PUBLIC basisu_zstd_encoder) +endif() + # Create the basisu executable and link against the static library add_executable(basisu basisu_tool.cpp) target_link_libraries(basisu PRIVATE basisu_encoder) @@ -308,7 +320,10 @@ if(BASISU_EXAMPLES) add_executable(example_capi example_capi/example_capi.c encoder/basisu_wasm_api.cpp encoder/basisu_wasm_transcoder_api.cpp) target_link_libraries(example_capi PRIVATE basisu_encoder) - add_executable(example_transcoding example_transcoding/example_transcoding.cpp example_transcoding/utils.cpp zstd/zstddeclib.c transcoder/basisu_transcoder.cpp) + add_executable(example_transcoding example_transcoding/example_transcoding.cpp example_transcoding/utils.cpp transcoder/basisu_transcoder.cpp) + if (BASISU_ZSTD) + target_link_libraries(example_transcoding PRIVATE basisu_zstd_decoder) + endif() endif() if (BASISU_BUILD_WASM) @@ -343,7 +358,7 @@ if (BASISU_BUILD_WASM) endif() - # 256 MB initial, 3.5 GB max � safe defaults for BasisU + # 256 MB initial, 3.5 GB max safe defaults for BasisU target_link_options(basisu PRIVATE -Wl,--initial-memory=268435456 -Wl,--max-memory=3758096384 @@ -375,14 +390,16 @@ endif() #endif() if (BASISU_ZSTD) - target_compile_definitions(basisu PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1) + target_compile_definitions(basisu_encoder PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1 BASISU_ASTC_LDR_SUPPORT_ZSTD=1) + target_compile_definitions(basisu PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1 BASISU_ASTC_LDR_SUPPORT_ZSTD=1) if(BASISU_EXAMPLES) target_compile_definitions(example PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1) target_compile_definitions(example_capi PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1) target_compile_definitions(example_transcoding PRIVATE BASISD_SUPPORT_KTX2_ZSTD=1) endif() else() - target_compile_definitions(basisu PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0) + target_compile_definitions(basisu_encoder PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0 BASISU_ASTC_LDR_SUPPORT_ZSTD=0) + target_compile_definitions(basisu PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0 BASISU_ASTC_LDR_SUPPORT_ZSTD=0) if(BASISU_EXAMPLES) target_compile_definitions(example PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0) target_compile_definitions(example_capi PRIVATE BASISD_SUPPORT_KTX2_ZSTD=0) @@ -581,8 +598,11 @@ if (BASISU_BUILD_WASM) add_executable(${BASISU_TRANSCODER_WASM_OUTPUT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/encoder/basisu_wasm_transcoder_api.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/transcoder/basisu_transcoder.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/zstd/zstddeclib.c) + ${CMAKE_CURRENT_SOURCE_DIR}/transcoder/basisu_transcoder.cpp) + + if (BASISU_ZSTD) + target_link_libraries(${BASISU_TRANSCODER_WASM_OUTPUT_NAME} PRIVATE basisu_zstd_decoder) + endif() set_target_properties(${BASISU_TRANSCODER_WASM_OUTPUT_NAME} PROPERTIES SUFFIX ".wasm") @@ -645,9 +665,12 @@ if (BASISU_BUILD_PYTHON AND NOT BASISU_BUILD_WASM) python/basisu_transcoder_pybind11.cpp encoder/basisu_wasm_transcoder_api.cpp transcoder/basisu_transcoder.cpp - zstd/zstddeclib.c ) + if (BASISU_ZSTD) + target_link_libraries(basisu_transcoder_python PRIVATE basisu_zstd_decoder) + endif() + # Ensure PIC ONLY for this target set_property(TARGET basisu_transcoder_python PROPERTY POSITION_INDEPENDENT_CODE ON) diff --git a/encoder/basisu_astc_ldr_encode.cpp b/encoder/basisu_astc_ldr_encode.cpp index 1710b1b5..59cf8d2d 100644 --- a/encoder/basisu_astc_ldr_encode.cpp +++ b/encoder/basisu_astc_ldr_encode.cpp @@ -1,4 +1,4 @@ -// File: basisu_astc_ldr_encode.cpp +// File: basisu_astc_ldr_encode.cpp // Copyright (C) 2019-2026 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,7 +18,14 @@ #include "3rdparty/android_astc_decomp.h" #include -#include "../zstd/zstd.h" +// Set BASISU_ASTC_LDR_SUPPORT_ZSTD to 0 to disable Zstd support for ASTC LDR encoding (cFullZStd and cHybridArithZStd syntaxes) +#ifndef BASISU_ASTC_LDR_SUPPORT_ZSTD + #define BASISU_ASTC_LDR_SUPPORT_ZSTD 1 +#endif + +#if BASISU_ASTC_LDR_SUPPORT_ZSTD +#include "zstd.h" +#endif namespace basisu { namespace astc_ldr { @@ -8061,6 +8068,7 @@ void configure_encoder_effort_level(int level, ldr_astc_block_encode_image_high_ } } +#if BASISU_ASTC_LDR_SUPPORT_ZSTD static bool zstd_compress(const uint8_t* pData, size_t data_len, uint8_vec& comp_data, int zstd_level) { if (!data_len) @@ -8100,7 +8108,9 @@ static bool zstd_compress(const uint8_vec& vec, uint8_vec& comp_data, int zstd_l { return zstd_compress(vec.data(), vec.size(), comp_data, zstd_level); } +#endif // BASISU_ASTC_LDR_SUPPORT_ZSTD +#if BASISU_ASTC_LDR_SUPPORT_ZSTD static uint32_t encode_values(bitwise_coder& coder, uint32_t total_values, const uint8_t* pVals, uint32_t endpoint_range) { const uint32_t MAX_VALS = 64; @@ -9323,6 +9333,7 @@ static bool compress_image_full_zstd( return true; } +#endif // BASISU_ASTC_LDR_SUPPORT_ZSTD bool compress_image( const image& orig_img, uint8_vec& comp_data, vector2D& coded_blocks, @@ -9445,6 +9456,7 @@ bool compress_image( if (total_blocks <= DISABLE_FASTER_FORMAT_TOTAL_BLOCKS_THRESH) syntax = basist::astc_ldr_t::xuastc_ldr_syntax::cFullArith; +#if BASISU_ASTC_LDR_SUPPORT_ZSTD if (syntax == basist::astc_ldr_t::xuastc_ldr_syntax::cFullZStd) { // Full ZStd syntax is so different we'll move that to another function. @@ -9454,6 +9466,14 @@ bool compress_image( job_pool, enc_cfg, enc_out); } +#else + if ((syntax == basist::astc_ldr_t::xuastc_ldr_syntax::cFullZStd) || + (syntax == basist::astc_ldr_t::xuastc_ldr_syntax::cHybridArithZStd)) + { + fmt_error_printf("ASTC LDR encoder: Zstd syntax requested but BASISU_ASTC_LDR_SUPPORT_ZSTD is disabled\n"); + return false; + } +#endif const bool use_faster_format = (syntax == basist::astc_ldr_t::xuastc_ldr_syntax::cHybridArithZStd); @@ -10803,9 +10823,12 @@ bool compress_image( return false; uint8_vec suffix_bytes; + + assert(comp_data.size() == 0); if (use_faster_format) { +#if BASISU_ASTC_LDR_SUPPORT_ZSTD suffix_bytes.reserve(8192); mean0_bits.flush(); @@ -10871,13 +10894,13 @@ bool compress_image( fmt_debug_printf(" Weight4 bytes: {} comp size: {}\n", (uint64_t)weight4_bits.get_bytes().size(), (uint64_t)comp_weight4.size()); fmt_debug_printf(" Weight8 bytes: {} comp size: {}\n", (uint64_t)weight8_bits.size(), (uint64_t)comp_weight8.size()); } - } - - assert(comp_data.size() == 0); - if (use_faster_format) - { + comp_data.resize(sizeof(hdr)); memcpy(comp_data.data(), &hdr, sizeof(hdr)); +#else + fmt_error_printf("ASTC LDR encoder: HybridArithZStd format requires BASISU_ASTC_LDR_SUPPORT_ZSTD to be enabled\n"); + return false; +#endif // BASISU_ASTC_LDR_SUPPORT_ZSTD } else { diff --git a/encoder/basisu_comp.cpp b/encoder/basisu_comp.cpp index 617ff307..4e55dee8 100644 --- a/encoder/basisu_comp.cpp +++ b/encoder/basisu_comp.cpp @@ -34,7 +34,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 347a0248..584bd580 100644 --- a/transcoder/basisu_transcoder.cpp +++ b/transcoder/basisu_transcoder.cpp @@ -1,4 +1,4 @@ -// basisu_transcoder.cpp +// basisu_transcoder.cpp // Copyright (C) 2019-2026 Binomial LLC. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -174,7 +174,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 @@ -20426,6 +20426,7 @@ namespace basist return false; } #else + BASISU_NOTE_UNUSED(pComp_data); BASISU_DEVEL_ERROR("ktx2_transcoder::decompress_level_data: File uses Zstd supercompression, but Zstd support was not enabled at compile time (BASISD_SUPPORT_KTX2_ZSTD is 0)\n"); return false; #endif @@ -27014,6 +27015,7 @@ namespace astc_ldr_t return true; #else + BASISU_NOTE_UNUSED(pComp_data); BASISU_DEVEL_ERROR("zstd_decompress: file uses ZStd compression, but ZStd support disabled (see BASISD_SUPPORT_KTX2_ZSTD) \n"); return false; #endif