#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 = typename Layout::template plane<0>; using TStorage = typename 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 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