Files
panopainter/docs/modernization/build-inventory.md
2026-06-05 08:14:11 +02:00

1035 lines
70 KiB
Markdown

# Build And Platform Inventory
Status: live
Last updated: 2026-06-05
This inventory records the known build surfaces during the CMake migration.
Keep it updated as platform paths move to shared CMake targets.
## Existing Build Entrypoints
| Platform/Target | Current Entrypoint | Notes |
| --- | --- | --- |
| Windows desktop | Root `CMakeLists.txt`, preset `windows-msvc-default`; target preset `windows-vs2026-x64` retained for VS 2026 | Raw `.sln/.vcxproj` files removed on 2026-05-31; local machine currently uses Visual Studio 17 2022; `PanoPainter` now links through `pp_platform_windows` and `panopainter_app`, with Windows/vendor link dependencies owned by the platform shell, runtime payload deployment in `cmake/PanoPainterRuntime.cmake`, tested app-level document-open routing plus open/close/save session decisions owned by `pp_app_core`, SDK-free clipboard/cursor/virtual-keyboard/display/share/picker service contracts owned by `pp_platform_api`, and injected `WindowsPlatformServices` now isolated in `src/platform_windows/windows_platform_services.*`; retained third-party source dependencies contained by `pp_legacy_vendor`, retained asset/file/serialization sources contained by `pp_legacy_assets_io`, retained paint/document/canvas sources contained by `pp_legacy_paint_document`, retained OpenGL runtime sources contained by `pp_legacy_renderer_gl` and folded into `pp_legacy_engine`, retained runtime shell sources contained by `pp_legacy_engine`, retained base UI controls contained by `pp_legacy_ui_core` and folded into `pp_legacy_app`, app orchestration/version metadata owned by `panopainter_app`, and app-specific modal/dialog/panel/canvas workflow nodes owned by `pp_panopainter_ui` |
| Windows AppX | `PanoPainterPackage/Package.appxmanifest`, `.wapproj` referenced by solution | Distribution packaging |
| macOS | `PanoPainter-OSX/` project files and `Info.plist` | Uses `NSOpenGLView` today |
| iOS | `PanoPainter/Info.plist`, related Apple sources | Uses OpenGL ES today |
| Android standard | `android/android/build.gradle`, `android/android/CMakeLists.txt` | Native library target `native-lib` |
| Android Quest | `android/quest/build.gradle`, `android/quest/CMakeLists.txt` | OVR SDK imported libraries |
| Android Focus/Wave | `android/focus/build.gradle`, `android/focus/CMakeLists.txt` | Wave SDK imported libraries |
| Linux | `linux/CMakeLists.txt` | Old CMake 3.4, C++14 flag |
| WebGL/Emscripten | `webgl/CMakeLists.txt` | Old CMake 3.4, WebGL2 flags |
## Existing Version Generation
- Script: `scripts/pre-build.py`
- Output: `src/version.gen.h`
- Current behavior: derives version from git branch, latest tag, short hash,
commit count, and configuration argument.
- Migration requirement: root CMake should call this script through a custom
command and avoid unnecessary tracked-file churn where possible.
## Existing Dependency Sources
Hybrid policy: migrate reliable packages to vcpkg and retain SDK/patched
dependencies until each platform triplet is proven.
| Dependency | Current Source | Initial Policy |
| --- | --- | --- |
| fmt | `libs/fmt` | Move to vcpkg |
| GLM | `libs/glm` | Move to vcpkg |
| tinyxml2 | `libs/tinyxml2` | Move to vcpkg |
| stb | `libs/stb` | Move to vcpkg or interface target if package friction |
| CURL | `libs/curl-win`, `libs/curl-android-ios` | Move to vcpkg where triplets work |
| SQLite | `libs/sqlite3` | Move to vcpkg |
| GLAD | `libs/glad` | Move to vcpkg or generated backend target |
| Catch2 | none yet | Add through vcpkg |
| OpenVR | `libs/openvr` | Retain initially |
| OVR Platform/Mobile | `libs/ovr_platform`, `libs/ovr_mobile` | Retain initially |
| Wave SDK | `libs/wave_sdk` | Retain initially |
| Wacom WinTab | `libs/wacom` | Retain initially |
| AppCenter Apple | `libs/appcenter-apple` | Retain initially |
| openh264/mp4v2/libyuv | `libs/openh264`, `libs/mp4v2`, `libs/libyuv` | Retain initially |
| jpeg helpers | `libs/jpeg` | Evaluate after image tests exist |
| poly2tri/nanort/base64/hash-library | `libs/*` | Evaluate after component split |
## Current Validation Commands
These commands are the current local baseline.
```powershell
cmake --preset windows-msvc-default
cmake --build --preset windows-msvc-default --config Debug --target PanoPainter
ctest --preset desktop-fast --build-config Debug
ctest --preset fuzz --build-config Debug
ctest --preset stress --build-config Debug
powershell -ExecutionPolicy Bypass -File scripts\automation\test.ps1 -Preset desktop-fast -Configuration Debug
powershell -ExecutionPolicy Bypass -File scripts\automation\build.ps1 -Preset windows-msvc-default -Configuration Debug -Target pano_cli
cmake --build --preset windows-msvc-default --target panopainter_validate_shaders
powershell -ExecutionPolicy Bypass -File scripts\automation\analyze.ps1 -Preset windows-msvc-default -NoApp
$env:VCPKG_ROOT = "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\vcpkg"
cmake --preset windows-msvc-vcpkg-headless
powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets windows-msvc-vcpkg-headless
ctest --preset desktop-fast-vcpkg --build-config Debug
cmake --preset android-arm64
powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -Presets android-arm64
powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug
powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -ReadinessOnly
cmake --fresh --preset windows-clangcl-asan
python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name execute_brush
python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name-regex "execute_.*preset"
python scripts/dev/clangd_nav.py symbols --file src/app_core/document_export.h --detail-regex "Export.*Plan"
python scripts/dev/clangd_nav.py definition --file src/node_panel_brush.cpp --line 511 --column 39
python scripts/dev/clangd_nav.py references --file src/app_core/brush_ui.h --line 783 --column 45 --path-regex "src[\\/]app_core"
python scripts/dev/clangd_nav.py self-test
python scripts/dev/check_platform_build_targets.py
python scripts/dev/check_package_smoke_readiness.py
```
Known local toolchain state:
- CMake: 4.0.0-rc4
- Local Visual Studio generator selected by CMake: Visual Studio 17 2022
- Bundled vcpkg: `C:\Program Files\Microsoft Visual Studio\2022\Community\VC\vcpkg`
(`vcpkg version` reports 2025-11-19)
- Android SDK: `C:\Users\omara\AppData\Local\Android\Sdk`
- Android NDK: `C:\Users\omara\AppData\Local\Android\Sdk\ndk\29.0.14206865`
- clang-cl: `C:\Program Files\LLVM\bin\clang-cl.exe` reports 18.1.8, but the
selected VS 2026-preview STL expects Clang 20 or newer; see DEBT-0014 before
treating `windows-clangcl-asan` as a passing sanitizer gate.
- clangd/clang-query/clang-tidy are installed under `C:\Program Files\LLVM\bin`.
`scripts/dev/clangd_nav.py` provides agent-friendly symbol, definition,
declaration, implementation, reference, and hover lookup through clangd using
the current `compile_commands.json` from `windows-clangcl-asan`,
`android-arm64`, or a caller-provided build directory. Symbol, hover,
declaration, definition, and implementation lookups are the reliable use case.
Symbol listing supports substring filtering with `--name`, regex filtering
against `qualifiedName` with `--name-regex`, and symbol detail/signature
regex filtering with `--detail-regex`. Definition, declaration,
implementation, and reference location output supports `--path-regex` for
path/URI filtering. Regex matching is case-insensitive by default and can be
made case-sensitive with `--no-ignore-case`. The helper exposes
`python scripts/dev/clangd_nav.py self-test`, also registered as
`panopainter_clangd_nav_regex_self_test`, so regex filter behavior can be
validated without clangd or a compile database.
Agents must use the repo skill `panopainter-code-navigation` before broad
text searches when a C++ refactor needs symbol identity, symbol-family lookup,
generated-style names, signatures, override groups, declarations/definitions,
or platform/backend path slices. Keep `rg` for docs, build files, string
literals, comments, and exact non-symbol text.
Reference lookup is guarded because a one-shot clangd process may not have a
complete project index: pass `--background-index` for broader best-effort
results or `--allow-incomplete-references` for explicitly
current-translation-unit-only results, and do not treat incomplete references
as proof that no other users exist.
- Android standard arm64/x64, Quest arm64, and Focus/Wave arm64 headless
configure/build pass through root CMake and the `platform-build` automation
wrapper defaults for `pp_foundation`, `pp_assets`,
`pp_paint`, `pp_document`, `pp_renderer_api`, `pp_renderer_gl`,
`pp_paint_renderer`,
`pp_ui_core`, `pano_cli`, and their current headless test binaries,
including foundation binary-stream/event/logging/task queue coverage, image
metadata/decode/encode coverage, PPI header/layout/body coverage, settings
document coverage, brush-package path/header coverage, document
snapshot/frame/layer/history/PPI import-export coverage, paint
brush/final-blend/stroke-alpha-blend/stroke spacing/stroke stress/
stroke-script coverage, renderer shader descriptor and OpenGL capability
coverage, UI color/layout/XML parse coverage, platform service coverage, and
the current `pp_app_core` automation surface for startup, file menus,
document session/open/import/export/animation/canvas/layer/resize/cloud/
sharing/platform-I/O, brush-package import/export, brush UI, canvas tools and
hotkeys, history, grid, quick UI, main toolbar, Tools, About, preferences,
and app status planning. The PowerShell wrapper accepts repeated, array, or
comma-separated `-Presets`/`-Targets` values so scripted callers can narrow
the same matrix without accidentally passing a single combined target.
`scripts/dev/check_platform_build_targets.py`, registered as
`panopainter_platform_build_target_matrix_self_test`, verifies the PowerShell
and shell wrapper defaults include every current CMake test executable plus
the required component and `pano_cli` targets, and that both wrappers default
to the standard arm64/x64, Quest arm64, and Focus/Wave arm64 Android presets.
- `package-smoke.ps1 -ReadinessOnly` and `package-smoke.sh --readiness-only`
emit the Windows AppX, Android standard/Quest/Focus APK, Apple bundle, and
WebGL package readiness matrix without first building an app artifact. The
full package smoke command still builds/checks the selected app target before
reporting the same readiness matrix. `scripts/dev/check_package_smoke_readiness.py`,
registered as `panopainter_package_smoke_readiness_self_test`, verifies both
wrappers keep the same six package kinds, blocked DEBT-0011 status, and
readiness-only mode.
- Root CMake exposes named `fuzz` and `stress` CTest presets. `fuzz` currently
runs deterministic parser/serializer edge tests for binary streams, image
metadata, PPI, stroke scripts, and layout XML; `stress` currently runs the
stroke sampler stress coverage.
- `pano_cli inspect-image` reports PNG IHDR metadata as JSON and is covered by
`pano_cli_inspect_png_metadata_smoke` with a tiny IHDR fixture.
- `pp_assets_image_pixels_tests` decodes PNG payloads, encodes RGBA8 pixels to
PNG, round-trips encoded pixels back through the decoder, and rejects corrupt
or malformed image payloads.
- `pano_cli import-image` accepts a PNG path, decodes RGBA8 pixels through
`pp_assets`, attaches them to a pure `pp_document` face payload, and is
covered for checked-in decodable PNG import by `pano_cli_import_image_smoke`
and metadata-valid truncated PNG rejection by
`pano_cli_import_image_rejects_truncated_png`.
- `pano_cli export-image` writes a deterministic RGBA8 PNG through `pp_assets`
and is covered by `pano_cli_export_image_roundtrip_smoke`, which imports the
generated file back through `pano_cli import-image`.
- `pano_cli inspect-project` reports validated PPI thumbnail/body byte layout,
body summary fields, layer/frame descriptors, and dirty-face PNG payload
metadata, and is covered by `pano_cli_inspect_project_layout_smoke` with a
minimal PPI fixture.
- `pp_document_ppi_import_tests` attaches decoded PPI dirty-face payloads to
`pp_document` layer/frame storage and rejects payloads outside document
layers.
- `pp_document_ppi_export_tests` exports pure `pp_document` metadata,
per-layer frame durations, and RGBA8 face payloads to PPI bytes through
`pp_assets`, then decodes and reimports them for round-trip coverage.
- `pano_cli simulate-document-export` exposes the same pure document-to-PPI
export, asset-level decode, and document reimport path through JSON
automation and is covered by `pano_cli_simulate_document_export_smoke`.
- `pano_cli save-document-project` writes that pure document export to a PPI
file and is covered by `pano_cli_save_document_project_roundtrip_smoke`,
which inspects and loads the generated file.
- `pano_cli load-project` creates a `pp_document` projection with per-layer
frame counts, durations, and decoded face-pixel payloads when present; the
metadata-only minimal fixture remains covered by
`pano_cli_load_project_metadata_smoke`.
- `pp_assets::create_ppi_project` writes generated multi-layer, multi-frame
PPI files with explicit per-layer names, opacity, blend mode, alpha lock,
visibility, per-layer frame durations, and targeted dirty-face layer/frame
payloads. `pano_cli save-project` exposes that path for automation and is
covered by `pano_cli_save_project_roundtrip_smoke` and
`pano_cli_save_project_payload_roundtrip_smoke`, which reload generated
metadata-only and targeted dirty-face-payload projects through
`pano_cli load-project`, plus
`pano_cli_save_project_rejects_non_finite_opacity`, which verifies rejected
automation floats do not create output files.
- `pano_cli create-document` supports `--frames` and `--frame-duration-ms` and
is covered by `pano_cli_create_animation_document_smoke`.
- `pano_cli simulate-document-edits` exercises pure document layer/frame edit
operations, renderer-free face payloads, and renderer-free selection masks,
and is covered by `pano_cli_simulate_document_edits_smoke`.
- `pano_cli simulate-document-history` exercises pure document history
apply/undo/redo behavior and is covered by
`pano_cli_simulate_document_history_smoke`.
- `src/legacy_document_layer_services.*` is the current app-shell bridge for
layer rename, layer menu clear/rename/merge, layer merge, and layer-panel
operations. It keeps those live paths on the `pp_app_core` contracts while
legacy `Canvas`, `NodeLayer`, `NodePanelLayer`, and `ActionManager`
execution remain tracked by `DEBT-0021` and `DEBT-0032`.
- `NodePanelLayer::update_attributes()` now consumes the tested
`pp_app_core` layer panel view model for current opacity, alpha-lock, blend
mode, and per-layer visibility projection. `pano_cli plan-layer-panel-view`
exposes the same view model for automation; retained canvas mutation, UI node
ownership, and undo behavior remain tracked by `DEBT-0021`.
- `src/legacy_app_shell_services.*` is the current app-shell bridge for File
menu routing, export-menu routing, main-toolbar commands, About menu
commands, and direct Tools menu commands. It keeps those live paths on the
`pp_app_core` contracts while legacy dialogs, pickers, cloud/share/export,
Tools, About, history, canvas-clear, settings, and platform SonarPen startup
execution remain tracked by `DEBT-0029`, `DEBT-0030`, `DEBT-0031`,
`DEBT-0033`, `DEBT-0034`, and `DEBT-0035`. `src/legacy_canvas_view_services.*`
is the shared bridge for reset-camera, viewport-density, and cursor-mode
execution; live Tools reset-camera, document open/new-document reset, cloud
download reset, and options viewport/cursor callbacks consume the tested
`pp_app_core` canvas-view plans exposed through
`pano_cli plan-canvas-camera-reset`, `pano_cli plan-canvas-view-density`,
and `pano_cli plan-canvas-view-cursor-mode` before retained canvas mutation
and settings writes.
- `src/legacy_app_startup_services.*` is the current main-app startup bridge for
run-counter persistence, startup runtime side effects, and startup resource
sequencing. `App::init` now consumes `pp_app_core` plans exposed through
`pano_cli plan-app-startup` and `pano_cli plan-app-startup-resources`, while
retained shader loading, asset initialization, layout creation, title updates,
UI render-target creation, recording startup, VR-controller state mutation,
settings writes, and license-warning dialogs remain legacy execution.
- `src/app_core/app_frame.h` owns the current initial surface, update-gating,
tick, resize, and draw-pass decisions consumed by `App::create`,
`App::tick`, `App::resize`, `App::update`, `App::draw`, and
`pano_cli plan-app-frame`; retained layout traversal, toolbar widget writes,
UI render-target recreation, canvas stroke drawing, VR UI render-target
drawing, main target binding, and OpenGL/UI drawing remain in the legacy app.
- `src/app_core/app_shutdown.h` owns the current shutdown cleanup staging
consumed by `App::terminate` and `pano_cli plan-app-shutdown`; retained
UI-state save, recording stop, resource invalidation, layout unload,
render-target/mesh destruction, and panel-node release remain in the legacy
app.
- `src/legacy_app_preference_services.*` is the current app-shell bridge for
options-menu preference execution. It keeps UI scale, viewport scale, RTL,
VR mode, VR-controller, auto-timelapse, and canvas cursor-mode callbacks on
the `pp_app_core` `AppPreferenceServices` contract while retained settings
persistence, recording lifecycle, and legacy canvas/UI execution remain
tracked by `DEBT-0045`; the VR mode callbacks now call `App` wrappers that
dispatch through `PlatformServices` before reaching the retained platform VR
bridge.
- `src/legacy_app_startup_services.*` is the current app-shell bridge for
startup preference/runtime execution. It keeps run-counter persistence,
startup preference save, auto-timelapse startup, stored VR-controller state,
and license-warning decisions on the `pp_app_core` `AppStartupServices`
contract while retained `Settings`, `App::rec_start`, and message-box
execution remain tracked by `DEBT-0046`.
- `src/legacy_canvas_tool_services.*` is the current app-shell bridge for
canvas toolbar tool selection, NodeCanvas stylus/input mode switching, and
canvas hotkey/touch execution. It keeps those live paths on the `pp_app_core`
contracts; `App::init_toolbar_draw()` now consumes the tested
`pp_app_core` draw-toolbar binding plan exposed through
`pano_cli plan-canvas-tool-toolbar` before retained button lookup and legacy
execution dispatch. Canvas mode tip visibility and pressure remapping now ask
`PlatformServices`; `NodeCanvas::update_cursor()` now consumes
`pp_app_core` canvas cursor visibility planning exposed through
`pano_cli plan-canvas-cursor` before retained platform cursor dispatch.
Legacy `Canvas` mode state, transform actions, picking, touch-lock,
save/UI/cursor calls, brush-size controls, and history execution remain
tracked by `DEBT-0027`.
- `src/legacy_document_animation_services.*` is the current UI-shell bridge for
animation frame commands, timeline/selected-frame execution, playback ticks,
onion-size updates, and play-mode toggles. It keeps those live paths on the
`pp_app_core` contracts. `NodeCanvas` onion-skin panorama drawing now also
consumes the tested `pp_app_core` onion frame range and alpha falloff helper,
and `NodeAnimationTimeline` mouse scrubbing consumes tested `pp_app_core`
cursor-to-frame planning exposed through `pano_cli plan-animation-timeline-scrub`,
and `NodePanelAnimation` layer/frame/timeline display state consumes the
tested `pp_app_core` panel view model exposed through
`pano_cli plan-animation-panel-view`,
while legacy `Canvas`/`Layer` frame state, canvas mode, animation-panel
timeline/playback fields, and the temporary `NodePanelAnimation` friend
adapter remain tracked by `DEBT-0022`.
- `src/legacy_brush_ui_services.*` is the current UI-shell bridge for brush
color, texture, preset, stroke-refresh, brush texture-list, and stroke-control
execution. `NodePanelBrushPreset` now consumes `pp_app_core` preset-list
planning and `BrushPresetListServices` execution for add/select/move/remove/
clear before the retained legacy bridge mutates child nodes.
`NodePanelStroke::update_controls()` now consumes the tested `pp_app_core`
stroke-panel view model for brush float settings, toggles, blend modes, and
thumbnail paths, and `pano_cli plan-brush-stroke-panel-view` exposes that
projection for automation. `App::brush_update()` now consumes the tested
`pp_app_core` brush refresh view before updating retained stroke, quick, and
floating color widgets, and `pano_cli plan-brush-refresh` exposes that
fan-out for automation. These paths stay on the `pp_app_core` contracts while
legacy `Brush`, `Canvas::I`, image load/save, `NodePanelBrush`,
`NodePanelStroke`, quick/color refreshes, direct preset child-node mutation,
brush thumbnail/popup ownership, and the temporary `NodePanelBrush` friend
adapter remain tracked by `DEBT-0023`.
- `src/legacy_grid_ui_services.*` is the current UI-shell bridge for grid
heightmap picker/load/reload/clear, lightmap render, and heightmap commit
execution. It keeps those live paths on the `pp_app_core` contracts while
legacy image loading, OpenGL texture updates, shared `parallel_for` CPU
lightmap baking/progress, and `Canvas::draw_objects` execution remain tracked
by `DEBT-0024`.
- `src/legacy_quick_ui_services.*` is the current UI-shell bridge for quick
brush/color slot selection, popup routing, mini-state restore, and mini-state
reset execution. Quick size/flow slider preview cursor placement and pen/line
mode tip flags now consume the tested `pp_app_core` planner directly from
`NodePanelQuick`, and `pano_cli plan-quick-slider-preview` exposes that path
for automation. It keeps those live paths on the `pp_app_core` contracts
while legacy quick widgets, brush previews, color picker state, preset popup
execution, and direct legacy `CanvasMode*` field writes remain tracked by
`DEBT-0025`.
- `pano_cli simulate-image-import` decodes an embedded tiny PNG through
`pp_assets`, attaches it to `pp_document`, and is covered by
`pano_cli_simulate_image_import_smoke`.
- `pano_cli simulate-blend` exposes deterministic final RGBA and stroke-alpha
blend reference vectors through JSON automation and is covered by
`pano_cli_simulate_blend_smoke`.
- `pano_cli simulate-stroke` exposes the pure stroke sampler for scripted
automation and is covered by `pano_cli_simulate_stroke_smoke`.
- `pano_cli simulate-stroke-script` loads a text stroke script fixture and is
covered by `pano_cli_simulate_stroke_script_smoke`.
- `pano_cli apply-stroke-script` parses a text stroke script fixture, samples
every stroke through `pp_paint`, maps the samples into a bounded
`pp_document` RGBA8 face payload, writes a PPI file, and is covered by
`pano_cli_apply_stroke_script_roundtrip_smoke`, which inspects the dirty-face
box and loads the generated file back as decoded document pixel data, plus
`pano_cli_apply_stroke_script_rejects_tiny_canvas` for invalid dimension
rejection.
- `panopainter_validate_shaders` validates the current combined GLSL shader
files for one vertex stage marker, one fragment stage marker, valid marker
order, and existing relative includes.
- `pp_renderer_api` owns the canonical PanoPainter shader catalog consumed by
the legacy OpenGL app initialization path; `pp_renderer_api_tests` validates
catalog size, key entries, duplicate rejection, and bad path rejection.
- `pp_renderer_gl` owns headless OpenGL runtime capability detection consumed
by the legacy app initialization path; `pp_renderer_gl_capabilities_tests`
validates framebuffer fetch, map-buffer alignment, desktop GL float support,
GLES float/half-float extensions, WebGL exclusion behavior, and the
upload-type mapping used by legacy `Texture2D` and `RTT` creation, plus the
RGBA pixel-format mapping used by `RTT` texture allocation. It also validates
image channel-count to OpenGL texture format mapping, including
invalid channel counts rejected by `Texture2D::create(Image)`, renderer API
texture-format to OpenGL internal/pixel/component token mapping including
depth-stencil formats, RGBA8/RGBA32F
readback formats, checked byte-count math, PBO pixel-buffer target/usage/access
mapping, and PBO allocation/readback/map/unmap/delete dispatch sequences used
by retained `PBO` recording readbacks, and framebuffer status naming
used by `RTT` and `Texture2D` diagnostics. It also owns the 2D texture target,
framebuffer setup, readback format, mipmap target, and update component-type
tokens used by `Texture2D`, plus cube-map binding and allocation face targets
used by `TextureCube`. It also owns and
validates framebuffer blit color mask and linear/nearest filters used by
`RTT::resize` and `RTT::copy`, renderer API blit-filter to OpenGL token
mapping, plus the default linear clamp-to-edge render-target texture
parameters and parameter dispatch, texture/renderbuffer targets, depth format,
framebuffer targets, binding queries, attachment points, render-target
framebuffer allocation/delete, binding restore, and completion status used by
`RTT::create`/`RTT::destroy` and framebuffer bind/restore paths, plus RTT
clear color/depth masks. RTT render-target clear, masked color clear with
color-write-mask restore, and texture bind/unbind now execute through tested
dispatch contracts here. Optional RTT depth renderbuffer allocation/storage/delete
and framebuffer depth attach/detach, plus canvas object-drawing depth
renderbuffer setup, also execute through tested dispatch contracts here. Renderer API render-pass color/depth/stencil
clear-mask and clear-value mapping, and color-write-mask query tokens. `RTT` no longer
spells GL enum names directly. `RTT` also exposes a retained RGBA8
region-readback helper that uses the tested framebuffer readback dispatch for
canvas pick/history/snapshot and transform history paths, plus a retained
RGBA8 region-update helper that uses the tested texture-update dispatch for
canvas undo, layer restore, and flood-fill texture writes. 2D
framebuffer-to-texture copies used by retained canvas, transform,
layer-conversion, panorama UI, and brush-preview paths now execute through a
tested `pp_renderer_gl` dispatch via `copy_framebuffer_to_texture_2d`; the
retained cube-map framebuffer copy remains tracked by `DEBT-0036`. It also
validates renderer API primitive-topology to OpenGL draw-mode mapping, Shape
index-type, fill/stroke primitive-mode, buffer target, static upload usage,
and vertex attribute component/normalization mapping used by
the legacy mesh draw path. Legacy `Shape` mesh buffer/VAO creation, zero-byte
dynamic-buffer creation, dynamic vertex/index uploads, fill/stroke draw
calls, and buffer/VAO deletion now consume tested dispatch contracts here,
plus the PanoPainter cube-face to OpenGL
texture-target mapping used by `TextureCube`.
It also owns and validates sampler wrap S/T/R, min/mag filter, and desktop
border-color parameter mapping used by legacy `Sampler`, plus renderer API
sampler filter/address-mode to OpenGL token mapping including mirrored-repeat
and aggregate renderer API sampler-state to OpenGL min/mag/wrap mapping.
Legacy `TextureCube` allocation/bind/delete and legacy `Sampler`
create/configure/border/bind/unbind calls now consume those resource dispatch
contracts directly from the retained app utilities.
The PanoPainter
shader attribute binding catalog, shader stage tokens, compile/link status
queries, active-uniform count query, and matrix-uniform transpose token used
by legacy `Shader` creation also live here. Renderer API blend factor/op to
OpenGL token mapping is tested here with explicit support flags so `GL_ZERO`
stays distinguishable from unsupported enum values. Aggregate renderer API
blend-state to OpenGL enable/factor/equation/color-mask mapping, depth
compare-op to OpenGL depth-function mapping, and aggregate renderer API
depth-state to OpenGL enable/write/compare mapping are tested here too.
`Shader` no longer spells GL enum
names directly. It also owns the PanoPainter shader uniform catalog and legacy hash
mapping used by `Shader` active-uniform discovery and the uniform uniqueness
check. Legacy `Shader` program use/delete, uniform writes, and
attribute-location lookup now consume tested dispatch contracts here.
Legacy shader source compilation, shader deletion, program attach/link,
attribute rebinding, active-uniform count/enumeration, and uniform-location
discovery now consume tested dispatch contracts as well, leaving the retained
shader utility with thin GL adapter functions.
App OpenGL initialization debug severity, debug output, GL info string,
renderer API viewport/scissor rect conversion, default depth/program-point/
line-smooth state, blend factor/equation, and UI render-target RGBA8 format
tokens are cataloged and tested here too. The legacy convert command now
applies its depth, program-point-size, source-alpha blend, and add-equation
startup policy through a tested dispatch contract here; the resize path
consumes the backend-owned mapping. App clear color-buffer masks, default
framebuffer binding, scissor state, and sampler filter/wrap tokens also
consume the backend mapping.
OpenGL extension enumeration query tokens
used before runtime capability detection are cataloged here. Legacy font
atlas texture formats, text mesh buffer targets, attribute component and
normalization tokens, draw primitive/index type, upload usage, and active
texture unit selection also consume the backend mapping. Text mesh
buffer/VAO creation, deferred index/vertex uploads, indexed draw calls, and
draw-time texture-unit activation now consume tested `pp_renderer_gl`
dispatch contracts too. Canvas undo/redo dirty-region texture updates and
readbacks also consume the backend-owned 2D texture target, RGBA pixel
format, and unsigned-byte component mapping; canvas stroke commit, thumbnail,
and object-draw history paths now consume tested capability-state query
dispatch for saved blend state.
`NodeViewport` preview rendering also consumes backend-owned viewport query,
clear-color query, color-buffer clear mask, and blend-state tokens.
`NodeImageTexture` preview drawing also consumes backend-owned fallback 2D
texture bind and blend-state tokens.
`NodeImage` drawing and remote-image texture creation also consume
backend-owned mipmapped sampler filters, blend-state tokens, and RGBA8/RGBA
texture format mapping.
`NodeColorWheel` triangle-buffer setup and draw-state handling also consume
backend-owned array-buffer, static-upload, vertex-attribute, primitive-mode,
and blend-state tokens.
Simple UI text, text-input, border, scroll, and animation timeline draw
paths also consume backend-owned blend-state tokens.
Canvas layer cube/equirect generation, clear, restore, and snapshot paths
also consume backend-owned cube/2D texture targets, active texture units,
cube texture binding, blend/clear state, viewport execution, target-aware
framebuffer-to-texture copies, and RGBA8 read/write pixel mapping.
`NodePanelGrid` heightmap preview and lightmap baking also consume
backend-owned texture readback formats, sampler filters, depth/blend state,
depth clears, viewport queries, color-mask booleans, active texture units,
and float render-target formats; its desktop texture-resize readback now
reuses `Texture2D::get_image()` and the tested framebuffer-backed texture
readback dispatch instead of direct `glGetTexImage`; CPU lightmap row dispatch
now uses shared `parallel_for` instead of platform-specific worker APIs. Its
live heightmap draw and bake paths now execute depth/blend state changes,
depth clears, color-write-mask toggles, active texture selection, and bake
viewport changes through tested `pp_renderer_gl` dispatch adapters. Grid
depth-state snapshots and sun overlay viewport queries now use tested backend
query dispatch as well.
Legacy `util.cpp` OpenGL error naming and `gl_state` save/restore also
consume backend-owned error codes, state queries, framebuffer targets,
texture binding targets, and active texture units.
`NodeStrokePreview` brush preview rendering also consumes backend-owned
depth/scissor/blend state, tested viewport/clear-color query dispatch,
clear-color restore, active texture unit execution, fallback 2D texture
unbinds, 2D texture targets, copy targets, and sampler filters/wraps. Its
live stroke-mixer and brush-preview viewport, scissor, and depth/blend state
changes now execute through tested `pp_renderer_gl` dispatch with only local
OpenGL adapter endpoints retained.
Retained `Canvas` stroke/thumbnail/object/export paths and `NodeCanvas`
panorama rendering use the same tested active-texture dispatch for
texture-unit switches, and their live viewport, scissor, and generic
depth/blend/scissor capability changes now route through the same backend
dispatch contracts. `NodeCanvas` saved blend/depth/scissor capability-state
queries now use tested backend query dispatch too. Retained `Canvas` stroke draw/commit, thumbnail
generation, object rendering, and `LayerFrame::clear` saved viewport or
clear-color query plus clear-color restore paths also use tested
`pp_renderer_gl` dispatch helpers. `NodeCanvas` saved viewport/clear-color
query, density/offscreen color clear, and clear-color restore paths use the
same helpers. Retained desktop HMD eye rendering also routes viewport
execution through tested backend dispatch.
Legacy `Texture2D`, `TextureManager`, `Sampler`, and `RTT` public headers no
longer expose raw OpenGL enum defaults; default texture formats, sampler
filters/wraps, and render-target formats resolve through backend-owned
overloads.
The Windows entrypoint also consumes backend-owned generic OpenGL
error-code/info-string tokens, runtime string query ordering, and WGL
core-context/pixel-format attribute catalogs.
The headless OpenGL command planner consumes `pp_renderer_api` recorded
commands and maps render-pass clear masks/values, viewport/scissor state,
blend/depth/sampler state, texture formats, primitive modes, draw counts, and
blit filters into GL-facing planned command data while rejecting unsupported
enum tokens before a real GL context is needed. It also plans whole recorded
command streams, preserving per-command planned data while counting render
passes, draws, shader binds, shader uniforms, texture/sampler binds, texture
uploads, mipmap generation, texture transitions, texture copies, texture
readbacks, frame captures, passthrough commands, trace commands, unsupported
commands, and render-pass ordering errors such as state changes outside a
pass, nested passes, texture I/O or blits inside a pass, and unclosed passes.
It also validates executable command dependencies, including
shader-before-uniform and shader-plus-mesh before draw within each render
pass, and rejects invalid texture/sampler bind slots in malformed recorded
streams. `pano_cli record-render` emits the OpenGL plan texture/sampler bind
counts so automation can assert backend interpretation without an OpenGL
context.
Desktop VR drawing also consumes backend-owned scissor/depth/blend state,
blend/depth state query-restore, depth clear masks, active texture unit
dispatch, and fallback 2D texture unbind dispatch; VR SDK start/stop now dispatches
through `PlatformServices` while retaining the existing Windows OpenVR bridge
shape.
Canvas mode overlay, mask, and transform paths also consume backend-owned
blend/depth state execution, active texture unit dispatch, transform/cut
viewport execution, 2D texture copy targets, and RGBA8 readback format tokens;
canvas-tip pick readback now routes through tested framebuffer readback
dispatch using the active read framebuffer, with only a local OpenGL adapter
endpoint retained in `src/canvas_modes.cpp`. Paint-mode blend/depth state
snapshots now use tested capability-state query dispatch.
`NodeCanvas` panorama UI rendering also consumes backend-owned sampler
defaults, tested viewport/clear-color query dispatch, blend/depth/scissor
state, color-buffer clear dispatch, clear-color restore, active texture
units, fallback 2D texture unbind targets, copy targets, and RGBA8
render-target formats.
Canvas resource setup also consumes backend-owned stroke-buffer
RGBA8/RGBA16F/RGBA32F formats, flood-fill texture upload format/type,
brush/stencil/mix sampler filters and wraps, and image channel-count texture
formats for cube-strip imports. Clamp-to-border sampler wrap is now part of
the backend capability catalog and test coverage.
Early canvas draw helpers also consume backend-owned pick readback
format/type and RTT-backed region-readback execution, stroke mixer
depth/scissor/blend state, saved viewport and clear-state queries, active
texture units, fallback 2D texture unbind targets, and stroke background
framebuffer-copy dispatch.
Canvas stroke commit also consumes backend-owned saved viewport/clear/blend
state, history readback format/type and RTT-backed region-readback execution,
active texture units, fallback 2D texture unbind targets, and layer
compositing framebuffer-copy dispatch.
Canvas layer merge rendering and explicit layer-merge compositing also consume
backend-owned depth/blend state, active texture units, fallback 2D texture
unbind targets, and merge framebuffer copy targets.
Canvas equirectangular import drawing and depth export rendering also consume
backend-owned depth/blend state and active texture units.
Canvas thumbnail generation and object-drawing helpers also consume
backend-owned saved viewport/clear/blend state, active texture units,
readback format/type, framebuffer copy targets, and depth renderbuffer
allocation plus framebuffer depth attach/detach dispatch contracts;
`src/canvas.cpp` no longer contains raw `GL_*` constants.
Windows desktop OpenGL context creation now consumes a tested
`windows_wgl_core_context_3_3_config()` catalog from `pp_renderer_gl` instead
of owning active WGL context/pixel-format attribute literals in `main.cpp`.
- `windows-msvc-vcpkg-headless` validates manifest install/configure/build/test
for the current headless component matrix; see DEBT-0007 for remaining app
and platform triplet migration.
- `scripts/automation/analyze.*` runs shader validation plus a
renderer-boundary guard that reports JSON and fails if active non-backend
source code reintroduces raw `GL_*`/`WGL_*` constants outside the allowed
legacy OpenGL implementation files.
- `pp_renderer_api` exposes a headless `RecordingRenderDevice` that reports
renderer feature flags and validates backend-owned resource creation,
explicit texture usage flags, command order,
render-pass color/depth/stencil clear intent, scissor state, depth state,
blend state, texture-slot binding, sampler-state binding, texture-upload byte
counts, texture mip-level counts, texture/mesh/shader resource debug labels, mipmap-generation commands,
texture-state transitions, shader-uniform writes, explicit draw descriptor ranges, texture-copy regions,
readback/frame-capture/blit descriptor validation, readback bounds, destination buffer sizes, and
render-target blit regions, records
render-pass-clear/scissor/depth/blend/shader-uniform/texture-bind/
sampler-bind/draw/upload/mipmap-generation/texture-transition/texture-copy/readback/
frame-capture/blit commands, draw mesh inputs, explicit draw ranges, and
records trace markers and scopes without a window or GL context. Recorder
`clear()` also resets active render-pass and trace-scope state so automation
can reuse the same recording device after an interrupted frame.
- `pano_cli record-render` exposes the recording renderer through JSON
automation, including backend feature flags, render-pass/depth-clear counts, scissor/depth/blend/
shader-uniform/texture-bind/sampler-bind/upload/mipmap-generation/texture-transition/texture-copy/readback/
frame-capture/blit command and byte totals, trace marker/scope counts,
labeled descriptor counts, backend resource creation counts, plus draw
descriptor vertex/index totals. When `pp_renderer_gl` is available, it also
emits an `openGlPlan` JSON object with the planned command count, support
status, render-pass/draw/shader-bind/uniform/texture-upload/mipmap/
transition/copy/readback/capture/passthrough/trace counts, unsupported
command count, render-pass order error count, dependency error count, and
unclosed-pass state. Its
`--exercise-clear` mode verifies
interrupted-frame recorder clear/reuse behavior and reports the result in
JSON, and is covered by `pano_cli_record_render_smoke`,
`pano_cli_record_render_exercises_clear_reset`, plus
`pano_cli_record_render_rejects_oversized_target`.
- `pano_cli simulate-document-history` exposes `pp_document::DocumentHistory`
apply/undo/redo state through JSON automation and is covered by
`pano_cli_simulate_document_history_smoke`.
- `pano_cli simulate-document-edits` exposes `pp_document` layer metadata,
frame order, active-index, tiny face-payload state, and selection-mask state
through JSON automation and is covered by
`pano_cli_simulate_document_edits_smoke`.
- `pano_cli simulate-image-import` exposes embedded PNG decode and document
face-payload attachment through JSON automation and is covered by
`pano_cli_simulate_image_import_smoke`.
- `pano_cli import-image` exposes file-driven PNG decode and document
face-payload attachment through JSON automation and is covered by
`pano_cli_import_image_smoke` and
`pano_cli_import_image_rejects_truncated_png`.
- `pano_cli export-image` exposes deterministic RGBA8 PNG writing through JSON
automation and is covered by `pano_cli_export_image_roundtrip_smoke`; full
legacy canvas export remains a future CLI task.
- `pano_cli save-project` exposes generated multi-layer, multi-frame PPI
writing with layer metadata and targeted dirty-face layer/frame payloads
through JSON automation and is covered by metadata-only and
dirty-face-payload round-trip smoke tests; full legacy canvas save parity
remains tracked by DEBT-0013.
- `pp_document::export_ppi_project_document` exposes pure document-to-PPI byte
export through CTest coverage; legacy Canvas save integration remains a
future DEBT-0010/DEBT-0013 task.
- `pano_cli simulate-document-export` exposes document export round-trip state
through JSON automation for agent-driven checks.
- `pano_cli save-document-project` exposes file-writing document export
automation for inspect/load round trips.
- `pano_cli apply-stroke-script` exposes file-driven stroke-script application
to a pure document face payload and writes a PPI artifact for inspect/load
round-trip automation.
- `pano_cli classify-open` exposes the `pp_app_core` document-open route
contract as JSON and is covered for project files, ABR imports, PPBR
imports, and malformed path rejection.
- `pano_cli plan-open-route` exposes `pp_app_core` document-open action
planning as JSON and is covered for clean project open, dirty project
discard-prompt, and ABR import-prompt states.
- `pano_cli plan-new-document` exposes `pp_app_core` new-document target,
legacy resolution-index mapping, and overwrite-prompt planning as JSON and is
covered for save-now, existing-target overwrite, and invalid-resolution
states.
- `pano_cli plan-document-file` exposes `pp_app_core` document-name
validation, legacy `.ppi` path construction, and overwrite-prompt decisions
as JSON through the same combined save-file plan consumed by the live save-as
dialog; it is covered for save-now and existing-target overwrite states.
- `pano_cli plan-document-version` exposes `pp_app_core` save-version suffix
parsing, candidate path generation, collision skipping, and no-slot failure
behavior as JSON and is covered for first-version and existing-path skip
states.
- `pano_cli plan-export-target` exposes `pp_app_core` export target planning
for image file exports, layer/frame collection directories, picked-directory
stems, and MP4 suggested names as JSON and is covered for file, collection,
and suggested-name states.
- `pano_cli plan-export-start` exposes `pp_app_core` export availability
planning for license-gated, demo-blocked, and missing-canvas states as JSON;
the live image, layer, animation-frame, depth, and cube-face export dialogs
plus MP4 animation and timelapse export dialogs consume the same start
contract before reaching legacy canvas/recording export execution.
- `pano_cli plan-recording-session` exposes `pp_app_core` recording start,
stop, clear, platform cleanup, frame-count reset, and export progress-total
planning as JSON; the live recording controls consume those contracts before
reaching legacy recording threads, retained PBO readback call sites, and MP4
encoder execution.
- `src/legacy_recording_services.*` is the current app-shell bridge for
recording start/stop/clear and MP4 export execution. It keeps those live paths
on the `pp_app_core` contracts while legacy recording thread ownership,
retained PBO readback call sites, progress UI, platform cleanup, and
`MP4Encoder` execution remain
tracked by `DEBT-0037`.
- `pano_cli plan-share-file` exposes `pp_app_core` share availability planning
as JSON for unsaved and saved document paths; the live platform share command
consumes the same contract before reaching iOS/macOS sharing bridges or
retained no-op platform branches.
- `pano_cli plan-picked-path` exposes `pp_app_core` selected-path planning as
JSON for empty and non-empty file picker results; live image/file/save/
directory picker branches consume the same contract before invoking retained
platform callbacks or legacy picker bridges.
- `pano_cli plan-display-file` exposes `pp_app_core` external file presentation
planning as JSON for empty and non-empty paths; the live display-file command
consumes the same contract before retained platform open-file bridges.
- `pano_cli plan-keyboard-visibility` exposes `pp_app_core` virtual keyboard
visibility planning as JSON for hidden and visible states; live show/hide
keyboard requests consume the same contract before retained mobile platform
keyboard bridges.
- `pano_cli plan-cursor-visibility` exposes `pp_app_core` cursor visibility
planning as JSON for hidden and visible states; live canvas cursor requests
consume the same contract before retained desktop platform cursor bridges.
- `pano_cli plan-clipboard-read` and `pano_cli plan-clipboard-write` expose
`pp_app_core` clipboard text planning as JSON, including empty text writes;
live clipboard get/set requests consume the same contracts before retained
platform clipboard bridges.
- `pp_platform_api` exposes the SDK-free `PlatformServices` interface for
startup storage path preparation, clipboard text, cursor visibility,
virtual-keyboard visibility, external file display, file sharing, native
app/window close, UI-thread lifecycle hooks, render-context lifecycle hooks,
render-target binding hooks, render platform hint hooks, render-capture frame
hooks, render debug callback hooks, per-frame platform hooks, picker
callbacks, recording cleanup, exported-image publishing, persistent storage
flushing, document browse roots, working-directory picker policy and
display-path formatting, canvas input tip visibility and pressure remapping,
native UI/window state saving, live asset/layout reload policy, diagnostic
stacktrace/crash hooks,
SonarPen availability/startup, VR mode lifecycle,
PPBR export data-directory policy,
prepared-file writable target selection, network TLS verification policy, and
prepared-file save/download handoff; PPBR
and MP4 export dialogs consume
the same prepared-file policy at runtime instead of spelling mobile/Web
branches locally, layer/frame collection export dialogs consume the
work-directory collection policy before `pp_app_core` plans immediate
collection export versus directory-picker stem export, and app-owned curl
upload/download/license helpers consume the TLS policy instead of spelling
Android branches locally; retained `Asset::open_url`, `LogRemote::net_init`,
and cloud browse-dialog curl sites now consume the same default platform TLS
policy helper in `pp_platform_api` instead of spelling Android branches
locally;
Windows
live app execution now uses injected
`WindowsPlatformServices` from
`src/platform_windows/windows_platform_services.*` in `pp_platform_windows`,
while non-Windows platforms still reach retained platform bridges through
the debt-tracked adapter isolated in
`src/platform_legacy/legacy_platform_services.*`.
- `src/app.h` now forward-declares retained platform handles instead of
including Objective-C, Android, or GLFW SDK headers. The full platform SDK
headers needed by retained non-Windows bridges are included in
`src/platform_legacy/legacy_platform_services.cpp`, keeping central app
header consumers lighter while `DEBT-0055` tracks removal of those handles
from `App`.
- `pp_platform_api` also owns `plan_asset_file_load`, the SDK-free file-load
policy consumed by `LayoutManager` for XML layout reload decisions. The
helper preserves desktop mtime-based reload behavior and non-desktop
already-loaded skip behavior while keeping direct platform guards out of the
shared layout parser.
- `pp_renderer_gl` owns the tested `OpenGlInitialState` startup depth/blend
policy and dispatch application consumed by `App::init`, tested runtime
version/vendor/renderer/GLSL string query dispatch consumed by `App::init`
and Windows startup logging/title construction, tested default clear
color/buffer dispatch consumed by `App::clear`, tested app UI
viewport/scissor dispatch consumed by `App::draw` and `App::vr_draw_ui`,
tested generic capability query/apply and buffer-clear dispatch consumed by
VR draw state setup and restore, tested saved-state snapshot/restore dispatch
consumed by the retained `gl_state` utility, tested texture lifecycle/readback dispatch consumed by
the retained `Texture2D` utility, tested framebuffer blit/readback dispatch
consumed by retained `RTT` resize/copy/readback and RGBA8 region-readback
paths, tested texture-update dispatch consumed by retained `RTT` RGBA8
dirty-region writes, tested render-target texture parameter, framebuffer allocation/delete,
color/depth attachment, status-check, and binding-restore dispatch consumed
by retained `RTT::create`/`RTT::destroy`, tested RTT render-target clear,
masked color clear with color-write-mask restore, and texture-bind dispatch,
tested active-texture dispatch consumed by retained Canvas, Font, NodeCanvas,
and NodeStrokePreview texture-unit switches,
tested viewport/scissor/capability dispatch consumed by retained Canvas,
NodeCanvas, NodeStrokePreview, and HMD render-state paths,
tested capability-state query dispatch consumed by retained `Canvas`,
`NodeCanvas`, `CanvasMode`, and `NodePanelGrid` draw-state restore paths,
tested viewport query, clear-color query, and clear-color restore dispatch
consumed by retained `Canvas`, `CanvasLayer`, `NodeCanvas`, and
`NodeStrokePreview` draw-state paths,
tested color-write-mask dispatch consumed by retained `NodePanelGrid`
transparent heightmap rendering, tested texture readback dispatch consumed by
`NodePanelGrid` texture-resize preservation,
tested pixel-buffer allocation/readback/map/unmap/delete dispatch
consumed by retained `PBO` recording readbacks, tested framebuffer-to-texture
copy dispatch consumed by retained canvas/UI paint paths and CanvasLayer
cube-face generation, tested cube texture bind dispatch consumed by
CanvasLayer equirect export, tested framebuffer bind/restore dispatch consumed by
retained `RTT` render-target pass entry
and exit paths, tested depth renderbuffer allocation/delete and framebuffer
depth attach/detach dispatch consumed by retained RTT and canvas object-drawing helpers,
shared legacy UI GL dispatch consumed by retained `NodeBorder`, `NodeImage`,
`NodeImageTexture`, `NodeColorWheel`, `NodeAnimationTimeline`, `NodeScroll`,
`NodeText`, `NodeTextInput`, and `NodeViewport` blend-state, fallback
texture unbind, viewport, color clear, and clear-color restore paths,
tested convert-command state dispatch consumed by
`App::cmd_convert`, tested render platform hint dispatch consumed by
`WindowsPlatformServices` and the retained macOS legacy fallback, tested
debug-output state dispatch consumed by `WindowsPlatformServices`, plus
renderer API to OpenGL token mapping and command-planning contracts used by
the OpenGL parity work.
- `pano_cli plan-cloud-upload` exposes `pp_app_core` cloud upload availability,
new-document warning, publish prompt, prompt title/message/captions, and
save-before-upload planning as JSON;
the live cloud upload command consumes the same start contract before
reaching legacy UI, canvas save, and network upload execution.
- `pano_cli plan-cloud-upload-all` exposes bulk cloud upload file-count,
progress UI availability, progress-total clamping, and progress dialog
metadata as JSON; the live upload-all command consumes the same contract
before reaching legacy asset file listing, OpenGL context guard, progress UI,
and network upload
execution.
- `pano_cli plan-cloud-browse` exposes `pp_app_core` cloud browse availability
and selected-file download planning as JSON; the live cloud browse command
consumes those contracts before reaching legacy dialog, network download,
canvas project-open, layer UI, and action-history execution.
- `src/legacy_cloud_services.*` is the current app-shell bridge for cloud
upload, bulk upload, browse dialog, and download execution. It keeps those
live paths on the `pp_app_core` `CloudServices` contract while the app-owned
curl upload/download/license helpers now ask `PlatformServices` for TLS
verification policy and retained dialog/network curl sites use the shared
default platform TLS helper. Cloud upload warning/publish/success copy, bulk
upload progress title, and download-progress copy now come from
`pp_app_core` dialog/progress plans before retained `NodeMessageBox` and
progress-bar execution. Legacy save-before-upload, progress/message UI,
network upload/download helper ownership, OpenGL context guarding,
`NodeDialogCloud`, project open, layer refresh, and action-history reset
remain tracked by `DEBT-0038`.
- `pano_cli simulate-app-session` exposes `pp_app_core` project-open,
app-close, save, save-as, save-version, and save-before-workflow decisions
as JSON and is covered for clean, dirty, already-prompting, missing-canvas,
new-document, save-as, save-version, and dirty-save-version states.
- Save, New Document, and Browse dialogs now use `PlatformServices` for
working-directory picker availability and displayed absolute-path formatting,
so `src/node_dialog_open.cpp` and `src/node_dialog_browse.cpp` no longer own
desktop-only path picker branches.
- `pp_app_core_document_route_tests` covers the app document-open route
contract for PPI/project files, ABR imports, PPBR imports, inner-dot names,
and malformed paths before the live `App::open_document` performs UI or
legacy canvas work.
- `pp_app_core_document_export_tests` covers export file targets, collection
directory/stem targets, picked-directory stems, work-directory versus
picker-stem collection target planning, MP4 suggested names, and invalid
export naming inputs, plus export-start license/canvas availability decisions,
export menu executor dispatch, file/stem/collection export execution
dispatch, failed directory creation preservation, named depth/cube export
dispatch, malformed export target rejection, video export dispatch for
animation MP4/timelapse paths, and empty video-path rejection.
- `pp_app_core_document_recording_tests` covers recording start/stop, clear,
platform recorded-file cleanup, frame-count reset, export progress totals,
oversized progress-total clamping, and recording-worker encode-wake
eligibility when recording, encoder, and canvas-document state vary.
- `pp_app_core_document_sharing_tests` covers saved-path gating before platform
share execution.
- `pp_app_core_document_platform_io_tests` covers empty selected-path filtering
and non-empty picked-path callback planning, plus empty/non-empty display-file
planning before platform picker/display callbacks, plus virtual keyboard
show/hide planning before platform keyboard callbacks, plus cursor visibility
planning before platform cursor callbacks, plus clipboard read/write
planning before platform clipboard callbacks.
- `pp_app_core_app_preferences_tests` covers UI scale/font-scale planning,
scale-option selection, viewport scale planning, RTL direction planning,
timelapse start/stop/no-op decisions, VR mode success/failure dispatch,
simple stored preferences, and `AppPreferenceServices` execution dispatch for
options-menu side effects.
- `pp_app_core_app_dialog_tests` covers app-level progress/message/input dialog
metadata planning, progress initialization, negative progress-total clamping,
message cancel-button/caption policy, input OK-caption propagation, and malformed
empty OK-caption rejection without requiring legacy `Node*` dialogs.
- `pp_app_core_app_startup_tests` covers startup run-counter increment
planning, optional auto-timelapse/license/VR-controller decisions, negative
and overflow run-counter rejection, stable full startup dispatch ordering,
split persistence/runtime dispatch, and malformed startup-plan rejection.
- `pp_app_core_app_frame_tests` covers the legacy initial surface default,
idle/redraw/animation update gating, canvas-stroke draw eligibility, VR UI
visibility, main UI suppression in VR-only mode, tick layout selection,
resize render-target/redraw projection, invalid resize rejection, redraw
reset planning, UI observer clipping, on-screen enter/leave transition
decisions, scissor projection, and malformed observer geometry rejection.
- `pp_app_core_app_thread_tests` covers render/UI task dispatch, immediate
same-thread execution, unique queued-task replacement, stopped-worker
no-wait behavior, render queue context wrapping, UI tick redraw scheduling,
UI-loop frame/FPS/reload timer thresholds, malformed timer rejection, redraw
frame-count projection, and thread start/stop intents.
- `pp_app_core_app_input_tests` covers pointer coordinate normalization,
invalid pointer/gesture inputs, designer-first mouse routing, mouse-cancel
routing, gesture midpoint/distance/delta math, main-layout routing, key state
mutation intent, VR spacebar camera-sync intent, UI visibility toggle target
selection, malformed UI-toggle layout rejection, and stylus touch-lock intent.
- `pp_app_core_app_shutdown_tests` covers legacy shutdown cleanup staging for
UI-state save, stroke-preview renderer shutdown, recording stop,
texture/shader invalidation, layout unload, render-target/mesh destruction,
panel-node release, and quick-mode cleanup.
- `pp_app_core_command_convert_tests` covers command-line panorama conversion
sequencing for renderer-state setup, temporary canvas allocation, project
open, equirectangular export, malformed input rejection, malformed-plan
rejection, and exact executor dispatch order.
- `pp_platform_api_tests` covers service dispatch for clipboard read/write,
empty clipboard writes, cursor visibility, virtual-keyboard visibility,
external file display, file sharing, VR lifecycle, layout/asset file load
policy, and picker callbacks without platform SDK headers or a window.
- `pp_app_core_document_cloud_tests` covers cloud upload no-canvas,
new-document warning, clean publish prompt, and dirty save-before-upload
decisions, plus cloud browse no-canvas/show-browser and selected-download
decisions, plus bulk upload progress visibility, zero-file, and clamped
progress-total decisions, plus cloud download/upload transfer request
validation, progress-callback enablement, TLS-verification policy, and
zero/negative/overrun transfer-progress fraction guards.
- `pp_app_core_document_session_tests` covers clean and dirty app session,
document-open action planning and executor dispatch/rejection, save-request,
close-request executor dispatch/no-op preservation, document-save executor
dispatch/no-op preservation, document-session prompt metadata for close,
save-before-workflow, overwrite, and save-error dialogs,
save-before-workflow executor dispatch,
new-document target/resolution/overwrite planning and executor dispatch,
document file target, combined save-file overwrite planning and executor
dispatch, plus save-version target decisions and executor validation without
requiring a window, canvas, or message box.
- `src/legacy_document_open_services.*` is the current app-shell bridge between
`pp_app_core` document-open plans and live ABR/PPBR import prompts,
unsaved-project discard prompts, project opening, layer UI refresh, title
updates, and action-history clearing. Accepted brush import prompts now
delegate import execution to `src/legacy_brush_package_import_services.*`;
remaining legacy document-open ownership is tracked by `DEBT-0039`.
- `src/legacy_brush_package_import_services.*` is the current app-shell bridge
between `pp_app_core` ABR/PPBR brush package import requests and live
`NodePanelBrushPreset::import_abr`/`import_ppbr` execution. It preserves the
detached legacy import worker threads and preset-panel storage ownership while
brush asset/paint/UI ownership is tracked by `DEBT-0048`.
- `pp_app_core_brush_package_import_tests` covers ABR and PPBR import kind
naming, path validation, service dispatch, and empty-path rejection without
requiring a window, brush preset panel, or filesystem read.
- `src/legacy_document_session_services.*` is the current app-shell bridge
between `pp_app_core` document-session decisions and live close prompts,
save dialogs, save-version routing, existing-project saves, and
save-before-workflow prompts. Close, save-before-workflow, new-document
overwrite, Save As overwrite, and save-error prompt text/captions now come
from the pure document-session prompt catalog exposed through
`pano_cli plan-document-session-prompt` before retained `NodeMessageBox`
creation. It also bridges accepted new-document plans to legacy canvas
resize/layer setup, overwrite prompts, title updates, and keyboard/dialog
cleanup. Accepted Save As and Save Version plans now also
route through this bridge before reaching legacy project-save execution,
overwrite prompts, document field updates, title updates, and keyboard/dialog
cleanup. Retained legacy UI/canvas execution remains tracked by `DEBT-0040`,
`DEBT-0041`, and `DEBT-0042`.
- `src/legacy_document_export_services.*` is the current app-shell bridge
between `pp_app_core` document export execution plans and live equirectangular,
layers, animation-frame, depth, and cube-face export calls. It preserves
platform-specific export messages, directory creation, picker-selected stem
exports, Web prepared-file handoff, and legacy `Canvas` export execution while
retained renderer/document/platform ownership is tracked by `DEBT-0043`. It
also bridges timelapse and animation MP4 export picker-selected paths while
preserving desktop worker-thread timelapse behavior, mobile/Web save
callbacks, `App::rec_export`, animation `Canvas::export_anim_mp4`, and
success messages; retained video/export ownership is tracked by `DEBT-0044`.
- `src/legacy_brush_package_export_services.*` is the current app-shell bridge
between `pp_app_core` PPBR brush package export requests and live
`NodePanelBrushPreset::export_ppbr` execution. It preserves dialog metadata,
the retained legacy `Image` header object, desktop worker-thread export,
mobile/Web save completion, dialog lifetime, and success messages while the
PPBR preview data-directory override now comes from `PlatformServices`;
remaining brush asset/storage/UI/platform ownership is tracked by
`DEBT-0047`.
- `src/assets/brush_package.*` owns the first headless PPBR package helpers:
header validation, legacy-compatible version acceptance, export path
normalization, preview-data-directory planning, and imported brush
tip/pattern image target paths. Live export maps the active platform PPBR
data-directory policy into these helpers, and live
`NodePanelBrushPreset::export_ppbr`/`import_ppbr` and ABR import image writes
consume these helpers, but legacy Serializer/Image payload parsing, preview
rendering, preset storage, duplicate policy, and strict-version cleanup remain
tracked by `DEBT-0047`, `DEBT-0048`, and `DEBT-0049`.
- `pp_assets_brush_package_tests` covers PPBR header parsing, truncated/bad
magic rejection, legacy version tolerance, export package/data path planning,
legacy extension containment, paths the legacy regex could not match, brush
tip/pattern image target planning, and invalid imported image target inputs.
- `pp_app_core_brush_package_export_tests` covers PPBR export request path
validation, metadata preservation, legacy-flexible destination/export-data
combinations, service dispatch, and malformed request rejection without
requiring a window, brush preset panel, or filesystem write.
- `src/legacy_history_services.*` is the current app-shell bridge between
`pp_app_core` history plans and legacy `ActionManager`; toolbar and
`NodeCanvas` hotkeys share it while document-history extraction remains
tracked by DEBT-0026.
- `src/legacy_document_canvas_services.*` is the current app-shell bridge
between `pp_app_core` canvas-clear/resize plans and legacy `Canvas`;
toolbar clear, Layer menu clear, and the resize dialog share it while
document/canvas execution extraction remains tracked by DEBT-0020 and
DEBT-0028.
- `pp_ui_core` consumes vcpkg tinyxml2 only when `PP_USE_VCPKG_TINYXML2=ON`
through the vcpkg preset; default and Android validation still use the
retained vendored fallback tracked by DEBT-0012.
Known warnings after the current CMake app build:
- Legacy code/vendor warnings under `/W4`.
- `pp_legacy_vendor` intentionally owns retained third-party source builds for
now, including JPEG, SQLite, Yoga, poly2tri, GLAD, fmt, Wacom utilities, and
other patched/embedded sources. Each dependency should either move to vcpkg,
an SDK import target, or a documented permanent vendored target.
- `pp_legacy_assets_io` is an object-library containment boundary for retained
ABR, asset/file, binary stream, image, serializer, and settings code. It
should shrink as app I/O consumes `pp_assets` directly. `src/asset.h` now
forward-declares Android asset-manager types and exposes
`Asset::set_android_asset_manager` instead of public mutable Android asset
manager state; concrete Android asset-manager headers remain in `asset.cpp`
and the retained Android entrypoint while DEBT-0056 tracks replacing the
static Android asset bridge with injected asset storage.
- `pp_legacy_paint_document` is an object-library containment boundary for
retained action, bezier, brush, canvas, canvas-layer, and event code. It
should shrink as app painting and document behavior consume `pp_paint` and
`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
sources for now, so it concentrates existing legacy tablet, video, HMD, log,
and low-level utility warnings until those paths move to cleaner component
ownership.
- `pp_legacy_renderer_gl` is an object-library containment boundary because
the retained OpenGL runtime classes still include legacy app/engine headers
and are still consumed directly by canvas and UI classes. It should become a
normal backend library once those call sites depend on `pp_renderer_api`.
`pp_renderer_gl` now owns OpenGL runtime build-target classification through
CMake target compile definitions and `opengl_runtime_for_current_build()`,
so app shader startup asks the backend for desktop GL/GLES/WebGL policy
instead of carrying local platform branches. It also owns headless-tested
OpenGL extension enumeration through `query_opengl_extensions`, moving the
extension count/string query loop out of `app_shaders.cpp`. Startup feature
negotiation now uses `query_opengl_capability_detection`, so extension
enumeration, runtime capability policy, and renderer-neutral feature
conversion are validated together before the retained `ShaderManager` static
flags are updated. `RenderDeviceFeatures` now includes float32-linear
filtering, and live canvas, diagnostics, and grid lightmap/bake decisions
consume that renderer-neutral snapshot rather than reading retained
`ShaderManager::ext_*` fields directly.
- `pp_legacy_ui_core` is an object-library containment boundary because the
retained base `Node` controls still depend on legacy renderer and app
headers. It should shrink as layout parsing, colors, generic controls, and
text/image primitives move to `pp_ui_core`.
- `pp_panopainter_ui` currently surfaces existing legacy `Node`/`Serializer`
header and static-analysis warnings while it still depends on
`pp_legacy_app`; these should be reduced as the UI core/app UI boundary is
tightened instead of suppressed globally.
- `pp_app_core` is the first pure app-engine target consumed by
`panopainter_app`; it should grow only with UI-free command routing,
validation, and app service contracts that can be tested without a window.
- `panopainter_app` currently surfaces existing app orchestration, GLM,
base64, VR, and serializer warnings now that app sources live in the
composition target; warning cleanup should follow component ownership rather
than be hidden with target-wide suppressions.
- Visual Studio vcpkg manifest warning because manifest mode is not enabled.
- `LNK4099` missing `yuv.pdb` for retained libyuv binaries.
- `LNK4098` runtime library conflict from retained vendor binaries.
Platform-specific commands should be added here when verified locally.