summaryrefslogtreecommitdiff
path: root/kms++util
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ideasonboard.com>2025-03-28 11:55:17 +0200
committerTomi Valkeinen <tomi.valkeinen@ideasonboard.com>2025-03-28 11:55:17 +0200
commit972d642b6dca9eb9108270429d5d54525a26ba5c (patch)
tree8bae077f53e839f908b254cca3848fed1d9d0681 /kms++util
parent9f7fd01b5d5bd064723888d3df1b4964da4946be (diff)
conv: Add X403 support
Diffstat (limited to 'kms++util')
-rw-r--r--kms++util/src/conv-yuv-planar-packed.h125
-rw-r--r--kms++util/src/conv.h1
-rw-r--r--kms++util/src/testpat.cpp8
3 files changed, 134 insertions, 0 deletions
diff --git a/kms++util/src/conv-yuv-planar-packed.h b/kms++util/src/conv-yuv-planar-packed.h
new file mode 100644
index 0000000..b66e593
--- /dev/null
+++ b/kms++util/src/conv-yuv-planar-packed.h
@@ -0,0 +1,125 @@
+#pragma once
+
+#include <vector>
+
+#include <kms++/framebuffer.h>
+#include <kms++util/color16.h>
+
+#include "conv-common.h"
+
+namespace kms
+{
+/* YUV Planar Packed (only X403 for now) */
+
+struct X403_Layout : FormatLayout <
+ PlaneLayout<uint32_t,
+ ComponentLayout<ComponentType::Y, 10, 0>,
+ ComponentLayout<ComponentType::Y, 10, 10>,
+ ComponentLayout<ComponentType::Y, 10, 20>,
+ ComponentLayout<ComponentType::X, 2, 30>>,
+ PlaneLayout<uint32_t,
+ ComponentLayout<ComponentType::Cb, 10, 0>,
+ ComponentLayout<ComponentType::Cb, 10, 10>,
+ ComponentLayout<ComponentType::Cb, 10, 20>,
+ ComponentLayout<ComponentType::X, 2, 30>>,
+ PlaneLayout<uint32_t,
+ ComponentLayout<ComponentType::Cr, 10, 0>,
+ ComponentLayout<ComponentType::Cr, 10, 10>,
+ ComponentLayout<ComponentType::Cr, 10, 20>,
+ ComponentLayout<ComponentType::X, 2, 30>>
+ >
+{
+ static constexpr size_t y_plane = 0;
+ static constexpr size_t cb_plane = 1;
+ static constexpr size_t cr_plane = 2;
+
+};
+
+template<typename Format>
+class YUVPlanarPackedWriter
+{
+ using YLayout = Format::template plane<Format::y_plane>;
+ using CbLayout = Format::template plane<Format::cb_plane>;
+ using CrLayout = Format::template plane<Format::cr_plane>;
+
+ using TY = typename YLayout::storage_type;
+ using TCb = typename CbLayout::storage_type;
+ using TCr = typename CrLayout::storage_type;
+
+ static constexpr size_t pixels_in_group = 3;
+
+ // Helper to extract the correct component based on component type
+ template<ComponentType CType>
+ static uint16_t extract_component(const YUV16& pixel)
+ {
+ if constexpr (CType == ComponentType::Y)
+ return pixel.y;
+ else if constexpr (CType == ComponentType::Cb)
+ return pixel.u;
+ else if constexpr (CType == ComponentType::Cr)
+ return pixel.v;
+ else
+ return 0; // For padding or other component types
+ }
+
+public:
+ static void write_pattern(IFramebuffer& fb, size_t start_y, size_t end_y,
+ auto&& generate_line)
+ {
+ // Line buffers
+ std::vector<YUV16> linebuf(fb.width());
+
+ // Views to all planes
+ auto y_buf = make_strided_fb_view<TY>(fb.map(Format::y_plane),
+ fb.height(), fb.width(),
+ fb.stride(Format::y_plane));
+
+ auto cb_buf = make_strided_fb_view<TCb>(fb.map(Format::cb_plane),
+ fb.height(), fb.width(),
+ fb.stride(Format::cb_plane));
+
+ auto cr_buf = make_strided_fb_view<TCr>(fb.map(Format::cr_plane),
+ fb.height(), fb.width(),
+ fb.stride(Format::cr_plane));
+
+ for (size_t y_src = start_y; y_src <= end_y; y_src++) {
+ generate_line(y_src, linebuf);
+
+ write_samples<YLayout, ComponentType::Y>(md::submdspan(y_buf, y_src, md::full_extent), linebuf, fb.width());
+ write_samples<CbLayout, ComponentType::Cb>(md::submdspan(cb_buf, y_src, md::full_extent), linebuf, fb.width());
+ write_samples<CrLayout, ComponentType::Cr>(md::submdspan(cr_buf, y_src, md::full_extent), linebuf, fb.width());
+ }
+ }
+
+
+private:
+ template<typename Plane, ComponentType CType, typename Buf>
+ static void write_samples(Buf&& view, auto&& linebuf, size_t num_pixels)
+ {
+ for (size_t x_src = 0; x_src < num_pixels; x_src += pixels_in_group) {
+ auto x_dst = x_src / pixels_in_group;
+
+ write_group<Plane, CType>(view, linebuf, x_src, x_dst,
+ std::make_index_sequence<pixels_in_group>{});
+ }
+ }
+
+ template<typename Plane, ComponentType CType, typename YBuf, size_t... I>
+ static void write_group(YBuf&& view, auto&& linebuf, size_t x_src,
+ size_t x_dst, std::index_sequence<I...>)
+ {
+ std::array<component_storage_type, Plane::num_components> values{
+ static_cast<component_storage_type>(
+ (extract_component<CType>(linebuf[x_src + I]) >>
+ (16 - Plane::template component_size<I>)))...
+ };
+
+ // Set padding bits to 0
+ if constexpr (Plane::template component_count<ComponentType::X>())
+ values[Plane::template find_pos<ComponentType::X>()] = 0;
+
+ view[x_dst] = Plane::pack(values);
+ }
+};
+
+} // namespace kms
diff --git a/kms++util/src/conv.h b/kms++util/src/conv.h
index 0120fed..720480a 100644
--- a/kms++util/src/conv.h
+++ b/kms++util/src/conv.h
@@ -5,4 +5,5 @@
#include "conv-yuv-packed.h"
#include "conv-yuv-semiplanar.h"
#include "conv-yuv-planar.h"
+#include "conv-yuv-planar-packed.h"
#include "conv-gray.h"
diff --git a/kms++util/src/testpat.cpp b/kms++util/src/testpat.cpp
index 4945f3e..5b7ca1b 100644
--- a/kms++util/src/testpat.cpp
+++ b/kms++util/src/testpat.cpp
@@ -361,6 +361,12 @@ static void draw_test_pattern_part(IFramebuffer& fb, size_t start_y, size_t end_
generate_line_yuv); \
break;
+#define CASE_YUV_PLANAR_PACKED(x) \
+ case PixelFormat::x: \
+ YUVPlanarPackedWriter<x##_Layout>::write_pattern(fb, start_y, end_y, \
+ generate_line_yuv); \
+ break;
+
switch (fb.format()) {
CASE_YUV_SEMI(XV20);
CASE_YUV_SEMI(XV15);
@@ -414,6 +420,8 @@ static void draw_test_pattern_part(IFramebuffer& fb, size_t start_y, size_t end_
CASE_Y_ONLY(Y8);
CASE_Y_ONLY(Y10_P32);
+ CASE_YUV_PLANAR_PACKED(X403);
+
default:
break;
}