Route stroke pad pass through helper callbacks

This commit is contained in:
2026-06-13 10:07:57 +02:00
parent c1724edc47
commit f1f0dd5d03
4 changed files with 82 additions and 30 deletions

View File

@@ -18,6 +18,11 @@ 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` pad-pass
destination bind/copy/unbind ordering now routes through
`legacy_canvas_stroke_execution_services.h`; shader setup, pad color
selection, framebuffer ownership, and final OpenGL draw remain retained in
`Canvas`.
- 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 live sample frame/face traversal plus dirty tracking now route through dual live sample frame/face traversal plus dirty tracking now route through
`legacy_canvas_stroke_execution_services.h`; shader timing, sampler/texture `legacy_canvas_stroke_execution_services.h`; shader timing, sampler/texture

View File

@@ -3093,6 +3093,10 @@ Results:
dirty tracking now share one retained stroke execution helper surface, while dirty tracking now share one retained stroke execution helper surface, while
shader timing, sampler/texture binding, framebuffer ownership, pad execution, shader timing, sampler/texture binding, framebuffer ownership, pad execution,
and final OpenGL draw ordering remain in the legacy Canvas path. and final OpenGL draw ordering remain in the legacy Canvas path.
- `Canvas::stroke_draw` pad-pass destination bind/copy/unbind ordering now
shares the retained stroke execution helper callback surface, while shader
setup, pad color selection, framebuffer ownership, and final OpenGL draw
remain in the legacy Canvas path.
- `Canvas::stroke_draw` pad-region planning now shares the retained stroke - `Canvas::stroke_draw` pad-region planning now shares the retained stroke
execution helper wrapping `pp_paint_renderer`, while pad color selection, execution helper wrapping `pp_paint_renderer`, while pad color selection,
dirty-face iteration, framebuffer copies, quad upload, and draw execution dirty-face iteration, framebuffer copies, quad upload, and draw execution

View File

@@ -742,10 +742,6 @@ void Canvas::stroke_draw()
.color = pad_color, .color = pad_color,
.uses_destination_feedback = copy_stroke_destination, .uses_destination_feedback = copy_stroke_destination,
}); });
if (copy_stroke_destination)
{
set_active_texture_unit(1);
}
const std::array<pp::panopainter::LegacyCanvasStrokePadFace, 6> pad_faces = { const std::array<pp::panopainter::LegacyCanvasStrokePadFace, 6> pad_faces = {
pp::panopainter::LegacyCanvasStrokePadFace { .index = 0, .dirty = box_dirty[0], .pass_dirty_box = box_face[0] }, pp::panopainter::LegacyCanvasStrokePadFace { .index = 0, .dirty = box_dirty[0], .pass_dirty_box = box_face[0] },
pp::panopainter::LegacyCanvasStrokePadFace { .index = 1, .dirty = box_dirty[1], .pass_dirty_box = box_face[1] }, pp::panopainter::LegacyCanvasStrokePadFace { .index = 1, .dirty = box_dirty[1], .pass_dirty_box = box_face[1] },
@@ -759,32 +755,40 @@ void Canvas::stroke_draw()
.context = "Canvas::stroke_draw", .context = "Canvas::stroke_draw",
.extent = stroke_extent, .extent = stroke_extent,
.faces = pad_faces, .faces = pad_faces,
.execute_face = .copy_stroke_destination = copy_stroke_destination,
[&](int face_index, .upload_pad_vertices = [&](std::span<const vertex_t> pad_quad) {
const pp::panopainter::LegacyCanvasStrokePadRegionResult& pad_region, m_brush_shape.update_vertices(
std::span<vertex_t> pad_quad) { const_cast<vertex_t*>(pad_quad.data()),
m_brush_shape.update_vertices(pad_quad.data(), pad_quad.size()); static_cast<int>(pad_quad.size()));
},
m_tmp[face_index].bindFramebuffer(); .begin_face = [&](int face_index) {
if (copy_stroke_destination) m_tmp[face_index].bindFramebuffer();
{ },
m_tex[face_index].bind(); .bind_destination_texture = [&](int face_index) {
copy_framebuffer_to_texture_2d( set_active_texture_unit(1);
pad_region.copy_region.x, m_tex[face_index].bind();
pad_region.copy_region.y, },
pad_region.copy_region.x, .copy_framebuffer_to_destination_texture =
pad_region.copy_region.y, [&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) {
pad_region.copy_region.width, copy_framebuffer_to_texture_2d(
pad_region.copy_region.height); copy_region.x,
} copy_region.y,
m_brush_shape.draw_fill(); copy_region.x,
m_tmp[face_index].unbindFramebuffer(); copy_region.y,
copy_region.width,
copy_region.height);
}, },
.unbind_destination_texture = [&](int face_index) {
set_active_texture_unit(1);
m_tex[face_index].unbind();
},
.draw_pad = [&] {
m_brush_shape.draw_fill();
},
.finish_face = [&](int face_index) {
m_tmp[face_index].unbindFramebuffer();
},
}); });
if (copy_stroke_destination)
{
unbind_texture_2d();
}
// DRAW DUAL BRUSH // DRAW DUAL BRUSH

View File

@@ -74,6 +74,14 @@ struct LegacyCanvasStrokePadExecutionRequest {
std::string_view context; std::string_view context;
pp::renderer::Extent2D extent {}; pp::renderer::Extent2D extent {};
std::span<const LegacyCanvasStrokePadFace> faces; std::span<const LegacyCanvasStrokePadFace> faces;
bool copy_stroke_destination = false;
std::function<void(std::span<const vertex_t>)> upload_pad_vertices;
std::function<void(int)> begin_face;
std::function<void(int)> bind_destination_texture;
std::function<void(const pp::paint_renderer::CanvasStrokeCopyRegion&)> copy_framebuffer_to_destination_texture;
std::function<void(int)> unbind_destination_texture;
std::function<void()> draw_pad;
std::function<void(int)> finish_face;
std::function<void(int, const LegacyCanvasStrokePadRegionResult&, std::span<vertex_t>)> execute_face; std::function<void(int, const LegacyCanvasStrokePadRegionResult&, std::span<vertex_t>)> execute_face;
}; };
@@ -423,7 +431,11 @@ template <typename ExecuteSample, typename BeginFace, typename PrepareDirtyReque
LegacyCanvasStrokePadExecutionResult result; LegacyCanvasStrokePadExecutionResult result;
if (request.extent.width == 0U || if (request.extent.width == 0U ||
request.extent.height == 0U || request.extent.height == 0U ||
!request.execute_face) { (!request.execute_face &&
(!request.upload_pad_vertices ||
!request.begin_face ||
!request.draw_pad ||
!request.finish_face))) {
return result; return result;
} }
@@ -450,7 +462,34 @@ template <typename ExecuteSample, typename BeginFace, typename PrepareDirtyReque
vertex_t({ pad_region.ndc_quad[5].x, pad_region.ndc_quad[5].y }), vertex_t({ pad_region.ndc_quad[5].x, pad_region.ndc_quad[5].y }),
}; };
request.execute_face(face.index, pad_region, pad_quad); if (request.execute_face) {
request.execute_face(face.index, pad_region, pad_quad);
} else {
if (!request.upload_pad_vertices ||
!request.begin_face ||
!request.draw_pad ||
!request.finish_face) {
return result;
}
if (request.copy_stroke_destination &&
(!request.bind_destination_texture ||
!request.copy_framebuffer_to_destination_texture ||
!request.unbind_destination_texture)) {
return result;
}
request.upload_pad_vertices(pad_quad);
request.begin_face(face.index);
if (request.copy_stroke_destination) {
request.bind_destination_texture(face.index);
request.copy_framebuffer_to_destination_texture(pad_region.copy_region);
}
request.draw_pad();
if (request.copy_stroke_destination) {
request.unbind_destination_texture(face.index);
}
request.finish_face(face.index);
}
++result.padded_faces; ++result.padded_faces;
} }