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":"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-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"}]}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
id: PLN-0073
|
||||
ticket: render-frame-packet-boundary
|
||||
title: Render Contract Specs
|
||||
status: open
|
||||
status: done
|
||||
created: 2026-05-25
|
||||
ref_decisions: [DEC-0030]
|
||||
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.
|
||||
|
||||
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
|
||||
- tilemaps
|
||||
@ -48,19 +70,19 @@ palette, host presentation, or compatibility contract.
|
||||
|
||||
## 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
|
||||
- **Front Buffer** — where the frame is displayed
|
||||
|
||||
Per-frame flow:
|
||||
|
||||
1. The system prepares the logical frame
|
||||
2. Canonical game composition is rendered into the back buffer
|
||||
3. Deferred final overlay/debug primitives are drained on top of the completed game frame
|
||||
4. Calls `present()`
|
||||
5. Buffers are swapped
|
||||
6. The host displays the front buffer
|
||||
1. Game or Shell code mutates mode-specific domain buffers during the logical frame.
|
||||
2. `RenderManager` closes the active buffers into an immutable `RenderSubmission`.
|
||||
3. The render surface implementation consumes the submission and rasterizes to its back buffer.
|
||||
4. The render surface publishes the completed RGBA8888 surface.
|
||||
5. The host displays the published surface.
|
||||
|
||||
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:
|
||||
- Rasterize visible tiles from the cache
|
||||
- Apply scroll, flip, and transparency
|
||||
- Write to the back buffer
|
||||
- Write to the render surface's working buffer
|
||||
|
||||
2. Draw sprites:
|
||||
- With priority between layers
|
||||
@ -207,9 +235,11 @@ For each frame:
|
||||
|
||||
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
|
||||
5. Sprites (by priority between layers)
|
||||
6. HUD Layer
|
||||
7. Scene Fade
|
||||
8. HUD Fade
|
||||
9. Deferred `gfx.*` overlay/debug primitives
|
||||
7. Buffered `gfx2d.*` Game primitives
|
||||
|
||||
Normative boundary:
|
||||
|
||||
- Items 1 through 8 belong to canonical game-frame composition.
|
||||
- Item 9 is a separate overlay/debug stage.
|
||||
- Deferred `gfx.*` primitives MUST NOT be interpreted as scene, sprite, or canonical HUD content.
|
||||
- Items 1 through 6 belong to `composer.*` Game-frame composition.
|
||||
- Item 7 belongs to `gfx2d.*`.
|
||||
- `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
|
||||
- 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
|
||||
|
||||
---
|
||||
@ -301,6 +332,7 @@ By design:
|
||||
- HDR
|
||||
- Gamma correction
|
||||
- RGB565 compatibility framebuffers
|
||||
- fade fields, fade syscalls, or fade packet members
|
||||
- multi-format backend selection
|
||||
- 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
|
||||
controls:
|
||||
The previous special fade model is not part of the canonical render contract.
|
||||
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)
|
||||
- **HUD Fade**: affects only the HUD Layer (always composed last)
|
||||
|
||||
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()`
|
||||
Future visual transitions between Shell and Game belong to `RenderManager`.
|
||||
They are not owned by `composer.*`, `gfx2d.*`, `gfxui.*`, `Game2DFramePacket`,
|
||||
or `ShellUiFramePacket`.
|
||||
|
||||
Rules:
|
||||
|
||||
- Scene Fade never affects the HUD
|
||||
- HUD Fade never affects the scene
|
||||
- render domain packets MUST NOT contain fade fields;
|
||||
- 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:
|
||||
|
||||
- `gfx.*` for direct drawing/backend-oriented operations;
|
||||
- `composer.*` for frame orchestration operations.
|
||||
- `composer.*` for Game 2D high-level frame composition;
|
||||
- `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.
|
||||
|
||||
@ -585,29 +542,32 @@ Fault boundary:
|
||||
|
||||
| Syscall | Return | Policy basis |
|
||||
| ----------------------- | ------------- | --------------------------------------------------- |
|
||||
| `gfx.clear` | `void` | no real operational failure path in v1 |
|
||||
| `gfx.fill_rect` | `void` | no real operational failure path in v1 |
|
||||
| `gfx.draw_line` | `void` | no real operational failure path in v1 |
|
||||
| `gfx.draw_circle` | `void` | no real operational failure path in v1 |
|
||||
| `gfx.draw_disc` | `void` | no real operational failure path in v1 |
|
||||
| `gfx.draw_square` | `void` | no real operational failure path in v1 |
|
||||
| `gfx.draw_text` | `void` | no real operational failure path in v1 |
|
||||
| `gfx2d.clear` | `void` | no real operational failure path in v1 |
|
||||
| `gfx2d.fill_rect` | `void` | no real operational failure path in v1 |
|
||||
| `gfx2d.draw_line` | `void` | no real operational failure path in v1 |
|
||||
| `gfx2d.draw_circle` | `void` | no real operational failure path in v1 |
|
||||
| `gfx2d.draw_disc` | `void` | no real operational failure path in v1 |
|
||||
| `gfx2d.draw_square` | `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.unbind_scene` | `status:int` | explicit orchestration-domain operational result |
|
||||
| `composer.set_camera` | `void` | no real operational failure path in v1 |
|
||||
| `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;
|
||||
- screen-space and pipeline-agnostic relative to `composer.*`;
|
||||
- outside `FrameComposer`;
|
||||
- above scene, sprites, and canonical HUD;
|
||||
- drained after `hud_fade`.
|
||||
- `gfx2d.*` is Game 2D primitive command buffering;
|
||||
- `gfx2d.*` is screen-space and primitive-only relative to `composer.*`;
|
||||
- `gfx2d.*` is outside scene, camera, sprites, HUD, and Game 2D frame orchestration;
|
||||
- `gfxui.*` is Shell UI primitive command buffering;
|
||||
- `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
|
||||
|
||||
|
||||
@ -116,26 +116,26 @@ Hardware differences:
|
||||
|
||||
The graphics system:
|
||||
|
||||
- operates on a logical RGBA8888 framebuffer
|
||||
- produces typed logical render submissions that render to RGBA8888 output
|
||||
- uses an indexed palette
|
||||
- does not depend on a specific GPU
|
||||
|
||||
The platform layer:
|
||||
|
||||
- only displays the framebuffer
|
||||
- does not reinterpret graphics commands
|
||||
- consumes closed render submissions through a render-surface implementation
|
||||
- **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
|
||||
framebuffer format. RGB565 conversion is not part of the normal host
|
||||
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:
|
||||
|
||||
- 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 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;
|
||||
- `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
|
||||
MUST NOT encode RGB565 or any other pixel format suffix.
|
||||
`DEC-0030` splits logical render production from render implementation. Public
|
||||
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:
|
||||
|
||||
- `gfx.clear(color) -> void`
|
||||
- `gfx.fill_rect(x, y, w, h, color) -> void`
|
||||
- `gfx.draw_line(x0, y0, x1, y1, color) -> void`
|
||||
- `gfx.draw_circle(x, y, radius, color) -> void`
|
||||
- `gfx.draw_disc(x, y, radius, color) -> void`
|
||||
- `gfx.draw_square(x, y, size, color) -> void`
|
||||
- `gfx.draw_text(x, y, text, color) -> void`
|
||||
- `gfx2d.clear(color) -> void`
|
||||
- `gfx2d.fill_rect(x, y, w, h, color) -> void`
|
||||
- `gfx2d.draw_line(x0, y0, x1, y1, color) -> void`
|
||||
- `gfx2d.draw_circle(x, y, radius, color) -> void`
|
||||
- `gfx2d.draw_disc(x, y, radius, color) -> void`
|
||||
- `gfx2d.draw_square(x, y, size, 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:
|
||||
|
||||
- `color` arguments are packed RGBA8888 values using RGBA channel order.
|
||||
- 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.
|
||||
- The runtime framebuffer exposed across the host boundary is RGBA8888, not
|
||||
`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)
|
||||
|
||||
@ -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
|
||||
`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:
|
||||
|
||||
- `composer.bind_scene(bank_id) -> (status)`
|
||||
@ -264,6 +318,8 @@ For mutating composer operations:
|
||||
- `bind_scene`, `unbind_scene`, and `emit_sprite` are status-returning;
|
||||
- `set_camera` remains `void` in v1;
|
||||
- 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`:
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user