Thin Windows entry, preview shell, and platform legacy state

This commit is contained in:
2026-06-17 00:42:50 +02:00
parent 9b1e593477
commit 5fdc9a9dd6
17 changed files with 368 additions and 216 deletions

View File

@@ -166,6 +166,8 @@ set(PP_PANOPAINTER_APP_SOURCES
src/legacy_document_session_services.h src/legacy_document_session_services.h
src/platform_legacy/legacy_platform_services.cpp src/platform_legacy/legacy_platform_services.cpp
src/platform_legacy/legacy_platform_services.h src/platform_legacy/legacy_platform_services.h
src/platform_legacy/legacy_platform_state.cpp
src/platform_legacy/legacy_platform_state.h
src/version.cpp src/version.cpp
) )

View File

@@ -1,7 +1,7 @@
# PanoPainter Modernization Roadmap # PanoPainter Modernization Roadmap
Status: live Status: live
Last updated: 2026-06-16 Last updated: 2026-06-17
This roadmap is now architecture-first. This roadmap is now architecture-first.
The active execution queue lives in `docs/modernization/tasks.md`. The active execution queue lives in `docs/modernization/tasks.md`.
@@ -80,18 +80,34 @@ What is still carrying too much live ownership:
Current hotspot files: Current hotspot files:
- `src/canvas.cpp`: 17 lines - `src/canvas.cpp`: 17 lines
- `src/app_layout.cpp`: 125 lines - `src/app_layout.cpp`: 109 lines
- `src/canvas_modes.cpp`: 1 line - `src/canvas_modes.cpp`: 1 line
- `src/node.cpp`: 12 lines - `src/node.cpp`: 12 lines
- `src/main.cpp`: 87 lines - `src/main.cpp`: 10 lines
- `src/node_panel_brush.cpp`: 2 lines - `src/node_panel_brush.cpp`: 2 lines
- `src/node_stroke_preview.cpp`: 160 lines - `src/node_stroke_preview.cpp`: 76 lines
- `src/node_canvas.cpp`: 85 lines - `src/node_canvas.cpp`: 69 lines
- `src/app.cpp`: 94 lines - `src/app.cpp`: 94 lines
- `src/app_dialogs.cpp`: 95 lines - `src/app_dialogs.cpp`: 95 lines
Latest slice: Latest slice:
- The live Windows entry shell now routes through
`run_main_application(...)` in
`src/platform_windows/windows_runtime_shell.*`, leaving `src/main.cpp` as a
minimal entry wrapper around `main(...)` and `WinMain(...)`.
- Retained legacy storage-path state now lives in
`src/platform_legacy/legacy_platform_state.*` instead of staying inline in
`src/platform_legacy/legacy_platform_services.cpp`, which trims another
process-global platform-state pocket out of the legacy platform shell.
- The remaining `NodeStrokePreview` clone-init, stroke-frame planning,
mix-pass adapter wiring, sample-pass adapter wiring, and immediate-draw
request construction now route through
`src/legacy_node_stroke_preview_runtime_services.*`,
`src/legacy_node_stroke_preview_draw_services.*`, and
`src/legacy_node_stroke_preview_sample_services.*`, leaving
`src/node_stroke_preview.cpp` as a thinner live adapter.
- `NodeCanvas::handle_event()` now routes through - `NodeCanvas::handle_event()` now routes through
`handle_legacy_node_canvas_event(...)` in `handle_legacy_node_canvas_event(...)` in
`src/legacy_canvas_tool_services.*`, leaving `src/node_canvas.cpp` as a much `src/legacy_canvas_tool_services.*`, leaving `src/node_canvas.cpp` as a much

View File

