diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 0f092d91..08cfc0db 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -476,6 +476,10 @@ impl Client { pci_id } + pub fn make_render_device(&self, device: DrmDevice) { + self.send(&ClientMessage::MakeRenderDevice { device }); + } + pub fn connector_connected(&self, connector: Connector) -> bool { let res = self.send_with_response(&ClientMessage::ConnectorConnected { connector }); get_response!(res, false, ConnectorConnected { connected }); diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index 23c52a59..b2850882 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -313,6 +313,9 @@ pub enum ClientMessage<'a> { connector: Connector, enabled: bool, }, + MakeRenderDevice { + device: DrmDevice, + }, } #[derive(Encode, Decode, Debug)] diff --git a/jay-config/src/video.rs b/jay-config/src/video.rs index 25076f61..5f9d494b 100644 --- a/jay-config/src/video.rs +++ b/jay-config/src/video.rs @@ -357,4 +357,9 @@ impl DrmDevice { pub fn pci_id(self) -> PciId { get!().drm_device_pci_id(self) } + + /// Makes this device the render device. + pub fn make_render_device(self) { + get!().make_render_device(self); + } } diff --git a/src/backend.rs b/src/backend.rs index 57b78438..706a8862 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -221,4 +221,5 @@ pub trait BackendDrmDevice { fn event(&self) -> Option; fn on_change(&self, cb: Rc); fn dev_t(&self) -> c::dev_t; + fn make_render_device(self: Rc); } diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 1864d29b..e3a703d5 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -55,6 +55,7 @@ pub struct MetalRenderContext { #[derive(Debug)] pub struct MetalDrmDevice { + pub backend: Rc, pub id: DrmDeviceId, pub devnum: c::dev_t, pub devnode: CString, @@ -88,6 +89,10 @@ impl BackendDrmDevice for MetalDrmDevice { fn dev_t(&self) -> dev_t { self.devnum } + + fn make_render_device(self: Rc) { + self.backend.make_render_device(&self, true); + } } pub struct HandleEvents { @@ -869,6 +874,7 @@ impl MetalBackend { fatal!("We are not innocent. Terminating."); } log::info!("Trying to create a new context"); + self.ctx.set(None); self.state.set_render_ctx(None); let mut old_buffers = vec![]; for dev in self.device_holder.drm_devices.lock().values() { @@ -876,16 +882,7 @@ impl MetalBackend { old_buffers.push(connector.buffers.take()); } } - if !self.install_render_context(&ctx.dev) { - return false; - } - let mut preserve = Preserve::default(); - for dev in self.device_holder.drm_devices.lock().values() { - if let Err(e) = self.init_drm_device(dev, &mut preserve) { - log::error!("Could not re-initialize device: {}", ErrorFmt(e)); - } - } - true + self.make_render_device(&ctx.dev, true) } fn install_render_context(&self, dev: &Rc) -> bool { @@ -1006,11 +1003,7 @@ impl MetalBackend { if !preserve.connectors.contains(&connector.id) { connector.can_present.set(true); } - let dd = connector.display.borrow_mut(); - if !connector.connect_sent.get() { - self.send_connected(connector, &dd); - } - self.start_connector(connector, &dd); + self.start_connector(connector, true); } } dev.unprocessed_change.set(false); @@ -1092,6 +1085,7 @@ impl MetalBackend { }; let dev = Rc::new(MetalDrmDevice { + backend: self.clone(), id: pending.id, devnum: pending.devnum, devnode: pending.devnode, @@ -1111,13 +1105,8 @@ impl MetalBackend { }, }); - let mut preserve = Preserve::default(); - if self.ctx.get().is_none() { - self.install_render_context(&dev); - for dev in self.device_holder.drm_devices.lock().values() { - let _ = self.init_drm_device(dev, &mut preserve); - } + self.make_render_device(&dev, false); } let (connectors, futures) = get_connectors(self, &dev, &resources.connectors)?; @@ -1129,7 +1118,7 @@ impl MetalBackend { unprocessed_change: Cell::new(false), }); - self.init_drm_device(&slf, &mut preserve)?; + self.init_drm_device(&slf, &mut Preserve::default())?; self.state .backend_events @@ -1140,9 +1129,7 @@ impl MetalBackend { .backend_events .push(BackendEvent::NewConnector(connector.clone())); if connector.connected() { - let dd = connector.display.borrow_mut(); - self.send_connected(connector, &dd); - self.start_connector(connector, &dd); + self.start_connector(connector, true); } } @@ -1417,6 +1404,31 @@ impl MetalBackend { } } + fn make_render_device(&self, dev: &Rc, log: bool) -> bool { + if let Some(ctx) = self.ctx.get() { + if ctx.dev.id == dev.id { + return true; + } + } + if !self.install_render_context(dev) { + return false; + } + let mut preserve = Preserve::default(); + for dev in self.device_holder.drm_devices.lock().values() { + if let Err(e) = self.init_drm_device(dev, &mut preserve) { + if log { + log::error!("Could not initialize device: {}", ErrorFmt(e)); + } + } + for connector in dev.connectors.lock().values() { + if connector.connected() { + self.start_connector(connector, false); + } + } + } + true + } + fn init_drm_device( &self, dev: &Rc, @@ -1749,13 +1761,19 @@ impl MetalBackend { Ok(()) } - fn start_connector(&self, connector: &Rc, dd: &ConnectorDisplayData) { - log::info!( - "Initialized connector {}-{} with mode {:?}", - dd.connector_type, - dd.connector_type_id, - dd.mode.as_ref().unwrap(), - ); + fn start_connector(&self, connector: &Rc, log_mode: bool) { + let dd = connector.display.borrow_mut(); + if !connector.connect_sent.get() { + self.send_connected(connector, &dd); + } + if log_mode { + log::info!( + "Initialized connector {}-{} with mode {:?}", + dd.connector_type, + dd.connector_type_id, + dd.mode.as_ref().unwrap(), + ); + } connector.has_damage.set(true); connector.cursor_changed.set(true); connector.schedule_present(); diff --git a/src/backends/x.rs b/src/backends/x.rs index bd8aeb4f..990adf03 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -960,6 +960,11 @@ impl BackendDrmDevice for XDrmDevice { fn dev_t(&self) -> dev_t { self.dev } + + fn make_render_device(self: Rc) { + log::warn!("make_render_device is not supported by the X backend"); + // nothing + } } struct XOutput { diff --git a/src/config/handler.rs b/src/config/handler.rs index 11d7590b..37bb66ef 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -195,6 +195,12 @@ impl ConfigProxyHandler { self.respond(Response::GetDrmDevices { devices: res }); } + fn handle_make_render_device(&self, dev: DrmDevice) -> Result<(), CphError> { + let dev = self.get_drm_device(dev)?; + dev.make_render_device(); + Ok(()) + } + fn handle_get_drm_device_model(&self, dev: DrmDevice) -> Result<(), CphError> { let dev = self.get_drm_device(dev)?; let model = dev.model.clone().unwrap_or_default(); @@ -1217,6 +1223,9 @@ impl ConfigProxyHandler { ClientMessage::DisablePointerConstraint { seat } => self .handle_disable_pointer_constraint(seat) .wrn("disable_pointer_constraint")?, + ClientMessage::MakeRenderDevice { device } => self + .handle_make_render_device(device) + .wrn("make_render_device")?, } Ok(()) } diff --git a/src/state.rs b/src/state.rs index 604021f1..5ce8def5 100644 --- a/src/state.rs +++ b/src/state.rs @@ -209,11 +209,22 @@ pub struct DrmDevData { pub handler: Cell>>, pub connectors: CopyHashMap>, pub syspath: Option, + pub devnode: Option, pub vendor: Option, pub model: Option, pub pci_id: Option, } +impl DrmDevData { + pub fn make_render_device(&self) { + log::info!( + "Making {} the render device", + self.devnode.as_deref().unwrap_or("unknown"), + ); + self.dev.clone().make_render_device(); + } +} + struct UpdateTextTexturesVisitor; impl NodeVisitorBase for UpdateTextTexturesVisitor { fn visit_container(&mut self, node: &Rc) { diff --git a/src/tasks/drmdev.rs b/src/tasks/drmdev.rs index 2703a67a..c4b413d5 100644 --- a/src/tasks/drmdev.rs +++ b/src/tasks/drmdev.rs @@ -12,6 +12,7 @@ use { pub fn handle(state: &Rc, dev: Rc) { let id = dev.id(); let mut syspath = None; + let mut devnode = None; let mut vendor = None; let mut model = None; let mut pci_id = None; @@ -40,6 +41,7 @@ pub fn handle(state: &Rc, dev: Rc) { syspath = dev.syspath().map(|s| s.to_string_lossy().into_owned()); vendor = dev.vendor().map(|s| s.to_string_lossy().into_owned()); model = dev.model().map(|s| s.to_string_lossy().into_owned()); + devnode = odev.devnode().map(|s| s.to_string_lossy().into_owned()); 'get_pci_id: { let id = match dev.pci_id() { Some(id) => id, @@ -68,6 +70,7 @@ pub fn handle(state: &Rc, dev: Rc) { handler: Cell::new(None), connectors: Default::default(), syspath, + devnode, vendor, model, pci_id,