Commit 2454f8b9122d
tarball3 files changed+43-2
@@ -9,7 +9,7 @@ use smithay::backend::renderer::ImportDma;
99
use smithay::reexports::wayland_server::DisplayHandle;1010
use smithay::wayland::compositor::CompositorState;1111
use smithay::wayland::cursor_shape::CursorShapeManagerState;12
-use smithay::wayland::dmabuf::{DmabufGlobal, DmabufState};12
+use smithay::wayland::dmabuf::{DmabufFeedbackBuilder, DmabufGlobal, DmabufState};1313
use smithay::wayland::foreign_toplevel_list::ForeignToplevelListState;1414
use smithay::wayland::idle_inhibit::IdleInhibitManagerState;1515
use smithay::wayland::image_capture_source::{@@ -59,7 +59,21 @@ pub struct Protocols {
5959
impl Protocols {6060
pub fn new(dh: &DisplayHandle, renderer: &VulkanRenderer) -> Self {6161
let mut dmabuf_state = DmabufState::new();62
- let dmabuf_global = dmabuf_state.create_global::<State>(dh, renderer.dmabuf_formats());62
+ let formats = renderer.dmabuf_formats();63
+ // EGL finds its device through the feedback main device, and without64
+ // one Mesa and egl-wayland give up and Qt falls back to wl_shm.65
+ let feedback = renderer.drm_node().and_then(|node| {66
+ DmabufFeedbackBuilder::new(node, formats.iter().copied())67
+ .build()68
+ .inspect_err(|e| tracing::warn!("no dmabuf feedback: {e}"))69
+ .ok()70
+ });71
+ let dmabuf_global = match &feedback {72
+ Some(feedback) => {73
+ dmabuf_state.create_global_with_default_feedback::<State>(dh, feedback)74
+ }75
+ None => dmabuf_state.create_global::<State>(dh, formats),76
+ };6377
let primary_selection_state = PrimarySelectionState::new::<State>(dh);6478
Self {6579
compositor_state: CompositorState::new::<State>(dh),@@ -54,6 +54,7 @@ pub(crate) struct Device {
5454
pub push_descriptor: ash::khr::push_descriptor::Device,5555
pub dmabuf: Option<DmabufExt>,5656
pub name: String,57
+ pub drm_node: Option<u64>,5758
/// Signalled fences kept for reuse, see `FenceInner`.5859
pub spare_fences: Mutex<Vec<vk::Fence>>,5960
}@@ -104,6 +105,11 @@ impl Shared {
104105
.iter()105106
.filter_map(|e| e.extension_name_as_c_str().ok().map(ToOwned::to_owned))106107
.collect();108
+ let drm_node = available109
+ .iter()110
+ .any(|a| a.as_c_str() == ash::ext::physical_device_drm::NAME)111
+ .then(|| unsafe { drm_node(&instance, physical) })112
+ .flatten();107113
let has_dmabuf = DMABUF_EXTENSIONS108114
.iter()109115
.all(|n| available.iter().any(|a| a.as_c_str() == *n));@@ -185,6 +191,7 @@ impl Shared {
185191
push_descriptor,186192
dmabuf,187193
name,194
+ drm_node,188195
spare_fences: Mutex::new(Vec::new()),189196
};190197
Ok(Self {@@ -209,6 +216,21 @@ unsafe fn serves_node(instance: &ash::Instance, physical: vk::PhysicalDevice, no
209216
|| (drm.has_render == vk::TRUE && (drm.render_major, drm.render_minor) == (major, minor))210217
}211218
219
+/// The render node of `physical`, or its primary node when it has none.220
+unsafe fn drm_node(instance: &ash::Instance, physical: vk::PhysicalDevice) -> Option<u64> {221
+ let mut drm = vk::PhysicalDeviceDrmPropertiesEXT::default();222
+ let mut props = vk::PhysicalDeviceProperties2::default().push_next(&mut drm);223
+ unsafe { instance.get_physical_device_properties2(physical, &mut props) };224
+ let node = |major: i64, minor: i64| rustix::fs::makedev(major as u32, minor as u32);225
+ if drm.has_render == vk::TRUE {226
+ Some(node(drm.render_major, drm.render_minor))227
+ } else if drm.has_primary == vk::TRUE {228
+ Some(node(drm.primary_major, drm.primary_minor))229
+ } else {230
+ None231
+ }232
+}233
+212234
unsafe fn pick_physical(213235
instance: &ash::Instance,214236
wanted: Option<&str>,@@ -138,6 +138,11 @@ impl VulkanRenderer {
138138
&self.shared.device.name139139
}140140
141
+ /// DRM device number of the GPU in use, its render node where it has one.142
+ pub fn drm_node(&self) -> Option<u64> {143
+ self.shared.device.drm_node144
+ }145
+141146
/// Whether dmabufs can be imported, rendered into and allocated.142147
pub fn supports_dmabuf(&self) -> bool {143148
self.caps.render.iter().next().is_some()