Extract edit menu and Windows/bootstrap preview seams

This commit is contained in:
2026-06-16 12:53:49 +02:00
parent 184f662493
commit cb9d06c6dc
12 changed files with 493 additions and 409 deletions

View File

@@ -99,6 +99,7 @@ set(PP_PANOPAINTER_APP_SOURCES
src/app_layout.cpp src/app_layout.cpp
src/app_layout_sidebar.cpp src/app_layout_sidebar.cpp
src/app_layout_main_toolbar.cpp src/app_layout_main_toolbar.cpp
src/app_layout_edit_menu.cpp
src/app_layout_about_layer_menu.cpp src/app_layout_about_layer_menu.cpp
src/app_layout_file_menu.cpp src/app_layout_file_menu.cpp
src/app_layout_tools_menu.cpp src/app_layout_tools_menu.cpp

View File

@@ -80,12 +80,12 @@ What is still carrying too much live ownership:
Current hotspot files: Current hotspot files:
- `src/canvas.cpp`: 2645 lines - `src/canvas.cpp`: 2645 lines
- `src/app_layout.cpp`: 743 lines - `src/app_layout.cpp`: 717 lines
- `src/canvas_modes.cpp`: 1798 lines - `src/canvas_modes.cpp`: 1798 lines
- `src/node.cpp`: 1594 lines - `src/node.cpp`: 1594 lines
- `src/main.cpp`: 1098 lines - `src/main.cpp`: 847 lines
- `src/node_panel_brush.cpp`: 1197 lines - `src/node_panel_brush.cpp`: 1197 lines
- `src/node_stroke_preview.cpp`: 933 lines - `src/node_stroke_preview.cpp`: 948 lines
- `src/node_canvas.cpp`: 910 lines - `src/node_canvas.cpp`: 910 lines
- `src/app.cpp`: 502 lines - `src/app.cpp`: 502 lines
- `src/app_dialogs.cpp`: 142 lines - `src/app_dialogs.cpp`: 142 lines
@@ -142,7 +142,9 @@ Current architecture mismatches that must be treated as real blockers:
binding and popup wiring now also live in `src/app_layout_sidebar.cpp` and binding and popup wiring now also live in `src/app_layout_sidebar.cpp` and
`App::init_sidebar()` is now a thin call-through, while main-toolbar binding `App::init_sidebar()` is now a thin call-through, while main-toolbar binding
now also lives in `src/app_layout_main_toolbar.cpp` and now also lives in `src/app_layout_main_toolbar.cpp` and
`App::init_toolbar_main()` is now a thin call-through, while the `App::init_toolbar_main()` is now a thin call-through, while edit-menu
binding now also lives in `src/app_layout_edit_menu.cpp` and
`App::init_menu_edit()` is now a thin call-through, while the
informational overlay opener family now also lives in informational overlay opener family now also lives in
`src/app_dialogs_info_openers.cpp` and the corresponding `App::dialog_*` `src/app_dialogs_info_openers.cpp` and the corresponding `App::dialog_*`
entrypoints are thinner, while the export/video/PPBR dialog family now also entrypoints are thinner, while the export/video/PPBR dialog family now also
@@ -186,12 +188,12 @@ Current architecture mismatches that must be treated as real blockers:
sequencing, FPS title update/wakeup posting, stylus frame update, window sequencing, FPS title update/wakeup posting, stylus frame update, window
preference save, and VR lifecycle wrappers now also live in preference save, and VR lifecycle wrappers now also live in
`src/platform_windows/windows_lifecycle_shell.cpp` instead of `src/main.cpp`, `src/platform_windows/windows_lifecycle_shell.cpp` instead of `src/main.cpp`,
while the Win32 startup/window/bootstrap path in `src/main.cpp` now also while the Win32 startup/window/bootstrap path now also lives under
routes through named local helper functions for runtime-data discovery, `src/platform_windows/windows_bootstrap_helpers.*` for runtime-data
startup-state initialization, window creation, pixel-format setup, GL loader discovery, startup-state initialization, window creation, pixel-format
init, runtime-info logging, and core-context upgrade sequencing even though setup, GL loader init, runtime-info logging, and core-context upgrade
that state still needs to move into platform-owned modules for the file to sequencing, which materially thins `src/main.cpp` even though broader window
shrink materially, procedure and retained shell flow still remain there,
while `App::rec_loop()` now delegates worker-iteration orchestration into while `App::rec_loop()` now delegates worker-iteration orchestration into
the retained recording bridge, `App::update_rec_frames()` now delegates the retained recording bridge, `App::update_rec_frames()` now delegates
recording label refresh through that same retained recording path, and the recording label refresh through that same retained recording path, and the
@@ -207,7 +209,10 @@ Current architecture mismatches that must be treated as real blockers:
document-IO cluster now lives in `src/legacy_canvas_document_io_services.cpp` document-IO cluster now lives in `src/legacy_canvas_document_io_services.cpp`
and `NodeStrokePreview` render-target setup plus immediate-pass sequencing and `NodeStrokePreview` render-target setup plus immediate-pass sequencing
now route through retained preview execution helpers, even though the bridge now route through retained preview execution helpers, even though the bridge
still owns worker-side readback flow and encoder-state label reads, while still owns worker-side readback flow and encoder-state label reads, while the
main live-pass request assembly and framebuffer-copy setup now also route
through `src/legacy_node_stroke_preview_execution_services.h`, even though
broader preview-pass orchestration still lives in `src/node_stroke_preview.cpp`, while
`Node` child attach/detach/reorder operations now route through named local `Node` child attach/detach/reorder operations now route through named local
helpers in `src/node.cpp`, which makes the scene-graph mutation paths easier helpers in `src/node.cpp`, which makes the scene-graph mutation paths easier
to reason about without yet reducing the file or moving ownership into to reason about without yet reducing the file or moving ownership into

View File

@@ -148,6 +148,11 @@ Current slice:
target setup was removed from `render_to_image()` and the queued worker path, 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 but the preview node still owns broader live-pass state and thread-facing
orchestration. orchestration.
- `NodeStrokePreview` main live-pass request assembly and preview framebuffer-
copy setup now also route through
`legacy_node_stroke_preview_execution_services.h`, which trims another
coherent pass-setup block from `src/node_stroke_preview.cpp`, but broader
preview-pass orchestration is still inline.
- `NodeCanvas` merged-path per-plane merged-texture draw execution now also - `NodeCanvas` merged-path per-plane merged-texture draw execution now also
routes through `execute_legacy_canvas_draw_merge_layer_texture(...)`. routes through `execute_legacy_canvas_draw_merge_layer_texture(...)`.
- `NodeCanvas` merged-path and non-blend checkerboard background setup now also - `NodeCanvas` merged-path and non-blend checkerboard background setup now also
@@ -293,7 +298,7 @@ targets look like helpers under one old monolith.
Status: In Progress Status: In Progress
Why now: Why now:
`src/app_layout.cpp` is still a 743-line mixed file that builds menus, `src/app_layout.cpp` is still a 717-line mixed file that builds menus,
attaches callbacks, computes planner inputs, and mutates UI state directly. attaches callbacks, computes planner inputs, and mutates UI state directly.
Current slice: Current slice:
@@ -316,6 +321,10 @@ Current slice:
- Main-toolbar binding now also lives in `src/app_layout_main_toolbar.cpp`, - Main-toolbar binding now also lives in `src/app_layout_main_toolbar.cpp`,
and `App::init_toolbar_main()` is now a thin call-through, but edit-menu and `App::init_toolbar_main()` is now a thin call-through, but edit-menu
wiring and broader layout composition are still inline in `src/app_layout.cpp`. wiring and broader layout composition are still inline in `src/app_layout.cpp`.
- Edit-menu binding now also lives in `src/app_layout_edit_menu.cpp`, and
`App::init_menu_edit()` is now a thin call-through, but draw-toolbar,
brush-refresh, and broader layout composition are still inline in
`src/app_layout.cpp`.
Write scope: Write scope:
- `src/app_layout.cpp` - `src/app_layout.cpp`
@@ -476,12 +485,12 @@ Current slice:
wakeup posting, stylus frame update, window preference save, and VR wakeup posting, stylus frame update, window preference save, and VR
lifecycle wrappers now also live in lifecycle wrappers now also live in
`src/platform_windows/windows_lifecycle_shell.cpp` instead of `src/main.cpp` `src/platform_windows/windows_lifecycle_shell.cpp` instead of `src/main.cpp`
- `main.cpp` startup/window/bootstrap flow now also routes through named local - Win32 startup/window/bootstrap flow now also lives in
helpers for runtime-data discovery, startup-state initialization, window `src/platform_windows/windows_bootstrap_helpers.*` for runtime-data
creation, pixel-format setup, GL loader init, runtime-info logging, and discovery, startup-state initialization, window creation, pixel-format
core-context upgrade sequencing, but the retained Win32 shell still needs setup, GL loader init, runtime-info logging, and core-context upgrade
those helpers moved into platform-owned modules before the file materially sequencing, which materially thins `src/main.cpp`, but the retained Win32
shrinks window procedure and broader shell flow are still open
- 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

View File

@@ -32,6 +32,7 @@
namespace pp::panopainter { namespace pp::panopainter {
void bind_legacy_main_toolbar(App& app); void bind_legacy_main_toolbar(App& app);
void bind_legacy_file_menu(App& app); void bind_legacy_file_menu(App& app);
void bind_legacy_edit_menu(App& app);
void bind_legacy_about_menu(App& app); void bind_legacy_about_menu(App& app);
void bind_legacy_layer_menu(App& app); void bind_legacy_layer_menu(App& app);
void bind_legacy_tools_menu(App& app); void bind_legacy_tools_menu(App& app);
@@ -54,25 +55,6 @@ bool apply_brush_preset_plan(App& app, const std::shared_ptr<Brush>& brush)
return pp::panopainter::apply_legacy_brush_preset_plan(app, brush); return pp::panopainter::apply_legacy_brush_preset_plan(app, brush);
} }
std::shared_ptr<NodePopupMenu> add_menu_popup(
App& app,
const char* template_id,
glm::vec2 position,
float rtl_anchor_width)
{
const auto popup = pp::panopainter::add_legacy_popup_menu(
app,
template_id,
position.x,
position.y,
rtl_anchor_width);
if (!popup) {
LOG("Popup menu '%s' failed: %s", template_id ? template_id : "<null>", popup.status().message);
return nullptr;
}
return popup.value();
}
[[nodiscard]] bool should_open_tools_panel(const pp::app::ToolsPanelPlan& plan) noexcept [[nodiscard]] bool should_open_tools_panel(const pp::app::ToolsPanelPlan& plan) noexcept
{ {
return plan.action == pp::app::ToolsPanelAction::open_floating_panel; return plan.action == pp::app::ToolsPanelAction::open_floating_panel;
@@ -197,15 +179,7 @@ void App::init_menu_file()
void App::init_menu_edit() void App::init_menu_edit()
{ {
if (auto* menu_file = layout[main_id]->find<NodeButtonCustom>("menu-edit")) pp::panopainter::bind_legacy_edit_menu(*this);
{
menu_file->on_click = [=](Node*) {
glm::vec2 pos = menu_file->m_pos + glm::vec2(0, menu_file->m_size.y);
auto popup = add_menu_popup(*this, "edit-menu", pos, menu_file->m_size.x);
if (!popup)
return;
};
}
} }
void App::init_menu_tools() void App::init_menu_tools()

View File

@@ -0,0 +1,47 @@
#include "pch.h"
#include "app.h"
#include "legacy_ui_overlay_services.h"
#include "node_button_custom.h"
#include "node_popup_menu.h"
namespace {
std::shared_ptr<NodePopupMenu> add_menu_popup(
App& app,
const char* template_id,
glm::vec2 position,
float rtl_anchor_width)
{
const auto popup = pp::panopainter::add_legacy_popup_menu(
app,
template_id,
position.x,
position.y,
rtl_anchor_width);
if (!popup) {
LOG("Popup menu '%s' failed: %s", template_id ? template_id : "<null>", popup.status().message);
return nullptr;
}
return popup.value();
}
} // namespace
namespace pp::panopainter {
void bind_legacy_edit_menu(App& app)
{
auto main = app.layout[app.main_id];
if (auto* menu_edit = main->find<NodeButtonCustom>("menu-edit"))
{
menu_edit->on_click = [&app, menu_edit](Node*) {
glm::vec2 pos = menu_edit->m_pos + glm::vec2(0, menu_edit->m_size.y);
auto popup = add_menu_popup(app, "edit-menu", pos, menu_edit->m_size.x);
if (!popup)
return;
};
}
}
} // namespace pp::panopainter

View File

@@ -10,6 +10,7 @@
#include "legacy_ui_gl_dispatch.h" #include "legacy_ui_gl_dispatch.h"
#include "paint_renderer/compositor.h" #include "paint_renderer/compositor.h"
#include "texture.h" #include "texture.h"
#include "util.h"
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
@@ -225,6 +226,22 @@ inline void bind_legacy_node_stroke_preview_main_pass_textures(
} }
} }
inline void copy_legacy_node_stroke_preview_framebuffer_to_texture(
Texture2D& texture,
glm::vec2 size,
std::uint32_t texture_slot)
{
pp::legacy::ui_gl::activate_texture_unit(texture_slot, "NodeStrokePreview");
texture.bind();
copy_framebuffer_to_texture_2d(
0,
0,
0,
0,
static_cast<int>(size.x),
static_cast<int>(size.y));
}
template <typename Frame> template <typename Frame>
struct LegacyNodeStrokePreviewMainLivePassRequestT { struct LegacyNodeStrokePreviewMainLivePassRequestT {
std::function<void()> setup_blend_uniforms; std::function<void()> setup_blend_uniforms;
@@ -238,6 +255,81 @@ struct LegacyNodeStrokePreviewMainLivePassRequestT {
std::function<void()> finish_main_pass; std::function<void()> finish_main_pass;
}; };
inline constexpr std::uint32_t kLegacyNodeStrokePreviewStrokeTextureSlot = 1U;
template <
typename Frame,
typename ComputeFrames,
typename BeforeFrame,
typename SetupSampleShader,
typename DrawSample,
typename FinishMainPass>
[[nodiscard]] inline LegacyNodeStrokePreviewMainLivePassRequestT<Frame>
make_legacy_node_stroke_preview_main_live_pass_request(
const Brush& brush,
const LegacyNodeStrokePreviewPassOrchestrationPlan& pass_orchestration,
Texture2D& stroke_texture,
RTT& mixer_rtt,
RTT& render_target,
bool copy_stroke_destination,
glm::vec2 size,
std::uint32_t stroke_texture_slot,
ComputeFrames&& compute_frames,
BeforeFrame&& before_frame,
SetupSampleShader&& setup_sample_shader,
DrawSample&& draw_sample,
FinishMainPass&& finish_main_pass)
{
return LegacyNodeStrokePreviewMainLivePassRequestT<Frame> {
.setup_blend_uniforms = [&] {
pp::panopainter::apply_legacy_stroke_blend_uniforms(
pass_orchestration.material.stroke_pass.uses_pattern,
brush.m_tip_mix,
brush.m_tip_wet,
brush.m_tip_noise);
},
.bind_main_pass_textures = [&] {
pp::panopainter::bind_legacy_node_stroke_preview_main_pass_textures(
pp::panopainter::make_legacy_node_stroke_preview_main_pass_texture_dispatch(
[&](int texture_slot) {
pp::legacy::ui_gl::activate_texture_unit(texture_slot, "NodeStrokePreview");
},
[&] {
brush.m_tip_texture ?
brush.m_tip_texture->bind() :
pp::legacy::ui_gl::unbind_texture_2d("NodeStrokePreview");
},
[&] {
stroke_texture.bind();
},
[&] {
brush.m_pattern_texture ?
brush.m_pattern_texture->bind() :
pp::legacy::ui_gl::unbind_texture_2d("NodeStrokePreview");
},
[&] {
mixer_rtt.bindTexture();
}),
copy_stroke_destination,
pass_orchestration.material.stroke_pass.uses_mixer);
},
.clear_target = [&] {
render_target.clear();
},
.compute_frames = std::forward<ComputeFrames>(compute_frames),
.before_frame = std::forward<BeforeFrame>(before_frame),
.setup_sample_shader = std::forward<SetupSampleShader>(setup_sample_shader),
.draw_sample = std::forward<DrawSample>(draw_sample),
.copy_pass_result = [&] {
copy_legacy_node_stroke_preview_framebuffer_to_texture(
stroke_texture,
size,
stroke_texture_slot);
},
.finish_main_pass = std::forward<FinishMainPass>(finish_main_pass),
};
}
template <typename Frame> template <typename Frame>
[[nodiscard]] inline bool execute_legacy_node_stroke_preview_main_live_pass( [[nodiscard]] inline bool execute_legacy_node_stroke_preview_main_live_pass(
const LegacyNodeStrokePreviewMainLivePassRequestT<Frame>& request) const LegacyNodeStrokePreviewMainLivePassRequestT<Frame>& request)

View File

@@ -7,9 +7,7 @@
#include "app.h" #include "app.h"
#include "canvas.h" #include "canvas.h"
#include "keymap.h" #include "keymap.h"
#include "legacy_gl_runtime_dispatch.h" #include "platform_windows/windows_bootstrap_helpers.h"
#include "legacy_preference_storage.h"
#include "renderer_gl/opengl_capabilities.h"
#include "platform_windows/windows_platform_services.h" #include "platform_windows/windows_platform_services.h"
#include "platform_windows/windows_lifecycle_shell.h" #include "platform_windows/windows_lifecycle_shell.h"
#include "platform_windows/windows_splash.h" #include "platform_windows/windows_splash.h"
@@ -17,22 +15,15 @@
#include "platform_windows/windows_vr_shell.h" #include "platform_windows/windows_vr_shell.h"
#include "../resource.h" #include "../resource.h"
#include <shellscalingapi.h>
#include <WbemCli.h> #include <WbemCli.h>
#include <deque> #include <deque>
#include "wacom.h" #include "wacom.h"
#include "abr.h" #include "abr.h"
#if __has_include(<renderdoc_app.h>)
#include <renderdoc_app.h>
#define USE_RENDERDOC
#endif
#include <iomanip> #include <iomanip>
#include <ctime> #include <ctime>
#include <sstream> #include <sstream>
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
namespace pp::platform::windows { namespace pp::platform::windows {
void set_async_render_context(HDC hdc, HGLRC hrc); void set_async_render_context(HDC hdc, HGLRC hrc);
void lock_async_render_context(); void lock_async_render_context();
@@ -40,20 +31,10 @@ namespace pp::platform::windows {
void unlock_async_render_context(); void unlock_async_render_context();
void swap_async_render_context(); void swap_async_render_context();
} }
extern HRESULT(*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
extern HRESULT(*SetProcessDpiAwareness_fn)(PROCESS_DPI_AWARENESS value);
bool win32_renderdoc_init();
void win32_renderdoc_frame_start();
void win32_renderdoc_frame_end();
void init_shcore_API();
std::string GetLastErrorAsString();
void _pre_call_callback(const char* name, void* funcptr, int len_args, ...);
void _post_call_callback(const char* name, void* funcptr, int len_args, ...);
struct RetainedState struct RetainedState
{ {
HINSTANCE hInst{}; HINSTANCE hInst{};
HWND hWnd{}; HWND hWnd{};
const wchar_t* className{};
bool keys[256]{}; bool keys[256]{};
std::map<kKey, int> vkey_map; std::map<kKey, int> vkey_map;
wchar_t window_title[512]{}; wchar_t window_title[512]{};
@@ -112,239 +93,6 @@ void drain_main_tasks()
} }
} }
struct MainWindowStartupState
{
WNDCLASS window_class{};
PIXELFORMATDESCRIPTOR pixel_format{};
DWORD window_style = WS_OVERLAPPEDWINDOW;
RECT client_rect{ 0, 0, 0, 0 };
POINT client_pos{ CW_USEDEFAULT, CW_USEDEFAULT };
int show_command = SW_NORMAL;
};
struct OpenGlWindowContext
{
HDC device_context{};
HGLRC render_context{};
pp::renderer::gl::OpenGlRuntimeInfo runtime_info{};
};
enum class MainStartupResult
{
Ok = 0,
GladLoadFailure = 1,
MissingCoreContextSupport = 2,
};
void ensure_runtime_data_directory()
{
FILE* fp_check = fopen("data\\layout.xml", "rb");
if (!fp_check)
{
LOG("data files not found");
static char path[MAX_PATH];
GetModuleFileNameA(NULL, path, MAX_PATH);
LOG("current dir %s", path);
PathRemoveFileSpecA(path);
SetCurrentDirectoryA(path);
LOG("change dir to %s", path);
return;
}
fclose(fp_check);
LOG("data files ok");
}
MainWindowStartupState initialize_main_window_startup_state()
{
auto& state = retained_state();
auto startup = MainWindowStartupState {};
state.hInst = GetModuleHandle(NULL);
state.className = L"EngineMain";
startup.window_class.hInstance = state.hInst;
startup.window_class.lpfnWndProc = (WNDPROC)WndProc;
startup.window_class.lpszClassName = state.className;
startup.window_class.hbrBackground = (HBRUSH)COLOR_WINDOW;
startup.window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClass(&startup.window_class);
auto monitor = MonitorFromWindow(0, MONITOR_DEFAULTTOPRIMARY);
auto x = unsigned{ 96 };
auto y = unsigned{ 96 };
if (GetDpiForMonitor_fn)
GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI, &x, &y);
App::I->display_density = (float)x / 96.f;
const auto window_preferences = pp::panopainter::read_legacy_window_preferences(SW_NORMAL);
if (window_preferences.has_ui_scale)
App::I->zoom = window_preferences.ui_scale;
else
App::I->zoom = (float)x / 96.f;
startup.show_command = window_preferences.show_command;
startup.client_rect = {
0,
0,
static_cast<LONG>(App::I->width * App::I->zoom),
static_cast<LONG>(App::I->height * App::I->zoom),
};
if (window_preferences.has_window_rect)
{
auto wnd_rect = window_preferences.window_rect;
App::I->width = wnd_rect.z - wnd_rect.x;
App::I->height = wnd_rect.w - wnd_rect.y;
startup.client_rect = { wnd_rect.x, wnd_rect.y, wnd_rect.z, wnd_rect.w };
startup.client_pos = { wnd_rect.x, wnd_rect.y };
}
else
{
AdjustWindowRect(&startup.client_rect, startup.window_style, false);
}
return startup;
}
void create_main_window(const MainWindowStartupState& startup, const wchar_t* window_title)
{
auto& state = retained_state();
const int window_width = startup.client_rect.right - startup.client_rect.left;
const int window_height = startup.client_rect.bottom - startup.client_rect.top;
state.hWnd = CreateWindow(
startup.window_class.lpszClassName,
window_title,
startup.window_style,
startup.client_pos.x,
startup.client_pos.y,
window_width,
window_height,
0,
0,
state.hInst,
0);
}
void initialize_pixel_format_descriptor(PIXELFORMATDESCRIPTOR& pixel_format)
{
pixel_format.nSize = sizeof(pixel_format);
pixel_format.nVersion = 1;
pixel_format.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pixel_format.iPixelType = PFD_TYPE_RGBA;
pixel_format.cColorBits = 32;
pixel_format.cDepthBits = 24;
pixel_format.iLayerType = PFD_MAIN_PLANE;
}
bool load_glad_entry_points(HDC device_context)
{
if (!gladLoadGL())
{
LOG("gladLoadGL() failed");
return false;
}
if (!gladLoadWGL(device_context))
{
LOG("gladLoadWGL() failed");
return false;
}
return true;
}
pp::renderer::gl::OpenGlRuntimeInfo log_runtime_info()
{
auto runtime_info = pp::renderer::gl::OpenGlRuntimeInfo {};
const auto runtime_info_result = pp::renderer::gl::query_opengl_runtime_info(
pp::legacy::gl_runtime::runtime_info_dispatch());
if (runtime_info_result.ok())
{
runtime_info = runtime_info_result.value();
LOG("GL version: %s", runtime_info.version);
LOG("GL vendor: %s", runtime_info.vendor);
LOG("GL renderer: %s", runtime_info.renderer);
}
else
{
LOG("OpenGL runtime info query failed: %s", runtime_info_result.status().message);
}
return runtime_info;
}
bool upgrade_to_core_gl_context(const MainWindowStartupState& startup, OpenGlWindowContext& context)
{
if (!GLAD_WGL_ARB_create_context)
{
LOG("WGL_ARB_create_context not supported");
// If not supported, go fuck yourself we are not gonna support your shitty device
return false;
}
const auto wgl_config = pp::renderer::gl::windows_wgl_core_context_3_3_config();
UINT num_format = 0;
wglMakeCurrent(NULL, NULL);
wglDeleteContext(context.render_context);
DestroyWindow(retained_state().hWnd);
create_main_window(startup, retained_state().window_title);
context.device_context = GetDC(retained_state().hWnd);
int pixel_format = 0;
wglChoosePixelFormatARB(
context.device_context,
wgl_config.pixel_format_attributes.data(),
nullptr,
1,
&pixel_format,
&num_format);
SetPixelFormat(context.device_context, pixel_format, &startup.pixel_format);
context.render_context = wglCreateContextAttribsARB(
context.device_context,
NULL,
wgl_config.context_attributes.data());
wglMakeCurrent(context.device_context, context.render_context);
pp::platform::windows::set_async_render_context(context.device_context, context.render_context);
return true;
}
MainStartupResult initialize_main_window_and_gl(MainWindowStartupState& startup, OpenGlWindowContext& context)
{
create_main_window(startup, L"PanoPainter");
initialize_pixel_format_descriptor(startup.pixel_format);
context.device_context = GetDC(retained_state().hWnd);
const int pixel_format = ChoosePixelFormat(context.device_context, &startup.pixel_format);
SetPixelFormat(context.device_context, pixel_format, &startup.pixel_format);
context.render_context = wglCreateContext(context.device_context);
wglMakeCurrent(context.device_context, context.render_context);
pp::platform::windows::set_async_render_context(context.device_context, context.render_context);
if (!load_glad_entry_points(context.device_context))
return MainStartupResult::GladLoadFailure;
context.runtime_info = log_runtime_info();
#ifdef USE_RENDERDOC
if (!win32_renderdoc_init())
LOG("Renderdoc not started");
#endif
const auto renderer_name = std::string(context.runtime_info.renderer != nullptr ? context.runtime_info.renderer : "");
swprintf_s(
retained_state().window_title,
L"PanoPainter %s (%s)",
g_version_number_w,
str2wstr(renderer_name).c_str());
if (!upgrade_to_core_gl_context(startup, context))
return MainStartupResult::MissingCoreContextSupport;
return MainStartupResult::Ok;
}
} }
HWND pp_windows_main_window_handle() HWND pp_windows_main_window_handle()
@@ -687,18 +435,19 @@ void win32_save_window_state()
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
auto& state = retained_state(); auto& state = retained_state();
state.hInst = GetModuleHandle(NULL);
App::I = new App(); App::I = new App();
App::I->set_platform_services(&pp::platform::windows::platform_services()); App::I->set_platform_services(&pp::platform::windows::platform_services());
App::I->initLog(); App::I->initLog();
init_shcore_API(); pp::platform::windows::init_shcore_API();
pp::platform::windows::initialize_stylus_input(); pp::platform::windows::initialize_stylus_input();
if(SetProcessDpiAwareness_fn) if (pp::platform::windows::SetProcessDpiAwareness_fn)
SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE); pp::platform::windows::SetProcessDpiAwareness_fn(PROCESS_PER_MONITOR_DPI_AWARE);
ensure_runtime_data_directory(); pp::platform::windows::ensure_runtime_data_directory();
pp::platform::windows::SplashScreen splash(GetModuleHandle(NULL)); pp::platform::windows::SplashScreen splash(GetModuleHandle(NULL));
@@ -712,15 +461,15 @@ int main(int argc, char** argv)
App::I->create(); App::I->create();
memset(&state.keys, 0, sizeof(state.keys)); memset(&state.keys, 0, sizeof(state.keys));
auto startup = initialize_main_window_startup_state(); auto startup = pp::platform::windows::initialize_main_window_startup_state();
auto context = OpenGlWindowContext {}; auto context = pp::platform::windows::OpenGlWindowContext {};
switch (initialize_main_window_and_gl(startup, context)) switch (pp::platform::windows::initialize_main_window_and_gl(startup, state.hWnd, state.hInst, state.window_title, context))
{ {
case MainStartupResult::Ok: case pp::platform::windows::MainStartupResult::Ok:
break; break;
case MainStartupResult::GladLoadFailure: case pp::platform::windows::MainStartupResult::GladLoadFailure:
return 0; return 0;
case MainStartupResult::MissingCoreContextSupport: case pp::platform::windows::MainStartupResult::MissingCoreContextSupport:
return -1; return -1;
} }
@@ -746,7 +495,7 @@ int main(int argc, char** argv)
// link: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registertouchwindow // link: https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-registertouchwindow
if (RegisterTouchWindow(state.hWnd, 0) == 0) if (RegisterTouchWindow(state.hWnd, 0) == 0)
{ {
LOG("RegisterTouchWindow error: %s", GetLastErrorAsString().c_str()); LOG("RegisterTouchWindow error: %s", pp::platform::windows::GetLastErrorAsString().c_str());
} }
wglMakeCurrent(NULL, NULL); wglMakeCurrent(NULL, NULL);
@@ -756,8 +505,8 @@ int main(int argc, char** argv)
App::I->runtime().ui_thread_start(*App::I); App::I->runtime().ui_thread_start(*App::I);
#ifdef _DEBUG #ifdef _DEBUG
glad_set_pre_callback(_pre_call_callback); glad_set_pre_callback(pp::platform::windows::_pre_call_callback);
glad_set_post_callback(_post_call_callback); glad_set_post_callback(pp::platform::windows::_post_call_callback);
#endif #endif
if (!state.sandboxed) if (!state.sandboxed)

