34 lines
3.7 KiB
Markdown
34 lines
3.7 KiB
Markdown
# STEP-058 Weather-local Target FPS 与 Repaint Gate 设计
|
||
|
||
## Host contract
|
||
|
||
`WeatherRuntime.TargetFps` 只提供 `AUTO`、`FPS_30`、`FPS_60`,默认 `AUTO`。`WeatherRuntime.setTargetFps()` 返回 typed `CommandResult`,`getTargetFps()` 返回当前 Host 选择。Host 不接触 RenderLayer、deadline、`needsRepaint()` 或 renderer `requestRender()` 细节;未来 RN 只包裹该 facade 方法。
|
||
|
||
## Shared cadence authority
|
||
|
||
天气 cadence 归 `RasterArrayTimelineRuntime` 所有,与 source 的 T0/T1、MIX、playback 共存。它保存 target mode、单一 monotonic last cadence tick、deadline 判定和低频 tick 计数。Particle 与 WeatherColor renderer 都读取同一 timeline authority;没有各自 timer 或 gate。AUTO 始终 due,30/60 使用约 33.33/16.67ms 间隔,且 target 切换重置 cadence deadline,不改变 Timeline/field/window。
|
||
|
||
`tick()` 仅在 deadline 到达时推进真实 `steady_clock` elapsed;不把 1/30 或 1/60 写入 simulation delta。这样 particle lifecycle、Trail fade、Timeline playback 和速度仍使用真实 wall time。
|
||
|
||
## Repaint 与 delayed wake-up
|
||
|
||
`RenderRasterParticleLayer::needsRepaint()` 与 `RenderWeatherColorLayer::needsRepaint()` 共享 source timeline 的 due 判定。Android `WeatherRuntime` 使用已有 `MapLibreMap.triggerRepaint()` 作为最小 delayed wake-up seam,在 READY 且至少一层需要天气持续动画时按目标间隔唤醒;AUTO 不安装天气 wake-up。Runtime disable/clear、两层 hidden 或错误状态会停止 wake-up。未使用 `MapView#setMaximumFps()`,因此 camera/其他 layer 仍可保持地图自身帧率。
|
||
|
||
地图高频 camera frame 在未到 deadline 时只重用现有粒子/Trail composite,不推进 State、Trail、Timeline 或 field upload;天气到 deadline 后两层再次消费同一 cadence。WeatherColor visibility 不依赖 particle visibility:Particle hidden + WeatherColor PLAY 仍可唤醒;两层 hidden、WeatherColor PAUSE 且 Particle hidden 时不持续唤醒。
|
||
|
||
## 动态修改与边界
|
||
|
||
target 切换仅更新 source/timeline cadence,不 reload Style、不重提交 field、不 reset particle State、不 clear Trail、不重建 field texture。clear/disabled 后 timeline 被清空,cadence naturally 无 due frame。Core 保留 canonical U/V、T0/T1/MIX、Runtime Field Window、OLD_T1→NEW_T0 reuse 与 only NEW_T1 upload。
|
||
|
||
## 测试策略
|
||
|
||
cadence deadline 通过显式 `steady_clock::time_point`/duration 的 deterministic 测试验证,不使用 sleep:AUTO always due、30/60 deadline 前后、target switch 和 single-authority 行为。Android popup 仅作为 Host 模拟器提供 FPS AUTO/30/60 与 HUD 显示;Android Gradle/设备验收另行执行。
|
||
|
||
## STEP-058A shared advance 与 Runtime 生命周期修正
|
||
|
||
`RasterArrayTimelineRuntime::advanceIfDue(now)` 在同一 mutex 内完成 due 判定、cadence revision、真实 wall-time Timeline 推进和 frame 返回。Particle 与 WeatherColor 均可作为 consumer;先到者推进,后到者收到相同 `cadenceRevision` 且不会再次推进。Particle 用 revision 判断是否运行 State/Trail,因而 WeatherColor-only PLAY 不再依赖 Particle pass,也不会发生双 tick。
|
||
|
||
WeatherColor 在 PLAY 时参与 shared advance;PAUSE 时仅显示当前 frame,`needsRepaint()` 不主动保持连续刷新。Particle 保持 active 时,即使 Timeline PAUSE,仍按 cadence 推进自身 simulation。两层 hidden 时 facade 不再安装 delayed wake-up。
|
||
|
||
`WeatherRuntime.dispose()` 是 map/style-scoped、幂等的 ownership 结束接口:取消 Handler callback,旧 Runnable 被执行时也不会 repaint 或再次 schedule,后续 control API 拒绝或 fail-fast。Test App 在 style reload、离开 REAL WEATHER 与 Activity destroy 前都先 dispose 旧 Runtime。
|