diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index d20b161..fb77dfd 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::draw_merge()` now routes + the remaining per-layer branch orchestration through + `execute_legacy_canvas_draw_merge_layer_composite(...)`; the retained path + still owns the concrete temporary-stroke, layer-texture, and layer-blend + callback bodies. - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_commit()` now builds its retained callback table through `make_legacy_canvas_stroke_commit_callbacks(...)`; the legacy executor still diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 8ae4231..eaed458 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -1022,3 +1022,39 @@ Completed Task Log: | Date | Task | Score | Validation | Commit | | --- | --- | ---: | --- | --- | | 2026-06-13 | STR-009 | +2 renderer boundary and OpenGL parity | `ctest --preset desktop-fast --build-config Debug -R "retained_stroke_commit_callback_builder_preserves_order|retained_stroke_commit_runner_preserves_per_face_step_order" --output-on-failure`; `& 'C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe' out\build\windows-msvc-default\tests\pp_paint_renderer_compositor_tests.vcxproj /p:Configuration=Debug /p:Platform=x64` | `pending` | + +### STR-010 - Extract Remaining Draw Merge Composite Orchestration + +Status: Done +Score: +2 renderer boundary and OpenGL parity +Debt: `DEBT-0036` +Scope: `src/canvas.cpp`, `src/legacy_canvas_draw_merge_services.*`, +`tests/paint_renderer/compositor_tests.cpp` + +Goal: + +Move the remaining inline `Canvas::draw_merge()` branch orchestration into +retained helpers so the merge path keeps only concrete framebuffer, sampler, +and texture wiring. Preserve per-plane order, temporary-stroke behavior, and +final merge composition. + +Done Checks: + +- `Canvas::draw_merge()` no longer contains the remaining large inline branch + orchestration for temporary-stroke or blend/final-plane composition. +- Regression coverage proves the extracted helper preserves ordering and + branch behavior. +- `docs/modernization/debt.md` records the reduced draw-merge callback surface. + +Validation: + +```powershell +ctest --preset desktop-fast --build-config Debug -R "pp_paint_renderer_compositor" --output-on-failure +& 'C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe' out\build\windows-msvc-default\tests\pp_paint_renderer_compositor_tests.vcxproj /p:Configuration=Debug /p:Platform=x64 +``` + +Completed Task Log: + +| Date | Task | Score | Validation | Commit | +| --- | --- | ---: | --- | --- | +| 2026-06-13 | STR-010 | +2 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`; `& 'C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\MSBuild.exe' out\build\windows-msvc-default\PanoPainter.vcxproj /p:Configuration=Debug /p:Platform=x64` | `pending` | diff --git a/src/canvas.cpp b/src/canvas.cpp index 228fb64..2fdf264 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -1403,9 +1403,13 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array faces /*= SI m_merge_rtt.clear(); } - if (m_current_stroke && m_current_mode == kCanvasMode::Erase && m_show_tmp && m_current_layer_idx == layer_index) - { - pp::panopainter::execute_legacy_canvas_stroke_temporary_composite( + pp::panopainter::execute_legacy_canvas_draw_merge_layer_composite( + m_current_stroke && m_current_mode == kCanvasMode::Erase && m_show_tmp && m_current_layer_idx == layer_index, + m_current_stroke && m_show_tmp && m_current_layer_idx == layer_index, + use_blend, + pp::panopainter::LegacyCanvasDrawMergeLayerCompositeExecution { + .execute_temporary_erase = [&] { + pp::panopainter::execute_legacy_canvas_stroke_temporary_composite( [&] { //ShaderManager::u_vec2(kShaderUniform::Resolution, zw(m_box) / zoom); //ShaderManager::u_int(kShaderUniform::Lock, m_layers[layer_index]->m_alpha_locked); @@ -1442,15 +1446,14 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array faces /*= SI set_active_texture_unit(0); m_layers[layer_index]->rtt(plane_index).unbindTexture(); }); - } - else if (m_current_stroke && m_show_tmp && m_current_layer_idx == layer_index) - { - const auto stroke_material = canvas_stroke_material_plan(*b, false); - glm::vec2 patt_scale = glm::vec2(b->m_pattern_scale); - if (b->m_pattern_flipx) patt_scale.x *= -1.f; - if (b->m_pattern_flipy) patt_scale.y *= -1.f; + }, + .execute_temporary_paint = [&] { + const auto stroke_material = canvas_stroke_material_plan(*b, false); + glm::vec2 patt_scale = glm::vec2(b->m_pattern_scale); + if (b->m_pattern_flipx) patt_scale.x *= -1.f; + if (b->m_pattern_flipy) patt_scale.y *= -1.f; - pp::panopainter::execute_legacy_canvas_stroke_temporary_composite( + pp::panopainter::execute_legacy_canvas_stroke_temporary_composite( [&] { pp::panopainter::setup_legacy_stroke_composite_shader( pp::panopainter::LegacyStrokeCompositeUniforms { @@ -1512,10 +1515,9 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array faces /*= SI set_active_texture_unit(0); m_layers[layer_index]->rtt(plane_index).unbindTexture(); }); - } - else - { - pp::panopainter::execute_legacy_canvas_draw_merge_layer_texture( + }, + .execute_layer_texture = [&] { + pp::panopainter::execute_legacy_canvas_draw_merge_layer_texture( pp::panopainter::LegacyCanvasDrawMergeTextureAlphaUniforms { .mvp = ortho, .texture_slot = 0, @@ -1537,11 +1539,9 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array faces /*= SI m_layers[layer_index]->rtt(plane_index).unbindTexture(); }, }); - } - - if (use_blend) - { - pp::panopainter::execute_legacy_canvas_draw_merge_layer_blend( + }, + .execute_layer_blend = [&] { + pp::panopainter::execute_legacy_canvas_draw_merge_layer_blend( pp::panopainter::LegacyCanvasDrawMergeLayerBlendUniforms { .shader = { .mvp = ortho, @@ -1584,7 +1584,8 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array faces /*= SI m_merge_rtt.unbindTexture(); }, }); - } + }, + }); } if (use_blend) diff --git a/src/legacy_canvas_draw_merge_services.h b/src/legacy_canvas_draw_merge_services.h index f9a86ce..63b3127 100644 --- a/src/legacy_canvas_draw_merge_services.h +++ b/src/legacy_canvas_draw_merge_services.h @@ -87,6 +87,13 @@ struct LegacyCanvasDrawMergeLayerTextureExecution { std::function unbind_layer_texture; }; +struct LegacyCanvasDrawMergeLayerCompositeExecution { + std::function execute_temporary_erase; + std::function execute_temporary_paint; + std::function execute_layer_texture; + std::function execute_layer_blend; +}; + struct LegacyCanvasDrawMergePlaneSetupUniforms { LegacyCanvasDrawMergeCheckerboardUniforms checkerboard; bool use_blend = false; @@ -304,6 +311,25 @@ inline void execute_legacy_canvas_draw_merge_layer_texture( execution.unbind_layer_texture(); } +inline void execute_legacy_canvas_draw_merge_layer_composite( + bool is_temporary_erase, + bool is_temporary_paint, + bool use_blend, + const LegacyCanvasDrawMergeLayerCompositeExecution& execution) +{ + if (is_temporary_erase) { + execution.execute_temporary_erase(); + } else if (is_temporary_paint) { + execution.execute_temporary_paint(); + } else { + execution.execute_layer_texture(); + } + + if (use_blend) { + execution.execute_layer_blend(); + } +} + inline void execute_legacy_canvas_draw_merge_plane_setup( const LegacyCanvasDrawMergePlaneSetupUniforms& uniforms, const LegacyCanvasDrawMergePlaneSetupExecution& execution)