From bf5286d25da17b8975a198f58840a9705ca0317a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 28 Mar 2026 16:53:59 +0100 Subject: [PATCH] drivers/graphics: Replace CpuBackedBuffer::sync_range with CpuBackedBuffer::sync_rect This can be a bit more efficient by doing bounds checks before the main loop. --- drivers/graphics/console-draw/src/lib.rs | 6 +----- drivers/graphics/graphics-ipc/src/lib.rs | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/drivers/graphics/console-draw/src/lib.rs b/drivers/graphics/console-draw/src/lib.rs index ec9f0996fa..5eb951df54 100644 --- a/drivers/graphics/console-draw/src/lib.rs +++ b/drivers/graphics/console-draw/src/lib.rs @@ -107,12 +107,8 @@ impl V2DisplayMap { } pub fn dirty_fb(&mut self, damage: Damage) -> io::Result<()> { - let pitch = self.buffer.buffer().pitch(); self.buffer - .sync_range((damage.y..damage.y + damage.height).map(|row| { - let start = (row * pitch + damage.x * 4) as usize; - start..start + damage.width as usize * 4 - })); + .sync_rect(damage.x, damage.y, damage.width, damage.height); self.display_handle.dirty_framebuffer( self.fb, diff --git a/drivers/graphics/graphics-ipc/src/lib.rs b/drivers/graphics/graphics-ipc/src/lib.rs index fedc5658b2..5c24df1d0f 100644 --- a/drivers/graphics/graphics-ipc/src/lib.rs +++ b/drivers/graphics/graphics-ipc/src/lib.rs @@ -1,8 +1,8 @@ use std::fs::File; -use std::ops::Range; use std::os::fd::{AsFd, BorrowedFd}; use std::{io, mem, ptr}; +use drm::buffer::Buffer; use drm::control::connector::{self, State}; use drm::control::dumbbuffer::{DumbBuffer, DumbMapping}; use drm::control::Device as _; @@ -86,20 +86,28 @@ impl CpuBackedBuffer { self.shadow.as_deref_mut().unwrap_or(&mut *self.map) } - pub fn sync_range(&mut self, ranges: impl Iterator>) { + pub fn sync_rect(&mut self, x: u32, y: u32, width: u32, height: u32) { let Some(shadow) = &self.shadow else { return; // No shadow buffer; all writes are already propagated to the GPU. }; - for range in ranges { - assert!(range.start <= range.end); - assert!(range.end <= self.map.len()); + assert!(x.checked_add(width).unwrap() <= self.buffer.size().0); + assert!(y.checked_add(height).unwrap() <= self.buffer.size().1); + let start_x: usize = x.try_into().unwrap(); + let start_y: usize = y.try_into().unwrap(); + let w: usize = width.try_into().unwrap(); + let h: usize = height.try_into().unwrap(); + + let offscreen_ptr = shadow.as_ptr().cast::(); + let onscreen_ptr = self.map.as_mut_ptr().cast::(); + + for row in start_y..start_y + h { unsafe { ptr::copy_nonoverlapping( - shadow.as_ptr().add(range.start), - self.map.as_mut_ptr().add(range.start), - range.end - range.start, + offscreen_ptr.add(row * self.buffer.pitch() as usize / 4 + start_x), + onscreen_ptr.add(row * self.buffer.pitch() as usize / 4 + start_x), + w, ); } }