summaryrefslogtreecommitdiff
path: root/subprojects/pixpat/pixpat-native/src/io/detail.h
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ideasonboard.com>2026-05-08 17:22:58 +0300
committerTomi Valkeinen <tomi.valkeinen@ideasonboard.com>2026-05-08 17:22:58 +0300
commit4e2b291a4acdc2cbd39f005c88bda363bc06bd34 (patch)
treee90048d5973ad1164b109d575cf577af7daf50be /subprojects/pixpat/pixpat-native/src/io/detail.h
parent8f94b39040e79eccd9312ed1e467fe8ebfab8860 (diff)
parente0b7d30fd437292c88141fb08d60681870b86c6e (diff)
Merge commit 'e0b7d30fd437292c88141fb08d60681870b86c6e' as 'subprojects/pixpat'
Diffstat (limited to 'subprojects/pixpat/pixpat-native/src/io/detail.h')
-rw-r--r--subprojects/pixpat/pixpat-native/src/io/detail.h62
1 files changed, 62 insertions, 0 deletions
diff --git a/subprojects/pixpat/pixpat-native/src/io/detail.h b/subprojects/pixpat/pixpat-native/src/io/detail.h
new file mode 100644
index 0000000..cb2b9fb
--- /dev/null
+++ b/subprojects/pixpat/pixpat-native/src/io/detail.h
@@ -0,0 +1,62 @@
+#pragma once
+
+// Per-component encode/decode against the descriptor + memcpy-based
+// load/store_word helpers. Shared by every Source / Sink template.
+
+#include <cstdint>
+#include <cstring>
+
+#include "../layout.h"
+
+namespace pixpat::detail
+{
+
+// Decode an N-bit stored value into the 16-bit normalized space and
+// encode it back. Decode bit-replicates the stored value across the 16
+// bits so that N-bit max maps to normalized max (e.g. 8-bit 0xFF →
+// 0xFFFF, not 0xFF00). Encode is a plain truncating right-shift: the
+// replicated bits land in the low (16-N) bits and get dropped, so
+// stored→norm→stored is exact for any N in [1, 16].
+//
+// `bits` is taken at runtime; in every call site it traces back to a
+// constexpr Plane::comps[I].bits read, which the optimizer constant-
+// folds after inlining.
+
+constexpr uint16_t decode_norm(unsigned bits, uint16_t stored) noexcept
+{
+ const int N = int(bits);
+ // Loop, not a single OR: one replication only covers 2N bits, so
+ // N < 8 (RGB565, RGBA4444, 1-bit alpha, ...) needs multiple tiles.
+ uint32_t result = 0;
+ for (int s = 16 - N; s > -N; s -= N) {
+ if (s >= 0)
+ result |= uint32_t(stored) << s;
+ else
+ result |= uint32_t(stored) >> -s;
+ }
+ return uint16_t(result);
+}
+
+constexpr uint16_t encode_norm(unsigned bits, uint16_t norm) noexcept
+{
+ return uint16_t(norm >> (16u - bits));
+}
+
+// Read one storage word from `p`. memcpy is uniform for tight and
+// non-tight (e.g. BGR888 24-bit) layouts; the optimizer folds it to a
+// single load when the size is constant.
+template <typename Plane>
+inline typename Plane::storage_t load_word(const uint8_t* p) noexcept
+{
+ typename Plane::storage_t word{};
+ std::memcpy(&word, p, Plane::bytes_per_pixel);
+ return word;
+}
+
+template <typename Plane>
+inline void store_word(uint8_t* p, typename Plane::storage_t word) noexcept
+{
+ std::memcpy(p, &word, Plane::bytes_per_pixel);
+}
+
+} // namespace pixpat::detail