diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index ef014e7..15b120e 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -105,6 +105,9 @@ agent or engineer to remove them without reconstructing context from chat. - 2026-06-13: `DEBT-0036` was narrowed again. `Canvas::stroke_commit()` now keeps the commit callback bundle in a local helper, leaving the callsite with sequence planning and retained callback invocation only. +- 2026-06-13: `DEBT-0036` was narrowed again. `Canvas::stroke_commit()` + now routes the commit-input texture role switch through a local helper, + leaving the callsite with sequence planning plus retained callback wiring. - 2026-06-13: `DEBT-0036` was narrowed again. `NodeStrokePreview::draw_stroke_immediate()` now routes final composite execution and preview copy-back through a retained local wrapper, leaving the call site with only sequence wiring. diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index 26e070d..f0fd057 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -650,6 +650,9 @@ Progress Notes: - 2026-06-13: `Canvas::stroke_commit()` now keeps the commit callback bundle in a local helper, leaving the callsite with sequence planning and retained callback invocation only. +- 2026-06-13: `Canvas::stroke_commit()` now routes the commit-input texture + role switch through a local helper, so the callsite no longer owns that + inline texture binding bundle. - 2026-06-13: `Canvas::stroke_draw_samples()` now reuses a retained destination texture dispatch helper for the live sample path; `Canvas` still owns the concrete face textures and callback execution. diff --git a/src/canvas.cpp b/src/canvas.cpp index 383cad8..66c4407 100644 --- a/src/canvas.cpp +++ b/src/canvas.cpp @@ -542,6 +542,49 @@ static auto make_canvas_stroke_commit_callbacks( const pp::paint_renderer::CanvasStrokeCommitMaterialPlan& stroke_material) { const auto& b = current_stroke->m_brush; + auto bind_commit_inputs = [&](int i) { + pp::panopainter::bind_legacy_canvas_stroke_commit_inputs( + sequence, + [&](int texture_slot) { + set_active_texture_unit(texture_slot); + }, + [&](pp::paint_renderer::CanvasStrokeCommitTextureRole role) { + switch (role) { + case pp::paint_renderer::CanvasStrokeCommitTextureRole::layer_scratch: + canvas.m_tex2[i].bind(); + break; + case pp::paint_renderer::CanvasStrokeCommitTextureRole::stroke: + canvas.m_tmp[i].bindTexture(); + break; + case pp::paint_renderer::CanvasStrokeCommitTextureRole::selection_mask: + canvas.m_smask.rtt(i).bindTexture(); + break; + case pp::paint_renderer::CanvasStrokeCommitTextureRole::dual_stroke: + canvas.m_tmp_dual[i].bindTexture(); + break; + case pp::paint_renderer::CanvasStrokeCommitTextureRole::pattern: + b->m_pattern_texture ? b->m_pattern_texture->bind() : unbind_texture_2d(); + break; + } + }, + [&](pp::paint_renderer::CanvasStrokeCommitTextureRole role, int texture_slot) { + switch (role) { + case pp::paint_renderer::CanvasStrokeCommitTextureRole::layer_scratch: + canvas.m_sampler.bind(texture_slot); + break; + case pp::paint_renderer::CanvasStrokeCommitTextureRole::stroke: + canvas.m_sampler_nearest.bind(texture_slot); + break; + case pp::paint_renderer::CanvasStrokeCommitTextureRole::selection_mask: + case pp::paint_renderer::CanvasStrokeCommitTextureRole::dual_stroke: + canvas.m_sampler.bind(texture_slot); + break; + case pp::paint_renderer::CanvasStrokeCommitTextureRole::pattern: + canvas.m_sampler_stencil.bind(texture_slot); + break; + } + }); + }; return pp::panopainter::make_legacy_canvas_stroke_commit_callbacks( [&]() { canvas.m_dirty = false; @@ -604,47 +647,7 @@ static auto make_canvas_stroke_commit_callbacks( canvas.m_tex2[i].unbind(); }, [&](int i) { - pp::panopainter::bind_legacy_canvas_stroke_commit_inputs( - sequence, - [&](int texture_slot) { - set_active_texture_unit(texture_slot); - }, - [&](pp::paint_renderer::CanvasStrokeCommitTextureRole role) { - switch (role) { - case pp::paint_renderer::CanvasStrokeCommitTextureRole::layer_scratch: - canvas.m_tex2[i].bind(); - break; - case pp::paint_renderer::CanvasStrokeCommitTextureRole::stroke: - canvas.m_tmp[i].bindTexture(); - break; - case pp::paint_renderer::CanvasStrokeCommitTextureRole::selection_mask: - canvas.m_smask.rtt(i).bindTexture(); - break; - case pp::paint_renderer::CanvasStrokeCommitTextureRole::dual_stroke: - canvas.m_tmp_dual[i].bindTexture(); - break; - case pp::paint_renderer::CanvasStrokeCommitTextureRole::pattern: - b->m_pattern_texture ? b->m_pattern_texture->bind() : unbind_texture_2d(); - break; - } - }, - [&](pp::paint_renderer::CanvasStrokeCommitTextureRole role, int texture_slot) { - switch (role) { - case pp::paint_renderer::CanvasStrokeCommitTextureRole::layer_scratch: - canvas.m_sampler.bind(texture_slot); - break; - case pp::paint_renderer::CanvasStrokeCommitTextureRole::stroke: - canvas.m_sampler_nearest.bind(texture_slot); - break; - case pp::paint_renderer::CanvasStrokeCommitTextureRole::selection_mask: - case pp::paint_renderer::CanvasStrokeCommitTextureRole::dual_stroke: - canvas.m_sampler.bind(texture_slot); - break; - case pp::paint_renderer::CanvasStrokeCommitTextureRole::pattern: - canvas.m_sampler_stencil.bind(texture_slot); - break; - } - }); + bind_commit_inputs(i); }, [&](int) { pp::panopainter::execute_legacy_canvas_stroke_commit_erase(