Extract edit menu and Windows/bootstrap preview seams
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
47
src/app_layout_edit_menu.cpp
Normal file
47
src/app_layout_edit_menu.cpp
Normal 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
|
||||||
@@ -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)
|
||||||
|
|||||||
281
src/main.cpp
281
src/main.cpp
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
57
src/platform_windows/windows_bootstrap_helpers.h
Normal file
57
src/platform_windows/windows_bootstrap_helpers.h
Normal 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);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
Reference in New Issue
Block a user