kms: Track active clients instead of active buffers
This commit is contained in:
parent
a15e378f1e
commit
ca00df0b37
6 changed files with 72 additions and 131 deletions
|
|
@ -38,12 +38,13 @@ use smithay::{
|
|||
drm::control::{Device as ControlDevice, ModeTypeFlags, connector, crtc},
|
||||
gbm::BufferObjectFlags as GbmBufferFlags,
|
||||
rustix::fs::OFlags,
|
||||
wayland_server::{DisplayHandle, Weak, protocol::wl_buffer::WlBuffer},
|
||||
wayland_server::DisplayHandle,
|
||||
},
|
||||
utils::{Clock, DevPath, DeviceFd, Monotonic, Point, Transform},
|
||||
wayland::drm_lease::{DrmLease, DrmLeaseState},
|
||||
};
|
||||
use tracing::{error, info, warn};
|
||||
use wayland_backend::server::ClientId;
|
||||
|
||||
use std::{
|
||||
borrow::BorrowMut,
|
||||
|
|
@ -117,7 +118,7 @@ pub struct InnerDevice {
|
|||
pub leased_connectors: Vec<(connector::Handle, crtc::Handle)>,
|
||||
pub leasing_global: Option<DrmLeaseState>,
|
||||
pub active_leases: Vec<DrmLease>,
|
||||
pub active_buffers: HashSet<Weak<WlBuffer>>,
|
||||
pub active_clients: HashSet<ClientId>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for InnerDevice {
|
||||
|
|
@ -133,7 +134,7 @@ impl fmt::Debug for InnerDevice {
|
|||
.field("leased_connectors", &self.leased_connectors)
|
||||
.field("leasing_global", &self.leasing_global)
|
||||
.field("active_leases", &self.active_leases)
|
||||
.field("active_buffers", &self.active_buffers.len())
|
||||
.field("active_clients", &self.active_clients.len())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
@ -338,7 +339,7 @@ impl State {
|
|||
leased_connectors: Vec::new(),
|
||||
leasing_global,
|
||||
active_leases: Vec::new(),
|
||||
active_buffers: HashSet::new(),
|
||||
active_clients: HashSet::new(),
|
||||
},
|
||||
|
||||
supports_atomic,
|
||||
|
|
@ -738,7 +739,7 @@ impl InnerDevice {
|
|||
pub fn in_use(&self, primary: Option<&DrmNode>) -> bool {
|
||||
Some(&self.render_node) == primary
|
||||
|| !self.surfaces.is_empty()
|
||||
|| !self.active_buffers.is_empty()
|
||||
|| !self.active_clients.is_empty()
|
||||
}
|
||||
|
||||
pub fn connector_added(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use indexmap::IndexMap;
|
|||
use render::gles::GbmGlowBackend;
|
||||
use smithay::{
|
||||
backend::{
|
||||
allocator::{Buffer, dmabuf::Dmabuf, format::FormatSet},
|
||||
allocator::{dmabuf::Dmabuf, format::FormatSet},
|
||||
drm::{DrmDeviceFd, DrmNode, NodeType, VrrSupport, output::DrmOutputRenderElements},
|
||||
egl::{EGLContext, EGLDevice, EGLDisplay},
|
||||
input::InputEvent,
|
||||
|
|
@ -41,7 +41,7 @@ use smithay::{
|
|||
},
|
||||
};
|
||||
use surface::GbmDrmOutput;
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
use tracing::{debug, error, info, warn};
|
||||
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
|
|
@ -487,78 +487,55 @@ impl KmsState {
|
|||
|
||||
pub fn dmabuf_imported(
|
||||
&mut self,
|
||||
_client: Option<Client>,
|
||||
client: Option<Client>,
|
||||
global: &DmabufGlobal,
|
||||
dmabuf: Dmabuf,
|
||||
) -> Result<DrmNode> {
|
||||
let (expected_node, mut other_nodes) = self
|
||||
let device = self
|
||||
.drm_devices
|
||||
.values_mut()
|
||||
.partition::<Vec<_>, _>(|device| {
|
||||
.find(|device| {
|
||||
device
|
||||
.socket
|
||||
.as_ref()
|
||||
.map(|s| &s.dmabuf_global == global)
|
||||
.unwrap_or(false)
|
||||
});
|
||||
other_nodes.retain(|device| device.socket.is_some());
|
||||
})
|
||||
.context("Couldn't find gpu for dmabuf global")?;
|
||||
|
||||
let mut last_err = anyhow::anyhow!("Dmabuf cannot be imported on any gpu");
|
||||
for device in expected_node.into_iter().chain(other_nodes.into_iter()) {
|
||||
let mut _egl = None;
|
||||
let egl_display = if let Some(egl_display) = device
|
||||
.inner
|
||||
.egl
|
||||
.as_ref()
|
||||
.map(|internals| &internals.display)
|
||||
{
|
||||
egl_display
|
||||
} else {
|
||||
_egl =
|
||||
Some(init_egl(&device.inner.gbm).context("Failed to initialize egl context")?);
|
||||
&_egl.as_ref().unwrap().display
|
||||
};
|
||||
let new_client = if let Some(client) = client {
|
||||
let new = device.inner.active_clients.insert(client.id());
|
||||
device.inner.update_egl(
|
||||
self.primary_node.read().unwrap().as_ref(),
|
||||
self.api.as_mut(),
|
||||
)? && new
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
if !egl_display
|
||||
.dmabuf_texture_formats()
|
||||
.contains(&dmabuf.format())
|
||||
{
|
||||
trace!(
|
||||
"Skipping import of dmabuf on {:?}: unsupported format",
|
||||
device.inner.render_node
|
||||
let egl = device
|
||||
.inner
|
||||
.egl
|
||||
.as_ref()
|
||||
.context("EGL initialization Error")?;
|
||||
egl.display
|
||||
.create_image_from_dmabuf(&dmabuf)
|
||||
.inspect(|image| unsafe {
|
||||
smithay::backend::egl::ffi::egl::DestroyImageKHR(
|
||||
**egl.display.get_display_handle(),
|
||||
*image,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
})
|
||||
.context("Failed to create EGLImage from dmabuf")?;
|
||||
|
||||
let result = egl_display
|
||||
.create_image_from_dmabuf(&dmabuf)
|
||||
.map(|image| {
|
||||
unsafe {
|
||||
smithay::backend::egl::ffi::egl::DestroyImageKHR(
|
||||
**egl_display.get_display_handle(),
|
||||
image,
|
||||
);
|
||||
};
|
||||
device.inner.render_node
|
||||
})
|
||||
.map_err(Into::into);
|
||||
let node = device.inner.render_node;
|
||||
dmabuf.set_node(node);
|
||||
|
||||
match result {
|
||||
Ok(node) => {
|
||||
dmabuf.set_node(node); // so the MultiRenderer knows what node to use
|
||||
return Ok(node);
|
||||
}
|
||||
Err(err) => {
|
||||
trace!(
|
||||
?err,
|
||||
"Failed to import dmabuf on {:?}", device.inner.render_node
|
||||
);
|
||||
last_err = err;
|
||||
}
|
||||
}
|
||||
if new_client {
|
||||
self.refresh_used_devices()?;
|
||||
}
|
||||
|
||||
Err(last_err)
|
||||
Ok(node)
|
||||
}
|
||||
|
||||
pub fn schedule_render(&mut self, output: &Output) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue