Extract stroke mix shell helper

This commit is contained in:
2026-06-13 19:40:16 +02:00
parent f53f943374
commit eb60c23e91
3 changed files with 43 additions and 16 deletions

View File

@@ -82,6 +82,10 @@ agent or engineer to remove them without reconstructing context from chat.
now calls the retained mix-pass executor directly instead of a local wrapper now calls the retained mix-pass executor directly instead of a local wrapper
shell helper; the live path still owns the concrete mixer framebuffer setup shell helper; the live path still owns the concrete mixer framebuffer setup
and GL capability toggles. and GL capability toggles.
- 2026-06-13: `LATER-003` was narrowed again. `Canvas::stroke_draw_mix()`
now routes the remaining mixer framebuffer/capability shell through a local
helper, leaving the call site with only mix-pass planning and helper
invocation.
- 2026-06-13: `DEBT-0036` was narrowed again. `NodeStrokePreview::draw_stroke_immediate()` - 2026-06-13: `DEBT-0036` was narrowed again. `NodeStrokePreview::draw_stroke_immediate()`
now routes final composite execution and preview copy-back through a retained now routes final composite execution and preview copy-back through a retained
local wrapper, leaving the call site with only sequence wiring. local wrapper, leaving the call site with only sequence wiring.

View File

@@ -626,6 +626,9 @@ Progress Notes:
- 2026-06-13: `Canvas::stroke_draw_mix()` now calls the retained mix-pass - 2026-06-13: `Canvas::stroke_draw_mix()` now calls the retained mix-pass
executor directly instead of a local wrapper shell helper; the live path executor directly instead of a local wrapper shell helper; the live path
still owns the concrete mixer framebuffer setup and GL capability toggles. still owns the concrete mixer framebuffer setup and GL capability toggles.
- 2026-06-13: `Canvas::stroke_draw_mix()` now routes the remaining mixer
framebuffer/capability shell through a local helper, leaving the call site
with only mix-pass planning and helper invocation.
- 2026-06-13: `Canvas::stroke_draw_samples()` now reuses a retained destination - 2026-06-13: `Canvas::stroke_draw_samples()` now reuses a retained destination
texture dispatch helper for the live sample path; `Canvas` still owns the texture dispatch helper for the live sample path; `Canvas` still owns the
concrete face textures and callback execution. concrete face textures and callback execution.

View File

@@ -386,43 +386,63 @@ void Canvas::stroke_cancel()
m_current_stroke = nullptr; m_current_stroke = nullptr;
m_show_tmp = false; m_show_tmp = false;
} }
void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz) static void execute_canvas_stroke_mix_pass(
Canvas& canvas,
const glm::vec2& bb_min,
const glm::vec2& bb_sz,
const std::array<glm::mat4, 6>& plane_transform,
const std::vector<std::shared_ptr<Layer>>& layers,
std::size_t layer_index,
const Stroke* current_stroke)
{ {
gl_state gl; auto& current_layer = *layers[layer_index];
gl.save();
const auto layer_index = m_current_layer_idx;
auto& current_layer = *m_layers[layer_index];
std::array<glm::mat4, 6> plane_transform {};
std::copy(std::begin(m_plane_transform), std::end(m_plane_transform), plane_transform.begin());
const auto mix_planes = pp::panopainter::plan_legacy_canvas_stroke_mix_pass_planes( const auto mix_planes = pp::panopainter::plan_legacy_canvas_stroke_mix_pass_planes(
current_layer.m_visible, current_layer.m_visible,
current_layer.m_opacity, current_layer.m_opacity,
glm::scale(glm::vec3(1, -1, 1)) * m_proj * m_mv, glm::scale(glm::vec3(1, -1, 1)) * canvas.m_proj * canvas.m_mv,
plane_transform, plane_transform,
[&](int plane_index) { [&](int plane_index) {
return current_layer.face(plane_index); return current_layer.face(plane_index);
}); });
const auto& b = m_current_stroke->m_brush; const auto& b = current_stroke->m_brush;
const auto mix_shell = pp::panopainter::make_legacy_canvas_stroke_mix_pass_shell( const auto mix_shell = pp::panopainter::make_legacy_canvas_stroke_mix_pass_shell(
[&] { [&] {
m_mixer.bindFramebuffer(); canvas.m_mixer.bindFramebuffer();
apply_canvas_viewport(0, 0, m_mixer.getWidth(), m_mixer.getHeight()); canvas.apply_canvas_viewport(0, 0, canvas.m_mixer.getWidth(), canvas.m_mixer.getHeight());
apply_canvas_capability(depth_test_state(), false); canvas.apply_canvas_capability(canvas.depth_test_state(), false);
apply_canvas_capability(scissor_test_state(), true); canvas.apply_canvas_capability(canvas.scissor_test_state(), true);
apply_canvas_capability(blend_state(), false); canvas.apply_canvas_capability(canvas.blend_state(), false);
apply_canvas_scissor( canvas.apply_canvas_scissor(
static_cast<std::int32_t>(bb_min.x), static_cast<std::int32_t>(bb_min.x),
static_cast<std::int32_t>(bb_min.y), static_cast<std::int32_t>(bb_min.y),
static_cast<std::int32_t>(bb_sz.x), static_cast<std::int32_t>(bb_sz.x),
static_cast<std::int32_t>(bb_sz.y)); static_cast<std::int32_t>(bb_sz.y));
}, },
[&] { [&] {
m_mixer.unbindFramebuffer(); canvas.m_mixer.unbindFramebuffer();
}); });
[[maybe_unused]] const auto mix_result = pp::panopainter::execute_legacy_canvas_stroke_mix_pass_shell( [[maybe_unused]] const auto mix_result = pp::panopainter::execute_legacy_canvas_stroke_mix_pass_shell(
mix_shell.setup.begin, mix_shell.setup.begin,
mix_shell.setup.end, mix_shell.setup.end,
mix_shell.request); mix_shell.request);
(void)mix_planes;
(void)b;
}
void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
{
gl_state gl;
gl.save();
std::array<glm::mat4, 6> plane_transform {};
std::copy(std::begin(m_plane_transform), std::end(m_plane_transform), plane_transform.begin());
execute_canvas_stroke_mix_pass(
*this,
bb_min,
bb_sz,
plane_transform,
m_layers,
m_current_layer_idx,
m_current_stroke);
gl.restore(); gl.restore();
} }