diff --git a/discussion/index.ndjson b/discussion/index.ndjson index 57896bbc..68d5cd88 100644 --- a/discussion/index.ndjson +++ b/discussion/index.ndjson @@ -35,4 +35,4 @@ {"type":"discussion","id":"DSC-0032","status":"done","ticket":"system-os-lifecycle-process-task-contract","title":"Agenda - SystemOS Lifecycle, Process and Task Contract","created_at":"2026-05-14","updated_at":"2026-05-15","tags":["runtime","os","lifecycle","process","task","shell","firmware"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0041","file":"discussion/lessons/DSC-0032-system-os-lifecycle-process-task-contract/LSN-0041-systemos-lifecycle-authority.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]} {"type":"discussion","id":"DSC-0033","status":"done","ticket":"system-os-service-ownership-and-module-layout","title":"Agenda - SystemOS Service Ownership and Module Layout","created_at":"2026-05-14","updated_at":"2026-05-15","tags":["runtime","os","services","module-layout","vm","window-manager","logging"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0042","file":"discussion/lessons/DSC-0033-system-os-service-ownership-and-module-layout/LSN-0042-systemos-service-ownership-boundary.md","status":"done","created_at":"2026-05-15","updated_at":"2026-05-15"}]} {"type":"discussion","id":"DSC-0036","status":"done","ticket":"prometeu-hub-ui-direction","title":"Agenda - Prometeu Hub UI Direction","created_at":"2026-05-15","updated_at":"2026-05-22","tags":["hub","ui","shell","system-apps","lifecycle","design-system"],"agendas":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0045","file":"discussion/lessons/DSC-0036-prometeu-hub-ui-direction/LSN-0045-hub-ui-slices-should-prove-os-boundaries.md","status":"done","created_at":"2026-05-22","updated_at":"2026-05-22"}]} -{"type":"discussion","id":"DSC-0037","status":"in_progress","ticket":"rgba8888-framebuffer-and-pixel-format-direction","title":"Agenda - RGBA8888 Framebuffer and Pixel Format Direction","created_at":"2026-05-22","updated_at":"2026-05-23","tags":["gfx","framebuffer","rgb565","rgba8888","renderer","assets","host","backend"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-rgba8888-framebuffer-and-pixel-format-direction.md","status":"accepted","created_at":"2026-05-22","updated_at":"2026-05-23"}],"decisions":[{"id":"DEC-0029","file":"DEC-0029-rgba8888-runtime-pixel-format-contract.md","status":"accepted","created_at":"2026-05-23","updated_at":"2026-05-23","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0067","file":"PLN-0067-rgba8888-published-contracts-and-specs.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0068","file":"PLN-0068-rgba8888-color-type-hal-and-abi-surface.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0069","file":"PLN-0069-rgba8888-cpu-renderer-and-composition.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0070","file":"PLN-0070-rgba8888-asset-palettes-tooling-and-fixtures.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0071","file":"PLN-0071-rgba8888-host-presentation-path.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0072","file":"PLN-0072-rgba8888-residue-removal-and-end-to-end-validation.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]}],"lessons":[]} +{"type":"discussion","id":"DSC-0037","status":"in_progress","ticket":"rgba8888-framebuffer-and-pixel-format-direction","title":"Agenda - RGBA8888 Framebuffer and Pixel Format Direction","created_at":"2026-05-22","updated_at":"2026-05-23","tags":["gfx","framebuffer","rgb565","rgba8888","renderer","assets","host","backend"],"agendas":[{"id":"AGD-0037","file":"AGD-0037-rgba8888-framebuffer-and-pixel-format-direction.md","status":"accepted","created_at":"2026-05-22","updated_at":"2026-05-23"}],"decisions":[{"id":"DEC-0029","file":"DEC-0029-rgba8888-runtime-pixel-format-contract.md","status":"accepted","created_at":"2026-05-23","updated_at":"2026-05-23","ref_agenda":"AGD-0037"}],"plans":[{"id":"PLN-0067","file":"PLN-0067-rgba8888-published-contracts-and-specs.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0068","file":"PLN-0068-rgba8888-color-type-hal-and-abi-surface.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0069","file":"PLN-0069-rgba8888-cpu-renderer-and-composition.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0070","file":"PLN-0070-rgba8888-asset-palettes-tooling-and-fixtures.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0071","file":"PLN-0071-rgba8888-host-presentation-path.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]},{"id":"PLN-0072","file":"PLN-0072-rgba8888-residue-removal-and-end-to-end-validation.md","status":"open","created_at":"2026-05-23","updated_at":"2026-05-23","ref_decisions":["DEC-0029"]}],"lessons":[]} diff --git a/discussion/workflow/plans/PLN-0067-rgba8888-published-contracts-and-specs.md b/discussion/workflow/plans/PLN-0067-rgba8888-published-contracts-and-specs.md index 820bb732..910cab10 100644 --- a/discussion/workflow/plans/PLN-0067-rgba8888-published-contracts-and-specs.md +++ b/discussion/workflow/plans/PLN-0067-rgba8888-published-contracts-and-specs.md @@ -2,7 +2,7 @@ id: PLN-0067 ticket: rgba8888-framebuffer-and-pixel-format-direction title: RGBA8888 Published Contracts and Specs -status: open +status: done created: 2026-05-23 ref_decisions: [DEC-0029] tags: [gfx, framebuffer, rgb565, rgba8888, renderer, assets, host, backend] diff --git a/docs/specs/runtime/02a-vm-values-and-calling-convention.md b/docs/specs/runtime/02a-vm-values-and-calling-convention.md index 1be23abd..ae23586e 100644 --- a/docs/specs/runtime/02a-vm-values-and-calling-convention.md +++ b/docs/specs/runtime/02a-vm-values-and-calling-convention.md @@ -35,7 +35,7 @@ These are treated as VM values with stable layout semantics. | Type | Description | | ------- | --------------------------------- | | `vec2` | 2D vector (x, y) | -| `color` | Packed color value | +| `color` | Packed RGBA8888 color value | | `pixel` | Combination of position and color | These values: @@ -44,6 +44,9 @@ These values: - are copied by value; - do not require heap allocation by themselves. +The canonical `color` raw channel order is RGBA. RGB565 is not a public VM +color contract. + ### Heap values Heap-resident entities are referenced indirectly through handles. diff --git a/docs/specs/runtime/04-gfx-peripheral.md b/docs/specs/runtime/04-gfx-peripheral.md index 9e757c1e..9783fa50 100644 --- a/docs/specs/runtime/04-gfx-peripheral.md +++ b/docs/specs/runtime/04-gfx-peripheral.md @@ -29,13 +29,20 @@ It is an explicit 2D graphics device based on: ### Pixel format -- **RGB565** -- 5 bits Red -- 6 bits Green -- 5 bits Blue -- no alpha channel +- **RGBA8888** +- 8 bits Red +- 8 bits Green +- 8 bits Blue +- 8 bits Alpha +- canonical raw channel order: **RGBA** -Transparency is handled via **color key**. +The framebuffer alpha channel may carry meaningful runtime output. The runtime +MUST NOT force the published front buffer alpha channel to `255` as a blanket +contract. + +Color values in the runtime, HAL, host-facing framebuffer, and GFX ABI are +logical RGBA8888 values. RGB565 is not a supported runtime framebuffer, +palette, host presentation, or compatibility contract. --- @@ -232,16 +239,21 @@ Normative boundary: --- -## 12. Transparency (Color Key) +## 12. Transparency -- One RGB565 value is reserved as TRANSPARENT_KEY -- Pixels with this color are not drawn +Transparency is represented by the alpha channel of the resolved RGBA8888 +color. + +Palette indices are ordinary indices. The runtime MUST NOT reserve palette +index `0` as a special transparent index. A palette entry may still be authored +as transparent by setting its alpha channel to `0`, but that is ordinary palette +data rather than a special index rule. ``` -if src == TRANSPARENT_KEY: +if resolved_color.alpha == 0: skip else: - draw + draw_or_blend(resolved_color) ``` @@ -259,8 +271,9 @@ Official modes: - `BLEND_HALF_MINUS` - `BLEND_FULL` -No continuous alpha. -No arbitrary blending. +Alpha is available through RGBA8888 colors. Discrete blend modes remain part of +the classic GFX contract, and later optimization work may specialize opaque, +masked, and alpha paths. Everything is: @@ -283,12 +296,13 @@ Everything is: By design: -- Continuous alpha -- RGBA framebuffer - Shaders - Modern GPU pipeline - HDR - Gamma correction +- RGB565 compatibility framebuffers +- multi-format backend selection +- render-thread ownership as part of this contract --- @@ -314,8 +328,7 @@ controls: 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 is implemented without continuous per-pixel alpha and without floats. -It uses a **discrete integer level** (0..31), which in practice produces an +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. --- @@ -327,32 +340,32 @@ 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: RGB565` +- `fade_color: RGBA8888` - color the image will be blended into Registers: - `SCENE_FADE_LEVEL` (0..31) -- `SCENE_FADE_COLOR` (RGB565) +- `SCENE_FADE_COLOR` (RGBA8888) - `HUD_FADE_LEVEL` (0..31) -- `HUD_FADE_COLOR` (RGB565) +- `HUD_FADE_COLOR` (RGBA8888) Common cases: - Fade-out: `fade_color = BLACK` - Flash/teleport: `fade_color = WHITE` -- Special effects: any RGB565 color +- Special effects: any RGBA8888 color --- ### 17.2 Fade Operation (Blending with Arbitrary Color) -For each RGB565 pixel `src` and fade color `fc`, the final pixel `dst` is calculated per channel. +For each RGBA8888 pixel `src` and fade color `fc`, the final pixel `dst` is calculated per channel. 1) Extract components: -- `src_r5`, `src_g6`, `src_b5` -- `fc_r5`, `fc_g6`, `fc_b5` +- `src_r8`, `src_g8`, `src_b8`, `src_a8` +- `fc_r8`, `fc_g8`, `fc_b8`, `fc_a8` 2) Apply integer blending: @@ -360,17 +373,18 @@ For each RGB565 pixel `src` and fade color `fc`, the final pixel `dst` is calcul src_weight = fade_level // 0..31 fc_weight = 31 - fade_level -r5 = (src_r5 * src_weight + fc_r5 * fc_weight) / 31 -g6 = (src_g6 * src_weight + fc_g6 * fc_weight) / 31 -b5 = (src_b5 * src_weight + fc_b5 * fc_weight) / 31 +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_r5`, `src_g6`, `src_b5` -- `fc_r5`, `fc_g6`, `fc_b5` +- `src_r8`, `src_g8`, `src_b8`, `src_a8` +- `fc_r8`, `fc_g8`, `fc_b8`, `fc_a8` 3) Repack: ``` -dst = pack_rgb565(r5, g6, b5) +dst = pack_rgba8888_rgba(r8, g8, b8, a8) ``` @@ -425,8 +439,8 @@ Each pixel of a tile or sprite is: Fixed rule: -- Index `0` = TRANSPARENT -- Indices `1..15` = valid palette colors +- Indices `0..15` are ordinary valid palette indices +- Transparency comes from the alpha channel of the resolved palette entry --- @@ -437,13 +451,13 @@ Each **Tile Bank** contains: - **64 palettes** in runtime-facing v1 - Each palette has: - **16 colors** - - each color in **RGB565 (`u16`, little-endian in serialized assets)** + - each color in **RGBA8888** with canonical RGBA channel order Size: -- 1 palette = 16 × 2 bytes = **32 bytes** -- 64 palettes = **2 KB per bank** -- 16 banks = **32 KB maximum palettes** +- 1 palette = 16 × 4 bytes = **64 bytes** +- 64 palettes = **4 KB per bank** +- 16 banks = **64 KB maximum palettes** --- @@ -496,22 +510,22 @@ Runtime-facing validity rule for v1: The pipeline works like this: 1. Read indexed pixel from tile (value 0..15) -2. If index == 0 → transparent pixel -3. Otherwise: +2. Resolve: - real_color = palette[palette_id][index] -4. Apply: +3. Apply: - flip - discrete blend + - alpha/skip behavior from the resolved RGBA8888 color - writing to back buffer In other words: ``` pixel_index = tile_pixel(x,y) -if pixel_index == 0: +color = bank.palettes[palette_id][pixel_index] +if color.alpha == 0: skip else: - color = bank.palettes[palette_id][pixel_index] - draw(color) + draw_or_blend(color) ``` --- @@ -578,7 +592,6 @@ Fault boundary: | `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 | -| `gfx.clear_565` | `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 | diff --git a/docs/specs/runtime/11-portability-and-cross-platform-execution.md b/docs/specs/runtime/11-portability-and-cross-platform-execution.md index 82d6fe1a..46317f0c 100644 --- a/docs/specs/runtime/11-portability-and-cross-platform-execution.md +++ b/docs/specs/runtime/11-portability-and-cross-platform-execution.md @@ -116,7 +116,7 @@ Hardware differences: The graphics system: -- operates on a logical framebuffer +- operates on a logical RGBA8888 framebuffer - uses an indexed palette - does not depend on a specific GPU @@ -127,6 +127,10 @@ The platform layer: - **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 +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. In particular: diff --git a/docs/specs/runtime/15-asset-management.md b/docs/specs/runtime/15-asset-management.md index cf76e3c3..d2e52306 100644 --- a/docs/specs/runtime/15-asset-management.md +++ b/docs/specs/runtime/15-asset-management.md @@ -114,7 +114,7 @@ For `BankType::GLYPH`, the v1 runtime-facing contract is: - `codec = NONE` - serialized pixels use packed `u4` palette indices -- serialized palettes use `RGB565` (`u16`, little-endian) +- serialized palettes use `RGBA8888` with canonical RGBA channel order - `palette_count = 64` - runtime materialization may expand pixel indices to one `u8` per pixel @@ -152,18 +152,25 @@ Validation rules for `GLYPH` v1: #### 4.1.2 Payload Layout 1. packed indexed pixels for the full sheet, using `ceil(width * height / 2)` bytes; -2. palette table, using `palette_count * 16 * 2` bytes. +2. palette table, using `palette_count * 16 * 4` bytes. The tile-bank payload therefore separates serialized storage form from runtime memory form: - serialized pixel plane: packed `4bpp` - decoded pixel plane: expanded `u8` indices, one entry per pixel -- palette table: `64 * 16` colors in `RGB565` +- palette table: `64 * 16` colors in RGBA8888 channel order For `GLYPH` v1: -- `size` must match `ceil(width * height / 2) + (palette_count * 16 * 2)` -- `decoded_size` must match `(width * height) + (palette_count * 16 * 2)` +- `size` must match `ceil(width * height / 2) + (palette_count * 16 * 4)` +- `decoded_size` must match `(width * height) + (palette_count * 16 * 4)` + +RGB565 palette payloads are not compatible runtime input. Existing assets with +two-byte RGB565 palette entries must be regenerated or converted by tooling +before they are loaded by the runtime. + +Palette indices are ordinary indices. Transparency is represented by the alpha +channel of the resolved RGBA8888 palette entry, not by reserving index `0`. ### 4.2 `SCENE` asset contract in v1 diff --git a/docs/specs/runtime/16-host-abi-and-syscalls.md b/docs/specs/runtime/16-host-abi-and-syscalls.md index 302a8e68..8a0ddb34 100644 --- a/docs/specs/runtime/16-host-abi-and-syscalls.md +++ b/docs/specs/runtime/16-host-abi-and-syscalls.md @@ -220,6 +220,30 @@ 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) + +The public GFX ABI uses format-neutral operation names. API and syscall names +MUST NOT encode RGB565 or any other pixel format suffix. + +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` + +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 + current ABI. +- The runtime framebuffer exposed across the host boundary is RGBA8888, not + `u16` RGB565. + ### Composition surface (`composer`, v1) The canonical frame-orchestration public ABI uses module `composer`.