Share retained stroke texture binding helpers
This commit is contained in:
@@ -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` main, pad,
|
||||||
|
and dual live-pass texture-input binding/unbinding intent now routes through
|
||||||
|
shared retained stroke execution helpers; sampler binding, concrete GL object
|
||||||
|
mapping, framebuffer ownership, and final draw execution remain retained in
|
||||||
|
`Canvas`.
|
||||||
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview` live-pass
|
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview` live-pass
|
||||||
sampler binding, dual/main pass texture binding, checkerboard/background
|
sampler binding, dual/main pass texture binding, checkerboard/background
|
||||||
capture wrapping, and final preview copy-back now route through shared local
|
capture wrapping, and final preview copy-back now route through shared local
|
||||||
|
|||||||
@@ -3111,6 +3111,10 @@ Results:
|
|||||||
binding, checkerboard/background capture wrapping, and final preview
|
binding, checkerboard/background capture wrapping, and final preview
|
||||||
copy-back now share named local helpers, while mixer state execution and
|
copy-back now share named local helpers, while mixer state execution and
|
||||||
per-sample GL ordering remain in the preview node.
|
per-sample GL ordering remain in the preview node.
|
||||||
|
- `Canvas::stroke_draw` main, pad, and dual live-pass texture-input
|
||||||
|
binding/unbinding intent now shares retained stroke execution helpers, while
|
||||||
|
sampler binding, concrete GL object mapping, framebuffer ownership, and final
|
||||||
|
draw execution remain in the legacy Canvas path.
|
||||||
- `Canvas::stroke_draw` pad-pass destination bind/copy/unbind ordering now
|
- `Canvas::stroke_draw` pad-pass destination bind/copy/unbind ordering now
|
||||||
shares the retained stroke execution helper callback surface, while shader
|
shares the retained stroke execution helper callback surface, while shader
|
||||||
setup, pad color selection, framebuffer ownership, and final OpenGL draw
|
setup, pad color selection, framebuffer ownership, and final OpenGL draw
|
||||||
|
|||||||
@@ -509,6 +509,13 @@ Done Checks:
|
|||||||
|
|
||||||
Progress Notes:
|
Progress Notes:
|
||||||
|
|
||||||
|
- 2026-06-13: `Canvas::stroke_draw` main, pad, and dual live-pass
|
||||||
|
texture-input binding/unbinding intent now routes through retained stroke
|
||||||
|
execution helpers; sampler binding, concrete GL object mapping, framebuffer
|
||||||
|
ownership, and final draw execution remain local to `Canvas`. Next slice
|
||||||
|
should target the remaining sampler binding/teardown or the direct
|
||||||
|
semantic-input-to-GL mapping callbacks without reopening the landed dirty,
|
||||||
|
face-framebuffer, or pad helpers.
|
||||||
- 2026-06-13: `NodeStrokePreview::draw_stroke_immediate()` live-pass sampler
|
- 2026-06-13: `NodeStrokePreview::draw_stroke_immediate()` live-pass sampler
|
||||||
binding, dual/main pass texture binding, checkerboard/background capture
|
binding, dual/main pass texture binding, checkerboard/background capture
|
||||||
wrapping, and final preview copy-back now route through named local helpers;
|
wrapping, and final preview copy-back now route through named local helpers;
|
||||||
|
|||||||
139
src/canvas.cpp
139
src/canvas.cpp
@@ -673,15 +673,50 @@ void Canvas::stroke_draw()
|
|||||||
});
|
});
|
||||||
|
|
||||||
// DRAW MAIN BRUSH
|
// DRAW MAIN BRUSH
|
||||||
|
constexpr std::array main_pass_texture_bindings {
|
||||||
set_active_texture_unit(0);
|
pp::panopainter::LegacyCanvasStrokeTextureBinding {
|
||||||
brush->m_tip_texture->bind();
|
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip,
|
||||||
set_active_texture_unit(2);
|
.slot = 0,
|
||||||
brush->m_pattern_texture ?
|
},
|
||||||
brush->m_pattern_texture->bind() :
|
pp::panopainter::LegacyCanvasStrokeTextureBinding {
|
||||||
unbind_texture_2d();
|
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::pattern,
|
||||||
set_active_texture_unit(3);
|
.slot = 2,
|
||||||
m_mixer.bindTexture();
|
},
|
||||||
|
pp::panopainter::LegacyCanvasStrokeTextureBinding {
|
||||||
|
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::mixer,
|
||||||
|
.slot = 3,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
constexpr std::array main_pass_texture_unbindings {
|
||||||
|
pp::panopainter::LegacyCanvasStrokeTextureBinding {
|
||||||
|
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::mixer,
|
||||||
|
.slot = 3,
|
||||||
|
},
|
||||||
|
pp::panopainter::LegacyCanvasStrokeTextureBinding {
|
||||||
|
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip,
|
||||||
|
.slot = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
pp::panopainter::bind_legacy_canvas_stroke_texture_inputs(
|
||||||
|
main_pass_texture_bindings,
|
||||||
|
[&](auto input, int texture_slot) {
|
||||||
|
set_active_texture_unit(texture_slot);
|
||||||
|
switch (input) {
|
||||||
|
case pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip:
|
||||||
|
brush->m_tip_texture->bind();
|
||||||
|
break;
|
||||||
|
case pp::panopainter::LegacyCanvasStrokeTextureInput::pattern:
|
||||||
|
brush->m_pattern_texture ?
|
||||||
|
brush->m_pattern_texture->bind() :
|
||||||
|
unbind_texture_2d();
|
||||||
|
break;
|
||||||
|
case pp::panopainter::LegacyCanvasStrokeTextureInput::mixer:
|
||||||
|
m_mixer.bindTexture();
|
||||||
|
break;
|
||||||
|
case pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
auto frames = stroke_draw_compute(*m_current_stroke);
|
auto frames = stroke_draw_compute(*m_current_stroke);
|
||||||
|
|
||||||
@@ -718,10 +753,22 @@ void Canvas::stroke_draw()
|
|||||||
},
|
},
|
||||||
m_tmp);
|
m_tmp);
|
||||||
|
|
||||||
set_active_texture_unit(3);
|
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
|
||||||
m_mixer.unbindTexture();
|
main_pass_texture_unbindings,
|
||||||
set_active_texture_unit(0);
|
[&](auto input, int texture_slot) {
|
||||||
brush->m_tip_texture->unbind();
|
set_active_texture_unit(texture_slot);
|
||||||
|
switch (input) {
|
||||||
|
case pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip:
|
||||||
|
brush->m_tip_texture->unbind();
|
||||||
|
break;
|
||||||
|
case pp::panopainter::LegacyCanvasStrokeTextureInput::mixer:
|
||||||
|
m_mixer.unbindTexture();
|
||||||
|
break;
|
||||||
|
case pp::panopainter::LegacyCanvasStrokeTextureInput::pattern:
|
||||||
|
case pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// pad stroke
|
// pad stroke
|
||||||
// In order to mitigate color bleeding at the edge of shapes in transparent layers
|
// In order to mitigate color bleeding at the edge of shapes in transparent layers
|
||||||
@@ -738,6 +785,12 @@ void Canvas::stroke_draw()
|
|||||||
.uses_destination_feedback = copy_stroke_destination,
|
.uses_destination_feedback = copy_stroke_destination,
|
||||||
});
|
});
|
||||||
const auto pad_faces = pp::panopainter::make_legacy_canvas_stroke_pad_faces(box_dirty, box_face);
|
const auto pad_faces = pp::panopainter::make_legacy_canvas_stroke_pad_faces(box_dirty, box_face);
|
||||||
|
constexpr std::array pad_destination_texture_binding {
|
||||||
|
pp::panopainter::LegacyCanvasStrokeTextureBinding {
|
||||||
|
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination,
|
||||||
|
.slot = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
[[maybe_unused]] const auto pad_result = pp::panopainter::execute_legacy_canvas_stroke_pad_faces(
|
[[maybe_unused]] const auto pad_result = pp::panopainter::execute_legacy_canvas_stroke_pad_faces(
|
||||||
pp::panopainter::LegacyCanvasStrokePadExecutionRequest {
|
pp::panopainter::LegacyCanvasStrokePadExecutionRequest {
|
||||||
.context = "Canvas::stroke_draw",
|
.context = "Canvas::stroke_draw",
|
||||||
@@ -753,8 +806,15 @@ void Canvas::stroke_draw()
|
|||||||
m_tmp[face_index].bindFramebuffer();
|
m_tmp[face_index].bindFramebuffer();
|
||||||
},
|
},
|
||||||
.bind_destination_texture = [&](int face_index) {
|
.bind_destination_texture = [&](int face_index) {
|
||||||
set_active_texture_unit(1);
|
pp::panopainter::bind_legacy_canvas_stroke_texture_inputs(
|
||||||
m_tex[face_index].bind();
|
pad_destination_texture_binding,
|
||||||
|
[&](auto input, int texture_slot) {
|
||||||
|
if (input != pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_active_texture_unit(texture_slot);
|
||||||
|
m_tex[face_index].bind();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
.copy_framebuffer_to_destination_texture =
|
.copy_framebuffer_to_destination_texture =
|
||||||
[&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) {
|
[&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) {
|
||||||
@@ -767,8 +827,15 @@ void Canvas::stroke_draw()
|
|||||||
copy_region.height);
|
copy_region.height);
|
||||||
},
|
},
|
||||||
.unbind_destination_texture = [&](int face_index) {
|
.unbind_destination_texture = [&](int face_index) {
|
||||||
set_active_texture_unit(1);
|
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
|
||||||
m_tex[face_index].unbind();
|
pad_destination_texture_binding,
|
||||||
|
[&](auto input, int texture_slot) {
|
||||||
|
if (input != pp::panopainter::LegacyCanvasStrokeTextureInput::stroke_destination) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_active_texture_unit(texture_slot);
|
||||||
|
m_tex[face_index].unbind();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
.draw_pad = [&] {
|
.draw_pad = [&] {
|
||||||
m_brush_shape.draw_fill();
|
m_brush_shape.draw_fill();
|
||||||
@@ -784,11 +851,24 @@ void Canvas::stroke_draw()
|
|||||||
{
|
{
|
||||||
const auto& dual_brush = m_dual_stroke->m_brush;
|
const auto& dual_brush = m_dual_stroke->m_brush;
|
||||||
pp::panopainter::setup_legacy_stroke_dual_shader(stroke_material.dual_pass.uses_pattern);
|
pp::panopainter::setup_legacy_stroke_dual_shader(stroke_material.dual_pass.uses_pattern);
|
||||||
|
|
||||||
set_active_texture_unit(0);
|
constexpr std::array dual_pass_texture_bindings {
|
||||||
dual_brush->m_tip_texture ?
|
pp::panopainter::LegacyCanvasStrokeTextureBinding {
|
||||||
dual_brush->m_tip_texture->bind() :
|
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip,
|
||||||
unbind_texture_2d();
|
.slot = 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
pp::panopainter::bind_legacy_canvas_stroke_texture_inputs(
|
||||||
|
dual_pass_texture_bindings,
|
||||||
|
[&](auto input, int texture_slot) {
|
||||||
|
if (input != pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_active_texture_unit(texture_slot);
|
||||||
|
dual_brush->m_tip_texture ?
|
||||||
|
dual_brush->m_tip_texture->bind() :
|
||||||
|
unbind_texture_2d();
|
||||||
|
});
|
||||||
auto frames_dual = stroke_draw_compute(*m_dual_stroke);
|
auto frames_dual = stroke_draw_compute(*m_dual_stroke);
|
||||||
const std::array<bool, 6> include_dual_dirty =
|
const std::array<bool, 6> include_dual_dirty =
|
||||||
SIXPLETTE(stroke_material.composite_pass.dual_blend_mode == 0);
|
SIXPLETTE(stroke_material.composite_pass.dual_blend_mode == 0);
|
||||||
@@ -813,10 +893,17 @@ void Canvas::stroke_draw()
|
|||||||
m_tmp_dual,
|
m_tmp_dual,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
set_active_texture_unit(0);
|
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
|
||||||
dual_brush->m_tip_texture ?
|
dual_pass_texture_bindings,
|
||||||
dual_brush->m_tip_texture->unbind() :
|
[&](auto input, int texture_slot) {
|
||||||
unbind_texture_2d();
|
if (input != pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
set_active_texture_unit(texture_slot);
|
||||||
|
dual_brush->m_tip_texture ?
|
||||||
|
dual_brush->m_tip_texture->unbind() :
|
||||||
|
unbind_texture_2d();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
m_sampler_brush.unbind();
|
m_sampler_brush.unbind();
|
||||||
|
|||||||
@@ -37,6 +37,18 @@ struct LegacyStrokeSampleExecutionResult {
|
|||||||
glm::vec4 dirty_bounds {};
|
glm::vec4 dirty_bounds {};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class LegacyCanvasStrokeTextureInput {
|
||||||
|
brush_tip,
|
||||||
|
stroke_destination,
|
||||||
|
pattern,
|
||||||
|
mixer,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LegacyCanvasStrokeTextureBinding {
|
||||||
|
LegacyCanvasStrokeTextureInput input = LegacyCanvasStrokeTextureInput::brush_tip;
|
||||||
|
int slot = 0;
|
||||||
|
};
|
||||||
|
|
||||||
struct LegacyCanvasStrokeFaceDirtyRequest {
|
struct LegacyCanvasStrokeFaceDirtyRequest {
|
||||||
pp::renderer::Extent2D extent {};
|
pp::renderer::Extent2D extent {};
|
||||||
glm::vec4 previous_accumulated_dirty_box {};
|
glm::vec4 previous_accumulated_dirty_box {};
|
||||||
@@ -200,6 +212,26 @@ std::size_t execute_legacy_canvas_stroke_frame_faces(
|
|||||||
return executed_faces;
|
return executed_faces;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BindTextureInput, std::size_t BindingCount>
|
||||||
|
inline void bind_legacy_canvas_stroke_texture_inputs(
|
||||||
|
const std::array<LegacyCanvasStrokeTextureBinding, BindingCount>& bindings,
|
||||||
|
BindTextureInput&& bind_texture_input)
|
||||||
|
{
|
||||||
|
for (const auto& binding : bindings) {
|
||||||
|
bind_texture_input(binding.input, binding.slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename UnbindTextureInput, std::size_t BindingCount>
|
||||||
|
inline void unbind_legacy_canvas_stroke_texture_inputs(
|
||||||
|
const std::array<LegacyCanvasStrokeTextureBinding, BindingCount>& bindings,
|
||||||
|
UnbindTextureInput&& unbind_texture_input)
|
||||||
|
{
|
||||||
|
for (const auto& binding : bindings) {
|
||||||
|
unbind_texture_input(binding.input, binding.slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Frames, typename BeginFrame, typename BeginFace, typename ExecuteSample, typename FinishFace>
|
template <typename Frames, typename BeginFrame, typename BeginFace, typename ExecuteSample, typename FinishFace>
|
||||||
std::size_t execute_legacy_canvas_stroke_frame_samples(
|
std::size_t execute_legacy_canvas_stroke_frame_samples(
|
||||||
Frames&& frames,
|
Frames&& frames,
|
||||||
|
|||||||
Reference in New Issue
Block a user