From 972d642b6dca9eb9108270429d5d54525a26ba5c Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Fri, 28 Mar 2025 11:55:17 +0200 Subject: conv: Add X403 support --- kms++util/src/conv-yuv-planar-packed.h | 125 +++++++++++++++++++++++++++++++++ kms++util/src/conv.h | 1 + kms++util/src/testpat.cpp | 8 +++ 3 files changed, 134 insertions(+) create mode 100644 kms++util/src/conv-yuv-planar-packed.h (limited to 'kms++util/src') 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 + +#include +#include + +#include "conv-common.h" + +namespace kms +{ +/* YUV Planar Packed (only X403 for now) */ + +struct X403_Layout : FormatLayout < + PlaneLayout, + ComponentLayout, + ComponentLayout, + ComponentLayout>, + PlaneLayout, + ComponentLayout, + ComponentLayout, + ComponentLayout>, + PlaneLayout, + ComponentLayout, + ComponentLayout, + ComponentLayout> + > +{ + static constexpr size_t y_plane = 0; + static constexpr size_t cb_plane = 1; + static constexpr size_t cr_plane = 2; + +}; + +template +class YUVPlanarPackedWriter +{ + using YLayout = Format::template plane; + using CbLayout = Format::template plane; + using CrLayout = Format::template 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 + 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 linebuf(fb.width()); + + // Views to all planes + auto y_buf = make_strided_fb_view(fb.map(Format::y_plane), + fb.height(), fb.width(), + fb.stride(Format::y_plane)); + + auto cb_buf = make_strided_fb_view(fb.map(Format::cb_plane), + fb.height(), fb.width(), + fb.stride(Format::cb_plane)); + + auto cr_buf = make_strided_fb_view(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(md::submdspan(y_buf, y_src, md::full_extent), linebuf, fb.width()); + write_samples(md::submdspan(cb_buf, y_src, md::full_extent), linebuf, fb.width()); + write_samples(md::submdspan(cr_buf, y_src, md::full_extent), linebuf, fb.width()); + } + } + + +private: + template + 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(view, linebuf, x_src, x_dst, + std::make_index_sequence{}); + } + } + + template + static void write_group(YBuf&& view, auto&& linebuf, size_t x_src, + size_t x_dst, std::index_sequence) + { + std::array values{ + static_cast( + (extract_component(linebuf[x_src + I]) >> + (16 - Plane::template component_size)))... + }; + + // Set padding bits to 0 + if constexpr (Plane::template component_count()) + values[Plane::template find_pos()] = 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::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; } -- cgit v1.2.3