diff --git a/docs/modernization/debt.md b/docs/modernization/debt.md index ccf9f08e..278ebe72 100644 --- a/docs/modernization/debt.md +++ b/docs/modernization/debt.md @@ -18,6 +18,20 @@ agent or engineer to remove them without reconstructing context from chat. ## Reductions +- 2026-06-16: `DEBT-0036` was narrowed again. `NodeCanvas` merged-path + per-plane merged-texture draw execution now routes through + `execute_legacy_canvas_draw_merge_layer_texture(...)` instead of spelling out + the sampler bind, `TextureAlpha` setup, texture bind, draw, and unbind + inline in `NodeCanvas::draw()`; broader canvas draw orchestration remains. +- 2026-06-16: `DEBT-0003` was narrowed again. Windows VR device ownership in + `src/main.cpp` now uses `std::unique_ptr` instead of a raw global + `Vive*`; retained global VR state, Win32 message-loop ownership, and broader + app/runtime coupling remain. +- 2026-06-16: `DEBT-0017` was narrowed again. Linux/Web GLFW render-context + acquire/present hooks and Linux app-close now route through retained local + GLFW callback hooks in `src/platform_legacy/legacy_platform_services.cpp` + instead of direct method-body `App::I` access; retained fallback platform + ownership and broader singleton reach remain. - 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 diff --git a/docs/modernization/roadmap.md b/docs/modernization/roadmap.md index a4383c3c..1ce49a12 100644 --- a/docs/modernization/roadmap.md +++ b/docs/modernization/roadmap.md @@ -100,7 +100,9 @@ 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, as do Apple crash-test, app-close, and iOS SonarPen hooks. + bridge style, as do Apple crash-test, app-close, and iOS SonarPen hooks, + while Linux/Web GLFW render-context acquire/present and Linux app-close now + route through retained local GLFW callback hooks. - `src/platform_legacy/legacy_platform_services.*` is still part of the live app shell. - `pp_panopainter_ui` still depends on `pp_legacy_app`. @@ -109,7 +111,9 @@ Current architecture mismatches that must be treated as real blockers: 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, - with the cache-to-screen checkerboard-plane callback setup also reduced. + with the cache-to-screen checkerboard-plane callback setup also reduced and + the merged-path per-plane merged-texture draw now routed through the same + retained helper family. - `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 @@ -119,8 +123,9 @@ 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 and `LogRemote` now uses the same - ownership model. + also use owned `std::jthread` lifecycle, `LogRemote` now uses the same + ownership model, and the Windows VR device now has explicit `std::unique_ptr` + ownership instead of raw global lifetime. - 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 764c9995..89d44f84 100644 --- a/docs/modernization/tasks.md +++ b/docs/modernization/tasks.md @@ -131,6 +131,8 @@ Current slice: - `NodeStrokePreview` final composite plus preview-texture copy now route through `legacy_node_stroke_preview_execution_services.h`, but the preview node still owns most live-pass and retained GL resource execution. +- `NodeCanvas` merged-path per-plane merged-texture draw execution now also + routes through `execute_legacy_canvas_draw_merge_layer_texture(...)`. - `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 @@ -377,6 +379,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` +- Windows VR device ownership in `main.cpp` now also uses `std::unique_ptr` + instead of a raw `Vive*` - `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 @@ -600,6 +604,9 @@ Current slice: - 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` +- Linux/Web GLFW render-context acquire/present hooks and Linux app-close now + also route through retained local GLFW callback hooks instead of direct + method-body `App::I` access in `LegacyPlatformServices` - retained Apple callback injection and broader `platform_legacy` singleton reach are still open diff --git a/src/main.cpp b/src/main.cpp index 87b9658c..9c350eaa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #define WM_USER_CLOSE (WM_USER + 1) @@ -519,18 +520,17 @@ void init_vk_map() std::mutex hmd_render_mutex; std::condition_variable hmd_render_cv; -Vive* vive = nullptr; +std::unique_ptr vive; bool win32_vr_start() { if (sandboxed) return false; - vive = new Vive; + vive = std::make_unique(); vive->on_draw = [](const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose) { App::I->vr_draw(proj, view, pose); }; if (!vive->Initialize()) { - delete vive; - vive = nullptr; + vive.reset(); LOG("VR: failed to initialize vive"); return false; } @@ -615,8 +615,7 @@ void win32_vr_stop() hmd_renderer.join(); } vive->Terminate(); - delete vive; - vive = nullptr; + vive.reset(); } } diff --git a/src/platform_legacy/legacy_platform_services.cpp b/src/platform_legacy/legacy_platform_services.cpp index 1ecf913e..425f4d18 100644 --- a/src/platform_legacy/legacy_platform_services.cpp +++ b/src/platform_legacy/legacy_platform_services.cpp @@ -94,6 +94,33 @@ public: #endif } +#if defined(__LINUX__) || defined(__WEB__) +struct RetainedLegacyGlfwWindowHooks final { + std::function acquire_render_context; + std::function present_render_context; + std::function request_app_close; +}; + +[[nodiscard]] RetainedLegacyGlfwWindowHooks& active_legacy_glfw_window_hooks() +{ + static RetainedLegacyGlfwWindowHooks hooks = [] { + RetainedLegacyGlfwWindowHooks retained; + GLFWwindow* const window = App::I->glfw_window; + retained.acquire_render_context = [window] { + glfwMakeContextCurrent(window); + }; + retained.present_render_context = [window] { + glfwSwapBuffers(window); + }; + retained.request_app_close = [window] { + glfwSetWindowShouldClose(window, GLFW_TRUE); + }; + return retained; + }(); + return hooks; +} +#endif + #if defined(__IOS__) || defined(__OSX__) [[nodiscard]] NSMutableArray* apple_file_types_array(const std::vector& file_types) { @@ -412,7 +439,7 @@ public: #elif __ANDROID__ android_async_lock(); #elif __LINUX__ || __WEB__ - glfwMakeContextCurrent(App::I->glfw_window); + active_legacy_glfw_window_hooks().acquire_render_context(); #endif } @@ -432,7 +459,7 @@ public: #elif __ANDROID__ android_async_swap(); #elif __LINUX__ || __WEB__ - glfwSwapBuffers(App::I->glfw_window); + active_legacy_glfw_window_hooks().present_render_context(); #endif } @@ -743,7 +770,7 @@ public: #ifdef __OSX__ active_apple_document_platform_services().request_app_close(); #elif __LINUX__ - glfwSetWindowShouldClose(App::I->glfw_window, GLFW_TRUE); + active_legacy_glfw_window_hooks().request_app_close(); #endif }