prometeu-runtime/discussion/workflow/agendas/AGD-0037-rgba8888-framebuffer-and-pixel-format-direction.md

764 lines
28 KiB
Markdown

---
id: AGD-0037
ticket: rgba8888-framebuffer-and-pixel-format-direction
title: Agenda - RGBA8888 Framebuffer and Pixel Format Direction
status: accepted
created: 2026-05-22
resolved: 2026-05-23
decision: DEC-0029
tags: [gfx, framebuffer, rgb565, rgba8888, renderer, assets, host, backend]
---
## Contexto
Estamos avaliando uma possivel mudanca no Prometeu de framebuffer/cor RGB565
para RGBA8888.
O Prometeu hoje usa um modelo grafico baseado em blit destrutivo, framebuffer
proprio, tiles/sprites/layers, scene cache, paletas, fonte de hardware e
primitivas basicas de desenho. Historicamente, RGB565 foi escolhido para
reforcar a identidade de console 16-bit / fantasy handheld, reduzir memoria e
manter uma estetica simples.
Agora existe pressao legitima por RGBA8888:
- e o formato natural de muitos hosts modernos, texturas e APIs de janela;
- facilita UI mais polida, alpha real, transicoes e efeitos;
- combina melhor com a direcao do Hub estilo Homebrew Channel;
- pode reduzir conversoes no host desktop;
- abre uma ponte mais direta para backends GPU futuros.
Ao mesmo tempo, o objetivo do Prometeu continua sendo:
- hardware agnostico;
- barato/DIY quando possivel, mas sem manter RGB565 como contrato de
compatibilidade nesta mudanca;
- bom em portateis modernos;
- 480x270 a 60 Hz;
- estetica de fantasy console;
- Hub visualmente mais rico sem perder o modelo operacional;
- caminho futuro para pipeline grafico mais avancado.
Direcao atual da discussao: seguir pela Opcao B. RGB565 deve sair por completo
do contrato runtime/HAL/renderer/host/asset decode desta frente. RGBA8888 deve
ser o formato unico fisico do framebuffer e tambem a representacao normal de
cor do runtime. Esta mudanca nao deve abrir compatibilidade dupla, backend
RGB565, render thread, GPU backend ou abstracao generica de pixel format.
Esta agenda e somente analise arquitetural. Nenhum codigo deve ser alterado
como parte desta discussao.
## Estado Atual do Codigo
### Acoplamento direto a RGB565
O acoplamento central esta em `crates/console/prometeu-hal/src/color.rs`:
- `Color(pub u16)` representa explicitamente RGB565.
- `Color::rgb(r, g, b)` quantiza componentes 8-bit para 5/6/5.
- `Color::from_raw(raw: u16)` e `Color::raw() -> u16` expõem o formato fisico.
- `Color::COLOR_KEY` e `Color::TRANSPARENT` usam magenta RGB565 como chave de
transparencia.
- `unpack_to_native` e `pack_from_native` operam nos canais 5/6/5.
Isso significa que `Color` hoje nao e uma cor logica independente; ele e o
proprio pixel RGB565.
### HAL e API publica de GFX
`crates/console/prometeu-hal/src/gfx_bridge.rs` fixa RGB565 no contrato:
- `front_buffer(&self) -> &[u16]`;
- todos os draws recebem `Color`;
- fades expõem `Color`;
- o nome de syscall `GfxClear565` reforca RGB565 no contrato VM/HAL.
Impacto: qualquer migracao direta para `Vec<u32>` quebra a API do HAL, testes,
VM dispatch e host.
### Buffers do renderer
`crates/console/prometeu-drivers/src/gfx.rs` fixa o formato fisico:
- `front: Vec<u16>`;
- `back: Vec<u16>`;
- `RenderTarget.back: &mut [u16]`;
- `front_buffer() -> &[u16]`;
- `clear`, `draw_pixel`, `draw_char`, tile draw e sprite draw escrevem `u16`;
- `present()` faz swap dos dois buffers, sem copia;
- `render_scene_from_cache()` limpa o back com `Color::BLACK.raw()`;
- tiles/sprites resolvem `Color` e gravam `color.raw()`;
- fades percorrem `&mut [u16]` e fazem blend em canais RGB565.
O modelo destrutivo em si nao depende conceitualmente de RGB565, mas a
implementacao atual depende.
### Host/window layer
`crates/host/prometeu-host-desktop-winit/src/runner.rs` assume que o runtime
publica RGB565:
- le `self.hardware.gfx.front_buffer()`;
- chama `draw_rgb565_to_rgba8(src, frame)`.
`crates/host/prometeu-host-desktop-winit/src/utilities.rs` contem:
- `draw_rgb565_to_rgba8(src: &[u16], dst_rgba: &mut [u8])`;
- `rgb565_to_rgb888(px: u16)`.
Ou seja, o host `pixels` ja apresenta RGBA8, mas o runtime entrega RGB565 e o
host converte a cada redraw necessario.
### GlyphBank, paletas, sprites e scene cache
`crates/console/prometeu-hal/src/glyph_bank.rs` preserva uma separacao util:
- pixels de glyph/tile sao indices `u8`;
- payload serializado usa indices 4bpp;
- runtime expande para um `u8` por pixel;
- indice 0 e reservado para transparencia;
- a tabela de paletas e `[[Color; 16]; 64]`.
Isso acopla a resolucao final de cor a RGB565, mas nao obriga os tiles/sprites
a deixarem de ser indexados. A estrutura mais importante para preservar a
estetica fantasy console ja existe: indices + paletas limitadas.
`crates/console/prometeu-drivers/src/asset.rs` fixa o formato serializado de
paleta:
- `GLYPH_BANK_PALETTE_BYTES_V1 = 64 * 16 * size_of::<u16>()`;
- decode le cada cor como `u16::from_le_bytes`;
- escreve `Color(color_raw)`;
- testes e `pbxgen-stress` tambem assumem paletas RGB565 little-endian.
O asset pipeline atual, portanto, e v1/RGB565 para paletas, mas os indices dos
tiles/sprites podem permanecer iguais.
### Fade, blend e primitivas
`gfx.rs` implementa blend/fade em RGB565:
- `blend_rgb565(dst: u16, src: u16, mode: BlendMode) -> u16`;
- `apply_fade_to_buffer(back: &mut [u16], level, fade_color)`;
- `fill_rect_blend` mistura por pixel nos canais 5/6/5;
- `draw_text` e fonte de hardware escrevem cor opaca direta.
RGBA8888 simplificaria alguns efeitos alpha, mas tambem exigiria disciplina
para nao transformar todos os draws em blend caro por pixel.
### VM e syscall
`crates/console/prometeu-system/src/services/vm_runtime/dispatch.rs` usa:
- `get_color(value: i64) -> Color` via `Color::from_raw(value as u16)`;
- `GfxClear565`, com range `0xFFFF`.
Essa e uma fronteira importante: o PBS/VM conhece hoje o valor bruto RGB565.
Se a cor logica mudar para RGBA8888, a VM API precisa de compatibilidade ou de
uma transicao clara.
## Problema
O problema nao e apenas trocar `Vec<u16>` por `Vec<u32>`.
Existem quatro conceitos misturados hoje:
1. cor logica usada pelo runtime e HAL;
2. formato fisico do framebuffer;
3. formato serializado das paletas em `assets.pa`;
4. formato de apresentacao do host/backend.
RGB565 hoje ocupa os quatro papeis. A direcao escolhida e remove-lo desses
papeis, aceitando a quebra coordenada de HAL, asset pipeline, testes, VM, host
e renderer como o custo da limpeza arquitetural.
A pergunta arquitetural restante nao e mais se RGBA8888 deve substituir RGB565.
A resposta operacional e sim. A pergunta agora e como fazer essa substituicao
sem misturar a migracao de pixel format com render thread, GPU backend,
abstracao de backend, asset pipeline v2 amplo ou outras frentes.
## Pontos Criticos
### Identidade visual nao precisa ser formato de memoria
O Prometeu pode continuar sendo uma maquina com estetica 16-bit mesmo usando
RGBA8888 em algum ponto do pipeline. A limitacao artistica pode morar em:
- assets indexados;
- paletas limitadas;
- regras de composicao;
- resolucao 480x270;
- fontes/pixel art;
- ferramentas de autoria;
- validadores do asset pipeline.
O formato fisico do framebuffer e uma decisao de implementacao, nao
necessariamente uma promessa estetica.
### RGBA8888 como cor logica e formato fisico unico
Um tipo `Color` semanticamente RGBA8888, ou um tipo explicito
`ColorRgba8888`, deve substituir `Color(pub u16)`:
- representar alpha real;
- evitar quantizacao precoce;
- facilitar UI/HUB;
- alinhar com texturas modernas;
- eliminar a conversao obrigatoria RGB565 -> RGBA8 no host desktop.
Nesta agenda, RGBA8888 nao e apenas um backend alternativo. Ele e o formato
unico fisico do framebuffer.
### RGB565 deve sair do contrato
RGB565 continua sendo historicamente importante, mas nao deve permanecer como
compatibilidade operacional nesta mudanca. A migracao deve remover:
- `Color(pub u16)` como cor publica;
- `Vec<u16>` como front/back buffer;
- `front_buffer() -> &[u16]`;
- APIs `Gfx*565` ou qualquer outra superficie publica com formato RGB565 no
nome como APIs canonicas;
- paletas runtime armazenadas como `Color` RGB565;
- conversao host `draw_rgb565_to_rgba8` no caminho normal;
- helpers `blend_rgb565`, `pack_from_native`, `unpack_to_native` como base do
renderer.
Se algum alvo futuro precisar RGB565 por hardware, isso deve ser tratado como
uma nova discussao depois, nao como requisito desta migracao.
### O blit destrutivo pode sobreviver
RGBA8888 nao exige scene graph, GPU obrigatoria ou renderer retained. O modelo
pode continuar:
```text
frame state -> compose into back buffer -> present/publish
```
O que muda e o tipo do pixel no alvo de materializacao.
### Evitar abrir backend abstraction nesta mudanca
A VM nao deveria tocar diretamente no framebuffer. Ela deve produzir estado ou
pacotes imutaveis de frame, e o renderer deve ser dono exclusivo dos buffers.
Essa direcao continua correta no longo prazo, mas esta agenda agora restringe o
escopo. A migracao RGBA8888 deve mudar o formato atual do renderer existente,
nao introduzir uma matriz de backends. Render thread, `RenderFramePacket`
formal, SDL/GPU backend e bare-metal backend ficam fora deste corte.
O limite pragmatico: a VM/HAL nao deve expor buffer mutavel direto, mas a
implementacao deste passo pode continuar com o renderer CPU destrutivo atual,
apenas migrado para RGBA8888.
## Trade-offs Numericos
Resolucao interna atual: `480x270 = 129600` pixels.
### Memoria de framebuffer
RGB565:
- 2 bytes por pixel;
- 1 buffer: `259200` bytes = `253.125 KiB`;
- front + back: `518400` bytes = `506.25 KiB`.
RGBA8888:
- 4 bytes por pixel;
- 1 buffer: `518400` bytes = `506.25 KiB`;
- front + back: `1036800` bytes = `1012.5 KiB`.
Conclusao: RGBA8888 dobra a memoria dos framebuffers. Em desktop isso e
irrelevante; em alvo DIY/barato pode ser significativo, mas ainda e pequeno em
termos absolutos para muitos portateis modernos.
### Largura de banda por full-frame touch
Um passe que toca um buffer inteiro:
- RGB565: `253.125 KiB/frame`, cerca de `14.8 MiB/s` a 60 Hz;
- RGBA8888: `506.25 KiB/frame`, cerca de `29.7 MiB/s` a 60 Hz.
O custo real pode multiplicar isso, porque o frame atual pode fazer:
- clear;
- raster de layers;
- raster de sprites;
- scene fade fullscreen;
- hud fade fullscreen;
- conversao/apresentacao no host.
No desktop atual, a conversao host RGB565 -> RGBA8 le `253.125 KiB` e escreve
`506.25 KiB` por frame convertido, cerca de `44.5 MiB/s` a 60 Hz so nessa
etapa. Um backend RGBA8888 pode eliminar essa conversao, mas so se evitar uma
copia equivalente para o frame do host.
### CPU
Impacto esperado por operacao:
- opaque blit: RGBA8888 pode ser simples (`dst = src`), mas move o dobro de
bytes; pode ficar mais rapido em CPUs modernas se alinhar melhor a `u32`;
- masked blit: continua barato se entradas com alpha transparente pulam antes
de blendar;
- alpha blit: fica mais expressivo, mas custa multiplicacoes/interpolacoes por
canal se usado indiscriminadamente;
- fade: RGBA8888 usa canais 8-bit e pode ser mais simples conceitualmente, mas
ainda e passe fullscreen caro;
- fill_rect: pode ser rapido com fill de `u32`, desde que seja opaco;
- draw_text: continua opaco e simples, nao deve virar alpha blend por padrao;
- sprites: devem manter fast path indexado opaco/mascarado; alpha por sprite
deve ser opt-in;
- scene composition: deve continuar priorizando writes opacos e masked skips.
### Bateria
Em portateis baratos, dobrar bytes movimentados pode afetar bateria se a CPU
fizer toda composicao. Por outro lado, em portateis modernos com GPU, RGBA8888
pode economizar conversoes e usar caminhos nativos de textura/composicao.
Conclusao da agenda atual: aceitar o custo de memoria/banda do RGBA8888 como
preco de simplificacao e futuro visual. A arquitetura nao deve exigir GPU, mas
tambem nao deve manter RGB565 como fallback no escopo desta mudanca.
### Simplicidade
RGBA8888 simplifica:
- alpha real;
- integracao com host moderno;
- efeitos UI;
- raciocinio em canais 8-bit;
- possivel upload de textura.
RGBA8888 complica:
- contrato atual da VM/HAL;
- asset palette v1;
- testes que comparam `u16`;
- risco de alpha blend virar caminho padrao;
- necessidade de remover RGB565 de forma coordenada, sem camada dupla de
compatibilidade.
## Blit Destrutivo com RGBA8888
O modelo destrutivo continuaria valido:
```text
clear/fill/raster tiles/raster sprites/fades/overlay -> back buffer -> present
```
Os caminhos rapidos precisam ser explicitos:
1. Opaque blit:
- `dst = src`;
- usado para background, tiles totalmente opacos, fills, texto opaco e UI
sem alpha;
- deve ser o caminho dominante.
2. Masked blit:
- se a entrada resolvida tiver alpha transparente, pula;
- caso contrario, `dst = resolved_color`;
- deve ser o caminho dominante para sprites e tiles com recorte.
3. Alpha blit:
- `dst = src-over(dst)`;
- usado apenas quando o asset/comando declarar alpha real ou efeito;
- nao deve ser implicito para todo sprite/tile.
Para evitar que tudo vire alpha blend caro:
- manter assets indexados como opacos/mascarados por padrao;
- resolver paletas para RGBA; transparencia deve vir do canal alpha da entrada
resolvida, nao de um indice reservado;
- separar APIs/comandos `draw_opaque`, `draw_masked`, `draw_alpha`;
- manter `BlendMode` classico como efeito opt-in;
- medir alpha paths separadamente;
- nao usar RGBA8888 como desculpa para tratar cada pixel como translucido.
## Compatibilidade com Asset Pipeline
Tiles/sprites podem continuar indexados e paletizados.
Recomendacao conceitual:
- `pixel_indices: Vec<u8>` permanece;
- indices de paleta sao indices comuns; transparencia vem do canal alpha da
entrada RGBA8888 resolvida;
- limites 16 cores por paleta e 64 paletas permanecem como contrato artistico;
- paletas passam a resolver para RGBA8888;
- o payload de paleta deve deixar de ser RGB565;
- `assets.pa` e as ferramentas que geram/validam glyph banks precisam migrar
para paletas RGBA8888 no mesmo contrato desta frente.
Isso preserva o modelo artistico indexado/paletizado, mas nao preserva
compatibilidade binaria RGB565 de paleta.
Forma alvo:
```text
asset palette RGBA8888 -> decode -> [[ColorRgba8888; 16]; 64]
```
Forma transitoria aceitavel apenas durante execucao da migracao, nao como
estado final:
```text
old RGB565 test fixture -> one-time conversion -> RGBA8888 fixture
```
A decisao importante e evitar conversao por pixel a cada frame. Depois da
migracao, o renderer deve compor diretamente em RGBA8888.
## Hardware Agnostico e Backends
O jogo/PBS/VM nao deve saber detalhes de apresentacao do host, mas nesta agenda
nao criaremos multiplos backends de pixel format.
Arquitetura alvo restrita desta mudanca:
```text
VM/game tick
-> estado/comandos atuais
-> renderer CPU destrutivo compoe RGBA8888
-> host apresenta RGBA8888
```
Fora de escopo desta agenda:
- CPU RGB565 reference backend;
- suporte simultaneo RGB565/RGBA8888;
- SDL texture backend como abstracao nova;
- OpenGL ES / wgpu GPU backend;
- bare-metal framebuffer backend;
- `FrameSurface` generico com matriz de formatos.
O contrato publico deve parar de expor `&[u16]`. No alvo desta migracao, a
saida normal deve ser RGBA8888, por exemplo `&[u32]` ou bytes RGBA8 com ordem
explicitamente documentada.
Se uma abstracao generica de surface for criada, ela deve ter apenas um formato
suportado inicialmente: RGBA8888. Nao deve reintroduzir RGB565 por design.
## VM e Render Thread
A separacao VM/render thread ajuda a migracao, mas nao deve ser feita no mesmo
passo da troca de pixel format.
Modelo desejado:
- VM thread executa logica, syscalls, `frame()`, estado de sprites/cenas;
- VM nao toca diretamente no framebuffer;
- VM publica pacote imutavel de frame;
- render thread e dona exclusiva do framebuffer;
- host consome frame publicado.
Impacto na migracao para RGBA8888:
- facilita trocar backend sem afetar VM;
- reduz disputas entre VM e blit CPU no mesmo core quando houver multicore;
- exige disciplina de snapshots e ownership;
- pode aumentar latencia se a publicacao nao for bem desenhada;
- cria uma mudanca arquitetural grande demais para misturar com color format.
Portanto, render thread deve ficar fora desta frente. A migracao deve focar em
substituir RGB565 por RGBA8888 no renderer existente.
## Opcoes
### Opcao A - Manter RGB565 como framebuffer principal
**Abordagem:** preservar `Color(pub u16)`, `Vec<u16>`, asset palettes RGB565 e
host convertendo para RGBA8.
**Pros:**
- menor memoria e banda;
- baixo risco;
- preserva compatibilidade com VM/HAL/testes;
- bom para bare-metal e DIY;
- alinhado com a decisao historica de performance.
**Contras:**
- alpha real continua ruim;
- Hub moderno fica limitado ou cheio de hacks;
- host moderno paga conversao RGB565 -> RGBA8;
- formato fisico continua confundido com identidade artistica;
- backends GPU/RGBA ficam menos naturais.
**Manutenibilidade:** simples no curto prazo, mas tende a acumular excecoes
para UI e backend moderno.
### Opcao B - Migrar tudo para RGBA8888
**Abordagem:** trocar `Color` para RGBA8888, `Gfx` para `Vec<u32>`, HAL para
`&[u32]`/RGBA, host sem conversao RGB565, paletas resolvidas em RGBA. RGB565
deixa de existir como contrato runtime, formato de framebuffer, formato normal
de paleta ou backend de compatibilidade.
**Pros:**
- modelo moderno e direto;
- alpha real;
- host desktop mais natural;
- UI/HUB mais expressivo;
- caminho mais direto para GPU.
- remove a ambiguidade entre cor logica, pixel fisico e formato de host;
- reduz superficie de manutencao ao evitar suporte duplo RGB565/RGBA8888.
**Contras:**
- quebra grande de HAL/VM/testes/assets;
- dobra memoria dos framebuffers;
- pode piorar portateis baratos se tudo for CPU;
- remove RGB565 como caminho barato;
- exige migracao coordenada de fixtures, geradores de asset e syscalls.
**Manutenibilidade:** direcao aceita nesta agenda. A migracao e agressiva, mas
o resultado final e mais simples porque ha um unico formato fisico e logico.
### Opcao C - Suportar ambos via backend/pixel format desde ja
**Abordagem:** introduzir abstracao de backend/pixel format agora, com renderer
capaz de materializar RGB565 ou RGBA8888.
**Pros:**
- hardware agnostico desde o inicio;
- desktop e bare-metal podem escolher formatos naturais;
- evita uma aposta unica.
**Contras:**
- alto risco de refatoracao ampla;
- pode criar abstracao prematura;
- `Gfx` pode virar god object;
- testes dobram;
- mistura pixel format com backend abstraction antes de consolidar cor logica.
**Manutenibilidade:** boa se bem delimitada, ruim se virar uma matriz de
formatos espalhada pelo renderer.
**Status nesta agenda:** rejeitada. Suporte duplo e compatibilidade RGB565
ficam fora de escopo.
### Opcao D - RGBA8888 como cor logica, backends RGB565/RGBA8888 como destino
**Abordagem:** separar primeiro cor logica de formato fisico. Introduzir tipos
explicitos `ColorRgba8888` e `ColorRgb565`; preservar asset v1 e backend atual;
permitir que paletas/assets resolvam para cor logica ou para formato de backend
em caches preparados; migrar `Gfx`/host em etapas.
**Pros:**
- separa identidade artistica de formato de memoria;
- preserva RGB565 para targets baratos;
- prepara RGBA8888 para Hub e backends modernos;
- permite migracao incremental;
- evita mexer em render thread/GPU/asset v2 de uma vez;
- reduz confusao entre logical color e physical pixel.
**Contras:**
- adiciona tipos e conversoes;
- exige disciplina para nao converter por pixel no hot path;
- precisa planejar compatibilidade VM/HAL;
- pode manter dois mundos por um tempo.
**Manutenibilidade:** melhor equilibrio se a primeira etapa for pequena e
explícita: tipos, conversoes e fronteiras; nao backend completo imediato.
**Status nesta agenda:** rejeitada pela direcao atual. Manter RGB565 como
backend valido criaria exatamente a compatibilidade que queremos evitar.
## Sugestao / Recomendacao
Recomendacao atual: seguir pela Opcao B.
Ou seja:
- tratar RGBA8888 como formato logico e fisico unico do runtime;
- remover RGB565 por completo do contrato normal;
- preservar assets indexados/paletizados e limites artisticos;
- migrar `Gfx` para buffers RGBA8888;
- atualizar HAL, VM/syscalls, host, testes, paletas e asset tooling para
RGBA8888;
- atualizar specs, docs publicos e contratos ABI para remover RGB565,
`Gfx*565`, `u16` como contrato de cor/framebuffer e paletas RGB565;
- nao introduzir render thread, GPU backend ou abstracao multi-backend no mesmo
passo.
A identidade 16-bit/fantasy console deve ser preservada por resolucao,
paletas, assets, regras de autoria e estilo visual, nao pelo fato de todo
framebuffer fisico ser RGB565.
O caminho incremental mais seguro parece:
1. Definir o tipo de cor RGBA8888 canonico:
- `Color` pode mudar para RGBA8888, ou ser substituido por
`ColorRgba8888`;
- a representacao raw deve ser `u32` ou bytes RGBA8 documentados;
- alpha `255` deve ser o default para cores opacas.
2. Remover o contrato RGB565 do HAL/VM:
- trocar `front_buffer() -> &[u16]`;
- remover APIs de compatibilidade com sufixo de formato, como
`GfxClear565` ou qualquer superficie `Gfx*565`, e substitui-las por nomes
canonicos format-neutral, como `GfxClear`;
- atualizar validacoes de range de cor de `0xFFFF` para RGBA8888;
- atualizar testes que comparam `Color::raw()` como `u16`.
2b. Atualizar contratos publicados:
- specs canonicas;
- docs publicos;
- contratos ABI/syscall;
- qualquer documento que ainda descreva RGB565, `Gfx*565`, `u16` como cor
ou framebuffer, ou paletas RGB565.
3. Atualizar constantes e helpers:
- cores passam a ter representacao logica clara;
- `COLOR_KEY` deve virar semantica de transparencia/mascara, nao magenta
em RGB565.
4. Migrar `Gfx` para RGBA8888:
- `front/back: Vec<u32>` ou storage equivalente;
- `RenderTarget` em RGBA8888;
- `blend_rgb565` substituido por blend RGBA8888;
- fade, fill, text, tile draw e sprite draw atualizados.
5. Migrar paletas e asset tooling:
- payload de paleta deixa de ser RGB565;
- `GlyphBank.palettes` passa para RGBA8888;
- `pbxgen-stress`, fixtures e testes acompanham;
- indices de paleta deixam de carregar semantica especial de transparencia.
6. Atualizar host/window layer:
- remover `draw_rgb565_to_rgba8` do caminho normal;
- copiar/publicar RGBA8888 para `pixels` com ordem correta;
- manter overlay compativel com frame RGBA8.
7. Validar visual e performance:
- testes unitarios atualizados;
- testes de render/fade/blend;
- snapshots ou verificacoes visuais quando disponiveis;
- medicao de custo do novo frame RGBA8888.
8. Deixar explicitamente para depois:
- render thread;
- GPU backend;
- backend RGB565;
- abstracao multi-formato;
- mudancas esteticas nao necessarias para a migracao.
## Perguntas em Aberto
- [x] Queremos declarar RGBA8888 como formato logico de cor do runtime, ou
apenas como um backend fisico adicional? RGBA8888 deve ser formato logico e
fisico unico.
- [x] A VM/PBS deve continuar aceitando valores RGB565 brutos como contrato de
compatibilidade? Nao. RGB565 nao deve permanecer como compatibilidade.
- [x] `GfxClear565` deve ganhar uma syscall nova RGBA/logical color antes de
qualquer deprecacao? Nao como API com sufixo de formato. APIs criadas para
compatibilidade RGB565, como `GfxClear565` ou qualquer superficie `Gfx*565`,
devem deixar de existir; o contrato canonico deve usar nomes format-neutral,
como `GfxClear`.
- [x] `Color` deve ser renomeado para `ColorRgb565` primeiro, ou deve mudar de
semantica para RGBA com um tipo RGB565 separado? A direcao aceita e que o
contrato final exponha RGBA8888; detalhes de rename ficam para decisao/plano.
- [x] O asset `.pa` v1 deve permanecer RGB565 ate haver necessidade de `.pa` v2?
Nao como estado final desta frente. Paletas devem migrar para RGBA8888.
- [x] Paletas carregadas devem guardar RGB565, RGBA8888, ou tabelas preparadas
por backend? RGBA8888.
- [x] Alpha real deve ser permitido em paletas, em sprites separados, ou apenas
em comandos/effects/UI por enquanto? Alpha real deve ser permitido em
qualquer paleta, sprite, tile e demais superficies/elementos que precisarem
dele. Comandos dedicados para gerenciar somente alpha serao necessarios, mas
ficam fora desta wave.
- [x] Quais operacoes podem usar alpha no primeiro corte sem comprometer custo?
Todas as operacoes podem usar alpha no primeiro corte. A direcao e tudo ou
nada; otimizacao e especializacao de caminhos ficam para depois.
- [x] O backend RGBA8888 deve ser implementado primeiro no CPU renderer ou no
host desktop? No CPU renderer existente, com host atualizado para consumir
RGBA8888.
- [x] Quais testes visuais/snapshots definem equivalencia aceitavel entre
RGB565 e RGBA8888? Como RGB565 sai, equivalencia deve ser apenas de
intencao visual/composicao, nao igualdade binaria. Todos os testes devem ser
RGBA8888-first.
- [x] A decisao antiga de `AGD-0010` contra RGBA8888 no `back` continua valida
apenas para aquela fase de performance, ou deve ser substituida por uma nova
direcao mais ampla? Deve ser substituida por nova decisao especifica desta
agenda.
- [x] Qual ordem raw deve ser canonica para `u32`/bytes: RGBA, ABGR, ARGB, ou
a ordem esperada pelo `pixels` frame? RGBA.
- [x] Alpha no framebuffer final deve ser sempre `255` apos composicao, ou o
front buffer pode publicar alpha significativo? Por enquanto, o front buffer
pode publicar alpha significativo. A diretriz deve forcar o minimo possivel
e dar liberdade ao desenvolvedor.
- [x] O asset package deve mudar versao/formato explicitamente para paletas
RGBA8888 ou apenas reinterpretar metadata existente? O asset package deve
usar paletas em formato RGBA8888, sem compatibilidade com paletas RGB565,
mesmo que isso quebre assets existentes.
## Criterio para Encerrar
Esta agenda pode ser encerrada quando houver acordo sobre:
- RGBA8888 como cor logica e formato fisico unico;
- RGB565 sem papel de compatibilidade nesta frente;
- como preservar a identidade fantasy console;
- como migrar asset package, VM/HAL, host, testes e renderer;
- quais conversoes temporarias sao aceitaveis apenas durante a migracao;
- qual e a ordem incremental de substituicao;
- o que fica explicitamente fora de escopo, especialmente render thread, GPU
backend e suporte multi-formato.
Com essas respostas, a agenda deve virar uma decisao normativa antes de
qualquer edicao de spec ou codigo.
## Discussao
Entrada inicial: avaliar cuidadosamente a viabilidade de migrar o Prometeu de
RGB565 para RGBA8888, considerando estado atual do codigo, trade-offs,
compatibilidade de assets, hardware agnostico, VM/render thread, plano
incremental, riscos e uma recomendacao arquitetural.
Analise inicial, agora superada parcialmente: a migracao e viavel, mas nao
deve ser feita como troca mecanica e isolada de `u16` por `u32`. A primeira
versao da agenda considerava separar cor logica, formato fisico de framebuffer,
formato serializado de assets e formato de apresentacao do backend, preservando
RGB565 como compatibilidade. Essa preservacao nao e mais a direcao aceita.
Atualizacao em 2026-05-23: a direcao da agenda mudou para Opcao B. RGB565 deve
sair por completo, sem compatibilidade. RGBA8888 deve ser o formato unico
fisico e logico. O escopo desta frente deve ser somente migrar RGB565 para
RGBA8888 no runtime/HAL/renderer/host/assets/testes atuais, sem abrir
multi-backend, render thread ou GPU backend.
Atualizacao em 2026-05-23: as perguntas restantes foram fechadas. Alpha real
e permitido amplamente em paletas, sprites, tiles e demais operacoes; comandos
especificos para gerenciar somente alpha ficam fora desta wave. O primeiro
corte aceita alpha em todas as operacoes, deixando otimizacoes para depois.
Testes devem ser RGBA8888-first. A ordem raw canonica e RGBA. O front buffer
pode publicar alpha significativo por enquanto. O asset package deve usar
paletas RGBA8888 sem compatibilidade com assets RGB565 existentes.
## Resolucao
A agenda esta pronta para ser aceita e convertida em decisao normativa. A
direcao atual e migrar tudo para RGBA8888 como formato unico fisico e logico,
removendo RGB565 sem compatibilidade. A decisao deve cristalizar:
- RGBA8888 como contrato logico e fisico unico;
- ordem raw canonica RGBA;
- alpha significativo permitido no framebuffer publicado;
- alpha permitido em paletas, sprites, tiles e operacoes do renderer;
- comandos dedicados de alpha fora desta wave;
- testes RGBA8888-first;
- asset package com paletas RGBA8888 sem compatibilidade RGB565;
- specs, docs e contratos ABI atualizados como parte obrigatoria da propagacao;
- render thread, GPU backend, backend RGB565 e suporte multi-formato fora de
escopo.