// basisu_dds_export.h // Copyright (C) 2019-2025 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. // 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. // // Basic DX10-style .DDS writer for basisu_tool's -dds command. It consumes the prepared source image // slices from a basis_compressor that has been run in process_source_images() mode (so all the image // loading, mipmap generation, and cubemap/array layout is done by the encoder), then packs each slice // into the requested output format and writes a modern DX10 (DDS_HEADER_DXT10) .dds file. // // Supported -dds_format tokens (see parse_dds_output_format): // Block compressed: bc1 bc2 bc3 bc4 bc5 bc7 // Uncompressed: a8r8g8b8 r8 r8g8 r5g6b5 a1r5g5b5 a4r4g4b4 // // The sRGB-vs-UNORM DXGI variant is selected from the compressor's transfer function flag // (m_ktx2_and_basis_srgb_transfer_function, set by -srgb/-photo/-linear); only bc1/bc2/bc3/bc7/a8r8g8b8/a8b8g8r8 // have an sRGB DXGI variant, the rest are always written as UNORM. No transfer-function conversion is // ever applied to the texel data - we only pick the format tag and pack the bytes as-is. #pragma once #include #include "../transcoder/basisu.h" // for basisu::uint8_vec namespace basisu { class basis_compressor; // The output formats supported by the -dds command. enum dds_output_format { cDDSFmtInvalid = -1, // Block compressed (packed with the real-time BC encoders). cDDSFmtBC1, cDDSFmtBC2, cDDSFmtBC3, cDDSFmtBC4, cDDSFmtBC5, cDDSFmtBC7, // Uncompressed (simple pixel format conversion). cDDSFmtA8R8G8B8, // DXGI B8G8R8A8 (32bpp, BGRA in memory), has sRGB variant cDDSFmtA8B8G8R8, // DXGI R8G8B8A8 (32bpp, RGBA in memory), has sRGB variant cDDSFmtR8, // DXGI R8 (8bpp) cDDSFmtR8G8, // DXGI R8G8 (16bpp), source R->R, source G->G (like BC5) cDDSFmtR5G6B5, // DXGI B5G6R5 (16bpp) cDDSFmtA1R5G5B5, // DXGI B5G5R5A1 (16bpp) cDDSFmtA4R4G4B4, // DXGI B4G4R4A4 (16bpp) cDDSFmtTotal }; // Parses a -dds_format token (case-insensitive) into a dds_output_format. Returns false (and sets // fmt to cDDSFmtInvalid) on an unrecognized token. bool parse_dds_output_format(const char* pToken, dds_output_format& fmt); // Returns the canonical token string for a format (for messages), or "?" if invalid. const char* get_dds_output_format_string(dds_output_format fmt); // True if the format has a distinct sRGB DXGI variant (bc1/bc3/bc7/a8r8g8b8); false for the formats // that are always written UNORM. Lets a caller report the actually-emitted variant accurately. bool dds_output_format_has_srgb_variant(dds_output_format fmt); // Which BC7 base packer to use for bc7 output. (Eventually a third encoder may be added.) enum dds_bc7_encoder { cDDSBC7Encoder_Default = -1, // "not specified" sentinel (CLI use); resolves to the dds_export_params default cDDSBC7Encoder_BC7F = 0, // built-in fast real-time packer (basist::bc7f), default cDDSBC7Encoder_BC7E_Scalar = 1 // higher-quality (slower) scalar bc7e encoder }; // bc7f quality level -> which analytical mode flags the bc7f packer uses (higher = slower/better). enum dds_bc7f_level { cDDSBC7FLevel_Analytical = 0, // cPackBC7FlagDefault cDDSBC7FLevel_PartiallyAnalytical = 1, // cPackBC7FlagDefaultPartiallyAnalytical (default) cDDSBC7FLevel_NonAnalytical = 2 // cPackBC7FlagDefaultNonAnalytical (slowest/best) }; // Input parameters for build_dds(). Intended to grow as more -dds options are added (BC1 quality, etc.). struct dds_export_params { dds_output_format m_format; // BC7-only knobs (ignored for non-bc7 formats): dds_bc7_encoder m_bc7_encoder; // which BC7 base packer int m_bc7f_level; // dds_bc7f_level [0,2]: analytical / partially / non analytical (bc7f only) int m_bc7e_scalar_level; // bc7e_scalar quality level [0,6], 0=ultrafast..6=slowest (bc7e_scalar only) dds_export_params() : m_format(cDDSFmtInvalid), m_bc7_encoder(cDDSBC7Encoder_BC7F), m_bc7f_level(cDDSBC7FLevel_PartiallyAnalytical), m_bc7e_scalar_level(2) { } explicit dds_export_params(dds_output_format format) : m_format(format), m_bc7_encoder(cDDSBC7Encoder_BC7F), m_bc7f_level(cDDSBC7FLevel_PartiallyAnalytical), m_bc7e_scalar_level(2) { } }; // Builds an in-memory DX10 .dds file from the prepared slices of comp (which must have had a successful // process_source_images() call) into dds_data (which is resize(0)'d first, then appended to). The caller // is responsible for writing dds_data out (or using it however it likes). Picks the UNORM vs sRGB DXGI // variant from comp's transfer function flag. On failure returns false and sets error_msg. On success, // the optional out_* values report the texture's dimensions/structure (for a caller summary). bool build_dds(uint8_vec& dds_data, const basis_compressor& comp, const dds_export_params& params, std::string& error_msg, uint32_t* pOut_width = nullptr, uint32_t* pOut_height = nullptr, uint32_t* pOut_levels = nullptr, uint32_t* pOut_layers = nullptr, uint32_t* pOut_faces = nullptr); } // namespace basisu