From f622387f4a378d0724ae4f28a843e38641abbe2f Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Mon, 20 Apr 2026 09:36:04 +0100 Subject: [PATCH] [PERF] Host Desktop Frame Pacing and Presentation --- discussion/index.ndjson | 4 +- ...t-desktop-frame-pacing-and-presentation.md | 17 +- ...t-desktop-frame-pacing-and-presentation.md | 141 +++++++++++++++ ...t-desktop-frame-pacing-and-presentation.md | 170 ++++++++++++++++++ 4 files changed, 327 insertions(+), 5 deletions(-) create mode 100644 discussion/workflow/decisions/DEC-0019-host-desktop-frame-pacing-and-presentation.md create mode 100644 discussion/workflow/plans/PLN-0036-host-desktop-frame-pacing-and-presentation.md diff --git a/discussion/index.ndjson b/discussion/index.ndjson index fa97b69b..e82c3ea4 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -1,4 +1,4 @@ -{"type":"meta","next_id":{"DSC":29,"AGD":29,"DEC":19,"PLN":36,"LSN":36,"CLSN":1}} +{"type":"meta","next_id":{"DSC":29,"AGD":29,"DEC":20,"PLN":37,"LSN":36,"CLSN":1}} {"type":"discussion","id":"DSC-0023","status":"done","ticket":"perf-full-migration-to-atomic-telemetry","title":"Agenda - [PERF] Full Migration to Atomic Telemetry","created_at":"2026-04-10","updated_at":"2026-04-10","tags":["perf","runtime","telemetry"],"agendas":[{"id":"AGD-0021","file":"workflow/agendas/AGD-0021-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0008","file":"workflow/decisions/DEC-0008-full-migration-to-atomic-telemetry.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0007","file":"workflow/plans/PLN-0007-full-migration-to-atomic-telemetry.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0028","file":"lessons/DSC-0023-perf-full-migration-to-atomic-telemetry/LSN-0028-converging-to-single-atomic-telemetry-source.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} {"type":"discussion","id":"DSC-0020","status":"done","ticket":"jenkins-gitea-integration","title":"Jenkins Gitea Integration and Relocation","created_at":"2026-04-07","updated_at":"2026-04-07","tags":["ci","jenkins","gitea"],"agendas":[{"id":"AGD-0018","file":"workflow/agendas/AGD-0018-jenkins-gitea-integration-and-relocation.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"decisions":[{"id":"DEC-0003","file":"workflow/decisions/DEC-0003-jenkins-gitea-strategy.md","status":"accepted","created_at":"2026-04-07","updated_at":"2026-04-07"}],"plans":[{"id":"PLN-0003","file":"workflow/plans/PLN-0003-jenkins-gitea-execution.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}],"lessons":[{"id":"LSN-0021","file":"lessons/DSC-0020-jenkins-gitea-integration/LSN-0021-jenkins-gitea-integration.md","status":"done","created_at":"2026-04-07","updated_at":"2026-04-07"}]} {"type":"discussion","id":"DSC-0021","status":"done","ticket":"asset-entry-codec-enum-with-metadata","title":"Asset Entry Codec Enum Contract","created_at":"2026-04-09","updated_at":"2026-04-09","tags":["asset","runtime","codec","metadata"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0024","file":"lessons/DSC-0021-asset-entry-codec-enum-contract/LSN-0024-string-on-the-wire-enum-in-runtime.md","status":"done","created_at":"2026-04-09","updated_at":"2026-04-09"}]} @@ -12,7 +12,7 @@ {"type":"discussion","id":"DSC-0007","status":"open","ticket":"app-home-filesystem-surface-and-semantics","title":"Agenda - App Home Filesystem Surface and Semantics","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0006","file":"workflow/agendas/AGD-0006-app-home-filesystem-surface-and-semantics.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0008","status":"done","ticket":"perf-runtime-telemetry-hot-path","title":"Agenda - [PERF] Runtime Telemetry Hot Path","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[{"id":"AGD-0007","file":"workflow/agendas/AGD-0007-perf-runtime-telemetry-hot-path.md","status":"done","created_at":"2026-03-27","updated_at":"2026-04-10"}],"decisions":[{"id":"DEC-0005","file":"workflow/decisions/DEC-0005-perf-push-based-telemetry-model.md","status":"accepted","created_at":"2026-04-10","updated_at":"2026-04-10"}],"plans":[{"id":"PLN-0005","file":"workflow/plans/PLN-0005-perf-push-based-telemetry-implementation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}],"lessons":[{"id":"LSN-0026","file":"lessons/DSC-0008-perf-runtime-telemetry-hot-path/LSN-0026-push-based-telemetry-model.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} {"type":"discussion","id":"DSC-0009","status":"open","ticket":"perf-async-background-work-lanes-for-assets-and-fs","title":"Agenda - [PERF] Async Background Work Lanes for Assets and FS","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0008","file":"workflow/agendas/AGD-0008-perf-async-background-work-lanes-for-assets-and-fs.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} -{"type":"discussion","id":"DSC-0010","status":"open","ticket":"perf-host-desktop-frame-pacing-and-presentation","title":"Agenda - [PERF] Host Desktop Frame Pacing and Presentation","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0009","file":"workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} +{"type":"discussion","id":"DSC-0010","status":"in_progress","ticket":"perf-host-desktop-frame-pacing-and-presentation","title":"Agenda - [PERF] Host Desktop Frame Pacing and Presentation","created_at":"2026-03-27","updated_at":"2026-04-20","tags":[],"agendas":[{"id":"AGD-0009","file":"workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md","status":"in_progress","created_at":"2026-03-27","updated_at":"2026-04-20"}],"decisions":[{"id":"DEC-0019","file":"DEC-0019-host-desktop-frame-pacing-and-presentation.md","status":"accepted","created_at":"2026-04-20","updated_at":"2026-04-20","ref_agenda":"AGD-0009"}],"plans":[{"id":"PLN-0036","file":"PLN-0036-host-desktop-frame-pacing-and-presentation.md","status":"review","created_at":"2026-04-20","updated_at":"2026-04-20","ref_decisions":["DEC-0019"]}],"lessons":[]} {"type":"discussion","id":"DSC-0011","status":"open","ticket":"perf-gfx-render-pipeline-and-dirty-regions","title":"Agenda - [PERF] GFX Render Pipeline and Dirty Regions","created_at":"2026-03-27","updated_at":"2026-03-27","tags":[],"agendas":[{"id":"AGD-0010","file":"workflow/agendas/AGD-0010-perf-gfx-render-pipeline-and-dirty-regions.md","status":"open","created_at":"2026-03-27","updated_at":"2026-03-27"}],"decisions":[],"plans":[],"lessons":[]} {"type":"discussion","id":"DSC-0012","status":"done","ticket":"perf-runtime-introspection-syscalls","title":"Agenda - [PERF] Runtime Introspection Syscalls","created_at":"2026-03-27","updated_at":"2026-04-19","tags":["perf","runtime","syscall","telemetry","debug","asset"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0034","file":"lessons/DSC-0012-perf-runtime-introspection-syscalls/LSN-0034-host-owned-debug-boundaries.md","status":"done","created_at":"2026-04-19","updated_at":"2026-04-19"}]} {"type":"discussion","id":"DSC-0013","status":"done","ticket":"perf-host-debug-overlay-isolation","title":"Agenda - [PERF] Host Debug Overlay Isolation","created_at":"2026-03-27","updated_at":"2026-04-10","tags":[],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0027","file":"lessons/DSC-0013-perf-host-debug-overlay-isolation/LSN-0027-host-debug-overlay-isolation.md","status":"done","created_at":"2026-04-10","updated_at":"2026-04-10"}]} diff --git a/discussion/workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md b/discussion/workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md index e2cf62f3..4ee79cfd 100644 --- a/discussion/workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md +++ b/discussion/workflow/agendas/AGD-0009-perf-host-desktop-frame-pacing-and-presentation.md @@ -2,10 +2,10 @@ id: AGD-0009 ticket: perf-host-desktop-frame-pacing-and-presentation title: Agenda - [PERF] Host Desktop Frame Pacing and Presentation -status: open +status: in_progress created: 2026-03-27 -resolved: -decision: +resolved: 2026-04-20 +decision: DEC-0019 tags: [] --- @@ -60,8 +60,19 @@ Fechar uma politica de pacing/apresentacao host-driven que nao desperdice CPU qu ## Open Questions de Arquitetura 1. O host desktop deve ser referencia conservadora de energia ou apenas shell de desenvolvimento? + R: O desktop eh shell de desenvolvimento, mas pode tb ser usado para jogar em um pc. Deve oferecer controle de energia como um handheld, especialmente para desenvolvimento. 2. O runtime precisa expor um sinal explicito de "novo frame disponivel" para o host? + R: Atualmente fazemos o swap do buffer somente quando o frame logico eh pronto, esse eh o "ponto de entrada" para o host. Eh ali que a conversao de RGB565 -> RGBA8 pode ser realizada e mostrada. Se o host precisar saber quando o frame eh pronto, pode ser exposto por um sinal explicito. 3. Existe necessidade real de redraw continuo quando o overlay esta desligado? + R: Nao + +## Perguntas em Aberto + +Nenhuma. As perguntas de arquitetura desta agenda foram respondidas e o tema esta pronto para cristalizacao em decisao. + +## Resolucao + +A agenda fecha com a direcao de que o host desktop nao deve manter redraw continuo por padrao. O host deve operar com pacing orientado por frame logico pronto e por eventos externos relevantes, preservando um comportamento energeticamente conservador sem perder utilidade como shell de desenvolvimento. Se o host precisar consumir esse momento de forma explicita, o runtime pode expor um sinal canonico de "novo frame disponivel" no ponto em que o frame logico eh concluido. ## Dependencias diff --git a/discussion/workflow/decisions/DEC-0019-host-desktop-frame-pacing-and-presentation.md b/discussion/workflow/decisions/DEC-0019-host-desktop-frame-pacing-and-presentation.md new file mode 100644 index 00000000..0d9a3145 --- /dev/null +++ b/discussion/workflow/decisions/DEC-0019-host-desktop-frame-pacing-and-presentation.md @@ -0,0 +1,141 @@ +--- +id: DEC-0019 +ticket: perf-host-desktop-frame-pacing-and-presentation +title: Decision - [PERF] Host Desktop Frame Pacing and Presentation +status: accepted +created: 2026-04-20 +accepted: 2026-04-20 +agenda: AGD-0009 +plans: [PLN-0036] +tags: [perf, host, desktop, frame-pacing, presentation, debug] +--- + +# Status + +Accepted. This decision is now normatively locked and is ready to drive planning and execution. + +## Contexto + +O host desktop atual usa `ControlFlow::Poll`, pede redraw continuamente e reapresenta o framebuffer mesmo quando a maquina nao publicou um novo frame logico. + +Esse comportamento conflita com o modelo temporal de `docs/specs/runtime/01-time-model-and-cycles.md`, onde a maquina opera em frames logicos de 60 Hz, e com o contrato de portabilidade e isolamento de debug em `docs/specs/runtime/10-debug-inspection-and-profiling.md` e `docs/specs/runtime/11-portability-and-cross-platform-execution.md`, onde apresentacao e overlay pertencem ao host, mas nao devem redefinir a semantica logica da maquina. + +O problema a ser fechado aqui nao eh o desenho final do backend grafico. O problema eh definir quando o host desktop tem permissao para acordar, converter e apresentar pixels sem transformar a shell desktop em um loop de polling agressivo. + +## Decisao + +O host desktop SHALL adotar pacing orientado por frame logico publicado e por eventos externos relevantes, e MUST NOT manter redraw continuo por padrao. + +Normas desta decisao: + +1. Gatilho canonico de redraw + - O host MUST considerar um novo frame logico publicado como gatilho principal de apresentacao. + - O host MAY solicitar redraw adicional quando houver evento externo relevante que altere apenas a superficie host-owned, incluindo resize da janela, expose/invalidate da janela, toggle de overlay, atualizacao visivel do debugger ou mudanca de estado local da shell. + - O host MUST NOT solicitar redraw continuo apenas para "ver se existe frame novo". + +2. Politica do event loop + - O host desktop MUST sair de `ControlFlow::Poll` como politica padrao. + - O event loop SHOULD operar em modo de espera dirigida por deadline ou evento, usando `WaitUntil` para o proximo slice logico quando houver trabalho temporal agendado e `Wait` quando nao houver deadline imediato. + - `Poll` MAY existir apenas em modo explicitamente opt-in de profiling/diagnostico host-owned e MUST NOT ser o comportamento normal de execucao. + +3. Conversao de framebuffer + - A conversao RGB565 -> RGBA8 permanece full-frame nesta fase. + - Essa conversao MUST acontecer apenas quando houver novo frame logico publicado ou quando um evento host-owned exigir recomposicao/apresentacao da superficie visivel. + - Dirty-region conversion e offload para shader/GPU ficam explicitamente fora do contrato desta decisao e poderao ser avaliados em discussao separada se o full-frame on-demand ainda for insuficiente. + +4. Modo ocioso, pausa e debug + - Quando a VM estiver pausada, em breakpoint, esperando `start`, ou sem cart carregado, o host MUST preservar o ultimo frame visivel valido e MUST NOT ficar redesenhando continuamente. + - Nesses estados, redraw adicional so pode ocorrer por evento host-owned relevante, como overlay/debug data visivel, resize/expose ou transicao explicita de estado. + - Buffers logicos da maquina MUST NOT ser trocados durante pausa apenas para sustentar HUD host-owned. + +5. Sinal de "novo frame disponivel" + - O runtime/host boundary MUST ter um ponto canonico de observacao do "frame pronto", alinhado ao momento em que o frame logico e publicado para apresentacao. + - A implementacao inicial MAY usar um sinal explicito, contador monotonicamente crescente, dirty flag ou observacao do ponto de swap/publicacao, desde que a semantica seja unica e nao ambigua. + - Essa decisao MUST NOT introduzir uma ABI guest-visible nova. O sinal pertence ao boundary interno runtime-host e as superficies host-owned de inspecao. + +## Rationale + +`Poll` com redraw continuo mascara custo de apresentacao, consome CPU sem beneficio visual e reduz a utilidade do desktop como referencia de comportamento energetico razoavel. + +Ao mesmo tempo, a shell desktop nao deve ser tratada como uma plataforma "ultra-conservadora" a ponto de perder ergonomia de debug. Por isso a decisao nao proibe redraw extra; ela apenas restringe redraw extra a eventos com causa concreta e visivel. + +Manter a conversao full-frame por enquanto evita reabrir a arquitetura de renderizacao durante um trabalho cujo alvo principal eh pacing. O ganho imediato vem de parar de converter e apresentar quando nada mudou. Se isso nao bastar, dirty regions ou shader path podem ser discutidos depois com evidencias. + +Separar "frame logico publicado" de "overlay host-owned mudou" preserva o contrato de portabilidade: o host pode mostrar mais informacao tecnica sem forcar a VM a produzir frames adicionais nem adulterar o framebuffer logico. + +## Invariantes / Contrato + +- A maquina continua definindo frames logicos em 60 Hz; o host nao redefine esse relogio. +- O host apresenta o ultimo frame logico publicado; ele nao inventa frames intermediarios. +- Overlay e debugger sao host-owned e MAY compor sobre uma superficie de apresentacao host-only. +- Overlay/debug MUST NOT exigir redraw continuo quando seu conteudo estiver estavel. +- Conversao/presentacao do framebuffer MUST ser dirigida por mudanca observavel, nao por polling agressivo. +- O boundary runtime-host MUST expor um criterio unico para detectar publicacao de frame logico. +- Esta decisao nao promove dirty regions nem GPU offload a contrato normativo. +- Esta decisao nao altera semantica guest-visible de `DRAW`, buffers logicos, ciclos, ou telemetria de certificacao. + +## Alternativas Descartadas + +### Manter `Poll` permanente no desktop + +Descartado porque esconde custo real de apresentacao, desperdiça CPU e cria uma shell cuja estabilidade aparente depende de trabalho inutil. + +### Redraw orientado apenas por vsync fisico + +Descartado como contrato canonico porque o modelo PROMETEU e dirigido por frame logico e a portabilidade nao depende de sincronizar a semantica da maquina a uma frequencia fisica do host. + +### Reabrir o problema com dirty regions ou shader path como pre-condicao + +Descartado nesta etapa porque mistura otimizacao secundaria com o contrato principal de pacing. O problema imediato pode e deve ser resolvido sem nova arquitetura de render backend. + +## Impactos + +### Spec + +- `docs/specs/runtime/10-debug-inspection-and-profiling.md` deve refletir que a apresentacao host-owned observa frame publicado e nao requer redraw continuo para HUD/overlay estavel. +- `docs/specs/runtime/11-portability-and-cross-platform-execution.md` deve explicitar que a superficie host de apresentacao pode recompor overlay por evento relevante, sem transformar isso em polling permanente. + +### Runtime + +- O runtime pode precisar expor ou estabilizar um ponto interno de publicacao de frame pronto para o host desktop consumir de forma canonica. +- Nenhuma nova ABI guest-visible deve ser criada por este trabalho. + +### Host Desktop + +- O loop winit deve migrar de `Poll` para espera dirigida por deadline/evento. +- `request_redraw()` deixa de ser incondicional no ciclo de idle. +- A apresentacao passa a depender de novo frame logico ou evento host-owned relevante. + +### Firmware + +- Sem mudanca de semantica guest-visible. +- Estados de pausa/breakpoint continuam impedindo avanco de tempo logico e swap de buffers logicos. + +### Tooling + +- Overlay/debugger continuam host-owned, mas precisam declarar quando realmente invalidam a superficie visivel. +- Profiling host-only pode manter um modo opt-in de polling agressivo, separado do comportamento normal. + +## Referencias + +- [AGD-0009]() +- [docs/specs/runtime/01-time-model-and-cycles.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/01-time-model-and-cycles.md) +- [docs/specs/runtime/10-debug-inspection-and-profiling.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/10-debug-inspection-and-profiling.md) +- [docs/specs/runtime/11-portability-and-cross-platform-execution.md](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/docs/specs/runtime/11-portability-and-cross-platform-execution.md) +- [runner.rs](/Users/niltonconstantino/personal/workspace.personal/intrepid/prometeu/runtime/crates/host/prometeu-host-desktop-winit/src/runner.rs:252) + +## Propagacao Necessaria + +- Escrever um `PLN` para implementar a mudanca no host desktop. +- Atualizar as specs normativas citadas para refletir este contrato. +- Ajustar o host desktop para consumir um gatilho canonico de frame publicado. +- Adicionar testes para: + - ausencia de redraw continuo sem frame novo; + - redraw em evento host-owned relevante; + - preservacao do ultimo frame em pausa/breakpoint/no-cart; + - modo opt-in de polling apenas quando explicitamente habilitado. + +## Revision Log + +- 2026-04-20: Initial draft from AGD-0009. +- 2026-04-20: Accepted and linked to PLN-0036. diff --git a/discussion/workflow/plans/PLN-0036-host-desktop-frame-pacing-and-presentation.md b/discussion/workflow/plans/PLN-0036-host-desktop-frame-pacing-and-presentation.md new file mode 100644 index 00000000..effb618d --- /dev/null +++ b/discussion/workflow/plans/PLN-0036-host-desktop-frame-pacing-and-presentation.md @@ -0,0 +1,170 @@ +--- +id: PLN-0036 +ticket: perf-host-desktop-frame-pacing-and-presentation +title: Plan - Host Desktop Frame Pacing and Presentation +status: review +created: 2026-04-20 +completed: +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.