@@ -1,7 +1,7 @@
# Modernization Task Tracker # Modernization Task Tracker
Status: live Status: live
Last updated: 2026-06-16 Last updated: 2026-06-17
This file now tracks only active architecture work. This file now tracks only active architecture work.
Completed, blocked, and superseded task history moved to Completed, blocked, and superseded task history moved to
@@ -36,10 +36,10 @@ Completed, blocked, and superseded task history moved to
- `pp_legacy_paint_document`: 7 files, about 5709 lines - `pp_legacy_paint_document`: 7 files, about 5709 lines
- `pp_legacy_app`: 20 files, about 4368 lines - `pp_legacy_app`: 20 files, about 4368 lines
- `pp_legacy_ui_core`: 20 files, about 3770 lines - `pp_legacy_ui_core`: 20 files, about 3770 lines
- The biggest single-file choke points are still `src/canvas_modes.cpp`, - The biggest remaining single-file pressure is no longer the old entrypoint
`src/node.cpp`, shell files; it now sits mostly in retained legacy service layers behind
`src/main.cpp`, `src/node_panel_brush.cpp`, `src/node_stroke_preview.cpp`, `src/node_stroke_preview.cpp`, `src/app.cpp`, `src/app_dialogs.cpp`, and the
`src/node_canvas.cpp`, `src/app.cpp`, and `src/app_dialogs.cpp`. extracted canvas/platform containment files.
- The platform boundary is not finished: - The platform boundary is not finished:
- `pp_platform_api` still compiles Apple implementation files - `pp_platform_api` still compiles Apple implementation files
- `platform_apple` no longer reaches `App::I` directly, and Linux FPS title - `platform_apple` no longer reaches `App::I` directly, and Linux FPS title
@@ -391,6 +391,13 @@ Current slice:
render-target validation, viewport/clear-color save-restore, and immediate render-target validation, viewport/clear-color save-restore, and immediate
runtime request assembly out of the live node file and leaves runtime request assembly out of the live node file and leaves
`src/node_stroke_preview.cpp` at 160 lines. `src/node_stroke_preview.cpp` at 160 lines.
- `NodeStrokePreview` clone-finalize setup, stroke-frame planning, mix-pass
adapter wiring, sample-pass adapter wiring, and the remaining
immediate-draw request construction now also route through
`src/legacy_node_stroke_preview_runtime_services.*`,
`src/legacy_node_stroke_preview_draw_services.*`, and
`src/legacy_node_stroke_preview_sample_services.*`, which leaves
`src/node_stroke_preview.cpp` at 76 lines.
- `CanvasModeGrid` plus `ActionModeGrid` undo/redo now also live in - `CanvasModeGrid` plus `ActionModeGrid` undo/redo now also live in
`src/legacy_canvas_mode_helpers.cpp` instead of staying inline in `src/legacy_canvas_mode_helpers.cpp` instead of staying inline in
`src/canvas_modes.cpp`, which leaves the live canvas-modes file as a `src/canvas_modes.cpp`, which leaves the live canvas-modes file as a
@@ -759,6 +766,9 @@ Current slice:
loop, and shutdown cleanup now also lives in loop, and shutdown cleanup now also lives in
`src/platform_windows/windows_runtime_shell.*` instead of `src/main.cpp`, `src/platform_windows/windows_runtime_shell.*` instead of `src/main.cpp`,
which reduces the entry TU to a much smaller composition root which reduces the entry TU to a much smaller composition root
- the remaining Windows app shell in `main(...)` now also routes through
`run_main_application(...)` in `src/platform_windows/windows_runtime_shell.*`,
which reduces `src/main.cpp` to a minimal `main`/`WinMain` wrapper
- prepared-file background work now runs through an `AppRuntime`-owned worker - prepared-file background work now runs through an `AppRuntime`-owned worker
queue instead of a retained static worker in `src/app_events.cpp` queue instead of a retained static worker in `src/app_events.cpp`
- canvas async import/export/save/open background work now also runs through an - canvas async import/export/save/open background work now also runs through an
@@ -1115,6 +1125,9 @@ Current slice:
- retained GLFW window hooks and the non-Linux fallback storage-path return now - retained GLFW window hooks and the non-Linux fallback storage-path return now
also route through retained local state helpers instead of reading `App::I` also route through retained local state helpers instead of reading `App::I`
directly in those method bodies directly in those method bodies
- retained storage-path state now also lives in
`src/platform_legacy/legacy_platform_state.*` instead of staying inline in
`src/platform_legacy/legacy_platform_services.cpp`
- retained Apple callback injection and broader `platform_legacy` singleton - retained Apple callback injection and broader `platform_legacy` singleton
reach are still open reach are still open
- The remaining Win32 shell wrappers for close, async lock/swap, - The remaining Win32 shell wrappers for close, async lock/swap,

View File

