implements PLN-0081 shell hub packet migration
This commit is contained in:
parent
ae85ed4eff
commit
74df4b89ac
@ -5,7 +5,7 @@ use prometeu_hal::glyph_bank::GlyphBank;
|
||||
use prometeu_hal::scene_viewport_cache::{CachedTileEntry, SceneViewportCache};
|
||||
use prometeu_hal::scene_viewport_resolver::{LayerCopyRequest, ResolverUpdate};
|
||||
use prometeu_hal::sprite::Sprite;
|
||||
use prometeu_hal::{Game2DFramePacket, Gfx2dCommand, GfxBridge};
|
||||
use prometeu_hal::{Game2DFramePacket, Gfx2dCommand, GfxBridge, GfxUiCommand, ShellUiFramePacket};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Blending modes inspired by classic 16-bit hardware.
|
||||
@ -714,6 +714,12 @@ impl Gfx {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_shell_ui_frame_packet(&mut self, packet: &ShellUiFramePacket) {
|
||||
for command in &packet.commands {
|
||||
self.apply_gfxui_command(command);
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_gfx2d_command(&mut self, command: &Gfx2dCommand) {
|
||||
match command {
|
||||
Gfx2dCommand::Clear { color } => self.clear(*color),
|
||||
@ -738,6 +744,30 @@ impl Gfx {
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_gfxui_command(&mut self, command: &GfxUiCommand) {
|
||||
match command {
|
||||
GfxUiCommand::Clear { color } => self.clear(*color),
|
||||
GfxUiCommand::FillRect { rect, color } => {
|
||||
self.fill_rect(rect.x, rect.y, rect.w, rect.h, *color);
|
||||
}
|
||||
GfxUiCommand::DrawLine { x0, y0, x1, y1, color } => {
|
||||
self.draw_line(*x0, *y0, *x1, *y1, *color);
|
||||
}
|
||||
GfxUiCommand::DrawCircle { x, y, radius, color } => {
|
||||
self.draw_circle(*x, *y, *radius, *color);
|
||||
}
|
||||
GfxUiCommand::DrawDisc { x, y, radius, border_color, fill_color } => {
|
||||
self.draw_disc(*x, *y, *radius, *border_color, *fill_color);
|
||||
}
|
||||
GfxUiCommand::DrawSquare { rect, border_color, fill_color } => {
|
||||
self.draw_square(rect.x, rect.y, rect.w, rect.h, *border_color, *fill_color);
|
||||
}
|
||||
GfxUiCommand::DrawText { x, y, text, color } => {
|
||||
self.draw_text(*x, *y, text, *color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn populate_layer_buckets(&mut self) {
|
||||
for bucket in self.layer_buckets.iter_mut() {
|
||||
bucket.clear();
|
||||
|
||||
@ -8,10 +8,10 @@ use crate::memory_banks::{
|
||||
};
|
||||
use crate::pad::Pad;
|
||||
use crate::touch::Touch;
|
||||
use prometeu_hal::Game2DFramePacket;
|
||||
use prometeu_hal::cartridge::AssetsPayloadSource;
|
||||
use prometeu_hal::sprite::Sprite;
|
||||
use prometeu_hal::{AssetBridge, AudioBridge, GfxBridge, HardwareBridge, PadBridge, TouchBridge};
|
||||
use prometeu_hal::{Game2DFramePacket, ShellUiFramePacket};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Aggregate structure for all virtual hardware peripherals.
|
||||
@ -72,6 +72,10 @@ impl HardwareBridge for Hardware {
|
||||
self.frame_composer.close_game2d_packet()
|
||||
}
|
||||
|
||||
fn render_shell_ui_packet(&mut self, packet: &ShellUiFramePacket) {
|
||||
self.gfx.render_shell_ui_frame_packet(packet);
|
||||
}
|
||||
|
||||
fn render_frame(&mut self) {
|
||||
if self.frame_composer.active_scene_id().is_none() {
|
||||
let packet = self.frame_composer.close_game2d_packet();
|
||||
@ -81,6 +85,10 @@ impl HardwareBridge for Hardware {
|
||||
}
|
||||
}
|
||||
|
||||
fn present(&mut self) {
|
||||
self.gfx.present();
|
||||
}
|
||||
|
||||
fn has_glyph_bank(&self, bank_id: usize) -> bool {
|
||||
self.gfx.glyph_banks.glyph_bank_slot(bank_id).is_some()
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ use crate::asset_bridge::AssetBridge;
|
||||
use crate::audio_bridge::AudioBridge;
|
||||
use crate::gfx_bridge::GfxBridge;
|
||||
use crate::pad_bridge::PadBridge;
|
||||
use crate::render_submission::Game2DFramePacket;
|
||||
use crate::render_submission::{Game2DFramePacket, ShellUiFramePacket};
|
||||
use crate::sprite::Sprite;
|
||||
use crate::touch_bridge::TouchBridge;
|
||||
|
||||
@ -13,7 +13,9 @@ pub trait HardwareBridge {
|
||||
fn set_camera(&mut self, x: i32, y: i32);
|
||||
fn emit_sprite(&mut self, sprite: Sprite) -> bool;
|
||||
fn close_game2d_packet(&self) -> Game2DFramePacket;
|
||||
fn render_shell_ui_packet(&mut self, packet: &ShellUiFramePacket);
|
||||
fn render_frame(&mut self);
|
||||
fn present(&mut self);
|
||||
fn has_glyph_bank(&self, bank_id: usize) -> bool;
|
||||
|
||||
fn gfx(&self) -> &dyn GfxBridge;
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
use crate::{CrashReport, SystemOS};
|
||||
use prometeu_hal::color::Color;
|
||||
use prometeu_hal::gfx_bridge::GfxBridge;
|
||||
use prometeu_hal::primitives::Rect;
|
||||
use prometeu_hal::{HardwareBridge, InputSignals};
|
||||
use prometeu_hal::{GfxUiCommand, HardwareBridge, InputSignals, ShellUiFramePacket};
|
||||
use prometeu_vm::VirtualMachine;
|
||||
|
||||
const SHELL_A_BUTTON: Rect = Rect { x: 112, y: 108, w: 112, h: 48 };
|
||||
@ -101,8 +100,6 @@ impl PrometeuHub {
|
||||
os: &mut SystemOS,
|
||||
hw: &mut dyn HardwareBridge,
|
||||
) -> Option<SystemProfileAction> {
|
||||
hw.gfx_mut().clear(Color::INDIGO);
|
||||
|
||||
let in_shell = os.windows().focused_window().is_some();
|
||||
|
||||
if !in_shell {
|
||||
@ -127,21 +124,23 @@ impl PrometeuHub {
|
||||
let pointer_x = hw.touch().x();
|
||||
let pointer_y = hw.touch().y();
|
||||
|
||||
if os.windows().window_count() == 0 {
|
||||
render_home(hw.gfx_mut(), pointer_x, pointer_y);
|
||||
return;
|
||||
}
|
||||
|
||||
for window in os.windows().windows() {
|
||||
render_shell_window(
|
||||
hw.gfx_mut(),
|
||||
window.viewport,
|
||||
window.color,
|
||||
&window.title,
|
||||
pointer_x,
|
||||
pointer_y,
|
||||
);
|
||||
}
|
||||
let packet = if os.windows().window_count() == 0 {
|
||||
render_home_packet(pointer_x, pointer_y)
|
||||
} else {
|
||||
let mut commands = Vec::new();
|
||||
for window in os.windows().windows() {
|
||||
append_shell_window_commands(
|
||||
&mut commands,
|
||||
window.viewport,
|
||||
window.color,
|
||||
&window.title,
|
||||
pointer_x,
|
||||
pointer_y,
|
||||
);
|
||||
}
|
||||
ShellUiFramePacket::new(commands)
|
||||
};
|
||||
hw.render_shell_ui_packet(&packet);
|
||||
}
|
||||
|
||||
pub fn update_shell_profile(
|
||||
@ -163,7 +162,7 @@ impl PrometeuHub {
|
||||
}
|
||||
|
||||
self.render(os, hw);
|
||||
hw.gfx_mut().present();
|
||||
hw.present();
|
||||
|
||||
SystemProfileUpdate { crash, action }
|
||||
}
|
||||
@ -192,15 +191,29 @@ fn activation_input_down(hw: &dyn HardwareBridge) -> bool {
|
||||
hw.touch().f().down || hw.pad().a().down || hw.pad().b().down || hw.pad().start().down
|
||||
}
|
||||
|
||||
fn render_home(gfx: &mut dyn GfxBridge, pointer_x: i32, pointer_y: i32) {
|
||||
gfx.fill_rect(VIEWPORT.x, VIEWPORT.y, VIEWPORT.w, VIEWPORT.h, COLOR_BG);
|
||||
draw_panel(gfx, TITLE_PANEL, COLOR_PANEL_DARK, COLOR_BORDER);
|
||||
draw_buffer_text(gfx, TITLE_PANEL.x + 58, TITLE_PANEL.y + 9, "PROMETEU HUB", COLOR_TEXT);
|
||||
|
||||
draw_panel(gfx, HOME_PANEL, COLOR_PANEL, COLOR_BORDER);
|
||||
draw_buffer_text(gfx, HOME_PANEL.x + 26, HOME_PANEL.y + 22, "Native Shell Apps", COLOR_TEXT);
|
||||
fn render_home_packet(pointer_x: i32, pointer_y: i32) -> ShellUiFramePacket {
|
||||
let mut commands = Vec::new();
|
||||
commands.push(GfxUiCommand::Clear { color: COLOR_BG });
|
||||
fill_rect(&mut commands, VIEWPORT, COLOR_BG);
|
||||
draw_panel(&mut commands, TITLE_PANEL, COLOR_PANEL_DARK, COLOR_BORDER);
|
||||
draw_buffer_text(
|
||||
gfx,
|
||||
&mut commands,
|
||||
TITLE_PANEL.x + 58,
|
||||
TITLE_PANEL.y + 9,
|
||||
"PROMETEU HUB",
|
||||
COLOR_TEXT,
|
||||
);
|
||||
|
||||
draw_panel(&mut commands, HOME_PANEL, COLOR_PANEL, COLOR_BORDER);
|
||||
draw_buffer_text(
|
||||
&mut commands,
|
||||
HOME_PANEL.x + 26,
|
||||
HOME_PANEL.y + 22,
|
||||
"Native Shell Apps",
|
||||
COLOR_TEXT,
|
||||
);
|
||||
draw_buffer_text(
|
||||
&mut commands,
|
||||
HOME_PANEL.x + 26,
|
||||
HOME_PANEL.y + 40,
|
||||
"first retro ui slice",
|
||||
@ -209,50 +222,105 @@ fn render_home(gfx: &mut dyn GfxBridge, pointer_x: i32, pointer_y: i32) {
|
||||
|
||||
for button in HOME_BUTTONS {
|
||||
let hovered = rect_contains(button.rect, pointer_x, pointer_y);
|
||||
draw_button(gfx, button.rect, button.label, hovered);
|
||||
draw_button(&mut commands, button.rect, button.label, hovered);
|
||||
}
|
||||
|
||||
ShellUiFramePacket::new(commands)
|
||||
}
|
||||
|
||||
fn render_shell_window(
|
||||
gfx: &mut dyn GfxBridge,
|
||||
fn append_shell_window_commands(
|
||||
commands: &mut Vec<GfxUiCommand>,
|
||||
viewport: Rect,
|
||||
color: Color,
|
||||
title: &str,
|
||||
pointer_x: i32,
|
||||
pointer_y: i32,
|
||||
) {
|
||||
gfx.fill_rect(VIEWPORT.x, VIEWPORT.y, VIEWPORT.w, VIEWPORT.h, COLOR_BG);
|
||||
draw_panel(gfx, viewport, COLOR_PANEL_DARK, COLOR_BORDER);
|
||||
gfx.fill_rect(viewport.x + 4, viewport.y + 24, viewport.w - 8, viewport.h - 28, color);
|
||||
draw_buffer_text(gfx, viewport.x + 10, viewport.y + 8, title, COLOR_TEXT);
|
||||
draw_buffer_text(gfx, viewport.x + 18, viewport.y + 44, "native fake shell", COLOR_PANEL_DARK);
|
||||
fill_rect(commands, VIEWPORT, COLOR_BG);
|
||||
draw_panel(commands, viewport, COLOR_PANEL_DARK, COLOR_BORDER);
|
||||
fill_rect(
|
||||
commands,
|
||||
Rect { x: viewport.x + 4, y: viewport.y + 24, w: viewport.w - 8, h: viewport.h - 28 },
|
||||
color,
|
||||
);
|
||||
draw_buffer_text(commands, viewport.x + 10, viewport.y + 8, title, COLOR_TEXT);
|
||||
draw_buffer_text(
|
||||
commands,
|
||||
viewport.x + 18,
|
||||
viewport.y + 44,
|
||||
"native fake shell",
|
||||
COLOR_PANEL_DARK,
|
||||
);
|
||||
|
||||
let close_hovered = rect_contains(CLOSE_BUTTON, pointer_x, pointer_y);
|
||||
let close_fill = if close_hovered { COLOR_HILITE } else { COLOR_BUTTON };
|
||||
gfx.fill_rect(CLOSE_BUTTON.x, CLOSE_BUTTON.y, CLOSE_BUTTON.w, CLOSE_BUTTON.h, close_fill);
|
||||
gfx.draw_rect(CLOSE_BUTTON.x, CLOSE_BUTTON.y, CLOSE_BUTTON.w, CLOSE_BUTTON.h, COLOR_BORDER);
|
||||
draw_buffer_text(gfx, CLOSE_BUTTON.x + 5, CLOSE_BUTTON.y + 4, "x", COLOR_TEXT);
|
||||
fill_rect(commands, CLOSE_BUTTON, close_fill);
|
||||
draw_rect(commands, CLOSE_BUTTON, COLOR_BORDER);
|
||||
draw_buffer_text(commands, CLOSE_BUTTON.x + 5, CLOSE_BUTTON.y + 4, "x", COLOR_TEXT);
|
||||
}
|
||||
|
||||
fn draw_panel(gfx: &mut dyn GfxBridge, rect: Rect, fill: Color, border: Color) {
|
||||
gfx.fill_rect(rect.x, rect.y, rect.w, rect.h, fill);
|
||||
gfx.draw_rect(rect.x, rect.y, rect.w, rect.h, border);
|
||||
gfx.draw_rect(rect.x + 2, rect.y + 2, rect.w - 4, rect.h - 4, COLOR_MUTED);
|
||||
fn fill_rect(commands: &mut Vec<GfxUiCommand>, rect: Rect, color: Color) {
|
||||
commands.push(GfxUiCommand::FillRect { rect, color });
|
||||
}
|
||||
|
||||
fn draw_button(gfx: &mut dyn GfxBridge, rect: Rect, label: &str, hovered: bool) {
|
||||
fn draw_rect(commands: &mut Vec<GfxUiCommand>, rect: Rect, color: Color) {
|
||||
commands.push(GfxUiCommand::DrawLine {
|
||||
x0: rect.x,
|
||||
y0: rect.y,
|
||||
x1: rect.x + rect.w - 1,
|
||||
y1: rect.y,
|
||||
color,
|
||||
});
|
||||
commands.push(GfxUiCommand::DrawLine {
|
||||
x0: rect.x,
|
||||
y0: rect.y + rect.h - 1,
|
||||
x1: rect.x + rect.w - 1,
|
||||
y1: rect.y + rect.h - 1,
|
||||
color,
|
||||
});
|
||||
commands.push(GfxUiCommand::DrawLine {
|
||||
x0: rect.x,
|
||||
y0: rect.y,
|
||||
x1: rect.x,
|
||||
y1: rect.y + rect.h - 1,
|
||||
color,
|
||||
});
|
||||
commands.push(GfxUiCommand::DrawLine {
|
||||
x0: rect.x + rect.w - 1,
|
||||
y0: rect.y,
|
||||
x1: rect.x + rect.w - 1,
|
||||
y1: rect.y + rect.h - 1,
|
||||
color,
|
||||
});
|
||||
}
|
||||
|
||||
fn draw_panel(commands: &mut Vec<GfxUiCommand>, rect: Rect, fill: Color, border: Color) {
|
||||
fill_rect(commands, rect, fill);
|
||||
draw_rect(commands, rect, border);
|
||||
draw_rect(
|
||||
commands,
|
||||
Rect { x: rect.x + 2, y: rect.y + 2, w: rect.w - 4, h: rect.h - 4 },
|
||||
COLOR_MUTED,
|
||||
);
|
||||
}
|
||||
|
||||
fn draw_button(commands: &mut Vec<GfxUiCommand>, rect: Rect, label: &str, hovered: bool) {
|
||||
let fill = if hovered { COLOR_BUTTON_ACTIVE } else { COLOR_BUTTON };
|
||||
let border = if hovered { COLOR_HILITE } else { COLOR_BORDER };
|
||||
gfx.fill_rect(rect.x, rect.y, rect.w, rect.h, fill);
|
||||
gfx.draw_rect(rect.x, rect.y, rect.w, rect.h, border);
|
||||
gfx.draw_rect(rect.x + 3, rect.y + 3, rect.w - 6, rect.h - 6, COLOR_MUTED);
|
||||
gfx.fill_rect(rect.x + 12, rect.y + 12, 16, 24, border);
|
||||
gfx.draw_rect(rect.x + 34, rect.y + 12, 62, 24, COLOR_PANEL_DARK);
|
||||
draw_buffer_text(gfx, rect.x + 40, rect.y + 21, label, COLOR_TEXT);
|
||||
fill_rect(commands, rect, fill);
|
||||
draw_rect(commands, rect, border);
|
||||
draw_rect(
|
||||
commands,
|
||||
Rect { x: rect.x + 3, y: rect.y + 3, w: rect.w - 6, h: rect.h - 6 },
|
||||
COLOR_MUTED,
|
||||
);
|
||||
fill_rect(commands, Rect { x: rect.x + 12, y: rect.y + 12, w: 16, h: 24 }, border);
|
||||
draw_rect(commands, Rect { x: rect.x + 34, y: rect.y + 12, w: 62, h: 24 }, COLOR_PANEL_DARK);
|
||||
draw_buffer_text(commands, rect.x + 40, rect.y + 21, label, COLOR_TEXT);
|
||||
}
|
||||
|
||||
fn draw_buffer_text(gfx: &mut dyn GfxBridge, x: i32, y: i32, text: &str, color: Color) {
|
||||
gfx.draw_text(x, y, text, color);
|
||||
fn draw_buffer_text(commands: &mut Vec<GfxUiCommand>, x: i32, y: i32, text: &str, color: Color) {
|
||||
commands.push(GfxUiCommand::DrawText { x, y, text: text.to_string(), color });
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -321,6 +389,16 @@ mod tests {
|
||||
assert_eq!(HOME_BUTTONS[1].app, NativeShellApp::ShellB);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn home_render_produces_shell_ui_packet_commands() {
|
||||
let packet = render_home_packet(SHELL_A_BUTTON.x, SHELL_A_BUTTON.y);
|
||||
|
||||
assert!(matches!(packet.commands.first(), Some(GfxUiCommand::Clear { .. })));
|
||||
assert!(packet.commands.iter().any(|command| {
|
||||
matches!(command, GfxUiCommand::DrawText { text, .. } if text == "PROMETEU HUB")
|
||||
}));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shell_close_button_sits_inside_shell_frame() {
|
||||
assert!(rect_contains(SHELL_FRAME, CLOSE_BUTTON.x, CLOSE_BUTTON.y));
|
||||
|
||||
@ -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":"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":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0075","file":"PLN-0075-rendermanager-core.md","status":"done","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":"done","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":"done","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":"done","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":"done","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":"done","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":"done","created_at":"2026-05-25","updated_at":"2026-05-25","ref_decisions":["DEC-0030"]},{"id":"PLN-0075","file":"PLN-0075-rendermanager-core.md","status":"done","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":"done","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":"done","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":"done","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":"done","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":"done","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":"done","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-0081
|
||||
ticket: render-frame-packet-boundary
|
||||
title: Shell Hub Migration
|
||||
status: open
|
||||
status: done
|
||||
created: 2026-05-25
|
||||
ref_decisions: [DEC-0030]
|
||||
tags: [gfx, renderer, runtime, frame-composer, architecture, ui, pipeline]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user