kms: Track used devices and free resources
This commit is contained in:
parent
e74b0dfaaa
commit
ef3486f7e0
14 changed files with 303 additions and 130 deletions
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}),
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -7,6 +7,7 @@
|
|||
// You can use all the types from my_protocol as if they went from `wayland_client::protocol`.
|
||||
pub use generated::wl_drm;
|
||||
|
||||
#[allow(non_snake_case, non_upper_case_globals, non_camel_case_types)]
|
||||
mod generated {
|
||||
use smithay::reexports::wayland_server::{self, protocol::*};
|
||||
|
||||
|
|
@ -43,13 +44,15 @@ pub enum ImportError {
|
|||
InvalidFormat,
|
||||
}
|
||||
|
||||
pub trait DrmHandler {
|
||||
fn dmabuf_imported(&mut self, global: &DmabufGlobal, dmabuf: Dmabuf)
|
||||
-> Result<(), ImportError>;
|
||||
pub trait DrmHandler<R: 'static> {
|
||||
fn dmabuf_imported(&mut self, global: &DmabufGlobal, dmabuf: Dmabuf) -> Result<R, ImportError>;
|
||||
fn buffer_created(&mut self, buffer: WlBuffer, result: R) {
|
||||
let _ = (buffer, result);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WlDrmState;
|
||||
#[derive(Debug, Default)]
|
||||
pub struct WlDrmState<R>(std::marker::PhantomData<R>);
|
||||
|
||||
/// Data associated with a drm global.
|
||||
pub struct DrmGlobalData {
|
||||
|
|
@ -64,13 +67,14 @@ pub struct DrmInstanceData {
|
|||
dmabuf_global: DmabufGlobal,
|
||||
}
|
||||
|
||||
impl<D> GlobalDispatch<wl_drm::WlDrm, DrmGlobalData, D> for WlDrmState
|
||||
impl<D, R> GlobalDispatch<wl_drm::WlDrm, DrmGlobalData, D> for WlDrmState<R>
|
||||
where
|
||||
D: GlobalDispatch<wl_drm::WlDrm, DrmGlobalData>
|
||||
+ Dispatch<wl_drm::WlDrm, DrmInstanceData>
|
||||
+ BufferHandler
|
||||
+ DmabufHandler
|
||||
+ 'static,
|
||||
R: 'static,
|
||||
{
|
||||
fn bind(
|
||||
_state: &mut D,
|
||||
|
|
@ -102,14 +106,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<D> Dispatch<wl_drm::WlDrm, DrmInstanceData, D> for WlDrmState
|
||||
impl<D, R> Dispatch<wl_drm::WlDrm, DrmInstanceData, D> for WlDrmState<R>
|
||||
where
|
||||
D: GlobalDispatch<wl_drm::WlDrm, DrmGlobalData>
|
||||
+ Dispatch<wl_drm::WlDrm, DrmInstanceData>
|
||||
+ Dispatch<WlBuffer, Dmabuf>
|
||||
+ BufferHandler
|
||||
+ DrmHandler
|
||||
+ DrmHandler<R>
|
||||
+ 'static,
|
||||
R: 'static,
|
||||
{
|
||||
fn request(
|
||||
state: &mut D,
|
||||
|
|
@ -178,10 +183,11 @@ where
|
|||
match dma.build() {
|
||||
Some(dmabuf) => {
|
||||
match state.dmabuf_imported(&data.dmabuf_global, dmabuf.clone()) {
|
||||
Ok(()) => {
|
||||
Ok(result) => {
|
||||
// import was successful
|
||||
data_init.init(id, dmabuf);
|
||||
let buffer = data_init.init(id, dmabuf);
|
||||
trace!("Created a new validated dma wl_buffer via wl_drm.");
|
||||
state.buffer_created(buffer, result);
|
||||
}
|
||||
|
||||
Err(ImportError::InvalidFormat) => {
|
||||
|
|
@ -212,7 +218,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl WlDrmState {
|
||||
impl<R: 'static> WlDrmState<R> {
|
||||
pub fn create_global<D>(
|
||||
&mut self,
|
||||
display: &DisplayHandle,
|
||||
|
|
@ -267,13 +273,13 @@ impl WlDrmState {
|
|||
}
|
||||
|
||||
macro_rules! delegate_wl_drm {
|
||||
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => {
|
||||
($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty; $r: ty) => {
|
||||
smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
||||
$crate::wayland::protocols::drm::wl_drm::WlDrm: $crate::wayland::protocols::drm::DrmGlobalData
|
||||
] => $crate::wayland::protocols::drm::WlDrmState);
|
||||
] => $crate::wayland::protocols::drm::WlDrmState<$r>);
|
||||
smithay::reexports::wayland_server::delegate_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [
|
||||
$crate::wayland::protocols::drm::wl_drm::WlDrm: $crate::wayland::protocols::drm::DrmInstanceData
|
||||
] => $crate::wayland::protocols::drm::WlDrmState);
|
||||
] => $crate::wayland::protocols::drm::WlDrmState<$r>);
|
||||
};
|
||||
}
|
||||
pub(crate) use delegate_wl_drm;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue