Route default canvas resolution through platform services

This commit is contained in:
2026-06-04 19:20:06 +02:00
parent b2334e65c9
commit 0489c4229e
12 changed files with 57 additions and 10 deletions

View File

@@ -776,7 +776,10 @@ Known warnings after the current CMake app build:
- `pp_legacy_paint_document` is an object-library containment boundary for - `pp_legacy_paint_document` is an object-library containment boundary for
retained action, bezier, brush, canvas, canvas-layer, and event code. It retained action, bezier, brush, canvas, canvas-layer, and event code. It
should shrink as app painting and document behavior consume `pp_paint` and should shrink as app painting and document behavior consume `pp_paint` and
`pp_document` directly. `pp_document` directly. Shared `canvas.h` no longer owns the platform
`CANVAS_RES` macro; default canvas allocation now asks `PlatformServices`,
preserving the WebGL 512 default in the legacy fallback while DEBT-0057
tracks moving that policy into an injected Web platform service.
- `pp_legacy_engine` intentionally contains retained legacy runtime shell - `pp_legacy_engine` intentionally contains retained legacy runtime shell
sources for now, so it concentrates existing legacy tablet, video, HMD, log, sources for now, so it concentrates existing legacy tablet, video, HMD, log,
and low-level utility warnings until those paths move to cleaner component and low-level utility warnings until those paths move to cleaner component

View File

@@ -74,6 +74,7 @@ agent or engineer to remove them without reconstructing context from chat.
| DEBT-0054 | Open | Modernization | Layout XML file read/reload decisions now consume `pp_platform_api::plan_asset_file_load`, but that helper still encodes the retained compile-time platform policy: Windows/macOS use `stat` mtime reload checks, while other platforms treat already-loaded layouts as successful no-op loads | Preserve current layout hot-reload and mobile/Web single-load behavior while removing platform guards from the shared `LayoutManager` parser | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests`; Windows app build | Layout reload decisions are owned by injected platform storage/file-watch services or an asset manager boundary with platform-specific file watching removed from compile-time helpers | | DEBT-0054 | Open | Modernization | Layout XML file read/reload decisions now consume `pp_platform_api::plan_asset_file_load`, but that helper still encodes the retained compile-time platform policy: Windows/macOS use `stat` mtime reload checks, while other platforms treat already-loaded layouts as successful no-op loads | Preserve current layout hot-reload and mobile/Web single-load behavior while removing platform guards from the shared `LayoutManager` parser | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests`; Windows app build | Layout reload decisions are owned by injected platform storage/file-watch services or an asset manager boundary with platform-specific file watching removed from compile-time helpers |
| DEBT-0055 | Open | Modernization | `src/app.h` now forward-declares retained iOS/macOS/Android/Linux/Web platform handles instead of including platform SDK headers, and full SDK includes are isolated in `src/platform_legacy/legacy_platform_services.cpp`, but the `App` singleton still stores those platform handles directly | Reduce central header platform coupling incrementally without rewriting non-Windows platform entrypoints before Phase 6 | Windows app build; Apple/Android/Linux/Web package smoke once platform root builds are active | Platform handles are owned by injected `pp_platform_*` shell state or services, and `App` has no platform SDK handle fields or platform conditional members | | DEBT-0055 | Open | Modernization | `src/app.h` now forward-declares retained iOS/macOS/Android/Linux/Web platform handles instead of including platform SDK headers, and full SDK includes are isolated in `src/platform_legacy/legacy_platform_services.cpp`, but the `App` singleton still stores those platform handles directly | Reduce central header platform coupling incrementally without rewriting non-Windows platform entrypoints before Phase 6 | Windows app build; Apple/Android/Linux/Web package smoke once platform root builds are active | Platform handles are owned by injected `pp_platform_*` shell state or services, and `App` has no platform SDK handle fields or platform conditional members |
| DEBT-0056 | Open | Modernization | `src/asset.h` now forward-declares Android asset-manager types and uses `Asset::set_android_asset_manager` instead of public mutable manager state, but retained `Asset` still stores Android asset handles and `src/asset.cpp` still performs Android `AAssetManager` reads directly; the current `android-arm64` root preset is headless and does not expose `pp_legacy_assets_io` | Reduce legacy asset I/O header coupling without rewriting Android asset loading before the asset manager/storage boundary exists | Windows app build; `cmake --build --preset android-arm64 --target pp_assets`; Android package smoke once package builds consume shared targets | Android asset loading is owned by injected asset storage/platform services or `pp_assets` file providers, with no static Android asset manager on `Asset` | | DEBT-0056 | Open | Modernization | `src/asset.h` now forward-declares Android asset-manager types and uses `Asset::set_android_asset_manager` instead of public mutable manager state, but retained `Asset` still stores Android asset handles and `src/asset.cpp` still performs Android `AAssetManager` reads directly; the current `android-arm64` root preset is headless and does not expose `pp_legacy_assets_io` | Reduce legacy asset I/O header coupling without rewriting Android asset loading before the asset manager/storage boundary exists | Windows app build; `cmake --build --preset android-arm64 --target pp_assets`; Android package smoke once package builds consume shared targets | Android asset loading is owned by injected asset storage/platform services or `pp_assets` file providers, with no static Android asset manager on `Asset` |
| DEBT-0057 | Open | Modernization | Default canvas allocation size now dispatches through `PlatformServices::default_canvas_resolution`, removing the `CANVAS_RES` platform macro from `src/canvas.h`, but WebGL's retained 512 default still lives in `src/platform_legacy/legacy_platform_services.cpp` until the Web shell owns injected services | Preserve WebGL memory behavior while moving canvas creation policy out of shared canvas headers and into the platform boundary | `pp_platform_api_tests`; `ctest --preset desktop-fast --build-config Debug -R pp_platform_api_tests`; Windows app build; WebGL package smoke once root Web build exists | Default canvas resolution is owned by injected `pp_platform_*` services for every supported platform, with no WebGL branch in the legacy fallback |
## Closed Debt ## Closed Debt

