kms: Change awkward new trait to InnerDevice
This commit is contained in:
parent
87742c1e0c
commit
6492629f90
8 changed files with 274 additions and 251 deletions
|
|
@ -88,62 +88,54 @@ pub type GbmDrmOutputManager = DrmOutputManager<
|
||||||
DrmDeviceFd,
|
DrmDeviceFd,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct Device {
|
pub struct Device {
|
||||||
|
pub inner: InnerDevice,
|
||||||
|
pub drm: GbmDrmOutputManager,
|
||||||
|
|
||||||
|
supports_atomic: bool,
|
||||||
|
event_token: Option<RegistrationToken>,
|
||||||
|
pub socket: Option<Socket>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LockedDevice<'a> {
|
||||||
|
pub inner: &'a mut InnerDevice,
|
||||||
|
pub drm: LockedGbmDrmOutputManager<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct InnerDevice {
|
||||||
pub dev_node: DrmNode,
|
pub dev_node: DrmNode,
|
||||||
pub render_node: DrmNode,
|
pub render_node: DrmNode,
|
||||||
pub egl: Option<EGLInternals>,
|
pub egl: Option<EGLInternals>,
|
||||||
|
|
||||||
pub outputs: HashMap<connector::Handle, Output>,
|
pub outputs: HashMap<connector::Handle, Output>,
|
||||||
pub surfaces: HashMap<crtc::Handle, Surface>,
|
pub surfaces: HashMap<crtc::Handle, Surface>,
|
||||||
pub drm: GbmDrmOutputManager,
|
|
||||||
pub gbm: GbmDevice<DrmDeviceFd>,
|
pub gbm: GbmDevice<DrmDeviceFd>,
|
||||||
|
|
||||||
supports_atomic: bool,
|
|
||||||
|
|
||||||
pub leased_connectors: Vec<(connector::Handle, crtc::Handle)>,
|
pub leased_connectors: Vec<(connector::Handle, crtc::Handle)>,
|
||||||
pub leasing_global: Option<DrmLeaseState>,
|
pub leasing_global: Option<DrmLeaseState>,
|
||||||
pub active_leases: Vec<DrmLease>,
|
pub active_leases: Vec<DrmLease>,
|
||||||
pub active_buffers: HashSet<Weak<WlBuffer>>,
|
pub active_buffers: HashSet<Weak<WlBuffer>>,
|
||||||
|
|
||||||
event_token: Option<RegistrationToken>,
|
|
||||||
pub socket: Option<Socket>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Device {
|
impl fmt::Debug for InnerDevice {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
f.debug_struct("Device")
|
f.debug_struct("Device")
|
||||||
.field("dev_node", &self.render_node)
|
.field("dev_node", &self.dev_node)
|
||||||
.field("render_node", &self.render_node)
|
.field("render_node", &self.render_node)
|
||||||
|
.field("egl", &self.egl)
|
||||||
.field("outputs", &self.outputs)
|
.field("outputs", &self.outputs)
|
||||||
.field("surfaces", &self.surfaces)
|
.field("surfaces", &self.surfaces)
|
||||||
.field("drm", &"..")
|
.field("gbm", &"..")
|
||||||
.field("egl", &self.egl)
|
|
||||||
.field("supports_atomic", &self.supports_atomic)
|
|
||||||
.field("leased_connectors", &self.leased_connectors)
|
.field("leased_connectors", &self.leased_connectors)
|
||||||
.field("leasing_global", &self.leasing_global)
|
.field("leasing_global", &self.leasing_global)
|
||||||
.field("active_leases", &self.active_leases)
|
.field("active_leases", &self.active_leases)
|
||||||
.field("event_token", &self.event_token)
|
.field("active_buffers", &self.active_buffers.len())
|
||||||
.field("socket", &self.socket)
|
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct LockedDevice<'a> {
|
|
||||||
pub dev_node: &'a DrmNode,
|
|
||||||
pub render_node: &'a DrmNode,
|
|
||||||
pub egl: &'a mut Option<EGLInternals>,
|
|
||||||
|
|
||||||
pub outputs: &'a HashMap<connector::Handle, Output>,
|
|
||||||
pub surfaces: &'a mut HashMap<crtc::Handle, Surface>,
|
|
||||||
pub drm: LockedGbmDrmOutputManager<'a>,
|
|
||||||
pub gbm: &'a GbmDevice<DrmDeviceFd>,
|
|
||||||
|
|
||||||
pub leased_connectors: &'a mut Vec<(connector::Handle, crtc::Handle)>,
|
|
||||||
pub leasing_global: &'a mut Option<DrmLeaseState>,
|
|
||||||
pub active_leases: &'a mut Vec<DrmLease>,
|
|
||||||
pub active_buffers: &'a HashSet<Weak<WlBuffer>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_egl(gbm: &GbmDevice<DrmDeviceFd>) -> Result<EGLInternals> {
|
pub fn init_egl(gbm: &GbmDevice<DrmDeviceFd>) -> Result<EGLInternals> {
|
||||||
let path = gbm.dev_path();
|
let path = gbm.dev_path();
|
||||||
|
|
||||||
|
|
@ -268,7 +260,7 @@ impl State {
|
||||||
move |event, metadata, state: &mut State| match event {
|
move |event, metadata, state: &mut State| match event {
|
||||||
DrmEvent::VBlank(crtc) => {
|
DrmEvent::VBlank(crtc) => {
|
||||||
if let Some(device) = state.backend.kms().drm_devices.get_mut(&drm_node) {
|
if let Some(device) = state.backend.kms().drm_devices.get_mut(&drm_node) {
|
||||||
if let Some(surface) = device.surfaces.get_mut(&crtc) {
|
if let Some(surface) = device.inner.surfaces.get_mut(&crtc) {
|
||||||
surface.on_vblank(metadata.take());
|
surface.on_vblank(metadata.take());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -309,31 +301,32 @@ impl State {
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut device = Device {
|
let mut device = Device {
|
||||||
dev_node: drm_node,
|
|
||||||
render_node,
|
|
||||||
egl: None,
|
|
||||||
|
|
||||||
outputs: HashMap::new(),
|
|
||||||
surfaces: HashMap::new(),
|
|
||||||
drm,
|
drm,
|
||||||
gbm,
|
inner: InnerDevice {
|
||||||
|
dev_node: drm_node,
|
||||||
|
render_node,
|
||||||
|
egl: None,
|
||||||
|
|
||||||
|
outputs: HashMap::new(),
|
||||||
|
surfaces: HashMap::new(),
|
||||||
|
gbm,
|
||||||
|
|
||||||
|
leased_connectors: Vec::new(),
|
||||||
|
leasing_global: DrmLeaseState::new::<State>(dh, &drm_node)
|
||||||
|
.map_err(|err| {
|
||||||
|
// TODO: replace with inspect_err, once stable
|
||||||
|
warn!(
|
||||||
|
?err,
|
||||||
|
"Failed to initialize drm lease global for: {}", drm_node
|
||||||
|
);
|
||||||
|
err
|
||||||
|
})
|
||||||
|
.ok(),
|
||||||
|
active_leases: Vec::new(),
|
||||||
|
active_buffers: HashSet::new(),
|
||||||
|
},
|
||||||
|
|
||||||
supports_atomic,
|
supports_atomic,
|
||||||
|
|
||||||
leased_connectors: Vec::new(),
|
|
||||||
leasing_global: DrmLeaseState::new::<State>(dh, &drm_node)
|
|
||||||
.map_err(|err| {
|
|
||||||
// TODO: replace with inspect_err, once stable
|
|
||||||
warn!(
|
|
||||||
?err,
|
|
||||||
"Failed to initialize drm lease global for: {}", drm_node
|
|
||||||
);
|
|
||||||
err
|
|
||||||
})
|
|
||||||
.ok(),
|
|
||||||
active_leases: Vec::new(),
|
|
||||||
active_buffers: HashSet::new(),
|
|
||||||
|
|
||||||
event_token: Some(token),
|
event_token: Some(token),
|
||||||
socket,
|
socket,
|
||||||
};
|
};
|
||||||
|
|
@ -344,7 +337,8 @@ impl State {
|
||||||
|
|
||||||
{
|
{
|
||||||
for (conn, maybe_crtc) in connectors {
|
for (conn, maybe_crtc) in connectors {
|
||||||
match device.connector_added(
|
match device.inner.connector_added(
|
||||||
|
device.drm.device_mut(),
|
||||||
self.backend.kms().primary_node.clone(),
|
self.backend.kms().primary_node.clone(),
|
||||||
conn,
|
conn,
|
||||||
maybe_crtc,
|
maybe_crtc,
|
||||||
|
|
@ -359,7 +353,7 @@ impl State {
|
||||||
w += output.geometry().size.w as u32;
|
w += output.geometry().size.w as u32;
|
||||||
wl_outputs.push(output.clone());
|
wl_outputs.push(output.clone());
|
||||||
}
|
}
|
||||||
device.outputs.insert(conn, output);
|
device.inner.outputs.insert(conn, output);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(?err, "Failed to initialize output, skipping");
|
warn!(?err, "Failed to initialize output, skipping");
|
||||||
|
|
@ -411,26 +405,29 @@ impl State {
|
||||||
for conn in changes.removed {
|
for conn in changes.removed {
|
||||||
// contains conns with updated crtcs, just drop the surface and re-create
|
// contains conns with updated crtcs, just drop the surface and re-create
|
||||||
if let Some(pos) = device
|
if let Some(pos) = device
|
||||||
|
.inner
|
||||||
.leased_connectors
|
.leased_connectors
|
||||||
.iter()
|
.iter()
|
||||||
.position(|(handle, _)| *handle == conn)
|
.position(|(handle, _)| *handle == conn)
|
||||||
{
|
{
|
||||||
let _ = device.leased_connectors.remove(pos);
|
let _ = device.inner.leased_connectors.remove(pos);
|
||||||
if let Some(leasing_state) = device.leasing_global.as_mut() {
|
if let Some(leasing_state) = device.inner.leasing_global.as_mut() {
|
||||||
leasing_state.withdraw_connector(conn);
|
leasing_state.withdraw_connector(conn);
|
||||||
}
|
}
|
||||||
} else if let Some(crtc) = device
|
} else if let Some(crtc) = device
|
||||||
|
.inner
|
||||||
.surfaces
|
.surfaces
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(crtc, surface)| (surface.connector == conn).then_some(crtc))
|
.find_map(|(crtc, surface)| (surface.connector == conn).then_some(crtc))
|
||||||
.cloned()
|
.cloned()
|
||||||
{
|
{
|
||||||
device.surfaces.remove(&crtc).unwrap();
|
device.inner.surfaces.remove(&crtc).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if !changes.added.iter().any(|(c, _)| c == &conn) {
|
if !changes.added.iter().any(|(c, _)| c == &conn) {
|
||||||
outputs_removed.push(
|
outputs_removed.push(
|
||||||
device
|
device
|
||||||
|
.inner
|
||||||
.outputs
|
.outputs
|
||||||
.remove(&conn)
|
.remove(&conn)
|
||||||
.expect("Connector without output?"),
|
.expect("Connector without output?"),
|
||||||
|
|
@ -439,7 +436,8 @@ impl State {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (conn, maybe_crtc) in changes.added {
|
for (conn, maybe_crtc) in changes.added {
|
||||||
match device.connector_added(
|
match device.inner.connector_added(
|
||||||
|
device.drm.device_mut(),
|
||||||
backend.primary_node.clone(),
|
backend.primary_node.clone(),
|
||||||
conn,
|
conn,
|
||||||
maybe_crtc,
|
maybe_crtc,
|
||||||
|
|
@ -455,7 +453,7 @@ impl State {
|
||||||
outputs_added.push(output.clone());
|
outputs_added.push(output.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
device.outputs.insert(conn, output);
|
device.inner.outputs.insert(conn, output);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(?err, "Failed to initialize output, skipping");
|
warn!(?err, "Failed to initialize output, skipping");
|
||||||
|
|
@ -502,15 +500,17 @@ impl State {
|
||||||
let drm_node = backend
|
let drm_node = backend
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values()
|
.values()
|
||||||
.find_map(|device| (device.dev_node.dev_id() == dev).then_some(device.dev_node))
|
.find_map(|device| {
|
||||||
|
(device.inner.dev_node.dev_id() == dev).then_some(device.inner.dev_node)
|
||||||
|
})
|
||||||
.with_context(|| format!("Couldn't find drm node for {}", dev))?;
|
.with_context(|| format!("Couldn't find drm node for {}", dev))?;
|
||||||
|
|
||||||
let mut outputs_removed = Vec::new();
|
let mut outputs_removed = Vec::new();
|
||||||
if let Some(mut device) = backend.drm_devices.shift_remove(&drm_node) {
|
if let Some(mut device) = backend.drm_devices.shift_remove(&drm_node) {
|
||||||
if let Some(mut leasing_global) = device.leasing_global.take() {
|
if let Some(mut leasing_global) = device.inner.leasing_global.take() {
|
||||||
leasing_global.disable_global::<State>();
|
leasing_global.disable_global::<State>();
|
||||||
}
|
}
|
||||||
for surface in device.surfaces.values_mut() {
|
for surface in device.inner.surfaces.values_mut() {
|
||||||
outputs_removed.push(surface.output.clone());
|
outputs_removed.push(surface.output.clone());
|
||||||
}
|
}
|
||||||
if let Some(token) = device.event_token.take() {
|
if let Some(token) = device.event_token.take() {
|
||||||
|
|
@ -523,12 +523,12 @@ impl State {
|
||||||
.destroy_global::<State>(dh, socket.dmabuf_global);
|
.destroy_global::<State>(dh, socket.dmabuf_global);
|
||||||
dh.remove_global::<State>(socket.drm_global);
|
dh.remove_global::<State>(socket.drm_global);
|
||||||
}
|
}
|
||||||
backend.api.as_mut().remove_node(&device.render_node);
|
backend.api.as_mut().remove_node(&device.inner.render_node);
|
||||||
backend
|
backend
|
||||||
.primary_node
|
.primary_node
|
||||||
.write()
|
.write()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.take_if(|node| node == &device.render_node);
|
.take_if(|node| node == &device.inner.render_node);
|
||||||
};
|
};
|
||||||
self.common
|
self.common
|
||||||
.output_configuration_state
|
.output_configuration_state
|
||||||
|
|
@ -570,11 +570,13 @@ impl Device {
|
||||||
drm_helpers::display_configuration(self.drm.device_mut(), self.supports_atomic)?;
|
drm_helpers::display_configuration(self.drm.device_mut(), self.supports_atomic)?;
|
||||||
|
|
||||||
let surfaces = self
|
let surfaces = self
|
||||||
|
.inner
|
||||||
.surfaces
|
.surfaces
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(c, s)| (s.connector, *c))
|
.map(|(c, s)| (s.connector, *c))
|
||||||
.chain(
|
.chain(
|
||||||
self.leased_connectors
|
self.inner
|
||||||
|
.leased_connectors
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(conn, crtc)| (*conn, *crtc)),
|
.map(|(conn, crtc)| (*conn, *crtc)),
|
||||||
)
|
)
|
||||||
|
|
@ -591,6 +593,7 @@ impl Device {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let removed = self
|
let removed = self
|
||||||
|
.inner
|
||||||
.outputs
|
.outputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(conn, _)| match config.get(conn) {
|
.filter(|(conn, _)| match config.get(conn) {
|
||||||
|
|
@ -605,17 +608,8 @@ impl Device {
|
||||||
|
|
||||||
pub fn lock(&mut self) -> LockedDevice<'_> {
|
pub fn lock(&mut self) -> LockedDevice<'_> {
|
||||||
LockedDevice {
|
LockedDevice {
|
||||||
dev_node: &self.dev_node,
|
inner: &mut self.inner,
|
||||||
render_node: &self.render_node,
|
|
||||||
egl: &mut self.egl,
|
|
||||||
outputs: &self.outputs,
|
|
||||||
surfaces: &mut self.surfaces,
|
|
||||||
drm: self.drm.lock(),
|
drm: self.drm.lock(),
|
||||||
gbm: &self.gbm,
|
|
||||||
leased_connectors: &mut self.leased_connectors,
|
|
||||||
leasing_global: &mut self.leasing_global,
|
|
||||||
active_leases: &mut self.active_leases,
|
|
||||||
active_buffers: &mut self.active_buffers,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -629,13 +623,14 @@ impl<'a> LockedDevice<'a> {
|
||||||
clock: &Clock<Monotonic>,
|
clock: &Clock<Monotonic>,
|
||||||
shell: &Arc<parking_lot::RwLock<Shell>>,
|
shell: &Arc<parking_lot::RwLock<Shell>>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
for surface in self.surfaces.values_mut() {
|
for surface in self.inner.surfaces.values_mut() {
|
||||||
surface.allow_frame_flags(flag, flags);
|
surface.allow_frame_flags(flag, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !flag {
|
if !flag {
|
||||||
let now = clock.now();
|
let now = clock.now();
|
||||||
let output_map = self
|
let output_map = self
|
||||||
|
.inner
|
||||||
.surfaces
|
.surfaces
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, s)| s.is_active())
|
.filter(|(_, s)| s.is_active())
|
||||||
|
|
@ -645,7 +640,7 @@ impl<'a> LockedDevice<'a> {
|
||||||
for (crtc, compositor) in self.drm.compositors().iter() {
|
for (crtc, compositor) in self.drm.compositors().iter() {
|
||||||
let elements = match output_map.get(crtc) {
|
let elements = match output_map.get(crtc) {
|
||||||
Some(output) => output_elements(
|
Some(output) => output_elements(
|
||||||
Some(&self.render_node),
|
Some(&self.inner.render_node),
|
||||||
renderer,
|
renderer,
|
||||||
shell,
|
shell,
|
||||||
now,
|
now,
|
||||||
|
|
@ -702,7 +697,7 @@ impl<'a> LockedDevice<'a> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for (crtc, comp) in self.drm.compositors() {
|
for (crtc, comp) in self.drm.compositors() {
|
||||||
let Some(surface) = self.surfaces.get_mut(crtc) else {
|
let Some(surface) = self.inner.surfaces.get_mut(crtc) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let comp = comp.lock().unwrap();
|
let comp = comp.lock().unwrap();
|
||||||
|
|
@ -725,25 +720,16 @@ impl<'a> LockedDevice<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait MaybeLockedDevice {
|
impl InnerDevice {
|
||||||
fn dev_node(&self) -> DrmNode;
|
pub fn in_use(&self, primary: Option<&DrmNode>) -> bool {
|
||||||
fn render_node(&self) -> DrmNode;
|
Some(&self.render_node) == primary
|
||||||
fn output(&self, conn: &connector::Handle) -> Option<&Output>;
|
|| !self.surfaces.is_empty()
|
||||||
fn drm_device_mut(&mut self) -> &mut DrmDevice;
|
|| !self.active_buffers.is_empty()
|
||||||
fn gbm(&self) -> &GbmDevice<DrmDeviceFd>;
|
}
|
||||||
fn egl(&mut self) -> &mut Option<EGLInternals>;
|
|
||||||
fn insert_surface(&mut self, crtc: crtc::Handle, surface: Surface);
|
|
||||||
|
|
||||||
fn in_use(&self, primary: Option<&DrmNode>) -> bool;
|
pub fn connector_added(
|
||||||
fn add_leased_connector(
|
|
||||||
&mut self,
|
|
||||||
crtc: crtc::Handle,
|
|
||||||
conn: connector::Handle,
|
|
||||||
output: &Output,
|
|
||||||
);
|
|
||||||
|
|
||||||
fn connector_added(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
|
drm: &mut DrmDevice,
|
||||||
primary_node: Arc<RwLock<Option<DrmNode>>>,
|
primary_node: Arc<RwLock<Option<DrmNode>>>,
|
||||||
conn: connector::Handle,
|
conn: connector::Handle,
|
||||||
maybe_crtc: Option<crtc::Handle>,
|
maybe_crtc: Option<crtc::Handle>,
|
||||||
|
|
@ -754,27 +740,39 @@ pub trait MaybeLockedDevice {
|
||||||
startup_done: Arc<AtomicBool>,
|
startup_done: Arc<AtomicBool>,
|
||||||
) -> Result<(Output, bool)> {
|
) -> Result<(Output, bool)> {
|
||||||
let output = self
|
let output = self
|
||||||
.output(&conn)
|
.outputs
|
||||||
|
.get(&conn)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(|output| Ok(output))
|
.map(|output| Ok(output))
|
||||||
.unwrap_or_else(|| create_output_for_conn(self.drm_device_mut(), conn))
|
.unwrap_or_else(|| create_output_for_conn(drm, conn))
|
||||||
.context("Failed to create `Output`")?;
|
.context("Failed to create `Output`")?;
|
||||||
|
|
||||||
let non_desktop =
|
let non_desktop = match drm_helpers::get_property_val(drm, conn, "non-desktop") {
|
||||||
match drm_helpers::get_property_val(self.drm_device_mut(), conn, "non-desktop") {
|
Ok((val_type, value)) => val_type.convert_value(value).as_boolean().unwrap(),
|
||||||
Ok((val_type, value)) => val_type.convert_value(value).as_boolean().unwrap(),
|
Err(err) => {
|
||||||
Err(err) => {
|
warn!(
|
||||||
warn!(
|
?err,
|
||||||
?err,
|
"Failed to determine if connector is meant desktop usage, assuming so."
|
||||||
"Failed to determine if connector is meant desktop usage, assuming so."
|
);
|
||||||
);
|
false
|
||||||
false
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
if non_desktop {
|
if non_desktop {
|
||||||
if let Some(crtc) = maybe_crtc {
|
if let Some(crtc) = maybe_crtc {
|
||||||
self.add_leased_connector(crtc, conn, &output);
|
self.leased_connectors.push((conn, crtc));
|
||||||
|
info!(
|
||||||
|
"Connector {} is non-desktop, setting up for leasing",
|
||||||
|
output.name()
|
||||||
|
);
|
||||||
|
if let Some(lease_state) = self.leasing_global.as_mut() {
|
||||||
|
let physical = output.physical_properties();
|
||||||
|
lease_state.add_connector::<State>(
|
||||||
|
conn,
|
||||||
|
output.name(),
|
||||||
|
format!("{} {}", physical.make, physical.model),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!(
|
warn!(
|
||||||
"Connector {} is non-desktop, but we don't have a free crtc: not leasing",
|
"Connector {} is non-desktop, but we don't have a free crtc: not leasing",
|
||||||
|
|
@ -788,7 +786,7 @@ pub trait MaybeLockedDevice {
|
||||||
.user_data()
|
.user_data()
|
||||||
.insert_if_missing(|| RefCell::new(OutputConfig::default()));
|
.insert_if_missing(|| RefCell::new(OutputConfig::default()));
|
||||||
|
|
||||||
populate_modes(self.drm_device_mut(), &output, conn, position)
|
populate_modes(drm, &output, conn, position)
|
||||||
.with_context(|| "Failed to enumerate connector modes")?;
|
.with_context(|| "Failed to enumerate connector modes")?;
|
||||||
|
|
||||||
let has_surface = if let Some(crtc) = maybe_crtc {
|
let has_surface = if let Some(crtc) = maybe_crtc {
|
||||||
|
|
@ -797,15 +795,15 @@ pub trait MaybeLockedDevice {
|
||||||
crtc,
|
crtc,
|
||||||
conn,
|
conn,
|
||||||
primary_node,
|
primary_node,
|
||||||
self.dev_node(),
|
self.dev_node,
|
||||||
self.render_node(),
|
self.render_node,
|
||||||
evlh,
|
evlh,
|
||||||
screen_filter,
|
screen_filter,
|
||||||
shell,
|
shell,
|
||||||
startup_done,
|
startup_done,
|
||||||
) {
|
) {
|
||||||
Ok(data) => {
|
Ok(data) => {
|
||||||
self.insert_surface(crtc, data);
|
self.surfaces.insert(crtc, data);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
@ -830,14 +828,14 @@ pub trait MaybeLockedDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_egl(
|
pub fn update_egl(
|
||||||
&mut self,
|
&mut self,
|
||||||
primary_node: Option<&DrmNode>,
|
primary_node: Option<&DrmNode>,
|
||||||
api: &mut GbmGlowBackend<DrmDeviceFd>,
|
api: &mut GbmGlowBackend<DrmDeviceFd>,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
if self.in_use(primary_node) {
|
if self.in_use(primary_node) {
|
||||||
if self.egl().is_none() {
|
if self.egl.is_none() {
|
||||||
let egl = init_egl(self.gbm()).context("Failed to create EGL context")?;
|
let egl = init_egl(&self.gbm).context("Failed to create EGL context")?;
|
||||||
let mut renderer = unsafe {
|
let mut renderer = unsafe {
|
||||||
GlowRenderer::new(
|
GlowRenderer::new(
|
||||||
EGLContext::new_shared_with_priority(
|
EGLContext::new_shared_with_priority(
|
||||||
|
|
@ -851,96 +849,34 @@ pub trait MaybeLockedDevice {
|
||||||
};
|
};
|
||||||
init_shaders(renderer.borrow_mut()).context("Failed to compile shaders")?;
|
init_shaders(renderer.borrow_mut()).context("Failed to compile shaders")?;
|
||||||
api.add_node(
|
api.add_node(
|
||||||
self.render_node(),
|
self.render_node,
|
||||||
GbmAllocator::new(
|
GbmAllocator::new(
|
||||||
self.gbm().clone(),
|
self.gbm.clone(),
|
||||||
// SCANOUT because stride bugs
|
// SCANOUT because stride bugs
|
||||||
GbmBufferFlags::RENDERING | GbmBufferFlags::SCANOUT,
|
GbmBufferFlags::RENDERING | GbmBufferFlags::SCANOUT,
|
||||||
),
|
),
|
||||||
renderer,
|
renderer,
|
||||||
);
|
);
|
||||||
*self.egl() = Some(egl);
|
self.egl = Some(egl);
|
||||||
}
|
}
|
||||||
Ok(true)
|
Ok(true)
|
||||||
} else {
|
} else {
|
||||||
if self.egl().is_some() {
|
if self.egl.is_some() {
|
||||||
let _ = self.egl().take();
|
let _ = self.egl.take();
|
||||||
api.remove_node(&self.render_node());
|
api.remove_node(&self.render_node);
|
||||||
}
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_surface_nodes<'b>(
|
pub fn update_surface_nodes<'b>(
|
||||||
&mut self,
|
&mut self,
|
||||||
used_devices: &HashSet<DrmNode>,
|
used_devices: &HashSet<DrmNode>,
|
||||||
others: impl Iterator<Item = &'b Self>,
|
mut others: impl Iterator<Item = &'b Self>,
|
||||||
) -> Result<()>
|
) -> Result<()>
|
||||||
where
|
where
|
||||||
Self: 'b;
|
Self: 'b,
|
||||||
}
|
{
|
||||||
|
|
||||||
impl MaybeLockedDevice for Device {
|
|
||||||
fn dev_node(&self) -> DrmNode {
|
|
||||||
self.dev_node
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render_node(&self) -> DrmNode {
|
|
||||||
self.render_node
|
|
||||||
}
|
|
||||||
|
|
||||||
fn output(&self, conn: &connector::Handle) -> Option<&Output> {
|
|
||||||
self.outputs.get(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn drm_device_mut(&mut self) -> &mut DrmDevice {
|
|
||||||
self.drm.device_mut()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gbm(&self) -> &GbmDevice<DrmDeviceFd> {
|
|
||||||
&self.gbm
|
|
||||||
}
|
|
||||||
|
|
||||||
fn egl(&mut self) -> &mut Option<EGLInternals> {
|
|
||||||
&mut self.egl
|
|
||||||
}
|
|
||||||
|
|
||||||
fn insert_surface(&mut self, crtc: crtc::Handle, surface: Surface) {
|
|
||||||
self.surfaces.insert(crtc, surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn in_use(&self, primary: Option<&DrmNode>) -> bool {
|
|
||||||
Some(&self.render_node) == primary
|
|
||||||
|| !self.surfaces.is_empty()
|
|
||||||
|| !self.active_buffers.is_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_leased_connector(
|
|
||||||
&mut self,
|
|
||||||
crtc: crtc::Handle,
|
|
||||||
conn: connector::Handle,
|
|
||||||
output: &Output,
|
|
||||||
) {
|
|
||||||
self.leased_connectors.push((conn, crtc));
|
|
||||||
info!(
|
|
||||||
"Connector {} is non-desktop, setting up for leasing",
|
|
||||||
output.name()
|
|
||||||
);
|
|
||||||
if let Some(lease_state) = self.leasing_global.as_mut() {
|
|
||||||
let physical = output.physical_properties();
|
|
||||||
lease_state.add_connector::<State>(
|
|
||||||
conn,
|
|
||||||
output.name(),
|
|
||||||
format!("{} {}", physical.make, physical.model),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_surface_nodes<'b>(
|
|
||||||
&mut self,
|
|
||||||
used_devices: &HashSet<DrmNode>,
|
|
||||||
mut others: impl Iterator<Item = &'b Device>,
|
|
||||||
) -> Result<()> {
|
|
||||||
for surface in self.surfaces.values_mut() {
|
for surface in self.surfaces.values_mut() {
|
||||||
let known_nodes = surface.known_nodes().clone();
|
let known_nodes = surface.known_nodes().clone();
|
||||||
for gone_device in known_nodes.difference(&used_devices) {
|
for gone_device in known_nodes.difference(&used_devices) {
|
||||||
|
|
@ -980,7 +916,59 @@ impl MaybeLockedDevice for Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MaybeLockedDevice for LockedDevice<'a> {
|
impl Device {
|
||||||
|
/*
|
||||||
|
fn dev_node(&self) -> DrmNode {
|
||||||
|
self.dev_node
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_node(&self) -> DrmNode {
|
||||||
|
self.render_node
|
||||||
|
}
|
||||||
|
|
||||||
|
fn output(&self, conn: &connector::Handle) -> Option<&Output> {
|
||||||
|
self.outputs.get(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn drm_device_mut(&mut self) -> &mut DrmDevice {
|
||||||
|
self.drm.device_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn gbm(&self) -> &GbmDevice<DrmDeviceFd> {
|
||||||
|
&self.gbm
|
||||||
|
}
|
||||||
|
|
||||||
|
fn egl(&mut self) -> &mut Option<EGLInternals> {
|
||||||
|
&mut self.egl
|
||||||
|
}
|
||||||
|
|
||||||
|
fn insert_surface(&mut self, crtc: crtc::Handle, surface: Surface) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn in_use(&self, primary: Option<&DrmNode>) -> bool {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_leased_connector(
|
||||||
|
&mut self,
|
||||||
|
crtc: crtc::Handle,
|
||||||
|
conn: connector::Handle,
|
||||||
|
output: &Output,
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_surface_nodes<'b>(
|
||||||
|
&mut self,
|
||||||
|
used_devices: &HashSet<DrmNode>,
|
||||||
|
mut others: impl Iterator<Item = &'b Device>,
|
||||||
|
) -> Result<()> {
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> LockedDevice<'a> {
|
||||||
|
/*
|
||||||
fn dev_node(&self) -> DrmNode {
|
fn dev_node(&self) -> DrmNode {
|
||||||
*self.dev_node
|
*self.dev_node
|
||||||
}
|
}
|
||||||
|
|
@ -1081,6 +1069,7 @@ impl<'a> MaybeLockedDevice for LockedDevice<'a> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_output_for_conn(drm: &mut DrmDevice, conn: connector::Handle) -> Result<Output> {
|
fn create_output_for_conn(drm: &mut DrmDevice, conn: connector::Handle) -> Result<Output> {
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,10 @@ mod drm_helpers;
|
||||||
pub mod render;
|
pub mod render;
|
||||||
mod socket;
|
mod socket;
|
||||||
mod surface;
|
mod surface;
|
||||||
|
use device::*;
|
||||||
pub(crate) use surface::Surface;
|
pub(crate) use surface::Surface;
|
||||||
pub use surface::Timings;
|
pub use surface::Timings;
|
||||||
|
|
||||||
pub use device::MaybeLockedDevice;
|
|
||||||
use device::*;
|
|
||||||
|
|
||||||
use super::render::{output_elements, CursorMode, CLEAR_COLOR};
|
use super::render::{output_elements, CursorMode, CLEAR_COLOR};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -203,17 +201,18 @@ fn determine_primary_gpu(
|
||||||
seat: String,
|
seat: String,
|
||||||
) -> Result<Option<DrmNode>> {
|
) -> Result<Option<DrmNode>> {
|
||||||
if let Some(device) = dev_var("COSMIC_RENDER_DEVICE") {
|
if let Some(device) = dev_var("COSMIC_RENDER_DEVICE") {
|
||||||
if let Some(node) = drm_devices
|
if let Some(node) = drm_devices.values().find_map(|dev| {
|
||||||
.values()
|
device
|
||||||
.find_map(|dev| device.matches(&dev.render_node).then_some(dev.render_node))
|
.matches(&dev.inner.render_node)
|
||||||
{
|
.then_some(dev.inner.render_node)
|
||||||
|
}) {
|
||||||
return Ok(Some(node));
|
return Ok(Some(node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to find builtin display
|
// try to find builtin display
|
||||||
for dev in drm_devices.values() {
|
for dev in drm_devices.values() {
|
||||||
if dev.surfaces.values().any(|s| {
|
if dev.inner.surfaces.values().any(|s| {
|
||||||
if let Some(conn_info) = dev.drm.device().get_connector(s.connector, false).ok() {
|
if let Some(conn_info) = dev.drm.device().get_connector(s.connector, false).ok() {
|
||||||
let i = conn_info.interface();
|
let i = conn_info.interface();
|
||||||
i == Interface::EmbeddedDisplayPort || i == Interface::LVDS || i == Interface::DSI
|
i == Interface::EmbeddedDisplayPort || i == Interface::LVDS || i == Interface::DSI
|
||||||
|
|
@ -221,20 +220,23 @@ fn determine_primary_gpu(
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
return Ok(Some(dev.render_node));
|
return Ok(Some(dev.inner.render_node));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// else try to find the boot gpu
|
// else try to find the boot gpu
|
||||||
let boot = determine_boot_gpu(seat);
|
let boot = determine_boot_gpu(seat);
|
||||||
if let Some(boot) = boot {
|
if let Some(boot) = boot {
|
||||||
if drm_devices.values().any(|dev| dev.render_node == boot) {
|
if drm_devices
|
||||||
|
.values()
|
||||||
|
.any(|dev| dev.inner.render_node == boot)
|
||||||
|
{
|
||||||
return Ok(Some(boot));
|
return Ok(Some(boot));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// else just take the first
|
// else just take the first
|
||||||
Ok(drm_devices.values().next().map(|dev| dev.render_node))
|
Ok(drm_devices.values().next().map(|dev| dev.inner.render_node))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create `GlowRenderer` for `EGL_MESA_device_software` device, if present
|
/// Create `GlowRenderer` for `EGL_MESA_device_software` device, if present
|
||||||
|
|
@ -316,7 +318,7 @@ impl State {
|
||||||
if let Err(err) = device.drm.lock().activate(true) {
|
if let Err(err) = device.drm.lock().activate(true) {
|
||||||
error!(?err, "Failed to resume drm device");
|
error!(?err, "Failed to resume drm device");
|
||||||
}
|
}
|
||||||
if let Some(lease_state) = device.leasing_global.as_mut() {
|
if let Some(lease_state) = device.inner.leasing_global.as_mut() {
|
||||||
lease_state.resume::<State>();
|
lease_state.resume::<State>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -367,10 +369,10 @@ impl State {
|
||||||
backend.libinput.suspend();
|
backend.libinput.suspend();
|
||||||
for device in backend.drm_devices.values_mut() {
|
for device in backend.drm_devices.values_mut() {
|
||||||
device.drm.pause();
|
device.drm.pause();
|
||||||
if let Some(lease_state) = device.leasing_global.as_mut() {
|
if let Some(lease_state) = device.inner.leasing_global.as_mut() {
|
||||||
lease_state.suspend();
|
lease_state.suspend();
|
||||||
}
|
}
|
||||||
for surface in device.surfaces.values_mut() {
|
for surface in device.inner.surfaces.values_mut() {
|
||||||
surface.suspend();
|
surface.suspend();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -451,12 +453,16 @@ impl KmsState {
|
||||||
let mut last_err = anyhow::anyhow!("Dmabuf cannot be imported on any gpu");
|
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()) {
|
for device in expected_node.into_iter().chain(other_nodes.into_iter()) {
|
||||||
let mut _egl = None;
|
let mut _egl = None;
|
||||||
let egl_display = if let Some(egl_display) =
|
let egl_display = if let Some(egl_display) = device
|
||||||
device.egl.as_ref().map(|internals| &internals.display)
|
.inner
|
||||||
|
.egl
|
||||||
|
.as_ref()
|
||||||
|
.map(|internals| &internals.display)
|
||||||
{
|
{
|
||||||
egl_display
|
egl_display
|
||||||
} else {
|
} else {
|
||||||
_egl = Some(init_egl(&device.gbm).context("Failed to initialize egl context")?);
|
_egl =
|
||||||
|
Some(init_egl(&device.inner.gbm).context("Failed to initialize egl context")?);
|
||||||
&_egl.as_ref().unwrap().display
|
&_egl.as_ref().unwrap().display
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -466,7 +472,7 @@ impl KmsState {
|
||||||
{
|
{
|
||||||
trace!(
|
trace!(
|
||||||
"Skipping import of dmabuf on {:?}: unsupported format",
|
"Skipping import of dmabuf on {:?}: unsupported format",
|
||||||
device.render_node
|
device.inner.render_node
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -480,7 +486,7 @@ impl KmsState {
|
||||||
image,
|
image,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
device.render_node
|
device.inner.render_node
|
||||||
})
|
})
|
||||||
.map_err(Into::into);
|
.map_err(Into::into);
|
||||||
|
|
||||||
|
|
@ -490,7 +496,11 @@ impl KmsState {
|
||||||
return Ok(node);
|
return Ok(node);
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
trace!(?err, "Failed to import dmabuf on {:?}", device.render_node);
|
trace!(
|
||||||
|
?err,
|
||||||
|
"Failed to import dmabuf on {:?}",
|
||||||
|
device.inner.render_node
|
||||||
|
);
|
||||||
last_err = err;
|
last_err = err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -503,7 +513,7 @@ impl KmsState {
|
||||||
for surface in self
|
for surface in self
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values()
|
.values()
|
||||||
.flat_map(|d| d.surfaces.values())
|
.flat_map(|d| d.inner.surfaces.values())
|
||||||
.filter(|s| s.output == *output || s.output.mirroring().is_some_and(|o| &o == output))
|
.filter(|s| s.output == *output || s.output.mirroring().is_some_and(|o| &o == output))
|
||||||
{
|
{
|
||||||
surface.schedule_render();
|
surface.schedule_render();
|
||||||
|
|
@ -513,14 +523,14 @@ impl KmsState {
|
||||||
pub fn target_node_for_output(&self, output: &Output) -> Option<DrmNode> {
|
pub fn target_node_for_output(&self, output: &Output) -> Option<DrmNode> {
|
||||||
self.drm_devices
|
self.drm_devices
|
||||||
.values()
|
.values()
|
||||||
.find(|dev| dev.surfaces.values().any(|s| s.output == *output))
|
.find(|dev| dev.inner.surfaces.values().any(|s| s.output == *output))
|
||||||
.map(|dev| &dev.render_node)
|
.map(|dev| &dev.inner.render_node)
|
||||||
.copied()
|
.copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_screen_filter(&mut self, screen_filter: &ScreenFilter) -> Result<()> {
|
pub fn update_screen_filter(&mut self, screen_filter: &ScreenFilter) -> Result<()> {
|
||||||
for device in self.drm_devices.values_mut() {
|
for device in self.drm_devices.values_mut() {
|
||||||
for surface in device.surfaces.values_mut() {
|
for surface in device.inner.surfaces.values_mut() {
|
||||||
surface.set_screen_filter(screen_filter.clone());
|
surface.set_screen_filter(screen_filter.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -538,8 +548,11 @@ impl KmsState {
|
||||||
let mut used_devices = HashSet::new();
|
let mut used_devices = HashSet::new();
|
||||||
|
|
||||||
for device in self.drm_devices.values_mut() {
|
for device in self.drm_devices.values_mut() {
|
||||||
if device.update_egl(primary_node.as_ref(), self.api.as_mut())? {
|
if device
|
||||||
used_devices.insert(device.render_node());
|
.inner
|
||||||
|
.update_egl(primary_node.as_ref(), self.api.as_mut())?
|
||||||
|
{
|
||||||
|
used_devices.insert(device.inner.render_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -552,14 +565,16 @@ impl KmsState {
|
||||||
let all_devices = self
|
let all_devices = self
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values()
|
.values()
|
||||||
.map(|d| d.render_node)
|
.map(|d| d.inner.render_node)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for node in all_devices {
|
for node in all_devices {
|
||||||
let (mut device, others) = self
|
let (mut device, others) = self
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values_mut()
|
.values_mut()
|
||||||
.partition::<Vec<_>, _>(|d| d.render_node == node);
|
.partition::<Vec<_>, _>(|d| d.inner.render_node == node);
|
||||||
device[0].update_surface_nodes(&used_devices, others.iter().map(|device| &**device))?;
|
device[0]
|
||||||
|
.inner
|
||||||
|
.update_surface_nodes(&used_devices, others.iter().map(|device| &device.inner))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -584,7 +599,7 @@ impl<'a> KmsGuard<'a> {
|
||||||
for surface in self
|
for surface in self
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values()
|
.values()
|
||||||
.flat_map(|d| d.surfaces.values())
|
.flat_map(|d| d.inner.surfaces.values())
|
||||||
.filter(|s| s.output == *output || s.output.mirroring().is_some_and(|o| &o == output))
|
.filter(|s| s.output == *output || s.output.mirroring().is_some_and(|o| &o == output))
|
||||||
{
|
{
|
||||||
surface.schedule_render();
|
surface.schedule_render();
|
||||||
|
|
@ -596,8 +611,11 @@ impl<'a> KmsGuard<'a> {
|
||||||
let mut used_devices = HashSet::new();
|
let mut used_devices = HashSet::new();
|
||||||
|
|
||||||
for device in self.drm_devices.values_mut() {
|
for device in self.drm_devices.values_mut() {
|
||||||
if device.update_egl(primary_node.as_ref(), self.api.as_mut())? {
|
if device
|
||||||
used_devices.insert(device.render_node());
|
.inner
|
||||||
|
.update_egl(primary_node.as_ref(), self.api.as_mut())?
|
||||||
|
{
|
||||||
|
used_devices.insert(device.inner.render_node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -610,14 +628,16 @@ impl<'a> KmsGuard<'a> {
|
||||||
let all_devices = self
|
let all_devices = self
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values()
|
.values()
|
||||||
.map(|d| d.render_node)
|
.map(|d| d.inner.render_node)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for node in all_devices {
|
for node in all_devices {
|
||||||
let (mut device, others) = self
|
let (mut device, others) = self
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values_mut()
|
.values_mut()
|
||||||
.partition::<Vec<_>, _>(|d| d.render_node == node);
|
.partition::<Vec<_>, _>(|d| d.inner.render_node == node);
|
||||||
device[0].update_surface_nodes(&used_devices, others.iter().map(|device| &**device))?;
|
device[0]
|
||||||
|
.inner
|
||||||
|
.update_surface_nodes(&used_devices, others.iter().map(|device| &*device.inner))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -628,10 +648,12 @@ impl<'a> KmsGuard<'a> {
|
||||||
.values()
|
.values()
|
||||||
.flat_map(|device| {
|
.flat_map(|device| {
|
||||||
device
|
device
|
||||||
|
.inner
|
||||||
.outputs
|
.outputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(conn, _)| {
|
.filter(|(conn, _)| {
|
||||||
!device
|
!device
|
||||||
|
.inner
|
||||||
.leased_connectors
|
.leased_connectors
|
||||||
.iter()
|
.iter()
|
||||||
.any(|(leased_conn, _)| *conn == leased_conn)
|
.any(|(leased_conn, _)| *conn == leased_conn)
|
||||||
|
|
@ -658,10 +680,12 @@ impl<'a> KmsGuard<'a> {
|
||||||
// we only want outputs exposed to wayland - not leased ones
|
// we only want outputs exposed to wayland - not leased ones
|
||||||
// but that is also not all surface, because that doesn't contain all detected, but unmapped outputs
|
// but that is also not all surface, because that doesn't contain all detected, but unmapped outputs
|
||||||
let outputs = device
|
let outputs = device
|
||||||
|
.inner
|
||||||
.outputs
|
.outputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(conn, _)| {
|
.filter(|(conn, _)| {
|
||||||
!device
|
!device
|
||||||
|
.inner
|
||||||
.leased_connectors
|
.leased_connectors
|
||||||
.iter()
|
.iter()
|
||||||
.any(|(leased_conn, _)| *conn == leased_conn)
|
.any(|(leased_conn, _)| *conn == leased_conn)
|
||||||
|
|
@ -681,6 +705,7 @@ impl<'a> KmsGuard<'a> {
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|crtc| {
|
.filter(|crtc| {
|
||||||
!device
|
!device
|
||||||
|
.inner
|
||||||
.surfaces
|
.surfaces
|
||||||
.get(crtc)
|
.get(crtc)
|
||||||
.is_some_and(|surface| surface.output.is_enabled())
|
.is_some_and(|surface| surface.output.is_enabled())
|
||||||
|
|
@ -690,10 +715,12 @@ impl<'a> KmsGuard<'a> {
|
||||||
let open_conns = outputs
|
let open_conns = outputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|output| {
|
.filter(|output| {
|
||||||
output.is_enabled() && !device.surfaces.values().any(|s| &s.output == *output)
|
output.is_enabled()
|
||||||
|
&& !device.inner.surfaces.values().any(|s| &s.output == *output)
|
||||||
})
|
})
|
||||||
.flat_map(|output| {
|
.flat_map(|output| {
|
||||||
device
|
device
|
||||||
|
.inner
|
||||||
.outputs
|
.outputs
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(conn, o)| (output == o).then_some(*conn))
|
.find_map(|(conn, o)| (output == o).then_some(*conn))
|
||||||
|
|
@ -731,6 +758,7 @@ impl<'a> KmsGuard<'a> {
|
||||||
if !test_only {
|
if !test_only {
|
||||||
for output in outputs.iter().filter(|o| !o.is_enabled()) {
|
for output in outputs.iter().filter(|o| !o.is_enabled()) {
|
||||||
device
|
device
|
||||||
|
.inner
|
||||||
.surfaces
|
.surfaces
|
||||||
.retain(|_, surface| surface.output != *output);
|
.retain(|_, surface| surface.output != *output);
|
||||||
}
|
}
|
||||||
|
|
@ -740,7 +768,8 @@ impl<'a> KmsGuard<'a> {
|
||||||
let mut w = shell.read().global_space().size.w as u32;
|
let mut w = shell.read().global_space().size.w as u32;
|
||||||
if !test_only {
|
if !test_only {
|
||||||
for (conn, crtc) in new_pairings {
|
for (conn, crtc) in new_pairings {
|
||||||
let (output, _) = device.connector_added(
|
let (output, _) = device.inner.connector_added(
|
||||||
|
device.drm.device_mut(),
|
||||||
self.primary_node.clone(),
|
self.primary_node.clone(),
|
||||||
conn,
|
conn,
|
||||||
Some(crtc),
|
Some(crtc),
|
||||||
|
|
@ -765,6 +794,7 @@ impl<'a> KmsGuard<'a> {
|
||||||
for device in self.drm_devices.values_mut() {
|
for device in self.drm_devices.values_mut() {
|
||||||
let now = clock.now();
|
let now = clock.now();
|
||||||
let output_map = device
|
let output_map = device
|
||||||
|
.inner
|
||||||
.surfaces
|
.surfaces
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, s)| s.is_active())
|
.filter(|(_, s)| s.is_active())
|
||||||
|
|
@ -772,7 +802,7 @@ impl<'a> KmsGuard<'a> {
|
||||||
.collect::<HashMap<_, _>>();
|
.collect::<HashMap<_, _>>();
|
||||||
|
|
||||||
// reconfigure existing
|
// reconfigure existing
|
||||||
for (crtc, surface) in device.surfaces.iter_mut() {
|
for (crtc, surface) in device.inner.surfaces.iter_mut() {
|
||||||
let output_config = surface.output.config();
|
let output_config = surface.output.config();
|
||||||
|
|
||||||
let drm = &mut device.drm;
|
let drm = &mut device.drm;
|
||||||
|
|
@ -815,13 +845,13 @@ impl<'a> KmsGuard<'a> {
|
||||||
|
|
||||||
let mut renderer = self
|
let mut renderer = self
|
||||||
.api
|
.api
|
||||||
.single_renderer(&device.render_node)
|
.single_renderer(&device.inner.render_node)
|
||||||
.with_context(|| "Failed to create renderer")?;
|
.with_context(|| "Failed to create renderer")?;
|
||||||
|
|
||||||
let mut elements = DrmOutputRenderElements::default();
|
let mut elements = DrmOutputRenderElements::default();
|
||||||
for (crtc, output) in output_map.iter() {
|
for (crtc, output) in output_map.iter() {
|
||||||
let output_elements = output_elements(
|
let output_elements = output_elements(
|
||||||
Some(&device.render_node),
|
Some(&device.inner.render_node),
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&shell,
|
&shell,
|
||||||
now,
|
now,
|
||||||
|
|
@ -924,13 +954,13 @@ impl<'a> KmsGuard<'a> {
|
||||||
|
|
||||||
let mut renderer = self
|
let mut renderer = self
|
||||||
.api
|
.api
|
||||||
.single_renderer(&device.render_node)
|
.single_renderer(&device.inner.render_node)
|
||||||
.with_context(|| "Failed to create renderer")?;
|
.with_context(|| "Failed to create renderer")?;
|
||||||
|
|
||||||
let mut elements = DrmOutputRenderElements::default();
|
let mut elements = DrmOutputRenderElements::default();
|
||||||
for (crtc, output) in output_map.iter() {
|
for (crtc, output) in output_map.iter() {
|
||||||
let output_elements = output_elements(
|
let output_elements = output_elements(
|
||||||
Some(&device.render_node),
|
Some(&device.inner.render_node),
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&shell,
|
&shell,
|
||||||
now,
|
now,
|
||||||
|
|
@ -950,15 +980,16 @@ impl<'a> KmsGuard<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure primary scanout allowance
|
// configure primary scanout allowance
|
||||||
if !device.surfaces.is_empty() {
|
if !device.inner.surfaces.is_empty() {
|
||||||
let mut renderer = self
|
let mut renderer = self
|
||||||
.api
|
.api
|
||||||
.single_renderer(&device.render_node)
|
.single_renderer(&device.inner.render_node)
|
||||||
.with_context(|| "Failed to create renderer")?;
|
.with_context(|| "Failed to create renderer")?;
|
||||||
|
|
||||||
device
|
device
|
||||||
.allow_primary_scanout_any(
|
.allow_primary_scanout_any(
|
||||||
device
|
device
|
||||||
|
.inner
|
||||||
.surfaces
|
.surfaces
|
||||||
.values()
|
.values()
|
||||||
.filter(|s| s.output.is_enabled() && s.output.mirroring().is_none())
|
.filter(|s| s.output.is_enabled() && s.output.mirroring().is_none())
|
||||||
|
|
@ -973,7 +1004,7 @@ impl<'a> KmsGuard<'a> {
|
||||||
let mut elements = DrmOutputRenderElements::default();
|
let mut elements = DrmOutputRenderElements::default();
|
||||||
for (crtc, output) in output_map.iter() {
|
for (crtc, output) in output_map.iter() {
|
||||||
let output_elements = output_elements(
|
let output_elements = output_elements(
|
||||||
Some(&device.render_node),
|
Some(&device.inner.render_node),
|
||||||
&mut renderer,
|
&mut renderer,
|
||||||
&shell,
|
&shell,
|
||||||
now,
|
now,
|
||||||
|
|
@ -998,7 +1029,7 @@ impl<'a> KmsGuard<'a> {
|
||||||
// we need to handle mirroring, after all outputs have been enabled
|
// we need to handle mirroring, after all outputs have been enabled
|
||||||
let all_outputs = self.all_outputs();
|
let all_outputs = self.all_outputs();
|
||||||
for device in self.drm_devices.values_mut() {
|
for device in self.drm_devices.values_mut() {
|
||||||
for surface in device.surfaces.values_mut() {
|
for surface in device.inner.surfaces.values_mut() {
|
||||||
let mirrored_output =
|
let mirrored_output =
|
||||||
if let OutputState::Mirroring(conn) = &surface.output.config().enabled {
|
if let OutputState::Mirroring(conn) = &surface.output.config().enabled {
|
||||||
Some(
|
Some(
|
||||||
|
|
|
||||||
|
|
@ -296,6 +296,7 @@ impl Surface {
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.get_mut(&dev_node)
|
.get_mut(&dev_node)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.inner
|
||||||
.surfaces
|
.surfaces
|
||||||
.get_mut(&crtc)
|
.get_mut(&crtc)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,6 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use crate::{
|
use crate::state::{BackendData, State};
|
||||||
backend::kms::MaybeLockedDevice,
|
|
||||||
state::{BackendData, State},
|
|
||||||
};
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
reexports::wayland_server::{protocol::wl_buffer::WlBuffer, Resource},
|
reexports::wayland_server::{protocol::wl_buffer::WlBuffer, Resource},
|
||||||
wayland::buffer::BufferHandler,
|
wayland::buffer::BufferHandler,
|
||||||
|
|
@ -14,8 +11,11 @@ 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 {
|
if let BackendData::Kms(kms_state) = &mut self.backend {
|
||||||
for device in kms_state.drm_devices.values_mut() {
|
for device in kms_state.drm_devices.values_mut() {
|
||||||
if device.active_buffers.remove(&buffer.downgrade()) {
|
if device.inner.active_buffers.remove(&buffer.downgrade()) {
|
||||||
if !device.in_use(kms_state.primary_node.read().unwrap().as_ref()) {
|
if !device
|
||||||
|
.inner
|
||||||
|
.in_use(kms_state.primary_node.read().unwrap().as_ref())
|
||||||
|
{
|
||||||
if let Err(err) = kms_state.refresh_used_devices() {
|
if let Err(err) = kms_state.refresh_used_devices() {
|
||||||
warn!(?err, "Failed to init devices.");
|
warn!(?err, "Failed to init devices.");
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ impl DmabufHandler for State {
|
||||||
if let Some(device) = kms_state
|
if let Some(device) = kms_state
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values_mut()
|
.values_mut()
|
||||||
.find(|dev| dev.render_node == node)
|
.find(|dev| dev.inner.render_node == node)
|
||||||
{
|
{
|
||||||
device.active_buffers.insert(buffer.downgrade());
|
device.inner.active_buffers.insert(buffer.downgrade());
|
||||||
}
|
}
|
||||||
if let Err(err) = kms_state.refresh_used_devices() {
|
if let Err(err) = kms_state.refresh_used_devices() {
|
||||||
warn!(?err, "Failed to init devices.");
|
warn!(?err, "Failed to init devices.");
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ impl DrmHandler<Option<DrmNode>> for State {
|
||||||
if let Some(device) = kms_state
|
if let Some(device) = kms_state
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values_mut()
|
.values_mut()
|
||||||
.find(|device| device.render_node == node)
|
.find(|device| device.inner.render_node == node)
|
||||||
{
|
{
|
||||||
device.active_buffers.insert(buffer.downgrade());
|
device.inner.active_buffers.insert(buffer.downgrade());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = kms_state.refresh_used_devices() {
|
if let Err(err) = kms_state.refresh_used_devices() {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ impl DrmLeaseHandler for State {
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.get_mut(&node)
|
.get_mut(&node)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.inner
|
||||||
.leasing_global
|
.leasing_global
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
@ -32,7 +33,7 @@ impl DrmLeaseHandler for State {
|
||||||
.get_mut(&node)
|
.get_mut(&node)
|
||||||
.ok_or(LeaseRejected::default())?
|
.ok_or(LeaseRejected::default())?
|
||||||
.lock();
|
.lock();
|
||||||
let mut renderer = match kms.api.single_renderer(&backend.render_node) {
|
let mut renderer = match kms.api.single_renderer(&backend.inner.render_node) {
|
||||||
Ok(renderer) => renderer,
|
Ok(renderer) => renderer,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::warn!(
|
tracing::warn!(
|
||||||
|
|
@ -55,6 +56,7 @@ impl DrmLeaseHandler for State {
|
||||||
let mut builder = DrmLeaseBuilder::new(backend.drm.device());
|
let mut builder = DrmLeaseBuilder::new(backend.drm.device());
|
||||||
for conn in request.connectors {
|
for conn in request.connectors {
|
||||||
if let Some((_, crtc)) = backend
|
if let Some((_, crtc)) = backend
|
||||||
|
.inner
|
||||||
.leased_connectors
|
.leased_connectors
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(handle, _)| *handle == conn)
|
.find(|(handle, _)| *handle == conn)
|
||||||
|
|
@ -101,7 +103,7 @@ impl DrmLeaseHandler for State {
|
||||||
|
|
||||||
fn new_active_lease(&mut self, node: DrmNode, lease: DrmLease) {
|
fn new_active_lease(&mut self, node: DrmNode, lease: DrmLease) {
|
||||||
if let Some(backend) = self.backend.kms().drm_devices.get_mut(&node) {
|
if let Some(backend) = self.backend.kms().drm_devices.get_mut(&node) {
|
||||||
backend.active_leases.push(lease);
|
backend.inner.active_leases.push(lease);
|
||||||
}
|
}
|
||||||
// else the backend is gone, drop the lease
|
// else the backend is gone, drop the lease
|
||||||
}
|
}
|
||||||
|
|
@ -110,10 +112,10 @@ impl DrmLeaseHandler for State {
|
||||||
let kms = self.backend.kms();
|
let kms = self.backend.kms();
|
||||||
if let Some(backend) = kms.drm_devices.get_mut(&node) {
|
if let Some(backend) = kms.drm_devices.get_mut(&node) {
|
||||||
let mut backend = backend.lock();
|
let mut backend = backend.lock();
|
||||||
backend.active_leases.retain(|l| l.id() != lease);
|
backend.inner.active_leases.retain(|l| l.id() != lease);
|
||||||
|
|
||||||
if backend.active_leases.is_empty() {
|
if backend.inner.active_leases.is_empty() {
|
||||||
let mut renderer = match kms.api.single_renderer(&backend.render_node) {
|
let mut renderer = match kms.api.single_renderer(&backend.inner.render_node) {
|
||||||
Ok(renderer) => renderer,
|
Ok(renderer) => renderer,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::warn!(?err, "Failed to create renderer to enable direct scanout.");
|
tracing::warn!(?err, "Failed to create renderer to enable direct scanout.");
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ fn kms_surfaces(state: &mut State) -> impl Iterator<Item = &mut Surface> {
|
||||||
kms_state
|
kms_state
|
||||||
.drm_devices
|
.drm_devices
|
||||||
.values_mut()
|
.values_mut()
|
||||||
.flat_map(|device| device.surfaces.values_mut()),
|
.flat_map(|device| device.inner.surfaces.values_mut()),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue