diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index 9eb60b4..2319164 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -160,6 +160,11 @@ agent or engineer to remove them without reconstructing context from chat. through `execute_legacy_node_stroke_preview_main_live_pass(...)`; the retained path still owns the concrete frame mutation, sample shader setup, and final mixer unbind. +- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview::draw_stroke_immediate()` + now routes the main live-pass request assembly through + `make_stroke_draw_immediate_main_live_pass_request(...)`; the retained path + still owns the concrete frame mutation, sample shader setup, and final mixer + unbind. - 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 diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 4892975..8bac9a3 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -1717,7 +1717,7 @@ Completed Task Log: ### STR-036 - Extract Preview Main Live Pass Orchestration -Status: Ready +Status: Done Score: no score movement Debt: `DEBT-0036` Scope: `src/node_stroke_preview.cpp`, `tests/paint_renderer/compositor_tests.cpp` @@ -1728,6 +1728,8 @@ Move the remaining `NodeStrokePreview::draw_stroke_immediate()` main live-pass orchestration into a retained helper so the callsite keeps only branch selection and direct live-pass dispatch. +Closeout: `b9647847` + Done Checks: - `NodeStrokePreview::draw_stroke_immediate()` no longer owns the main live-pass diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index 857e329..fe09f5e 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -790,62 +790,12 @@ void NodeStrokePreview::draw_stroke_immediate() .execute_main_pass = [&] { [[maybe_unused]] const bool main_live_ok = pp::panopainter::execute_legacy_node_stroke_preview_main_live_pass( - pp::panopainter::LegacyNodeStrokePreviewMainLivePassRequestT { - .setup_blend_uniforms = [&] { - pp::panopainter::apply_legacy_stroke_blend_uniforms( - material.stroke_pass.uses_pattern, - b->m_tip_mix, - b->m_tip_wet, - b->m_tip_noise); - }, - .bind_main_pass_textures = [&] { - bind_stroke_preview_main_pass_textures( - *b, - m_tex, - m_rtt_mixer, - copy_stroke_destination, - material.stroke_pass.uses_mixer); - }, - .clear_target = [&] { - m_rtt.clear(); - }, - .compute_frames = [&] { - return stroke_draw_compute(m_stroke, zoom); - }, - .before_frame = [&](auto& frame) { - if (b->m_tip_mix > 0.f) - { - stroke_draw_mix(xy(frame.m_mixer_rect), zw(frame.m_mixer_rect)); - } - - frame.col = b->m_blend_mode != 0 || b->m_tip_mix > 0.f ? - glm::vec4 { .7, .4, .1, 1 } : - glm::vec4 { 0, 0, 0, 1 }; - frame.flow = glm::max(frame.flow, m_min_flow); - }, - .setup_sample_shader = [&](auto& frame) { - pp::panopainter::use_legacy_stroke_shader(); - pp::panopainter::apply_legacy_stroke_sample_uniforms( - pp::panopainter::LegacyStrokeSampleUniforms { - .color = frame.col, - .alpha = frame.flow, - .opacity = frame.opacity, - }); - }, - .draw_sample = [&](auto& frame) { - /*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex, copy_stroke_destination); - }, - .copy_pass_result = [&] { - copy_stroke_preview_framebuffer_to_texture( - m_tex, - size, - stroke_preview_composite_slots::kStroke); - }, - .finish_main_pass = [&] { - set_active_texture_unit(stroke_preview_live_slots::kMixer); - m_rtt_mixer.unbindTexture(); - }, - }); + make_stroke_draw_immediate_main_live_pass_request( + *b, + pass_orchestration, + copy_stroke_destination, + zoom, + size)); }, .finish_main_pass = [&] {}, .execute_final_composite = [&] { @@ -877,6 +827,72 @@ void NodeStrokePreview::draw_stroke_immediate() apply_stroke_preview_clear_color(cc); } +NodeStrokePreview::StrokeMainLivePassRequest +NodeStrokePreview::make_stroke_draw_immediate_main_live_pass_request( + const Brush& brush, + const pp::panopainter::LegacyNodeStrokePreviewPassOrchestrationPlan& pass_orchestration, + bool copy_stroke_destination, + float zoom, + const glm::vec2& size) +{ + return StrokeMainLivePassRequest { + .setup_blend_uniforms = [&] { + pp::panopainter::apply_legacy_stroke_blend_uniforms( + pass_orchestration.material.stroke_pass.uses_pattern, + brush.m_tip_mix, + brush.m_tip_wet, + brush.m_tip_noise); + }, + .bind_main_pass_textures = [&] { + bind_stroke_preview_main_pass_textures( + brush, + m_tex, + m_rtt_mixer, + copy_stroke_destination, + pass_orchestration.material.stroke_pass.uses_mixer); + }, + .clear_target = [&] { + m_rtt.clear(); + }, + .compute_frames = [&] { + return stroke_draw_compute(m_stroke, zoom); + }, + .before_frame = [&](auto& frame) { + if (brush.m_tip_mix > 0.f) + { + stroke_draw_mix(xy(frame.m_mixer_rect), zw(frame.m_mixer_rect)); + } + + frame.col = brush.m_blend_mode != 0 || brush.m_tip_mix > 0.f ? + glm::vec4 { .7, .4, .1, 1 } : + glm::vec4 { 0, 0, 0, 1 }; + frame.flow = glm::max(frame.flow, m_min_flow); + }, + .setup_sample_shader = [&](auto& frame) { + pp::panopainter::use_legacy_stroke_shader(); + pp::panopainter::apply_legacy_stroke_sample_uniforms( + pp::panopainter::LegacyStrokeSampleUniforms { + .color = frame.col, + .alpha = frame.flow, + .opacity = frame.opacity, + }); + }, + .draw_sample = [&](auto& frame) { + /*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex, copy_stroke_destination); + }, + .copy_pass_result = [&] { + copy_stroke_preview_framebuffer_to_texture( + m_tex, + size, + stroke_preview_composite_slots::kStroke); + }, + .finish_main_pass = [&] { + set_active_texture_unit(stroke_preview_live_slots::kMixer); + m_rtt_mixer.unbindTexture(); + }, + }; +} + Image NodeStrokePreview::render_to_image() { std::lock_guard _lock(s_render_mutex); diff --git a/src/node_stroke_preview.h b/src/node_stroke_preview.h index 3d46e2d..4a7a9b9 100644 --- a/src/node_stroke_preview.h +++ b/src/node_stroke_preview.h @@ -15,6 +15,8 @@ class NodeStrokePreview : public NodeBorder glm::vec4 m_mixer_rect; }; + using StrokeMainLivePassRequest = pp::panopainter::LegacyNodeStrokePreviewMainLivePassRequestT; + static RTT m_rtt; static RTT m_rtt_mixer; static Texture2D m_tex; // blending tmp texture @@ -51,6 +53,12 @@ public: // return rect {origin, size} glm::vec4 stroke_draw_samples(std::array& P, Texture2D& blend_tex, bool copy_stroke_destination); std::vector stroke_draw_compute(Stroke& stroke, float zoom) const; + StrokeMainLivePassRequest make_stroke_draw_immediate_main_live_pass_request( + const Brush& brush, + const pp::panopainter::LegacyNodeStrokePreviewPassOrchestrationPlan& pass_orchestration, + bool copy_stroke_destination, + float zoom, + const glm::vec2& size); void draw_stroke(); void draw_stroke_immediate(); Image render_to_image();