Route stroke face sample ordering through helper

This commit is contained in:
2026-06-13 09:28:51 +02:00
parent 91f3b7f3dc
commit 5dc0bc7342
5 changed files with 57 additions and 16 deletions

View File

@@ -18,6 +18,10 @@ agent or engineer to remove them without reconstructing context from chat.
## Recent Reductions ## Recent Reductions
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw` current and
dual stroke per-face framebuffer/sample callback ordering now routes through
the retained stroke execution helper; framebuffer ownership, shader uniform
timing, sampler/texture binding, and live draw execution remain retained.
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw` current and - 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw` current and
dual stroke dirty-box mutation now routes through the retained stroke dual stroke dirty-box mutation now routes through the retained stroke
execution helper; framebuffer binding, shader uniform timing, sampler/texture execution helper; framebuffer binding, shader uniform timing, sampler/texture

View File

@@ -3104,6 +3104,10 @@ Results:
the retained stroke execution helper, while framebuffer binding, shader the retained stroke execution helper, while framebuffer binding, shader
uniform timing, sampler/texture binding, and live draw execution remain uniform timing, sampler/texture binding, and live draw execution remain
retained. retained.
- `Canvas::stroke_draw` current and dual stroke per-face framebuffer/sample
callback ordering now shares the retained stroke execution helper, while
framebuffer ownership, shader uniform timing, sampler/texture binding, and
live draw execution remain retained.
- Remaining simple color, hue, color-quad, grid heightmap, and pen/line - Remaining simple color, hue, color-quad, grid heightmap, and pen/line
preview shader setup in UI nodes and canvas modes now shares retained helper preview shader setup in UI nodes and canvas modes now shares retained helper
surfaces, while geometry, texture/sampler binding, blend/depth state, surfaces, while geometry, texture/sampler binding, blend/depth state,

View File

@@ -509,6 +509,13 @@ Done Checks:
Progress Notes: Progress Notes:
- 2026-06-13: `Canvas::stroke_draw` current and dual stroke per-face
framebuffer/sample callback ordering now routes through
`legacy_canvas_stroke_execution_services.h`; framebuffer ownership, shader
uniform timing, sampler/texture binding, and draw execution remain local to
Canvas. Next slice should target the remaining per-face retained state around
sample execution without reopening the new pad-pass, dirty-mutation, or
commit executors.
- 2026-06-13: `Canvas::stroke_draw` current and dual stroke dirty-box mutation - 2026-06-13: `Canvas::stroke_draw` current and dual stroke dirty-box mutation
now routes through `legacy_canvas_stroke_execution_services.h`; framebuffer now routes through `legacy_canvas_stroke_execution_services.h`; framebuffer
binding, shader uniform timing, sampler/texture binding, and draw execution binding, shader uniform timing, sampler/texture binding, and draw execution

View File

@@ -690,7 +690,7 @@ void Canvas::stroke_draw()
std::array<glm::vec4, 6> box_face = SIXPLETTE(glm::vec4(m_size, 0, 0)); std::array<glm::vec4, 6> box_face = SIXPLETTE(glm::vec4(m_size, 0, 0));
std::array<bool, 6> box_dirty = SIXPLETTE(false); std::array<bool, 6> box_dirty = SIXPLETTE(false);
glm::vec4 pad_color; glm::vec4 pad_color;
pp::panopainter::execute_legacy_canvas_stroke_frame_faces( pp::panopainter::execute_legacy_canvas_stroke_frame_samples(
frames, frames,
[&](auto& f) { [&](auto& f) {
if (brush->m_tip_mix > 0.f) if (brush->m_tip_mix > 0.f)
@@ -698,13 +698,13 @@ void Canvas::stroke_draw()
stroke_draw_mix(xy(f.m_mixer_rect), zw(f.m_mixer_rect)); stroke_draw_mix(xy(f.m_mixer_rect), zw(f.m_mixer_rect));
} }
}, },
[&](auto& f, int i, auto& P) { [&](auto&, int i, auto&) {
m_dirty_face[i] = true; m_dirty_face[i] = true;
merge_faces[i] = true; merge_faces[i] = true;
box_dirty[i] = true; box_dirty[i] = true;
m_tmp[i].bindFramebuffer(); m_tmp[i].bindFramebuffer();
},
[&](auto& f, int i, auto& P) {
pp::panopainter::use_legacy_stroke_shader(); pp::panopainter::use_legacy_stroke_shader();
pp::panopainter::apply_legacy_stroke_sample_uniforms( pp::panopainter::apply_legacy_stroke_sample_uniforms(
pp::panopainter::LegacyStrokeSampleUniforms { pp::panopainter::LegacyStrokeSampleUniforms {
@@ -712,11 +712,11 @@ void Canvas::stroke_draw()
.alpha = f.flow, .alpha = f.flow,
.opacity = f.opacity, .opacity = f.opacity,
}); });
auto box_sample = stroke_draw_samples(i, P, copy_stroke_destination); return stroke_draw_samples(i, P, copy_stroke_destination);
},
[&](auto& f, int i, glm::vec4 box_sample) {
m_tmp[i].unbindFramebuffer(); m_tmp[i].unbindFramebuffer();
[[maybe_unused]] const auto dirty_update = pp::panopainter::apply_legacy_canvas_stroke_face_dirty_update(
const auto dirty_update = pp::panopainter::apply_legacy_canvas_stroke_face_dirty_update(
pp::panopainter::LegacyCanvasStrokeFaceDirtyRequest { pp::panopainter::LegacyCanvasStrokeFaceDirtyRequest {
.extent = stroke_extent, .extent = stroke_extent,
.previous_accumulated_dirty_box = m_dirty_box[i], .previous_accumulated_dirty_box = m_dirty_box[i],
@@ -726,7 +726,6 @@ void Canvas::stroke_draw()
}, },
m_dirty_box[i], m_dirty_box[i],
&box_face[i]); &box_face[i]);
// TODO: maybe average color?
pad_color = f.col; pad_color = f.col;
}); });
@@ -804,7 +803,7 @@ void Canvas::stroke_draw()
dual_brush->m_tip_texture->bind() : dual_brush->m_tip_texture->bind() :
unbind_texture_2d(); unbind_texture_2d();
auto frames_dual = stroke_draw_compute(*m_dual_stroke); auto frames_dual = stroke_draw_compute(*m_dual_stroke);
pp::panopainter::execute_legacy_canvas_stroke_frame_faces( pp::panopainter::execute_legacy_canvas_stroke_frame_samples(
frames_dual, frames_dual,
[&](auto& f) { [&](auto& f) {
pp::panopainter::apply_legacy_stroke_sample_uniforms( pp::panopainter::apply_legacy_stroke_sample_uniforms(
@@ -814,14 +813,15 @@ void Canvas::stroke_draw()
.opacity = f.opacity, .opacity = f.opacity,
}); });
}, },
[&](auto&, int i, auto& P) { [&](auto&, int i, auto&) {
m_tmp_dual[i].bindFramebuffer(); m_tmp_dual[i].bindFramebuffer();
auto box_sample = stroke_draw_samples(i, P, copy_stroke_destination); },
[&](auto&, int i, auto& P) {
return stroke_draw_samples(i, P, copy_stroke_destination);
},
[&](auto&, int i, glm::vec4 box_sample) {
m_tmp_dual[i].unbindFramebuffer(); m_tmp_dual[i].unbindFramebuffer();
[[maybe_unused]] const auto dirty_update = pp::panopainter::apply_legacy_canvas_stroke_face_dirty_update(
// this mode overflows the main brush boundries
[[maybe_unused]] const auto dirty_update =
pp::panopainter::apply_legacy_canvas_stroke_face_dirty_update(
pp::panopainter::LegacyCanvasStrokeFaceDirtyRequest { pp::panopainter::LegacyCanvasStrokeFaceDirtyRequest {
.extent = stroke_extent, .extent = stroke_extent,
.previous_accumulated_dirty_box = m_dirty_box[i], .previous_accumulated_dirty_box = m_dirty_box[i],

View File

@@ -192,6 +192,32 @@ std::size_t execute_legacy_canvas_stroke_frame_faces(
return executed_faces; return executed_faces;
} }
template <typename Frames, typename BeginFrame, typename BeginFace, typename ExecuteSample, typename FinishFace>
std::size_t execute_legacy_canvas_stroke_frame_samples(
Frames&& frames,
BeginFrame&& begin_frame,
BeginFace&& begin_face,
ExecuteSample&& execute_sample,
FinishFace&& finish_face)
{
std::size_t executed_faces = 0;
for (auto& frame : frames) {
begin_frame(frame);
for (int face_index = 0; face_index < 6; ++face_index) {
auto& vertices = frame.shapes[face_index];
if (vertices.size() < 3) {
continue;
}
begin_face(frame, face_index, vertices);
auto sample_dirty_box = execute_sample(frame, face_index, vertices);
finish_face(frame, face_index, sample_dirty_box);
++executed_faces;
}
}
return executed_faces;
}
[[nodiscard]] inline pp::paint_renderer::CanvasStrokeBox legacy_canvas_stroke_box(glm::vec4 box) noexcept [[nodiscard]] inline pp::paint_renderer::CanvasStrokeBox legacy_canvas_stroke_box(glm::vec4 box) noexcept
{ {
return pp::paint_renderer::CanvasStrokeBox { return pp::paint_renderer::CanvasStrokeBox {