implements PLN-0067
This commit is contained in:
parent
4d5818c244
commit
1256d33a72
@ -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-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-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-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":[]}
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
id: PLN-0067
|
id: PLN-0067
|
||||||
ticket: rgba8888-framebuffer-and-pixel-format-direction
|
ticket: rgba8888-framebuffer-and-pixel-format-direction
|
||||||
title: RGBA8888 Published Contracts and Specs
|
title: RGBA8888 Published Contracts and Specs
|
||||||
status: open
|
status: done
|
||||||
created: 2026-05-23
|
created: 2026-05-23
|
||||||
ref_decisions: [DEC-0029]
|
ref_decisions: [DEC-0029]
|
||||||
tags: [gfx, framebuffer, rgb565, rgba8888, renderer, assets, host, backend]
|
tags: [gfx, framebuffer, rgb565, rgba8888, renderer, assets, host, backend]
|
||||||
|
|||||||
@ -35,7 +35,7 @@ These are treated as VM values with stable layout semantics.
|
|||||||
| Type | Description |
|
| Type | Description |
|
||||||
| ------- | --------------------------------- |
|
| ------- | --------------------------------- |
|
||||||
| `vec2` | 2D vector (x, y) |
|
| `vec2` | 2D vector (x, y) |
|
||||||
| `color` | Packed color value |
|
| `color` | Packed RGBA8888 color value |
|
||||||
| `pixel` | Combination of position and color |
|
| `pixel` | Combination of position and color |
|
||||||
|
|
||||||
These values:
|
These values:
|
||||||
@ -44,6 +44,9 @@ These values:
|
|||||||
- are copied by value;
|
- are copied by value;
|
||||||
- do not require heap allocation by themselves.
|
- 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 values
|
||||||
|
|
||||||
Heap-resident entities are referenced indirectly through handles.
|
Heap-resident entities are referenced indirectly through handles.
|
||||||
|
|||||||
@ -29,13 +29,20 @@ It is an explicit 2D graphics device based on:
|
|||||||
|
|
||||||
### Pixel format
|
### Pixel format
|
||||||
|
|
||||||
- **RGB565**
|
- **RGBA8888**
|
||||||
- 5 bits Red
|
- 8 bits Red
|
||||||
- 6 bits Green
|
- 8 bits Green
|
||||||
- 5 bits Blue
|
- 8 bits Blue
|
||||||
- no alpha channel
|
- 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
|
Transparency is represented by the alpha channel of the resolved RGBA8888
|
||||||
- Pixels with this color are not drawn
|
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
|
skip
|
||||||
else:
|
else:
|
||||||
draw
|
draw_or_blend(resolved_color)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
@ -259,8 +271,9 @@ Official modes:
|
|||||||
- `BLEND_HALF_MINUS`
|
- `BLEND_HALF_MINUS`
|
||||||
- `BLEND_FULL`
|
- `BLEND_FULL`
|
||||||
|
|
||||||
No continuous alpha.
|
Alpha is available through RGBA8888 colors. Discrete blend modes remain part of
|
||||||
No arbitrary blending.
|
the classic GFX contract, and later optimization work may specialize opaque,
|
||||||
|
masked, and alpha paths.
|
||||||
|
|
||||||
Everything is:
|
Everything is:
|
||||||
|
|
||||||
@ -283,12 +296,13 @@ Everything is:
|
|||||||
|
|
||||||
By design:
|
By design:
|
||||||
|
|
||||||
- Continuous alpha
|
|
||||||
- RGBA framebuffer
|
|
||||||
- Shaders
|
- Shaders
|
||||||
- Modern GPU pipeline
|
- Modern GPU pipeline
|
||||||
- HDR
|
- HDR
|
||||||
- Gamma correction
|
- 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.
|
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.
|
The fade uses a **discrete integer level** (0..31), which in practice produces an
|
||||||
It uses a **discrete integer level** (0..31), which in practice produces an
|
|
||||||
"almost continuous" visual result in Prometeu's `480x270` pixel-art framebuffer.
|
"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]**
|
- `fade_level: u8` in the range **[0..31]**
|
||||||
- `0` → fully replaced by the fade color
|
- `0` → fully replaced by the fade color
|
||||||
- `31` → fully visible (no fade)
|
- `31` → fully visible (no fade)
|
||||||
- `fade_color: RGB565`
|
- `fade_color: RGBA8888`
|
||||||
- color the image will be blended into
|
- color the image will be blended into
|
||||||
|
|
||||||
Registers:
|
Registers:
|
||||||
|
|
||||||
- `SCENE_FADE_LEVEL` (0..31)
|
- `SCENE_FADE_LEVEL` (0..31)
|
||||||
- `SCENE_FADE_COLOR` (RGB565)
|
- `SCENE_FADE_COLOR` (RGBA8888)
|
||||||
- `HUD_FADE_LEVEL` (0..31)
|
- `HUD_FADE_LEVEL` (0..31)
|
||||||
- `HUD_FADE_COLOR` (RGB565)
|
- `HUD_FADE_COLOR` (RGBA8888)
|
||||||
|
|
||||||
Common cases:
|
Common cases:
|
||||||
|
|
||||||
- Fade-out: `fade_color = BLACK`
|
- Fade-out: `fade_color = BLACK`
|
||||||
- Flash/teleport: `fade_color = WHITE`
|
- Flash/teleport: `fade_color = WHITE`
|
||||||
- Special effects: any RGB565 color
|
- Special effects: any RGBA8888 color
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### 17.2 Fade Operation (Blending with Arbitrary 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:
|
1) Extract components:
|
||||||
|
|
||||||
- `src_r5`, `src_g6`, `src_b5`
|
- `src_r8`, `src_g8`, `src_b8`, `src_a8`
|
||||||
- `fc_r5`, `fc_g6`, `fc_b5`
|
- `fc_r8`, `fc_g8`, `fc_b8`, `fc_a8`
|
||||||
|
|
||||||
2) Apply integer blending:
|
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
|
src_weight = fade_level // 0..31
|
||||||
fc_weight = 31 - fade_level
|
fc_weight = 31 - fade_level
|
||||||
|
|
||||||
r5 = (src_r5 * src_weight + fc_r5 * fc_weight) / 31
|
r8 = (src_r8 * src_weight + fc_r8 * fc_weight) / 31
|
||||||
g6 = (src_g6 * src_weight + fc_g6 * fc_weight) / 31
|
g8 = (src_g8 * src_weight + fc_g8 * fc_weight) / 31
|
||||||
b5 = (src_b5 * src_weight + fc_b5 * 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`
|
- `src_r8`, `src_g8`, `src_b8`, `src_a8`
|
||||||
- `fc_r5`, `fc_g6`, `fc_b5`
|
- `fc_r8`, `fc_g8`, `fc_b8`, `fc_a8`
|
||||||
|
|
||||||
3) Repack:
|
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:
|
Fixed rule:
|
||||||
|
|
||||||
- Index `0` = TRANSPARENT
|
- Indices `0..15` are ordinary valid palette indices
|
||||||
- Indices `1..15` = valid palette colors
|
- 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
|
- **64 palettes** in runtime-facing v1
|
||||||
- Each palette has:
|
- Each palette has:
|
||||||
- **16 colors**
|
- **16 colors**
|
||||||
- each color in **RGB565 (`u16`, little-endian in serialized assets)**
|
- each color in **RGBA8888** with canonical RGBA channel order
|
||||||
|
|
||||||
Size:
|
Size:
|
||||||
|
|
||||||
- 1 palette = 16 × 2 bytes = **32 bytes**
|
- 1 palette = 16 × 4 bytes = **64 bytes**
|
||||||
- 64 palettes = **2 KB per bank**
|
- 64 palettes = **4 KB per bank**
|
||||||
- 16 banks = **32 KB maximum palettes**
|
- 16 banks = **64 KB maximum palettes**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -496,22 +510,22 @@ Runtime-facing validity rule for v1:
|
|||||||
The pipeline works like this:
|
The pipeline works like this:
|
||||||
|
|
||||||
1. Read indexed pixel from tile (value 0..15)
|
1. Read indexed pixel from tile (value 0..15)
|
||||||
2. If index == 0 → transparent pixel
|
2. Resolve:
|
||||||
3. Otherwise:
|
|
||||||
- real_color = palette[palette_id][index]
|
- real_color = palette[palette_id][index]
|
||||||
4. Apply:
|
3. Apply:
|
||||||
- flip
|
- flip
|
||||||
- discrete blend
|
- discrete blend
|
||||||
|
- alpha/skip behavior from the resolved RGBA8888 color
|
||||||
- writing to back buffer
|
- writing to back buffer
|
||||||
|
|
||||||
In other words:
|
In other words:
|
||||||
```
|
```
|
||||||
pixel_index = tile_pixel(x,y)
|
pixel_index = tile_pixel(x,y)
|
||||||
if pixel_index == 0:
|
color = bank.palettes[palette_id][pixel_index]
|
||||||
|
if color.alpha == 0:
|
||||||
skip
|
skip
|
||||||
else:
|
else:
|
||||||
color = bank.palettes[palette_id][pixel_index]
|
draw_or_blend(color)
|
||||||
draw(color)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -578,7 +592,6 @@ Fault boundary:
|
|||||||
| `gfx.draw_disc` | `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_square` | `void` | no real operational failure path in v1 |
|
||||||
| `gfx.draw_text` | `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.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 |
|
||||||
|
|||||||
@ -116,7 +116,7 @@ Hardware differences:
|
|||||||
|
|
||||||
The graphics system:
|
The graphics system:
|
||||||
|
|
||||||
- operates on a logical framebuffer
|
- operates on a logical RGBA8888 framebuffer
|
||||||
- uses an indexed palette
|
- uses an indexed palette
|
||||||
- does not depend on a specific GPU
|
- does not depend on a specific GPU
|
||||||
|
|
||||||
@ -127,6 +127,10 @@ The platform layer:
|
|||||||
- **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 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.
|
Host presentation SHOULD be driven by published logical frames and explicit host-owned invalidation, not by perpetual redraw polling.
|
||||||
|
|
||||||
In particular:
|
In particular:
|
||||||
|
|||||||
@ -114,7 +114,7 @@ For `BankType::GLYPH`, the v1 runtime-facing contract is:
|
|||||||
|
|
||||||
- `codec = NONE`
|
- `codec = NONE`
|
||||||
- serialized pixels use packed `u4` palette indices
|
- 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`
|
- `palette_count = 64`
|
||||||
- runtime materialization may expand pixel indices to one `u8` per pixel
|
- 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
|
#### 4.1.2 Payload Layout
|
||||||
|
|
||||||
1. packed indexed pixels for the full sheet, using `ceil(width * height / 2)` bytes;
|
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:
|
The tile-bank payload therefore separates serialized storage form from runtime memory form:
|
||||||
|
|
||||||
- serialized pixel plane: packed `4bpp`
|
- serialized pixel plane: packed `4bpp`
|
||||||
- decoded pixel plane: expanded `u8` indices, one entry per pixel
|
- 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:
|
For `GLYPH` v1:
|
||||||
|
|
||||||
- `size` must match `ceil(width * height / 2) + (palette_count * 16 * 2)`
|
- `size` must match `ceil(width * height / 2) + (palette_count * 16 * 4)`
|
||||||
- `decoded_size` must match `(width * height) + (palette_count * 16 * 2)`
|
- `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
|
### 4.2 `SCENE` asset contract in v1
|
||||||
|
|
||||||
|
|||||||
@ -220,6 +220,30 @@ 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)
|
||||||
|
|
||||||
|
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)
|
### Composition surface (`composer`, v1)
|
||||||
|
|
||||||
The canonical frame-orchestration public ABI uses module `composer`.
|
The canonical frame-orchestration public ABI uses module `composer`.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user