aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tty.rs
diff options
context:
space:
mode:
authorMichael Yang <admin@my4ng.dev>2024-08-22 18:58:07 +1000
committerGitHub <noreply@github.com>2024-08-22 11:58:07 +0300
commitf1894f6f9a7470b8b1493cf96b28a48e8a704636 (patch)
treed70a3ab350d39dea1b8240e2a92b281b01be5d12 /src/backend/tty.rs
parentdfc2d452c55d59d6d9014c98a9da3a082c4f7379 (diff)
downloadniri-f1894f6f9a7470b8b1493cf96b28a48e8a704636.tar.gz
niri-f1894f6f9a7470b8b1493cf96b28a48e8a704636.tar.bz2
niri-f1894f6f9a7470b8b1493cf96b28a48e8a704636.zip
feature: add on-demand vrr (#586)
* feature: add on-demand vrr * Don't require connector::Info in try_to_set_vrr * Improve VRR help message * Rename connector_handle => connector * Fix tracy span name * Move on demand vrr flag set higher * wiki: Mention on-demand VRR --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
Diffstat (limited to 'src/backend/tty.rs')
-rw-r--r--src/backend/tty.rs88
1 files changed, 50 insertions, 38 deletions
diff --git a/src/backend/tty.rs b/src/backend/tty.rs
index 10becafe..1d891d91 100644
--- a/src/backend/tty.rs
+++ b/src/backend/tty.rs
@@ -180,6 +180,7 @@ struct TtyOutputState {
struct Surface {
name: String,
compositor: GbmDrmCompositor,
+ connector: connector::Handle,
dmabuf_feedback: Option<SurfaceDmabufFeedback>,
gamma_props: Option<GammaProps>,
/// Gamma change to apply upon session resume.
@@ -426,18 +427,6 @@ impl Tty {
}
// Restore VRR.
- let Some(connector) =
- surface.compositor.pending_connectors().into_iter().next()
- else {
- error!("surface pending connectors is empty");
- continue;
- };
- let Some(connector) = device.drm_scanner.connectors().get(&connector)
- else {
- error!("missing enabled connector in drm_scanner");
- continue;
- };
-
let output = niri
.global_space
.outputs()
@@ -457,7 +446,7 @@ impl Tty {
try_to_change_vrr(
&device.drm,
- connector,
+ surface.connector,
*crtc,
surface,
output_state,
@@ -832,15 +821,13 @@ impl Tty {
let mut vrr_enabled = false;
if let Some(capable) = is_vrr_capable(&device.drm, connector.handle()) {
if capable {
- let word = if config.variable_refresh_rate {
- "enabling"
- } else {
- "disabling"
- };
+ // 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, config.variable_refresh_rate) {
+ match set_vrr_enabled(&device.drm, crtc, vrr) {
Ok(enabled) => {
- if enabled != config.variable_refresh_rate {
+ if enabled != vrr {
warn!("failed {} VRR", word);
}
@@ -851,13 +838,13 @@ impl Tty {
}
}
} else {
- if config.variable_refresh_rate {
+ 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, config.variable_refresh_rate);
+ let res = set_vrr_enabled(&device.drm, crtc, false);
if matches!(res, Ok(true)) {
warn!("error disabling VRR");
@@ -865,7 +852,7 @@ impl Tty {
vrr_enabled = true;
}
}
- } else if config.variable_refresh_rate {
+ } else if !config.is_vrr_always_off() {
warn!("cannot enable VRR because connector is not vrr_capable");
}
@@ -1017,6 +1004,7 @@ impl Tty {
let surface = Surface {
name: output_name.clone(),
+ connector: connector.handle(),
compositor,
dmabuf_feedback,
gamma_props,
@@ -1661,6 +1649,33 @@ impl Tty {
}
}
+ pub fn set_output_on_demand_vrr(&mut self, niri: &mut Niri, output: &Output, enable_vrr: bool) {
+ let _span = tracy_client::span!("Tty::set_output_on_demand_vrr");
+
+ let output_state = niri.output_state.get_mut(output).unwrap();
+ output_state.on_demand_vrr_enabled = enable_vrr;
+ if output_state.frame_clock.vrr() == enable_vrr {
+ return;
+ }
+ for (&node, device) in self.devices.iter_mut() {
+ 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,
+ );
+ self.refresh_ipc_outputs(niri);
+ return;
+ }
+ }
+ }
+ }
+
pub fn on_output_config_changed(&mut self, niri: &mut Niri) {
let _span = tracy_client::span!("Tty::on_output_config_changed");
@@ -1675,9 +1690,7 @@ impl Tty {
let mut to_connect = vec![];
for (&node, device) in &mut self.devices {
- for surface in device.surfaces.values_mut() {
- let crtc = surface.compositor.crtc();
-
+ for (&crtc, surface) in device.surfaces.iter_mut() {
let config = self
.config
.borrow()
@@ -1691,12 +1704,8 @@ impl Tty {
}
// Check if we need to change the mode.
- let Some(connector) = surface.compositor.pending_connectors().into_iter().next()
+ let Some(connector) = device.drm_scanner.connectors().get(&surface.connector)
else {
- error!("surface pending connectors is empty");
- continue;
- };
- let Some(connector) = device.drm_scanner.connectors().get(&connector) else {
error!("missing enabled connector in drm_scanner");
continue;
};
@@ -1707,8 +1716,9 @@ impl Tty {
};
let change_mode = surface.compositor.pending_mode() != mode;
- let change_vrr = surface.vrr_enabled != config.variable_refresh_rate;
- if !change_mode && !change_vrr {
+ let change_always_vrr = surface.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;
}
@@ -1729,14 +1739,16 @@ impl Tty {
continue;
};
- if change_vrr {
+ if (is_on_demand_vrr && surface.vrr_enabled != output_state.on_demand_vrr_enabled)
+ || (!is_on_demand_vrr && change_always_vrr)
+ {
try_to_change_vrr(
&device.drm,
- connector,
+ connector.handle(),
crtc,
surface,
output_state,
- config.variable_refresh_rate,
+ !surface.vrr_enabled,
);
}
@@ -2388,7 +2400,7 @@ pub fn set_gamma_for_crtc(
fn try_to_change_vrr(
device: &DrmDevice,
- connector: &connector::Info,
+ connector: connector::Handle,
crtc: crtc::Handle,
surface: &mut Surface,
output_state: &mut crate::niri::OutputState,
@@ -2396,7 +2408,7 @@ fn try_to_change_vrr(
) {
let _span = tracy_client::span!("try_to_change_vrr");
- if is_vrr_capable(device, connector.handle()) == Some(true) {
+ if is_vrr_capable(device, connector) == Some(true) {
let word = if enable_vrr { "enabling" } else { "disabling" };
match set_vrr_enabled(device, crtc, enable_vrr) {