kms: Fixup new backend initializtion

This commit is contained in:
Victoria Brekenfeld 2023-02-14 23:15:58 +01:00
parent 1a05121498
commit 5ba068ec82

View file

@ -179,7 +179,7 @@ pub fn init_backend(
match match event { match match event {
UdevEvent::Added { device_id, path } => data UdevEvent::Added { device_id, path } => data
.state .state
.device_added(device_id, path, &data.display.handle()) .device_added(device_id, path, &data.display.handle(), true)
.with_context(|| format!("Failed to add drm device: {}", device_id)), .with_context(|| format!("Failed to add drm device: {}", device_id)),
UdevEvent::Changed { device_id } => data UdevEvent::Changed { device_id } => data
.state .state
@ -241,7 +241,7 @@ pub fn init_backend(
} else { } else {
if let Err(err) = if let Err(err) =
data.state data.state
.device_added(dev, path.into(), &data.display.handle()) .device_added(dev, path.into(), &data.display.handle(), true)
{ {
slog_scope::error!( slog_scope::error!(
"Failed to add drm device {}: {}", "Failed to add drm device {}: {}",
@ -319,14 +319,21 @@ pub fn init_backend(
for (dev, path) in udev_dispatcher.as_source_ref().device_list() { for (dev, path) in udev_dispatcher.as_source_ref().device_list() {
state state
.device_added(dev, path.into(), dh) .device_added(dev, path.into(), dh, false)
.with_context(|| format!("Failed to add drm device: {}", path.display()))?; .with_context(|| format!("Failed to add drm device: {}", path.display()))?;
} }
// HACK: amdgpu doesn't like us initializing vulkan too early..
// so lets do that delayed until mesa fixes that.
let devices = state.backend.kms().devices.iter().map(|(drm_node, device)| (*drm_node, device.render_node)).collect::<Vec<_>>();
for (drm_node, render_node) in devices {
state.init_vulkan(drm_node, render_node);
}
Ok(()) Ok(())
} }
impl State { impl State {
fn device_added(&mut self, dev: dev_t, path: PathBuf, dh: &DisplayHandle) -> Result<()> { fn device_added(&mut self, dev: dev_t, path: PathBuf, dh: &DisplayHandle, try_vulkan: bool) -> Result<()> {
if !self.backend.kms().session.is_active() { if !self.backend.kms().session.is_active() {
return Ok(()); return Ok(());
} }
@ -358,25 +365,30 @@ impl State {
let gbm = GbmDevice::new(fd) let gbm = GbmDevice::new(fd)
.with_context(|| format!("Failed to initialize GBM device for {}", path.display()))?; .with_context(|| format!("Failed to initialize GBM device for {}", path.display()))?;
let egl_display = EGLDisplay::new(gbm.clone(), None).with_context(|| { let (render_node, formats) = {
format!("Failed to create EGLDisplay for device: {}", path.display()) let egl_display = EGLDisplay::new(gbm.clone(), None).with_context(|| {
})?; format!("Failed to create EGLDisplay for device: {}", path.display())
let egl_device = EGLDevice::device_for_display(&egl_display).with_context(|| { })?;
format!("Unable to find matching egl device for {}", path.display()) let egl_device = EGLDevice::device_for_display(&egl_display).with_context(|| {
})?; format!("Unable to find matching egl device for {}", path.display())
let render_node = egl_device })?;
.try_get_render_node() let render_node = egl_device
.ok() .try_get_render_node()
.and_then(std::convert::identity) .ok()
.unwrap_or(drm_node); .and_then(std::convert::identity)
let egl_context = EGLContext::new(&egl_display, None).with_context(|| { .unwrap_or(drm_node);
format!( let egl_context = EGLContext::new(&egl_display, None).with_context(|| {
"Failed to create EGLContext for device {:?}:{}", format!(
egl_device, "Failed to create EGLContext for device {:?}:{}",
path.display() egl_device,
) path.display()
})?; )
let formats = egl_context.dmabuf_render_formats().clone(); })?;
let formats = egl_context.dmabuf_render_formats().clone();
(render_node, formats)
// NOTE: We need the to drop the EGL types here again,
// otherwise the EGLDisplay created below might share the same GBM context
};
let dispatcher = let dispatcher =
Dispatcher::new(drm, move |event, metadata, data: &mut Data| match event { Dispatcher::new(drm, move |event, metadata, data: &mut Data| match event {
@ -494,7 +506,7 @@ impl State {
let mut device = Device { let mut device = Device {
render_node, render_node,
surfaces: HashMap::new(), surfaces: HashMap::new(),
gbm, gbm: gbm.clone(),
allocator, allocator,
drm: dispatcher, drm: dispatcher,
formats, formats,
@ -508,6 +520,16 @@ impl State {
let mut w = self.common.shell.global_space().size.w; let mut w = self.common.shell.global_space().size.w;
{ {
let backend = self.backend.kms(); let backend = self.backend.kms();
backend
.api
.as_mut()
.add_node(render_node, gbm)
.with_context(|| {
format!(
"Failed to initialize renderer for device: {}, skipping",
render_node
)
})?;
for (crtc, conn) in outputs { for (crtc, conn) in outputs {
let mut renderer = match backend.api.single_renderer(&render_node) { let mut renderer = match backend.api.single_renderer(&render_node) {
Ok(renderer) => renderer, Ok(renderer) => renderer,
@ -545,6 +567,14 @@ impl State {
&self.common.event_loop_handle, &self.common.event_loop_handle,
); );
if try_vulkan {
self.init_vulkan(drm_node, render_node);
}
Ok(())
}
fn init_vulkan(&mut self, drm_node: DrmNode, render_node: DrmNode) {
if let Ok(instance) = Instance::new(Version::VERSION_1_2, None, None) { if let Ok(instance) = Instance::new(Version::VERSION_1_2, None, None) {
if let Some(physical_device) = if let Some(physical_device) =
PhysicalDevice::enumerate(&instance) PhysicalDevice::enumerate(&instance)
@ -582,8 +612,6 @@ impl State {
} }
} }
} }
Ok(())
} }
fn device_changed(&mut self, dev: dev_t) -> Result<()> { fn device_changed(&mut self, dev: dev_t) -> Result<()> {
@ -663,7 +691,9 @@ impl State {
fn device_removed(&mut self, dev: dev_t, dh: &DisplayHandle) -> Result<()> { fn device_removed(&mut self, dev: dev_t, dh: &DisplayHandle) -> Result<()> {
let drm_node = DrmNode::from_dev_id(dev)?; let drm_node = DrmNode::from_dev_id(dev)?;
let mut outputs_removed = Vec::new(); let mut outputs_removed = Vec::new();
if let Some(mut device) = self.backend.kms().devices.remove(&drm_node) { let backend = self.backend.kms();
if let Some(mut device) = backend.devices.remove(&drm_node) {
backend.api.as_mut().remove_node(&device.render_node);
for surface in device.surfaces.values_mut() { for surface in device.surfaces.values_mut() {
if let Some(token) = surface.render_timer_token.take() { if let Some(token) = surface.render_timer_token.take() {
self.common.event_loop_handle.remove(token); self.common.event_loop_handle.remove(token);