Extract pad destination dispatch helper

This commit is contained in:
2026-06-13 23:14:35 +02:00
parent 59a83468a6
commit 4bca83982c
4 changed files with 69 additions and 23 deletions

View File

@@ -547,6 +547,10 @@ agent or engineer to remove them without reconstructing context from chat.
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw()` dual-pass - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw()` dual-pass
shader setup now uses a retained wrapper helper; the dual-pass branch still shader setup now uses a retained wrapper helper; the dual-pass branch still
owns the concrete shader selection and framebuffer wiring. owns the concrete shader selection and framebuffer wiring.
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw()` pad
destination dispatch now reuses a retained helper object, with regression
coverage proving the helper order; the pad branch still owns the concrete
texture-object wiring and copy timing.
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge` checkerboard - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge` checkerboard
background shader setup and final merged-texture redraw setup now route background shader setup and final merged-texture redraw setup now route
through `legacy_canvas_draw_merge_services.h`. The retained Canvas path still through `legacy_canvas_draw_merge_services.h`. The retained Canvas path still

View File

@@ -791,7 +791,7 @@ ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_composito
### STR-027 - Extract Stroke Draw Pad Destination Dispatch ### STR-027 - Extract Stroke Draw Pad Destination Dispatch
Status: Ready Status: Done
Score: +1 renderer boundary and OpenGL parity Score: +1 renderer boundary and OpenGL parity
Debt: `DEBT-0036` Debt: `DEBT-0036`
Scope: `src/canvas.cpp`, `src/legacy_canvas_stroke_execution_services.h`, `tests/paint_renderer/compositor_tests.cpp` Scope: `src/canvas.cpp`, `src/legacy_canvas_stroke_execution_services.h`, `tests/paint_renderer/compositor_tests.cpp`
@@ -817,6 +817,12 @@ Validation:
ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_compositor|pp_paint_renderer_stroke_execution" --output-onfailure ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_compositor|pp_paint_renderer_stroke_execution" --output-onfailure
``` ```
### Completed Task Log
| Date | Task | Score | Validation | Commit |
| --- | --- | --- | --- | --- |
| 2026-06-13 | STR-027 | +1 renderer boundary and OpenGL parity | `ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_compositor|pp_paint_renderer_stroke_execution" --output-onfailure` | `pending` |
### STR-028 - Extract Stroke Draw Pad Face Orchestration ### STR-028 - Extract Stroke Draw Pad Face Orchestration
Status: Ready Status: Ready

View File

@@ -1052,6 +1052,18 @@ void Canvas::stroke_draw()
.slot = 1, .slot = 1,
}, },
}; };
const auto pad_destination_texture_dispatch =
pp::panopainter::make_legacy_canvas_stroke_pad_destination_texture_dispatch(
[&](int texture_slot) {
set_active_texture_unit(texture_slot);
},
[&](int dst_face_index) {
m_tex[dst_face_index].bind();
},
[&](int dst_face_index) {
m_tex[dst_face_index].unbind();
},
0);
[[maybe_unused]] const auto pad_result = pp::panopainter::execute_legacy_canvas_stroke_pad_face_callbacks( [[maybe_unused]] const auto pad_result = pp::panopainter::execute_legacy_canvas_stroke_pad_face_callbacks(
pad_faces, pad_faces,
stroke_extent, stroke_extent,
@@ -1067,17 +1079,7 @@ void Canvas::stroke_draw()
[&](int face_index) { [&](int face_index) {
pp::panopainter::bind_legacy_canvas_stroke_texture_inputs( pp::panopainter::bind_legacy_canvas_stroke_texture_inputs(
pad_destination_texture_binding, pad_destination_texture_binding,
pp::panopainter::make_legacy_canvas_stroke_pad_destination_texture_dispatch( pad_destination_texture_dispatch);
[&](int texture_slot) {
set_active_texture_unit(texture_slot);
},
[&](int dst_face_index) {
m_tex[dst_face_index].bind();
},
[&](int dst_face_index) {
m_tex[dst_face_index].unbind();
},
face_index));
}, },
[&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) { [&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) {
pp::panopainter::execute_legacy_canvas_stroke_pad_copy_region( pp::panopainter::execute_legacy_canvas_stroke_pad_copy_region(
@@ -1087,17 +1089,7 @@ void Canvas::stroke_draw()
[&](int face_index) { [&](int face_index) {
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs( pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
pad_destination_texture_binding, pad_destination_texture_binding,
pp::panopainter::make_legacy_canvas_stroke_pad_destination_texture_dispatch( pad_destination_texture_dispatch);
[&](int texture_slot) {
set_active_texture_unit(texture_slot);
},
[&](int dst_face_index) {
m_tex[dst_face_index].bind();
},
[&](int dst_face_index) {
m_tex[dst_face_index].unbind();
},
face_index));
}, },
[&] { [&] {
m_brush_shape.draw_fill(); m_brush_shape.draw_fill();

View File

@@ -1968,6 +1968,47 @@ void legacy_canvas_stroke_dual_shader_wrapper_preserves_setup(pp::tests::Harness
PP_EXPECT(h, steps.size() == 1U); PP_EXPECT(h, steps.size() == 1U);
} }
void legacy_canvas_stroke_pad_destination_dispatch_preserves_order(pp::tests::Harness& h)
{
std::vector<std::string> steps;
const auto dispatch = pp::panopainter::make_legacy_canvas_stroke_pad_destination_texture_dispatch(
[&](int slot) {
steps.emplace_back("activate:" + std::to_string(slot));
},
[&](int face_index) {
steps.emplace_back("bind:" + std::to_string(face_index));
},
[&](int face_index) {
steps.emplace_back("unbind:" + std::to_string(face_index));
},
4);
pp::panopainter::bind_legacy_canvas_stroke_texture_inputs(
std::array {
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination,
.slot = 1,
},
},
dispatch);
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
std::array {
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination,
.slot = 1,
},
},
dispatch);
const std::vector<std::string> expected {
"activate:1",
"bind:4",
"activate:1",
"unbind:4",
};
PP_EXPECT(h, steps == expected);
}
void plans_canvas_stroke_commit_erase_sequence(pp::tests::Harness& h) void plans_canvas_stroke_commit_erase_sequence(pp::tests::Harness& h)
{ {
const auto plan = plan_canvas_stroke_commit_sequence( const auto plan = plan_canvas_stroke_commit_sequence(
@@ -3849,6 +3890,9 @@ int main()
harness.run( harness.run(
"legacy_canvas_stroke_pad_copy_region_preserves_coordinates", "legacy_canvas_stroke_pad_copy_region_preserves_coordinates",
legacy_canvas_stroke_pad_copy_region_preserves_coordinates); legacy_canvas_stroke_pad_copy_region_preserves_coordinates);
harness.run(
"legacy_canvas_stroke_pad_destination_dispatch_preserves_order",
legacy_canvas_stroke_pad_destination_dispatch_preserves_order);
harness.run("plans_canvas_stroke_commit_erase_sequence", plans_canvas_stroke_commit_erase_sequence); 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("plans_canvas_stroke_commit_composite_sequence", plans_canvas_stroke_commit_composite_sequence);
harness.run( harness.run(