Haio 0.2.X
Homebrew Asset IO/CDN
Loading...
Searching...
No Matches
haio_util.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "haio_codec.hpp"
4
5#include <span>
6#include <string_view>
7#include <vector>
8
9/**
10 * byte level helpers shared by the codecs. every container haio reads or writes
11 * stores its integers little endian, which the names say out loud: ktx even carries
12 * an endianness marker that the decoder checks, so leaving it implicit was asking
13 * for a silent bug on a big endian host.
14 */
15namespace Haio::Util {
16
17bool matches(Bytes data, Bytes magic);
18bool matches(Bytes data, std::string_view magic);
19
20/** true when data holds len bytes starting at off, so a decoder checks once */
21bool hasBytes(Bytes data, size_t off, size_t len);
22
23/**
24 * a four character code, the tag formats put at the front of a header. it is the
25 * same operation as readU32LE over a literal, and it carries the suffix for the
26 * same reason: riff and dds pack it little endian, iff and aiff pack it the other
27 * way round, so "fourcc" alone does not say which.
28 */
29constexpr uint32_t fourccLE(char a, char b, char c, char d) {
30 return static_cast<uint32_t>(static_cast<uint8_t>(a))
31 | (static_cast<uint32_t>(static_cast<uint8_t>(b)) << 8)
32 | (static_cast<uint32_t>(static_cast<uint8_t>(c)) << 16)
33 | (static_cast<uint32_t>(static_cast<uint8_t>(d)) << 24);
34}
35
36void appendU32LE(std::vector<uint8_t>& out, uint32_t value);
37void appendU64LE(std::vector<uint8_t>& out, uint64_t value);
38
39/** reads zero when out of range; pair it with hasBytes where that matters */
40uint32_t readU32LE(Bytes data, size_t off);
41
42/** png and the netpbm family are big endian, unlike every gpu container here */
43uint32_t readU32BE(Bytes data, size_t off);
44uint64_t readU64LE(Bytes data, size_t off);
45
46Result<std::vector<uint8_t>> slice(Bytes data, size_t off, size_t len);
47
48/**
49 * what the gpu containers need to agree on. these always spoke about colour rather
50 * than about files; the old single enum just made it look otherwise.
51 */
52/**
53 * ordered dithering, which is a threshold that depends on where a pixel is rather
54 * than on what its neighbours became.
55 *
56 * it lives here and not in the palette code because the matrix is not about colour
57 * at all: the same thresholds order a gradient, pick which pixels of a mask survive
58 * a downscale, or break up a banded sky. a caller that needs one of those should not
59 * have to reach into a quantiser to find it.
60 */
61namespace Dither {
62
63/**
64 * the threshold at x,y of a side by side matrix, from 0 to side*side-1.
65 *
66 * the matrix is defined by doubling: each step turns one cell into four, keeping the
67 * order top left, bottom right, top right, bottom left. that is why the side has to
68 * be a power of two, and why the same function answers for a four colour palette and
69 * a two hundred and fifty six colour one.
70 */
71constexpr int bayer(int side, int x, int y) {
72 if (side <= 1) return 0;
73
74 const auto half = side / 2;
75 // the order the quadrants are filled in, which is what makes the pattern spread
76 // rather than clump
77 constexpr int quadrant[4] = {0, 2, 3, 1};
78 const auto which = (y >= half ? 2 : 0) + (x >= half ? 1 : 0);
79
80 return 4 * bayer(half, x % half, y % half) + quadrant[which];
81}
82
83/** how wide a matrix has to be to hold that many levels, rounded up to a power of two */
84constexpr int bayerSideFor(int levels) {
85 int side = 2;
86 while (side * side < levels && side < 16) side *= 2;
87 return side;
88}
89
90}
91
92namespace GPU {
93
94inline constexpr uint32_t GL_UNSIGNED_BYTE = 0x1401;
95inline constexpr uint32_t GL_UNSIGNED_SHORT_5_6_5 = 0x8363;
96inline constexpr uint32_t GL_RGB = 0x1907;
97inline constexpr uint32_t GL_RGBA = 0x1908;
98inline constexpr uint32_t GL_RGBA8 = 0x8058;
99inline constexpr uint32_t GL_RGB565 = 0x8d62;
100inline constexpr uint32_t GL_ETC1_RGB8_OES = 0x8d64;
101inline constexpr uint32_t VK_FORMAT_R5G6B5_UNORM_PACK16 = 4;
102inline constexpr uint32_t VK_FORMAT_R8G8B8A8_UNORM = 37;
103inline constexpr uint32_t VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK = 147;
104
105struct Profile {
106 uint32_t glType;
107 uint32_t glFormat;
108 uint32_t glInternal;
109 uint32_t glBase;
110 uint32_t vkFormat;
111 uint64_t pvrFormat;
112 size_t size;
113};
114
115constexpr uint64_t pvrRaw(char a, char b, char c, char d, uint8_t ba, uint8_t bb, uint8_t bc, uint8_t bd) {
116 return static_cast<uint64_t>(a) | (static_cast<uint64_t>(b) << 8) | (static_cast<uint64_t>(c) << 16)
117 | (static_cast<uint64_t>(d) << 24) | (static_cast<uint64_t>(ba) << 32) | (static_cast<uint64_t>(bb) << 40)
118 | (static_cast<uint64_t>(bc) << 48) | (static_cast<uint64_t>(bd) << 56);
119}
120
121/** etc1 rounds up to whole 4x4 blocks, so the stored size is not width times height */
122constexpr size_t etc1Size(Size size) {
123 return static_cast<size_t>((size.width + 3) / 4) * static_cast<size_t>((size.height + 3) / 4) * 8;
124}
125
128uint32_t typeSize(const Profile& profile);
129
130/** what colour a container header is describing */
131Result<Color> colorFromGL(uint32_t glType, uint32_t glFormat, uint32_t glInternal);
132Result<Color> colorFromVK(uint32_t format);
133Result<Color> colorFromPVR(uint64_t format);
134
135}
136
137}
constexpr int bayer(int side, int x, int y)
Definition haio_util.hpp:71
constexpr int bayerSideFor(int levels)
Definition haio_util.hpp:84
constexpr uint64_t pvrRaw(char a, char b, char c, char d, uint8_t ba, uint8_t bb, uint8_t bc, uint8_t bd)
Result< Profile > profileFor(Color color, Size size)
Definition gpu.cpp:20
constexpr uint32_t GL_RGB565
Definition haio_util.hpp:99
Result< Color > colorFromPVR(uint64_t format)
Definition gpu.cpp:52
constexpr uint32_t GL_UNSIGNED_BYTE
Definition haio_util.hpp:94
constexpr uint32_t GL_ETC1_RGB8_OES
Result< Color > colorFromGL(uint32_t glType, uint32_t glFormat, uint32_t glInternal)
Definition gpu.cpp:38
constexpr uint32_t VK_FORMAT_R5G6B5_UNORM_PACK16
constexpr size_t etc1Size(Size size)
uint32_t typeSize(const Profile &profile)
Definition gpu.cpp:34
constexpr uint32_t VK_FORMAT_R8G8B8A8_UNORM
constexpr uint32_t GL_RGB
Definition haio_util.hpp:96
Result< Color > colorFromVK(uint32_t format)
Definition gpu.cpp:45
constexpr uint32_t GL_UNSIGNED_SHORT_5_6_5
Definition haio_util.hpp:95
constexpr uint32_t VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK
constexpr uint32_t GL_RGBA8
Definition haio_util.hpp:98
Result< size_t > payloadSize(Color color, Size size)
Definition gpu.cpp:5
constexpr uint32_t GL_RGBA
Definition haio_util.hpp:97
uint32_t readU32BE(Bytes data, size_t off)
Definition bytes.cpp:29
Result< std::vector< uint8_t > > slice(Bytes data, size_t off, size_t len)
Definition bytes.cpp:42
uint64_t readU64LE(Bytes data, size_t off)
Definition bytes.cpp:37
bool hasBytes(Bytes data, size_t off, size_t len)
Definition bytes.cpp:5
void appendU64LE(std::vector< uint8_t > &out, uint64_t value)
Definition bytes.cpp:16
constexpr uint32_t fourccLE(char a, char b, char c, char d)
Definition haio_util.hpp:29
uint32_t readU32LE(Bytes data, size_t off)
Definition bytes.cpp:21
void appendU32LE(std::vector< uint8_t > &out, uint32_t value)
Definition bytes.cpp:9
bool matches(Bytes data, Bytes magic)
Definition matches.cpp:7
std::expected< T, Error > Result
std::span< const uint8_t > Bytes