drivers/graphics: Implement force probing of connectors in virtio-gpud
This commit is contained in:
@@ -18,7 +18,7 @@ use redox_scheme::{CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket};
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
use syscall::{Error, MapFlags, Result, EAGAIN, EBADF, EINVAL, ENOENT, EOPNOTSUPP};
|
||||
|
||||
use crate::objects::{DrmObjectId, DrmObjects};
|
||||
use crate::objects::{DrmConnector, DrmObjectId, DrmObjects};
|
||||
|
||||
pub mod objects;
|
||||
|
||||
@@ -36,6 +36,8 @@ pub trait GraphicsAdapter: Sized {
|
||||
fn get_cap(&self, cap: u32) -> Result<u64>;
|
||||
fn set_client_cap(&self, cap: u32, value: u64) -> Result<()>;
|
||||
|
||||
fn probe_connector(&mut self, connector: &mut DrmConnector<Self>);
|
||||
|
||||
/// The maximum amount of displays that could be attached.
|
||||
///
|
||||
/// This must be constant for the lifetime of the graphics adapter.
|
||||
@@ -111,6 +113,9 @@ impl<T: GraphicsAdapter> GraphicsScheme<T> {
|
||||
|
||||
let mut objects = DrmObjects::new();
|
||||
adapter.init(&mut objects);
|
||||
for connector in objects.connectors_mut() {
|
||||
adapter.probe_connector(connector);
|
||||
}
|
||||
|
||||
GraphicsScheme {
|
||||
adapter,
|
||||
@@ -523,9 +528,17 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsScheme<T> {
|
||||
}),
|
||||
ipc::MODE_CARD_RES => ipc::DrmModeCardRes::with(payload, |mut data| {
|
||||
let count = self.adapter.display_count();
|
||||
let conn_ids = self.objects.connectors().map(|id| id.0).collect::<Vec<_>>();
|
||||
let conn_ids = self
|
||||
.objects
|
||||
.connector_ids()
|
||||
.map(|id| id.0)
|
||||
.collect::<Vec<_>>();
|
||||
let mut crtc_ids = Vec::with_capacity(count);
|
||||
let enc_ids = self.objects.encoders().map(|id| id.0).collect::<Vec<_>>();
|
||||
let enc_ids = self
|
||||
.objects
|
||||
.encoder_ids()
|
||||
.map(|id| id.0)
|
||||
.collect::<Vec<_>>();
|
||||
let mut fb_ids = Vec::with_capacity(count);
|
||||
for i in 0..(count as u32) {
|
||||
crtc_ids.push(crtc_id(i));
|
||||
@@ -563,7 +576,10 @@ impl<T: GraphicsAdapter> SchemeSync for GraphicsScheme<T> {
|
||||
ipc::MODE_GET_CONNECTOR => ipc::DrmModeGetConnector::with(payload, |mut data| {
|
||||
let connector = self
|
||||
.objects
|
||||
.get_connector(DrmObjectId(data.connector_id()))?;
|
||||
.get_connector_mut(DrmObjectId(data.connector_id()))?;
|
||||
if data.count_modes() == 0 {
|
||||
self.adapter.probe_connector(connector);
|
||||
}
|
||||
data.set_connection(connector.connection as u32);
|
||||
data.set_modes_ptr(&connector.modes);
|
||||
data.set_mm_width(connector.mm_width);
|
||||
|
||||
@@ -47,7 +47,7 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
connector_id
|
||||
}
|
||||
|
||||
pub fn connectors(&self) -> impl Iterator<Item = DrmObjectId> + use<'_, T> {
|
||||
pub fn connector_ids(&self) -> impl Iterator<Item = DrmObjectId> + use<'_, T> {
|
||||
self.objects
|
||||
.iter()
|
||||
.filter_map(|(&id, object)| match object.kind {
|
||||
@@ -56,6 +56,24 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn connectors(&self) -> impl Iterator<Item = &DrmConnector<T>> + use<'_, T> {
|
||||
self.objects
|
||||
.values()
|
||||
.filter_map(|object| match &object.kind {
|
||||
DrmObjectKind::Connector(connector) => Some(connector),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn connectors_mut(&mut self) -> impl Iterator<Item = &mut DrmConnector<T>> + use<'_, T> {
|
||||
self.objects
|
||||
.values_mut()
|
||||
.filter_map(|object| match &mut object.kind {
|
||||
DrmObjectKind::Connector(connector) => Some(connector),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_connector(&self, id: DrmObjectId) -> Result<&DrmConnector<T>> {
|
||||
let object = self.objects.get(&id).ok_or(Error::new(EINVAL))?;
|
||||
match &object.kind {
|
||||
@@ -72,7 +90,7 @@ impl<T: GraphicsAdapter> DrmObjects<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn encoders(&self) -> impl Iterator<Item = DrmObjectId> + use<'_, T> {
|
||||
pub fn encoder_ids(&self) -> impl Iterator<Item = DrmObjectId> + use<'_, T> {
|
||||
self.objects
|
||||
.iter()
|
||||
.filter_map(|(&id, object)| match object.kind {
|
||||
|
||||
@@ -16,13 +16,17 @@ use syscall::{error::EINVAL, PAGE_SIZE};
|
||||
|
||||
use super::Device;
|
||||
|
||||
pub struct Connector {
|
||||
framebuffer_id: usize,
|
||||
}
|
||||
|
||||
//TODO: use hardware cursor
|
||||
pub enum Cursor {}
|
||||
|
||||
impl CursorFramebuffer for Cursor {}
|
||||
|
||||
impl GraphicsAdapter for Device {
|
||||
type Connector = ();
|
||||
type Connector = Connector;
|
||||
|
||||
type Framebuffer = DumbFb;
|
||||
type Cursor = Cursor;
|
||||
@@ -37,12 +41,9 @@ impl GraphicsAdapter for Device {
|
||||
|
||||
fn init(&mut self, objects: &mut DrmObjects<Self>) {
|
||||
// FIXME enumerate actual connectors
|
||||
for framebuffer in &self.framebuffers {
|
||||
for (framebuffer_id, _) in self.framebuffers.iter().enumerate() {
|
||||
objects.add_connector(DrmConnector {
|
||||
modes: vec![modeinfo_for_size(
|
||||
framebuffer.width as u32,
|
||||
framebuffer.height as u32,
|
||||
)],
|
||||
modes: vec![],
|
||||
encoder_id: DrmObjectId::INVALID,
|
||||
connector_type: 0,
|
||||
connector_type_id: 0,
|
||||
@@ -50,7 +51,7 @@ impl GraphicsAdapter for Device {
|
||||
mm_width: 0,
|
||||
mm_height: 0,
|
||||
subpixel: DrmSubpixelOrder::Unknown,
|
||||
driver_data: (),
|
||||
driver_data: Connector { framebuffer_id },
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -70,6 +71,14 @@ impl GraphicsAdapter for Device {
|
||||
}
|
||||
}
|
||||
|
||||
fn probe_connector(&mut self, connector: &mut DrmConnector<Self>) {
|
||||
let framebuffer = &self.framebuffers[connector.driver_data.framebuffer_id];
|
||||
connector.modes = vec![modeinfo_for_size(
|
||||
framebuffer.width as u32,
|
||||
framebuffer.height as u32,
|
||||
)];
|
||||
}
|
||||
|
||||
fn display_count(&self) -> usize {
|
||||
self.framebuffers.len()
|
||||
}
|
||||
|
||||
@@ -67,6 +67,8 @@ impl GraphicsAdapter for FbAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
fn probe_connector(&mut self, _connector: &mut DrmConnector<Self>) {}
|
||||
|
||||
fn display_count(&self) -> usize {
|
||||
self.framebuffers.len()
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
use std::os::fd::AsRawFd;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
use driver_graphics::GraphicsAdapter;
|
||||
use event::{user_data, EventQueue};
|
||||
use pcid_interface::PciFunctionHandle;
|
||||
|
||||
@@ -542,7 +543,10 @@ fn deamon(deamon: daemon::Daemon, mut pcid_handle: PciFunctionHandle) -> anyhow:
|
||||
|
||||
if events & VIRTIO_GPU_EVENT_DISPLAY != 0 {
|
||||
let (adapter, objects) = scheme.adapter_and_objects_mut();
|
||||
futures::executor::block_on(adapter.update_displays(objects)).unwrap();
|
||||
futures::executor::block_on(async { adapter.update_displays().await.unwrap() });
|
||||
for connector in objects.connectors_mut() {
|
||||
adapter.probe_connector(connector);
|
||||
}
|
||||
scheme.notify_displays_changed();
|
||||
scheme
|
||||
.adapter_mut()
|
||||
|
||||
@@ -76,6 +76,7 @@ impl CursorFramebuffer for VirtGpuCursor {}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Display {
|
||||
enabled: bool,
|
||||
width: u32,
|
||||
height: u32,
|
||||
active_resource: Option<ResourceId>,
|
||||
@@ -90,13 +91,14 @@ pub struct VirtGpuAdapter<'a> {
|
||||
}
|
||||
|
||||
impl VirtGpuAdapter<'_> {
|
||||
pub async fn update_displays(&mut self, objects: &mut DrmObjects<Self>) -> Result<(), Error> {
|
||||
pub async fn update_displays(&mut self) -> Result<(), Error> {
|
||||
let display_info = self.get_display_info().await?;
|
||||
let raw_displays = &display_info.display_info[..self.config.num_scanouts() as usize];
|
||||
|
||||
self.displays.resize(
|
||||
raw_displays.len(),
|
||||
Display {
|
||||
enabled: false,
|
||||
width: 0,
|
||||
height: 0,
|
||||
active_resource: None,
|
||||
@@ -109,6 +111,8 @@ impl VirtGpuAdapter<'_> {
|
||||
info.rect.height
|
||||
);
|
||||
|
||||
self.displays[i].enabled = info.enabled != 0;
|
||||
|
||||
if info.rect.width == 0 || info.rect.height == 0 {
|
||||
// QEMU gives all displays other than the first a zero width and height, but trying
|
||||
// to attach a zero sized framebuffer to the display will result an error, so
|
||||
@@ -121,19 +125,6 @@ impl VirtGpuAdapter<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
for connector in objects.connectors().collect::<Vec<_>>() {
|
||||
let connector = objects.get_connector_mut(connector).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 raw_displays[connector.driver_data.display_id as usize].enabled != 0 {
|
||||
DrmConnectorStatus::Connected
|
||||
} else {
|
||||
DrmConnectorStatus::Disconnected
|
||||
};
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -233,6 +224,10 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
|
||||
}
|
||||
|
||||
fn init(&mut self, objects: &mut DrmObjects<Self>) {
|
||||
futures::executor::block_on(async {
|
||||
self.update_displays().await.unwrap();
|
||||
});
|
||||
|
||||
for display_id in 0..self.config.num_scanouts.get() {
|
||||
objects.add_connector(DrmConnector {
|
||||
modes: vec![],
|
||||
@@ -246,10 +241,6 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
|
||||
driver_data: VirtGpuConnector { display_id },
|
||||
});
|
||||
}
|
||||
|
||||
futures::executor::block_on(async {
|
||||
self.update_displays(objects).await.unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
fn get_cap(&self, cap: u32) -> syscall::Result<u64> {
|
||||
@@ -267,6 +258,19 @@ impl<'a> GraphicsAdapter for VirtGpuAdapter<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn probe_connector(&mut self, connector: &mut DrmConnector<Self>) {
|
||||
futures::executor::block_on(async {
|
||||
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 {
|
||||
DrmConnectorStatus::Disconnected
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
fn display_count(&self) -> usize {
|
||||
self.displays.len()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user