@@ -187,6 +187,33 @@ bool execute_legacy_node_stroke_preview_mix_pass(
return mix_result.ok; return mix_result.ok;
} }
bool execute_legacy_node_stroke_preview_mix_pass(
const Brush& brush,
glm::vec2 preview_size,
RTT& mixer_rtt,
glm::vec2 bb_min,
glm::vec2 bb_sz,
Sampler& linear_sampler,
Texture2D& background_texture,
Texture2D& stroke_texture,
Texture2D& dual_texture,
std::function<void()> draw_mix)
{
return execute_legacy_node_stroke_preview_mix_pass(
LegacyNodeStrokePreviewMixPassExecutionRequest {
.brush = brush,
.preview_size = preview_size,
.mixer_rtt = mixer_rtt,
.bb_min = bb_min,
.bb_sz = bb_sz,
.linear_sampler = linear_sampler,
.background_texture = background_texture,
.stroke_texture = stroke_texture,
.dual_texture = dual_texture,
.draw_mix = std::move(draw_mix),
});
}
bool has_valid_live_render_callbacks(const LegacyNodeStrokePreviewLiveRenderRequest& request) bool has_valid_live_render_callbacks(const LegacyNodeStrokePreviewLiveRenderRequest& request)
{ {
return request.bind_dual_pass_textures && return request.bind_dual_pass_textures &&

View File

@@ -61,6 +61,18 @@ struct LegacyNodeStrokePreviewMixPassExecutionRequest {
[[nodiscard]] bool execute_legacy_node_stroke_preview_mix_pass( [[nodiscard]] bool execute_legacy_node_stroke_preview_mix_pass(
const LegacyNodeStrokePreviewMixPassExecutionRequest& request); const LegacyNodeStrokePreviewMixPassExecutionRequest& request);
[[nodiscard]] bool execute_legacy_node_stroke_preview_mix_pass(
const Brush& brush,
glm::vec2 preview_size,
RTT& mixer_rtt,
glm::vec2 bb_min,
glm::vec2 bb_sz,
Sampler& linear_sampler,
Texture2D& background_texture,
Texture2D& stroke_texture,
Texture2D& dual_texture,
std::function<void()> draw_mix);
[[nodiscard]] bool execute_legacy_node_stroke_preview_live_render_passes( [[nodiscard]] bool execute_legacy_node_stroke_preview_live_render_passes(
const LegacyNodeStrokePreviewLiveRenderRequest& request); const LegacyNodeStrokePreviewLiveRenderRequest& request);

View File

@@ -14,6 +14,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 "legacy_node_stroke_preview_execution_services.h" #include "legacy_node_stroke_preview_execution_services.h"
#include "legacy_node_stroke_preview_sample_services.h"
#include "legacy_ui_gl_dispatch.h" #include "legacy_ui_gl_dispatch.h"
#include "paint_renderer/compositor.h" #include "paint_renderer/compositor.h"
#include "renderer_gl/opengl_capabilities.h" #include "renderer_gl/opengl_capabilities.h"
@@ -299,6 +300,19 @@ std::vector<LegacyNodeStrokePreviewFrame> plan_legacy_node_stroke_preview_stroke
}); });
} }
std::vector<LegacyNodeStrokePreviewFrame> plan_legacy_node_stroke_preview_stroke_frames(
const Stroke& stroke,
float zoom,
glm::vec2 mixer_size)
{
return plan_legacy_node_stroke_preview_stroke_frames(
LegacyNodeStrokePreviewStrokeComputeRequest {
.stroke = stroke,
.zoom = zoom,
.mixer_size = mixer_size,
});
}
bool execute_legacy_node_stroke_preview_immediate_runtime( bool execute_legacy_node_stroke_preview_immediate_runtime(
const LegacyNodeStrokePreviewImmediateRuntimeRequest& request) const LegacyNodeStrokePreviewImmediateRuntimeRequest& request)
{ {
@@ -375,6 +389,92 @@ bool execute_legacy_node_stroke_preview_immediate_runtime(
return sequence_ok; return sequence_ok;
} }
void initialize_legacy_node_stroke_preview_clone(Node* dest)
{
static_cast<NodeStrokePreview*>(dest)->init_controls();
}
bool execute_legacy_node_stroke_preview_immediate_draw(NodeStrokePreview& preview)
{
if (preview.m_size.x == 0 || preview.m_size.y == 0) {
return false;
}
const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_immediate_draw(
pp::panopainter::LegacyNodeStrokePreviewImmediateDrawRequest {
.brush = preview.m_brush,
.preview_size = preview.m_size,
.zoom = preview.root()->m_zoom,
.min_flow = preview.m_min_flow,
.stroke_max_size_override = preview.m_max_size,
.pad_override = preview.m_pad_override,
.camera_fov = Canvas::I->m_cam_fov,
.camera_rot = Canvas::I->m_cam_rot,
.render_device_features = pp::panopainter::stroke_preview_render_device_features(),
.preview_rtt = preview.m_rtt,
.preview_rtt_mixer = preview.m_rtt_mixer,
.preview_stroke_texture = preview.m_tex,
.preview_dual_texture = preview.m_tex_dual,
.preview_background_texture = preview.m_tex_background,
.preview_image_texture = preview.m_tex_preview,
.linear_sampler = preview.m_sampler_linear,
.repeat_sampler = preview.m_sampler_linear_repeat,
.prepare_render_target = [&] {
pp::panopainter::apply_legacy_node_stroke_preview_viewport(
0,
0,
preview.m_rtt.getWidth(),
preview.m_rtt.getHeight());
preview.m_rtt.bindFramebuffer();
preview.m_rtt.clear();
pp::panopainter::bind_legacy_node_stroke_preview_live_samplers(
preview.m_sampler_mipmap,
preview.m_sampler_linear,
preview.m_sampler_linear_repeat);
},
.finish_render_target = [&] {
preview.m_rtt.unbindFramebuffer();
},
.compute_frames = [&](const Stroke& stroke, float frame_zoom) {
return plan_legacy_node_stroke_preview_stroke_frames(
stroke,
frame_zoom,
glm::vec2(preview.m_rtt.getWidth(), preview.m_rtt.getHeight()));
},
.draw_samples = [&](std::array<vertex_t, 4>& shapes, Texture2D& texture, bool copy_stroke_destination) {
return pp::panopainter::execute_legacy_node_stroke_preview_sample_pass(
preview.m_rtt,
shapes,
preview.m_brush_shape,
texture,
copy_stroke_destination);
},
.draw_mix = [&](const glm::vec2& bb_min, const glm::vec2& bb_sz) {
pp::panopainter::execute_legacy_node_stroke_preview_mix_pass(
*preview.m_brush,
preview.m_size,
preview.m_rtt_mixer,
bb_min,
bb_sz,
preview.m_sampler_linear,
preview.m_tex_background,
preview.m_tex,
preview.m_tex_dual,
[&] {
preview.m_plane.draw_fill();
});
},
.draw_checkerboard = [&] {
preview.m_plane.draw_fill();
},
.draw_composite = [&] {
preview.m_plane.draw_fill();
},
});
assert(sequence_ok);
return sequence_ok;
}
} // namespace pp::panopainter } // namespace pp::panopainter
std::atomic_int NodeStrokePreview::s_instances{ 0 }; std::atomic_int NodeStrokePreview::s_instances{ 0 };

