aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-12-14 13:15:14 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-12-30 20:12:37 +0300
commite6d8932b3bd0486bf56309f3578f809625abc9a2 (patch)
tree515645502d3046138771799b2c6c6d35465d28a8 /src
parent70f96cca0a2b985dcc7298b4a87a2f0819991878 (diff)
downloadniri-e6d8932b3bd0486bf56309f3578f809625abc9a2.tar.gz
niri-e6d8932b3bd0486bf56309f3578f809625abc9a2.tar.bz2
niri-e6d8932b3bd0486bf56309f3578f809625abc9a2.zip
Update for Smithay VRR changes
Diffstat (limited to 'src')
-rw-r--r--src/backend/tty.rs218
1 files changed, 70 insertions, 148 deletions
diff --git a/src/backend/tty.rs b/src/backend/tty.rs
index f9b9d33c..1f72440a 100644
--- a/src/backend/tty.rs
+++ b/src/backend/tty.rs
@@ -20,7 +20,7 @@ use smithay::backend::allocator::gbm::{GbmAllocator, GbmBufferFlags, GbmDevice};
use smithay::backend::allocator::Fourcc;
use smithay::backend::drm::compositor::{DrmCompositor, PrimaryPlaneElement};
use smithay::backend::drm::{
- DrmDevice, DrmDeviceFd, DrmEvent, DrmEventMetadata, DrmEventTime, DrmNode, NodeType,
+ DrmDevice, DrmDeviceFd, DrmEvent, DrmEventMetadata, DrmEventTime, DrmNode, NodeType, VrrSupport,
};
use smithay::backend::egl::context::ContextPriority;
use smithay::backend::egl::{EGLDevice, EGLDisplay};
@@ -184,7 +184,6 @@ struct Surface {
gamma_props: Option<GammaProps>,
/// Gamma change to apply upon session resume.
pending_gamma_change: Option<Option<Vec<u16>>>,
- vrr_enabled: bool,
/// Tracy frame that goes from vblank to vblank.
vblank_frame: Option<tracy_client::Frame>,
/// Frame name for the VBlank frame.
@@ -405,8 +404,6 @@ impl Tty {
self.device_changed(node.dev_id(), niri);
// Apply pending gamma changes and restore our existing gamma.
- //
- // Also, restore our VRR.
let device = self.devices.get_mut(&node).unwrap();
for (crtc, surface) in device.surfaces.iter_mut() {
if let Some(ramp) = surface.pending_gamma_change.take() {
@@ -424,33 +421,6 @@ impl Tty {
warn!("error restoring gamma: {err:?}");
}
}
-
- // Restore VRR.
- let output = niri
- .global_space
- .outputs()
- .find(|output| {
- let tty_state: &TtyOutputState = output.user_data().get().unwrap();
- tty_state.node == node && tty_state.crtc == *crtc
- })
- .cloned();
- let Some(output) = output else {
- error!("missing output for crtc: {crtc:?}");
- continue;
- };
- let Some(output_state) = niri.output_state.get_mut(&output) else {
- error!("missing state for output {:?}", surface.name.connector);
- continue;
- };
-
- try_to_change_vrr(
- &device.drm,
- surface.connector,
- *crtc,
- surface,
- output_state,
- surface.vrr_enabled,
- );
}
}
@@ -822,45 +792,6 @@ impl Tty {
Err(err) => debug!("error setting max bpc: {err:?}"),
}
- // Try to enable VRR if requested.
- let mut vrr_enabled = false;
- if let Some(capable) = is_vrr_capable(&device.drm, connector.handle()) {
- if capable {
- // Even if on-demand, we still disable it until later checks.
- let vrr = config.is_vrr_always_on();
- let word = if vrr { "enabling" } else { "disabling" };
-
- match set_vrr_enabled(&device.drm, crtc, vrr) {
- Ok(enabled) => {
- if enabled != vrr {
- warn!("failed {} VRR", word);
- }
-
- vrr_enabled = enabled;
- }
- Err(err) => {
- warn!("error {} VRR: {err:?}", word);
- }
- }
- } else {
- if !config.is_vrr_always_off() {
- warn!("cannot enable VRR because connector is not vrr_capable");
- }
-
- // Try to disable it anyway to work around a bug where resetting DRM state causes
- // vrr_capable to be reset to 0, potentially leaving VRR_ENABLED at 1.
- let res = set_vrr_enabled(&device.drm, crtc, false);
- if matches!(res, Ok(true)) {
- warn!("error disabling VRR");
-
- // So that we can try it again later.
- vrr_enabled = true;
- }
- }
- } else if !config.is_vrr_always_off() {
- warn!("cannot enable VRR because connector is not vrr_capable");
- }
-
let mut gamma_props = GammaProps::new(&device.drm, crtc)
.map_err(|err| debug!("error getting gamma properties: {err:?}"))
.ok();
@@ -879,6 +810,31 @@ impl Tty {
.drm
.create_surface(crtc, mode, &[connector.handle()])?;
+ // Try to enable VRR if requested.
+ match surface.vrr_supported(connector.handle()) {
+ Ok(VrrSupport::Supported | VrrSupport::RequiresModeset) => {
+ // Even if on-demand, we still disable it until later checks.
+ let vrr = config.is_vrr_always_on();
+ let word = if vrr { "enabling" } else { "disabling" };
+
+ if let Err(err) = surface.use_vrr(vrr) {
+ warn!("error {} VRR: {err:?}", word);
+ }
+ }
+ Ok(VrrSupport::NotSupported) => {
+ if !config.is_vrr_always_off() {
+ warn!("cannot enable VRR because connector does not support it");
+ }
+
+ // Try to disable it anyway to work around a bug where resetting DRM state causes
+ // vrr_capable to be reset to 0, potentially leaving VRR_ENABLED at 1.
+ let _ = surface.use_vrr(false);
+ }
+ Err(err) => {
+ warn!("error querying for VRR support: {err:?}");
+ }
+ }
+
// Create GBM allocator.
let gbm_flags = GbmBufferFlags::RENDERING | GbmBufferFlags::SCANOUT;
let allocator = GbmAllocator::new(device.gbm.clone(), gbm_flags);
@@ -1038,6 +994,8 @@ impl Tty {
}
}
+ let vrr_enabled = compositor.vrr_enabled();
+
let vblank_frame_name =
tracy_client::FrameName::new_leak(format!("vblank on {connector_name}"));
let time_since_presentation_plot_name = tracy_client::PlotName::new_leak(format!(
@@ -1055,7 +1013,6 @@ impl Tty {
compositor,
dmabuf_feedback,
gamma_props,
- vrr_enabled,
pending_gamma_change: None,
vblank_frame: None,
vblank_frame_name,
@@ -1622,8 +1579,17 @@ impl Tty {
}
}
- let vrr_supported = is_vrr_capable(&device.drm, connector.handle()) == Some(true);
- let vrr_enabled = surface.map_or(false, |surface| surface.vrr_enabled);
+ let vrr_supported = surface
+ .map(|surface| {
+ matches!(
+ surface.compositor.vrr_supported(connector.handle()),
+ Ok(VrrSupport::Supported | VrrSupport::RequiresModeset)
+ )
+ })
+ .unwrap_or_else(|| {
+ is_vrr_capable(&device.drm, connector.handle()) == Some(true)
+ });
+ let vrr_enabled = surface.map_or(false, |surface| surface.compositor.vrr_enabled());
let logical = niri
.global_space
@@ -1708,14 +1674,17 @@ impl Tty {
for (&crtc, surface) in device.surfaces.iter_mut() {
let tty_state: &TtyOutputState = output.user_data().get().unwrap();
if tty_state.node == node && tty_state.crtc == crtc {
- try_to_change_vrr(
- &device.drm,
- surface.connector,
- crtc,
- surface,
- output_state,
- enable_vrr,
- );
+ let word = if enable_vrr { "enabling" } else { "disabling" };
+ if let Err(err) = surface.compositor.use_vrr(enable_vrr) {
+ warn!(
+ "output {:?}: error {} VRR: {err:?}",
+ surface.name.connector, word
+ );
+ }
+ output_state
+ .frame_clock
+ .set_vrr(surface.compositor.vrr_enabled());
+
self.refresh_ipc_outputs(niri);
return;
}
@@ -1781,8 +1750,11 @@ impl Tty {
};
let change_mode = surface.compositor.pending_mode() != mode;
- let change_always_vrr = surface.vrr_enabled != config.is_vrr_always_on();
+
+ let vrr_enabled = surface.compositor.vrr_enabled();
+ let change_always_vrr = vrr_enabled != config.is_vrr_always_on();
let is_on_demand_vrr = config.is_vrr_on_demand();
+
if !change_mode && !change_always_vrr && !is_on_demand_vrr {
continue;
}
@@ -1804,17 +1776,20 @@ impl Tty {
continue;
};
- if (is_on_demand_vrr && surface.vrr_enabled != output_state.on_demand_vrr_enabled)
+ if (is_on_demand_vrr && vrr_enabled != output_state.on_demand_vrr_enabled)
|| (!is_on_demand_vrr && change_always_vrr)
{
- try_to_change_vrr(
- &device.drm,
- connector.handle(),
- crtc,
- surface,
- output_state,
- !surface.vrr_enabled,
- );
+ let vrr = !vrr_enabled;
+ let word = if vrr { "enabling" } else { "disabling" };
+ if let Err(err) = surface.compositor.use_vrr(vrr) {
+ warn!(
+ "output {:?}: error {} VRR: {err:?}",
+ surface.name.connector, word
+ );
+ }
+ output_state
+ .frame_clock
+ .set_vrr(surface.compositor.vrr_enabled());
}
if change_mode {
@@ -1846,8 +1821,10 @@ impl Tty {
let wl_mode = Mode::from(mode);
output.change_current_state(Some(wl_mode), None, None, None);
output.set_preferred(wl_mode);
- output_state.frame_clock =
- FrameClock::new(Some(refresh_interval(mode)), surface.vrr_enabled);
+ output_state.frame_clock = FrameClock::new(
+ Some(refresh_interval(mode)),
+ surface.compositor.vrr_enabled(),
+ );
niri.output_resized(&output);
}
}
@@ -2431,24 +2408,6 @@ fn is_vrr_capable(device: &DrmDevice, connector: connector::Handle) -> Option<bo
info.value_type().convert_value(value).as_boolean()
}
-fn set_vrr_enabled(device: &DrmDevice, crtc: crtc::Handle, enabled: bool) -> anyhow::Result<bool> {
- let (prop, info, _) =
- find_drm_property(device, crtc, "VRR_ENABLED").context("VRR_ENABLED property missing")?;
-
- let value = property::Value::UnsignedRange(if enabled { 1 } else { 0 });
- device
- .set_property(crtc, prop, value.into())
- .context("error setting VRR_ENABLED property")?;
-
- let value = get_drm_property(device, crtc, prop)
- .context("VRR_ENABLED property missing after setting")?;
- match info.value_type().convert_value(value) {
- property::Value::UnsignedRange(value) => Ok(value == 1),
- property::Value::Boolean(value) => Ok(value),
- _ => bail!("wrong VRR_ENABLED property type"),
- }
-}
-
pub fn set_gamma_for_crtc(
device: &DrmDevice,
crtc: crtc::Handle,
@@ -2494,43 +2453,6 @@ pub fn set_gamma_for_crtc(
Ok(())
}
-fn try_to_change_vrr(
- device: &DrmDevice,
- connector: connector::Handle,
- crtc: crtc::Handle,
- surface: &mut Surface,
- output_state: &mut crate::niri::OutputState,
- enable_vrr: bool,
-) {
- let _span = tracy_client::span!("try_to_change_vrr");
-
- if is_vrr_capable(device, connector) == Some(true) {
- let word = if enable_vrr { "enabling" } else { "disabling" };
-
- match set_vrr_enabled(device, crtc, enable_vrr) {
- Ok(enabled) => {
- if enabled != enable_vrr {
- warn!("output {:?}: failed {} VRR", surface.name.connector, word);
- }
-
- surface.vrr_enabled = enabled;
- output_state.frame_clock.set_vrr(enabled);
- }
- Err(err) => {
- warn!(
- "output {:?}: error {} VRR: {err:?}",
- surface.name.connector, word
- );
- }
- }
- } else if enable_vrr {
- warn!(
- "output {:?}: cannot enable VRR because connector is not vrr_capable",
- surface.name.connector
- );
- }
-}
-
fn format_connector_name(connector: &connector::Info) -> String {
format!(
"{}-{}",