Share retained stroke texture binding helpers

This commit is contained in:
2026-06-13 10:30:13 +02:00
parent 3f071620dc
commit 323abdea57
5 changed files with 161 additions and 26 deletions

View File

@@ -673,15 +673,50 @@ void Canvas::stroke_draw()
});
// DRAW MAIN BRUSH
set_active_texture_unit(0);
brush->m_tip_texture->bind();
set_active_texture_unit(2);
brush->m_pattern_texture ?
brush->m_pattern_texture->bind() :
unbind_texture_2d();
set_active_texture_unit(3);
m_mixer.bindTexture();
constexpr std::array main_pass_texture_bindings {
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip,
.slot = 0,
},
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::pattern,
.slot = 2,
},
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);
@@ -718,10 +753,22 @@ void Canvas::stroke_draw()
},
m_tmp);
set_active_texture_unit(3);
m_mixer.unbindTexture();
set_active_texture_unit(0);
brush->m_tip_texture->unbind();
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
main_pass_texture_unbindings,
[&](auto input, int texture_slot) {
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
// 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,
});
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(
pp::panopainter::LegacyCanvasStrokePadExecutionRequest {
.context = "Canvas::stroke_draw",
@@ -753,8 +806,15 @@ void Canvas::stroke_draw()
m_tmp[face_index].bindFramebuffer();
},
.bind_destination_texture = [&](int face_index) {
set_active_texture_unit(1);
m_tex[face_index].bind();
pp::panopainter::bind_legacy_canvas_stroke_texture_inputs(
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 =
[&](const pp::paint_renderer::CanvasStrokeCopyRegion& copy_region) {
@@ -767,8 +827,15 @@ void Canvas::stroke_draw()
copy_region.height);
},
.unbind_destination_texture = [&](int face_index) {
set_active_texture_unit(1);
m_tex[face_index].unbind();
pp::panopainter::unbind_legacy_canvas_stroke_texture_inputs(
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 = [&] {
m_brush_shape.draw_fill();
@@ -784,11 +851,24 @@ void Canvas::stroke_draw()
{
const auto& dual_brush = m_dual_stroke->m_brush;
pp::panopainter::setup_legacy_stroke_dual_shader(stroke_material.dual_pass.uses_pattern);
set_active_texture_unit(0);
dual_brush->m_tip_texture ?
dual_brush->m_tip_texture->bind() :
unbind_texture_2d();
constexpr std::array dual_pass_texture_bindings {
pp::panopainter::LegacyCanvasStrokeTextureBinding {
.input = pp::panopainter::LegacyCanvasStrokeTextureInput::brush_tip,
.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);
const std::array<bool, 6> include_dual_dirty =
SIXPLETTE(stroke_material.composite_pass.dual_blend_mode == 0);
@@ -813,10 +893,17 @@ void Canvas::stroke_draw()
m_tmp_dual,
true);
set_active_texture_unit(0);
dual_brush->m_tip_texture ?
dual_brush->m_tip_texture->unbind() :
unbind_texture_2d();
pp::panopainter::unbind_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->unbind() :
unbind_texture_2d();
});
}
m_sampler_brush.unbind();

View File

@@ -37,6 +37,18 @@ struct LegacyStrokeSampleExecutionResult {
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 {
pp::renderer::Extent2D extent {};
glm::vec4 previous_accumulated_dirty_box {};
@@ -200,6 +212,26 @@ std::size_t execute_legacy_canvas_stroke_frame_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>
std::size_t execute_legacy_canvas_stroke_frame_samples(
Frames&& frames,