Extract draw merge temporary branch helper

This commit is contained in:
2026-06-13 19:01:01 +02:00
parent 1a5d828d5c
commit d441e5e2bc
4 changed files with 136 additions and 120 deletions

View File

@@ -80,6 +80,11 @@ agent or engineer to remove them without reconstructing context from chat.
composite setup now routes through `execute_canvas_draw_merge_temporary_composite(...)`; composite setup now routes through `execute_canvas_draw_merge_temporary_composite(...)`;
setup, sampler, texture, draw, and unbind callbacks still remain retained in setup, sampler, texture, draw, and unbind callbacks still remain retained in
the legacy Canvas path. the legacy Canvas path.
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge()` temporary
erase and paint branch wiring now routes through
`execute_legacy_canvas_draw_merge_temporary_composite(...)`; the retained
path still owns the concrete setup, sampler, texture, draw, and unbind
callbacks.
- 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 retained preview feedback/material/composite planning plus stroke now routes retained preview feedback/material/composite planning plus stroke
shader uniform assembly through shader uniform assembly through

View File

@@ -660,6 +660,11 @@ Progress Notes:
path still owns the concrete setup, sampler, texture, draw, and unbind path still owns the concrete setup, sampler, texture, draw, and unbind
callbacks. Next slice should target another narrow draw-merge seam without callbacks. Next slice should target another narrow draw-merge seam without
reopening the landed temporary-composite helper. reopening the landed temporary-composite helper.
- 2026-06-13: `Canvas::draw_merge()` temporary erase and paint branch wiring
now routes through `execute_legacy_canvas_draw_merge_temporary_composite(...)`;
the retained path still owns the concrete setup, sampler, texture, draw, and
unbind callbacks. Next slice should target another narrow draw-merge seam
without reopening the landed temporary-composite helper.
- 2026-06-13: `pp_paint_renderer_stroke_execution_tests` now also covers - 2026-06-13: `pp_paint_renderer_stroke_execution_tests` now also covers
retained frame-plan assembly for previous-sample projection mode and zoom retained frame-plan assembly for previous-sample projection mode and zoom
scaling. Next slice should target the remaining preview/Canvas stroke scaling. Next slice should target the remaining preview/Canvas stroke

View File

@@ -480,22 +480,6 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
gl.restore(); gl.restore();
} }
template <typename Setup, typename BindSamplers, typename BindTextures, typename Draw, typename UnbindTextures>
static void execute_canvas_draw_merge_temporary_composite(
Setup&& setup,
BindSamplers&& bind_samplers,
BindTextures&& bind_textures,
Draw&& draw,
UnbindTextures&& unbind_textures)
{
pp::panopainter::execute_legacy_canvas_stroke_temporary_composite(
std::forward<Setup>(setup),
std::forward<BindSamplers>(bind_samplers),
std::forward<BindTextures>(bind_textures),
std::forward<Draw>(draw),
std::forward<UnbindTextures>(unbind_textures));
}
std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vertex_t, 4>& B, bool project_3d /*= false*/, glm::mat4 mv /*= glm::mat4(1)*/) const std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vertex_t, 4>& B, bool project_3d /*= false*/, glm::mat4 mv /*= glm::mat4(1)*/) const
{ {
// intersect P with the current face to clip diverging points from the plane // intersect P with the current face to clip diverging points from the plane
@@ -1445,119 +1429,123 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
m_merge_rtt.clear(); m_merge_rtt.clear();
} }
pp::panopainter::execute_legacy_canvas_draw_merge_layer_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_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, m_current_stroke && m_show_tmp && m_current_layer_idx == layer_index,
use_blend, use_blend,
pp::panopainter::LegacyCanvasDrawMergeLayerCompositeExecution { pp::panopainter::LegacyCanvasDrawMergeLayerCompositeExecution {
.execute_temporary_erase = [&] { .execute_temporary_erase = [&] {
execute_canvas_draw_merge_temporary_composite( pp::panopainter::execute_legacy_canvas_draw_merge_temporary_composite(
[&] { pp::panopainter::LegacyCanvasDrawMergeTemporaryCompositeExecution {
//ShaderManager::u_vec2(kShaderUniform::Resolution, zw(m_box) / zoom); .setup = [&] {
//ShaderManager::u_int(kShaderUniform::Lock, m_layers[layer_index]->m_alpha_locked); //ShaderManager::u_vec2(kShaderUniform::Resolution, zw(m_box) / zoom);
pp::panopainter::setup_legacy_stroke_erase_shader( //ShaderManager::u_int(kShaderUniform::Lock, m_layers[layer_index]->m_alpha_locked);
pp::panopainter::LegacyStrokeEraseUniforms { pp::panopainter::setup_legacy_stroke_erase_shader(
.mvp = ortho, pp::panopainter::LegacyStrokeEraseUniforms {
.texture_slot = 0, .mvp = ortho,
.stroke_texture_slot = 1, .texture_slot = 0,
.mask_texture_slot = 2, .stroke_texture_slot = 1,
.alpha = m_layers[layer_index]->m_opacity, .mask_texture_slot = 2,
.mask_enabled = m_smask_active, .alpha = m_layers[layer_index]->m_opacity,
}); .mask_enabled = m_smask_active,
}, });
[&] { },
m_sampler.bind(0); .bind_samplers = [&] {
m_sampler.bind(1); m_sampler.bind(0);
m_sampler.bind(2); m_sampler.bind(1);
}, m_sampler.bind(2);
[&] { },
set_active_texture_unit(0); .bind_textures = [&] {
m_layers[layer_index]->rtt(plane_index).bindTexture(); set_active_texture_unit(0);
set_active_texture_unit(1); m_layers[layer_index]->rtt(plane_index).bindTexture();
m_tmp[plane_index].bindTexture(); set_active_texture_unit(1);
set_active_texture_unit(2); m_tmp[plane_index].bindTexture();
m_smask.rtt(plane_index).bindTexture(); set_active_texture_unit(2);
}, m_smask.rtt(plane_index).bindTexture();
[&] { },
m_plane.draw_fill(); .draw = [&] {
}, m_plane.draw_fill();
[&] { },
m_smask.rtt(plane_index).unbindTexture(); .unbind_textures = [&] {
set_active_texture_unit(1); m_smask.rtt(plane_index).unbindTexture();
m_tmp[plane_index].unbindTexture(); set_active_texture_unit(1);
set_active_texture_unit(0); m_tmp[plane_index].unbindTexture();
m_layers[layer_index]->rtt(plane_index).unbindTexture(); set_active_texture_unit(0);
}); m_layers[layer_index]->rtt(plane_index).unbindTexture();
}, },
});
},
.execute_temporary_paint = [&] { .execute_temporary_paint = [&] {
const auto stroke_material = canvas_stroke_material_plan(*b, false); const auto stroke_material = canvas_stroke_material_plan(*b, false);
glm::vec2 patt_scale = glm::vec2(b->m_pattern_scale); glm::vec2 patt_scale = glm::vec2(b->m_pattern_scale);
if (b->m_pattern_flipx) patt_scale.x *= -1.f; if (b->m_pattern_flipx) patt_scale.x *= -1.f;
if (b->m_pattern_flipy) patt_scale.y *= -1.f; if (b->m_pattern_flipy) patt_scale.y *= -1.f;
execute_canvas_draw_merge_temporary_composite( pp::panopainter::execute_legacy_canvas_draw_merge_temporary_composite(
[&] { pp::panopainter::LegacyCanvasDrawMergeTemporaryCompositeExecution {
pp::panopainter::setup_legacy_stroke_composite_shader( .setup = [&] {
pp::panopainter::LegacyStrokeCompositeUniforms { pp::panopainter::setup_legacy_stroke_composite_shader(
.resolution = Canvas::I->m_size, pp::panopainter::LegacyStrokeCompositeUniforms {
.pattern = { .resolution = Canvas::I->m_size,
.scale = patt_scale, .pattern = {
.invert = static_cast<float>(b->m_pattern_invert), .scale = patt_scale,
.brightness = b->m_pattern_brightness, .invert = static_cast<float>(b->m_pattern_invert),
.contrast = b->m_pattern_contrast, .brightness = b->m_pattern_brightness,
.depth = b->m_pattern_depth, .contrast = b->m_pattern_contrast,
.blend_mode = b->m_pattern_blend_mode, .depth = b->m_pattern_depth,
.offset = Canvas::I->m_pattern_offset, .blend_mode = b->m_pattern_blend_mode,
.offset = Canvas::I->m_pattern_offset,
},
.mvp = ortho,
.layer_alpha = m_layers[layer_index]->m_opacity,
.alpha_lock = m_layers[layer_index]->m_alpha_locked,
.mask_enabled = m_smask_active,
.use_fragcoord = false,
.blend_mode = b->m_blend_mode,
.use_dual = stroke_material.composite_pass.use_dual,
.dual_blend_mode = stroke_material.composite_pass.dual_blend_mode,
.dual_alpha = stroke_material.composite_pass.dual_alpha,
.use_pattern = stroke_material.composite_pass.use_pattern,
});
},
.bind_samplers = [&] {
m_sampler.bind(0);
m_sampler.bind(1);
m_sampler.bind(2);
m_sampler.bind(3);
m_sampler_stencil.bind(4);
},
.bind_textures = [&] {
set_active_texture_unit(0);
m_layers[layer_index]->rtt(plane_index).bindTexture();
set_active_texture_unit(1);
m_tmp[plane_index].bindTexture();
set_active_texture_unit(2);
m_smask.rtt(plane_index).bindTexture();
set_active_texture_unit(3);
if (stroke_material.composite_pass.use_dual)
m_tmp_dual[plane_index].bindTexture();
set_active_texture_unit(4);
b->m_pattern_texture ?
b->m_pattern_texture->bind() :
unbind_texture_2d();
},
.draw = [&] {
m_plane.draw_fill();
},
.unbind_textures = [&] {
set_active_texture_unit(3);
if (stroke_material.composite_pass.use_dual)
m_tmp_dual[plane_index].unbindTexture();
set_active_texture_unit(2);
m_smask.rtt(plane_index).unbindTexture();
set_active_texture_unit(1);
m_tmp[plane_index].unbindTexture();
set_active_texture_unit(0);
m_layers[layer_index]->rtt(plane_index).unbindTexture();
}, },
.mvp = ortho,
.layer_alpha = m_layers[layer_index]->m_opacity,
.alpha_lock = m_layers[layer_index]->m_alpha_locked,
.mask_enabled = m_smask_active,
.use_fragcoord = false,
.blend_mode = b->m_blend_mode,
.use_dual = stroke_material.composite_pass.use_dual,
.dual_blend_mode = stroke_material.composite_pass.dual_blend_mode,
.dual_alpha = stroke_material.composite_pass.dual_alpha,
.use_pattern = stroke_material.composite_pass.use_pattern,
}); });
}, },
[&] {
m_sampler.bind(0);
m_sampler.bind(1);
m_sampler.bind(2);
m_sampler.bind(3);
m_sampler_stencil.bind(4);
},
[&] {
set_active_texture_unit(0);
m_layers[layer_index]->rtt(plane_index).bindTexture();
set_active_texture_unit(1);
m_tmp[plane_index].bindTexture();
set_active_texture_unit(2);
m_smask.rtt(plane_index).bindTexture();
set_active_texture_unit(3);
if (stroke_material.composite_pass.use_dual)
m_tmp_dual[plane_index].bindTexture();
set_active_texture_unit(4);
b->m_pattern_texture ?
b->m_pattern_texture->bind() :
unbind_texture_2d();
},
[&] {
m_plane.draw_fill();
},
[&] {
set_active_texture_unit(3);
if (stroke_material.composite_pass.use_dual)
m_tmp_dual[plane_index].unbindTexture();
set_active_texture_unit(2);
m_smask.rtt(plane_index).unbindTexture();
set_active_texture_unit(1);
m_tmp[plane_index].unbindTexture();
set_active_texture_unit(0);
m_layers[layer_index]->rtt(plane_index).unbindTexture();
});
},
.execute_layer_texture = [&] { .execute_layer_texture = [&] {
pp::panopainter::execute_legacy_canvas_draw_merge_layer_texture( pp::panopainter::execute_legacy_canvas_draw_merge_layer_texture(
pp::panopainter::LegacyCanvasDrawMergeTextureAlphaUniforms { pp::panopainter::LegacyCanvasDrawMergeTextureAlphaUniforms {

View File

@@ -94,6 +94,14 @@ struct LegacyCanvasDrawMergeLayerCompositeExecution {
std::function<void()> execute_layer_blend; std::function<void()> execute_layer_blend;
}; };
struct LegacyCanvasDrawMergeTemporaryCompositeExecution {
std::function<void()> setup;
std::function<void()> bind_samplers;
std::function<void()> bind_textures;
std::function<void()> draw;
std::function<void()> unbind_textures;
};
struct LegacyCanvasDrawMergePlaneSetupUniforms { struct LegacyCanvasDrawMergePlaneSetupUniforms {
LegacyCanvasDrawMergeCheckerboardUniforms checkerboard; LegacyCanvasDrawMergeCheckerboardUniforms checkerboard;
bool use_blend = false; bool use_blend = false;
@@ -330,6 +338,16 @@ inline void execute_legacy_canvas_draw_merge_layer_composite(
} }
} }
inline void execute_legacy_canvas_draw_merge_temporary_composite(
const LegacyCanvasDrawMergeTemporaryCompositeExecution& execution)
{
execution.setup();
execution.bind_samplers();
execution.bind_textures();
execution.draw();
execution.unbind_textures();
}
inline void execute_legacy_canvas_draw_merge_plane_setup( inline void execute_legacy_canvas_draw_merge_plane_setup(
const LegacyCanvasDrawMergePlaneSetupUniforms& uniforms, const LegacyCanvasDrawMergePlaneSetupUniforms& uniforms,
const LegacyCanvasDrawMergePlaneSetupExecution& execution) const LegacyCanvasDrawMergePlaneSetupExecution& execution)