Extract draw merge temporary paint branch

This commit is contained in:
2026-06-13 22:51:11 +02:00
parent c118b92b86
commit 037be1a72a
4 changed files with 114 additions and 63 deletions

View File

@@ -198,6 +198,11 @@ agent or engineer to remove them without reconstructing context from chat.
`make_legacy_canvas_draw_merge_temporary_erase_composite(...)`; the live `make_legacy_canvas_draw_merge_temporary_erase_composite(...)`; the live
path still owns the concrete layer RTT, mixer RTT, sampler, and plane path still owns the concrete layer RTT, mixer RTT, sampler, and plane
callbacks. callbacks.
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge()` temporary
paint branch execution now routes through
`make_legacy_canvas_draw_merge_temporary_paint_composite(...)`; the live
path still owns the concrete layer RTT, mixer RTT, sampler, and plane
callbacks.
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge()` now routes - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge()` now routes
the layer-composite shell through a local wrapper around the layer-composite shell through a local wrapper around
`execute_legacy_canvas_draw_merge_layer_composite(...)`; the final branch `execute_legacy_canvas_draw_merge_layer_composite(...)`; the final branch

View File

@@ -1485,70 +1485,69 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
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;
pp::panopainter::execute_legacy_canvas_draw_merge_temporary_composite( const auto execution = pp::panopainter::make_legacy_canvas_draw_merge_temporary_paint_composite(
pp::panopainter::LegacyCanvasDrawMergeTemporaryCompositeExecution { [&] {
.setup = [&] { pp::panopainter::setup_legacy_stroke_composite_shader(
pp::panopainter::setup_legacy_stroke_composite_shader( pp::panopainter::LegacyStrokeCompositeUniforms {
pp::panopainter::LegacyStrokeCompositeUniforms { .resolution = Canvas::I->m_size,
.resolution = Canvas::I->m_size, .pattern = {
.pattern = { .scale = patt_scale,
.scale = patt_scale, .invert = static_cast<float>(b->m_pattern_invert),
.invert = static_cast<float>(b->m_pattern_invert), .brightness = b->m_pattern_brightness,
.brightness = b->m_pattern_brightness, .contrast = b->m_pattern_contrast,
.contrast = b->m_pattern_contrast, .depth = b->m_pattern_depth,
.depth = b->m_pattern_depth, .blend_mode = b->m_pattern_blend_mode,
.blend_mode = b->m_pattern_blend_mode, .offset = Canvas::I->m_pattern_offset,
.offset = Canvas::I->m_pattern_offset, },
}, .mvp = ortho,
.mvp = ortho, .layer_alpha = m_layers[layer_index]->m_opacity,
.layer_alpha = m_layers[layer_index]->m_opacity, .alpha_lock = m_layers[layer_index]->m_alpha_locked,
.alpha_lock = m_layers[layer_index]->m_alpha_locked, .mask_enabled = m_smask_active,
.mask_enabled = m_smask_active, .use_fragcoord = false,
.use_fragcoord = false, .blend_mode = b->m_blend_mode,
.blend_mode = b->m_blend_mode, .use_dual = stroke_material.composite_pass.use_dual,
.use_dual = stroke_material.composite_pass.use_dual, .dual_blend_mode = stroke_material.composite_pass.dual_blend_mode,
.dual_blend_mode = stroke_material.composite_pass.dual_blend_mode, .dual_alpha = stroke_material.composite_pass.dual_alpha,
.dual_alpha = stroke_material.composite_pass.dual_alpha, .use_pattern = stroke_material.composite_pass.use_pattern,
.use_pattern = stroke_material.composite_pass.use_pattern, });
}); },
}, [&] {
.bind_samplers = [&] { m_sampler.bind(0);
m_sampler.bind(0); m_sampler.bind(1);
m_sampler.bind(1); m_sampler.bind(2);
m_sampler.bind(2); m_sampler.bind(3);
m_sampler.bind(3); m_sampler_stencil.bind(4);
m_sampler_stencil.bind(4); },
}, [&] {
.bind_textures = [&] { set_active_texture_unit(0);
set_active_texture_unit(0); m_layers[layer_index]->rtt(plane_index).bindTexture();
m_layers[layer_index]->rtt(plane_index).bindTexture(); set_active_texture_unit(1);
set_active_texture_unit(1); m_tmp[plane_index].bindTexture();
m_tmp[plane_index].bindTexture(); set_active_texture_unit(2);
set_active_texture_unit(2); m_smask.rtt(plane_index).bindTexture();
m_smask.rtt(plane_index).bindTexture(); set_active_texture_unit(3);
set_active_texture_unit(3); if (stroke_material.composite_pass.use_dual)
if (stroke_material.composite_pass.use_dual) m_tmp_dual[plane_index].bindTexture();
m_tmp_dual[plane_index].bindTexture(); set_active_texture_unit(4);
set_active_texture_unit(4); b->m_pattern_texture ?
b->m_pattern_texture ? b->m_pattern_texture->bind() :
b->m_pattern_texture->bind() : unbind_texture_2d();
unbind_texture_2d(); },
}, [&] {
.draw = [&] { m_plane.draw_fill();
m_plane.draw_fill(); },
}, [&] {
.unbind_textures = [&] { set_active_texture_unit(3);
set_active_texture_unit(3); if (stroke_material.composite_pass.use_dual)
if (stroke_material.composite_pass.use_dual) m_tmp_dual[plane_index].unbindTexture();
m_tmp_dual[plane_index].unbindTexture(); set_active_texture_unit(2);
set_active_texture_unit(2); m_smask.rtt(plane_index).unbindTexture();
m_smask.rtt(plane_index).unbindTexture(); set_active_texture_unit(1);
set_active_texture_unit(1); m_tmp[plane_index].unbindTexture();
m_tmp[plane_index].unbindTexture(); set_active_texture_unit(0);
set_active_texture_unit(0); m_layers[layer_index]->rtt(plane_index).unbindTexture();
m_layers[layer_index]->rtt(plane_index).unbindTexture();
},
}); });
pp::panopainter::execute_legacy_canvas_draw_merge_temporary_composite(execution);
}, },
.execute_layer_texture = [&] { .execute_layer_texture = [&] {
execute_canvas_draw_merge_layer_texture( execute_canvas_draw_merge_layer_texture(

View File

@@ -124,6 +124,28 @@ template <
}; };
} }
template <
typename Setup,
typename BindSamplers,
typename BindTextures,
typename Draw,
typename UnbindTextures>
[[nodiscard]] inline LegacyCanvasDrawMergeTemporaryCompositeExecution make_legacy_canvas_draw_merge_temporary_paint_composite(
Setup&& setup,
BindSamplers&& bind_samplers,
BindTextures&& bind_textures,
Draw&& draw,
UnbindTextures&& unbind_textures)
{
return LegacyCanvasDrawMergeTemporaryCompositeExecution {
.setup = std::forward<Setup>(setup),
.bind_samplers = std::forward<BindSamplers>(bind_samplers),
.bind_textures = std::forward<BindTextures>(bind_textures),
.draw = std::forward<Draw>(draw),
.unbind_textures = std::forward<UnbindTextures>(unbind_textures),
};
}
struct LegacyCanvasDrawMergePlaneSetupUniforms { struct LegacyCanvasDrawMergePlaneSetupUniforms {
LegacyCanvasDrawMergeCheckerboardUniforms checkerboard; LegacyCanvasDrawMergeCheckerboardUniforms checkerboard;
bool use_blend = false; bool use_blend = false;

View File

@@ -3194,6 +3194,28 @@ void legacy_canvas_draw_merge_temporary_erase_helper_preserves_order(pp::tests::
PP_EXPECT(h, order == expected); PP_EXPECT(h, order == expected);
} }
void legacy_canvas_draw_merge_temporary_paint_helper_preserves_order(pp::tests::Harness& h)
{
std::vector<std::string> order;
const auto execution = pp::panopainter::make_legacy_canvas_draw_merge_temporary_paint_composite(
[&] { order.emplace_back("setup"); },
[&] { order.emplace_back("bind_samplers"); },
[&] { order.emplace_back("bind_textures"); },
[&] { order.emplace_back("draw"); },
[&] { order.emplace_back("unbind_textures"); });
pp::panopainter::execute_legacy_canvas_draw_merge_temporary_composite(execution);
const std::vector<std::string> expected {
"setup",
"bind_samplers",
"bind_textures",
"draw",
"unbind_textures",
};
PP_EXPECT(h, order == expected);
}
void plans_canvas_stroke_feedback_paths(pp::tests::Harness& h) void plans_canvas_stroke_feedback_paths(pp::tests::Harness& h)
{ {
const Extent2D extent { .width = 32, .height = 16 }; const Extent2D extent { .width = 32, .height = 16 };
@@ -3557,6 +3579,9 @@ int main()
harness.run( harness.run(
"legacy_canvas_draw_merge_temporary_erase_helper_preserves_order", "legacy_canvas_draw_merge_temporary_erase_helper_preserves_order",
legacy_canvas_draw_merge_temporary_erase_helper_preserves_order); legacy_canvas_draw_merge_temporary_erase_helper_preserves_order);
harness.run(
"legacy_canvas_draw_merge_temporary_paint_helper_preserves_order",
legacy_canvas_draw_merge_temporary_paint_helper_preserves_order);
harness.run("plans_canvas_stroke_feedback_paths", plans_canvas_stroke_feedback_paths); harness.run("plans_canvas_stroke_feedback_paths", plans_canvas_stroke_feedback_paths);
harness.run("canvas_stroke_feedback_preserves_legacy_fallback", canvas_stroke_feedback_preserves_legacy_fallback); harness.run("canvas_stroke_feedback_preserves_legacy_fallback", canvas_stroke_feedback_preserves_legacy_fallback);
harness.run("plans_canvas_stroke_rasterization_boundary", plans_canvas_stroke_rasterization_boundary); harness.run("plans_canvas_stroke_rasterization_boundary", plans_canvas_stroke_rasterization_boundary);