View File

@@ -16,6 +16,9 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
class Node;
class NodeStrokePreview;
namespace pp::panopainter { namespace pp::panopainter {
[[nodiscard]] pp::renderer::RenderDeviceFeatures stroke_preview_render_device_features() noexcept; [[nodiscard]] pp::renderer::RenderDeviceFeatures stroke_preview_render_device_features() noexcept;
@@ -63,6 +66,11 @@ struct LegacyNodeStrokePreviewStrokeComputeRequest {
[[nodiscard]] std::vector<LegacyNodeStrokePreviewFrame> plan_legacy_node_stroke_preview_stroke_frames( [[nodiscard]] std::vector<LegacyNodeStrokePreviewFrame> plan_legacy_node_stroke_preview_stroke_frames(
const LegacyNodeStrokePreviewStrokeComputeRequest& request); const LegacyNodeStrokePreviewStrokeComputeRequest& request);
[[nodiscard]] std::vector<LegacyNodeStrokePreviewFrame> plan_legacy_node_stroke_preview_stroke_frames(
const Stroke& stroke,
float zoom,
glm::vec2 mixer_size);
struct LegacyNodeStrokePreviewImmediateRuntimeRequest { struct LegacyNodeStrokePreviewImmediateRuntimeRequest {
const std::shared_ptr<Brush>& brush; const std::shared_ptr<Brush>& brush;
glm::vec2 preview_size {}; glm::vec2 preview_size {};
@@ -128,4 +136,7 @@ struct LegacyNodeStrokePreviewImmediateDrawRequest {
[[nodiscard]] bool execute_legacy_node_stroke_preview_immediate_runtime( [[nodiscard]] bool execute_legacy_node_stroke_preview_immediate_runtime(
const LegacyNodeStrokePreviewImmediateRuntimeRequest& request); const LegacyNodeStrokePreviewImmediateRuntimeRequest& request);
void initialize_legacy_node_stroke_preview_clone(Node* dest);
[[nodiscard]] bool execute_legacy_node_stroke_preview_immediate_draw(NodeStrokePreview& preview);
} // namespace pp::panopainter } // namespace pp::panopainter

View File

@@ -1,6 +1,7 @@
#include "pch.h" #include "pch.h"
#include "legacy_node_stroke_preview_sample_services.h" #include "legacy_node_stroke_preview_sample_services.h"
#include "legacy_node_stroke_preview_runtime_services.h"
namespace pp::panopainter { namespace pp::panopainter {
@@ -57,4 +58,41 @@ glm::vec4 execute_legacy_node_stroke_preview_sample_pass(
return result.dirty_bounds; return result.dirty_bounds;
} }
glm::vec4 execute_legacy_node_stroke_preview_sample_pass(
RTT& preview_rtt,
std::array<vertex_t, 4>& vertices,
DynamicShape& brush_shape,
Texture2D& blend_tex,
bool copy_stroke_destination)
{
return execute_legacy_node_stroke_preview_sample_pass(
LegacyNodeStrokePreviewSamplePassRequest {
.target_size = { static_cast<float>(preview_rtt.getWidth()), static_cast<float>(preview_rtt.getHeight()) },
.vertices = vertices,
.brush_shape = brush_shape,
.copy_stroke_destination = copy_stroke_destination,
.bind_destination_texture = [&] {
bind_legacy_node_stroke_preview_destination_texture(blend_tex);
},
.copy_framebuffer_to_destination_texture = [](
int src_x,
int src_y,
int dst_x,
int dst_y,
int width,
int height) {
copy_legacy_node_stroke_preview_destination_texture_region(
src_x,
src_y,
dst_x,
dst_y,
width,
height);
},
.unbind_destination_texture = [&] {
unbind_legacy_node_stroke_preview_destination_texture(blend_tex);
},
});
}
} // namespace pp::panopainter } // namespace pp::panopainter

View File

@@ -25,4 +25,11 @@ struct LegacyNodeStrokePreviewSamplePassRequest {
[[nodiscard]] glm::vec4 execute_legacy_node_stroke_preview_sample_pass( [[nodiscard]] glm::vec4 execute_legacy_node_stroke_preview_sample_pass(
const LegacyNodeStrokePreviewSamplePassRequest& request); const LegacyNodeStrokePreviewSamplePassRequest& request);
[[nodiscard]] glm::vec4 execute_legacy_node_stroke_preview_sample_pass(
RTT& preview_rtt,
std::array<vertex_t, 4>& vertices,
DynamicShape& brush_shape,
Texture2D& blend_tex,
bool copy_stroke_destination);
} // namespace pp::panopainter } // namespace pp::panopainter

View File

@@ -1,84 +1,10 @@
#include "pch.h" #include "pch.h"
#include "log.h"
#include "shader.h"
#include "shape.h"
#include "texture.h"
#include "image.h"
#include "app.h"
#include "canvas.h"
#include "platform_windows/windows_bootstrap_helpers.h"
#include "platform_windows/windows_platform_services.h"
#include "platform_windows/windows_lifecycle_shell.h"
#include "platform_windows/windows_runtime_shell.h" #include "platform_windows/windows_runtime_shell.h"
#include "platform_windows/windows_splash.h"
#include "platform_windows/windows_stylus_input.h"
#include "platform_windows/windows_window_shell.h"
#include "platform_windows/windows_vr_shell.h"
#include "../resource.h"
#include "wacom.h"
#include "abr.h"
using pp::platform::windows::retained_state;
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
auto& state = retained_state(); return pp::platform::windows::run_main_application(argc, argv);
state.hInst = GetModuleHandle(NULL);
App::I = new App();
App::I->set_platform_services(&pp::platform::windows::platform_services());
App::I->initLog();
pp::platform::windows::init_shcore_API();
pp::platform::windows::initialize_stylus_input();
if (pp::platform::windows::SetProcessDpiAwareness_fn)
pp::platform::windows::SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE);
pp::platform::windows::ensure_runtime_data_directory();
pp::platform::windows::SplashScreen splash(GetModuleHandle(NULL));
pp::platform::windows::initialize_retained_input_state();
pp::platform::windows::setup_exception_handler();
pp::platform::windows::read_WMI_info();
App::I->create();
auto startup = pp::platform::windows::initialize_main_window_startup_state();
auto context = pp::platform::windows::OpenGlWindowContext {};
switch (pp::platform::windows::initialize_main_window_and_gl(startup, state.hWnd, state.hInst, state.window_title, context))
{
case pp::platform::windows::MainStartupResult::Ok:
break;
case pp::platform::windows::MainStartupResult::GladLoadFailure:
return 0;
case pp::platform::windows::MainStartupResult::MissingCoreContextSupport:
return -1;
}
//wglSwapIntervalEXT(1);
bool start_in_vr = false;
if (argc > 1)
{
switch (const_hash(argv[1]))
{
case const_hash("convert"):
App::I->initShaders();
App::I->cmd_convert(argv[2], argv[3]);
return 0;
case const_hash("-vrmode"):
start_in_vr = true;
break;
default:
break;
}
}
pp::platform::windows::run_main_window_runtime(startup, start_in_vr, splash);
} }
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

View File

@@ -28,8 +28,7 @@ void NodeStrokePreview::clone_children(Node* dest) const
void NodeStrokePreview::clone_finalize(Node* dest) const void NodeStrokePreview::clone_finalize(Node* dest) const
{ {
NodeStrokePreview* n = (NodeStrokePreview*)dest; pp::panopainter::initialize_legacy_node_stroke_preview_clone(dest);
n->init_controls();
} }
void NodeStrokePreview::init_controls() void NodeStrokePreview::init_controls()
@@ -40,21 +39,18 @@ void NodeStrokePreview::init_controls()
void NodeStrokePreview::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz) void NodeStrokePreview::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
{ {
const auto& b = m_brush;
const bool mix_ok = pp::panopainter::execute_legacy_node_stroke_preview_mix_pass( const bool mix_ok = pp::panopainter::execute_legacy_node_stroke_preview_mix_pass(
pp::panopainter::LegacyNodeStrokePreviewMixPassExecutionRequest { *m_brush,
.brush = *b, m_size,
.preview_size = m_size, m_rtt_mixer,
.mixer_rtt = m_rtt_mixer, bb_min,
.bb_min = bb_min, bb_sz,
.bb_sz = bb_sz, m_sampler_linear,
.linear_sampler = m_sampler_linear, m_tex_background,
.background_texture = m_tex_background, m_tex,
.stroke_texture = m_tex, m_tex_dual,
.dual_texture = m_tex_dual, [this] {
.draw_mix = [this] { m_plane.draw_fill();
m_plane.draw_fill();
},
}); });
assert(mix_ok); assert(mix_ok);
} }
@@ -64,97 +60,26 @@ glm::vec4 NodeStrokePreview::stroke_draw_samples(
Texture2D& blend_tex, Texture2D& blend_tex,
bool copy_stroke_destination) bool copy_stroke_destination)
{ {
const glm::vec2 size = { m_rtt.getWidth(), m_rtt.getHeight() };
return pp::panopainter::execute_legacy_node_stroke_preview_sample_pass( return pp::panopainter::execute_legacy_node_stroke_preview_sample_pass(
pp::panopainter::LegacyNodeStrokePreviewSamplePassRequest { m_rtt,
.target_size = size, P,
.vertices = P, m_brush_shape,
.brush_shape = m_brush_shape, blend_tex,
.copy_stroke_destination = copy_stroke_destination, copy_stroke_destination);
.bind_destination_texture = [&] {
pp::panopainter::bind_legacy_node_stroke_preview_destination_texture(blend_tex);
},
.copy_framebuffer_to_destination_texture = [](
int src_x,
int src_y,
int dst_x,
int dst_y,
int width,
int height) {
pp::panopainter::copy_legacy_node_stroke_preview_destination_texture_region(
src_x,
src_y,
dst_x,
dst_y,
width,
height);
},
.unbind_destination_texture = [&] {
pp::panopainter::unbind_legacy_node_stroke_preview_destination_texture(blend_tex);
},
});
} }
std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compute(const Stroke& stroke, float zoom) const std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compute(const Stroke& stroke, float zoom) const
{ {
return pp::panopainter::plan_legacy_node_stroke_preview_stroke_frames( return pp::panopainter::plan_legacy_node_stroke_preview_stroke_frames(
pp::panopainter::LegacyNodeStrokePreviewStrokeComputeRequest { stroke,
.stroke = stroke, zoom,
.zoom = zoom, glm::vec2(m_rtt.getWidth(), m_rtt.getHeight()));
.mixer_size = glm::vec2(m_rtt.getWidth(), m_rtt.getHeight()),
});
} }
void NodeStrokePreview::draw_stroke_immediate() void NodeStrokePreview::draw_stroke_immediate()
{ {
if (m_size.x == 0 || m_size.y == 0) if (m_size.x == 0 || m_size.y == 0)
return; return;
const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_immediate_draw( const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_immediate_draw(*this);
pp::panopainter::LegacyNodeStrokePreviewImmediateDrawRequest {
.brush = m_brush,
.preview_size = m_size,
.zoom = root()->m_zoom,
.min_flow = m_min_flow,
.stroke_max_size_override = m_max_size,
.pad_override = m_pad_override,
.camera_fov = Canvas::I->m_cam_fov,
.camera_rot = Canvas::I->m_cam_rot,
.render_device_features = pp::panopainter::stroke_preview_render_device_features(),
.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,
.linear_sampler = m_sampler_linear,
.repeat_sampler = m_sampler_linear_repeat,
.prepare_render_target = [&] {
pp::panopainter::apply_legacy_node_stroke_preview_viewport(0, 0, m_rtt.getWidth(), m_rtt.getHeight());
m_rtt.bindFramebuffer();
m_rtt.clear();
pp::panopainter::bind_legacy_node_stroke_preview_live_samplers(
m_sampler_mipmap,
m_sampler_linear,
m_sampler_linear_repeat);
},
.finish_render_target = [&] {
m_rtt.unbindFramebuffer();
},
.compute_frames = [&](const Stroke& stroke, float frame_zoom) {
return stroke_draw_compute(stroke, frame_zoom);
},
.draw_samples = [&](std::array<vertex_t, 4>& shapes, Texture2D& texture, bool copy_stroke_destination) {
return stroke_draw_samples(shapes, texture, copy_stroke_destination);
},
.draw_mix = [&](const glm::vec2& bb_min, const glm::vec2& bb_sz) {
stroke_draw_mix(bb_min, bb_sz);
},
.draw_checkerboard = [&] {
m_plane.draw_fill();
},
.draw_composite = [&] {
m_plane.draw_fill();
},
});
assert(sequence_ok); assert(sequence_ok);
} }