View File

@@ -667,6 +667,11 @@ hides the Android asset handles behind `Asset::set_android_asset_manager`, and
keeps concrete Android asset-manager headers in `asset.cpp`/the Android keeps concrete Android asset-manager headers in `asset.cpp`/the Android
entrypoint. This reduces legacy asset I/O header coupling while the actual entrypoint. This reduces legacy asset I/O header coupling while the actual
Android asset-reader implementation remains inside `pp_legacy_assets_io`. Android asset-reader implementation remains inside `pp_legacy_assets_io`.
Default canvas allocation size now dispatches through `PlatformServices`, so
`NodeCanvas` and command-line conversion creation paths preserve the desktop
1536 and WebGL 512 defaults without carrying the old `CANVAS_RES` platform
macro in `canvas.h`; DEBT-0057 tracks moving the retained WebGL policy branch
out of the legacy fallback when the Web shell owns injected services.
Prepared-file save/download handoff is now also part of the service contract, Prepared-file save/download handoff is now also part of the service contract,
so iOS/Web export completion routes through `PlatformServices` after the app so iOS/Web export completion routes through `PlatformServices` after the app
writes the temporary/exported payload. writes the temporary/exported payload.

View File

@@ -192,6 +192,7 @@ public:
[[nodiscard]] bool uses_ppbr_export_data_directory_override() const; [[nodiscard]] bool uses_ppbr_export_data_directory_override() const;
[[nodiscard]] bool platform_supports_sonarpen() const; [[nodiscard]] bool platform_supports_sonarpen() const;
void start_platform_sonarpen(); void start_platform_sonarpen();
[[nodiscard]] int default_canvas_resolution() const;
[[nodiscard]] bool draws_canvas_tip_for_input(kEventSource source, kEventType type) const; [[nodiscard]] bool draws_canvas_tip_for_input(kEventSource source, kEventType type) const;
[[nodiscard]] float adjust_canvas_input_pressure(float pressure) const; [[nodiscard]] float adjust_canvas_input_pressure(float pressure) const;
void pick_dir(std::function<void(std::string path)> callback); void pick_dir(std::function<void(std::string path)> callback);

