--- id: PLN-0017 ticket: render-all-scene-cache-and-camera-integration title: Plan - FrameComposer Core and Hardware Ownership status: accepted created: 2026-04-14 completed: tags: [gfx, runtime, render, hardware, frame-composer] --- ## Objective Introduce `FrameComposer` as a first-class hardware-side subsystem and move canonical frame orchestration ownership out of `Gfx`. ## Background `DEC-0014` locks `FrameComposer` as the canonical frame orchestration service. The first implementation step is to create the owning type, place it in `hardware/drivers`, and make `Hardware` aggregate it next to `Gfx` without yet completing the full render-path migration. ## Scope ### Included - Create the `FrameComposer` type in `crates/console/prometeu-drivers`. - Define the minimal owned state shape: - active scene binding state; - camera / viewport state; - optional cache; - optional resolver; - owned `SpriteController`. - Aggregate `FrameComposer` inside `Hardware`. - Expose the minimum driver-facing surface required for subsequent plans. ### Excluded - full sprite-model migration - full scene binding implementation - cache refresh application - render-path retirement of `Gfx.render_all()` ## Execution Steps ### Step 1 - Introduce the `FrameComposer` module and owned state **What:** Create `FrameComposer` as a concrete driver-side subsystem. **How:** - Add a new module such as `crates/console/prometeu-drivers/src/frame_composer.rs`. - Define a `FrameComposer` struct with explicit placeholders for: - `active_scene_id` - `active_scene` - `scene_status` - `camera_x_px` - `camera_y_px` - `SceneViewportCache` - `SceneViewportResolver` - `SpriteController` - Keep scene/cache/resolver fields optional where no-scene operation is required. **File(s):** - `crates/console/prometeu-drivers/src/frame_composer.rs` - `crates/console/prometeu-drivers/src/lib.rs` ### Step 2 - Aggregate `FrameComposer` in `Hardware` **What:** Make `Hardware` own `FrameComposer` alongside `Gfx`. **How:** - Extend `Hardware` with a `frame_composer` field. - Wire construction so `FrameComposer` receives the shared bank access it needs for later plans. - Keep ownership boundaries explicit: `FrameComposer` prepares frame state, `Gfx` remains backend. **File(s):** - `crates/console/prometeu-drivers/src/hardware.rs` - `crates/console/prometeu-drivers/src/memory_banks.rs` ### Step 3 - Define the minimum public driver-facing surface **What:** Give the driver layer a stable initial surface for `FrameComposer`. **How:** - Expose minimal constructor and accessor paths. - Do not yet overdesign HAL-facing traits. - Ensure the code compiles with no implicit dependence on `Gfx.render_all()` ownership for frame state. **File(s):** - `crates/console/prometeu-drivers/src/frame_composer.rs` - `crates/console/prometeu-drivers/src/hardware.rs` - `crates/console/prometeu-drivers/src/lib.rs` ## Test Requirements ### Unit Tests - `FrameComposer` can be constructed without a bound scene. - `Hardware` successfully constructs with both `gfx` and `frame_composer`. ### Integration Tests - Shared bank access needed by `FrameComposer` is available through hardware construction. ### Manual Verification - Inspect the resulting type ownership and confirm scene/sprite state is no longer being newly introduced into `Gfx`. ## Acceptance Criteria - [ ] `FrameComposer` exists as a dedicated driver-side subsystem. - [ ] `Hardware` aggregates `FrameComposer` next to `Gfx`. - [ ] `FrameComposer` has explicit owned placeholders for scene/camera/cache/resolver/sprites. - [ ] The build remains green with the new ownership structure in place. ## Dependencies - Source decision: `DEC-0014` ## Risks - Introducing `FrameComposer` with too much behavior too early can blur later migration steps. - Introducing too little owned state can leave ownership ambiguous and force rework in later plans.