diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 8dfb34612c..741a4c3dfc 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -39,8 +39,7 @@ pub struct StandardProperties { pub trait GraphicsAdapter: Sized + Debug { type Connector: Debug + 'static; - type Framebuffer: Framebuffer; - type Cursor: CursorFramebuffer; + type Buffer: Buffer; fn name(&self) -> &'static [u8]; fn desc(&self) -> &'static [u8]; @@ -63,23 +62,27 @@ pub trait GraphicsAdapter: Sized + Debug { fn display_count(&self) -> usize; fn display_size(&self, display_id: usize) -> (u32, u32); - fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer; - fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8; + fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer; + fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8; - fn update_plane(&mut self, display_id: usize, framebuffer: &Self::Framebuffer, damage: Damage); + fn update_plane( + &mut self, + display_id: usize, + framebuffer: Option<&Self::Buffer>, + damage: Damage, + ); - fn supports_hw_cursor(&self) -> bool; - fn create_cursor_framebuffer(&mut self) -> Self::Cursor; - fn map_cursor_framebuffer(&mut self, cursor: &Self::Cursor) -> *mut u8; - fn handle_cursor(&mut self, cursor: &CursorPlane, dirty_fb: bool); + fn hw_cursor_size(&self) -> Option<(u32, u32)>; + fn handle_cursor(&mut self, cursor: Option<&CursorPlane>, dirty_fb: bool); } -pub trait Framebuffer { +pub trait Buffer { fn width(&self) -> u32; fn height(&self) -> u32; } -pub struct CursorPlane { +#[derive(Debug)] +pub struct CursorPlane { pub x: i32, pub y: i32, pub hot_x: i32, @@ -87,8 +90,6 @@ pub struct CursorPlane { pub framebuffer: C, } -pub trait CursorFramebuffer {} - pub struct GraphicsScheme { inner: GraphicsSchemeInner, inputd_handle: DisplayHandle, @@ -217,15 +218,22 @@ impl GraphicsScheme { ); for (display_id, fb) in vt_state.display_fbs.iter().enumerate() { - GraphicsSchemeInner::update_whole_screen( - &mut self.inner.adapter, + self.inner.adapter.update_plane( display_id, - fb, + fb.as_deref(), + Damage { + x: 0, + y: 0, + width: fb.as_deref().map_or(0, |fb| fb.width()), + height: fb.as_deref().map_or(0, |fb| fb.height()), + }, ); } - if let Some(cursor_plane) = &vt_state.cursor_plane { - self.inner.adapter.handle_cursor(cursor_plane, true); + if self.inner.adapter.hw_cursor_size().is_some() { + self.inner + .adapter + .handle_cursor(vt_state.cursor_plane.as_ref(), true); } } @@ -291,8 +299,8 @@ struct GraphicsSchemeInner { } struct VtState { - display_fbs: Vec>, - cursor_plane: Option>, + display_fbs: Vec>>, + cursor_plane: Option>, } enum Handle { @@ -304,7 +312,7 @@ enum Handle { V2 { vt: usize, next_id: u32, - fbs: HashMap>, + fbs: HashMap>, }, SchemeRoot, } @@ -315,41 +323,12 @@ impl GraphicsSchemeInner { vts: &'a mut HashMap>, vt: usize, ) -> &'a mut VtState { - vts.entry(vt).or_insert_with(|| { - let mut display_fbs = vec![]; - for display_id in 0..adapter.display_count() { - let (width, height) = adapter.display_size(display_id); - display_fbs.push(Arc::new(adapter.create_dumb_framebuffer(width, height))); - } - - let cursor_plane = adapter.supports_hw_cursor().then(|| CursorPlane { - x: 0, - y: 0, - hot_x: 0, - hot_y: 0, - framebuffer: adapter.create_cursor_framebuffer(), - }); - - VtState { - display_fbs, - cursor_plane, - } + vts.entry(vt).or_insert_with(|| VtState { + display_fbs: vec![None; adapter.display_count()], + cursor_plane: None, }) } - fn update_whole_screen(adapter: &mut T, screen: usize, framebuffer: &T::Framebuffer) { - adapter.update_plane( - screen, - framebuffer, - Damage { - x: 0, - y: 0, - width: framebuffer.width(), - height: framebuffer.height(), - }, - ); - } - fn handle_cursor_update( &mut self, vt: usize, @@ -357,11 +336,18 @@ impl GraphicsSchemeInner { ) -> Result<()> { let vt_state = self.vts.get_mut(&vt).unwrap(); - let Some(cursor_plane) = &mut vt_state.cursor_plane else { - // Hardware cursor not supported + let Some((width, height)) = self.adapter.hw_cursor_size() else { return Err(Error::new(EINVAL)); }; + let cursor_plane = vt_state.cursor_plane.get_or_insert_with(|| CursorPlane { + x: 0, + y: 0, + hot_x: 0, + hot_y: 0, + framebuffer: self.adapter.create_dumb_buffer(width, height), + }); + cursor_plane.x = cursor_damage.x; cursor_plane.y = cursor_damage.y; @@ -370,7 +356,7 @@ impl GraphicsSchemeInner { return Ok(()); } - self.adapter.handle_cursor(cursor_plane, false); + self.adapter.handle_cursor(Some(cursor_plane), false); } else { cursor_plane.hot_x = cursor_damage.hot_x; cursor_plane.hot_y = cursor_damage.hot_y; @@ -378,9 +364,7 @@ impl GraphicsSchemeInner { let w: i32 = cursor_damage.width; let h: i32 = cursor_damage.height; let cursor_image = cursor_damage.cursor_img_bytes; - let cursor_ptr = self - .adapter - .map_cursor_framebuffer(&cursor_plane.framebuffer); + let cursor_ptr = self.adapter.map_dumb_buffer(&cursor_plane.framebuffer); //Clear previous image from backing storage unsafe { @@ -405,7 +389,7 @@ impl GraphicsSchemeInner { return Ok(()); } - self.adapter.handle_cursor(cursor_plane, true); + self.adapter.handle_cursor(Some(cursor_plane), true); } return Ok(()); @@ -483,13 +467,8 @@ impl SchemeSync for GraphicsSchemeInner { fn fpath(&mut self, id: usize, buf: &mut [u8], _ctx: &CallerCtx) -> syscall::Result { let path = match self.handles.get(&id).ok_or(Error::new(EBADF))? { Handle::V1Screen { vt, screen } => { - let framebuffer = &self.vts[vt].display_fbs[*screen]; - format!( - "{}:{vt}.{screen}/{}/{}", - self.scheme_name, - framebuffer.width(), - framebuffer.height() - ) + let (width, height) = self.adapter.display_size(*screen); + format!("{}:{vt}.{screen}/{width}/{height}", self.scheme_name) } Handle::V2 { vt, @@ -629,7 +608,7 @@ impl SchemeSync for GraphicsSchemeInner { } let connector = self .objects - .get_connector_mut(DrmObjectId(data.connector_id()))?; + .get_connector(DrmObjectId(data.connector_id()))?; data.set_connection(connector.connection as u32); data.set_modes_ptr(&connector.modes); data.set_mm_width(connector.mm_width); @@ -753,9 +732,7 @@ impl SchemeSync for GraphicsSchemeInner { return Err(Error::new(EINVAL)); } - let fb = self - .adapter - .create_dumb_framebuffer(data.width(), data.height()); + let fb = self.adapter.create_dumb_buffer(data.width(), data.height()); *next_id += 1; fbs.insert(*next_id, Arc::new(fb)); @@ -856,15 +833,23 @@ impl SchemeSync for GraphicsSchemeInner { return Err(Error::new(EINVAL)); } - let Some(framebuffer) = fbs.get(&id_index(payload.fb_id)) else { + let framebuffer = if payload.fb_id == 0 { + None + } else if let Some(framebuffer) = fbs.get(&id_index(payload.fb_id)) { + Some(framebuffer) + } else { return Err(Error::new(EINVAL)); }; - self.vts.get_mut(vt).unwrap().display_fbs[display_id] = framebuffer.clone(); + self.vts.get_mut(vt).unwrap().display_fbs[display_id] = + framebuffer.map(Arc::clone); if *vt == self.active_vt { - self.adapter - .update_plane(display_id, framebuffer, payload.damage); + self.adapter.update_plane( + display_id, + framebuffer.map(|fb| &**fb), + payload.damage, + ); } Ok(size_of::()) @@ -910,7 +895,7 @@ impl SchemeSync for GraphicsSchemeInner { ), Handle::V1Screen { .. } | Handle::SchemeRoot => return Err(Error::new(EOPNOTSUPP)), }; - let ptr = T::map_dumb_framebuffer(&mut self.adapter, framebuffer); + let ptr = T::map_dumb_buffer(&mut self.adapter, framebuffer); Ok(unsafe { ptr.add(offset as usize) } as usize) } } diff --git a/drivers/graphics/driver-graphics/src/objects.rs b/drivers/graphics/driver-graphics/src/objects.rs index a90029e374..a7d04a949e 100644 --- a/drivers/graphics/driver-graphics/src/objects.rs +++ b/drivers/graphics/driver-graphics/src/objects.rs @@ -66,9 +66,16 @@ impl DrmObjects { } pub fn add_connector(&mut self, driver_data: T::Connector) -> DrmObjectId { + let encoder_id = self.add(DrmEncoder { + crtc_id: DrmObjectId::INVALID, + possible_crtcs: 0, + possible_clones: 0, + }); + self.encoders.push(encoder_id); + let connector_id = self.add(DrmConnector { modes: vec![], - encoder_id: DrmObjectId::INVALID, + encoder_id, connector_type: 0, connector_type_id: 0, connection: DrmConnectorStatus::Unknown, @@ -79,15 +86,6 @@ impl DrmObjects { }); self.connectors.push(connector_id); - let encoder_id = self.add(DrmEncoder { - crtc_id: DrmObjectId::INVALID, - possible_crtcs: 0, - possible_clones: 0, - }); - self.encoders.push(encoder_id); - - self.get_connector_mut(connector_id).unwrap().encoder_id = encoder_id; - connector_id } @@ -121,10 +119,6 @@ impl DrmObjects { pub fn get_encoder(&self, id: DrmObjectId) -> Result<&DrmEncoder> { self.get(id) } - - pub fn get_encoder_mut(&mut self, id: DrmObjectId) -> Result<&mut DrmEncoder> { - self.get_mut(id) - } } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] diff --git a/drivers/graphics/ihdgd/src/device/scheme.rs b/drivers/graphics/ihdgd/src/device/scheme.rs index 742d61a1db..4b2b9f7115 100644 --- a/drivers/graphics/ihdgd/src/device/scheme.rs +++ b/drivers/graphics/ihdgd/src/device/scheme.rs @@ -6,8 +6,7 @@ use std::ptr::{self, NonNull}; use driver_graphics::objects::{DrmConnectorStatus, DrmObjectId, DrmObjects}; use driver_graphics::{ - modeinfo_for_size, CursorFramebuffer, CursorPlane, Framebuffer, GraphicsAdapter, - StandardProperties, + modeinfo_for_size, Buffer, CursorPlane, GraphicsAdapter, StandardProperties, }; use drm_sys::DRM_MODE_DPMS_ON; use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT}; @@ -21,16 +20,10 @@ pub struct Connector { framebuffer_id: usize, } -//TODO: use hardware cursor -pub enum Cursor {} - -impl CursorFramebuffer for Cursor {} - impl GraphicsAdapter for Device { type Connector = Connector; - type Framebuffer = DumbFb; - type Cursor = Cursor; + type Buffer = DumbFb; fn name(&self) -> &'static [u8] { b"ihdgd" @@ -94,31 +87,37 @@ impl GraphicsAdapter for Device { ) } - fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer { + fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer { DumbFb::new(width as usize, height as usize) } - fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8 { + fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8 { framebuffer.ptr.as_ptr().cast::() } - fn update_plane(&mut self, display_id: usize, framebuffer: &Self::Framebuffer, damage: Damage) { - framebuffer.sync(&mut self.framebuffers[display_id], damage) + fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) { + let framebuffer = &mut self.framebuffers[display_id]; + if let Some(buffer) = buffer { + buffer.sync(framebuffer, damage) + } else { + let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable + for row in 0..framebuffer.height { + unsafe { + ptr::write_bytes( + onscreen_ptr.add(row * framebuffer.stride), + 0, + framebuffer.width, + ); + } + } + } } - fn supports_hw_cursor(&self) -> bool { - false + fn hw_cursor_size(&self) -> Option<(u32, u32)> { + None } - fn create_cursor_framebuffer(&mut self) -> Self::Cursor { - unimplemented!("ihdgd does not support this function"); - } - - fn map_cursor_framebuffer(&mut self, _cursor: &Self::Cursor) -> *mut u8 { - unimplemented!("ihdgd does not support this function"); - } - - fn handle_cursor(&mut self, _cursor: &CursorPlane, _dirty_fb: bool) { + fn handle_cursor(&mut self, _cursor: Option<&CursorPlane>, _dirty_fb: bool) { unimplemented!("ihdgd does not support this function"); } } @@ -185,7 +184,7 @@ impl Drop for DumbFb { } } -impl Framebuffer for DumbFb { +impl Buffer for DumbFb { fn width(&self) -> u32 { self.width as u32 } diff --git a/drivers/graphics/vesad/src/scheme.rs b/drivers/graphics/vesad/src/scheme.rs index ab58b4b14a..b858067c6a 100644 --- a/drivers/graphics/vesad/src/scheme.rs +++ b/drivers/graphics/vesad/src/scheme.rs @@ -4,8 +4,7 @@ use std::ptr::{self, NonNull}; use driver_graphics::objects::{DrmConnectorStatus, DrmObjectId, DrmObjects}; use driver_graphics::{ - modeinfo_for_size, CursorFramebuffer, CursorPlane, Framebuffer, GraphicsAdapter, - StandardProperties, + modeinfo_for_size, Buffer, CursorPlane, GraphicsAdapter, StandardProperties, }; use drm_sys::DRM_MODE_DPMS_ON; use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT}; @@ -23,15 +22,10 @@ pub struct Connector { height: u32, } -pub enum VesadCursor {} - -impl CursorFramebuffer for VesadCursor {} - impl GraphicsAdapter for FbAdapter { type Connector = Connector; - type Framebuffer = GraphicScreen; - type Cursor = VesadCursor; + type Buffer = GraphicScreen; fn name(&self) -> &'static [u8] { b"vesad" @@ -94,31 +88,37 @@ impl GraphicsAdapter for FbAdapter { ) } - fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer { + fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer { GraphicScreen::new(width as usize, height as usize) } - fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8 { + fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8 { framebuffer.ptr.as_ptr().cast::() } - fn update_plane(&mut self, display_id: usize, framebuffer: &Self::Framebuffer, damage: Damage) { - framebuffer.sync(&mut self.framebuffers[display_id], damage) + fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) { + let framebuffer = &mut self.framebuffers[display_id]; + if let Some(buffer) = buffer { + buffer.sync(framebuffer, damage) + } else { + let onscreen_ptr = framebuffer.onscreen as *mut u32; // FIXME use as_mut_ptr once stable + for row in 0..framebuffer.height { + unsafe { + ptr::write_bytes( + onscreen_ptr.add(row * framebuffer.stride), + 0, + framebuffer.width, + ); + } + } + } } - fn supports_hw_cursor(&self) -> bool { - false + fn hw_cursor_size(&self) -> Option<(u32, u32)> { + None } - fn create_cursor_framebuffer(&mut self) -> VesadCursor { - unimplemented!("Vesad does not support this function"); - } - - fn map_cursor_framebuffer(&mut self, _cursor: &Self::Cursor) -> *mut u8 { - unimplemented!("Vesad does not support this function"); - } - - fn handle_cursor(&mut self, _cursor: &CursorPlane, _dirty_fb: bool) { + fn handle_cursor(&mut self, _cursor: Option<&CursorPlane>, _dirty_fb: bool) { unimplemented!("Vesad does not support this function"); } } @@ -216,7 +216,7 @@ impl Drop for GraphicScreen { } } -impl Framebuffer for GraphicScreen { +impl Buffer for GraphicScreen { fn width(&self) -> u32 { self.width as u32 } diff --git a/drivers/graphics/virtio-gpud/src/main.rs b/drivers/graphics/virtio-gpud/src/main.rs index 0796055534..8bf1239ef0 100644 --- a/drivers/graphics/virtio-gpud/src/main.rs +++ b/drivers/graphics/virtio-gpud/src/main.rs @@ -207,6 +207,8 @@ static RESOURCE_ALLOC: AtomicU32 = AtomicU32::new(1); // XXX: 0 is reserved for pub struct ResourceId(u32); impl ResourceId { + const NONE: ResourceId = ResourceId(0); + fn alloc() -> Self { ResourceId(RESOURCE_ALLOC.fetch_add(1, Ordering::SeqCst)) } diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs index 9aaae63770..259a5fd942 100644 --- a/drivers/graphics/virtio-gpud/src/scheme.rs +++ b/drivers/graphics/virtio-gpud/src/scheme.rs @@ -4,8 +4,8 @@ use std::sync::Arc; use common::{dma::Dma, sgl}; use driver_graphics::objects::{DrmConnectorStatus, DrmObjectId, DrmObjects}; use driver_graphics::{ - modeinfo_for_size, CursorFramebuffer, CursorPlane, Framebuffer, GraphicsAdapter, - GraphicsScheme, StandardProperties, + modeinfo_for_size, Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme, + StandardProperties, }; use drm_sys::{ DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH, DRM_MODE_DPMS_ON, DRM_MODE_TYPE_PREFERRED, @@ -44,7 +44,7 @@ pub struct VirtGpuFramebuffer<'a> { height: u32, } -impl Framebuffer for VirtGpuFramebuffer<'_> { +impl DrmBuffer for VirtGpuFramebuffer<'_> { fn width(&self) -> u32 { self.width } @@ -70,13 +70,6 @@ impl Drop for VirtGpuFramebuffer<'_> { } } -pub struct VirtGpuCursor { - resource_id: ResourceId, - sgl: sgl::Sgl, -} - -impl CursorFramebuffer for VirtGpuCursor {} - #[derive(Debug, Clone)] pub struct Display { enabled: bool, @@ -93,6 +86,7 @@ pub struct VirtGpuAdapter<'a> { transport: Arc, has_edid: bool, displays: Vec, + hidden_cursor: Option>>, } impl<'a> fmt::Debug for VirtGpuAdapter<'a> { @@ -200,11 +194,18 @@ impl VirtGpuAdapter<'_> { Ok(response) } - fn update_cursor(&mut self, cursor: &VirtGpuCursor, x: i32, y: i32, hot_x: i32, hot_y: i32) { + fn update_cursor( + &mut self, + cursor: &VirtGpuFramebuffer, + x: i32, + y: i32, + hot_x: i32, + hot_y: i32, + ) { //Transfering cursor resource to host futures::executor::block_on(async { let transfer_request = Dma::new(XferToHost2d::new( - cursor.resource_id, + cursor.id, GpuRect { x: 0, y: 0, @@ -219,14 +220,7 @@ impl VirtGpuAdapter<'_> { }); //Update the cursor position - let request = Dma::new(UpdateCursor::update_cursor( - x, - y, - hot_x, - hot_y, - cursor.resource_id, - )) - .unwrap(); + let request = Dma::new(UpdateCursor::update_cursor(x, y, hot_x, hot_y, cursor.id)).unwrap(); futures::executor::block_on(async { let command = ChainBuilder::new().chain(Buffer::new(&request)).build(); self.cursor_queue.send(command).await; @@ -241,13 +235,30 @@ impl VirtGpuAdapter<'_> { self.cursor_queue.send(command).await; }); } + + fn disable_cursor(&mut self) { + if self.hidden_cursor.is_none() { + let (width, height) = self.hw_cursor_size().unwrap(); + let cursor = self.create_dumb_buffer(width, height); + unsafe { + core::ptr::write_bytes( + cursor.sgl.as_ptr() as *mut u8, + 0, + (width * height * 4) as usize, + ); + } + self.hidden_cursor = Some(Arc::new(cursor)); + } + let hidden_cursor = self.hidden_cursor.as_ref().unwrap().clone(); + + self.update_cursor(&hidden_cursor, 0, 0, 0, 0); + } } impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { type Connector = VirtGpuConnector; - type Framebuffer = VirtGpuFramebuffer<'a>; - type Cursor = VirtGpuCursor; + type Buffer = VirtGpuFramebuffer<'a>; fn name(&self) -> &'static [u8] { b"virtio-gpud" @@ -278,8 +289,8 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { fn get_cap(&self, cap: u32) -> syscall::Result { match cap { DRM_CAP_DUMB_BUFFER => Ok(1), - DRM_CAP_CURSOR_WIDTH => Ok(32), - DRM_CAP_CURSOR_HEIGHT => Ok(32), + DRM_CAP_CURSOR_WIDTH => Ok(64), + DRM_CAP_CURSOR_HEIGHT => Ok(64), _ => Err(syscall::Error::new(EINVAL)), } } @@ -367,7 +378,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { ) } - fn create_dumb_framebuffer(&mut self, width: u32, height: u32) -> Self::Framebuffer { + fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer { futures::executor::block_on(async { let bpp = 32; let fb_size = width as usize * height as usize * bpp / 8; @@ -426,12 +437,30 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { }) } - fn map_dumb_framebuffer(&mut self, framebuffer: &Self::Framebuffer) -> *mut u8 { + fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8 { framebuffer.sgl.as_ptr() } - fn update_plane(&mut self, display_id: usize, framebuffer: &Self::Framebuffer, damage: Damage) { + fn update_plane( + &mut self, + display_id: usize, + framebuffer: Option<&Self::Buffer>, + damage: Damage, + ) { futures::executor::block_on(async { + let Some(framebuffer) = framebuffer else { + let scanout_request = Dma::new(SetScanout::new( + display_id as u32, + ResourceId::NONE, + GpuRect::new(0, 0, 0, 0), + )) + .unwrap(); + let header = self.send_request(scanout_request).await.unwrap(); + assert_eq!(header.ty, CommandTy::RespOkNodata); + self.displays[display_id].active_resource = None; + return; + }; + let req = Dma::new(XferToHost2d::new( framebuffer.id, GpuRect { @@ -468,88 +497,27 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { }); } - fn supports_hw_cursor(&self) -> bool { - true + fn hw_cursor_size(&self) -> Option<(u32, u32)> { + Some((64, 64)) } - fn create_cursor_framebuffer(&mut self) -> VirtGpuCursor { - //Creating a new resource for the cursor - let fb_size = 64 * 64 * 4; - let sgl = sgl::Sgl::new(fb_size).unwrap(); - let res_id = ResourceId::alloc(); - - futures::executor::block_on(async { - unsafe { - core::ptr::write_bytes(sgl.as_ptr() as *mut u8, 0, fb_size); + fn handle_cursor(&mut self, cursor: Option<&CursorPlane>, dirty_fb: bool) { + if let Some(cursor) = cursor { + if dirty_fb { + self.update_cursor( + &cursor.framebuffer, + cursor.x, + cursor.y, + cursor.hot_x, + cursor.hot_y, + ); + } else { + self.move_cursor(cursor.x, cursor.y); } - - let resource_request = - Dma::new(ResourceCreate2d::new(res_id, ResourceFormat::Bgrx, 64, 64)).unwrap(); - - let header = self.send_request_fenced(resource_request).await.unwrap(); - assert_eq!(header.ty, CommandTy::RespOkNodata); - - //Attaching cursor resource as backing storage - let mut mem_entries = - unsafe { Dma::zeroed_slice(sgl.chunks().len()).unwrap().assume_init() }; - for (entry, chunk) in mem_entries.iter_mut().zip(sgl.chunks().iter()) { - *entry = MemEntry { - address: chunk.phys as u64, - length: chunk.length.next_multiple_of(PAGE_SIZE) as u32, - padding: 0, - }; - } - - let attach_request = - Dma::new(AttachBacking::new(res_id, mem_entries.len() as u32)).unwrap(); - let mut header = Dma::new(ControlHeader::default()).unwrap(); - header.flags |= VIRTIO_GPU_FLAG_FENCE; - let command = ChainBuilder::new() - .chain(Buffer::new(&attach_request)) - .chain(Buffer::new_unsized(&mem_entries)) - .chain(Buffer::new(&header).flags(DescriptorFlags::WRITE_ONLY)) - .build(); - - self.control_queue.send(command).await; - assert_eq!(header.ty, CommandTy::RespOkNodata); - - //Transfering cursor resource to host - let transfer_request = Dma::new(XferToHost2d::new( - res_id, - GpuRect { - x: 0, - y: 0, - width: 64, - height: 64, - }, - 0, - )) - .unwrap(); - let header = self.send_request_fenced(transfer_request).await.unwrap(); - assert_eq!(header.ty, CommandTy::RespOkNodata); - }); - - VirtGpuCursor { - resource_id: res_id, - sgl, - } - } - - fn map_cursor_framebuffer(&mut self, cursor: &Self::Cursor) -> *mut u8 { - cursor.sgl.as_ptr() - } - - fn handle_cursor(&mut self, cursor: &CursorPlane, dirty_fb: bool) { - if dirty_fb { - self.update_cursor( - &cursor.framebuffer, - cursor.x, - cursor.y, - cursor.hot_x, - cursor.hot_y, - ); } else { - self.move_cursor(cursor.x, cursor.y); + if dirty_fb { + self.disable_cursor(); + } } } } @@ -571,6 +539,7 @@ impl<'a> GpuScheme { transport, has_edid, displays: vec![], + hidden_cursor: None, }; Ok(GraphicsScheme::new(