From 68c24fcc007eedbcb9b9021e16911c0d652e0469 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Sun, 9 Mar 2025 14:02:49 -0500 Subject: [PATCH] allow multiple schedules for temporal dithering (however, there's no code yet to generate such schedules) --- src/include/piomatter/matrixmap.h | 11 +++++----- src/include/piomatter/piomatter.h | 34 ++++++++++++++++++------------- src/include/piomatter/render.h | 6 +++--- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/include/piomatter/matrixmap.h b/src/include/piomatter/matrixmap.h index 47885f1..3c4f40a 100644 --- a/src/include/piomatter/matrixmap.h +++ b/src/include/piomatter/matrixmap.h @@ -86,8 +86,9 @@ struct schedule_entry { }; using schedule = std::vector; +using schedule_sequence = std::vector; -schedule make_simple_schedule(int n_planes, int pixels_across) { +schedule_sequence make_simple_schedule(int n_planes, int pixels_across) { schedule result; uint32_t max_count = 1 << n_planes; while (max_count < pixels_across) @@ -96,7 +97,7 @@ schedule make_simple_schedule(int n_planes, int pixels_across) { for (int i = 0; i < n_planes; i++) { result.emplace_back(10 - i, max_count >> i); } - return result; + return {result}; } struct matrix_geometry { @@ -115,10 +116,10 @@ struct matrix_geometry { matrix_geometry(size_t pixels_across, size_t n_addr_lines, size_t width, size_t height, matrix_map map, size_t n_lanes, - const std::vector schedule) + const schedule_sequence &schedules) : pixels_across(pixels_across), n_addr_lines(n_addr_lines), n_lanes(n_lanes), width(width), height(height), - map(map), schedule{schedule} { + map(map), schedules{schedules} { size_t pixels_down = n_lanes << n_addr_lines; if (map.size() != pixels_down * pixels_across) { throw std::range_error( @@ -127,7 +128,7 @@ struct matrix_geometry { } size_t pixels_across, n_addr_lines, n_lanes; - std::vector schedule; + schedule_sequence schedules; size_t width, height; matrix_map map; }; diff --git a/src/include/piomatter/piomatter.h b/src/include/piomatter/piomatter.h index 918811e..837c9a3 100644 --- a/src/include/piomatter/piomatter.h +++ b/src/include/piomatter/piomatter.h @@ -49,6 +49,7 @@ template struct piomatter : piomatter_base { using buffer_type = std::vector; + using bufseq_type = std::vector; piomatter(std::span framebuffer, const matrix_geometry &geometry) : framebuffer(framebuffer), geometry{geometry}, converter{}, @@ -63,9 +64,13 @@ struct piomatter : piomatter_base { void show() override { int buffer_idx = manager.get_free_buffer(); - auto &buffer = buffers[buffer_idx]; + auto &bufseq = buffers[buffer_idx]; + bufseq.resize(geometry.schedules.size()); auto converted = converter.convert(framebuffer); - protomatter_render_rgb10(buffer, geometry, converted.data()); + for (size_t i = 0; i < geometry.schedules.size(); i++) { + protomatter_render_rgb10( + bufseq[i], geometry, geometry.schedules[i], converted.data()); + } manager.put_filled_buffer(buffer_idx); } @@ -161,26 +166,27 @@ struct piomatter : piomatter_base { } void blit_thread() { - const uint32_t *databuf = nullptr; - size_t datasize = 0; - int old_buffer_idx = buffer_manager::no_buffer; + int cur_buffer_idx = buffer_manager::no_buffer; int buffer_idx; + int seq_idx = -1; uint64_t t0, t1; t0 = monotonicns64(); while ((buffer_idx = manager.get_filled_buffer()) != buffer_manager::exit_request) { if (buffer_idx != buffer_manager::no_buffer) { - const auto &buffer = buffers[buffer_idx]; - databuf = &buffer[0]; - datasize = buffer.size() * sizeof(*databuf); - if (old_buffer_idx != buffer_manager::no_buffer) { - manager.put_free_buffer(old_buffer_idx); + if (cur_buffer_idx != buffer_manager::no_buffer) { + manager.put_free_buffer(cur_buffer_idx); } - old_buffer_idx = buffer_idx; + cur_buffer_idx = buffer_idx; } - if (datasize) { + if (cur_buffer_idx != buffer_manager::no_buffer) { + const auto &cur_buf = buffers[cur_buffer_idx]; + seq_idx = (seq_idx + 1) % cur_buf.size(); + const auto &data = cur_buf[seq_idx]; + auto datasize = sizeof(uint32_t) * data.size(); + auto dataptr = const_cast(&data[0]); pio_sm_xfer_data_large(pio, sm, PIO_DIR_TO_SM, datasize, - (uint32_t *)databuf); + dataptr); t1 = monotonicns64(); if (t0 != t1) { fps = 1e9 / (t1 - t0); @@ -195,7 +201,7 @@ struct piomatter : piomatter_base { PIO pio = NULL; int sm = -1; std::span framebuffer; - buffer_type buffers[3]; + bufseq_type buffers[3]; buffer_manager manager{}; matrix_geometry geometry; colorspace converter; diff --git a/src/include/piomatter/render.h b/src/include/piomatter/render.h index c8bc059..1d94586 100644 --- a/src/include/piomatter/render.h +++ b/src/include/piomatter/render.h @@ -132,7 +132,7 @@ struct colorspace_rgb10 { template void protomatter_render_rgb10(std::vector &result, const matrix_geometry &matrixmap, - const uint32_t *pixels) { + const schedule &sched, const uint32_t *pixels) { result.clear(); int data_count = 0; @@ -194,8 +194,8 @@ void protomatter_render_rgb10(std::vector &result, uint32_t addr_bits = calc_addr_bits(prev_addr); for (size_t addr = 0; addr < n_addr; addr++) { - uint32_t active_time = matrixmap.schedule.back().active_time; - for (auto &schedule_ent : matrixmap.schedule) { + uint32_t active_time = sched.back().active_time; + for (auto &schedule_ent : sched) { uint32_t r_mask = 1 << (20 + schedule_ent.shift); uint32_t g_mask = 1 << (10 + schedule_ent.shift); uint32_t b_mask = 1 << (0 + schedule_ent.shift);