View File

@@ -40,7 +40,8 @@ void App::cmd_convert(std::string pano_path, std::string out_path)
glBlendEquation(add_blend_equation()); glBlendEquation(add_blend_equation());
Canvas* command_canvas = new Canvas; Canvas* command_canvas = new Canvas;
command_canvas->create(CANVAS_RES, CANVAS_RES); const int canvas_resolution = default_canvas_resolution();
command_canvas->create(canvas_resolution, canvas_resolution);
command_canvas->project_open_thread(pano_path); command_canvas->project_open_thread(pano_path);
command_canvas->export_equirectangular_thread(out_path); command_canvas->export_equirectangular_thread(out_path);
} }

View File

@@ -211,6 +211,11 @@ void App::start_platform_sonarpen()
active_platform_services().start_sonarpen(); active_platform_services().start_sonarpen();
} }
int App::default_canvas_resolution() const
{
return active_platform_services().default_canvas_resolution();
}
bool App::draws_canvas_tip_for_input(kEventSource source, kEventType type) const bool App::draws_canvas_tip_for_input(kEventSource source, kEventType type) const
{ {
return active_platform_services().draws_canvas_tip_for_pointer( return active_platform_services().draws_canvas_tip_for_pointer(

View File

@@ -10,12 +10,6 @@
#include <stack> #include <stack>
#include "mp4enc.h" #include "mp4enc.h"
#if __WEB__
#define CANVAS_RES 512
#else
#define CANVAS_RES 1536
#endif
struct PPIThumb struct PPIThumb
{ {
int width = 128; int width = 128;

View File

@@ -153,7 +153,8 @@ void NodeCanvas::init()
m_mouse_ignore = false; m_mouse_ignore = false;
m_canvas = std::make_unique<Canvas>(); m_canvas = std::make_unique<Canvas>();
m_canvas->create(CANVAS_RES, CANVAS_RES); const int canvas_resolution = App::I->default_canvas_resolution();
m_canvas->create(canvas_resolution, canvas_resolution);
m_canvas->m_unsaved = false; m_canvas->m_unsaved = false;
m_canvas->m_node = this; m_canvas->m_node = this;
@@ -179,7 +180,8 @@ void NodeCanvas::init()
void NodeCanvas::restore_context() void NodeCanvas::restore_context()
{ {
Node::restore_context(); Node::restore_context();
m_canvas->create(CANVAS_RES, CANVAS_RES); const int canvas_resolution = App::I->default_canvas_resolution();
m_canvas->create(canvas_resolution, canvas_resolution);
m_sampler.create(); m_sampler.create();

View File

@@ -73,6 +73,7 @@ public:
[[nodiscard]] virtual bool uses_ppbr_export_data_directory_override() = 0; [[nodiscard]] virtual bool uses_ppbr_export_data_directory_override() = 0;
[[nodiscard]] virtual bool supports_sonarpen() = 0; [[nodiscard]] virtual bool supports_sonarpen() = 0;
virtual void start_sonarpen() = 0; virtual void start_sonarpen() = 0;
[[nodiscard]] virtual int default_canvas_resolution() = 0;
[[nodiscard]] virtual bool draws_canvas_tip_for_pointer( [[nodiscard]] virtual bool draws_canvas_tip_for_pointer(
bool is_mouse, bool is_mouse,
bool is_stylus, bool is_stylus,

View File

@@ -510,6 +510,15 @@ public:
#endif #endif
} }
[[nodiscard]] int default_canvas_resolution() override
{
#if __WEB__
return 512;
#else
return 1536;
#endif
}
[[nodiscard]] bool draws_canvas_tip_for_pointer( [[nodiscard]] bool draws_canvas_tip_for_pointer(
bool is_mouse, bool is_mouse,
bool is_stylus, bool is_stylus,

View File

@@ -508,6 +508,11 @@ public:
{ {
} }
[[nodiscard]] int default_canvas_resolution() override
{
return 1536;
}
[[nodiscard]] bool draws_canvas_tip_for_pointer( [[nodiscard]] bool draws_canvas_tip_for_pointer(
bool is_mouse, bool is_mouse,
bool is_stylus, bool is_stylus,

View File

@@ -274,6 +274,12 @@ public:
++sonarpen_starts; ++sonarpen_starts;
} }
[[nodiscard]] int default_canvas_resolution() override
{
++default_canvas_resolution_requests;
return canvas_resolution;
}
[[nodiscard]] bool draws_canvas_tip_for_pointer( [[nodiscard]] bool draws_canvas_tip_for_pointer(
bool is_mouse, bool is_mouse,
bool is_stylus, bool is_stylus,
@@ -362,6 +368,7 @@ public:
int ppbr_export_data_directory_override_checks = 0; int ppbr_export_data_directory_override_checks = 0;
int sonarpen_support_checks = 0; int sonarpen_support_checks = 0;
int sonarpen_starts = 0; int sonarpen_starts = 0;
int default_canvas_resolution_requests = 0;
int canvas_tip_policy_checks = 0; int canvas_tip_policy_checks = 0;
int canvas_pressure_adjustments = 0; int canvas_pressure_adjustments = 0;
int prepare_writable_file_requests = 0; int prepare_writable_file_requests = 0;
@@ -376,6 +383,7 @@ public:
bool network_tls_verification_disabled = false; bool network_tls_verification_disabled = false;
bool ppbr_export_data_directory_override = false; bool ppbr_export_data_directory_override = false;
bool sonarpen_supported = false; bool sonarpen_supported = false;
int canvas_resolution = 1536;
bool canvas_tip_visible = false; bool canvas_tip_visible = false;
bool last_canvas_tip_mouse = false; bool last_canvas_tip_mouse = false;
bool last_canvas_tip_stylus = false; bool last_canvas_tip_stylus = false;
@@ -815,6 +823,17 @@ void platform_services_dispatch_sonarpen_policy_and_start(pp::tests::Harness& ha
PP_EXPECT(harness, fake.sonarpen_starts == 1); PP_EXPECT(harness, fake.sonarpen_starts == 1);
} }
void platform_services_dispatch_default_canvas_resolution(pp::tests::Harness& harness)
{
FakePlatformServices fake("unused");
pp::platform::PlatformServices& services = fake;
PP_EXPECT(harness, services.default_canvas_resolution() == 1536);
fake.canvas_resolution = 512;
PP_EXPECT(harness, services.default_canvas_resolution() == 512);
PP_EXPECT(harness, fake.default_canvas_resolution_requests == 2);
}
void platform_services_dispatch_canvas_input_policy(pp::tests::Harness& harness) void platform_services_dispatch_canvas_input_policy(pp::tests::Harness& harness)
{ {
FakePlatformServices fake("unused"); FakePlatformServices fake("unused");
@@ -873,6 +892,7 @@ int main()
"platform services dispatch ppbr export directory policy", "platform services dispatch ppbr export directory policy",
platform_services_dispatch_ppbr_export_directory_policy); platform_services_dispatch_ppbr_export_directory_policy);
harness.run("platform services dispatch sonarpen policy and start", platform_services_dispatch_sonarpen_policy_and_start); harness.run("platform services dispatch sonarpen policy and start", platform_services_dispatch_sonarpen_policy_and_start);
harness.run("platform services dispatch default canvas resolution", platform_services_dispatch_default_canvas_resolution);
harness.run("platform services dispatch canvas input policy", platform_services_dispatch_canvas_input_policy); harness.run("platform services dispatch canvas input policy", platform_services_dispatch_canvas_input_policy);
return harness.finish(); return harness.finish();
} }