Share retained stroke preview sample helper
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. `NodeStrokePreview::stroke_draw_samples`
|
||||||
|
now routes destination bind/unbind, framebuffer copy callback wrapping,
|
||||||
|
sample-point assembly, and brush-vertex upload/draw through one local helper;
|
||||||
|
mixer-pass state execution and higher-level pass orchestration remain retained
|
||||||
|
in the preview node.
|
||||||
- 2026-06-13: DEBT-0036 was narrowed again. `Canvas::stroke_draw` main, pad,
|
- 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
|
and dual live-pass texture-input binding/unbinding intent now routes through
|
||||||
shared retained stroke execution helpers; sampler binding, concrete GL object
|
shared retained stroke execution helpers; sampler binding, concrete GL object
|
||||||
|
|||||||
@@ -3115,6 +3115,10 @@ Results:
|
|||||||
binding/unbinding intent now shares retained stroke execution helpers, while
|
binding/unbinding intent now shares retained stroke execution helpers, while
|
||||||
sampler binding, concrete GL object mapping, framebuffer ownership, and final
|
sampler binding, concrete GL object mapping, framebuffer ownership, and final
|
||||||
draw execution remain in the legacy Canvas path.
|
draw execution remain in the legacy Canvas path.
|
||||||
|
- `NodeStrokePreview::stroke_draw_samples` now shares one local helper for
|
||||||
|
destination bind/unbind, framebuffer copy callback wrapping, sample-point
|
||||||
|
assembly, and brush-vertex upload/draw, while mixer-pass state execution and
|
||||||
|
higher-level pass orchestration remain in the preview node.
|
||||||
- `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: `NodeStrokePreview::stroke_draw_samples()` now routes
|
||||||
|
destination bind/unbind, framebuffer copy callback wrapping, sample-point
|
||||||
|
assembly, and brush-vertex upload/draw through one local helper; mixer-pass
|
||||||
|
state execution and higher-level pass orchestration remain local to the
|
||||||
|
preview node. Next slice should target the remaining mixer-pass state/copy
|
||||||
|
ordering without reopening the landed preview live-pass, binding, or final
|
||||||
|
composite helpers.
|
||||||
- 2026-06-13: `Canvas::stroke_draw` main, pad, and dual live-pass
|
- 2026-06-13: `Canvas::stroke_draw` main, pad, and dual live-pass
|
||||||
texture-input binding/unbinding intent now routes through retained stroke
|
texture-input binding/unbinding intent now routes through retained stroke
|
||||||
execution helpers; sampler binding, concrete GL object mapping, framebuffer
|
execution helpers; sampler binding, concrete GL object mapping, framebuffer
|
||||||
|
|||||||
@@ -258,6 +258,93 @@ void bind_stroke_preview_main_pass_textures(
|
|||||||
uses_mixer ? mixer_rtt.bindTexture() : unbind_texture_2d();
|
uses_mixer ? mixer_rtt.bindTexture() : unbind_texture_2d();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bind_stroke_preview_destination_texture(Texture2D& texture)
|
||||||
|
{
|
||||||
|
set_active_texture_unit(stroke_preview_live_slots::kDestination);
|
||||||
|
texture.bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void unbind_stroke_preview_destination_texture(Texture2D& texture)
|
||||||
|
{
|
||||||
|
set_active_texture_unit(stroke_preview_live_slots::kDestination);
|
||||||
|
texture.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy_stroke_preview_destination_texture_region(
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<pp::paint_renderer::CanvasStrokePoint, 4> make_stroke_preview_sample_points(
|
||||||
|
const std::array<vertex_t, 4>& vertices)
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
pp::paint_renderer::CanvasStrokePoint { .x = vertices[0].pos.x, .y = vertices[0].pos.y },
|
||||||
|
pp::paint_renderer::CanvasStrokePoint { .x = vertices[1].pos.x, .y = vertices[1].pos.y },
|
||||||
|
pp::paint_renderer::CanvasStrokePoint { .x = vertices[2].pos.x, .y = vertices[2].pos.y },
|
||||||
|
pp::paint_renderer::CanvasStrokePoint { .x = vertices[3].pos.x, .y = vertices[3].pos.y },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void upload_stroke_preview_brush_vertices(DynamicShape& brush_shape, std::span<const vertex_t> vertices)
|
||||||
|
{
|
||||||
|
brush_shape.update_vertices(
|
||||||
|
const_cast<vertex_t*>(vertices.data()),
|
||||||
|
static_cast<int>(vertices.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec4 execute_stroke_preview_sample_pass(
|
||||||
|
std::array<vertex_t, 4>& vertices,
|
||||||
|
glm::vec2 target_size,
|
||||||
|
Texture2D& blend_texture,
|
||||||
|
DynamicShape& brush_shape,
|
||||||
|
bool copy_stroke_destination)
|
||||||
|
{
|
||||||
|
const auto sample_points = make_stroke_preview_sample_points(vertices);
|
||||||
|
const auto result = pp::panopainter::execute_legacy_canvas_stroke_sample(
|
||||||
|
pp::panopainter::LegacyStrokeSampleExecutionRequest {
|
||||||
|
.context = "NodeStrokePreview::stroke_draw_samples",
|
||||||
|
.target_size = target_size,
|
||||||
|
.vertices = vertices,
|
||||||
|
.sample_points = sample_points,
|
||||||
|
.copy_stroke_destination = copy_stroke_destination,
|
||||||
|
.bind_destination_texture = [&] {
|
||||||
|
bind_stroke_preview_destination_texture(blend_texture);
|
||||||
|
},
|
||||||
|
.copy_framebuffer_to_destination_texture = [](
|
||||||
|
int src_x,
|
||||||
|
int src_y,
|
||||||
|
int dst_x,
|
||||||
|
int dst_y,
|
||||||
|
int width,
|
||||||
|
int height) {
|
||||||
|
copy_stroke_preview_destination_texture_region(
|
||||||
|
src_x,
|
||||||
|
src_y,
|
||||||
|
dst_x,
|
||||||
|
dst_y,
|
||||||
|
width,
|
||||||
|
height);
|
||||||
|
},
|
||||||
|
.unbind_destination_texture = [&] {
|
||||||
|
unbind_stroke_preview_destination_texture(blend_texture);
|
||||||
|
},
|
||||||
|
.upload_brush_vertices = [&](std::span<const vertex_t> brush_vertices) {
|
||||||
|
upload_stroke_preview_brush_vertices(brush_shape, brush_vertices);
|
||||||
|
},
|
||||||
|
.draw_brush_shape = [&] {
|
||||||
|
brush_shape.draw_fill();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return result.dirty_bounds;
|
||||||
|
}
|
||||||
|
|
||||||
void execute_stroke_preview_background_capture_pass(
|
void execute_stroke_preview_background_capture_pass(
|
||||||
glm::vec2 size,
|
glm::vec2 size,
|
||||||
bool colorize,
|
bool colorize,
|
||||||
@@ -486,48 +573,12 @@ glm::vec4 NodeStrokePreview::stroke_draw_samples(
|
|||||||
bool copy_stroke_destination)
|
bool copy_stroke_destination)
|
||||||
{
|
{
|
||||||
const glm::vec2 size = { m_rtt.getWidth(), m_rtt.getHeight() };
|
const glm::vec2 size = { m_rtt.getWidth(), m_rtt.getHeight() };
|
||||||
const std::array<pp::paint_renderer::CanvasStrokePoint, 4> sample_points {
|
return execute_stroke_preview_sample_pass(
|
||||||
pp::paint_renderer::CanvasStrokePoint { .x = P[0].pos.x, .y = P[0].pos.y },
|
P,
|
||||||
pp::paint_renderer::CanvasStrokePoint { .x = P[1].pos.x, .y = P[1].pos.y },
|
size,
|
||||||
pp::paint_renderer::CanvasStrokePoint { .x = P[2].pos.x, .y = P[2].pos.y },
|
blend_tex,
|
||||||
pp::paint_renderer::CanvasStrokePoint { .x = P[3].pos.x, .y = P[3].pos.y },
|
m_brush_shape,
|
||||||
};
|
copy_stroke_destination);
|
||||||
const auto result = pp::panopainter::execute_legacy_canvas_stroke_sample(
|
|
||||||
pp::panopainter::LegacyStrokeSampleExecutionRequest {
|
|
||||||
.context = "NodeStrokePreview::stroke_draw_samples",
|
|
||||||
.target_size = size,
|
|
||||||
.vertices = P,
|
|
||||||
.sample_points = sample_points,
|
|
||||||
.copy_stroke_destination = copy_stroke_destination,
|
|
||||||
.bind_destination_texture = [&] {
|
|
||||||
set_active_texture_unit(1U);
|
|
||||||
blend_tex.bind(); // bg, copy of framebuffer (copied before drawing)
|
|
||||||
},
|
|
||||||
.copy_framebuffer_to_destination_texture = [](
|
|
||||||
int src_x,
|
|
||||||
int src_y,
|
|
||||||
int dst_x,
|
|
||||||
int dst_y,
|
|
||||||
int width,
|
|
||||||
int height) {
|
|
||||||
// this is also used by the mixer
|
|
||||||
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
|
||||||
},
|
|
||||||
.unbind_destination_texture = [&] {
|
|
||||||
set_active_texture_unit(1U);
|
|
||||||
blend_tex.unbind();
|
|
||||||
},
|
|
||||||
.upload_brush_vertices = [&](std::span<const vertex_t> vertices) {
|
|
||||||
m_brush_shape.update_vertices(
|
|
||||||
const_cast<vertex_t*>(vertices.data()),
|
|
||||||
static_cast<int>(vertices.size()));
|
|
||||||
},
|
|
||||||
.draw_brush_shape = [&] {
|
|
||||||
m_brush_shape.draw_fill();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return result.dirty_bounds;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compute(Stroke& stroke, float zoom) const
|
std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compute(Stroke& stroke, float zoom) const
|
||||||
|
|||||||
Reference in New Issue
Block a user