pub struct RclParams {
pub tile_alloc_address: u32,
pub width_in_tiles: u8,
pub height_in_tiles: u8,
pub color_write_address: u32,
pub depth_write_address: Option<u32>,
pub width_px: u16,
pub height_px: u16,
pub clear_color_rgba8888: u32,
}
pub const fn size(width_in_tiles: u8, height_in_tiles: u8, with_depth: bool) -> usize {
let tile_count = width_in_tiles as usize * height_in_tiles as usize;
let per_tile = if with_depth { 19 } else { 9 };
35 + per_tile * tile_count + 1
}
pub fn build(cl: &mut [u8], params: &RclParams) -> usize {
let mut b = Builder { bytes: cl, len: 0 };
b.tile_rendering_mode_configuration(params);
b.clear_colors(params);
b.tile_coordinates(0, 0);
b.store_tile_buffer_general_none();
let width_in_tiles = u32::from(params.width_in_tiles);
let height_in_tiles = u32::from(params.height_in_tiles);
for y in 0..height_in_tiles {
for x in 0..width_in_tiles {
let first = x == 0 && y == 0;
let last = x == width_in_tiles - 1 && y == height_in_tiles - 1;
b.tile_coordinates(x as u8, y as u8);
if first {
b.wait_on_semaphore();
}
b.branch_to_sub_list(params.tile_alloc_address + (y * width_in_tiles + x) * 32);
if let Some(depth_write_address) = params.depth_write_address {
b.store_depth(depth_write_address);
b.tile_coordinates(x as u8, y as u8);
}
b.store_ms_tile_buffer(last);
}
}
b.len
}
struct Builder<'a> {
bytes: &'a mut [u8],
len: usize,
}
impl<'a> Builder<'a> {
fn push_u8(&mut self, v: u8) {
self.bytes[self.len] = v;
self.len += 1;
}
fn push_u16(&mut self, v: u16) {
self.bytes[self.len..self.len + 2].copy_from_slice(&v.to_le_bytes());
self.len += 2;
}
fn push_u32(&mut self, v: u32) {
self.bytes[self.len..self.len + 4].copy_from_slice(&v.to_le_bytes());
self.len += 4;
}
fn tile_rendering_mode_configuration(&mut self, params: &RclParams) {
self.push_u8(0x71);
self.push_u32(params.color_write_address);
self.push_u16(params.width_px);
self.push_u16(params.height_px);
self.push_u16(0x0004);
}
fn clear_colors(&mut self, params: &RclParams) {
self.push_u8(0x72);
self.push_u32(params.clear_color_rgba8888);
self.push_u32(params.clear_color_rgba8888);
self.push_u32(0x00ff_ffff);
self.push_u8(0);
}
fn tile_coordinates(&mut self, x: u8, y: u8) {
self.push_u8(0x73);
self.push_u8(x);
self.push_u8(y);
}
fn store_tile_buffer_general_none(&mut self) {
self.push_u8(0x1c);
self.push_u16(0x0000);
self.push_u32(0);
}
fn store_depth(&mut self, address: u32) {
self.push_u8(0x1c);
self.push_u16(0x2002);
self.push_u32(address);
}
fn wait_on_semaphore(&mut self) {
self.push_u8(0x08);
}
fn branch_to_sub_list(&mut self, address: u32) {
self.push_u8(0x11);
self.push_u32(address);
}
fn store_ms_tile_buffer(&mut self, last: bool) {
self.push_u8(if last { 0x19 } else { 0x18 });
}
}