From 87e6c1118b4c047a0e55fb6aaea60337bae571bb Mon Sep 17 00:00:00 2001 From: omigamedev Date: Sat, 13 Jun 2026 22:59:24 +0200 Subject: [PATCH] Extract stroke draw main pass texture dispatch --- docs/modernization/debt.md | 4 ++ docs/modernization/tasks.md | 8 ++- tests/paint_renderer/compositor_tests.cpp | 71 +++++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 25a8299..a387978 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -529,6 +529,10 @@ agent or engineer to remove them without reconstructing context from chat. has regression coverage for retained mixer-state callback ordering through `execute_legacy_canvas_stroke_mix_pass(...)`; the live path still owns the concrete mixer framebuffer setup and GL capability toggles. +- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw()` main-pass + texture dispatch now has regression coverage through + `make_legacy_canvas_stroke_main_pass_texture_dispatch(...)`; the live path + still owns the concrete texture objects and sampler state. - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge` checkerboard background shader setup and final merged-texture redraw setup now route through `legacy_canvas_draw_merge_services.h`. The retained Canvas path still diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 9f4d868..996916f 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -575,7 +575,7 @@ Done Checks: ### STR-020 - Extract Stroke Draw Main Pass Texture Dispatch -Status: Ready +Status: Done Score: +1 renderer boundary and OpenGL parity Debt: `DEBT-0036` Scope: `src/canvas.cpp`, `src/legacy_canvas_stroke_execution_services.h`, `tests/paint_renderer/compositor_tests.cpp` @@ -601,6 +601,12 @@ Validation: ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_compositor|pp_paint_renderer_stroke_execution" --output-on-failure ``` +### Completed Task Log + +| Date | Task | Score | Validation | Commit | +| --- | --- | --- | --- | --- | +| 2026-06-13 | STR-020 | +1 renderer boundary and OpenGL parity | `ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_compositor|pp_paint_renderer_stroke_execution" --output-on-failure` | `pending` | + Progress Notes: - 2026-06-13: `NodeStrokePreview::draw_stroke_immediate()` now routes final diff --git a/tests/paint_renderer/compositor_tests.cpp b/tests/paint_renderer/compositor_tests.cpp index 5698b7d..3c59eb4 100644 --- a/tests/paint_renderer/compositor_tests.cpp +++ b/tests/paint_renderer/compositor_tests.cpp @@ -1729,6 +1729,74 @@ void plans_canvas_stroke_dual_material_intent(pp::tests::Harness& h) PP_EXPECT(h, has_texture_binding(dual_composite_pattern, CanvasStrokeTextureRole::pattern, 2)); } +void legacy_canvas_stroke_main_pass_texture_dispatch_preserves_order(pp::tests::Harness& h) +{ + std::vector steps; + const auto dispatch = pp::panopainter::make_legacy_canvas_stroke_main_pass_texture_dispatch( + [&](int slot) { + steps.emplace_back("activate:" + std::to_string(slot)); + }, + [&] { + steps.emplace_back("bind-tip"); + }, + [&] { + steps.emplace_back("unbind-tip"); + }, + [&] { + steps.emplace_back("bind-pattern"); + }, + [&] { + steps.emplace_back("bind-mixer"); + }, + [&] { + steps.emplace_back("unbind-mixer"); + }); + + pp::panopainter::bind_legacy_canvas_stroke_texture_inputs( + std::array { + pp::panopainter::LegacyCanvasStrokeTextureBinding { + .input = pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip, + .slot = 0, + }, + pp::panopainter::LegacyCanvasStrokeTextureBinding { + .input = pp::panopainter::LegacyCanvasStrokeTextureInput::pattern, + .slot = 2, + }, + pp::panopainter::LegacyCanvasStrokeTextureBinding { + .input = pp::panopainter::LegacyCanvasStrokeTextureInput::mixer, + .slot = 3, + }, + }, + dispatch); + + pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs( + std::array { + pp::panopainter::LegacyCanvasStrokeTextureBinding { + .input = pp::panopainter::LegacyCanvasStrokeTextureInput::mixer, + .slot = 3, + }, + pp::panopainter::LegacyCanvasStrokeTextureBinding { + .input = pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip, + .slot = 0, + }, + }, + dispatch); + + const std::vector expected { + "activate:0", + "bind-tip", + "activate:2", + "bind-pattern", + "activate:3", + "bind-mixer", + "activate:3", + "unbind-mixer", + "activate:0", + "unbind-tip", + }; + PP_EXPECT(h, steps == expected); +} + void plans_canvas_stroke_commit_erase_sequence(pp::tests::Harness& h) { const auto plan = plan_canvas_stroke_commit_sequence( @@ -3598,6 +3666,9 @@ int main() harness.run("rejects_bad_stroke_composite_plans", rejects_bad_stroke_composite_plans); harness.run("plans_canvas_stroke_material_passes", plans_canvas_stroke_material_passes); harness.run("plans_canvas_stroke_dual_material_intent", plans_canvas_stroke_dual_material_intent); + harness.run( + "legacy_canvas_stroke_main_pass_texture_dispatch_preserves_order", + legacy_canvas_stroke_main_pass_texture_dispatch_preserves_order); harness.run("plans_canvas_stroke_commit_erase_sequence", plans_canvas_stroke_commit_erase_sequence); harness.run("plans_canvas_stroke_commit_composite_sequence", plans_canvas_stroke_commit_composite_sequence); harness.run(