mirror of
https://github.com/LegitCamper/picocalc-os-rs.git
synced 2025-12-27 07:45:28 +00:00
only mark framebuffer tile as dirty if pixel changes
This commit is contained in:
@@ -38,10 +38,6 @@ static mut DIRTY_TILES: LazyLock<heapless::Vec<AtomicBool, TILE_COUNT>> = LazyLo
|
|||||||
pub struct AtomicFrameBuffer;
|
pub struct AtomicFrameBuffer;
|
||||||
|
|
||||||
impl AtomicFrameBuffer {
|
impl AtomicFrameBuffer {
|
||||||
pub const fn new() -> Self {
|
|
||||||
Self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mark_tiles_dirty(&mut self, rect: Rectangle) {
|
fn mark_tiles_dirty(&mut self, rect: Rectangle) {
|
||||||
let tiles_x = (SCREEN_WIDTH + TILE_SIZE - 1) / TILE_SIZE;
|
let tiles_x = (SCREEN_WIDTH + TILE_SIZE - 1) / TILE_SIZE;
|
||||||
let start_tx = (rect.top_left.x as usize) / TILE_SIZE;
|
let start_tx = (rect.top_left.x as usize) / TILE_SIZE;
|
||||||
@@ -57,12 +53,6 @@ impl AtomicFrameBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_pixel(&mut self, x: u16, y: u16, color: u16) -> Result<(), ()> {
|
|
||||||
unsafe { BUFFER[(y as usize * SCREEN_WIDTH) + x as usize] = color };
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_pixels_buffered<P: IntoIterator<Item = u16>>(
|
fn set_pixels_buffered<P: IntoIterator<Item = u16>>(
|
||||||
&mut self,
|
&mut self,
|
||||||
sx: u16,
|
sx: u16,
|
||||||
@@ -262,6 +252,7 @@ impl DrawTarget for AtomicFrameBuffer {
|
|||||||
I: IntoIterator<Item = Pixel<Self::Color>>,
|
I: IntoIterator<Item = Pixel<Self::Color>>,
|
||||||
{
|
{
|
||||||
let mut dirty_rect: Option<Rectangle> = None;
|
let mut dirty_rect: Option<Rectangle> = None;
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
for Pixel(coord, color) in pixels {
|
for Pixel(coord, color) in pixels {
|
||||||
if coord.x >= 0 && coord.y >= 0 {
|
if coord.x >= 0 && coord.y >= 0 {
|
||||||
@@ -269,10 +260,14 @@ impl DrawTarget for AtomicFrameBuffer {
|
|||||||
let y = coord.y as i32;
|
let y = coord.y as i32;
|
||||||
|
|
||||||
if (x as usize) < SCREEN_WIDTH && (y as usize) < SCREEN_HEIGHT {
|
if (x as usize) < SCREEN_WIDTH && (y as usize) < SCREEN_HEIGHT {
|
||||||
|
let idx = (y as usize) * SCREEN_WIDTH + (x as usize);
|
||||||
|
let raw_color = RawU16::from(color).into_inner();
|
||||||
unsafe {
|
unsafe {
|
||||||
BUFFER[(y as usize) * SCREEN_WIDTH + (x as usize)] =
|
if BUFFER[idx] != raw_color {
|
||||||
RawU16::from(color).into_inner()
|
BUFFER[idx] = raw_color;
|
||||||
};
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(ref mut rect) = dirty_rect {
|
if let Some(ref mut rect) = dirty_rect {
|
||||||
rect.top_left.x = rect.top_left.x.min(x);
|
rect.top_left.x = rect.top_left.x.min(x);
|
||||||
@@ -288,8 +283,10 @@ impl DrawTarget for AtomicFrameBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(rect) = dirty_rect {
|
if changed {
|
||||||
self.mark_tiles_dirty(rect);
|
if let Some(rect) = dirty_rect {
|
||||||
|
self.mark_tiles_dirty(rect);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -307,6 +304,7 @@ impl DrawTarget for AtomicFrameBuffer {
|
|||||||
let area_width = area.size.width;
|
let area_width = area.size.width;
|
||||||
let area_height = area.size.height;
|
let area_height = area.size.height;
|
||||||
let mut colors = colors.into_iter();
|
let mut colors = colors.into_iter();
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
for y in 0..area_height {
|
for y in 0..area_height {
|
||||||
for x in 0..area_width {
|
for x in 0..area_width {
|
||||||
@@ -314,11 +312,14 @@ impl DrawTarget for AtomicFrameBuffer {
|
|||||||
|
|
||||||
if drawable_area.contains(p) {
|
if drawable_area.contains(p) {
|
||||||
if let Some(color) = colors.next() {
|
if let Some(color) = colors.next() {
|
||||||
self.set_pixel(
|
let idx = (p.y as usize * SCREEN_WIDTH) + (p.x as usize);
|
||||||
p.x as u16,
|
let raw_color = RawU16::from(color).into_inner();
|
||||||
p.y as u16,
|
unsafe {
|
||||||
RawU16::from(color).into_inner(),
|
if BUFFER[idx] != raw_color {
|
||||||
)?;
|
BUFFER[idx] = raw_color;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -329,7 +330,9 @@ impl DrawTarget for AtomicFrameBuffer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.mark_tiles_dirty(*area);
|
if changed {
|
||||||
|
self.mark_tiles_dirty(*area);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Reference in New Issue
Block a user