Split Apple platform target and move platform state ownership
This commit is contained in:
@@ -239,8 +239,6 @@ add_library(pp_platform_api STATIC
|
||||
src/platform_api/asset_file_load_policy.h
|
||||
src/platform_api/network_tls_policy.cpp
|
||||
src/platform_api/network_tls_policy.h
|
||||
src/platform_apple/apple_platform_services.cpp
|
||||
src/platform_apple/apple_platform_services.h
|
||||
src/platform_api/platform_policy.cpp
|
||||
src/platform_api/platform_policy.h
|
||||
src/platform_api/platform_services.cpp
|
||||
@@ -255,6 +253,18 @@ target_link_libraries(pp_platform_api
|
||||
PRIVATE
|
||||
pp_project_warnings)
|
||||
|
||||
add_library(pp_platform_apple STATIC
|
||||
${PP_PLATFORM_APPLE_SOURCES})
|
||||
target_include_directories(pp_platform_apple
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/src")
|
||||
target_link_libraries(pp_platform_apple
|
||||
PUBLIC
|
||||
pp_platform_api
|
||||
pp_project_options
|
||||
PRIVATE
|
||||
pp_project_warnings)
|
||||
|
||||
add_library(pp_app_core STATIC
|
||||
src/app_core/about_menu.h
|
||||
src/app_core/app_dialog.h
|
||||
@@ -608,6 +618,9 @@ if(PP_BUILD_APP)
|
||||
pp_project_options
|
||||
PRIVATE
|
||||
pp_project_warnings)
|
||||
if(APPLE)
|
||||
target_link_libraries(panopainter_app PRIVATE pp_platform_apple)
|
||||
endif()
|
||||
pp_add_version_generation(panopainter_app "$<IF:$<CONFIG:Debug>,debug,release>")
|
||||
|
||||
add_library(pp_platform_windows OBJECT
|
||||
|
||||
@@ -117,6 +117,11 @@ set(PP_PLATFORM_LINUX_SOURCES
|
||||
src/platform_linux/linux_platform_services.h
|
||||
)
|
||||
|
||||
set(PP_PLATFORM_APPLE_SOURCES
|
||||
src/platform_apple/apple_platform_services.cpp
|
||||
src/platform_apple/apple_platform_services.h
|
||||
)
|
||||
|
||||
set(PP_PANOPAINTER_APP_SOURCES
|
||||
src/app.cpp
|
||||
src/app_runtime.cpp
|
||||
|
||||
@@ -92,6 +92,20 @@ Current hotspot files:
|
||||
|
||||
Latest slice:
|
||||
|
||||
- `pp_platform_api` no longer compiles
|
||||
`src/platform_apple/apple_platform_services.*`; Apple concrete platform
|
||||
code now lives in the new `pp_platform_apple` target, and
|
||||
`panopainter_app` plus `pp_platform_api_tests` link that concrete target
|
||||
where needed.
|
||||
- Retained GLFW window hooks/state and retained Apple UI/app handle snapshots
|
||||
now live in `src/platform_legacy/legacy_platform_state.*` instead of staying
|
||||
inline in `src/platform_legacy/legacy_platform_services.cpp`, which trims
|
||||
another process-global platform-state pocket out of the legacy platform
|
||||
shell and removes more direct `App::I` reads from touched platform paths.
|
||||
- Windows VR session snapshot ownership now lives in
|
||||
`src/platform_windows/windows_vr_shell.h` and
|
||||
`src/platform_windows/windows_platform_services.*` instead of on `App`,
|
||||
with app-side reads now routed through `App::vr_session_snapshot()`.
|
||||
- The live Windows entry shell now routes through
|
||||
`run_main_application(...)` in
|
||||
`src/platform_windows/windows_runtime_shell.*`, leaving `src/main.cpp` as a
|
||||
@@ -172,8 +186,9 @@ Latest slice:
|
||||
|
||||
Current architecture mismatches that must be treated as real blockers:
|
||||
|
||||
- `pp_platform_api` still compiles Apple implementation files instead of only
|
||||
platform-neutral policy and interface code.
|
||||
- `pp_platform_api` no longer compiles Apple implementation files, but it
|
||||
still owns concrete Linux platform sources instead of only platform-neutral
|
||||
policy and interface code.
|
||||
- `src/platform_apple/apple_platform_services.cpp` no longer reaches `App::I`
|
||||
directly, and Linux FPS title reporting now uses an injected callback, but
|
||||
retained Apple bridging in `platform_legacy` and other platform/app coupling
|
||||
@@ -185,8 +200,10 @@ Current architecture mismatches that must be treated as real blockers:
|
||||
route through retained local GLFW callback hooks, and retained Apple ObjC
|
||||
handles plus storage paths now sit behind one local `platform_legacy`
|
||||
helper instead of being re-read through `App::I` in each touched path, with
|
||||
the retained GLFW window hooks and fallback storage-path return now also
|
||||
using local retained-state helpers instead of direct method-body reads.
|
||||
the retained GLFW window hooks, Apple handle snapshots, and fallback
|
||||
storage-path return now also using local retained-state helpers instead of
|
||||
direct method-body reads, while Windows VR session snapshot state now also
|
||||
lives behind platform-owned helpers instead of on `App`.
|
||||
- `src/platform_legacy/legacy_platform_services.*` is still part of the live
|
||||
app shell.
|
||||
- `pp_panopainter_ui` still depends on `pp_legacy_app`.
|
||||
|
||||
@@ -41,7 +41,8 @@ Completed, blocked, and superseded task history moved to
|
||||
`src/node_stroke_preview.cpp`, `src/app.cpp`, `src/app_dialogs.cpp`, and the
|
||||
extracted canvas/platform containment files.
|
||||
- The platform boundary is not finished:
|
||||
- `pp_platform_api` still compiles Apple implementation files
|
||||
- `pp_platform_api` no longer compiles Apple implementation files, but it
|
||||
still compiles concrete Linux platform sources
|
||||
- `platform_apple` no longer reaches `App::I` directly, and Linux FPS title
|
||||
reporting now uses an injected callback, but retained Apple bridging and
|
||||
broader platform-to-app singleton reach are still open in
|
||||
@@ -1063,11 +1064,21 @@ layer.
|
||||
|
||||
#### ARC-PLT-001 - Split `pp_platform_api` From Concrete Platform Code
|
||||
|
||||
Status: Ready
|
||||
Status: In Progress
|
||||
|
||||
Why now:
|
||||
`pp_platform_api` is supposed to be the SDK-free policy and interface layer,
|
||||
but it still compiles `src/platform_apple/apple_platform_services.*`.
|
||||
and while Apple implementation has now moved out, it still compiles concrete
|
||||
Linux platform sources.
|
||||
|
||||
Current slice:
|
||||
- `pp_platform_api` no longer compiles
|
||||
`src/platform_apple/apple_platform_services.*`.
|
||||
- Apple concrete platform code now lives in the new `pp_platform_apple`
|
||||
target, and `panopainter_app` plus `pp_platform_api_tests` now link that
|
||||
concrete target where needed.
|
||||
- The dependency direction is cleaner for Apple, but the same split is still
|
||||
incomplete for Linux and the broader concrete platform family.
|
||||
|
||||
Write scope:
|
||||
- `CMakeLists.txt`
|
||||
@@ -1128,6 +1139,10 @@ Current slice:
|
||||
- retained storage-path state now also lives in
|
||||
`src/platform_legacy/legacy_platform_state.*` instead of staying inline in
|
||||
`src/platform_legacy/legacy_platform_services.cpp`
|
||||
- retained GLFW window hooks/state and retained Apple UI/app handle state now
|
||||
also live in `src/platform_legacy/legacy_platform_state.*`, and
|
||||
`src/platform_legacy/legacy_platform_services.cpp` now consumes those
|
||||
snapshots without direct `App::I` reads in the touched paths
|
||||
- retained Apple callback injection and broader `platform_legacy` singleton
|
||||
reach are still open
|
||||
- The remaining Win32 shell wrappers for close, async lock/swap,
|
||||
@@ -1160,12 +1175,22 @@ Mini-model packet:
|
||||
|
||||
#### ARC-PLT-003 - Remove App-Owned Cross-Platform Handle Storage
|
||||
|
||||
Status: Ready
|
||||
Status: In Progress
|
||||
|
||||
Why now:
|
||||
`src/platform_legacy/legacy_platform_services.cpp` and `src/app.h` still keep
|
||||
platform-handle state on `App`, which blocks a real `pp_platform_*` shell split.
|
||||
|
||||
Current slice:
|
||||
- Windows VR session snapshot ownership no longer lives on `App`.
|
||||
- `VrSessionSnapshot` now lives behind
|
||||
`src/platform_windows/windows_vr_shell.h` and
|
||||
`read_platform_vr_session_snapshot()` in
|
||||
`src/platform_windows/windows_platform_services.*`, with app-side reads now
|
||||
routed through `App::vr_session_snapshot()`.
|
||||
- `App` still owns other platform-facing handles and retained legacy platform
|
||||
state is not fully removed, so this remains a live ownership task.
|
||||
|
||||
Write scope:
|
||||
- `src/platform_legacy/legacy_platform_services.*`
|
||||
- `src/app.h`
|
||||
|
||||
13
src/app.h
13
src/app.h
@@ -77,6 +77,14 @@ struct VRController
|
||||
virtual float get_trigger_value() const { return 1.f; }
|
||||
};
|
||||
|
||||
struct VrSessionSnapshot
|
||||
{
|
||||
bool has_vr = false;
|
||||
bool vr_active = false;
|
||||
std::array<VRController, 2> vr_controllers{};
|
||||
glm::mat4 vr_head{1.0f};
|
||||
};
|
||||
|
||||
class App
|
||||
{
|
||||
public:
|
||||
@@ -125,7 +133,6 @@ public:
|
||||
std::string doc_dir;
|
||||
std::string doc_filename;
|
||||
bool has_stylus = false;
|
||||
bool has_vr = false;
|
||||
bool vr_controllers_enabled = true;
|
||||
float off_x = 0;
|
||||
float off_y = 0;
|
||||
@@ -136,10 +143,7 @@ public:
|
||||
bool animate = false;
|
||||
bool ui_visible = true;
|
||||
bool ui_rtl = false;
|
||||
bool vr_active = false;
|
||||
bool vr_only = false;
|
||||
VRController vr_controllers[2];
|
||||
glm::mat4 vr_head;
|
||||
float vr_pressure = 1.f;
|
||||
glm::mat4 vr_rot{ 0 };
|
||||
glm::mat4 vr_uirot{ 0 };
|
||||
@@ -209,6 +213,7 @@ public:
|
||||
[[nodiscard]] bool platform_enables_live_asset_reloading();
|
||||
void update_platform_frame(float delta_time_seconds);
|
||||
void report_rendered_frames(int frames);
|
||||
[[nodiscard]] VrSessionSnapshot vr_session_snapshot() const;
|
||||
void save_prepared_file(
|
||||
std::string path,
|
||||
std::string suggested_name,
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
#include <GLFW/glfw3.h>
|
||||
#include "platform_linux/linux_platform_services.h"
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include "platform_windows/windows_platform_services.h"
|
||||
#endif
|
||||
#include "platform_legacy/legacy_platform_services.h"
|
||||
#include "renderer_gl/opengl_capabilities.h"
|
||||
|
||||
@@ -435,6 +438,15 @@ void App::report_rendered_frames(int frames)
|
||||
active_platform_services().report_rendered_frames(frames);
|
||||
}
|
||||
|
||||
VrSessionSnapshot App::vr_session_snapshot() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return pp::platform::windows::read_platform_vr_session_snapshot();
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
void App::save_prepared_file(
|
||||
std::string path,
|
||||
std::string suggested_name,
|
||||
@@ -655,10 +667,11 @@ bool App::touch_tap(const glm::vec2& pos, int fingers, int tap_count)
|
||||
}
|
||||
bool App::key_down(kKey key)
|
||||
{
|
||||
const auto vr_session = vr_session_snapshot();
|
||||
const auto plan = pp::app::plan_app_key_down_dispatch(
|
||||
layout.get(main_id) != nullptr,
|
||||
key == kKey::KeySpacebar,
|
||||
vr_active);
|
||||
vr_session.vr_active);
|
||||
if (plan.sync_vr_camera_rotation)
|
||||
canvas->m_canvas->m_cam_rot = vr_rot;
|
||||
redraw = plan.request_redraw;
|
||||
|
||||
@@ -357,7 +357,7 @@ void bind_legacy_tools_menu(App& app)
|
||||
if (auto vr_btn = popup_time->find<NodeButtonCustom>("tools-vr"))
|
||||
{
|
||||
NodeCheckBox* cb = vr_btn->find<NodeCheckBox>("tools-vr-check");
|
||||
cb->set_value(app.has_vr);
|
||||
cb->set_value(app.vr_session_snapshot().has_vr);
|
||||
|
||||
vr_btn->on_click = [vr_btn](Node*)
|
||||
{
|
||||
|
||||
@@ -128,6 +128,8 @@ void App::vr_update(float dt)
|
||||
{
|
||||
if (!vr_controllers_enabled)
|
||||
return;
|
||||
|
||||
const auto vr_session = vr_session_snapshot();
|
||||
canvas->m_canvas->m_cam_fov = 60;
|
||||
float tan_fov = glm::tan(glm::radians(canvas->m_canvas->m_cam_fov / 2.f));
|
||||
glm::vec3 aspect = { (float)uirtt.getWidth() / (float)uirtt.getHeight(), 1.f, 1.f };
|
||||
@@ -142,8 +144,8 @@ void App::vr_update(float dt)
|
||||
auto r = glm::normalize(glm::vec3(glm::vec4(1, 0, 0, 0) * mm));
|
||||
auto n = glm::normalize(glm::vec3(glm::vec4(0, 0, 1, 0) * mm));
|
||||
auto u = glm::normalize(glm::vec3(glm::vec4(0, 1, 0, 0) * mm));
|
||||
auto co = vr_controllers[0].get_pos();
|
||||
auto cd = glm::mat3(vr_controllers[0].m_mat) * glm::mat3(glm::eulerAngleX(glm::radians(-30.f))) * glm::vec3(0, 0, -1);
|
||||
auto co = vr_session.vr_controllers[0].get_pos();
|
||||
auto cd = glm::mat3(vr_session.vr_controllers[0].m_mat) * glm::mat3(glm::eulerAngleX(glm::radians(-30.f))) * glm::vec3(0, 0, -1);
|
||||
ui_inside = false;
|
||||
glm::vec3 hit;
|
||||
float t;
|
||||
@@ -167,7 +169,7 @@ void App::vr_update(float dt)
|
||||
|
||||
if (down_controller)
|
||||
{
|
||||
glm::vec3 head_position = vr_head[3];
|
||||
glm::vec3 head_position = vr_session.vr_head[3];
|
||||
glm::vec3 c_pos = glm::normalize(down_controller->get_pos() - head_position) * 800.f;
|
||||
controller_points.add(c_pos);
|
||||
auto p = controller_points.average();
|
||||
@@ -210,7 +212,7 @@ void App::vr_analog(const VRController& c, VRController::kButton b, VRController
|
||||
{
|
||||
if (a == VRController::kAction::Press)
|
||||
{
|
||||
glm::vec3 head_position = vr_head[3];
|
||||
glm::vec3 head_position = vr_session_snapshot().vr_head[3];
|
||||
glm::vec3 c_pos = glm::normalize(c.get_pos() - head_position) * 800.f;
|
||||
render_task_async([=] {
|
||||
Canvas::I->stroke_start(c_pos, force.x);
|
||||
@@ -517,7 +519,8 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
// draw the motion controller sphere
|
||||
if (vr_controllers_enabled && ui_visible && ui_inside)
|
||||
{
|
||||
auto mvp = proj * camera * vr_controllers[0].m_mat * glm::eulerAngleX(glm::radians(-30.f));
|
||||
const auto vr_session = vr_session_snapshot();
|
||||
auto mvp = proj * camera * vr_session.vr_controllers[0].m_mat * glm::eulerAngleX(glm::radians(-30.f));
|
||||
pp::panopainter::setup_legacy_vr_color_shader(
|
||||
pp::panopainter::LegacyVrColorUniforms {
|
||||
.color = { 1, 0, 1, 1 },
|
||||
@@ -530,7 +533,8 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
// draw the motion controller brush
|
||||
if (vr_controllers_enabled && (!ui_visible || !ui_inside))
|
||||
{
|
||||
glm::vec3 cpos = vr_controllers[0].get_pos() - xyz(pose[3]);
|
||||
const auto vr_session = vr_session_snapshot();
|
||||
glm::vec3 cpos = vr_session.vr_controllers[0].get_pos() - xyz(pose[3]);
|
||||
auto pos = glm::translate(glm::normalize(cpos) * 100.f);
|
||||
auto tip_color = glm::vec4(glm::vec3(canvas->m_canvas->m_current_brush->m_tip_color), 1);
|
||||
pp::panopainter::setup_legacy_vr_stroke_preview_shader(
|
||||
|
||||
@@ -110,10 +110,11 @@ void execute_legacy_app_ui_thread_stop(App& app)
|
||||
|
||||
void App::draw(float dt)
|
||||
{
|
||||
const auto vr_session = vr_session_snapshot();
|
||||
const auto draw_plan = pp::app::plan_app_frame_draw(
|
||||
canvas != nullptr,
|
||||
canvas && canvas->m_canvas,
|
||||
vr_active,
|
||||
vr_session.vr_active,
|
||||
ui_visible,
|
||||
vr_only);
|
||||
|
||||
|
||||
@@ -106,7 +106,8 @@ void CanvasModeBasicCamera::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto dir = (App::I->has_vr && App::I->vr_active) ? glm::vec2(1, 1) : glm::vec2(-1, -1);
|
||||
const auto vr_session = App::I->vr_session_snapshot();
|
||||
auto dir = (vr_session.has_vr && vr_session.vr_active) ? glm::vec2(1, 1) : glm::vec2(-1, -1);
|
||||
Canvas::I->m_pan = m_pan_start + (me->m_pos - m_dragR_start) * dir * (Canvas::I->m_cam_fov / 85.f);
|
||||
auto angle = Canvas::I->m_pan * 0.003f;
|
||||
Canvas::I->m_cam_rot = glm::eulerAngleXY(angle.y, angle.x);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include "platform_legacy/legacy_platform_services.h"
|
||||
#include "platform_legacy/legacy_platform_state.h"
|
||||
|
||||
#include "app.h"
|
||||
#include "legacy_ui_gl_dispatch.h"
|
||||
#include "log.h"
|
||||
#include "platform_apple/apple_platform_services.h"
|
||||
@@ -36,13 +35,11 @@ void delete_all_files_in_path(const std::string& source_path);
|
||||
void save_image_library(const std::string& path);
|
||||
#endif
|
||||
#elif __LINUX__
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <tinyfiledialogs.h>
|
||||
#include "platform_linux/linux_platform_services.h"
|
||||
std::string linux_home_path();
|
||||
int mkpath(const std::string& dir, mode_t mode = DEFFILEMODE);
|
||||
#elif __WEB__
|
||||
#include <GLFW/glfw3.h>
|
||||
void webgl_pick_file(std::function<void(std::string)> callback);
|
||||
void webgl_pick_file_save(
|
||||
const std::string& path,
|
||||
@@ -95,43 +92,6 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(__LINUX__) || defined(__WEB__)
|
||||
struct RetainedLegacyGlfwWindowHooks final {
|
||||
std::function<void()> acquire_render_context;
|
||||
std::function<void()> present_render_context;
|
||||
std::function<void()> request_app_close;
|
||||
};
|
||||
|
||||
struct RetainedLegacyGlfwWindowState final {
|
||||
decltype(App::I->glfw_window) window = nullptr;
|
||||
RetainedLegacyGlfwWindowHooks hooks;
|
||||
};
|
||||
|
||||
[[nodiscard]] RetainedLegacyGlfwWindowState& active_legacy_glfw_window_state()
|
||||
{
|
||||
static RetainedLegacyGlfwWindowState state = [] {
|
||||
RetainedLegacyGlfwWindowState retained;
|
||||
retained.window = App::I->glfw_window;
|
||||
retained.hooks.acquire_render_context = [window = retained.window] {
|
||||
glfwMakeContextCurrent(window);
|
||||
};
|
||||
retained.hooks.present_render_context = [window = retained.window] {
|
||||
glfwSwapBuffers(window);
|
||||
};
|
||||
retained.hooks.request_app_close = [window = retained.window] {
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
};
|
||||
return retained;
|
||||
}();
|
||||
return state;
|
||||
}
|
||||
|
||||
[[nodiscard]] RetainedLegacyGlfwWindowHooks& active_legacy_glfw_window_hooks()
|
||||
{
|
||||
return active_legacy_glfw_window_state().hooks;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__IOS__) || defined(__OSX__)
|
||||
[[nodiscard]] NSMutableArray<NSString*>* apple_file_types_array(const std::vector<std::string>& file_types)
|
||||
{
|
||||
@@ -143,47 +103,21 @@ struct RetainedLegacyGlfwWindowState final {
|
||||
return types;
|
||||
}
|
||||
|
||||
struct RetainedLegacyAppleState final {
|
||||
#ifdef __IOS__
|
||||
decltype(App::I->ios_view) ios_view = nullptr;
|
||||
decltype(App::I->ios_app) ios_app = nullptr;
|
||||
#elif defined(__OSX__)
|
||||
decltype(App::I->osx_view) osx_view = nullptr;
|
||||
decltype(App::I->osx_app) osx_app = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
[[nodiscard]] RetainedLegacyAppleState& active_legacy_apple_state()
|
||||
{
|
||||
static RetainedLegacyAppleState state = [] {
|
||||
RetainedLegacyAppleState retained;
|
||||
#ifdef __IOS__
|
||||
retained.ios_view = App::I->ios_view;
|
||||
retained.ios_app = App::I->ios_app;
|
||||
#elif defined(__OSX__)
|
||||
retained.osx_view = App::I->osx_view;
|
||||
retained.osx_app = App::I->osx_app;
|
||||
#endif
|
||||
return retained;
|
||||
}();
|
||||
return state;
|
||||
}
|
||||
|
||||
[[nodiscard]] pp::platform::PlatformStoragePaths prepare_legacy_apple_storage_paths()
|
||||
{
|
||||
const auto& apple_state = active_legacy_apple_state();
|
||||
const auto& apple_state = pp::platform::legacy::active_legacy_apple_state();
|
||||
#ifdef __IOS__
|
||||
[apple_state.ios_view init_dirs];
|
||||
#elif defined(__OSX__)
|
||||
[apple_state.osx_app init_dirs];
|
||||
#endif
|
||||
return active_legacy_storage_paths();
|
||||
return pp::platform::legacy::active_legacy_storage_paths();
|
||||
}
|
||||
|
||||
[[nodiscard]] pp::platform::apple::AppleDocumentPlatformServices& active_apple_document_platform_services()
|
||||
{
|
||||
#ifdef __IOS__
|
||||
const auto& apple_state = active_legacy_apple_state();
|
||||
const auto& apple_state = pp::platform::legacy::active_legacy_apple_state();
|
||||
auto* const ios_view = apple_state.ios_view;
|
||||
auto* const ios_app = apple_state.ios_app;
|
||||
static pp::platform::apple::AppleDocumentPlatformServices services(
|
||||
@@ -259,7 +193,7 @@ struct RetainedLegacyAppleState final {
|
||||
}());
|
||||
return services;
|
||||
#else
|
||||
const auto& apple_state = active_legacy_apple_state();
|
||||
const auto& apple_state = pp::platform::legacy::active_legacy_apple_state();
|
||||
auto* const osx_view = apple_state.osx_view;
|
||||
auto* const osx_app = apple_state.osx_app;
|
||||
static pp::platform::apple::AppleDocumentPlatformServices services(
|
||||
@@ -470,7 +404,7 @@ public:
|
||||
#elif __ANDROID__
|
||||
android_async_lock();
|
||||
#elif __LINUX__ || __WEB__
|
||||
active_legacy_glfw_window_hooks().acquire_render_context();
|
||||
pp::platform::legacy::active_legacy_glfw_window_hooks().acquire_render_context();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -490,7 +424,7 @@ public:
|
||||
#elif __ANDROID__
|
||||
android_async_swap();
|
||||
#elif __LINUX__ || __WEB__
|
||||
active_legacy_glfw_window_hooks().present_render_context();
|
||||
pp::platform::legacy::active_legacy_glfw_window_hooks().present_render_context();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -801,7 +735,7 @@ public:
|
||||
#ifdef __OSX__
|
||||
active_apple_document_platform_services().request_app_close();
|
||||
#elif __LINUX__
|
||||
active_legacy_glfw_window_hooks().request_app_close();
|
||||
pp::platform::legacy::active_legacy_glfw_window_hooks().request_app_close();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
|
||||
#include "app.h"
|
||||
|
||||
#if defined(__LINUX__) || defined(__WEB__)
|
||||
#include <GLFW/glfw3.h>
|
||||
#endif
|
||||
|
||||
namespace pp::platform::legacy {
|
||||
namespace {
|
||||
|
||||
@@ -12,6 +16,50 @@ struct RetainedLegacyStoragePaths final {
|
||||
|
||||
}
|
||||
|
||||
#if defined(__LINUX__) || defined(__WEB__)
|
||||
[[nodiscard]] RetainedLegacyGlfwWindowState& active_legacy_glfw_window_state()
|
||||
{
|
||||
static RetainedLegacyGlfwWindowState state = [] {
|
||||
RetainedLegacyGlfwWindowState retained;
|
||||
retained.window = App::I->glfw_window;
|
||||
retained.hooks.acquire_render_context = [window = retained.window] {
|
||||
glfwMakeContextCurrent(window);
|
||||
};
|
||||
retained.hooks.present_render_context = [window = retained.window] {
|
||||
glfwSwapBuffers(window);
|
||||
};
|
||||
retained.hooks.request_app_close = [window = retained.window] {
|
||||
glfwSetWindowShouldClose(window, GLFW_TRUE);
|
||||
};
|
||||
return retained;
|
||||
}();
|
||||
return state;
|
||||
}
|
||||
|
||||
[[nodiscard]] RetainedLegacyGlfwWindowHooks& active_legacy_glfw_window_hooks()
|
||||
{
|
||||
return active_legacy_glfw_window_state().hooks;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__IOS__) || defined(__OSX__)
|
||||
[[nodiscard]] RetainedLegacyAppleState& active_legacy_apple_state()
|
||||
{
|
||||
static RetainedLegacyAppleState state = [] {
|
||||
RetainedLegacyAppleState retained;
|
||||
#ifdef __IOS__
|
||||
retained.ios_view = App::I->ios_view;
|
||||
retained.ios_app = App::I->ios_app;
|
||||
#elif defined(__OSX__)
|
||||
retained.osx_view = App::I->osx_view;
|
||||
retained.osx_app = App::I->osx_app;
|
||||
#endif
|
||||
return retained;
|
||||
}();
|
||||
return state;
|
||||
}
|
||||
#endif
|
||||
|
||||
[[nodiscard]] const pp::platform::PlatformStoragePaths& active_legacy_storage_paths()
|
||||
{
|
||||
static RetainedLegacyStoragePaths state = [] {
|
||||
|
||||
@@ -2,8 +2,52 @@
|
||||
|
||||
#include "platform_api/platform_services.h"
|
||||
|
||||
#if __LINUX__ || __WEB__
|
||||
struct GLFWwindow;
|
||||
#endif
|
||||
|
||||
#if defined(__OBJC__) && defined(__IOS__)
|
||||
@class GameViewController;
|
||||
@class AppDelegate;
|
||||
#endif
|
||||
|
||||
#if defined(__OBJC__) && defined(__OSX__)
|
||||
@class View;
|
||||
@class AppOSX;
|
||||
#endif
|
||||
|
||||
namespace pp::platform::legacy {
|
||||
|
||||
#if defined(__LINUX__) || defined(__WEB__)
|
||||
struct RetainedLegacyGlfwWindowHooks final {
|
||||
std::function<void()> acquire_render_context;
|
||||
std::function<void()> present_render_context;
|
||||
std::function<void()> request_app_close;
|
||||
};
|
||||
|
||||
struct RetainedLegacyGlfwWindowState final {
|
||||
GLFWwindow* window = nullptr;
|
||||
RetainedLegacyGlfwWindowHooks hooks;
|
||||
};
|
||||
|
||||
[[nodiscard]] RetainedLegacyGlfwWindowState& active_legacy_glfw_window_state();
|
||||
[[nodiscard]] RetainedLegacyGlfwWindowHooks& active_legacy_glfw_window_hooks();
|
||||
#endif
|
||||
|
||||
#if defined(__IOS__) || defined(__OSX__)
|
||||
struct RetainedLegacyAppleState final {
|
||||
#ifdef __IOS__
|
||||
GameViewController* ios_view = nullptr;
|
||||
AppDelegate* ios_app = nullptr;
|
||||
#elif defined(__OSX__)
|
||||
View* osx_view = nullptr;
|
||||
AppOSX* osx_app = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
[[nodiscard]] RetainedLegacyAppleState& active_legacy_apple_state();
|
||||
#endif
|
||||
|
||||
[[nodiscard]] const pp::platform::PlatformStoragePaths& active_legacy_storage_paths();
|
||||
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ void update_window_fps(HWND hWnd, const wchar_t* window_title, VrShellState& vr,
|
||||
{
|
||||
static wchar_t title_fps[512];
|
||||
const int vr_fps = current_vr_fps(vr);
|
||||
if (App::I->vr_active)
|
||||
if (read_vr_session_snapshot(vr).vr_active)
|
||||
swprintf_s(title_fps, L"%s - %d fps - %d vr fps", window_title, frames, vr_fps);
|
||||
else
|
||||
swprintf_s(title_fps, L"%s - %d fps", window_title, frames);
|
||||
|
||||
@@ -793,4 +793,9 @@ PlatformServices& platform_services()
|
||||
return services;
|
||||
}
|
||||
|
||||
VrSessionSnapshot read_platform_vr_session_snapshot() noexcept
|
||||
{
|
||||
return read_vr_session_snapshot(retained_state().vr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#include <future>
|
||||
|
||||
struct VrSessionSnapshot;
|
||||
|
||||
namespace pp::platform::windows {
|
||||
|
||||
[[nodiscard]] PlatformServices& platform_services();
|
||||
[[nodiscard]] VrSessionSnapshot read_platform_vr_session_snapshot() noexcept;
|
||||
void enqueue_main_thread_task(std::packaged_task<void()> task);
|
||||
void drain_main_thread_tasks();
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
namespace pp::platform::windows {
|
||||
|
||||
struct VrShellState final {
|
||||
std::mutex snapshot_mutex;
|
||||
VrSessionSnapshot session;
|
||||
std::jthread hmd_renderer;
|
||||
std::mutex hmd_render_mutex;
|
||||
std::condition_variable hmd_render_cv;
|
||||
@@ -27,6 +29,35 @@ inline int current_vr_fps(const VrShellState& state)
|
||||
return state.vr_frames.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
inline VrSessionSnapshot read_vr_session_snapshot(VrShellState& state)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state.snapshot_mutex);
|
||||
return state.session;
|
||||
}
|
||||
|
||||
inline void write_vr_session_snapshot(
|
||||
VrShellState& state,
|
||||
bool has_vr,
|
||||
bool vr_active,
|
||||
const VRController& primary_controller,
|
||||
const glm::mat4& vr_head)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state.snapshot_mutex);
|
||||
state.session.has_vr = has_vr;
|
||||
state.session.vr_active = vr_active;
|
||||
state.session.vr_controllers[0] = primary_controller;
|
||||
state.session.vr_head = vr_head;
|
||||
}
|
||||
|
||||
inline void clear_vr_session_snapshot(VrShellState& state, bool has_vr)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(state.snapshot_mutex);
|
||||
state.session.has_vr = has_vr;
|
||||
state.session.vr_active = false;
|
||||
state.session.vr_controllers[0] = {};
|
||||
state.session.vr_head = glm::mat4(1.0f);
|
||||
}
|
||||
|
||||
inline void request_stop_and_join_vr_thread(VrShellState& state)
|
||||
{
|
||||
if (state.hmd_renderer.joinable())
|
||||
@@ -64,7 +95,7 @@ inline bool start_vr_shell(VrShellState& state, bool sandboxed, std::atomic<int>
|
||||
|
||||
BT_SetTerminate();
|
||||
LOG("start hmd render thread");
|
||||
App::I->has_vr = true;
|
||||
clear_vr_session_snapshot(state, true);
|
||||
state.vr_running.store(true, std::memory_order_relaxed);
|
||||
|
||||
state.vive->on_analog_button = std::bind(&App::vr_analog, App::I, std::placeholders::_1,
|
||||
@@ -99,9 +130,12 @@ inline bool start_vr_shell(VrShellState& state, bool sandboxed, std::atomic<int>
|
||||
frames++;
|
||||
|
||||
state.vive->Update();
|
||||
App::I->vr_active = state.vive->m_active;
|
||||
App::I->vr_controllers[0] = state.vive->m_controllers[0];
|
||||
App::I->vr_head = state.vive->m_pose;
|
||||
write_vr_session_snapshot(
|
||||
state,
|
||||
true,
|
||||
state.vive->m_active,
|
||||
state.vive->m_controllers[0],
|
||||
state.vive->m_pose);
|
||||
App::I->vr_update(dt);
|
||||
|
||||
if (state.vr_running.load(std::memory_order_relaxed) && state.vive->m_active)
|
||||
@@ -118,8 +152,7 @@ inline bool start_vr_shell(VrShellState& state, bool sandboxed, std::atomic<int>
|
||||
t0 = t1;
|
||||
}
|
||||
|
||||
App::I->vr_active = false;
|
||||
App::I->has_vr = false;
|
||||
clear_vr_session_snapshot(state, false);
|
||||
state.vr_running.store(false, std::memory_order_relaxed);
|
||||
state.vive->Terminate();
|
||||
LOG("hmd renderer terminated");
|
||||
|
||||
@@ -352,6 +352,9 @@ add_executable(pp_platform_api_tests
|
||||
target_link_libraries(pp_platform_api_tests PRIVATE
|
||||
pp_platform_api
|
||||
pp_test_harness)
|
||||
if(TARGET pp_platform_apple)
|
||||
target_link_libraries(pp_platform_api_tests PRIVATE pp_platform_apple)
|
||||
endif()
|
||||
|
||||
add_test(NAME pp_platform_api_tests COMMAND pp_platform_api_tests)
|
||||
set_tests_properties(pp_platform_api_tests PROPERTIES
|
||||
|
||||
Reference in New Issue
Block a user