drivers/graphics: Add helpers for updating the connector state
This commit is contained in:
Generated
+1
-1
@@ -592,6 +592,7 @@ version = "0.1.0"
|
||||
dependencies = [
|
||||
"common",
|
||||
"drm-sys",
|
||||
"edid",
|
||||
"graphics-ipc",
|
||||
"inputd",
|
||||
"libredox",
|
||||
@@ -2567,7 +2568,6 @@ dependencies = [
|
||||
"daemon",
|
||||
"driver-graphics",
|
||||
"drm-sys",
|
||||
"edid",
|
||||
"futures",
|
||||
"graphics-ipc",
|
||||
"libredox",
|
||||
|
||||
@@ -5,6 +5,8 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
drm-sys.workspace = true
|
||||
#TODO: edid is abandoned, fork it an maintain?
|
||||
edid = "0.3.0"
|
||||
log.workspace = true
|
||||
redox-scheme.workspace = true
|
||||
redox_syscall.workspace = true
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use std::ffi::c_char;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use drm_sys::{
|
||||
drm_mode_modeinfo, DRM_MODE_CONNECTOR_Unknown, DRM_MODE_OBJECT_CONNECTOR,
|
||||
DRM_MODE_OBJECT_ENCODER,
|
||||
DRM_MODE_OBJECT_ENCODER, DRM_MODE_TYPE_PREFERRED,
|
||||
};
|
||||
use syscall::Result;
|
||||
|
||||
@@ -75,6 +76,88 @@ pub struct DrmConnector<T: Debug + 'static> {
|
||||
pub driver_data: T,
|
||||
}
|
||||
|
||||
impl<T: Debug + 'static> DrmConnector<T> {
|
||||
pub fn update_from_size(&mut self, width: u32, height: u32) {
|
||||
self.modes = vec![Self::modeinfo_for_size(width, height)];
|
||||
}
|
||||
|
||||
pub fn update_from_edid(&mut self, edid: &[u8]) {
|
||||
let edid = edid::parse(edid).unwrap().1;
|
||||
|
||||
if let Some(first_detailed_timing) =
|
||||
edid.descriptors
|
||||
.iter()
|
||||
.find_map(|descriptor| match descriptor {
|
||||
edid::Descriptor::DetailedTiming(detailed_timing) => Some(detailed_timing),
|
||||
_ => None,
|
||||
})
|
||||
{
|
||||
self.mm_width = first_detailed_timing.horizontal_size.into();
|
||||
self.mm_height = first_detailed_timing.vertical_size.into();
|
||||
} else {
|
||||
log::error!("No edid timing descriptor detected");
|
||||
}
|
||||
|
||||
self.modes = edid
|
||||
.descriptors
|
||||
.iter()
|
||||
.filter_map(|descriptor| {
|
||||
match descriptor {
|
||||
edid::Descriptor::DetailedTiming(detailed_timing) => {
|
||||
// FIXME extract full information
|
||||
Some(Self::modeinfo_for_size(
|
||||
u32::from(detailed_timing.horizontal_active_pixels),
|
||||
u32::from(detailed_timing.vertical_active_lines),
|
||||
))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// First detailed timing descriptor indicates preferred mode.
|
||||
for mode in self.modes.iter_mut().skip(1) {
|
||||
mode.flags &= !DRM_MODE_TYPE_PREFERRED;
|
||||
}
|
||||
|
||||
// FIXME update the EDID property
|
||||
}
|
||||
|
||||
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,
|
||||
vdisplay: height as u16,
|
||||
|
||||
// These are used to calculate the refresh rate
|
||||
clock: 60 * width * height / 1000,
|
||||
htotal: width as u16,
|
||||
vtotal: height as u16,
|
||||
vscan: 0,
|
||||
vrefresh: 60,
|
||||
|
||||
type_: drm_sys::DRM_MODE_TYPE_PREFERRED | drm_sys::DRM_MODE_TYPE_DRIVER,
|
||||
name: [0; 32],
|
||||
|
||||
// These only matter when modesetting physical display adapters. For
|
||||
// those we should be able to parse the EDID blob.
|
||||
hsync_start: width as u16,
|
||||
hsync_end: width as u16,
|
||||
hskew: 0,
|
||||
vsync_start: height as u16,
|
||||
vsync_end: height as u16,
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
let name = format!("{width}x{height}").into_bytes();
|
||||
for (to, from) in modeinfo.name.iter_mut().zip(name) {
|
||||
*to = from as c_char;
|
||||
}
|
||||
|
||||
modeinfo
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[repr(u32)]
|
||||
pub enum DrmConnectorStatus {
|
||||
|
||||
@@ -11,10 +11,10 @@ use std::os::fd::BorrowedFd;
|
||||
use std::sync::Arc;
|
||||
|
||||
use drm_sys::{
|
||||
drm_mode_modeinfo, 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_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,
|
||||
};
|
||||
use graphics_ipc::v2::Damage;
|
||||
use inputd::{DisplayHandle, VtEventKind};
|
||||
@@ -908,37 +908,3 @@ impl<T: GraphicsAdapter> GraphicsSchemeInner<T> {
|
||||
self.handles.remove(&id);
|
||||
}
|
||||
}
|
||||
|
||||
pub 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,
|
||||
vdisplay: height as u16,
|
||||
|
||||
// These are used to calculate the refresh rate
|
||||
clock: 60 * width * height / 1000,
|
||||
htotal: width as u16,
|
||||
vtotal: height as u16,
|
||||
vscan: 0,
|
||||
vrefresh: 60,
|
||||
|
||||
type_: drm_sys::DRM_MODE_TYPE_PREFERRED | drm_sys::DRM_MODE_TYPE_DRIVER,
|
||||
name: [0; 32],
|
||||
|
||||
// These only matter when modesetting physical display adapters. For
|
||||
// those we should be able to parse the EDID blob.
|
||||
hsync_start: width as u16,
|
||||
hsync_end: width as u16,
|
||||
hskew: 0,
|
||||
vsync_start: height as u16,
|
||||
vsync_end: height as u16,
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
let name = format!("{width}x{height}").into_bytes();
|
||||
for (to, from) in modeinfo.name.iter_mut().zip(name) {
|
||||
*to = from as c_char;
|
||||
}
|
||||
|
||||
modeinfo
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@ use std::ptr::{self, NonNull};
|
||||
|
||||
use driver_graphics::connector::DrmConnectorStatus;
|
||||
use driver_graphics::objects::{DrmObjectId, DrmObjects};
|
||||
use driver_graphics::{
|
||||
modeinfo_for_size, Buffer, CursorPlane, GraphicsAdapter, StandardProperties,
|
||||
};
|
||||
use driver_graphics::{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};
|
||||
use graphics_ipc::v2::Damage;
|
||||
@@ -70,10 +68,7 @@ impl GraphicsAdapter for Device {
|
||||
let connector = objects.get_connector_mut(id).unwrap();
|
||||
let framebuffer = &self.framebuffers[connector.driver_data.framebuffer_id];
|
||||
connector.connection = DrmConnectorStatus::Connected;
|
||||
connector.modes = vec![modeinfo_for_size(
|
||||
framebuffer.width as u32,
|
||||
framebuffer.height as u32,
|
||||
)];
|
||||
connector.update_from_size(framebuffer.width as u32, framebuffer.height as u32);
|
||||
// FIXME fetch EDID
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,7 @@ use std::ptr::{self, NonNull};
|
||||
|
||||
use driver_graphics::connector::DrmConnectorStatus;
|
||||
use driver_graphics::objects::{DrmObjectId, DrmObjects};
|
||||
use driver_graphics::{
|
||||
modeinfo_for_size, Buffer, CursorPlane, GraphicsAdapter, StandardProperties,
|
||||
};
|
||||
use driver_graphics::{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};
|
||||
use graphics_ipc::v2::Damage;
|
||||
@@ -71,11 +69,8 @@ impl GraphicsAdapter for FbAdapter {
|
||||
id: DrmObjectId,
|
||||
) {
|
||||
let connector = objects.get_connector_mut(id).unwrap();
|
||||
connector.modes = vec![modeinfo_for_size(
|
||||
connector.driver_data.width,
|
||||
connector.driver_data.height,
|
||||
)];
|
||||
connector.connection = DrmConnectorStatus::Connected;
|
||||
connector.update_from_size(connector.driver_data.width, connector.driver_data.height);
|
||||
}
|
||||
|
||||
fn display_count(&self) -> usize {
|
||||
|
||||
@@ -6,8 +6,6 @@ authors = ["Anhad Singh <andypython@protonmail.com>"]
|
||||
|
||||
[dependencies]
|
||||
drm-sys.workspace = true
|
||||
#TODO: edid is abandoned, fork it an maintain?
|
||||
edid = "0.3.0"
|
||||
log.workspace = true
|
||||
static_assertions = "1.1.0"
|
||||
futures = { version = "0.3.28", features = ["executor"] }
|
||||
|
||||
@@ -5,12 +5,9 @@ use common::{dma::Dma, sgl};
|
||||
use driver_graphics::connector::DrmConnectorStatus;
|
||||
use driver_graphics::objects::{DrmObjectId, DrmObjects};
|
||||
use driver_graphics::{
|
||||
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,
|
||||
Buffer as DrmBuffer, CursorPlane, GraphicsAdapter, GraphicsScheme, StandardProperties,
|
||||
};
|
||||
use drm_sys::{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;
|
||||
|
||||
@@ -314,7 +311,6 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
|
||||
let connector = objects.get_connector_mut(id).unwrap();
|
||||
let display = &self.displays[connector.driver_data.display_id as usize];
|
||||
|
||||
connector.modes = vec![modeinfo_for_size(display.width, display.height)];
|
||||
connector.connection = if display.enabled {
|
||||
DrmConnectorStatus::Connected
|
||||
} else {
|
||||
@@ -322,48 +318,12 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
|
||||
};
|
||||
|
||||
if self.has_edid {
|
||||
let edid = edid::parse(&display.edid).unwrap().1;
|
||||
|
||||
if let Some(first_detailed_timing) =
|
||||
edid.descriptors
|
||||
.iter()
|
||||
.find_map(|descriptor| match descriptor {
|
||||
edid::Descriptor::DetailedTiming(detailed_timing) => {
|
||||
Some(detailed_timing)
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
{
|
||||
connector.mm_width = first_detailed_timing.horizontal_size.into();
|
||||
connector.mm_height = first_detailed_timing.vertical_size.into();
|
||||
} else {
|
||||
log::error!("No edid timing descriptor detected");
|
||||
}
|
||||
|
||||
connector.modes = edid
|
||||
.descriptors
|
||||
.iter()
|
||||
.filter_map(|descriptor| {
|
||||
match descriptor {
|
||||
edid::Descriptor::DetailedTiming(detailed_timing) => {
|
||||
// FIXME extract full information
|
||||
Some(modeinfo_for_size(
|
||||
u32::from(detailed_timing.horizontal_active_pixels),
|
||||
u32::from(detailed_timing.vertical_active_lines),
|
||||
))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// First detailed timing descriptor indicates preferred mode.
|
||||
for mode in connector.modes.iter_mut().skip(1) {
|
||||
mode.flags &= !DRM_MODE_TYPE_PREFERRED;
|
||||
}
|
||||
connector.update_from_edid(&display.edid);
|
||||
|
||||
let blob = objects.add_blob(display.edid.clone());
|
||||
objects.set_object_property(id, standard_properties.edid, blob.into());
|
||||
} else {
|
||||
connector.update_from_size(display.width, display.height);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user