From d39c319c057897758b93ddfb8e752bf8ab595eb3 Mon Sep 17 00:00:00 2001 From: bunnie Date: Wed, 15 Jun 2022 01:32:12 +0800 Subject: [PATCH] recode GAM interface to send one tile at a time Don't add Tiles to ObjectList because it greatly inflates the amount of RAM required to sling tiles around --- services/gam/src/api.rs | 12 ++++++++++-- services/gam/src/lib.rs | 13 ++++++++----- services/gam/src/main.rs | 41 ++++++++++++++++++++++++---------------- 3 files changed, 43 insertions(+), 23 deletions(-) diff --git a/services/gam/src/api.rs b/services/gam/src/api.rs index 6e44b0e9a..4e91e0691 100644 --- a/services/gam/src/api.rs +++ b/services/gam/src/api.rs @@ -11,8 +11,6 @@ pub enum GamObjectType { Circ(Circle), Rect(Rectangle), RoundRect(RoundedRectangle), - #[cfg(feature="ditherpunk")] - Tile(Tile), } #[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Copy, Clone)] @@ -20,6 +18,12 @@ pub struct GamObject { pub canvas: Gid, pub obj: GamObjectType, } +#[cfg(feature="ditherpunk")] +#[derive(Debug, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, Copy, Clone)] +pub struct GamTile { + pub canvas: Gid, + pub tile: Tile, +} #[derive(Debug, Copy, Clone, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)] pub struct GamObjectList { pub canvas: Gid, @@ -121,6 +125,10 @@ pub(crate) enum Opcode { // draws an object RenderObject, //(GamObject), RenderObjectList, + // draws a tile. this is *not* part of the ObjectList because then every vector object suddenly also carries + // the allocation burden of a bitmap tile. + #[cfg(feature="ditherpunk")] + RenderTile, // renders a TextView RenderTextView, //(TextView), diff --git a/services/gam/src/lib.rs b/services/gam/src/lib.rs index d64e764d1..42a3f80d6 100644 --- a/services/gam/src/lib.rs +++ b/services/gam/src/lib.rs @@ -197,13 +197,16 @@ impl Gam { } #[cfg(feature="ditherpunk")] pub fn draw_bitmap(&self, gid: Gid, bm: &Bitmap) -> Result<(), xous::Error> { - let mut list = GamObjectList::new(gid); for (_i, tile) in bm.iter().enumerate(){ - list.push(GamObjectType::Tile(*tile)).unwrap(); + let gt = GamTile { + tile: *tile, + canvas: gid, + }; + let buf = Buffer::into_buf(gt).or(Err(xous::Error::InternalError))?; + buf.lend(self.conn, Opcode::RenderTile.to_u32().unwrap()) + .map(|_| ())?; }; - let buf = Buffer::into_buf(list).or(Err(xous::Error::InternalError))?; - buf.lend(self.conn, Opcode::RenderObjectList.to_u32().unwrap()) - .map(|_| ()) + Ok(()) } pub fn draw_circle(&self, gid: Gid, circ: Circle) -> Result<(), xous::Error> { let go = GamObject { diff --git a/services/gam/src/main.rs b/services/gam/src/main.rs index 93031611b..563765332 100644 --- a/services/gam/src/main.rs +++ b/services/gam/src/main.rs @@ -305,6 +305,31 @@ fn main() -> ! { let ret = api::Return::ContentCanvasReturn(context_mgr.get_content_canvas(req)); buffer.replace(ret).unwrap(); } + #[cfg(feature="ditherpunk")] + Some(Opcode::RenderTile) => { + let buffer = unsafe { Buffer::from_memory_message(msg.body.memory_message().unwrap()) }; + let mut obj = buffer.to_original::().unwrap(); + log::debug!("RenderTile {:?}", obj); + if let Some(canvas) = canvases.get_mut(&obj.canvas) { + // first, figure out if we should even be drawing to this canvas. + log::debug!("drawable {} onscreen {} state{:?} for canvas {:?}", canvas.is_drawable(), canvas.is_onscreen(), canvas.state(), canvas.gid()); + if canvas.is_drawable() && canvas.is_onscreen() { + obj.tile.translate(canvas.clip_rect().tl); + obj.tile.translate(canvas.pan_offset()); + log::trace!("drawing tile {:?}", obj.tile); + gfx.draw_tile_clipped( + obj.tile, + canvas.clip_rect(), + ).expect("couldn't draw bitmap"); + canvas.do_drawn().expect("couldn't set canvas to drawn"); + } else { + log::info!("attempt to draw Object on non-drawable canvas. Not fatal, but request ignored: {:?}", obj); + } + } else { + info!("bogus GID in Object, not doing anything in response to draw request."); + } + log::trace!("leaving RenderTile"); + } Some(Opcode::RenderObject) => { let buffer = unsafe { Buffer::from_memory_message(msg.body.memory_message().unwrap()) }; let obj = buffer.to_original::().unwrap(); @@ -346,16 +371,6 @@ fn main() -> ! { canvas.clip_rect(), ).expect("couldn't draw rounded rectangle"); } - #[cfg(feature="ditherpunk")] - GamObjectType::Tile(mut tile) => { - log::info!("drawing tile {:?}", tile); - tile.translate(canvas.clip_rect().tl); - tile.translate(canvas.pan_offset()); - gfx.draw_tile_clipped( - tile, - canvas.clip_rect(), - ).expect("couldn't draw bitmap"); - } } canvas.do_drawn().expect("couldn't set canvas to drawn"); } else { @@ -396,12 +411,6 @@ fn main() -> ! { rr.translate(canvas.pan_offset()); obj_list.push(ClipObjectType::RoundRect(rr), canvas.clip_rect()).unwrap(); }, - #[cfg(feature="ditherpunk")] - GamObjectType::Tile(mut tile) => { - tile.translate(canvas.clip_rect().tl); - tile.translate(canvas.pan_offset()); - obj_list.push(ClipObjectType::Tile(tile), canvas.clip_rect()).unwrap(); - } } } else { break;