View File

@@ -199,22 +199,6 @@ pp::panopainter::LegacyCanvasStrokeMixPassRequest make_stroke_preview_mix_pass_e
}); });
} }
void copy_stroke_preview_framebuffer_to_texture(
Texture2D& texture,
glm::vec2 size,
std::uint32_t texture_unit)
{
set_active_texture_unit(texture_unit);
texture.bind();
copy_framebuffer_to_texture_2d(
0,
0,
0,
0,
static_cast<int>(size.x),
static_cast<int>(size.y));
}
void bind_stroke_preview_live_samplers( void bind_stroke_preview_live_samplers(
Sampler& mipmap_sampler, Sampler& mipmap_sampler,
Sampler& linear_sampler, Sampler& linear_sampler,
@@ -235,38 +219,6 @@ void bind_stroke_preview_dual_pass_textures(const Brush& dual_brush)
unbind_texture_2d(); unbind_texture_2d();
} }
void bind_stroke_preview_main_pass_textures(
const Brush& brush,
Texture2D& stroke_destination_texture,
RTT& mixer_rtt,
bool copy_stroke_destination,
bool uses_mixer)
{
pp::panopainter::bind_legacy_node_stroke_preview_main_pass_textures(
pp::panopainter::make_legacy_node_stroke_preview_main_pass_texture_dispatch(
[&](int texture_slot) {
set_active_texture_unit(texture_slot);
},
[&] {
brush.m_tip_texture ?
brush.m_tip_texture->bind() :
unbind_texture_2d();
},
[&] {
stroke_destination_texture.bind();
},
[&] {
brush.m_pattern_texture ?
brush.m_pattern_texture->bind() :
unbind_texture_2d();
},
[&] {
mixer_rtt.bindTexture();
}),
copy_stroke_destination,
uses_mixer);
}
void bind_stroke_preview_destination_texture(Texture2D& texture) void bind_stroke_preview_destination_texture(Texture2D& texture)
{ {
set_active_texture_unit(stroke_preview_live_slots::kDestination); set_active_texture_unit(stroke_preview_live_slots::kDestination);
@@ -782,29 +734,19 @@ NodeStrokePreview::make_stroke_draw_immediate_main_live_pass_request(
float zoom, float zoom,
const glm::vec2& size) const glm::vec2& size)
{ {
return StrokeMainLivePassRequest { return pp::panopainter::make_legacy_node_stroke_preview_main_live_pass_request<StrokeFrame>(
.setup_blend_uniforms = [&] { brush,
pp::panopainter::apply_legacy_stroke_blend_uniforms( pass_orchestration,
pass_orchestration.material.stroke_pass.uses_pattern, m_tex,
brush.m_tip_mix, m_rtt_mixer,
brush.m_tip_wet, m_rtt,
brush.m_tip_noise); copy_stroke_destination,
}, size,
.bind_main_pass_textures = [&] { pp::panopainter::kLegacyNodeStrokePreviewStrokeTextureSlot,
bind_stroke_preview_main_pass_textures( [&] {
brush,
m_tex,
m_rtt_mixer,
copy_stroke_destination,
pass_orchestration.material.stroke_pass.uses_mixer);
},
.clear_target = [&] {
m_rtt.clear();
},
.compute_frames = [&] {
return stroke_draw_compute(stroke, zoom); return stroke_draw_compute(stroke, zoom);
}, },
.before_frame = [&](auto& frame) { [&](auto& frame) {
if (brush.m_tip_mix > 0.f) if (brush.m_tip_mix > 0.f)
{ {
stroke_draw_mix(xy(frame.m_mixer_rect), zw(frame.m_mixer_rect)); stroke_draw_mix(xy(frame.m_mixer_rect), zw(frame.m_mixer_rect));
@@ -815,24 +757,17 @@ NodeStrokePreview::make_stroke_draw_immediate_main_live_pass_request(
glm::vec4 { 0, 0, 0, 1 }; glm::vec4 { 0, 0, 0, 1 };
frame.flow = glm::max(frame.flow, m_min_flow); frame.flow = glm::max(frame.flow, m_min_flow);
}, },
.setup_sample_shader = [&](auto& frame) { [&](auto& frame) {
execute_stroke_draw_immediate_main_live_sample_pass( execute_stroke_draw_immediate_main_live_sample_pass(
brush, brush,
copy_stroke_destination, copy_stroke_destination,
frame, frame,
size); size);
}, },
.draw_sample = [&](auto& frame) { [&](auto& frame) {
/*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex, copy_stroke_destination); /*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex, copy_stroke_destination);
}, },
.copy_pass_result = [&] { [&] { set_active_texture_unit(stroke_preview_live_slots::kMixer); m_rtt_mixer.unbindTexture(); });
copy_stroke_preview_framebuffer_to_texture(
m_tex,
size,
stroke_preview_composite_slots::kStroke);
},
.finish_main_pass = [&] { set_active_texture_unit(stroke_preview_live_slots::kMixer); m_rtt_mixer.unbindTexture(); },
};
} }
void NodeStrokePreview::execute_stroke_draw_immediate_dual_pass( void NodeStrokePreview::execute_stroke_draw_immediate_dual_pass(
@@ -869,7 +804,7 @@ void NodeStrokePreview::execute_stroke_draw_immediate_dual_pass(
/*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex_dual, copy_stroke_destination); /*auto rect =*/ stroke_draw_samples(frame.shapes, m_tex_dual, copy_stroke_destination);
}, },
[&] { [&] {
copy_stroke_preview_framebuffer_to_texture( pp::panopainter::copy_legacy_node_stroke_preview_framebuffer_to_texture(
m_tex_dual, m_tex_dual,
size, size,
stroke_preview_composite_slots::kStroke); stroke_preview_composite_slots::kStroke);

View File

@@ -1,7 +1,11 @@
#include "pch.h" #include "pch.h"
#include "platform_windows/windows_bootstrap_helpers.h"
#include "app.h" #include "app.h"
#include "legacy_gl_runtime_dispatch.h"
#include "legacy_preference_storage.h"
#include "log.h" #include "log.h"
#include "renderer_gl/opengl_capabilities.h"
#include <shellscalingapi.h> #include <shellscalingapi.h>
#include <string> #include <string>
@@ -11,6 +15,14 @@
#define USE_RENDERDOC #define USE_RENDERDOC
#endif #endif
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
namespace pp::platform::windows {
void set_async_render_context(HDC hdc, HGLRC hrc);
}
namespace pp::platform::windows {
#ifdef USE_RENDERDOC #ifdef USE_RENDERDOC
RENDERDOC_API_1_4_0* rdoc_api = NULL; RENDERDOC_API_1_4_0* rdoc_api = NULL;
@@ -75,6 +87,213 @@ std::string GetLastErrorAsString()
return message; return message;
} }
void ensure_runtime_data_directory()
{
FILE* fp_check = fopen("data\\layout.xml", "rb");
if (!fp_check)
{
LOG("data files not found");
static char path[MAX_PATH];
GetModuleFileNameA(NULL, path, MAX_PATH);
LOG("current dir %s", path);
PathRemoveFileSpecA(path);
SetCurrentDirectoryA(path);
LOG("change dir to %s", path);
return;
}
fclose(fp_check);
LOG("data files ok");
}
MainWindowStartupState initialize_main_window_startup_state()
{
auto startup = MainWindowStartupState {};
const auto hInst = GetModuleHandle(NULL);
const auto className = L"EngineMain";
startup.window_class.hInstance = hInst;
startup.window_class.lpfnWndProc = (WNDPROC)WndProc;
startup.window_class.lpszClassName = className;
startup.window_class.hbrBackground = (HBRUSH)COLOR_WINDOW;
startup.window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
RegisterClass(&startup.window_class);
auto monitor = MonitorFromWindow(0, MONITOR_DEFAULTTOPRIMARY);
auto x = unsigned{ 96 };
auto y = unsigned{ 96 };
if (GetDpiForMonitor_fn)
GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI, &x, &y);
App::I->display_density = (float)x / 96.f;
const auto window_preferences = pp::panopainter::read_legacy_window_preferences(SW_NORMAL);
if (window_preferences.has_ui_scale)
App::I->zoom = window_preferences.ui_scale;
else
App::I->zoom = (float)x / 96.f;
startup.show_command = window_preferences.show_command;
startup.client_rect = {
0,
0,
static_cast<LONG>(App::I->width * App::I->zoom),
static_cast<LONG>(App::I->height * App::I->zoom),
};
if (window_preferences.has_window_rect)
{
auto wnd_rect = window_preferences.window_rect;
App::I->width = wnd_rect.z - wnd_rect.x;
App::I->height = wnd_rect.w - wnd_rect.y;
startup.client_rect = { wnd_rect.x, wnd_rect.y, wnd_rect.z, wnd_rect.w };
startup.client_pos = { wnd_rect.x, wnd_rect.y };
}
else
{
AdjustWindowRect(&startup.client_rect, startup.window_style, false);
}
return startup;
}
void create_main_window(const MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, const wchar_t* window_title)
{
const int window_width = startup.client_rect.right - startup.client_rect.left;
const int window_height = startup.client_rect.bottom - startup.client_rect.top;
hWnd = CreateWindow(
startup.window_class.lpszClassName,
window_title,
startup.window_style,
startup.client_pos.x,
startup.client_pos.y,
window_width,
window_height,
0,
0,
hInst,
0);
}
void initialize_pixel_format_descriptor(PIXELFORMATDESCRIPTOR& pixel_format)
{
pixel_format.nSize = sizeof(pixel_format);
pixel_format.nVersion = 1;
pixel_format.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pixel_format.iPixelType = PFD_TYPE_RGBA;
pixel_format.cColorBits = 32;
pixel_format.cDepthBits = 24;
pixel_format.iLayerType = PFD_MAIN_PLANE;
}
bool load_glad_entry_points(HDC device_context)
{
if (!gladLoadGL())
{
LOG("gladLoadGL() failed");
return false;
}
if (!gladLoadWGL(device_context))
{
LOG("gladLoadWGL() failed");
return false;
}
return true;
}
pp::renderer::gl::OpenGlRuntimeInfo log_runtime_info()
{
auto runtime_info = pp::renderer::gl::OpenGlRuntimeInfo {};
const auto runtime_info_result = pp::renderer::gl::query_opengl_runtime_info(
pp::legacy::gl_runtime::runtime_info_dispatch());
if (runtime_info_result.ok())
{
runtime_info = runtime_info_result.value();
LOG("GL version: %s", runtime_info.version);
LOG("GL vendor: %s", runtime_info.vendor);
LOG("GL renderer: %s", runtime_info.renderer);
}
else
{
LOG("OpenGL runtime info query failed: %s", runtime_info_result.status().message);
}
return runtime_info;
}
bool upgrade_to_core_gl_context(const MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, const wchar_t* window_title, OpenGlWindowContext& context)
{
if (!GLAD_WGL_ARB_create_context)
{
LOG("WGL_ARB_create_context not supported");
// If not supported, go fuck yourself we are not gonna support your shitty device
return false;
}
const auto wgl_config = pp::renderer::gl::windows_wgl_core_context_3_3_config();
UINT num_format = 0;
wglMakeCurrent(NULL, NULL);
wglDeleteContext(context.render_context);
DestroyWindow(hWnd);
create_main_window(startup, hWnd, hInst, window_title);
context.device_context = GetDC(hWnd);
int pixel_format = 0;
wglChoosePixelFormatARB(
context.device_context,
wgl_config.pixel_format_attributes.data(),
nullptr,
1,
&pixel_format,
&num_format);
SetPixelFormat(context.device_context, pixel_format, &startup.pixel_format);
context.render_context = wglCreateContextAttribsARB(
context.device_context,
NULL,
wgl_config.context_attributes.data());
wglMakeCurrent(context.device_context, context.render_context);
set_async_render_context(context.device_context, context.render_context);
return true;
}
MainStartupResult initialize_main_window_and_gl(MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, wchar_t* window_title, OpenGlWindowContext& context)
{
create_main_window(startup, hWnd, hInst, L"PanoPainter");
initialize_pixel_format_descriptor(startup.pixel_format);
context.device_context = GetDC(hWnd);
const int pixel_format = ChoosePixelFormat(context.device_context, &startup.pixel_format);
SetPixelFormat(context.device_context, pixel_format, &startup.pixel_format);
context.render_context = wglCreateContext(context.device_context);
wglMakeCurrent(context.device_context, context.render_context);
set_async_render_context(context.device_context, context.render_context);
if (!load_glad_entry_points(context.device_context))
return MainStartupResult::GladLoadFailure;
context.runtime_info = log_runtime_info();
#ifdef USE_RENDERDOC
if (!win32_renderdoc_init())
LOG("Renderdoc not started");
#endif
const auto renderer_name = std::string(context.runtime_info.renderer != nullptr ? context.runtime_info.renderer : "");
swprintf_s(
window_title,
512,
L"PanoPainter %s (%s)",
g_version_number_w,
str2wstr(renderer_name).c_str());
if (!upgrade_to_core_gl_context(startup, hWnd, hInst, window_title, context))
return MainStartupResult::MissingCoreContextSupport;
return MainStartupResult::Ok;
}
BOOL UnadjustWindowRectEx(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwExStyle) BOOL UnadjustWindowRectEx(LPRECT prc, DWORD dwStyle, BOOL fMenu, DWORD dwExStyle)
{ {
RECT rc; RECT rc;
@@ -104,3 +323,5 @@ void _post_call_callback(const char* name, void* funcptr, int len_args, ...)
LOG("ERROR %d in %s\n", error_code, name); LOG("ERROR %d in %s\n", error_code, name);
} }
} }
}

View File

@@ -0,0 +1,57 @@
#pragma once
#include <Windows.h>
#include <shellscalingapi.h>
#include <string>
#include "renderer_gl/opengl_capabilities.h"
namespace pp::platform::windows {
bool win32_renderdoc_init();
void win32_renderdoc_frame_start();
void win32_renderdoc_frame_end();
extern HRESULT (*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
extern HRESULT (*SetProcessDpiAwareness_fn)(PROCESS_DPI_AWARENESS value);
void init_shcore_API();
std::string GetLastErrorAsString();
void _pre_call_callback(const char* name, void* funcptr, int len_args, ...);
void _post_call_callback(const char* name, void* funcptr, int len_args, ...);
struct MainWindowStartupState
{
WNDCLASS window_class{};
PIXELFORMATDESCRIPTOR pixel_format{};
DWORD window_style = WS_OVERLAPPEDWINDOW;
RECT client_rect{ 0, 0, 0, 0 };
POINT client_pos{ CW_USEDEFAULT, CW_USEDEFAULT };
int show_command = SW_NORMAL;
};
struct OpenGlWindowContext
{
HDC device_context{};
HGLRC render_context{};
pp::renderer::gl::OpenGlRuntimeInfo runtime_info{};
};
enum class MainStartupResult
{
Ok = 0,
GladLoadFailure = 1,
MissingCoreContextSupport = 2,
};
void ensure_runtime_data_directory();
MainWindowStartupState initialize_main_window_startup_state();
void create_main_window(const MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, const wchar_t* window_title);
void initialize_pixel_format_descriptor(PIXELFORMATDESCRIPTOR& pixel_format);
bool load_glad_entry_points(HDC device_context);
pp::renderer::gl::OpenGlRuntimeInfo log_runtime_info();
bool upgrade_to_core_gl_context(const MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, const wchar_t* window_title, OpenGlWindowContext& context);
MainStartupResult initialize_main_window_and_gl(MainWindowStartupState& startup, HWND& hWnd, HINSTANCE hInst, wchar_t* window_title, OpenGlWindowContext& context);
}

View File

@@ -1,4 +1,5 @@
#include "pch.h" #include "pch.h"
#include "platform_windows/windows_bootstrap_helpers.h"
#include "platform_windows/windows_platform_services.h" #include "platform_windows/windows_platform_services.h"
#include "log.h" #include "log.h"
@@ -15,19 +16,15 @@ void destroy_window();
void async_lock(); void async_lock();
void async_unlock(); void async_unlock();
void win32_async_swap(); void win32_async_swap();
void win32_renderdoc_frame_start();
void win32_renderdoc_frame_end();
void win32_update_fps(int frames); void win32_update_fps(int frames);
void win32_update_stylus(float dt); void win32_update_stylus(float dt);
void win32_save_window_state(); void win32_save_window_state();
bool win32_vr_start(); bool win32_vr_start();
void win32_vr_stop(); void win32_vr_stop();
std::string GetLastErrorAsString();
HWND pp_windows_main_window_handle(); HWND pp_windows_main_window_handle();
void pp_windows_enqueue_main_task(std::packaged_task<void()> task); void pp_windows_enqueue_main_task(std::packaged_task<void()> task);
namespace pp::platform::windows { namespace pp::platform::windows {
namespace { namespace {
struct RetainedWin32AsyncRenderContextState final { struct RetainedWin32AsyncRenderContextState final {
@@ -43,8 +40,7 @@ struct RetainedWin32AsyncRenderContextState final {
static RetainedWin32AsyncRenderContextState state; static RetainedWin32AsyncRenderContextState state;
return state; return state;
} }
} // namespace
}
void set_async_render_context(HDC hdc, HGLRC hrc) void set_async_render_context(HDC hdc, HGLRC hrc)
{ {
@@ -63,7 +59,7 @@ void lock_async_render_context()
state.gl_mutex.lock(); state.gl_mutex.lock();
const bool ret = wglMakeCurrent(state.hdc, state.hrc); const bool ret = wglMakeCurrent(state.hdc, state.hrc);
if (!ret) if (!ret)
LOG("FAILED wglMakeCurrent: %s", GetLastErrorAsString().c_str()); LOG("FAILED wglMakeCurrent: %s", pp::platform::windows::GetLastErrorAsString().c_str());
state.gl_thread = std::this_thread::get_id(); state.gl_thread = std::this_thread::get_id();
} }
state.gl_count++; state.gl_count++;
@@ -78,7 +74,7 @@ bool try_lock_async_render_context()
return false; return false;
const bool ret = wglMakeCurrent(state.hdc, state.hrc); const bool ret = wglMakeCurrent(state.hdc, state.hrc);
if (!ret) if (!ret)
LOG("FAILED wglMakeCurrent: %s", GetLastErrorAsString().c_str()); LOG("FAILED wglMakeCurrent: %s", pp::platform::windows::GetLastErrorAsString().c_str());
state.gl_thread = std::this_thread::get_id(); state.gl_thread = std::this_thread::get_id();
} }
state.gl_count++; state.gl_count++;
@@ -100,8 +96,7 @@ void swap_async_render_context()
{ {
SwapBuffers(retained_win32_async_render_context_state().hdc); SwapBuffers(retained_win32_async_render_context_state().hdc);
} }
} // namespace pp::platform::windows
}
namespace { namespace {
@@ -438,12 +433,12 @@ public:
void begin_render_capture_frame() override void begin_render_capture_frame() override
{ {
win32_renderdoc_frame_start(); pp::platform::windows::win32_renderdoc_frame_start();
} }
void end_render_capture_frame() override void end_render_capture_frame() override
{ {
win32_renderdoc_frame_end(); pp::platform::windows::win32_renderdoc_frame_end();
} }
[[nodiscard]] bool deletes_recorded_files_on_clear() override [[nodiscard]] bool deletes_recorded_files_on_clear() override

View File

@@ -1,5 +1,6 @@
#include "pch.h" #include "pch.h"
#include "platform_windows/windows_splash.h" #include "platform_windows/windows_splash.h"
#include "platform_windows/windows_bootstrap_helpers.h"
#include "app.h" #include "app.h"
#include "image.h" #include "image.h"
@@ -13,8 +14,6 @@
#include <string> #include <string>
#include <stop_token> #include <stop_token>
extern HRESULT(*GetDpiForMonitor_fn)(HMONITOR hmonitor, MONITOR_DPI_TYPE dpiType, UINT* dpiX, UINT* dpiY);
namespace { namespace {
constexpr UINT kSplashCloseMessage = WM_USER + 1; constexpr UINT kSplashCloseMessage = WM_USER + 1;
@@ -42,8 +41,8 @@ LRESULT CALLBACK splash_proc(HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lPara
auto monitor = MonitorFromWindow(0, MONITOR_DEFAULTTOPRIMARY); auto monitor = MonitorFromWindow(0, MONITOR_DEFAULTTOPRIMARY);
auto x = unsigned{ 96 }; auto x = unsigned{ 96 };
auto y = unsigned{ 96 }; auto y = unsigned{ 96 };
if (GetDpiForMonitor_fn) if (pp::platform::windows::GetDpiForMonitor_fn)
GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI, &x, &y); pp::platform::windows::GetDpiForMonitor_fn(monitor, MDT_EFFECTIVE_DPI, &x, &y);
float z = (float)x / 96.f; float z = (float)x / 96.f;
static char base_path[MAX_PATH]; static char base_path[MAX_PATH];