View File

@@ -7,11 +7,14 @@
#include "texture.h" #include "texture.h"
#include "legacy_node_stroke_preview_draw_services.h" #include "legacy_node_stroke_preview_draw_services.h"
#include "legacy_node_stroke_preview_execution_services.h" #include "legacy_node_stroke_preview_execution_services.h"
#include "legacy_node_stroke_preview_runtime_services.h"
class NodeStrokePreview : public NodeBorder class NodeStrokePreview : public NodeBorder
{ {
using StrokeFrame = pp::panopainter::LegacyNodeStrokePreviewFrame; using StrokeFrame = pp::panopainter::LegacyNodeStrokePreviewFrame;
friend bool pp::panopainter::execute_legacy_node_stroke_preview_immediate_draw(NodeStrokePreview& preview);
static RTT m_rtt; static RTT m_rtt;
static RTT m_rtt_mixer; static RTT m_rtt_mixer;
static Texture2D m_tex; // blending tmp texture static Texture2D m_tex; // blending tmp texture

View File

@@ -1,5 +1,6 @@
#include "pch.h" #include "pch.h"
#include "platform_legacy/legacy_platform_services.h" #include "platform_legacy/legacy_platform_services.h"
#include "platform_legacy/legacy_platform_state.h"
#include "app.h" #include "app.h"
#include "legacy_ui_gl_dispatch.h" #include "legacy_ui_gl_dispatch.h"
@@ -131,25 +132,6 @@ struct RetainedLegacyGlfwWindowState final {
} }
#endif #endif
struct RetainedLegacyStoragePaths final {
pp::platform::PlatformStoragePaths storage_paths;
};
[[nodiscard]] RetainedLegacyStoragePaths& active_legacy_storage_paths()
{
static RetainedLegacyStoragePaths state = [] {
RetainedLegacyStoragePaths retained;
retained.storage_paths = {
App::I->data_path,
App::I->work_path,
App::I->rec_path,
App::I->tmp_path,
};
return retained;
}();
return state;
}
#if defined(__IOS__) || defined(__OSX__) #if defined(__IOS__) || defined(__OSX__)
[[nodiscard]] NSMutableArray<NSString*>* apple_file_types_array(const std::vector<std::string>& file_types) [[nodiscard]] NSMutableArray<NSString*>* apple_file_types_array(const std::vector<std::string>& file_types)
{ {
@@ -169,7 +151,6 @@ struct RetainedLegacyAppleState final {
decltype(App::I->osx_view) osx_view = nullptr; decltype(App::I->osx_view) osx_view = nullptr;
decltype(App::I->osx_app) osx_app = nullptr; decltype(App::I->osx_app) osx_app = nullptr;
#endif #endif
pp::platform::PlatformStoragePaths storage_paths;
}; };
[[nodiscard]] RetainedLegacyAppleState& active_legacy_apple_state() [[nodiscard]] RetainedLegacyAppleState& active_legacy_apple_state()
@@ -179,21 +160,9 @@ struct RetainedLegacyAppleState final {
#ifdef __IOS__ #ifdef __IOS__
retained.ios_view = App::I->ios_view; retained.ios_view = App::I->ios_view;
retained.ios_app = App::I->ios_app; retained.ios_app = App::I->ios_app;
retained.storage_paths = {
App::I->data_path,
App::I->work_path,
App::I->rec_path,
App::I->tmp_path,
};
#elif defined(__OSX__) #elif defined(__OSX__)
retained.osx_view = App::I->osx_view; retained.osx_view = App::I->osx_view;
retained.osx_app = App::I->osx_app; retained.osx_app = App::I->osx_app;
retained.storage_paths = {
App::I->data_path,
App::I->work_path,
App::I->rec_path,
App::I->tmp_path,
};
#endif #endif
return retained; return retained;
}(); }();
@@ -208,7 +177,7 @@ struct RetainedLegacyAppleState final {
#elif defined(__OSX__) #elif defined(__OSX__)
[apple_state.osx_app init_dirs]; [apple_state.osx_app init_dirs];
#endif #endif
return apple_state.storage_paths; return active_legacy_storage_paths();
} }
[[nodiscard]] pp::platform::apple::AppleDocumentPlatformServices& active_apple_document_platform_services() [[nodiscard]] pp::platform::apple::AppleDocumentPlatformServices& active_apple_document_platform_services()
@@ -406,7 +375,7 @@ public:
{}, {},
}; };
#else #else
return active_legacy_storage_paths().storage_paths; return pp::platform::legacy::active_legacy_storage_paths();
#endif #endif
} }

