Files
basis_universal/encoder/basisu_dds_export.h
Richard Geldreich 3cfdd2240b new files for v2.5
2026-07-01 13:20:12 -04:00

124 lines
5.5 KiB
C++

// 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 <string>
#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