kms: Track used devices and free resources

This commit is contained in:
Victoria Brekenfeld 2024-01-17 11:34:19 +00:00 • committed by Victoria Brekenfeld
parent e74b0dfaaa
commit ef3486f7e0
14 changed files with 303 additions and 130 deletions

View file

@ -1,10 +1,22 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::utils::prelude::*;
use crate::{state::BackendData, utils::prelude::*};
use smithay::{
reexports::wayland_server::protocol::wl_buffer::WlBuffer, wayland::buffer::BufferHandler,
reexports::wayland_server::{protocol::wl_buffer::WlBuffer, Resource},
wayland::buffer::BufferHandler,
};
impl BufferHandler for State {
fn buffer_destroyed(&mut self, _buffer: &WlBuffer) {}
fn buffer_destroyed(&mut self, buffer: &WlBuffer) {
if let BackendData::Kms(kms_state) = &mut self.backend {
for device in kms_state.devices.values_mut() {
if device.active_buffers.remove(&buffer.downgrade()) {
if !device.in_use(&kms_state.primary_node) {
kms_state.api.as_mut().remove_node(&device.render_node);
}
break;
}
}
}
}
}

View file

@ -1,9 +1,10 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::state::State;
use crate::state::{BackendData, State};
use smithay::{
backend::allocator::dmabuf::Dmabuf,
delegate_dmabuf,
reexports::wayland_server::Resource,
wayland::dmabuf::{DmabufGlobal, DmabufHandler, DmabufState, ImportNotifier},
};
@ -18,10 +19,33 @@ impl DmabufHandler for State {
dmabuf: Dmabuf,
import_notifier: ImportNotifier,
) {
if self.backend.dmabuf_imported(global, dmabuf).is_err() {
import_notifier.failed();
} else {
let _ = import_notifier.successful::<State>();
match self
.backend
.dmabuf_imported(import_notifier.client(), global, dmabuf)
{
Err(err) => {
tracing::debug!(?err, "dmabuf import failed");
import_notifier.failed()
}
Ok(Some(node)) => {
// kms backend
let Ok(buffer) = import_notifier.successful::<State>() else {
return
};
if let BackendData::Kms(kms_state) = &mut self.backend {
if let Some(device) = kms_state
.devices
.values_mut()
.find(|dev| dev.render_node == node)
{
device.active_buffers.insert(buffer.downgrade());
}
}
}
Ok(None) => {
let _ = import_notifier.successful::<State>();
}
}
}
}

View file

@ -1,19 +1,40 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::{
state::State,
wayland::protocols::drm::{DrmHandler, ImportError},
state::{BackendData, State},
wayland::protocols::drm::{delegate_wl_drm, DrmHandler, ImportError},
};
use smithay::{
backend::{allocator::dmabuf::Dmabuf, drm::DrmNode},
reexports::wayland_server::{protocol::wl_buffer::WlBuffer, Resource},
wayland::dmabuf::DmabufGlobal,
};
use smithay::{backend::allocator::dmabuf::Dmabuf, wayland::dmabuf::DmabufGlobal};
impl DrmHandler for State {
impl DrmHandler<Option<DrmNode>> for State {
fn dmabuf_imported(
&mut self,
global: &DmabufGlobal,
dmabuf: Dmabuf,
) -> Result<(), ImportError> {
) -> Result<Option<DrmNode>, ImportError> {
self.backend
.dmabuf_imported(global, dmabuf)
.dmabuf_imported(None, global, dmabuf)
.map_err(|_| ImportError::Failed)
}
fn buffer_created(&mut self, buffer: WlBuffer, result: Option<DrmNode>) {
if let Some(node) = result {
// kms backend
if let BackendData::Kms(kms_state) = &mut self.backend {
if let Some(device) = kms_state
.devices
.values_mut()
.find(|device| device.render_node == node)
{
device.active_buffers.insert(buffer.downgrade());
}
}
}
}
}
delegate_wl_drm!(State; Option<DrmNode>);

View file

@ -31,7 +31,6 @@ pub mod toplevel_info;
pub mod toplevel_management;
pub mod viewporter;
pub mod virtual_keyboard;
pub mod wl_drm;
pub mod workspace;
pub mod xdg_activation;
pub mod xdg_shell;

View file

@ -180,7 +180,7 @@ impl ScreencopyHandler for State {
.and_then(|client| {
// Lets check the global drm-node the client got either through default-feedback or wl_drm
if let Some(normal_client) = client.get_data::<ClientState>() {
return normal_client.drm_node.clone();
return normal_client.advertised_drm_node.clone();
}
// last but not least all xwayland-surfaces should also share a single node
if let Some(xwayland_client) = client.get_data::<XWaylandClientData>() {
@ -188,7 +188,7 @@ impl ScreencopyHandler for State {
}
None
})
.unwrap_or(kms.primary.clone());
.unwrap_or(kms.primary_node.clone());
_kms_renderer = Some(kms.api.single_renderer(&node).unwrap());
_kms_renderer.as_mut().unwrap().as_mut()
}
@ -456,7 +456,9 @@ fn formats_for_output(
let mut _kms_renderer = None;
let renderer = match backend {
BackendData::Kms(ref mut kms) => {
let node = kms.target_node_for_output(&output).unwrap_or(kms.primary);
let node = kms
.target_node_for_output(&output)
.unwrap_or(kms.primary_node);
_kms_renderer = Some(kms.api.single_renderer(&node).unwrap());
_kms_renderer.as_mut().unwrap().as_mut()
}
@ -530,7 +532,7 @@ fn node_from_params(
BackendData::Kms(kms) => Some(
output
.and_then(|output| kms.target_node_for_output(output))
.unwrap_or(kms.primary),
.unwrap_or(kms.primary_node),
),
_ => None,
},

View file

@ -37,14 +37,14 @@ impl SecurityContextHandler for State {
let drm_node = client_data
.as_ref()
.and_then(|data| data.downcast_ref::<ClientState>())
.and_then(|data| data.drm_node.clone())
.and_then(|data| data.advertised_drm_node.clone())
.or_else(|| {
client_data
.as_ref()
.and_then(|data| data.downcast_ref::<XWaylandClientData>())
.and_then(|data| data.user_data().get::<DrmNode>().cloned())
})
.or_else(|| new_state.drm_node.clone());
.or_else(|| new_state.advertised_drm_node.clone());
if let Err(err) = state.common.display_handle.insert_client(
client_stream,
@ -53,7 +53,7 @@ impl SecurityContextHandler for State {
privileged: privileged
&& security_context.sandbox_engine.as_deref()
== Some("com.system76.CosmicPanel"),
drm_node,
advertised_drm_node: drm_node,
..new_state
}),
) {

View file

@ -1,5 +0,0 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::{state::State, wayland::protocols::drm::delegate_wl_drm};
delegate_wl_drm!(State);