From 39cc62f41f4d3505c500b8dfe99eda9f67fb104f Mon Sep 17 00:00:00 2001 From: omigamedev Date: Sat, 13 Jun 2026 10:13:53 +0200 Subject: [PATCH] Extract stroke preview final composite helper --- docs/modernization/debt.md | 4 + docs/modernization/roadmap.md | 4 + src/node_stroke_preview.cpp | 133 ++++++++++++++++++++++------------ 3 files changed, 94 insertions(+), 47 deletions(-) diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index fad6012..8d596b6 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -18,6 +18,10 @@ agent or engineer to remove them without reconstructing context from chat. ## Recent Reductions +- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview` final + composite sampler/input binding and slot intent now route through one local + preview helper; mixer execution, per-sample stroke callbacks, framebuffer + copies, and final OpenGL draw ownership remain retained in the preview node. - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw` pad-pass destination bind/copy/unbind ordering now routes through `legacy_canvas_stroke_execution_services.h`; shader setup, pad color diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 5afb4c1..ec38b4c 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -3097,6 +3097,10 @@ Results: shares the retained stroke execution helper callback surface, while shader setup, pad color selection, framebuffer ownership, and final OpenGL draw remain in the legacy Canvas path. +- `NodeStrokePreview` final composite sampler/input binding and texture-slot + intent now share one local retained helper, while mixer execution, + per-sample stroke callbacks, framebuffer copies, and final OpenGL draw + ownership remain in the preview node. - `Canvas::stroke_draw` pad-region planning now shares the retained stroke execution helper wrapping `pp_paint_renderer`, while pad color selection, dirty-face iteration, framebuffer copies, quad upload, and draw execution diff --git a/src/node_stroke_preview.cpp b/src/node_stroke_preview.cpp index c399602..3996014 100644 --- a/src/node_stroke_preview.cpp +++ b/src/node_stroke_preview.cpp @@ -96,6 +96,78 @@ void apply_stroke_preview_capability(std::uint32_t state, bool enabled) pp::legacy::ui_gl::set_capability(state, enabled, "NodeStrokePreview"); } +namespace stroke_preview_composite_slots { +constexpr std::uint32_t kBackground = 0U; +constexpr std::uint32_t kStroke = 1U; +constexpr std::uint32_t kDual = 3U; +constexpr std::uint32_t kPattern = 4U; +} + +struct StrokePreviewCompositePassInputs { + glm::vec2 resolution; + glm::vec2 pattern_scale; + const Brush& brush; + const pp::paint_renderer::CanvasStrokeCompositePassPlan& composite_pass; + Texture2D& background_texture; + Texture2D& stroke_texture; + Texture2D& dual_texture; + Sampler& linear_sampler; + Sampler& repeat_sampler; + std::function draw_composite; +}; + +void execute_stroke_preview_final_composite_pass(const StrokePreviewCompositePassInputs& inputs) +{ + pp::panopainter::execute_legacy_stroke_preview_final_composite( + [&] { + pp::panopainter::setup_legacy_stroke_composite_shader( + pp::panopainter::LegacyStrokeCompositeUniforms { + .resolution = inputs.resolution, + .pattern = { + .scale = inputs.pattern_scale, + .invert = static_cast(inputs.brush.m_pattern_invert), + .brightness = inputs.brush.m_pattern_brightness, + .contrast = inputs.brush.m_pattern_contrast, + .depth = inputs.brush.m_pattern_depth, + .blend_mode = inputs.composite_pass.pattern_blend_mode, + .offset = glm::vec2(inputs.brush.m_pattern_rand_offset ? 0.5f : 0.0f), + }, + .mvp = glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f), + .layer_alpha = 1.0f, + .alpha_lock = false, + .mask_enabled = false, + .use_fragcoord = false, + .blend_mode = inputs.brush.m_blend_mode, + .use_dual = inputs.composite_pass.use_dual, + .dual_blend_mode = inputs.composite_pass.dual_blend_mode, + .dual_alpha = inputs.composite_pass.dual_alpha, + .use_pattern = inputs.composite_pass.use_pattern, + }); + }, + [&] { + inputs.linear_sampler.bind(stroke_preview_composite_slots::kBackground); + inputs.linear_sampler.bind(stroke_preview_composite_slots::kStroke); + inputs.linear_sampler.bind(2U); + inputs.linear_sampler.bind(stroke_preview_composite_slots::kDual); + inputs.repeat_sampler.bind(stroke_preview_composite_slots::kPattern); + }, + [&] { + set_active_texture_unit(stroke_preview_composite_slots::kBackground); + inputs.background_texture.bind(); + set_active_texture_unit(stroke_preview_composite_slots::kStroke); + inputs.stroke_texture.bind(); + set_active_texture_unit(stroke_preview_composite_slots::kDual); + inputs.dual_texture.bind(); + set_active_texture_unit(stroke_preview_composite_slots::kPattern); + inputs.brush.m_pattern_texture ? + inputs.brush.m_pattern_texture->bind() : + unbind_texture_2d(); + }, + [&] { + inputs.draw_composite(); + }); +} + template void execute_stroke_preview_frames( Frames& frames, @@ -585,53 +657,20 @@ void NodeStrokePreview::draw_stroke_immediate() // COMPOSITE - pp::panopainter::execute_legacy_stroke_preview_final_composite( - [&] { - pp::panopainter::setup_legacy_stroke_composite_shader( - pp::panopainter::LegacyStrokeCompositeUniforms { - .resolution = size, - .pattern = { - .scale = patt_scale, - .invert = static_cast(b->m_pattern_invert), - .brightness = b->m_pattern_brightness, - .contrast = b->m_pattern_contrast, - .depth = b->m_pattern_depth, - .blend_mode = material.composite_pass.pattern_blend_mode, - .offset = glm::vec2(b->m_pattern_rand_offset ? 0.5f : 0.0f), - }, - .mvp = glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f), - .layer_alpha = 1.0f, - .alpha_lock = false, - .mask_enabled = false, - .use_fragcoord = false, - .blend_mode = b->m_blend_mode, - .use_dual = material.composite_pass.use_dual, - .dual_blend_mode = material.composite_pass.dual_blend_mode, - .dual_alpha = material.composite_pass.dual_alpha, - .use_pattern = material.composite_pass.use_pattern, - }); - }, - [&] { - m_sampler_linear.bind(0); - m_sampler_linear.bind(1); - m_sampler_linear.bind(2); - m_sampler_linear.bind(3); - m_sampler_linear_repeat.bind(4); - }, - [&] { - set_active_texture_unit(0U); - m_tex_background.bind(); - set_active_texture_unit(1U); - m_tex.bind(); - set_active_texture_unit(3U); - m_tex_dual.bind(); - set_active_texture_unit(4U); - b->m_pattern_texture ? - b->m_pattern_texture->bind() : - unbind_texture_2d(); - }, - [&] { - m_plane.draw_fill(); + execute_stroke_preview_final_composite_pass( + StrokePreviewCompositePassInputs { + .resolution = size, + .pattern_scale = patt_scale, + .brush = *b, + .composite_pass = material.composite_pass, + .background_texture = m_tex_background, + .stroke_texture = m_tex, + .dual_texture = m_tex_dual, + .linear_sampler = m_sampler_linear, + .repeat_sampler = m_sampler_linear_repeat, + .draw_composite = [&] { + m_plane.draw_fill(); + }, }); // copy the result to the actual preview