From f758e324e17b52116075bb9175a3dd03d223a424 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Sun, 2 Feb 2025 11:26:23 +0200 Subject: kms++util: New template based conversion & testpat code New templated conversion and test pattern code. Signed-off-by: Tomi Valkeinen --- kms++util/src/conv-rgb.h | 300 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 kms++util/src/conv-rgb.h (limited to 'kms++util/src/conv-rgb.h') diff --git a/kms++util/src/conv-rgb.h b/kms++util/src/conv-rgb.h new file mode 100644 index 0000000..e03ded1 --- /dev/null +++ b/kms++util/src/conv-rgb.h @@ -0,0 +1,300 @@ +#pragma once + +#include + +#include +#include + +#include "conv-common.h" + +namespace kms +{ + +/* + * RGB + */ + +template +struct RGB_16_Layout + : public FormatLayout, + ComponentLayout, + ComponentLayout, + ComponentLayout>> +{ +}; + +using XRGB4444_Layout = RGB_16_Layout< + ComponentType::X, 4, 12, + ComponentType::R, 4, 8, + ComponentType::G, 4, 4, + ComponentType::B, 4, 0 +>; + +using ARGB4444_Layout = RGB_16_Layout< + ComponentType::A, 4, 12, + ComponentType::R, 4, 8, + ComponentType::G, 4, 4, + ComponentType::B, 4, 0 +>; + +using XRGB1555_Layout = RGB_16_Layout< + ComponentType::X, 1, 15, + ComponentType::R, 5, 10, + ComponentType::G, 5, 5, + ComponentType::B, 5, 0 +>; + +using ARGB1555_Layout = RGB_16_Layout< + ComponentType::A, 1, 15, + ComponentType::R, 5, 10, + ComponentType::G, 5, 5, + ComponentType::B, 5, 0 +>; + +using RGB565_Layout = FormatLayout, + ComponentLayout, + ComponentLayout> +>; + +using BGR565_Layout = FormatLayout, + ComponentLayout, + ComponentLayout> +>; + +using RGB888_Layout = FormatLayout, + ComponentLayout, + ComponentLayout> +>; + +using BGR888_Layout = FormatLayout, + ComponentLayout, + ComponentLayout> +>; + +template +struct RGB_32_Layout + : public FormatLayout, + ComponentLayout, + ComponentLayout, + ComponentLayout>> +{ +}; + +template +struct RGB_8_32_Layout + : public RGB_32_Layout< + C0, 8, 0, + C1, 8, 8, + C2, 8, 16, + C3, 8, 24> +{ +}; + +using XRGB8888_Layout = RGB_8_32_Layout; +using ARGB8888_Layout = RGB_8_32_Layout; + +using XBGR8888_Layout = RGB_8_32_Layout; +using ABGR8888_Layout = RGB_8_32_Layout; + +using RGBX8888_Layout = RGB_8_32_Layout; +using RGBA8888_Layout = RGB_8_32_Layout; + +using BGRX8888_Layout = RGB_8_32_Layout; +using BGRA8888_Layout = RGB_8_32_Layout; + +using XRGB2101010_Layout = RGB_32_Layout< + ComponentType::X, 2, 30, + ComponentType::R, 10, 20, + ComponentType::G, 10, 10, + ComponentType::B, 10, 0 +>; + +using ARGB2101010_Layout = RGB_32_Layout< + ComponentType::A, 2, 30, + ComponentType::R, 10, 20, + ComponentType::G, 10, 10, + ComponentType::B, 10, 0 +>; + +using XBGR2101010_Layout = RGB_32_Layout< + ComponentType::X, 2, 30, + ComponentType::B, 10, 20, + ComponentType::G, 10, 10, + ComponentType::R, 10, 0 +>; + +using ABGR2101010_Layout = RGB_32_Layout< + ComponentType::A, 2, 30, + ComponentType::B, 10, 20, + ComponentType::G, 10, 10, + ComponentType::R, 10, 0 +>; + +using RGBX1010102_Layout = RGB_32_Layout< + ComponentType::R, 10, 22, + ComponentType::G, 10, 12, + ComponentType::B, 10, 2, + ComponentType::X, 2, 0 +>; + +using RGBA1010102_Layout = RGB_32_Layout< + ComponentType::R, 10, 22, + ComponentType::G, 10, 12, + ComponentType::B, 10, 2, + ComponentType::A, 2, 0 +>; + +using BGRX1010102_Layout = RGB_32_Layout< + ComponentType::B, 10, 22, + ComponentType::G, 10, 12, + ComponentType::R, 10, 2, + ComponentType::X, 2, 0 +>; + +using BGRA1010102_Layout = RGB_32_Layout< + ComponentType::B, 10, 22, + ComponentType::G, 10, 12, + ComponentType::R, 10, 2, + ComponentType::A, 2, 0 +>; + +template +class ARGB_Writer +{ + using Plane = Layout::template plane<0>; + using TStorage = Plane::storage_type; + + static_assert(Layout::num_planes == 1); + static_assert(Plane::num_components == 3 || Plane::num_components == 4); + + static_assert(Plane::template component_count() == 1); + static_assert(Plane::template component_count() == 1); + static_assert(Plane::template component_count() == 1); + + static constexpr bool has_alpha = Plane::template component_count(); + static constexpr bool has_padding = Plane::template component_count(); + + static constexpr bool needs_packed_access = Plane::total_bits != Plane::storage_bits; + + static constexpr size_t a_idx = Plane::template find_pos(); + static constexpr size_t x_idx = Plane::template find_pos(); + static constexpr size_t r_idx = Plane::template find_pos(); + static constexpr size_t g_idx = Plane::template find_pos(); + static constexpr size_t b_idx = Plane::template find_pos(); + + static constexpr size_t a_shift = has_alpha ? 16 - Plane::template component_size : 0; + static constexpr size_t x_shift = has_padding ? 16 - Plane::template component_size : 0; + static constexpr size_t r_shift = 16 - Plane::template component_size; + static constexpr size_t g_shift = 16 - Plane::template component_size; + static constexpr size_t b_shift = 16 - Plane::template component_size; + + static_assert(Plane::total_bits % 8 == 0); + static constexpr size_t bytes_per_pixel = Plane::total_bits / 8; + +public: + // Pack and write num_pixels pixels from src_line to dst_line + static void pack_line(HasIndexOperatorReturning auto&& dst_line, + HasIndexOperatorReturning auto&& src_line, + size_t num_pixels) + { + for (size_t x = 0; x < num_pixels; x++) { + const RGB16& pix = src_line[x]; + + std::array + components; + + if constexpr (has_alpha) + components[a_idx] = pix.a >> a_shift; + + if constexpr (has_padding) + components[x_idx] = 0; + + components[r_idx] = pix.r >> r_shift; + components[g_idx] = pix.g >> g_shift; + components[b_idx] = pix.b >> b_shift; + + if constexpr (!needs_packed_access) { + dst_line[x] = Plane::pack(components); + } else { + auto dst_bytes = reinterpret_cast(&dst_line[0]); + + TStorage packed = Plane::pack(components); + + memcpy(dst_bytes + x * bytes_per_pixel, &packed, + bytes_per_pixel); + } + } + } + + // Read and unpack num_pixels pixels from src_line to dst_line + static void unpack_line(HasIndexOperatorReturning auto&& dst_line, + HasIndexOperatorReturning auto&& src_line, + size_t num_pixels) + { + for (size_t x = 0; x < num_pixels; x++) { + decltype(Plane::unpack(src_line[x])) components; + + if constexpr (!needs_packed_access) { + components = Plane::unpack(src_line[x]); + } else { + auto src_bytes = + reinterpret_cast(&src_line[0]); + TStorage packed; + + memcpy(&packed, src_bytes + x * bytes_per_pixel, + bytes_per_pixel); + + components = Plane::unpack(packed); + } + + dst_line[x] = RGB16 { + static_cast(components[r_idx] << r_shift), + static_cast(components[g_idx] << g_shift), + static_cast(components[b_idx] << b_shift), + static_cast(has_alpha ? components[a_idx] << a_shift : 0), + }; + } + } + + static void write_pattern(IFramebuffer& fb, size_t start_y, size_t end_y, + auto&& generate_line) + { + std::vector linebuf(fb.width()); + + // View to the plane + auto view = make_strided_fb_view(fb.map(0), fb.height(), fb.width(), + fb.stride(0)); + + for (size_t y_src = start_y; y_src <= end_y; y_src++) { + generate_line(y_src, linebuf); + + auto dst = md::submdspan(view, y_src, md::full_extent); + + pack_line(dst, linebuf, fb.width()); + } + } + + static void get_line(IFramebuffer& fb, size_t w, size_t h, size_t row, std::span linebuf) + { + auto view = make_strided_fb_view(fb.map(0), fb.height(), fb.width(), + fb.stride(0)); + + auto src = md::submdspan(view, row, md::full_extent); + + unpack_line(linebuf, src); + } +}; + +} // namespace kms -- cgit v1.2.3