diff --git a/Cargo.lock b/Cargo.lock index 8b27bc28..90adf615 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1064,7 +1064,7 @@ version = "0.19.0" source = "git+https://github.com/gfx-rs/wgpu?rev=20fda69#20fda698341efbdc870b8027d6d49f5bf3f36109" dependencies = [ "bitflags 2.6.0", - "libloading 0.8.5", + "libloading 0.7.4", "winapi", ] @@ -1199,7 +1199,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" dependencies = [ - "libloading 0.8.5", + "libloading 0.7.4", ] [[package]] @@ -1896,9 +1896,9 @@ dependencies = [ [[package]] name = "gbm" -version = "0.16.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c724107aa10444b1d2709aae4727c18a33c16b3e15ea8a46cc4ae226c084c88a" +checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a" dependencies = [ "bitflags 2.6.0", "drm 0.14.0", @@ -1909,9 +1909,9 @@ dependencies = [ [[package]] name = "gbm-sys" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9cc2f64de9fa707b5c6b2d2f10d7a7e49e845018a9f5685891eb40d3bab2538" +checksum = "c13a5f2acc785d8fb6bf6b7ab6bfb0ef5dad4f4d97e8e70bb8e470722312f76f" dependencies = [ "libc", ] @@ -2162,7 +2162,7 @@ dependencies = [ "bitflags 2.6.0", "com", "libc", - "libloading 0.8.5", + "libloading 0.7.4", "thiserror", "widestring", "winapi", @@ -2828,7 +2828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -4667,7 +4667,7 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/smithay//smithay?rev=bc1d732#bc1d7320f95cdf17f9e7aa6867cccc5903548032" +source = "git+https://github.com/cmeissl/smithay?branch=feature/drm_auto_select#fc1c6b1eb9a21dc2ef5fcfc083c8e1ba5bbbe2fb" dependencies = [ "appendlist", "ash 0.38.0+1.3.281", @@ -5879,7 +5879,7 @@ dependencies = [ "js-sys", "khronos-egl", "libc", - "libloading 0.8.5", + "libloading 0.7.4", "log", "metal", "naga", diff --git a/Cargo.toml b/Cargo.toml index 6b8e669d..9e61e1f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -119,4 +119,5 @@ inherits = "release" lto = "fat" [patch."https://github.com/Smithay/smithay.git"] -smithay = { git = "https://github.com/smithay//smithay", rev = "bc1d732" } +#smithay = { git = "https://github.com/smithay//smithay", rev = "bc1d732" } +smithay = { git = "https://github.com/cmeissl/smithay", branch = "feature/drm_auto_select" } diff --git a/src/backend/kms/device.rs b/src/backend/kms/device.rs index be22b7f9..936bb960 100644 --- a/src/backend/kms/device.rs +++ b/src/backend/kms/device.rs @@ -4,25 +4,31 @@ use crate::{ config::{AdaptiveSync, OutputConfig, OutputState}, shell::Shell, utils::prelude::*, + wayland::protocols::screencopy::Frame as ScreencopyFrame, }; use anyhow::{Context, Result}; use libc::dev_t; use smithay::{ backend::{ - allocator::gbm::GbmDevice, - drm::{DrmDevice, DrmDeviceFd, DrmEvent, DrmNode}, + allocator::{ + gbm::{GbmAllocator, GbmDevice}, + Fourcc, + }, + drm::{output::DrmOutputManager, DrmDevice, DrmDeviceFd, DrmEvent, DrmNode}, egl::{context::ContextPriority, EGLContext, EGLDevice, EGLDisplay}, session::Session, }, + desktop::utils::OutputPresentationFeedback, output::{Mode as OutputMode, Output, PhysicalProperties, Scale, Subpixel}, reexports::{ calloop::{LoopHandle, RegistrationToken}, drm::control::{connector, crtc, Device as ControlDevice, ModeTypeFlags}, + gbm::BufferObjectFlags as GbmBufferFlags, rustix::fs::OFlags, wayland_server::{protocol::wl_buffer::WlBuffer, DisplayHandle, Weak}, }, - utils::{DevPath, DeviceFd, Point, Transform}, + utils::{Buffer as BufferCoords, DevPath, DeviceFd, Point, Rectangle, Transform}, wayland::drm_lease::{DrmLease, DrmLeaseState}, }; use tracing::{error, info, warn}; @@ -32,7 +38,7 @@ use std::{ collections::{HashMap, HashSet}, fmt, path::{Path, PathBuf}, - sync::{atomic::AtomicBool, Arc, RwLock}, + sync::{atomic::AtomicBool, mpsc::Receiver, Arc, RwLock}, }; use super::{drm_helpers, socket::Socket, surface::Surface}; @@ -44,6 +50,16 @@ pub struct EGLInternals { pub context: EGLContext, } +pub type GbmDrmOutputManager = DrmOutputManager< + GbmAllocator, + GbmDevice, + Option<( + OutputPresentationFeedback, + Receiver<(ScreencopyFrame, Vec>)>, + )>, + DrmDeviceFd, +>; + pub struct Device { pub dev_node: DrmNode, pub render_node: DrmNode, @@ -51,8 +67,8 @@ pub struct Device { pub outputs: HashMap, pub surfaces: HashMap, + pub drm: GbmDrmOutputManager, pub gbm: GbmDevice, - pub drm: DrmDevice, supports_atomic: bool, @@ -72,8 +88,7 @@ impl fmt::Debug for Device { .field("render_node", &self.render_node) .field("outputs", &self.outputs) .field("surfaces", &self.surfaces) - .field("drm", &self.drm) - .field("gbm", &self.gbm) + .field("drm", &"..") .field("egl", &self.egl) .field("supports_atomic", &self.supports_atomic) .field("leased_connectors", &self.leased_connectors) @@ -190,6 +205,23 @@ impl State { } }; + let drm = GbmDrmOutputManager::new( + drm, + GbmAllocator::new( + gbm.clone(), + GbmBufferFlags::RENDERING | GbmBufferFlags::SCANOUT, + ), + gbm.clone(), + Some(gbm.clone()), + [ + Fourcc::Abgr2101010, + Fourcc::Argb2101010, + Fourcc::Abgr8888, + Fourcc::Argb8888, + ], + render_formats, + ); + let mut device = Device { dev_node: drm_node, render_node, @@ -197,8 +229,8 @@ impl State { outputs: HashMap::new(), surfaces: HashMap::new(), - gbm: gbm.clone(), drm, + gbm, supports_atomic, @@ -264,6 +296,7 @@ impl State { &mut self.common.workspace_state.update(), &self.common.xdg_activation_state, self.common.startup_done.clone(), + &self.common.clock, ); self.backend.kms().refresh_used_devices()?; @@ -364,6 +397,7 @@ impl State { &mut self.common.workspace_state.update(), &self.common.xdg_activation_state, self.common.startup_done.clone(), + &self.common.clock, ); // Don't remove the outputs, before potentially new ones have been initialized. // reading a new config means outputs might become enabled, that were previously disabled. @@ -417,6 +451,7 @@ impl State { &mut self.common.workspace_state.update(), &self.common.xdg_activation_state, self.common.startup_done.clone(), + &self.common.clock, ); self.common.refresh(); } else { @@ -435,7 +470,8 @@ pub struct OutputChanges { impl Device { pub fn enumerate_surfaces(&mut self) -> Result { // enumerate our outputs - let config = drm_helpers::display_configuration(&mut self.drm, self.supports_atomic)?; + let config = + drm_helpers::display_configuration(self.drm.device_mut(), self.supports_atomic)?; let surfaces = self .surfaces @@ -486,19 +522,20 @@ impl Device { .get(&conn) .cloned() .map(|output| Ok(output)) - .unwrap_or_else(|| create_output_for_conn(&mut self.drm, conn)) + .unwrap_or_else(|| create_output_for_conn(self.drm.device_mut(), conn)) .context("Failed to create `Output`")?; - let non_desktop = match drm_helpers::get_property_val(&self.drm, conn, "non-desktop") { - Ok((val_type, value)) => val_type.convert_value(value).as_boolean().unwrap(), - Err(err) => { - warn!( - ?err, - "Failed to determine if connector is meant desktop usage, assuming so." - ); - false - } - }; + let 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(), + Err(err) => { + warn!( + ?err, + "Failed to determine if connector is meant desktop usage, assuming so." + ); + false + } + }; if non_desktop { if let Some(crtc) = maybe_crtc { @@ -528,7 +565,7 @@ impl Device { .user_data() .insert_if_missing(|| RefCell::new(OutputConfig::default())); - populate_modes(&mut self.drm, &output, conn, position) + populate_modes(self.drm.device_mut(), &output, conn, position) .with_context(|| "Failed to enumerate connector modes")?; let has_surface = if let Some(crtc) = maybe_crtc { diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index b1e54710..927b277c 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -27,13 +27,17 @@ use smithay::{ output::Output, reexports::{ calloop::{Dispatcher, EventLoop, LoopHandle}, - drm::control::{crtc, Device as _}, + drm::{ + control::{crtc, Device as _}, + Device as _, + }, input::{self, Libinput}, wayland_server::{Client, DisplayHandle}, }, - utils::{DevPath, Size}, + utils::{Clock, DevPath, Monotonic, Size}, wayland::{dmabuf::DmabufGlobal, relative_pointer::RelativePointerManagerState}, }; +use surface::GbmDrmOutput; use tracing::{error, info, trace, warn}; use std::{ @@ -53,7 +57,9 @@ pub(crate) use surface::Surface; use device::*; pub use surface::Timings; -use super::render::init_shaders; +use super::render::{ + element::CosmicElement, init_shaders, output_elements, CursorMode, CLEAR_COLOR, +}; #[derive(Debug)] pub struct KmsState { @@ -321,6 +327,7 @@ impl State { &mut state.common.workspace_state.update(), &state.common.xdg_activation_state, state.common.startup_done.clone(), + &state.common.clock, ); state.common.refresh(); }); @@ -528,6 +535,7 @@ impl KmsState { loop_handle: &LoopHandle<'static, State>, shell: Arc>, startup_done: Arc, + clock: &Clock, ) -> Result, anyhow::Error> { if !self.session.is_active() { return Ok(Vec::new()); @@ -554,7 +562,7 @@ impl KmsState { // TODO: Right now we always keep crtcs of already enabled outputs, // even if another configuration could potentially enable more outputs - let res_handles = device.drm.resource_handles()?; + let res_handles = device.drm.device().resource_handles()?; let free_crtcs = res_handles .crtcs() .iter() @@ -579,16 +587,20 @@ impl KmsState { }); for conn in open_conns { - let conn_info = device.drm.get_connector(conn, false).with_context(|| { - format!( - "Failed to query drm device: {:?}", - device.drm.dev_path().as_deref().map(Path::display), - ) - })?; + let conn_info = device + .drm + .device() + .get_connector(conn, false) + .with_context(|| { + format!( + "Failed to query drm device: {:?}", + device.drm.device().dev_path().as_deref().map(Path::display), + ) + })?; 'outer: for encoder_info in conn_info .encoders() .iter() - .flat_map(|encoder_handle| device.drm.get_encoder(*encoder_handle)) + .flat_map(|encoder_handle| device.drm.device().get_encoder(*encoder_handle)) { for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) { if free_crtcs.contains(&crtc) { @@ -638,13 +650,20 @@ impl KmsState { let mut all_outputs = Vec::new(); for device in self.drm_devices.values_mut() { - // reconfigure + // reconfigure existing + let now = clock.now(); + let output_map = device + .surfaces + .iter() + .map(|(crtc, surface)| (*crtc, surface.output.clone())) + .collect::>(); + for (crtc, surface) in device.surfaces.iter_mut() { let output_config = surface.output.config(); let drm = &mut device.drm; let conn = surface.connector; - let conn_info = drm.get_connector(conn, false)?; + let conn_info = drm.device().get_connector(conn, false)?; let mode = conn_info .modes() .iter() @@ -662,14 +681,57 @@ impl KmsState { if !test_only { if !surface.is_active() { - let drm_surface = drm - .create_surface(*crtc, *mode, &[conn]) - .with_context(|| "Failed to create drm surface")?; - let gbm = device.gbm.clone(); - let cursor_size = drm.cursor_size(); + let compositor: GbmDrmOutput = { + let mut planes = drm + .device() + .planes(crtc) + .with_context(|| "Failed to enumerate planes")?; + let driver = drm.device().get_driver().ok(); + + // QUIRK: Using an overlay plane on a nvidia card breaks the display controller (wtf...) + if driver.is_some_and(|driver| { + driver + .name() + .to_string_lossy() + .to_lowercase() + .contains("nvidia") + }) { + planes.overlay = vec![]; + } + + let mut builder = drm.initialize_output::<_, CosmicElement<_>>(*crtc); + + let mut renderer = self + .api + .single_renderer(&device.render_node) + .with_context(|| "Failed to create renderer")?; + + for (crtc, output) in output_map.iter() { + let elements = output_elements( + Some(&device.render_node), + &mut renderer, + &shell, + now, + &output, + CursorMode::All, + None, + ) + .with_context(|| "Failed to render outputs")?; + + builder.add_render_contents(crtc, CLEAR_COLOR, elements); + } + + let compositor = builder + .build(&mut renderer, *mode, &[conn], &surface.output, Some(planes)) + .with_context(|| "Failed to create drm surface")?; + + let _ = renderer; + + compositor + }; if let Some(bpc) = output_config.max_bpc { - if let Err(err) = drm_helpers::set_max_bpc(drm, conn, bpc) { + if let Err(err) = drm_helpers::set_max_bpc(drm.device(), conn, bpc) { warn!( ?bpc, ?err, @@ -682,7 +744,7 @@ impl KmsState { let vrr = output_config.vrr; std::mem::drop(output_config); - match surface.resume(drm_surface, gbm, cursor_size) { + match surface.resume(compositor) { Ok(_) => { surface.output.set_adaptive_sync_support( surface.adaptive_sync_support().ok(), diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index e7893dee..a0350a21 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -3,12 +3,12 @@ use crate::{ backend::render::{ element::{CosmicElement, DamageElement}, - init_shaders, workspace_elements, CursorMode, ElementFilter, GlMultiRenderer, CLEAR_COLOR, + init_shaders, output_elements, CursorMode, GlMultiRenderer, CLEAR_COLOR, }, config::AdaptiveSync, shell::Shell, state::SurfaceDmabufFeedback, - utils::{prelude::*, quirks::workspace_overview_is_open}, + utils::prelude::*, wayland::{ handlers::screencopy::{submit_buffer, FrameHolder, SessionData}, protocols::screencopy::{ @@ -23,12 +23,13 @@ use smithay::{ backend::{ allocator::{ format::FormatSet, - gbm::{GbmAllocator, GbmBufferFlags, GbmDevice}, + gbm::{GbmAllocator, GbmDevice}, Fourcc, }, drm::{ - compositor::{BlitFrameResultError, DrmCompositor, FrameError, PrimaryPlaneElement}, - DrmDeviceFd, DrmEventMetadata, DrmEventTime, DrmNode, DrmSurface, VrrSupport, + compositor::{BlitFrameResultError, FrameError, FrameMode, PrimaryPlaneElement}, + output::DrmOutput, + DrmDeviceFd, DrmEventMetadata, DrmEventTime, DrmNode, VrrSupport, }, egl::EGLContext, renderer::{ @@ -55,17 +56,14 @@ use smithay::{ timer::{TimeoutAction, Timer}, EventLoop, LoopHandle, RegistrationToken, }, - drm::{ - control::{connector, crtc, Mode}, - Device as _, - }, + drm::control::{connector, crtc, Mode}, wayland_protocols::wp::{ linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1, presentation_time::server::wp_presentation_feedback, }, wayland_server::protocol::wl_surface::WlSurface, }, - utils::{Buffer as BufferCoords, Clock, Monotonic, Physical, Rectangle, Size, Transform}, + utils::{Buffer as BufferCoords, Clock, Monotonic, Physical, Rectangle, Transform}, wayland::{ dmabuf::{get_dmabuf, DmabufFeedbackBuilder}, presentation::Refresh, @@ -127,7 +125,7 @@ pub struct SurfaceThreadState { target_node: DrmNode, active: Arc, vrr_mode: AdaptiveSync, - compositor: Option, + compositor: Option, state: QueueState, timings: Timings, @@ -186,7 +184,7 @@ impl MirroringState { } } -pub type GbmDrmCompositor = DrmCompositor< +pub type GbmDrmOutput = DrmOutput< GbmAllocator, GbmDevice, Option<( @@ -224,9 +222,7 @@ impl Default for QueueState { pub enum ThreadCommand { Suspend, Resume { - surface: DrmSurface, - gbm: GbmDevice, - cursor_size: Size, + compositor: GbmDrmOutput, result: SyncSender>, }, NodeAdded { @@ -436,31 +432,26 @@ impl Surface { let _ = self.thread_command.send(ThreadCommand::Suspend); } - pub fn resume( - &mut self, - surface: DrmSurface, - gbm: GbmDevice, - cursor_size: Size, - ) -> Result<()> { + pub fn resume(&mut self, compositor: GbmDrmOutput) -> Result<()> { let (tx, rx) = std::sync::mpsc::sync_channel(1); - self.plane_formats = surface - .plane_info() - .formats - .iter() - .copied() - .chain( - surface - .planes() - .overlay - .iter() - .flat_map(|p| p.formats.iter().cloned()), - ) - .collect::(); + self.plane_formats = compositor.with_compositor(|c| { + c.surface() + .plane_info() + .formats + .iter() + .copied() + .chain( + c.surface() + .planes() + .overlay + .iter() + .flat_map(|p| p.formats.iter().cloned()), + ) + .collect::() + }); let _ = self.thread_command.send(ThreadCommand::Resume { - surface, - gbm, - cursor_size, + compositor, result: tx, }); @@ -554,13 +545,8 @@ fn surface_thread( .handle() .insert_source(thread_receiver, move |command, _, state| match command { Event::Msg(ThreadCommand::Suspend) => state.suspend(), - Event::Msg(ThreadCommand::Resume { - surface, - gbm, - cursor_size, - result, - }) => { - let _ = result.send(state.resume(surface, gbm, cursor_size)); + Event::Msg(ThreadCommand::Resume { compositor, result }) => { + let _ = result.send(state.resume(compositor)); } Event::Msg(ThreadCommand::NodeAdded { node, gbm, egl }) => { if let Err(err) = state.node_added(node, gbm, egl) { @@ -585,7 +571,11 @@ fn surface_thread( } Event::Msg(ThreadCommand::SetMode(mode, result)) => { if let Some(compositor) = state.compositor.as_mut() { - let _ = result.send(compositor.use_mode(mode).map_err(Into::into)); + let _ = result.send( + compositor + .with_compositor(|c| c.use_mode(mode)) + .map_err(Into::into), + ); } else { let _ = result.send(Err(anyhow::anyhow!("Set mode with inactive surface"))); } @@ -594,9 +584,9 @@ fn surface_thread( if let Some(compositor) = state.compositor.as_mut() { let _ = result.send( compositor - .vrr_supported( - compositor.pending_connectors().into_iter().next().unwrap(), - ) + .with_compositor(|c| { + c.vrr_supported(c.pending_connectors().into_iter().next().unwrap()) + }) .map_err(Into::into), ); } else { @@ -608,7 +598,7 @@ fn surface_thread( } Event::Msg(ThreadCommand::DpmsOff) => { if let Some(compositor) = state.compositor.as_mut() { - if let Err(err) = compositor.clear() { + if let Err(err) = compositor.with_compositor(|c| c.clear()) { error!("Failed to set DPMS off: {:?}", err); } match std::mem::replace(&mut state.state, QueueState::Idle) { @@ -662,69 +652,19 @@ impl SurfaceThreadState { }; } - fn resume( - &mut self, - surface: DrmSurface, - gbm: GbmDevice, - cursor_size: Size, - ) -> Result<()> { - let driver = surface.get_driver().ok(); - let mut planes = surface.planes().clone(); - - // QUIRK: Using an overlay plane on a nvidia card breaks the display controller (wtf...) - if driver.is_some_and(|driver| { - driver - .name() - .to_string_lossy() - .to_lowercase() - .contains("nvidia") - }) { - planes.overlay = vec![]; - } - - let render_formats = self - .api - .single_renderer(&self.target_node) - .unwrap() - .dmabuf_formats(); - + fn resume(&mut self, compositor: GbmDrmOutput) -> Result<()> { + let mode = compositor.with_compositor(|c| c.surface().pending_mode()); self.timings .set_refresh_interval(Some(Duration::from_secs_f64( - 1_000.0 / drm_helpers::calculate_refresh_rate(surface.pending_mode()) as f64, + 1_000.0 / drm_helpers::calculate_refresh_rate(mode) as f64, ))); - match DrmCompositor::new( - &self.output, - surface, - Some(planes), - GbmAllocator::new( - gbm.clone(), - GbmBufferFlags::RENDERING | GbmBufferFlags::SCANOUT, - ), - gbm.clone(), - &[ - Fourcc::Abgr2101010, - Fourcc::Argb2101010, - Fourcc::Abgr8888, - Fourcc::Argb8888, - ], - render_formats, - cursor_size, - Some(gbm), - ) { - Ok(mut compositor) => { - if crate::utils::env::bool_var("COSMIC_DISABLE_DIRECT_SCANOUT").unwrap_or(false) { - compositor.use_direct_scanout(false); - } - self.active.store(true, Ordering::SeqCst); - self.compositor = Some(compositor); - Ok(()) - } - Err(err) => { - self.active.store(false, Ordering::SeqCst); - Err(err.into()) - } - } + /*if crate::utils::env::bool_var("COSMIC_DISABLE_DIRECT_SCANOUT").unwrap_or(false) { + compositor.use_direct_scanout(false); + }*/ + self.active.store(true, Ordering::SeqCst); + self.compositor = Some(compositor); + Ok(()) } fn node_added( @@ -809,7 +749,7 @@ impl SurfaceThreadState { if self .compositor .as_ref() - .is_some_and(|comp| comp.vrr_enabled()) => + .is_some_and(|comp| comp.with_compositor(|c| c.vrr_enabled())) => { Refresh::Variable(rate) } @@ -967,47 +907,27 @@ impl SurfaceThreadState { _ => false, }; - let mut elements = { + if self.vrr_mode == AdaptiveSync::Enabled { let shell = self.shell.read().unwrap(); let output = self.mirroring.as_ref().unwrap_or(&self.output); + vrr = shell.workspaces.active(output).1.get_fullscreen().is_some(); + } - let (previous_workspace, workspace) = shell.workspaces.active(output); - let (previous_idx, idx) = shell.workspaces.active_num(&output); - let previous_workspace = previous_workspace - .zip(previous_idx) - .map(|((w, start), idx)| (w.handle, idx, start)); - if self.vrr_mode == AdaptiveSync::Enabled { - vrr = workspace.get_fullscreen().is_some(); - } - let workspace = (workspace.handle, idx); - - std::mem::drop(shell); - - let element_filter = if workspace_overview_is_open(output) { - ElementFilter::LayerShellOnly - } else { - ElementFilter::All - }; - - workspace_elements( - Some(&render_node), - &mut renderer, - &self.shell, - self.clock.now(), - output, - previous_workspace, - workspace, - CursorMode::All, - element_filter, - #[cfg(not(feature = "debug"))] - None, - #[cfg(feature = "debug")] - Some((&self.egui, &self.timings)), - ) - .map_err(|err| { - anyhow::format_err!("Failed to accumulate elements for rendering: {:?}", err) - })? - }; + let mut elements = output_elements( + Some(&render_node), + &mut renderer, + &self.shell, + self.clock.now(), + self.mirroring.as_ref().unwrap_or(&self.output), + CursorMode::All, + #[cfg(not(feature = "debug"))] + None, + #[cfg(feature = "debug")] + Some((&self.egui, &self.timings)), + ) + .map_err(|err| { + anyhow::format_err!("Failed to accumulate elements for rendering: {:?}", err) + })?; self.timings.set_vrr(vrr); self.timings.elements_done(&self.clock); @@ -1164,18 +1084,21 @@ impl SurfaceThreadState { .collect::>(); renderer = self.api.single_renderer(&self.target_node).unwrap(); - if let Err(err) = compositor.use_vrr(false) { - warn!("Unable to set adaptive VRR state: {}", err); - } - compositor.render_frame(&mut renderer, &elements, [0.0, 0.0, 0.0, 1.0]) + compositor.render_frame( + &mut renderer, + &elements, + [0.0, 0.0, 0.0, 1.0], + FrameMode::ALL, + ) } else { - if let Err(err) = compositor.use_vrr(vrr) { + if let Err(err) = compositor.with_compositor(|c| c.use_vrr(vrr)) { warn!("Unable to set adaptive VRR state: {}", err); } compositor.render_frame( &mut renderer, &elements, CLEAR_COLOR, // TODO use a theme neutral color + FrameMode::ALL, ) }; self.timings.draw_done(&self.clock); @@ -1230,10 +1153,10 @@ impl SurfaceThreadState { if let Ok(dmabuf) = get_dmabuf(&buffer) { renderer .bind(dmabuf.clone()) - .map_err(RenderError::::Rendering)?; + .map_err(RenderError::<::Error>::Rendering)?; } else { let size = buffer_dimensions(&buffer).ok_or(RenderError::< - GlMultiRenderer, + ::Error, >::Rendering( MultiError::ImportFailed, ))?; @@ -1247,10 +1170,10 @@ impl SurfaceThreadState { format, size, ) - .map_err(RenderError::::Rendering)?; + .map_err(RenderError::<::Error>::Rendering)?; renderer .bind(render_buffer) - .map_err(RenderError::::Rendering)?; + .map_err(RenderError::<::Error>::Rendering)?; } let (output_size, output_scale, output_transform) = ( @@ -1292,14 +1215,16 @@ impl SurfaceThreadState { filter, ) .map_err(|err| match err { - BlitFrameResultError::Rendering(err) => { - RenderError::::Rendering(err) - } - BlitFrameResultError::Export(_) => { - RenderError::::Rendering( - MultiError::DeviceMissing, - ) - } + BlitFrameResultError::Rendering(err) => RenderError::< + ::Error, + >::Rendering( + err + ), + BlitFrameResultError::Export(_) => RenderError::< + ::Error, + >::Rendering( + MultiError::DeviceMissing, + ), }) { Ok(new_sync) => { sync = new_sync; diff --git a/src/backend/render/mod.rs b/src/backend/render/mod.rs index aa545068..53fd49b8 100644 --- a/src/backend/render/mod.rs +++ b/src/backend/render/mod.rs @@ -499,6 +499,53 @@ pub enum ElementFilter { LayerShellOnly, } +pub fn output_elements( + _gpu: Option<&DrmNode>, + renderer: &mut R, + shell: &Arc>, + now: Time, + output: &Output, + cursor_mode: CursorMode, + _fps: Option<(&EguiState, &Timings)>, +) -> Result>, RenderError> +where + R: Renderer + ImportAll + ImportMem + AsGlowRenderer, + ::TextureId: Send + Clone + 'static, + ::Error: FromGlesError, + CosmicMappedRenderElement: RenderElement, + WorkspaceRenderElement: RenderElement, +{ + let shell_guard = shell.read().unwrap(); + + let (previous_workspace, workspace) = shell_guard.workspaces.active(output); + let (previous_idx, idx) = shell_guard.workspaces.active_num(&output); + let previous_workspace = previous_workspace + .zip(previous_idx) + .map(|((w, start), idx)| (w.handle, idx, start)); + let workspace = (workspace.handle, idx); + + std::mem::drop(shell_guard); + + let element_filter = if workspace_overview_is_open(output) { + ElementFilter::LayerShellOnly + } else { + ElementFilter::All + }; + + workspace_elements( + _gpu, + renderer, + shell, + now, + output, + previous_workspace, + workspace, + cursor_mode, + element_filter, + _fps, + ) +} + #[profiling::function] pub fn workspace_elements( _gpu: Option<&DrmNode>, @@ -511,7 +558,7 @@ pub fn workspace_elements( cursor_mode: CursorMode, element_filter: ElementFilter, _fps: Option<(&EguiState, &Timings)>, -) -> Result>, RenderError> +) -> Result>, RenderError> where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: Send + Clone + 'static, @@ -867,7 +914,7 @@ pub fn render_output<'d, R, Target, OffTarget>( now: Time, output: &Output, cursor_mode: CursorMode, -) -> Result, RenderError> +) -> Result, RenderError> where R: Renderer + ImportAll @@ -1026,7 +1073,7 @@ pub fn render_workspace<'d, R, Target, OffTarget>( current: (WorkspaceHandle, usize), cursor_mode: CursorMode, element_filter: ElementFilter, -) -> Result<(RenderOutputResult<'d>, Vec>), RenderError> +) -> Result<(RenderOutputResult<'d>, Vec>), RenderError> where R: Renderer + ImportAll diff --git a/src/backend/winit.rs b/src/backend/winit.rs index a1a2bdce..f293341c 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -228,6 +228,7 @@ pub fn init_backend( &mut state.common.workspace_state.update(), &state.common.xdg_activation_state, state.common.startup_done.clone(), + &state.common.clock, ); state.common.refresh(); } diff --git a/src/backend/x11.rs b/src/backend/x11.rs index ba33c14b..a18bcaf5 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -363,6 +363,7 @@ pub fn init_backend( &mut state.common.workspace_state.update(), &state.common.xdg_activation_state, state.common.startup_done.clone(), + &state.common.clock, ); state.common.refresh(); } diff --git a/src/config/mod.rs b/src/config/mod.rs index f8bd9a2f..edf13d30 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -11,7 +11,6 @@ use cosmic_config::{ConfigGet, CosmicConfigEntry}; use cosmic_settings_config::window_rules::ApplicationException; use cosmic_settings_config::{shortcuts, window_rules, Shortcuts}; use serde::{Deserialize, Serialize}; -use smithay::wayland::xdg_activation::XdgActivationState; pub use smithay::{ backend::input::KeyState, input::keyboard::{keysyms as KeySyms, Keysym, ModifiersState}, @@ -25,6 +24,10 @@ pub use smithay::{ }, utils::{Logical, Physical, Point, Size, Transform}, }; +use smithay::{ + utils::{Clock, Monotonic}, + wayland::xdg_activation::XdgActivationState, +}; use std::{ cell::RefCell, collections::{BTreeMap, HashMap}, @@ -381,6 +384,7 @@ impl Config { workspace_state: &mut WorkspaceUpdateGuard<'_, State>, xdg_activation_state: &XdgActivationState, startup_done: Arc, + clock: &Clock, ) { let outputs = output_state.outputs().collect::>(); let mut infos = outputs @@ -422,6 +426,7 @@ impl Config { workspace_state, xdg_activation_state, startup_done.clone(), + clock, ) { warn!(?err, "Failed to set new config."); found_outputs.clear(); @@ -446,6 +451,7 @@ impl Config { workspace_state, xdg_activation_state, startup_done, + clock, ) { error!(?err, "Failed to reset config."); } else { @@ -477,6 +483,7 @@ impl Config { workspace_state, xdg_activation_state, startup_done, + clock, ) { warn!(?err, "Failed to set new config.",); } else { diff --git a/src/state.rs b/src/state.rs index fc2ba06e..e7a09efa 100644 --- a/src/state.rs +++ b/src/state.rs @@ -297,11 +297,16 @@ impl BackendData { workspace_state: &mut WorkspaceUpdateGuard<'_, State>, xdg_activation_state: &XdgActivationState, startup_done: Arc, + clock: &Clock, ) -> Result<(), anyhow::Error> { let result = match self { - BackendData::Kms(ref mut state) => { - state.apply_config_for_outputs(test_only, loop_handle, shell.clone(), startup_done) - } + BackendData::Kms(ref mut state) => state.apply_config_for_outputs( + test_only, + loop_handle, + shell.clone(), + startup_done, + clock, + ), BackendData::Winit(ref mut state) => state.apply_config_for_outputs(test_only), BackendData::X11(ref mut state) => state.apply_config_for_outputs(test_only), _ => unreachable!("No backend set when applying output config"), diff --git a/src/wayland/handlers/drm_lease.rs b/src/wayland/handlers/drm_lease.rs index daf8794f..55528cce 100644 --- a/src/wayland/handlers/drm_lease.rs +++ b/src/wayland/handlers/drm_lease.rs @@ -33,7 +33,7 @@ impl DrmLeaseHandler for State { .get_mut(&node) .ok_or(LeaseRejected::default())?; - let mut builder = DrmLeaseBuilder::new(&backend.drm); + let mut builder = DrmLeaseBuilder::new(backend.drm.device()); for conn in request.connectors { if let Some((_, crtc)) = backend .leased_connectors @@ -44,6 +44,7 @@ impl DrmLeaseHandler for State { builder.add_crtc(*crtc); let planes = backend .drm + .device() .planes(crtc) .map_err(LeaseRejected::with_cause)?; let (primary_plane, primary_plane_claim) = planes @@ -52,6 +53,7 @@ impl DrmLeaseHandler for State { .find_map(|plane| { backend .drm + .device_mut() .claim_plane(plane.handle, *crtc) .map(|claim| (plane, claim)) }) @@ -60,6 +62,7 @@ impl DrmLeaseHandler for State { if let Some((cursor, claim)) = planes.cursor.into_iter().find_map(|plane| { backend .drm + .device_mut() .claim_plane(plane.handle, *crtc) .map(|claim| (plane, claim)) }) { diff --git a/src/wayland/handlers/output_configuration.rs b/src/wayland/handlers/output_configuration.rs index eb900ddc..72549a8b 100644 --- a/src/wayland/handlers/output_configuration.rs +++ b/src/wayland/handlers/output_configuration.rs @@ -140,6 +140,7 @@ impl State { &mut self.common.workspace_state.update(), &self.common.xdg_activation_state, self.common.startup_done.clone(), + &self.common.clock, ); if let Err(err) = res { warn!(?err, "Failed to apply config. Resetting"); @@ -161,6 +162,7 @@ impl State { &mut self.common.workspace_state.update(), &self.common.xdg_activation_state, self.common.startup_done.clone(), + &self.common.clock, ) { error!(?err, "Failed to reset output config."); } diff --git a/src/wayland/handlers/screencopy/render.rs b/src/wayland/handlers/screencopy/render.rs index 54f3070e..606a6b6e 100644 --- a/src/wayland/handlers/screencopy/render.rs +++ b/src/wayland/handlers/screencopy/render.rs @@ -140,7 +140,7 @@ pub fn render_session( frame: Frame, transform: Transform, render_fn: F, -) -> Result>)>, DTError> +) -> Result>)>, DTError> where R: ExportMem, ::Error: FromGlesError, @@ -150,7 +150,7 @@ where &'d mut OutputDamageTracker, usize, Vec>, - ) -> Result, DTError>, + ) -> Result, DTError>, { let mut session_damage_tracking = session.lock().unwrap(); @@ -225,7 +225,7 @@ pub fn render_workspace_to_buffer( common: &mut Common, output: &Output, handle: (WorkspaceHandle, usize), - ) -> Result, DTError> + ) -> Result, DTError> where R: Renderer + ImportAll @@ -464,7 +464,7 @@ pub fn render_window_to_buffer( common: &mut Common, window: &CosmicSurface, geometry: Rectangle, - ) -> Result, DTError> + ) -> Result, DTError> where R: Renderer + ImportAll @@ -705,7 +705,7 @@ pub fn render_cursor_to_buffer( additional_damage: Vec>, common: &mut Common, seat: &Seat, - ) -> Result, DTError> + ) -> Result, DTError> where R: Renderer + ImportAll