From 7ef399eb75e74816498d8b3569b27198ca433dcc Mon Sep 17 00:00:00 2001 From: omigamedev Date: Tue, 16 Jun 2026 07:49:03 +0200 Subject: [PATCH] Own log worker and trim Apple platform hooks --- docs/modernization/debt.md | 16 +++++++++++++ docs/modernization/roadmap.md | 8 ++++--- docs/modernization/tasks.md | 7 ++++++ src/legacy_canvas_draw_merge_services.h | 22 +++++++++++++++++ src/log.cpp | 5 ++-- src/log.h | 2 +- src/node_canvas.cpp | 18 +++++++------- .../apple_platform_services.cpp | 18 ++++++++++++++ src/platform_apple/apple_platform_services.h | 6 +++++ .../legacy_platform_services.cpp | 24 ++++++++++++++----- 10 files changed, 104 insertions(+), 22 deletions(-) diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index d064e3f8..ccf9f08e 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -18,6 +18,22 @@ agent or engineer to remove them without reconstructing context from chat. ## Reductions +- 2026-06-16: `DEBT-0036` was narrowed again. `NodeCanvas` cache-to-screen + checkerboard-plane callback setup now routes through + `make_legacy_canvas_draw_merge_cache_to_screen_checkerboard_plane(...)` in + `src/legacy_canvas_draw_merge_services.h` instead of building the full MVP + callback body inline in `NodeCanvas::draw()`; broader canvas draw + orchestration remains. +- 2026-06-16: `DEBT-0003` was narrowed again. `LogRemote` now owns its network + logging worker as `std::jthread` with explicit stop requests in `src/log.*` + instead of raw `std::thread` ownership; retained global logger singleton, + network logging policy, and queue execution remain. +- 2026-06-16: `DEBT-0017` was narrowed again. Apple crash-test, app-close, and + iOS SonarPen hooks now route through explicit bridge callbacks in + `src/platform_apple/apple_platform_services.*` consumed by + `src/platform_legacy/legacy_platform_services.cpp` instead of direct `App::I` + calls in those legacy platform methods; the retained Apple fallback adapter + and broader platform singleton reach remain. - 2026-06-16: `DEBT-0036` was narrowed again. `NodeCanvas` merged-path and non-blend checkerboard background setup now route through `execute_legacy_canvas_draw_merge_background_setup(...)` in diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index 4890335c..a4383c3c 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -100,7 +100,7 @@ Current architecture mismatches that must be treated as real blockers: remain, even though iOS keyboard visibility and prepared-file save handoff now also route through explicit Apple bridge callbacks and Apple render- context hooks plus iOS main-render-target binding now route through the same - bridge style. + bridge style, as do Apple crash-test, app-close, and iOS SonarPen hooks. - `src/platform_legacy/legacy_platform_services.*` is still part of the live app shell. - `pp_panopainter_ui` still depends on `pp_legacy_app`. @@ -108,7 +108,8 @@ Current architecture mismatches that must be treated as real blockers: OpenGL execution around the renderer boundary, even though `NodeCanvas` display resolve, cache-to-screen composite, post-draw mask/grid/current-mode sequencing, per-layer/per-plane retained draw execution, and shared - checkerboard background setup now route through retained draw-merge helpers. + checkerboard background setup now route through retained draw-merge helpers, + with the cache-to-screen checkerboard-plane callback setup also reduced. - `app_layout.cpp` and `app_dialogs.cpp` are still mixed shell/controller files rather than thin composition/binding surfaces. - `App`, `Canvas`, `Node`, retained workers, and platform entrypoints still use @@ -118,7 +119,8 @@ Current architecture mismatches that must be treated as real blockers: launches now use owned `std::jthread` or service-owned worker queues and `AppRuntime` now owns render/UI workers with explicit `std::jthread` shutdown semantics while the Windows splash-dialog and HMD renderer workers - also use owned `std::jthread` lifecycle. + also use owned `std::jthread` lifecycle and `LogRemote` now uses the same + ownership model. - Modern C++23 usage exists in extracted components, especially `std::span`, explicit result/status objects, and a few concepts, but the live app still does not consistently express ownership, thread affinity, or renderer diff --git a/docs/modernization/tasks.md b/docs/modernization/tasks.md index c2ca8731..764c9995 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -133,6 +133,8 @@ Current slice: node still owns most live-pass and retained GL resource execution. - `NodeCanvas` merged-path and non-blend checkerboard background setup now also route through `execute_legacy_canvas_draw_merge_background_setup(...)`. +- `NodeCanvas` cache-to-screen checkerboard-plane callback setup now also routes + through a retained helper in `legacy_canvas_draw_merge_services.h`. - `NodeCanvas` display resolve plus cache-to-screen checkerboard/cache-texture composite now route through `legacy_canvas_draw_merge_services.h`. - `NodeCanvas` smoothing-mask overlay, smoothing-mask face pass, grid keepalive @@ -375,6 +377,8 @@ Current slice: - Windows splash-dialog and HMD renderer worker ownership in `main.cpp` now also use `std::jthread` with explicit stop requests instead of raw `std::thread` +- `LogRemote` worker ownership in `src/log.*` now also uses `std::jthread` + with explicit stop requests instead of raw `std::thread` - brush package import/export now use service-owned `std::jthread` workers and UI-thread completion handoff - prepared-file save work and grid lightmap launch now also use service-owned @@ -593,6 +597,9 @@ Current slice: - Apple render-context acquire/release/present hooks and iOS `bind_main_render_target()` now also route through explicit Apple bridge callbacks instead of direct `App::I` calls in `LegacyPlatformServices` +- Apple crash-test, app-close, and iOS SonarPen hooks now also route through + explicit Apple bridge callbacks instead of direct `App::I` calls in + `LegacyPlatformServices` - retained Apple callback injection and broader `platform_legacy` singleton reach are still open diff --git a/src/legacy_canvas_draw_merge_services.h b/src/legacy_canvas_draw_merge_services.h index 887daefc..534aa46e 100644 --- a/src/legacy_canvas_draw_merge_services.h +++ b/src/legacy_canvas_draw_merge_services.h @@ -568,6 +568,28 @@ inline void execute_legacy_canvas_draw_merge_cache_to_screen_composite( execution.unbind_cache_texture(); } +template +[[nodiscard]] inline auto make_legacy_canvas_draw_merge_cache_to_screen_checkerboard_plane( + glm::mat4 proj, + glm::mat4 camera, + float layer_scale, + PlaneTransform plane_transform, + DrawPlane draw_plane) +{ + return [proj, camera, layer_scale, plane_transform, draw_plane]( + const LegacyCanvasDrawMergeCheckerboardUniforms& uniforms, + int plane_index) { + auto checkerboard_uniforms = uniforms; + checkerboard_uniforms.mvp = proj * camera * + glm::scale(glm::vec3(layer_scale)) * + plane_transform[plane_index] * + glm::translate(glm::vec3(0, 0, -1.f)); + + setup_legacy_canvas_draw_merge_checkerboard_shader(checkerboard_uniforms); + draw_plane(); + }; +} + inline void execute_legacy_canvas_draw_merge_display_resolve( const LegacyCanvasDrawMergeDisplayResolveUniforms& uniforms, const LegacyCanvasDrawMergeDisplayResolveExecution& execution) diff --git a/src/log.cpp b/src/log.cpp index 1d813139..cc55cb54 100644 --- a/src/log.cpp +++ b/src/log.cpp @@ -12,12 +12,12 @@ void LogRemote::start() return; // already running m_running = true; - m_thread = std::thread([&] { + m_thread = std::jthread([this](std::stop_token stop_token) { BT_SetTerminate(); net_init(); auto session_string = net_request("/start"); m_session = atoi(session_string.c_str()); - while (m_running && !m_error) + while (m_running && !m_error && !stop_token.stop_requested()) { auto m = m_mq.Get(); auto escaped = curl_easy_escape(curl, m.c_str(), (int)m.size()); @@ -35,6 +35,7 @@ void LogRemote::start() void LogRemote::stop() { m_running = false; + m_thread.request_stop(); m_mq.UnlockGetters(); if (m_thread.joinable()) m_thread.join(); diff --git a/src/log.h b/src/log.h index 4e4f29ed..73d95045 100644 --- a/src/log.h +++ b/src/log.h @@ -18,7 +18,7 @@ public: static LogRemote I; bool m_running = false; bool m_error = false; - std::thread m_thread; + std::jthread m_thread; std::mutex m_mutex; BlockingQueue m_mq; // Store messages until the file is open diff --git a/src/node_canvas.cpp b/src/node_canvas.cpp index 53ea5013..64bd8dcd 100644 --- a/src/node_canvas.cpp +++ b/src/node_canvas.cpp @@ -690,16 +690,14 @@ void NodeCanvas::draw() .enable_blend = [&] { apply_node_canvas_capability(pp::renderer::gl::blend_state(), true); }, - .draw_checkerboard_plane = [&](const pp::panopainter::LegacyCanvasDrawMergeCheckerboardUniforms& uniforms, int plane_index) { - auto checkerboard_uniforms = uniforms; - checkerboard_uniforms.mvp = proj * camera * - glm::scale(glm::vec3(m_canvas->m_layers.size() + 500.f)) * - m_canvas->m_plane_transform[plane_index] * - glm::translate(glm::vec3(0, 0, -1.f)); - - pp::panopainter::setup_legacy_canvas_draw_merge_checkerboard_shader(checkerboard_uniforms); - m_face_plane.draw_fill(); - }, + .draw_checkerboard_plane = pp::panopainter::make_legacy_canvas_draw_merge_cache_to_screen_checkerboard_plane( + proj, + camera, + m_canvas->m_layers.size() + 500.f, + m_canvas->m_plane_transform, + [&] { + m_face_plane.draw_fill(); + }), .bind_sampler = [&] { m_sampler.bind(0); set_active_texture_unit(0); diff --git a/src/platform_apple/apple_platform_services.cpp b/src/platform_apple/apple_platform_services.cpp index 013674ad..2a709360 100644 --- a/src/platform_apple/apple_platform_services.cpp +++ b/src/platform_apple/apple_platform_services.cpp @@ -183,6 +183,24 @@ void AppleDocumentPlatformServices::set_cursor_visible(bool visible) const #endif } +void AppleDocumentPlatformServices::trigger_crash_test() const +{ + if (bridge_.trigger_crash_test) + bridge_.trigger_crash_test(); +} + +void AppleDocumentPlatformServices::request_app_close() const +{ + if (bridge_.request_app_close) + bridge_.request_app_close(); +} + +void AppleDocumentPlatformServices::start_sonarpen() const +{ + if (bridge_.start_sonarpen) + bridge_.start_sonarpen(); +} + void AppleDocumentPlatformServices::acquire_render_context() const { if (bridge_.acquire_render_context) diff --git a/src/platform_apple/apple_platform_services.h b/src/platform_apple/apple_platform_services.h index f96f57f4..8df0dc42 100644 --- a/src/platform_apple/apple_platform_services.h +++ b/src/platform_apple/apple_platform_services.h @@ -22,6 +22,9 @@ struct AppleDocumentPickerBridge { std::function display_file; std::function share_file; std::function set_cursor_visible; + std::function trigger_crash_test; + std::function request_app_close; + std::function start_sonarpen; std::function acquire_render_context; std::function release_render_context; std::function present_render_context; @@ -53,6 +56,9 @@ public: void display_file(std::string_view path) const; void share_file(std::string_view path) const; void set_cursor_visible(bool visible) const; + void trigger_crash_test() const; + void request_app_close() const; + void start_sonarpen() const; void acquire_render_context() const; void release_render_context() const; void present_render_context() const; diff --git a/src/platform_legacy/legacy_platform_services.cpp b/src/platform_legacy/legacy_platform_services.cpp index 333c5f28..1ecf913e 100644 --- a/src/platform_legacy/legacy_platform_services.cpp +++ b/src/platform_legacy/legacy_platform_services.cpp @@ -143,6 +143,12 @@ public: [ios_view hide_keyboard]; }); }; + bridge.trigger_crash_test = [ios_view] { + [ios_view crash]; + }; + bridge.start_sonarpen = [ios_view] { + [App::I->ios_app sonarpen_start]; + }; bridge.acquire_render_context = [ios_view] { [ios_view async_lock]; }; @@ -209,6 +215,14 @@ public: [osx_view share_file:[NSString stringWithUTF8String:path.c_str()]]; }); }; + bridge.trigger_crash_test = [osx_view] { + [osx_view hockeyapp_crash]; + }; + bridge.request_app_close = [osx_view] { + dispatch_async(dispatch_get_main_queue(), ^{ + [osx_view close]; + }); + }; bridge.acquire_render_context = [osx_view] { [osx_view async_lock]; }; @@ -318,9 +332,9 @@ public: void trigger_crash_test() override { #ifdef __IOS__ - [App::I->ios_view crash]; + active_apple_document_platform_services().trigger_crash_test(); #elif __OSX__ - [App::I->osx_view hockeyapp_crash]; + active_apple_document_platform_services().trigger_crash_test(); #elif defined(__ANDROID__) int *x = nullptr; *x = 42; LOG("%d", *x); @@ -663,7 +677,7 @@ public: void start_sonarpen() override { #if __IOS__ - [App::I->ios_app sonarpen_start]; + active_apple_document_platform_services().start_sonarpen(); #endif } @@ -727,9 +741,7 @@ public: void request_app_close() override { #ifdef __OSX__ - dispatch_async(dispatch_get_main_queue(), ^{ - [App::I->osx_view close]; - }); + active_apple_document_platform_services().request_app_close(); #elif __LINUX__ glfwSetWindowShouldClose(App::I->glfw_window, GLFW_TRUE); #endif