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 {
UdevEvent::Added { device_id, path } => data
.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)),
UdevEvent::Changed { device_id } => data
.state
@ -241,7 +241,7 @@ pub fn init_backend(
} else {
if let Err(err) =
data.state
.device_added(dev, path.into(), &data.display.handle())
.device_added(dev, path.into(), &data.display.handle(), true)
{
slog_scope::error!(
"Failed to add drm device {}: {}",
@ -319,14 +319,21 @@ pub fn init_backend(
for (dev, path) in udev_dispatcher.as_source_ref().device_list() {
state
.device_added(dev, path.into(), dh)
.device_added(dev, path.into(), dh, false)
.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(())
}
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() {
return Ok(());
}
@ -358,25 +365,30 @@ impl State {
let gbm = GbmDevice::new(fd)
.with_context(|| format!("Failed to initialize GBM device for {}", 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 render_node = egl_device
.try_get_render_node()
.ok()
.and_then(std::convert::identity)
.unwrap_or(drm_node);
let egl_context = EGLContext::new(&egl_display, None).with_context(|| {
format!(
"Failed to create EGLContext for device {:?}:{}",
egl_device,
path.display()
)
})?;
let formats = egl_context.dmabuf_render_formats().clone();
let (render_node, formats) = {
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 render_node = egl_device
.try_get_render_node()
.ok()
.and_then(std::convert::identity)
.unwrap_or(drm_node);
let egl_context = EGLContext::new(&egl_display, None).with_context(|| {
format!(
"Failed to create EGLContext for device {:?}:{}",
egl_device,
path.display()
)
})?;
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 =
Dispatcher::new(drm, move |event, metadata, data: &mut Data| match event {
@ -494,7 +506,7 @@ impl State {
let mut device = Device {
render_node,
surfaces: HashMap::new(),
gbm,
gbm: gbm.clone(),
allocator,
drm: dispatcher,
formats,
@ -508,6 +520,16 @@ impl State {
let mut w = self.common.shell.global_space().size.w;
{
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 {
let mut renderer = match backend.api.single_renderer(&render_node) {
Ok(renderer) => renderer,
@ -545,6 +567,14 @@ impl State {
&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 Some(physical_device) =
PhysicalDevice::enumerate(&instance)
@ -582,8 +612,6 @@ impl State {
}
}
}
Ok(())
}
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<()> {
let drm_node = DrmNode::from_dev_id(dev)?;
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() {
if let Some(token) = surface.render_timer_token.take() {
self.common.event_loop_handle.remove(token);