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

@@ -187,6 +187,33 @@ bool execute_legacy_node_stroke_preview_mix_pass(
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)
{
return request.bind_dual_pass_textures &&

View File

@@ -61,6 +61,18 @@ struct LegacyNodeStrokePreviewMixPassExecutionRequest {
[[nodiscard]] bool execute_legacy_node_stroke_preview_mix_pass(
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(
const LegacyNodeStrokePreviewLiveRenderRequest& request);

View File

@@ -14,6 +14,7 @@
#include "legacy_canvas_stroke_shader_services.h"
#include "legacy_canvas_stroke_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 "paint_renderer/compositor.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(
const LegacyNodeStrokePreviewImmediateRuntimeRequest& request)
{
@@ -375,6 +389,92 @@ bool execute_legacy_node_stroke_preview_immediate_runtime(
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
std::atomic_int NodeStrokePreview::s_instances{ 0 };

View File

@@ -16,6 +16,9 @@
#include <memory>
#include <vector>
class Node;
class NodeStrokePreview;
namespace pp::panopainter {
[[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(
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 {
const std::shared_ptr<Brush>& brush;
glm::vec2 preview_size {};
@@ -128,4 +136,7 @@ struct LegacyNodeStrokePreviewImmediateDrawRequest {
[[nodiscard]] bool execute_legacy_node_stroke_preview_immediate_runtime(
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

View File

@@ -1,6 +1,7 @@
#include "pch.h"
#include "legacy_node_stroke_preview_sample_services.h"
#include "legacy_node_stroke_preview_runtime_services.h"
namespace pp::panopainter {
@@ -57,4 +58,41 @@ glm::vec4 execute_legacy_node_stroke_preview_sample_pass(
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

View File

@@ -25,4 +25,11 @@ struct LegacyNodeStrokePreviewSamplePassRequest {
[[nodiscard]] glm::vec4 execute_legacy_node_stroke_preview_sample_pass(
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

View File

@@ -1,84 +1,10 @@
#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_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)
{
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(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);
return pp::platform::windows::run_main_application(argc, argv);
}
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
{
NodeStrokePreview* n = (NodeStrokePreview*)dest;
n->init_controls();
pp::panopainter::initialize_legacy_node_stroke_preview_clone(dest);
}
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)
{
const auto& b = m_brush;
const bool mix_ok = pp::panopainter::execute_legacy_node_stroke_preview_mix_pass(
pp::panopainter::LegacyNodeStrokePreviewMixPassExecutionRequest {
.brush = *b,
.preview_size = m_size,
.mixer_rtt = m_rtt_mixer,
.bb_min = bb_min,
.bb_sz = bb_sz,
.linear_sampler = m_sampler_linear,
.background_texture = m_tex_background,
.stroke_texture = m_tex,
.dual_texture = m_tex_dual,
.draw_mix = [this] {
m_plane.draw_fill();
},
*m_brush,
m_size,
m_rtt_mixer,
bb_min,
bb_sz,
m_sampler_linear,
m_tex_background,
m_tex,
m_tex_dual,
[this] {
m_plane.draw_fill();
});
assert(mix_ok);
}
@@ -64,97 +60,26 @@ glm::vec4 NodeStrokePreview::stroke_draw_samples(
Texture2D& blend_tex,
bool copy_stroke_destination)
{
const glm::vec2 size = { m_rtt.getWidth(), m_rtt.getHeight() };
return pp::panopainter::execute_legacy_node_stroke_preview_sample_pass(
pp::panopainter::LegacyNodeStrokePreviewSamplePassRequest {
.target_size = size,
.vertices = P,
.brush_shape = m_brush_shape,
.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);
},
});
m_rtt,
P,
m_brush_shape,
blend_tex,
copy_stroke_destination);
}
std::vector<NodeStrokePreview::StrokeFrame> NodeStrokePreview::stroke_draw_compute(const Stroke& stroke, float zoom) const
{
return pp::panopainter::plan_legacy_node_stroke_preview_stroke_frames(
pp::panopainter::LegacyNodeStrokePreviewStrokeComputeRequest {
.stroke = stroke,
.zoom = zoom,
.mixer_size = glm::vec2(m_rtt.getWidth(), m_rtt.getHeight()),
});
stroke,
zoom,
glm::vec2(m_rtt.getWidth(), m_rtt.getHeight()));
}
void NodeStrokePreview::draw_stroke_immediate()
{
if (m_size.x == 0 || m_size.y == 0)
return;
const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_immediate_draw(
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();
},
});
const bool sequence_ok = pp::panopainter::execute_legacy_node_stroke_preview_immediate_draw(*this);
assert(sequence_ok);
}

View File

@@ -7,11 +7,14 @@
#include "texture.h"
#include "legacy_node_stroke_preview_draw_services.h"
#include "legacy_node_stroke_preview_execution_services.h"
#include "legacy_node_stroke_preview_runtime_services.h"
class NodeStrokePreview : public NodeBorder
{
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_mixer;
static Texture2D m_tex; // blending tmp texture

View File

@@ -1,5 +1,6 @@
#include "pch.h"
#include "platform_legacy/legacy_platform_services.h"
#include "platform_legacy/legacy_platform_state.h"
#include "app.h"
#include "legacy_ui_gl_dispatch.h"
@@ -131,25 +132,6 @@ struct RetainedLegacyGlfwWindowState final {
}
#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__)
[[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_app) osx_app = nullptr;
#endif
pp::platform::PlatformStoragePaths storage_paths;
};
[[nodiscard]] RetainedLegacyAppleState& active_legacy_apple_state()
@@ -179,21 +160,9 @@ struct RetainedLegacyAppleState final {
#ifdef __IOS__
retained.ios_view = App::I->ios_view;
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__)
retained.osx_view = App::I->osx_view;
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
return retained;
}();
@@ -208,7 +177,7 @@ struct RetainedLegacyAppleState final {
#elif defined(__OSX__)
[apple_state.osx_app init_dirs];
#endif
return apple_state.storage_paths;
return active_legacy_storage_paths();
}
[[nodiscard]] pp::platform::apple::AppleDocumentPlatformServices& active_apple_document_platform_services()
@@ -406,7 +375,7 @@ public:
{},
};
#else
return active_legacy_storage_paths().storage_paths;
return pp::platform::legacy::active_legacy_storage_paths();
#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_lifecycle_shell.h"
#include "platform_windows/windows_platform_services.h"
#include "platform_windows/windows_stylus_input.h"
#include "platform_windows/windows_window_shell.h"
#include "wacom.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)
{
auto& state = retained_state();

View File

@@ -5,6 +5,7 @@
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);
}