View File

@@ -0,0 +1,30 @@
#include "pch.h"
#include "platform_legacy/legacy_platform_state.h"
#include "app.h"
namespace pp::platform::legacy {
namespace {
struct RetainedLegacyStoragePaths final {
pp::platform::PlatformStoragePaths storage_paths;
};
}
[[nodiscard]] const pp::platform::PlatformStoragePaths& active_legacy_storage_paths()
{
static RetainedLegacyStoragePaths state = [] {
RetainedLegacyStoragePaths retained;
retained.storage_paths = {
App::I->data_path,
App::I->work_path,
App::I->rec_path,
App::I->tmp_path,
};
return retained;
}();
return state.storage_paths;
}
}

View File

@@ -0,0 +1,9 @@
#pragma once
#include "platform_api/platform_services.h"
namespace pp::platform::legacy {
[[nodiscard]] const pp::platform::PlatformStoragePaths& active_legacy_storage_paths();
}

View File

@@ -7,6 +7,7 @@
#include "platform_windows/windows_bootstrap_helpers.h" #include "platform_windows/windows_bootstrap_helpers.h"
#include "platform_windows/windows_lifecycle_shell.h" #include "platform_windows/windows_lifecycle_shell.h"
#include "platform_windows/windows_platform_services.h" #include "platform_windows/windows_platform_services.h"
#include "platform_windows/windows_stylus_input.h"
#include "platform_windows/windows_window_shell.h" #include "platform_windows/windows_window_shell.h"
#include "wacom.h" #include "wacom.h"
#include "../resource.h" #include "../resource.h"
@@ -101,6 +102,68 @@ void shutdown_main_window_runtime(const MainWindowStartupState& startup, HINSTAN
} }
int run_main_application(int argc, char** argv)
{
auto& state = retained_state();
state.hInst = GetModuleHandle(NULL);
App::I = new App();
App::I->set_platform_services(&pp::platform::windows::platform_services());
App::I->initLog();
pp::platform::windows::init_shcore_API();
pp::platform::windows::initialize_stylus_input();
if (pp::platform::windows::SetProcessDpiAwareness_fn)
pp::platform::windows::SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE);
pp::platform::windows::ensure_runtime_data_directory();
pp::platform::windows::SplashScreen splash(state.hInst);
pp::platform::windows::initialize_retained_input_state();
pp::platform::windows::setup_exception_handler();
pp::platform::windows::read_WMI_info();
App::I->create();
auto startup = pp::platform::windows::initialize_main_window_startup_state();
auto context = pp::platform::windows::OpenGlWindowContext {};
switch (pp::platform::windows::initialize_main_window_and_gl(startup, state.hWnd, state.hInst, state.window_title, context))
{
case pp::platform::windows::MainStartupResult::Ok:
break;
case pp::platform::windows::MainStartupResult::GladLoadFailure:
return 0;
case pp::platform::windows::MainStartupResult::MissingCoreContextSupport:
return -1;
}
//wglSwapIntervalEXT(1);
bool start_in_vr = false;
if (argc > 1)
{
switch (const_hash(argv[1]))
{
case const_hash("convert"):
App::I->initShaders();
App::I->cmd_convert(argv[2], argv[3]);
return 0;
case const_hash("-vrmode"):
start_in_vr = true;
break;
default:
break;
}
}
pp::platform::windows::run_main_window_runtime(startup, start_in_vr, splash);
return 0;
}
void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash) void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash)
{ {
auto& state = retained_state(); auto& state = retained_state();

View File

@@ -5,6 +5,7 @@
namespace pp::platform::windows { namespace pp::platform::windows {
int run_main_application(int argc, char** argv);
void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash); void run_main_window_runtime(const MainWindowStartupState& startup, bool start_in_vr, SplashScreen& splash);
} }