implements PLN-0073 render contract specs
This commit is contained in:
parent
2b69be0f11
commit
96a23e5419
@ -1,5 +1,5 @@
|
|||||||
{"type":"meta","next_id":{"DSC":39,"AGD":39,"DEC":31,"PLN":87,"LSN":47,"CLSN":1}}
|
{"type":"meta","next_id":{"DSC":39,"AGD":39,"DEC":31,"PLN":87,"LSN":47,"CLSN":1}}
|
||||||
{"type":"discussion","id":"DSC-0038","status":"in_progress","ticket":"render-frame-packet-boundary","title":"Logical Render Pipelines and Command Packets","created_at":"2026-05-25","updated_at":"2026-05-25","tags":["gfx","renderer","runtime","frame-composer","architecture","ui","pipeline"],"agendas":[{"id":"AGD-0038","file":"AGD-0038-renderframepacket-boundary-for-classic-2d-renderer.md","status":"accepted","created_at":"2026-05-25","updated_at":"2026-05-25"}],"decisions":[{"id":"DEC-0030","file":"DEC-0030-logical-render-pipeline-command-boundary.md","status":"accepted","created_at":"2026-05-25","updated_at":"2026-05-25","ref_agenda":"AGD-0038"}],"plans":[{"id":"PLN-0073","file":"PLN-0073-render-contract-specs.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0074","file":"PLN-0074-hal-render-submission-types.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0075","file":"PLN-0075-rendermanager-core.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0076","file":"PLN-0076-capabilities-and-abi-domain-split.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0077","file":"PLN-0077-composer-buffer-and-game2d-packet.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0078","file":"PLN-0078-classic2d-game-renderer-consumer.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0079","file":"PLN-0079-gfx2d-primitive-domain.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0080","file":"PLN-0080-shell-ui-packet-and-gfxui-domain.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0081","file":"PLN-0081-shell-hub-migration.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0082","file":"PLN-0082-frame-publication-and-present-boundary.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0083","file":"PLN-0083-fade-removal.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0084","file":"PLN-0084-host-debug-overlay-removal.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0085","file":"PLN-0085-pbs-stdlib-and-syscall-declarations.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0086","file":"PLN-0086-end-to-end-render-boundary-validation.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]}],"lessons":[]}
|
{"type":"discussion","id":"DSC-0038","status":"in_progress","ticket":"render-frame-packet-boundary","title":"Logical Render Pipelines and Command Packets","created_at":"2026-05-25","updated_at":"2026-05-25","tags":["gfx","renderer","runtime","frame-composer","architecture","ui","pipeline"],"agendas":[{"id":"AGD-0038","file":"AGD-0038-renderframepacket-boundary-for-classic-2d-renderer.md","status":"accepted","created_at":"2026-05-25","updated_at":"2026-05-25"}],"decisions":[{"id":"DEC-0030","file":"DEC-0030-logical-render-pipeline-command-boundary.md","status":"accepted","created_at":"2026-05-25","updated_at":"2026-05-25","ref_agenda":"AGD-0038"}],"plans":[{"id":"PLN-0073","file":"PLN-0073-render-contract-specs.md","status":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0074","file":"PLN-0074-hal-render-submission-types.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0075","file":"PLN-0075-rendermanager-core.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0076","file":"PLN-0076-capabilities-and-abi-domain-split.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0077","file":"PLN-0077-composer-buffer-and-game2d-packet.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0078","file":"PLN-0078-classic2d-game-renderer-consumer.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0079","file":"PLN-0079-gfx2d-primitive-domain.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0080","file":"PLN-0080-shell-ui-packet-and-gfxui-domain.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0081","file":"PLN-0081-shell-hub-migration.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0082","file":"PLN-0082-frame-publication-and-present-boundary.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0083","file":"PLN-0083-fade-removal.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0084","file":"PLN-0084-host-debug-overlay-removal.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0085","file":"PLN-0085-pbs-stdlib-and-syscall-declarations.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0086","file":"PLN-0086-end-to-end-render-boundary-validation.md","status":"open","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]}],"lessons":[]}
|
||||||
{"type":"discussion","id":"DSC-0035","status":"done","ticket":"task-owned-shell-windows","title":"Agenda - Task-Owned Shell Windows","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","task","window-manager","shell","lifecycle"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0044","file":"discussion/lessons/DSC-0035-task-owned-shell-windows/LSN-0044-task-window-liveness-belongs-to-the-task.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
{"type":"discussion","id":"DSC-0035","status":"done","ticket":"task-owned-shell-windows","title":"Agenda - Task-Owned Shell Windows","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","task","window-manager","shell","lifecycle"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0044","file":"discussion/lessons/DSC-0035-task-owned-shell-windows/LSN-0044-task-window-liveness-belongs-to-the-task.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
||||||
{"type":"discussion","id":"DSC-0034","status":"done","ticket":"system-os-domain-facades","title":"Agenda - SystemOS Domain Facades","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","services","api-surface","lifecycle","fs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0043","file":"discussion/lessons/DSC-0034-system-os-domain-facades/LSN-0043-systemos-domain-facades.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
{"type":"discussion","id":"DSC-0034","status":"done","ticket":"system-os-domain-facades","title":"Agenda - SystemOS Domain Facades","created_at":"2026-05-15","updated_at":"2026-05-15","tags":["runtime","os","services","api-surface","lifecycle","fs"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0043","file":"discussion/lessons/DSC-0034-system-os-domain-facades/LSN-0043-systemos-domain-facades.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]}
|
||||||
{"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":"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":"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":"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":"discussion/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-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":"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":"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":"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":"discussion/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"}]}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
id: PLN-0073
|
id: PLN-0073
|
||||||
ticket: render-frame-packet-boundary
|
ticket: render-frame-packet-boundary
|
||||||
title: Render Contract Specs
|
title: Render Contract Specs
|
||||||
status: open
|
status: done
|
||||||
created: 2026-05-25
|
created: 2026-05-25
|
||||||
ref_decisions: [DEC-0030]
|
ref_decisions: [DEC-0030]
|
||||||
tags: [gfx, renderer, runtime, frame-composer, architecture, ui, pipeline]
|
tags: [gfx, renderer, runtime, frame-composer, architecture, ui, pipeline]
|
||||||
|
|||||||
@ -9,7 +9,29 @@ Didactic companion: [`../learn/mental-model-gfx.md`](../runtime/learn/mental-mod
|
|||||||
|
|
||||||
The **GFX** peripheral is responsible for generating images in PROMETEU.
|
The **GFX** peripheral is responsible for generating images in PROMETEU.
|
||||||
|
|
||||||
It is an explicit 2D graphics device based on:
|
`DEC-0030` defines the current logical render boundary. PROMETEU render
|
||||||
|
production is split from render implementation:
|
||||||
|
|
||||||
|
```text
|
||||||
|
domain buffers during logical frame
|
||||||
|
-> RenderManager closes buffers
|
||||||
|
-> RenderSubmission snapshot
|
||||||
|
-> render surface / implementation consumes submission
|
||||||
|
-> RGBA8888 surface publication
|
||||||
|
```
|
||||||
|
|
||||||
|
The GFX peripheral remains the classic local raster implementation for
|
||||||
|
PROMETEU's 2D output. Logical render APIs do not target `Gfx` or the
|
||||||
|
framebuffer directly.
|
||||||
|
|
||||||
|
`RenderSubmission` is the closed snapshot passed across the render boundary. It
|
||||||
|
MUST contain a frame id, the active app mode, and one typed packet:
|
||||||
|
`Game2DFramePacket` for `AppMode::Game` or `ShellUiFramePacket` for
|
||||||
|
`AppMode::Shell`. Once closed, producers MUST treat the submission as
|
||||||
|
immutable. The runtime backpressure policy is latest-complete-submission-wins;
|
||||||
|
it MUST NOT accumulate an unbounded frame queue.
|
||||||
|
|
||||||
|
The current 2D graphics model is based on:
|
||||||
|
|
||||||
- framebuffer
|
- framebuffer
|
||||||
- tilemaps
|
- tilemaps
|
||||||
@ -48,19 +70,19 @@ palette, host presentation, or compatibility contract.
|
|||||||
|
|
||||||
## 3. Double Buffering
|
## 3. Double Buffering
|
||||||
|
|
||||||
The GFX maintains two buffers:
|
The render surface implementation maintains the concrete buffers needed to
|
||||||
|
publish a frame. The classic software implementation uses:
|
||||||
|
|
||||||
- **Back Buffer** — where the frame is built
|
- **Back Buffer** — where the frame is built
|
||||||
- **Front Buffer** — where the frame is displayed
|
- **Front Buffer** — where the frame is displayed
|
||||||
|
|
||||||
Per-frame flow:
|
Per-frame flow:
|
||||||
|
|
||||||
1. The system prepares the logical frame
|
1. Game or Shell code mutates mode-specific domain buffers during the logical frame.
|
||||||
2. Canonical game composition is rendered into the back buffer
|
2. `RenderManager` closes the active buffers into an immutable `RenderSubmission`.
|
||||||
3. Deferred final overlay/debug primitives are drained on top of the completed game frame
|
3. The render surface implementation consumes the submission and rasterizes to its back buffer.
|
||||||
4. Calls `present()`
|
4. The render surface publishes the completed RGBA8888 surface.
|
||||||
5. Buffers are swapped
|
5. The host displays the published surface.
|
||||||
6. The host displays the front buffer
|
|
||||||
|
|
||||||
This guarantees:
|
This guarantees:
|
||||||
|
|
||||||
@ -192,14 +214,20 @@ Access:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 10. Canonical Game Projection to the Back Buffer
|
## 10. Canonical Game Projection
|
||||||
|
|
||||||
For each frame:
|
Game mode uses a typed Game 2D submission. `composer.*` owns high-level Game 2D
|
||||||
|
frame composition: scene binding, camera, sprites, HUD, and frame orchestration.
|
||||||
|
`gfx2d.*` owns Game 2D primitives only. Both domains are mutable while the
|
||||||
|
logical frame is being produced and are closed by `RenderManager` into a
|
||||||
|
`Game2DFramePacket`.
|
||||||
|
|
||||||
|
For each Game 2D packet:
|
||||||
|
|
||||||
1. For each Tile Layer, in order:
|
1. For each Tile Layer, in order:
|
||||||
- Rasterize visible tiles from the cache
|
- Rasterize visible tiles from the cache
|
||||||
- Apply scroll, flip, and transparency
|
- Apply scroll, flip, and transparency
|
||||||
- Write to the back buffer
|
- Write to the render surface's working buffer
|
||||||
|
|
||||||
2. Draw sprites:
|
2. Draw sprites:
|
||||||
- With priority between layers
|
- With priority between layers
|
||||||
@ -207,9 +235,11 @@ For each frame:
|
|||||||
|
|
||||||
3. Draw HUD layer last
|
3. Draw HUD layer last
|
||||||
|
|
||||||
This section describes only the canonical game composition path.
|
4. Draw buffered `gfx2d.*` primitives according to the Game 2D packet contract.
|
||||||
|
|
||||||
`gfx.*` primitives such as `draw_text`, `draw_line`, and `draw_disc` are not part of this canonical game projection order. In v1 they belong to a deferred final overlay/debug stage that is drained after canonical game composition is complete.
|
This section describes only the Game 2D packet rendering path. Shell/system UI
|
||||||
|
uses `gfxui.*` and `ShellUiFramePacket`; it is never part of Game HUD or
|
||||||
|
`composer.*`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -227,15 +257,15 @@ Base order:
|
|||||||
4. Tile Layer 3
|
4. Tile Layer 3
|
||||||
5. Sprites (by priority between layers)
|
5. Sprites (by priority between layers)
|
||||||
6. HUD Layer
|
6. HUD Layer
|
||||||
7. Scene Fade
|
7. Buffered `gfx2d.*` Game primitives
|
||||||
8. HUD Fade
|
|
||||||
9. Deferred `gfx.*` overlay/debug primitives
|
|
||||||
|
|
||||||
Normative boundary:
|
Normative boundary:
|
||||||
|
|
||||||
- Items 1 through 8 belong to canonical game-frame composition.
|
- Items 1 through 6 belong to `composer.*` Game-frame composition.
|
||||||
- Item 9 is a separate overlay/debug stage.
|
- Item 7 belongs to `gfx2d.*`.
|
||||||
- Deferred `gfx.*` primitives MUST NOT be interpreted as scene, sprite, or canonical HUD content.
|
- `gfx2d.*` primitives MUST NOT be interpreted as scene, sprite, camera, HUD,
|
||||||
|
or frame orchestration.
|
||||||
|
- Shell/system UI belongs to `gfxui.*` and `ShellUiFramePacket`, not Game HUD.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -287,7 +317,8 @@ Everything is:
|
|||||||
|
|
||||||
- Blending occurs during drawing
|
- Blending occurs during drawing
|
||||||
- For canonical game composition, the result goes to the back buffer during composition
|
- For canonical game composition, the result goes to the back buffer during composition
|
||||||
- For deferred `gfx.*` overlay/debug primitives, the result is applied during the final overlay/debug drain stage
|
- For `gfx2d.*` and `gfxui.*` primitives, the result is applied when the render
|
||||||
|
surface consumes the closed packet for the active app mode
|
||||||
- There is no automatic GPU-style post-processing pipeline
|
- There is no automatic GPU-style post-processing pipeline
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -301,6 +332,7 @@ By design:
|
|||||||
- HDR
|
- HDR
|
||||||
- Gamma correction
|
- Gamma correction
|
||||||
- RGB565 compatibility framebuffers
|
- RGB565 compatibility framebuffers
|
||||||
|
- fade fields, fade syscalls, or fade packet members
|
||||||
- multi-format backend selection
|
- multi-format backend selection
|
||||||
- render-thread ownership as part of this contract
|
- render-thread ownership as part of this contract
|
||||||
|
|
||||||
@ -318,104 +350,24 @@ By design:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 17. Special PostFX — Fade (Scene and HUD)
|
## 17. Transitions and Removed Fade Contract
|
||||||
|
|
||||||
PROMETEU supports **gradual fade** as a special PostFX, with two independent
|
The previous special fade model is not part of the canonical render contract.
|
||||||
controls:
|
Current render packets, syscalls, and ABI domains MUST NOT expose scene fade,
|
||||||
|
HUD fade, fade levels, fade colors, or equivalent inherited fade state.
|
||||||
|
|
||||||
- **Scene Fade**: affects the entire scene (Tile Layers 0–3 + Sprites)
|
Future visual transitions between Shell and Game belong to `RenderManager`.
|
||||||
- **HUD Fade**: affects only the HUD Layer (always composed last)
|
They are not owned by `composer.*`, `gfx2d.*`, `gfxui.*`, `Game2DFramePacket`,
|
||||||
|
or `ShellUiFramePacket`.
|
||||||
In v1, deferred `gfx.*` overlay/debug primitives are drained after both fades and therefore are not themselves part of scene or HUD fade application.
|
|
||||||
|
|
||||||
The fade uses a **discrete integer level** (0..31), which in practice produces an
|
|
||||||
"almost continuous" visual result in Prometeu's `480x270` pixel-art framebuffer.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 17.1 Fade Representation
|
|
||||||
|
|
||||||
Each fade is represented by:
|
|
||||||
|
|
||||||
- `fade_level: u8` in the range **[0..31]**
|
|
||||||
- `0` → fully replaced by the fade color
|
|
||||||
- `31` → fully visible (no fade)
|
|
||||||
- `fade_color: RGBA8888`
|
|
||||||
- color the image will be blended into
|
|
||||||
|
|
||||||
Registers:
|
|
||||||
|
|
||||||
- `SCENE_FADE_LEVEL` (0..31)
|
|
||||||
- `SCENE_FADE_COLOR` (RGBA8888)
|
|
||||||
- `HUD_FADE_LEVEL` (0..31)
|
|
||||||
- `HUD_FADE_COLOR` (RGBA8888)
|
|
||||||
|
|
||||||
Common cases:
|
|
||||||
|
|
||||||
- Fade-out: `fade_color = BLACK`
|
|
||||||
- Flash/teleport: `fade_color = WHITE`
|
|
||||||
- Special effects: any RGBA8888 color
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 17.2 Fade Operation (Blending with Arbitrary Color)
|
|
||||||
|
|
||||||
For each RGBA8888 pixel `src` and fade color `fc`, the final pixel `dst` is calculated per channel.
|
|
||||||
|
|
||||||
1) Extract components:
|
|
||||||
|
|
||||||
- `src_r8`, `src_g8`, `src_b8`, `src_a8`
|
|
||||||
- `fc_r8`, `fc_g8`, `fc_b8`, `fc_a8`
|
|
||||||
|
|
||||||
2) Apply integer blending:
|
|
||||||
|
|
||||||
```
|
|
||||||
src_weight = fade_level // 0..31
|
|
||||||
fc_weight = 31 - fade_level
|
|
||||||
|
|
||||||
r8 = (src_r8 * src_weight + fc_r8 * fc_weight) / 31
|
|
||||||
g8 = (src_g8 * src_weight + fc_g8 * fc_weight) / 31
|
|
||||||
b8 = (src_b8 * src_weight + fc_b8 * fc_weight) / 31
|
|
||||||
a8 = (src_a8 * src_weight + fc_a8 * fc_weight) / 31
|
|
||||||
```
|
|
||||||
- `src_r8`, `src_g8`, `src_b8`, `src_a8`
|
|
||||||
- `fc_r8`, `fc_g8`, `fc_b8`, `fc_a8`
|
|
||||||
|
|
||||||
3) Repack:
|
|
||||||
|
|
||||||
```
|
|
||||||
dst = pack_rgba8888_rgba(r8, g8, b8, a8)
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
- Deterministic operation
|
|
||||||
- Integers only
|
|
||||||
- Can be optimized via LUT
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### 17.3 Order of Application in the Frame
|
|
||||||
|
|
||||||
The frame composition follows this order:
|
|
||||||
|
|
||||||
1. Rasterize **Tile Layers 0–3** → Back Buffer
|
|
||||||
2. Rasterize **Sprites** according to priority
|
|
||||||
3. (Optional) Extra pipeline (Emission/Light/Glow etc.)
|
|
||||||
4. Apply **Scene Fade** using:
|
|
||||||
- `SCENE_FADE_LEVEL`
|
|
||||||
- `SCENE_FADE_COLOR`
|
|
||||||
5. Rasterize **HUD Layer**
|
|
||||||
6. Apply **HUD Fade** using:
|
|
||||||
- `HUD_FADE_LEVEL`
|
|
||||||
- `HUD_FADE_COLOR`
|
|
||||||
7. `present()`
|
|
||||||
|
|
||||||
Rules:
|
Rules:
|
||||||
|
|
||||||
- Scene Fade never affects the HUD
|
- render domain packets MUST NOT contain fade fields;
|
||||||
- HUD Fade never affects the scene
|
- public render syscalls MUST NOT expose fade controls;
|
||||||
|
- render implementations MUST NOT treat fade as an inherited post-processing
|
||||||
|
habit;
|
||||||
|
- transition work requires an explicit `RenderManager` contract or a later
|
||||||
|
decision.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -570,8 +522,13 @@ The system can measure:
|
|||||||
|
|
||||||
Graphics-related public ABI in v1 is split between:
|
Graphics-related public ABI in v1 is split between:
|
||||||
|
|
||||||
- `gfx.*` for direct drawing/backend-oriented operations;
|
- `composer.*` for Game 2D high-level frame composition;
|
||||||
- `composer.*` for frame orchestration operations.
|
- `gfx2d.*` for Game 2D primitives only;
|
||||||
|
- `gfxui.*` for Shell UI primitives only.
|
||||||
|
|
||||||
|
`composer.*` and `gfx2d.*` are available to `AppMode::Game`.
|
||||||
|
`gfxui.*` is available to `AppMode::Shell`. Renderers and capabilities may
|
||||||
|
differ by app mode.
|
||||||
|
|
||||||
Only operations with real operational rejection paths return explicit status values.
|
Only operations with real operational rejection paths return explicit status values.
|
||||||
|
|
||||||
@ -585,29 +542,32 @@ Fault boundary:
|
|||||||
|
|
||||||
| Syscall | Return | Policy basis |
|
| Syscall | Return | Policy basis |
|
||||||
| ----------------------- | ------------- | --------------------------------------------------- |
|
| ----------------------- | ------------- | --------------------------------------------------- |
|
||||||
| `gfx.clear` | `void` | no real operational failure path in v1 |
|
| `gfx2d.clear` | `void` | no real operational failure path in v1 |
|
||||||
| `gfx.fill_rect` | `void` | no real operational failure path in v1 |
|
| `gfx2d.fill_rect` | `void` | no real operational failure path in v1 |
|
||||||
| `gfx.draw_line` | `void` | no real operational failure path in v1 |
|
| `gfx2d.draw_line` | `void` | no real operational failure path in v1 |
|
||||||
| `gfx.draw_circle` | `void` | no real operational failure path in v1 |
|
| `gfx2d.draw_circle` | `void` | no real operational failure path in v1 |
|
||||||
| `gfx.draw_disc` | `void` | no real operational failure path in v1 |
|
| `gfx2d.draw_disc` | `void` | no real operational failure path in v1 |
|
||||||
| `gfx.draw_square` | `void` | no real operational failure path in v1 |
|
| `gfx2d.draw_square` | `void` | no real operational failure path in v1 |
|
||||||
| `gfx.draw_text` | `void` | no real operational failure path in v1 |
|
| `gfx2d.draw_text` | `void` | no real operational failure path in v1 |
|
||||||
|
| `gfxui.*` primitives | `void` | no real operational failure path in v1 |
|
||||||
| `composer.bind_scene` | `status:int` | status-returning API, but missing scene glyph dependencies are fatal runtime errors |
|
| `composer.bind_scene` | `status:int` | status-returning API, but missing scene glyph dependencies are fatal runtime errors |
|
||||||
| `composer.unbind_scene` | `status:int` | explicit orchestration-domain operational result |
|
| `composer.unbind_scene` | `status:int` | explicit orchestration-domain operational result |
|
||||||
| `composer.set_camera` | `void` | no real operational failure path in v1 |
|
| `composer.set_camera` | `void` | no real operational failure path in v1 |
|
||||||
| `composer.emit_sprite` | `status:int` | explicit orchestration-domain operational rejection |
|
| `composer.emit_sprite` | `status:int` | explicit orchestration-domain operational rejection |
|
||||||
|
|
||||||
### 19.1.a Deferred overlay/debug semantics for `gfx.*`
|
### 19.1.a Primitive domain semantics
|
||||||
|
|
||||||
The public `gfx.*` primitive family remains valid in v1, but its stable operational meaning is:
|
The primitive domains have stable operational meaning:
|
||||||
|
|
||||||
- deferred final overlay/debug composition;
|
- `gfx2d.*` is Game 2D primitive command buffering;
|
||||||
- screen-space and pipeline-agnostic relative to `composer.*`;
|
- `gfx2d.*` is screen-space and primitive-only relative to `composer.*`;
|
||||||
- outside `FrameComposer`;
|
- `gfx2d.*` is outside scene, camera, sprites, HUD, and Game 2D frame orchestration;
|
||||||
- above scene, sprites, and canonical HUD;
|
- `gfxui.*` is Shell UI primitive command buffering;
|
||||||
- drained after `hud_fade`.
|
- `gfxui.*` does not contain widget or layout policy.
|
||||||
|
|
||||||
This means callers MUST NOT rely on stable immediate writes to the working back buffer as the public contract for `gfx.draw_text(...)` or sibling primitives.
|
Callers MUST NOT rely on stable immediate writes to the working back buffer as
|
||||||
|
the public contract for primitive drawing. Primitive calls mutate domain command
|
||||||
|
buffers that close into the active typed submission.
|
||||||
|
|
||||||
### 19.1.b Scene dependency fatal boundary
|
### 19.1.b Scene dependency fatal boundary
|
||||||
|
|
||||||
|
|||||||
@ -116,26 +116,26 @@ Hardware differences:
|
|||||||
|
|
||||||
The graphics system:
|
The graphics system:
|
||||||
|
|
||||||
- operates on a logical RGBA8888 framebuffer
|
- produces typed logical render submissions that render to RGBA8888 output
|
||||||
- uses an indexed palette
|
- uses an indexed palette
|
||||||
- does not depend on a specific GPU
|
- does not depend on a specific GPU
|
||||||
|
|
||||||
The platform layer:
|
The platform layer:
|
||||||
|
|
||||||
- only displays the framebuffer
|
- consumes closed render submissions through a render-surface implementation
|
||||||
- does not reinterpret graphics commands
|
|
||||||
- **may overlay technical HUDs without modifying the logical framebuffer**
|
- **may overlay technical HUDs without modifying the logical framebuffer**
|
||||||
- may transport the logical framebuffer into a host presentation surface where a host-only overlay layer is composed
|
- may transport published RGBA8888 output into a host presentation surface where a host-only overlay layer is composed
|
||||||
|
|
||||||
The host presentation layer MUST treat RGBA8888 as the canonical logical
|
The host presentation layer MUST treat RGBA8888 as the canonical logical
|
||||||
framebuffer format. RGB565 conversion is not part of the normal host
|
framebuffer format. RGB565 conversion is not part of the normal host
|
||||||
presentation contract.
|
presentation contract.
|
||||||
|
|
||||||
Host presentation SHOULD be driven by published logical frames and explicit host-owned invalidation, not by perpetual redraw polling.
|
Host presentation SHOULD be driven by published render submissions and explicit
|
||||||
|
host-owned invalidation, not by perpetual redraw polling.
|
||||||
|
|
||||||
In particular:
|
In particular:
|
||||||
|
|
||||||
- a stable logical frame MAY remain visible across multiple host wakeups without recomposition;
|
- a stable published submission MAY remain visible across multiple host wakeups without recomposition;
|
||||||
- a host MAY redraw the same logical frame again when its own surface is invalidated by resize, expose, or host-only overlay/debug changes;
|
- a host MAY redraw the same logical frame again when its own surface is invalidated by resize, expose, or host-only overlay/debug changes;
|
||||||
- a host MUST NOT invent intermediate logical frames or require continuous redraw merely to discover whether a new logical frame exists.
|
- a host MUST NOT invent intermediate logical frames or require continuous redraw merely to discover whether a new logical frame exists.
|
||||||
|
|
||||||
|
|||||||
@ -220,29 +220,78 @@ For `asset.load`:
|
|||||||
- JSON-on-the-wire bank inspection payloads are not valid public ABI;
|
- JSON-on-the-wire bank inspection payloads are not valid public ABI;
|
||||||
- `bank.info` returns stack values, not textual structured payloads.
|
- `bank.info` returns stack values, not textual structured payloads.
|
||||||
|
|
||||||
### GFX surface (`gfx`, v1)
|
### Render surfaces (`composer`, `gfx2d`, `gfxui`, v1)
|
||||||
|
|
||||||
The public GFX ABI uses format-neutral operation names. API and syscall names
|
`DEC-0030` splits logical render production from render implementation. Public
|
||||||
MUST NOT encode RGB565 or any other pixel format suffix.
|
render syscalls mutate app-mode-specific domain buffers. They do not directly
|
||||||
|
publish a framebuffer and do not call host presentation APIs.
|
||||||
|
|
||||||
|
The canonical flow is:
|
||||||
|
|
||||||
|
```text
|
||||||
|
domain buffers during logical frame
|
||||||
|
-> RenderManager closes buffers
|
||||||
|
-> RenderSubmission snapshot
|
||||||
|
-> render surface / implementation consumes submission
|
||||||
|
-> RGBA8888 surface publication
|
||||||
|
```
|
||||||
|
|
||||||
|
`RenderSubmission` is a typed closed snapshot containing `frame_id`, `app_mode`,
|
||||||
|
and exactly one packet: `Game2DFramePacket` for `AppMode::Game` or
|
||||||
|
`ShellUiFramePacket` for `AppMode::Shell`. Producers may mutate domain buffers
|
||||||
|
before closure only. Once `RenderManager` closes a submission, producers MUST
|
||||||
|
NOT mutate it. Backpressure is latest-complete-submission-wins; the runtime
|
||||||
|
MUST NOT expose an unbounded submission queue as part of the ABI.
|
||||||
|
|
||||||
|
Render API and syscall names MUST NOT encode RGB565 or any other pixel format
|
||||||
|
suffix.
|
||||||
|
|
||||||
|
#### Game 2D primitive surface (`gfx2d`, v1)
|
||||||
|
|
||||||
|
The `gfx2d` module is a Game profile primitive surface. It is limited to Game
|
||||||
|
2D primitive commands and does not own scene, camera, sprites, HUD, or frame
|
||||||
|
orchestration.
|
||||||
|
|
||||||
Canonical operations in v1 include:
|
Canonical operations in v1 include:
|
||||||
|
|
||||||
- `gfx.clear(color) -> void`
|
- `gfx2d.clear(color) -> void`
|
||||||
- `gfx.fill_rect(x, y, w, h, color) -> void`
|
- `gfx2d.fill_rect(x, y, w, h, color) -> void`
|
||||||
- `gfx.draw_line(x0, y0, x1, y1, color) -> void`
|
- `gfx2d.draw_line(x0, y0, x1, y1, color) -> void`
|
||||||
- `gfx.draw_circle(x, y, radius, color) -> void`
|
- `gfx2d.draw_circle(x, y, radius, color) -> void`
|
||||||
- `gfx.draw_disc(x, y, radius, color) -> void`
|
- `gfx2d.draw_disc(x, y, radius, color) -> void`
|
||||||
- `gfx.draw_square(x, y, size, color) -> void`
|
- `gfx2d.draw_square(x, y, size, color) -> void`
|
||||||
- `gfx.draw_text(x, y, text, color) -> void`
|
- `gfx2d.draw_text(x, y, text, color) -> void`
|
||||||
|
|
||||||
|
#### Shell UI primitive surface (`gfxui`, v1)
|
||||||
|
|
||||||
|
The `gfxui` module is a Shell profile primitive surface. It contains Shell UI
|
||||||
|
primitive commands only. Widget and layout policy belongs in Shell/UI code or
|
||||||
|
stdlib code, not in the host/render-surface implementation.
|
||||||
|
|
||||||
|
Canonical operations in v1 include primitive shapes equivalent to the subset
|
||||||
|
needed by Shell UI:
|
||||||
|
|
||||||
|
- `gfxui.clear(color) -> void`
|
||||||
|
- `gfxui.fill_rect(x, y, w, h, color) -> void`
|
||||||
|
- `gfxui.draw_line(x0, y0, x1, y1, color) -> void`
|
||||||
|
- `gfxui.draw_circle(x, y, radius, color) -> void`
|
||||||
|
- `gfxui.draw_disc(x, y, radius, color) -> void`
|
||||||
|
- `gfxui.draw_square(x, y, size, color) -> void`
|
||||||
|
- `gfxui.draw_text(x, y, text, color) -> void`
|
||||||
|
|
||||||
Rules:
|
Rules:
|
||||||
|
|
||||||
- `color` arguments are packed RGBA8888 values using RGBA channel order.
|
- `color` arguments are packed RGBA8888 values using RGBA channel order.
|
||||||
- RGB565 raw values are not a public ABI contract.
|
- RGB565 raw values are not a public ABI contract.
|
||||||
- `Gfx*565` syscall names and `gfx.*_565` canonical identities are not valid
|
- `Gfx*565` syscall names and `gfx*.*_565` canonical identities are not valid
|
||||||
current ABI.
|
current ABI.
|
||||||
- The runtime framebuffer exposed across the host boundary is RGBA8888, not
|
- The runtime framebuffer exposed across the host boundary is RGBA8888, not
|
||||||
`u16` RGB565.
|
`u16` RGB565.
|
||||||
|
- The old primitive `gfx.*` ABI is not the canonical render domain. PBS stdlibs
|
||||||
|
may expose ergonomic high-level names, but generated host bindings must map
|
||||||
|
to `gfx2d.*` in Game mode or `gfxui.*` in Shell mode.
|
||||||
|
- Render packets and public render syscalls MUST NOT expose fade fields or fade
|
||||||
|
controls.
|
||||||
|
|
||||||
### Composition surface (`composer`, v1)
|
### Composition surface (`composer`, v1)
|
||||||
|
|
||||||
@ -251,6 +300,11 @@ The canonical frame-orchestration public ABI uses module `composer`.
|
|||||||
The `composer` module is a game profile surface. It is not inherited by
|
The `composer` module is a game profile surface. It is not inherited by
|
||||||
`System` profile apps as their public UI/composition API.
|
`System` profile apps as their public UI/composition API.
|
||||||
|
|
||||||
|
`composer` owns Game 2D high-level frame composition: scene binding, camera,
|
||||||
|
sprites, HUD, and Game 2D frame orchestration. It closes into a
|
||||||
|
`Game2DFramePacket` through `RenderManager`; it does not publish or present a
|
||||||
|
framebuffer directly.
|
||||||
|
|
||||||
Canonical operations in v1 are:
|
Canonical operations in v1 are:
|
||||||
|
|
||||||
- `composer.bind_scene(bank_id) -> (status)`
|
- `composer.bind_scene(bank_id) -> (status)`
|
||||||
@ -264,6 +318,8 @@ For mutating composer operations:
|
|||||||
- `bind_scene`, `unbind_scene`, and `emit_sprite` are status-returning;
|
- `bind_scene`, `unbind_scene`, and `emit_sprite` are status-returning;
|
||||||
- `set_camera` remains `void` in v1;
|
- `set_camera` remains `void` in v1;
|
||||||
- no caller-provided sprite index or `active` flag is part of the canonical contract.
|
- no caller-provided sprite index or `active` flag is part of the canonical contract.
|
||||||
|
- no fade level, fade color, or transition control is part of the canonical
|
||||||
|
composer ABI.
|
||||||
|
|
||||||
Fatal boundary clarification for `bind_scene`:
|
Fatal boundary clarification for `bind_scene`:
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user