Extract Canvas draw_merge layer blend helper

This commit is contained in:
2026-06-13 11:26:48 +02:00
parent 51458ad0e7
commit 499747173b
5 changed files with 102 additions and 40 deletions

View File

@@ -18,6 +18,13 @@ agent or engineer to remove them without reconstructing context from chat.
## Recent Reductions ## Recent Reductions
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge()` per-layer
blend composite now routes merge-RTT unbind, shader setup, optional
destination-copy feedback, draw, and cleanup ordering through
`execute_legacy_canvas_draw_merge_layer_blend(...)`; layer iteration,
temporary-stroke branch selection, framebuffer copies, sampler/texture
object callbacks, and final merged-plane ownership remain retained in
`Canvas`.
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge()` erase live - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::draw_merge()` erase live
temporary-stroke composite now routes retained setup, sampler bind, texture temporary-stroke composite now routes retained setup, sampler bind, texture
bind, draw, and texture unbind ordering through bind, draw, and texture unbind ordering through

View File

@@ -3145,6 +3145,11 @@ Results:
`execute_legacy_canvas_stroke_temporary_composite(...)`, leaving only the `execute_legacy_canvas_stroke_temporary_composite(...)`, leaving only the
concrete GL object callbacks and broader final composite ownership in the concrete GL object callbacks and broader final composite ownership in the
legacy Canvas path. legacy Canvas path.
- `Canvas::draw_merge()` per-layer blend composite now routes merge-RTT
unbind, shader setup, optional destination-copy feedback, draw, and cleanup
ordering through `execute_legacy_canvas_draw_merge_layer_blend(...)`, while
temporary-stroke branch selection, framebuffer copies, and final merged-plane
ownership remain in the legacy Canvas path.
- `NodeStrokePreview::draw_stroke_immediate()` now shares - `NodeStrokePreview::draw_stroke_immediate()` now shares
`execute_legacy_node_stroke_preview_pass_sequence(...)` for `execute_legacy_node_stroke_preview_pass_sequence(...)` for
dual-pass/background/main-pass/final-composite/copy-back ordering, while the dual-pass/background/main-pass/final-composite/copy-back ordering, while the

View File

@@ -509,6 +509,15 @@ Done Checks:
Progress Notes: Progress Notes:
- 2026-06-13: `Canvas::draw_merge()` per-layer blend composite now routes
merge-RTT unbind, shader setup, optional destination-copy feedback, draw,
and cleanup ordering through
`execute_legacy_canvas_draw_merge_layer_blend(...)`; temporary-stroke
branch selection, layer iteration, and final merged-plane redraw ownership
remain local to `Canvas`. Next slice should target the remaining end-of-plane
merged-texture copy/grid/final-redraw seam or another similarly narrow final
composite boundary without reopening landed temporary-composite or
per-layer blend helpers.
- 2026-06-13: `Canvas::draw_merge()` erase live temporary-stroke composite now - 2026-06-13: `Canvas::draw_merge()` erase live temporary-stroke composite now
routes retained setup, sampler bind, texture bind, draw, and texture unbind routes retained setup, sampler bind, texture bind, draw, and texture unbind
ordering through `execute_legacy_canvas_stroke_temporary_composite(...)`; ordering through `execute_legacy_canvas_stroke_temporary_composite(...)`;

View File

@@ -1535,47 +1535,49 @@ void Canvas::draw_merge(bool draw_checkerboard, std::array<bool, 6> faces /*= SI
if (use_blend) if (use_blend)
{ {
m_merge_rtt.unbindFramebuffer(); pp::panopainter::execute_legacy_canvas_draw_merge_layer_blend(
} pp::panopainter::LegacyCanvasDrawMergeLayerBlendUniforms {
.shader = {
// draw the blended .mvp = ortho,
if (use_blend) .texture_slot = 0,
{ .destination_texture_slot = 2,
m_sampler.bind(0); .use_destination_texture = copy_blend_destination,
m_sampler.bind(2); .blend_mode = m_layers[layer_index]->m_blend_mode,
.alpha = 1.f,
pp::panopainter::setup_legacy_canvas_draw_merge_texture_blend_shader( },
pp::panopainter::LegacyCanvasDrawMergeTextureBlendUniforms { .copy_destination = copy_blend_destination,
.mvp = ortho, },
.texture_slot = 0, pp::panopainter::LegacyCanvasDrawMergeLayerBlendExecution {
.destination_texture_slot = 2, .unbind_merge_framebuffer = [&] {
.use_destination_texture = copy_blend_destination, m_merge_rtt.unbindFramebuffer();
.blend_mode = m_layers[layer_index]->m_blend_mode, },
.alpha = 1.f, .bind_samplers = [&] {
m_sampler.bind(0);
m_sampler.bind(2);
},
.bind_merge_texture = [&] {
set_active_texture_unit(0);
m_merge_rtt.bindTexture();
},
.bind_destination_texture = [&] {
set_active_texture_unit(2);
m_merge_tex.bind();
},
.copy_destination_framebuffer = [&] {
copy_framebuffer_to_texture_2d(0, 0, 0, 0, m_width, m_height);
},
.draw = [&] {
m_plane.draw_fill();
},
.unbind_destination_texture = [&] {
set_active_texture_unit(2);
m_merge_tex.unbind();
},
.unbind_merge_texture = [&] {
set_active_texture_unit(0);
m_merge_rtt.unbindTexture();
},
}); });
if (copy_blend_destination)
{
m_sampler.bind(2);
}
set_active_texture_unit(0);
m_merge_rtt.bindTexture();
if (copy_blend_destination)
{
set_active_texture_unit(2);
m_merge_tex.bind();
copy_framebuffer_to_texture_2d(0, 0, 0, 0, m_width, m_height);
}
m_plane.draw_fill();
if (copy_blend_destination)
{
set_active_texture_unit(2);
m_merge_tex.unbind();
}
set_active_texture_unit(0);
m_merge_rtt.unbindTexture();
} }
} }

View File

@@ -64,6 +64,22 @@ struct LegacyCanvasDrawMergeShaderExecution {
std::function<void(kShaderUniform, const glm::mat4&)> set_mat4; std::function<void(kShaderUniform, const glm::mat4&)> set_mat4;
}; };
struct LegacyCanvasDrawMergeLayerBlendUniforms {
LegacyCanvasDrawMergeTextureBlendUniforms shader;
bool copy_destination = false;
};
struct LegacyCanvasDrawMergeLayerBlendExecution {
std::function<void()> unbind_merge_framebuffer;
std::function<void()> bind_samplers;
std::function<void()> bind_merge_texture;
std::function<void()> bind_destination_texture;
std::function<void()> copy_destination_framebuffer;
std::function<void()> draw;
std::function<void()> unbind_destination_texture;
std::function<void()> unbind_merge_texture;
};
[[nodiscard]] inline LegacyCanvasDrawMergeShaderExecution legacy_shader_manager_draw_merge_execution() noexcept [[nodiscard]] inline LegacyCanvasDrawMergeShaderExecution legacy_shader_manager_draw_merge_execution() noexcept
{ {
return { return {
@@ -218,4 +234,27 @@ inline void setup_legacy_canvas_draw_merge_texture_colorize_shader(
setup_legacy_canvas_draw_merge_texture_colorize_shader(uniforms, legacy_shader_manager_draw_merge_execution()); setup_legacy_canvas_draw_merge_texture_colorize_shader(uniforms, legacy_shader_manager_draw_merge_execution());
} }
inline void execute_legacy_canvas_draw_merge_layer_blend(
const LegacyCanvasDrawMergeLayerBlendUniforms& uniforms,
const LegacyCanvasDrawMergeLayerBlendExecution& execution)
{
execution.unbind_merge_framebuffer();
execution.bind_samplers();
setup_legacy_canvas_draw_merge_texture_blend_shader(uniforms.shader);
execution.bind_merge_texture();
if (uniforms.copy_destination) {
execution.bind_destination_texture();
execution.copy_destination_framebuffer();
}
execution.draw();
if (uniforms.copy_destination) {
execution.unbind_destination_texture();
}
execution.unbind_merge_texture();
}
} // namespace pp::panopainter } // namespace pp::panopainter