autocommit 2022-04-05 18:28:42 CEST
This commit is contained in:
parent
1f05ea431e
commit
a3e9f21fc5
29 changed files with 568 additions and 225 deletions
|
|
@ -1,4 +1,5 @@
|
|||
use crate::backend::{Backend, Connector, ConnectorEvent, OutputId};
|
||||
use crate::backend::{Backend, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId};
|
||||
use crate::drm::drm::ConnectorType;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct DummyBackend {}
|
||||
|
|
@ -10,14 +11,21 @@ impl Backend for DummyBackend {
|
|||
}
|
||||
|
||||
pub struct DummyOutput {
|
||||
pub id: OutputId,
|
||||
pub id: ConnectorId,
|
||||
}
|
||||
|
||||
impl Connector for DummyOutput {
|
||||
fn id(&self) -> OutputId {
|
||||
fn id(&self) -> ConnectorId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn kernel_id(&self) -> ConnectorKernelId {
|
||||
ConnectorKernelId {
|
||||
ty: ConnectorType::Unknown(0),
|
||||
id: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn event(&self) -> Option<ConnectorEvent> {
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::async_engine::{AsyncFd, SpawnedFuture};
|
||||
use crate::backend::{BackendEvent, Connector, ConnectorEvent, Mode, OutputId};
|
||||
use crate::backend::{BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, MonitorInfo};
|
||||
use crate::backends::metal::{DrmId, MetalBackend, MetalError};
|
||||
use crate::drm::drm::{
|
||||
drm_mode_modeinfo, Change, ConnectorStatus, ConnectorType, DrmBlob, DrmConnector, DrmCrtc,
|
||||
|
|
@ -25,6 +25,7 @@ use std::ffi::CString;
|
|||
use std::fmt::{Debug, Formatter};
|
||||
use std::rc::Rc;
|
||||
use uapi::c;
|
||||
use crate::edid::Descriptor;
|
||||
|
||||
pub struct PendingDrmDevice {
|
||||
pub id: DrmId,
|
||||
|
|
@ -72,12 +73,16 @@ pub struct MetalConnector {
|
|||
pub id: DrmConnector,
|
||||
pub master: Rc<DrmMaster>,
|
||||
|
||||
pub output_id: OutputId,
|
||||
pub connector_id: ConnectorId,
|
||||
|
||||
pub crtcs: AHashMap<DrmCrtc, Rc<MetalCrtc>>,
|
||||
pub modes: Vec<DrmModeInfo>,
|
||||
pub mode: CloneCell<Option<Rc<DrmModeInfo>>>,
|
||||
|
||||
pub monitor_manufacturer: String,
|
||||
pub monitor_name: String,
|
||||
pub monitor_serial_number: String,
|
||||
|
||||
pub events: SyncQueue<ConnectorEvent>,
|
||||
|
||||
pub buffers: CloneCell<Option<Rc<[RenderBuffer; 2]>>>,
|
||||
|
|
@ -114,8 +119,15 @@ impl Debug for OnChange {
|
|||
}
|
||||
|
||||
impl Connector for MetalConnector {
|
||||
fn id(&self) -> OutputId {
|
||||
self.output_id
|
||||
fn id(&self) -> ConnectorId {
|
||||
self.connector_id
|
||||
}
|
||||
|
||||
fn kernel_id(&self) -> ConnectorKernelId {
|
||||
ConnectorKernelId {
|
||||
ty: self.connector_type,
|
||||
id: self.connector_type_id,
|
||||
}
|
||||
}
|
||||
|
||||
fn event(&self) -> Option<ConnectorEvent> {
|
||||
|
|
@ -212,28 +224,73 @@ fn create_connector(
|
|||
}
|
||||
}
|
||||
let props = collect_properties(&dev.master, connector)?;
|
||||
let mode = info.modes.first().cloned().map(Rc::new);
|
||||
let events = SyncQueue::default();
|
||||
if let Some(mode) = &mode {
|
||||
events.push(ConnectorEvent::ModeChanged(Mode {
|
||||
width: mode.hdisplay as _,
|
||||
height: mode.vdisplay as _,
|
||||
refresh_rate: mode.refresh_rate(),
|
||||
}));
|
||||
let connection = ConnectorStatus::from(info.connection);
|
||||
let connector_type = ConnectorType::from(info.connector_type);
|
||||
let mut name = String::new();
|
||||
let mut manufacturer = String::new();
|
||||
let mut serial_number = String::new();
|
||||
'fetch_edid: {
|
||||
if connection != ConnectorStatus::Connected {
|
||||
break 'fetch_edid;
|
||||
}
|
||||
let edid = match props.get("EDID") {
|
||||
Ok(e) => e,
|
||||
_ => {
|
||||
log::warn!("Connector {}-{} is connected but has no EDID blob", connector_type, info.connector_type_id);
|
||||
break 'fetch_edid;
|
||||
}
|
||||
};
|
||||
let blob = match dev.master.getblob_vec::<u8>(DrmBlob(edid.value.get() as _)) {
|
||||
Ok(b) => b,
|
||||
Err(e) => {
|
||||
log::error!("Could not fetch edid property of connector {}-{}: {}", connector_type, info.connector_type_id, ErrorFmt(e));
|
||||
break 'fetch_edid;
|
||||
}
|
||||
};
|
||||
let edid = match crate::edid::parse(&blob) {
|
||||
Ok(e) => e,
|
||||
Err(e) => {
|
||||
log::error!("Could not parse edid property of connector {}-{}: {}", connector_type, info.connector_type_id, ErrorFmt(e));
|
||||
break 'fetch_edid;
|
||||
}
|
||||
};
|
||||
manufacturer = edid.base_block.id_manufacturer_name.to_string();
|
||||
for descriptor in &edid.base_block.descriptors {
|
||||
if let Some(d) = descriptor {
|
||||
match d {
|
||||
Descriptor::DisplayProductSerialNumber(s) => {
|
||||
serial_number = s.to_string();
|
||||
}
|
||||
Descriptor::DisplayProductName(s) => {
|
||||
name = s.to_string();
|
||||
}
|
||||
_ => { },
|
||||
}
|
||||
}
|
||||
}
|
||||
if name.is_empty() {
|
||||
log::warn!("The display attached to connector {}-{} does not have a product name descriptor", connector_type, info.connector_type_id);
|
||||
}
|
||||
if serial_number.is_empty() {
|
||||
serial_number = edid.base_block.id_serial_number.to_string();
|
||||
}
|
||||
}
|
||||
Ok(MetalConnector {
|
||||
id: connector,
|
||||
master: dev.master.clone(),
|
||||
output_id: state.output_ids.next(),
|
||||
connector_id: state.connector_ids.next(),
|
||||
crtcs,
|
||||
mode: CloneCell::new(mode),
|
||||
events,
|
||||
mode: CloneCell::new(info.modes.first().cloned().map(Rc::new)),
|
||||
monitor_manufacturer: manufacturer,
|
||||
monitor_name: name,
|
||||
monitor_serial_number: serial_number,
|
||||
events: Default::default(),
|
||||
modes: info.modes,
|
||||
buffers: Default::default(),
|
||||
next_buffer: Default::default(),
|
||||
connector_type: info.connector_type.into(),
|
||||
connector_type,
|
||||
connector_type_id: info.connector_type_id,
|
||||
connection: info.connection.into(),
|
||||
connection,
|
||||
mm_width: info.mm_width,
|
||||
mm_height: info.mm_height,
|
||||
subpixel: info.subpixel,
|
||||
|
|
@ -488,7 +545,27 @@ impl MetalBackend {
|
|||
self.state
|
||||
.backend_events
|
||||
.push(BackendEvent::NewConnector(connector.clone()));
|
||||
if connector.primary_plane.get().is_some() {
|
||||
if connector.connection == ConnectorStatus::Connected {
|
||||
if connector.primary_plane.get().is_none() {
|
||||
log::error!("Connector {}-{} is connected but does not have a primary plane", connector.connector_type, connector.connector_type_id);
|
||||
continue;
|
||||
}
|
||||
let mut prev_mode = None;
|
||||
let mut modes = vec!();
|
||||
for mode in connector.modes.iter().map(|m| m.to_backend()) {
|
||||
if prev_mode.replace(mode) != Some(mode) {
|
||||
modes.push(mode);
|
||||
}
|
||||
}
|
||||
connector.events.push(ConnectorEvent::Connected(MonitorInfo {
|
||||
modes,
|
||||
manufacturer: connector.monitor_manufacturer.clone(),
|
||||
product: connector.monitor_name.clone(),
|
||||
serial_number: connector.monitor_serial_number.clone(),
|
||||
initial_mode: connector.mode.get().unwrap().to_backend(),
|
||||
width_mm: connector.mm_width as _,
|
||||
height_mm: connector.mm_height as _,
|
||||
}));
|
||||
self.start_connector(connector);
|
||||
}
|
||||
}
|
||||
|
|
@ -901,7 +978,7 @@ impl MetalBackend {
|
|||
_ => return,
|
||||
};
|
||||
let buffer = &buffers[connector.next_buffer.fetch_add(1) % buffers.len()];
|
||||
if let Some(node) = self.state.root.outputs.get(&connector.output_id) {
|
||||
if let Some(node) = self.state.root.outputs.get(&connector.connector_id) {
|
||||
buffer
|
||||
.egl
|
||||
.render(&*node, &self.state, Some(node.global.pos.get()));
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
use crate::async_engine::{Phase, SpawnedFuture};
|
||||
use crate::backend::{
|
||||
Backend, BackendEvent, Connector, ConnectorEvent, InputDevice, InputDeviceAccelProfile,
|
||||
InputDeviceCapability, InputDeviceId, InputEvent, KeyState, Mode, OutputId, ScrollAxis,
|
||||
};
|
||||
use crate::drm::drm::{Drm, DrmError};
|
||||
use crate::backend::{Backend, BackendEvent, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent, KeyState, Mode, MonitorInfo, ScrollAxis};
|
||||
use crate::drm::drm::{ConnectorType, Drm, DrmError};
|
||||
use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING};
|
||||
use crate::drm::{ModifiedFormat, INVALID_MODIFIER};
|
||||
use crate::fixed::Fixed;
|
||||
|
|
@ -394,7 +391,7 @@ impl XBackendData {
|
|||
};
|
||||
let images = self.create_images(window_id, WIDTH, HEIGHT).await?;
|
||||
let output = Rc::new(XOutput {
|
||||
id: self.state.output_ids.next(),
|
||||
id: self.state.connector_ids.next(),
|
||||
_backend: self.clone(),
|
||||
window: window_id,
|
||||
events: Default::default(),
|
||||
|
|
@ -481,6 +478,20 @@ impl XBackendData {
|
|||
self.state
|
||||
.backend_events
|
||||
.push(BackendEvent::NewConnector(output.clone()));
|
||||
output.events.push(ConnectorEvent::Connected(MonitorInfo {
|
||||
modes: vec![],
|
||||
manufacturer: "X.Org Foundation".to_string(),
|
||||
product: format!("X-Window-{}", window_id),
|
||||
serial_number: window_id.to_string(),
|
||||
initial_mode: Mode {
|
||||
width: WIDTH,
|
||||
height: HEIGHT,
|
||||
refresh_rate_millihz: 60_000, // TODO
|
||||
},
|
||||
width_mm: WIDTH,
|
||||
height_mm: HEIGHT,
|
||||
}));
|
||||
output.changed();
|
||||
self.present(&output).await;
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -759,7 +770,7 @@ impl XBackendData {
|
|||
self.outputs.get(&event.event),
|
||||
self.mouse_seats.get(&event.deviceid),
|
||||
) {
|
||||
seat.mouse_event(InputEvent::OutputPosition(
|
||||
seat.mouse_event(InputEvent::ConnectorPosition(
|
||||
win.id,
|
||||
Fixed::from_1616(event.event_x),
|
||||
Fixed::from_1616(event.event_y),
|
||||
|
|
@ -777,7 +788,7 @@ impl XBackendData {
|
|||
(Some(a), Some(b)) => (a, b),
|
||||
_ => return Ok(()),
|
||||
};
|
||||
seat.mouse_event(InputEvent::OutputPosition(
|
||||
seat.mouse_event(InputEvent::ConnectorPosition(
|
||||
win.id,
|
||||
Fixed::from_1616(event.event_x),
|
||||
Fixed::from_1616(event.event_y),
|
||||
|
|
@ -792,6 +803,7 @@ impl XBackendData {
|
|||
Some(o) => o,
|
||||
_ => return Ok(()),
|
||||
};
|
||||
output.events.push(ConnectorEvent::Disconnected);
|
||||
output.events.push(ConnectorEvent::Removed);
|
||||
output.changed();
|
||||
Ok(())
|
||||
|
|
@ -820,7 +832,7 @@ impl XBackendData {
|
|||
output.events.push(ConnectorEvent::ModeChanged(Mode {
|
||||
width,
|
||||
height,
|
||||
refresh_rate: 60, // TODO
|
||||
refresh_rate_millihz: 60, // TODO
|
||||
}));
|
||||
output.changed();
|
||||
}
|
||||
|
|
@ -829,7 +841,7 @@ impl XBackendData {
|
|||
}
|
||||
|
||||
struct XOutput {
|
||||
id: OutputId,
|
||||
id: ConnectorId,
|
||||
_backend: Rc<XBackendData>,
|
||||
window: u32,
|
||||
events: SyncQueue<ConnectorEvent>,
|
||||
|
|
@ -859,10 +871,17 @@ impl XOutput {
|
|||
}
|
||||
|
||||
impl Connector for XOutput {
|
||||
fn id(&self) -> OutputId {
|
||||
fn id(&self) -> ConnectorId {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn kernel_id(&self) -> ConnectorKernelId {
|
||||
ConnectorKernelId {
|
||||
ty: ConnectorType::EmbeddedWindow,
|
||||
id: self.id.raw(),
|
||||
}
|
||||
}
|
||||
|
||||
fn event(&self) -> Option<ConnectorEvent> {
|
||||
self.events.pop()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue