dev/runtime-owned-variable-glyph-bank-palette-protocol #37
@ -1212,7 +1212,7 @@ impl AssetManager {
|
|||||||
&buffer[packed_pixel_bytes..packed_pixel_bytes + GLYPH_BANK_PALETTE_BYTES_V1];
|
&buffer[packed_pixel_bytes..packed_pixel_bytes + GLYPH_BANK_PALETTE_BYTES_V1];
|
||||||
|
|
||||||
let mut palettes =
|
let mut palettes =
|
||||||
[[Color::BLACK; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1];
|
vec![[Color::BLACK; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1];
|
||||||
for (p, pal) in palettes.iter_mut().enumerate() {
|
for (p, pal) in palettes.iter_mut().enumerate() {
|
||||||
for (c, slot) in pal.iter_mut().enumerate() {
|
for (c, slot) in pal.iter_mut().enumerate() {
|
||||||
let offset = (p * 16 + c) * 4;
|
let offset = (p * 16 + c) * 4;
|
||||||
@ -1247,7 +1247,7 @@ impl AssetManager {
|
|||||||
.map_err(|_| "Buffer too small for GLYPHBANK".to_string())?;
|
.map_err(|_| "Buffer too small for GLYPHBANK".to_string())?;
|
||||||
|
|
||||||
let mut palettes =
|
let mut palettes =
|
||||||
[[Color::BLACK; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1];
|
vec![[Color::BLACK; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1];
|
||||||
for (p, pal) in palettes.iter_mut().enumerate() {
|
for (p, pal) in palettes.iter_mut().enumerate() {
|
||||||
for (c, slot) in pal.iter_mut().enumerate() {
|
for (c, slot) in pal.iter_mut().enumerate() {
|
||||||
let offset = (p * 16 + c) * 4;
|
let offset = (p * 16 + c) * 4;
|
||||||
|
|||||||
@ -557,8 +557,9 @@ mod tests {
|
|||||||
|
|
||||||
fn make_glyph_bank(tile_size: TileSize, palette_id: u8, color: Color) -> GlyphBank {
|
fn make_glyph_bank(tile_size: TileSize, palette_id: u8, color: Color) -> GlyphBank {
|
||||||
let size = tile_size as usize;
|
let size = tile_size as usize;
|
||||||
let mut bank = GlyphBank::new(tile_size, size, size);
|
let mut bank =
|
||||||
bank.palettes[palette_id as usize][1] = color;
|
GlyphBank::with_palette_count(tile_size, size, size, palette_id as usize + 1);
|
||||||
|
bank.palette_mut(palette_id).unwrap()[1] = color;
|
||||||
for pixel in &mut bank.pixel_indices {
|
for pixel in &mut bank.pixel_indices {
|
||||||
*pixel = 1;
|
*pixel = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -812,7 +812,10 @@ impl Gfx {
|
|||||||
let fetch_x = if tile.entry.flip_x() { size - 1 - local_x } else { local_x };
|
let fetch_x = if tile.entry.flip_x() { size - 1 - local_x } else { local_x };
|
||||||
let fetch_y = if tile.entry.flip_y() { size - 1 - local_y } else { local_y };
|
let fetch_y = if tile.entry.flip_y() { size - 1 - local_y } else { local_y };
|
||||||
let px_index = tile.bank.get_pixel_index(tile.entry.glyph_id, fetch_x, fetch_y);
|
let px_index = tile.bank.get_pixel_index(tile.entry.glyph_id, fetch_x, fetch_y);
|
||||||
let color = tile.bank.resolve_color(tile.entry.palette_id, px_index);
|
let color = tile
|
||||||
|
.bank
|
||||||
|
.resolve_color(tile.entry.palette_id, px_index)
|
||||||
|
.unwrap_or(Color::TRANSPARENT);
|
||||||
if color.alpha() == 0 {
|
if color.alpha() == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -862,7 +865,9 @@ impl Gfx {
|
|||||||
let fetch_y = if sprite.flip_y { size - 1 - local_y } else { local_y };
|
let fetch_y = if sprite.flip_y { size - 1 - local_y } else { local_y };
|
||||||
|
|
||||||
let px_index = bank.get_pixel_index(sprite.glyph.glyph_id, fetch_x, fetch_y);
|
let px_index = bank.get_pixel_index(sprite.glyph.glyph_id, fetch_x, fetch_y);
|
||||||
let color = bank.resolve_color(sprite.glyph.palette_id, px_index);
|
let color = bank
|
||||||
|
.resolve_color(sprite.glyph.palette_id, px_index)
|
||||||
|
.unwrap_or(Color::TRANSPARENT);
|
||||||
if color.alpha() == 0 {
|
if color.alpha() == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1010,9 +1015,14 @@ mod tests {
|
|||||||
|
|
||||||
fn make_glyph_bank(tile_size: TileSize, palette_colors: &[(u8, u8, Color)]) -> GlyphBank {
|
fn make_glyph_bank(tile_size: TileSize, palette_colors: &[(u8, u8, Color)]) -> GlyphBank {
|
||||||
let size = tile_size as usize;
|
let size = tile_size as usize;
|
||||||
let mut bank = GlyphBank::new(tile_size, size, size);
|
let palette_count = palette_colors
|
||||||
|
.iter()
|
||||||
|
.map(|(palette_id, _, _)| *palette_id as usize + 1)
|
||||||
|
.max()
|
||||||
|
.unwrap_or(1);
|
||||||
|
let mut bank = GlyphBank::with_palette_count(tile_size, size, size, palette_count);
|
||||||
for (palette_id, color_index, color) in palette_colors {
|
for (palette_id, color_index, color) in palette_colors {
|
||||||
bank.palettes[*palette_id as usize][*color_index as usize] = *color;
|
bank.palette_mut(*palette_id).unwrap()[*color_index as usize] = *color;
|
||||||
}
|
}
|
||||||
bank
|
bank
|
||||||
}
|
}
|
||||||
|
|||||||
@ -261,7 +261,7 @@ mod tests {
|
|||||||
|
|
||||||
fn make_glyph_bank() -> GlyphBank {
|
fn make_glyph_bank() -> GlyphBank {
|
||||||
let mut bank = GlyphBank::new(TileSize::Size8, 8, 8);
|
let mut bank = GlyphBank::new(TileSize::Size8, 8, 8);
|
||||||
bank.palettes[0][1] = Color::RED;
|
bank.palette_mut(0).unwrap()[1] = Color::RED;
|
||||||
for pixel in &mut bank.pixel_indices {
|
for pixel in &mut bank.pixel_indices {
|
||||||
*pixel = 1;
|
*pixel = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -196,7 +196,7 @@ mod tests {
|
|||||||
|
|
||||||
fn make_glyph_bank() -> GlyphBank {
|
fn make_glyph_bank() -> GlyphBank {
|
||||||
let mut bank = GlyphBank::new(TileSize::Size8, 8, 8);
|
let mut bank = GlyphBank::new(TileSize::Size8, 8, 8);
|
||||||
bank.palettes[0][1] = Color::WHITE;
|
bank.palette_mut(0).unwrap()[1] = Color::WHITE;
|
||||||
bank
|
bank
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -203,7 +203,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::asset::{AssetCodec, AssetEntry, BankType, PreloadEntry};
|
use crate::asset::{AssetCodec, AssetEntry, BankType, PreloadEntry};
|
||||||
use crate::cartridge::{ASSETS_PA_MAGIC, ASSETS_PA_SCHEMA_VERSION, AssetsPackPrelude};
|
use crate::cartridge::{ASSETS_PA_MAGIC, ASSETS_PA_SCHEMA_VERSION, AssetsPackPrelude};
|
||||||
use crate::glyph_bank::GLYPH_BANK_PALETTE_COUNT_V1;
|
use crate::glyph_bank::GLYPH_BANK_MAX_PALETTE_COUNT_V1;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
@ -369,14 +369,14 @@ mod tests {
|
|||||||
bank_type: BankType::GLYPH,
|
bank_type: BankType::GLYPH,
|
||||||
offset,
|
offset,
|
||||||
size,
|
size,
|
||||||
decoded_size: 16 * 16 + (GLYPH_BANK_PALETTE_COUNT_V1 as u64 * 16 * 4),
|
decoded_size: 16 * 16 + (GLYPH_BANK_MAX_PALETTE_COUNT_V1 as u64 * 16 * 4),
|
||||||
codec: AssetCodec::None,
|
codec: AssetCodec::None,
|
||||||
metadata: json!({
|
metadata: json!({
|
||||||
"tile_size": 16,
|
"tile_size": 16,
|
||||||
"width": 16,
|
"width": 16,
|
||||||
"height": 16,
|
"height": 16,
|
||||||
"palette_count": GLYPH_BANK_PALETTE_COUNT_V1,
|
"palette_count": GLYPH_BANK_MAX_PALETTE_COUNT_V1,
|
||||||
"palette_authored": GLYPH_BANK_PALETTE_COUNT_V1
|
"palette_authored": GLYPH_BANK_MAX_PALETTE_COUNT_V1
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -452,14 +452,14 @@ mod tests {
|
|||||||
bank_type: BankType::GLYPH,
|
bank_type: BankType::GLYPH,
|
||||||
offset: 4,
|
offset: 4,
|
||||||
size: 4,
|
size: 4,
|
||||||
decoded_size: 16 * 16 + (GLYPH_BANK_PALETTE_COUNT_V1 as u64 * 16 * 4),
|
decoded_size: 16 * 16 + (GLYPH_BANK_MAX_PALETTE_COUNT_V1 as u64 * 16 * 4),
|
||||||
codec: AssetCodec::None,
|
codec: AssetCodec::None,
|
||||||
metadata: json!({
|
metadata: json!({
|
||||||
"tile_size": 16,
|
"tile_size": 16,
|
||||||
"width": 16,
|
"width": 16,
|
||||||
"height": 16,
|
"height": 16,
|
||||||
"palette_count": GLYPH_BANK_PALETTE_COUNT_V1,
|
"palette_count": GLYPH_BANK_MAX_PALETTE_COUNT_V1,
|
||||||
"palette_authored": GLYPH_BANK_PALETTE_COUNT_V1
|
"palette_authored": GLYPH_BANK_MAX_PALETTE_COUNT_V1
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -519,8 +519,8 @@ mod tests {
|
|||||||
"tile_size": 16,
|
"tile_size": 16,
|
||||||
"width": 16,
|
"width": 16,
|
||||||
"height": 16,
|
"height": 16,
|
||||||
"palette_count": GLYPH_BANK_PALETTE_COUNT_V1,
|
"palette_count": GLYPH_BANK_MAX_PALETTE_COUNT_V1,
|
||||||
"palette_authored": GLYPH_BANK_PALETTE_COUNT_V1
|
"palette_authored": GLYPH_BANK_MAX_PALETTE_COUNT_V1
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
"preload": []
|
"preload": []
|
||||||
@ -561,8 +561,8 @@ mod tests {
|
|||||||
"tile_size": 16,
|
"tile_size": 16,
|
||||||
"width": 16,
|
"width": 16,
|
||||||
"height": 16,
|
"height": 16,
|
||||||
"palette_count": GLYPH_BANK_PALETTE_COUNT_V1,
|
"palette_count": GLYPH_BANK_MAX_PALETTE_COUNT_V1,
|
||||||
"palette_authored": GLYPH_BANK_PALETTE_COUNT_V1
|
"palette_authored": GLYPH_BANK_MAX_PALETTE_COUNT_V1
|
||||||
}
|
}
|
||||||
}],
|
}],
|
||||||
"preload": []
|
"preload": []
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::color::Color;
|
use crate::color::Color;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub const GLYPH_BANK_PALETTE_COUNT_V1: usize = 64;
|
pub const GLYPH_BANK_MAX_PALETTE_COUNT_V1: usize = 64;
|
||||||
pub const GLYPH_BANK_COLORS_PER_PALETTE: usize = 16;
|
pub const GLYPH_BANK_COLORS_PER_PALETTE: usize = 16;
|
||||||
|
|
||||||
/// Standard sizes for square tiles.
|
/// Standard sizes for square tiles.
|
||||||
@ -35,22 +35,59 @@ pub struct GlyphBank {
|
|||||||
/// Palette indices are ordinary indices; transparency is resolved through
|
/// Palette indices are ordinary indices; transparency is resolved through
|
||||||
/// the RGBA alpha channel of the palette entry.
|
/// the RGBA alpha channel of the palette entry.
|
||||||
pub pixel_indices: Vec<u8>,
|
pub pixel_indices: Vec<u8>,
|
||||||
/// Runtime-facing v1 palette table: 64 palettes of 16 RGBA8888 colors each.
|
/// Runtime-facing v1 palette table.
|
||||||
pub palettes: [[Color; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1],
|
///
|
||||||
|
/// Palette identity is the direct index in this vector. A resident glyph
|
||||||
|
/// bank carries exactly the palettes materialized from its payload.
|
||||||
|
pub palettes: Vec<[Color; GLYPH_BANK_COLORS_PER_PALETTE]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GlyphBank {
|
impl GlyphBank {
|
||||||
/// Creates an empty glyph bank with the specified dimensions.
|
/// Creates an empty glyph bank with one palette.
|
||||||
pub fn new(tile_size: TileSize, width: usize, height: usize) -> Self {
|
pub fn new(tile_size: TileSize, width: usize, height: usize) -> Self {
|
||||||
|
Self::with_palette_count(tile_size, width, height, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates an empty glyph bank with the specified resident palette count.
|
||||||
|
pub fn with_palette_count(
|
||||||
|
tile_size: TileSize,
|
||||||
|
width: usize,
|
||||||
|
height: usize,
|
||||||
|
palette_count: usize,
|
||||||
|
) -> Self {
|
||||||
|
assert!(
|
||||||
|
(1..=GLYPH_BANK_MAX_PALETTE_COUNT_V1).contains(&palette_count),
|
||||||
|
"glyph bank palette_count must be in 1..={}",
|
||||||
|
GLYPH_BANK_MAX_PALETTE_COUNT_V1
|
||||||
|
);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
tile_size,
|
tile_size,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
pixel_indices: vec![0; width * height],
|
pixel_indices: vec![0; width * height],
|
||||||
palettes: [[Color::BLACK; GLYPH_BANK_COLORS_PER_PALETTE]; GLYPH_BANK_PALETTE_COUNT_V1],
|
palettes: vec![[Color::BLACK; GLYPH_BANK_COLORS_PER_PALETTE]; palette_count],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the number of resident palettes.
|
||||||
|
pub fn palette_count(&self) -> usize {
|
||||||
|
self.palettes.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true when the palette id is valid for this resident bank.
|
||||||
|
pub fn contains_palette(&self, palette_id: u8) -> bool {
|
||||||
|
(palette_id as usize) < self.palette_count()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable palette slot when the palette exists.
|
||||||
|
pub fn palette_mut(
|
||||||
|
&mut self,
|
||||||
|
palette_id: u8,
|
||||||
|
) -> Option<&mut [Color; GLYPH_BANK_COLORS_PER_PALETTE]> {
|
||||||
|
self.palettes.get_mut(palette_id as usize)
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolves a global tile ID and local pixel coordinates to a palette index.
|
/// Resolves a global tile ID and local pixel coordinates to a palette index.
|
||||||
/// tile_id: the tile index in the bank
|
/// tile_id: the tile index in the bank
|
||||||
/// local_x, local_y: the pixel position inside the tile (0 to tile_size-1)
|
/// local_x, local_y: the pixel position inside the tile (0 to tile_size-1)
|
||||||
@ -71,11 +108,48 @@ impl GlyphBank {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Maps a 4-bit index to a real RGBA8888 Color using the specified palette.
|
/// Maps a 4-bit index to a real RGBA8888 Color using the specified palette.
|
||||||
pub fn resolve_color(&self, palette_id: u8, pixel_index: u8) -> Color {
|
pub fn resolve_color(&self, palette_id: u8, pixel_index: u8) -> Option<Color> {
|
||||||
self.palettes
|
self.palettes
|
||||||
.get(palette_id as usize)
|
.get(palette_id as usize)
|
||||||
.and_then(|palette| palette.get(pixel_index as usize))
|
.and_then(|palette| palette.get(pixel_index as usize))
|
||||||
.copied()
|
.copied()
|
||||||
.unwrap_or(Color::TRANSPARENT)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn new_glyph_bank_uses_single_resident_palette() {
|
||||||
|
let bank = GlyphBank::new(TileSize::Size8, 8, 8);
|
||||||
|
|
||||||
|
assert_eq!(bank.palette_count(), 1);
|
||||||
|
assert!(bank.contains_palette(0));
|
||||||
|
assert!(!bank.contains_palette(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn glyph_bank_can_materialize_v1_max_palette_count() {
|
||||||
|
let bank =
|
||||||
|
GlyphBank::with_palette_count(TileSize::Size8, 8, 8, GLYPH_BANK_MAX_PALETTE_COUNT_V1);
|
||||||
|
|
||||||
|
assert_eq!(bank.palette_count(), GLYPH_BANK_MAX_PALETTE_COUNT_V1);
|
||||||
|
assert!(bank.contains_palette((GLYPH_BANK_MAX_PALETTE_COUNT_V1 - 1) as u8));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn invalid_palette_lookup_is_distinct_from_transparent_color() {
|
||||||
|
let mut bank = GlyphBank::new(TileSize::Size8, 8, 8);
|
||||||
|
bank.palette_mut(0).unwrap()[1] = Color::TRANSPARENT;
|
||||||
|
|
||||||
|
assert_eq!(bank.resolve_color(0, 1), Some(Color::TRANSPARENT));
|
||||||
|
assert_eq!(bank.resolve_color(1, 1), None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic(expected = "glyph bank palette_count must be in 1..=64")]
|
||||||
|
fn glyph_bank_rejects_zero_resident_palettes() {
|
||||||
|
let _ = GlyphBank::with_palette_count(TileSize::Size8, 8, 8, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ use prometeu_hal::asset::{
|
|||||||
use prometeu_hal::cartridge::{AssetsPayloadSource, Cartridge};
|
use prometeu_hal::cartridge::{AssetsPayloadSource, Cartridge};
|
||||||
use prometeu_hal::color::Color;
|
use prometeu_hal::color::Color;
|
||||||
use prometeu_hal::glyph::Glyph;
|
use prometeu_hal::glyph::Glyph;
|
||||||
use prometeu_hal::glyph_bank::{GLYPH_BANK_PALETTE_COUNT_V1, GlyphBank, TileSize};
|
use prometeu_hal::glyph_bank::{GLYPH_BANK_MAX_PALETTE_COUNT_V1, GlyphBank, TileSize};
|
||||||
use prometeu_hal::scene_bank::SceneBank;
|
use prometeu_hal::scene_bank::SceneBank;
|
||||||
use prometeu_hal::scene_layer::{ParallaxFactor, SceneLayer};
|
use prometeu_hal::scene_layer::{ParallaxFactor, SceneLayer};
|
||||||
use prometeu_hal::syscalls::caps;
|
use prometeu_hal::syscalls::caps;
|
||||||
@ -113,11 +113,12 @@ fn serialized_single_function_module_with_consts(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn test_glyph_payload_size(width: usize, height: usize) -> usize {
|
fn test_glyph_payload_size(width: usize, height: usize) -> usize {
|
||||||
(width * height).div_ceil(2) + (GLYPH_BANK_PALETTE_COUNT_V1 * 16 * std::mem::size_of::<u32>())
|
(width * height).div_ceil(2)
|
||||||
|
+ (GLYPH_BANK_MAX_PALETTE_COUNT_V1 * 16 * std::mem::size_of::<u32>())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_glyph_decoded_size(width: usize, height: usize) -> usize {
|
fn test_glyph_decoded_size(width: usize, height: usize) -> usize {
|
||||||
width * height + (GLYPH_BANK_PALETTE_COUNT_V1 * 16 * std::mem::size_of::<u32>())
|
width * height + (GLYPH_BANK_MAX_PALETTE_COUNT_V1 * 16 * std::mem::size_of::<u32>())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_glyph_asset_entry(asset_name: &str, data_len: usize) -> AssetEntry {
|
fn test_glyph_asset_entry(asset_name: &str, data_len: usize) -> AssetEntry {
|
||||||
@ -133,23 +134,26 @@ fn test_glyph_asset_entry(asset_name: &str, data_len: usize) -> AssetEntry {
|
|||||||
"tile_size": 16,
|
"tile_size": 16,
|
||||||
"width": 16,
|
"width": 16,
|
||||||
"height": 16,
|
"height": 16,
|
||||||
"palette_count": GLYPH_BANK_PALETTE_COUNT_V1,
|
"palette_count": GLYPH_BANK_MAX_PALETTE_COUNT_V1,
|
||||||
"palette_authored": GLYPH_BANK_PALETTE_COUNT_V1
|
"palette_authored": GLYPH_BANK_MAX_PALETTE_COUNT_V1
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_glyph_asset_data() -> Vec<u8> {
|
fn test_glyph_asset_data() -> Vec<u8> {
|
||||||
let mut data =
|
let mut data =
|
||||||
vec![0x11u8; test_glyph_payload_size(16, 16) - (GLYPH_BANK_PALETTE_COUNT_V1 * 16 * 4)];
|
vec![
|
||||||
data.extend_from_slice(&[0u8; GLYPH_BANK_PALETTE_COUNT_V1 * 16 * 4]);
|
0x11u8;
|
||||||
|
test_glyph_payload_size(16, 16) - (GLYPH_BANK_MAX_PALETTE_COUNT_V1 * 16 * 4)
|
||||||
|
];
|
||||||
|
data.extend_from_slice(&[0u8; GLYPH_BANK_MAX_PALETTE_COUNT_V1 * 16 * 4]);
|
||||||
data
|
data
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runtime_test_glyph_bank(tile_size: TileSize, palette_id: u8, color: Color) -> GlyphBank {
|
fn runtime_test_glyph_bank(tile_size: TileSize, palette_id: u8, color: Color) -> GlyphBank {
|
||||||
let size = tile_size as usize;
|
let size = tile_size as usize;
|
||||||
let mut bank = GlyphBank::new(tile_size, size, size);
|
let mut bank = GlyphBank::with_palette_count(tile_size, size, size, palette_id as usize + 1);
|
||||||
bank.palettes[palette_id as usize][1] = color;
|
bank.palette_mut(palette_id).unwrap()[1] = color;
|
||||||
for pixel in &mut bank.pixel_indices {
|
for pixel in &mut bank.pixel_indices {
|
||||||
*pixel = 1;
|
*pixel = 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,4 +44,4 @@
|
|||||||
{"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":"done","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":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0037-rgba8888-framebuffer-and-pixel-format-direction/LSN-0046-pixel-format-contracts-must-move-as-one-surface.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23"}]}
|
{"type":"discussion","id":"DSC-0037","status":"done","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":[],"decisions":[],"plans":[],"lessons":[{"id":"LSN-0046","file":"discussion/lessons/DSC-0037-rgba8888-framebuffer-and-pixel-format-direction/LSN-0046-pixel-format-contracts-must-move-as-one-surface.md","status":"done","created_at":"2026-05-23","updated_at":"2026-05-23"}]}
|
||||||
{"type":"discussion","id":"DSC-0046","status":"in_progress","ticket":"runtime-owned-variable-glyph-bank-palette-protocol","title":"Runtime-Owned Variable Glyph Bank Palette Protocol","created_at":"2026-07-14","updated_at":"2026-07-14","tags":["runtime","gfx","assets","glyph-bank","palette-serialization","protocol"],"agendas":[{"id":"AGD-0049","file":"AGD-0049-runtime-owned-variable-glyph-bank-palette-protocol.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-variable-glyph-bank-palette-protocol.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0049"}],"plans":[{"id":"PLN-0167","file":"PLN-0167-spec-contract-update-for-variable-glyph-palettes.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0168","file":"PLN-0168-glyphbank-variable-palette-resident-model.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0169","file":"PLN-0169-asset-decode-validation-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0170","file":"PLN-0170-composer-palette-reference-failure-semantics.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0171","file":"PLN-0171-variable-glyph-palette-tests-fixtures-and-residue-scan.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0172","file":"PLN-0172-runtime-spec-handoff-to-packer-and-studio.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]}],"lessons":[]}
|
{"type":"discussion","id":"DSC-0046","status":"in_progress","ticket":"runtime-owned-variable-glyph-bank-palette-protocol","title":"Runtime-Owned Variable Glyph Bank Palette Protocol","created_at":"2026-07-14","updated_at":"2026-07-14","tags":["runtime","gfx","assets","glyph-bank","palette-serialization","protocol"],"agendas":[{"id":"AGD-0049","file":"AGD-0049-runtime-owned-variable-glyph-bank-palette-protocol.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14"}],"decisions":[{"id":"DEC-0041","file":"DEC-0041-variable-glyph-bank-palette-protocol.md","status":"accepted","created_at":"2026-07-14","updated_at":"2026-07-14","ref_agenda":"AGD-0049"}],"plans":[{"id":"PLN-0167","file":"PLN-0167-spec-contract-update-for-variable-glyph-palettes.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0168","file":"PLN-0168-glyphbank-variable-palette-resident-model.md","status":"done","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0169","file":"PLN-0169-asset-decode-validation-for-variable-glyph-palettes.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0170","file":"PLN-0170-composer-palette-reference-failure-semantics.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0171","file":"PLN-0171-variable-glyph-palette-tests-fixtures-and-residue-scan.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]},{"id":"PLN-0172","file":"PLN-0172-runtime-spec-handoff-to-packer-and-studio.md","status":"open","created_at":"2026-07-14","updated_at":"2026-07-14","ref_decisions":["DEC-0041"]}],"lessons":[]}
|
||||||
|
|||||||
@ -2,7 +2,8 @@
|
|||||||
id: PLN-0168
|
id: PLN-0168
|
||||||
ticket: runtime-owned-variable-glyph-bank-palette-protocol
|
ticket: runtime-owned-variable-glyph-bank-palette-protocol
|
||||||
title: GlyphBank Variable Palette Resident Model
|
title: GlyphBank Variable Palette Resident Model
|
||||||
status: open
|
status: done
|
||||||
|
completed: 2026-07-14
|
||||||
created: 2026-07-14
|
created: 2026-07-14
|
||||||
ref_decisions: [DEC-0041]
|
ref_decisions: [DEC-0041]
|
||||||
tags: [runtime, gfx, assets, glyph-bank, hal]
|
tags: [runtime, gfx, assets, glyph-bank, hal]
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user