diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 91a8445..cfdbcf0 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -115,6 +115,10 @@ agent or engineer to remove them without reconstructing context from chat. - 2026-06-13: `DEBT-0036` was narrowed again. `Canvas::stroke_commit()` now routes the face-indexed commit-input binding wrapper through the retained service boundary, leaving `Canvas` with only concrete face bindings. +- 2026-06-13: `DEBT-0036` was narrowed again. `Canvas::stroke_commit()` + now routes the retained commit request assembly through + `make_legacy_canvas_stroke_commit_request(...)`, leaving the callsite with + only concrete faces, sequence, and callbacks. - 2026-06-13: `DEBT-0036` was narrowed again. `NodeStrokePreview::draw_stroke_immediate()` now routes final composite execution and preview copy-back through a retained local wrapper, leaving the call site with only sequence wiring. diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 7bf33b9..60b7c61 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -1253,6 +1253,10 @@ ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_stroke_ex | --- | --- | ---: | --- | --- | | 2026-06-13 | STR-014 | +1 renderer boundary and OpenGL parity | `ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_stroke_execution|pp_paint_renderer_compositor" --output-on-failure` | `536f2683` | +- 2026-06-13: `Canvas::stroke_commit()` now routes the retained commit request + assembly through `make_legacy_canvas_stroke_commit_request(...)`, so the + callsite only supplies concrete faces, sequence, and callbacks. + ### STR-011 - Extract Preview Main Pass Orchestration Status: Done diff --git a/src/canvas.cpp b/src/canvas.cpp index 1afa5e2..27e89de 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -736,19 +736,6 @@ static auto make_canvas_stroke_commit_callbacks( }); } -static auto make_canvas_stroke_commit_request( - const std::array& faces, - const pp::paint_renderer::CanvasStrokeCommitSequencePlan& sequence, - const pp::panopainter::LegacyCanvasStrokeCommitCallbacks& callbacks) -{ - return pp::panopainter::LegacyCanvasStrokeCommitRequest { - .context = "Canvas::stroke_commit", - .faces = faces, - .sequence = sequence, - .callbacks = callbacks, - }; -} - glm::vec4 Canvas::stroke_draw_samples( int i, std::vector& P, @@ -1353,7 +1340,7 @@ void Canvas::stroke_commit() }; [[maybe_unused]] const auto commit_result = pp::panopainter::execute_legacy_canvas_stroke_commit_sequence( - make_canvas_stroke_commit_request(faces, sequence, commit_callbacks)); + pp::panopainter::make_legacy_canvas_stroke_commit_request(faces, sequence, commit_callbacks)); } void Canvas::stroke_commit_timelapse() diff --git a/src/legacy_canvas_stroke_commit_services.h b/src/legacy_canvas_stroke_commit_services.h index f198f8f..32b6b31 100644 --- a/src/legacy_canvas_stroke_commit_services.h +++ b/src/legacy_canvas_stroke_commit_services.h @@ -165,6 +165,19 @@ inline void bind_legacy_canvas_stroke_commit_face_inputs( std::forward(bind_face_sampler_role)); } +[[nodiscard]] inline LegacyCanvasStrokeCommitRequest make_legacy_canvas_stroke_commit_request( + const std::array& faces, + const pp::paint_renderer::CanvasStrokeCommitSequencePlan& sequence, + const LegacyCanvasStrokeCommitCallbacks& callbacks) +{ + return LegacyCanvasStrokeCommitRequest { + .context = "Canvas::stroke_commit", + .faces = faces, + .sequence = sequence, + .callbacks = callbacks, + }; +} + template inline void execute_legacy_canvas_stroke_commit_erase( SetupShader&& setup_shader, diff --git a/tests/paint_renderer/compositor_tests.cpp b/tests/paint_renderer/compositor_tests.cpp index 1e2860f..ef83949 100644 --- a/tests/paint_renderer/compositor_tests.cpp +++ b/tests/paint_renderer/compositor_tests.cpp @@ -1972,6 +1972,55 @@ void retained_stroke_commit_request_builder_preserves_dirty_face_order(pp::tests PP_EXPECT(h, request.faces[5].index == 5); } +void retained_stroke_commit_request_helper_preserves_dirty_face_order(pp::tests::Harness& h) +{ + const pp::panopainter::LegacyCanvasStrokeCommitCallbacks callbacks { + .mark_commit_started = []() {}, + .capture_render_state = []() {}, + .prepare_render_state = []() {}, + .restore_render_state = []() {}, + .publish_history = []() {}, + .capture_timelapse_frame = []() {}, + .bind_layer_framebuffer = [](int) {}, + .capture_history_region = [](int) {}, + .apply_layer_dirty_region = [](int) {}, + .copy_layer_to_commit_destination = [](int) {}, + .bind_commit_inputs = [](int) {}, + .execute_erase_composite = [](int) {}, + .execute_paint_composite = [](int) {}, + .copy_committed_to_dilate_source = [](int) {}, + .execute_commit_dilate = [](int) {}, + .unbind_layer_framebuffer = [](int) {}, + }; + const auto sequence = plan_canvas_stroke_commit_sequence( + CanvasStrokeCommitRequest { + .erase_mode = true, + .alpha_locked = true, + .selection_mask_active = false, + .dual_stroke_enabled = false, + .pattern_enabled = false, + }); + const std::array faces { + pp::panopainter::LegacyCanvasStrokeCommitFace { .index = 0, .dirty = true }, + pp::panopainter::LegacyCanvasStrokeCommitFace { .index = 1, .dirty = false }, + pp::panopainter::LegacyCanvasStrokeCommitFace { .index = 2, .dirty = true }, + pp::panopainter::LegacyCanvasStrokeCommitFace { .index = 3, .dirty = false }, + pp::panopainter::LegacyCanvasStrokeCommitFace { .index = 4, .dirty = true }, + pp::panopainter::LegacyCanvasStrokeCommitFace { .index = 5, .dirty = false }, + }; + + const auto request = pp::panopainter::make_legacy_canvas_stroke_commit_request( + faces, + sequence, + callbacks); + + PP_EXPECT(h, request.context == "Canvas::stroke_commit"); + PP_EXPECT(h, request.faces[0].dirty); + PP_EXPECT(h, request.faces[1].index == 1); + PP_EXPECT(h, request.faces[2].dirty); + PP_EXPECT(h, request.faces[4].dirty); +} + void retained_stroke_commit_dilate_copy_uses_layer_scratch_slot(pp::tests::Harness& h) { const auto sequence = plan_canvas_stroke_commit_sequence(