Extract preview final composite orchestration
This commit is contained in:
@@ -18,6 +18,10 @@ agent or engineer to remove them without reconstructing context from chat.
|
|||||||
|
|
||||||
## Recent Reductions
|
## Recent Reductions
|
||||||
|
|
||||||
|
- 2026-06-13: DEBT-0036 was narrowed again. `NodeStrokePreview::draw_stroke_immediate()`
|
||||||
|
now routes final-composite setup and preview copy-back through retained
|
||||||
|
helpers in `legacy_node_stroke_preview_execution_services.h`; the retained
|
||||||
|
path still owns the concrete texture objects and pass-order wiring.
|
||||||
- 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 main-pass texture binding through
|
now routes main-pass texture binding through
|
||||||
`bind_legacy_node_stroke_preview_main_pass_textures(...)`; the retained path
|
`bind_legacy_node_stroke_preview_main_pass_textures(...)`; the retained path
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#include "legacy_canvas_stroke_shader_services.h"
|
#include "legacy_canvas_stroke_shader_services.h"
|
||||||
#include "legacy_canvas_stroke_services.h"
|
#include "legacy_canvas_stroke_services.h"
|
||||||
#include "paint_renderer/compositor.h"
|
#include "paint_renderer/compositor.h"
|
||||||
|
#include "texture.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@@ -242,6 +243,69 @@ struct LegacyNodeStrokePreviewMainPassTextureDispatch {
|
|||||||
std::function<void()> bind_mixer;
|
std::function<void()> bind_mixer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct LegacyNodeStrokePreviewFinalCompositeRequest {
|
||||||
|
glm::vec2 resolution {};
|
||||||
|
glm::vec2 pattern_scale {};
|
||||||
|
const Brush* brush = nullptr;
|
||||||
|
const pp::paint_renderer::CanvasStrokeCompositePassPlan* composite_pass = nullptr;
|
||||||
|
std::function<void()> setup_composite_shader;
|
||||||
|
std::function<void()> bind_composite_samplers;
|
||||||
|
std::function<void()> bind_composite_inputs;
|
||||||
|
std::function<void()> draw_composite;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool execute_legacy_node_stroke_preview_final_composite(
|
||||||
|
const LegacyNodeStrokePreviewFinalCompositeRequest& request)
|
||||||
|
{
|
||||||
|
if (!request.brush ||
|
||||||
|
!request.composite_pass ||
|
||||||
|
!request.setup_composite_shader ||
|
||||||
|
!request.bind_composite_samplers ||
|
||||||
|
!request.bind_composite_inputs ||
|
||||||
|
!request.draw_composite) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
pp::panopainter::execute_legacy_stroke_preview_final_composite(
|
||||||
|
[&] {
|
||||||
|
request.setup_composite_shader();
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
|
request.bind_composite_samplers();
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
|
request.bind_composite_inputs();
|
||||||
|
},
|
||||||
|
[&] {
|
||||||
|
request.draw_composite();
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LegacyNodeStrokePreviewCopyResultRequest {
|
||||||
|
Texture2D* preview_texture = nullptr;
|
||||||
|
glm::vec2 size {};
|
||||||
|
std::function<void(int, int, int, int, int, int)> copy_framebuffer_to_texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] inline bool copy_legacy_node_stroke_preview_result(
|
||||||
|
const LegacyNodeStrokePreviewCopyResultRequest& request)
|
||||||
|
{
|
||||||
|
if (!request.preview_texture || !request.copy_framebuffer_to_texture) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pp::panopainter::copy_legacy_stroke_preview_texture(
|
||||||
|
[&] {
|
||||||
|
request.preview_texture->bind();
|
||||||
|
},
|
||||||
|
request.copy_framebuffer_to_texture,
|
||||||
|
pp::panopainter::LegacyStrokePreviewCopySize {
|
||||||
|
.width = static_cast<int>(request.size.x),
|
||||||
|
.height = static_cast<int>(request.size.y),
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] inline LegacyNodeStrokePreviewMainPassTextureDispatch make_legacy_node_stroke_preview_main_pass_texture_dispatch(
|
[[nodiscard]] inline LegacyNodeStrokePreviewMainPassTextureDispatch make_legacy_node_stroke_preview_main_pass_texture_dispatch(
|
||||||
std::function<void(int)> activate_texture_unit,
|
std::function<void(int)> activate_texture_unit,
|
||||||
std::function<void()> bind_brush_tip,
|
std::function<void()> bind_brush_tip,
|
||||||
|
|||||||
@@ -151,8 +151,14 @@ pp::panopainter::LegacyStrokeCompositeUniforms make_stroke_preview_mix_composite
|
|||||||
|
|
||||||
void execute_stroke_preview_final_composite_pass(const StrokePreviewCompositePassInputs& inputs)
|
void execute_stroke_preview_final_composite_pass(const StrokePreviewCompositePassInputs& inputs)
|
||||||
{
|
{
|
||||||
pp::panopainter::execute_legacy_stroke_preview_final_composite(
|
[[maybe_unused]] const bool composite_ok =
|
||||||
[&] {
|
pp::panopainter::execute_legacy_node_stroke_preview_final_composite(
|
||||||
|
pp::panopainter::LegacyNodeStrokePreviewFinalCompositeRequest {
|
||||||
|
.resolution = inputs.resolution,
|
||||||
|
.pattern_scale = inputs.pattern_scale,
|
||||||
|
.brush = &inputs.brush,
|
||||||
|
.composite_pass = &inputs.composite_pass,
|
||||||
|
.setup_composite_shader = [&] {
|
||||||
pp::panopainter::setup_legacy_stroke_composite_shader(
|
pp::panopainter::setup_legacy_stroke_composite_shader(
|
||||||
pp::panopainter::LegacyStrokeCompositeUniforms {
|
pp::panopainter::LegacyStrokeCompositeUniforms {
|
||||||
.resolution = inputs.resolution,
|
.resolution = inputs.resolution,
|
||||||
@@ -177,14 +183,14 @@ void execute_stroke_preview_final_composite_pass(const StrokePreviewCompositePas
|
|||||||
.use_pattern = inputs.composite_pass.use_pattern,
|
.use_pattern = inputs.composite_pass.use_pattern,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[&] {
|
.bind_composite_samplers = [&] {
|
||||||
inputs.linear_sampler.bind(stroke_preview_composite_slots::kBackground);
|
inputs.linear_sampler.bind(stroke_preview_composite_slots::kBackground);
|
||||||
inputs.linear_sampler.bind(stroke_preview_composite_slots::kStroke);
|
inputs.linear_sampler.bind(stroke_preview_composite_slots::kStroke);
|
||||||
inputs.linear_sampler.bind(2U);
|
inputs.linear_sampler.bind(2U);
|
||||||
inputs.linear_sampler.bind(stroke_preview_composite_slots::kDual);
|
inputs.linear_sampler.bind(stroke_preview_composite_slots::kDual);
|
||||||
inputs.repeat_sampler.bind(stroke_preview_composite_slots::kPattern);
|
inputs.repeat_sampler.bind(stroke_preview_composite_slots::kPattern);
|
||||||
},
|
},
|
||||||
[&] {
|
.bind_composite_inputs = [&] {
|
||||||
set_active_texture_unit(stroke_preview_composite_slots::kBackground);
|
set_active_texture_unit(stroke_preview_composite_slots::kBackground);
|
||||||
inputs.background_texture.bind();
|
inputs.background_texture.bind();
|
||||||
set_active_texture_unit(stroke_preview_composite_slots::kStroke);
|
set_active_texture_unit(stroke_preview_composite_slots::kStroke);
|
||||||
@@ -196,9 +202,11 @@ void execute_stroke_preview_final_composite_pass(const StrokePreviewCompositePas
|
|||||||
inputs.brush.m_pattern_texture->bind() :
|
inputs.brush.m_pattern_texture->bind() :
|
||||||
unbind_texture_2d();
|
unbind_texture_2d();
|
||||||
},
|
},
|
||||||
[&] {
|
.draw_composite = [&] {
|
||||||
inputs.draw_composite();
|
inputs.draw_composite();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
assert(composite_ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_stroke_preview_framebuffer_to_texture(
|
void copy_stroke_preview_framebuffer_to_texture(
|
||||||
@@ -394,11 +402,12 @@ void execute_stroke_preview_background_capture_pass(
|
|||||||
|
|
||||||
void copy_stroke_preview_result_to_texture(Texture2D& preview_texture, glm::vec2 size)
|
void copy_stroke_preview_result_to_texture(Texture2D& preview_texture, glm::vec2 size)
|
||||||
{
|
{
|
||||||
pp::panopainter::copy_legacy_stroke_preview_texture(
|
[[maybe_unused]] const bool copy_ok =
|
||||||
[&] {
|
pp::panopainter::copy_legacy_node_stroke_preview_result(
|
||||||
preview_texture.bind();
|
pp::panopainter::LegacyNodeStrokePreviewCopyResultRequest {
|
||||||
},
|
.preview_texture = &preview_texture,
|
||||||
[](
|
.size = size,
|
||||||
|
.copy_framebuffer_to_texture = [](
|
||||||
int src_x,
|
int src_x,
|
||||||
int src_y,
|
int src_y,
|
||||||
int dst_x,
|
int dst_x,
|
||||||
@@ -407,10 +416,8 @@ void copy_stroke_preview_result_to_texture(Texture2D& preview_texture, glm::vec2
|
|||||||
int height) {
|
int height) {
|
||||||
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
copy_framebuffer_to_texture_2d(src_x, src_y, dst_x, dst_y, width, height);
|
||||||
},
|
},
|
||||||
pp::panopainter::LegacyStrokePreviewCopySize {
|
|
||||||
.width = static_cast<int>(size.x),
|
|
||||||
.height = static_cast<int>(size.y),
|
|
||||||
});
|
});
|
||||||
|
assert(copy_ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2659,6 +2659,58 @@ void legacy_node_stroke_preview_main_pass_texture_dispatch_preserves_order(pp::t
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void legacy_node_stroke_preview_final_composite_and_copy_helpers_preserve_order(pp::tests::Harness& h)
|
||||||
|
{
|
||||||
|
std::vector<std::string> steps;
|
||||||
|
const bool composite_ok = pp::panopainter::execute_legacy_node_stroke_preview_final_composite(
|
||||||
|
pp::panopainter::LegacyNodeStrokePreviewFinalCompositeRequest {
|
||||||
|
.resolution = glm::vec2(64.0F, 32.0F),
|
||||||
|
.pattern_scale = glm::vec2(0.25F, -0.5F),
|
||||||
|
.brush = reinterpret_cast<const Brush*>(1),
|
||||||
|
.composite_pass = reinterpret_cast<const pp::paint_renderer::CanvasStrokeCompositePassPlan*>(1),
|
||||||
|
.setup_composite_shader = [&] {
|
||||||
|
steps.emplace_back("setup");
|
||||||
|
},
|
||||||
|
.bind_composite_samplers = [&] {
|
||||||
|
steps.emplace_back("bind_samplers");
|
||||||
|
},
|
||||||
|
.bind_composite_inputs = [&] {
|
||||||
|
steps.emplace_back("bind_inputs");
|
||||||
|
},
|
||||||
|
.draw_composite = [&] {
|
||||||
|
steps.emplace_back("draw");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
PP_EXPECT(h, composite_ok);
|
||||||
|
PP_EXPECT(h, steps == std::vector<std::string> {
|
||||||
|
"setup",
|
||||||
|
"bind_samplers",
|
||||||
|
"bind_inputs",
|
||||||
|
"draw",
|
||||||
|
});
|
||||||
|
|
||||||
|
steps.clear();
|
||||||
|
const bool copy_ok = pp::panopainter::copy_legacy_node_stroke_preview_result(
|
||||||
|
pp::panopainter::LegacyNodeStrokePreviewCopyResultRequest {
|
||||||
|
.preview_texture = reinterpret_cast<Texture2D*>(1),
|
||||||
|
.size = glm::vec2(32.0F, 16.0F),
|
||||||
|
.copy_framebuffer_to_texture = [&](int src_x, int src_y, int dst_x, int dst_y, int width, int height) {
|
||||||
|
steps.emplace_back(
|
||||||
|
"copy:" +
|
||||||
|
std::to_string(src_x) + "," +
|
||||||
|
std::to_string(src_y) + "," +
|
||||||
|
std::to_string(dst_x) + "," +
|
||||||
|
std::to_string(dst_y) + "," +
|
||||||
|
std::to_string(width) + "," +
|
||||||
|
std::to_string(height));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
PP_EXPECT(h, copy_ok);
|
||||||
|
PP_EXPECT(h, steps == std::vector<std::string> {
|
||||||
|
"copy:0,0,0,0,32,16",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs(pp::tests::Harness& h)
|
void legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs(pp::tests::Harness& h)
|
||||||
{
|
{
|
||||||
const auto plan = pp::panopainter::plan_legacy_node_stroke_preview_stroke_setup(
|
const auto plan = pp::panopainter::plan_legacy_node_stroke_preview_stroke_setup(
|
||||||
@@ -3255,6 +3307,9 @@ int main()
|
|||||||
harness.run(
|
harness.run(
|
||||||
"legacy_node_stroke_preview_main_pass_texture_dispatch_preserves_order",
|
"legacy_node_stroke_preview_main_pass_texture_dispatch_preserves_order",
|
||||||
legacy_node_stroke_preview_main_pass_texture_dispatch_preserves_order);
|
legacy_node_stroke_preview_main_pass_texture_dispatch_preserves_order);
|
||||||
|
harness.run(
|
||||||
|
"legacy_node_stroke_preview_final_composite_and_copy_helpers_preserve_order",
|
||||||
|
legacy_node_stroke_preview_final_composite_and_copy_helpers_preserve_order);
|
||||||
harness.run(
|
harness.run(
|
||||||
"legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs",
|
"legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs",
|
||||||
legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs);
|
legacy_node_stroke_preview_stroke_setup_plan_preserves_curve_and_dual_inputs);
|
||||||
|
|||||||
Reference in New Issue
Block a user