prometeu-runtime/discussion/workflow/plans/PLN-0036-host-desktop-frame-pacing-and-presentation.md

171 lines
8.8 KiB
Markdown

---
id: PLN-0036
ticket: perf-host-desktop-frame-pacing-and-presentation
title: Plan - Host Desktop Frame Pacing and Presentation
status: done
created: 2026-04-20
completed: 2026-04-20
tags: [perf, host, desktop, frame-pacing, presentation, debug]
---
## Briefing
Implement `DEC-0019` by removing unconditional desktop redraw polling, introducing a canonical host-side frame-publication trigger, preserving the last visible frame during paused or idle states, and updating the normative specs to reflect the locked contract.
## Decisions de Origem
- `DEC-0019` - Host Desktop Frame Pacing and Presentation
## Alvo
Deliver a host desktop execution path where:
- the winit loop no longer uses continuous polling by default;
- redraw happens only after logical frame publication or explicit host-owned invalidation events;
- RGB565 to RGBA8 conversion remains full-frame but only runs on demand;
- paused, debugger-waiting, and no-cartridge states keep the last valid image without continuous redraw;
- specs and tests match the accepted decision.
## Escopo
- Update the desktop host loop in `crates/host/prometeu-host-desktop-winit/src/runner.rs`.
- Introduce or stabilize a canonical "new frame published" signal at the runtime-host boundary.
- Track host-owned invalidation causes for overlay, debugger, and window events.
- Update the relevant runtime specs under `docs/specs/runtime/`.
- Add or extend automated tests for redraw gating and paused-state behavior.
## Fora de Escopo
- Dirty-region framebuffer conversion.
- GPU/shader-based presentation paths.
- New guest-visible ABI or debug surface.
- Redesign of overlay visuals or debugger protocol beyond invalidation signaling.
- Reopening the architecture covered by `DEC-0019`.
## Plano de Execucao
### Step 1 - Establish the canonical frame-publication trigger
**What:** Define the single host-consumable signal that indicates a new logical frame has been published.
**How:** Inspect the current buffer swap/publication point in the desktop runtime path and choose the existing internal publication event, dirty flag, or monotonic frame counter that can become the canonical trigger required by `DEC-0019`. If no stable signal exists, add a host-internal publication marker that changes exactly once per newly published logical frame and is not guest-visible.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
- any directly related runtime/firmware module discovered as the current frame-publication owner
**Depends on:** none
### Step 2 - Replace unconditional redraw requests with invalidation-driven scheduling
**What:** Remove the unconditional redraw call from the idle loop and gate presentation on frame publication or host-owned invalidation.
**How:** Refactor `about_to_wait()` and redraw scheduling in `runner.rs` so the host requests redraw only when:
- a new logical frame was published since the last presentation;
- the window receives a visible invalidation event such as resize/expose;
- overlay state toggles or changes a visible host-owned layer;
- debugger-visible state changes require host-side recomposition.
Introduce explicit host-owned invalidation state if needed so redraw causes are tracked instead of inferred by polling.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
**Depends on:** Step 1
### Step 3 - Move the event loop from default `Poll` to deadline/event waiting
**What:** Change the normal desktop control flow so the host waits for the next logical deadline or external event instead of spinning continuously.
**How:** Update `resumed()` and any related loop control code in `runner.rs` to stop using `ControlFlow::Poll` as the default. Use `WaitUntil` when a next logical tick deadline is known and `Wait` when the host is effectively idle with no immediate timing deadline. Keep any aggressive polling path behind an explicit profiling-only switch rather than as baseline behavior.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
- `crates/host/prometeu-host-desktop-winit/src/main.rs` if a profiling-only opt-in flag is wired at startup
**Depends on:** Step 2
### Step 4 - Preserve the last valid frame during paused, breakpoint, and no-cart states
**What:** Ensure non-running machine states do not cause repeated conversion/presentation work while still allowing host-owned UI recomposition when something visible changes.
**How:** Separate "machine produced a new frame" from "host-owned layer needs redraw". Keep the last presented RGBA output available for reuse, avoid logical buffer swaps during pause-only overlay activity, and ensure debugger waiting and no-cartridge states do not schedule continuous redraws. If overlay or debugger content changes while the machine is paused, redraw only the host-owned composition layer on explicit invalidation.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
- `crates/host/prometeu-host-desktop-winit/src/overlay.rs`
- `crates/host/prometeu-host-desktop-winit/src/debugger.rs`
**Depends on:** Step 2
### Step 5 - Update the normative specs
**What:** Propagate the accepted decision into the canonical runtime specs.
**How:** Update the portability and debug chapters so they explicitly state that desktop presentation observes published logical frames, that host-owned overlay/debug redraw is event-driven rather than continuously polled, and that stable host HUD state does not justify perpetual redraw. Keep the text aligned with the locked decision and do not introduce new architecture.
**File(s):**
- `docs/specs/runtime/10-debug-inspection-and-profiling.md`
- `docs/specs/runtime/11-portability-and-cross-platform-execution.md`
**Depends on:** Step 1
### Step 6 - Add regression tests and evidence
**What:** Add automated coverage for the redraw contract and document manual evidence where platform events are hard to model.
**How:** Extend or add tests in the desktop host crate to cover:
- no redraw request when no new frame and no host invalidation occurred;
- redraw request after a newly published logical frame;
- redraw request after overlay toggle or equivalent host-owned invalidation;
- no continuous redraw in paused/debugger-waiting/no-cart states;
- preservation of last visible frame semantics while paused.
Where direct winit event simulation is difficult, factor logic into testable state transitions and keep any remaining platform verification in a short manual checklist.
**File(s):**
- `crates/host/prometeu-host-desktop-winit/src/runner.rs`
- `crates/host/prometeu-host-desktop-winit/src/overlay.rs` if overlay invalidation helpers become testable
- `crates/host/prometeu-host-desktop-winit/src/debugger.rs` if debugger invalidation hooks are exposed
**Depends on:** Steps 2, 3, 4
## Criterios de Aceite
- The default desktop event loop no longer runs in continuous `ControlFlow::Poll`.
- The host requests redraw only after canonical frame publication or explicit host-owned invalidation.
- Full-frame RGB565 to RGBA8 conversion remains in place but is not executed continuously while the visible machine frame is unchanged.
- Paused, breakpoint, debugger-waiting, and no-cartridge states preserve the last valid image without continuous redraw.
- Overlay or debugger changes can still trigger targeted host-owned redraw when visually necessary.
- No guest-visible ABI is added for this feature.
- The relevant runtime specs state the same redraw and presentation contract as `DEC-0019`.
- Automated tests cover the main redraw gating paths and paused-state behavior.
## Tests / Validacao
### Unit Tests
- Add focused tests for redraw scheduling state transitions in the desktop host runner.
- Add tests for any helper that tracks frame-publication state or host-owned invalidation causes.
### Integration Tests
- Extend host crate tests to verify frame publication and debugger/overlay invalidation do not regress redraw policy.
- Run `cargo test -p prometeu-host-desktop-winit --lib`.
### Manual Verification
- Launch the desktop host with overlay disabled and confirm CPU usage drops when the machine is visually stable.
- Toggle overlay on and off and confirm redraw happens on the visible transition without restoring continuous polling.
- Pause execution or wait for debugger start and confirm the last frame remains visible without repeated redraw.
- Resize or expose the window and confirm the surface is recomposed correctly.
## Riscos
- The actual frame-publication point may be less explicit than assumed, requiring a small host-internal contract addition before redraw gating can be made reliable.
- winit waiting semantics can introduce timing regressions if the next logical deadline is computed incorrectly.
- Overlay or debugger code may currently assume redraw is always free, which can surface hidden invalidation bugs after polling is removed.
- Manual verification may still be needed for some window-system invalidation behavior that is cumbersome to model in tests.