Extract stroke commit callback helper
This commit is contained in:
@@ -99,6 +99,12 @@ agent or engineer to remove them without reconstructing context from chat.
|
|||||||
leaving the method with only shell assembly and executor dispatch.
|
leaving the method with only shell assembly and executor dispatch.
|
||||||
- 2026-06-13: `LATER-003` was narrowed again. `Canvas::stroke_draw_mix()`
|
- 2026-06-13: `LATER-003` was narrowed again. `Canvas::stroke_draw_mix()`
|
||||||
now keeps only retained shell assembly and executor dispatch at the callsite.
|
now keeps only retained shell assembly and executor dispatch at the callsite.
|
||||||
|
- 2026-06-13: `DEBT-0036` was narrowed again. `Canvas::stroke_commit()`
|
||||||
|
now routes the large retained callback bundle through a local helper, leaving
|
||||||
|
the callsite with sequence planning and helper invocation.
|
||||||
|
- 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. `NodeStrokePreview::draw_stroke_immediate()`
|
- 2026-06-13: `DEBT-0036` was narrowed again. `NodeStrokePreview::draw_stroke_immediate()`
|
||||||
now routes final composite execution and preview copy-back through a retained
|
now routes final composite execution and preview copy-back through a retained
|
||||||
local wrapper, leaving the call site with only sequence wiring.
|
local wrapper, leaving the call site with only sequence wiring.
|
||||||
|
|||||||
@@ -644,6 +644,12 @@ Progress Notes:
|
|||||||
- 2026-06-13: `Canvas::stroke_draw_mix()` now keeps just the retained shell
|
- 2026-06-13: `Canvas::stroke_draw_mix()` now keeps just the retained shell
|
||||||
assembly and executor dispatch at the callsite; the framebuffer setup
|
assembly and executor dispatch at the callsite; the framebuffer setup
|
||||||
callbacks are isolated in the helper.
|
callbacks are isolated in the helper.
|
||||||
|
- 2026-06-13: `Canvas::stroke_commit()` now routes the large retained callback
|
||||||
|
bundle through a local helper, leaving the callsite with sequence planning
|
||||||
|
and helper invocation.
|
||||||
|
- 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_draw_samples()` now reuses a retained destination
|
- 2026-06-13: `Canvas::stroke_draw_samples()` now reuses a retained destination
|
||||||
texture dispatch helper for the live sample path; `Canvas` still owns the
|
texture dispatch helper for the live sample path; `Canvas` still owns the
|
||||||
concrete face textures and callback execution.
|
concrete face textures and callback execution.
|
||||||
|
|||||||
403
src/canvas.cpp
403
src/canvas.cpp
@@ -531,6 +531,206 @@ static auto make_canvas_stroke_mix_pass_shell(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static auto make_canvas_stroke_commit_callbacks(
|
||||||
|
Canvas& canvas,
|
||||||
|
const glm::vec4& vp,
|
||||||
|
const glm::vec4& cc,
|
||||||
|
bool blend,
|
||||||
|
ActionStroke* action,
|
||||||
|
const Stroke* current_stroke,
|
||||||
|
const pp::paint_renderer::CanvasStrokeCommitSequencePlan& sequence,
|
||||||
|
const pp::paint_renderer::CanvasStrokeCommitMaterialPlan& stroke_material)
|
||||||
|
{
|
||||||
|
const auto& b = current_stroke->m_brush;
|
||||||
|
return pp::panopainter::make_legacy_canvas_stroke_commit_callbacks(
|
||||||
|
[&]() {
|
||||||
|
canvas.m_dirty = false;
|
||||||
|
canvas.m_dirty_stroke = true; // new stroke ready for timelapse capture
|
||||||
|
App::I->redraw = true;
|
||||||
|
canvas.m_unsaved = true;
|
||||||
|
App::I->title_update();
|
||||||
|
},
|
||||||
|
[]() {},
|
||||||
|
[&]() {
|
||||||
|
canvas.apply_canvas_viewport(0, 0, canvas.m_width, canvas.m_height);
|
||||||
|
canvas.apply_canvas_capability(canvas.blend_state(), false);
|
||||||
|
},
|
||||||
|
[&]() {
|
||||||
|
blend ? canvas.apply_canvas_capability(canvas.blend_state(), true) : canvas.apply_canvas_capability(canvas.blend_state(), false);
|
||||||
|
canvas.apply_canvas_viewport(vp.x, vp.y, vp.width, vp.height);
|
||||||
|
canvas.apply_canvas_clear_color(cc);
|
||||||
|
set_active_texture_unit(0);
|
||||||
|
},
|
||||||
|
[&]() {
|
||||||
|
action->m_layer_idx = canvas.m_current_layer_idx;
|
||||||
|
action->m_frame_idx = canvas.layer().m_frame_index;
|
||||||
|
action->m_canvas = &canvas;
|
||||||
|
ActionManager::add(action);
|
||||||
|
},
|
||||||
|
[&]() {
|
||||||
|
canvas.stroke_commit_timelapse();
|
||||||
|
},
|
||||||
|
[&](int i) {
|
||||||
|
canvas.m_layers[canvas.m_current_layer_idx]->rtt(i).bindFramebuffer();
|
||||||
|
},
|
||||||
|
[&](int i) {
|
||||||
|
glm::vec2 box_sz = zw(canvas.m_dirty_box[i]) - xy(canvas.m_dirty_box[i]);
|
||||||
|
action->m_image[i] = std::make_unique<uint8_t[]>(
|
||||||
|
static_cast<std::size_t>(box_sz.x * box_sz.y * 4));
|
||||||
|
canvas.m_layers[canvas.m_current_layer_idx]->rtt(i).readPixelsRgba8(
|
||||||
|
static_cast<int>(canvas.m_dirty_box[i].x),
|
||||||
|
static_cast<int>(canvas.m_dirty_box[i].y),
|
||||||
|
static_cast<int>(box_sz.x),
|
||||||
|
static_cast<int>(box_sz.y),
|
||||||
|
action->m_image[i].get());
|
||||||
|
|
||||||
|
action->m_box[i] = canvas.m_dirty_box[i];
|
||||||
|
action->m_old_box[i] = canvas.m_layers[canvas.m_current_layer_idx]->box(i);
|
||||||
|
action->m_old_dirty[i] = canvas.m_layers[canvas.m_current_layer_idx]->face(i);
|
||||||
|
},
|
||||||
|
[&](int i) {
|
||||||
|
if (!canvas.m_layers[canvas.m_current_layer_idx]->m_alpha_locked) {
|
||||||
|
auto& lbox = canvas.m_layers[canvas.m_current_layer_idx]->box(i);
|
||||||
|
lbox = glm::vec4(
|
||||||
|
glm::min(xy(canvas.m_dirty_box[i]), xy(lbox)),
|
||||||
|
glm::max(zw(canvas.m_dirty_box[i]), zw(lbox)));
|
||||||
|
}
|
||||||
|
canvas.m_layers[canvas.m_current_layer_idx]->face(i) = true;
|
||||||
|
},
|
||||||
|
[&](int i) {
|
||||||
|
set_active_texture_unit(0);
|
||||||
|
canvas.m_tex2[i].bind();
|
||||||
|
copy_framebuffer_to_texture_2d(0, 0, 0, 0, canvas.m_width, canvas.m_height);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[&](int) {
|
||||||
|
pp::panopainter::execute_legacy_canvas_stroke_commit_erase(
|
||||||
|
[&]() {
|
||||||
|
pp::panopainter::setup_legacy_stroke_erase_shader(
|
||||||
|
pp::panopainter::LegacyStrokeEraseUniforms {
|
||||||
|
.mvp = glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f),
|
||||||
|
.texture_slot = 0,
|
||||||
|
.stroke_texture_slot = 1,
|
||||||
|
.mask_texture_slot = 2,
|
||||||
|
.alpha = 1.0f,
|
||||||
|
.mask_enabled = canvas.m_smask_active,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[&]() {
|
||||||
|
canvas.m_plane.draw_fill();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[&](int) {
|
||||||
|
glm::vec2 patt_scale = glm::vec2(b->m_pattern_scale);
|
||||||
|
if (b->m_pattern_flipx) patt_scale.x *= -1.f;
|
||||||
|
if (b->m_pattern_flipy) patt_scale.y *= -1.f;
|
||||||
|
|
||||||
|
pp::panopainter::execute_legacy_canvas_stroke_commit_paint(
|
||||||
|
[&]() {
|
||||||
|
pp::panopainter::setup_legacy_stroke_composite_shader(
|
||||||
|
pp::panopainter::LegacyStrokeCompositeUniforms {
|
||||||
|
.resolution = canvas.m_size,
|
||||||
|
.pattern = {
|
||||||
|
.scale = patt_scale,
|
||||||
|
.invert = static_cast<float>(b->m_pattern_invert),
|
||||||
|
.brightness = b->m_pattern_brightness,
|
||||||
|
.contrast = b->m_pattern_contrast,
|
||||||
|
.depth = b->m_pattern_depth,
|
||||||
|
.blend_mode = b->m_pattern_blend_mode,
|
||||||
|
.offset = canvas.m_pattern_offset,
|
||||||
|
},
|
||||||
|
.mvp = glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f),
|
||||||
|
.layer_alpha = 1.0f,
|
||||||
|
.alpha_lock = canvas.m_layers[canvas.m_current_layer_idx]->m_alpha_locked,
|
||||||
|
.mask_enabled = canvas.m_smask_active,
|
||||||
|
.use_fragcoord = false,
|
||||||
|
.blend_mode = b->m_blend_mode,
|
||||||
|
.use_dual = stroke_material.composite_pass.use_dual,
|
||||||
|
.dual_blend_mode = stroke_material.composite_pass.dual_blend_mode,
|
||||||
|
.dual_alpha = stroke_material.composite_pass.dual_alpha,
|
||||||
|
.use_pattern = stroke_material.composite_pass.use_pattern,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[&]() {
|
||||||
|
canvas.m_plane.draw_fill();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[&](int i) {
|
||||||
|
pp::panopainter::copy_legacy_canvas_stroke_commit_to_dilate_source(
|
||||||
|
sequence,
|
||||||
|
[&]() {
|
||||||
|
pp::panopainter::setup_legacy_stroke_dilate_shader(
|
||||||
|
pp::panopainter::LegacyStrokeDilateUniforms {
|
||||||
|
.mvp = glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[&](int texture_slot) {
|
||||||
|
set_active_texture_unit(texture_slot);
|
||||||
|
},
|
||||||
|
[&]() {
|
||||||
|
canvas.m_tex2[i].bind();
|
||||||
|
},
|
||||||
|
[&](int src_x, int src_y, int dst_x, int dst_y, int width, int height) {
|
||||||
|
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
||||||
|
},
|
||||||
|
pp::panopainter::LegacyCanvasStrokeCommitCopyExtent {
|
||||||
|
.width = canvas.m_width,
|
||||||
|
.height = canvas.m_height,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[&](int) {
|
||||||
|
pp::panopainter::execute_legacy_canvas_stroke_commit_dilate([&]() {
|
||||||
|
canvas.m_plane.draw_fill();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[&](int i) {
|
||||||
|
canvas.m_layers[canvas.m_current_layer_idx]->rtt(i).unbindFramebuffer();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
glm::vec4 Canvas::stroke_draw_samples(
|
glm::vec4 Canvas::stroke_draw_samples(
|
||||||
int i,
|
int i,
|
||||||
std::vector<vertex_t>& P,
|
std::vector<vertex_t>& P,
|
||||||
@@ -1120,200 +1320,15 @@ void Canvas::stroke_commit()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto commit_callbacks = pp::panopainter::make_legacy_canvas_stroke_commit_callbacks(
|
const auto commit_callbacks = make_canvas_stroke_commit_callbacks(
|
||||||
[&]() {
|
*this,
|
||||||
m_dirty = false;
|
vp,
|
||||||
m_dirty_stroke = true; // new stroke ready for timelapse capture
|
cc,
|
||||||
App::I->redraw = true;
|
blend,
|
||||||
m_unsaved = true;
|
action,
|
||||||
App::I->title_update();
|
m_current_stroke,
|
||||||
},
|
sequence,
|
||||||
[]() {},
|
stroke_material);
|
||||||
[&]() {
|
|
||||||
apply_canvas_viewport(0, 0, m_width, m_height);
|
|
||||||
apply_canvas_capability(blend_state(), false);
|
|
||||||
},
|
|
||||||
[&]() {
|
|
||||||
blend ? apply_canvas_capability(blend_state(), true) : apply_canvas_capability(blend_state(), false);
|
|
||||||
apply_canvas_viewport(vp.x, vp.y, vp.width, vp.height);
|
|
||||||
apply_canvas_clear_color(cc);
|
|
||||||
set_active_texture_unit(0);
|
|
||||||
},
|
|
||||||
[&]() {
|
|
||||||
action->m_layer_idx = m_current_layer_idx;
|
|
||||||
action->m_frame_idx = layer().m_frame_index;
|
|
||||||
action->m_canvas = this;
|
|
||||||
//action->m_stroke = std::move(m_current_stroke);
|
|
||||||
ActionManager::add(action);
|
|
||||||
},
|
|
||||||
[&]() {
|
|
||||||
stroke_commit_timelapse();
|
|
||||||
},
|
|
||||||
[&](int i) {
|
|
||||||
m_layers[m_current_layer_idx]->rtt(i).bindFramebuffer();
|
|
||||||
},
|
|
||||||
[&](int i) {
|
|
||||||
// save image before commit
|
|
||||||
glm::vec2 box_sz = zw(m_dirty_box[i]) - xy(m_dirty_box[i]);
|
|
||||||
action->m_image[i] = std::make_unique<uint8_t[]>(
|
|
||||||
static_cast<std::size_t>(box_sz.x * box_sz.y * 4));
|
|
||||||
m_layers[m_current_layer_idx]->rtt(i).readPixelsRgba8(
|
|
||||||
static_cast<int>(m_dirty_box[i].x),
|
|
||||||
static_cast<int>(m_dirty_box[i].y),
|
|
||||||
static_cast<int>(box_sz.x),
|
|
||||||
static_cast<int>(box_sz.y),
|
|
||||||
action->m_image[i].get());
|
|
||||||
|
|
||||||
action->m_box[i] = m_dirty_box[i];
|
|
||||||
action->m_old_box[i] = m_layers[m_current_layer_idx]->box(i);
|
|
||||||
action->m_old_dirty[i] = m_layers[m_current_layer_idx]->face(i);
|
|
||||||
},
|
|
||||||
[&](int i) {
|
|
||||||
if (!m_layers[m_current_layer_idx]->m_alpha_locked)
|
|
||||||
{
|
|
||||||
auto& lbox = m_layers[m_current_layer_idx]->box(i);
|
|
||||||
lbox = glm::vec4(
|
|
||||||
glm::min(xy(m_dirty_box[i]), xy(lbox)),
|
|
||||||
glm::max(zw(m_dirty_box[i]), zw(lbox))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
m_layers[m_current_layer_idx]->face(i) = true;
|
|
||||||
},
|
|
||||||
[&](int i) {
|
|
||||||
// copy to tmp2 for layer blending
|
|
||||||
set_active_texture_unit(0);
|
|
||||||
m_tex2[i].bind();
|
|
||||||
copy_framebuffer_to_texture_2d(0, 0, 0, 0, m_width, m_height);
|
|
||||||
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:
|
|
||||||
m_tex2[i].bind();
|
|
||||||
break;
|
|
||||||
case pp::paint_renderer::CanvasStrokeCommitTextureRole::stroke:
|
|
||||||
m_tmp[i].bindTexture();
|
|
||||||
break;
|
|
||||||
case pp::paint_renderer::CanvasStrokeCommitTextureRole::selection_mask:
|
|
||||||
m_smask.rtt(i).bindTexture();
|
|
||||||
break;
|
|
||||||
case pp::paint_renderer::CanvasStrokeCommitTextureRole::dual_stroke:
|
|
||||||
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:
|
|
||||||
m_sampler.bind(texture_slot);
|
|
||||||
break;
|
|
||||||
case pp::paint_renderer::CanvasStrokeCommitTextureRole::stroke:
|
|
||||||
m_sampler_nearest.bind(texture_slot);
|
|
||||||
break;
|
|
||||||
case pp::paint_renderer::CanvasStrokeCommitTextureRole::selection_mask:
|
|
||||||
case pp::paint_renderer::CanvasStrokeCommitTextureRole::dual_stroke:
|
|
||||||
m_sampler.bind(texture_slot);
|
|
||||||
break;
|
|
||||||
case pp::paint_renderer::CanvasStrokeCommitTextureRole::pattern:
|
|
||||||
m_sampler_stencil.bind(texture_slot);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[&](int) {
|
|
||||||
pp::panopainter::execute_legacy_canvas_stroke_commit_erase(
|
|
||||||
[&]() {
|
|
||||||
pp::panopainter::setup_legacy_stroke_erase_shader(
|
|
||||||
pp::panopainter::LegacyStrokeEraseUniforms {
|
|
||||||
.mvp = glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f),
|
|
||||||
.texture_slot = 0,
|
|
||||||
.stroke_texture_slot = 1,
|
|
||||||
.mask_texture_slot = 2,
|
|
||||||
.alpha = 1.0f,
|
|
||||||
.mask_enabled = m_smask_active,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[&]() {
|
|
||||||
m_plane.draw_fill();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[&](int) {
|
|
||||||
glm::vec2 patt_scale = glm::vec2(b->m_pattern_scale);
|
|
||||||
if (b->m_pattern_flipx) patt_scale.x *= -1.f;
|
|
||||||
if (b->m_pattern_flipy) patt_scale.y *= -1.f;
|
|
||||||
|
|
||||||
pp::panopainter::execute_legacy_canvas_stroke_commit_paint(
|
|
||||||
[&]() {
|
|
||||||
pp::panopainter::setup_legacy_stroke_composite_shader(
|
|
||||||
pp::panopainter::LegacyStrokeCompositeUniforms {
|
|
||||||
.resolution = m_size,
|
|
||||||
.pattern = {
|
|
||||||
.scale = patt_scale,
|
|
||||||
.invert = static_cast<float>(b->m_pattern_invert),
|
|
||||||
.brightness = b->m_pattern_brightness,
|
|
||||||
.contrast = b->m_pattern_contrast,
|
|
||||||
.depth = b->m_pattern_depth,
|
|
||||||
.blend_mode = b->m_pattern_blend_mode,
|
|
||||||
.offset = m_pattern_offset,
|
|
||||||
},
|
|
||||||
.mvp = glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f),
|
|
||||||
.layer_alpha = 1.0f,
|
|
||||||
.alpha_lock = m_layers[m_current_layer_idx]->m_alpha_locked,
|
|
||||||
.mask_enabled = m_smask_active,
|
|
||||||
.use_fragcoord = false,
|
|
||||||
.blend_mode = b->m_blend_mode,
|
|
||||||
.use_dual = stroke_material.composite_pass.use_dual,
|
|
||||||
.dual_blend_mode = stroke_material.composite_pass.dual_blend_mode,
|
|
||||||
.dual_alpha = stroke_material.composite_pass.dual_alpha,
|
|
||||||
.use_pattern = stroke_material.composite_pass.use_pattern,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[&]() {
|
|
||||||
m_plane.draw_fill();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[&](int i) {
|
|
||||||
pp::panopainter::copy_legacy_canvas_stroke_commit_to_dilate_source(
|
|
||||||
sequence,
|
|
||||||
[&]() {
|
|
||||||
// Dilate borders to avoid interpolation bleeding
|
|
||||||
pp::panopainter::setup_legacy_stroke_dilate_shader(
|
|
||||||
pp::panopainter::LegacyStrokeDilateUniforms {
|
|
||||||
.mvp = glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[&](int texture_slot) {
|
|
||||||
set_active_texture_unit(texture_slot);
|
|
||||||
},
|
|
||||||
[&]() {
|
|
||||||
m_tex2[i].bind();
|
|
||||||
},
|
|
||||||
[&](int src_x, int src_y, int dst_x, int dst_y, int width, int height) {
|
|
||||||
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
|
||||||
},
|
|
||||||
pp::panopainter::LegacyCanvasStrokeCommitCopyExtent {
|
|
||||||
.width = m_width,
|
|
||||||
.height = m_height,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[&](int) {
|
|
||||||
pp::panopainter::execute_legacy_canvas_stroke_commit_dilate([&]() {
|
|
||||||
m_plane.draw_fill();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
[&](int i) {
|
|
||||||
m_layers[m_current_layer_idx]->rtt(i).unbindFramebuffer();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
[[maybe_unused]] const auto commit_result = pp::panopainter::execute_legacy_canvas_stroke_commit_sequence(
|
[[maybe_unused]] const auto commit_result = pp::panopainter::execute_legacy_canvas_stroke_commit_sequence(
|
||||||
pp::panopainter::LegacyCanvasStrokeCommitRequest {
|
pp::panopainter::LegacyCanvasStrokeCommitRequest {
|
||||||
|
|||||||
Reference in New Issue
Block a user