diff --git a/Cargo.lock b/Cargo.lock index 4722e016e7..e8c04fa45e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -469,6 +469,7 @@ dependencies = [ name = "console-draw" version = "0.1.0" dependencies = [ + "drm", "graphics-ipc", "orbclient", "ransid", @@ -956,7 +957,6 @@ version = "0.1.0" dependencies = [ "common", "drm", - "drm-fourcc", "libredox", "log", "redox-ioctl", diff --git a/drivers/graphics/console-draw/Cargo.toml b/drivers/graphics/console-draw/Cargo.toml index 6153d6143d..80496fb250 100644 --- a/drivers/graphics/console-draw/Cargo.toml +++ b/drivers/graphics/console-draw/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +drm = "0.14" orbclient = "0.3.27" ransid = "0.4" diff --git a/drivers/graphics/console-draw/src/lib.rs b/drivers/graphics/console-draw/src/lib.rs index 20bc77b6e6..20be8bb8d2 100644 --- a/drivers/graphics/console-draw/src/lib.rs +++ b/drivers/graphics/console-draw/src/lib.rs @@ -2,15 +2,51 @@ extern crate ransid; use std::collections::VecDeque; use std::convert::{TryFrom, TryInto}; -use std::{cmp, ptr}; +use std::{cmp, io, mem, ptr}; +use drm::buffer::{Buffer, DrmFourcc}; +use drm::control::dumbbuffer::{DumbBuffer, DumbMapping}; +use drm::control::Device; use graphics_ipc::v1::Damage; +use graphics_ipc::v2::V2GraphicsHandle; use orbclient::FONT; -pub struct DisplayMap { - pub offscreen: *mut [u32], - pub width: usize, - pub height: usize, +pub struct V2DisplayMap { + pub display_handle: V2GraphicsHandle, + pub fb: DumbBuffer, + mapping: DumbMapping<'static>, +} + +impl V2DisplayMap { + pub fn new(display_handle: V2GraphicsHandle, width: u32, height: u32) -> io::Result { + let mut fb = display_handle.create_dumb_buffer((width, height), DrmFourcc::Argb8888, 32)?; + + let map = display_handle.map_dumb_buffer(&mut fb)?; + let map = unsafe { mem::transmute::, DumbMapping<'static>>(map) }; + + Ok(Self { + display_handle, + fb, + mapping: map, + }) + } + + unsafe fn console_map(&mut self) -> DisplayMap { + DisplayMap { + offscreen: ptr::slice_from_raw_parts_mut( + self.mapping.as_mut_ptr() as *mut u32, + self.mapping.len() / 4, + ), + width: self.fb.size().0 as usize, + height: self.fb.size().1 as usize, + } + } +} + +struct DisplayMap { + offscreen: *mut [u32], + width: usize, + height: usize, } pub struct TextScreen { @@ -116,7 +152,14 @@ impl TextScreen { } impl TextScreen { - pub fn write(&mut self, map: &mut DisplayMap, buf: &[u8], input: &mut VecDeque) -> Damage { + pub fn write( + &mut self, + map: &mut V2DisplayMap, + buf: &[u8], + input: &mut VecDeque, + ) -> Damage { + let map = unsafe { &mut map.console_map() }; + let mut min_changed = map.height; let mut max_changed = 0; let mut line_changed = |line| { @@ -227,7 +270,7 @@ impl TextScreen { damage } - pub fn resize(&mut self, old_map: &mut DisplayMap, new_map: &mut DisplayMap) { + pub fn resize(&mut self, map: &mut V2DisplayMap, width: u32, height: u32) -> io::Result<()> { // FIXME fold row when target is narrower and maybe unfold when it is wider fn copy_row( old_map: &mut DisplayMap, @@ -244,20 +287,49 @@ impl TextScreen { } } - if new_map.height >= old_map.height { - for row in 0..old_map.height { - copy_row(old_map, new_map, row, row); - } - } else { - let deleted_rows = (old_map.height - new_map.height).div_ceil(16); - for row in 0..new_map.height { - if row + (deleted_rows + 1) * 16 >= old_map.height { - break; + let mut new_fb = + map.display_handle + .create_dumb_buffer((width, height), DrmFourcc::Argb8888, 32)?; + + let new_mapping = map.display_handle.map_dumb_buffer(&mut new_fb)?; + let mut new_mapping = + unsafe { mem::transmute::, DumbMapping<'static>>(new_mapping) }; + + new_mapping.fill(0); + + { + let old_map = unsafe { &mut map.console_map() }; + let new_map = &mut DisplayMap { + offscreen: ptr::slice_from_raw_parts_mut( + new_mapping.as_mut_ptr() as *mut u32, + new_mapping.len() / 4, + ), + width: new_fb.size().0 as usize, + height: new_fb.size().1 as usize, + }; + + if new_map.height >= old_map.height { + for row in 0..old_map.height { + copy_row(old_map, new_map, row, row); } - copy_row(old_map, new_map, row + deleted_rows * 16, row); + } else { + let deleted_rows = (old_map.height - new_map.height).div_ceil(16); + for row in 0..new_map.height { + if row + (deleted_rows + 1) * 16 >= old_map.height { + break; + } + copy_row(old_map, new_map, row + deleted_rows * 16, row); + } + self.console.state.y = self.console.state.y.saturating_sub(deleted_rows); } - self.console.state.y = self.console.state.y.saturating_sub(deleted_rows); } + + let old_fb = mem::replace(&mut map.fb, new_fb); + map.mapping = new_mapping; + + let _ = map.display_handle.destroy_dumb_buffer(old_fb); + + Ok(()) } } diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 25d54b3593..29bece881b 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -8,7 +8,8 @@ use std::mem; use std::mem::transmute; use std::sync::Arc; -use graphics_ipc::v1::{CursorDamage, Damage}; +use graphics_ipc::v1::CursorDamage; +use graphics_ipc::v2::Damage; use inputd::{VtEvent, VtEventKind}; use libredox::Fd; use redox_scheme::scheme::SchemeSync; diff --git a/drivers/graphics/fbbootlogd/src/scheme.rs b/drivers/graphics/fbbootlogd/src/scheme.rs index 3ea92547a3..ff0108e46c 100644 --- a/drivers/graphics/fbbootlogd/src/scheme.rs +++ b/drivers/graphics/fbbootlogd/src/scheme.rs @@ -1,10 +1,10 @@ +use std::cmp; use std::collections::VecDeque; -use std::{cmp, mem, ptr}; -use console_draw::TextScreen; +use console_draw::{TextScreen, V2DisplayMap}; use drm::buffer::Buffer; -use drm::control::dumbbuffer::{DumbBuffer, DumbMapping}; -use graphics_ipc::v2::V2GraphicsHandle; +use drm::control::Device; +use graphics_ipc::v2::{Damage, V2GraphicsHandle}; use inputd::ConsumerHandle; use orbclient::{Event, EventOption}; use redox_scheme::scheme::SchemeSync; @@ -12,28 +12,9 @@ use redox_scheme::{CallerCtx, OpenResult}; use syscall::schemev2::NewFdFlags; use syscall::{Error, Result, EINVAL, ENOENT}; -pub struct DisplayMap { - display_handle: V2GraphicsHandle, - fb: DumbBuffer, - mapping: DumbMapping<'static>, -} - -impl DisplayMap { - unsafe fn console_map(&mut self) -> console_draw::DisplayMap { - console_draw::DisplayMap { - offscreen: ptr::slice_from_raw_parts_mut( - self.mapping.as_mut_ptr() as *mut u32, - self.mapping.len() / 4, - ), - width: self.fb.size().0 as usize, - height: self.fb.size().1 as usize, - } - } -} - pub struct FbbootlogScheme { pub input_handle: ConsumerHandle, - display_map: Option, + display_map: Option, text_screen: console_draw::TextScreen, text_buffer: console_draw::TextBuffer, is_scrollback: bool, @@ -68,28 +49,19 @@ impl FbbootlogScheme { }; let (width, height) = new_display_handle - .display_size(new_display_handle.first_display().unwrap()) - .unwrap(); - let mut fb = new_display_handle - .create_dumb_framebuffer(width, height) - .unwrap(); + .get_connector(new_display_handle.first_display().unwrap(), true) + .unwrap() + .modes()[0] + .size(); - let display_map = match new_display_handle.map_dumb_framebuffer(&mut fb) { - Ok(display_map) => unsafe { - mem::transmute::, DumbMapping<'static>>(display_map) - }, + match V2DisplayMap::new(new_display_handle, width.into(), height.into()) { + Ok(display_map) => self.display_map = Some(display_map), Err(err) => { eprintln!("fbbootlogd: failed to open display: {}", err); return; } }; - self.display_map = Some(DisplayMap { - display_handle: new_display_handle, - mapping: display_map, - fb, - }); - eprintln!("fbbootlogd: mapped display"); } @@ -145,46 +117,44 @@ impl FbbootlogScheme { return; }; let buffer_len = self.text_buffer.lines.len(); - let dmap = unsafe { &mut map.console_map() }; // for both extra space on wrapping text and a scrollback indicator let spare_lines = 3; self.is_scrollback = true; self.scrollback_offset = cmp::min( self.scrollback_offset, - buffer_len - dmap.height / 16 + spare_lines, + buffer_len - map.fb.size().1 as usize / 16 + spare_lines, ); let mut i = self.scrollback_offset; self.text_screen - .write(dmap, b"\x1B[1;1H\x1B[2J", &mut VecDeque::new()); + .write(map, b"\x1B[1;1H\x1B[2J", &mut VecDeque::new()); + + let mut total_damage = Damage::NONE; while i < buffer_len { let mut damage = self.text_screen - .write(dmap, &self.text_buffer.lines[i][..], &mut VecDeque::new()); + .write(map, &self.text_buffer.lines[i][..], &mut VecDeque::new()); i += 1; let yd = (damage.y + damage.height) as usize; - if i == buffer_len || yd + spare_lines * 16 > dmap.height { + if i == buffer_len || yd + spare_lines * 16 > map.fb.size().1 as usize { // render until end of screen - damage.height = (dmap.height as u32) - damage.y; - map.display_handle - .update_plane(0, u32::from(map.fb.handle()), damage) - .unwrap(); + damage.height = map.fb.size().1 - damage.y; + total_damage = total_damage.merge(damage); self.is_scrollback = i < buffer_len; break; } else { - map.display_handle - .update_plane(0, u32::from(map.fb.handle()), damage) - .unwrap(); + total_damage = total_damage.merge(damage); } } + map.display_handle + .update_plane(0, u32::from(map.fb.handle()), total_damage) + .unwrap(); } - fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) { - let (width, height) = match map - .display_handle - .first_display() - .and_then(|handle| map.display_handle.display_size(handle)) - { - Ok((width, height)) => (width, height), + fn handle_resize(map: &mut V2DisplayMap, text_screen: &mut TextScreen) { + let (width, height) = match map.display_handle.first_display().and_then(|handle| { + Ok(map.display_handle.get_connector(handle, true)?.modes()[0].size()) + }) { + Ok((width, height)) => (width.into(), height.into()), Err(err) => { eprintln!("fbbootlogd: failed to get display size: {}", err); map.fb.size() @@ -192,41 +162,10 @@ impl FbbootlogScheme { }; if (width, height) != map.fb.size() { - match map.display_handle.create_dumb_framebuffer(width, height) { - Ok(mut fb) => { - let mut new_map = match map.display_handle.map_dumb_framebuffer(&mut fb) { - Ok(new_map) => unsafe { - mem::transmute::, DumbMapping<'static>>(new_map) - }, - Err(err) => { - eprintln!("fbbootlogd: failed to open display: {}", err); - return; - } - }; - - new_map.fill(0); - - text_screen.resize( - unsafe { &mut map.console_map() }, - &mut console_draw::DisplayMap { - offscreen: ptr::slice_from_raw_parts_mut( - new_map.as_mut_ptr() as *mut u32, - new_map.len() / 4, - ), - width: fb.size().0 as usize, - height: fb.size().1 as usize, - }, - ); - - let old_fb = mem::replace(&mut map.fb, fb); - map.mapping = new_map; - - let _ = map.display_handle.destroy_dumb_framebuffer(old_fb); - - eprintln!("fbbootlogd: mapped display"); - } + match text_screen.resize(map, width, height) { + Ok(()) => eprintln!("fbbootlogd: mapped display"), Err(err) => { - eprintln!("fbbootlogd: failed to create framebuffer: {}", err); + eprintln!("fbbootlogd: failed to create or map framebuffer: {}", err); return; } } @@ -286,11 +225,7 @@ impl SchemeSync for FbbootlogScheme { self.text_buffer.write(buf); if !self.is_scrollback { - let damage = self.text_screen.write( - unsafe { &mut map.console_map() }, - buf, - &mut VecDeque::new(), - ); + let damage = self.text_screen.write(map, buf, &mut VecDeque::new()); if let Some(map) = &self.display_map { map.display_handle diff --git a/drivers/graphics/fbcond/src/display.rs b/drivers/graphics/fbcond/src/display.rs index 0a4d7fb833..639bc8f06a 100644 --- a/drivers/graphics/fbcond/src/display.rs +++ b/drivers/graphics/fbcond/src/display.rs @@ -1,32 +1,13 @@ -use console_draw::TextScreen; +use console_draw::{TextScreen, V2DisplayMap}; use drm::buffer::Buffer; -use drm::control::dumbbuffer::{DumbBuffer, DumbMapping}; +use drm::control::Device; use graphics_ipc::v2::{Damage, V2GraphicsHandle}; use inputd::ConsumerHandle; -use std::{io, mem, ptr}; +use std::io; pub struct Display { pub input_handle: ConsumerHandle, - pub map: Option, -} - -pub struct DisplayMap { - display_handle: V2GraphicsHandle, - fb: DumbBuffer, - mapping: DumbMapping<'static>, -} - -impl DisplayMap { - pub unsafe fn console_map(&mut self) -> console_draw::DisplayMap { - console_draw::DisplayMap { - offscreen: ptr::slice_from_raw_parts_mut( - self.mapping.as_mut_ptr() as *mut u32, - self.mapping.len() / 4, - ), - width: self.fb.size().0 as usize, - height: self.fb.size().1 as usize, - } - } + pub map: Option, } impl Display { @@ -49,40 +30,32 @@ impl Display { log::debug!("fbcond: Opened new display"); let (width, height) = new_display_handle - .display_size(new_display_handle.first_display().unwrap()) - .unwrap(); - let mut fb = new_display_handle - .create_dumb_framebuffer(width, height) - .unwrap(); + .get_connector(new_display_handle.first_display().unwrap(), true) + .unwrap() + .modes()[0] + .size(); - let map = match new_display_handle.map_dumb_framebuffer(&mut fb) { - Ok(map) => unsafe { mem::transmute::, DumbMapping<'static>>(map) }, + match V2DisplayMap::new(new_display_handle, width.into(), height.into()) { + Ok(map) => { + log::debug!( + "fbcond: Mapped new display with size {}x{}", + map.fb.size().0, + map.fb.size().1, + ); + self.map = Some(map) + } Err(err) => { - log::error!("failed to map display: {}", err); + eprintln!("fbcond: failed to open display: {}", err); return; } - }; - - log::debug!( - "fbcond: Mapped new display with size {}x{}", - fb.size().0, - fb.size().1, - ); - - self.map = Some(DisplayMap { - display_handle: new_display_handle, - fb, - mapping: map, - }); + } } - pub fn handle_resize(map: &mut DisplayMap, text_screen: &mut TextScreen) { - let (width, height) = match map - .display_handle - .first_display() - .and_then(|handle| map.display_handle.display_size(handle)) - { - Ok((width, height)) => (width, height), + pub fn handle_resize(map: &mut V2DisplayMap, text_screen: &mut TextScreen) { + let (width, height) = match map.display_handle.first_display().and_then(|handle| { + Ok(map.display_handle.get_connector(handle, true)?.modes()[0].size()) + }) { + Ok((width, height)) => (width.into(), height.into()), Err(err) => { log::error!("fbcond: failed to get display size: {}", err); map.fb.size() @@ -90,41 +63,11 @@ impl Display { }; if (width, height) != map.fb.size() { - match map.display_handle.create_dumb_framebuffer(width, height) { - Ok(mut fb) => { - let mut new_map = match map.display_handle.map_dumb_framebuffer(&mut fb) { - Ok(new_map) => unsafe { - mem::transmute::, DumbMapping<'static>>(new_map) - }, - Err(err) => { - eprintln!("fbcond: failed to open display: {}", err); - return; - } - }; - - new_map.fill(0); - - text_screen.resize( - unsafe { &mut map.console_map() }, - &mut console_draw::DisplayMap { - offscreen: ptr::slice_from_raw_parts_mut( - new_map.as_mut_ptr() as *mut u32, - new_map.len() / 4, - ), - width: fb.size().0 as usize, - height: fb.size().1 as usize, - }, - ); - - let old_fb = mem::replace(&mut map.fb, fb); - map.mapping = new_map; - - let _ = map.display_handle.destroy_dumb_framebuffer(old_fb); - - eprintln!("fbcond: mapped display"); - } + match text_screen.resize(map, width, height) { + Ok(()) => eprintln!("fbcond: mapped display"), Err(err) => { - log::error!("fbcond: failed to create framebuffer: {}", err); + eprintln!("fbcond: failed to create or map framebuffer: {}", err); + return; } } } diff --git a/drivers/graphics/fbcond/src/text.rs b/drivers/graphics/fbcond/src/text.rs index 438af68912..8a24bbebe6 100644 --- a/drivers/graphics/fbcond/src/text.rs +++ b/drivers/graphics/fbcond/src/text.rs @@ -124,9 +124,7 @@ impl TextScreen { if let Some(map) = &mut self.display.map { Display::handle_resize(map, &mut self.inner); - let damage = self - .inner - .write(unsafe { &mut map.console_map() }, buf, &mut self.input); + let damage = self.inner.write(map, buf, &mut self.input); self.display.sync_rect(damage); } diff --git a/drivers/graphics/graphics-ipc/Cargo.toml b/drivers/graphics/graphics-ipc/Cargo.toml index 8e8d98503d..5ad5afd9a0 100644 --- a/drivers/graphics/graphics-ipc/Cargo.toml +++ b/drivers/graphics/graphics-ipc/Cargo.toml @@ -5,7 +5,6 @@ edition = "2021" [dependencies] drm = "0.14" -drm-fourcc = "2.2.0" log = "0.4" libredox = "0.1.3" redox-ioctl = { git = "https://gitlab.redox-os.org/redox-os/relibc.git" } diff --git a/drivers/graphics/graphics-ipc/src/common.rs b/drivers/graphics/graphics-ipc/src/common.rs index 81e02640d5..ca5dc48392 100644 --- a/drivers/graphics/graphics-ipc/src/common.rs +++ b/drivers/graphics/graphics-ipc/src/common.rs @@ -13,6 +13,35 @@ pub struct Damage { } impl Damage { + pub const NONE: Self = Damage { + x: 0, + y: 0, + width: 0, + height: 0, + }; + + pub fn merge(self, other: Self) -> Self { + if self.width == 0 || self.height == 0 { + return other; + } + + if other.width == 0 || other.height == 0 { + return self; + } + + let x = cmp::min(self.x, other.x); + let y = cmp::min(self.y, other.y); + let x2 = cmp::max(self.x + self.width, other.x + other.width); + let y2 = cmp::max(self.y + self.height, other.y + other.height); + + Damage { + x, + y, + width: x2 - x, + height: y2 - y, + } + } + #[must_use] pub fn clip(mut self, width: u32, height: u32) -> Self { // Clip damage @@ -30,46 +59,3 @@ impl Damage { self } } - -pub struct DisplayMap { - offscreen: *mut [u32], - width: usize, - height: usize, -} - -impl DisplayMap { - pub(crate) unsafe fn new(offscreen: *mut [u32], width: usize, height: usize) -> Self { - DisplayMap { - offscreen, - width, - height, - } - } - - pub fn ptr(&self) -> *const [u32] { - self.offscreen - } - - pub fn ptr_mut(&mut self) -> *mut [u32] { - self.offscreen - } - - pub fn width(&self) -> usize { - self.width - } - - pub fn height(&self) -> usize { - self.height - } -} - -unsafe impl Send for DisplayMap {} -unsafe impl Sync for DisplayMap {} - -impl Drop for DisplayMap { - fn drop(&mut self) { - unsafe { - let _ = libredox::call::munmap(self.offscreen as *mut (), self.offscreen.len()); - } - } -} diff --git a/drivers/graphics/graphics-ipc/src/v1.rs b/drivers/graphics/graphics-ipc/src/v1.rs index 640d117bab..df882024c2 100644 --- a/drivers/graphics/graphics-ipc/src/v1.rs +++ b/drivers/graphics/graphics-ipc/src/v1.rs @@ -1,80 +1,4 @@ -use std::fs::File; -use std::os::unix::io::AsRawFd; -use std::{io, mem, ptr, slice}; - -use libredox::flag; - pub use crate::common::Damage; -pub use crate::common::DisplayMap; - -/// A graphics handle using the v1 graphics API. -/// -/// The v1 graphics API only allows a single framebuffer for each VT, requires each display to be -/// handled separately and doesn't support page flipping. -/// -/// This API is stable. No breaking changes are allowed to be made without a version bump. -pub struct V1GraphicsHandle { - file: File, -} - -impl V1GraphicsHandle { - pub fn from_file(file: File) -> io::Result { - Ok(V1GraphicsHandle { file }) - } - - pub fn map_display(&self) -> io::Result { - let mut buf: [u8; 4096] = [0; 4096]; - let count = - libredox::call::fpath(self.file.as_raw_fd() as usize, &mut buf).unwrap_or_else(|e| { - panic!("Could not read display path with fpath(): {e}"); - }); - - let url = - String::from_utf8(Vec::from(&buf[..count])).expect("Could not create Utf8 Url String"); - let path = url.split(':').nth(1).expect("Could not get path from url"); - - let mut path_parts = path.split('/').skip(1); - let width = path_parts - .next() - .unwrap_or("") - .parse::() - .unwrap_or(0); - let height = path_parts - .next() - .unwrap_or("") - .parse::() - .unwrap_or(0); - - let display_ptr = unsafe { - libredox::call::mmap(libredox::call::MmapArgs { - fd: self.file.as_raw_fd() as usize, - offset: 0, - length: (width * height * 4), - prot: flag::PROT_READ | flag::PROT_WRITE, - flags: flag::MAP_SHARED, - addr: core::ptr::null_mut(), - })? - }; - let offscreen = ptr::slice_from_raw_parts_mut(display_ptr as *mut u32, width * height); - - Ok(unsafe { DisplayMap::new(offscreen, width, height) }) - } - - pub fn sync_full_screen(&self) -> io::Result<()> { - libredox::call::fsync(self.file.as_raw_fd() as usize)?; - Ok(()) - } - - pub fn sync_rect(&self, sync_rect: Damage) -> io::Result<()> { - libredox::call::write(self.file.as_raw_fd() as usize, unsafe { - slice::from_raw_parts( - ptr::addr_of!(sync_rect).cast::(), - mem::size_of::(), - ) - })?; - Ok(()) - } -} #[derive(Debug, Copy, Clone)] #[repr(C, packed)] diff --git a/drivers/graphics/graphics-ipc/src/v2.rs b/drivers/graphics/graphics-ipc/src/v2.rs index fb9c98b997..fc368ccb89 100644 --- a/drivers/graphics/graphics-ipc/src/v2.rs +++ b/drivers/graphics/graphics-ipc/src/v2.rs @@ -4,12 +4,10 @@ use std::os::unix::io::AsRawFd; use std::{io, mem}; use drm::control::connector::{self, State}; -use drm::control::dumbbuffer::{DumbBuffer, DumbMapping}; use drm::control::Device as _; use drm::{ClientCapability, Device as _, DriverCapability}; -use drm_fourcc::DrmFourcc; -pub use crate::common::{Damage, DisplayMap}; +pub use crate::common::Damage; extern "C" { fn redox_sys_call_v0( @@ -75,26 +73,6 @@ impl V2GraphicsHandle { Err(io::Error::other("no connected display")) } - pub fn display_size(&self, handle: connector::Handle) -> io::Result<(u32, u32)> { - let (width, height) = self.get_connector(handle, true)?.modes()[0].size(); - Ok((u32::from(width), u32::from(height))) - } - - pub fn create_dumb_framebuffer(&self, width: u32, height: u32) -> io::Result { - self.create_dumb_buffer((width, height), DrmFourcc::Argb8888, 32) - } - - pub fn map_dumb_framebuffer<'a>( - &self, - buffer: &'a mut DumbBuffer, - ) -> io::Result> { - self.map_dumb_buffer(buffer) - } - - pub fn destroy_dumb_framebuffer(&self, buffer: DumbBuffer) -> io::Result<()> { - self.destroy_dumb_buffer(buffer) - } - pub fn update_plane(&self, display_id: usize, fb_id: u32, damage: Damage) -> io::Result<()> { let mut cmd = ipc::UpdatePlane { display_id,