Extract canvas document IO and preview pass setup
This commit is contained in:
@@ -22,6 +22,7 @@ set(PP_LEGACY_PAINT_DOCUMENT_SOURCES
|
||||
src/canvas.cpp
|
||||
src/canvas_actions.cpp
|
||||
src/canvas_layer.cpp
|
||||
src/legacy_canvas_document_io_services.cpp
|
||||
src/legacy_canvas_state_services.cpp
|
||||
src/event.cpp
|
||||
)
|
||||
|
||||
@@ -79,13 +79,13 @@ What is still carrying too much live ownership:
|
||||
|
||||
Current hotspot files:
|
||||
|
||||
- `src/canvas.cpp`: 3622 lines
|
||||
- `src/canvas.cpp`: 2645 lines
|
||||
- `src/app_layout.cpp`: 1498 lines
|
||||
- `src/canvas_modes.cpp`: 1798 lines
|
||||
- `src/node.cpp`: 1551 lines
|
||||
- `src/main.cpp`: 1374 lines
|
||||
- `src/node_panel_brush.cpp`: 1197 lines
|
||||
- `src/node_stroke_preview.cpp`: 1129 lines
|
||||
- `src/node_stroke_preview.cpp`: 933 lines
|
||||
- `src/node_canvas.cpp`: 888 lines
|
||||
- `src/app.cpp`: 950 lines
|
||||
- `src/app_dialogs.cpp`: 908 lines
|
||||
@@ -155,8 +155,11 @@ Current architecture mismatches that must be treated as real blockers:
|
||||
canvas state-management cluster for picking, clear/clear-all, layer
|
||||
add/remove/order/lookups, animation frame control, resize, and snapshot
|
||||
save/restore now lives in `src/legacy_canvas_state_services.cpp` instead of
|
||||
`src/canvas.cpp`, even though the bridge still owns worker-side readback flow
|
||||
and encoder-state label reads.
|
||||
`src/canvas.cpp`, while the larger import/export/save/open/thumbnail
|
||||
document-IO cluster now lives in `src/legacy_canvas_document_io_services.cpp`
|
||||
and `NodeStrokePreview` render-target setup plus immediate-pass sequencing
|
||||
now route through retained preview execution helpers, even though the bridge
|
||||
still owns worker-side readback flow and encoder-state label reads.
|
||||
- Modern C++23 usage exists in extracted components, especially `std::span`,
|
||||
explicit result/status objects, and a few concepts, but the live app still
|
||||
does not consistently express ownership, thread affinity, or renderer
|
||||
|
||||
@@ -91,7 +91,7 @@ Status: In Progress
|
||||
|
||||
Why now:
|
||||
`src/canvas.cpp` is still the biggest single architectural blocker at about
|
||||
3622 lines.
|
||||
2645 lines.
|
||||
|
||||
Current slice:
|
||||
- Canvas state-management helpers for picking, clear/clear-all, layer
|
||||
@@ -99,6 +99,10 @@ Current slice:
|
||||
save/restore now live in `src/legacy_canvas_state_services.cpp` instead of
|
||||
staying inline in `src/canvas.cpp`, but the file still owns the larger
|
||||
document-plus-render shell.
|
||||
- Canvas import/export/save/open/thumbnail ownership now lives in
|
||||
`src/legacy_canvas_document_io_services.cpp` instead of staying inline in
|
||||
`src/canvas.cpp`, which materially reduces document IO ownership in the live
|
||||
render shell.
|
||||
|
||||
Write scope:
|
||||
- `src/canvas.cpp`
|
||||
@@ -138,6 +142,12 @@ Current slice:
|
||||
- `NodeStrokePreview` final composite plus preview-texture copy now route
|
||||
through `legacy_node_stroke_preview_execution_services.h`, but the preview
|
||||
node still owns most live-pass and retained GL resource execution.
|
||||
- `NodeStrokePreview` render-target setup plus immediate-pass sequence
|
||||
orchestration now also route through
|
||||
`legacy_node_stroke_preview_execution_services.h`, and duplicate render-
|
||||
target setup was removed from `render_to_image()` and the queued worker path,
|
||||
but the preview node still owns broader live-pass state and thread-facing
|
||||
orchestration.
|
||||
- `NodeCanvas` merged-path per-plane merged-texture draw execution now also
|
||||
routes through `execute_legacy_canvas_draw_merge_layer_texture(...)`.
|
||||
- `NodeCanvas` merged-path and non-blend checkerboard background setup now also
|
||||
|
||||
1097
src/canvas.cpp
1097
src/canvas.cpp
File diff suppressed because it is too large
Load Diff
1195
src/legacy_canvas_document_io_services.cpp
Normal file
1195
src/legacy_canvas_document_io_services.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -148,6 +148,40 @@ struct LegacyNodeStrokePreviewPassOrchestrationPlan {
|
||||
bool background_colorize = false;
|
||||
};
|
||||
|
||||
struct LegacyNodeStrokePreviewRenderTargetSetup {
|
||||
RTT& preview_rtt;
|
||||
RTT& preview_rtt_mixer;
|
||||
Texture2D& preview_stroke_texture;
|
||||
Texture2D& preview_dual_texture;
|
||||
Texture2D& preview_background_texture;
|
||||
Texture2D& preview_image_texture;
|
||||
glm::vec2 size {};
|
||||
};
|
||||
|
||||
[[nodiscard]] inline bool ensure_legacy_node_stroke_preview_render_targets(
|
||||
const LegacyNodeStrokePreviewRenderTargetSetup& setup)
|
||||
{
|
||||
if (setup.size.x <= 0.0f || setup.size.y <= 0.0f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto width = static_cast<int>(setup.size.x);
|
||||
const auto height = static_cast<int>(setup.size.y);
|
||||
|
||||
if (!setup.preview_image_texture.ready() || setup.preview_image_texture.size() != setup.size) {
|
||||
setup.preview_image_texture.create(width, height);
|
||||
}
|
||||
if (setup.preview_stroke_texture.size() != setup.size) {
|
||||
setup.preview_rtt.create(width, height);
|
||||
setup.preview_rtt_mixer.create(width, height);
|
||||
setup.preview_stroke_texture.create(width, height);
|
||||
setup.preview_dual_texture.create(width, height);
|
||||
setup.preview_background_texture.create(width, height);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct LegacyNodeStrokePreviewMainPassTextureDispatch {
|
||||
std::function<void(int)> activate_texture_unit;
|
||||
std::function<void()> bind_brush_tip;
|
||||
@@ -245,6 +279,34 @@ template <typename Frame>
|
||||
return true;
|
||||
}
|
||||
|
||||
struct LegacyNodeStrokePreviewImmediatePassSequenceRequest {
|
||||
std::function<void()> execute_dual_pass;
|
||||
std::function<void()> capture_background;
|
||||
std::function<bool()> execute_main_live_pass;
|
||||
std::function<bool()> execute_final_composite;
|
||||
};
|
||||
|
||||
[[nodiscard]] inline bool execute_legacy_node_stroke_preview_immediate_pass_sequence(
|
||||
const LegacyNodeStrokePreviewImmediatePassSequenceRequest& request)
|
||||
{
|
||||
if (!request.capture_background ||
|
||||
!request.execute_main_live_pass ||
|
||||
!request.execute_final_composite) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (request.execute_dual_pass) {
|
||||
request.execute_dual_pass();
|
||||
}
|
||||
|
||||
request.capture_background();
|
||||
if (!request.execute_main_live_pass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return request.execute_final_composite();
|
||||
}
|
||||
|
||||
[[nodiscard]] inline bool execute_legacy_node_stroke_preview_final_composite(
|
||||
glm::vec2 size,
|
||||
glm::vec2 pattern_scale,
|
||||
|
||||
@@ -588,6 +588,19 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
if (m_size.x == 0 || m_size.y == 0)
|
||||
return;
|
||||
|
||||
if (!pp::panopainter::ensure_legacy_node_stroke_preview_render_targets(
|
||||
pp::panopainter::LegacyNodeStrokePreviewRenderTargetSetup {
|
||||
.preview_rtt = m_rtt,
|
||||
.preview_rtt_mixer = m_rtt_mixer,
|
||||
.preview_stroke_texture = m_tex,
|
||||
.preview_dual_texture = m_tex_dual,
|
||||
.preview_background_texture = m_tex_background,
|
||||
.preview_image_texture = m_tex_preview,
|
||||
.size = m_preview_size,
|
||||
})) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto vp = query_stroke_preview_viewport();
|
||||
const auto cc = query_stroke_preview_clear_color();
|
||||
|
||||
@@ -665,8 +678,6 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
m_dual_stroke.add_point(point.position, point.pressure);
|
||||
}
|
||||
|
||||
const glm::vec2 patt_scale = stroke_setup.pattern_scale;
|
||||
|
||||
apply_stroke_preview_capability(pp::renderer::gl::blend_state(), false);
|
||||
const auto pass_orchestration = pp::panopainter::plan_legacy_node_stroke_preview_pass_orchestration(
|
||||
pp::panopainter::LegacyNodeStrokePreviewPassOrchestrationRequest {
|
||||
@@ -696,64 +707,64 @@ void NodeStrokePreview::draw_stroke_immediate()
|
||||
const auto& material = pass_orchestration.material;
|
||||
pp::panopainter::setup_legacy_stroke_shader(pass_orchestration.stroke_shader);
|
||||
|
||||
const bool sequence_ok = [&] {
|
||||
if (pass_orchestration.material.dual_pass.enabled) {
|
||||
pp::panopainter::setup_legacy_stroke_dual_shader(
|
||||
pass_orchestration.material.dual_pass.uses_pattern);
|
||||
bind_stroke_preview_dual_pass_textures(*dual_brush);
|
||||
execute_stroke_draw_immediate_dual_pass(
|
||||
m_dual_stroke,
|
||||
*b,
|
||||
pass_orchestration,
|
||||
std::move(dual_brush),
|
||||
copy_stroke_destination,
|
||||
zoom,
|
||||
size);
|
||||
}
|
||||
const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_immediate_pass_sequence(
|
||||
pp::panopainter::LegacyNodeStrokePreviewImmediatePassSequenceRequest {
|
||||
.execute_dual_pass = [&] {
|
||||
if (!pass_orchestration.material.dual_pass.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
execute_stroke_preview_background_capture_pass(
|
||||
size,
|
||||
pass_orchestration.background_colorize,
|
||||
m_tex_background,
|
||||
[&] {
|
||||
m_plane.draw_fill();
|
||||
});
|
||||
|
||||
[[maybe_unused]] const bool main_live_ok =
|
||||
pp::panopainter::execute_legacy_node_stroke_preview_main_live_pass(
|
||||
make_stroke_draw_immediate_main_live_pass_request(
|
||||
m_stroke,
|
||||
pp::panopainter::setup_legacy_stroke_dual_shader(
|
||||
pass_orchestration.material.dual_pass.uses_pattern);
|
||||
bind_stroke_preview_dual_pass_textures(*dual_brush);
|
||||
execute_stroke_draw_immediate_dual_pass(
|
||||
m_dual_stroke,
|
||||
*b,
|
||||
pass_orchestration,
|
||||
std::move(dual_brush),
|
||||
copy_stroke_destination,
|
||||
zoom,
|
||||
size));
|
||||
if (!main_live_ok) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool final_composite_ok = pp::panopainter::execute_legacy_node_stroke_preview_final_composite(
|
||||
size,
|
||||
glm::vec2(b->m_pattern_scale),
|
||||
*b,
|
||||
material.composite_pass,
|
||||
m_tex_background,
|
||||
m_tex,
|
||||
m_tex_dual,
|
||||
m_tex_preview,
|
||||
m_sampler_linear,
|
||||
m_sampler_linear_repeat,
|
||||
[&] {
|
||||
b->m_pattern_texture ? b->m_pattern_texture->bind() : unbind_texture_2d();
|
||||
size);
|
||||
},
|
||||
[&] {
|
||||
m_plane.draw_fill();
|
||||
});
|
||||
if (!final_composite_ok) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
.capture_background = [&] {
|
||||
execute_stroke_preview_background_capture_pass(
|
||||
size,
|
||||
pass_orchestration.background_colorize,
|
||||
m_tex_background,
|
||||
[&] {
|
||||
m_plane.draw_fill();
|
||||
});
|
||||
},
|
||||
.execute_main_live_pass = [&]() -> bool {
|
||||
return pp::panopainter::execute_legacy_node_stroke_preview_main_live_pass(
|
||||
make_stroke_draw_immediate_main_live_pass_request(
|
||||
m_stroke,
|
||||
*b,
|
||||
pass_orchestration,
|
||||
copy_stroke_destination,
|
||||
zoom,
|
||||
size));
|
||||
},
|
||||
.execute_final_composite = [&]() -> bool {
|
||||
return pp::panopainter::execute_legacy_node_stroke_preview_final_composite(
|
||||
size,
|
||||
glm::vec2(b->m_pattern_scale),
|
||||
*b,
|
||||
material.composite_pass,
|
||||
m_tex_background,
|
||||
m_tex,
|
||||
m_tex_dual,
|
||||
m_tex_preview,
|
||||
m_sampler_linear,
|
||||
m_sampler_linear_repeat,
|
||||
[&] {
|
||||
b->m_pattern_texture ? b->m_pattern_texture->bind() : unbind_texture_2d();
|
||||
},
|
||||
[&] {
|
||||
m_plane.draw_fill();
|
||||
});
|
||||
},
|
||||
});
|
||||
assert(sequence_ok);
|
||||
|
||||
m_rtt.unbindFramebuffer();
|
||||
@@ -888,17 +899,6 @@ Image NodeStrokePreview::render_to_image()
|
||||
std::lock_guard<std::mutex> _lock(s_render_mutex);
|
||||
|
||||
App::I->render_task([this] {
|
||||
auto new_size = m_preview_size;
|
||||
if (!m_tex_preview.ready() || m_tex_preview.size() != new_size)
|
||||
m_tex_preview.create((int)new_size.x, (int)new_size.y);
|
||||
if (m_tex.size() != new_size)
|
||||
{
|
||||
m_rtt.create((int)new_size.x, (int)new_size.y);
|
||||
m_rtt_mixer.create((int)new_size.x, (int)new_size.y);
|
||||
m_tex.create((int)new_size.x, (int)new_size.y);
|
||||
m_tex_dual.create((int)new_size.x, (int)new_size.y);
|
||||
m_tex_background.create((int)new_size.x, (int)new_size.y);
|
||||
}
|
||||
draw_stroke_immediate();
|
||||
});
|
||||
return m_tex_preview.get_image();
|
||||
@@ -940,18 +940,6 @@ void NodeStrokePreview::draw_stroke()
|
||||
gl_state gl;
|
||||
gl.save();
|
||||
|
||||
auto new_size = node->m_preview_size;
|
||||
if (!node->m_tex_preview.ready() || node->m_tex_preview.size() != new_size)
|
||||
node->m_tex_preview.create((int)new_size.x, (int)new_size.y);
|
||||
if (m_tex.size() != new_size)
|
||||
{
|
||||
m_rtt.create((int)new_size.x, (int)new_size.y);
|
||||
m_rtt_mixer.create((int)new_size.x, (int)new_size.y);
|
||||
m_tex.create((int)new_size.x, (int)new_size.y);
|
||||
m_tex_dual.create((int)new_size.x, (int)new_size.y);
|
||||
m_tex_background.create((int)new_size.x, (int)new_size.y);
|
||||
}
|
||||
|
||||
node->m_brush->load();
|
||||
node->draw_stroke_immediate();
|
||||
if (to_unload)
|
||||
|
||||
Reference in New Issue
Block a user