Merge branch 'gpu_drm14' into 'main'

Implement proper support for DRM framebuffers and nicer handling of standard DRM properties

See merge request redox-os/base!172
This commit is contained in:
Jeremy Soller
2026-03-15 06:55:25 -06:00
8 changed files with 313 additions and 205 deletions
+1 -1
View File
@@ -21,7 +21,7 @@ impl V2DisplayMap {
pub fn new(display_handle: V2GraphicsHandle, width: u32, height: u32) -> io::Result<Self> {
let mut buffer =
display_handle.create_dumb_buffer((width, height), DrmFourcc::Argb8888, 32)?;
let fb = display_handle.add_framebuffer(&buffer, 24, 32)?;
let fb = display_handle.add_framebuffer(&buffer, 32, 32)?;
let map = display_handle.map_dumb_buffer(&mut buffer)?;
let map = unsafe { mem::transmute::<DumbMapping<'_>, DumbMapping<'static>>(map) };
@@ -5,12 +5,12 @@ use std::sync::{Arc, Mutex};
use drm_sys::{
drm_mode_modeinfo, DRM_MODE_OBJECT_BLOB, DRM_MODE_OBJECT_CONNECTOR, DRM_MODE_OBJECT_CRTC,
DRM_MODE_OBJECT_ENCODER, DRM_MODE_OBJECT_PROPERTY,
DRM_MODE_OBJECT_ENCODER, DRM_MODE_OBJECT_FB, DRM_MODE_OBJECT_PROPERTY,
};
use syscall::{Error, Result, EINVAL};
use crate::kms::connector::{KmsConnector, KmsEncoder};
use crate::kms::properties::{KmsBlob, KmsProperty};
use crate::kms::properties::{init_standard_props, KmsBlob, KmsProperty};
use crate::GraphicsAdapter;
#[derive(Debug)]
@@ -19,20 +19,24 @@ pub struct KmsObjects<T: GraphicsAdapter> {
pub(crate) connectors: Vec<KmsObjectId>,
pub(crate) encoders: Vec<KmsObjectId>,
crtcs: Vec<KmsObjectId>,
framebuffers: Vec<KmsObjectId>,
pub(crate) objects: HashMap<KmsObjectId, Arc<KmsObjectData<T>>>,
_marker: PhantomData<T>,
}
impl<T: GraphicsAdapter> KmsObjects<T> {
pub(crate) fn new() -> Self {
KmsObjects {
let mut objects = KmsObjects {
next_id: KmsObjectId(1),
connectors: vec![],
encoders: vec![],
crtcs: vec![],
framebuffers: vec![],
objects: HashMap::new(),
_marker: PhantomData,
}
};
init_standard_props(&mut objects);
objects
}
pub(crate) fn add<U: Into<KmsObjectKind<T>>>(&mut self, data: U) -> KmsObjectId {
@@ -93,6 +97,39 @@ impl<T: GraphicsAdapter> KmsObjects<T> {
pub fn get_crtc(&self, id: KmsObjectId) -> Result<&Mutex<KmsCrtc<T::Crtc>>> {
self.get(id)
}
pub fn add_framebuffer(
&mut self,
fb: KmsFramebuffer<T::Framebuffer, T::Buffer>,
) -> KmsObjectId {
let id = self.add(fb);
self.framebuffers.push(id);
id
}
pub fn remove_framebuffer(&mut self, id: KmsObjectId) -> Result<()> {
let kind = match self.objects.get(&id).map(|object| &**object) {
Some(KmsObjectData { kind, .. }) => kind,
_ => return Err(Error::new(EINVAL)),
};
let KmsObjectKind::Framebuffer(_) = **kind else {
return Err(Error::new(EINVAL));
};
self.objects.remove(&id).unwrap();
Ok(())
}
pub fn fb_ids(&self) -> &[KmsObjectId] {
&self.framebuffers
}
pub fn get_framebuffer(
&self,
id: KmsObjectId,
) -> Result<&KmsFramebuffer<T::Framebuffer, T::Buffer>> {
self.get(id)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -158,6 +195,7 @@ define_object_kinds! { <T>
Connector(Mutex<KmsConnector<T::Connector>>) = DRM_MODE_OBJECT_CONNECTOR,
Encoder(KmsEncoder) = DRM_MODE_OBJECT_ENCODER,
Property(KmsProperty) = DRM_MODE_OBJECT_PROPERTY,
Framebuffer(KmsFramebuffer<T::Framebuffer, T::Buffer>) = DRM_MODE_OBJECT_FB,
Blob(KmsBlob) = DRM_MODE_OBJECT_BLOB,
}
@@ -169,3 +207,14 @@ pub struct KmsCrtc<T> {
pub mode: Option<drm_mode_modeinfo>,
pub driver_data: T,
}
#[derive(Debug)]
pub struct KmsFramebuffer<T, Buf> {
pub width: u32,
pub height: u32,
pub pitch: u32,
pub bpp: u32,
pub depth: u32,
pub buffer: Arc<Buf>,
pub driver_data: T,
}
@@ -2,7 +2,10 @@ use std::ffi::c_char;
use std::fmt::Debug;
use std::sync::Mutex;
use drm_sys::DRM_PROP_NAME_LEN;
use drm_sys::{
DRM_MODE_DPMS_OFF, DRM_MODE_DPMS_ON, DRM_MODE_DPMS_STANDBY, DRM_MODE_DPMS_SUSPEND,
DRM_PLANE_TYPE_CURSOR, DRM_PLANE_TYPE_OVERLAY, DRM_PLANE_TYPE_PRIMARY, DRM_PROP_NAME_LEN,
};
use syscall::{Error, Result, EINVAL};
use crate::kms::objects::{KmsObjectId, KmsObjects};
@@ -115,3 +118,78 @@ pub enum KmsPropertyKind {
pub struct KmsBlob {
data: Vec<u8>,
}
macro_rules! define_properties {
($($prop:ident $($prop_name:literal)?: $prop_type:ident $({$($prop_content:tt)*})? [$($prop_flag:ident)?],)*) => {
$(#[allow(non_upper_case_globals)] pub const $prop: KmsObjectId = KmsObjectId(1 + ${index()});)*
pub(super) fn init_standard_props<T: GraphicsAdapter>(objects: &mut KmsObjects<T>) {
$(
assert_eq!(objects.add_property(
define_properties!(@prop_name $prop $($prop_name)?),
define_properties!(@is_immutable $($prop_flag)?),
define_properties!(@is_atomic $($prop_flag)?),
define_properties!(@prop_kind $prop_type $({$($prop_content)*})?),
), $prop);
)*
}
};
(@prop_name $prop:ident $prop_name:literal) => { $prop_name };
(@prop_name $prop:ident) => { stringify!($prop) };
(@is_immutable) => { false };
(@is_immutable immutable) => { true };
(@is_immutable atomic) => { false };
(@is_atomic) => { false };
(@is_atomic immutable) => { false };
(@is_atomic atomic) => { true };
(@prop_kind range { $start:expr, $end:expr }) => {
KmsPropertyKind::Range($start, $end)
};
(@prop_kind enum { $($variant:ident = $value:expr,)* }) => {
KmsPropertyKind::Enum(vec![$((stringify!($variant), $value)),*])
};
(@prop_kind blob) => {
KmsPropertyKind::Blob
};
(@prop_kind object) => {
KmsPropertyKind::Object
};
(@prop_kind srange { $start:expr, $end:expr }) => {
KmsPropertyKind::SignedRange($start, $end)
};
}
define_properties! {
// Connector + Plane
CRTC_ID: object [atomic],
// Connector
EDID: blob [immutable],
DPMS: enum {
On = u64::from(DRM_MODE_DPMS_ON),
Standby = u64::from(DRM_MODE_DPMS_STANDBY),
Suspend = u64::from(DRM_MODE_DPMS_SUSPEND),
Off = u64::from(DRM_MODE_DPMS_OFF),
} [],
// CRTC
ACTIVE: range { 0,1 } [atomic],
MODE_ID: blob [atomic],
// Plane
type_ "type": enum {
Overlay = u64::from(DRM_PLANE_TYPE_OVERLAY),
Primary = u64::from(DRM_PLANE_TYPE_PRIMARY),
Cursor = u64::from(DRM_PLANE_TYPE_CURSOR),
} [immutable],
FB_ID: object [atomic],
CRTC_X: srange { i64::from(i32::MIN), i64::from(i32::MAX) } [atomic],
CRTC_Y: srange { i64::from(i32::MIN), i64::from(i32::MAX) } [atomic],
CRTC_W: range { 0, u64::from(u32::MAX) } [atomic],
CRTC_H: range { 0, u64::from(u32::MAX) } [atomic],
SRC_X: range { 0, u64::from(u32::MAX) } [atomic],
SRC_Y: range { 0, u64::from(u32::MAX) } [atomic],
SRC_W: range { 0, u64::from(u32::MAX) } [atomic],
SRC_H: range { 0, u64::from(u32::MAX) } [atomic],
FB_DAMAGE_CLIPS: blob [atomic],
}
+132 -106
View File
@@ -1,3 +1,4 @@
#![feature(macro_metavar_expr)]
#![feature(slice_as_array)]
use std::collections::{BTreeMap, HashMap};
@@ -12,7 +13,6 @@ use std::sync::{Arc, Mutex};
use drm_sys::{
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,
@@ -26,46 +26,32 @@ use syscall::schemev2::NewFdFlags;
use syscall::{Error, MapFlags, Result, EACCES, EAGAIN, EBADF, EINVAL, ENOENT, EOPNOTSUPP};
use crate::kms::connector::KmsConnector;
use crate::kms::objects::{KmsCrtc, KmsObjectId, KmsObjects};
use crate::kms::objects::{self, KmsCrtc, KmsObjectId, KmsObjects};
use crate::kms::properties::KmsPropertyKind;
pub mod kms;
#[derive(Debug, Copy, Clone)]
pub struct StandardProperties {
pub edid: KmsObjectId,
pub dpms: KmsObjectId,
}
pub trait GraphicsAdapter: Sized + Debug {
type Connector: Debug;
type Crtc: Debug;
type Buffer: Buffer;
type Framebuffer: Framebuffer;
fn name(&self) -> &'static [u8];
fn desc(&self) -> &'static [u8];
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties);
fn init(&mut self, objects: &mut KmsObjects<Self>);
fn get_cap(&self, cap: u32) -> Result<u64>;
fn set_client_cap(&self, cap: u32, value: u64) -> Result<()>;
fn probe_connector(
&mut self,
objects: &mut KmsObjects<Self>,
standard_properties: &StandardProperties,
id: KmsObjectId,
);
/// The maximum amount of displays that could be attached.
///
/// This must be constant for the lifetime of the graphics adapter.
fn display_count(&self) -> usize;
fn display_size(&self, display_id: usize) -> (u32, u32);
fn probe_connector(&mut self, objects: &mut KmsObjects<Self>, id: KmsObjectId);
fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer;
fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8;
fn map_dumb_buffer(&mut self, buffer: &Self::Buffer) -> *mut u8;
fn create_framebuffer(&mut self, buffer: &Self::Buffer) -> Self::Framebuffer;
fn set_crtc(
&mut self,
@@ -73,7 +59,7 @@ pub trait GraphicsAdapter: Sized + Debug {
crtc: &Mutex<KmsCrtc<Self::Crtc>>,
connectors: &[KmsObjectId],
mode: Option<drm_mode_modeinfo>,
framebuffer: Option<&Self::Buffer>,
framebuffer: Option<&objects::KmsFramebuffer<Self::Framebuffer, Self::Buffer>>,
damage: Damage,
);
@@ -86,7 +72,10 @@ pub trait Buffer: Debug {
fn height(&self) -> u32;
}
#[derive(Debug)]
pub trait Framebuffer: Debug {}
impl Framebuffer for () {}
pub struct CursorPlane<C: Buffer> {
pub x: i32,
pub y: i32,
@@ -112,24 +101,9 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
);
let mut objects = KmsObjects::new();
let edid = objects.add_property("EDID", true, false, KmsPropertyKind::Blob);
let dpms = objects.add_property(
"DPMS",
false,
false,
KmsPropertyKind::Enum(vec![
("On", DRM_MODE_DPMS_ON.into()),
("Standby", DRM_MODE_DPMS_STANDBY.into()),
("Suspend", DRM_MODE_DPMS_SUSPEND.into()),
("Off", DRM_MODE_DPMS_OFF.into()),
]),
);
let standard_properties = StandardProperties { edid, dpms };
adapter.init(&mut objects, &standard_properties);
adapter.init(&mut objects);
for connector_id in objects.connector_ids().to_vec() {
adapter.probe_connector(&mut objects, &standard_properties, connector_id)
adapter.probe_connector(&mut objects, connector_id)
}
let mut inner = GraphicsSchemeInner {
@@ -138,7 +112,6 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
disable_graphical_debug,
socket,
objects,
standard_properties,
next_id: 0,
handles: BTreeMap::new(),
active_vt: 0,
@@ -190,10 +163,6 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
(&mut self.inner.adapter, &mut self.inner.objects)
}
pub fn standard_properties(&self) -> StandardProperties {
self.inner.standard_properties
}
pub fn handle_vt_events(&mut self) {
while let Some(vt_event) = self
.inputd_handle
@@ -217,7 +186,7 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
self.inner.active_vt = vt_event.vt;
let vt_state = GraphicsSchemeInner::get_or_create_vt(
&mut self.inner.adapter,
&self.inner.objects,
&mut self.inner.vts,
vt_event.vt,
);
@@ -225,21 +194,29 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
for (display_id, fb) in vt_state.display_fbs.iter().enumerate() {
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())
crtc.lock().unwrap().fb_id = fb.unwrap_or(KmsObjectId::INVALID);
let fb = fb.map(|fb| {
self.inner
.objects
.get_framebuffer(fb)
.expect("removed framebuffers should be unset")
});
let mode =
fb.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(),
fb,
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()),
width: fb.map_or(0, |fb| fb.width),
height: fb.map_or(0, |fb| fb.height),
},
);
}
@@ -304,7 +281,6 @@ struct GraphicsSchemeInner<T: GraphicsAdapter> {
disable_graphical_debug: Option<File>,
socket: Socket,
objects: KmsObjects<T>,
standard_properties: StandardProperties,
next_id: usize,
handles: BTreeMap<usize, Handle<T>>,
@@ -313,7 +289,7 @@ struct GraphicsSchemeInner<T: GraphicsAdapter> {
}
struct VtState<T: GraphicsAdapter> {
display_fbs: Vec<Option<Arc<T::Buffer>>>,
display_fbs: Vec<Option<KmsObjectId>>,
cursor_plane: CursorPlane<T::Buffer>,
}
@@ -333,12 +309,12 @@ enum Handle<T: GraphicsAdapter> {
impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
fn get_or_create_vt<'a>(
adapter: &mut T,
objects: &KmsObjects<T>,
vts: &'a mut HashMap<usize, VtState<T>>,
vt: usize,
) -> &'a mut VtState<T> {
vts.entry(vt).or_insert_with(|| VtState {
display_fbs: vec![None; adapter.display_count()],
display_fbs: vec![None; objects.crtc_ids().len()],
cursor_plane: CursorPlane {
x: 0,
y: 0,
@@ -386,7 +362,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
.map_err(|_| Error::new(EINVAL))?;
// Ensure the VT exists such that the rest of the methods can freely access it.
Self::get_or_create_vt(&mut self.adapter, &mut self.vts, vt);
Self::get_or_create_vt(&self.objects, &mut self.vts, vt);
Handle::V2 {
vt,
@@ -400,7 +376,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
let vt = screen.next().unwrap_or("").parse::<usize>().unwrap();
let id = screen.next().unwrap_or("").parse::<usize>().unwrap_or(0);
if id >= self.adapter.display_count() {
if id >= self.objects.crtc_ids().len() {
return Err(Error::new(EINVAL));
}
@@ -454,14 +430,6 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
id & 0xFF
}
fn fb_id(i: u32) -> u32 {
id_index(i) | (1 << 11)
}
fn fb_handle_id(i: u32) -> u32 {
id_index(i) | (1 << 12)
}
fn plane_id(i: u32) -> u32 {
id_index(i) | (1 << 13)
}
@@ -504,7 +472,6 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
Ok(0)
}),
ipc::MODE_CARD_RES => ipc::DrmModeCardRes::with(payload, |mut data| {
let count = self.adapter.display_count();
let conn_ids = self
.objects
.connector_ids()
@@ -523,10 +490,12 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
.iter()
.map(|id| id.0)
.collect::<Vec<_>>();
let mut fb_ids = Vec::with_capacity(count);
for i in 0..(count as u32) {
fb_ids.push(fb_id(i));
}
let fb_ids = self
.objects
.fb_ids()
.iter()
.map(|id| id.0)
.collect::<Vec<_>>();
data.set_fb_id_ptr(&fb_ids);
data.set_crtc_id_ptr(&crtc_ids);
data.set_connector_id_ptr(&conn_ids);
@@ -592,11 +561,8 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
}),
ipc::MODE_GET_CONNECTOR => ipc::DrmModeGetConnector::with(payload, |mut data| {
if data.count_modes() == 0 {
self.adapter.probe_connector(
&mut self.objects,
&self.standard_properties,
KmsObjectId(data.connector_id()),
);
self.adapter
.probe_connector(&mut self.objects, KmsObjectId(data.connector_id()));
}
let connector = self
.objects
@@ -711,18 +677,71 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
Ok(0)
}),
ipc::MODE_GET_FB => ipc::DrmModeFbCmd::with(payload, |mut data| {
let i = id_index(data.fb_id());
let (width, height) = self.adapter.display_size(i as usize);
data.set_width(width);
data.set_height(height);
data.set_pitch(width * 4); //TODO: stride
data.set_bpp(32);
data.set_depth(24);
data.set_handle(fb_handle_id(i));
let fb = self.objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
*next_id += 1;
buffers.insert(*next_id, fb.buffer.clone());
data.set_width(fb.width);
data.set_height(fb.height);
data.set_pitch(fb.pitch);
data.set_bpp(fb.bpp);
data.set_depth(fb.depth);
data.set_handle(*next_id);
Ok(0)
}),
ipc::MODE_ADD_FB => ipc::DrmModeFbCmd::with(payload, |mut data| {
data.set_fb_id(fb_handle_id(data.handle()));
let buffer = buffers.get(&data.handle()).ok_or(Error::new(EINVAL))?;
let fb = self.adapter.create_framebuffer(buffer);
let id = self.objects.add_framebuffer(objects::KmsFramebuffer {
width: data.width(),
height: data.height(),
pitch: data.pitch(),
bpp: data.bpp(),
depth: data.depth(),
buffer: buffer.clone(),
driver_data: fb,
});
data.set_fb_id(id.0);
Ok(0)
}),
ipc::MODE_RM_FB => ipc::StandinForUint::with(payload, |data| {
let fb_id = KmsObjectId(data.inner());
self.objects.remove_framebuffer(fb_id)?;
// Disable planes that use this framebuffer.
for (vt, vt_data) in &mut self.vts {
for (display_id, fb) in vt_data.display_fbs.iter_mut().enumerate() {
if *fb != Some(fb_id) {
continue;
}
*fb = None;
if *vt != self.active_vt {
continue;
}
let crtc = self.objects.crtcs().nth(display_id).unwrap();
crtc.lock().unwrap().fb_id = KmsObjectId::INVALID;
self.adapter.set_crtc(
&self.objects,
crtc,
&[self.objects.connector_ids()[display_id]],
None,
None,
Damage {
x: 0,
y: 0,
width: 0,
height: 0,
},
);
}
}
Ok(0)
}),
ipc::MODE_CREATE_DUMB => ipc::DrmModeCreateDumb::with(payload, |mut data| {
@@ -730,10 +749,10 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
return Err(Error::new(EINVAL));
}
let fb = self.adapter.create_dumb_buffer(data.width(), data.height());
let buffer = self.adapter.create_dumb_buffer(data.width(), data.height());
*next_id += 1;
buffers.insert(*next_id, Arc::new(fb));
buffers.insert(*next_id, Arc::new(buffer));
data.set_handle(*next_id as u32);
data.set_pitch(data.width() * 4);
data.set_size(u64::from(data.width()) * u64::from(data.height()) * 4);
@@ -767,7 +786,7 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
Ok(0)
}),
ipc::MODE_GET_PLANE_RES => ipc::DrmModeGetPlaneRes::with(payload, |mut data| {
let count = self.adapter.display_count();
let count = self.objects.crtc_ids().len();
let mut ids = Vec::with_capacity(count);
for i in 0..(count as u32) {
ids.push(plane_id(i));
@@ -777,8 +796,10 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
}),
ipc::MODE_GET_PLANE => ipc::DrmModeGetPlane::with(payload, |mut data| {
let i = id_index(data.plane_id());
data.set_crtc_id(self.objects.crtc_ids()[i as usize].0);
data.set_fb_id(fb_id(i));
let crtc_id = self.objects.crtc_ids()[i as usize];
let crtc = self.objects.get_crtc(crtc_id).unwrap();
data.set_crtc_id(crtc_id.0);
data.set_fb_id(crtc.lock().unwrap().fb_id.0);
data.set_possible_crtcs(1 << i);
data.set_format_type_ptr(&[DRM_FORMAT_ARGB8888]);
Ok(0)
@@ -833,13 +854,16 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
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);
data.set_width(width);
data.set_height(height);
let fb = self.objects.get_framebuffer(KmsObjectId(data.fb_id()))?;
*next_id += 1;
buffers.insert(*next_id, fb.buffer.clone());
data.set_width(fb.width);
data.set_height(fb.height);
data.set_pixel_format(DRM_FORMAT_ARGB8888);
data.set_handles([fb_handle_id(i), 0, 0, 0]);
data.set_pitches([width * 4, 0, 0, 0]);
data.set_handles([*next_id, 0, 0, 0]);
data.set_pitches([fb.width * 4, 0, 0, 0]);
data.set_offsets([0; 4]);
data.set_modifier([0; 4]);
Ok(0)
@@ -859,28 +883,30 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsSchemeInner<T> {
return Err(Error::new(EINVAL));
};
let framebuffer = if payload.fb_id == 0 {
let fb = if payload.fb_id == 0 {
None
} else if let Some(framebuffer) = buffers.get(&id_index(payload.fb_id)) {
Some(framebuffer)
} else {
return Err(Error::new(EINVAL));
Some(self.objects.get_framebuffer(KmsObjectId(payload.fb_id))?)
};
self.vts.get_mut(vt).unwrap().display_fbs[display_id] =
framebuffer.map(Arc::clone);
self.vts.get_mut(vt).unwrap().display_fbs[display_id] = if payload.fb_id == 0 {
None
} else {
Some(KmsObjectId(payload.fb_id))
};
if *vt == self.active_vt {
let mode = framebuffer.as_ref().map(|fb| {
KmsConnector::<()>::modeinfo_for_size(fb.width(), fb.height())
});
crtc.lock().unwrap().fb_id = KmsObjectId(payload.fb_id);
let mode =
fb.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),
fb,
payload.damage,
);
}
+13 -27
View File
@@ -6,8 +6,9 @@ use std::ptr::{self, NonNull};
use std::sync::Mutex;
use driver_graphics::kms::connector::KmsConnectorStatus;
use driver_graphics::kms::objects::{KmsCrtc, KmsObjectId, KmsObjects};
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties};
use driver_graphics::kms::objects::{self, KmsCrtc, KmsObjectId, KmsObjects};
use driver_graphics::kms::properties::DPMS;
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter};
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;
@@ -25,6 +26,7 @@ impl GraphicsAdapter for Device {
type Crtc = ();
type Buffer = DumbFb;
type Framebuffer = ();
fn name(&self) -> &'static [u8] {
b"ihdgd"
@@ -34,17 +36,13 @@ impl GraphicsAdapter for Device {
b"Intel HD Graphics"
}
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties) {
fn init(&mut self, objects: &mut KmsObjects<Self>) {
// FIXME enumerate actual connectors
for (framebuffer_id, _) in self.framebuffers.iter().enumerate() {
let crtc = objects.add_crtc(());
let connector = objects.add_connector(Connector { framebuffer_id }, &[crtc]);
objects.add_object_property(
connector,
standard_properties.dpms,
DRM_MODE_DPMS_ON.into(),
);
objects.add_object_property(connector, DPMS, DRM_MODE_DPMS_ON.into());
}
}
@@ -63,12 +61,7 @@ impl GraphicsAdapter for Device {
}
}
fn probe_connector(
&mut self,
objects: &mut KmsObjects<Self>,
_standard_properties: &StandardProperties,
id: KmsObjectId,
) {
fn probe_connector(&mut self, objects: &mut KmsObjects<Self>, id: KmsObjectId) {
let mut connector = objects.get_connector(id).unwrap().lock().unwrap();
let framebuffer = &self.framebuffers[connector.driver_data.framebuffer_id];
connector.connection = KmsConnectorStatus::Connected;
@@ -76,17 +69,6 @@ impl GraphicsAdapter for Device {
// FIXME fetch EDID
}
fn display_count(&self) -> usize {
self.framebuffers.len()
}
fn display_size(&self, display_id: usize) -> (u32, u32) {
(
self.framebuffers[display_id].width as u32,
self.framebuffers[display_id].height as u32,
)
}
fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer {
DumbFb::new(width as usize, height as usize)
}
@@ -95,13 +77,17 @@ impl GraphicsAdapter for Device {
framebuffer.ptr.as_ptr().cast::<u8>()
}
fn create_framebuffer(&mut self, _buffer: &Self::Buffer) -> Self::Framebuffer {
()
}
fn set_crtc(
&mut self,
objects: &KmsObjects<Self>,
crtc: &Mutex<KmsCrtc<Self::Crtc>>,
connectors: &[KmsObjectId],
mode: Option<drm_mode_modeinfo>,
buffer: Option<&Self::Buffer>,
buffer: Option<&objects::KmsFramebuffer<Self::Framebuffer, Self::Buffer>>,
damage: Damage,
) {
crtc.lock().unwrap().mode = mode;
@@ -116,7 +102,7 @@ impl GraphicsAdapter for Device {
let framebuffer = &mut self.framebuffers[framebuffer_id];
if let Some(buffer) = buffer {
buffer.sync(framebuffer, damage)
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 {
+13 -27
View File
@@ -4,8 +4,9 @@ use std::ptr::{self, NonNull};
use std::sync::Mutex;
use driver_graphics::kms::connector::KmsConnectorStatus;
use driver_graphics::kms::objects::{KmsCrtc, KmsObjectId, KmsObjects};
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter, StandardProperties};
use driver_graphics::kms::objects::{self, KmsCrtc, KmsObjectId, KmsObjects};
use driver_graphics::kms::properties::DPMS;
use driver_graphics::{Buffer, CursorPlane, GraphicsAdapter};
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;
@@ -28,6 +29,7 @@ impl GraphicsAdapter for FbAdapter {
type Crtc = ();
type Buffer = GraphicScreen;
type Framebuffer = ();
fn name(&self) -> &'static [u8] {
b"vesad"
@@ -37,7 +39,7 @@ impl GraphicsAdapter for FbAdapter {
b"VESA"
}
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties) {
fn init(&mut self, objects: &mut KmsObjects<Self>) {
for (framebuffer_id, framebuffer) in self.framebuffers.iter().enumerate() {
let crtc = objects.add_crtc(());
@@ -49,11 +51,7 @@ impl GraphicsAdapter for FbAdapter {
},
&[crtc],
);
objects.add_object_property(
connector,
standard_properties.dpms,
DRM_MODE_DPMS_ON.into(),
);
objects.add_object_property(connector, DPMS, DRM_MODE_DPMS_ON.into());
}
}
@@ -71,29 +69,13 @@ impl GraphicsAdapter for FbAdapter {
}
}
fn probe_connector(
&mut self,
objects: &mut KmsObjects<Self>,
_standard_properties: &StandardProperties,
id: KmsObjectId,
) {
fn probe_connector(&mut self, objects: &mut KmsObjects<Self>, id: KmsObjectId) {
let mut connector = objects.get_connector(id).unwrap().lock().unwrap();
let connector = &mut *connector;
connector.connection = KmsConnectorStatus::Connected;
connector.update_from_size(connector.driver_data.width, connector.driver_data.height);
}
fn display_count(&self) -> usize {
self.framebuffers.len()
}
fn display_size(&self, display_id: usize) -> (u32, u32) {
(
self.framebuffers[display_id].width as u32,
self.framebuffers[display_id].height as u32,
)
}
fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer {
GraphicScreen::new(width as usize, height as usize)
}
@@ -102,13 +84,17 @@ impl GraphicsAdapter for FbAdapter {
framebuffer.ptr.as_ptr().cast::<u8>()
}
fn create_framebuffer(&mut self, _buffer: &Self::Buffer) -> Self::Framebuffer {
()
}
fn set_crtc(
&mut self,
objects: &KmsObjects<Self>,
crtc: &Mutex<KmsCrtc<Self::Crtc>>,
connectors: &[KmsObjectId],
mode: Option<drm_mode_modeinfo>,
buffer: Option<&Self::Buffer>,
buffer: Option<&objects::KmsFramebuffer<Self::Framebuffer, Self::Buffer>>,
damage: Damage,
) {
crtc.lock().unwrap().mode = mode;
@@ -123,7 +109,7 @@ impl GraphicsAdapter for FbAdapter {
let framebuffer = &mut self.framebuffers[framebuffer_id];
if let Some(buffer) = buffer {
buffer.sync(framebuffer, damage)
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 {
+1 -2
View File
@@ -586,11 +586,10 @@ fn deamon(deamon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow:
let events = scheme.adapter().config.events_read.get();
if events & VIRTIO_GPU_EVENT_DISPLAY != 0 {
let standard_properties = scheme.standard_properties();
let (adapter, objects) = scheme.adapter_and_kms_objects_mut();
futures::executor::block_on(async { adapter.update_displays().await.unwrap() });
for connector_id in objects.connector_ids().to_vec() {
adapter.probe_connector(objects, &standard_properties, connector_id);
adapter.probe_connector(objects, connector_id);
}
scheme.notify_displays_changed();
scheme
+21 -37
View File
@@ -3,10 +3,9 @@ use std::sync::{Arc, Mutex};
use common::{dma::Dma, sgl};
use driver_graphics::kms::connector::KmsConnectorStatus;
use driver_graphics::kms::objects::{KmsCrtc, KmsObjectId, KmsObjects};
use driver_graphics::{
Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme, StandardProperties,
};
use driver_graphics::kms::objects::{self, KmsCrtc, KmsObjectId, KmsObjects};
use driver_graphics::kms::properties::{DPMS, EDID};
use driver_graphics::{Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme};
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;
@@ -269,6 +268,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
type Crtc = ();
type Buffer = VirtGpuFramebuffer<'a>;
type Framebuffer = ();
fn name(&self) -> &'static [u8] {
b"virtio-gpud"
@@ -278,7 +278,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
b"VirtIO GPU"
}
fn init(&mut self, objects: &mut KmsObjects<Self>, standard_properties: &StandardProperties) {
fn init(&mut self, objects: &mut KmsObjects<Self>) {
futures::executor::block_on(async {
self.update_displays().await.unwrap();
});
@@ -288,13 +288,9 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
let connector = objects.add_connector(VirtGpuConnector { display_id }, &[crtc]);
if self.has_edid {
objects.add_object_property(connector, standard_properties.edid, 0);
objects.add_object_property(connector, EDID, 0);
}
objects.add_object_property(
connector,
standard_properties.dpms,
DRM_MODE_DPMS_ON.into(),
);
objects.add_object_property(connector, DPMS, DRM_MODE_DPMS_ON.into());
}
}
@@ -315,12 +311,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
}
}
fn probe_connector(
&mut self,
objects: &mut KmsObjects<Self>,
standard_properties: &StandardProperties,
id: KmsObjectId,
) {
fn probe_connector(&mut self, objects: &mut KmsObjects<Self>, id: KmsObjectId) {
futures::executor::block_on(async {
let mut connector = objects.get_connector(id).unwrap().lock().unwrap();
let display = &self.displays[connector.driver_data.display_id as usize];
@@ -337,24 +328,13 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
drop(connector);
let blob = objects.add_blob(display.edid.clone());
objects.set_object_property(id, standard_properties.edid, blob.into());
objects.set_object_property(id, EDID, blob.into());
} else {
connector.update_from_size(display.width, display.height);
}
});
}
fn display_count(&self) -> usize {
self.displays.len()
}
fn display_size(&self, display_id: usize) -> (u32, u32) {
(
self.displays[display_id].width,
self.displays[display_id].height,
)
}
fn create_dumb_buffer(&mut self, width: u32, height: u32) -> Self::Buffer {
futures::executor::block_on(async {
let bpp = 32;
@@ -414,8 +394,12 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
})
}
fn map_dumb_buffer(&mut self, framebuffer: &Self::Buffer) -> *mut u8 {
framebuffer.sgl.as_ptr()
fn map_dumb_buffer(&mut self, buffer: &Self::Buffer) -> *mut u8 {
buffer.sgl.as_ptr()
}
fn create_framebuffer(&mut self, _buffer: &Self::Buffer) -> Self::Framebuffer {
()
}
fn set_crtc(
@@ -424,7 +408,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
crtc: &Mutex<KmsCrtc<Self::Crtc>>,
connectors: &[KmsObjectId],
mode: Option<drm_mode_modeinfo>,
framebuffer: Option<&Self::Buffer>,
framebuffer: Option<&objects::KmsFramebuffer<Self::Framebuffer, Self::Buffer>>,
damage: Damage,
) {
futures::executor::block_on(async {
@@ -452,7 +436,7 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
};
let req = Dma::new(XferToHost2d::new(
framebuffer.id,
framebuffer.buffer.id,
GpuRect {
x: 0,
y: 0,
@@ -466,20 +450,20 @@ 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 as usize].active_resource != Some(framebuffer.id) {
if self.displays[display_id as usize].active_resource != Some(framebuffer.buffer.id) {
let scanout_request = Dma::new(SetScanout::new(
display_id,
framebuffer.id,
framebuffer.buffer.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 as usize].active_resource = Some(framebuffer.id);
self.displays[display_id as usize].active_resource = Some(framebuffer.buffer.id);
}
let flush = ResourceFlush::new(
framebuffer.id,
framebuffer.buffer.id,
damage.clip(framebuffer.width, framebuffer.height).into(),
);
let header = self.send_request(Dma::new(flush).unwrap()).await.unwrap();