| /* | |
| * Copyright 2026 Rive | |
| */ | |
| #ifndef _RIVE_DECODE_KTX2_HPP_ | |
| #define _RIVE_DECODE_KTX2_HPP_ | |
| #include "rive/gpu_texture_format.hpp" | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <vector> | |
| namespace rive | |
| { | |
| // HW support flags for the formats KTX2 may contain. When a format is not | |
| // supported by the backend, DecodeKtx2 will software-decode mip 0 to RGBA8 | |
| // (if the corresponding RIVE_*_DECODER family was compiled in) and store | |
| // the result in `blocks` with `format = rgba32`. | |
| // Defaults assume the caller's backend natively supports every GPU | |
| // compressed format we recognise. Callers that have actually queried HW | |
| // caps should set the relevant booleans to false to opt the parser into | |
| // the software-decode fallback. Tests + parser-only consumers can use the | |
| // defaults to keep the original "pass blocks through verbatim" behavior. | |
| struct Ktx2HwSupport | |
| { | |
| bool bc = true; | |
| bool astc = true; | |
| bool etc2 = true; | |
| }; | |
| // Result of parsing a KTX2 container. Block data is held in a contiguous | |
| // owned buffer, level 0 first (largest), then level 1, … level N-1 | |
| // (smallest). Each level's region is exactly its block-grid size in bytes | |
| // (no inter-level padding). | |
| // | |
| // If `softwareDecoded` is true, the GPU format in the container was not | |
| // supported by the caller's backend and mip 0 was decoded to RGBA8. In that | |
| // case `format == rgba32`, `levelCount == 1`, and `blocks` holds tightly | |
| // packed RGBA8 pixels. | |
| struct Ktx2DecodeResult | |
| { | |
| GPUTextureFormat format; | |
| uint32_t pixelWidth; // logical mip 0 width | |
| uint32_t pixelHeight; // logical mip 0 height | |
| uint32_t levelCount; // number of mip levels stored (>=1) | |
| uint8_t blockWidth = 4; // compressed block footprint width (1 for rgba32) | |
| uint8_t blockHeight = 4; // compressed block footprint height (1 for rgba32) | |
| bool srgb = false; // sRGB colour space (BC7_SRGB / ASTC_SRGB) | |
| std::vector<uint8_t> blocks; | |
| bool softwareDecoded = false; | |
| }; | |
| // Parses a KTX2 container. Returns true on success and fills `out`. Returns | |
| // false (with a stderr log) on: | |
| // - bad magic, truncated header / level index | |
| // - unsupported vkFormat (today: only BC7 UNORM/SRGB) | |
| // - non-NONE supercompressionScheme | |
| // - cubemaps / array layers | |
| // - oversized dimensions or level count | |
| // - level data outside the buffer | |
| // | |
| // `hwSupport` is consulted after parsing to decide whether to fall back to | |
| // CPU decompression. Pass all-true to skip the fallback path entirely. | |
| bool DecodeKtx2( | |
| const uint8_t* bytes, | |
| size_t byteCount, | |
| Ktx2DecodeResult& out, | |
| const Ktx2HwSupport& hwSupport = {}); | |
| } // namespace rive | |
| #endif |