mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-06-08 00:23:52 +00:00
merging v2.0 from xuastc_private
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// basisu.h
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2026 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");
|
||||
@@ -15,12 +15,16 @@
|
||||
// limitations under the License.
|
||||
#pragma once
|
||||
|
||||
#ifndef BASISD_SUPPORT_XUASTC
|
||||
#define BASISD_SUPPORT_XUASTC 1
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma warning (disable : 4201)
|
||||
#pragma warning (disable : 4127) // warning C4127: conditional expression is constant
|
||||
#pragma warning (disable : 4530) // C++ exception handler used, but unwind semantics are not enabled.
|
||||
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <stdlib.h>
|
||||
@@ -40,9 +44,11 @@
|
||||
#include <assert.h>
|
||||
#include <random>
|
||||
#include <inttypes.h>
|
||||
#include <cfloat>
|
||||
|
||||
#include "basisu_containers.h"
|
||||
|
||||
// We never use min/max macros, slam them to off.
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
@@ -57,6 +63,7 @@
|
||||
|
||||
// Set to one to enable debug printf()'s when any errors occur, for development/debugging. Especially useful for WebGL development.
|
||||
#ifndef BASISU_FORCE_DEVEL_MESSAGES
|
||||
// Do not check in as 1!
|
||||
#define BASISU_FORCE_DEVEL_MESSAGES 0
|
||||
#endif
|
||||
|
||||
@@ -93,6 +100,7 @@ namespace basisu
|
||||
typedef basisu::vector<int> int_vec;
|
||||
typedef basisu::vector<bool> bool_vec;
|
||||
typedef basisu::vector<float> float_vec;
|
||||
typedef basisu::vector<double> double_vec;
|
||||
|
||||
void enable_debug_printf(bool enabled);
|
||||
void debug_printf(const char *pFmt, ...);
|
||||
@@ -109,14 +117,14 @@ namespace basisu
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
|
||||
|
||||
template <typename T> inline void clear_obj(T& obj) { memset((void *)&obj, 0, sizeof(obj)); }
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
constexpr double cPiD = 3.14159265358979323846264338327950288;
|
||||
constexpr float REALLY_SMALL_FLOAT_VAL = .000000125f;
|
||||
@@ -124,7 +132,7 @@ namespace basisu
|
||||
constexpr float BIG_FLOAT_VAL = 1e+30f;
|
||||
|
||||
template <typename T0, typename T1> inline T0 lerp(T0 a, T0 b, T1 c) { return a + (b - a) * c; }
|
||||
|
||||
|
||||
inline float clampf(float value, float low, float high) { if (value < low) value = low; else if (value > high) value = high; return value; }
|
||||
inline float saturate(float value) { return clampf(value, 0, 1.0f); }
|
||||
inline uint8_t minimumub(uint8_t a, uint8_t b) { return (a < b) ? a : b; }
|
||||
@@ -141,6 +149,41 @@ namespace basisu
|
||||
template<typename T> inline T square(T a) { return a * a; }
|
||||
template<typename T> inline T sign(T a) { return (a < 0) ? (T)-1 : ((a == 0) ? (T)0 : (T)1); }
|
||||
|
||||
inline int imod(int i, int d)
|
||||
{
|
||||
assert(i != INT_MIN);
|
||||
|
||||
if (i >= 0)
|
||||
return i % d;
|
||||
|
||||
int r = (-i) % d;
|
||||
return (r == 0) ? 0 : d - r;
|
||||
}
|
||||
|
||||
inline uint8_t safe_cast_uint8(uint32_t x)
|
||||
{
|
||||
assert(x <= UINT8_MAX);
|
||||
return (uint8_t)x;
|
||||
}
|
||||
|
||||
inline int8_t safe_cast_int8(int32_t x)
|
||||
{
|
||||
assert((x >= INT8_MIN) && (x <= INT8_MAX));
|
||||
return (int8_t)x;
|
||||
}
|
||||
|
||||
inline uint16_t safe_cast_uint16(uint32_t x)
|
||||
{
|
||||
assert(x <= UINT16_MAX);
|
||||
return (uint16_t)x;
|
||||
}
|
||||
|
||||
inline int16_t safe_cast_int16(int32_t x)
|
||||
{
|
||||
assert((x >= INT16_MIN) && (x <= INT16_MAX));
|
||||
return (int16_t)x;
|
||||
}
|
||||
|
||||
inline bool equal_tol(float a, float b, float t) { return fabsf(a - b) <= ((maximum(fabsf(a), fabsf(b)) + 1.0f) * t); }
|
||||
inline bool equal_tol(double a, double b, double t) { return fabs(a - b) <= ((maximum(fabs(a), fabs(b)) + 1.0f) * t); }
|
||||
|
||||
@@ -161,27 +204,35 @@ namespace basisu
|
||||
temp = 0;
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
inline uint32_t iabs(int32_t i) { return (i < 0) ? static_cast<uint32_t>(-i) : static_cast<uint32_t>(i); }
|
||||
inline uint64_t iabs64(int64_t i) { return (i < 0) ? static_cast<uint64_t>(-i) : static_cast<uint64_t>(i); }
|
||||
|
||||
template<typename T> inline void clear_vector(T &vec) { vec.erase(vec.begin(), vec.end()); }
|
||||
template<typename T> inline void clear_vector(T &vec) { vec.erase(vec.begin(), vec.end()); }
|
||||
template<typename T> inline typename T::value_type *enlarge_vector(T &vec, size_t n) { size_t cs = vec.size(); vec.resize(cs + n); return &vec[cs]; }
|
||||
|
||||
inline bool is_pow2(uint32_t x) { return x && ((x & (x - 1U)) == 0U); }
|
||||
inline bool is_pow2(uint64_t x) { return x && ((x & (x - 1U)) == 0U); }
|
||||
|
||||
template<typename T> inline T 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 range_check(T v, T maxv) { assert(v <= maxv); BASISU_NOTE_UNUSED(maxv); return v; }
|
||||
|
||||
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)
|
||||
inline bool is_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)
|
||||
inline bool is_in_range(int v, int l, int h)
|
||||
{
|
||||
return (v >= l) && (v <= h);
|
||||
}
|
||||
|
||||
inline bool is_in_range(float v, float l, float h)
|
||||
{
|
||||
return (v >= l) && (v <= h);
|
||||
}
|
||||
@@ -192,7 +243,7 @@ namespace basisu
|
||||
|
||||
inline uint32_t get_bit(uint32_t src, int ndx)
|
||||
{
|
||||
assert(in_bounds(ndx, 0, 32));
|
||||
assert(is_in_bounds(ndx, 0, 32));
|
||||
return (src >> ndx) & 1;
|
||||
}
|
||||
|
||||
@@ -204,7 +255,7 @@ namespace basisu
|
||||
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));
|
||||
assert(is_in_range(num_bits, 1, 32));
|
||||
|
||||
val >>= low;
|
||||
if (num_bits != 32)
|
||||
@@ -213,8 +264,8 @@ namespace basisu
|
||||
return val;
|
||||
}
|
||||
|
||||
template<typename T, typename R> inline void append_vector(T &vec, const R *pObjs, size_t n)
|
||||
{
|
||||
template<typename T, typename R> inline void append_vector(T &vec, const R *pObjs, size_t n)
|
||||
{
|
||||
if (n)
|
||||
{
|
||||
if (vec.size())
|
||||
@@ -265,7 +316,7 @@ namespace basisu
|
||||
for (size_t i = 0; i < vec.size(); i++)
|
||||
vec[i] = obj;
|
||||
}
|
||||
|
||||
|
||||
inline uint64_t read_be64(const void *p)
|
||||
{
|
||||
uint64_t val = 0;
|
||||
@@ -307,6 +358,14 @@ namespace basisu
|
||||
return (m != 0) ? (y - m) : m;
|
||||
}
|
||||
|
||||
inline float posmodf(float x, float y)
|
||||
{
|
||||
float m = fmodf(x, y);
|
||||
if (m < 0.0f)
|
||||
m += y;
|
||||
return m;
|
||||
}
|
||||
|
||||
inline bool do_excl_ranges_overlap(int la, int ha, int lb, int hb)
|
||||
{
|
||||
assert(la < ha && lb < hb);
|
||||
@@ -331,7 +390,7 @@ namespace basisu
|
||||
pBytes[2] = (uint8_t)(val >> 16U);
|
||||
pBytes[3] = (uint8_t)(val >> 24U);
|
||||
}
|
||||
|
||||
|
||||
// Always little endian 1-8 byte unsigned int
|
||||
template<uint32_t NumBytes>
|
||||
struct packed_uint
|
||||
@@ -341,21 +400,21 @@ namespace basisu
|
||||
inline packed_uint() { static_assert(NumBytes <= sizeof(uint64_t), "Invalid NumBytes"); }
|
||||
inline packed_uint(uint64_t v) { *this = v; }
|
||||
inline packed_uint(const packed_uint& other) { *this = other; }
|
||||
|
||||
inline packed_uint& operator= (uint64_t v)
|
||||
{
|
||||
|
||||
inline packed_uint& operator= (uint64_t v)
|
||||
{
|
||||
// TODO: Add assert on truncation?
|
||||
for (uint32_t i = 0; i < NumBytes; i++)
|
||||
m_bytes[i] = static_cast<uint8_t>(v >> (i * 8));
|
||||
return *this;
|
||||
for (uint32_t i = 0; i < NumBytes; i++)
|
||||
m_bytes[i] = static_cast<uint8_t>(v >> (i * 8));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline packed_uint& operator= (const packed_uint& rhs)
|
||||
{
|
||||
memcpy(m_bytes, rhs.m_bytes, sizeof(m_bytes));
|
||||
inline packed_uint& operator= (const packed_uint& rhs)
|
||||
{
|
||||
memcpy(m_bytes, rhs.m_bytes, sizeof(m_bytes));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline uint64_t get_uint64() const
|
||||
{
|
||||
// Some compilers may warn about this code. It clearly cannot access beyond the end of the m_bytes struct here.
|
||||
@@ -411,7 +470,7 @@ namespace basisu
|
||||
static_assert(NumBytes <= sizeof(uint32_t), "packed_uint too large to use get_uint32");
|
||||
return static_cast<uint32_t>(get_uint64());
|
||||
}
|
||||
|
||||
|
||||
inline operator uint32_t() const
|
||||
{
|
||||
static_assert(NumBytes <= sizeof(uint32_t), "packed_uint too large to use operator uint32_t");
|
||||
@@ -421,14 +480,14 @@ namespace basisu
|
||||
|
||||
enum eZero { cZero };
|
||||
enum eNoClamp { cNoClamp };
|
||||
|
||||
|
||||
// Rice/Huffman entropy coding
|
||||
|
||||
|
||||
// This is basically Deflate-style canonical Huffman, except we allow for a lot more symbols.
|
||||
enum
|
||||
{
|
||||
cHuffmanMaxSupportedCodeSize = 16, cHuffmanMaxSupportedInternalCodeSize = 31,
|
||||
cHuffmanFastLookupBits = 10,
|
||||
cHuffmanMaxSupportedCodeSize = 16, cHuffmanMaxSupportedInternalCodeSize = 31,
|
||||
cHuffmanFastLookupBits = 10,
|
||||
cHuffmanMaxSymsLog2 = 14, cHuffmanMaxSyms = 1 << cHuffmanMaxSymsLog2,
|
||||
|
||||
// Small zero runs
|
||||
@@ -454,13 +513,13 @@ namespace basisu
|
||||
enum class texture_format
|
||||
{
|
||||
cInvalidTextureFormat = -1,
|
||||
|
||||
|
||||
// Block-based formats
|
||||
cETC1, // ETC1
|
||||
cETC1S, // ETC1 (subset: diff colors only, no subblocks)
|
||||
cETC2_RGB, // ETC2 color block (basisu doesn't support ETC2 planar/T/H modes - just basic ETC1)
|
||||
cETC2_RGBA, // ETC2 EAC alpha block followed by ETC2 color block
|
||||
cETC2_ALPHA, // ETC2 EAC alpha block
|
||||
cETC2_ALPHA, // ETC2 EAC alpha block
|
||||
cBC1, // DXT1
|
||||
cBC3, // DXT5 (BC4/DXT5A block followed by a BC1/DXT1 block)
|
||||
cBC4, // DXT5A
|
||||
@@ -479,11 +538,11 @@ namespace basisu
|
||||
cPVRTC2_4_RGBA,
|
||||
cETC2_R11_EAC,
|
||||
cETC2_RG11_EAC,
|
||||
cUASTC4x4,
|
||||
cUASTC4x4,
|
||||
cUASTC_HDR_4x4,
|
||||
cBC1_NV,
|
||||
cBC1_AMD,
|
||||
|
||||
|
||||
// Uncompressed/raw pixels
|
||||
cRGBA32,
|
||||
cRGB565,
|
||||
@@ -492,9 +551,89 @@ namespace basisu
|
||||
cABGR4444,
|
||||
cRGBA_HALF,
|
||||
cRGB_HALF,
|
||||
cRGB_9E5
|
||||
cRGB_9E5,
|
||||
|
||||
// All remaining ASTC LDR block size variants (other than 4x4 which is above). There are 14 total ASTC block sizes, including 4x4.
|
||||
cASTC_LDR_5x4,
|
||||
cASTC_LDR_5x5,
|
||||
cASTC_LDR_6x5,
|
||||
cASTC_LDR_6x6,
|
||||
cASTC_LDR_8x5,
|
||||
cASTC_LDR_8x6,
|
||||
cASTC_LDR_10x5,
|
||||
cASTC_LDR_10x6,
|
||||
cASTC_LDR_8x8,
|
||||
cASTC_LDR_10x8,
|
||||
cASTC_LDR_10x10,
|
||||
cASTC_LDR_12x10,
|
||||
cASTC_LDR_12x12
|
||||
};
|
||||
|
||||
inline bool is_astc(texture_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cASTC_HDR_4x4:
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
case texture_format::cASTC_LDR_4x4:
|
||||
case texture_format::cASTC_LDR_5x4:
|
||||
case texture_format::cASTC_LDR_5x5:
|
||||
case texture_format::cASTC_LDR_6x5:
|
||||
case texture_format::cASTC_LDR_6x6:
|
||||
case texture_format::cASTC_LDR_8x5:
|
||||
case texture_format::cASTC_LDR_8x6:
|
||||
case texture_format::cASTC_LDR_10x5:
|
||||
case texture_format::cASTC_LDR_10x6:
|
||||
case texture_format::cASTC_LDR_8x8:
|
||||
case texture_format::cASTC_LDR_10x8:
|
||||
case texture_format::cASTC_LDR_10x10:
|
||||
case texture_format::cASTC_LDR_12x10:
|
||||
case texture_format::cASTC_LDR_12x12:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_hdr_astc(texture_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cASTC_HDR_4x4:
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_ldr_astc(texture_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cASTC_LDR_4x4:
|
||||
case texture_format::cASTC_LDR_5x4:
|
||||
case texture_format::cASTC_LDR_5x5:
|
||||
case texture_format::cASTC_LDR_6x5:
|
||||
case texture_format::cASTC_LDR_6x6:
|
||||
case texture_format::cASTC_LDR_8x5:
|
||||
case texture_format::cASTC_LDR_8x6:
|
||||
case texture_format::cASTC_LDR_10x5:
|
||||
case texture_format::cASTC_LDR_10x6:
|
||||
case texture_format::cASTC_LDR_8x8:
|
||||
case texture_format::cASTC_LDR_10x8:
|
||||
case texture_format::cASTC_LDR_10x10:
|
||||
case texture_format::cASTC_LDR_12x10:
|
||||
case texture_format::cASTC_LDR_12x12:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool is_uncompressed_texture_format(texture_format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
@@ -555,7 +694,7 @@ namespace basisu
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Everything else is 16 bytes/block.
|
||||
return 16;
|
||||
}
|
||||
@@ -575,10 +714,21 @@ namespace basisu
|
||||
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cFXT1_RGB:
|
||||
return 8;
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
return 6;
|
||||
case texture_format::cFXT1_RGB: return 8;
|
||||
case texture_format::cASTC_HDR_6x6: return 6;
|
||||
case texture_format::cASTC_LDR_5x4: return 5;
|
||||
case texture_format::cASTC_LDR_5x5: return 5;
|
||||
case texture_format::cASTC_LDR_6x5: return 6;
|
||||
case texture_format::cASTC_LDR_6x6: return 6;
|
||||
case texture_format::cASTC_LDR_8x5: return 8;
|
||||
case texture_format::cASTC_LDR_8x6: return 8;
|
||||
case texture_format::cASTC_LDR_10x5: return 10;
|
||||
case texture_format::cASTC_LDR_10x6: return 10;
|
||||
case texture_format::cASTC_LDR_8x8: return 8;
|
||||
case texture_format::cASTC_LDR_10x8: return 10;
|
||||
case texture_format::cASTC_LDR_10x10: return 10;
|
||||
case texture_format::cASTC_LDR_12x10: return 12;
|
||||
case texture_format::cASTC_LDR_12x12: return 12;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -591,8 +741,19 @@ namespace basisu
|
||||
|
||||
switch (fmt)
|
||||
{
|
||||
case texture_format::cASTC_HDR_6x6:
|
||||
return 6;
|
||||
case texture_format::cASTC_HDR_6x6: return 6;
|
||||
case texture_format::cASTC_LDR_5x5: return 5;
|
||||
case texture_format::cASTC_LDR_6x5: return 5;
|
||||
case texture_format::cASTC_LDR_6x6: return 6;
|
||||
case texture_format::cASTC_LDR_8x5: return 5;
|
||||
case texture_format::cASTC_LDR_8x6: return 6;
|
||||
case texture_format::cASTC_LDR_10x5: return 5;
|
||||
case texture_format::cASTC_LDR_10x6: return 6;
|
||||
case texture_format::cASTC_LDR_8x8: return 8;
|
||||
case texture_format::cASTC_LDR_10x8: return 8;
|
||||
case texture_format::cASTC_LDR_10x10: return 10;
|
||||
case texture_format::cASTC_LDR_12x10: return 10;
|
||||
case texture_format::cASTC_LDR_12x12: return 12;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -623,5 +784,38 @@ namespace basisu
|
||||
{
|
||||
return !is_hdr_texture_format(fmt);
|
||||
}
|
||||
|
||||
inline texture_format get_astc_ldr_texture_format(uint32_t width, uint32_t height)
|
||||
{
|
||||
#define BU_ASTC_LDR_MATCH_BLOCK_DIM(x, y, f) if ((width == (x)) && (height == (y))) return (f);
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(4, 4, texture_format::cASTC_LDR_4x4);
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(5, 4, texture_format::cASTC_LDR_5x4);
|
||||
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(5, 5, texture_format::cASTC_LDR_5x5);
|
||||
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(6, 5, texture_format::cASTC_LDR_6x5);
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(6, 6, texture_format::cASTC_LDR_6x6);
|
||||
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(8, 5, texture_format::cASTC_LDR_8x5);
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(8, 6, texture_format::cASTC_LDR_8x6);
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(10, 5, texture_format::cASTC_LDR_10x5);
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(10, 6, texture_format::cASTC_LDR_10x6);
|
||||
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(8, 8, texture_format::cASTC_LDR_8x8);
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(10, 8, texture_format::cASTC_LDR_10x8);
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(10, 10, texture_format::cASTC_LDR_10x10);
|
||||
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(12, 10, texture_format::cASTC_LDR_12x10);
|
||||
BU_ASTC_LDR_MATCH_BLOCK_DIM(12, 12, texture_format::cASTC_LDR_12x12);
|
||||
#undef BU_ASTC_LDR_MATCH_BLOCK_DIM
|
||||
|
||||
return texture_format::cInvalidTextureFormat;
|
||||
}
|
||||
|
||||
inline bool is_valid_astc_block_size(uint32_t width, uint32_t height)
|
||||
{
|
||||
return get_astc_ldr_texture_format(width, height) != texture_format::cInvalidTextureFormat;
|
||||
}
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// File: basisu_astc_hdr_core.h
|
||||
#pragma once
|
||||
#include "basisu_astc_helpers.h"
|
||||
|
||||
namespace basist
|
||||
{
|
||||
@@ -109,7 +108,10 @@ namespace basist
|
||||
const uint32_t TOTAL_BLOCK_MODE_DECS = 75;
|
||||
extern const block_mode_desc g_block_mode_descs[TOTAL_BLOCK_MODE_DECS];
|
||||
|
||||
void copy_weight_grid(bool dual_plane, uint32_t grid_x, uint32_t grid_y, const uint8_t* transcode_weights, astc_helpers::log_astc_block& decomp_blk);
|
||||
const uint32_t UASTC_6x6_HDR_SIG0 = 0xABCD; // original release
|
||||
const uint32_t UASTC_6x6_HDR_SIG1 = 0xABCE; // 2x2->4x4 weight grid upsampling change, not backwards compatible with older decoders
|
||||
|
||||
void copy_weight_grid(bool dual_plane, uint32_t grid_x, uint32_t grid_y, const uint8_t* transcode_weights, astc_helpers::log_astc_block& decomp_blk, bool orig_behavior);
|
||||
|
||||
enum class encoding_type
|
||||
{
|
||||
@@ -181,7 +183,7 @@ namespace basist
|
||||
|
||||
bool m_hq_ls;
|
||||
bool m_brute_force_weight4_assignment;
|
||||
|
||||
|
||||
fast_bc6h_params()
|
||||
{
|
||||
init();
|
||||
@@ -203,3 +205,4 @@ namespace basist
|
||||
} // namespace astc_6x6_hdr
|
||||
|
||||
} // namespace basist
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -159,8 +159,8 @@ namespace basisu
|
||||
static inline void construct(T** p) { memset(p, 0, sizeof(T*)); }
|
||||
static inline void construct(T** p, T* init) { *p = init; }
|
||||
static inline void construct_array(T** p, size_t n) { memset(p, 0, sizeof(T*) * n); }
|
||||
static inline void destruct(T** p) { p; }
|
||||
static inline void destruct_array(T** p, size_t n) { p, n; }
|
||||
static inline void destruct(T** p) { (void)p; }
|
||||
static inline void destruct_array(T** p, size_t n) { (void)p, (void)n; }
|
||||
};
|
||||
|
||||
#define BASISU_DEFINE_BUILT_IN_TYPE(X) \
|
||||
@@ -169,8 +169,8 @@ namespace basisu
|
||||
static inline void construct(X* p) { memset(p, 0, sizeof(X)); } \
|
||||
static inline void construct(X* p, const X& init) { memcpy(p, &init, sizeof(X)); } \
|
||||
static inline void construct_array(X* p, size_t n) { memset(p, 0, sizeof(X) * n); } \
|
||||
static inline void destruct(X* p) { p; } \
|
||||
static inline void destruct_array(X* p, size_t n) { p, n; } };
|
||||
static inline void destruct(X* p) { (void)p; } \
|
||||
static inline void destruct_array(X* p, size_t n) { (void)p, (void)n; } };
|
||||
|
||||
BASISU_DEFINE_BUILT_IN_TYPE(bool)
|
||||
BASISU_DEFINE_BUILT_IN_TYPE(char)
|
||||
@@ -272,7 +272,7 @@ namespace basisu
|
||||
size_t c = a + b;
|
||||
return c < a;
|
||||
}
|
||||
|
||||
|
||||
// Returns false on overflow, true if OK.
|
||||
template<typename T>
|
||||
inline bool can_fit_into_size_t(T val)
|
||||
@@ -294,7 +294,7 @@ namespace basisu
|
||||
|
||||
template<typename T>
|
||||
class writable_span;
|
||||
|
||||
|
||||
template<typename T>
|
||||
class readable_span
|
||||
{
|
||||
@@ -304,7 +304,7 @@ namespace basisu
|
||||
using const_pointer = const T*;
|
||||
using const_reference = const T&;
|
||||
using const_iterator = const T*;
|
||||
|
||||
|
||||
inline readable_span() :
|
||||
m_p(nullptr),
|
||||
m_size(0)
|
||||
@@ -941,7 +941,7 @@ namespace basisu
|
||||
|
||||
inline iterator begin() const { return m_p; }
|
||||
inline iterator end() const { assert(m_p || !m_size); return m_p + m_size; }
|
||||
|
||||
|
||||
inline const_iterator cbegin() const { return m_p; }
|
||||
inline const_iterator cend() const { assert(m_p || !m_size); return m_p + m_size; }
|
||||
|
||||
@@ -1506,7 +1506,7 @@ namespace basisu
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
if ((m_p) && (other.m_p))
|
||||
{
|
||||
@@ -1563,6 +1563,52 @@ namespace basisu
|
||||
set(ws);
|
||||
}
|
||||
|
||||
// mostly to ease porting from std::vector, not particularly optimized
|
||||
inline void assign(size_t new_size, const T& init)
|
||||
{
|
||||
assert(!m_p || (&init < m_p) || (&init >= (m_p + m_size)));
|
||||
|
||||
// Blow away existing contents
|
||||
resize(0);
|
||||
|
||||
if (new_size)
|
||||
{
|
||||
resize(new_size);
|
||||
|
||||
for (size_t i = 0; i < new_size; ++i)
|
||||
m_p[i] = init;
|
||||
}
|
||||
}
|
||||
|
||||
// mostly to ease porting from std::vector, not particularly optimized
|
||||
template<typename R>
|
||||
inline void assign(const R* pBegin, const R* pEnd)
|
||||
{
|
||||
assert(!m_p ||
|
||||
(reinterpret_cast<const uint8_t *>(pEnd) <= reinterpret_cast<const uint8_t*>(m_p)) ||
|
||||
(reinterpret_cast<const uint8_t *>(pBegin) >= reinterpret_cast<const uint8_t*>(m_p + m_size))
|
||||
);
|
||||
|
||||
// Blow away existing contents
|
||||
resize(0);
|
||||
|
||||
if ((!pBegin) || (!pEnd) || (pEnd <= pBegin))
|
||||
{
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t new_size = static_cast<size_t>(static_cast<ptrdiff_t>(pEnd - pBegin));
|
||||
|
||||
if (new_size)
|
||||
{
|
||||
resize(new_size);
|
||||
|
||||
for (size_t i = 0; i < new_size; ++i)
|
||||
m_p[i] = static_cast<T>(*pBegin++);
|
||||
}
|
||||
}
|
||||
|
||||
// Set contents of vector to contents of the readable span
|
||||
bool set(const readable_span<T>& rs)
|
||||
{
|
||||
@@ -1647,7 +1693,7 @@ namespace basisu
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
if ((m_p) && (other.m_p))
|
||||
memcpy((void *)m_p, other.m_p, other.m_size * sizeof(T));
|
||||
@@ -2147,7 +2193,7 @@ namespace basisu
|
||||
if (!try_insert(p, obj))
|
||||
container_abort("vector::insert() failed!\n");
|
||||
}
|
||||
|
||||
|
||||
// push_front() isn't going to be very fast - it's only here for usability.
|
||||
inline void push_front(const T& obj)
|
||||
{
|
||||
@@ -2228,7 +2274,7 @@ namespace basisu
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
|
||||
memmove((void *)pDst, pSrc, num_to_move * sizeof(T));
|
||||
@@ -2239,7 +2285,7 @@ namespace basisu
|
||||
}
|
||||
else
|
||||
{
|
||||
// Type is not bitwise copyable or movable.
|
||||
// Type is not bitwise copyable or movable.
|
||||
// Move them down one at a time by using the equals operator, and destroying anything that's left over at the end.
|
||||
T* pDst_end = pDst + num_to_move;
|
||||
|
||||
@@ -2482,7 +2528,7 @@ namespace basisu
|
||||
{
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#pragma GCC diagnostic ignored "-Wclass-memaccess"
|
||||
#endif
|
||||
memset(m_p, *reinterpret_cast<const uint8_t*>(&o), m_size);
|
||||
|
||||
@@ -2770,6 +2816,7 @@ namespace basisu
|
||||
m_grow_threshold = 0;
|
||||
}
|
||||
|
||||
// Destroys elements/empties container but doesn't free memory.
|
||||
inline void reset()
|
||||
{
|
||||
if (!m_num_valid)
|
||||
@@ -2798,7 +2845,7 @@ namespace basisu
|
||||
}
|
||||
else if (sizeof(node) <= 16)
|
||||
{
|
||||
memset(&m_values[0], 0, m_values.size_in_bytes());
|
||||
memset((void *)&m_values[0], 0, m_values.size_in_bytes());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2829,6 +2876,11 @@ namespace basisu
|
||||
return m_num_valid;
|
||||
}
|
||||
|
||||
inline uint32_t size_u32()
|
||||
{
|
||||
return static_cast<uint32_t>(m_num_valid);
|
||||
}
|
||||
|
||||
inline size_t get_table_size()
|
||||
{
|
||||
return m_values.size();
|
||||
@@ -3102,7 +3154,7 @@ namespace basisu
|
||||
{
|
||||
return try_insert(result, std::move(v.first), std::move(v.second));
|
||||
}
|
||||
|
||||
|
||||
inline const_iterator find(const Key& k) const
|
||||
{
|
||||
return const_iterator(*this, find_index(k));
|
||||
@@ -3183,12 +3235,12 @@ namespace basisu
|
||||
static inline void construct_value_type(value_type* pDst, const Key& k, const Value& v)
|
||||
{
|
||||
if (BASISU_IS_BITWISE_COPYABLE(Key))
|
||||
memcpy(&pDst->first, &k, sizeof(Key));
|
||||
memcpy((void *)&pDst->first, &k, sizeof(Key));
|
||||
else
|
||||
scalar_type<Key>::construct(&pDst->first, k);
|
||||
|
||||
if (BASISU_IS_BITWISE_COPYABLE(Value))
|
||||
memcpy(&pDst->second, &v, sizeof(Value));
|
||||
memcpy((void *)&pDst->second, &v, sizeof(Value));
|
||||
else
|
||||
scalar_type<Value>::construct(&pDst->second, v);
|
||||
}
|
||||
@@ -3197,17 +3249,17 @@ namespace basisu
|
||||
{
|
||||
if ((BASISU_IS_BITWISE_COPYABLE(Key)) && (BASISU_IS_BITWISE_COPYABLE(Value)))
|
||||
{
|
||||
memcpy(pDst, pSrc, sizeof(value_type));
|
||||
memcpy((void *)pDst, pSrc, sizeof(value_type));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BASISU_IS_BITWISE_COPYABLE(Key))
|
||||
memcpy(&pDst->first, &pSrc->first, sizeof(Key));
|
||||
memcpy((void *)&pDst->first, &pSrc->first, sizeof(Key));
|
||||
else
|
||||
scalar_type<Key>::construct(&pDst->first, pSrc->first);
|
||||
|
||||
if (BASISU_IS_BITWISE_COPYABLE(Value))
|
||||
memcpy(&pDst->second, &pSrc->second, sizeof(Value));
|
||||
memcpy((void *)&pDst->second, &pSrc->second, sizeof(Value));
|
||||
else
|
||||
scalar_type<Value>::construct(&pDst->second, pSrc->second);
|
||||
}
|
||||
@@ -3227,14 +3279,14 @@ namespace basisu
|
||||
|
||||
if (BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(Key) && BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(Value))
|
||||
{
|
||||
memcpy(pDst, pSrc, sizeof(node));
|
||||
memcpy((void *)pDst, pSrc, sizeof(node));
|
||||
|
||||
assert(pDst->state == cStateValid);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(Key))
|
||||
memcpy(&pDst->first, &pSrc->first, sizeof(Key));
|
||||
memcpy((void*)&pDst->first, &pSrc->first, sizeof(Key));
|
||||
else
|
||||
{
|
||||
new ((void*)&pDst->first) Key(std::move(pSrc->first));
|
||||
@@ -3242,7 +3294,7 @@ namespace basisu
|
||||
}
|
||||
|
||||
if (BASISU_IS_BITWISE_COPYABLE_OR_MOVABLE(Value))
|
||||
memcpy(&pDst->second, &pSrc->second, sizeof(Value));
|
||||
memcpy((void*)&pDst->second, &pSrc->second, sizeof(Value));
|
||||
else
|
||||
{
|
||||
new ((void*)&pDst->second) Value(std::move(pSrc->second));
|
||||
@@ -3583,7 +3635,7 @@ namespace basisu
|
||||
// Not checking for is MOVABLE because the caller could later destruct k and/or v (what state do we set them to?)
|
||||
if (BASISU_IS_BITWISE_COPYABLE(Key))
|
||||
{
|
||||
memcpy(&pDst->first, &k, sizeof(Key));
|
||||
memcpy((void *)&pDst->first, (const void *)&k, sizeof(Key));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3593,7 +3645,7 @@ namespace basisu
|
||||
|
||||
if (BASISU_IS_BITWISE_COPYABLE(Value))
|
||||
{
|
||||
memcpy(&pDst->second, &v, sizeof(Value));
|
||||
memcpy((void *)&pDst->second, (const void*)&v, sizeof(Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3721,11 +3773,11 @@ namespace basisu
|
||||
|
||||
va_list args;
|
||||
va_start(args, pFmt);
|
||||
#ifdef _WIN32
|
||||
#ifdef _WIN32
|
||||
vsprintf_s(buf, sizeof(buf), pFmt, args);
|
||||
#else
|
||||
vsnprintf(buf, sizeof(buf), pFmt, args);
|
||||
#endif
|
||||
#endif
|
||||
va_end(args);
|
||||
|
||||
return std::string(buf);
|
||||
@@ -3893,7 +3945,7 @@ namespace basisu
|
||||
std::size_t copy_size = std::min(list.size(), N);
|
||||
std::copy_n(list.begin(), copy_size, m_data); // Copy up to min(list.size(), N)
|
||||
|
||||
if (list.size() < N)
|
||||
if (list.size() < N)
|
||||
{
|
||||
// Initialize the rest of the array
|
||||
std::fill(m_data + copy_size, m_data + N, T{});
|
||||
@@ -3907,7 +3959,7 @@ namespace basisu
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
BASISU_FORCE_INLINE const T& operator[](std::size_t index) const
|
||||
BASISU_FORCE_INLINE const T& operator[](std::size_t index) const
|
||||
{
|
||||
if (index >= N)
|
||||
container_abort("fixed_array: Index out of bounds.");
|
||||
@@ -3950,26 +4002,26 @@ namespace basisu
|
||||
{
|
||||
return writable_span<T>(m_data, N);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
BASISU_FORCE_INLINE void initialize_array()
|
||||
{
|
||||
if constexpr (std::is_integral<T>::value || std::is_floating_point<T>::value)
|
||||
if constexpr (std::is_integral<T>::value || std::is_floating_point<T>::value)
|
||||
memset(m_data, 0, sizeof(m_data));
|
||||
else
|
||||
else
|
||||
std::fill(m_data, m_data + N, T{});
|
||||
}
|
||||
|
||||
BASISU_FORCE_INLINE T& access_element(std::size_t index)
|
||||
{
|
||||
if (index >= N)
|
||||
if (index >= N)
|
||||
container_abort("fixed_array: Index out of bounds.");
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
BASISU_FORCE_INLINE const T& access_element(std::size_t index) const
|
||||
{
|
||||
if (index >= N)
|
||||
if (index >= N)
|
||||
container_abort("fixed_array: Index out of bounds.");
|
||||
return m_data[index];
|
||||
}
|
||||
@@ -4046,6 +4098,9 @@ namespace basisu
|
||||
inline uint32_t get_width() const { return m_width; }
|
||||
inline uint32_t get_height() const { return m_height; }
|
||||
|
||||
inline uint32_t get_cols() const { return m_width; }
|
||||
inline uint32_t get_rows() const { return m_height; }
|
||||
|
||||
inline const T& operator() (uint32_t x, uint32_t y) const { assert(x < m_width && y < m_height); return m_values[x + y * m_width]; }
|
||||
inline T& operator() (uint32_t x, uint32_t y) { assert(x < m_width && y < m_height); return m_values[x + y * m_width]; }
|
||||
|
||||
@@ -4054,9 +4109,23 @@ 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(int x, int y) const { return (*this)((uint32_t)x, (uint32_t)y); }
|
||||
inline T& at(int x, int y) { return (*this)((uint32_t)x, (uint32_t)y); }
|
||||
|
||||
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)); }
|
||||
|
||||
inline const T& at_row_col(int y, int x) const { return (*this)(clamp<int>(x, 0, m_width - 1), clamp<int>(y, 0, m_height - 1)); }
|
||||
inline T& at_row_col(int y, int x) { return (*this)(clamp<int>(x, 0, m_width - 1), clamp<int>(y, 0, m_height - 1)); }
|
||||
|
||||
inline void set_clipped(int x, int y, const T& val)
|
||||
{
|
||||
if ( ((uint32_t)x >= m_width) || ((uint32_t)y >= m_height) )
|
||||
return;
|
||||
|
||||
m_values[x + y * m_width] = val;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_width = 0;
|
||||
@@ -4141,9 +4210,18 @@ namespace basisu
|
||||
return true;
|
||||
}
|
||||
|
||||
vector2D& resize_rows_cols(uint32_t rows, uint32_t cols)
|
||||
{
|
||||
return resize(cols, rows);
|
||||
}
|
||||
|
||||
bool try_resize_rows_cols(uint32_t rows, uint32_t cols)
|
||||
{
|
||||
return try_resize(cols, rows);
|
||||
}
|
||||
|
||||
const vector2D& extract_block_clamped(T* pDst, uint32_t src_x, uint32_t src_y, uint32_t w, uint32_t h) const
|
||||
{
|
||||
// HACK HACK
|
||||
if (((src_x + w) > m_width) || ((src_y + h) > m_height))
|
||||
{
|
||||
// Slower clamping case
|
||||
@@ -4165,8 +4243,87 @@ namespace basisu
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
const vector2D& extract_block_clamped(T* pDst, uint32_t src_x, uint32_t src_y, uint32_t w, uint32_t h, uint32_t override_height) const
|
||||
{
|
||||
assert(override_height && (override_height <= m_height));
|
||||
|
||||
if (((src_x + w) > m_width) || ((src_y + h) > minimum(m_height, override_height)))
|
||||
{
|
||||
// Slower clamping case
|
||||
for (uint32_t y = 0; y < h; y++)
|
||||
for (uint32_t x = 0; x < w; x++)
|
||||
*pDst++ = at_clamped(src_x + x, minimum(src_y + y, override_height - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
const T* pSrc = &m_values[src_x + src_y * m_width];
|
||||
|
||||
for (uint32_t y = 0; y < h; y++)
|
||||
{
|
||||
memcpy(pDst, pSrc, w * sizeof(T));
|
||||
pSrc += m_width;
|
||||
pDst += w;
|
||||
}
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
// Explictly primitive container intended for POD's, simple usage.
|
||||
// push_back() and resize() will refuse to push anymore and just return when full.
|
||||
template<typename T, uint32_t N>
|
||||
class static_vector
|
||||
{
|
||||
T m_data[N];
|
||||
uint32_t m_size;
|
||||
|
||||
public:
|
||||
static_vector() : m_size(0) { }
|
||||
|
||||
inline void reserve(size_t reserve_size)
|
||||
{
|
||||
(void)(reserve_size);
|
||||
|
||||
assert(reserve_size <= N);
|
||||
}
|
||||
|
||||
inline void push_back(const T& value)
|
||||
{
|
||||
// Should never happen.
|
||||
if (m_size >= N)
|
||||
{
|
||||
assert(0);
|
||||
fprintf(stderr, "basisu::static_vector overflow!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
m_data[m_size++] = value;
|
||||
}
|
||||
|
||||
inline std::size_t size() const { return m_size; }
|
||||
inline uint32_t size_u32() const { return m_size; }
|
||||
inline constexpr std::size_t capacity() const { return N; }
|
||||
|
||||
inline bool empty() const { return !m_size; }
|
||||
|
||||
inline T& operator[](std::size_t i) { return m_data[i]; }
|
||||
inline const T& operator[](std::size_t i) const { return m_data[i]; }
|
||||
|
||||
inline void resize(size_t new_size)
|
||||
{
|
||||
if (new_size > N)
|
||||
{
|
||||
assert(0);
|
||||
fprintf(stderr, "basisu::static_vector overflow!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
m_size = (uint32_t)new_size;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
namespace std
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace basisu
|
||||
#ifdef _MSC_VER
|
||||
__declspec(noreturn)
|
||||
#else
|
||||
[[noreturn]]
|
||||
[[noreturn]]
|
||||
#endif
|
||||
void container_abort(const char* pMsg, ...)
|
||||
{
|
||||
@@ -42,12 +42,12 @@ namespace basisu
|
||||
assert(m_size <= m_capacity);
|
||||
assert(min_new_capacity >= m_size);
|
||||
assert(element_size);
|
||||
|
||||
|
||||
// Basic sanity check min_new_capacity
|
||||
if (!can_fit_into_size_t((uint64_t)min_new_capacity * element_size))
|
||||
{
|
||||
assert(0);
|
||||
|
||||
|
||||
if (nofail_flag)
|
||||
return false;
|
||||
|
||||
@@ -100,7 +100,7 @@ namespace basisu
|
||||
}
|
||||
|
||||
const size_t desired_size = static_cast<size_t>(desired_size_u64);
|
||||
|
||||
|
||||
size_t actual_size = 0;
|
||||
BASISU_NOTE_UNUSED(actual_size);
|
||||
|
||||
@@ -109,6 +109,7 @@ namespace basisu
|
||||
void* new_p = realloc(m_p, desired_size);
|
||||
if (!new_p)
|
||||
{
|
||||
fprintf(stderr, "elemental_vector::increase_capacity: Allocation failed!\n");
|
||||
assert(0);
|
||||
|
||||
if (nofail_flag)
|
||||
@@ -133,7 +134,9 @@ namespace basisu
|
||||
void* new_p = malloc(desired_size);
|
||||
if (!new_p)
|
||||
{
|
||||
fprintf(stderr, "elemental_vector::increase_capacity: Allocation failed!\n");
|
||||
assert(0);
|
||||
|
||||
if (nofail_flag)
|
||||
return false;
|
||||
|
||||
@@ -269,7 +272,7 @@ namespace basisu
|
||||
s.insert(i);
|
||||
k.push_back(i);
|
||||
}
|
||||
|
||||
|
||||
for (uint32_t i = 0; i < k.size(); i++)
|
||||
{
|
||||
uint32_t r = rand() ^ (rand() << 15);
|
||||
@@ -315,7 +318,7 @@ namespace basisu
|
||||
{
|
||||
typedef basisu::hash_map< uint32_t, basisu::vector<uint32_t> > hm;
|
||||
hm q;
|
||||
|
||||
|
||||
basisu::vector<uint32_t> a, b;
|
||||
a.push_back(1);
|
||||
b.push_back(2);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// basis_file_headers.h
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
// 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.
|
||||
@@ -39,7 +39,7 @@ namespace basist
|
||||
basisu::packed_uint<2> m_orig_height; // The original image height (may not be a multiple of 4 pixels)
|
||||
|
||||
basisu::packed_uint<2> m_num_blocks_x; // The slice's block X dimensions. Each block is 4x4 or 6x6 pixels. The slice's pixel resolution may or may not be a power of 2.
|
||||
basisu::packed_uint<2> m_num_blocks_y; // The slice's block Y dimensions.
|
||||
basisu::packed_uint<2> m_num_blocks_y; // The slice's block Y dimensions.
|
||||
|
||||
basisu::packed_uint<4> m_file_ofs; // Offset from the start of the file to the start of the slice's data
|
||||
basisu::packed_uint<4> m_file_size; // The size of the compressed slice data in bytes
|
||||
@@ -59,16 +59,16 @@ namespace basist
|
||||
// Set if any slices contain alpha (for ETC1S, if the odd slices contain alpha data)
|
||||
cBASISHeaderFlagHasAlphaSlices = 4,
|
||||
|
||||
// For ETC1S files, this will be true if the file utilizes a codebook from another .basis file.
|
||||
// For ETC1S files, this will be true if the file utilizes a codebook from another .basis file.
|
||||
cBASISHeaderFlagUsesGlobalCodebook = 8,
|
||||
|
||||
// Set if the texture data is sRGB, otherwise it's linear.
|
||||
// Set if the texture data is sRGB, otherwise it's linear.
|
||||
// In reality, we have no idea if the texture data is actually linear or sRGB. This is the m_perceptual parameter passed to the compressor.
|
||||
cBASISHeaderFlagSRGB = 16,
|
||||
};
|
||||
|
||||
// The image type field attempts to describe how to interpret the image data in a Basis file.
|
||||
// The encoder library doesn't really do anything special or different with these texture types, this is mostly here for the benefit of the user.
|
||||
// The encoder library doesn't really do anything special or different with these texture types, this is mostly here for the benefit of the user.
|
||||
// We do make sure the various constraints are followed (2DArray/cubemap/videoframes/volume implies that each image has the same resolution and # of mipmap levels, etc., cubemap implies that the # of image slices is a multiple of 6)
|
||||
enum basis_texture_type
|
||||
{
|
||||
@@ -88,14 +88,113 @@ namespace basist
|
||||
|
||||
enum class basis_tex_format
|
||||
{
|
||||
// Original LDR formats
|
||||
cETC1S = 0,
|
||||
cUASTC4x4 = 1,
|
||||
cUASTC_LDR_4x4 = 1,
|
||||
|
||||
// HDR formats
|
||||
cUASTC_HDR_4x4 = 2,
|
||||
cASTC_HDR_6x6 = 3,
|
||||
cASTC_HDR_6x6_INTERMEDIATE = 4,
|
||||
cUASTC_HDR_6x6_INTERMEDIATE = 4, // TODO: rename to UASTC_HDR_6x6
|
||||
|
||||
// XUASTC (supercompressed) LDR variants (the standard ASTC block sizes)
|
||||
cXUASTC_LDR_4x4 = 5,
|
||||
cXUASTC_LDR_5x4 = 6,
|
||||
cXUASTC_LDR_5x5 = 7,
|
||||
cXUASTC_LDR_6x5 = 8,
|
||||
|
||||
cXUASTC_LDR_6x6 = 9,
|
||||
cXUASTC_LDR_8x5 = 10,
|
||||
cXUASTC_LDR_8x6 = 11,
|
||||
cXUASTC_LDR_10x5 = 12,
|
||||
|
||||
cXUASTC_LDR_10x6 = 13,
|
||||
cXUASTC_LDR_8x8 = 14,
|
||||
cXUASTC_LDR_10x8 = 15,
|
||||
cXUASTC_LDR_10x10 = 16,
|
||||
|
||||
cXUASTC_LDR_12x10 = 17,
|
||||
cXUASTC_LDR_12x12 = 18,
|
||||
|
||||
// Standard (non-supercompressed) ASTC LDR variants (the standard ASTC block sizes)
|
||||
cASTC_LDR_4x4 = 19,
|
||||
cASTC_LDR_5x4 = 20,
|
||||
cASTC_LDR_5x5 = 21,
|
||||
cASTC_LDR_6x5 = 22,
|
||||
|
||||
cASTC_LDR_6x6 = 23,
|
||||
cASTC_LDR_8x5 = 24,
|
||||
cASTC_LDR_8x6 = 25,
|
||||
cASTC_LDR_10x5 = 26,
|
||||
|
||||
cASTC_LDR_10x6 = 27,
|
||||
cASTC_LDR_8x8 = 28,
|
||||
cASTC_LDR_10x8 = 29,
|
||||
cASTC_LDR_10x10 = 30,
|
||||
|
||||
cASTC_LDR_12x10 = 31,
|
||||
cASTC_LDR_12x12 = 32,
|
||||
|
||||
cTotalFormats
|
||||
};
|
||||
|
||||
// True if the basis_tex_format is XUASTC LDR 4x4-12x12.
|
||||
inline bool basis_tex_format_is_xuastc_ldr(basis_tex_format tex_fmt)
|
||||
{
|
||||
return ((uint32_t)tex_fmt >= (uint32_t)basis_tex_format::cXUASTC_LDR_4x4) && ((uint32_t)tex_fmt <= (uint32_t)basis_tex_format::cXUASTC_LDR_12x12);
|
||||
}
|
||||
|
||||
// True if the basis_tex_format is ASTC LDR 4x4-12x12.
|
||||
inline bool basis_tex_format_is_astc_ldr(basis_tex_format tex_fmt)
|
||||
{
|
||||
return ((uint32_t)tex_fmt >= (uint32_t)basis_tex_format::cASTC_LDR_4x4) && ((uint32_t)tex_fmt <= (uint32_t)basis_tex_format::cASTC_LDR_12x12);
|
||||
}
|
||||
|
||||
inline void get_basis_tex_format_block_size(basis_tex_format tex_fmt, uint32_t &width, uint32_t &height)
|
||||
{
|
||||
switch (tex_fmt)
|
||||
{
|
||||
case basis_tex_format::cETC1S: width = 4; height = 4; break;
|
||||
case basis_tex_format::cUASTC_LDR_4x4: width = 4; height = 4; break;
|
||||
case basis_tex_format::cUASTC_HDR_4x4: width = 4; height = 4; break;
|
||||
case basis_tex_format::cASTC_HDR_6x6: width = 6; height = 6; break;
|
||||
case basis_tex_format::cUASTC_HDR_6x6_INTERMEDIATE: width = 6; height = 6; break;
|
||||
case basis_tex_format::cXUASTC_LDR_4x4: width = 4; height = 4; break;
|
||||
case basis_tex_format::cXUASTC_LDR_5x4: width = 5; height = 4; break;
|
||||
case basis_tex_format::cXUASTC_LDR_5x5: width = 5; height = 5; break;
|
||||
case basis_tex_format::cXUASTC_LDR_6x5: width = 6; height = 5; break;
|
||||
case basis_tex_format::cXUASTC_LDR_6x6: width = 6; height = 6; break;
|
||||
case basis_tex_format::cXUASTC_LDR_8x5: width = 8; height = 5; break;
|
||||
case basis_tex_format::cXUASTC_LDR_8x6: width = 8; height = 6; break;
|
||||
case basis_tex_format::cXUASTC_LDR_10x5: width = 10; height = 5; break;
|
||||
case basis_tex_format::cXUASTC_LDR_10x6: width = 10; height = 6; break;
|
||||
case basis_tex_format::cXUASTC_LDR_8x8: width = 8; height = 8; break;
|
||||
case basis_tex_format::cXUASTC_LDR_10x8: width = 10; height = 8; break;
|
||||
case basis_tex_format::cXUASTC_LDR_10x10: width = 10; height = 10; break;
|
||||
case basis_tex_format::cXUASTC_LDR_12x10: width = 12; height = 10; break;
|
||||
case basis_tex_format::cXUASTC_LDR_12x12: width = 12; height = 12; break;
|
||||
case basis_tex_format::cASTC_LDR_4x4: width = 4; height = 4; break;
|
||||
case basis_tex_format::cASTC_LDR_5x4: width = 5; height = 4; break;
|
||||
case basis_tex_format::cASTC_LDR_5x5: width = 5; height = 5; break;
|
||||
case basis_tex_format::cASTC_LDR_6x5: width = 6; height = 5; break;
|
||||
case basis_tex_format::cASTC_LDR_6x6: width = 6; height = 6; break;
|
||||
case basis_tex_format::cASTC_LDR_8x5: width = 8; height = 5; break;
|
||||
case basis_tex_format::cASTC_LDR_8x6: width = 8; height = 6; break;
|
||||
case basis_tex_format::cASTC_LDR_10x5: width = 10; height = 5; break;
|
||||
case basis_tex_format::cASTC_LDR_10x6: width = 10; height = 6; break;
|
||||
case basis_tex_format::cASTC_LDR_8x8: width = 8; height = 8; break;
|
||||
case basis_tex_format::cASTC_LDR_10x8: width = 10; height = 8; break;
|
||||
case basis_tex_format::cASTC_LDR_10x10: width = 10; height = 10; break;
|
||||
case basis_tex_format::cASTC_LDR_12x10: width = 12; height = 10; break;
|
||||
case basis_tex_format::cASTC_LDR_12x12: width = 12; height = 12; break;
|
||||
default:
|
||||
assert(0);
|
||||
width = 0;
|
||||
height = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct basis_file_header
|
||||
{
|
||||
enum
|
||||
@@ -115,7 +214,7 @@ namespace basist
|
||||
basisu::packed_uint<3> m_total_slices; // The total # of compressed slices (1 slice per image, or 2 for alpha .basis files)
|
||||
|
||||
basisu::packed_uint<3> m_total_images; // The total # of images
|
||||
|
||||
|
||||
basisu::packed_uint<1> m_tex_format; // enum basis_tex_format
|
||||
basisu::packed_uint<2> m_flags; // enum basist::header_flags
|
||||
basisu::packed_uint<1> m_tex_type; // enum basist::basis_texture_type
|
||||
@@ -125,11 +224,11 @@ namespace basist
|
||||
basisu::packed_uint<4> m_userdata0; // For client use
|
||||
basisu::packed_uint<4> m_userdata1; // For client use
|
||||
|
||||
basisu::packed_uint<2> m_total_endpoints; // The number of endpoints in the endpoint codebook
|
||||
basisu::packed_uint<2> m_total_endpoints; // The number of endpoints in the endpoint codebook
|
||||
basisu::packed_uint<4> m_endpoint_cb_file_ofs; // The compressed endpoint codebook's file offset relative to the start of the file
|
||||
basisu::packed_uint<3> m_endpoint_cb_file_size; // The compressed endpoint codebook's size in bytes
|
||||
|
||||
basisu::packed_uint<2> m_total_selectors; // The number of selectors in the endpoint codebook
|
||||
basisu::packed_uint<2> m_total_selectors; // The number of selectors in the endpoint codebook
|
||||
basisu::packed_uint<4> m_selector_cb_file_ofs; // The compressed selectors codebook's file offset relative to the start of the file
|
||||
basisu::packed_uint<3> m_selector_cb_file_size; // The compressed selector codebook's size in bytes
|
||||
|
||||
@@ -137,7 +236,7 @@ namespace basist
|
||||
basisu::packed_uint<4> m_tables_file_size; // The file size in bytes of the compressed huffman codelength tables
|
||||
|
||||
basisu::packed_uint<4> m_slice_desc_file_ofs; // The file offset to the slice description array, usually follows the header
|
||||
|
||||
|
||||
basisu::packed_uint<4> m_extended_file_ofs; // The file offset of the "extended" header and compressed data, for future use
|
||||
basisu::packed_uint<4> m_extended_file_size; // The file size in bytes of the "extended" header and compressed data, for future use
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
// basisu_transcoder.h
|
||||
// Copyright (C) 2019-2024 Binomial LLC. All Rights Reserved.
|
||||
// Copyright (C) 2019-2026 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");
|
||||
@@ -13,6 +13,8 @@
|
||||
// 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.
|
||||
//
|
||||
// Also see basis_tex_format in basisu_file_headers.h (TODO: Perhaps move key definitions into here.)
|
||||
#pragma once
|
||||
|
||||
// By default KTX2 support is enabled to simplify compilation. This implies the need for the Zstandard library (which we distribute as a single source file in the "zstd" directory) by default.
|
||||
@@ -22,17 +24,11 @@
|
||||
#define BASISD_SUPPORT_KTX2 1
|
||||
#endif
|
||||
|
||||
// Set BASISD_SUPPORT_KTX2_ZSTD to 0 to disable Zstd usage and KTX2 UASTC Zstd supercompression support
|
||||
// Set BASISD_SUPPORT_KTX2_ZSTD to 0 to disable Zstd usage and KTX2 UASTC Zstd supercompression support
|
||||
#ifndef BASISD_SUPPORT_KTX2_ZSTD
|
||||
#define BASISD_SUPPORT_KTX2_ZSTD 1
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
||||
#include "basisu_transcoder_internal.h"
|
||||
#include "basisu_transcoder_uastc.h"
|
||||
#include "basisu_file_headers.h"
|
||||
@@ -42,7 +38,7 @@ namespace basist
|
||||
// High-level composite texture formats supported by the transcoder.
|
||||
// Each of these texture formats directly correspond to OpenGL/D3D/Vulkan etc. texture formats.
|
||||
// Notes:
|
||||
// - If you specify a texture format that supports alpha, but the .basis file doesn't have alpha, the transcoder will automatically output a
|
||||
// - If you specify a texture format that supports alpha, but the .basis file doesn't have alpha, the transcoder will automatically output a
|
||||
// fully opaque (255) alpha channel.
|
||||
// - The PVRTC1 texture formats only support power of 2 dimension .basis files, but this may be relaxed in a future version.
|
||||
// - The PVRTC1 transcoders are real-time encoders, so don't expect the highest quality. We may add a slower encoder with improved quality.
|
||||
@@ -66,13 +62,13 @@ namespace basist
|
||||
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.
|
||||
|
||||
// ASTC (mobile, Intel devices, hopefully all desktop GPU's one day)
|
||||
cTFASTC_4x4_RGBA = 10, // LDR. Opaque+alpha, ASTC 4x4, alpha channel will be opaque for opaque .basis files.
|
||||
// ASTC (mobile, some Intel CPU's, hopefully all desktop GPU's one day)
|
||||
cTFASTC_LDR_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)
|
||||
cTFATC_RGBA = 12, // Opaque+alpha, alpha channel will be opaque for opaque .basis files. ATI ATC (GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD)
|
||||
cTFATC_RGBA = 12, // Opaque+alpha, alpha channel will be opaque for opaque .basis files. ATI ATC (GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD)
|
||||
|
||||
// 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).
|
||||
@@ -94,7 +90,7 @@ namespace basist
|
||||
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
|
||||
|
||||
|
||||
// Note these uncompressed formats (HALF and 9E5) can only be transcoded to from HDR input files (UASTC HDR 4x4 or ASTC HDR 6x6).
|
||||
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)
|
||||
@@ -102,7 +98,23 @@ namespace basist
|
||||
|
||||
cTFASTC_HDR_6x6_RGBA = 27, // HDR, RGBA (currently our ASTC HDR 6x6 encodes are only RGB), unsigned
|
||||
|
||||
cTFTotalTextureFormats = 28,
|
||||
|
||||
// The remaining LDR ASTC block sizes, excluding 4x4 (which is above). There are 14 total valid ASTC LDR/HDR block sizes.
|
||||
cTFASTC_LDR_5x4_RGBA = 28,
|
||||
cTFASTC_LDR_5x5_RGBA = 29,
|
||||
cTFASTC_LDR_6x5_RGBA = 30,
|
||||
cTFASTC_LDR_6x6_RGBA = 31,
|
||||
cTFASTC_LDR_8x5_RGBA = 32,
|
||||
cTFASTC_LDR_8x6_RGBA = 33,
|
||||
cTFASTC_LDR_10x5_RGBA = 34,
|
||||
cTFASTC_LDR_10x6_RGBA = 35,
|
||||
cTFASTC_LDR_8x8_RGBA = 36,
|
||||
cTFASTC_LDR_10x8_RGBA = 37,
|
||||
cTFASTC_LDR_10x10_RGBA = 38,
|
||||
cTFASTC_LDR_12x10_RGBA = 39,
|
||||
cTFASTC_LDR_12x12_RGBA = 40,
|
||||
|
||||
cTFTotalTextureFormats = 41,
|
||||
|
||||
// ----- The following are old/legacy enums for compatibility with code compiled against previous versions
|
||||
cTFETC1 = cTFETC1_RGB,
|
||||
@@ -112,25 +124,30 @@ namespace basist
|
||||
cTFBC4 = cTFBC4_R,
|
||||
cTFBC5 = cTFBC5_RG,
|
||||
|
||||
// Previously, the caller had some control over which BC7 mode the transcoder output. We've simplified this due to UASTC, which supports numerous modes.
|
||||
// Previously, the caller had some control over which BC7 mode the transcoder output. We've simplified this due to UASTC LDR 4x4, which supports numerous modes.
|
||||
cTFBC7_M6_RGB = cTFBC7_RGBA, // Opaque only, RGB or alpha if cDecodeFlagsTranscodeAlphaDataToOpaqueFormats flag is specified. Highest quality of all the non-ETC1 formats.
|
||||
cTFBC7_M5_RGBA = cTFBC7_RGBA, // Opaque+alpha, alpha channel will be opaque for opaque .basis files
|
||||
cTFBC7_M6_OPAQUE_ONLY = cTFBC7_RGBA,
|
||||
cTFBC7_M5 = cTFBC7_RGBA,
|
||||
cTFBC7_ALT = 7,
|
||||
|
||||
cTFASTC_4x4 = cTFASTC_4x4_RGBA,
|
||||
cTFASTC_4x4 = cTFASTC_LDR_4x4_RGBA,
|
||||
|
||||
cTFATC_RGBA_INTERPOLATED_ALPHA = cTFATC_RGBA,
|
||||
|
||||
cTFASTC_4x4_RGBA = cTFASTC_LDR_4x4_RGBA
|
||||
};
|
||||
|
||||
// For compressed texture formats, this returns the # of bytes per block. For uncompressed, it returns the # of bytes per pixel.
|
||||
// NOTE: Previously, this function was called basis_get_bytes_per_block(), and it always returned 16*bytes_per_pixel for uncompressed formats which was confusing.
|
||||
uint32_t basis_get_bytes_per_block_or_pixel(transcoder_texture_format fmt);
|
||||
|
||||
// Returns format's name in ASCII
|
||||
// Returns the transcoder texture format's name in ASCII
|
||||
const char* basis_get_format_name(transcoder_texture_format fmt);
|
||||
|
||||
// Returns basis texture format name in ASCII
|
||||
const char* basis_get_tex_format_name(basis_tex_format fmt);
|
||||
|
||||
// Returns block format name in ASCII
|
||||
const char* basis_get_block_format_name(block_format fmt);
|
||||
|
||||
@@ -143,6 +160,9 @@ namespace basist
|
||||
// Returns true if the format is LDR.
|
||||
inline bool basis_transcoder_format_is_ldr(transcoder_texture_format fmt) { return !basis_transcoder_format_is_hdr(fmt); }
|
||||
|
||||
// Returns true if the format is an LDR or HDR ASTC format.
|
||||
bool basis_is_transcoder_texture_format_astc(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);
|
||||
|
||||
@@ -156,23 +176,32 @@ namespace basist
|
||||
uint32_t basis_get_uncompressed_bytes_per_pixel(transcoder_texture_format fmt);
|
||||
|
||||
// Returns the block width for the specified texture format, which is currently either 4 or 8 for FXT1.
|
||||
uint32_t basis_get_block_width(transcoder_texture_format tex_type);
|
||||
uint32_t basis_get_block_width(transcoder_texture_format fmt);
|
||||
|
||||
// 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);
|
||||
uint32_t basis_get_block_height(transcoder_texture_format fmt);
|
||||
|
||||
// ASTC/XUASTC LDR formats only: Given a basis_tex_format (mode or codec), return the corresponding ASTC basisu::texture_format with the proper block size from 4x4-12x12.
|
||||
basisu::texture_format basis_get_texture_format_from_xuastc_or_astc_ldr_basis_tex_format(basis_tex_format fmt);
|
||||
|
||||
// For any given basis_tex_format (mode or codec), return the LDR/HDR ASTC transcoder texture format with the proper block size.
|
||||
transcoder_texture_format basis_get_transcoder_texture_format_from_basis_tex_format(basis_tex_format fmt);
|
||||
// basis_get_transcoder_texture_format_from_xuastc_or_astc_ldr_basis_tex_format: same as basis_get_transcoder_texture_format_from_basis_tex_format (TODO: remove)
|
||||
transcoder_texture_format basis_get_transcoder_texture_format_from_xuastc_or_astc_ldr_basis_tex_format(basis_tex_format fmt);
|
||||
|
||||
// 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).
|
||||
// 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, or XUASTC LDR 4x4-12x12).
|
||||
// For XUASTC the ASTC block size must match the transcoder_texture_format's ASTC block size.
|
||||
bool basis_is_format_supported(transcoder_texture_format tex_type, basis_tex_format fmt = basis_tex_format::cETC1S);
|
||||
|
||||
// Returns the block width/height for the specified basis texture file format.
|
||||
uint32_t basis_tex_format_get_block_width(basis_tex_format fmt);
|
||||
uint32_t basis_tex_format_get_block_height(basis_tex_format fmt);
|
||||
|
||||
|
||||
bool basis_tex_format_is_hdr(basis_tex_format fmt);
|
||||
inline bool basis_tex_format_is_ldr(basis_tex_format fmt) { return !basis_tex_format_is_hdr(fmt); }
|
||||
|
||||
|
||||
// Validates that the output buffer is large enough to hold the entire transcoded texture.
|
||||
// For uncompressed texture formats, most input parameters are in pixels, not blocks. Blocks are 4x4 pixels.
|
||||
// For uncompressed texture formats, most input parameters are in pixels, not blocks.
|
||||
bool basis_validate_output_buffer_size(transcoder_texture_format target_format,
|
||||
uint32_t output_blocks_buf_size_in_blocks_or_pixels,
|
||||
uint32_t orig_width, uint32_t orig_height,
|
||||
@@ -199,7 +228,7 @@ namespace basist
|
||||
basisu::vector<block_preds> m_block_endpoint_preds[2];
|
||||
|
||||
enum { cMaxPrevFrameLevels = 16 };
|
||||
basisu::vector<uint32_t> m_prev_frame_indices[2][cMaxPrevFrameLevels]; // [alpha_flag][level_index]
|
||||
basisu::vector<uint32_t> m_prev_frame_indices[2][cMaxPrevFrameLevels]; // [alpha_flag][level_index]
|
||||
|
||||
void clear()
|
||||
{
|
||||
@@ -214,7 +243,46 @@ namespace basist
|
||||
};
|
||||
|
||||
// Low-level helper classes that do the actual transcoding.
|
||||
enum basisu_decode_flags
|
||||
{
|
||||
// PVRTC1: decode non-pow2 ETC1S texture level to the next larger power of 2 (not implemented yet, but we're going to support it). Ignored if the slice's dimensions are already a power of 2.
|
||||
cDecodeFlagsPVRTCDecodeToNextPow2 = 2,
|
||||
|
||||
// When decoding to an opaque texture format, if the basis file has alpha, decode the alpha slice instead of the color slice to the output texture format.
|
||||
// This is primarily to allow decoding of textures with alpha to multiple ETC1 textures (one for color, another for alpha).
|
||||
cDecodeFlagsTranscodeAlphaDataToOpaqueFormats = 4,
|
||||
|
||||
// Forbid usage of BC1 3 color blocks (we don't support BC1 punchthrough alpha yet).
|
||||
// This flag is used internally when decoding to BC3.
|
||||
cDecodeFlagsBC1ForbidThreeColorBlocks = 8,
|
||||
|
||||
// The output buffer contains alpha endpoint/selector indices.
|
||||
// Used internally when decoding formats like ASTC that require both color and alpha data to be available when transcoding to the output format.
|
||||
cDecodeFlagsOutputHasAlphaIndices = 16,
|
||||
|
||||
// Enable slower, but higher quality transcoding for some formats.
|
||||
// For ASTC/XUASTC->BC7, this enables partially analytical encoding vs. fully analytical.
|
||||
cDecodeFlagsHighQuality = 32,
|
||||
|
||||
// Disable ETC1S->BC7 adaptive chroma filtering, for much faster transcoding to BC7.
|
||||
cDecodeFlagsNoETC1SChromaFiltering = 64,
|
||||
|
||||
// Disable deblock filtering for XUASTC LDR transcoding to non-ASTC formats.
|
||||
// For ASTC 8x6 or smaller block sizes, deblocking is always disabled unless you force it on using cDecodeFlagsForceDeblockFiltering.
|
||||
cDecodeFlagsNoDeblockFiltering = 128,
|
||||
|
||||
// More aggressive deblock filtering (only used when it's enabled)
|
||||
cDecodeFlagsStrongerDeblockFiltering = 256,
|
||||
|
||||
// Always apply deblocking, even for smaller ASTC block sizes (4x4-8x6).
|
||||
cDecodeFlagsForceDeblockFiltering = 512,
|
||||
|
||||
// By default XUASTC LDR 4x4, 6x6 and 8x6 are directly transcoded to BC7 without always requiring a full ASTC block unpack and analytical BC7 encode. This is 1.4x up to 3x faster in WASM.
|
||||
// This trade offs some quality. The largest transcoding speed gain is achieved when the source XUASTC data isn't dual plane and only uses 1 subset. Otherwise the actual perf. gain is variable.
|
||||
// To disable this optimization for all XUASTC block sizes and always use the fallback encoder, specify cDecodeFlagXUASTCLDRDisableFastBC7Transcoding.
|
||||
cDecodeFlagXUASTCLDRDisableFastBC7Transcoding = 1024
|
||||
};
|
||||
|
||||
// ETC1S
|
||||
class basisu_lowlevel_etc1s_transcoder
|
||||
{
|
||||
@@ -279,42 +347,20 @@ namespace basist
|
||||
|
||||
typedef basisu::vector<selector> selector_vec;
|
||||
const selector_vec& get_selectors() const { return m_local_selectors; }
|
||||
|
||||
|
||||
private:
|
||||
const basisu_lowlevel_etc1s_transcoder* m_pGlobal_codebook;
|
||||
|
||||
endpoint_vec m_local_endpoints;
|
||||
selector_vec m_local_selectors;
|
||||
|
||||
|
||||
huffman_decoding_table m_endpoint_pred_model, m_delta_endpoint_model, m_selector_model, m_selector_history_buf_rle_model;
|
||||
|
||||
uint32_t m_selector_history_buf_size;
|
||||
|
||||
basisu_transcoder_state m_def_state;
|
||||
};
|
||||
|
||||
enum basisu_decode_flags
|
||||
{
|
||||
// PVRTC1: decode non-pow2 ETC1S texture level to the next larger power of 2 (not implemented yet, but we're going to support it). Ignored if the slice's dimensions are already a power of 2.
|
||||
cDecodeFlagsPVRTCDecodeToNextPow2 = 2,
|
||||
|
||||
// When decoding to an opaque texture format, if the basis file has alpha, decode the alpha slice instead of the color slice to the output texture format.
|
||||
// This is primarily to allow decoding of textures with alpha to multiple ETC1 textures (one for color, another for alpha).
|
||||
cDecodeFlagsTranscodeAlphaDataToOpaqueFormats = 4,
|
||||
|
||||
// Forbid usage of BC1 3 color blocks (we don't support BC1 punchthrough alpha yet).
|
||||
// This flag is used internally when decoding to BC3.
|
||||
cDecodeFlagsBC1ForbidThreeColorBlocks = 8,
|
||||
|
||||
// The output buffer contains alpha endpoint/selector indices.
|
||||
// Used internally when decoding formats like ASTC that require both color and alpha data to be available when transcoding to the output format.
|
||||
cDecodeFlagsOutputHasAlphaIndices = 16,
|
||||
|
||||
cDecodeFlagsHighQuality = 32,
|
||||
|
||||
cDecodeFlagsNoETC1SChromaFiltering = 64
|
||||
};
|
||||
|
||||
|
||||
// UASTC LDR 4x4
|
||||
class basisu_lowlevel_uastc_ldr_4x4_transcoder
|
||||
{
|
||||
@@ -352,6 +398,76 @@ namespace basist
|
||||
int channel0 = -1, int channel1 = -1);
|
||||
};
|
||||
|
||||
#if BASISD_SUPPORT_XUASTC
|
||||
// XUASTC LDR 4x4-12x12 or ASTC LDR 4x4-12x12
|
||||
struct xuastc_decoded_image
|
||||
{
|
||||
uint32_t m_actual_block_width = 0, m_actual_block_height = 0, m_actual_width = 0, m_actual_height = 0;
|
||||
bool m_actual_has_alpha = false, m_uses_srgb_astc_decode_mode = false;
|
||||
|
||||
bool decode(const uint8_t* pImage_data, uint32_t image_data_size,
|
||||
astc_ldr_t::xuastc_decomp_image_init_callback_ptr pInit_callback, void* pInit_callback_data,
|
||||
astc_ldr_t::xuastc_decomp_image_block_callback_ptr pBlock_callback, void* pBlock_callback_data)
|
||||
{
|
||||
const bool decomp_flag = astc_ldr_t::xuastc_ldr_decompress_image(pImage_data, image_data_size,
|
||||
m_actual_block_width, m_actual_block_height,
|
||||
m_actual_width, m_actual_height,
|
||||
m_actual_has_alpha, m_uses_srgb_astc_decode_mode, basisu::g_debug_printf,
|
||||
pInit_callback, pInit_callback_data,
|
||||
pBlock_callback, pBlock_callback_data);
|
||||
|
||||
return decomp_flag;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_actual_block_width = 0;
|
||||
m_actual_block_height = 0;
|
||||
m_actual_width = 0;
|
||||
m_actual_height = 0;
|
||||
m_actual_has_alpha = false;
|
||||
m_uses_srgb_astc_decode_mode = false;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class basisu_lowlevel_xuastc_ldr_transcoder
|
||||
{
|
||||
friend class basisu_transcoder;
|
||||
|
||||
public:
|
||||
basisu_lowlevel_xuastc_ldr_transcoder();
|
||||
|
||||
bool transcode_slice(basis_tex_format src_format, bool use_astc_srgb_decode_profile, void* pDst_blocks, uint32_t src_num_blocks_x, uint32_t src_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(basis_tex_format src_format, bool use_astc_srgb_decode_profile, void* pDst_blocks, uint32_t src_num_blocks_x, uint32_t src_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(src_format, use_astc_srgb_decode_profile, pDst_blocks, src_num_blocks_x, src_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(
|
||||
basis_tex_format src_format, bool use_astc_srgb_decode_profile,
|
||||
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 src_num_blocks_x, uint32_t src_num_blocks_y, uint32_t orig_width, uint32_t orig_height, uint32_t level_index,
|
||||
uint64_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);
|
||||
};
|
||||
|
||||
// UASTC HDR 4x4
|
||||
class basisu_lowlevel_uastc_hdr_4x4_transcoder
|
||||
{
|
||||
@@ -426,13 +542,13 @@ namespace basist
|
||||
int channel0 = -1, int channel1 = -1);
|
||||
};
|
||||
|
||||
// ASTC HDR 6x6 intermediate
|
||||
class basisu_lowlevel_astc_hdr_6x6_intermediate_transcoder
|
||||
// UASTC HDR 6x6 intermediate
|
||||
class basisu_lowlevel_uastc_hdr_6x6_intermediate_transcoder
|
||||
{
|
||||
friend class basisu_transcoder;
|
||||
|
||||
public:
|
||||
basisu_lowlevel_astc_hdr_6x6_intermediate_transcoder();
|
||||
basisu_lowlevel_uastc_hdr_6x6_intermediate_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,
|
||||
@@ -465,9 +581,11 @@ namespace basist
|
||||
|
||||
struct basisu_slice_info
|
||||
{
|
||||
// The image's ACTUAL dimensions in texels.
|
||||
uint32_t m_orig_width;
|
||||
uint32_t m_orig_height;
|
||||
|
||||
// The texture's dimensions in texels - always a multiple of the texture's underlying block size (4x4-12x12).
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
|
||||
@@ -497,9 +615,11 @@ namespace basist
|
||||
uint32_t m_image_index;
|
||||
uint32_t m_total_levels;
|
||||
|
||||
// The image's ACTUAL dimensions in texels.
|
||||
uint32_t m_orig_width;
|
||||
uint32_t m_orig_height;
|
||||
|
||||
|
||||
// The texture's dimensions in texels - always a multiple of the texture's underlying block size (4x4-12x12).
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
|
||||
@@ -583,12 +703,13 @@ namespace basist
|
||||
uint32_t m_block_height;
|
||||
|
||||
bool m_y_flipped; // true if the image was Y flipped
|
||||
bool m_srgb; // true if the image is sRGB, false if linear
|
||||
bool m_etc1s; // true if the file is ETC1S
|
||||
bool m_has_alpha_slices; // true if the texture has alpha slices (for ETC1S: even slices RGB, odd slices alpha)
|
||||
};
|
||||
|
||||
// High-level transcoder class which accepts .basis file data and allows the caller to query information about the file and transcode image levels to various texture formats.
|
||||
// If you're just starting out this is the class you care about.
|
||||
// If you're just starting out this is the class you care about (or see the KTX2 transcoder below).
|
||||
class basisu_transcoder
|
||||
{
|
||||
basisu_transcoder(basisu_transcoder&);
|
||||
@@ -639,11 +760,11 @@ namespace basist
|
||||
// transcode_image_level() decodes a single mipmap level from the .basis file to any of the supported output texture formats.
|
||||
// It'll first find the slice(s) to transcode, then call transcode_slice() one or two times to decode both the color and alpha texture data (or RG texture data from two slices for BC5).
|
||||
// If the .basis file doesn't have alpha slices, the output alpha blocks will be set to fully opaque (all 255's).
|
||||
// Currently, to decode to PVRTC1 the basis texture's dimensions in pixels must be a power of 2, due to PVRTC1 format requirements.
|
||||
// Currently, to decode to PVRTC1 the basis texture's dimensions in pixels must be a power of 2, due to PVRTC1 format requirements.
|
||||
// output_blocks_buf_size_in_blocks_or_pixels should be at least the image level's total_blocks (num_blocks_x * num_blocks_y), or the total number of output pixels if fmt==cTFRGBA32 etc.
|
||||
// output_row_pitch_in_blocks_or_pixels: Number of blocks or pixels per row. If 0, the transcoder uses the slice's num_blocks_x or orig_width (NOT num_blocks_x * 4). Ignored for PVRTC1 (due to texture swizzling).
|
||||
// output_rows_in_pixels: Ignored unless fmt is uncompressed (cRGBA32, etc.). The total number of output rows in the output buffer. If 0, the transcoder assumes the slice's orig_height (NOT num_blocks_y * 4).
|
||||
// Notes:
|
||||
// Notes:
|
||||
// - basisu_transcoder_init() must have been called first to initialize the transcoder lookup tables before calling this function.
|
||||
// - This method assumes the output texture buffer is readable. In some cases to handle alpha, the transcoder will write temporary data to the output texture in
|
||||
// a first pass, which will be read in a second pass.
|
||||
@@ -682,15 +803,16 @@ namespace basist
|
||||
const basisu_lowlevel_etc1s_transcoder& get_lowlevel_etc1s_decoder() const { return m_lowlevel_etc1s_decoder; }
|
||||
basisu_lowlevel_etc1s_transcoder& get_lowlevel_etc1s_decoder() { return m_lowlevel_etc1s_decoder; }
|
||||
|
||||
const basisu_lowlevel_uastc_ldr_4x4_transcoder& get_lowlevel_uastc_decoder() const { return m_lowlevel_uastc_decoder; }
|
||||
basisu_lowlevel_uastc_ldr_4x4_transcoder& get_lowlevel_uastc_decoder() { return m_lowlevel_uastc_decoder; }
|
||||
const basisu_lowlevel_uastc_ldr_4x4_transcoder& get_lowlevel_uastc_decoder() const { return m_lowlevel_uastc_ldr_4x4_decoder; }
|
||||
basisu_lowlevel_uastc_ldr_4x4_transcoder& get_lowlevel_uastc_decoder() { return m_lowlevel_uastc_ldr_4x4_decoder; }
|
||||
|
||||
private:
|
||||
mutable basisu_lowlevel_etc1s_transcoder m_lowlevel_etc1s_decoder;
|
||||
mutable basisu_lowlevel_uastc_ldr_4x4_transcoder m_lowlevel_uastc_decoder;
|
||||
mutable basisu_lowlevel_uastc_ldr_4x4_transcoder m_lowlevel_uastc_ldr_4x4_decoder;
|
||||
mutable basisu_lowlevel_xuastc_ldr_transcoder m_lowlevel_xuastc_ldr_decoder;
|
||||
mutable basisu_lowlevel_uastc_hdr_4x4_transcoder m_lowlevel_uastc_4x4_hdr_decoder;
|
||||
mutable basisu_lowlevel_astc_hdr_6x6_transcoder m_lowlevel_astc_6x6_hdr_decoder;
|
||||
mutable basisu_lowlevel_astc_hdr_6x6_intermediate_transcoder m_lowlevel_astc_6x6_hdr_intermediate_decoder;
|
||||
mutable basisu_lowlevel_uastc_hdr_6x6_intermediate_transcoder m_lowlevel_astc_6x6_hdr_intermediate_decoder;
|
||||
|
||||
bool m_ready_to_transcode;
|
||||
|
||||
@@ -701,7 +823,7 @@ namespace basist
|
||||
|
||||
// basisu_transcoder_init() MUST be called before a .basis file can be transcoded.
|
||||
void basisu_transcoder_init();
|
||||
|
||||
|
||||
enum debug_flags_t
|
||||
{
|
||||
cDebugFlagVisCRs = 1,
|
||||
@@ -711,10 +833,10 @@ namespace basist
|
||||
uint32_t get_debug_flags();
|
||||
void set_debug_flags(uint32_t f);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// Optional .KTX2 file format support
|
||||
// KTX2 reading optionally requires miniz or Zstd decompressors for supercompressed UASTC files.
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
// ------------------------------------------------------------------------------------------------------
|
||||
#if BASISD_SUPPORT_KTX2
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
@@ -764,10 +886,10 @@ namespace basist
|
||||
basisu::packed_uint<4> m_alpha_slice_byte_length;
|
||||
};
|
||||
|
||||
struct ktx2_astc_hdr_6x6_intermediate_image_desc
|
||||
struct ktx2_slice_offset_len_desc
|
||||
{
|
||||
basisu::packed_uint<4> m_rgb_slice_byte_offset;
|
||||
basisu::packed_uint<4> m_rgb_slice_byte_length;
|
||||
basisu::packed_uint<4> m_slice_byte_offset;
|
||||
basisu::packed_uint<4> m_slice_byte_length;
|
||||
};
|
||||
|
||||
struct ktx2_animdata
|
||||
@@ -779,7 +901,7 @@ namespace basist
|
||||
#pragma pack(pop)
|
||||
|
||||
const uint32_t KTX2_VK_FORMAT_UNDEFINED = 0;
|
||||
|
||||
|
||||
// These are standard Vulkan texture VkFormat ID's, see https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkFormat.html
|
||||
const uint32_t KTX2_FORMAT_ASTC_4x4_SFLOAT_BLOCK = 1000066000;
|
||||
const uint32_t KTX2_FORMAT_ASTC_5x4_SFLOAT_BLOCK = 1000066001;
|
||||
@@ -789,12 +911,28 @@ namespace basist
|
||||
const uint32_t KTX2_FORMAT_ASTC_8x5_SFLOAT_BLOCK = 1000066005;
|
||||
const uint32_t KTX2_FORMAT_ASTC_8x6_SFLOAT_BLOCK = 1000066006;
|
||||
|
||||
const uint32_t KTX2_FORMAT_ASTC_4x4_UNORM_BLOCK = 157, KTX2_FORMAT_ASTC_4x4_SRGB_BLOCK = 158;
|
||||
const uint32_t KTX2_FORMAT_ASTC_5x4_UNORM_BLOCK = 159, KTX2_FORMAT_ASTC_5x4_SRGB_BLOCK = 160;
|
||||
const uint32_t KTX2_FORMAT_ASTC_5x5_UNORM_BLOCK = 161, KTX2_FORMAT_ASTC_5x5_SRGB_BLOCK = 162;
|
||||
const uint32_t KTX2_FORMAT_ASTC_6x5_UNORM_BLOCK = 163, KTX2_FORMAT_ASTC_6x5_SRGB_BLOCK = 164;
|
||||
const uint32_t KTX2_FORMAT_ASTC_6x6_UNORM_BLOCK = 165, KTX2_FORMAT_ASTC_6x6_SRGB_BLOCK = 166;
|
||||
const uint32_t KTX2_FORMAT_ASTC_8x5_UNORM_BLOCK = 167, KTX2_FORMAT_ASTC_8x5_SRGB_BLOCK = 168;
|
||||
const uint32_t KTX2_FORMAT_ASTC_8x6_UNORM_BLOCK = 169, KTX2_FORMAT_ASTC_8x6_SRGB_BLOCK = 170;
|
||||
const uint32_t KTX2_FORMAT_ASTC_10x5_UNORM_BLOCK = 173, KTX2_FORMAT_ASTC_10x5_SRGB_BLOCK = 174;
|
||||
const uint32_t KTX2_FORMAT_ASTC_10x6_UNORM_BLOCK = 175, KTX2_FORMAT_ASTC_10x6_SRGB_BLOCK = 176;
|
||||
const uint32_t KTX2_FORMAT_ASTC_8x8_UNORM_BLOCK = 171, KTX2_FORMAT_ASTC_8x8_SRGB_BLOCK = 172; // note the ASTC block size order is off in the vkFormat definitions
|
||||
const uint32_t KTX2_FORMAT_ASTC_10x8_UNORM_BLOCK = 177, KTX2_FORMAT_ASTC_10x8_SRGB_BLOCK = 178;
|
||||
const uint32_t KTX2_FORMAT_ASTC_10x10_UNORM_BLOCK = 179, KTX2_FORMAT_ASTC_10x10_SRGB_BLOCK = 180;
|
||||
const uint32_t KTX2_FORMAT_ASTC_12x10_UNORM_BLOCK = 181, KTX2_FORMAT_ASTC_12x10_SRGB_BLOCK = 182;
|
||||
const uint32_t KTX2_FORMAT_ASTC_12x12_UNORM_BLOCK = 183, KTX2_FORMAT_ASTC_12x12_SRGB_BLOCK = 184;
|
||||
|
||||
const uint32_t KTX2_KDF_DF_MODEL_ASTC = 162; // 0xA2
|
||||
const uint32_t KTX2_KDF_DF_MODEL_ETC1S = 163; // 0xA3
|
||||
const uint32_t KTX2_KDF_DF_MODEL_UASTC_LDR_4X4 = 166; // 0xA6
|
||||
const uint32_t KTX2_KDF_DF_MODEL_UASTC_HDR_4X4 = 167; // 0xA7
|
||||
const uint32_t KTX2_KDF_DF_MODEL_ASTC_HDR_6X6_INTERMEDIATE = 168; // 0xA8, TODO - coordinate with Khronos on this
|
||||
|
||||
const uint32_t KTX2_KDF_DF_MODEL_UASTC_HDR_6X6_INTERMEDIATE = 168; // 0xA8, TODO - coordinate with Khronos on this
|
||||
const uint32_t KTX2_KDF_DF_MODEL_XUASTC_LDR_INTERMEDIATE = 169; // 0xA9, TODO - coordinate with Khronos on this
|
||||
|
||||
const uint32_t KTX2_IMAGE_IS_P_FRAME = 2;
|
||||
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
|
||||
@@ -878,12 +1016,12 @@ namespace basist
|
||||
{
|
||||
case KTX2_DF_PRIMARIES_UNSPECIFIED: return "UNSPECIFIED";
|
||||
case KTX2_DF_PRIMARIES_BT709: return "BT709";
|
||||
case KTX2_DF_PRIMARIES_BT601_EBU: return "EBU";
|
||||
case KTX2_DF_PRIMARIES_BT601_EBU: return "EBU";
|
||||
case KTX2_DF_PRIMARIES_BT601_SMPTE: return "SMPTE";
|
||||
case KTX2_DF_PRIMARIES_BT2020: return "BT2020";
|
||||
case KTX2_DF_PRIMARIES_CIEXYZ: return "CIEXYZ";
|
||||
case KTX2_DF_PRIMARIES_ACES: return "ACES";
|
||||
case KTX2_DF_PRIMARIES_ACESCC: return "ACESCC";
|
||||
case KTX2_DF_PRIMARIES_ACESCC: return "ACESCC";
|
||||
case KTX2_DF_PRIMARIES_NTSC1953: return "NTSC1953";
|
||||
case KTX2_DF_PRIMARIES_PAL525: return "PAL525";
|
||||
case KTX2_DF_PRIMARIES_DISPLAYP3: return "DISPLAYP3";
|
||||
@@ -891,7 +1029,7 @@ namespace basist
|
||||
default: break;
|
||||
}
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
// Information about a single 2D texture "image" in a KTX2 file.
|
||||
struct ktx2_image_level_info
|
||||
@@ -901,19 +1039,19 @@ namespace basist
|
||||
uint32_t m_layer_index;
|
||||
uint32_t m_face_index;
|
||||
|
||||
// The image's actual (or the original source image's) width/height in pixels, which may not be divisible by 4 pixels.
|
||||
// The image's ACTUAL (or the original source image's) width/height in pixels, which may not be divisible by the block size (4-12 pixels).
|
||||
uint32_t m_orig_width;
|
||||
uint32_t m_orig_height;
|
||||
|
||||
// The image's physical width/height, which will always be divisible by 4 pixels.
|
||||
// The image's physical width/height, which will always be divisible by the format's block size (4-12 pixels).
|
||||
uint32_t m_width;
|
||||
uint32_t m_height;
|
||||
|
||||
// The texture's dimensions in 4x4 or 6x6 texel blocks.
|
||||
|
||||
// The texture's dimensions in 4x4-12x12 texel blocks.
|
||||
uint32_t m_num_blocks_x;
|
||||
uint32_t m_num_blocks_y;
|
||||
|
||||
// The format's block width/height (currently either 4 or 6).
|
||||
// The format's block width/height (4-12).
|
||||
uint32_t m_block_width;
|
||||
uint32_t m_block_height;
|
||||
|
||||
@@ -926,7 +1064,7 @@ namespace basist
|
||||
// true if the image is an I-Frame. Currently, for ETC1S textures, the first frame will always be an I-Frame, and subsequent frames will always be P-Frames.
|
||||
bool m_iframe_flag;
|
||||
};
|
||||
|
||||
|
||||
// Thread-specific ETC1S/supercompressed UASTC transcoder state. (If you're not doing multithreading transcoding you can ignore this.)
|
||||
struct ktx2_transcoder_state
|
||||
{
|
||||
@@ -944,9 +1082,9 @@ namespace basist
|
||||
|
||||
// This class is quite similar to basisu_transcoder. It treats KTX2 files as a simple container for ETC1S/UASTC texture data.
|
||||
// It does not support 1D or 3D textures.
|
||||
// It only supports 2D and cubemap textures, with or without mipmaps, texture arrays of 2D/cubemap textures, and texture video files.
|
||||
// It only supports 2D and cubemap textures, with or without mipmaps, texture arrays of 2D/cubemap textures, and texture video files.
|
||||
// It only supports raw non-supercompressed UASTC, ETC1S, UASTC+Zstd, or UASTC+zlib compressed files.
|
||||
// DFD (Data Format Descriptor) parsing is purposely as simple as possible.
|
||||
// DFD (Data Format Descriptor) parsing is purposely as simple as possible.
|
||||
// If you need to know how to interpret the texture channels you'll need to parse the DFD yourself after calling get_dfd().
|
||||
class ktx2_transcoder
|
||||
{
|
||||
@@ -971,10 +1109,10 @@ namespace basist
|
||||
// Returns the KTX2 level index array. There will be one entry for each mipmap level. Valid after init().
|
||||
const basisu::vector<ktx2_level_index>& get_level_index() const { return m_levels; }
|
||||
|
||||
// Returns the texture's width in texels. Always non-zero, might not be divisible by 4. Valid after init().
|
||||
// Returns the texture's width in texels. Always non-zero, might not be divisible by the block size. Valid after init().
|
||||
uint32_t get_width() const { return m_header.m_pixel_width; }
|
||||
|
||||
// Returns the texture's height in texels. Always non-zero, might not be divisible by 4. Valid after init().
|
||||
// Returns the texture's height in texels. Always non-zero, might not be divisible by the block size. Valid after init().
|
||||
uint32_t get_height() const { return m_header.m_pixel_height; }
|
||||
|
||||
// Returns the texture's number of mipmap levels. Always returns 1 or higher. Valid after init().
|
||||
@@ -986,15 +1124,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, cUASTC4x4, cUASTC_HDR_4x4, cASTC_HDR_6x6, cASTC_HDR_6x6_INTERMEDIATE. Valid after init().
|
||||
// Returns cETC1S, cUASTC4x4, cUASTC_HDR_4x4, cASTC_HDR_6x6, cUASTC_HDR_6x6_INTERMEDIATE, etc. Valid after init().
|
||||
basist::basis_tex_format get_basis_tex_format() const { return m_format; }
|
||||
|
||||
// ETC1S LDR 4x4
|
||||
bool is_etc1s() const { return get_basis_tex_format() == basist::basis_tex_format::cETC1S; }
|
||||
|
||||
// UASTC LDR 4x4 (only)
|
||||
bool is_uastc() const { return get_basis_tex_format() == basist::basis_tex_format::cUASTC4x4; }
|
||||
|
||||
bool is_uastc() const { return get_basis_tex_format() == basist::basis_tex_format::cUASTC_LDR_4x4; }
|
||||
|
||||
// Is ASTC HDR 4x4 or 6x6
|
||||
bool is_hdr() const
|
||||
{
|
||||
@@ -1006,18 +1144,26 @@ namespace basist
|
||||
return !is_hdr();
|
||||
}
|
||||
|
||||
// is UASTC HDR 4x4 (which is also standard ASTC HDR 4x4 data)
|
||||
bool is_hdr_4x4() const
|
||||
{
|
||||
return (get_basis_tex_format() == basist::basis_tex_format::cUASTC_HDR_4x4);
|
||||
}
|
||||
|
||||
// is ASTC HDR 6x6 or UASTC HDR 6x6 intermediate (only)
|
||||
bool is_hdr_6x6() const
|
||||
{
|
||||
return (get_basis_tex_format() == basist::basis_tex_format::cASTC_HDR_6x6) || (get_basis_tex_format() == basist::basis_tex_format::cASTC_HDR_6x6_INTERMEDIATE);
|
||||
return (get_basis_tex_format() == basist::basis_tex_format::cASTC_HDR_6x6) || (get_basis_tex_format() == basist::basis_tex_format::cUASTC_HDR_6x6_INTERMEDIATE);
|
||||
}
|
||||
|
||||
// is ASTC LDR 4x4-12x12 (only)
|
||||
bool is_astc_ldr() const { return basis_tex_format_is_astc_ldr(get_basis_tex_format()); }
|
||||
|
||||
// is XUASTC LDR 4x4-12x12 (only)
|
||||
bool is_xuastc_ldr() const { return basis_tex_format_is_xuastc_ldr(get_basis_tex_format()); }
|
||||
|
||||
uint32_t get_block_width() const { return basis_tex_format_get_block_width(get_basis_tex_format()); }
|
||||
uint32_t get_block_height() const { return basis_tex_format_get_block_height(get_basis_tex_format()); }
|
||||
uint32_t get_block_height() const { return basis_tex_format_get_block_height(get_basis_tex_format()); }
|
||||
|
||||
// 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; }
|
||||
@@ -1032,17 +1178,19 @@ namespace basist
|
||||
// Returns the DFD color primary.
|
||||
// We do not validate the color primaries, so the returned value may not be in the ktx2_df_color_primaries enum.
|
||||
ktx2_df_color_primaries get_dfd_color_primaries() const { return m_dfd_color_prims; }
|
||||
|
||||
|
||||
// Returns KTX2_KHR_DF_TRANSFER_LINEAR or KTX2_KHR_DF_TRANSFER_SRGB.
|
||||
uint32_t get_dfd_transfer_func() const { return m_dfd_transfer_func; }
|
||||
|
||||
bool is_srgb() const { return (get_dfd_transfer_func() == KTX2_KHR_DF_TRANSFER_SRGB); }
|
||||
|
||||
uint32_t get_dfd_flags() const { return m_dfd_flags; }
|
||||
|
||||
// Returns 1 (ETC1S/UASTC) or 2 (ETC1S with an internal alpha channel).
|
||||
uint32_t get_dfd_total_samples() const { return m_dfd_samples; }
|
||||
|
||||
// Returns the channel mapping for each DFD "sample". UASTC always has 1 sample, ETC1S can have one or two.
|
||||
// Note the returned value SHOULD be one of the ktx2_df_channel_id enums, but we don't validate that.
|
||||
|
||||
// Returns the channel mapping for each DFD "sample". UASTC always has 1 sample, ETC1S can have one or two.
|
||||
// Note the returned value SHOULD be one of the ktx2_df_channel_id enums, but we don't validate that.
|
||||
// It's up to the caller to decide what to do if the value isn't in the enum.
|
||||
ktx2_df_channel_id get_dfd_channel_id0() const { return m_dfd_chan0; }
|
||||
ktx2_df_channel_id get_dfd_channel_id1() const { return m_dfd_chan1; }
|
||||
@@ -1050,11 +1198,11 @@ namespace basist
|
||||
// Key value field data.
|
||||
struct key_value
|
||||
{
|
||||
// The key field is UTF8 and always zero terminated.
|
||||
// The key field is UTF8 and always zero terminated.
|
||||
// In memory we always append a zero terminator to the key.
|
||||
basisu::uint8_vec m_key;
|
||||
|
||||
// The value may be empty. In the KTX2 file it consists of raw bytes which may or may not be zero terminated.
|
||||
// The value may be empty. In the KTX2 file it consists of raw bytes which may or may not be zero terminated.
|
||||
// In memory we always append a zero terminator to the value.
|
||||
basisu::uint8_vec m_value;
|
||||
|
||||
@@ -1076,7 +1224,7 @@ namespace basist
|
||||
// Returns the array of ETC1S image descriptors, which is only valid after get_etc1s_image_descs() is called.
|
||||
const basisu::vector<ktx2_etc1s_image_desc>& get_etc1s_image_descs() const { return m_etc1s_image_descs; }
|
||||
|
||||
const basisu::vector<ktx2_astc_hdr_6x6_intermediate_image_desc>& get_astc_hdr_6x6_intermediate_image_descs() const { return m_astc_6x6_intermediate_image_descs; }
|
||||
const basisu::vector<ktx2_slice_offset_len_desc>& get_slice_offset_len_descs() const { return m_slice_offset_len_descs; }
|
||||
|
||||
// Must have called startTranscoding() first
|
||||
uint32_t get_etc1s_image_descs_image_flags(uint32_t level_index, uint32_t layer_index, uint32_t face_index) const;
|
||||
@@ -1084,21 +1232,21 @@ namespace basist
|
||||
// is_video() is only valid after start_transcoding() is called.
|
||||
// For ETC1S data, if this returns true you must currently transcode the file from first to last frame, in order, without skipping any frames.
|
||||
bool is_video() const { return m_is_video; }
|
||||
|
||||
|
||||
// Defaults to 0, only non-zero if the key existed in the source KTX2 file.
|
||||
float get_ldr_hdr_upconversion_nit_multiplier() const { return m_ldr_hdr_upconversion_nit_multiplier; }
|
||||
|
||||
// start_transcoding() MUST be called before calling transcode_image().
|
||||
|
||||
// start_transcoding() MUST be called before calling transcode_image_level().
|
||||
// This method decompresses the ETC1S global endpoint/selector codebooks, which is not free, so try to avoid calling it excessively.
|
||||
bool start_transcoding();
|
||||
|
||||
|
||||
// get_image_level_info() be called after init(), but the m_iframe_flag's won't be valid until start_transcoding() is called.
|
||||
// You can call this method before calling transcode_image_level() to retrieve basic information about the mipmap level's dimensions, etc.
|
||||
bool get_image_level_info(ktx2_image_level_info& level_info, uint32_t level_index, uint32_t layer_index, uint32_t face_index) const;
|
||||
|
||||
// transcode_image_level() transcodes a single 2D texture or cubemap face from the KTX2 file.
|
||||
// Internally it uses the same low-level transcode API's as basisu_transcoder::transcode_image_level().
|
||||
// If the file is UASTC and is supercompressed with Zstandard, and the file is a texture array or cubemap, it's highly recommended that each mipmap level is
|
||||
// If the file is UASTC and is supercompressed with Zstandard, and the file is a texture array or cubemap, it's highly recommended that each mipmap level is
|
||||
// completely transcoded before switching to another level. Every time the mipmap level is changed all supercompressed level data must be decompressed using Zstandard as a single unit.
|
||||
// Currently ETC1S videos must always be transcoded from first to last frame (or KTX2 "layer"), in order, with no skipping of frames.
|
||||
// By default this method is not thread safe unless you specify a pointer to a user allocated thread-specific transcoder_state struct.
|
||||
@@ -1108,7 +1256,7 @@ namespace basist
|
||||
basist::transcoder_texture_format fmt,
|
||||
uint32_t decode_flags = 0, uint32_t output_row_pitch_in_blocks_or_pixels = 0, uint32_t output_rows_in_pixels = 0, int channel0 = -1, int channel1 = -1,
|
||||
ktx2_transcoder_state *pState = nullptr);
|
||||
|
||||
|
||||
private:
|
||||
const uint8_t* m_pData;
|
||||
uint32_t m_data_size;
|
||||
@@ -1117,26 +1265,30 @@ namespace basist
|
||||
basisu::vector<ktx2_level_index> m_levels;
|
||||
basisu::uint8_vec m_dfd;
|
||||
key_value_vec m_key_values;
|
||||
|
||||
|
||||
ktx2_etc1s_global_data_header m_etc1s_header;
|
||||
basisu::vector<ktx2_etc1s_image_desc> m_etc1s_image_descs;
|
||||
basisu::vector<ktx2_astc_hdr_6x6_intermediate_image_desc> m_astc_6x6_intermediate_image_descs;
|
||||
basisu::vector<ktx2_slice_offset_len_desc> m_slice_offset_len_descs;
|
||||
|
||||
basist::basis_tex_format m_format;
|
||||
|
||||
|
||||
uint32_t m_dfd_color_model;
|
||||
ktx2_df_color_primaries m_dfd_color_prims;
|
||||
uint32_t m_dfd_transfer_func;
|
||||
|
||||
// KTX2_KHR_DF_TRANSFER_LINEAR vs. KTX2_KHR_DF_TRANSFER_SRGB (for XUASTC LDR: which profile was used during encoding)
|
||||
uint32_t m_dfd_transfer_func;
|
||||
|
||||
uint32_t m_dfd_flags;
|
||||
uint32_t m_dfd_samples;
|
||||
ktx2_df_channel_id m_dfd_chan0, m_dfd_chan1;
|
||||
|
||||
|
||||
basist::basisu_lowlevel_etc1s_transcoder m_etc1s_transcoder;
|
||||
basist::basisu_lowlevel_uastc_ldr_4x4_transcoder m_uastc_transcoder;
|
||||
basist::basisu_lowlevel_uastc_ldr_4x4_transcoder m_uastc_ldr_transcoder;
|
||||
basist::basisu_lowlevel_xuastc_ldr_transcoder m_xuastc_ldr_transcoder;
|
||||
basist::basisu_lowlevel_uastc_hdr_4x4_transcoder m_uastc_hdr_transcoder;
|
||||
basist::basisu_lowlevel_astc_hdr_6x6_transcoder m_astc_hdr_6x6_transcoder;
|
||||
basist::basisu_lowlevel_astc_hdr_6x6_intermediate_transcoder m_astc_hdr_6x6_intermediate_transcoder;
|
||||
|
||||
basist::basisu_lowlevel_uastc_hdr_6x6_intermediate_transcoder m_astc_hdr_6x6_intermediate_transcoder;
|
||||
|
||||
ktx2_transcoder_state m_def_transcoder_state;
|
||||
|
||||
bool m_has_alpha;
|
||||
@@ -1144,7 +1296,7 @@ namespace basist
|
||||
float m_ldr_hdr_upconversion_nit_multiplier;
|
||||
|
||||
bool decompress_level_data(uint32_t level_index, basisu::uint8_vec& uncomp_data);
|
||||
bool read_astc_6x6_hdr_intermediate_global_data();
|
||||
bool read_slice_offset_len_global_data();
|
||||
bool decompress_etc1s_global_data();
|
||||
bool read_key_values();
|
||||
};
|
||||
@@ -1165,7 +1317,7 @@ namespace basist
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!p)
|
||||
p = key_values.enlarge(1);
|
||||
|
||||
@@ -1189,3 +1341,4 @@ namespace basist
|
||||
bool basisu_transcoder_supports_ktx2_zstd();
|
||||
|
||||
} // namespace basisu
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user