From f1f0dd5d03f67805f17a3794664eff33cdb659ac Mon Sep 17 00:00:00 2001 From: omigamedev Date: Sat, 13 Jun 2026 10:07:57 +0200 Subject: [PATCH] Route stroke pad pass through helper callbacks --- docs/modernization/debt.md | 5 ++ docs/modernization/roadmap.md | 4 ++ src/canvas.cpp | 60 ++++++++++--------- src/legacy_canvas_stroke_execution_services.h | 43 ++++++++++++- 4 files changed, 82 insertions(+), 30 deletions(-) diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 896c885..fad6012 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -18,6 +18,11 @@ agent or engineer to remove them without reconstructing context from chat. ## Recent Reductions +- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw` pad-pass + destination bind/copy/unbind ordering now routes through + `legacy_canvas_stroke_execution_services.h`; shader setup, pad color + selection, framebuffer ownership, and final OpenGL draw remain retained in + `Canvas`. - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw` current and dual live sample frame/face traversal plus dirty tracking now route through `legacy_canvas_stroke_execution_services.h`; shader timing, sampler/texture diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 533c7b0..5afb4c1 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -3093,6 +3093,10 @@ Results: dirty tracking now share one retained stroke execution helper surface, while shader timing, sampler/texture binding, framebuffer ownership, pad execution, and final OpenGL draw ordering remain in the legacy Canvas path. +- `Canvas::stroke_draw` pad-pass destination bind/copy/unbind ordering now + shares the retained stroke execution helper callback surface, while shader + setup, pad color selection, framebuffer ownership, and final OpenGL draw + remain in the legacy Canvas path. - `Canvas::stroke_draw` pad-region planning now shares the retained stroke execution helper wrapping `pp_paint_renderer`, while pad color selection, dirty-face iteration, framebuffer copies, quad upload, and draw execution diff --git a/src/canvas.cpp b/src/canvas.cpp index 0779733..3c247d4 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -742,10 +742,6 @@ void Canvas::stroke_draw() .color = pad_color, .uses_destination_feedback = copy_stroke_destination, }); - if (copy_stroke_destination) - { - set_active_texture_unit(1); - } const std::array pad_faces = { pp::panopainter::LegacyCanvasStrokePadFace { .index = 0, .dirty = box_dirty[0], .pass_dirty_box = box_face[0] }, pp::panopainter::LegacyCanvasStrokePadFace { .index = 1, .dirty = box_dirty[1], .pass_dirty_box = box_face[1] }, @@ -759,32 +755,40 @@ void Canvas::stroke_draw() .context = "Canvas::stroke_draw", .extent = stroke_extent, .faces = pad_faces, - .execute_face = - [&](int face_index, - const pp::panopainter::LegacyCanvasStrokePadRegionResult& pad_region, - std::span pad_quad) { - m_brush_shape.update_vertices(pad_quad.data(), pad_quad.size()); - - m_tmp[face_index].bindFramebuffer(); - if (copy_stroke_destination) - { - m_tex[face_index].bind(); - copy_framebuffer_to_texture_2d( - pad_region.copy_region.x, - pad_region.copy_region.y, - pad_region.copy_region.x, - pad_region.copy_region.y, - pad_region.copy_region.width, - pad_region.copy_region.height); - } - m_brush_shape.draw_fill(); - m_tmp[face_index].unbindFramebuffer(); + .copy_stroke_destination = copy_stroke_destination, + .upload_pad_vertices = [&](std::span pad_quad) { + m_brush_shape.update_vertices( + const_cast(pad_quad.data()), + static_cast(pad_quad.size())); + }, + .begin_face = [&](int face_index) { + m_tmp[face_index].bindFramebuffer(); + }, + .bind_destination_texture = [&](int face_index) { + set_active_texture_unit(1); + m_tex[face_index].bind(); + }, + .copy_framebuffer_to_destination_texture = + [&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) { + copy_framebuffer_to_texture_2d( + copy_region.x, + copy_region.y, + copy_region.x, + copy_region.y, + copy_region.width, + copy_region.height); }, + .unbind_destination_texture = [&](int face_index) { + set_active_texture_unit(1); + m_tex[face_index].unbind(); + }, + .draw_pad = [&] { + m_brush_shape.draw_fill(); + }, + .finish_face = [&](int face_index) { + m_tmp[face_index].unbindFramebuffer(); + }, }); - if (copy_stroke_destination) - { - unbind_texture_2d(); - } // DRAW DUAL BRUSH diff --git a/src/legacy_canvas_stroke_execution_services.h b/src/legacy_canvas_stroke_execution_services.h index 8ea0ce6..eaaadfd 100644 --- a/src/legacy_canvas_stroke_execution_services.h +++ b/src/legacy_canvas_stroke_execution_services.h @@ -74,6 +74,14 @@ struct LegacyCanvasStrokePadExecutionRequest { std::string_view context; pp::renderer::Extent2D extent {}; std::span faces; + bool copy_stroke_destination = false; + std::function)> upload_pad_vertices; + std::function begin_face; + std::function bind_destination_texture; + std::function copy_framebuffer_to_destination_texture; + std::function unbind_destination_texture; + std::function draw_pad; + std::function finish_face; std::function)> execute_face; }; @@ -423,7 +431,11 @@ template