diff --git a/Cargo.lock b/Cargo.lock index 7dfaff86dd..78594176df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1793,7 +1793,7 @@ dependencies = [ [[package]] name = "redox-ioctl" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#f278abbb205803aeb17b022ac6ca20cce88b2843" +source = "git+https://gitlab.redox-os.org/redox-os/relibc.git#266bf56554403ac36425113af06ea9ea273ce820" dependencies = [ "drm-sys", "redox_syscall 0.7.3", diff --git a/drivers/graphics/driver-graphics/src/kms/connector.rs b/drivers/graphics/driver-graphics/src/kms/connector.rs index 248d9a3b3f..ed36692d08 100644 --- a/drivers/graphics/driver-graphics/src/kms/connector.rs +++ b/drivers/graphics/driver-graphics/src/kms/connector.rs @@ -9,10 +9,19 @@ use crate::kms::objects::{KmsObjectId, KmsObjects}; use crate::GraphicsAdapter; impl KmsObjects { - pub fn add_connector(&mut self, driver_data: T::Connector) -> KmsObjectId { + pub fn add_connector( + &mut self, + driver_data: T::Connector, + crtcs: &[KmsObjectId], + ) -> KmsObjectId { + let mut possible_crtcs = 0; + for &crtc in crtcs { + possible_crtcs = 1 << self.get_crtc(crtc).unwrap().lock().unwrap().crtc_index; + } + let encoder_id = self.add(KmsEncoder { crtc_id: KmsObjectId::INVALID, - possible_crtcs: 0, + possible_crtcs: possible_crtcs, possible_clones: 1 << self.encoders.len(), }); self.encoders.push(encoder_id); @@ -118,7 +127,7 @@ impl KmsConnector { // FIXME update the EDID property } - fn modeinfo_for_size(width: u32, height: u32) -> drm_mode_modeinfo { + pub(crate) fn modeinfo_for_size(width: u32, height: u32) -> drm_mode_modeinfo { let mut modeinfo = drm_mode_modeinfo { // The actual visible display size hdisplay: width as u16, diff --git a/drivers/graphics/driver-graphics/src/kms/objects.rs b/drivers/graphics/driver-graphics/src/kms/objects.rs index 8c5506a24d..c7b16ebf39 100644 --- a/drivers/graphics/driver-graphics/src/kms/objects.rs +++ b/drivers/graphics/driver-graphics/src/kms/objects.rs @@ -4,8 +4,8 @@ use std::marker::PhantomData; use std::sync::{Arc, Mutex}; use drm_sys::{ - DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_ENCODER, - DRM_MODE_OBJECT_PROPERTY, + drm_mode_modeinfo, DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_CRTC, + DRM_MODE_OBJECT_ENCODER, DRM_MODE_OBJECT_PROPERTY, }; use syscall::{Error, Result, EINVAL}; @@ -18,6 +18,7 @@ pub struct KmsObjects { next_id: KmsObjectId, pub(crate) connectors: Vec, pub(crate) encoders: Vec, + crtcs: Vec, pub(crate) objects: HashMap>>, _marker: PhantomData, } @@ -28,6 +29,7 @@ impl KmsObjects { next_id: KmsObjectId(1), connectors: vec![], encoders: vec![], + crtcs: vec![], objects: HashMap::new(), _marker: PhantomData, } @@ -63,6 +65,34 @@ impl KmsObjects { let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?; Ok(object.kind.object_type()) } + + pub fn add_crtc(&mut self, driver_data: T::Crtc) -> KmsObjectId { + let crtc_index = self.crtcs.len() as u32; + let id = self.add(Mutex::new(KmsCrtc { + crtc_index, + fb_id: KmsObjectId::INVALID, + gamma_size: 0, + mode: None, + driver_data, + })); + self.crtcs.push(id); + + id + } + + pub fn crtc_ids(&self) -> &[KmsObjectId] { + &self.crtcs + } + + pub fn crtcs(&self) -> impl Iterator>> + use<'_, T> { + self.crtcs + .iter() + .map(|&id| self.get::>>(id).unwrap()) + } + + pub fn get_crtc(&self, id: KmsObjectId) -> Result<&Mutex>> { + self.get(id) + } } #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] @@ -124,8 +154,18 @@ macro_rules! define_object_kinds { } define_object_kinds! { + Crtc(Mutex>) = DRM_MODE_OBJECT_CRTC, Connector(Mutex>) = DRM_MODE_OBJECT_CONNECTOR, Encoder(KmsEncoder) = DRM_MODE_OBJECT_ENCODER, Property(KmsProperty) = DRM_MODE_OBJECT_PROPERTY, Blob(KmsBlob) = DRM_MODE_OBJECT_BLOB, } + +#[derive(Debug)] +pub struct KmsCrtc { + pub crtc_index: u32, + pub fb_id: KmsObjectId, + pub gamma_size: u32, + pub mode: Option, + pub driver_data: T, +} diff --git a/drivers/graphics/driver-graphics/src/lib.rs b/drivers/graphics/driver-graphics/src/lib.rs index 0565fa8f55..bad8e93160 100644 --- a/drivers/graphics/driver-graphics/src/lib.rs +++ b/drivers/graphics/driver-graphics/src/lib.rs @@ -8,13 +8,14 @@ use std::io::{self, Write}; use std::mem; use std::mem::transmute; use std::os::fd::BorrowedFd; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use drm_sys::{ - drm_mode_property_enum, DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON, DRM_MODE_DPMS_STANDBY, - DRM_MODE_DPMS_SUSPEND, DRM_MODE_PROP_ATOMIC, DRM_MODE_PROP_BITMASK, DRM_MODE_PROP_BLOB, - DRM_MODE_PROP_ENUM, DRM_MODE_PROP_IMMUTABLE, DRM_MODE_PROP_OBJECT, DRM_MODE_PROP_RANGE, - DRM_MODE_PROP_SIGNED_RANGE, DRM_PROP_NAME_LEN, + drm_mode_modeinfo, drm_mode_property_enum, DRM_MODE_CURSOR_BO, DRM_MODE_CURSOR_MOVE, + DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON, DRM_MODE_DPMS_STANDBY, DRM_MODE_DPMS_SUSPEND, + DRM_MODE_PROP_ATOMIC, DRM_MODE_PROP_BITMASK, DRM_MODE_PROP_BLOB, DRM_MODE_PROP_ENUM, + DRM_MODE_PROP_IMMUTABLE, DRM_MODE_PROP_OBJECT, DRM_MODE_PROP_RANGE, DRM_MODE_PROP_SIGNED_RANGE, + DRM_PROP_NAME_LEN, }; use graphics_ipc::v2::Damage; use inputd::{DisplayHandle, VtEventKind}; @@ -24,7 +25,8 @@ use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket}; use syscall::schemev2::NewFdFlags; use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EBADF, EINVAL, ENOENT, EOPNOTSUPP}; -use crate::kms::objects::{KmsObjectId, KmsObjects}; +use crate::kms::connector::KmsConnector; +use crate::kms::objects::{KmsCrtc, KmsObjectId, KmsObjects}; use crate::kms::properties::KmsPropertyKind; pub mod kms; @@ -37,6 +39,7 @@ pub struct StandardProperties { pub trait GraphicsAdapter: Sized + Debug { type Connector: Debug; + type Crtc: Debug; type Buffer: Buffer; @@ -64,15 +67,18 @@ pub trait GraphicsAdapter: Sized + Debug { 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( + fn set_crtc( &mut self, - display_id: usize, + objects: &KmsObjects, + crtc: &Mutex>, + connectors: &[KmsObjectId], + mode: Option, framebuffer: Option<&Self::Buffer>, damage: Damage, ); fn hw_cursor_size(&self) -> Option<(u32, u32)>; - fn handle_cursor(&mut self, cursor: Option<&CursorPlane>, dirty_fb: bool); + fn handle_cursor(&mut self, cursor: &CursorPlane, dirty_fb: bool); } pub trait Buffer: Debug { @@ -86,7 +92,7 @@ pub struct CursorPlane { pub y: i32, pub hot_x: i32, pub hot_y: i32, - pub framebuffer: C, + pub framebuffer: Option>, } pub struct GraphicsScheme { @@ -217,8 +223,17 @@ impl GraphicsScheme { ); for (display_id, fb) in vt_state.display_fbs.iter().enumerate() { - self.inner.adapter.update_plane( - display_id, + let crtc = self.inner.objects.crtcs().nth(display_id).unwrap(); + + let mode = fb.as_ref().map(|fb| { + KmsConnector::<()>::modeinfo_for_size(fb.width(), fb.height()) + }); + + self.inner.adapter.set_crtc( + &self.inner.objects, + crtc, + &[self.inner.objects.connector_ids()[display_id]], + mode, fb.as_deref(), Damage { x: 0, @@ -232,7 +247,7 @@ impl GraphicsScheme { if self.inner.adapter.hw_cursor_size().is_some() { self.inner .adapter - .handle_cursor(vt_state.cursor_plane.as_ref(), true); + .handle_cursor(&vt_state.cursor_plane, true); } } @@ -299,7 +314,7 @@ struct GraphicsSchemeInner { struct VtState { display_fbs: Vec>>, - cursor_plane: Option>, + cursor_plane: CursorPlane, } enum Handle { @@ -324,7 +339,13 @@ impl GraphicsSchemeInner { ) -> &'a mut VtState { vts.entry(vt).or_insert_with(|| VtState { display_fbs: vec![None; adapter.display_count()], - cursor_plane: None, + cursor_plane: CursorPlane { + x: 0, + y: 0, + hot_x: 0, + hot_y: 0, + framebuffer: None, + }, }) } @@ -339,13 +360,7 @@ impl GraphicsSchemeInner { 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), - }); + let cursor_plane = &mut vt_state.cursor_plane; cursor_plane.x = cursor_damage.x; cursor_plane.y = cursor_damage.y; @@ -355,7 +370,7 @@ impl GraphicsSchemeInner { return Ok(()); } - self.adapter.handle_cursor(Some(cursor_plane), false); + self.adapter.handle_cursor(cursor_plane, false); } else { cursor_plane.hot_x = cursor_damage.hot_x; cursor_plane.hot_y = cursor_damage.hot_y; @@ -363,7 +378,10 @@ 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_dumb_buffer(&cursor_plane.framebuffer); + let framebuffer = cursor_plane + .framebuffer + .get_or_insert_with(|| Arc::new(self.adapter.create_dumb_buffer(width, height))); + let cursor_ptr = self.adapter.map_dumb_buffer(framebuffer); //Clear previous image from backing storage unsafe { @@ -388,7 +406,7 @@ impl GraphicsSchemeInner { return Ok(()); } - self.adapter.handle_cursor(Some(cursor_plane), true); + self.adapter.handle_cursor(cursor_plane, true); } return Ok(()); @@ -495,10 +513,6 @@ impl SchemeSync for GraphicsSchemeInner { id & 0xFF } - fn crtc_id(i: u32) -> u32 { - id_index(i) | (1 << 10) - } - fn fb_id(i: u32) -> u32 { id_index(i) | (1 << 11) } @@ -556,7 +570,12 @@ impl SchemeSync for GraphicsSchemeInner { .iter() .map(|id| id.0) .collect::>(); - let mut crtc_ids = Vec::with_capacity(count); + let crtc_ids = self + .objects + .crtc_ids() + .iter() + .map(|id| id.0) + .collect::>(); let enc_ids = self .objects .encoder_ids() @@ -565,7 +584,6 @@ impl SchemeSync for GraphicsSchemeInner { .collect::>(); let mut fb_ids = Vec::with_capacity(count); for i in 0..(count as u32) { - crtc_ids.push(crtc_id(i)); fb_ids.push(fb_id(i)); } data.set_fb_id_ptr(&fb_ids); @@ -579,15 +597,49 @@ impl SchemeSync for GraphicsSchemeInner { Ok(0) }), ipc::MODE_GET_CRTC => ipc::DrmModeCrtc::with(payload, |mut data| { - let i = id_index(data.crtc_id()); - //TOOD: connectors - data.set_fb_id(fb_id(i)); + let crtc = self + .objects + .get_crtc(KmsObjectId(data.crtc_id()))? + .lock() + .unwrap(); + // Don't touch set_connectors, that is only used by MODE_SET_CRTC + data.set_fb_id(crtc.fb_id.0); + // FIXME fill x and y with the data from the primary plane data.set_x(0); data.set_y(0); - data.set_gamma_size(0); - data.set_mode_valid(0); - //TODO: mode - data.set_mode(Default::default()); + data.set_gamma_size(crtc.gamma_size); + if let Some(mode) = crtc.mode { + data.set_mode_valid(1); + data.set_mode(mode); + } else { + data.set_mode_valid(0); + data.set_mode(Default::default()); + } + Ok(0) + }), + ipc::MODE_CURSOR => ipc::DrmModeCursor::with(payload, |data| { + let vt_state = self.vts.get_mut(vt).unwrap(); + + let cursor_plane = &mut vt_state.cursor_plane; + + let update_buffer = data.flags() & DRM_MODE_CURSOR_BO != 0; + if update_buffer { + cursor_plane.framebuffer = if data.handle() == 0 { + None + } else if let Some(buffer) = fbs.get(&id_index(data.handle())) { + Some(buffer.clone()) + } else { + return Err(Error::new(EINVAL)); + }; + } + + if data.flags() & DRM_MODE_CURSOR_MOVE != 0 { + cursor_plane.x = data.x(); + cursor_plane.y = data.y(); + } + + self.adapter.handle_cursor(cursor_plane, update_buffer); + Ok(0) }), ipc::MODE_GET_ENCODER => ipc::DrmModeGetEncoder::with(payload, |mut data| { @@ -785,7 +837,7 @@ impl SchemeSync for GraphicsSchemeInner { }), ipc::MODE_GET_PLANE => ipc::DrmModeGetPlane::with(payload, |mut data| { let i = id_index(data.plane_id()); - data.set_crtc_id(crtc_id(i)); + data.set_crtc_id(self.objects.crtc_ids()[i as usize].0); data.set_fb_id(fb_id(i)); data.set_possible_crtcs(1 << i); data.set_format_type_ptr(&[DRM_FORMAT_ARGB8888]); @@ -794,7 +846,7 @@ impl SchemeSync for GraphicsSchemeInner { ipc::MODE_OBJ_GET_PROPERTIES => { ipc::DrmModeObjGetProperties::with(payload, |mut data| { // FIXME remove once all drm objects are materialized in self.objects - if data.obj_id() >= 1 << 10 { + if data.obj_id() >= 1 << 11 { data.set_props_ptr(&[]); data.set_prop_values_ptr(&[]); return Ok(0); @@ -813,6 +865,33 @@ impl SchemeSync for GraphicsSchemeInner { Ok(0) }) } + ipc::MODE_CURSOR2 => ipc::DrmModeCursor2::with(payload, |data| { + let vt_state = self.vts.get_mut(vt).unwrap(); + + let cursor_plane = &mut vt_state.cursor_plane; + + let update_buffer = data.flags() & DRM_MODE_CURSOR_BO != 0; + if update_buffer { + cursor_plane.framebuffer = if data.handle() == 0 { + None + } else if let Some(buffer) = fbs.get(&id_index(data.handle())) { + Some(buffer.clone()) + } else { + return Err(Error::new(EINVAL)); + }; + cursor_plane.hot_x = data.hot_x(); + cursor_plane.hot_y = data.hot_y(); + } + + if data.flags() & DRM_MODE_CURSOR_MOVE != 0 { + cursor_plane.x = data.x(); + cursor_plane.y = data.y(); + } + + self.adapter.handle_cursor(cursor_plane, update_buffer); + + Ok(0) + }), ipc::MODE_GET_FB2 => ipc::DrmModeFbCmd2::with(payload, |mut data| { let i = id_index(data.fb_id()); let (width, height) = self.adapter.display_size(i as usize); @@ -836,9 +915,9 @@ impl SchemeSync for GraphicsSchemeInner { }; let display_id = payload.display_id; - if display_id >= self.adapter.display_count() { + let Some(crtc) = self.objects.crtcs().nth(display_id) else { return Err(Error::new(EINVAL)); - } + }; let framebuffer = if payload.fb_id == 0 { None @@ -852,8 +931,15 @@ impl SchemeSync for GraphicsSchemeInner { framebuffer.map(Arc::clone); if *vt == self.active_vt { - self.adapter.update_plane( - display_id, + let mode = framebuffer.as_ref().map(|fb| { + KmsConnector::<()>::modeinfo_for_size(fb.width(), fb.height()) + }); + + self.adapter.set_crtc( + &self.objects, + crtc, + &[self.objects.connector_ids()[display_id]], + mode, framebuffer.map(|fb| &**fb), payload.damage, ); diff --git a/drivers/graphics/ihdgd/src/device/scheme.rs b/drivers/graphics/ihdgd/src/device/scheme.rs index 8fd741bb89..287aa31dea 100644 --- a/drivers/graphics/ihdgd/src/device/scheme.rs +++ b/drivers/graphics/ihdgd/src/device/scheme.rs @@ -3,11 +3,12 @@ use std::alloc::{self, Layout}; use std::convert::TryInto; use std::ptr::{self, NonNull}; +use std::sync::Mutex; use driver_graphics::kms::connector::KmsConnectorStatus; -use driver_graphics::kms::objects::{KmsObjectId, KmsObjects}; +use driver_graphics::kms::objects::{KmsCrtc, KmsObjectId, KmsObjects}; use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties}; -use drm_sys::DRM_MODE_DPMS_ON; +use drm_sys::{drm_mode_modeinfo, DRM_MODE_DPMS_ON}; use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT}; use graphics_ipc::v2::Damage; use syscall::{error::EINVAL, PAGE_SIZE}; @@ -21,6 +22,7 @@ pub struct Connector { impl GraphicsAdapter for Device { type Connector = Connector; + type Crtc = (); type Buffer = DumbFb; @@ -35,7 +37,9 @@ impl GraphicsAdapter for Device { fn init(&mut self, objects: &mut KmsObjects, standard_properties: &StandardProperties) { // FIXME enumerate actual connectors for (framebuffer_id, _) in self.framebuffers.iter().enumerate() { - let connector = objects.add_connector(Connector { framebuffer_id }); + let crtc = objects.add_crtc(()); + + let connector = objects.add_connector(Connector { framebuffer_id }, &[crtc]); objects.add_object_property( connector, standard_properties.dpms, @@ -91,8 +95,26 @@ impl GraphicsAdapter for Device { framebuffer.ptr.as_ptr().cast::() } - fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) { - let framebuffer = &mut self.framebuffers[display_id]; + fn set_crtc( + &mut self, + objects: &KmsObjects, + crtc: &Mutex>, + connectors: &[KmsObjectId], + mode: Option, + buffer: Option<&Self::Buffer>, + damage: Damage, + ) { + crtc.lock().unwrap().mode = mode; + + let framebuffer_id = objects + .get_connector(connectors[0]) + .unwrap() + .lock() + .unwrap() + .driver_data + .framebuffer_id; + + let framebuffer = &mut self.framebuffers[framebuffer_id]; if let Some(buffer) = buffer { buffer.sync(framebuffer, damage) } else { @@ -113,7 +135,7 @@ impl GraphicsAdapter for Device { None } - fn handle_cursor(&mut self, _cursor: Option<&CursorPlane>, _dirty_fb: bool) { + fn handle_cursor(&mut self, _cursor: &CursorPlane, _dirty_fb: bool) { unimplemented!("ihdgd does not support this function"); } } diff --git a/drivers/graphics/vesad/src/scheme.rs b/drivers/graphics/vesad/src/scheme.rs index f1bbd60cba..6aa1cfc559 100644 --- a/drivers/graphics/vesad/src/scheme.rs +++ b/drivers/graphics/vesad/src/scheme.rs @@ -1,11 +1,12 @@ use std::alloc::{self, Layout}; use std::convert::TryInto; use std::ptr::{self, NonNull}; +use std::sync::Mutex; use driver_graphics::kms::connector::KmsConnectorStatus; -use driver_graphics::kms::objects::{KmsObjectId, KmsObjects}; +use driver_graphics::kms::objects::{KmsCrtc, KmsObjectId, KmsObjects}; use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties}; -use drm_sys::DRM_MODE_DPMS_ON; +use drm_sys::{drm_mode_modeinfo, DRM_MODE_DPMS_ON}; use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT}; use graphics_ipc::v2::Damage; use syscall::{EINVAL, PAGE_SIZE}; @@ -19,10 +20,12 @@ pub struct FbAdapter { pub struct Connector { width: u32, height: u32, + framebuffer_id: usize, } impl GraphicsAdapter for FbAdapter { type Connector = Connector; + type Crtc = (); type Buffer = GraphicScreen; @@ -35,11 +38,17 @@ impl GraphicsAdapter for FbAdapter { } fn init(&mut self, objects: &mut KmsObjects, standard_properties: &StandardProperties) { - for framebuffer in &self.framebuffers { - let connector = objects.add_connector(Connector { - width: framebuffer.width as u32, - height: framebuffer.height as u32, - }); + for (framebuffer_id, framebuffer) in self.framebuffers.iter().enumerate() { + let crtc = objects.add_crtc(()); + + let connector = objects.add_connector( + Connector { + width: framebuffer.width as u32, + height: framebuffer.height as u32, + framebuffer_id, + }, + &[crtc], + ); objects.add_object_property( connector, standard_properties.dpms, @@ -93,8 +102,26 @@ impl GraphicsAdapter for FbAdapter { framebuffer.ptr.as_ptr().cast::() } - fn update_plane(&mut self, display_id: usize, buffer: Option<&Self::Buffer>, damage: Damage) { - let framebuffer = &mut self.framebuffers[display_id]; + fn set_crtc( + &mut self, + objects: &KmsObjects, + crtc: &Mutex>, + connectors: &[KmsObjectId], + mode: Option, + buffer: Option<&Self::Buffer>, + damage: Damage, + ) { + crtc.lock().unwrap().mode = mode; + + let framebuffer_id = objects + .get_connector(connectors[0]) + .unwrap() + .lock() + .unwrap() + .driver_data + .framebuffer_id; + let framebuffer = &mut self.framebuffers[framebuffer_id]; + if let Some(buffer) = buffer { buffer.sync(framebuffer, damage) } else { @@ -115,7 +142,7 @@ impl GraphicsAdapter for FbAdapter { None } - fn handle_cursor(&mut self, _cursor: Option<&CursorPlane>, _dirty_fb: bool) { + fn handle_cursor(&mut self, _cursor: &CursorPlane, _dirty_fb: bool) { unimplemented!("Vesad does not support this function"); } } diff --git a/drivers/graphics/virtio-gpud/src/scheme.rs b/drivers/graphics/virtio-gpud/src/scheme.rs index 7cddf275ae..c507ada4a8 100644 --- a/drivers/graphics/virtio-gpud/src/scheme.rs +++ b/drivers/graphics/virtio-gpud/src/scheme.rs @@ -1,13 +1,13 @@ use std::fmt; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use common::{dma::Dma, sgl}; use driver_graphics::kms::connector::KmsConnectorStatus; -use driver_graphics::kms::objects::{KmsObjectId, KmsObjects}; +use driver_graphics::kms::objects::{KmsCrtc, KmsObjectId, KmsObjects}; use driver_graphics::{ Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme, StandardProperties, }; -use drm_sys::{DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH, DRM_MODE_DPMS_ON}; +use drm_sys::{drm_mode_modeinfo, DRM_CAP_CURSOR_HEIGHT, DRM_CAP_CURSOR_WIDTH, DRM_MODE_DPMS_ON}; use graphics_ipc::v2::ipc::{DRM_CAP_DUMB_BUFFER, DRM_CLIENT_CAP_CURSOR_PLANE_HOTSPOT}; use graphics_ipc::v2::Damage; @@ -266,6 +266,7 @@ impl VirtGpuAdapter<'_> { impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { type Connector = VirtGpuConnector; + type Crtc = (); type Buffer = VirtGpuFramebuffer<'a>; @@ -283,7 +284,9 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { }); for display_id in 0..self.config.num_scanouts.get() { - let connector = objects.add_connector(VirtGpuConnector { display_id }); + let crtc = objects.add_crtc(()); + + let connector = objects.add_connector(VirtGpuConnector { display_id }, &[crtc]); if self.has_edid { objects.add_object_property(connector, standard_properties.edid, 0); } @@ -415,23 +418,36 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { framebuffer.sgl.as_ptr() } - fn update_plane( + fn set_crtc( &mut self, - display_id: usize, + objects: &KmsObjects, + crtc: &Mutex>, + connectors: &[KmsObjectId], + mode: Option, framebuffer: Option<&Self::Buffer>, damage: Damage, ) { futures::executor::block_on(async { + crtc.lock().unwrap().mode = mode; + + let display_id = objects + .get_connector(connectors[0]) + .unwrap() + .lock() + .unwrap() + .driver_data + .display_id; + let Some(framebuffer) = framebuffer else { let scanout_request = Dma::new(SetScanout::new( - display_id as u32, + display_id, 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; + self.displays[display_id as usize].active_resource = None; return; }; @@ -450,16 +466,16 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { assert_eq!(header.ty, CommandTy::RespOkNodata); // FIXME once we support resizing we also need to check that the current and target size match - if self.displays[display_id].active_resource != Some(framebuffer.id) { + if self.displays[display_id as usize].active_resource != Some(framebuffer.id) { let scanout_request = Dma::new(SetScanout::new( - display_id as u32, + display_id, framebuffer.id, GpuRect::new(0, 0, framebuffer.width, framebuffer.height), )) .unwrap(); let header = self.send_request(scanout_request).await.unwrap(); assert_eq!(header.ty, CommandTy::RespOkNodata); - self.displays[display_id].active_resource = Some(framebuffer.id); + self.displays[display_id as usize].active_resource = Some(framebuffer.id); } let flush = ResourceFlush::new( @@ -475,16 +491,10 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> { Some((64, 64)) } - fn handle_cursor(&mut self, cursor: Option<&CursorPlane>, dirty_fb: bool) { - if let Some(cursor) = cursor { + fn handle_cursor(&mut self, cursor: &CursorPlane, dirty_fb: bool) { + if let Some(buffer) = &cursor.framebuffer { if dirty_fb { - self.update_cursor( - &cursor.framebuffer, - cursor.x, - cursor.y, - cursor.hot_x, - cursor.hot_y, - ); + self.update_cursor(buffer, cursor.x, cursor.y, cursor.hot_x, cursor.hot_y); } else { self.move_cursor(cursor.x, cursor.y); }